"ROR" in Microsoft BASIC for 6502

If you disassemble any version of Microsoft BASIC for 6502, you’ll find this code in a function that normalizes the (simulated) floating point accumulator:

NORMALIZE_FAC6:
	inc	FAC		; MANTISSA CARRIED, SO SHIFT RIGHT
	beq	OVERFLOW	; OVERFLOW IF EXPONENT TOO BIG
	ror	FAC+1
	ror	FAC+2
	ror	FAC+3
	ror	FAC+4
	ror	FACEXTENSION
	rts

Well, not any BASIC. All versions of

  • Commodore BASIC (all versions, since 1977)
  • AppleSoft BASIC (all versions, since 1977)
  • Microsoft BASIC for the OHIO Scientific (all versions, since 1977)
  • Microsoft BASIC for the rare Mattel Intellivision Keyboard Component (1980)

use this code, but if you look at the disassembly of

  • Microsoft BASIC for the MOS KIM-1 (1977)
  • Microsoft BASIC for the Tangerine Microtan 65 (1979)

you will see this code instead:

NORMALIZE_FAC6:
        inc     FAC
        beq     OVERFLOW
        lda     #$00
        bcc     @1
        lda     #$80
@1:
        lsr     FAC+1
        ora     FAC+1
        sta     FAC+1
        lda     #$00
        bcc     @2
        lda     #$80
@2:
        lsr     FAC+2
        ora     FAC+2
        sta     FAC+2
        lda     #$00
        bcc     @3
        lda     #$80
@3
        lsr     FAC+3
        ora     FAC+3
        sta     FAC+3
        lda     #$00
        bcc     @4
        lda     #$80
@4:
        lsr     FAC+4
        ora     FAC+4
        sta     FAC+4
        lda     #$00
        bcc     @5
        lda     #$80
@5:
        lsr     FACEXTENSION
        ora     FACEXTENSION
        sta     FACEXTENSION
        rts

(Actually, the OHIO Scientific and Intellivision versions work on a 3 byte (“6 digit”) instead of a 4 byte (“9 digit”) mantissa, so the “FAC+4” part is missing.)

Similar replacement has happened in other parts of the floating point library. It seems to be a compile-time option of the assembly source code.

Todays puzzle is to find out why there are two versions of this code, and why the different computer vendors chose to use one version or another.

See comments for solution.

15 thoughts on “"ROR" in Microsoft BASIC for 6502”

  1. @MagerValp: That’s correct. 6502’s ROR was broken in such a way that it was even left out of the KIM-1 docs. However, the bug was fixed around ’77. Did Tangerine buy stockpiles of broken 6502’s for their Microtan?

    Reply
  2. Okay, part one is solved: The 6502 was introduced in september 1975, and all parts before June 1976 had a bug in ROR. But the second part of the question is: Why do exactly the two mentioned versions contain the workaround, and the others don’t? Marco is going the right direction there, but this needs more analysis. 🙂

    Reply
  3. Leaving it out of the KIM-1 makes sense, since the earliest 6502s would show up on said KIM-1s.

    Microtan 65 sounds like quite the anomaly, as if the workaround was switched on in error. There’s a program listing in this magazine that has a ROR instruction on page 24, line 160: http://www.geoff.org.uk/microtan/images/microt3.gif

    Unless, of course, it was just “ROR zpage” that was broken and “ROR A” was ok. What, exactly, was broken with ROR?

    Other magazines here: http://www.geoff.org.uk/microtan/magazines.htm

    Reply
  4. I looked through a scan I have of MOSTEK’s Aug 1975 6502 manual and ROR in all forms is indeed absent, which hints (but does not state equivocally) it wasn’t tied to an address mode.

    Reply
  5. Right. The KIM-1 was introduced in late 1975, and there were definitely devices with faulty 6502 chips, so Microsoft BASIC for the KIM-1, which was introduced in 1977, couldn’t use ROR.

    The Microtan 65 indeed is an anomaly. It was introduced in 1979, and there is no way there were using CPUs in their devices that had been manufactured three years before. The monitor ROM even uses ROR, here are two examples:

    jsr LF556
    php
    ror $51
    plp
    adc #$00
    […]
    asl $00
    sec
    ror $00
    jsr LC558

    So it is obvious that Tangerine used an incorrect build switch for Microsoft BASIC.

    And this find also shows that there was always an actual build switch, as opposed to Microsoft replacing the workaround with the ROR code at some point.

    Reply
  6. Another plausible explanation could be that the Microtan developer prototype was assembled with an old 6502 chip, or that the firmware was developed on a KIM board.

    Reply
  7. @MagerVelp: That seems unlikely if the ROR instruction itself is in the Microtan’s own monitor ROM. 4 years from development to production also seems a bit long.

    Reply
  8. If you replace the macro expansions of ROR in Basic with actual ROR instructions, you free up a little bit of space that can be used for other things. I did this with a copy of Ohio Scientific 9-digit Disk Basic (which, like the company’s previous versions, used the macro expansion, not the ROR instruction). I used the bytes that were freed up to implement a RESTORE command and a few other enhancements and bug fixes, such as the ability to properly handle a statement like POKE A, PEEK(B).

    Reply
  9. Oops, that was supposed to read “a RESTORE <line number> command”. Simple RESTORE was of course always included. I also got rid of the NULL command while I was at it and replaced it with CALL. Other changes included fixing FRE to always return a positive value, and a computed GOTO (e.g. GOTO 100+10*X).

    Reply
  10. lda #$80
    bcs @1
    asl a
    @1:
    lsr FAC+1
    ora FAC+1
    sta FAC+1

    … wastes one fewer byte for every invocation of the ror replacement macro …

    Reply

Leave a Comment