mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
IR: fix byte to word assignment not doing value extension
This commit is contained in:
parent
ef46fb2685
commit
97df33ab1a
@ -161,7 +161,8 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
val targetIdent = assignment.target.identifier
|
||||
val targetMemory = assignment.target.memory
|
||||
val targetArray = assignment.target.array
|
||||
val vmDt = codeGen.irType(assignment.value.type)
|
||||
val valueDt = codeGen.irType(assignment.value.type)
|
||||
val targetDt = codeGen.irType(assignment.target.type)
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
|
||||
var valueRegister = -1
|
||||
@ -169,30 +170,42 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
val zero = codeGen.isZero(assignment.value)
|
||||
if(!zero) {
|
||||
// calculate the assignment value
|
||||
if (vmDt == IRDataType.FLOAT) {
|
||||
if (valueDt == IRDataType.FLOAT) {
|
||||
val tr = expressionEval.translateExpression(assignment.value)
|
||||
valueFpRegister = tr.resultFpReg
|
||||
addToResult(result, tr, -1, valueFpRegister)
|
||||
} else {
|
||||
val extendByteToWord = if(targetDt != valueDt) {
|
||||
// usually an error EXCEPT when a byte is assigned to a word.
|
||||
if(targetDt==IRDataType.WORD && valueDt==IRDataType.BYTE)
|
||||
true
|
||||
else
|
||||
throw AssemblyError("assignment value and target dt mismatch")
|
||||
} else false
|
||||
if (assignment.value is PtMachineRegister) {
|
||||
valueRegister = (assignment.value as PtMachineRegister).register
|
||||
if(extendByteToWord)
|
||||
addInstr(result, IRInstruction(Opcode.EXT, IRDataType.BYTE, reg1=valueRegister), null)
|
||||
} else {
|
||||
val tr = expressionEval.translateExpression(assignment.value)
|
||||
valueRegister = tr.resultReg
|
||||
addToResult(result, tr, valueRegister, -1)
|
||||
if(extendByteToWord) {
|
||||
val opcode = if(assignment.value.type in SignedDatatypes) Opcode.EXTS else Opcode.EXT
|
||||
addInstr(result, IRInstruction(opcode, IRDataType.BYTE, reg1 = valueRegister), null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(targetIdent!=null) {
|
||||
val instruction = if(zero) {
|
||||
IRInstruction(Opcode.STOREZM, vmDt, labelSymbol = targetIdent.name)
|
||||
IRInstruction(Opcode.STOREZM, targetDt, labelSymbol = targetIdent.name)
|
||||
} else {
|
||||
if (vmDt == IRDataType.FLOAT) {
|
||||
IRInstruction(Opcode.STOREM, vmDt, fpReg1 = valueFpRegister, labelSymbol = targetIdent.name)
|
||||
}
|
||||
if (targetDt == IRDataType.FLOAT)
|
||||
IRInstruction(Opcode.STOREM, targetDt, fpReg1 = valueFpRegister, labelSymbol = targetIdent.name)
|
||||
else
|
||||
IRInstruction(Opcode.STOREM, vmDt, reg1 = valueRegister, labelSymbol = targetIdent.name)
|
||||
IRInstruction(Opcode.STOREM, targetDt, reg1 = valueRegister, labelSymbol = targetIdent.name)
|
||||
}
|
||||
result += IRCodeChunk(null, null).also { it += instruction }
|
||||
return result
|
||||
@ -214,9 +227,9 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
if(zero) {
|
||||
// there's no STOREZIX instruction
|
||||
valueRegister = codeGen.registers.nextFree()
|
||||
code += IRInstruction(Opcode.LOAD, vmDt, reg1=valueRegister, immediate = 0)
|
||||
code += IRInstruction(Opcode.LOAD, targetDt, reg1=valueRegister, immediate = 0)
|
||||
}
|
||||
code += IRInstruction(Opcode.STOREIX, vmDt, reg1=valueRegister, reg2=idxReg, labelSymbol = variable)
|
||||
code += IRInstruction(Opcode.STOREIX, targetDt, reg1=valueRegister, reg2=idxReg, labelSymbol = variable)
|
||||
result += code
|
||||
return result
|
||||
}
|
||||
@ -225,59 +238,59 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
if(zero) {
|
||||
if(fixedIndex!=null) {
|
||||
val offset = fixedIndex*itemsize
|
||||
val chunk = IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREZM, vmDt, labelSymbol = "$variable+$offset") }
|
||||
val chunk = IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREZM, targetDt, labelSymbol = "$variable+$offset") }
|
||||
result += chunk
|
||||
} else {
|
||||
val (code, indexReg) = loadIndexReg(targetArray, itemsize)
|
||||
result += code
|
||||
result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREZX, vmDt, reg1=indexReg, labelSymbol = variable) }
|
||||
result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREZX, targetDt, reg1=indexReg, labelSymbol = variable) }
|
||||
}
|
||||
} else {
|
||||
if(vmDt== IRDataType.FLOAT) {
|
||||
if(targetDt== IRDataType.FLOAT) {
|
||||
if(fixedIndex!=null) {
|
||||
val offset = fixedIndex*itemsize
|
||||
val chunk = IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREM, vmDt, fpReg1 = valueFpRegister, labelSymbol = "$variable+$offset") }
|
||||
val chunk = IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREM, targetDt, fpReg1 = valueFpRegister, labelSymbol = "$variable+$offset") }
|
||||
result += chunk
|
||||
} else {
|
||||
val (code, indexReg) = loadIndexReg(targetArray, itemsize)
|
||||
result += code
|
||||
result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREX, vmDt, reg1 = indexReg, fpReg1 = valueFpRegister, labelSymbol = variable) }
|
||||
result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREX, targetDt, reg1 = indexReg, fpReg1 = valueFpRegister, labelSymbol = variable) }
|
||||
}
|
||||
} else {
|
||||
if(fixedIndex!=null) {
|
||||
val offset = fixedIndex*itemsize
|
||||
val chunk = IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREM, vmDt, reg1 = valueRegister, labelSymbol = "$variable+$offset") }
|
||||
val chunk = IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREM, targetDt, reg1 = valueRegister, labelSymbol = "$variable+$offset") }
|
||||
result += chunk
|
||||
} else {
|
||||
val (code, indexReg) = loadIndexReg(targetArray, itemsize)
|
||||
result += code
|
||||
result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREX, vmDt, reg1 = valueRegister, reg2=indexReg, labelSymbol = variable) }
|
||||
result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREX, targetDt, reg1 = valueRegister, reg2=indexReg, labelSymbol = variable) }
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
else if(targetMemory!=null) {
|
||||
require(vmDt== IRDataType.BYTE) { "must be byte type ${targetMemory.position}"}
|
||||
require(targetDt == IRDataType.BYTE) { "must be byte type ${targetMemory.position}"}
|
||||
if(zero) {
|
||||
if(targetMemory.address is PtNumber) {
|
||||
val chunk = IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREZM, vmDt, address = (targetMemory.address as PtNumber).number.toInt()) }
|
||||
val chunk = IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREZM, targetDt, address = (targetMemory.address as PtNumber).number.toInt()) }
|
||||
result += chunk
|
||||
} else {
|
||||
val tr = expressionEval.translateExpression(targetMemory.address)
|
||||
val addressReg = tr.resultReg
|
||||
addToResult(result, tr, tr.resultReg, -1)
|
||||
result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREZI, vmDt, reg1=addressReg) }
|
||||
result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREZI, targetDt, reg1=addressReg) }
|
||||
}
|
||||
} else {
|
||||
if(targetMemory.address is PtNumber) {
|
||||
val chunk = IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREM, vmDt, reg1=valueRegister, address=(targetMemory.address as PtNumber).number.toInt()) }
|
||||
val chunk = IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREM, targetDt, reg1=valueRegister, address=(targetMemory.address as PtNumber).number.toInt()) }
|
||||
result += chunk
|
||||
} else {
|
||||
val tr = expressionEval.translateExpression(targetMemory.address)
|
||||
val addressReg = tr.resultReg
|
||||
addToResult(result, tr, tr.resultReg, -1)
|
||||
result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREI, vmDt, reg1=valueRegister, reg2=addressReg) }
|
||||
result += IRCodeChunk(null, null).also { it += IRInstruction(Opcode.STOREI, targetDt, reg1=valueRegister, reg2=addressReg) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ TODO
|
||||
For next minor release
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
- fix crash: uword remainder = seconds_uword % $0003 ==0
|
||||
- fix VM: void string.copy(".prg", &output_filename + string.length(output_filename))
|
||||
- fix VM problem with param passing: void string.copy(".prg", &output_filename + string.length(output_filename))
|
||||
- try to optimize newexpr a bit more
|
||||
|
||||
...
|
||||
|
@ -5,9 +5,51 @@
|
||||
main {
|
||||
|
||||
sub start() {
|
||||
str output_filename = "?????????\x00????????????"
|
||||
void string.copy(".prg", &output_filename + string.length(output_filename))
|
||||
txt.print(output_filename)
|
||||
str output_filename = "12345678\x00abcdefghij"
|
||||
void myprint2("hallo", &output_filename+string.length(output_filename))
|
||||
; ubyte length = string.length(output_filename)
|
||||
; txt.print_ub(length)
|
||||
; txt.nl()
|
||||
; txt.print_uw(&output_filename)
|
||||
; txt.nl()
|
||||
; output_filename[2]='!'
|
||||
; txt.print(output_filename)
|
||||
; txt.nl()
|
||||
;
|
||||
; void string_copy(".prg", &output_filename + string.length(output_filename))
|
||||
; txt.print(output_filename)
|
||||
}
|
||||
|
||||
sub myprint2(str source1, str source2) {
|
||||
txt.print(source1)
|
||||
txt.nl()
|
||||
txt.print(source2)
|
||||
txt.nl()
|
||||
}
|
||||
|
||||
sub string_copy(str source, str target) -> ubyte {
|
||||
; Copy a string to another, overwriting that one.
|
||||
; Returns the length of the string that was copied.
|
||||
; Often you don’t have to call this explicitly and can just write string1 = string2
|
||||
; but this function is useful if you’re dealing with addresses for instance.
|
||||
txt.print("src=")
|
||||
txt.print(source)
|
||||
txt.nl()
|
||||
txt.print("target=")
|
||||
txt.print(target)
|
||||
txt.nl()
|
||||
ubyte ix
|
||||
repeat 5 {
|
||||
ubyte qq=source[ix]
|
||||
txt.print_ub(qq)
|
||||
target[ix]=qq
|
||||
txt.spc()
|
||||
if qq==0 {
|
||||
txt.nl()
|
||||
return ix
|
||||
}
|
||||
ix++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,26 +89,26 @@ bgesr reg1, reg2, address - jump to location in program given by l
|
||||
ble reg1, value, address - jump to location in program given by location, if reg1 <= immediate value (unsigned)
|
||||
bles reg1, value, address - jump to location in program given by location, if reg1 <= immediate value (signed)
|
||||
( NOTE: there are no bltr/bler instructions because these are equivalent to bgtr/bger with the register operands swapped around.)
|
||||
sz reg1, reg2 - set reg1=1 if reg2==0, otherwise set reg1=0
|
||||
snz reg1, reg2 - set reg1=1 if reg2!=0, otherwise set reg1=0
|
||||
seq reg1, reg2 - set reg1=1 if reg1 == reg2, otherwise set reg1=0
|
||||
sne reg1, reg2 - set reg1=1 if reg1 != reg2, otherwise set reg1=0
|
||||
slt reg1, reg2 - set reg1=1 if reg1 < reg2 (unsigned), otherwise set reg1=0
|
||||
slts reg1, reg2 - set reg1=1 if reg1 < reg2 (signed), otherwise set reg1=0
|
||||
sle reg1, reg2 - set reg1=1 if reg1 <= reg2 (unsigned), otherwise set reg1=0
|
||||
sles reg1, reg2 - set reg1=1 if reg1 <= reg2 (signed), otherwise set reg1=0
|
||||
sgt reg1, reg2 - set reg1=1 if reg1 > reg2 (unsigned), otherwise set reg1=0
|
||||
sgts reg1, reg2 - set reg1=1 if reg1 > reg2 (signed), otherwise set reg1=0
|
||||
sge reg1, reg2 - set reg1=1 if reg1 >= reg2 (unsigned), otherwise set reg1=0
|
||||
sges reg1, reg2 - set reg1=1 if reg1 >= reg2 (signed), otherwise set reg1=0
|
||||
sz reg1, reg2 - set reg1=1.b if reg2==0, otherwise set reg1=0.b
|
||||
snz reg1, reg2 - set reg1=1.b if reg2!=0, otherwise set reg1=0.b
|
||||
seq reg1, reg2 - set reg1=1.b if reg1 == reg2, otherwise set reg1=0.b
|
||||
sne reg1, reg2 - set reg1=1.b if reg1 != reg2, otherwise set reg1=0.b
|
||||
slt reg1, reg2 - set reg1=1.b if reg1 < reg2 (unsigned), otherwise set reg1=0.b
|
||||
slts reg1, reg2 - set reg1=1.b if reg1 < reg2 (signed), otherwise set reg1=0.b
|
||||
sle reg1, reg2 - set reg1=1.b if reg1 <= reg2 (unsigned), otherwise set reg1=0.b
|
||||
sles reg1, reg2 - set reg1=1.b if reg1 <= reg2 (signed), otherwise set reg1=0.b
|
||||
sgt reg1, reg2 - set reg1=1.b if reg1 > reg2 (unsigned), otherwise set reg1=0.b
|
||||
sgts reg1, reg2 - set reg1=1.b if reg1 > reg2 (signed), otherwise set reg1=0.b
|
||||
sge reg1, reg2 - set reg1=1.b if reg1 >= reg2 (unsigned), otherwise set reg1=0.b
|
||||
sges reg1, reg2 - set reg1=1.b if reg1 >= reg2 (signed), otherwise set reg1=0.b
|
||||
|
||||
|
||||
ARITHMETIC
|
||||
----------
|
||||
All have type b or w or f. Note: result types are the same as operand types! E.g. byte*byte->byte.
|
||||
|
||||
ext reg1 - reg1 = unsigned extension of reg1 (which in practice just means clearing the MSB / MSW) (ext.w not yet implemented as we don't have longs yet)
|
||||
exts reg1 - reg1 = signed extension of reg1 (byte to word, or word to long) (note: ext.w is not yet implemented as we don't have longs yet)
|
||||
ext reg1 - reg1 = unsigned extension of reg1 (which in practice just means clearing the MSB / MSW) (ext.w not yet implemented as we don't have longs yet)
|
||||
inc reg1 - reg1 = reg1+1
|
||||
incm address - memory at address += 1
|
||||
dec reg1 - reg1 = reg1-1
|
||||
|
Loading…
x
Reference in New Issue
Block a user