After playing with this code I realized that MAP was a general purpose routine.
\ Forth translation of same word in TurboForth : MAP ( bank addr -- ) \ ASM converted to Forth F000 AND 0B RSHIFT 4000 + SWAP 00FF AND DUP >< OR \ Hi & lo bytes are now identical SWAP ( -- bank address) 1E00 CRU! SBO \ enable SAMS card ! \ store bank in SAMS register SBZ ; \ disable SAMS card
I didn't need general purpose for the following reasons:
- I didn't need to protect from mapping to a non-4k boundary. I use a constant (MBLOCK)
- I don't need to re-calculate the SAMS register every time cuz I always use >2000
- The bank# is computed will not exceed >FF
- I could remove ' >< OR' because CAMEL99 has 'FUSE' which "fuses" 2 bytes into an integer
So with all that considered I could remove MAP entirely and just put the remaining code in >BANK.
One very Forthy thing I did was moving the calculation of the correct SAMS register to compile time.
This register is calculated based on the constant MBLOCK at compile time but kept in the code as one literal number.
So >BANK now becomes this and saves about 36 bytes!
HEX : >BANK ( 32bit -- addr) \ must have 32bit address!! B/BANK UM/MOD 1STBANK + ( -- offset bank#+1STBANK) BANK# @ OVER <> \ do we need to change banks? IF DUP BANK# ! \ update bank# DUP FUSE \ Hi & lo bytes are now identical \ compute SAMS register for address=MBLOCK at compile time [ MBLOCK 0B RSHIFT 4000 + ] LITERAL 1E00 CRU! SBO \ enable SAMS card ( bank# register) ! \ store bank in SAMS register SBZ \ disable SAMS card ELSE DROP \ not needed. Drop the bank# THEN MBLOCK OR \ return the address in mapped block ;