Was using up too many S registers, so moved internal functions to use new registers I0 - I7, added IEEE rounding to MUL and DIV, refactored to reduce size, and trimmed trailing spaces.

This commit is contained in:
Russell-S-Harper 2018-08-21 09:14:16 -04:00
parent 6dc8517120
commit 8bbb5016cd
10 changed files with 440 additions and 475 deletions

View File

@ -158,15 +158,15 @@ _1 DEY ; transfer four bytes over
.)
_EXC .( ; EXC r 4r Rr <-> RS - exchange Rr with stack
LDY _RSI ; RS to RD
LDY _RSI ; RS to I0
LDA _RS-1,Y
STA _RD+3
STA _I0+3
LDA _RS-2,Y
STA _RD+2
STA _I0+2
LDA _RS-3,Y
STA _RD+1
STA _I0+1
LDA _RS-4,Y
STA _RD
STA _I0
LDA _R0,X ; copy Rr to RS
STA _RS-4,Y
LDA _R0+1,X
@ -175,70 +175,70 @@ _EXC .( ; EXC r 4r Rr <-> RS - exchange Rr with stack
STA _RS-2,Y
LDA _R0+3,X
STA _RS-1,Y
LDA _RD ; copy RD to Rr
LDA _I0 ; copy I0 to Rr
STA _R0,X
LDA _RD+1
LDA _I0+1
STA _R0+1,X
LDA _RD+2
LDA _I0+2
STA _R0+2,X
LDA _RD+3
LDA _I0+3
STA _R0+3,X
RTS
.)
_ADDRD .( ; add RD to register indexed by X
_ADDI0X .( ; add I0 to register indexed by X
LDA _R0+3,X
AND #_MSK_O ; check for existing overflow condition
BEQ _4
BEQ _1
EOR #_MSK_O
BNE _3 ; existing overflow, skip decrement operation
_4 CLC ; adding RD
LDA _RD
BNE _2 ; existing overflow, skip decrement operation
_1 CLC ; adding RD
LDA _I0
ADC _R0,X
STA _R0,X
LDA _RD+1
LDA _I0+1
ADC _R0+1,X
STA _R0+1,X
LDA _RD+2
LDA _I0+2
ADC _R0+2,X
STA _R0+2,X
LDA _RD+3
LDA _I0+3
ADC _R0+3,X
STA _R0+3,X
AND #_MSK_O ; check for overflow
BEQ _2
BEQ _3
EOR #_MSK_O
BEQ _2
_3 LDA _F ; set overflow
_2 LDA _F ; set overflow
ORA #_F_O
STA _F
BNE _5
_2 LDA _F ; clear overflow
BNE _4
_3 LDA _F ; clear overflow
AND #_F_O^$FF
STA _F
_5 RTS
_4 RTS
.)
_INR .( ; INR r 5r Rr <- Rr + 1.0 - increment register
LDA #0 ; set RD to plus one
STA _RD
LDA #0 ; set I0 to plus one
STA _I0
LDA #_PLS_1
STA _RD+1
STA _I0+1
LDA #0
STA _RD+2
STA _RD+3
BEQ _ADDRD
STA _I0+2
STA _I0+3
BEQ _ADDI0X
.)
_DCR .( ; DCR r 6r Rr <- Rr - 1.0 - decrement register
LDA #0 ; set RD to minus one
STA _RD
LDA #0 ; set I0 to minus one
STA _I0
LDA #_MNS_1
STA _RD+1
STA _I0+1
LDA #$FF
STA _RD+2
STA _RD+3
BNE _ADDRD
STA _I0+2
STA _I0+3
BNE _ADDI0X
.)
_TST .( ; TST r 7r F <- Rr <=> 0.0 - test register
@ -299,117 +299,195 @@ _2 INC _PCL ; advance PC
_3 RTS
.)
_RETZD .( ; clears register D, clears underflow, falls through to _TRFDR
_ZERI0 .( ; clears I0
LDA #0
STA _RD
STA _RD+1
STA _RD+2
STA _RD+3
STA _I0
STA _I0+1
STA _I0+2
STA _I0+3
RTS
.)
_TRFI0X .( ; transfer I0 to register indexed by X, MSB returned in A
LDA _I0
STA _R0,X
LDA _I0+1
STA _R0+1,X
LDA _I0+2
STA _R0+2,X
LDA _I0+3
STA _R0+3,X
RTS
.)
_RTZI0X .( ; clears I0, clears underflow, falls through to _RETI0X
JSR _ZERI0
LDA _F ; clear underflow
AND #_F_U^$FF
STA _F
.)
_TRFDR .( ; pulls X, transfers RD to X as r register, updates overflow flag
_RETI0X .( ; pulls X, transfers I0 to register indexed by X, updates overflow flag
PLA
TAX
LDA _RD ; transfer result to Rr
STA _R0,X
LDA _RD+1
STA _R0+1,X
LDA _RD+2
STA _R0+2,X
LDA _RD+3
STA _R0+3,X
JSR _TRFI0X ; transfer result to register indexed by X
AND #_MSK_O ; check for overflow
BEQ _4
BEQ _1
EOR #_MSK_O
BEQ _4
_3 LDA _F ; set overflow
BEQ _1
LDA _F ; set overflow
ORA #_F_O
STA _F
BNE _5
_4 LDA _F ; clear overflow
BNE _2
_1 LDA _F ; clear overflow
AND #_F_O^$FF
STA _F
_5 RTS
_2 RTS
.)
_ADD .( ; ADD r pq ar pq Rr <- Rp + Rq - addition
TXA
PHA ; save r register for later
JSR _GETPQ
CLC ; set RD to Rp + Rq
CLC ; set I0 to Rp + Rq
LDA _R0,X
ADC _R0,Y
STA _RD
STA _I0
LDA _R0+1,X
ADC _R0+1,Y
STA _RD+1
STA _I0+1
LDA _R0+2,X
ADC _R0+2,Y
STA _RD+2
STA _I0+2
LDA _R0+3,X
ADC _R0+3,Y
STA _RD+3
JMP _TRFDR ; pull X, transfer RD to r register, let it handle the return
STA _I0+3
JMP _RETI0X ; pull X, transfer I0 to r register, let it handle the return
.)
_SUB .( ; SUB r pq br pq Rr <- Rp - Rq - subtraction
TXA
PHA ; save r register for later
JSR _GETPQ
SEC ; set RD to Rp - Rq
SEC ; set I0 to Rp - Rq
LDA _R0,X
SBC _R0,Y
STA _RD
STA _I0
LDA _R0+1,X
SBC _R0+1,Y
STA _RD+1
STA _I0+1
LDA _R0+2,X
SBC _R0+2,Y
STA _RD+2
STA _I0+2
LDA _R0+3,X
SBC _R0+3,Y
STA _RD+3
JMP _TRFDR ; pull X, transfer RD to r register, let it handle the return
STA _I0+3
JMP _RETI0X ; pull X, transfer I0 to r register, let it handle the return
.)
_TRFQD .( ; transfers Y as q register to RD
LDA _R0,Y
STA _RD
LDA _R0+1,Y
STA _RD+1
LDA _R0+2,Y
STA _RD+2
LDA _R0+3,Y
STA _RD+3
RTS
.)
_NEGRY .( ; negates register at Y
_NEGX .( ; negates register at X
SEC
LDA #0
SBC _R0,Y
STA _R0,Y
SBC _R0,X
STA _R0,X
LDA #0
SBC _R0+1,Y
STA _R0+1,Y
SBC _R0+1,X
STA _R0+1,X
LDA #0
SBC _R0+2,Y
STA _R0+2,Y
SBC _R0+2,X
STA _R0+2,X
LDA #0
SBC _R0+3,Y
STA _R0+3,Y
SBC _R0+3,X
STA _R0+3,X
RTS
.)
_ABSRY .( ; sets register at Y to absolute value
LDA _R0+3,Y
BMI _NEGRY
_ABSX .( ; sets register at X to absolute value
LDA _R0+3,X
BMI _NEGX
RTS
.)
_BKRRD .( ; implement banker's rounding on quadword pointed by X
; The logic table below shows the expected results. The only differences are
; when the least significant byte (LSB) is 128 and the second byte (2B) is even
; vs odd.
;
; LSB 2B CARRY LSB + 127 + C CARRY* DELTA 2B*
; <127 EVEN 0 <254 0 0
; 127 EVEN 0 254 0 0
; 128 EVEN 0 255 0 0 <- not rounding up
; 129 EVEN 0 0 1 +1
; >129 EVEN 0 >0 1 +1
; <127 ODD 1 <255 0 0
; 127 ODD 1 255 0 0
; 128 ODD 1 0 1 +1 <- rounding up
; 129 ODD 1 1 1 +1
; >129 ODD 1 >1 1 +1
LDA _R0+1,X
ROR ; will set carry if odd
LDA _R0,X
ADC #127 ; adding just less than half
STA _R0,X
BCC _1
INC _R0+1,X ; propagate through the rest
BNE _1
INC _R0+2,X
BNE _1
INC _R0+3,X
BNE _1
INC _R1,X
BNE _1
INC _R1+1,X
BNE _1
INC _R1+2,X
BNE _1
INC _R1+3,X
_1 RTS
.)
_CPXI0 .( ; copy four bytes at X index to I0, returns MSB in A
LDA _R0,X
STA _I0
LDA _R0+1,X
STA _I0+1
LDA _R0+2,X
STA _I0+2
LDA _R0+3,X
STA _I0+3
RTS
.)
_RDXFI0 .( ; using X index, round quad-word, transfer to I0, set overflow in I0, set or clear the underflow flag
JSR _BKRRD ; banker's rounding
INX ; skip extra fraction
JSR _CPXI0 ; copy to I0
AND #_MSK_O ; consider the overflow bits
ORA _R1,X ; check all the other bytes
ORA _R1+1,X
ORA _R1+2,X
BEQ _1 ; all zeroes means no overflow
LDA _I0+3 ; overflow situation
AND #_MSK_O^$FF ; set overflow
ORA #_F_O
STA _I0+3
_1 LDA _I0 ; check for underflow
ORA _I0+1
ORA _I0+2
ORA _I0+3
BNE _2 ; non-zero result means no underflow
LDA _F ; we checked earlier for zero operands, so a zero result means underflow, set underflow
ORA #_F_U
STA _F
BNE _3
_2 LDA _F ; clear underflow
AND #_F_U^$FF
STA _F
_3 RTS
.)
_MUL .( ; MUL r pq cr pq Rr <- Rp * Rq - multiplication
TXA ; adapted from http://www.6502.org/source/integers/32muldiv.htm
PHA ; save r register for later
@ -419,353 +497,244 @@ _MUL .( ; MUL r pq cr pq Rr <- Rp * Rq - multiplication
ORA _R0+2,X
ORA _R0+3,X
BNE _1 ; p is non-zero
JMP _RETZD ; p is zero, return zero
JMP _RTZI0X ; p is zero, return zero
_1 LDA _R0,Y ; check for zero argument
ORA _R0+1,Y
ORA _R0+2,Y
ORA _R0+3,Y
BNE _2 ; q is non-zero
JMP _RETZD ; q is zero, return zero
_2 LDA _R0+3,X ; save sign of register p
AND #_MSK_O
PHA
JMP _RTZI0X ; q is zero, return zero
_2 LDA _R0+3,X
EOR _R0+3,Y
AND #_MSK_O ; save sign of product
PHA
JSR _TRFQD
TXA
TAY ; absolute value of register p
JSR _ABSRY
LDY #_RD-_R0 ; absolute value of register q saved in D
JSR _ABSRY
JSR _CPXI0 ; transfer p to I0
LDA _R0,Y ; transfer q to I1
STA _I1
LDA _R0+1,Y
STA _I1+1
LDA _R0+2,Y
STA _I1+2
LDA _R0+3,Y
STA _I1+3
LDX #_I0-_R0
JSR _ABSX ; set to absolute value
LDX #_I1-_R0
JSR _ABSX ; set to absolute value
LDA #0
STA _RB+4 ; clear upper half of product
STA _RB+5
STA _RB+6
STA _RB+7
LDY #34 ; thirty bit multiply and four bit shift
_3 LSR _RD+3 ; shift operand
ROR _RD+2
ROR _RD+1
ROR _RD
STA _I3 ; clear upper half of product in I3
STA _I3+1
STA _I3+2
STA _I3+3
LDY #34 ; thirty bit multiply and four bit shift to ensure product is aligned
_3 LSR _I1+3 ; get lowest bit of operand
ROR _I1+2
ROR _I1+1
ROR _I1
BCC _4 ; skip adding in product if bit is zero
CLC
LDA _RB+4 ; add in p register
ADC _R0,X
STA _RB+4
LDA _RB+5
ADC _R0+1,X
STA _RB+5
LDA _RB+6
ADC _R0+2,X
STA _RB+6
LDA _RB+7
ADC _R0+3,X
_4 ROR ; shift the product
STA _RB+7
ROR _RB+6
ROR _RB+5
ROR _RB+4
ROR _RB+3
ROR _RB+2
ROR _RB+1
ROR _RB
LDA _I3 ; add in p register
ADC _I0
STA _I3
LDA _I3+1
ADC _I0+1
STA _I3+1
LDA _I3+2
ADC _I0+2
STA _I3+2
LDA _I3+3
ADC _I0+3
STA _I3+3
_4 LSR _I3+3 ; shift the product down
ROR _I3+2
ROR _I3+1
ROR _I3
ROR _I2+3
ROR _I2+2
ROR _I2+1
ROR _I2
DEY
BNE _3 ; repeat until bits are done
LDA _RB+1 ; copy result to RD
STA _RD
LDA _RB+2
STA _RD+1
LDA _RB+3
STA _RD+2
LDA _RB+4
STA _RD+3
AND #_MSK_O ; consider the overflow bits
ORA _RB+5 ; check all the other bytes
ORA _RB+6
ORA _RB+7
BEQ _5 ; all zeroes means no overflow
LDA _RD+3 ; overflow situation, set accordingly
AND #_MSK_O^$FF ; set overflow
ORA #_F_O
STA _RD+3
BNE _6
_5 LDA _RD ; check for underflow
ORA _RD+1
ORA _RD+2
ORA _RD+3
BNE _6 ; non-zero result means no underflow
LDA _F ; we checked earlier for zero operands, so a zero result means underflow, set underflow
ORA #_F_U
STA _F
BNE _7
_6 LDA _F ; clear underflow
AND #_F_U^$FF
STA _F
_7 PLA ; set the sign of the product
BEQ _8
LDY #_RD-_R0 ; negate register D
JSR _NEGRY
_8 PLA ; reset the sign of register p
BEQ _9
TXA
TAY
JSR _NEGRY
_9 JMP _TRFDR ; pull X, transfer RD to r register, let it handle the return
LDX #_I2-_R0
JSR _RDXFI0 ; round and transfer to I0, set or clear underflow flag
PLA ; set the sign of the product
BEQ _5
LDX #_I0-_R0 ; negate I0
JSR _NEGX
_5 JMP _RETI0X ; pull X, transfer I0 to r register, let it handle the return
.)
_ZERQX .( ; zero quad-word (64 bits) at X
LDA #0
STA _R0,X
STA _R0+1,X
STA _R0+2,X
STA _R0+3,X
STA _R0+4,X
STA _R0+5,X
STA _R0+6,X
STA _R0+7,X
RTS
.)
_INTDM .( ; initialize for DIV and MOD, returns sign of result in A
TXA
PHA ; save r register for later
JSR _GETPQ
LDA _R0,X ; check for zero argument
ORA _R0+1,X
ORA _R0+2,X
ORA _R0+3,X
BNE _1 ; p is non-zero
JMP _RETZD ; p is zero, return zero
JMP _RTZI0X ; p is zero, return zero
_1 LDA _R0,Y ; check for zero argument
ORA _R0+1,Y
ORA _R0+2,Y
ORA _R0+3,Y
BNE _2 ; q is non-zero
BRK ; q is zero, abort and call exception handler (TODO)
_2 LDA _R0,X ; copy p to RD
STA _RD
LDA _R0+1,X
STA _RD+1
LDA _R0+2,X
STA _RD+2
LDA _R0+3,X
STA _RD+3
LDA _R0,Y ; copy q to RC
STA _RC
; I0 / I1 will form 64-bit quantity with high order bytes I1 as zero
_2 JSR _CPXI0 ; copy p to I0
LDX #_I1-_R0
JSR _ZERQX
; I2 / I3 will form 64-bit quantity with low order bytes I2 as zero
LDA _R0,Y ; copy q to I3
STA _I3
LDA _R0+1,Y
STA _RC+1
STA _I3+1
LDA _R0+2,Y
STA _RC+2
STA _I3+2
LDA _R0+3,Y
STA _RC+3
LDA #0 ; set RB to 1
STA _RB
LDA #_PLS_1
STA _RB+1
LDA #0
STA _RB+2
STA _RB+3
PLA ; restore r register
TAX
LDA #0 ; set r to 0
STA _R0,X
STA _R0+1,X
STA _R0+2,X
STA _R0+3,X
LDA _RD+3 ; get sign of result
EOR _RC+3
STA _I3+3
; I4 / I5 will form 64-bit result
LDX #_I4-_R0
JSR _ZERQX
LDA _I0+3 ; get sign of result
EOR _I3+3
AND #_MSK_O
RTS
.)
_CMPDC .( ; compare D to C, return result in status
LDA _RD+3
CMP _RC+3
_CMPDM .( ; compare I0/I1 to I2/I3, return result in status
LDA _I1+3
CMP _I3+3
BCC _1 ; definitely less
BNE _1 ; definitely greater
LDA _RD+2
CMP _RC+2
LDA _I1+2
CMP _I3+2
BCC _1 ; definitely less
BNE _1 ; definitely greater
LDA _RD+1
CMP _RC+1
LDA _I1+1
CMP _I3+1
BCC _1 ; definitely less
BNE _1 ; definitely greater
LDA _RD
CMP _RC
LDA _I1
CMP _I3
BCC _1 ; definitely less
BNE _1 ; definitely greater
LDA _I0+3
CMP _I2+3
BCC _1 ; definitely less
BNE _1 ; definitely greater
LDA _I0+2
CMP _I2+2
BCC _1 ; definitely less
BNE _1 ; definitely greater
LDA _I0+1
CMP _I2+1
BCC _1 ; definitely less
BNE _1 ; definitely greater
LDA _I0
CMP _I2
_1 RTS
.)
_UPDDM .( ; update DIV and MOD
SEC ; RD -= RC
LDA _RD
SBC _RC
STA _RD
LDA _RD+1
SBC _RC+1
STA _RD+1
LDA _RD+2
SBC _RC+2
STA _RD+2
LDA _RD+3
SBC _RC+3
STA _RD+3
CLC ; RX += RB
LDA _R0,X
ADC _RB
STA _R0,X
LDA _R0+1,X
ADC _RB+1
STA _R0+1,X
LDA _R0+2,X
ADC _RB+2
STA _R0+2,X
LDA _R0+3,X
ADC _RB+3
STA _R0+3,X
SEC ; I0/I1 -= I2/I3
LDA _I0
SBC _I2
STA _I0
LDA _I0+1
SBC _I2+1
STA _I0+1
LDA _I0+2
SBC _I2+2
STA _I0+2
LDA _I0+3
SBC _I2+3
STA _I0+3
LDA _I1
SBC _I3
STA _I1
LDA _I1+1
SBC _I3+1
STA _I1+1
LDA _I1+2
SBC _I3+2
STA _I1+2
LDA _I1+3
SBC _I3+3
STA _I1+3
RTS
.)
_SHUDM .( ; shift up for DIV and MOD
ASL _RC ; RC *= 2
ROL _RC+1
ROL _RC+2
ROL _RC+3
ASL _RB ; RB *= 2
ROL _RB+1
ROL _RB+2
ROL _RB+3
_SHUDM .( ; shift up for DIV and MOD, C should be set or cleared as required
ROL _I4 ; I4/I5 *= 2
ROL _I4+1
ROL _I4+2
ROL _I4+3
ROL _I5
ROL _I5+1
ROL _I5+2
ROL _I5+3
RTS
.)
_SHDDM .( ; shift down for DIV and MOD
CLC ; RC /= 2
ROR _RC+3
ROR _RC+2
ROR _RC+1
ROR _RC
CLC ; RB /= 2
ROR _RB+3
ROR _RB+2
ROR _RB+1
ROR _RB
CLC ; I2/I3 /= 2
ROR _I3+3
ROR _I3+2
ROR _I3+1
ROR _I3
ROR _I2+3
ROR _I2+2
ROR _I2+1
ROR _I2
RTS
.)
_DIV .( ; DIV r pq dr pq Rr <- Rp / Rq - division
TXA
PHA ; save r register for later
JSR _INTDM ; initialize
PHA ; save sign of result
LDY #_RD-_R0 ; absolute value of register p saved in D
JSR _ABSRY
LDY #_RC-_R0 ; absolute value of register q saved in C
JSR _ABSRY
_3 JSR _CMPDC ; is D < C?
BCC _4 ; yes, continue
BEQ _5 ; D = C
JSR _UPDDM ; confirmed D > C, so RD -= RC, RX += RB
JSR _SHUDM ; shift up
BCC _3 ; if carry is set, means a really bad overflow condition
LDA #$FF ; set to the maximum
STA _R0,X
STA _R0+1,X
STA _R0+2,X
LDA #_MAX_V|_F_O
STA _R0+3,X
BNE _9
_4 LDA _RB ; is RB > 0?
ORA _RB+1
ORA _RB+2
ORA _RB+3
BEQ _7 ; no, done
JSR _CMPDC ; is D >= C?
BCC _6 ; no, skip subtraction
_5 JSR _UPDDM ; RD -= RC, RX += RB
LDA _RD ; is RD > 0?
ORA _RD+1
ORA _RD+2
ORA _RD+3
BEQ _7 ; no, done
_6 JSR _SHDDM ; shift down
JMP _4
_7 LDA _R0,X ; check for underflow
ORA _R0+1,X
ORA _R0+2,X
ORA _R0+3,X
BNE _8 ; non-zero result means no underflow
LDA _F ; we checked earlier for zero operands, so a zero result means underflow, set underflow
ORA #_F_U
STA _F
BNE _A
_8 LDA _F ; clear underflow
AND #_F_U^$FF
STA _F
_9 LDA _R0+3,X ; check for overflow
AND #_MSK_O
BEQ _A ; all zero, no overflow
LDA _F ; set overflow
ORA #_F_O
STA _F
BNE _B
_A LDA _F ; clear overflow
AND #_F_O^$FF
STA _F
_B PLA ; set the sign of quotient
BEQ _C
TXA
TAY
JSR _NEGRY
_C RTS
LDX #_I0-_R0 ; absolute value of register p saved in I0
JSR _ABSX
LDX #_I3-_R0 ; absolute value of register q saved in I3
JSR _ABSX
LDY #51 ; 51 bits are enough, and ensure alignment
_1 JSR _CMPDM ; is I0/I1 < I2/I3
BCC _2 ; yes, skip subtraction
BEQ _4 ; special case when p = q
JSR _UPDDM ; I0/I1 -= I2/I3
_2 JSR _SHUDM ; I4/I5 *= 2 += CARRY
JSR _SHDDM ; I2/I3 /= 2
DEY
BNE _1
BEQ _5
_3 CLC ; special case when p = q, just shift up to the end
_4 JSR _SHUDM ; I4/I5 *= 2 += CARRY
DEY
BNE _3
_5 LDX #_I4-_R0
JSR _RDXFI0 ; round and transfer to I0, set or clear underflow flag
PLA ; set the sign of the product
BEQ _6
LDX #_I0-_R0 ; negate I0
JSR _NEGX
_6 JMP _RETI0X ; pull X, transfer I0 to r register, let it handle the return
.)
_MOD .( ; MOD r pq er pq Rr <- Rp % Rq - modulus
JSR _INTDM ; initialize
PHA ; save sign of result
LDY #_RD-_R0 ; absolute value of register p saved in D
JSR _ABSRY
LDY #_RC-_R0 ; absolute value of register q saved in C
JSR _ABSRY
_3 JSR _CMPDC ; is D < C?
BCC _4 ; yes, continue
BEQ _5 ; D = C
JSR _UPDDM ; confirmed D > C, so RD -= RC, RX += RB
JSR _SHUDM ; shift up
BCC _3 ; if carry is set, means a really bad overflow condition
LDA #1 ; set to "overflowed non-zero"
STA _R0,X
LDA #0
STA _R0+1,X
STA _R0+2,X
ORA #_F_O
STA _R0+3,X
BNE _9
_4 LDA _RB+1 ; is RB < 1?
CMP #_PLS_1
BCC _7 ; yes, done
JSR _CMPDC ; is D >= C?
BCC _6 ; no, skip subtraction
_5 JSR _UPDDM ; RD -= RC, RX += RB
LDA _RD ; is RD > 0?
ORA _RD+1
ORA _RD+2
ORA _RD+3
BEQ _7 ; no, done
_6 JSR _SHDDM ; shift down
JMP _4
_7 LDA _RD ; transfer RD to RX
STA _R0,X
LDA _RD+1
STA _R0+1,X
LDA _RD+2
STA _R0+2,X
LDA _RD+3
STA _R0+3,X
_8 LDA _F ; clear underflow
AND #_F_U^$FF
STA _F
_9 LDA _R0+3,X ; check for overflow
AND #_MSK_O
BEQ _A ; all zero, no overflow
LDA _F ; set overflow
ORA #_F_O
STA _F
BNE _B
_A LDA _F ; clear overflow
AND #_F_O^$FF
STA _F
_B PLA ; set the sign of modulus
BEQ _C
TXA
TAY
JSR _NEGRY
_C RTS
_MOD .(
RTS
.)
_ESC .( ; ESC 00 - escape back into regular assembler

View File

@ -46,8 +46,8 @@
; SVI pq 0e pq (int(Rp)) <- Rq - save indirect to memory
; CMR pq 0f pq F <- Rp <=> Rq - compare registers
; 64 bytes in page zero for common registers
_R0 = $c0
; 40 bytes in page zero for common registers
_R0 = $b8
_R1 = _R0 + 4
_R2 = _R1 + 4
_R3 = _R2 + 4
@ -57,16 +57,20 @@ _R6 = _R5 + 4
_R7 = _R6 + 4
_R8 = _R7 + 4
_R9 = _R8 + 4
_RA = _R9 + 4
_RB = _RA + 4 ; workspace for MUL, DIV, and MOD
_RC = _RB + 4 ; as above
_RD = _RC + 4 ; as above and for ADD, SUB, and EXC
_RE = _RD + 4 ; register E maintains common status
_RF = _RE + 4 ; register F saves/restores processor status
; register E maintains common status
; 32 bytes in page zero for internal registers
_I0 = $e0 ; workspace for ADD, SUB, MUL, DIV, MOD, EXC
_I1 = _I0 + 4
_I2 = _I1 + 4
_I3 = _I2 + 4
_I4 = _I3 + 4
_I5 = _I4 + 4
_I6 = _I5 + 4 ; register I6 maintains common status
_I7 = _I6 + 4 ; register I7 saves/restores processor status
; register I6 maintains common status
; (dd cc bb aa) aa: index for register stack RS / ccbb: program counter PC / dd: flags F UONPZLGE
_RSI = _RE ; register stack index
_RSI = _I6 ; register stack index
_PCL = _RSI + 1 ; program counter low
_PCH = _PCL + 1 ; program counter high
_F = _PCH + 1 ; flags
@ -82,9 +86,9 @@ _F_N = 32 ; if Rr < 0.0 (after TST)
_F_O = 64 ; if overflow (after arithmetic operations)
_F_U = 128 ; if underflow (after arithmetic operations)
; register F saves/restores processor status
; register I7 saves/restores processor status
; (dd cc bb aa) aa: accumulator, bb: index X, cc: index Y, dd: processor status
_ACC = _RF ; saved accumulator to restore
_ACC = _I7 ; saved accumulator to restore
_IDX = _ACC + 1 ; saved index X to restore
_IDY = _IDX + 1 ; saved index Y to restore
_PS = _IDY + 1 ; saved processor status to restore

View File

@ -3,7 +3,7 @@
#ifndef __MACROS_H
#define __MACROS_H
; registers
; common registers
#define R0 0
#define R1 1
#define R2 2
@ -14,12 +14,6 @@
#define R7 7
#define R8 8
#define R9 9
#define RA 10
#define RB 11
#define RC 12
#define RD 13
#define RE 14
#define RF 15
; system functions
#define S0 0
@ -32,12 +26,6 @@
#define S7 7
#define S8 8
#define S9 9
#define SA 10
#define SB 11
#define SC 12
#define SD 13
#define SE 14
#define SF 15
; user functions
#define U0 15
@ -50,12 +38,6 @@
#define U7 8
#define U8 7
#define U9 6
#define UA 5
#define UB 4
#define UC 3
#define UD 2
#define UE 1
#define UF 0
; macros
#define ESC .BYTE _ESC_C

View File

@ -5,9 +5,10 @@
HDR(DEMO)
CMN
SET(R0, 1024 * 1024 - 0.001)
SET(R1, 1/4)
MOD(R2, R0, R1)
SET(R0, 1048575.9995)
SET(R1, 3)
DIV(R2, R0, R1)
MUL(R3, R2, R1)
ESC
BRK

View File

@ -26,10 +26,19 @@ void hook() {
int i, j;
printf("\n%04x %u %u\n", pc, instructions, clockticks6502);
for (i = 0x00c0; i < 0x0100; i += 16) {
printf("%04x ", i);
for (j = 0; j < 16; ++j)
printf("%02x%s", memory[i + j], (i + j + 1) % 16? " ": "\n");
for (i = 0x00b8; i < 0x00d8; i += 4) {
printf("R%d: ", (i - 0x00b8) / 4);
for (j = 0; j < 4; ++j)
printf("%02x ", memory[i + j]);
if (((i - 0x00b8) / 4) % 4 == 3)
printf("\n");
}
for (i = 0x00e0; i < 0x0100; i += 4) {
printf("I%d: ", (i - 0x00e0) / 4);
for (j = 0; j < 4; ++j)
printf("%02x ", memory[i + j]);
if (((i - 0x00e0) / 4) % 4 == 3)
printf("\n");
}
}