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,86 +512,135 @@ 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")
require(dt==DataType.UBYTE) if(expr.operator==">>")
if (expr.operator == "<<") { if(signed)
repeat(shifts) { asmgen.out(" jsr math.lsr_byte_A")
asmgen.out(" asl a") else
} asmgen.out(" jsr math.lsr_ubyte_A")
} else { else
if (signed && shifts > 0) { asmgen.out(" jsr math.asl_byte_A")
asmgen.out(" ldy #$shifts | jsr math.lsr_byte_A") assignRegisterByte(target, CpuRegister.A, signed)
} else { 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)
if (expr.operator == "<<") {
repeat(shifts) { repeat(shifts) {
asmgen.out(" lsr a") asmgen.out(" asl a")
}
} else {
if (signed && shifts > 0) {
asmgen.out(" ldy #$shifts | jsr math.lsr_byte_A")
} else {
repeat(shifts) {
asmgen.out(" lsr a")
}
} }
} }
assignRegisterByte(target, CpuRegister.A, signed)
return true
} }
assignRegisterByte(target, CpuRegister.A, signed) else -> {
return true if(signed && expr.operator==">>") {
} else { TODO("signed byte >> overshift should have been compiled away?")
if(signed && expr.operator==">>") { } else {
TODO("signed byte >> overshift should have been compiled away?") asmgen.out(" lda #0")
} else { }
asmgen.out(" lda #0") assignRegisterByte(target, CpuRegister.A, signed)
return true
} }
assignRegisterByte(target, CpuRegister.A, signed)
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) {
if(expr.operator=="<<") { in 0..7 -> {
if(shifts>0) { if(expr.operator=="<<") {
asmgen.out(" sty P8ZP_SCRATCH_B1")
repeat(shifts) {
asmgen.out(" asl a | rol P8ZP_SCRATCH_B1")
}
asmgen.out(" ldy P8ZP_SCRATCH_B1")
}
} else {
if(signed && shifts>0) {
asmgen.out(" ldx #$shifts | jsr math.lsr_word_AY")
} else {
if(shifts>0) { if(shifts>0) {
asmgen.out(" sty P8ZP_SCRATCH_B1") asmgen.out(" sty P8ZP_SCRATCH_B1")
repeat(shifts) { repeat(shifts) {
asmgen.out(" lsr P8ZP_SCRATCH_B1 | ror a") asmgen.out(" asl a | rol P8ZP_SCRATCH_B1")
} }
asmgen.out(" ldy P8ZP_SCRATCH_B1") asmgen.out(" ldy P8ZP_SCRATCH_B1")
} }
} else {
if(signed && shifts>0) {
asmgen.out(" ldx #$shifts | jsr math.lsr_word_AY")
} else {
if(shifts>0) {
asmgen.out(" sty P8ZP_SCRATCH_B1")
repeat(shifts) {
asmgen.out(" lsr P8ZP_SCRATCH_B1 | ror a")
}
asmgen.out(" ldy P8ZP_SCRATCH_B1")
}
}
} }
assignRegisterpairWord(target, RegisterOrPair.AY)
return true
} }
assignRegisterpairWord(target, RegisterOrPair.AY) in 8..15 -> {
return true if(expr.operator == "<<") {
} else if (shifts in 8..15) { // msb = lsb << (shifts-8), lsb = 0
if(expr.operator == "<<") { repeat(shifts-8) {
// msb = lsb << (shifts-8), lsb = 0 asmgen.out(" asl a")
repeat(shifts-8) { }
asmgen.out(" asl a") asmgen.out(" tay | lda #0")
} else {
asmgen.out(" ldx #$shifts | jsr math.lsr_word_AY")
} }
asmgen.out(" tay | lda #0") assignRegisterpairWord(target, RegisterOrPair.AY)
} else { return true
asmgen.out(" ldx #$shifts | jsr math.lsr_word_AY")
} }
assignRegisterpairWord(target, RegisterOrPair.AY) else -> {
return true if(signed && expr.operator==">>") {
} TODO("signed word >> overshift should have been compiled away?")
else { } else {
if(signed && expr.operator==">>") { asmgen.out(" lda #0 | ldy #0")
TODO("signed word >> overshift should have been compiled away?") }
} else { assignRegisterpairWord(target, RegisterOrPair.AY)
asmgen.out(" lda #0 | ldy #0") return true
} }
assignRegisterpairWord(target, RegisterOrPair.AY)
return true
} }
} }
} }

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)
} }
} }