mirror of
https://github.com/irmen/prog8.git
synced 2024-11-04 04:05:00 +00:00
IR: handle split arrays without new custom opcodes
This commit is contained in:
parent
0b580ad05d
commit
bfaad1388c
@ -241,20 +241,24 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
if(zero) {
|
||||
if(fixedIndex!=null) {
|
||||
val chunk = IRCodeChunk(null, null).also {
|
||||
it += if(targetArray.splitWords)
|
||||
IRInstruction(Opcode.STOREZMSPLIT, targetDt, immediate = arrayLength, labelSymbol = "$variable+$fixedIndex")
|
||||
if(targetArray.splitWords) {
|
||||
it += IRInstruction(Opcode.STOREZM, IRDataType.BYTE, immediate = arrayLength, labelSymbol = "${variable}_lsb+$fixedIndex")
|
||||
it += IRInstruction(Opcode.STOREZM, IRDataType.BYTE, immediate = arrayLength, labelSymbol = "${variable}_msb+$fixedIndex")
|
||||
}
|
||||
else
|
||||
IRInstruction(Opcode.STOREZM, targetDt, labelSymbol = "$variable+${fixedIndex*itemsize}")
|
||||
it += IRInstruction(Opcode.STOREZM, targetDt, labelSymbol = "$variable+${fixedIndex*itemsize}")
|
||||
}
|
||||
result += chunk
|
||||
} else {
|
||||
val (code, indexReg) = loadIndexReg(targetArray, itemsize)
|
||||
result += code
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += if(targetArray.splitWords)
|
||||
IRInstruction(Opcode.STOREZXSPLIT, targetDt, reg1 = valueRegister, reg2=indexReg, immediate = arrayLength, labelSymbol = variable)
|
||||
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")
|
||||
}
|
||||
else
|
||||
IRInstruction(Opcode.STOREZX, targetDt, reg1=indexReg, labelSymbol = variable)
|
||||
it += IRInstruction(Opcode.STOREZX, targetDt, reg1=indexReg, labelSymbol = variable)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -275,20 +279,28 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
} else {
|
||||
if(fixedIndex!=null) {
|
||||
val chunk = IRCodeChunk(null, null).also {
|
||||
it += if(targetArray.splitWords)
|
||||
IRInstruction(Opcode.STOREMSPLIT, targetDt, reg1 = valueRegister, immediate = arrayLength, labelSymbol = "$variable+$fixedIndex")
|
||||
if(targetArray.splitWords) {
|
||||
val msbReg = codeGen.registers.nextFree()
|
||||
it += IRInstruction(Opcode.STOREM, IRDataType.BYTE, reg1 = valueRegister, immediate = arrayLength, labelSymbol = "${variable}_lsb+$fixedIndex")
|
||||
it += IRInstruction(Opcode.MSIG, IRDataType.BYTE, reg1 = msbReg, reg2 = valueRegister)
|
||||
it += IRInstruction(Opcode.STOREM, IRDataType.BYTE, reg1 = msbReg, immediate = arrayLength, labelSymbol = "${variable}_msb+$fixedIndex")
|
||||
}
|
||||
else
|
||||
IRInstruction(Opcode.STOREM, targetDt, reg1 = valueRegister, labelSymbol = "$variable+${fixedIndex*itemsize}")
|
||||
it += IRInstruction(Opcode.STOREM, targetDt, reg1 = valueRegister, labelSymbol = "$variable+${fixedIndex*itemsize}")
|
||||
}
|
||||
result += chunk
|
||||
} else {
|
||||
val (code, indexReg) = loadIndexReg(targetArray, itemsize)
|
||||
result += code
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += if(targetArray.splitWords)
|
||||
IRInstruction(Opcode.STOREXSPLIT, targetDt, reg1 = valueRegister, reg2=indexReg, immediate = arrayLength, labelSymbol = variable)
|
||||
if(targetArray.splitWords) {
|
||||
val msbReg = codeGen.registers.nextFree()
|
||||
it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1 = valueRegister, reg2=indexReg, immediate = arrayLength, labelSymbol = "${variable}_lsb")
|
||||
it += IRInstruction(Opcode.MSIG, IRDataType.BYTE, reg1 = msbReg, reg2 = valueRegister)
|
||||
it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1 = msbReg, reg2=indexReg, immediate = arrayLength, labelSymbol = "${variable}_msb")
|
||||
}
|
||||
else
|
||||
IRInstruction(Opcode.STOREX, targetDt, reg1 = valueRegister, reg2=indexReg, labelSymbol = variable)
|
||||
it += IRInstruction(Opcode.STOREX, targetDt, reg1 = valueRegister, reg2=indexReg, labelSymbol = variable)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -168,11 +168,21 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
resultRegister = codeGen.registers.nextFree()
|
||||
if(arrayIx.index is PtNumber) {
|
||||
val memOffset = (arrayIx.index as PtNumber).number.toInt()
|
||||
addInstr(result, IRInstruction(Opcode.LOADMSPLIT, IRDataType.WORD, reg1=resultRegister, immediate = arrayLength, labelSymbol = "$arrayVarSymbol+$memOffset"), null)
|
||||
result += IRCodeChunk(null, null).also {
|
||||
val tmpRegMsb = codeGen.registers.nextFree()
|
||||
it += IRInstruction(Opcode.LOADM, IRDataType.BYTE, reg1=resultRegister, immediate = arrayLength, labelSymbol= "${arrayVarSymbol}_lsb+$memOffset")
|
||||
it += IRInstruction(Opcode.LOADM, IRDataType.BYTE, reg1=tmpRegMsb, immediate = arrayLength, labelSymbol= "${arrayVarSymbol}_msb+$memOffset")
|
||||
it += IRInstruction(Opcode.CONCAT, IRDataType.BYTE, reg1=resultRegister, reg2=tmpRegMsb)
|
||||
}
|
||||
} else {
|
||||
val tr = translateExpression(arrayIx.index)
|
||||
addToResult(result, tr, tr.resultReg, -1)
|
||||
addInstr(result, IRInstruction(Opcode.LOADXSPLIT, IRDataType.WORD, reg1=resultRegister, reg2=tr.resultReg, immediate = arrayLength, labelSymbol = arrayVarSymbol), null)
|
||||
result += IRCodeChunk(null, null).also {
|
||||
val tmpRegMsb = codeGen.registers.nextFree()
|
||||
it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=resultRegister, reg2 = tr.resultReg, immediate = arrayLength, labelSymbol= "${arrayVarSymbol}_lsb")
|
||||
it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=tmpRegMsb, reg2 = tr.resultReg, immediate = arrayLength, labelSymbol= "${arrayVarSymbol}_msb")
|
||||
it += IRInstruction(Opcode.CONCAT, IRDataType.BYTE, reg1=resultRegister, reg2=tmpRegMsb)
|
||||
}
|
||||
}
|
||||
return ExpressionCodeResult(result, vmDt, resultRegister, -1)
|
||||
}
|
||||
|
@ -457,23 +457,11 @@ class IRCodeGen(
|
||||
if(iterableVar.dt==DataType.STR) {
|
||||
// iterate over a zero-terminated string
|
||||
addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1 = indexReg, immediate = 0), null)
|
||||
val chunk = IRCodeChunk(loopLabel, null)
|
||||
chunk += IRInstruction(
|
||||
Opcode.LOADX,
|
||||
IRDataType.BYTE,
|
||||
reg1 = tmpReg,
|
||||
reg2 = indexReg,
|
||||
labelSymbol = iterable.name
|
||||
)
|
||||
chunk += IRInstruction(
|
||||
Opcode.BEQ,
|
||||
IRDataType.BYTE,
|
||||
reg1 = tmpReg,
|
||||
immediate = 0,
|
||||
labelSymbol = endLabel
|
||||
)
|
||||
chunk += IRInstruction(Opcode.STOREM, IRDataType.BYTE, reg1 = tmpReg, labelSymbol = loopvarSymbol)
|
||||
result += chunk
|
||||
result += IRCodeChunk(loopLabel, null).also {
|
||||
it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1 = tmpReg, reg2 = indexReg, labelSymbol = iterable.name)
|
||||
it += IRInstruction(Opcode.BEQ, IRDataType.BYTE, reg1 = tmpReg, immediate = 0, labelSymbol = endLabel)
|
||||
it += IRInstruction(Opcode.STOREM, IRDataType.BYTE, reg1 = tmpReg, labelSymbol = loopvarSymbol)
|
||||
}
|
||||
result += translateNode(forLoop.statements)
|
||||
val jumpChunk = IRCodeChunk(null, null)
|
||||
jumpChunk += IRInstruction(Opcode.INC, IRDataType.BYTE, reg1 = indexReg)
|
||||
@ -488,8 +476,12 @@ class IRCodeGen(
|
||||
val length = iterableVar.length!!
|
||||
addInstr(result, IRInstruction(Opcode.LOAD, IRDataType.BYTE, reg1=indexReg, immediate = 0), null)
|
||||
result += IRCodeChunk(loopLabel, null).also {
|
||||
it += IRInstruction(Opcode.LOADXSPLIT, irType(elementDt), reg1=tmpReg, reg2=indexReg, immediate = length, labelSymbol=iterable.name)
|
||||
it += IRInstruction(Opcode.STOREM, irType(elementDt), reg1=tmpReg, labelSymbol = loopvarSymbol)
|
||||
val tmpRegLsb = registers.nextFree()
|
||||
val tmpRegMsb = registers.nextFree()
|
||||
it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=tmpRegLsb, reg2=indexReg, immediate = length, labelSymbol=iterable.name+"_lsb")
|
||||
it += IRInstruction(Opcode.LOADX, IRDataType.BYTE, reg1=tmpRegMsb, reg2=indexReg, immediate = length, labelSymbol=iterable.name+"_msb")
|
||||
it += IRInstruction(Opcode.CONCAT, IRDataType.BYTE, reg1=tmpRegLsb, reg2=tmpRegMsb)
|
||||
it += IRInstruction(Opcode.STOREM, irType(elementDt), reg1=tmpRegLsb, labelSymbol = loopvarSymbol)
|
||||
}
|
||||
result += translateNode(forLoop.statements)
|
||||
result += IRCodeChunk(null, null).also {
|
||||
@ -1367,76 +1359,84 @@ class IRCodeGen(
|
||||
}
|
||||
|
||||
private fun translate(postIncrDecr: PtPostIncrDecr): IRCodeChunks {
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
val array = postIncrDecr.target.array
|
||||
val operationMem: Opcode
|
||||
val operationRegister: Opcode
|
||||
val array = postIncrDecr.target.array
|
||||
when(postIncrDecr.operator) {
|
||||
"++" -> {
|
||||
operationMem = if(array?.splitWords==true) Opcode.INCMSPLIT else Opcode.INCM
|
||||
operationMem = Opcode.INCM
|
||||
operationRegister = Opcode.INC
|
||||
}
|
||||
"--" -> {
|
||||
operationMem = if(array?.splitWords==true) Opcode.DECMSPLIT else Opcode.DECM
|
||||
operationMem = Opcode.DECM
|
||||
operationRegister = Opcode.DEC
|
||||
}
|
||||
else -> throw AssemblyError("weird operator")
|
||||
}
|
||||
val ident = postIncrDecr.target.identifier
|
||||
val memory = postIncrDecr.target.memory
|
||||
val irDt = irType(postIncrDecr.target.type)
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
if(ident!=null) {
|
||||
addInstr(result, IRInstruction(operationMem, irDt, labelSymbol = ident.name), null)
|
||||
} else if(memory!=null) {
|
||||
if(memory.address is PtNumber) {
|
||||
val address = (memory.address as PtNumber).number.toInt()
|
||||
addInstr(result, IRInstruction(operationMem, irDt, address = address), null)
|
||||
|
||||
if(array?.splitWords==true) {
|
||||
val variable = array.variable.name
|
||||
val fixedIndex = constIntValue(array.index)
|
||||
val iterable = symbolTable.flat.getValue(array.variable.name) as StStaticVariable
|
||||
val arrayLength = iterable.length!!
|
||||
if(fixedIndex!=null) {
|
||||
TODO("split incr decr")
|
||||
// addInstr(result, IRInstruction(operationMem, irDt, immediate = arrayLength, labelSymbol="$variable+$fixedIndex"), null)
|
||||
} else {
|
||||
val tr = expressionEval.translateExpression(memory.address)
|
||||
addToResult(result, tr, tr.resultReg, -1)
|
||||
val indexTr = expressionEval.translateExpression(array.index)
|
||||
addToResult(result, indexTr, indexTr.resultReg, -1)
|
||||
val chunk = IRCodeChunk(null, null)
|
||||
val incReg = registers.nextFree()
|
||||
chunk += IRInstruction(Opcode.LOADI, irDt, reg1 = incReg, reg2 = tr.resultReg)
|
||||
chunk += IRInstruction(operationRegister, irDt, reg1 = incReg)
|
||||
chunk += IRInstruction(Opcode.STOREI, irDt, reg1 = incReg, reg2 = tr.resultReg)
|
||||
TODO("load split")
|
||||
// chunk += IRInstruction(Opcode.LOADXSPLIT, irDt, reg1=incReg, reg2=indexTr.resultReg, immediate = arrayLength, labelSymbol=variable)
|
||||
// chunk += IRInstruction(operationRegister, irDt, reg1=incReg)
|
||||
TODO("store split")
|
||||
// chunk += IRInstruction(Opcode.STOREXSPLIT, irDt, reg1=incReg, reg2=indexTr.resultReg, immediate = arrayLength, labelSymbol=variable)
|
||||
result += chunk
|
||||
}
|
||||
} else if (array!=null) {
|
||||
val variable = array.variable.name
|
||||
val itemsize = program.memsizer.memorySize(array.type)
|
||||
val fixedIndex = constIntValue(array.index)
|
||||
if(array.splitWords) {
|
||||
val iterable = symbolTable.flat.getValue(array.variable.name) as StStaticVariable
|
||||
val arrayLength = iterable.length!!
|
||||
if(fixedIndex!=null) {
|
||||
addInstr(result, IRInstruction(operationMem, irDt, immediate = arrayLength, labelSymbol="$variable+$fixedIndex"), null)
|
||||
} else {
|
||||
val ident = postIncrDecr.target.identifier
|
||||
val memory = postIncrDecr.target.memory
|
||||
val irDt = irType(postIncrDecr.target.type)
|
||||
if(ident!=null) {
|
||||
addInstr(result, IRInstruction(operationMem, irDt, labelSymbol = ident.name), null)
|
||||
} else if(memory!=null) {
|
||||
if(memory.address is PtNumber) {
|
||||
val address = (memory.address as PtNumber).number.toInt()
|
||||
addInstr(result, IRInstruction(operationMem, irDt, address = address), null)
|
||||
} else {
|
||||
val indexTr = expressionEval.translateExpression(array.index)
|
||||
addToResult(result, indexTr, indexTr.resultReg, -1)
|
||||
val chunk = IRCodeChunk(null, null)
|
||||
val incReg = registers.nextFree()
|
||||
chunk += IRInstruction(Opcode.LOADXSPLIT, irDt, reg1=incReg, reg2=indexTr.resultReg, immediate = arrayLength, labelSymbol=variable)
|
||||
chunk += IRInstruction(operationRegister, irDt, reg1=incReg)
|
||||
chunk += IRInstruction(Opcode.STOREXSPLIT, irDt, reg1=incReg, reg2=indexTr.resultReg, immediate = arrayLength, labelSymbol=variable)
|
||||
result += chunk
|
||||
val tr = expressionEval.translateExpression(memory.address)
|
||||
addToResult(result, tr, tr.resultReg, -1)
|
||||
result += IRCodeChunk(null, null).also {
|
||||
val incReg = registers.nextFree()
|
||||
it += IRInstruction(Opcode.LOADI, irDt, reg1 = incReg, reg2 = tr.resultReg)
|
||||
it += IRInstruction(operationRegister, irDt, reg1 = incReg)
|
||||
it += IRInstruction(Opcode.STOREI, irDt, reg1 = incReg, reg2 = tr.resultReg)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else if (array!=null) {
|
||||
val variable = array.variable.name
|
||||
val itemsize = program.memsizer.memorySize(array.type)
|
||||
val fixedIndex = constIntValue(array.index)
|
||||
if(fixedIndex!=null) {
|
||||
val offset = fixedIndex*itemsize
|
||||
addInstr(result, IRInstruction(operationMem, irDt, labelSymbol="$variable+$offset"), null)
|
||||
} else {
|
||||
val indexTr = expressionEval.translateExpression(array.index)
|
||||
addToResult(result, indexTr, indexTr.resultReg, -1)
|
||||
val chunk = IRCodeChunk(null, null)
|
||||
val incReg = registers.nextFree()
|
||||
chunk += IRInstruction(Opcode.LOADX, irDt, reg1=incReg, reg2=indexTr.resultReg, labelSymbol=variable)
|
||||
chunk += IRInstruction(operationRegister, irDt, reg1=incReg)
|
||||
chunk += IRInstruction(Opcode.STOREX, irDt, reg1=incReg, reg2=indexTr.resultReg, labelSymbol=variable)
|
||||
result += chunk
|
||||
if(itemsize>1)
|
||||
result += multiplyByConst(IRDataType.BYTE, indexTr.resultReg, itemsize)
|
||||
result += IRCodeChunk(null, null).also {
|
||||
val incReg = registers.nextFree()
|
||||
it += IRInstruction(Opcode.LOADX, irDt, reg1=incReg, reg2=indexTr.resultReg, labelSymbol=variable)
|
||||
it += IRInstruction(operationRegister, irDt, reg1=incReg)
|
||||
it += IRInstruction(Opcode.STOREX, irDt, reg1=incReg, reg2=indexTr.resultReg, labelSymbol=variable)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
throw AssemblyError("weird assigntarget")
|
||||
} else
|
||||
throw AssemblyError("weird assigntarget")
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
@ -1459,10 +1459,10 @@ class IRCodeGen(
|
||||
addToResult(result, countTr, countTr.resultReg, -1)
|
||||
addInstr(result, IRInstruction(Opcode.BEQ, irDt, reg1=countTr.resultReg, immediate = 0, labelSymbol = skipRepeatLabel), null)
|
||||
result += labelFirstChunk(translateNode(repeat.statements), repeatLabel)
|
||||
val chunk = IRCodeChunk(null, null)
|
||||
chunk += IRInstruction(Opcode.DEC, irDt, reg1=countTr.resultReg)
|
||||
chunk += IRInstruction(Opcode.BNE, irDt, reg1=countTr.resultReg, immediate = 0, labelSymbol = repeatLabel)
|
||||
result += chunk
|
||||
result += IRCodeChunk(null, null).also {
|
||||
it += IRInstruction(Opcode.DEC, irDt, reg1 = countTr.resultReg)
|
||||
it += IRInstruction(Opcode.BNE, irDt, reg1 = countTr.resultReg, immediate = 0, labelSymbol = repeatLabel)
|
||||
}
|
||||
result += IRCodeChunk(skipRepeatLabel, null)
|
||||
return result
|
||||
}
|
||||
|
@ -697,6 +697,9 @@ internal class AstChecker(private val program: Program,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(decl.splitArray && decl.type==VarDeclType.MEMORY)
|
||||
err("@split can't be used on memory mapped arrays")
|
||||
}
|
||||
|
||||
if(decl.datatype==DataType.STR) {
|
||||
|
@ -1,6 +1,8 @@
|
||||
TODO
|
||||
====
|
||||
|
||||
- vm: fix the last replacement code for the now removed LOADSPLIT/STORESPLIT opcodes.
|
||||
|
||||
...
|
||||
|
||||
|
||||
|
@ -1,30 +1,34 @@
|
||||
%import textio
|
||||
%option splitarrays
|
||||
%zeropage basicsafe
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
str name1 = "name1"
|
||||
str name2 = "name2"
|
||||
uword[] names = [name1, name2, "name3"]
|
||||
cx16.r0++
|
||||
ubyte xx = 2
|
||||
names[xx] = "irmen"
|
||||
uword ww
|
||||
for ww in names {
|
||||
txt.print(ww)
|
||||
txt.spc()
|
||||
}
|
||||
txt.nl()
|
||||
|
||||
names = [1111,2222,3333]
|
||||
for ww in names {
|
||||
txt.print_uw(ww)
|
||||
txt.spc()
|
||||
}
|
||||
txt.nl()
|
||||
uword[] names = [name1, name2, "name3"]
|
||||
|
||||
uword ww
|
||||
; for ww in names {
|
||||
; txt.print(ww)
|
||||
; txt.spc()
|
||||
; }
|
||||
; txt.nl()
|
||||
ubyte idx=1
|
||||
names[idx] = 2000
|
||||
txt.print_uw(names[1])
|
||||
names[idx]++
|
||||
txt.print_uw(names[1])
|
||||
names[idx]--
|
||||
txt.print_uw(names[1])
|
||||
|
||||
; names = [1111,2222,3333]
|
||||
; for ww in names {
|
||||
; txt.print_uw(ww)
|
||||
; txt.spc()
|
||||
; }
|
||||
; txt.nl()
|
||||
txt.print("end.")
|
||||
repeat {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,8 +185,14 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
||||
xml.writeStartElement("VARIABLESNOINIT")
|
||||
xml.writeCharacters("\n")
|
||||
for (variable in variablesNoInit) {
|
||||
val typeStr = getTypeString(variable)
|
||||
xml.writeCharacters("$typeStr ${variable.name} zp=${variable.zpwish}\n")
|
||||
if(variable.dt in SplitWordArrayTypes) {
|
||||
// split into 2 ubyte arrays lsb+msb
|
||||
xml.writeCharacters("ubyte[${variable.length}] ${variable.name}_lsb zp=${variable.zpwish}\n")
|
||||
xml.writeCharacters("ubyte[${variable.length}] ${variable.name}_msb zp=${variable.zpwish}\n")
|
||||
} else {
|
||||
val typeStr = getTypeString(variable)
|
||||
xml.writeCharacters("$typeStr ${variable.name} zp=${variable.zpwish}\n")
|
||||
}
|
||||
}
|
||||
|
||||
xml.writeEndElement()
|
||||
@ -195,36 +201,60 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
||||
xml.writeCharacters("\n")
|
||||
|
||||
for (variable in variablesWithInit) {
|
||||
val typeStr = getTypeString(variable)
|
||||
val value: String = when(variable.dt) {
|
||||
DataType.FLOAT -> (variable.onetimeInitializationNumericValue ?: "").toString()
|
||||
in NumericDatatypes -> (variable.onetimeInitializationNumericValue?.toInt()?.toHex() ?: "").toString()
|
||||
DataType.STR -> {
|
||||
val encoded = irProgram.encoding.encodeString(variable.onetimeInitializationStringValue!!.first, variable.onetimeInitializationStringValue!!.second) + listOf(0u)
|
||||
encoded.joinToString(",") { it.toInt().toString() }
|
||||
}
|
||||
DataType.ARRAY_F -> {
|
||||
if(variable.onetimeInitializationArrayValue!=null) {
|
||||
variable.onetimeInitializationArrayValue!!.joinToString(",") { it.number!!.toString() }
|
||||
} else {
|
||||
"" // array will be zero'd out at program start
|
||||
if(variable.dt in SplitWordArrayTypes) {
|
||||
val lsbValue: String
|
||||
val msbValue: String
|
||||
if(variable.onetimeInitializationArrayValue==null) {
|
||||
lsbValue = ""
|
||||
msbValue = ""
|
||||
} else {
|
||||
lsbValue = variable.onetimeInitializationArrayValue!!.joinToString(",") {
|
||||
if(it.number!=null)
|
||||
(it.number!!.toInt() and 255).toHex()
|
||||
else
|
||||
"@<${it.addressOfSymbol}"
|
||||
}
|
||||
msbValue = variable.onetimeInitializationArrayValue!!.joinToString(",") {
|
||||
if(it.number!=null)
|
||||
(it.number!!.toInt() shr 8).toHex()
|
||||
else
|
||||
"@>${it.addressOfSymbol}"
|
||||
}
|
||||
}
|
||||
in ArrayDatatypes -> {
|
||||
if(variable.onetimeInitializationArrayValue!==null) {
|
||||
variable.onetimeInitializationArrayValue!!.joinToString(",") {
|
||||
if(it.number!=null)
|
||||
it.number!!.toInt().toHex()
|
||||
else
|
||||
"@${it.addressOfSymbol}"
|
||||
xml.writeCharacters("ubyte[${variable.length}] ${variable.name}_lsb=$lsbValue zp=${variable.zpwish}\n")
|
||||
xml.writeCharacters("ubyte[${variable.length}] ${variable.name}_msb=$msbValue zp=${variable.zpwish}\n")
|
||||
} else {
|
||||
val typeStr = getTypeString(variable)
|
||||
val value: String = when(variable.dt) {
|
||||
DataType.FLOAT -> (variable.onetimeInitializationNumericValue ?: "").toString()
|
||||
in NumericDatatypes -> (variable.onetimeInitializationNumericValue?.toInt()?.toHex() ?: "").toString()
|
||||
DataType.STR -> {
|
||||
val encoded = irProgram.encoding.encodeString(variable.onetimeInitializationStringValue!!.first, variable.onetimeInitializationStringValue!!.second) + listOf(0u)
|
||||
encoded.joinToString(",") { it.toInt().toString() }
|
||||
}
|
||||
DataType.ARRAY_F -> {
|
||||
if(variable.onetimeInitializationArrayValue!=null) {
|
||||
variable.onetimeInitializationArrayValue!!.joinToString(",") { it.number!!.toString() }
|
||||
} else {
|
||||
"" // array will be zero'd out at program start
|
||||
}
|
||||
} else {
|
||||
"" // array will be zero'd out at program start
|
||||
}
|
||||
in ArrayDatatypes -> {
|
||||
if(variable.onetimeInitializationArrayValue!==null) {
|
||||
variable.onetimeInitializationArrayValue!!.joinToString(",") {
|
||||
if(it.number!=null)
|
||||
it.number!!.toInt().toHex()
|
||||
else
|
||||
"@${it.addressOfSymbol}"
|
||||
}
|
||||
} else {
|
||||
"" // array will be zero'd out at program start
|
||||
}
|
||||
}
|
||||
else -> throw InternalCompilerException("weird dt")
|
||||
}
|
||||
else -> throw InternalCompilerException("weird dt")
|
||||
xml.writeCharacters("$typeStr ${variable.name}=$value zp=${variable.zpwish}\n")
|
||||
}
|
||||
xml.writeCharacters("$typeStr ${variable.name}=$value zp=${variable.zpwish}\n")
|
||||
}
|
||||
xml.writeEndElement()
|
||||
xml.writeCharacters("\n")
|
||||
|
@ -36,15 +36,11 @@ load reg1, value - load immediate value into register. If y
|
||||
loadm reg1, address - load reg1 with value at memory address
|
||||
loadi reg1, reg2 - load reg1 with value at memory indirect, memory pointed to by reg2
|
||||
loadx reg1, reg2, address - load reg1 with value at memory address indexed by value in reg2
|
||||
loadxsplit reg1, reg2, arraylength, arrayaddress - load reg1 word with value from "split lsb/msb array" indexed by reg2
|
||||
loadmsplit reg1, arraylength, indexedarrayaddress - load reg1 word with value from "split lsb/msb array" element at indexedarrayaddress
|
||||
loadix reg1, reg2, pointeraddr - load reg1 with value at memory indirect, pointed to by pointeraddr indexed by value in reg2
|
||||
loadr reg1, reg2 - load reg1 with value in register reg2
|
||||
storem reg1, address - store reg1 at memory address
|
||||
storei reg1, reg2 - store reg1 at memory indirect, memory pointed to by reg2
|
||||
storex reg1, reg2, address - store reg1 at memory address, indexed by value in reg2
|
||||
storexsplit reg1, reg2, arraylength, arrayaddress - store reg1 word in "split lsb/msb array", indexed by value in reg2
|
||||
storemsplit reg1, arraylength, indexedarrayaddress - store reg1 word in "split lsb/msb array" element at indexedarrayaddress
|
||||
storeix reg1, reg2, pointeraddr - store reg1 at memory indirect, pointed to by pointeraddr indexed by value in reg2
|
||||
storezm address - store zero at memory address
|
||||
storezi reg1 - store zero at memory pointed to by reg1
|
||||
@ -121,10 +117,8 @@ exts reg1 - reg1 = signed extension of reg1 (b
|
||||
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
|
||||
incmsplit arraylen, address - memory at address += 1 (in lsb/msb split word array)
|
||||
dec reg1 - reg1 = reg1-1
|
||||
decm address - memory at address -= 1
|
||||
decmsplit arraylen, address - memory at address -= 1 (in lsb/msb split word array)
|
||||
neg reg1 - reg1 = sign negation of reg1
|
||||
negm address - sign negate memory at address
|
||||
addr reg1, reg2 - reg1 += reg2
|
||||
@ -233,21 +227,15 @@ enum class Opcode {
|
||||
LOADM,
|
||||
LOADI,
|
||||
LOADX,
|
||||
LOADXSPLIT,
|
||||
LOADMSPLIT,
|
||||
LOADIX,
|
||||
LOADR,
|
||||
STOREM,
|
||||
STOREI,
|
||||
STOREX,
|
||||
STOREXSPLIT,
|
||||
STOREMSPLIT,
|
||||
STOREIX,
|
||||
STOREZM,
|
||||
STOREZI,
|
||||
STOREZX,
|
||||
STOREZXSPLIT,
|
||||
STOREZMSPLIT,
|
||||
|
||||
JUMP,
|
||||
JUMPA,
|
||||
@ -295,10 +283,8 @@ enum class Opcode {
|
||||
|
||||
INC,
|
||||
INCM,
|
||||
INCMSPLIT,
|
||||
DEC,
|
||||
DECM,
|
||||
DECMSPLIT,
|
||||
NEG,
|
||||
NEGM,
|
||||
ADDR,
|
||||
@ -516,21 +502,15 @@ val instructionFormats = mutableMapOf(
|
||||
Opcode.LOADM to InstructionFormat.from("BW,>r1,<a | F,>fr1,<a"),
|
||||
Opcode.LOADI to InstructionFormat.from("BW,>r1,<r2 | F,>fr1,<r1"),
|
||||
Opcode.LOADX to InstructionFormat.from("BW,>r1,<r2,<a | F,>fr1,<r1,<a"),
|
||||
Opcode.LOADXSPLIT to InstructionFormat.from("W,>r1,<r2,<i,<a"),
|
||||
Opcode.LOADMSPLIT to InstructionFormat.from("W,>r1,<i,<a"),
|
||||
Opcode.LOADIX to InstructionFormat.from("BW,>r1,<r2,<a | F,>fr1,<r1,<a"),
|
||||
Opcode.LOADR to InstructionFormat.from("BW,>r1,<r2 | F,>fr1,<fr2"),
|
||||
Opcode.STOREM to InstructionFormat.from("BW,<r1,>a | F,<fr1,>a"),
|
||||
Opcode.STOREI to InstructionFormat.from("BW,<r1,<r2 | F,<fr1,<r1"),
|
||||
Opcode.STOREX to InstructionFormat.from("BW,<r1,<r2,>a | F,<fr1,<r1,>a"),
|
||||
Opcode.STOREXSPLIT to InstructionFormat.from("W,<r1,<r2,<i,>a"),
|
||||
Opcode.STOREMSPLIT to InstructionFormat.from("W,<r1,<i,>a"),
|
||||
Opcode.STOREIX to InstructionFormat.from("BW,<r1,<r2,>a | F,<fr1,<r1,>a"),
|
||||
Opcode.STOREZM to InstructionFormat.from("BW,>a | F,>a"),
|
||||
Opcode.STOREZI to InstructionFormat.from("BW,<r1 | F,<r1"),
|
||||
Opcode.STOREZX to InstructionFormat.from("BW,<r1,>a | F,<r1,>a"),
|
||||
Opcode.STOREZMSPLIT to InstructionFormat.from("W,<i,>a"),
|
||||
Opcode.STOREZXSPLIT to InstructionFormat.from("W,<r1,<i,>a"),
|
||||
Opcode.JUMP to InstructionFormat.from("N,<a"),
|
||||
Opcode.JUMPA to InstructionFormat.from("N,<a"),
|
||||
Opcode.CALL to InstructionFormat.from("N,call"),
|
||||
@ -575,10 +555,8 @@ val instructionFormats = mutableMapOf(
|
||||
Opcode.SGES to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.INC to InstructionFormat.from("BW,<>r1 | F,<>fr1"),
|
||||
Opcode.INCM to InstructionFormat.from("BW,<>a | F,<>a"),
|
||||
Opcode.INCMSPLIT to InstructionFormat.from("W,<i,<>a"),
|
||||
Opcode.DEC to InstructionFormat.from("BW,<>r1 | F,<>fr1"),
|
||||
Opcode.DECM to InstructionFormat.from("BW,<>a | F,<>a"),
|
||||
Opcode.DECMSPLIT to InstructionFormat.from("W,<i,<>a"),
|
||||
Opcode.NEG to InstructionFormat.from("BW,<>r1 | F,<>fr1"),
|
||||
Opcode.NEGM to InstructionFormat.from("BW,<>a | F,<>a"),
|
||||
Opcode.ADDR to InstructionFormat.from("BW,<>r1,<r2 | F,<>fr1,<fr2"),
|
||||
|
@ -14,10 +14,9 @@ fun getTypeString(dt : DataType): String = when(dt) {
|
||||
DataType.ARRAY_UB, DataType.STR -> "ubyte[]"
|
||||
DataType.ARRAY_B -> "byte[]"
|
||||
DataType.ARRAY_UW -> "uword[]"
|
||||
DataType.ARRAY_UW_SPLIT -> "uword_split[]"
|
||||
DataType.ARRAY_W -> "word[]"
|
||||
DataType.ARRAY_W_SPLIT -> "word_split[]"
|
||||
DataType.ARRAY_F -> "float[]"
|
||||
in SplitWordArrayTypes -> throw InternalCompilerException("split array should have been converted to 2 ubyte arrays")
|
||||
else -> throw InternalCompilerException("weird dt")
|
||||
}
|
||||
|
||||
@ -31,10 +30,9 @@ fun getTypeString(memvar: StMemVar): String = when(memvar.dt) {
|
||||
DataType.ARRAY_UB, DataType.STR -> "ubyte[${memvar.length}]"
|
||||
DataType.ARRAY_B -> "byte[${memvar.length}]"
|
||||
DataType.ARRAY_UW -> "uword[${memvar.length}]"
|
||||
DataType.ARRAY_UW_SPLIT -> "uword_split[${memvar.length}]"
|
||||
DataType.ARRAY_W -> "word[${memvar.length}]"
|
||||
DataType.ARRAY_W_SPLIT -> "word_split[${memvar.length}]"
|
||||
DataType.ARRAY_F -> "float[${memvar.length}]"
|
||||
in SplitWordArrayTypes -> throw InternalCompilerException("@split can't be used on memory mapped arrays")
|
||||
else -> throw InternalCompilerException("weird dt")
|
||||
}
|
||||
|
||||
@ -48,10 +46,9 @@ fun getTypeString(variable : StStaticVariable): String = when(variable.dt) {
|
||||
DataType.ARRAY_UB, DataType.STR -> "ubyte[${variable.length}]"
|
||||
DataType.ARRAY_B -> "byte[${variable.length}]"
|
||||
DataType.ARRAY_UW -> "uword[${variable.length}]"
|
||||
DataType.ARRAY_UW_SPLIT -> "uword_split[${variable.length}]"
|
||||
DataType.ARRAY_W -> "word[${variable.length}]"
|
||||
DataType.ARRAY_W_SPLIT -> "word_split[${variable.length}]"
|
||||
DataType.ARRAY_F -> "float[${variable.length}]"
|
||||
in SplitWordArrayTypes -> throw InternalCompilerException("split array should have been converted to 2 ubyte arrays")
|
||||
else -> throw InternalCompilerException("weird dt")
|
||||
}
|
||||
|
||||
@ -78,6 +75,8 @@ fun parseIRValue(value: String): Float {
|
||||
throw IRParseException("attempt to parse a label as numeric value")
|
||||
else if(value.startsWith('&'))
|
||||
throw IRParseException("address-of should be done with normal LOAD <symbol>")
|
||||
else if(value.startsWith('@'))
|
||||
throw IRParseException("address-of @ should have been handled earlier")
|
||||
else
|
||||
return value.toFloat()
|
||||
}
|
||||
|
@ -164,17 +164,11 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
Opcode.LOAD -> InsLOAD(ins)
|
||||
Opcode.LOADM -> InsLOADM(ins)
|
||||
Opcode.LOADX -> InsLOADX(ins)
|
||||
Opcode.LOADXSPLIT -> InsLOADXSPLIT(ins)
|
||||
Opcode.LOADMSPLIT -> InsLOADMSPLIT(ins)
|
||||
Opcode.LOADI -> InsLOADI(ins)
|
||||
Opcode.LOADIX -> InsLOADIX(ins)
|
||||
Opcode.LOADR -> InsLOADR(ins)
|
||||
Opcode.STOREM -> InsSTOREM(ins)
|
||||
Opcode.STOREX -> InsSTOREX(ins)
|
||||
Opcode.STOREXSPLIT -> InsSTOREXSPLIT(ins)
|
||||
Opcode.STOREZXSPLIT -> InsSTOREZXSPLIT(ins)
|
||||
Opcode.STOREMSPLIT -> InsSTOREMSPLIT(ins)
|
||||
Opcode.STOREZMSPLIT -> InsSTOREZMSPLIT(ins)
|
||||
Opcode.STOREIX -> InsSTOREIX(ins)
|
||||
Opcode.STOREI -> InsSTOREI(ins)
|
||||
Opcode.STOREZM -> InsSTOREZM(ins)
|
||||
@ -223,10 +217,8 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
Opcode.SGES -> InsSGES(ins)
|
||||
Opcode.INC -> InsINC(ins)
|
||||
Opcode.INCM -> InsINCM(ins)
|
||||
Opcode.INCMSPLIT -> InsINCMSPLIT(ins)
|
||||
Opcode.DEC -> InsDEC(ins)
|
||||
Opcode.DECM -> InsDECM(ins)
|
||||
Opcode.DECMSPLIT -> InsDECMSPLIT(ins)
|
||||
Opcode.NEG -> InsNEG(ins)
|
||||
Opcode.NEGM -> InsNEGM(ins)
|
||||
Opcode.ADDR -> InsADDR(ins)
|
||||
@ -421,60 +413,6 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsLOADXSPLIT(i: IRInstruction) {
|
||||
require(i.type==IRDataType.WORD)
|
||||
val address = i.address!! + registers.getUW(i.reg2!!).toInt()
|
||||
val lsb = memory.getUB(address)
|
||||
val msb = memory.getUB(address+i.immediate!!)
|
||||
registers.setUW(i.reg1!!, ((msb.toInt() shl 8) or lsb.toInt()).toUShort())
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsLOADMSPLIT(i: IRInstruction) {
|
||||
require(i.type==IRDataType.WORD)
|
||||
val address = i.address!!
|
||||
val lsb = memory.getUB(address)
|
||||
val msb = memory.getUB(address+i.immediate!!)
|
||||
registers.setUW(i.reg1!!, ((msb.toInt() shl 8) or lsb.toInt()).toUShort())
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsSTOREXSPLIT(i: IRInstruction) {
|
||||
require(i.type==IRDataType.WORD)
|
||||
val address = i.address!! + registers.getUW(i.reg2!!).toInt()
|
||||
val lsb = registers.getUW(i.reg1!!).toUByte()
|
||||
val msb = (registers.getUW(i.reg1!!).toInt() shr 8).toUByte()
|
||||
memory.setUB(address, lsb)
|
||||
memory.setUB(address+i.immediate!!, msb)
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsSTOREMSPLIT(i: IRInstruction) {
|
||||
require(i.type==IRDataType.WORD)
|
||||
val address = i.address!!
|
||||
val lsb = registers.getUW(i.reg1!!).toUByte()
|
||||
val msb = (registers.getUW(i.reg1!!).toInt() shr 8).toUByte()
|
||||
memory.setUB(address, lsb)
|
||||
memory.setUB(address+i.immediate!!, msb)
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsSTOREZXSPLIT(i: IRInstruction) {
|
||||
require(i.type==IRDataType.WORD)
|
||||
val address = i.address!! + registers.getUW(i.reg2!!).toInt()
|
||||
memory.setUB(address, 0u)
|
||||
memory.setUB(address+i.immediate!!, 0u)
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsSTOREZMSPLIT(i: IRInstruction) {
|
||||
require(i.type==IRDataType.WORD)
|
||||
val address = i.address!!
|
||||
memory.setUB(address, 0u)
|
||||
memory.setUB(address+i.immediate!!, 0u)
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsLOADIX(i: IRInstruction) {
|
||||
when (i.type!!) {
|
||||
IRDataType.BYTE -> {
|
||||
@ -921,20 +859,6 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsINCMSPLIT(i: IRInstruction) {
|
||||
val address = i.address!!
|
||||
var lsb = memory.getUB(address).toInt()
|
||||
var msb = memory.getUB(address+i.immediate!!).toInt()
|
||||
lsb++
|
||||
if(lsb>255) {
|
||||
lsb = 0
|
||||
msb++
|
||||
}
|
||||
memory.setUB(address, lsb.toUByte())
|
||||
memory.setUB(address+i.immediate!!, msb.toUByte())
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsDEC(i: IRInstruction) {
|
||||
when(i.type!!) {
|
||||
IRDataType.BYTE -> registers.setUB(i.reg1!!, (registers.getUB(i.reg1!!)-1u).toUByte())
|
||||
@ -953,21 +877,6 @@ class VirtualMachine(irProgram: IRProgram) {
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsDECMSPLIT(i: IRInstruction) {
|
||||
val address = i.address!!
|
||||
var lsb = memory.getUB(address).toInt()
|
||||
var msb = memory.getUB(address+i.immediate!!).toInt()
|
||||
lsb--
|
||||
if(lsb<0) {
|
||||
lsb = 255
|
||||
msb--
|
||||
}
|
||||
memory.setUB(address, lsb.toUByte())
|
||||
memory.setUB(address+i.immediate!!, msb.toUByte())
|
||||
nextPc()
|
||||
|
||||
}
|
||||
|
||||
private fun InsNEG(i: IRInstruction) {
|
||||
when(i.type!!) {
|
||||
IRDataType.BYTE -> registers.setUB(i.reg1!!, (-registers.getUB(i.reg1!!).toInt()).toUByte())
|
||||
|
@ -295,7 +295,20 @@ class VmProgramLoader {
|
||||
when(variable.dt) {
|
||||
DataType.STR, DataType.ARRAY_UB -> {
|
||||
for(elt in it) {
|
||||
memory.setUB(addr, elt.number!!.toInt().toUByte())
|
||||
if(elt.addressOfSymbol!=null) {
|
||||
val name = elt.addressOfSymbol!!
|
||||
val symbolAddress = if(name.startsWith('<')) {
|
||||
symbolAddresses[name.drop(1)]?.and(255)
|
||||
?: throw IRParseException("vm cannot yet load a label address as a value: $name") // TODO
|
||||
} else if(name.startsWith('>')) {
|
||||
symbolAddresses[name.drop(1)]?.shr(8)
|
||||
?: throw IRParseException("vm cannot yet load a label address as a value: $name") // TODO
|
||||
} else
|
||||
throw IRParseException("for byte-array address-of, expected < or > (lsb/msb)")
|
||||
memory.setUB(addr, symbolAddress.toUByte())
|
||||
} else {
|
||||
memory.setUB(addr, elt.number!!.toInt().toUByte())
|
||||
}
|
||||
addr++
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user