[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