diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt index 0ce6dddaf..1bedba2c8 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt @@ -627,8 +627,8 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express result += code result += IRCodeChunk(null, null).also { if(targetArray.splitWords) { - it += IRInstruction(Opcode.STOREZX, IRDataType.BYTE, reg1 = indexReg, immediate = arrayLength, labelSymbol = variable+"_lsb") - it += IRInstruction(Opcode.STOREZX, IRDataType.BYTE, reg1 = indexReg, immediate = arrayLength, labelSymbol = variable+"_msb") + it += IRInstruction(Opcode.STOREZX, IRDataType.BYTE, reg1 = indexReg, labelSymbol = variable+"_lsb") + it += IRInstruction(Opcode.STOREZX, IRDataType.BYTE, reg1 = indexReg, labelSymbol = variable+"_msb") } else it += IRInstruction(Opcode.STOREZX, targetDt, reg1=indexReg, labelSymbol = variable) @@ -753,7 +753,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express if(itemsize==1 || array.splitWords) return Pair(result, byteIndexTr.resultReg) - result += codeGen.multiplyByConst(DataType.UWORD, byteIndexTr.resultReg, itemsize) + result += codeGen.multiplyByConst(DataType.UBYTE, byteIndexTr.resultReg, itemsize) return Pair(result, byteIndexTr.resultReg) } @@ -1317,13 +1317,18 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express IRInstruction(opc, vmDt, labelSymbol = symbol) addInstr(result, ins, null) } else { - val tr = expressionEval.translateExpression(operand) - addToResult(result, tr, tr.resultReg, -1) + val shiftTr = expressionEval.translateExpression(operand) + addToResult(result, shiftTr, shiftTr.resultReg, -1) + var shiftReg = shiftTr.resultReg + if(vmDt==IRDataType.WORD && shiftTr.dt==IRDataType.BYTE) { + shiftReg = codeGen.registers.next(IRDataType.WORD) + addInstr(result, IRInstruction(Opcode.EXT, IRDataType.BYTE, reg1=shiftReg, reg2=shiftTr.resultReg), null) + } val opc = if (signed) Opcode.ASRNM else Opcode.LSRNM val ins = if(constAddress!=null) - IRInstruction(opc, vmDt, reg1 = tr.resultReg, address = constAddress) + IRInstruction(opc, vmDt, reg1 = shiftReg, address = constAddress) else - IRInstruction(opc, vmDt, reg1 = tr.resultReg, labelSymbol = symbol) + IRInstruction(opc, vmDt, reg1 = shiftReg, labelSymbol = symbol) addInstr(result, ins, null) } return result @@ -1376,12 +1381,17 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express IRInstruction(Opcode.LSLM, vmDt, labelSymbol = symbol) , null) } else { - val tr = expressionEval.translateExpression(operand) - addToResult(result, tr, tr.resultReg, -1) + val shiftTr = expressionEval.translateExpression(operand) + addToResult(result, shiftTr, shiftTr.resultReg, -1) + var shiftReg = shiftTr.resultReg + if(vmDt==IRDataType.WORD && shiftTr.dt==IRDataType.BYTE) { + shiftReg = codeGen.registers.next(IRDataType.WORD) + addInstr(result, IRInstruction(Opcode.EXT, IRDataType.BYTE, reg1=shiftReg, reg2=shiftTr.resultReg), null) + } addInstr(result, if(constAddress!=null) - IRInstruction(Opcode.LSLNM, vmDt, reg1=tr.resultReg, address = constAddress) + IRInstruction(Opcode.LSLNM, vmDt, reg1=shiftReg, address = constAddress) else - IRInstruction(Opcode.LSLNM, vmDt, reg1=tr.resultReg, labelSymbol = symbol) + IRInstruction(Opcode.LSLNM, vmDt, reg1=shiftReg, labelSymbol = symbol) ,null) } return result diff --git a/compiler/test/codegeneration/TestArrayThings.kt b/compiler/test/codegeneration/TestArrayThings.kt index 38bb543a4..b0285fef2 100644 --- a/compiler/test/codegeneration/TestArrayThings.kt +++ b/compiler/test/codegeneration/TestArrayThings.kt @@ -409,5 +409,68 @@ main { errors.errors.size shouldBe 0 errors.warnings.size shouldBe 0 } + + test("various array indexed assignment scenarios") { + val src=""" +%import floats +%import textio +%zeropage basicsafe + +main { + bool[10] barray + uword[10] @nosplit warrayns + uword[10] warray + float[10] farray + + sub start() { + dump() + + ; ALL OK + barray[2] = true + warrayns[2] = 1234 + warray[2] = 5678 + farray[2] = 3.1415 + dump() + + ; ALL OK + cx16.r0L=2 + barray[cx16.r0L] = false + warrayns[cx16.r0L] = 0 + warray[cx16.r0L] = 0 + farray[cx16.r0L] = 0 + dump() + + ; ALL OK + cx16.r0L=2 + barray[cx16.r0L] = true + warrayns[cx16.r0L] = 1234 + warray[cx16.r0L] = 5678 + farray[cx16.r0L] = 3.1415 + dump() + + ; ALL OK + barray[2] = false + warrayns[2] = 0 + warray[2] = 0 + farray[2] = 0.0 + dump() + + sub dump() { + txt.print_bool(barray[2]) + txt.spc() + txt.print_uw(warrayns[2]) + txt.spc() + txt.print_uw(warray[2]) + txt.spc() + txt.print_f(farray[2]) + txt.nl() + } + } +}""" + compileText(C64Target(), optimize=true, src, outputDir) shouldNotBe null + compileText(VMTarget(), optimize=true, src, outputDir) shouldNotBe null + compileText(C64Target(), optimize=false, src, outputDir) shouldNotBe null + compileText(VMTarget(), optimize=false, src, outputDir) shouldNotBe null + } }) diff --git a/compiler/test/codegeneration/TestVariousCodeGen.kt b/compiler/test/codegeneration/TestVariousCodeGen.kt index 23d18f1b5..7cf629efe 100644 --- a/compiler/test/codegeneration/TestVariousCodeGen.kt +++ b/compiler/test/codegeneration/TestVariousCodeGen.kt @@ -615,4 +615,19 @@ main { compileText(C64Target(), false, src, outputDir, writeAssembly = true) shouldNotBe null compileText(VMTarget(), false, src, outputDir, writeAssembly = true) shouldNotBe null } + + test("word bitshift with byte operand") { + val src=""" +main{ + sub start() { + cx16.r0 >>= 4 + cx16.r1 <<= 4 + } +}""" + + compileText(C64Target(), false, src, outputDir) shouldNotBe null + compileText(VMTarget(), false, src, outputDir) shouldNotBe null + compileText(C64Target(), true, src, outputDir) shouldNotBe null + compileText(VMTarget(), true, src, outputDir) shouldNotBe null + } }) \ No newline at end of file diff --git a/examples/test.p8 b/examples/test.p8 index 9ec6ffb1a..a177468df 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -1,103 +1,56 @@ %import floats %import textio +%zeropage basicsafe main { + bool[10] barray + uword[10] @nosplit warrayns + uword[10] warray + float[10] farray + sub start() { - simpleptrindexing() + dump() - struct List { - float f - ^^uword s - ^^float fp - uword n - } - ^^List l = List() - l.s = 2000 - l.fp = 3000 + ; ALL OK + barray[2] = true + warrayns[2] = 1234 + warray[2] = 5678 + farray[2] = 3.1415 + dump() - pokew(2000, 1) - pokew(2002, 2) - pokew(2004, 3) - pokew(2006, 4) - pokew(2008, 5) - pokef(3000, 1.111) - pokef(3008, 2.222) - pokef(3016, 3.333) - pokef(3024, 4.444) - pokef(3032, 5.555) + ; ALL OK + cx16.r0L=2 + barray[cx16.r0L] = false + warrayns[cx16.r0L] = 0 + warray[cx16.r0L] = 0 + farray[cx16.r0L] = 0 + dump() - cx16.r9L = 2 + ; ALL OK + cx16.r0L=2 + barray[cx16.r0L] = true + warrayns[cx16.r0L] = 1234 + warray[cx16.r0L] = 5678 + farray[cx16.r0L] = 3.1415 + dump() - lvref1() - lvref2() - lvref1f() - lvref2f() + ; ALL OK + barray[2] = false + warrayns[2] = 0 + warray[2] = 0 + farray[2] = 0.0 + dump() - ref1() - ref2() - ref1f() - ref2f() - - sub lvref1() { - l.s[2] = 3333 - } - sub lvref2() { - l.s[cx16.r9L+1] = 4444 - } - sub lvref1f() { - l.fp[2] = 3333.3 - } - sub lvref2f() { - l.fp[cx16.r9L+1] = 4444.4 - } - - sub ref1() { - cx16.r0 = l.s[2] - txt.print_uw(l.s[2]) - txt.nl() - } - sub ref2() { - cx16.r1 = l.s[cx16.r9L+1] - txt.print_uw(l.s[cx16.r9L+1]) - txt.nl() - } - sub ref1f() { - txt.print_f(l.fp[2]) - txt.nl() - } - sub ref2f() { - txt.print_f(l.fp[cx16.r9L+1]) + sub dump() { + txt.print_bool(barray[2]) + txt.spc() + txt.print_uw(warrayns[2]) + txt.spc() + txt.print_uw(warray[2]) + txt.spc() + txt.print_f(farray[2]) txt.nl() } } - - - sub simpleptrindexing() { - ^^float flptr = 2000 - ^^bool bptr = 3000 - - -; flptr[0] = 0.0 -; flptr[1] = 1.1 - cx16.r9L = 2 - flptr[cx16.r9L] = 2.2 - bptr[cx16.r9L] = true - -; txt.print_f(flptr[0]) -; txt.nl() -; txt.print_f(flptr[1]) -; txt.nl() - txt.print_f(peekf(2000+8*2)) - txt.nl() - txt.print_f(flptr[2]) - txt.nl() - - pokef(2000+8*2, 9.9999) - txt.print_f(peekf(2000+8*2)) - txt.nl() - txt.print_f(flptr[2]) - txt.nl() - } - } diff --git a/intermediate/src/prog8/intermediate/IRInstructions.kt b/intermediate/src/prog8/intermediate/IRInstructions.kt index 47b1e1faa..5dd9504f8 100644 --- a/intermediate/src/prog8/intermediate/IRInstructions.kt +++ b/intermediate/src/prog8/intermediate/IRInstructions.kt @@ -1019,8 +1019,15 @@ data class IRInstruction( private fun determineReg1Type(): IRDataType? { if(type==IRDataType.FLOAT) { - // some float instructions have an integer register as well. - return if(opcode in arrayOf(Opcode.FFROMUB, Opcode.FFROMSB, Opcode.FTOUB, Opcode.FTOSB, Opcode.FCOMP, Opcode.LOADIX, Opcode.LOADX, Opcode.STOREIX, Opcode.STOREX, Opcode.STOREZX)) + // some float instructions have an integer (byte or word) register as well in reg1 + return if(opcode in arrayOf(Opcode.FFROMUB, Opcode.FFROMSB, Opcode.FTOUB, Opcode.FTOSB, Opcode.FCOMP, Opcode.LOADIX, Opcode.LOADX, Opcode.STOREX, Opcode.STOREIX, Opcode.STOREZX)) + IRDataType.BYTE + else + IRDataType.WORD + } + if(type==IRDataType.WORD) { + // some word instructions have byte reg1 + return if(opcode in arrayOf(Opcode.STOREZX)) IRDataType.BYTE else IRDataType.WORD