mirror of
https://github.com/irmen/prog8.git
synced 2025-08-15 14:27:37 +00:00
added more missing codegen for bit shifts
This commit is contained in:
@@ -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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
|
||||||
|
@@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user