From 3841cef49790564fd000f5f6e8ddee1b08284a1e Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 15 Jul 2023 18:02:23 +0200 Subject: [PATCH] implemented missing bitshift codegen (non-stack) --- .../cpu6502/assignment/AssignmentAsmGen.kt | 89 +++++++++++++------ compiler/res/prog8lib/math.asm | 28 +++++- examples/test.p8 | 20 ++++- 3 files changed, 105 insertions(+), 32 deletions(-) diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index 0e0df30be..36274bccb 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -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") + 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 { + repeat(shifts) { + asmgen.out(" lsr a") + } + } } + assignRegisterByte(target, CpuRegister.A, signed) + return true } else { - if(signed && shifts>0) { - asmgen.out(" ldy #$shifts | jsr math.lsr_byte_A") + if(signed && expr.operator==">>") { + TODO("signed byte >> overshift should have been compiled away?") } else { - repeat(shifts) { - asmgen.out(" lsr a") - } + 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 diff --git a/compiler/res/prog8lib/math.asm b/compiler/res/prog8lib/math.asm index 3d5d9e36c..3efa4e42e 100644 --- a/compiler/res/prog8lib/math.asm +++ b/compiler/res/prog8lib/math.asm @@ -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 diff --git a/examples/test.p8 b/examples/test.p8 index 4d0865344..725b19339 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -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() } }