mirror of
https://github.com/irmen/prog8.git
synced 2025-01-10 20:30:23 +00:00
added more missing codegen for bit shifts
This commit is contained in:
parent
64254e758d
commit
47485e4b49
@ -512,86 +512,135 @@ internal class AssignmentAsmGen(private val program: PtProgram,
|
||||
}
|
||||
|
||||
private fun optimizedBitshiftExpr(expr: PtBinaryExpression, target: AsmAssignTarget): Boolean {
|
||||
val signed = expr.left.type in SignedDatatypes
|
||||
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) {
|
||||
val signed = dt == DataType.BYTE
|
||||
assignExpressionToRegister(expr.left, RegisterOrPair.A, signed)
|
||||
if(shifts in 0..7) {
|
||||
require(dt==DataType.UBYTE)
|
||||
if (expr.operator == "<<") {
|
||||
repeat(shifts) {
|
||||
asmgen.out(" asl a")
|
||||
}
|
||||
} else {
|
||||
if (signed && shifts > 0) {
|
||||
asmgen.out(" ldy #$shifts | jsr math.lsr_byte_A")
|
||||
} else {
|
||||
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)
|
||||
if (expr.operator == "<<") {
|
||||
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)
|
||||
return true
|
||||
} else {
|
||||
if(signed && expr.operator==">>") {
|
||||
TODO("signed byte >> overshift should have been compiled away?")
|
||||
} else {
|
||||
asmgen.out(" lda #0")
|
||||
else -> {
|
||||
if(signed && expr.operator==">>") {
|
||||
TODO("signed byte >> overshift should have been compiled away?")
|
||||
} else {
|
||||
asmgen.out(" lda #0")
|
||||
}
|
||||
assignRegisterByte(target, CpuRegister.A, signed)
|
||||
return true
|
||||
}
|
||||
assignRegisterByte(target, CpuRegister.A, signed)
|
||||
return true
|
||||
}
|
||||
} else if(dt in WordDatatypes) {
|
||||
val signed = dt == DataType.WORD
|
||||
assignExpressionToRegister(expr.left, RegisterOrPair.AY, signed)
|
||||
if(shifts in 0..7) {
|
||||
if(expr.operator=="<<") {
|
||||
if(shifts>0) {
|
||||
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 {
|
||||
when (shifts) {
|
||||
in 0..7 -> {
|
||||
if(expr.operator=="<<") {
|
||||
if(shifts>0) {
|
||||
asmgen.out(" sty P8ZP_SCRATCH_B1")
|
||||
repeat(shifts) {
|
||||
asmgen.out(" lsr P8ZP_SCRATCH_B1 | ror a")
|
||||
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) {
|
||||
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)
|
||||
return true
|
||||
} else if (shifts in 8..15) {
|
||||
if(expr.operator == "<<") {
|
||||
// msb = lsb << (shifts-8), lsb = 0
|
||||
repeat(shifts-8) {
|
||||
asmgen.out(" asl a")
|
||||
in 8..15 -> {
|
||||
if(expr.operator == "<<") {
|
||||
// msb = lsb << (shifts-8), lsb = 0
|
||||
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")
|
||||
} else {
|
||||
asmgen.out(" ldx #$shifts | jsr math.lsr_word_AY")
|
||||
assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||
return true
|
||||
}
|
||||
assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||
return true
|
||||
}
|
||||
else {
|
||||
if(signed && expr.operator==">>") {
|
||||
TODO("signed word >> overshift should have been compiled away?")
|
||||
} else {
|
||||
asmgen.out(" lda #0 | ldy #0")
|
||||
else -> {
|
||||
if(signed && expr.operator==">>") {
|
||||
TODO("signed word >> overshift should have been compiled away?")
|
||||
} else {
|
||||
asmgen.out(" lda #0 | ldy #0")
|
||||
}
|
||||
assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||
return true
|
||||
}
|
||||
assignRegisterpairWord(target, RegisterOrPair.AY)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -751,37 +751,64 @@ mul_word_640 .proc
|
||||
lsr_byte_A .proc
|
||||
; -- lsr signed byte in A times the value in Y (>1)
|
||||
cmp #0
|
||||
bmi _negative
|
||||
- lsr a
|
||||
dey
|
||||
bne -
|
||||
rts
|
||||
_negative sec
|
||||
bpl lsr_ubyte_A
|
||||
- sec
|
||||
ror a
|
||||
dey
|
||||
bne _negative
|
||||
bne -
|
||||
rts
|
||||
.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 signed word in AY times the value in X (>1)
|
||||
sta P8ZP_SCRATCH_B1
|
||||
tya
|
||||
bmi _negative
|
||||
- lsr a
|
||||
ror P8ZP_SCRATCH_B1
|
||||
dex
|
||||
bne -
|
||||
tay
|
||||
lda P8ZP_SCRATCH_B1
|
||||
rts
|
||||
cpy #0
|
||||
bpl lsr_uword_AY
|
||||
sty P8ZP_SCRATCH_B1
|
||||
_negative sec
|
||||
ror a
|
||||
ror P8ZP_SCRATCH_B1
|
||||
ror a
|
||||
dex
|
||||
bne _negative
|
||||
tay
|
||||
lda P8ZP_SCRATCH_B1
|
||||
ldy 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
|
||||
.pend
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
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: reduce the number of branch instructions (gradually), replace with CMP(I) + status branch instruction
|
||||
|
||||
|
@ -5,15 +5,32 @@ main
|
||||
{
|
||||
sub start()
|
||||
{
|
||||
byte zc = -55
|
||||
uword zc = 54321
|
||||
ubyte zb = 123
|
||||
ubyte shift = 2
|
||||
|
||||
when zc*3 {
|
||||
123 -> zc++
|
||||
124 -> zc++
|
||||
125 -> zc++
|
||||
121 -> zc++
|
||||
120 -> zc++
|
||||
else -> zc++
|
||||
}
|
||||
txt.print_uw(zc<<shift)
|
||||
txt.nl()
|
||||
txt.print_uw(zc>>shift)
|
||||
txt.nl()
|
||||
txt.print_ub(zb<<shift)
|
||||
txt.nl()
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user