implemented missing bitshift codegen (non-stack)

This commit is contained in:
Irmen de Jong 2023-07-15 18:02:23 +02:00
parent b717f1c7eb
commit 3841cef497
3 changed files with 106 additions and 33 deletions

View File

@ -515,51 +515,84 @@ internal class AssignmentAsmGen(private val program: PtProgram,
val shifts = expr.right.asConstInteger()
if(shifts!=null) {
val dt = expr.left.type
if(dt in ByteDatatypes && shifts in 0..7) {
if(dt in ByteDatatypes) {
val signed = dt == DataType.BYTE
assignExpressionToRegister(expr.left, RegisterOrPair.A, signed)
if(expr.operator=="<<") {
repeat(shifts) {
asmgen.out(" asl a")
}
} else {
if(signed && shifts>0) {
asmgen.out(" ldy #$shifts | jsr math.lsr_byte_A")
} else {
if(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
} 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 && shifts in 0..7) {
} else if(dt in WordDatatypes) {
val signed = dt == DataType.WORD
assignExpressionToRegister(expr.left, RegisterOrPair.AY, signed)
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) {
// TODO("shift AY >> $shifts signed")
return false
} else {
if(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
} else if (shifts 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")
}
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")
}
assignRegisterpairWord(target, RegisterOrPair.AY)
return true
}
assignRegisterpairWord(target, RegisterOrPair.AY)
return true
}
}
return false

View File

@ -749,20 +749,42 @@ mul_word_640 .proc
; support for bit shifting that is too large to be unrolled:
lsr_byte_A .proc
; -- lsr signed byte in A times the value in Y (assume >0)
; -- lsr signed byte in A times the value in Y (>1)
cmp #0
bmi _negative
- lsr a
dey
bne -
rts
_negative lsr a
ora #$80
_negative sec
ror a
dey
bne _negative
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
_negative sec
ror a
ror P8ZP_SCRATCH_B1
dex
bne _negative
tay
lda P8ZP_SCRATCH_B1
rts
.pend
square .proc
; -- calculate square root of signed word in AY, result in AY

View File

@ -5,9 +5,27 @@ main
{
sub start()
{
; uword zc = $ea31
word zc = -5583
txt.print_w(zc)
txt.spc()
txt.print_w(zc>>10) ; -6
txt.nl()
txt.print_w(zc)
txt.spc()
txt.print_w(zc>>4) ; -349
txt.nl()
txt.print_w(zc)
txt.spc()
txt.print_w(zc>>10) ; -6
txt.nl()
cx16.r1L = (zc>>10) as ubyte
txt.print_ub(cx16.r1L) ; 250
txt.nl()
cx16.r1L = (zc>>4) as ubyte
txt.print_ub(cx16.r1L) ; 163
txt.nl()
}
}