mirror of
https://github.com/irmen/prog8.git
synced 2025-04-28 04:37:46 +00:00
ir: consolidate IRCodeInstruction and Instruction
This commit is contained in:
parent
0da117efd2
commit
4d6dcbd173
@ -6,7 +6,7 @@ import prog8.code.core.DataType
|
||||
import prog8.code.core.Position
|
||||
import prog8.code.core.SignedDatatypes
|
||||
import prog8.intermediate.IRCodeChunk
|
||||
import prog8.intermediate.IRCodeInstruction
|
||||
import prog8.intermediate.IRInstruction
|
||||
import prog8.intermediate.Opcode
|
||||
import prog8.intermediate.VmDataType
|
||||
|
||||
@ -62,8 +62,8 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
else {
|
||||
// read and write a (i/o) memory location to itself.
|
||||
val tempReg = codeGen.vmRegisters.nextFree()
|
||||
code += IRCodeInstruction(Opcode.LOADM, vmDt, reg1 = tempReg, value = address)
|
||||
code += IRCodeInstruction(Opcode.STOREM, vmDt, reg1 = tempReg, value = address)
|
||||
code += IRInstruction(Opcode.LOADM, vmDt, reg1 = tempReg, value = address)
|
||||
code += IRInstruction(Opcode.STOREM, vmDt, reg1 = tempReg, value = address)
|
||||
code
|
||||
}
|
||||
}
|
||||
@ -85,8 +85,8 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
is PtBinaryExpression -> return inplaceBinexpr(value.operator, value.right, vmDt, value.type in SignedDatatypes, null, symbol, origAssign)
|
||||
is PtMemoryByte -> {
|
||||
val tempReg = codeGen.vmRegisters.nextFree()
|
||||
code += IRCodeInstruction(Opcode.LOADM, vmDt, reg1 = tempReg, labelSymbol = symbol)
|
||||
code += IRCodeInstruction(Opcode.STOREM, vmDt, reg1 = tempReg, labelSymbol = symbol)
|
||||
code += IRInstruction(Opcode.LOADM, vmDt, reg1 = tempReg, labelSymbol = symbol)
|
||||
code += IRInstruction(Opcode.STOREM, vmDt, reg1 = tempReg, labelSymbol = symbol)
|
||||
return code
|
||||
}
|
||||
else -> return fallbackAssign(origAssign)
|
||||
@ -145,18 +145,18 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
"+" -> { }
|
||||
"-" -> {
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.NEGM, vmDt, value = knownAddress)
|
||||
IRInstruction(Opcode.NEGM, vmDt, value = knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.NEGM, vmDt, labelSymbol = addressSymbol)
|
||||
IRInstruction(Opcode.NEGM, vmDt, labelSymbol = addressSymbol)
|
||||
}
|
||||
"~" -> {
|
||||
val regMask = codeGen.vmRegisters.nextFree()
|
||||
val mask = if(vmDt==VmDataType.BYTE) 0x00ff else 0xffff
|
||||
code += IRCodeInstruction(Opcode.LOAD, vmDt, reg1=regMask, value = mask)
|
||||
code += IRInstruction(Opcode.LOAD, vmDt, reg1=regMask, value = mask)
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.XORM, vmDt, reg1=regMask, value = knownAddress)
|
||||
IRInstruction(Opcode.XORM, vmDt, reg1=regMask, value = knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.XORM, vmDt, reg1=regMask, labelSymbol = addressSymbol)
|
||||
IRInstruction(Opcode.XORM, vmDt, reg1=regMask, labelSymbol = addressSymbol)
|
||||
}
|
||||
else -> throw AssemblyError("weird prefix operator")
|
||||
}
|
||||
@ -192,12 +192,12 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
if(ident!=null) {
|
||||
val symbol = ident.targetName.joinToString(".")
|
||||
code += if(zero) {
|
||||
IRCodeInstruction(Opcode.STOREZM, vmDt, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.STOREZM, vmDt, labelSymbol = symbol)
|
||||
} else {
|
||||
if (vmDt == VmDataType.FLOAT)
|
||||
IRCodeInstruction(Opcode.STOREM, vmDt, fpReg1 = resultFpRegister, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.STOREM, vmDt, fpReg1 = resultFpRegister, labelSymbol = symbol)
|
||||
else
|
||||
IRCodeInstruction(Opcode.STOREM, vmDt, reg1 = resultRegister, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.STOREM, vmDt, reg1 = resultRegister, labelSymbol = symbol)
|
||||
}
|
||||
}
|
||||
else if(array!=null) {
|
||||
@ -215,9 +215,9 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
if(zero) {
|
||||
// there's no STOREZIX instruction
|
||||
resultRegister = codeGen.vmRegisters.nextFree()
|
||||
code += IRCodeInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=0)
|
||||
code += IRInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=0)
|
||||
}
|
||||
code += IRCodeInstruction(Opcode.STOREIX, vmDt, reg1=resultRegister, reg2=idxReg, labelSymbol = variable)
|
||||
code += IRInstruction(Opcode.STOREIX, vmDt, reg1=resultRegister, reg2=idxReg, labelSymbol = variable)
|
||||
return code
|
||||
}
|
||||
|
||||
@ -225,30 +225,30 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
if(zero) {
|
||||
if(fixedIndex!=null) {
|
||||
val offset = fixedIndex*itemsize
|
||||
code += IRCodeInstruction(Opcode.STOREZM, vmDt, labelSymbol = "$variable+$offset")
|
||||
code += IRInstruction(Opcode.STOREZM, vmDt, labelSymbol = "$variable+$offset")
|
||||
} else {
|
||||
val indexReg = codeGen.vmRegisters.nextFree()
|
||||
code += loadIndexReg(array, itemsize, indexReg, array.position)
|
||||
code += IRCodeInstruction(Opcode.STOREZX, vmDt, reg1=indexReg, labelSymbol = variable)
|
||||
code += IRInstruction(Opcode.STOREZX, vmDt, reg1=indexReg, labelSymbol = variable)
|
||||
}
|
||||
} else {
|
||||
if(vmDt== VmDataType.FLOAT) {
|
||||
if(fixedIndex!=null) {
|
||||
val offset = fixedIndex*itemsize
|
||||
code += IRCodeInstruction(Opcode.STOREM, vmDt, fpReg1 = resultFpRegister, labelSymbol = "$variable+$offset")
|
||||
code += IRInstruction(Opcode.STOREM, vmDt, fpReg1 = resultFpRegister, labelSymbol = "$variable+$offset")
|
||||
} else {
|
||||
val indexReg = codeGen.vmRegisters.nextFree()
|
||||
code += loadIndexReg(array, itemsize, indexReg, array.position)
|
||||
code += IRCodeInstruction(Opcode.STOREX, vmDt, reg1 = resultRegister, reg2=indexReg, labelSymbol = variable)
|
||||
code += IRInstruction(Opcode.STOREX, vmDt, reg1 = resultRegister, reg2=indexReg, labelSymbol = variable)
|
||||
}
|
||||
} else {
|
||||
if(fixedIndex!=null) {
|
||||
val offset = fixedIndex*itemsize
|
||||
code += IRCodeInstruction(Opcode.STOREM, vmDt, reg1 = resultRegister, labelSymbol = "$variable+$offset")
|
||||
code += IRInstruction(Opcode.STOREM, vmDt, reg1 = resultRegister, labelSymbol = "$variable+$offset")
|
||||
} else {
|
||||
val indexReg = codeGen.vmRegisters.nextFree()
|
||||
code += loadIndexReg(array, itemsize, indexReg, array.position)
|
||||
code += IRCodeInstruction(Opcode.STOREX, vmDt, reg1 = resultRegister, reg2=indexReg, labelSymbol = variable)
|
||||
code += IRInstruction(Opcode.STOREX, vmDt, reg1 = resultRegister, reg2=indexReg, labelSymbol = variable)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -257,19 +257,19 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
|
||||
require(vmDt== VmDataType.BYTE)
|
||||
if(zero) {
|
||||
if(memory.address is PtNumber) {
|
||||
code += IRCodeInstruction(Opcode.STOREZM, vmDt, value=(memory.address as PtNumber).number.toInt())
|
||||
code += IRInstruction(Opcode.STOREZM, vmDt, value=(memory.address as PtNumber).number.toInt())
|
||||
} else {
|
||||
val addressReg = codeGen.vmRegisters.nextFree()
|
||||
code += expressionEval.translateExpression(memory.address, addressReg, -1)
|
||||
code += IRCodeInstruction(Opcode.STOREZI, vmDt, reg1=addressReg)
|
||||
code += IRInstruction(Opcode.STOREZI, vmDt, reg1=addressReg)
|
||||
}
|
||||
} else {
|
||||
if(memory.address is PtNumber) {
|
||||
code += IRCodeInstruction(Opcode.STOREM, vmDt, reg1=resultRegister, value=(memory.address as PtNumber).number.toInt())
|
||||
code += IRInstruction(Opcode.STOREM, vmDt, reg1=resultRegister, value=(memory.address as PtNumber).number.toInt())
|
||||
} else {
|
||||
val addressReg = codeGen.vmRegisters.nextFree()
|
||||
code += expressionEval.translateExpression(memory.address, addressReg, -1)
|
||||
code += IRCodeInstruction(Opcode.STOREI, vmDt, reg1=resultRegister, reg2=addressReg)
|
||||
code += IRInstruction(Opcode.STOREI, vmDt, reg1=resultRegister, reg2=addressReg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
val rightRegister = codeGen.vmRegisters.nextFree()
|
||||
code += exprGen.translateExpression(call.args[0], leftRegister, -1)
|
||||
code += exprGen.translateExpression(call.args[1], rightRegister, -1)
|
||||
code += IRCodeInstruction(Opcode.CMP, codeGen.vmType(call.args[0].type), reg1=leftRegister, reg2=rightRegister)
|
||||
code += IRInstruction(Opcode.CMP, codeGen.vmType(call.args[0].type), reg1=leftRegister, reg2=rightRegister)
|
||||
return code
|
||||
}
|
||||
|
||||
@ -73,10 +73,10 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
else -> throw IllegalArgumentException("weird type")
|
||||
}
|
||||
code += exprGen.translateExpression(call.args[0], 0, -1)
|
||||
code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1 = 1, value = array.length)
|
||||
code += IRCodeInstruction(Opcode.SYSCALL, value = syscall.ordinal)
|
||||
code += IRInstruction(Opcode.LOAD, VmDataType.BYTE, reg1 = 1, value = array.length)
|
||||
code += IRInstruction(Opcode.SYSCALL, value = syscall.ordinal)
|
||||
if (resultRegister != 0)
|
||||
code += IRCodeInstruction(Opcode.LOADR, VmDataType.BYTE, reg1 = resultRegister, reg2 = 0)
|
||||
code += IRInstruction(Opcode.LOADR, VmDataType.BYTE, reg1 = resultRegister, reg2 = 0)
|
||||
return code
|
||||
}
|
||||
|
||||
@ -94,10 +94,10 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
}
|
||||
val code = IRCodeChunk(call.position)
|
||||
code += exprGen.translateExpression(call.args[0], 0, -1)
|
||||
code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
|
||||
code += IRCodeInstruction(Opcode.SYSCALL, value=syscall.ordinal)
|
||||
code += IRInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
|
||||
code += IRInstruction(Opcode.SYSCALL, value=syscall.ordinal)
|
||||
if(resultRegister!=0)
|
||||
code += IRCodeInstruction(Opcode.LOADR, VmDataType.BYTE, reg1=resultRegister, reg2=0)
|
||||
code += IRInstruction(Opcode.LOADR, VmDataType.BYTE, reg1=resultRegister, reg2=0)
|
||||
return code
|
||||
}
|
||||
|
||||
@ -108,25 +108,25 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
code += exprGen.translateExpression(call.args[0], resultRegister, -1)
|
||||
when (sourceDt) {
|
||||
DataType.UBYTE -> {
|
||||
code += IRCodeInstruction(Opcode.EXT, VmDataType.BYTE, reg1=resultRegister)
|
||||
code += IRInstruction(Opcode.EXT, VmDataType.BYTE, reg1=resultRegister)
|
||||
}
|
||||
DataType.BYTE -> {
|
||||
val notNegativeLabel = codeGen.createLabelName()
|
||||
val compareReg = codeGen.vmRegisters.nextFree()
|
||||
code += IRCodeInstruction(Opcode.LOADR, VmDataType.BYTE, reg1=compareReg, reg2=resultRegister)
|
||||
code += IRCodeInstruction(Opcode.AND, VmDataType.BYTE, reg1=compareReg, value=0x80)
|
||||
code += IRCodeInstruction(Opcode.BZ, VmDataType.BYTE, reg1=compareReg, labelSymbol = notNegativeLabel)
|
||||
code += IRCodeInstruction(Opcode.NEG, VmDataType.BYTE, reg1=resultRegister)
|
||||
code += IRCodeInstruction(Opcode.EXT, VmDataType.BYTE, reg1=resultRegister)
|
||||
code += IRInstruction(Opcode.LOADR, VmDataType.BYTE, reg1=compareReg, reg2=resultRegister)
|
||||
code += IRInstruction(Opcode.AND, VmDataType.BYTE, reg1=compareReg, value=0x80)
|
||||
code += IRInstruction(Opcode.BZ, VmDataType.BYTE, reg1=compareReg, labelSymbol = notNegativeLabel)
|
||||
code += IRInstruction(Opcode.NEG, VmDataType.BYTE, reg1=resultRegister)
|
||||
code += IRInstruction(Opcode.EXT, VmDataType.BYTE, reg1=resultRegister)
|
||||
code += IRCodeLabel(notNegativeLabel)
|
||||
}
|
||||
DataType.WORD -> {
|
||||
val notNegativeLabel = codeGen.createLabelName()
|
||||
val compareReg = codeGen.vmRegisters.nextFree()
|
||||
code += IRCodeInstruction(Opcode.LOADR, VmDataType.WORD, reg1=compareReg, reg2=resultRegister)
|
||||
code += IRCodeInstruction(Opcode.AND, VmDataType.WORD, reg1=compareReg, value=0x8000)
|
||||
code += IRCodeInstruction(Opcode.BZ, VmDataType.WORD, reg1=compareReg, labelSymbol = notNegativeLabel)
|
||||
code += IRCodeInstruction(Opcode.NEG, VmDataType.WORD, reg1=resultRegister)
|
||||
code += IRInstruction(Opcode.LOADR, VmDataType.WORD, reg1=compareReg, reg2=resultRegister)
|
||||
code += IRInstruction(Opcode.AND, VmDataType.WORD, reg1=compareReg, value=0x8000)
|
||||
code += IRInstruction(Opcode.BZ, VmDataType.WORD, reg1=compareReg, labelSymbol = notNegativeLabel)
|
||||
code += IRInstruction(Opcode.NEG, VmDataType.WORD, reg1=resultRegister)
|
||||
code += IRCodeLabel(notNegativeLabel)
|
||||
}
|
||||
else -> throw AssemblyError("weird type")
|
||||
@ -139,7 +139,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
val code = IRCodeChunk(call.position)
|
||||
val reg = codeGen.vmRegisters.nextFree()
|
||||
code += exprGen.translateExpression(call.args.single(), reg, -1)
|
||||
code += IRCodeInstruction(Opcode.SGN, codeGen.vmType(call.type), reg1=resultRegister, reg2=reg)
|
||||
code += IRInstruction(Opcode.SGN, codeGen.vmType(call.type), reg1=resultRegister, reg2=reg)
|
||||
return code
|
||||
}
|
||||
|
||||
@ -147,14 +147,14 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
val code = IRCodeChunk(call.position)
|
||||
val reg = codeGen.vmRegisters.nextFree()
|
||||
code += exprGen.translateExpression(call.args.single(), reg, -1)
|
||||
code += IRCodeInstruction(Opcode.SQRT, VmDataType.WORD, reg1=resultRegister, reg2=reg)
|
||||
code += IRInstruction(Opcode.SQRT, VmDataType.WORD, reg1=resultRegister, reg2=reg)
|
||||
return code
|
||||
}
|
||||
|
||||
private fun funcPop(call: PtBuiltinFunctionCall): IRCodeChunk {
|
||||
val code = IRCodeChunk(call.position)
|
||||
val reg = codeGen.vmRegisters.nextFree()
|
||||
code += IRCodeInstruction(Opcode.POP, VmDataType.BYTE, reg1=reg)
|
||||
code += IRInstruction(Opcode.POP, VmDataType.BYTE, reg1=reg)
|
||||
code += assignRegisterTo(call.args.single(), reg)
|
||||
return code
|
||||
}
|
||||
@ -162,7 +162,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
private fun funcPopw(call: PtBuiltinFunctionCall): IRCodeChunk {
|
||||
val code = IRCodeChunk(call.position)
|
||||
val reg = codeGen.vmRegisters.nextFree()
|
||||
code += IRCodeInstruction(Opcode.POP, VmDataType.WORD, reg1=reg)
|
||||
code += IRInstruction(Opcode.POP, VmDataType.WORD, reg1=reg)
|
||||
code += assignRegisterTo(call.args.single(), reg)
|
||||
return code
|
||||
}
|
||||
@ -171,7 +171,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
val code = IRCodeChunk(call.position)
|
||||
val reg = codeGen.vmRegisters.nextFree()
|
||||
code += exprGen.translateExpression(call.args.single(), reg, -1)
|
||||
code += IRCodeInstruction(Opcode.PUSH, VmDataType.BYTE, reg1=reg)
|
||||
code += IRInstruction(Opcode.PUSH, VmDataType.BYTE, reg1=reg)
|
||||
return code
|
||||
}
|
||||
|
||||
@ -179,7 +179,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
val code = IRCodeChunk(call.position)
|
||||
val reg = codeGen.vmRegisters.nextFree()
|
||||
code += exprGen.translateExpression(call.args.single(), reg, -1)
|
||||
code += IRCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1=reg)
|
||||
code += IRInstruction(Opcode.PUSH, VmDataType.WORD, reg1=reg)
|
||||
return code
|
||||
}
|
||||
|
||||
@ -195,8 +195,8 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
}
|
||||
val code = IRCodeChunk(call.position)
|
||||
code += exprGen.translateExpression(call.args[0], 0, -1)
|
||||
code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
|
||||
code += IRCodeInstruction(Opcode.SYSCALL, value=syscall.ordinal)
|
||||
code += IRInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
|
||||
code += IRInstruction(Opcode.SYSCALL, value=syscall.ordinal)
|
||||
return code
|
||||
}
|
||||
|
||||
@ -215,8 +215,8 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
}
|
||||
val code = IRCodeChunk(call.position)
|
||||
code += exprGen.translateExpression(call.args[0], 0, -1)
|
||||
code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
|
||||
code += IRCodeInstruction(Opcode.SYSCALL, value=syscall.ordinal)
|
||||
code += IRInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
|
||||
code += IRInstruction(Opcode.SYSCALL, value=syscall.ordinal)
|
||||
return code
|
||||
}
|
||||
|
||||
@ -225,7 +225,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
val code = IRCodeChunk(call.position)
|
||||
code += exprGen.translateExpression(call.args[0], msbReg, -1)
|
||||
code += exprGen.translateExpression(call.args[1], resultRegister, -1)
|
||||
code += IRCodeInstruction(Opcode.CONCAT, VmDataType.BYTE, reg1=resultRegister, reg2=msbReg)
|
||||
code += IRInstruction(Opcode.CONCAT, VmDataType.BYTE, reg1=resultRegister, reg2=msbReg)
|
||||
return code
|
||||
}
|
||||
|
||||
@ -234,23 +234,23 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
if(codeGen.isZero(call.args[1])) {
|
||||
if (call.args[0] is PtNumber) {
|
||||
val address = (call.args[0] as PtNumber).number.toInt()
|
||||
code += IRCodeInstruction(Opcode.STOREZM, VmDataType.WORD, value = address)
|
||||
code += IRInstruction(Opcode.STOREZM, VmDataType.WORD, value = address)
|
||||
} else {
|
||||
val addressReg = codeGen.vmRegisters.nextFree()
|
||||
code += exprGen.translateExpression(call.args[0], addressReg, -1)
|
||||
code += IRCodeInstruction(Opcode.STOREZI, VmDataType.WORD, reg2 = addressReg)
|
||||
code += IRInstruction(Opcode.STOREZI, VmDataType.WORD, reg2 = addressReg)
|
||||
}
|
||||
} else {
|
||||
val valueReg = codeGen.vmRegisters.nextFree()
|
||||
if (call.args[0] is PtNumber) {
|
||||
val address = (call.args[0] as PtNumber).number.toInt()
|
||||
code += exprGen.translateExpression(call.args[1], valueReg, -1)
|
||||
code += IRCodeInstruction(Opcode.STOREM, VmDataType.WORD, reg1 = valueReg, value = address)
|
||||
code += IRInstruction(Opcode.STOREM, VmDataType.WORD, reg1 = valueReg, value = address)
|
||||
} else {
|
||||
val addressReg = codeGen.vmRegisters.nextFree()
|
||||
code += exprGen.translateExpression(call.args[0], addressReg, -1)
|
||||
code += exprGen.translateExpression(call.args[1], valueReg, -1)
|
||||
code += IRCodeInstruction(Opcode.STOREI, VmDataType.WORD, reg1 = valueReg, reg2 = addressReg)
|
||||
code += IRInstruction(Opcode.STOREI, VmDataType.WORD, reg1 = valueReg, reg2 = addressReg)
|
||||
}
|
||||
}
|
||||
return code
|
||||
@ -261,23 +261,23 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
if(codeGen.isZero(call.args[1])) {
|
||||
if (call.args[0] is PtNumber) {
|
||||
val address = (call.args[0] as PtNumber).number.toInt()
|
||||
code += IRCodeInstruction(Opcode.STOREZM, VmDataType.BYTE, value = address)
|
||||
code += IRInstruction(Opcode.STOREZM, VmDataType.BYTE, value = address)
|
||||
} else {
|
||||
val addressReg = codeGen.vmRegisters.nextFree()
|
||||
code += exprGen.translateExpression(call.args[0], addressReg, -1)
|
||||
code += IRCodeInstruction(Opcode.STOREZI, VmDataType.BYTE, reg2 = addressReg)
|
||||
code += IRInstruction(Opcode.STOREZI, VmDataType.BYTE, reg2 = addressReg)
|
||||
}
|
||||
} else {
|
||||
val valueReg = codeGen.vmRegisters.nextFree()
|
||||
if (call.args[0] is PtNumber) {
|
||||
val address = (call.args[0] as PtNumber).number.toInt()
|
||||
code += exprGen.translateExpression(call.args[1], valueReg, -1)
|
||||
code += IRCodeInstruction(Opcode.STOREM, VmDataType.BYTE, reg1 = valueReg, value = address)
|
||||
code += IRInstruction(Opcode.STOREM, VmDataType.BYTE, reg1 = valueReg, value = address)
|
||||
} else {
|
||||
val addressReg = codeGen.vmRegisters.nextFree()
|
||||
code += exprGen.translateExpression(call.args[0], addressReg, -1)
|
||||
code += exprGen.translateExpression(call.args[1], valueReg, -1)
|
||||
code += IRCodeInstruction(Opcode.STOREI, VmDataType.BYTE, reg1 = valueReg, reg2 = addressReg)
|
||||
code += IRInstruction(Opcode.STOREI, VmDataType.BYTE, reg1 = valueReg, reg2 = addressReg)
|
||||
}
|
||||
}
|
||||
return code
|
||||
@ -287,11 +287,11 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
val code = IRCodeChunk(call.position)
|
||||
if(call.args[0] is PtNumber) {
|
||||
val address = (call.args[0] as PtNumber).number.toInt()
|
||||
code += IRCodeInstruction(Opcode.LOADM, VmDataType.WORD, reg1 = resultRegister, value = address)
|
||||
code += IRInstruction(Opcode.LOADM, VmDataType.WORD, reg1 = resultRegister, value = address)
|
||||
} else {
|
||||
val addressReg = codeGen.vmRegisters.nextFree()
|
||||
code += exprGen.translateExpression(call.args.single(), addressReg, -1)
|
||||
code += IRCodeInstruction(Opcode.LOADI, VmDataType.WORD, reg1 = resultRegister, reg2 = addressReg)
|
||||
code += IRInstruction(Opcode.LOADI, VmDataType.WORD, reg1 = resultRegister, reg2 = addressReg)
|
||||
}
|
||||
return code
|
||||
}
|
||||
@ -300,24 +300,24 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
val code = IRCodeChunk(call.position)
|
||||
if(call.args[0] is PtNumber) {
|
||||
val address = (call.args[0] as PtNumber).number.toInt()
|
||||
code += IRCodeInstruction(Opcode.LOADM, VmDataType.BYTE, reg1 = resultRegister, value = address)
|
||||
code += IRInstruction(Opcode.LOADM, VmDataType.BYTE, reg1 = resultRegister, value = address)
|
||||
} else {
|
||||
val addressReg = codeGen.vmRegisters.nextFree()
|
||||
code += exprGen.translateExpression(call.args.single(), addressReg, -1)
|
||||
code += IRCodeInstruction(Opcode.LOADI, VmDataType.BYTE, reg1 = resultRegister, reg2 = addressReg)
|
||||
code += IRInstruction(Opcode.LOADI, VmDataType.BYTE, reg1 = resultRegister, reg2 = addressReg)
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
||||
private fun funcRnd(resultRegister: Int, position: Position): IRCodeChunk {
|
||||
val code = IRCodeChunk(position)
|
||||
code += IRCodeInstruction(Opcode.RND, VmDataType.BYTE, reg1=resultRegister)
|
||||
code += IRInstruction(Opcode.RND, VmDataType.BYTE, reg1=resultRegister)
|
||||
return code
|
||||
}
|
||||
|
||||
private fun funcRndw(resultRegister: Int, position: Position): IRCodeChunk {
|
||||
val code = IRCodeChunk(position)
|
||||
code += IRCodeInstruction(Opcode.RND, VmDataType.WORD, reg1=resultRegister)
|
||||
code += IRInstruction(Opcode.RND, VmDataType.WORD, reg1=resultRegister)
|
||||
return code
|
||||
}
|
||||
|
||||
@ -327,7 +327,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
val align = (call.args[2] as PtNumber).number.toUInt()
|
||||
val label = codeGen.addMemorySlab(name, size, align, call.position)
|
||||
val code = IRCodeChunk(call.position)
|
||||
code += IRCodeInstruction(Opcode.LOAD, VmDataType.WORD, reg1=resultRegister, labelSymbol = label)
|
||||
code += IRInstruction(Opcode.LOAD, VmDataType.WORD, reg1=resultRegister, labelSymbol = label)
|
||||
return code
|
||||
}
|
||||
|
||||
@ -341,7 +341,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
private fun funcMsb(call: PtBuiltinFunctionCall, resultRegister: Int): IRCodeChunk {
|
||||
val code = IRCodeChunk(call.position)
|
||||
code += exprGen.translateExpression(call.args.single(), resultRegister, -1)
|
||||
code += IRCodeInstruction(Opcode.MSIG, VmDataType.BYTE, reg1 = resultRegister, reg2=resultRegister)
|
||||
code += IRInstruction(Opcode.MSIG, VmDataType.BYTE, reg1 = resultRegister, reg2=resultRegister)
|
||||
// note: if a word result is needed, the upper byte is cleared by the typecast that follows. No need to do it here.
|
||||
return code
|
||||
}
|
||||
@ -350,7 +350,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
val vmDt = codeGen.vmType(call.args[0].type)
|
||||
val code = IRCodeChunk(call.position)
|
||||
code += exprGen.translateExpression(call.args[0], resultRegister, -1)
|
||||
code += IRCodeInstruction(opcode, vmDt, reg1=resultRegister)
|
||||
code += IRInstruction(opcode, vmDt, reg1=resultRegister)
|
||||
code += assignRegisterTo(call.args[0], resultRegister)
|
||||
return code
|
||||
}
|
||||
|
@ -18,43 +18,43 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
is PtMachineRegister -> {
|
||||
if(resultRegister!=expr.register) {
|
||||
val vmDt = codeGen.vmType(expr.type)
|
||||
code += IRCodeInstruction(Opcode.LOADR, vmDt, reg1=resultRegister, reg2=expr.register)
|
||||
code += IRInstruction(Opcode.LOADR, vmDt, reg1=resultRegister, reg2=expr.register)
|
||||
}
|
||||
}
|
||||
is PtNumber -> {
|
||||
val vmDt = codeGen.vmType(expr.type)
|
||||
code += if(vmDt==VmDataType.FLOAT)
|
||||
IRCodeInstruction(Opcode.LOAD, vmDt, fpReg1 = resultFpRegister, fpValue = expr.number.toFloat())
|
||||
IRInstruction(Opcode.LOAD, vmDt, fpReg1 = resultFpRegister, fpValue = expr.number.toFloat())
|
||||
else
|
||||
IRCodeInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=expr.number.toInt())
|
||||
IRInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=expr.number.toInt())
|
||||
}
|
||||
is PtIdentifier -> {
|
||||
val vmDt = codeGen.vmType(expr.type)
|
||||
val symbol = expr.targetName.joinToString(".")
|
||||
code += if (expr.type in PassByValueDatatypes) {
|
||||
if(vmDt==VmDataType.FLOAT)
|
||||
IRCodeInstruction(Opcode.LOADM, vmDt, fpReg1 = resultFpRegister, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.LOADM, vmDt, fpReg1 = resultFpRegister, labelSymbol = symbol)
|
||||
else
|
||||
IRCodeInstruction(Opcode.LOADM, vmDt, reg1 = resultRegister, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.LOADM, vmDt, reg1 = resultRegister, labelSymbol = symbol)
|
||||
} else {
|
||||
// for strings and arrays etc., load the *address* of the value instead
|
||||
IRCodeInstruction(Opcode.LOAD, vmDt, reg1 = resultRegister, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.LOAD, vmDt, reg1 = resultRegister, labelSymbol = symbol)
|
||||
}
|
||||
}
|
||||
is PtAddressOf -> {
|
||||
val vmDt = codeGen.vmType(expr.type)
|
||||
val symbol = expr.identifier.targetName.joinToString(".")
|
||||
// note: LOAD <symbol> gets you the address of the symbol, whereas LOADM <symbol> would get you the value stored at that location
|
||||
code += IRCodeInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, labelSymbol = symbol)
|
||||
code += IRInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, labelSymbol = symbol)
|
||||
}
|
||||
is PtMemoryByte -> {
|
||||
if(expr.address is PtNumber) {
|
||||
val address = (expr.address as PtNumber).number.toInt()
|
||||
code += IRCodeInstruction(Opcode.LOADM, VmDataType.BYTE, reg1=resultRegister, value = address)
|
||||
code += IRInstruction(Opcode.LOADM, VmDataType.BYTE, reg1=resultRegister, value = address)
|
||||
} else {
|
||||
val addressRegister = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(expr.address, addressRegister, -1)
|
||||
code += IRCodeInstruction(Opcode.LOADI, VmDataType.BYTE, reg1=resultRegister, reg2=addressRegister)
|
||||
code += IRInstruction(Opcode.LOADI, VmDataType.BYTE, reg1=resultRegister, reg2=addressRegister)
|
||||
}
|
||||
}
|
||||
is PtTypeCast -> code += translate(expr, resultRegister, resultFpRegister)
|
||||
@ -117,24 +117,24 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
if(arrayIx.index.type!=DataType.UBYTE)
|
||||
throw AssemblyError("non-array var indexing requires bytes index")
|
||||
code += translateExpression(arrayIx.index, idxReg, -1)
|
||||
code += IRCodeInstruction(Opcode.LOADIX, vmDt, reg1=resultRegister, reg2=idxReg, labelSymbol = arrayVarSymbol)
|
||||
code += IRInstruction(Opcode.LOADIX, vmDt, reg1=resultRegister, reg2=idxReg, labelSymbol = arrayVarSymbol)
|
||||
return code
|
||||
}
|
||||
|
||||
if(arrayIx.index is PtNumber) {
|
||||
val memOffset = ((arrayIx.index as PtNumber).number.toInt() * eltSize).toString()
|
||||
if(vmDt==VmDataType.FLOAT)
|
||||
code += IRCodeInstruction(Opcode.LOADM, VmDataType.FLOAT, fpReg1=resultFpRegister, labelSymbol = "$arrayVarSymbol+$memOffset")
|
||||
code += IRInstruction(Opcode.LOADM, VmDataType.FLOAT, fpReg1=resultFpRegister, labelSymbol = "$arrayVarSymbol+$memOffset")
|
||||
else
|
||||
code += IRCodeInstruction(Opcode.LOADM, vmDt, reg1=resultRegister, labelSymbol = "$arrayVarSymbol+$memOffset")
|
||||
code += IRInstruction(Opcode.LOADM, vmDt, reg1=resultRegister, labelSymbol = "$arrayVarSymbol+$memOffset")
|
||||
} else {
|
||||
code += translateExpression(arrayIx.index, idxReg, -1)
|
||||
if(eltSize>1)
|
||||
code += codeGen.multiplyByConst(VmDataType.BYTE, idxReg, eltSize, arrayIx.position)
|
||||
if(vmDt==VmDataType.FLOAT)
|
||||
code += IRCodeInstruction(Opcode.LOADX, VmDataType.FLOAT, fpReg1 = resultFpRegister, reg1=idxReg, labelSymbol = arrayVarSymbol)
|
||||
code += IRInstruction(Opcode.LOADX, VmDataType.FLOAT, fpReg1 = resultFpRegister, reg1=idxReg, labelSymbol = arrayVarSymbol)
|
||||
else
|
||||
code += IRCodeInstruction(Opcode.LOADX, vmDt, reg1=resultRegister, reg2=idxReg, labelSymbol = arrayVarSymbol)
|
||||
code += IRInstruction(Opcode.LOADX, vmDt, reg1=resultRegister, reg2=idxReg, labelSymbol = arrayVarSymbol)
|
||||
}
|
||||
return code
|
||||
}
|
||||
@ -146,11 +146,11 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
when(expr.operator) {
|
||||
"+" -> { }
|
||||
"-" -> {
|
||||
code += IRCodeInstruction(Opcode.NEG, vmDt, reg1=resultRegister)
|
||||
code += IRInstruction(Opcode.NEG, vmDt, reg1=resultRegister)
|
||||
}
|
||||
"~" -> {
|
||||
val mask = if(vmDt==VmDataType.BYTE) 0x00ff else 0xffff
|
||||
code += IRCodeInstruction(Opcode.XOR, vmDt, reg1=resultRegister, value=mask)
|
||||
code += IRInstruction(Opcode.XOR, vmDt, reg1=resultRegister, value=mask)
|
||||
}
|
||||
else -> throw AssemblyError("weird prefix operator")
|
||||
}
|
||||
@ -173,14 +173,14 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
DataType.UBYTE -> {
|
||||
when(cast.value.type) {
|
||||
DataType.BYTE, DataType.UWORD, DataType.WORD -> { /* just keep the LSB as it is */ }
|
||||
DataType.FLOAT -> code += IRCodeInstruction(Opcode.FTOUB, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
|
||||
DataType.FLOAT -> code += IRInstruction(Opcode.FTOUB, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
|
||||
else -> throw AssemblyError("weird cast value type")
|
||||
}
|
||||
}
|
||||
DataType.BYTE -> {
|
||||
when(cast.value.type) {
|
||||
DataType.UBYTE, DataType.UWORD, DataType.WORD -> { /* just keep the LSB as it is */ }
|
||||
DataType.FLOAT -> code += IRCodeInstruction(Opcode.FTOSB, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
|
||||
DataType.FLOAT -> code += IRInstruction(Opcode.FTOSB, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
|
||||
else -> throw AssemblyError("weird cast value type")
|
||||
}
|
||||
}
|
||||
@ -188,15 +188,15 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
when(cast.value.type) {
|
||||
DataType.BYTE -> {
|
||||
// byte -> uword: sign extend
|
||||
code += IRCodeInstruction(Opcode.EXTS, type = VmDataType.BYTE, reg1 = actualResultReg)
|
||||
code += IRInstruction(Opcode.EXTS, type = VmDataType.BYTE, reg1 = actualResultReg)
|
||||
}
|
||||
DataType.UBYTE -> {
|
||||
// ubyte -> uword: sign extend
|
||||
code += IRCodeInstruction(Opcode.EXT, type = VmDataType.BYTE, reg1 = actualResultReg)
|
||||
code += IRInstruction(Opcode.EXT, type = VmDataType.BYTE, reg1 = actualResultReg)
|
||||
}
|
||||
DataType.WORD -> { }
|
||||
DataType.FLOAT -> {
|
||||
code += IRCodeInstruction(Opcode.FTOUW, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
|
||||
code += IRInstruction(Opcode.FTOUW, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
|
||||
}
|
||||
else -> throw AssemblyError("weird cast value type")
|
||||
}
|
||||
@ -205,15 +205,15 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
when(cast.value.type) {
|
||||
DataType.BYTE -> {
|
||||
// byte -> word: sign extend
|
||||
code += IRCodeInstruction(Opcode.EXTS, type = VmDataType.BYTE, reg1 = actualResultReg)
|
||||
code += IRInstruction(Opcode.EXTS, type = VmDataType.BYTE, reg1 = actualResultReg)
|
||||
}
|
||||
DataType.UBYTE -> {
|
||||
// byte -> word: sign extend
|
||||
code += IRCodeInstruction(Opcode.EXT, type = VmDataType.BYTE, reg1 = actualResultReg)
|
||||
code += IRInstruction(Opcode.EXT, type = VmDataType.BYTE, reg1 = actualResultReg)
|
||||
}
|
||||
DataType.UWORD -> { }
|
||||
DataType.FLOAT -> {
|
||||
code += IRCodeInstruction(Opcode.FTOSW, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
|
||||
code += IRInstruction(Opcode.FTOSW, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
|
||||
}
|
||||
else -> throw AssemblyError("weird cast value type")
|
||||
}
|
||||
@ -221,16 +221,16 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
DataType.FLOAT -> {
|
||||
code += when(cast.value.type) {
|
||||
DataType.UBYTE -> {
|
||||
IRCodeInstruction(Opcode.FFROMUB, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
|
||||
IRInstruction(Opcode.FFROMUB, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
|
||||
}
|
||||
DataType.BYTE -> {
|
||||
IRCodeInstruction(Opcode.FFROMSB, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
|
||||
IRInstruction(Opcode.FFROMSB, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
|
||||
}
|
||||
DataType.UWORD -> {
|
||||
IRCodeInstruction(Opcode.FFROMUW, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
|
||||
IRInstruction(Opcode.FFROMUW, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
|
||||
}
|
||||
DataType.WORD -> {
|
||||
IRCodeInstruction(Opcode.FFROMSW, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
|
||||
IRInstruction(Opcode.FFROMSW, VmDataType.FLOAT, reg1=actualResultReg, fpReg1 = actualResultFpReg)
|
||||
}
|
||||
else -> throw AssemblyError("weird cast value type")
|
||||
}
|
||||
@ -278,14 +278,14 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val zeroRegister = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, -1, leftFpReg)
|
||||
code += translateExpression(binExpr.right, -1, rightFpReg)
|
||||
code += IRCodeInstruction(Opcode.FCOMP, VmDataType.FLOAT, reg1=resultRegister, fpReg1 = leftFpReg, fpReg2 = rightFpReg)
|
||||
code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=zeroRegister, value=0)
|
||||
code += IRInstruction(Opcode.FCOMP, VmDataType.FLOAT, reg1=resultRegister, fpReg1 = leftFpReg, fpReg2 = rightFpReg)
|
||||
code += IRInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=zeroRegister, value=0)
|
||||
val ins = if (signed) {
|
||||
if (greaterEquals) Opcode.SGES else Opcode.SGTS
|
||||
} else {
|
||||
if (greaterEquals) Opcode.SGE else Opcode.SGT
|
||||
}
|
||||
code += IRCodeInstruction(ins, VmDataType.BYTE, reg1 = resultRegister, reg2 = zeroRegister)
|
||||
code += IRInstruction(ins, VmDataType.BYTE, reg1 = resultRegister, reg2 = zeroRegister)
|
||||
} else {
|
||||
if(binExpr.left.type==DataType.STR && binExpr.right.type==DataType.STR) {
|
||||
val comparisonCall = PtFunctionCall(listOf("prog8_lib", "string_compare"), false, DataType.BYTE, Position.DUMMY)
|
||||
@ -293,11 +293,11 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
comparisonCall.children.add(binExpr.right)
|
||||
code += translate(comparisonCall, resultRegister, -1)
|
||||
val zeroRegister = codeGen.vmRegisters.nextFree()
|
||||
code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=zeroRegister, value=0)
|
||||
code += IRInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=zeroRegister, value=0)
|
||||
code += if(greaterEquals)
|
||||
IRCodeInstruction(Opcode.SGES, VmDataType.BYTE, reg1=resultRegister, reg2=zeroRegister)
|
||||
IRInstruction(Opcode.SGES, VmDataType.BYTE, reg1=resultRegister, reg2=zeroRegister)
|
||||
else
|
||||
IRCodeInstruction(Opcode.SGTS, VmDataType.BYTE, reg1=resultRegister, reg2=zeroRegister)
|
||||
IRInstruction(Opcode.SGTS, VmDataType.BYTE, reg1=resultRegister, reg2=zeroRegister)
|
||||
} else {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
@ -307,7 +307,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
} else {
|
||||
if (greaterEquals) Opcode.SGE else Opcode.SGT
|
||||
}
|
||||
code += IRCodeInstruction(ins, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
code += IRInstruction(ins, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
}
|
||||
}
|
||||
return code
|
||||
@ -327,14 +327,14 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val zeroRegister = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, -1, leftFpReg)
|
||||
code += translateExpression(binExpr.right, -1, rightFpReg)
|
||||
code += IRCodeInstruction(Opcode.FCOMP, VmDataType.FLOAT, reg1=resultRegister, fpReg1 = leftFpReg, fpReg2 = rightFpReg)
|
||||
code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=zeroRegister, value=0)
|
||||
code += IRInstruction(Opcode.FCOMP, VmDataType.FLOAT, reg1=resultRegister, fpReg1 = leftFpReg, fpReg2 = rightFpReg)
|
||||
code += IRInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=zeroRegister, value=0)
|
||||
val ins = if (signed) {
|
||||
if (lessEquals) Opcode.SLES else Opcode.SLTS
|
||||
} else {
|
||||
if (lessEquals) Opcode.SLE else Opcode.SLT
|
||||
}
|
||||
code += IRCodeInstruction(ins, VmDataType.BYTE, reg1 = resultRegister, reg2 = zeroRegister)
|
||||
code += IRInstruction(ins, VmDataType.BYTE, reg1 = resultRegister, reg2 = zeroRegister)
|
||||
} else {
|
||||
if(binExpr.left.type==DataType.STR && binExpr.right.type==DataType.STR) {
|
||||
val comparisonCall = PtFunctionCall(listOf("prog8_lib", "string_compare"), false, DataType.BYTE, Position.DUMMY)
|
||||
@ -342,11 +342,11 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
comparisonCall.children.add(binExpr.right)
|
||||
code += translate(comparisonCall, resultRegister, -1)
|
||||
val zeroRegister = codeGen.vmRegisters.nextFree()
|
||||
code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=zeroRegister, value=0)
|
||||
code += IRInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=zeroRegister, value=0)
|
||||
code += if(lessEquals)
|
||||
IRCodeInstruction(Opcode.SLES, VmDataType.BYTE, reg1=resultRegister, reg2=zeroRegister)
|
||||
IRInstruction(Opcode.SLES, VmDataType.BYTE, reg1=resultRegister, reg2=zeroRegister)
|
||||
else
|
||||
IRCodeInstruction(Opcode.SLTS, VmDataType.BYTE, reg1=resultRegister, reg2=zeroRegister)
|
||||
IRInstruction(Opcode.SLTS, VmDataType.BYTE, reg1=resultRegister, reg2=zeroRegister)
|
||||
} else {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
@ -356,7 +356,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
} else {
|
||||
if (lessEquals) Opcode.SLE else Opcode.SLT
|
||||
}
|
||||
code += IRCodeInstruction(ins, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
code += IRInstruction(ins, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
}
|
||||
}
|
||||
return code
|
||||
@ -370,14 +370,14 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
code += translateExpression(binExpr.left, -1, leftFpReg)
|
||||
code += translateExpression(binExpr.right, -1, rightFpReg)
|
||||
if (notEquals) {
|
||||
code += IRCodeInstruction(Opcode.FCOMP, VmDataType.FLOAT, reg1=resultRegister, fpReg1 = leftFpReg, fpReg2 = rightFpReg)
|
||||
code += IRInstruction(Opcode.FCOMP, VmDataType.FLOAT, reg1=resultRegister, fpReg1 = leftFpReg, fpReg2 = rightFpReg)
|
||||
} else {
|
||||
val label = codeGen.createLabelName()
|
||||
val valueReg = codeGen.vmRegisters.nextFree()
|
||||
code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=resultRegister, value=1)
|
||||
code += IRCodeInstruction(Opcode.FCOMP, VmDataType.FLOAT, reg1=valueReg, fpReg1 = leftFpReg, fpReg2 = rightFpReg)
|
||||
code += IRCodeInstruction(Opcode.BZ, VmDataType.BYTE, reg1=valueReg, labelSymbol = label)
|
||||
code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=resultRegister, value=0)
|
||||
code += IRInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=resultRegister, value=1)
|
||||
code += IRInstruction(Opcode.FCOMP, VmDataType.FLOAT, reg1=valueReg, fpReg1 = leftFpReg, fpReg2 = rightFpReg)
|
||||
code += IRInstruction(Opcode.BZ, VmDataType.BYTE, reg1=valueReg, labelSymbol = label)
|
||||
code += IRInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=resultRegister, value=0)
|
||||
code += IRCodeLabel(label)
|
||||
}
|
||||
} else {
|
||||
@ -387,14 +387,14 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
comparisonCall.children.add(binExpr.right)
|
||||
code += translate(comparisonCall, resultRegister, -1)
|
||||
if(!notEquals)
|
||||
code += IRCodeInstruction(Opcode.INV, vmDt, reg1=resultRegister)
|
||||
code += IRCodeInstruction(Opcode.AND, vmDt, reg1=resultRegister, value=1)
|
||||
code += IRInstruction(Opcode.INV, vmDt, reg1=resultRegister)
|
||||
code += IRInstruction(Opcode.AND, vmDt, reg1=resultRegister, value=1)
|
||||
} else {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
val opcode = if (notEquals) Opcode.SNE else Opcode.SEQ
|
||||
code += IRCodeInstruction(opcode, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
code += IRInstruction(opcode, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
}
|
||||
}
|
||||
return code
|
||||
@ -405,13 +405,13 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
if(codeGen.isOne(binExpr.right)) {
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
val opc = if (signed) Opcode.ASR else Opcode.LSR
|
||||
code += IRCodeInstruction(opc, vmDt, reg1 = resultRegister)
|
||||
code += IRInstruction(opc, vmDt, reg1 = resultRegister)
|
||||
} else {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
val opc = if (signed) Opcode.ASRN else Opcode.LSRN
|
||||
code += IRCodeInstruction(opc, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
code += IRInstruction(opc, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
}
|
||||
return code
|
||||
}
|
||||
@ -421,17 +421,17 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
if(codeGen.isOne(operand)) {
|
||||
val opc = if (signed) Opcode.ASRM else Opcode.LSRM
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(opc, vmDt, value=knownAddress)
|
||||
IRInstruction(opc, vmDt, value=knownAddress)
|
||||
else
|
||||
IRCodeInstruction(opc, vmDt, labelSymbol = symbol)
|
||||
IRInstruction(opc, vmDt, labelSymbol = symbol)
|
||||
} else {
|
||||
val operandReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(operand, operandReg, -1)
|
||||
val opc = if (signed) Opcode.ASRNM else Opcode.LSRNM
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(opc, vmDt, reg1 = operandReg, value=knownAddress)
|
||||
IRInstruction(opc, vmDt, reg1 = operandReg, value=knownAddress)
|
||||
else
|
||||
IRCodeInstruction(opc, vmDt, reg1 = operandReg, labelSymbol = symbol)
|
||||
IRInstruction(opc, vmDt, reg1 = operandReg, labelSymbol = symbol)
|
||||
}
|
||||
return code
|
||||
}
|
||||
@ -440,12 +440,12 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val code = IRCodeChunk(binExpr.position)
|
||||
if(codeGen.isOne(binExpr.right)){
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += IRCodeInstruction(Opcode.LSL, vmDt, reg1=resultRegister)
|
||||
code += IRInstruction(Opcode.LSL, vmDt, reg1=resultRegister)
|
||||
} else {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += IRCodeInstruction(Opcode.LSLN, vmDt, reg1=resultRegister, rightResultReg)
|
||||
code += IRInstruction(Opcode.LSLN, vmDt, reg1=resultRegister, rightResultReg)
|
||||
}
|
||||
return code
|
||||
}
|
||||
@ -454,16 +454,16 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val code = IRCodeChunk(operand.position)
|
||||
if(codeGen.isOne(operand)){
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.LSLM, vmDt, value=knownAddress)
|
||||
IRInstruction(Opcode.LSLM, vmDt, value=knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.LSLM, vmDt, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.LSLM, vmDt, labelSymbol = symbol)
|
||||
} else {
|
||||
val operandReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(operand, operandReg, -1)
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.LSLNM, vmDt, reg1=operandReg, value=knownAddress)
|
||||
IRInstruction(Opcode.LSLNM, vmDt, reg1=operandReg, value=knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.LSLNM, vmDt, reg1=operandReg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.LSLNM, vmDt, reg1=operandReg, labelSymbol = symbol)
|
||||
}
|
||||
return code
|
||||
}
|
||||
@ -472,12 +472,12 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val code = IRCodeChunk(binExpr.position)
|
||||
if(binExpr.right is PtNumber) {
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += IRCodeInstruction(Opcode.XOR, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt())
|
||||
code += IRInstruction(Opcode.XOR, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt())
|
||||
} else {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += IRCodeInstruction(Opcode.XORR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
code += IRInstruction(Opcode.XORR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
}
|
||||
return code
|
||||
}
|
||||
@ -487,9 +487,9 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val operandReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(operand, operandReg, -1)
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.XORM, vmDt, reg1=operandReg, value = knownAddress)
|
||||
IRInstruction(Opcode.XORM, vmDt, reg1=operandReg, value = knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.XORM, vmDt, reg1=operandReg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.XORM, vmDt, reg1=operandReg, labelSymbol = symbol)
|
||||
return code
|
||||
}
|
||||
|
||||
@ -497,12 +497,12 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val code = IRCodeChunk(binExpr.position)
|
||||
if(binExpr.right is PtNumber) {
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += IRCodeInstruction(Opcode.AND, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt())
|
||||
code += IRInstruction(Opcode.AND, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt())
|
||||
} else {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += IRCodeInstruction(Opcode.ANDR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
code += IRInstruction(Opcode.ANDR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
}
|
||||
return code
|
||||
}
|
||||
@ -512,9 +512,9 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val operandReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(operand, operandReg, -1)
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.ANDM, vmDt, reg1=operandReg, value=knownAddress)
|
||||
IRInstruction(Opcode.ANDM, vmDt, reg1=operandReg, value=knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.ANDM, vmDt, reg1=operandReg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.ANDM, vmDt, reg1=operandReg, labelSymbol = symbol)
|
||||
return code
|
||||
}
|
||||
|
||||
@ -522,12 +522,12 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val code = IRCodeChunk(binExpr.position)
|
||||
if(binExpr.right is PtNumber) {
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += IRCodeInstruction(Opcode.OR, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt())
|
||||
code += IRInstruction(Opcode.OR, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt())
|
||||
} else {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += IRCodeInstruction(Opcode.ORR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
code += IRInstruction(Opcode.ORR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
}
|
||||
return code
|
||||
}
|
||||
@ -537,9 +537,9 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val operandReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(operand, operandReg, -1)
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.ORM, vmDt, reg1=operandReg, value = knownAddress)
|
||||
IRInstruction(Opcode.ORM, vmDt, reg1=operandReg, value = knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.ORM, vmDt, reg1=operandReg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.ORM, vmDt, reg1=operandReg, labelSymbol = symbol)
|
||||
return code
|
||||
}
|
||||
|
||||
@ -550,11 +550,11 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
if(binExpr.right is PtNumber) {
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += IRCodeInstruction(Opcode.MOD, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt())
|
||||
code += IRInstruction(Opcode.MOD, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt())
|
||||
} else {
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += IRCodeInstruction(Opcode.MODR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
code += IRInstruction(Opcode.MODR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
}
|
||||
return code
|
||||
}
|
||||
@ -576,9 +576,9 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
code += translateExpression(binExpr.left, -1, resultFpRegister)
|
||||
code += translateExpression(binExpr.right, -1, rightResultFpReg)
|
||||
code += if(signed)
|
||||
IRCodeInstruction(Opcode.DIVSR, vmDt, fpReg1 = resultFpRegister, fpReg2=rightResultFpReg)
|
||||
IRInstruction(Opcode.DIVSR, vmDt, fpReg1 = resultFpRegister, fpReg2=rightResultFpReg)
|
||||
else
|
||||
IRCodeInstruction(Opcode.DIVR, vmDt, fpReg1 = resultFpRegister, fpReg2=rightResultFpReg)
|
||||
IRInstruction(Opcode.DIVR, vmDt, fpReg1 = resultFpRegister, fpReg2=rightResultFpReg)
|
||||
}
|
||||
} else {
|
||||
if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) {
|
||||
@ -590,16 +590,16 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
if(binExpr.right is PtNumber) {
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += if (signed)
|
||||
IRCodeInstruction(Opcode.DIVS, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt())
|
||||
IRInstruction(Opcode.DIVS, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt())
|
||||
else
|
||||
IRCodeInstruction(Opcode.DIV, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt())
|
||||
IRInstruction(Opcode.DIV, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt())
|
||||
} else {
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += if (signed)
|
||||
IRCodeInstruction(Opcode.DIVSR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
IRInstruction(Opcode.DIVSR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
else
|
||||
IRCodeInstruction(Opcode.DIVR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
IRInstruction(Opcode.DIVR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -618,15 +618,15 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
code += translateExpression(operand, -1, operandFpReg)
|
||||
code += if(signed) {
|
||||
if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.DIVSM, vmDt, fpReg1 = operandFpReg, value = knownAddress)
|
||||
IRInstruction(Opcode.DIVSM, vmDt, fpReg1 = operandFpReg, value = knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.DIVSM, vmDt, fpReg1 = operandFpReg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.DIVSM, vmDt, fpReg1 = operandFpReg, labelSymbol = symbol)
|
||||
}
|
||||
else {
|
||||
if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.DIVM, vmDt, fpReg1 = operandFpReg, value = knownAddress)
|
||||
IRInstruction(Opcode.DIVM, vmDt, fpReg1 = operandFpReg, value = knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.DIVM, vmDt, fpReg1 = operandFpReg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.DIVM, vmDt, fpReg1 = operandFpReg, labelSymbol = symbol)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -638,15 +638,15 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
code += translateExpression(operand, operandReg, -1)
|
||||
code += if(signed) {
|
||||
if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.DIVSM, vmDt, reg1 = operandReg, value = knownAddress)
|
||||
IRInstruction(Opcode.DIVSM, vmDt, reg1 = operandReg, value = knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.DIVSM, vmDt, reg1 = operandReg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.DIVSM, vmDt, reg1 = operandReg, labelSymbol = symbol)
|
||||
}
|
||||
else {
|
||||
if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.DIVM, vmDt, reg1 = operandReg, value = knownAddress)
|
||||
IRInstruction(Opcode.DIVM, vmDt, reg1 = operandReg, value = knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.DIVM, vmDt, reg1 = operandReg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.DIVM, vmDt, reg1 = operandReg, labelSymbol = symbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -670,7 +670,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val rightResultFpReg = codeGen.vmRegisters.nextFreeFloat()
|
||||
code += translateExpression(binExpr.left, -1, resultFpRegister)
|
||||
code += translateExpression(binExpr.right, -1, rightResultFpReg)
|
||||
code += IRCodeInstruction(Opcode.MULR, vmDt, fpReg1 = resultFpRegister, fpReg2 = rightResultFpReg)
|
||||
code += IRInstruction(Opcode.MULR, vmDt, fpReg1 = resultFpRegister, fpReg2 = rightResultFpReg)
|
||||
}
|
||||
} else {
|
||||
if(constFactorLeft!=null && constFactorLeft.type!=DataType.FLOAT) {
|
||||
@ -685,7 +685,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += IRCodeInstruction(Opcode.MULR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
code += IRInstruction(Opcode.MULR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
}
|
||||
}
|
||||
return code
|
||||
@ -702,9 +702,9 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val operandFpReg = codeGen.vmRegisters.nextFreeFloat()
|
||||
code += translateExpression(operand, -1, operandFpReg)
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.MULM, vmDt, fpReg1 = operandFpReg, value = knownAddress)
|
||||
IRInstruction(Opcode.MULM, vmDt, fpReg1 = operandFpReg, value = knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.MULM, vmDt, fpReg1 = operandFpReg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.MULM, vmDt, fpReg1 = operandFpReg, labelSymbol = symbol)
|
||||
}
|
||||
} else {
|
||||
if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) {
|
||||
@ -714,9 +714,9 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val operandReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(operand, operandReg, -1)
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.MULM, vmDt, reg1=operandReg, value = knownAddress)
|
||||
IRInstruction(Opcode.MULM, vmDt, reg1=operandReg, value = knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.MULM, vmDt, reg1=operandReg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.MULM, vmDt, reg1=operandReg, labelSymbol = symbol)
|
||||
}
|
||||
}
|
||||
return code
|
||||
@ -727,33 +727,33 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
if(vmDt==VmDataType.FLOAT) {
|
||||
if((binExpr.right as? PtNumber)?.number==1.0) {
|
||||
code += translateExpression(binExpr.left, -1, resultFpRegister)
|
||||
code += IRCodeInstruction(Opcode.DEC, vmDt, fpReg1 = resultFpRegister)
|
||||
code += IRInstruction(Opcode.DEC, vmDt, fpReg1 = resultFpRegister)
|
||||
}
|
||||
else {
|
||||
if(binExpr.right is PtNumber) {
|
||||
code += translateExpression(binExpr.left, -1, resultFpRegister)
|
||||
code += IRCodeInstruction(Opcode.SUB, vmDt, fpReg1 = resultFpRegister, fpValue = (binExpr.right as PtNumber).number.toFloat())
|
||||
code += IRInstruction(Opcode.SUB, vmDt, fpReg1 = resultFpRegister, fpValue = (binExpr.right as PtNumber).number.toFloat())
|
||||
} else {
|
||||
val rightResultFpReg = codeGen.vmRegisters.nextFreeFloat()
|
||||
code += translateExpression(binExpr.left, -1, resultFpRegister)
|
||||
code += translateExpression(binExpr.right, -1, rightResultFpReg)
|
||||
code += IRCodeInstruction(Opcode.SUBR, vmDt, fpReg1 = resultFpRegister, fpReg2 = rightResultFpReg)
|
||||
code += IRInstruction(Opcode.SUBR, vmDt, fpReg1 = resultFpRegister, fpReg2 = rightResultFpReg)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if((binExpr.right as? PtNumber)?.number==1.0) {
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += IRCodeInstruction(Opcode.DEC, vmDt, reg1=resultRegister)
|
||||
code += IRInstruction(Opcode.DEC, vmDt, reg1=resultRegister)
|
||||
}
|
||||
else {
|
||||
if(binExpr.right is PtNumber) {
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += IRCodeInstruction(Opcode.SUB, vmDt, reg1 = resultRegister, value = (binExpr.right as PtNumber).number.toInt())
|
||||
code += IRInstruction(Opcode.SUB, vmDt, reg1 = resultRegister, value = (binExpr.right as PtNumber).number.toInt())
|
||||
} else {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += IRCodeInstruction(Opcode.SUBR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
code += IRInstruction(Opcode.SUBR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -765,32 +765,32 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
if(vmDt==VmDataType.FLOAT) {
|
||||
if((operand as? PtNumber)?.number==1.0) {
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.DECM, vmDt, value=knownAddress)
|
||||
IRInstruction(Opcode.DECM, vmDt, value=knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.DECM, vmDt, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.DECM, vmDt, labelSymbol = symbol)
|
||||
}
|
||||
else {
|
||||
val operandFpReg = codeGen.vmRegisters.nextFreeFloat()
|
||||
code += translateExpression(operand, -1, operandFpReg)
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.SUBM, vmDt, fpReg1=operandFpReg, value=knownAddress)
|
||||
IRInstruction(Opcode.SUBM, vmDt, fpReg1=operandFpReg, value=knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.SUBM, vmDt, fpReg1=operandFpReg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.SUBM, vmDt, fpReg1=operandFpReg, labelSymbol = symbol)
|
||||
}
|
||||
} else {
|
||||
if((operand as? PtNumber)?.number==1.0) {
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.DECM, vmDt, value=knownAddress)
|
||||
IRInstruction(Opcode.DECM, vmDt, value=knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.DECM, vmDt, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.DECM, vmDt, labelSymbol = symbol)
|
||||
}
|
||||
else {
|
||||
val operandReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(operand, operandReg, -1)
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.SUBM, vmDt, reg1=operandReg, value = knownAddress)
|
||||
IRInstruction(Opcode.SUBM, vmDt, reg1=operandReg, value = knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.SUBM, vmDt, reg1=operandReg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.SUBM, vmDt, reg1=operandReg, labelSymbol = symbol)
|
||||
}
|
||||
}
|
||||
return code
|
||||
@ -801,41 +801,41 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
if(vmDt==VmDataType.FLOAT) {
|
||||
if((binExpr.left as? PtNumber)?.number==1.0) {
|
||||
code += translateExpression(binExpr.right, -1, resultFpRegister)
|
||||
code += IRCodeInstruction(Opcode.INC, vmDt, fpReg1=resultFpRegister)
|
||||
code += IRInstruction(Opcode.INC, vmDt, fpReg1=resultFpRegister)
|
||||
}
|
||||
else if((binExpr.right as? PtNumber)?.number==1.0) {
|
||||
code += translateExpression(binExpr.left, -1, resultFpRegister)
|
||||
code += IRCodeInstruction(Opcode.INC, vmDt, fpReg1=resultFpRegister)
|
||||
code += IRInstruction(Opcode.INC, vmDt, fpReg1=resultFpRegister)
|
||||
}
|
||||
else {
|
||||
if(binExpr.right is PtNumber) {
|
||||
code += translateExpression(binExpr.left, -1, resultFpRegister)
|
||||
code += IRCodeInstruction(Opcode.ADD, vmDt, fpReg1 = resultFpRegister, fpValue = (binExpr.right as PtNumber).number.toFloat())
|
||||
code += IRInstruction(Opcode.ADD, vmDt, fpReg1 = resultFpRegister, fpValue = (binExpr.right as PtNumber).number.toFloat())
|
||||
} else {
|
||||
val rightResultFpReg = codeGen.vmRegisters.nextFreeFloat()
|
||||
code += translateExpression(binExpr.left, -1, resultFpRegister)
|
||||
code += translateExpression(binExpr.right, -1, rightResultFpReg)
|
||||
code += IRCodeInstruction(Opcode.ADDR, vmDt, fpReg1 = resultFpRegister, fpReg2 = rightResultFpReg)
|
||||
code += IRInstruction(Opcode.ADDR, vmDt, fpReg1 = resultFpRegister, fpReg2 = rightResultFpReg)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if((binExpr.left as? PtNumber)?.number==1.0) {
|
||||
code += translateExpression(binExpr.right, resultRegister, -1)
|
||||
code += IRCodeInstruction(Opcode.INC, vmDt, reg1=resultRegister)
|
||||
code += IRInstruction(Opcode.INC, vmDt, reg1=resultRegister)
|
||||
}
|
||||
else if((binExpr.right as? PtNumber)?.number==1.0) {
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += IRCodeInstruction(Opcode.INC, vmDt, reg1=resultRegister)
|
||||
code += IRInstruction(Opcode.INC, vmDt, reg1=resultRegister)
|
||||
}
|
||||
else {
|
||||
if(binExpr.right is PtNumber) {
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += IRCodeInstruction(Opcode.ADD, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt())
|
||||
code += IRInstruction(Opcode.ADD, vmDt, reg1 = resultRegister, value=(binExpr.right as PtNumber).number.toInt())
|
||||
} else {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += IRCodeInstruction(Opcode.ADDR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
code += IRInstruction(Opcode.ADDR, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -847,32 +847,32 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
if(vmDt==VmDataType.FLOAT) {
|
||||
if((operand as? PtNumber)?.number==1.0) {
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.INCM, vmDt, value = knownAddress)
|
||||
IRInstruction(Opcode.INCM, vmDt, value = knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.INCM, vmDt, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.INCM, vmDt, labelSymbol = symbol)
|
||||
}
|
||||
else {
|
||||
val operandFpReg = codeGen.vmRegisters.nextFreeFloat()
|
||||
code += translateExpression(operand, -1, operandFpReg)
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.ADDM, vmDt, fpReg1=operandFpReg, value = knownAddress)
|
||||
IRInstruction(Opcode.ADDM, vmDt, fpReg1=operandFpReg, value = knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.ADDM, vmDt, fpReg1=operandFpReg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.ADDM, vmDt, fpReg1=operandFpReg, labelSymbol = symbol)
|
||||
}
|
||||
} else {
|
||||
if((operand as? PtNumber)?.number==1.0) {
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.INCM, vmDt, value = knownAddress)
|
||||
IRInstruction(Opcode.INCM, vmDt, value = knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.INCM, vmDt, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.INCM, vmDt, labelSymbol = symbol)
|
||||
}
|
||||
else {
|
||||
val operandReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(operand, operandReg, -1)
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.ADDM, vmDt, reg1=operandReg, value=knownAddress)
|
||||
IRInstruction(Opcode.ADDM, vmDt, reg1=operandReg, value=knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.ADDM, vmDt, reg1=operandReg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.ADDM, vmDt, reg1=operandReg, labelSymbol = symbol)
|
||||
}
|
||||
}
|
||||
return code
|
||||
@ -886,29 +886,29 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val paramDt = codeGen.vmType(parameter.type)
|
||||
val symbol = (fcall.functionName + parameter.name).joinToString(".")
|
||||
if(codeGen.isZero(arg)) {
|
||||
code += IRCodeInstruction(Opcode.STOREZM, paramDt, labelSymbol = symbol)
|
||||
code += IRInstruction(Opcode.STOREZM, paramDt, labelSymbol = symbol)
|
||||
} else {
|
||||
if (paramDt == VmDataType.FLOAT) {
|
||||
val argFpReg = codeGen.vmRegisters.nextFreeFloat()
|
||||
code += translateExpression(arg, -1, argFpReg)
|
||||
code += IRCodeInstruction(Opcode.STOREM, paramDt, fpReg1 = argFpReg, labelSymbol = symbol)
|
||||
code += IRInstruction(Opcode.STOREM, paramDt, fpReg1 = argFpReg, labelSymbol = symbol)
|
||||
} else {
|
||||
val argReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(arg, argReg, -1)
|
||||
code += IRCodeInstruction(Opcode.STOREM, paramDt, reg1 = argReg, labelSymbol = symbol)
|
||||
code += IRInstruction(Opcode.STOREM, paramDt, reg1 = argReg, labelSymbol = symbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
code += IRCodeInstruction(Opcode.CALL, labelSymbol=fcall.functionName.joinToString("."))
|
||||
code += IRInstruction(Opcode.CALL, labelSymbol=fcall.functionName.joinToString("."))
|
||||
if(fcall.type==DataType.FLOAT) {
|
||||
if (!fcall.void && resultFpRegister != 0) {
|
||||
// Call convention: result value is in fr0, so put it in the required register instead.
|
||||
code += IRCodeInstruction(Opcode.LOADR, VmDataType.FLOAT, fpReg1 = resultFpRegister, fpReg2 = 0)
|
||||
code += IRInstruction(Opcode.LOADR, VmDataType.FLOAT, fpReg1 = resultFpRegister, fpReg2 = 0)
|
||||
}
|
||||
} else {
|
||||
if (!fcall.void && resultRegister != 0) {
|
||||
// Call convention: result value is in r0, so put it in the required register instead.
|
||||
code += IRCodeInstruction(Opcode.LOADR, codeGen.vmType(fcall.type), reg1 = resultRegister, reg2 = 0)
|
||||
code += IRInstruction(Opcode.LOADR, codeGen.vmType(fcall.type), reg1 = resultRegister, reg2 = 0)
|
||||
}
|
||||
}
|
||||
return code
|
||||
@ -919,16 +919,16 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
val paramDt = codeGen.vmType(parameter.type)
|
||||
val paramRegStr = if(parameter.register.registerOrPair!=null) parameter.register.registerOrPair.toString() else parameter.register.statusflag.toString()
|
||||
if(codeGen.isZero(arg)) {
|
||||
code += IRCodeInstruction(Opcode.STOREZCPU, paramDt, labelSymbol = paramRegStr)
|
||||
code += IRInstruction(Opcode.STOREZCPU, paramDt, labelSymbol = paramRegStr)
|
||||
} else {
|
||||
if (paramDt == VmDataType.FLOAT)
|
||||
throw AssemblyError("doesn't support float register argument in asm romsub")
|
||||
val argReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(arg, argReg, -1)
|
||||
code += IRCodeInstruction(Opcode.STORECPU, paramDt, reg1 = argReg, labelSymbol = paramRegStr)
|
||||
code += IRInstruction(Opcode.STORECPU, paramDt, reg1 = argReg, labelSymbol = paramRegStr)
|
||||
}
|
||||
}
|
||||
code += IRCodeInstruction(Opcode.CALL, value=callTarget.address.toInt())
|
||||
code += IRInstruction(Opcode.CALL, value=callTarget.address.toInt())
|
||||
if(!fcall.void) {
|
||||
if(callTarget.returns.size!=1)
|
||||
throw AssemblyError("expect precisely 1 return value")
|
||||
@ -936,7 +936,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
|
||||
throw AssemblyError("doesn't support float register result in asm romsub")
|
||||
val returns = callTarget.returns.single()
|
||||
val regStr = if(returns.registerOrPair!=null) returns.registerOrPair.toString() else returns.statusflag.toString()
|
||||
code += IRCodeInstruction(Opcode.LOADCPU, codeGen.vmType(fcall.type), reg1=resultRegister, labelSymbol = regStr)
|
||||
code += IRInstruction(Opcode.LOADCPU, codeGen.vmType(fcall.type), reg1=resultRegister, labelSymbol = regStr)
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
@ -64,8 +64,8 @@ class IRCodeGen(
|
||||
val replacements = mutableListOf<Triple<IRCodeChunkBase, Int, UInt>>()
|
||||
irProg.blocks.asSequence().flatMap { it.subroutines }.flatMap { it.chunks }.forEach { chunk ->
|
||||
chunk.lines.withIndex().forEach {
|
||||
(lineIndex, line)-> if(line is IRCodeInstruction) {
|
||||
val symbolExpr = line.ins.labelSymbol
|
||||
(lineIndex, line) -> if(line is IRInstruction) {
|
||||
val symbolExpr = line.labelSymbol
|
||||
if(symbolExpr!=null) {
|
||||
val symbol: String
|
||||
val index: UInt
|
||||
@ -87,14 +87,14 @@ class IRCodeGen(
|
||||
}
|
||||
|
||||
replacements.forEach {
|
||||
val old = it.first.lines[it.second] as IRCodeInstruction
|
||||
it.first.lines[it.second] = IRCodeInstruction(
|
||||
old.ins.opcode,
|
||||
old.ins.type,
|
||||
old.ins.reg1,
|
||||
old.ins.reg2,
|
||||
old.ins.fpReg1,
|
||||
old.ins.fpReg2,
|
||||
val old = it.first.lines[it.second] as IRInstruction
|
||||
it.first.lines[it.second] = IRInstruction(
|
||||
old.opcode,
|
||||
old.type,
|
||||
old.reg1,
|
||||
old.reg2,
|
||||
old.fpReg1,
|
||||
old.fpReg2,
|
||||
it.third.toInt(),
|
||||
null,
|
||||
null
|
||||
@ -234,7 +234,7 @@ class IRCodeGen(
|
||||
}
|
||||
is PtBreakpoint -> {
|
||||
val chunk = IRCodeChunk(node.position)
|
||||
chunk += IRCodeInstruction(Opcode.BREAKPOINT)
|
||||
chunk += IRInstruction(Opcode.BREAKPOINT)
|
||||
return chunk
|
||||
}
|
||||
is PtConditionalBranch -> translate(node)
|
||||
@ -275,19 +275,19 @@ class IRCodeGen(
|
||||
val elseLabel = createLabelName()
|
||||
// note that the branch opcode used is the opposite as the branch condition, because the generated code jumps to the 'else' part
|
||||
code += when(branch.condition) {
|
||||
BranchCondition.CS -> IRCodeInstruction(Opcode.BSTCC, labelSymbol = elseLabel)
|
||||
BranchCondition.CC -> IRCodeInstruction(Opcode.BSTCS, labelSymbol = elseLabel)
|
||||
BranchCondition.EQ, BranchCondition.Z -> IRCodeInstruction(Opcode.BSTNE, labelSymbol = elseLabel)
|
||||
BranchCondition.NE, BranchCondition.NZ -> IRCodeInstruction(Opcode.BSTEQ, labelSymbol = elseLabel)
|
||||
BranchCondition.MI, BranchCondition.NEG -> IRCodeInstruction(Opcode.BSTPOS, labelSymbol = elseLabel)
|
||||
BranchCondition.PL, BranchCondition.POS -> IRCodeInstruction(Opcode.BSTNEG, labelSymbol = elseLabel)
|
||||
BranchCondition.CS -> IRInstruction(Opcode.BSTCC, labelSymbol = elseLabel)
|
||||
BranchCondition.CC -> IRInstruction(Opcode.BSTCS, labelSymbol = elseLabel)
|
||||
BranchCondition.EQ, BranchCondition.Z -> IRInstruction(Opcode.BSTNE, labelSymbol = elseLabel)
|
||||
BranchCondition.NE, BranchCondition.NZ -> IRInstruction(Opcode.BSTEQ, labelSymbol = elseLabel)
|
||||
BranchCondition.MI, BranchCondition.NEG -> IRInstruction(Opcode.BSTPOS, labelSymbol = elseLabel)
|
||||
BranchCondition.PL, BranchCondition.POS -> IRInstruction(Opcode.BSTNEG, labelSymbol = elseLabel)
|
||||
BranchCondition.VC,
|
||||
BranchCondition.VS -> throw AssemblyError("conditional branch ${branch.condition} not supported in vm target due to lack of cpu V flag ${branch.position}")
|
||||
}
|
||||
code += translateNode(branch.trueScope)
|
||||
if(branch.falseScope.children.isNotEmpty()) {
|
||||
val endLabel = createLabelName()
|
||||
code += IRCodeInstruction(Opcode.JUMP, labelSymbol = endLabel)
|
||||
code += IRInstruction(Opcode.JUMP, labelSymbol = endLabel)
|
||||
code += IRCodeLabel(elseLabel)
|
||||
code += translateNode(branch.falseScope)
|
||||
code += IRCodeLabel(endLabel)
|
||||
@ -314,22 +314,22 @@ class IRCodeGen(
|
||||
val skipLabel = createLabelName()
|
||||
val values = choice.values.children.map {it as PtNumber}
|
||||
if(values.size==1) {
|
||||
code += IRCodeInstruction(Opcode.LOAD, valueDt, reg1=choiceReg, value=values[0].number.toInt())
|
||||
code += IRCodeInstruction(Opcode.BNE, valueDt, reg1=valueReg, reg2=choiceReg, labelSymbol = skipLabel)
|
||||
code += IRInstruction(Opcode.LOAD, valueDt, reg1=choiceReg, value=values[0].number.toInt())
|
||||
code += IRInstruction(Opcode.BNE, valueDt, reg1=valueReg, reg2=choiceReg, labelSymbol = skipLabel)
|
||||
code += translateNode(choice.statements)
|
||||
if(choice.statements.children.last() !is PtReturn)
|
||||
code += IRCodeInstruction(Opcode.JUMP, labelSymbol = endLabel)
|
||||
code += IRInstruction(Opcode.JUMP, labelSymbol = endLabel)
|
||||
} else {
|
||||
val matchLabel = createLabelName()
|
||||
for (value in values) {
|
||||
code += IRCodeInstruction(Opcode.LOAD, valueDt, reg1=choiceReg, value=value.number.toInt())
|
||||
code += IRCodeInstruction(Opcode.BEQ, valueDt, reg1=valueReg, reg2=choiceReg, labelSymbol = matchLabel)
|
||||
code += IRInstruction(Opcode.LOAD, valueDt, reg1=choiceReg, value=value.number.toInt())
|
||||
code += IRInstruction(Opcode.BEQ, valueDt, reg1=valueReg, reg2=choiceReg, labelSymbol = matchLabel)
|
||||
}
|
||||
code += IRCodeInstruction(Opcode.JUMP, labelSymbol = skipLabel)
|
||||
code += IRInstruction(Opcode.JUMP, labelSymbol = skipLabel)
|
||||
code += IRCodeLabel(matchLabel)
|
||||
code += translateNode(choice.statements)
|
||||
if(choice.statements.children.last() !is PtReturn)
|
||||
code += IRCodeInstruction(Opcode.JUMP, labelSymbol = endLabel)
|
||||
code += IRInstruction(Opcode.JUMP, labelSymbol = endLabel)
|
||||
}
|
||||
code += IRCodeLabel(skipLabel)
|
||||
}
|
||||
@ -359,14 +359,14 @@ class IRCodeGen(
|
||||
val endLabel = createLabelName()
|
||||
if(iterableVar.dt==DataType.STR) {
|
||||
// iterate over a zero-terminated string
|
||||
code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=indexReg, value=0)
|
||||
code += IRInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=indexReg, value=0)
|
||||
code += IRCodeLabel(loopLabel)
|
||||
code += IRCodeInstruction(Opcode.LOADX, VmDataType.BYTE, reg1=tmpReg, reg2=indexReg, labelSymbol = symbol)
|
||||
code += IRCodeInstruction(Opcode.BZ, VmDataType.BYTE, reg1=tmpReg, labelSymbol = endLabel)
|
||||
code += IRCodeInstruction(Opcode.STOREM, VmDataType.BYTE, reg1=tmpReg, labelSymbol = loopvarSymbol)
|
||||
code += IRInstruction(Opcode.LOADX, VmDataType.BYTE, reg1=tmpReg, reg2=indexReg, labelSymbol = symbol)
|
||||
code += IRInstruction(Opcode.BZ, VmDataType.BYTE, reg1=tmpReg, labelSymbol = endLabel)
|
||||
code += IRInstruction(Opcode.STOREM, VmDataType.BYTE, reg1=tmpReg, labelSymbol = loopvarSymbol)
|
||||
code += translateNode(forLoop.statements)
|
||||
code += IRCodeInstruction(Opcode.INC, VmDataType.BYTE, reg1=indexReg)
|
||||
code += IRCodeInstruction(Opcode.JUMP, labelSymbol = loopLabel)
|
||||
code += IRInstruction(Opcode.INC, VmDataType.BYTE, reg1=indexReg)
|
||||
code += IRInstruction(Opcode.JUMP, labelSymbol = loopLabel)
|
||||
code += IRCodeLabel(endLabel)
|
||||
} else {
|
||||
// iterate over array
|
||||
@ -375,22 +375,22 @@ class IRCodeGen(
|
||||
val lengthBytes = iterableVar.length!! * elementSize
|
||||
if(lengthBytes<256) {
|
||||
val lengthReg = vmRegisters.nextFree()
|
||||
code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=indexReg, value=0)
|
||||
code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=lengthReg, value=lengthBytes)
|
||||
code += IRInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=indexReg, value=0)
|
||||
code += IRInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=lengthReg, value=lengthBytes)
|
||||
code += IRCodeLabel(loopLabel)
|
||||
code += IRCodeInstruction(Opcode.LOADX, vmType(elementDt), reg1=tmpReg, reg2=indexReg, labelSymbol=symbol)
|
||||
code += IRCodeInstruction(Opcode.STOREM, vmType(elementDt), reg1=tmpReg, labelSymbol = loopvarSymbol)
|
||||
code += IRInstruction(Opcode.LOADX, vmType(elementDt), reg1=tmpReg, reg2=indexReg, labelSymbol=symbol)
|
||||
code += IRInstruction(Opcode.STOREM, vmType(elementDt), reg1=tmpReg, labelSymbol = loopvarSymbol)
|
||||
code += translateNode(forLoop.statements)
|
||||
code += addConstReg(VmDataType.BYTE, indexReg, elementSize, iterable.position)
|
||||
code += IRCodeInstruction(Opcode.BNE, VmDataType.BYTE, reg1=indexReg, reg2=lengthReg, labelSymbol = loopLabel)
|
||||
code += IRInstruction(Opcode.BNE, VmDataType.BYTE, reg1=indexReg, reg2=lengthReg, labelSymbol = loopLabel)
|
||||
} else if(lengthBytes==256) {
|
||||
code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=indexReg, value=0)
|
||||
code += IRInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=indexReg, value=0)
|
||||
code += IRCodeLabel(loopLabel)
|
||||
code += IRCodeInstruction(Opcode.LOADX, vmType(elementDt), reg1=tmpReg, reg2=indexReg, labelSymbol=symbol)
|
||||
code += IRCodeInstruction(Opcode.STOREM, vmType(elementDt), reg1=tmpReg, labelSymbol = loopvarSymbol)
|
||||
code += IRInstruction(Opcode.LOADX, vmType(elementDt), reg1=tmpReg, reg2=indexReg, labelSymbol=symbol)
|
||||
code += IRInstruction(Opcode.STOREM, vmType(elementDt), reg1=tmpReg, labelSymbol = loopvarSymbol)
|
||||
code += translateNode(forLoop.statements)
|
||||
code += addConstReg(VmDataType.BYTE, indexReg, elementSize, iterable.position)
|
||||
code += IRCodeInstruction(Opcode.BNZ, VmDataType.BYTE, reg1=indexReg, labelSymbol = loopLabel)
|
||||
code += IRInstruction(Opcode.BNZ, VmDataType.BYTE, reg1=indexReg, labelSymbol = loopLabel)
|
||||
} else {
|
||||
throw AssemblyError("iterator length should never exceed 256")
|
||||
}
|
||||
@ -415,13 +415,13 @@ class IRCodeGen(
|
||||
|
||||
code += expressionEval.translateExpression(iterable.to, endvalueReg, -1)
|
||||
code += expressionEval.translateExpression(iterable.from, indexReg, -1)
|
||||
code += IRCodeInstruction(Opcode.STOREM, loopvarDt, reg1=indexReg, labelSymbol=loopvarSymbol)
|
||||
code += IRInstruction(Opcode.STOREM, loopvarDt, reg1=indexReg, labelSymbol=loopvarSymbol)
|
||||
code += IRCodeLabel(loopLabel)
|
||||
code += translateNode(forLoop.statements)
|
||||
code += addConstMem(loopvarDt, null, loopvarSymbol, step, iterable.position)
|
||||
code += IRCodeInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, labelSymbol = loopvarSymbol)
|
||||
code += IRInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, labelSymbol = loopvarSymbol)
|
||||
val branchOpcode = if(loopvar.dt in SignedDatatypes) Opcode.BLES else Opcode.BLE
|
||||
code += IRCodeInstruction(branchOpcode, loopvarDt, reg1=indexReg, reg2=endvalueReg, labelSymbol=loopLabel)
|
||||
code += IRInstruction(branchOpcode, loopvarDt, reg1=indexReg, reg2=endvalueReg, labelSymbol=loopLabel)
|
||||
return code
|
||||
}
|
||||
|
||||
@ -443,20 +443,20 @@ class IRCodeGen(
|
||||
val endvalueReg: Int
|
||||
if(rangeEndWrapped!=0) {
|
||||
endvalueReg = vmRegisters.nextFree()
|
||||
code += IRCodeInstruction(Opcode.LOAD, loopvarDt, reg1 = endvalueReg, value = rangeEndWrapped)
|
||||
code += IRInstruction(Opcode.LOAD, loopvarDt, reg1 = endvalueReg, value = rangeEndWrapped)
|
||||
} else {
|
||||
endvalueReg = -1 // not used
|
||||
}
|
||||
code += IRCodeInstruction(Opcode.LOAD, loopvarDt, reg1=indexReg, value=rangeStart)
|
||||
code += IRCodeInstruction(Opcode.STOREM, loopvarDt, reg1=indexReg, labelSymbol=loopvarSymbol)
|
||||
code += IRInstruction(Opcode.LOAD, loopvarDt, reg1=indexReg, value=rangeStart)
|
||||
code += IRInstruction(Opcode.STOREM, loopvarDt, reg1=indexReg, labelSymbol=loopvarSymbol)
|
||||
code += IRCodeLabel(loopLabel)
|
||||
code += translateNode(forLoop.statements)
|
||||
code += addConstMem(loopvarDt, null, loopvarSymbol, step, iterable.position)
|
||||
code += IRCodeInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, labelSymbol = loopvarSymbol)
|
||||
code += IRInstruction(Opcode.LOADM, loopvarDt, reg1 = indexReg, labelSymbol = loopvarSymbol)
|
||||
code += if(rangeEndWrapped==0) {
|
||||
IRCodeInstruction(Opcode.BNZ, loopvarDt, reg1 = indexReg, labelSymbol = loopLabel)
|
||||
IRInstruction(Opcode.BNZ, loopvarDt, reg1 = indexReg, labelSymbol = loopLabel)
|
||||
} else {
|
||||
IRCodeInstruction(Opcode.BNE, loopvarDt, reg1 = indexReg, reg2 = endvalueReg, labelSymbol = loopLabel)
|
||||
IRInstruction(Opcode.BNE, loopvarDt, reg1 = indexReg, reg2 = endvalueReg, labelSymbol = loopLabel)
|
||||
}
|
||||
return code
|
||||
}
|
||||
@ -466,24 +466,24 @@ class IRCodeGen(
|
||||
when(value) {
|
||||
0 -> { /* do nothing */ }
|
||||
1 -> {
|
||||
code += IRCodeInstruction(Opcode.INC, dt, reg1=reg)
|
||||
code += IRInstruction(Opcode.INC, dt, reg1=reg)
|
||||
}
|
||||
2 -> {
|
||||
code += IRCodeInstruction(Opcode.INC, dt, reg1=reg)
|
||||
code += IRCodeInstruction(Opcode.INC, dt, reg1=reg)
|
||||
code += IRInstruction(Opcode.INC, dt, reg1=reg)
|
||||
code += IRInstruction(Opcode.INC, dt, reg1=reg)
|
||||
}
|
||||
-1 -> {
|
||||
code += IRCodeInstruction(Opcode.DEC, dt, reg1=reg)
|
||||
code += IRInstruction(Opcode.DEC, dt, reg1=reg)
|
||||
}
|
||||
-2 -> {
|
||||
code += IRCodeInstruction(Opcode.DEC, dt, reg1=reg)
|
||||
code += IRCodeInstruction(Opcode.DEC, dt, reg1=reg)
|
||||
code += IRInstruction(Opcode.DEC, dt, reg1=reg)
|
||||
code += IRInstruction(Opcode.DEC, dt, reg1=reg)
|
||||
}
|
||||
else -> {
|
||||
code += if(value>0) {
|
||||
IRCodeInstruction(Opcode.ADD, dt, reg1 = reg, value=value)
|
||||
IRInstruction(Opcode.ADD, dt, reg1 = reg, value=value)
|
||||
} else {
|
||||
IRCodeInstruction(Opcode.SUB, dt, reg1 = reg, value=-value)
|
||||
IRInstruction(Opcode.SUB, dt, reg1 = reg, value=-value)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -496,49 +496,49 @@ class IRCodeGen(
|
||||
0 -> { /* do nothing */ }
|
||||
1 -> {
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.INCM, dt, value=knownAddress.toInt())
|
||||
IRInstruction(Opcode.INCM, dt, value=knownAddress.toInt())
|
||||
else
|
||||
IRCodeInstruction(Opcode.INCM, dt, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.INCM, dt, labelSymbol = symbol)
|
||||
}
|
||||
2 -> {
|
||||
if(knownAddress!=null) {
|
||||
code += IRCodeInstruction(Opcode.INCM, dt, value = knownAddress.toInt())
|
||||
code += IRCodeInstruction(Opcode.INCM, dt, value = knownAddress.toInt())
|
||||
code += IRInstruction(Opcode.INCM, dt, value = knownAddress.toInt())
|
||||
code += IRInstruction(Opcode.INCM, dt, value = knownAddress.toInt())
|
||||
} else {
|
||||
code += IRCodeInstruction(Opcode.INCM, dt, labelSymbol = symbol)
|
||||
code += IRCodeInstruction(Opcode.INCM, dt, labelSymbol = symbol)
|
||||
code += IRInstruction(Opcode.INCM, dt, labelSymbol = symbol)
|
||||
code += IRInstruction(Opcode.INCM, dt, labelSymbol = symbol)
|
||||
}
|
||||
}
|
||||
-1 -> {
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.DECM, dt, value=knownAddress.toInt())
|
||||
IRInstruction(Opcode.DECM, dt, value=knownAddress.toInt())
|
||||
else
|
||||
IRCodeInstruction(Opcode.DECM, dt, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.DECM, dt, labelSymbol = symbol)
|
||||
}
|
||||
-2 -> {
|
||||
if(knownAddress!=null) {
|
||||
code += IRCodeInstruction(Opcode.DECM, dt, value = knownAddress.toInt())
|
||||
code += IRCodeInstruction(Opcode.DECM, dt, value = knownAddress.toInt())
|
||||
code += IRInstruction(Opcode.DECM, dt, value = knownAddress.toInt())
|
||||
code += IRInstruction(Opcode.DECM, dt, value = knownAddress.toInt())
|
||||
} else {
|
||||
code += IRCodeInstruction(Opcode.DECM, dt, labelSymbol = symbol)
|
||||
code += IRCodeInstruction(Opcode.DECM, dt, labelSymbol = symbol)
|
||||
code += IRInstruction(Opcode.DECM, dt, labelSymbol = symbol)
|
||||
code += IRInstruction(Opcode.DECM, dt, labelSymbol = symbol)
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
val valueReg = vmRegisters.nextFree()
|
||||
if(value>0) {
|
||||
code += IRCodeInstruction(Opcode.LOAD, dt, reg1=valueReg, value=value)
|
||||
code += IRInstruction(Opcode.LOAD, dt, reg1=valueReg, value=value)
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.ADDM, dt, reg1=valueReg, value=knownAddress.toInt())
|
||||
IRInstruction(Opcode.ADDM, dt, reg1=valueReg, value=knownAddress.toInt())
|
||||
else
|
||||
IRCodeInstruction(Opcode.ADDM, dt, reg1=valueReg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.ADDM, dt, reg1=valueReg, labelSymbol = symbol)
|
||||
}
|
||||
else {
|
||||
code += IRCodeInstruction(Opcode.LOAD, dt, reg1=valueReg, value=-value)
|
||||
code += IRInstruction(Opcode.LOAD, dt, reg1=valueReg, value=-value)
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.SUBM, dt, reg1=valueReg, value=knownAddress.toInt())
|
||||
IRInstruction(Opcode.SUBM, dt, reg1=valueReg, value=knownAddress.toInt())
|
||||
else
|
||||
IRCodeInstruction(Opcode.SUBM, dt, reg1=valueReg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.SUBM, dt, reg1=valueReg, labelSymbol = symbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -550,9 +550,9 @@ class IRCodeGen(
|
||||
if(factor==1f)
|
||||
return code
|
||||
code += if(factor==0f) {
|
||||
IRCodeInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1 = fpReg, fpValue = 0f)
|
||||
IRInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1 = fpReg, fpValue = 0f)
|
||||
} else {
|
||||
IRCodeInstruction(Opcode.MUL, VmDataType.FLOAT, fpReg1 = fpReg, fpValue=factor)
|
||||
IRInstruction(Opcode.MUL, VmDataType.FLOAT, fpReg1 = fpReg, fpValue=factor)
|
||||
}
|
||||
return code
|
||||
}
|
||||
@ -563,16 +563,16 @@ class IRCodeGen(
|
||||
return code
|
||||
if(factor==0f) {
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.STOREZM, VmDataType.FLOAT, value = knownAddress)
|
||||
IRInstruction(Opcode.STOREZM, VmDataType.FLOAT, value = knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.STOREZM, VmDataType.FLOAT, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.STOREZM, VmDataType.FLOAT, labelSymbol = symbol)
|
||||
} else {
|
||||
val factorReg = vmRegisters.nextFreeFloat()
|
||||
code += IRCodeInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1=factorReg, fpValue = factor)
|
||||
code += IRInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1=factorReg, fpValue = factor)
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.MULM, VmDataType.FLOAT, fpReg1 = factorReg, value = knownAddress)
|
||||
IRInstruction(Opcode.MULM, VmDataType.FLOAT, fpReg1 = factorReg, value = knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.MULM, VmDataType.FLOAT, fpReg1 = factorReg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.MULM, VmDataType.FLOAT, fpReg1 = factorReg, labelSymbol = symbol)
|
||||
}
|
||||
return code
|
||||
}
|
||||
@ -586,18 +586,18 @@ class IRCodeGen(
|
||||
val pow2 = powersOfTwo.indexOf(factor)
|
||||
if(pow2==1) {
|
||||
// just shift 1 bit
|
||||
code += IRCodeInstruction(Opcode.LSL, dt, reg1=reg)
|
||||
code += IRInstruction(Opcode.LSL, dt, reg1=reg)
|
||||
}
|
||||
else if(pow2>=1) {
|
||||
// just shift multiple bits
|
||||
val pow2reg = vmRegisters.nextFree()
|
||||
code += IRCodeInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2)
|
||||
code += IRCodeInstruction(Opcode.LSLN, dt, reg1=reg, reg2=pow2reg)
|
||||
code += IRInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2)
|
||||
code += IRInstruction(Opcode.LSLN, dt, reg1=reg, reg2=pow2reg)
|
||||
} else {
|
||||
code += if (factor == 0) {
|
||||
IRCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0)
|
||||
IRInstruction(Opcode.LOAD, dt, reg1=reg, value=0)
|
||||
} else {
|
||||
IRCodeInstruction(Opcode.MUL, dt, reg1=reg, value=factor)
|
||||
IRInstruction(Opcode.MUL, dt, reg1=reg, value=factor)
|
||||
}
|
||||
}
|
||||
return code
|
||||
@ -611,32 +611,32 @@ class IRCodeGen(
|
||||
if(pow2==1) {
|
||||
// just shift 1 bit
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.LSLM, dt, value = knownAddress)
|
||||
IRInstruction(Opcode.LSLM, dt, value = knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.LSLM, dt, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.LSLM, dt, labelSymbol = symbol)
|
||||
}
|
||||
else if(pow2>=1) {
|
||||
// just shift multiple bits
|
||||
val pow2reg = vmRegisters.nextFree()
|
||||
code += IRCodeInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2)
|
||||
code += IRInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2)
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.LSLNM, dt, reg1=pow2reg, value=knownAddress)
|
||||
IRInstruction(Opcode.LSLNM, dt, reg1=pow2reg, value=knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.LSLNM, dt, reg1=pow2reg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.LSLNM, dt, reg1=pow2reg, labelSymbol = symbol)
|
||||
} else {
|
||||
if (factor == 0) {
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.STOREZM, dt, value=knownAddress)
|
||||
IRInstruction(Opcode.STOREZM, dt, value=knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.STOREZM, dt, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.STOREZM, dt, labelSymbol = symbol)
|
||||
}
|
||||
else {
|
||||
val factorReg = vmRegisters.nextFree()
|
||||
code += IRCodeInstruction(Opcode.LOAD, dt, reg1=factorReg, value = factor)
|
||||
code += IRInstruction(Opcode.LOAD, dt, reg1=factorReg, value = factor)
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.MULM, dt, reg1=factorReg, value = knownAddress)
|
||||
IRInstruction(Opcode.MULM, dt, reg1=factorReg, value = knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.MULM, dt, reg1=factorReg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.MULM, dt, reg1=factorReg, labelSymbol = symbol)
|
||||
}
|
||||
}
|
||||
return code
|
||||
@ -647,9 +647,9 @@ class IRCodeGen(
|
||||
if(factor==1f)
|
||||
return code
|
||||
code += if(factor==0f) {
|
||||
IRCodeInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1 = fpReg, fpValue = Float.MAX_VALUE)
|
||||
IRInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1 = fpReg, fpValue = Float.MAX_VALUE)
|
||||
} else {
|
||||
IRCodeInstruction(Opcode.DIVS, VmDataType.FLOAT, fpReg1 = fpReg, fpValue=factor)
|
||||
IRInstruction(Opcode.DIVS, VmDataType.FLOAT, fpReg1 = fpReg, fpValue=factor)
|
||||
}
|
||||
return code
|
||||
}
|
||||
@ -660,18 +660,18 @@ class IRCodeGen(
|
||||
return code
|
||||
if(factor==0f) {
|
||||
val maxvalueReg = vmRegisters.nextFreeFloat()
|
||||
code += IRCodeInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1 = maxvalueReg, fpValue = Float.MAX_VALUE)
|
||||
code += IRInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1 = maxvalueReg, fpValue = Float.MAX_VALUE)
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.STOREM, VmDataType.FLOAT, fpReg1 = maxvalueReg, value=knownAddress)
|
||||
IRInstruction(Opcode.STOREM, VmDataType.FLOAT, fpReg1 = maxvalueReg, value=knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.STOREM, VmDataType.FLOAT, fpReg1 = maxvalueReg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.STOREM, VmDataType.FLOAT, fpReg1 = maxvalueReg, labelSymbol = symbol)
|
||||
} else {
|
||||
val factorReg = vmRegisters.nextFreeFloat()
|
||||
code += IRCodeInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1=factorReg, fpValue = factor)
|
||||
code += IRInstruction(Opcode.LOAD, VmDataType.FLOAT, fpReg1=factorReg, fpValue = factor)
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.DIVSM, VmDataType.FLOAT, fpReg1 = factorReg, value=knownAddress)
|
||||
IRInstruction(Opcode.DIVSM, VmDataType.FLOAT, fpReg1 = factorReg, value=knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.DIVSM, VmDataType.FLOAT, fpReg1 = factorReg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.DIVSM, VmDataType.FLOAT, fpReg1 = factorReg, labelSymbol = symbol)
|
||||
}
|
||||
return code
|
||||
}
|
||||
@ -682,24 +682,24 @@ class IRCodeGen(
|
||||
return code
|
||||
val pow2 = powersOfTwo.indexOf(factor)
|
||||
if(pow2==1 && !signed) {
|
||||
code += IRCodeInstruction(Opcode.LSR, dt, reg1=reg) // simple single bit shift
|
||||
code += IRInstruction(Opcode.LSR, dt, reg1=reg) // simple single bit shift
|
||||
}
|
||||
else if(pow2>=1 &&!signed) {
|
||||
// just shift multiple bits
|
||||
val pow2reg = vmRegisters.nextFree()
|
||||
code += IRCodeInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2)
|
||||
code += IRInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2)
|
||||
code += if(signed)
|
||||
IRCodeInstruction(Opcode.ASRN, dt, reg1=reg, reg2=pow2reg)
|
||||
IRInstruction(Opcode.ASRN, dt, reg1=reg, reg2=pow2reg)
|
||||
else
|
||||
IRCodeInstruction(Opcode.LSRN, dt, reg1=reg, reg2=pow2reg)
|
||||
IRInstruction(Opcode.LSRN, dt, reg1=reg, reg2=pow2reg)
|
||||
} else {
|
||||
code += if (factor == 0) {
|
||||
IRCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0xffff)
|
||||
IRInstruction(Opcode.LOAD, dt, reg1=reg, value=0xffff)
|
||||
} else {
|
||||
if(signed)
|
||||
IRCodeInstruction(Opcode.DIVS, dt, reg1=reg, value=factor)
|
||||
IRInstruction(Opcode.DIVS, dt, reg1=reg, value=factor)
|
||||
else
|
||||
IRCodeInstruction(Opcode.DIV, dt, reg1=reg, value=factor)
|
||||
IRInstruction(Opcode.DIV, dt, reg1=reg, value=factor)
|
||||
}
|
||||
}
|
||||
return code
|
||||
@ -713,49 +713,49 @@ class IRCodeGen(
|
||||
if(pow2==1 && !signed) {
|
||||
// just simple bit shift
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.LSRM, dt, value=knownAddress)
|
||||
IRInstruction(Opcode.LSRM, dt, value=knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.LSRM, dt, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.LSRM, dt, labelSymbol = symbol)
|
||||
}
|
||||
else if(pow2>=1 && !signed) {
|
||||
// just shift multiple bits
|
||||
val pow2reg = vmRegisters.nextFree()
|
||||
code += IRCodeInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2)
|
||||
code += IRInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2)
|
||||
code += if(signed) {
|
||||
if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.ASRNM, dt, reg1 = pow2reg, value = knownAddress)
|
||||
IRInstruction(Opcode.ASRNM, dt, reg1 = pow2reg, value = knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.ASRNM, dt, reg1 = pow2reg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.ASRNM, dt, reg1 = pow2reg, labelSymbol = symbol)
|
||||
}
|
||||
else {
|
||||
if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.LSRNM, dt, reg1 = pow2reg, value = knownAddress)
|
||||
IRInstruction(Opcode.LSRNM, dt, reg1 = pow2reg, value = knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.LSRNM, dt, reg1 = pow2reg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.LSRNM, dt, reg1 = pow2reg, labelSymbol = symbol)
|
||||
}
|
||||
} else {
|
||||
if (factor == 0) {
|
||||
val reg = vmRegisters.nextFree()
|
||||
code += IRCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0xffff)
|
||||
code += IRInstruction(Opcode.LOAD, dt, reg1=reg, value=0xffff)
|
||||
code += if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.STOREM, dt, reg1=reg, value=knownAddress)
|
||||
IRInstruction(Opcode.STOREM, dt, reg1=reg, value=knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.STOREM, dt, reg1=reg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.STOREM, dt, reg1=reg, labelSymbol = symbol)
|
||||
}
|
||||
else {
|
||||
val factorReg = vmRegisters.nextFree()
|
||||
code += IRCodeInstruction(Opcode.LOAD, dt, reg1=factorReg, value= factor)
|
||||
code += IRInstruction(Opcode.LOAD, dt, reg1=factorReg, value= factor)
|
||||
code += if(signed) {
|
||||
if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.DIVSM, dt, reg1 = factorReg, value = knownAddress)
|
||||
IRInstruction(Opcode.DIVSM, dt, reg1 = factorReg, value = knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.DIVSM, dt, reg1 = factorReg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.DIVSM, dt, reg1 = factorReg, labelSymbol = symbol)
|
||||
}
|
||||
else {
|
||||
if(knownAddress!=null)
|
||||
IRCodeInstruction(Opcode.DIVM, dt, reg1 = factorReg, value = knownAddress)
|
||||
IRInstruction(Opcode.DIVM, dt, reg1 = factorReg, value = knownAddress)
|
||||
else
|
||||
IRCodeInstruction(Opcode.DIVM, dt, reg1 = factorReg, labelSymbol = symbol)
|
||||
IRInstruction(Opcode.DIVM, dt, reg1 = factorReg, labelSymbol = symbol)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -789,16 +789,16 @@ class IRCodeGen(
|
||||
// if and else parts
|
||||
val elseLabel = createLabelName()
|
||||
val afterIfLabel = createLabelName()
|
||||
code += IRCodeInstruction(elseBranch, vmDt, reg1=leftReg, reg2=rightReg, labelSymbol = elseLabel)
|
||||
code += IRInstruction(elseBranch, vmDt, reg1=leftReg, reg2=rightReg, labelSymbol = elseLabel)
|
||||
code += translateNode(ifElse.ifScope)
|
||||
code += IRCodeInstruction(Opcode.JUMP, labelSymbol = afterIfLabel)
|
||||
code += IRInstruction(Opcode.JUMP, labelSymbol = afterIfLabel)
|
||||
code += IRCodeLabel(elseLabel)
|
||||
code += translateNode(ifElse.elseScope)
|
||||
code += IRCodeLabel(afterIfLabel)
|
||||
} else {
|
||||
// only if part
|
||||
val afterIfLabel = createLabelName()
|
||||
code += IRCodeInstruction(elseBranch, vmDt, reg1=leftReg, reg2=rightReg, labelSymbol = afterIfLabel)
|
||||
code += IRInstruction(elseBranch, vmDt, reg1=leftReg, reg2=rightReg, labelSymbol = afterIfLabel)
|
||||
code += translateNode(ifElse.ifScope)
|
||||
code += IRCodeLabel(afterIfLabel)
|
||||
}
|
||||
@ -813,16 +813,16 @@ class IRCodeGen(
|
||||
// if and else parts
|
||||
val elseLabel = createLabelName()
|
||||
val afterIfLabel = createLabelName()
|
||||
code += IRCodeInstruction(elseBranch, vmDt, reg1=leftReg, labelSymbol = elseLabel)
|
||||
code += IRInstruction(elseBranch, vmDt, reg1=leftReg, labelSymbol = elseLabel)
|
||||
code += translateNode(ifElse.ifScope)
|
||||
code += IRCodeInstruction(Opcode.JUMP, labelSymbol = afterIfLabel)
|
||||
code += IRInstruction(Opcode.JUMP, labelSymbol = afterIfLabel)
|
||||
code += IRCodeLabel(elseLabel)
|
||||
code += translateNode(ifElse.elseScope)
|
||||
code += IRCodeLabel(afterIfLabel)
|
||||
} else {
|
||||
// only if part
|
||||
val afterIfLabel = createLabelName()
|
||||
code += IRCodeInstruction(elseBranch, vmDt, reg1=leftReg, labelSymbol = afterIfLabel)
|
||||
code += IRInstruction(elseBranch, vmDt, reg1=leftReg, labelSymbol = afterIfLabel)
|
||||
code += translateNode(ifElse.ifScope)
|
||||
code += IRCodeLabel(afterIfLabel)
|
||||
}
|
||||
@ -871,18 +871,18 @@ class IRCodeGen(
|
||||
val array = postIncrDecr.target.array
|
||||
val vmDt = vmType(postIncrDecr.target.type)
|
||||
if(ident!=null) {
|
||||
code += IRCodeInstruction(operationMem, vmDt, labelSymbol = ident.targetName.joinToString("."))
|
||||
code += IRInstruction(operationMem, vmDt, labelSymbol = ident.targetName.joinToString("."))
|
||||
} else if(memory!=null) {
|
||||
if(memory.address is PtNumber) {
|
||||
val address = (memory.address as PtNumber).number.toInt()
|
||||
code += IRCodeInstruction(operationMem, vmDt, value = address)
|
||||
code += IRInstruction(operationMem, vmDt, value = address)
|
||||
} else {
|
||||
val incReg = vmRegisters.nextFree()
|
||||
val addressReg = vmRegisters.nextFree()
|
||||
code += expressionEval.translateExpression(memory.address, addressReg, -1)
|
||||
code += IRCodeInstruction(Opcode.LOADI, vmDt, reg1 = incReg, reg2 = addressReg)
|
||||
code += IRCodeInstruction(operationRegister, vmDt, reg1 = incReg)
|
||||
code += IRCodeInstruction(Opcode.STOREI, vmDt, reg1 = incReg, reg2 = addressReg)
|
||||
code += IRInstruction(Opcode.LOADI, vmDt, reg1 = incReg, reg2 = addressReg)
|
||||
code += IRInstruction(operationRegister, vmDt, reg1 = incReg)
|
||||
code += IRInstruction(Opcode.STOREI, vmDt, reg1 = incReg, reg2 = addressReg)
|
||||
}
|
||||
} else if (array!=null) {
|
||||
val variable = array.variable.targetName.joinToString(".")
|
||||
@ -890,14 +890,14 @@ class IRCodeGen(
|
||||
val fixedIndex = constIntValue(array.index)
|
||||
if(fixedIndex!=null) {
|
||||
val offset = fixedIndex*itemsize
|
||||
code += IRCodeInstruction(operationMem, vmDt, labelSymbol="$variable+$offset")
|
||||
code += IRInstruction(operationMem, vmDt, labelSymbol="$variable+$offset")
|
||||
} else {
|
||||
val incReg = vmRegisters.nextFree()
|
||||
val indexReg = vmRegisters.nextFree()
|
||||
code += expressionEval.translateExpression(array.index, indexReg, -1)
|
||||
code += IRCodeInstruction(Opcode.LOADX, vmDt, reg1=incReg, reg2=indexReg, labelSymbol=variable)
|
||||
code += IRCodeInstruction(operationRegister, vmDt, reg1=incReg)
|
||||
code += IRCodeInstruction(Opcode.STOREX, vmDt, reg1=incReg, reg2=indexReg, labelSymbol=variable)
|
||||
code += IRInstruction(Opcode.LOADX, vmDt, reg1=incReg, reg2=indexReg, labelSymbol=variable)
|
||||
code += IRInstruction(operationRegister, vmDt, reg1=incReg)
|
||||
code += IRInstruction(Opcode.STOREX, vmDt, reg1=incReg, reg2=indexReg, labelSymbol=variable)
|
||||
}
|
||||
} else
|
||||
throw AssemblyError("weird assigntarget")
|
||||
@ -921,11 +921,11 @@ class IRCodeGen(
|
||||
val counterReg = vmRegisters.nextFree()
|
||||
val vmDt = vmType(repeat.count.type)
|
||||
code += expressionEval.translateExpression(repeat.count, counterReg, -1)
|
||||
code += IRCodeInstruction(Opcode.BZ, vmDt, reg1=counterReg, labelSymbol = skipRepeatLabel)
|
||||
code += IRInstruction(Opcode.BZ, vmDt, reg1=counterReg, labelSymbol = skipRepeatLabel)
|
||||
code += IRCodeLabel(repeatLabel)
|
||||
code += translateNode(repeat.statements)
|
||||
code += IRCodeInstruction(Opcode.DEC, vmDt, reg1=counterReg)
|
||||
code += IRCodeInstruction(Opcode.BNZ, vmDt, reg1=counterReg, labelSymbol = repeatLabel)
|
||||
code += IRInstruction(Opcode.DEC, vmDt, reg1=counterReg)
|
||||
code += IRInstruction(Opcode.BNZ, vmDt, reg1=counterReg, labelSymbol = repeatLabel)
|
||||
code += IRCodeLabel(skipRepeatLabel)
|
||||
return code
|
||||
}
|
||||
@ -935,9 +935,9 @@ class IRCodeGen(
|
||||
if(jump.address!=null)
|
||||
throw AssemblyError("cannot jump to memory location in the vm target")
|
||||
code += if(jump.generatedLabel!=null)
|
||||
IRCodeInstruction(Opcode.JUMP, labelSymbol = jump.generatedLabel!!)
|
||||
IRInstruction(Opcode.JUMP, labelSymbol = jump.generatedLabel!!)
|
||||
else if(jump.identifier!=null)
|
||||
IRCodeInstruction(Opcode.JUMP, labelSymbol = jump.identifier!!.targetName.joinToString("."))
|
||||
IRInstruction(Opcode.JUMP, labelSymbol = jump.identifier!!.targetName.joinToString("."))
|
||||
else
|
||||
throw AssemblyError("weird jump")
|
||||
return code
|
||||
@ -959,7 +959,7 @@ class IRCodeGen(
|
||||
else
|
||||
expressionEval.translateExpression(value, 0, -1)
|
||||
}
|
||||
code += IRCodeInstruction(Opcode.RETURN)
|
||||
code += IRInstruction(Opcode.RETURN)
|
||||
return code
|
||||
}
|
||||
|
||||
|
@ -10,8 +10,8 @@ internal class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
||||
if(chunk is IRCodeChunk) {
|
||||
do {
|
||||
val indexedInstructions = chunk.lines.withIndex()
|
||||
.filter { it.value is IRCodeInstruction }
|
||||
.map { IndexedValue(it.index, (it.value as IRCodeInstruction).ins) }
|
||||
.filter { it.value is IRInstruction }
|
||||
.map { IndexedValue(it.index, it.value as IRInstruction) }
|
||||
val changed = removeNops(chunk, indexedInstructions)
|
||||
|| removeDoubleLoadsAndStores(chunk, indexedInstructions) // TODO not yet implemented
|
||||
|| removeUselessArithmetic(chunk, indexedInstructions)
|
||||
@ -26,19 +26,19 @@ internal class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun cleanupPushPop(chunk: IRCodeChunk, indexedInstructions: List<IndexedValue<Instruction>>): Boolean {
|
||||
private fun cleanupPushPop(chunk: IRCodeChunk, indexedInstructions: List<IndexedValue<IRInstruction>>): Boolean {
|
||||
// push followed by pop to same target, or different target->replace with load
|
||||
var changed = false
|
||||
indexedInstructions.reversed().forEach { (idx, ins) ->
|
||||
if(ins.opcode== Opcode.PUSH) {
|
||||
if(idx < chunk.lines.size-1) {
|
||||
val insAfter = chunk.lines[idx+1] as? IRCodeInstruction
|
||||
if(insAfter!=null && insAfter.ins.opcode == Opcode.POP) {
|
||||
if(ins.reg1==insAfter.ins.reg1) {
|
||||
val insAfter = chunk.lines[idx+1] as? IRInstruction
|
||||
if(insAfter!=null && insAfter.opcode == Opcode.POP) {
|
||||
if(ins.reg1==insAfter.reg1) {
|
||||
chunk.lines.removeAt(idx)
|
||||
chunk.lines.removeAt(idx)
|
||||
} else {
|
||||
chunk.lines[idx] = IRCodeInstruction(Opcode.LOADR, ins.type, reg1=insAfter.ins.reg1, reg2=ins.reg1)
|
||||
chunk.lines[idx] = IRInstruction(Opcode.LOADR, ins.type, reg1=insAfter.reg1, reg2=ins.reg1)
|
||||
chunk.lines.removeAt(idx+1)
|
||||
}
|
||||
changed = true
|
||||
@ -49,23 +49,23 @@ internal class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
||||
return changed
|
||||
}
|
||||
|
||||
private fun removeDoubleSecClc(chunk: IRCodeChunk, indexedInstructions: List<IndexedValue<Instruction>>): Boolean {
|
||||
private fun removeDoubleSecClc(chunk: IRCodeChunk, indexedInstructions: List<IndexedValue<IRInstruction>>): Boolean {
|
||||
// double sec, clc
|
||||
// sec+clc or clc+sec
|
||||
var changed = false
|
||||
indexedInstructions.reversed().forEach { (idx, ins) ->
|
||||
if(ins.opcode== Opcode.SEC || ins.opcode== Opcode.CLC) {
|
||||
if(idx < chunk.lines.size-1) {
|
||||
val insAfter = chunk.lines[idx+1] as? IRCodeInstruction
|
||||
if(insAfter?.ins?.opcode == ins.opcode) {
|
||||
val insAfter = chunk.lines[idx+1] as? IRInstruction
|
||||
if(insAfter?.opcode == ins.opcode) {
|
||||
chunk.lines.removeAt(idx)
|
||||
changed = true
|
||||
}
|
||||
else if(ins.opcode== Opcode.SEC && insAfter?.ins?.opcode== Opcode.CLC) {
|
||||
else if(ins.opcode== Opcode.SEC && insAfter?.opcode== Opcode.CLC) {
|
||||
chunk.lines.removeAt(idx)
|
||||
changed = true
|
||||
}
|
||||
else if(ins.opcode== Opcode.CLC && insAfter?.ins?.opcode== Opcode.SEC) {
|
||||
else if(ins.opcode== Opcode.CLC && insAfter?.opcode== Opcode.SEC) {
|
||||
chunk.lines.removeAt(idx)
|
||||
changed = true
|
||||
}
|
||||
@ -75,7 +75,7 @@ internal class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
||||
return changed
|
||||
}
|
||||
|
||||
private fun removeWeirdBranches(chunk: IRCodeChunk, indexedInstructions: List<IndexedValue<Instruction>>): Boolean {
|
||||
private fun removeWeirdBranches(chunk: IRCodeChunk, indexedInstructions: List<IndexedValue<IRInstruction>>): Boolean {
|
||||
// jump/branch to label immediately below
|
||||
var changed = false
|
||||
indexedInstructions.reversed().forEach { (idx, ins) ->
|
||||
@ -94,7 +94,7 @@ internal class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
||||
return changed
|
||||
}
|
||||
|
||||
private fun removeUselessArithmetic(chunk: IRCodeChunk, indexedInstructions: List<IndexedValue<Instruction>>): Boolean {
|
||||
private fun removeUselessArithmetic(chunk: IRCodeChunk, indexedInstructions: List<IndexedValue<IRInstruction>>): Boolean {
|
||||
// note: this is hard to solve for the non-immediate instructions atm because the values are loaded into registers first
|
||||
var changed = false
|
||||
indexedInstructions.reversed().forEach { (idx, ins) ->
|
||||
@ -107,7 +107,7 @@ internal class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
||||
}
|
||||
Opcode.ADD, Opcode.SUB -> {
|
||||
if (ins.value == 1) {
|
||||
chunk.lines[idx] = IRCodeInstruction(
|
||||
chunk.lines[idx] = IRInstruction(
|
||||
if (ins.opcode == Opcode.ADD) Opcode.INC else Opcode.DEC,
|
||||
ins.type,
|
||||
ins.reg1
|
||||
@ -120,7 +120,7 @@ internal class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
||||
}
|
||||
Opcode.AND -> {
|
||||
if (ins.value == 0) {
|
||||
chunk.lines[idx] = IRCodeInstruction(Opcode.LOAD, ins.type, reg1 = ins.reg1, value = 0)
|
||||
chunk.lines[idx] = IRInstruction(Opcode.LOAD, ins.type, reg1 = ins.reg1, value = 0)
|
||||
changed = true
|
||||
} else if (ins.value == 255 && ins.type == VmDataType.BYTE) {
|
||||
chunk.lines.removeAt(idx)
|
||||
@ -135,7 +135,7 @@ internal class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
||||
chunk.lines.removeAt(idx)
|
||||
changed = true
|
||||
} else if ((ins.value == 255 && ins.type == VmDataType.BYTE) || (ins.value == 65535 && ins.type == VmDataType.WORD)) {
|
||||
chunk.lines[idx] = IRCodeInstruction(Opcode.LOAD, ins.type, reg1 = ins.reg1, value = ins.value)
|
||||
chunk.lines[idx] = IRInstruction(Opcode.LOAD, ins.type, reg1 = ins.reg1, value = ins.value)
|
||||
changed = true
|
||||
}
|
||||
}
|
||||
@ -151,7 +151,7 @@ internal class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
||||
return changed
|
||||
}
|
||||
|
||||
private fun removeNops(chunk: IRCodeChunk, indexedInstructions: List<IndexedValue<Instruction>>): Boolean {
|
||||
private fun removeNops(chunk: IRCodeChunk, indexedInstructions: List<IndexedValue<IRInstruction>>): Boolean {
|
||||
var changed = false
|
||||
indexedInstructions.reversed().forEach { (idx, ins) ->
|
||||
if (ins.opcode == Opcode.NOP) {
|
||||
@ -162,7 +162,7 @@ internal class IRPeepholeOptimizer(private val irprog: IRProgram) {
|
||||
return changed
|
||||
}
|
||||
|
||||
private fun removeDoubleLoadsAndStores(chunk: IRCodeChunk, indexedInstructions: List<IndexedValue<Instruction>>): Boolean {
|
||||
private fun removeDoubleLoadsAndStores(chunk: IRCodeChunk, indexedInstructions: List<IndexedValue<IRInstruction>>): Boolean {
|
||||
var changed = false
|
||||
indexedInstructions.forEach { (idx, ins) ->
|
||||
|
||||
|
@ -34,9 +34,9 @@ class TestIRPeepholeOpt: FunSpec({
|
||||
|
||||
test("remove nops") {
|
||||
val irProg = makeIRProgram(listOf(
|
||||
IRCodeInstruction(Opcode.JUMP, labelSymbol = "dummy"),
|
||||
IRCodeInstruction(Opcode.NOP),
|
||||
IRCodeInstruction(Opcode.NOP)
|
||||
IRInstruction(Opcode.JUMP, labelSymbol = "dummy"),
|
||||
IRInstruction(Opcode.NOP),
|
||||
IRInstruction(Opcode.NOP)
|
||||
))
|
||||
irProg.lines().size shouldBe 3
|
||||
val opt = IRPeepholeOptimizer(irProg)
|
||||
@ -46,13 +46,13 @@ class TestIRPeepholeOpt: FunSpec({
|
||||
|
||||
test("remove jmp to label below") {
|
||||
val irProg = makeIRProgram(listOf(
|
||||
IRCodeInstruction(Opcode.JUMP, labelSymbol = "label"), // removed
|
||||
IRInstruction(Opcode.JUMP, labelSymbol = "label"), // removed
|
||||
IRCodeLabel("label"),
|
||||
IRCodeInstruction(Opcode.JUMP, labelSymbol = "label2"), // removed
|
||||
IRCodeInstruction(Opcode.NOP), // removed
|
||||
IRInstruction(Opcode.JUMP, labelSymbol = "label2"), // removed
|
||||
IRInstruction(Opcode.NOP), // removed
|
||||
IRCodeLabel("label2"),
|
||||
IRCodeInstruction(Opcode.JUMP, labelSymbol = "label3"),
|
||||
IRCodeInstruction(Opcode.INC, VmDataType.BYTE, reg1=1),
|
||||
IRInstruction(Opcode.JUMP, labelSymbol = "label3"),
|
||||
IRInstruction(Opcode.INC, VmDataType.BYTE, reg1=1),
|
||||
IRCodeLabel("label3")
|
||||
))
|
||||
irProg.lines().size shouldBe 8
|
||||
@ -62,57 +62,57 @@ class TestIRPeepholeOpt: FunSpec({
|
||||
lines.size shouldBe 5
|
||||
(lines[0] as IRCodeLabel).name shouldBe "label"
|
||||
(lines[1] as IRCodeLabel).name shouldBe "label2"
|
||||
(lines[2] as IRCodeInstruction).ins.opcode shouldBe Opcode.JUMP
|
||||
(lines[3] as IRCodeInstruction).ins.opcode shouldBe Opcode.INC
|
||||
(lines[2] as IRInstruction).opcode shouldBe Opcode.JUMP
|
||||
(lines[3] as IRInstruction).opcode shouldBe Opcode.INC
|
||||
(lines[4] as IRCodeLabel).name shouldBe "label3"
|
||||
}
|
||||
|
||||
test("remove double sec/clc") {
|
||||
val irProg = makeIRProgram(listOf(
|
||||
IRCodeInstruction(Opcode.SEC),
|
||||
IRCodeInstruction(Opcode.SEC),
|
||||
IRCodeInstruction(Opcode.SEC),
|
||||
IRCodeInstruction(Opcode.CLC),
|
||||
IRCodeInstruction(Opcode.CLC),
|
||||
IRCodeInstruction(Opcode.CLC)
|
||||
IRInstruction(Opcode.SEC),
|
||||
IRInstruction(Opcode.SEC),
|
||||
IRInstruction(Opcode.SEC),
|
||||
IRInstruction(Opcode.CLC),
|
||||
IRInstruction(Opcode.CLC),
|
||||
IRInstruction(Opcode.CLC)
|
||||
))
|
||||
irProg.lines().size shouldBe 6
|
||||
val opt = IRPeepholeOptimizer(irProg)
|
||||
opt.optimize()
|
||||
val lines = irProg.lines()
|
||||
lines.size shouldBe 1
|
||||
(lines[0] as IRCodeInstruction).ins.opcode shouldBe Opcode.CLC
|
||||
(lines[0] as IRInstruction).opcode shouldBe Opcode.CLC
|
||||
}
|
||||
|
||||
test("push followed by pop") {
|
||||
val irProg = makeIRProgram(listOf(
|
||||
IRCodeInstruction(Opcode.PUSH, VmDataType.BYTE, reg1=42),
|
||||
IRCodeInstruction(Opcode.POP, VmDataType.BYTE, reg1=42),
|
||||
IRCodeInstruction(Opcode.PUSH, VmDataType.BYTE, reg1=99),
|
||||
IRCodeInstruction(Opcode.POP, VmDataType.BYTE, reg1=222)
|
||||
IRInstruction(Opcode.PUSH, VmDataType.BYTE, reg1=42),
|
||||
IRInstruction(Opcode.POP, VmDataType.BYTE, reg1=42),
|
||||
IRInstruction(Opcode.PUSH, VmDataType.BYTE, reg1=99),
|
||||
IRInstruction(Opcode.POP, VmDataType.BYTE, reg1=222)
|
||||
))
|
||||
irProg.lines().size shouldBe 4
|
||||
val opt = IRPeepholeOptimizer(irProg)
|
||||
opt.optimize()
|
||||
val lines = irProg.lines()
|
||||
lines.size shouldBe 1
|
||||
(lines[0] as IRCodeInstruction).ins.opcode shouldBe Opcode.LOADR
|
||||
(lines[0] as IRCodeInstruction).ins.reg1 shouldBe 222
|
||||
(lines[0] as IRCodeInstruction).ins.reg2 shouldBe 99
|
||||
(lines[0] as IRInstruction).opcode shouldBe Opcode.LOADR
|
||||
(lines[0] as IRInstruction).reg1 shouldBe 222
|
||||
(lines[0] as IRInstruction).reg2 shouldBe 99
|
||||
}
|
||||
|
||||
test("remove useless div/mul, add/sub") {
|
||||
val irProg = makeIRProgram(listOf(
|
||||
IRCodeInstruction(Opcode.DIV, VmDataType.BYTE, reg1=42, value = 1),
|
||||
IRCodeInstruction(Opcode.DIVS, VmDataType.BYTE, reg1=42, value = 1),
|
||||
IRCodeInstruction(Opcode.MUL, VmDataType.BYTE, reg1=42, value = 1),
|
||||
IRCodeInstruction(Opcode.MOD, VmDataType.BYTE, reg1=42, value = 1),
|
||||
IRCodeInstruction(Opcode.DIV, VmDataType.BYTE, reg1=42, value = 2),
|
||||
IRCodeInstruction(Opcode.DIVS, VmDataType.BYTE, reg1=42, value = 2),
|
||||
IRCodeInstruction(Opcode.MUL, VmDataType.BYTE, reg1=42, value = 2),
|
||||
IRCodeInstruction(Opcode.MOD, VmDataType.BYTE, reg1=42, value = 2),
|
||||
IRCodeInstruction(Opcode.ADD, VmDataType.BYTE, reg1=42, value = 0),
|
||||
IRCodeInstruction(Opcode.SUB, VmDataType.BYTE, reg1=42, value = 0)
|
||||
IRInstruction(Opcode.DIV, VmDataType.BYTE, reg1=42, value = 1),
|
||||
IRInstruction(Opcode.DIVS, VmDataType.BYTE, reg1=42, value = 1),
|
||||
IRInstruction(Opcode.MUL, VmDataType.BYTE, reg1=42, value = 1),
|
||||
IRInstruction(Opcode.MOD, VmDataType.BYTE, reg1=42, value = 1),
|
||||
IRInstruction(Opcode.DIV, VmDataType.BYTE, reg1=42, value = 2),
|
||||
IRInstruction(Opcode.DIVS, VmDataType.BYTE, reg1=42, value = 2),
|
||||
IRInstruction(Opcode.MUL, VmDataType.BYTE, reg1=42, value = 2),
|
||||
IRInstruction(Opcode.MOD, VmDataType.BYTE, reg1=42, value = 2),
|
||||
IRInstruction(Opcode.ADD, VmDataType.BYTE, reg1=42, value = 0),
|
||||
IRInstruction(Opcode.SUB, VmDataType.BYTE, reg1=42, value = 0)
|
||||
))
|
||||
irProg.lines().size shouldBe 10
|
||||
val opt = IRPeepholeOptimizer(irProg)
|
||||
@ -123,28 +123,28 @@ class TestIRPeepholeOpt: FunSpec({
|
||||
|
||||
test("replace add/sub 1 by inc/dec") {
|
||||
val irProg = makeIRProgram(listOf(
|
||||
IRCodeInstruction(Opcode.ADD, VmDataType.BYTE, reg1=42, value = 1),
|
||||
IRCodeInstruction(Opcode.SUB, VmDataType.BYTE, reg1=42, value = 1)
|
||||
IRInstruction(Opcode.ADD, VmDataType.BYTE, reg1=42, value = 1),
|
||||
IRInstruction(Opcode.SUB, VmDataType.BYTE, reg1=42, value = 1)
|
||||
))
|
||||
irProg.lines().size shouldBe 2
|
||||
val opt = IRPeepholeOptimizer(irProg)
|
||||
opt.optimize()
|
||||
val lines = irProg.lines()
|
||||
lines.size shouldBe 2
|
||||
(lines[0] as IRCodeInstruction).ins.opcode shouldBe Opcode.INC
|
||||
(lines[1] as IRCodeInstruction).ins.opcode shouldBe Opcode.DEC
|
||||
(lines[0] as IRInstruction).opcode shouldBe Opcode.INC
|
||||
(lines[1] as IRInstruction).opcode shouldBe Opcode.DEC
|
||||
}
|
||||
|
||||
test("remove useless and/or/xor") {
|
||||
val irProg = makeIRProgram(listOf(
|
||||
IRCodeInstruction(Opcode.AND, VmDataType.BYTE, reg1=42, value = 255),
|
||||
IRCodeInstruction(Opcode.AND, VmDataType.WORD, reg1=42, value = 65535),
|
||||
IRCodeInstruction(Opcode.OR, VmDataType.BYTE, reg1=42, value = 0),
|
||||
IRCodeInstruction(Opcode.XOR, VmDataType.BYTE, reg1=42, value = 0),
|
||||
IRCodeInstruction(Opcode.AND, VmDataType.BYTE, reg1=42, value = 200),
|
||||
IRCodeInstruction(Opcode.AND, VmDataType.WORD, reg1=42, value = 60000),
|
||||
IRCodeInstruction(Opcode.OR, VmDataType.BYTE, reg1=42, value = 1),
|
||||
IRCodeInstruction(Opcode.XOR, VmDataType.BYTE, reg1=42, value = 1)
|
||||
IRInstruction(Opcode.AND, VmDataType.BYTE, reg1=42, value = 255),
|
||||
IRInstruction(Opcode.AND, VmDataType.WORD, reg1=42, value = 65535),
|
||||
IRInstruction(Opcode.OR, VmDataType.BYTE, reg1=42, value = 0),
|
||||
IRInstruction(Opcode.XOR, VmDataType.BYTE, reg1=42, value = 0),
|
||||
IRInstruction(Opcode.AND, VmDataType.BYTE, reg1=42, value = 200),
|
||||
IRInstruction(Opcode.AND, VmDataType.WORD, reg1=42, value = 60000),
|
||||
IRInstruction(Opcode.OR, VmDataType.BYTE, reg1=42, value = 1),
|
||||
IRInstruction(Opcode.XOR, VmDataType.BYTE, reg1=42, value = 1)
|
||||
))
|
||||
irProg.lines().size shouldBe 8
|
||||
val opt = IRPeepholeOptimizer(irProg)
|
||||
@ -155,23 +155,23 @@ class TestIRPeepholeOpt: FunSpec({
|
||||
|
||||
test("replace and/or/xor by constant number") {
|
||||
val irProg = makeIRProgram(listOf(
|
||||
IRCodeInstruction(Opcode.AND, VmDataType.BYTE, reg1=42, value = 0),
|
||||
IRCodeInstruction(Opcode.AND, VmDataType.WORD, reg1=42, value = 0),
|
||||
IRCodeInstruction(Opcode.OR, VmDataType.BYTE, reg1=42, value = 255),
|
||||
IRCodeInstruction(Opcode.OR, VmDataType.WORD, reg1=42, value = 65535)
|
||||
IRInstruction(Opcode.AND, VmDataType.BYTE, reg1=42, value = 0),
|
||||
IRInstruction(Opcode.AND, VmDataType.WORD, reg1=42, value = 0),
|
||||
IRInstruction(Opcode.OR, VmDataType.BYTE, reg1=42, value = 255),
|
||||
IRInstruction(Opcode.OR, VmDataType.WORD, reg1=42, value = 65535)
|
||||
))
|
||||
irProg.lines().size shouldBe 4
|
||||
val opt = IRPeepholeOptimizer(irProg)
|
||||
opt.optimize()
|
||||
val lines = irProg.lines()
|
||||
lines.size shouldBe 4
|
||||
(lines[0] as IRCodeInstruction).ins.opcode shouldBe Opcode.LOAD
|
||||
(lines[1] as IRCodeInstruction).ins.opcode shouldBe Opcode.LOAD
|
||||
(lines[2] as IRCodeInstruction).ins.opcode shouldBe Opcode.LOAD
|
||||
(lines[3] as IRCodeInstruction).ins.opcode shouldBe Opcode.LOAD
|
||||
(lines[0] as IRCodeInstruction).ins.value shouldBe 0
|
||||
(lines[1] as IRCodeInstruction).ins.value shouldBe 0
|
||||
(lines[2] as IRCodeInstruction).ins.value shouldBe 255
|
||||
(lines[3] as IRCodeInstruction).ins.value shouldBe 65535
|
||||
(lines[0] as IRInstruction).opcode shouldBe Opcode.LOAD
|
||||
(lines[1] as IRInstruction).opcode shouldBe Opcode.LOAD
|
||||
(lines[2] as IRInstruction).opcode shouldBe Opcode.LOAD
|
||||
(lines[3] as IRInstruction).opcode shouldBe Opcode.LOAD
|
||||
(lines[0] as IRInstruction).value shouldBe 0
|
||||
(lines[1] as IRInstruction).value shouldBe 0
|
||||
(lines[2] as IRInstruction).value shouldBe 255
|
||||
(lines[3] as IRInstruction).value shouldBe 65535
|
||||
}
|
||||
})
|
@ -1,16 +0,0 @@
|
||||
package prog8.codegen.virtual
|
||||
|
||||
import prog8.code.core.CompilationOptions
|
||||
import prog8.code.core.IAssemblyProgram
|
||||
import prog8.intermediate.IRFileWriter
|
||||
import prog8.intermediate.IRProgram
|
||||
|
||||
|
||||
internal class VmAssemblyProgram(override val name: String, private val irProgram: IRProgram): IAssemblyProgram {
|
||||
|
||||
override fun assemble(options: CompilationOptions): Boolean {
|
||||
val writtenFile = IRFileWriter(irProgram, null).write()
|
||||
println("Wrote intermediate representation to $writtenFile")
|
||||
return true
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ import prog8.code.core.IErrorReporter
|
||||
import prog8.codegen.intermediate.IRCodeGen
|
||||
import prog8.intermediate.IRFileReader
|
||||
import prog8.intermediate.IRFileWriter
|
||||
import prog8.intermediate.IRProgram
|
||||
import java.nio.file.Path
|
||||
|
||||
class VmCodeGen(private val program: PtProgram,
|
||||
@ -37,4 +38,14 @@ class VmCodeGen(private val program: PtProgram,
|
||||
return VmAssemblyProgram(irProgram.name, irProgram)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal class VmAssemblyProgram(override val name: String, private val irProgram: IRProgram): IAssemblyProgram {
|
||||
|
||||
override fun assemble(options: CompilationOptions): Boolean {
|
||||
val writtenFile = IRFileWriter(irProgram, null).write()
|
||||
println("Wrote intermediate representation to $writtenFile")
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ TODO
|
||||
|
||||
For next release
|
||||
^^^^^^^^^^^^^^^^
|
||||
- vm: merge IRCodeInstruction into Instruction directly
|
||||
- vm: move codeGenVirtual module into virtualmachine module?
|
||||
- vm: actually translate IRProgram to vm program list again.
|
||||
- docs: modify compiler arch picture once this is done.
|
||||
|
||||
|
@ -562,7 +562,7 @@ class IRFileReader {
|
||||
if(format.fpValue && value!=null)
|
||||
floatValue = value
|
||||
|
||||
return IRCodeInstruction(opcode, type, reg1, reg2, fpReg1, fpReg2, intValue, floatValue, labelSymbol)
|
||||
return IRInstruction(opcode, type, reg1, reg2, fpReg1, fpReg2, intValue, floatValue, labelSymbol)
|
||||
}
|
||||
|
||||
private fun convertVmType(typestr: String): VmDataType? {
|
||||
|
@ -152,9 +152,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
||||
private fun BufferedWriter.writeLine(line: IRCodeLine) {
|
||||
when(line) {
|
||||
is IRCodeComment -> write("; ${line.comment}\n")
|
||||
is IRCodeInstruction -> {
|
||||
write(line.ins.toString() + "\n")
|
||||
}
|
||||
is IRInstruction -> write(line.toString() + "\n")
|
||||
is IRCodeLabel -> write("_${line.name}:\n")
|
||||
is IRCodeInlineBinary -> {
|
||||
write("<BYTES>\n")
|
||||
|
@ -398,7 +398,7 @@ enum class VmDataType {
|
||||
// TODO add INT (32-bit)? INT24 (24-bit)?
|
||||
}
|
||||
|
||||
data class Instruction(
|
||||
data class IRInstruction(
|
||||
val opcode: Opcode,
|
||||
val type: VmDataType?=null,
|
||||
val reg1: Int?=null, // 0-$ffff
|
||||
@ -409,13 +409,38 @@ data class Instruction(
|
||||
val fpValue: Float?=null,
|
||||
val labelSymbol: String?=null, // symbolic label name as alternative to value (so only for Branch/jump/call Instructions!)
|
||||
val binaryData: ByteArray?=null
|
||||
) {
|
||||
): IRCodeLine() {
|
||||
// reg1 and fpreg1 can be IN/OUT/INOUT (all others are readonly INPUT)
|
||||
// This knowledge is useful in IL assembly optimizers to see how registers are used.
|
||||
val reg1direction: OperandDirection
|
||||
val fpReg1direction: OperandDirection
|
||||
|
||||
init {
|
||||
if(labelSymbol?.startsWith('_')==true) {
|
||||
throw IllegalArgumentException("label/symbol should not start with underscore $labelSymbol")
|
||||
}
|
||||
if(reg1!=null && (reg1<0 || reg1>65536))
|
||||
throw IllegalArgumentException("reg1 out of bounds")
|
||||
if(reg2!=null && (reg2<0 || reg2>65536))
|
||||
throw IllegalArgumentException("reg2 out of bounds")
|
||||
if(fpReg1!=null && (fpReg1<0 || fpReg1>65536))
|
||||
throw IllegalArgumentException("fpReg1 out of bounds")
|
||||
if(fpReg2!=null && (fpReg2<0 || fpReg2>65536))
|
||||
throw IllegalArgumentException("fpReg2 out of bounds")
|
||||
if(value!=null && opcode !in OpcodesWithAddress) {
|
||||
when (type) {
|
||||
VmDataType.BYTE -> {
|
||||
if (value < -128 || value > 255)
|
||||
throw IllegalArgumentException("value out of range for byte: $value")
|
||||
}
|
||||
VmDataType.WORD -> {
|
||||
if (value < -32768 || value > 65535)
|
||||
throw IllegalArgumentException("value out of range for word: $value")
|
||||
}
|
||||
VmDataType.FLOAT, null -> {}
|
||||
}
|
||||
}
|
||||
|
||||
if(opcode==Opcode.BINARYDATA && binaryData==null || binaryData!=null && opcode!=Opcode.BINARYDATA)
|
||||
throw IllegalArgumentException("binarydata inconsistency")
|
||||
|
@ -126,49 +126,6 @@ class IRAsmSubroutine(val name: String,
|
||||
|
||||
sealed class IRCodeLine
|
||||
|
||||
class IRCodeInstruction( // TODO join this into Instruction directly
|
||||
opcode: Opcode,
|
||||
type: VmDataType?=null,
|
||||
reg1: Int?=null, // 0-$ffff
|
||||
reg2: Int?=null, // 0-$ffff
|
||||
fpReg1: Int?=null, // 0-$ffff
|
||||
fpReg2: Int?=null, // 0-$ffff
|
||||
value: Int?=null, // 0-$ffff
|
||||
fpValue: Float?=null,
|
||||
labelSymbol: String?=null // alternative to value
|
||||
): IRCodeLine() {
|
||||
val ins = Instruction(opcode, type, reg1, reg2, fpReg1, fpReg2, value, fpValue, labelSymbol)
|
||||
|
||||
init {
|
||||
if(reg1!=null && (reg1<0 || reg1>65536))
|
||||
throw IllegalArgumentException("reg1 out of bounds")
|
||||
if(reg2!=null && (reg2<0 || reg2>65536))
|
||||
throw IllegalArgumentException("reg2 out of bounds")
|
||||
if(fpReg1!=null && (fpReg1<0 || fpReg1>65536))
|
||||
throw IllegalArgumentException("fpReg1 out of bounds")
|
||||
if(fpReg2!=null && (fpReg2<0 || fpReg2>65536))
|
||||
throw IllegalArgumentException("fpReg2 out of bounds")
|
||||
|
||||
if(value!=null && opcode !in OpcodesWithAddress) {
|
||||
when (type) {
|
||||
VmDataType.BYTE -> {
|
||||
if (value < -128 || value > 255)
|
||||
throw IllegalArgumentException("value out of range for byte: $value")
|
||||
}
|
||||
VmDataType.WORD -> {
|
||||
if (value < -32768 || value > 65535)
|
||||
throw IllegalArgumentException("value out of range for word: $value")
|
||||
}
|
||||
VmDataType.FLOAT, null -> {}
|
||||
}
|
||||
}
|
||||
|
||||
if(labelSymbol?.startsWith('_')==true) {
|
||||
throw IllegalArgumentException("label/symbol should not start with underscore $labelSymbol")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class IRCodeLabel(val name: String): IRCodeLine()
|
||||
|
||||
class IRCodeComment(val comment: String): IRCodeLine()
|
||||
|
@ -8,7 +8,7 @@ import prog8.intermediate.*
|
||||
class TestInstructions: FunSpec({
|
||||
|
||||
test("simple") {
|
||||
val ins = Instruction(Opcode.NOP)
|
||||
val ins = IRInstruction(Opcode.NOP)
|
||||
ins.opcode shouldBe Opcode.NOP
|
||||
ins.type shouldBe null
|
||||
ins.reg1 shouldBe null
|
||||
@ -21,33 +21,33 @@ class TestInstructions: FunSpec({
|
||||
}
|
||||
|
||||
test("with value") {
|
||||
val ins = Instruction(Opcode.BZ, VmDataType.BYTE, reg1=42, value = 9999)
|
||||
val ins = IRInstruction(Opcode.BZ, VmDataType.BYTE, reg1=42, value = 99)
|
||||
ins.opcode shouldBe Opcode.BZ
|
||||
ins.type shouldBe VmDataType.BYTE
|
||||
ins.reg1 shouldBe 42
|
||||
ins.reg2 shouldBe null
|
||||
ins.value shouldBe 9999
|
||||
ins.value shouldBe 99
|
||||
ins.labelSymbol shouldBe null
|
||||
ins.reg1direction shouldBe OperandDirection.INPUT
|
||||
ins.fpReg1direction shouldBe OperandDirection.INPUT
|
||||
ins.toString() shouldBe "bz.b r42,9999"
|
||||
ins.toString() shouldBe "bz.b r42,99"
|
||||
}
|
||||
|
||||
test("with label") {
|
||||
val ins = Instruction(Opcode.BZ, VmDataType.WORD, reg1=11, labelSymbol = "a.b.c")
|
||||
val ins = IRInstruction(Opcode.BZ, VmDataType.WORD, reg1=11, labelSymbol = "a.b.c")
|
||||
ins.opcode shouldBe Opcode.BZ
|
||||
ins.type shouldBe VmDataType.WORD
|
||||
ins.reg1 shouldBe 11
|
||||
ins.reg2 shouldBe null
|
||||
ins.value shouldBe null
|
||||
ins.labelSymbol shouldBe listOf("a","b","c")
|
||||
ins.labelSymbol shouldBe "a.b.c"
|
||||
ins.reg1direction shouldBe OperandDirection.INPUT
|
||||
ins.fpReg1direction shouldBe OperandDirection.INPUT
|
||||
ins.toString() shouldBe "bz.w r11,_a.b.c"
|
||||
}
|
||||
|
||||
test("with output registers") {
|
||||
val ins = Instruction(Opcode.ADDR, VmDataType.WORD, reg1=11, reg2=22)
|
||||
val ins = IRInstruction(Opcode.ADDR, VmDataType.WORD, reg1=11, reg2=22)
|
||||
ins.opcode shouldBe Opcode.ADDR
|
||||
ins.type shouldBe VmDataType.WORD
|
||||
ins.reg1 shouldBe 11
|
||||
@ -58,7 +58,7 @@ class TestInstructions: FunSpec({
|
||||
ins.fpReg1direction shouldBe OperandDirection.INPUT
|
||||
ins.toString() shouldBe "addr.w r11,r22"
|
||||
|
||||
val ins2 = Instruction(Opcode.SQRT, VmDataType.BYTE, reg1=11, reg2=22)
|
||||
val ins2 = IRInstruction(Opcode.SQRT, VmDataType.BYTE, reg1=11, reg2=22)
|
||||
ins2.opcode shouldBe Opcode.SQRT
|
||||
ins2.type shouldBe VmDataType.BYTE
|
||||
ins2.reg1 shouldBe 11
|
||||
@ -73,19 +73,19 @@ class TestInstructions: FunSpec({
|
||||
|
||||
test("missing type should fail") {
|
||||
shouldThrow<IllegalArgumentException> {
|
||||
Instruction(Opcode.BZ, reg1=42, value=9999)
|
||||
IRInstruction(Opcode.BZ, reg1=42, value=9999)
|
||||
}
|
||||
}
|
||||
|
||||
test("missing registers should fail") {
|
||||
shouldThrow<IllegalArgumentException> {
|
||||
Instruction(Opcode.BZ, VmDataType.BYTE, value=9999)
|
||||
IRInstruction(Opcode.BZ, VmDataType.BYTE, value=9999)
|
||||
}
|
||||
}
|
||||
|
||||
test("missing value should fail") {
|
||||
shouldThrow<IllegalArgumentException> {
|
||||
Instruction(Opcode.BZ, VmDataType.BYTE, reg1=42)
|
||||
IRInstruction(Opcode.BZ, VmDataType.BYTE, reg1=42)
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -5,11 +5,11 @@ import java.lang.IllegalArgumentException
|
||||
|
||||
class VmProgramLoader {
|
||||
|
||||
fun load(irProgram: IRProgram, memory: Memory): Array<Instruction> {
|
||||
fun load(irProgram: IRProgram, memory: Memory): Array<IRInstruction> {
|
||||
|
||||
// at long last, allocate the variables in memory.
|
||||
val allocations = VmVariableAllocator(irProgram.st, irProgram.encoding, irProgram.options.compTarget)
|
||||
val program = mutableListOf<Instruction>()
|
||||
val program = mutableListOf<IRInstruction>()
|
||||
|
||||
// TODO stuff the allocated variables into memory
|
||||
|
||||
@ -22,7 +22,7 @@ class VmProgramLoader {
|
||||
// make sure that if there is a "main.start" entrypoint, we jump to it
|
||||
irProgram.blocks.firstOrNull()?.let {
|
||||
if(it.subroutines.any { sub -> sub.name=="main.start" }) {
|
||||
program.add(Instruction(Opcode.JUMP, labelSymbol = "main.start"))
|
||||
program.add(IRInstruction(Opcode.JUMP, labelSymbol = "main.start"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,9 +42,9 @@ class TestVm: FunSpec( {
|
||||
val block = IRBlock("main", null, IRBlock.BlockAlignment.NONE, Position.DUMMY)
|
||||
val startSub = IRSubroutine("main.start2222", emptyList(), null, Position.DUMMY) // TODO proper name main.start
|
||||
val code = IRCodeChunk(Position.DUMMY)
|
||||
code += IRCodeInstruction(Opcode.LOAD, VmDataType.WORD, reg1=1, value=12345)
|
||||
code += IRCodeInstruction(Opcode.STOREM, VmDataType.WORD, reg1=1, value=1000)
|
||||
code += IRCodeInstruction(Opcode.RETURN)
|
||||
code += IRInstruction(Opcode.LOAD, VmDataType.WORD, reg1=1, value=12345)
|
||||
code += IRInstruction(Opcode.STOREM, VmDataType.WORD, reg1=1, value=1000)
|
||||
code += IRInstruction(Opcode.RETURN)
|
||||
startSub += code
|
||||
block += startSub
|
||||
program.addBlock(block)
|
||||
|
Loading…
x
Reference in New Issue
Block a user