[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
ARM and 6502 (was WOZ vs ...)
There was some talk about the ARM instruction set and 6502 compatibility. Here
is some stuff I dug out. I hope the format comes through OK.
ARM versus 65C02 examples. These are equivalent routines for identical
implementations of Forth I did for the Apple II nad the ARM 7500, except one is
16 bits and the other is 32. I used MPW //gs and an MPW ARM assembler probably
not available publicly (later became part of Newton tools?). Remember, the
shortest 65C02 instruction is 2 cycles and the average is 4. All ARM
instructions are one cycle except special store multiple type that let you save
a bunch of registers with one instruction -- a neat way to move data fast
without DMA.
An ambitious person could use this to compare 65816 versus ARM at 6MHz. Send me
some simple 816 examples and I will give you the ARM code and cycle counts.
This is what Acorn did when they saw the 65816. What do you think?
In the 65C02, the Forth data stack is in zero page and is 16 bits wide. On the
ARM, the data stack is in RAM and is 32 bits wide and one of the 16 registers
is assigned as the �stack pointer�. On the ARM, since the registers are 32
bits, one of them is used as the top of the stack so the top datum is always
ready for action. The assembler lets you rename the registers which I will
point out in the examples. I�ll leave off the usual linked list and name
fields for clarity.
65C02, Forth word @ (fetch) fetches to the top of the stack, the 16 bits
pointed to by the address on top of the stack. Replaces the address with the
data. BOT is alias for zpage stack pointer.
FETCH lda (BOT,x) ; Indirect off top of stack.
tay
inc BOT,x
bne @1
inc BOT+1,x
@1 lda (BOT,x)
sty BOT,x
sta BOT+1,x
jmp NEXT ; NEXT is shown at end and is 13 instructions long.
ARM: TOP is an alias for one of the registers used as top of stack,
and NEXT is a two instruction, and therefore two cycle, macro.
FETCH LDR TOP,[TOP]
NEXT
65C02: Forth word ! (16 bit store). Put the second item on the stack in the
address on the top of the stack and purge both items from the stack.
STORE lda SCD,x
sta (BOT,x)
inc BOT,x
bne @1
inc BOT+1,x
@1 lda SCD+1,x
sta (BOT,x)
inx
inx
inx
inx
jmp NEXT
ARM: 32 bit store.
STORE LDR R0,[PSTACK],#4 ; Get the second item in a temp
register.
STR R0,[TOP] ; Store at address on top.
LDR TOP,[PSTACK],#4 ; move old 3rd item to top and adjust .
NEXT
This kind of thing, LDR TOP,[PSTACK],#4 is load indirect with auto increment.
Any register can act as an index register for another. On the 6502 you had to
use X or Y or a special Zpage mode.
65C02: Forth word + (plus). Add top two items on stack leaving result on top.
16 bit add.
PLUS clc
lda BOT,x
adc SCD,x
sta SCD,x
lda BOT+1,x
adc SCD+1,x
sta SCD+1,x
inx
inx
jmp NEXT
ARM: 32 bit add.
PLUS LDR R0,[PSTACK],#4
ADD TOP,TOP,R0
NEXT
65C02: Here is a good comparison. Forth word D+ (double precision add) 32 bits.
Equivalent to the ARM PLUS above.
DPLUS clc
lda BOT+2,x
adc BOT+6,x
sta BOT+6,x
lda BOT+3,x
adc BOT+7,x
sta BOT+7,x
lda BOT+0,x
adc BOT+4,x
sta BOT+4,x
lda BOT+1,x
adc BOT+5,x
sta BOT+5,x
inx
inx
inx
inx
jmp NEXT
65C02: Forth word 16 bit OVER. Bring a copy of the second item to the top. A,B
becomes A,B,A
OVER lda SCD,x
ldy SCD+1,x
dex
dex
sta BOT,x
sty BOT+1,x
jmp NEXT
ARM 32 bit OVER.
OVER STR TOP,[PSTACK,#-4]!
LDR TOP,[PSTACK,#4]
NEXT
65C02: Exchange the top two items, 16 bit.
SWAP lda SCD,x
ldy BOT,x
sty SCD,x
sta BOT,x
lda SCD+1,x
ldy BOT+1,x
sty SCD+1,x
sta BOT+1,x
jmp NEXT
ARM, 32 bit SWAP
SWAP SWP TOP,TOP,[PSTACK]
NEXT
I�m cheating, its so common there is a little macro instruction, SWP.
ARM Forth word ABS. Replace top item with its absolute value. This is
interesting because it uses the ARM feature that all instructions are
conditional. This means short branches over one instruction are not needed. The
instruction is just skipped if the processor status flags say to. Why mess up
the pipeline if you don�t have to?
ABS TEQ TOP,#0 ;Set condition codes
RSBMI TOP,TOP,#0 ; Skip if Minus.
NEXT
Now, what about these NEXT macros? I�m not going to explain what they do other
than to say these are both indirectly threaded Forths.
65C02: Really a routine, not a macro. Uses zero page locations as if they were
16 bit registers that allow indirect addressing modes (which they do, sort of).
NEXT ldy #01
lda (IP),y ; W = (IP) {the next parameter}
sta W+1
dey
lda (IP),y
sta W
clc ; IP = IP+2
lda IP
adc #02
sta IP
bcc nexta
inc IP+1
nexta jmp W-1 ; JMP indirect through W
ARM: Since NEXT is only two instructions long and instructions are all the same
length (4 bytes) and take the same amount of time to execute (1 cycle), I just
use a macro and put NEXT inline.
MACRO NEXT
LDR WPOINTER,[IPOINTER],#4 ; Do NEXT right here.
LDR PC,[WPOINTER] ; JMP indirect through W.
MEND
; Synonyms for special registers.
RSTACK RN 4 ; Return Stack Pointer
WPOINTER RN 5 ; Word Pointer
IPOINTER RN 6 ; Instruction Pointer
PSTACK RN 7 ; Forth Parameter Stack Pointer
LSTACK RN 8 ; Loop Stack Pointer
FPSTACK RN 9 ; Floating Point Stack Pointer
FPLOW RN 10 ; Holds top of floating stack low
FPHIGH RN 11 ; Holds top of floating stack high
TOP RN 12 ; Holds top of parameter stack
SP RN 13 ; Machine Stack Pointer
LK RN 14 ; Link
PC RN 15 ; Program Counter