mirror of
https://github.com/irmen/prog8.git
synced 2024-12-25 23:29:55 +00:00
implemented signed byte and word division
This commit is contained in:
parent
9154d8bd37
commit
e112dfd910
@ -86,8 +86,40 @@ result .byte 0,0,0,0
|
||||
.pend
|
||||
|
||||
|
||||
divmod_b_asm .proc
|
||||
; signed byte division: make everything positive and fix sign afterwards
|
||||
sta P8ZP_SCRATCH_B1
|
||||
tya
|
||||
eor P8ZP_SCRATCH_B1
|
||||
php ; save sign
|
||||
lda P8ZP_SCRATCH_B1
|
||||
bpl +
|
||||
eor #$ff
|
||||
sec
|
||||
adc #0 ; make it positive
|
||||
+ pha
|
||||
tya
|
||||
bpl +
|
||||
eor #$ff
|
||||
sec
|
||||
adc #0 ; make it positive
|
||||
tay
|
||||
+ pla
|
||||
jsr divmod_ub_asm
|
||||
sta _remainder
|
||||
plp
|
||||
bpl +
|
||||
tya
|
||||
eor #$ff
|
||||
sec
|
||||
adc #0 ; negate result
|
||||
tay
|
||||
+ rts
|
||||
_remainder .byte 0
|
||||
.pend
|
||||
|
||||
|
||||
divmod_ub_asm .proc
|
||||
; TODO divmod_ub_asm doesn't work correctly. (remainder = ok, quotient = FAULTY)
|
||||
; -- divide A by Y, result quotient in Y, remainder in A (unsigned)
|
||||
; division by zero will result in quotient = 255 and remainder = original number
|
||||
sty P8ZP_SCRATCH_REG
|
||||
@ -109,6 +141,49 @@ divmod_ub_asm .proc
|
||||
rts
|
||||
.pend
|
||||
|
||||
divmod_w_asm .proc
|
||||
; signed word division: make everything positive and fix sign afterwards
|
||||
sta P8ZP_SCRATCH_W2
|
||||
sty P8ZP_SCRATCH_W2+1
|
||||
lda P8ZP_SCRATCH_W1+1
|
||||
eor P8ZP_SCRATCH_W2+1
|
||||
php ; save sign
|
||||
lda P8ZP_SCRATCH_W1+1
|
||||
bpl +
|
||||
lda #0
|
||||
sec
|
||||
sbc P8ZP_SCRATCH_W1
|
||||
sta P8ZP_SCRATCH_W1
|
||||
lda #0
|
||||
sbc P8ZP_SCRATCH_W1+1
|
||||
sta P8ZP_SCRATCH_W1+1
|
||||
+ lda P8ZP_SCRATCH_W2+1
|
||||
bpl +
|
||||
lda #0
|
||||
sec
|
||||
sbc P8ZP_SCRATCH_W2
|
||||
sta P8ZP_SCRATCH_W2
|
||||
lda #0
|
||||
sbc P8ZP_SCRATCH_W2+1
|
||||
sta P8ZP_SCRATCH_W2+1
|
||||
+ tay
|
||||
lda P8ZP_SCRATCH_W2
|
||||
jsr divmod_uw_asm
|
||||
plp ; restore sign
|
||||
bpl +
|
||||
sta P8ZP_SCRATCH_W2
|
||||
sty P8ZP_SCRATCH_W2+1
|
||||
lda #0
|
||||
sec
|
||||
sbc P8ZP_SCRATCH_W2
|
||||
pha
|
||||
lda #0
|
||||
sbc P8ZP_SCRATCH_W2+1
|
||||
tay
|
||||
pla
|
||||
+ rts
|
||||
.pend
|
||||
|
||||
divmod_uw_asm .proc
|
||||
; -- divide two unsigned words (16 bit each) into 16 bit results
|
||||
; input: P8ZP_SCRATCH_W1 in ZP: 16 bit number, A/Y: 16 bit divisor
|
||||
|
@ -251,16 +251,16 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
else
|
||||
asmgen.out(" sta (P8ZP_SCRATCH_W1),y")
|
||||
}
|
||||
"*" -> TODO("mul")// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
||||
"/" -> TODO("div")// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
||||
"*" -> TODO("mul mem byte")// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
||||
"/" -> TODO("div mem byte")// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
||||
"%" -> {
|
||||
TODO("byte remainder")
|
||||
TODO("mem byte remainder")
|
||||
// if(types==DataType.BYTE)
|
||||
// throw AssemblyError("remainder of signed integers is not properly defined/implemented, use unsigned instead")
|
||||
// asmgen.out(" jsr prog8_lib.remainder_ub")
|
||||
}
|
||||
"<<" -> TODO("ubyte asl")
|
||||
">>" -> TODO("ubyte lsr")
|
||||
"<<" -> TODO("mem ubyte asl")
|
||||
">>" -> TODO("mem ubyte lsr")
|
||||
"&" -> {
|
||||
val (ptrOnZp, sourceName) = asmgen.loadByteFromPointerIntoA(pointervar)
|
||||
asmgen.out(" and P8ESTACK_LO+1,x")
|
||||
@ -310,16 +310,16 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
else
|
||||
asmgen.out(" sta (P8ZP_SCRATCH_W1),y")
|
||||
}
|
||||
"*" -> TODO("mul")// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
||||
"/" -> TODO("div")// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
||||
"*" -> TODO("mem mul")// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
||||
"/" -> TODO("mem div")// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
||||
"%" -> {
|
||||
TODO("byte remainder")
|
||||
TODO("mem byte remainder")
|
||||
// if(types==DataType.BYTE)
|
||||
// throw AssemblyError("remainder of signed integers is not properly defined/implemented, use unsigned instead")
|
||||
// asmgen.out(" jsr prog8_lib.remainder_ub")
|
||||
}
|
||||
"<<" -> TODO("ubyte asl")
|
||||
">>" -> TODO("ubyte lsr")
|
||||
"<<" -> TODO("mem ubyte asl")
|
||||
">>" -> TODO("mem ubyte lsr")
|
||||
"&" -> {
|
||||
val (ptrOnZp, sourceName) = asmgen.loadByteFromPointerIntoA(pointervar)
|
||||
asmgen.out(" and $otherName")
|
||||
@ -368,19 +368,19 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
asmgen.out(" sta (P8ZP_SCRATCH_W1),y")
|
||||
}
|
||||
"*" -> {
|
||||
TODO("mul byte litval")
|
||||
TODO("mem mul byte litval")
|
||||
// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
||||
}
|
||||
"/" -> {
|
||||
if(value==0)
|
||||
throw AssemblyError("division by zero")
|
||||
TODO("div byte litval")
|
||||
TODO("mem div byte litval")
|
||||
// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
||||
}
|
||||
"%" -> {
|
||||
if(value==0)
|
||||
throw AssemblyError("division by zero")
|
||||
TODO("byte remainder litval")
|
||||
TODO("mem byte remainder litval")
|
||||
// if(types==DataType.BYTE)
|
||||
// throw AssemblyError("remainder of signed integers is not properly defined/implemented, use unsigned instead")
|
||||
// asmgen.out(" jsr prog8_lib.remainder_ub")
|
||||
@ -443,14 +443,14 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
"+" -> asmgen.out(" lda $name | clc | adc P8ESTACK_LO+1,x | sta $name")
|
||||
"-" -> asmgen.out(" lda $name | sec | sbc P8ESTACK_LO+1,x | sta $name")
|
||||
"*" -> {
|
||||
TODO("mul byte expr")
|
||||
TODO("var mul byte expr")
|
||||
// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
||||
}
|
||||
"/" -> {
|
||||
TODO("div byte expr")// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
||||
TODO("var div byte expr")// asmgen.out(if(types==DataType.UBYTE) " jsr prog8_lib.idiv_ub" else " jsr prog8_lib.idiv_b")
|
||||
}
|
||||
"%" -> {
|
||||
TODO("byte remainder expr")
|
||||
TODO("var byte remainder expr")
|
||||
// if(types==DataType.BYTE)
|
||||
// throw AssemblyError("remainder of signed integers is not properly defined/implemented, use unsigned instead")
|
||||
// asmgen.out(" jsr prog8_lib.remainder_ub")
|
||||
@ -507,7 +507,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
"*" -> asmgen.out(" lda $name | ldy $otherName | jsr math.multiply_bytes | sta $name")
|
||||
"/" -> {
|
||||
if(dt==DataType.BYTE) {
|
||||
TODO("signed byte divide see prog8lib.idiv_b")
|
||||
asmgen.out(" lda $name | ldy $otherName | jsr math.divmod_b_asm | sty $name")
|
||||
}
|
||||
else {
|
||||
asmgen.out(" lda $name | ldy $otherName | jsr math.divmod_ub_asm | sty $name")
|
||||
@ -574,7 +574,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
"-" -> asmgen.out(" lda $name | sec | sbc #$value | sta $name")
|
||||
"*" -> {
|
||||
// TODO what about the optimized mul_5 etc routines?
|
||||
TODO("byte mul litval")
|
||||
TODO("var byte mul litval")
|
||||
// asmgen.out(" jsr prog8_lib.mul_byte") // the optimized routines should have been checked earlier
|
||||
}
|
||||
"/" -> {
|
||||
@ -586,7 +586,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
sty $name
|
||||
""")
|
||||
} else {
|
||||
TODO("BYTE div litval")
|
||||
TODO("var BYTE div litval")
|
||||
}
|
||||
}
|
||||
"%" -> {
|
||||
@ -688,7 +688,17 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
if(value==0)
|
||||
throw AssemblyError("division by zero")
|
||||
if(dt==DataType.WORD) {
|
||||
TODO("signed word divide see prog8lib.idiv_w")
|
||||
asmgen.out("""
|
||||
lda $name
|
||||
ldy $name+1
|
||||
sta P8ZP_SCRATCH_W1
|
||||
sty P8ZP_SCRATCH_W1+1
|
||||
lda #<$value
|
||||
ldy #>$value
|
||||
jsr math.divmod_w_asm
|
||||
sta $name
|
||||
sty $name+1
|
||||
""")
|
||||
}
|
||||
else {
|
||||
asmgen.out("""
|
||||
@ -863,7 +873,17 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
}
|
||||
"/" -> {
|
||||
if(dt==DataType.WORD) {
|
||||
TODO("signed word divide see prog8lib.idiv_w")
|
||||
asmgen.out("""
|
||||
lda $name
|
||||
ldy $name+1
|
||||
sta P8ZP_SCRATCH_W1
|
||||
sty P8ZP_SCRATCH_W1+1
|
||||
lda $otherName
|
||||
ldy $otherName+1
|
||||
jsr math.divmod_w_asm
|
||||
sta $name
|
||||
sty $name+1
|
||||
""")
|
||||
}
|
||||
else {
|
||||
asmgen.out("""
|
||||
@ -1007,7 +1027,17 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
|
||||
}
|
||||
"/" -> {
|
||||
if (dt == DataType.WORD) {
|
||||
TODO("signed word divide see prog8lib.idiv_w")
|
||||
asmgen.out("""
|
||||
lda $name
|
||||
ldy $name+1
|
||||
sta P8ZP_SCRATCH_W1
|
||||
sty P8ZP_SCRATCH_W1+1
|
||||
lda P8ESTACK_LO+1,x
|
||||
ldy P8ESTACK_HI+1,x
|
||||
jsr math.divmod_w_asm
|
||||
sta $name
|
||||
sty $name+1
|
||||
""")
|
||||
} else {
|
||||
asmgen.out("""
|
||||
lda $name
|
||||
|
@ -30,7 +30,7 @@ internal object CX16MachineDefinition: IMachineDefinition {
|
||||
|
||||
override fun getFloat(num: Number) = C64MachineDefinition.Mflpt5.fromNumber(num)
|
||||
|
||||
override fun getFloatRomConst(number: Double): String? = null // TODO Does Cx16 have ROM float locations?
|
||||
override fun getFloatRomConst(number: Double): String? = null // Cx16 has no pulblic ROM float locations
|
||||
override fun importLibs(compilerOptions: CompilationOptions, importer: ModuleImporter, program: Program) {
|
||||
if (compilerOptions.launcher == LauncherType.BASIC || compilerOptions.output == OutputType.PRG)
|
||||
importer.importLibraryModule(program, "cx16lib")
|
||||
@ -58,16 +58,17 @@ internal object CX16MachineDefinition: IMachineDefinition {
|
||||
}
|
||||
|
||||
// 6502 opcodes (including aliases and illegal opcodes), these cannot be used as variable or label names
|
||||
// TODO add 65C02 opcodes
|
||||
override val opcodeNames = setOf("adc", "ahx", "alr", "anc", "and", "ane", "arr", "asl", "asr", "axs", "bcc", "bcs",
|
||||
override val opcodeNames = setOf("adc", "and", "asl", "bcc", "bcs",
|
||||
"beq", "bge", "bit", "blt", "bmi", "bne", "bpl", "brk", "bvc", "bvs", "clc",
|
||||
"cld", "cli", "clv", "cmp", "cpx", "cpy", "dcm", "dcp", "dec", "dex", "dey",
|
||||
"cld", "cli", "clv", "cmp", "cpx", "cpy", "dec", "dex", "dey",
|
||||
"eor", "gcc", "gcs", "geq", "gge", "glt", "gmi", "gne", "gpl", "gvc", "gvs",
|
||||
"inc", "ins", "inx", "iny", "isb", "isc", "jam", "jmp", "jsr", "lae", "las",
|
||||
"lax", "lda", "lds", "ldx", "ldy", "lsr", "lxa", "nop", "ora", "pha", "php",
|
||||
"pla", "plp", "rla", "rol", "ror", "rra", "rti", "rts", "sax", "sbc", "sbx",
|
||||
"sec", "sed", "sei", "sha", "shl", "shr", "shs", "shx", "shy", "slo", "sre",
|
||||
"sta", "stx", "sty", "tas", "tax", "tay", "tsx", "txa", "txs", "tya", "xaa")
|
||||
"inc", "inx", "iny", "jmp", "jsr",
|
||||
"lda", "ldx", "ldy", "lsr", "nop", "ora", "pha", "php",
|
||||
"pla", "plp", "rol", "ror", "rti", "rts", "sbc",
|
||||
"sec", "sed", "sei",
|
||||
"sta", "stx", "sty", "tax", "tay", "tsx", "txa", "txs", "tya",
|
||||
"bra", "phx", "phy", "plx", "ply", "stz", "trb", "tsb", "bbr", "bbs",
|
||||
"rmb", "smb", "stp", "wai")
|
||||
|
||||
|
||||
internal class CX16Zeropage(options: CompilationOptions) : Zeropage(options) {
|
||||
|
@ -2,8 +2,6 @@
|
||||
%import c64textio
|
||||
%zeropage basicsafe
|
||||
|
||||
; TODO implement signed byte/word DIV asm generation, fix unsigned DIV asm generation (for in-place)
|
||||
|
||||
main {
|
||||
|
||||
sub start() {
|
||||
@ -11,17 +9,17 @@ main {
|
||||
div_ubyte(100, 6, 16)
|
||||
div_ubyte(255, 2, 127)
|
||||
|
||||
;div_byte(0, 1, 0) ; TODO implement
|
||||
;div_byte(100, -6, -16) ; TODO implement
|
||||
;div_byte(127, -2, -63) ; TODO implement
|
||||
div_byte(0, 1, 0)
|
||||
div_byte(100, -6, -16)
|
||||
div_byte(127, -2, -63)
|
||||
|
||||
div_uword(0,1,0)
|
||||
div_uword(40000,500,80)
|
||||
div_uword(43211,2,21605)
|
||||
|
||||
;div_word(0,1,0) ; TODO implement
|
||||
;div_word(-20000,500,-40) ; TODO implement
|
||||
;div_word(-2222,2,-1111) ; TODO implement
|
||||
div_word(0,1,0)
|
||||
div_word(-20000,500,-40)
|
||||
div_word(-2222,2,-1111)
|
||||
|
||||
div_float(0,1,0)
|
||||
div_float(999.9,111.0,9.008108108108107)
|
||||
|
116
examples/test.p8
116
examples/test.p8
@ -3,16 +3,116 @@
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
ubyte b1 = 2
|
||||
ubyte b2 = 13
|
||||
ubyte b3 = 100
|
||||
byte b1
|
||||
byte b2
|
||||
byte b3
|
||||
|
||||
uword w1 = 2222
|
||||
uword w2 = 11
|
||||
uword w3 = 33
|
||||
word w1
|
||||
word w2
|
||||
word w3
|
||||
|
||||
w1 %= (w2+w3)
|
||||
txt.print_uw(w1)
|
||||
|
||||
b2 = 13
|
||||
b3 = 100
|
||||
b1 = b3 / b2
|
||||
txt.print_b(b1)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
b2 = -13
|
||||
b3 = 100
|
||||
b1 = b3 / b2
|
||||
txt.print_b(b1)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
b2 = 13
|
||||
b3 = -100
|
||||
b1 = b3 / b2
|
||||
txt.print_b(b1)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
b2 = -13
|
||||
b3 = -100
|
||||
b1 = b3 / b2
|
||||
txt.print_b(b1)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
|
||||
b2 = 13
|
||||
b3 = 100
|
||||
b3 /= b2
|
||||
txt.print_b(b3)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
b2 = -13
|
||||
b3 = 100
|
||||
b3 /= b2
|
||||
txt.print_b(b3)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
b2 = 13
|
||||
b3 = -100
|
||||
b3 /= b2
|
||||
txt.print_b(b3)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
b2 = -13
|
||||
b3 = -100
|
||||
b3 /= b2
|
||||
txt.print_b(b3)
|
||||
c64.CHROUT('\n')
|
||||
c64.CHROUT('\n')
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
w2 = 133
|
||||
w3 = 20000
|
||||
w1 = w3 / w2
|
||||
txt.print_w(w1)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
w2 = -133
|
||||
w3 = 20000
|
||||
w1 = w3 / w2
|
||||
txt.print_w(w1)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
w2 = 133
|
||||
w3 = -20000
|
||||
w1 = w3 / w2
|
||||
txt.print_w(w1)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
w2 = -133
|
||||
w3 = -20000
|
||||
w1 = w3 / w2
|
||||
txt.print_w(w1)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
|
||||
w2 = 133
|
||||
w3 = 20000
|
||||
w3 /= w2
|
||||
txt.print_w(w3)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
w2 = -133
|
||||
w3 = 20000
|
||||
w3 /= w2
|
||||
txt.print_w(w3)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
w2 = 133
|
||||
w3 = -20000
|
||||
w3 /= w2
|
||||
txt.print_w(w3)
|
||||
c64.CHROUT('\n')
|
||||
|
||||
w2 = -133
|
||||
w3 = -20000
|
||||
w3 /= w2
|
||||
txt.print_w(w3)
|
||||
c64.CHROUT('\n')
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user