added more missing codegen for bit shifts

This commit is contained in:
Irmen de Jong
2023-07-16 17:39:30 +02:00
parent 64254e758d
commit 47485e4b49
4 changed files with 183 additions and 87 deletions

View File

@@ -512,13 +512,58 @@ internal class AssignmentAsmGen(private val program: PtProgram,
} }
private fun optimizedBitshiftExpr(expr: PtBinaryExpression, target: AsmAssignTarget): Boolean { private fun optimizedBitshiftExpr(expr: PtBinaryExpression, target: AsmAssignTarget): Boolean {
val signed = expr.left.type in SignedDatatypes
val shifts = expr.right.asConstInteger() val shifts = expr.right.asConstInteger()
if(shifts!=null) {
val dt = expr.left.type val dt = expr.left.type
if(shifts==null) {
// bit shifts with variable shifts
when(expr.right.type) {
in ByteDatatypes -> {
assignExpressionToRegister(expr.right, RegisterOrPair.A, false)
}
in WordDatatypes -> {
assignExpressionToRegister(expr.right, RegisterOrPair.AY, false)
asmgen.out("""
cpy #0
beq +
lda #127
+""")
}
else -> throw AssemblyError("weird shift value type")
}
asmgen.out(" pha")
if(dt in ByteDatatypes) { if(dt in ByteDatatypes) {
val signed = dt == DataType.BYTE
assignExpressionToRegister(expr.left, RegisterOrPair.A, signed) assignExpressionToRegister(expr.left, RegisterOrPair.A, signed)
if(shifts in 0..7) { asmgen.out(" ply")
if(expr.operator==">>")
if(signed)
asmgen.out(" jsr math.lsr_byte_A")
else
asmgen.out(" jsr math.lsr_ubyte_A")
else
asmgen.out(" jsr math.asl_byte_A")
assignRegisterByte(target, CpuRegister.A, signed)
return true
} else {
assignExpressionToRegister(expr.left, RegisterOrPair.AY, signed)
asmgen.out(" plx")
if(expr.operator==">>")
if(signed)
asmgen.out(" jsr math.lsr_word_AY")
else
asmgen.out(" jsr math.lsr_uword_AY")
else
asmgen.out(" jsr math.asl_word_AY")
assignRegisterpairWord(target, RegisterOrPair.AY)
return true
}
}
else {
// bit shift with constant value
if(dt in ByteDatatypes) {
assignExpressionToRegister(expr.left, RegisterOrPair.A, signed)
when (shifts) {
in 0..7 -> {
require(dt==DataType.UBYTE) require(dt==DataType.UBYTE)
if (expr.operator == "<<") { if (expr.operator == "<<") {
repeat(shifts) { repeat(shifts) {
@@ -535,7 +580,8 @@ internal class AssignmentAsmGen(private val program: PtProgram,
} }
assignRegisterByte(target, CpuRegister.A, signed) assignRegisterByte(target, CpuRegister.A, signed)
return true return true
} else { }
else -> {
if(signed && expr.operator==">>") { if(signed && expr.operator==">>") {
TODO("signed byte >> overshift should have been compiled away?") TODO("signed byte >> overshift should have been compiled away?")
} else { } else {
@@ -544,10 +590,11 @@ internal class AssignmentAsmGen(private val program: PtProgram,
assignRegisterByte(target, CpuRegister.A, signed) assignRegisterByte(target, CpuRegister.A, signed)
return true return true
} }
}
} else if(dt in WordDatatypes) { } else if(dt in WordDatatypes) {
val signed = dt == DataType.WORD
assignExpressionToRegister(expr.left, RegisterOrPair.AY, signed) assignExpressionToRegister(expr.left, RegisterOrPair.AY, signed)
if(shifts in 0..7) { when (shifts) {
in 0..7 -> {
if(expr.operator=="<<") { if(expr.operator=="<<") {
if(shifts>0) { if(shifts>0) {
asmgen.out(" sty P8ZP_SCRATCH_B1") asmgen.out(" sty P8ZP_SCRATCH_B1")
@@ -571,7 +618,8 @@ internal class AssignmentAsmGen(private val program: PtProgram,
} }
assignRegisterpairWord(target, RegisterOrPair.AY) assignRegisterpairWord(target, RegisterOrPair.AY)
return true return true
} else if (shifts in 8..15) { }
in 8..15 -> {
if(expr.operator == "<<") { if(expr.operator == "<<") {
// msb = lsb << (shifts-8), lsb = 0 // msb = lsb << (shifts-8), lsb = 0
repeat(shifts-8) { repeat(shifts-8) {
@@ -584,7 +632,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
assignRegisterpairWord(target, RegisterOrPair.AY) assignRegisterpairWord(target, RegisterOrPair.AY)
return true return true
} }
else { else -> {
if(signed && expr.operator==">>") { if(signed && expr.operator==">>") {
TODO("signed word >> overshift should have been compiled away?") TODO("signed word >> overshift should have been compiled away?")
} else { } else {
@@ -595,6 +643,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
} }
} }
} }
}
return false return false
} }

View File

@@ -751,37 +751,64 @@ mul_word_640 .proc
lsr_byte_A .proc lsr_byte_A .proc
; -- lsr signed byte in A times the value in Y (>1) ; -- lsr signed byte in A times the value in Y (>1)
cmp #0 cmp #0
bmi _negative bpl lsr_ubyte_A
- lsr a - sec
dey
bne -
rts
_negative sec
ror a ror a
dey dey
bne _negative bne -
rts rts
.pend .pend
lsr_ubyte_A .proc
; -- lsr unsigned byte in A times the value in Y (>1)
- lsr a
dey
bne -
rts
.pend
asl_byte_A .proc
; -- asl any byte in A times the value in Y (>1)
- asl a
dey
bne -
rts
.pend
lsr_word_AY .proc lsr_word_AY .proc
; -- lsr signed word in AY times the value in X (>1) ; -- lsr signed word in AY times the value in X (>1)
sta P8ZP_SCRATCH_B1 cpy #0
tya bpl lsr_uword_AY
bmi _negative sty P8ZP_SCRATCH_B1
- lsr a
ror P8ZP_SCRATCH_B1
dex
bne -
tay
lda P8ZP_SCRATCH_B1
rts
_negative sec _negative sec
ror a
ror P8ZP_SCRATCH_B1 ror P8ZP_SCRATCH_B1
ror a
dex dex
bne _negative bne _negative
tay ldy P8ZP_SCRATCH_B1
lda P8ZP_SCRATCH_B1 rts
.pend
lsr_uword_AY .proc
; -- lsr unsigned word in AY times the value in X (>1)
sty P8ZP_SCRATCH_B1
- lsr P8ZP_SCRATCH_B1
ror a
dex
bne -
ldy P8ZP_SCRATCH_B1
rts
.pend
asl_word_AY .proc
; -- asl any word in AY times the value in X (>1)
sty P8ZP_SCRATCH_B1
- asl a
rol P8ZP_SCRATCH_B1
dex
bne -
ldy P8ZP_SCRATCH_B1
rts rts
.pend .pend

View File

@@ -1,6 +1,9 @@
TODO TODO
==== ====
- (branch): fix float expressions codegen, it relied heavily on the evalstack
- (branch): improve integer expression codegen even more to support even more cases?
- IR: instructions that do type conversion (SZ etc, CONCAT, SGN) should put the result in a DIFFERENT register. - IR: instructions that do type conversion (SZ etc, CONCAT, SGN) should put the result in a DIFFERENT register.
- IR: reduce the number of branch instructions (gradually), replace with CMP(I) + status branch instruction - IR: reduce the number of branch instructions (gradually), replace with CMP(I) + status branch instruction

View File

@@ -5,15 +5,32 @@ main
{ {
sub start() sub start()
{ {
byte zc = -55 uword zc = 54321
ubyte zb = 123
ubyte shift = 2
when zc*3 { txt.print_uw(zc<<shift)
123 -> zc++ txt.nl()
124 -> zc++ txt.print_uw(zc>>shift)
125 -> zc++ txt.nl()
121 -> zc++ txt.print_ub(zb<<shift)
120 -> zc++ txt.nl()
else -> zc++ txt.print_ub(zb>>shift)
} txt.nl()
word szc = -12345
byte szb = -123
txt.print_w(szc<<shift)
txt.nl()
txt.print_w(szc>>shift)
txt.nl()
txt.print_b(szb<<shift)
txt.nl()
txt.print_b(szb>>shift)
txt.nl()
; cx16.r1L = (zc<<shift) as ubyte
; txt.print_ub(cx16.r1L)
} }
} }