mirror of
https://github.com/irmen/prog8.git
synced 2025-09-12 00:24:34 +00:00
IR: fix various register type mismatches
This commit is contained in:
@@ -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
|
||||
|
@@ -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
|
||||
}
|
||||
})
|
||||
|
||||
|
@@ -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
|
||||
}
|
||||
})
|
129
examples/test.p8
129
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()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user