Awesome thread, guys ... [bump] ...
I have been test-coding various sources to determine whether or not my
65m32 design has enough functionality to be 'fun' to program, like the
65xx is (at least to me). In typical 'old-school' fashion, I decided that an
ITC forth would be a good initial practice target, not because I know how to use it, but because I know how to translate it (with one or two embarrassing exceptions). The
65m32 only allows one built-in level of indirection (what a 65xx programmer would simply call 'direct' or 'absolute'), but it also has a couple more registers. I was intrigued by this
TOS in accumulator idea, and coded up some tests to see how it might go:
Code:
Keeping dTOS in register a seems like an overall 'win'
for ITC Forth on the 65m32 ... an analysis of some
figFORTH primitives follow. The 65m32 approaches the
instruction density of the pdp-11 version, and makes
everything 32-bits.
Register a is an important temporary for 'dTOS in (x)'
Register a is dTOS and (x) is d2OS for 'dTOS in a'
Register b is an important temporary for 'dTOS in a'
Register x is the data SP
Register y is IP
Register u is W
Register s is the return SP
NEXT, BUMP, BRANCH and ;S are identical for either
version. The code headers are also identical, and are
therefore not included in this analysis. Machine word
and memory cycle counts are shown in parentheses.
It is assumed that R-M-W instructions and successful
branches take an extra cycle to complete.
NEXT (2; 5)
ldu ,y+ ; W = (IP) , IP += 1
jmp (,u+) ; execute code @ (W) , W += 1
BUMP (2; 8)
iny ; IP += 1
bra NEXT ; continue
BRANCH (2; 9)
ady ,y ; IP += (IP)
bra NEXT ; continue
;S (2; 9)
ply ; pop IP from rstack
bra NEXT ; continue
When the choice presented itself, code density was
given higher priority than execution speed for both
versions.
First, the 'ties': ------------------------------------
Before: dTOS in (x) After: dTOS in a
------------------- -----------------
PERFORM (3; 7) PERFORM (3; 7)
lda ,x+ ldu ,a
ldu ,a lda ,x+
jmp (,u+) jmp (,u+)
>R (2; 10) >R (2; 10)
psh ,x+ pda ,x+
bra NEXT bra NEXT
R (3; 11) R (3; 11)
lda ,s sta ,-x
sta ,-x lda ,s
bra NEXT bra NEXT
R> (3; 11) R> (3; 11)
pla sta ,-x
sta ,-x pla
bra NEXT bra NEXT
LIT (3; 11) LIT (3; 11)
lda ,y+ sta ,-x
sta ,-x lda ,y+
bra NEXT bra NEXT
I (3; 11) I (3; 11)
lda ,s sta ,-x
sta ,-x lda ,s
bra NEXT bra NEXT
LEAVE (3; 11) LEAVE (3; 11)
lda ,s ldb ,s
sta 1,s stb 1,s
bra NEXT bra NEXT
OVER (3; 11) OVER (3; 11)
lda 1,x sta ,-x
sta ,-x lda 1,x
bra NEXT bra NEXT
(DO) (3; 13) (DO) (3; 13)
psh 1,x+ psh ,x+
psh -1,x+ pda ,x+
bra NEXT bra NEXT
(LOOP) (6; 18 or 19) (LOOP) (6; 18 or 19)
inc ,s inc ,s
lda ,s ldb ,s
cmp 1,s cpb 1,s
bmi BRANCH bmi BRANCH
lds #2,s lds #2,s
bra BUMP bra BUMP
The 'winners': ----------------------------------------
1+ (2; 10) 1+ (2; 8)
inc ,x lda #1,a
bra NEXT bra NEXT
2+ (2; 15) 2+ (2; 8)
inc ,x lda #2,a
bra 1+ bra NEXT
1- (2; 10) 1- (2; 8)
dec ,x lda #-1,a
bra NEXT bra NEXT
2- (2; 15) 2- (2; 8)
dec ,x lda #-2,a
bra 1- bra NEXT
PUT (2; 9) PUTB (2; 8)
sta ,x tba
bra NEXT bra NEXT
DUP (2; 13) DUP (2; 9)
lda ,x sta ,-x
bra PUSH bra NEXT
-DUP (3; 10 or 13) -DUP (3; 9 or 10)
lda ,x tst #,a
bne PUSH sta [ne],-x
bra NEXT bra NEXT
SWAP (3; 16) SWAP (2; 10)
lda ,x exa ,x
exa 1,x bra NEXT
bra PUT
+ (3; 15) + (2; 9)
lda 1,x add ,x+
add ,x+ bra NEXT
bra PUT
NOT (3; 14) NOT (2; 8)
lda ,x cdd #0
cdd #0 bra NEXT
bra PUT
MINUS (3; 14) MINUS (2; 8)
lda ,x cdd #1
cdd #1 bra NEXT
bra PUT
- (3; 15) - (3; 10)
lda 1,x sub #1
sub ,x+ cdd ,x+
bra PUT bra NEXT
U* (3; 15 + ???) U* (2; 9 + ???)
lda 1,x mul ,x+
mul ,x+ bra NEXT
bra PUT
AND (3; 15) AND (2; 9)
lda ,x+ and ,x+
and ,x bra NEXT
bra PUT
OR (3; 15) OR (2; 9)
lda ,x+ ora ,x+
ora ,x bra NEXT
bra PUT
XOR (3; 15) XOR (2; 9)
lda ,x+ eor ,x+
eor ,x bra NEXT
bra PUT
ABS (3; 14) ABS (3; 9)
lda ,x tst #,a
cdd [mi],#1 cdd [mi],#1
bra PUT bra NEXT
@ (3; 15) @ (2; 9)
lda ,x lda ,a
lda ,a bra NEXT
bra PUT
0= (4; 15) 0= (3; 9)
lda ,x cdd #1
cdd #1 cdc #1,a
cdc #1,a bra NEXT
bra PUT
0< (4; 15) 0< (3; 9)
lda ,x rol #1,a
rol #1,a cdc #1,a
cdc #1,a bra NEXT
bra PUT
= (3; 21) = (2; 13)
lda 1,x sub ,x+
sub ,x+ bra 0=
bra 0=
ROT (6; 21) ROT (5; 15)
lda 2,x tab
ldb 1,x lda ,x
stb 2,x exa 1,x
ldb ,x stb ,x
stb 1,x bra NEXT
bra PUT
The 'losers': -----------------------------------------
DROP (2; 8) DROP (2; 9)
inx lda ,x+
bra NEXT bra NEXT
PUSH (2; 9) PUSHB (2; 12)
sta ,-x sta ,-x
bra NEXT bra PUTB
SP@ (2; 9) SP@ (2; 15)
stx ,-x txb
bra NEXT bra PUSHB
EXECUTE (2; 5) EXECUTE (3; 6)
ldu ,x+ tau
jmp (,u+) lda ,x+
jmp (,u+)
0BRANCH (3; 13) 0BRANCH (5; 15)
tst ,x+ tab
bne BRANCH lda ,x+
bra BUMP tst #,b
bne BRANCH
bra BUMP
(+LOOP) (13; ~24) (+LOOP) (15; ~27)
lda ,s tab
add ,x add ,s
sta ,s sta ,s
tst ,x+ lda ,x+
bpl 2$ tst #,b
lda 1,s bpl 2$
cmp ,s ldb 1,s
bmi BRANCH cpb ,s
bra 3$ bmi BRANCH
2$ cmp 1,s bra 3$
bmi BRANCH 2$ ldb ,s
3$ lds #2,s cpb 1,s
bra BUMP bmi BRANCH
3$ lds #2,s
bra BUMP
The 'mixed bag': --------------------------------------
+! (5; 15) +! (4; 17)
lda ,x+ ldb ,a
ldb ,a adb ,x+
adb ,x+ stb ,a
stb ,a bra DROP
bra NEXT
! (4; 13) ! (3; 15)
lda ,x+ ldb ,x+
ldb ,x+ stb ,a
stb ,a bra DROP
bra NEXT
I'm sure that there is a coding error or two in there, but it seems like an overall win. I also find myself wondering whether or not
ITC is even the best choice for the
65m32. My quest for a completed spec doc continues ... still wandering around a bit, waiting for that burst of inspiration!
Mike