working on vm

This commit is contained in:
Irmen de Jong
2022-03-30 21:44:48 +02:00
parent f46300016d
commit 0dc592b819
15 changed files with 372 additions and 145 deletions
@@ -4,6 +4,7 @@ import prog8.code.core.CompilationOptions
import prog8.code.core.IAssemblyProgram
import prog8.vm.Instruction
import prog8.vm.Opcode
import prog8.vm.VmDataType
import java.io.BufferedWriter
import kotlin.io.path.bufferedWriter
import kotlin.io.path.div
@@ -51,7 +52,17 @@ internal class AssemblyProgram(override val name: String,
internal sealed class VmCodeLine
internal class VmCodeInstruction(val ins: Instruction): VmCodeLine()
internal class VmCodeInstruction(
opcode: Opcode,
type: VmDataType?=null,
reg1: Int?=null, // 0-$ffff
reg2: Int?=null, // 0-$ffff
reg3: Int?=null, // 0-$ffff
value: Int?=null, // 0-$ffff
symbol: List<String>?=null // alternative to value
): VmCodeLine() {
val ins = Instruction(opcode, type, reg1, reg2, reg3, value, symbol)
}
internal class VmCodeLabel(val name: List<String>): VmCodeLine()
internal class VmCodeComment(val comment: String): VmCodeLine()
@@ -3,7 +3,6 @@ package prog8.codegen.virtual
import prog8.code.ast.PtBuiltinFunctionCall
import prog8.code.ast.PtNumber
import prog8.code.ast.PtString
import prog8.vm.Instruction
import prog8.vm.Opcode
import prog8.vm.Syscall
import prog8.vm.VmDataType
@@ -15,32 +14,32 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
when(call.name) {
"syscall" -> {
val vExpr = call.args.single() as PtNumber
code += VmCodeInstruction(Instruction(Opcode.SYSCALL, value=vExpr.number.toInt()))
code += VmCodeInstruction(Opcode.SYSCALL, value=vExpr.number.toInt())
}
"syscall1" -> {
code += VmCodeInstruction(Instruction(Opcode.PUSH, VmDataType.BYTE, reg1 = 0))
code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1 = 0)
val callNr = (call.args[0] as PtNumber).number.toInt()
code += exprGen.translateExpression(call.args[1], 0)
code += VmCodeInstruction(Instruction(Opcode.SYSCALL, value=callNr))
code += VmCodeInstruction(Instruction(Opcode.POP, VmDataType.BYTE, reg1 = 0))
code += VmCodeInstruction(Opcode.SYSCALL, value=callNr)
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 0)
}
"syscall2" -> {
code += VmCodeInstruction(Instruction(Opcode.PUSH, VmDataType.BYTE, reg1 = 0))
code += VmCodeInstruction(Instruction(Opcode.PUSH, VmDataType.WORD, reg1 = 1))
code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1 = 0)
code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1 = 1)
while(codeGen.vmRegisters.peekNext()<2) {
codeGen.vmRegisters.nextFree()
}
val callNr = (call.args[0] as PtNumber).number.toInt()
code += exprGen.translateExpression(call.args[1], 0)
code += exprGen.translateExpression(call.args[2], 1)
code += VmCodeInstruction(Instruction(Opcode.SYSCALL, value=callNr))
code += VmCodeInstruction(Instruction(Opcode.POP, VmDataType.WORD, reg1 = 1))
code += VmCodeInstruction(Instruction(Opcode.POP, VmDataType.BYTE, reg1 = 0))
code += VmCodeInstruction(Opcode.SYSCALL, value=callNr)
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 1)
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 0)
}
"syscall3" -> {
code += VmCodeInstruction(Instruction(Opcode.PUSH, VmDataType.BYTE, reg1 = 0))
code += VmCodeInstruction(Instruction(Opcode.PUSH, VmDataType.WORD, reg1 = 1))
code += VmCodeInstruction(Instruction(Opcode.PUSH, VmDataType.WORD, reg1 = 2))
code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1 = 0)
code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1 = 1)
code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1 = 2)
while(codeGen.vmRegisters.peekNext()<3) {
codeGen.vmRegisters.nextFree()
}
@@ -48,14 +47,14 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
code += exprGen.translateExpression(call.args[1], 0)
code += exprGen.translateExpression(call.args[2], 1)
code += exprGen.translateExpression(call.args[3], 2)
code += VmCodeInstruction(Instruction(Opcode.SYSCALL, value=callNr))
code += VmCodeInstruction(Instruction(Opcode.POP, VmDataType.WORD, reg1 = 2))
code += VmCodeInstruction(Instruction(Opcode.POP, VmDataType.WORD, reg1 = 1))
code += VmCodeInstruction(Instruction(Opcode.POP, VmDataType.BYTE, reg1 = 0))
code += VmCodeInstruction(Opcode.SYSCALL, value=callNr)
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 2)
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 1)
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 0)
}
"msb" -> {
code += exprGen.translateExpression(call.args.single(), resultRegister)
code += VmCodeInstruction(Instruction(Opcode.SWAP, VmDataType.BYTE, reg1 = resultRegister, reg2=resultRegister))
code += VmCodeInstruction(Opcode.SWAP, VmDataType.BYTE, reg1 = resultRegister)
// note: if a word result is needed, the upper byte is cleared by the typecast that follows. No need to do it here.
}
"lsb" -> {
@@ -75,50 +74,50 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
}
else
existing.first
code += VmCodeInstruction(Instruction(Opcode.LOAD, VmDataType.WORD, reg1=resultRegister, value=address.toInt()))
code += VmCodeInstruction(Opcode.LOAD, VmDataType.WORD, reg1=resultRegister, value=address.toInt())
}
"rnd" -> {
code += VmCodeInstruction(Instruction(Opcode.SYSCALL, value= Syscall.RND.ordinal))
code += VmCodeInstruction(Opcode.SYSCALL, value= Syscall.RND.ordinal)
if(resultRegister!=0)
code += VmCodeInstruction(Instruction(Opcode.LOADR, VmDataType.BYTE, reg1=resultRegister, reg2=0))
code += VmCodeInstruction(Opcode.LOADR, VmDataType.BYTE, reg1=resultRegister, reg2=0)
}
"peek" -> {
val addressReg = codeGen.vmRegisters.nextFree()
code += exprGen.translateExpression(call.args.single(), addressReg)
code += VmCodeInstruction(Instruction(Opcode.LOADI, VmDataType.BYTE, reg1 = resultRegister, reg2=addressReg))
code += VmCodeInstruction(Opcode.LOADI, VmDataType.BYTE, reg1 = resultRegister, reg2=addressReg)
}
"peekw" -> {
val addressReg = codeGen.vmRegisters.nextFree()
code += exprGen.translateExpression(call.args.single(), addressReg)
code += VmCodeInstruction(Instruction(Opcode.LOADI, VmDataType.WORD, reg1 = resultRegister, reg2=addressReg))
code += VmCodeInstruction(Opcode.LOADI, VmDataType.WORD, reg1 = resultRegister, reg2=addressReg)
}
"mkword" -> {
val msbReg = codeGen.vmRegisters.nextFree()
val lsbReg = codeGen.vmRegisters.nextFree()
code += exprGen.translateExpression(call.args[0], msbReg)
code += exprGen.translateExpression(call.args[1], lsbReg)
code += VmCodeInstruction(Instruction(Opcode.CONCAT, VmDataType.BYTE, reg1=resultRegister, reg2=msbReg, reg3=lsbReg))
code += VmCodeInstruction(Opcode.CONCAT, VmDataType.BYTE, reg1=resultRegister, reg2=msbReg, reg3=lsbReg)
}
else -> {
TODO("builtinfunc ${call.name}")
// code += VmCodeInstruction(Instruction(Opcode.NOP))
// code += VmCodeInstruction(Opcode.NOP))
// for (arg in call.args) {
// code += translateExpression(arg, resultRegister)
// code += when(arg.type) {
// in ByteDatatypes -> VmCodeInstruction(Instruction(Opcode.PUSH, VmDataType.BYTE, reg1=resultRegister))
// in WordDatatypes -> VmCodeInstruction(Instruction(Opcode.PUSH, VmDataType.WORD, reg1=resultRegister))
// in ByteDatatypes -> VmCodeInstruction(Opcode.PUSH, VmDataType.BYTE, reg1=resultRegister))
// in WordDatatypes -> VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1=resultRegister))
// else -> throw AssemblyError("weird arg dt")
// }
// }
// code += VmCodeInstruction(Instruction(Opcode.CALL), labelArg = listOf("_prog8_builtin", call.name))
// code += VmCodeInstruction(Opcode.CALL), labelArg = listOf("_prog8_builtin", call.name))
// for (arg in call.args) {
// code += when(arg.type) {
// in ByteDatatypes -> VmCodeInstruction(Instruction(Opcode.POP, VmDataType.BYTE, reg1=resultRegister))
// in WordDatatypes -> VmCodeInstruction(Instruction(Opcode.POP, VmDataType.WORD, reg1=resultRegister))
// in ByteDatatypes -> VmCodeInstruction(Opcode.POP, VmDataType.BYTE, reg1=resultRegister))
// in WordDatatypes -> VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1=resultRegister))
// else -> throw AssemblyError("weird arg dt")
// }
// }
// code += VmCodeInstruction(Instruction(Opcode.NOP))
// code += VmCodeInstruction(Opcode.NOP))
}
}
return code
@@ -4,10 +4,8 @@ import prog8.code.StStaticVariable
import prog8.code.SymbolTable
import prog8.code.ast.*
import prog8.code.core.*
import prog8.vm.Instruction
import prog8.vm.Opcode
import prog8.vm.VmDataType
import java.lang.Math.pow
import kotlin.math.pow
@@ -82,7 +80,7 @@ class CodeGen(internal val program: PtProgram,
is PtPostIncrDecr -> translate(node)
is PtRepeatLoop -> translate(node)
is PtLabel -> VmCodeChunk(VmCodeLabel(node.scopedName))
is PtBreakpoint -> VmCodeChunk(VmCodeInstruction(Instruction(Opcode.BREAKPOINT)))
is PtBreakpoint -> VmCodeChunk(VmCodeInstruction(Opcode.BREAKPOINT))
is PtAddressOf,
is PtContainmentCheck,
is PtMemoryByte,
@@ -129,14 +127,14 @@ class CodeGen(internal val program: PtProgram,
val endLabel = createLabelName()
if(iterableVar.dt==DataType.STR) {
// iterate over a zero-terminated string
code += VmCodeInstruction(Instruction(Opcode.LOAD, VmDataType.BYTE, reg1=indexReg, value=0))
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=indexReg, value=0)
code += VmCodeLabel(loopLabel)
code += VmCodeInstruction(Instruction(Opcode.LOADX, VmDataType.BYTE, reg1=0, reg2=indexReg, value = arrayAddress))
code += VmCodeInstruction(Instruction(Opcode.BZ, VmDataType.BYTE, reg1=0, symbol = endLabel))
code += VmCodeInstruction(Instruction(Opcode.STOREM, VmDataType.BYTE, reg1=0, value = loopvarAddress))
code += VmCodeInstruction(Opcode.LOADX, VmDataType.BYTE, reg1=0, reg2=indexReg, value = arrayAddress)
code += VmCodeInstruction(Opcode.BZ, VmDataType.BYTE, reg1=0, symbol = endLabel)
code += VmCodeInstruction(Opcode.STOREM, VmDataType.BYTE, reg1=0, value = loopvarAddress)
code += translateNode(forLoop.statements)
code += VmCodeInstruction(Instruction(Opcode.INC, VmDataType.BYTE, reg1=indexReg))
code += VmCodeInstruction(Instruction(Opcode.JUMP, symbol = loopLabel))
code += VmCodeInstruction(Opcode.INC, VmDataType.BYTE, reg1=indexReg)
code += VmCodeInstruction(Opcode.JUMP, symbol = loopLabel)
code += VmCodeLabel(endLabel)
} else {
// iterate over array
@@ -154,15 +152,15 @@ class CodeGen(internal val program: PtProgram,
goto _loop
_end: ...
*/
code += VmCodeInstruction(Instruction(Opcode.LOAD, VmDataType.BYTE, reg1=indexReg, value=0))
code += VmCodeInstruction(Instruction(Opcode.LOAD, VmDataType.BYTE, reg1=lengthReg, value=lengthBytes))
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=indexReg, value=0)
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=lengthReg, value=lengthBytes)
code += VmCodeLabel(loopLabel)
code += VmCodeInstruction(Instruction(Opcode.BEQ, VmDataType.BYTE, reg1=indexReg, reg2=lengthReg, symbol = endLabel))
code += VmCodeInstruction(Instruction(Opcode.LOADX, vmType(elementDt), reg1=0, reg2=indexReg, value=arrayAddress))
code += VmCodeInstruction(Instruction(Opcode.STOREM, vmType(elementDt), reg1=0, value = loopvarAddress))
code += VmCodeInstruction(Opcode.BEQ, VmDataType.BYTE, reg1=indexReg, reg2=lengthReg, symbol = endLabel)
code += VmCodeInstruction(Opcode.LOADX, vmType(elementDt), reg1=0, reg2=indexReg, value=arrayAddress)
code += VmCodeInstruction(Opcode.STOREM, vmType(elementDt), reg1=0, value = loopvarAddress)
code += translateNode(forLoop.statements)
code += addConst(VmDataType.BYTE, indexReg, elementSize)
code += VmCodeInstruction(Instruction(Opcode.JUMP, symbol = loopLabel))
code += VmCodeInstruction(Opcode.JUMP, symbol = loopLabel)
code += VmCodeLabel(endLabel)
}
}
@@ -176,12 +174,12 @@ class CodeGen(internal val program: PtProgram,
when(value) {
0u -> { /* do nothing */ }
1u -> {
code += VmCodeInstruction(Instruction(Opcode.INC, dt, reg1=reg))
code += VmCodeInstruction(Opcode.INC, dt, reg1=reg)
}
else -> {
val valueReg = vmRegisters.nextFree()
code += VmCodeInstruction(Instruction(Opcode.LOAD, dt, reg1=valueReg, value=value.toInt()))
code += VmCodeInstruction(Instruction(Opcode.ADD, dt, reg1=reg, reg2=reg, reg3=valueReg))
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=valueReg, value=value.toInt())
code += VmCodeInstruction(Opcode.ADD, dt, reg1=reg, reg2=reg, reg3=valueReg)
}
}
return code
@@ -194,17 +192,17 @@ class CodeGen(internal val program: PtProgram,
val pow2 = powersOfTwo.indexOf(factor.toInt())
if(pow2>=1) {
// just shift bits
code += VmCodeInstruction(Instruction(Opcode.LSL, dt, reg1=reg, reg2=reg, reg3=pow2))
code += VmCodeInstruction(Opcode.LSL, dt, reg1=reg, reg2=reg, reg3=pow2)
} else {
when(factor) {
0u -> {
code += VmCodeInstruction(Instruction(Opcode.LOAD, dt, reg1=reg, value=0))
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0)
}
1u -> { /* do nothing */ }
else -> {
val factorReg = vmRegisters.nextFree()
code += VmCodeInstruction(Instruction(Opcode.LOAD, dt, reg1=factorReg, value=factor.toInt()))
code += VmCodeInstruction(Instruction(Opcode.MUL, dt, reg1=reg, reg2=reg, reg3=factorReg))
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=factorReg, value=factor.toInt())
code += VmCodeInstruction(Opcode.MUL, dt, reg1=reg, reg2=reg, reg3=factorReg)
}
}
}
@@ -236,16 +234,16 @@ class CodeGen(internal val program: PtProgram,
// if and else parts
val elseLabel = createLabelName()
val afterIfLabel = createLabelName()
code += VmCodeInstruction(Instruction(branch, vmDt, reg1=conditionReg, symbol = elseLabel))
code += VmCodeInstruction(branch, vmDt, reg1=conditionReg, symbol = elseLabel)
code += translateNode(ifElse.ifScope)
code += VmCodeInstruction(Instruction(Opcode.JUMP, symbol = afterIfLabel))
code += VmCodeInstruction(Opcode.JUMP, symbol = afterIfLabel)
code += VmCodeLabel(elseLabel)
code += translateNode(ifElse.elseScope)
code += VmCodeLabel(afterIfLabel)
} else {
// only if part
val afterIfLabel = createLabelName()
code += VmCodeInstruction(Instruction(branch, vmDt, reg1=conditionReg, symbol = afterIfLabel))
code += VmCodeInstruction(branch, vmDt, reg1=conditionReg, symbol = afterIfLabel)
code += translateNode(ifElse.ifScope)
code += VmCodeLabel(afterIfLabel)
}
@@ -266,15 +264,15 @@ class CodeGen(internal val program: PtProgram,
val resultReg = vmRegisters.nextFree()
if(ident!=null) {
val address = allocations.get(ident.targetName)
code += VmCodeInstruction(Instruction(Opcode.LOADM, vmDt, reg1=resultReg, value = address))
code += VmCodeInstruction(Instruction(operation, vmDt, reg1=resultReg))
code += VmCodeInstruction(Instruction(Opcode.STOREM, vmDt, reg1=resultReg, value = address))
code += VmCodeInstruction(Opcode.LOADM, vmDt, reg1=resultReg, value = address)
code += VmCodeInstruction(operation, vmDt, reg1=resultReg)
code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1=resultReg, value = address)
} else if(memory!=null) {
val addressReg = vmRegisters.nextFree()
code += expressionEval.translateExpression(memory.address, addressReg)
code += VmCodeInstruction(Instruction(Opcode.LOADI, vmDt, reg1=resultReg, reg2=addressReg))
code += VmCodeInstruction(Instruction(operation, vmDt, reg1=resultReg))
code += VmCodeInstruction(Instruction(Opcode.STOREI, vmDt, reg1=resultReg, reg2=addressReg))
code += VmCodeInstruction(Opcode.LOADI, vmDt, reg1=resultReg, reg2=addressReg)
code += VmCodeInstruction(operation, vmDt, reg1=resultReg)
code += VmCodeInstruction(Opcode.STOREI, vmDt, reg1=resultReg, reg2=addressReg)
} else if (array!=null) {
TODO("postincrdecr array")
} else
@@ -300,8 +298,8 @@ class CodeGen(internal val program: PtProgram,
val repeatLabel = createLabelName()
code += VmCodeLabel(repeatLabel)
code += translateNode(repeat.statements)
code += VmCodeInstruction(Instruction(Opcode.DEC, vmDt, reg1=counterReg))
code += VmCodeInstruction(Instruction(Opcode.BNZ, vmDt, reg1=counterReg, symbol = repeatLabel))
code += VmCodeInstruction(Opcode.DEC, vmDt, reg1=counterReg)
code += VmCodeInstruction(Opcode.BNZ, vmDt, reg1=counterReg, symbol = repeatLabel)
return code
}
@@ -310,9 +308,9 @@ class CodeGen(internal val program: PtProgram,
if(jump.address!=null)
throw AssemblyError("cannot jump to memory location in the vm target")
code += if(jump.generatedLabel!=null)
VmCodeInstruction(Instruction(Opcode.JUMP, symbol = listOf(jump.generatedLabel!!)))
VmCodeInstruction(Opcode.JUMP, symbol = listOf(jump.generatedLabel!!))
else if(jump.identifier!=null)
VmCodeInstruction(Instruction(Opcode.JUMP, symbol = jump.identifier!!.targetName))
VmCodeInstruction(Opcode.JUMP, symbol = jump.identifier!!.targetName)
else
throw AssemblyError("weird jump")
return code
@@ -336,8 +334,7 @@ class CodeGen(internal val program: PtProgram,
val vmDt = vmType(assignment.value.type)
if(ident!=null) {
val address = allocations.get(ident.targetName)
val ins = Instruction(Opcode.STOREM, vmDt, reg1=resultRegister, value=address)
code += VmCodeInstruction(ins)
code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1=resultRegister, value=address)
}
else if(array!=null) {
val variable = array.variable.targetName
@@ -347,23 +344,21 @@ class CodeGen(internal val program: PtProgram,
val vmDtArrayIdx = vmType(array.type)
if(fixedIndex!=null) {
variableAddr += fixedIndex*itemsize
code += VmCodeInstruction(Instruction(Opcode.STOREM, vmDtArrayIdx, reg1 = resultRegister, value=variableAddr))
code += VmCodeInstruction(Opcode.STOREM, vmDtArrayIdx, reg1 = resultRegister, value=variableAddr)
} else {
val indexReg = vmRegisters.nextFree()
code += expressionEval.translateExpression(array.index, indexReg)
code += VmCodeInstruction(Instruction(Opcode.STOREX, vmDtArrayIdx, reg1 = resultRegister, reg2=indexReg, value=variableAddr))
code += VmCodeInstruction(Opcode.STOREX, vmDtArrayIdx, reg1 = resultRegister, reg2=indexReg, value=variableAddr)
}
}
else if(memory!=null) {
val ins =
if(memory.address is PtNumber) {
Instruction(Opcode.STOREM, vmDt, reg1=resultRegister, value=(memory.address as PtNumber).number.toInt())
} else {
val addressRegister = vmRegisters.nextFree()
code += expressionEval.translateExpression(assignment.value, addressRegister)
Instruction(Opcode.STOREI, vmDt, reg1=resultRegister, reg2=addressRegister)
}
code += VmCodeInstruction(ins)
if(memory.address is PtNumber) {
code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1=resultRegister, value=(memory.address as PtNumber).number.toInt())
} else {
val addressRegister = vmRegisters.nextFree()
code += expressionEval.translateExpression(assignment.value, addressRegister)
code += VmCodeInstruction(Opcode.STOREI, vmDt, reg1=resultRegister, reg2=addressRegister)
}
}
else
throw AssemblyError("weird assigntarget")
@@ -377,7 +372,7 @@ class CodeGen(internal val program: PtProgram,
// Call Convention: return value is always returned in r0
code += expressionEval.translateExpression(value, 0)
}
code += VmCodeInstruction(Instruction(Opcode.RETURN))
code += VmCodeInstruction(Opcode.RETURN)
return code
}
@@ -7,7 +7,6 @@ import prog8.code.core.AssemblyError
import prog8.code.core.DataType
import prog8.code.core.PassByValueDatatypes
import prog8.code.core.SignedDatatypes
import prog8.vm.Instruction
import prog8.vm.Opcode
import prog8.vm.VmDataType
@@ -21,20 +20,20 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
when (expr) {
is PtNumber -> {
code += VmCodeInstruction(Instruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=expr.number.toInt()))
code += VmCodeInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=expr.number.toInt())
}
is PtIdentifier -> {
val mem = codeGen.allocations.get(expr.targetName)
code += if(expr.type in PassByValueDatatypes) {
VmCodeInstruction(Instruction(Opcode.LOADM, vmDt, reg1=resultRegister, value=mem))
VmCodeInstruction(Opcode.LOADM, vmDt, reg1=resultRegister, value=mem)
} else {
// for strings and arrays etc., load the *address* of the value instead
VmCodeInstruction(Instruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=mem))
VmCodeInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=mem)
}
}
is PtAddressOf -> {
val mem = codeGen.allocations.get(expr.identifier.targetName)
code += VmCodeInstruction(Instruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=mem))
code += VmCodeInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=mem)
}
is PtMemoryByte -> {
val addressRegister = codeGen.vmRegisters.nextFree()
@@ -100,11 +99,11 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
code += translateExpression(arrayIx.index, idxReg)
if(eltSize>1) {
val factorReg = codeGen.vmRegisters.nextFree()
code += VmCodeInstruction(Instruction(Opcode.LOAD, VmDataType.BYTE, reg1=factorReg, value=eltSize))
code += VmCodeInstruction(Instruction(Opcode.MUL, VmDataType.BYTE, reg1=idxReg, reg2=factorReg))
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=factorReg, value=eltSize)
code += VmCodeInstruction(Opcode.MUL, VmDataType.BYTE, reg1=idxReg, reg2=factorReg)
}
val arrayLocation = codeGen.allocations.get(arrayIx.variable.targetName)
code += VmCodeInstruction(Instruction(Opcode.LOADX, vmDt, reg1=resultRegister, reg2=idxReg, value = arrayLocation))
code += VmCodeInstruction(Opcode.LOADX, vmDt, reg1=resultRegister, reg2=idxReg, value = arrayLocation)
return code
}
@@ -115,22 +114,22 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
when(expr.operator) {
"+" -> { }
"-" -> {
code += VmCodeInstruction(Instruction(Opcode.NEG, vmDt, reg1=resultRegister))
code += VmCodeInstruction(Opcode.NEG, vmDt, reg1=resultRegister)
}
"~" -> {
val regMask = codeGen.vmRegisters.nextFree()
val mask = if(vmDt==VmDataType.BYTE) 0x00ff else 0xffff
code += VmCodeInstruction(Instruction(Opcode.LOAD, vmDt, reg1=regMask, value=mask))
code += VmCodeInstruction(Instruction(Opcode.XOR, vmDt, reg1=resultRegister, reg2=resultRegister, reg3=regMask))
code += VmCodeInstruction(Opcode.LOAD, vmDt, reg1=regMask, value=mask)
code += VmCodeInstruction(Opcode.XOR, vmDt, reg1=resultRegister, reg2=resultRegister, reg3=regMask)
}
"not" -> {
val label = codeGen.createLabelName()
code += VmCodeInstruction(Instruction(Opcode.BZ, vmDt, reg1=resultRegister, symbol = label))
code += VmCodeInstruction(Instruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=1))
code += VmCodeInstruction(Opcode.BZ, vmDt, reg1=resultRegister, symbol = label)
code += VmCodeInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=1)
code += VmCodeLabel(label)
val regMask = codeGen.vmRegisters.nextFree()
code += VmCodeInstruction(Instruction(Opcode.LOAD, vmDt, reg1=regMask, value=1))
code += VmCodeInstruction(Instruction(Opcode.XOR, vmDt, reg1=resultRegister, reg2=resultRegister, reg3=regMask))
code += VmCodeInstruction(Opcode.LOAD, vmDt, reg1=regMask, value=1)
code += VmCodeInstruction(Opcode.XOR, vmDt, reg1=resultRegister, reg2=resultRegister, reg3=regMask)
}
else -> throw AssemblyError("weird prefix operator")
}
@@ -165,11 +164,11 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
when(cast.value.type) {
DataType.BYTE -> {
// byte -> uword: sign extend
code += VmCodeInstruction(Instruction(Opcode.EXTS, type = VmDataType.BYTE, reg1 = resultRegister))
code += VmCodeInstruction(Opcode.EXTS, type = VmDataType.BYTE, reg1 = resultRegister)
}
DataType.UBYTE -> {
// ubyte -> uword: sign extend
code += VmCodeInstruction(Instruction(Opcode.EXT, type = VmDataType.BYTE, reg1 = resultRegister))
code += VmCodeInstruction(Opcode.EXT, type = VmDataType.BYTE, reg1 = resultRegister)
}
DataType.WORD -> { }
DataType.FLOAT -> {
@@ -182,11 +181,11 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
when(cast.value.type) {
DataType.BYTE -> {
// byte -> word: sign extend
code += VmCodeInstruction(Instruction(Opcode.EXTS, type = VmDataType.BYTE, reg1 = resultRegister))
code += VmCodeInstruction(Opcode.EXTS, type = VmDataType.BYTE, reg1 = resultRegister)
}
DataType.UBYTE -> {
// byte -> word: sign extend
code += VmCodeInstruction(Instruction(Opcode.EXT, type = VmDataType.BYTE, reg1 = resultRegister))
code += VmCodeInstruction(Opcode.EXT, type = VmDataType.BYTE, reg1 = resultRegister)
}
DataType.UWORD -> { }
DataType.FLOAT -> {
@@ -228,57 +227,57 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
val signed = binExpr.left.type in SignedDatatypes
when(binExpr.operator) {
"+" -> {
code += VmCodeInstruction(Instruction(Opcode.ADD, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
code += VmCodeInstruction(Opcode.ADD, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
}
"-" -> {
code += VmCodeInstruction(Instruction(Opcode.SUB, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
code += VmCodeInstruction(Opcode.SUB, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
}
"*" -> {
code += VmCodeInstruction(Instruction(Opcode.MUL, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
code += VmCodeInstruction(Opcode.MUL, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
}
"/" -> {
code += VmCodeInstruction(Instruction(Opcode.DIV, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
code += VmCodeInstruction(Opcode.DIV, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
}
"%" -> {
code += VmCodeInstruction(Instruction(Opcode.MOD, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
code += VmCodeInstruction(Opcode.MOD, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
}
"|", "or" -> {
code += VmCodeInstruction(Instruction(Opcode.OR, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
code += VmCodeInstruction(Opcode.OR, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
}
"&", "and" -> {
code += VmCodeInstruction(Instruction(Opcode.AND, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
code += VmCodeInstruction(Opcode.AND, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
}
"^", "xor" -> {
code += VmCodeInstruction(Instruction(Opcode.XOR, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
code += VmCodeInstruction(Opcode.XOR, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
}
"<<" -> {
code += VmCodeInstruction(Instruction(Opcode.LSL, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
code += VmCodeInstruction(Opcode.LSL, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
}
">>" -> {
val opc = if(signed) Opcode.ASR else Opcode.LSR
code += VmCodeInstruction(Instruction(opc, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
code += VmCodeInstruction(opc, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
}
"==" -> {
code += VmCodeInstruction(Instruction(Opcode.SEQ, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
code += VmCodeInstruction(Opcode.SEQ, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
}
"!=" -> {
code += VmCodeInstruction(Instruction(Opcode.SNE, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
code += VmCodeInstruction(Opcode.SNE, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
}
"<" -> {
val ins = if(signed) Opcode.SLTS else Opcode.SLT
code += VmCodeInstruction(Instruction(ins, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
code += VmCodeInstruction(ins, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
}
">" -> {
val ins = if(signed) Opcode.SGTS else Opcode.SGT
code += VmCodeInstruction(Instruction(ins, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
code += VmCodeInstruction(ins, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
}
"<=" -> {
val ins = if(signed) Opcode.SLES else Opcode.SLE
code += VmCodeInstruction(Instruction(ins, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
code += VmCodeInstruction(ins, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
}
">=" -> {
val ins = if(signed) Opcode.SGES else Opcode.SGE
code += VmCodeInstruction(Instruction(ins, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
code += VmCodeInstruction(ins, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
}
else -> throw AssemblyError("weird operator ${binExpr.operator}")
}
@@ -293,12 +292,12 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
code += translateExpression(arg, argReg)
val vmDt = codeGen.vmType(parameter.type)
val mem = codeGen.allocations.get(fcall.functionName + parameter.name)
code += VmCodeInstruction(Instruction(Opcode.STOREM, vmDt, reg1=argReg, value=mem))
code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1=argReg, value=mem)
}
code += VmCodeInstruction(Instruction(Opcode.CALL, symbol=fcall.functionName))
code += VmCodeInstruction(Opcode.CALL, symbol=fcall.functionName)
if(!fcall.void && resultRegister!=0) {
// Call convention: result value is in r0, so put it in the required register instead. TODO does this work correctly?
code += VmCodeInstruction(Instruction(Opcode.LOADR, codeGen.vmType(fcall.type), reg1=resultRegister, reg2=0))
code += VmCodeInstruction(Opcode.LOADR, codeGen.vmType(fcall.type), reg1=resultRegister, reg2=0)
}
return code
}