Merge pull request #21 from Russell-S-Harper/development

Was using up too many S registers, so moved internal functions to use…
This commit is contained in:
Russell-S-Harper 2018-08-21 09:17:00 -04:00 committed by GitHub
commit 3d8424be98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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 _EXC .( ; EXC r 4r Rr <-> RS - exchange Rr with stack
LDY _RSI ; RS to RD LDY _RSI ; RS to I0
LDA _RS-1,Y LDA _RS-1,Y
STA _RD+3 STA _I0+3
LDA _RS-2,Y LDA _RS-2,Y
STA _RD+2 STA _I0+2
LDA _RS-3,Y LDA _RS-3,Y
STA _RD+1 STA _I0+1
LDA _RS-4,Y LDA _RS-4,Y
STA _RD STA _I0
LDA _R0,X ; copy Rr to RS LDA _R0,X ; copy Rr to RS
STA _RS-4,Y STA _RS-4,Y
LDA _R0+1,X LDA _R0+1,X
@ -175,70 +175,70 @@ _EXC .( ; EXC r 4r Rr <-> RS - exchange Rr with stack
STA _RS-2,Y STA _RS-2,Y
LDA _R0+3,X LDA _R0+3,X
STA _RS-1,Y STA _RS-1,Y
LDA _RD ; copy RD to Rr LDA _I0 ; copy I0 to Rr
STA _R0,X STA _R0,X
LDA _RD+1 LDA _I0+1
STA _R0+1,X STA _R0+1,X
LDA _RD+2 LDA _I0+2
STA _R0+2,X STA _R0+2,X
LDA _RD+3 LDA _I0+3
STA _R0+3,X STA _R0+3,X
RTS RTS
.) .)
_ADDRD .( ; add RD to register indexed by X _ADDI0X .( ; add I0 to register indexed by X
LDA _R0+3,X LDA _R0+3,X
AND #_MSK_O ; check for existing overflow condition AND #_MSK_O ; check for existing overflow condition
BEQ _4 BEQ _1
EOR #_MSK_O EOR #_MSK_O
BNE _3 ; existing overflow, skip decrement operation BNE _2 ; existing overflow, skip decrement operation
_4 CLC ; adding RD _1 CLC ; adding RD
LDA _RD LDA _I0
ADC _R0,X ADC _R0,X
STA _R0,X STA _R0,X
LDA _RD+1 LDA _I0+1
ADC _R0+1,X ADC _R0+1,X
STA _R0+1,X STA _R0+1,X
LDA _RD+2 LDA _I0+2
ADC _R0+2,X ADC _R0+2,X
STA _R0+2,X STA _R0+2,X
LDA _RD+3 LDA _I0+3
ADC _R0+3,X ADC _R0+3,X
STA _R0+3,X STA _R0+3,X
AND #_MSK_O ; check for overflow AND #_MSK_O ; check for overflow
BEQ _2 BEQ _3
EOR #_MSK_O EOR #_MSK_O
BEQ _2 BEQ _2
_3 LDA _F ; set overflow _2 LDA _F ; set overflow
ORA #_F_O ORA #_F_O
STA _F STA _F
BNE _5 BNE _4
_2 LDA _F ; clear overflow _3 LDA _F ; clear overflow
AND #_F_O^$FF AND #_F_O^$FF
STA _F STA _F
_5 RTS _4 RTS
.) .)
_INR .( ; INR r 5r Rr <- Rr + 1.0 - increment register _INR .( ; INR r 5r Rr <- Rr + 1.0 - increment register
LDA #0 ; set RD to plus one LDA #0 ; set I0 to plus one
STA _RD STA _I0
LDA #_PLS_1 LDA #_PLS_1
STA _RD+1 STA _I0+1
LDA #0 LDA #0
STA _RD+2 STA _I0+2
STA _RD+3 STA _I0+3
BEQ _ADDRD BEQ _ADDI0X
.) .)
_DCR .( ; DCR r 6r Rr <- Rr - 1.0 - decrement register _DCR .( ; DCR r 6r Rr <- Rr - 1.0 - decrement register
LDA #0 ; set RD to minus one LDA #0 ; set I0 to minus one
STA _RD STA _I0
LDA #_MNS_1 LDA #_MNS_1
STA _RD+1 STA _I0+1
LDA #$FF LDA #$FF
STA _RD+2 STA _I0+2
STA _RD+3 STA _I0+3
BNE _ADDRD BNE _ADDI0X
.) .)
_TST .( ; TST r 7r F <- Rr <=> 0.0 - test register _TST .( ; TST r 7r F <- Rr <=> 0.0 - test register
@ -299,117 +299,195 @@ _2 INC _PCL ; advance PC
_3 RTS _3 RTS
.) .)
_RETZD .( ; clears register D, clears underflow, falls through to _TRFDR _ZERI0 .( ; clears I0
LDA #0 LDA #0
STA _RD STA _I0
STA _RD+1 STA _I0+1
STA _RD+2 STA _I0+2
STA _RD+3 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 LDA _F ; clear underflow
AND #_F_U^$FF AND #_F_U^$FF
STA _F 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 PLA
TAX TAX
LDA _RD ; transfer result to Rr JSR _TRFI0X ; transfer result to register indexed by X
STA _R0,X
LDA _RD+1
STA _R0+1,X
LDA _RD+2
STA _R0+2,X
LDA _RD+3
STA _R0+3,X
AND #_MSK_O ; check for overflow AND #_MSK_O ; check for overflow
BEQ _4 BEQ _1
EOR #_MSK_O EOR #_MSK_O
BEQ _4 BEQ _1
_3 LDA _F ; set overflow LDA _F ; set overflow
ORA #_F_O ORA #_F_O
STA _F STA _F
BNE _5 BNE _2
_4 LDA _F ; clear overflow _1 LDA _F ; clear overflow
AND #_F_O^$FF AND #_F_O^$FF
STA _F STA _F
_5 RTS _2 RTS
.) .)
_ADD .( ; ADD r pq ar pq Rr <- Rp + Rq - addition _ADD .( ; ADD r pq ar pq Rr <- Rp + Rq - addition
TXA TXA
PHA ; save r register for later PHA ; save r register for later
JSR _GETPQ JSR _GETPQ
CLC ; set RD to Rp + Rq CLC ; set I0 to Rp + Rq
LDA _R0,X LDA _R0,X
ADC _R0,Y ADC _R0,Y
STA _RD STA _I0
LDA _R0+1,X LDA _R0+1,X
ADC _R0+1,Y ADC _R0+1,Y
STA _RD+1 STA _I0+1
LDA _R0+2,X LDA _R0+2,X
ADC _R0+2,Y ADC _R0+2,Y
STA _RD+2 STA _I0+2
LDA _R0+3,X LDA _R0+3,X
ADC _R0+3,Y ADC _R0+3,Y
STA _RD+3 STA _I0+3
JMP _TRFDR ; pull X, transfer RD to r register, let it handle the return JMP _RETI0X ; pull X, transfer I0 to r register, let it handle the return
.) .)
_SUB .( ; SUB r pq br pq Rr <- Rp - Rq - subtraction _SUB .( ; SUB r pq br pq Rr <- Rp - Rq - subtraction
TXA TXA
PHA ; save r register for later PHA ; save r register for later
JSR _GETPQ JSR _GETPQ
SEC ; set RD to Rp - Rq SEC ; set I0 to Rp - Rq
LDA _R0,X LDA _R0,X
SBC _R0,Y SBC _R0,Y
STA _RD STA _I0
LDA _R0+1,X LDA _R0+1,X
SBC _R0+1,Y SBC _R0+1,Y
STA _RD+1 STA _I0+1
LDA _R0+2,X LDA _R0+2,X
SBC _R0+2,Y SBC _R0+2,Y
STA _RD+2 STA _I0+2
LDA _R0+3,X LDA _R0+3,X
SBC _R0+3,Y SBC _R0+3,Y
STA _RD+3 STA _I0+3
JMP _TRFDR ; pull X, transfer RD to r register, let it handle the return JMP _RETI0X ; pull X, transfer I0 to r register, let it handle the return
.) .)
_TRFQD .( ; transfers Y as q register to RD _NEGX .( ; negates register at X
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
SEC SEC
LDA #0 LDA #0
SBC _R0,Y SBC _R0,X
STA _R0,Y STA _R0,X
LDA #0 LDA #0
SBC _R0+1,Y SBC _R0+1,X
STA _R0+1,Y STA _R0+1,X
LDA #0 LDA #0
SBC _R0+2,Y SBC _R0+2,X
STA _R0+2,Y STA _R0+2,X
LDA #0 LDA #0
SBC _R0+3,Y SBC _R0+3,X
STA _R0+3,Y STA _R0+3,X
RTS RTS
.) .)
_ABSRY .( ; sets register at Y to absolute value _ABSX .( ; sets register at X to absolute value
LDA _R0+3,Y LDA _R0+3,X
BMI _NEGRY BMI _NEGX
RTS 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 _MUL .( ; MUL r pq cr pq Rr <- Rp * Rq - multiplication
TXA ; adapted from http://www.6502.org/source/integers/32muldiv.htm TXA ; adapted from http://www.6502.org/source/integers/32muldiv.htm
PHA ; save r register for later 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+2,X
ORA _R0+3,X ORA _R0+3,X
BNE _1 ; p is non-zero 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 _1 LDA _R0,Y ; check for zero argument
ORA _R0+1,Y ORA _R0+1,Y
ORA _R0+2,Y ORA _R0+2,Y
ORA _R0+3,Y ORA _R0+3,Y
BNE _2 ; q is non-zero BNE _2 ; q is non-zero
JMP _RETZD ; q is zero, return zero JMP _RTZI0X ; q is zero, return zero
_2 LDA _R0+3,X ; save sign of register p _2 LDA _R0+3,X
AND #_MSK_O
PHA
EOR _R0+3,Y EOR _R0+3,Y
AND #_MSK_O ; save sign of product AND #_MSK_O ; save sign of product
PHA PHA
JSR _TRFQD JSR _CPXI0 ; transfer p to I0
TXA LDA _R0,Y ; transfer q to I1
TAY ; absolute value of register p STA _I1
JSR _ABSRY LDA _R0+1,Y
LDY #_RD-_R0 ; absolute value of register q saved in D STA _I1+1
JSR _ABSRY 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 LDA #0
STA _RB+4 ; clear upper half of product STA _I3 ; clear upper half of product in I3
STA _RB+5 STA _I3+1
STA _RB+6 STA _I3+2
STA _RB+7 STA _I3+3
LDY #34 ; thirty bit multiply and four bit shift LDY #34 ; thirty bit multiply and four bit shift to ensure product is aligned
_3 LSR _RD+3 ; shift operand _3 LSR _I1+3 ; get lowest bit of operand
ROR _RD+2 ROR _I1+2
ROR _RD+1 ROR _I1+1
ROR _RD ROR _I1
BCC _4 ; skip adding in product if bit is zero BCC _4 ; skip adding in product if bit is zero
CLC CLC
LDA _RB+4 ; add in p register LDA _I3 ; add in p register
ADC _R0,X ADC _I0
STA _RB+4 STA _I3
LDA _RB+5 LDA _I3+1
ADC _R0+1,X ADC _I0+1
STA _RB+5 STA _I3+1
LDA _RB+6 LDA _I3+2
ADC _R0+2,X ADC _I0+2
STA _RB+6 STA _I3+2
LDA _RB+7 LDA _I3+3
ADC _R0+3,X ADC _I0+3
_4 ROR ; shift the product STA _I3+3
STA _RB+7 _4 LSR _I3+3 ; shift the product down
ROR _RB+6 ROR _I3+2
ROR _RB+5 ROR _I3+1
ROR _RB+4 ROR _I3
ROR _RB+3 ROR _I2+3
ROR _RB+2 ROR _I2+2
ROR _RB+1 ROR _I2+1
ROR _RB ROR _I2
DEY DEY
BNE _3 ; repeat until bits are done BNE _3 ; repeat until bits are done
LDA _RB+1 ; copy result to RD LDX #_I2-_R0
STA _RD JSR _RDXFI0 ; round and transfer to I0, set or clear underflow flag
LDA _RB+2 PLA ; set the sign of the product
STA _RD+1 BEQ _5
LDA _RB+3 LDX #_I0-_R0 ; negate I0
STA _RD+2 JSR _NEGX
LDA _RB+4 _5 JMP _RETI0X ; pull X, transfer I0 to r register, let it handle the return
STA _RD+3 .)
AND #_MSK_O ; consider the overflow bits
ORA _RB+5 ; check all the other bytes _ZERQX .( ; zero quad-word (64 bits) at X
ORA _RB+6 LDA #0
ORA _RB+7 STA _R0,X
BEQ _5 ; all zeroes means no overflow STA _R0+1,X
LDA _RD+3 ; overflow situation, set accordingly STA _R0+2,X
AND #_MSK_O^$FF ; set overflow STA _R0+3,X
ORA #_F_O STA _R0+4,X
STA _RD+3 STA _R0+5,X
BNE _6 STA _R0+6,X
_5 LDA _RD ; check for underflow STA _R0+7,X
ORA _RD+1 RTS
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
.) .)
_INTDM .( ; initialize for DIV and MOD, returns sign of result in A _INTDM .( ; initialize for DIV and MOD, returns sign of result in A
TXA
PHA ; save r register for later
JSR _GETPQ JSR _GETPQ
LDA _R0,X ; check for zero argument LDA _R0,X ; check for zero argument
ORA _R0+1,X ORA _R0+1,X
ORA _R0+2,X ORA _R0+2,X
ORA _R0+3,X ORA _R0+3,X
BNE _1 ; p is non-zero 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 _1 LDA _R0,Y ; check for zero argument
ORA _R0+1,Y ORA _R0+1,Y
ORA _R0+2,Y ORA _R0+2,Y
ORA _R0+3,Y ORA _R0+3,Y
BNE _2 ; q is non-zero BNE _2 ; q is non-zero
BRK ; q is zero, abort and call exception handler (TODO) BRK ; q is zero, abort and call exception handler (TODO)
_2 LDA _R0,X ; copy p to RD ; I0 / I1 will form 64-bit quantity with high order bytes I1 as zero
STA _RD _2 JSR _CPXI0 ; copy p to I0
LDA _R0+1,X LDX #_I1-_R0
STA _RD+1 JSR _ZERQX
LDA _R0+2,X ; I2 / I3 will form 64-bit quantity with low order bytes I2 as zero
STA _RD+2 LDA _R0,Y ; copy q to I3
LDA _R0+3,X STA _I3
STA _RD+3
LDA _R0,Y ; copy q to RC
STA _RC
LDA _R0+1,Y LDA _R0+1,Y
STA _RC+1 STA _I3+1
LDA _R0+2,Y LDA _R0+2,Y
STA _RC+2 STA _I3+2
LDA _R0+3,Y LDA _R0+3,Y
STA _RC+3 STA _I3+3
LDA #0 ; set RB to 1 ; I4 / I5 will form 64-bit result
STA _RB LDX #_I4-_R0
LDA #_PLS_1 JSR _ZERQX
STA _RB+1 LDA _I0+3 ; get sign of result
LDA #0 EOR _I3+3
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
AND #_MSK_O AND #_MSK_O
RTS RTS
.) .)
_CMPDC .( ; compare D to C, return result in status _CMPDM .( ; compare I0/I1 to I2/I3, return result in status
LDA _RD+3 LDA _I1+3
CMP _RC+3 CMP _I3+3
BCC _1 ; definitely less BCC _1 ; definitely less
BNE _1 ; definitely greater BNE _1 ; definitely greater
LDA _RD+2 LDA _I1+2
CMP _RC+2 CMP _I3+2
BCC _1 ; definitely less BCC _1 ; definitely less
BNE _1 ; definitely greater BNE _1 ; definitely greater
LDA _RD+1 LDA _I1+1
CMP _RC+1 CMP _I3+1
BCC _1 ; definitely less BCC _1 ; definitely less
BNE _1 ; definitely greater BNE _1 ; definitely greater
LDA _RD LDA _I1
CMP _RC 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 _1 RTS
.) .)
_UPDDM .( ; update DIV and MOD _UPDDM .( ; update DIV and MOD
SEC ; RD -= RC SEC ; I0/I1 -= I2/I3
LDA _RD LDA _I0
SBC _RC SBC _I2
STA _RD STA _I0
LDA _RD+1 LDA _I0+1
SBC _RC+1 SBC _I2+1
STA _RD+1 STA _I0+1
LDA _RD+2 LDA _I0+2
SBC _RC+2 SBC _I2+2
STA _RD+2 STA _I0+2
LDA _RD+3 LDA _I0+3
SBC _RC+3 SBC _I2+3
STA _RD+3 STA _I0+3
CLC ; RX += RB LDA _I1
LDA _R0,X SBC _I3
ADC _RB STA _I1
STA _R0,X LDA _I1+1
LDA _R0+1,X SBC _I3+1
ADC _RB+1 STA _I1+1
STA _R0+1,X LDA _I1+2
LDA _R0+2,X SBC _I3+2
ADC _RB+2 STA _I1+2
STA _R0+2,X LDA _I1+3
LDA _R0+3,X SBC _I3+3
ADC _RB+3 STA _I1+3
STA _R0+3,X
RTS RTS
.) .)
_SHUDM .( ; shift up for DIV and MOD _SHUDM .( ; shift up for DIV and MOD, C should be set or cleared as required
ASL _RC ; RC *= 2 ROL _I4 ; I4/I5 *= 2
ROL _RC+1 ROL _I4+1
ROL _RC+2 ROL _I4+2
ROL _RC+3 ROL _I4+3
ASL _RB ; RB *= 2 ROL _I5
ROL _RB+1 ROL _I5+1
ROL _RB+2 ROL _I5+2
ROL _RB+3 ROL _I5+3
RTS RTS
.) .)
_SHDDM .( ; shift down for DIV and MOD _SHDDM .( ; shift down for DIV and MOD
CLC ; RC /= 2 CLC ; I2/I3 /= 2
ROR _RC+3 ROR _I3+3
ROR _RC+2 ROR _I3+2
ROR _RC+1 ROR _I3+1
ROR _RC ROR _I3
CLC ; RB /= 2 ROR _I2+3
ROR _RB+3 ROR _I2+2
ROR _RB+2 ROR _I2+1
ROR _RB+1 ROR _I2
ROR _RB
RTS RTS
.) .)
_DIV .( ; DIV r pq dr pq Rr <- Rp / Rq - division _DIV .( ; DIV r pq dr pq Rr <- Rp / Rq - division
TXA
PHA ; save r register for later
JSR _INTDM ; initialize JSR _INTDM ; initialize
PHA ; save sign of result PHA ; save sign of result
LDY #_RD-_R0 ; absolute value of register p saved in D LDX #_I0-_R0 ; absolute value of register p saved in I0
JSR _ABSRY JSR _ABSX
LDY #_RC-_R0 ; absolute value of register q saved in C LDX #_I3-_R0 ; absolute value of register q saved in I3
JSR _ABSRY JSR _ABSX
_3 JSR _CMPDC ; is D < C? LDY #51 ; 51 bits are enough, and ensure alignment
BCC _4 ; yes, continue _1 JSR _CMPDM ; is I0/I1 < I2/I3
BEQ _5 ; D = C BCC _2 ; yes, skip subtraction
JSR _UPDDM ; confirmed D > C, so RD -= RC, RX += RB BEQ _4 ; special case when p = q
JSR _SHUDM ; shift up JSR _UPDDM ; I0/I1 -= I2/I3
BCC _3 ; if carry is set, means a really bad overflow condition _2 JSR _SHUDM ; I4/I5 *= 2 += CARRY
LDA #$FF ; set to the maximum JSR _SHDDM ; I2/I3 /= 2
STA _R0,X DEY
STA _R0+1,X BNE _1
STA _R0+2,X BEQ _5
LDA #_MAX_V|_F_O _3 CLC ; special case when p = q, just shift up to the end
STA _R0+3,X _4 JSR _SHUDM ; I4/I5 *= 2 += CARRY
BNE _9 DEY
_4 LDA _RB ; is RB > 0? BNE _3
ORA _RB+1 _5 LDX #_I4-_R0
ORA _RB+2 JSR _RDXFI0 ; round and transfer to I0, set or clear underflow flag
ORA _RB+3 PLA ; set the sign of the product
BEQ _7 ; no, done BEQ _6
JSR _CMPDC ; is D >= C? LDX #_I0-_R0 ; negate I0
BCC _6 ; no, skip subtraction JSR _NEGX
_5 JSR _UPDDM ; RD -= RC, RX += RB _6 JMP _RETI0X ; pull X, transfer I0 to r register, let it handle the return
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
.) .)
_MOD .( ; MOD r pq er pq Rr <- Rp % Rq - modulus _MOD .(
JSR _INTDM ; initialize RTS
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
.) .)
_ESC .( ; ESC 00 - escape back into regular assembler _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 ; SVI pq 0e pq (int(Rp)) <- Rq - save indirect to memory
; CMR pq 0f pq F <- Rp <=> Rq - compare registers ; CMR pq 0f pq F <- Rp <=> Rq - compare registers
; 64 bytes in page zero for common registers ; 40 bytes in page zero for common registers
_R0 = $c0 _R0 = $b8
_R1 = _R0 + 4 _R1 = _R0 + 4
_R2 = _R1 + 4 _R2 = _R1 + 4
_R3 = _R2 + 4 _R3 = _R2 + 4
@ -57,16 +57,20 @@ _R6 = _R5 + 4
_R7 = _R6 + 4 _R7 = _R6 + 4
_R8 = _R7 + 4 _R8 = _R7 + 4
_R9 = _R8 + 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 ; (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 _PCL = _RSI + 1 ; program counter low
_PCH = _PCL + 1 ; program counter high _PCH = _PCL + 1 ; program counter high
_F = _PCH + 1 ; flags _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_O = 64 ; if overflow (after arithmetic operations)
_F_U = 128 ; if underflow (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 ; (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 _IDX = _ACC + 1 ; saved index X to restore
_IDY = _IDX + 1 ; saved index Y to restore _IDY = _IDX + 1 ; saved index Y to restore
_PS = _IDY + 1 ; saved processor status to restore _PS = _IDY + 1 ; saved processor status to restore

View File

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

View File

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

View File

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