mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
vm: implementing floating-point
This commit is contained in:
parent
f4993d6e5d
commit
7844ace934
@ -119,7 +119,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
|
||||
"cmp" -> funcCmp(fcall)
|
||||
"callfar" -> funcCallFar(fcall)
|
||||
"callrom" -> funcCallRom(fcall)
|
||||
"syscall", "syscall1", "syscall2", "syscall3" -> throw AssemblyError("6502 assembly target doesn't use syscall function interface")
|
||||
"syscall", "syscall1", "syscall2", "syscall3", "syscall1fp" -> throw AssemblyError("6502 assembly target doesn't use syscall function interface")
|
||||
else -> throw AssemblyError("missing asmgen for builtin func ${func.name}")
|
||||
}
|
||||
}
|
||||
|
@ -71,6 +71,19 @@ internal class VmCodeInstruction(
|
||||
val ins = Instruction(opcode, type, reg1, reg2, reg3, fpReg1, fpReg2, fpReg3, value, fpValue, symbol)
|
||||
|
||||
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(reg3!=null && (reg3<0 || reg3>65536))
|
||||
throw IllegalArgumentException("reg3 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(fpReg3!=null && (fpReg3<0 || fpReg3>65536))
|
||||
throw IllegalArgumentException("fpReg3 out of bounds")
|
||||
|
||||
if(value!=null && opcode !in OpcodesWithAddress) {
|
||||
when (type) {
|
||||
VmDataType.BYTE -> {
|
||||
|
@ -36,6 +36,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
"syscall1" -> funcSyscall1(call)
|
||||
"syscall2" -> funcSyscall2(call)
|
||||
"syscall3" -> funcSyscall3(call)
|
||||
"syscall1fp" -> funcSyscall1fp(call)
|
||||
"msb" -> funcMsb(call, resultRegister)
|
||||
"lsb" -> funcLsb(call, resultRegister)
|
||||
"memory" -> funcMemory(call, resultRegister)
|
||||
@ -60,8 +61,8 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
val code = VmCodeChunk()
|
||||
val leftRegister = codeGen.vmRegisters.nextFree()
|
||||
val rightRegister = codeGen.vmRegisters.nextFree()
|
||||
code += exprGen.translateExpression(call.args[0], leftRegister, 99999)
|
||||
code += exprGen.translateExpression(call.args[1], rightRegister, 99999)
|
||||
code += exprGen.translateExpression(call.args[0], leftRegister, -1)
|
||||
code += exprGen.translateExpression(call.args[1], rightRegister, -1)
|
||||
code += VmCodeInstruction(Opcode.CMP, codeGen.vmType(call.args[0].type), reg1=leftRegister, reg2=rightRegister)
|
||||
return code
|
||||
}
|
||||
@ -80,7 +81,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
else -> throw IllegalArgumentException("weird type")
|
||||
}
|
||||
val code = VmCodeChunk()
|
||||
code += exprGen.translateExpression(call.args[0], 0, 99999)
|
||||
code += exprGen.translateExpression(call.args[0], 0, -1)
|
||||
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
|
||||
code += VmCodeInstruction(Opcode.SYSCALL, value=syscall.ordinal)
|
||||
if(resultRegister!=0)
|
||||
@ -102,7 +103,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
else -> throw IllegalArgumentException("weird type")
|
||||
}
|
||||
val code = VmCodeChunk()
|
||||
code += exprGen.translateExpression(call.args[0], 0, 99999)
|
||||
code += exprGen.translateExpression(call.args[0], 0, -1)
|
||||
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
|
||||
code += VmCodeInstruction(Opcode.SYSCALL, value=syscall.ordinal)
|
||||
if(resultRegister!=0)
|
||||
@ -114,7 +115,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
val code = VmCodeChunk()
|
||||
val sourceDt = call.args.single().type
|
||||
if(sourceDt!=DataType.UWORD) {
|
||||
code += exprGen.translateExpression(call.args[0], resultRegister, 99999)
|
||||
code += exprGen.translateExpression(call.args[0], resultRegister, -1)
|
||||
when (sourceDt) {
|
||||
DataType.UBYTE -> {
|
||||
code += VmCodeInstruction(Opcode.EXT, VmDataType.BYTE, reg1=resultRegister)
|
||||
@ -146,14 +147,14 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
|
||||
private fun funcSgn(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
||||
val code = VmCodeChunk()
|
||||
code += exprGen.translateExpression(call.args.single(), 0, 99999)
|
||||
code += exprGen.translateExpression(call.args.single(), 0, -1)
|
||||
code += VmCodeInstruction(Opcode.SGN, codeGen.vmType(call.type), reg1=resultRegister, reg2=0)
|
||||
return code
|
||||
}
|
||||
|
||||
private fun funcSqrt16(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
||||
val code = VmCodeChunk()
|
||||
code += exprGen.translateExpression(call.args.single(), 0, 99999)
|
||||
code += exprGen.translateExpression(call.args.single(), 0, -1)
|
||||
code += VmCodeInstruction(Opcode.SQRT, VmDataType.WORD, reg1=resultRegister, reg2=0)
|
||||
return code
|
||||
}
|
||||
@ -174,14 +175,14 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
|
||||
private fun funcPush(call: PtBuiltinFunctionCall): VmCodeChunk {
|
||||
val code = VmCodeChunk()
|
||||
code += exprGen.translateExpression(call.args.single(), 0, 99999)
|
||||
code += exprGen.translateExpression(call.args.single(), 0, -1)
|
||||
code += VmCodeInstruction(Opcode.PUSH, VmDataType.BYTE, reg1=0)
|
||||
return code
|
||||
}
|
||||
|
||||
private fun funcPushw(call: PtBuiltinFunctionCall): VmCodeChunk {
|
||||
val code = VmCodeChunk()
|
||||
code += exprGen.translateExpression(call.args.single(), 0, 99999)
|
||||
code += exprGen.translateExpression(call.args.single(), 0, -1)
|
||||
code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1=0)
|
||||
return code
|
||||
}
|
||||
@ -192,8 +193,8 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
val leftReg = codeGen.vmRegisters.nextFree()
|
||||
val rightReg = codeGen.vmRegisters.nextFree()
|
||||
val code = VmCodeChunk()
|
||||
code += exprGen.translateExpression(left, leftReg, 99999)
|
||||
code += exprGen.translateExpression(right, rightReg, 99999)
|
||||
code += exprGen.translateExpression(left, leftReg, -1)
|
||||
code += exprGen.translateExpression(right, rightReg, -1)
|
||||
code += assignRegisterTo(left, rightReg)
|
||||
code += assignRegisterTo(right, leftReg)
|
||||
return code
|
||||
@ -210,7 +211,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
else -> throw IllegalArgumentException("weird type to reverse")
|
||||
}
|
||||
val code = VmCodeChunk()
|
||||
code += exprGen.translateExpression(call.args[0], 0, 99999)
|
||||
code += exprGen.translateExpression(call.args[0], 0, -1)
|
||||
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
|
||||
code += VmCodeInstruction(Opcode.SYSCALL, value=sortSyscall.ordinal)
|
||||
return code
|
||||
@ -230,7 +231,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
else -> throw IllegalArgumentException("weird type to sort")
|
||||
}
|
||||
val code = VmCodeChunk()
|
||||
code += exprGen.translateExpression(call.args[0], 0, 99999)
|
||||
code += exprGen.translateExpression(call.args[0], 0, -1)
|
||||
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
|
||||
code += VmCodeInstruction(Opcode.SYSCALL, value=sortSyscall.ordinal)
|
||||
return code
|
||||
@ -240,8 +241,8 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
val msbReg = codeGen.vmRegisters.nextFree()
|
||||
val lsbReg = codeGen.vmRegisters.nextFree()
|
||||
val code = VmCodeChunk()
|
||||
code += exprGen.translateExpression(call.args[0], msbReg, 99999)
|
||||
code += exprGen.translateExpression(call.args[1], lsbReg, 99999)
|
||||
code += exprGen.translateExpression(call.args[0], msbReg, -1)
|
||||
code += exprGen.translateExpression(call.args[1], lsbReg, -1)
|
||||
code += VmCodeInstruction(Opcode.CONCAT, VmDataType.BYTE, reg1=resultRegister, reg2=msbReg, reg3=lsbReg)
|
||||
return code
|
||||
}
|
||||
@ -251,12 +252,12 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
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, 99999)
|
||||
code += exprGen.translateExpression(call.args[1], valueReg, -1)
|
||||
code += VmCodeInstruction(Opcode.STOREM, VmDataType.WORD, reg1 = valueReg, value=address)
|
||||
} else {
|
||||
val addressReg = codeGen.vmRegisters.nextFree()
|
||||
code += exprGen.translateExpression(call.args[0], addressReg, 99999)
|
||||
code += exprGen.translateExpression(call.args[1], valueReg, 99999)
|
||||
code += exprGen.translateExpression(call.args[0], addressReg, -1)
|
||||
code += exprGen.translateExpression(call.args[1], valueReg, -1)
|
||||
code += VmCodeInstruction(Opcode.STOREI, VmDataType.WORD, reg1 = valueReg, reg2 = addressReg)
|
||||
}
|
||||
return code
|
||||
@ -267,12 +268,12 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
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, 99999)
|
||||
code += exprGen.translateExpression(call.args[1], valueReg, -1)
|
||||
code += VmCodeInstruction(Opcode.STOREM, VmDataType.BYTE, reg1 = valueReg, value=address)
|
||||
} else {
|
||||
val addressReg = codeGen.vmRegisters.nextFree()
|
||||
code += exprGen.translateExpression(call.args[0], addressReg, 99999)
|
||||
code += exprGen.translateExpression(call.args[1], valueReg, 99999)
|
||||
code += exprGen.translateExpression(call.args[0], addressReg, -1)
|
||||
code += exprGen.translateExpression(call.args[1], valueReg, -1)
|
||||
code += VmCodeInstruction(Opcode.STOREI, VmDataType.BYTE, reg1 = valueReg, reg2 = addressReg)
|
||||
}
|
||||
return code
|
||||
@ -285,7 +286,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
code += VmCodeInstruction(Opcode.LOADM, VmDataType.WORD, reg1 = resultRegister, value = address)
|
||||
} else {
|
||||
val addressReg = codeGen.vmRegisters.nextFree()
|
||||
code += exprGen.translateExpression(call.args.single(), addressReg, 99999)
|
||||
code += exprGen.translateExpression(call.args.single(), addressReg, -1)
|
||||
code += VmCodeInstruction(Opcode.LOADI, VmDataType.WORD, reg1 = resultRegister, reg2 = addressReg)
|
||||
}
|
||||
return code
|
||||
@ -298,7 +299,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
code += VmCodeInstruction(Opcode.LOADM, VmDataType.BYTE, reg1 = resultRegister, value = address)
|
||||
} else {
|
||||
val addressReg = codeGen.vmRegisters.nextFree()
|
||||
code += exprGen.translateExpression(call.args.single(), addressReg, 99999)
|
||||
code += exprGen.translateExpression(call.args.single(), addressReg, -1)
|
||||
code += VmCodeInstruction(Opcode.LOADI, VmDataType.BYTE, reg1 = resultRegister, reg2 = addressReg)
|
||||
}
|
||||
return code
|
||||
@ -336,14 +337,14 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
|
||||
private fun funcLsb(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
||||
val code = VmCodeChunk()
|
||||
code += exprGen.translateExpression(call.args.single(), resultRegister, 99999)
|
||||
code += exprGen.translateExpression(call.args.single(), resultRegister, -1)
|
||||
// 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
|
||||
}
|
||||
|
||||
private fun funcMsb(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
||||
val code = VmCodeChunk()
|
||||
code += exprGen.translateExpression(call.args.single(), resultRegister, 99999)
|
||||
code += exprGen.translateExpression(call.args.single(), resultRegister, -1)
|
||||
code += VmCodeInstruction(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
|
||||
@ -359,7 +360,15 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
private fun funcSyscall1(call: PtBuiltinFunctionCall): VmCodeChunk {
|
||||
val code = VmCodeChunk()
|
||||
val callNr = (call.args[0] as PtNumber).number.toInt()
|
||||
code += exprGen.translateExpression(call.args[1], 0, 99999)
|
||||
code += exprGen.translateExpression(call.args[1], 0, -1)
|
||||
code += VmCodeInstruction(Opcode.SYSCALL, value=callNr)
|
||||
return code
|
||||
}
|
||||
|
||||
private fun funcSyscall1fp(call: PtBuiltinFunctionCall): VmCodeChunk {
|
||||
val code = VmCodeChunk()
|
||||
val callNr = (call.args[0] as PtNumber).number.toInt()
|
||||
code += exprGen.translateExpression(call.args[1], -1, 0)
|
||||
code += VmCodeInstruction(Opcode.SYSCALL, value=callNr)
|
||||
return code
|
||||
}
|
||||
@ -371,8 +380,8 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
codeGen.vmRegisters.nextFree()
|
||||
}
|
||||
val callNr = (call.args[0] as PtNumber).number.toInt()
|
||||
code += exprGen.translateExpression(call.args[1], 0, 99999)
|
||||
code += exprGen.translateExpression(call.args[2], 1, 99999)
|
||||
code += exprGen.translateExpression(call.args[1], 0, -1)
|
||||
code += exprGen.translateExpression(call.args[2], 1, -1)
|
||||
code += VmCodeInstruction(Opcode.SYSCALL, value=callNr)
|
||||
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 1)
|
||||
return code
|
||||
@ -386,9 +395,9 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
codeGen.vmRegisters.nextFree()
|
||||
}
|
||||
val callNr = (call.args[0] as PtNumber).number.toInt()
|
||||
code += exprGen.translateExpression(call.args[1], 0, 99999)
|
||||
code += exprGen.translateExpression(call.args[2], 1, 99999)
|
||||
code += exprGen.translateExpression(call.args[3], 2, 99999)
|
||||
code += exprGen.translateExpression(call.args[1], 0, -1)
|
||||
code += exprGen.translateExpression(call.args[2], 1, -1)
|
||||
code += exprGen.translateExpression(call.args[3], 2, -1)
|
||||
code += VmCodeInstruction(Opcode.SYSCALL, value=callNr)
|
||||
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 2)
|
||||
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 1)
|
||||
@ -398,7 +407,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
||||
private fun funcRolRor2(opcode: Opcode, call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
||||
val vmDt = codeGen.vmType(call.args[0].type)
|
||||
val code = VmCodeChunk()
|
||||
code += exprGen.translateExpression(call.args[0], resultRegister, 99999)
|
||||
code += exprGen.translateExpression(call.args[0], resultRegister, -1)
|
||||
code += VmCodeInstruction(opcode, vmDt, reg1=resultRegister)
|
||||
code += assignRegisterTo(call.args[0], resultRegister)
|
||||
return code
|
||||
|
@ -78,7 +78,7 @@ class CodeGen(internal val program: PtProgram,
|
||||
is PtAssignment -> translate(node)
|
||||
is PtNodeGroup -> translateGroup(node.children)
|
||||
is PtBuiltinFunctionCall -> translateBuiltinFunc(node, 0)
|
||||
is PtFunctionCall -> expressionEval.translate(node, 0)
|
||||
is PtFunctionCall -> expressionEval.translate(node, 0, 0)
|
||||
is PtNop -> VmCodeChunk()
|
||||
is PtReturn -> translate(node)
|
||||
is PtJump -> translate(node)
|
||||
@ -151,7 +151,7 @@ class CodeGen(internal val program: PtProgram,
|
||||
val valueReg = vmRegisters.nextFree()
|
||||
val choiceReg = vmRegisters.nextFree()
|
||||
val valueDt = vmType(whenStmt.value.type)
|
||||
code += expressionEval.translateExpression(whenStmt.value, valueReg, 99999)
|
||||
code += expressionEval.translateExpression(whenStmt.value, valueReg, -1)
|
||||
val choices = whenStmt.choices.children.map {it as PtWhenChoice }
|
||||
val endLabel = createLabelName()
|
||||
for (choice in choices) {
|
||||
@ -249,8 +249,8 @@ class CodeGen(internal val program: PtProgram,
|
||||
val loopLabel = createLabelName()
|
||||
val code = VmCodeChunk()
|
||||
|
||||
code += expressionEval.translateExpression(iterable.to, endvalueReg, 99999)
|
||||
code += expressionEval.translateExpression(iterable.from, indexReg, 99999)
|
||||
code += expressionEval.translateExpression(iterable.to, endvalueReg, -1)
|
||||
code += expressionEval.translateExpression(iterable.from, indexReg, -1)
|
||||
code += VmCodeInstruction(Opcode.STOREM, loopvarDt, reg1=indexReg, value=loopvarAddress)
|
||||
code += VmCodeLabel(loopLabel)
|
||||
code += translateNode(forLoop.statements)
|
||||
@ -458,7 +458,7 @@ class CodeGen(internal val program: PtProgram,
|
||||
val conditionReg = vmRegisters.nextFree()
|
||||
val vmDt = vmType(condition.type)
|
||||
val code = VmCodeChunk()
|
||||
code += expressionEval.translateExpression(condition, conditionReg, 99999)
|
||||
code += expressionEval.translateExpression(condition, conditionReg, -1)
|
||||
if(ifElse.elseScope.children.isNotEmpty()) {
|
||||
// if and else parts
|
||||
val elseLabel = createLabelName()
|
||||
@ -504,7 +504,7 @@ class CodeGen(internal val program: PtProgram,
|
||||
code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1 = resultReg, value=address)
|
||||
} else {
|
||||
val addressReg = vmRegisters.nextFree()
|
||||
code += expressionEval.translateExpression(memory.address, addressReg, 99999)
|
||||
code += expressionEval.translateExpression(memory.address, addressReg, -1)
|
||||
code += VmCodeInstruction(Opcode.LOADI, vmDt, reg1 = resultReg, reg2 = addressReg)
|
||||
code += VmCodeInstruction(operation, vmDt, reg1 = resultReg)
|
||||
code += VmCodeInstruction(Opcode.STOREI, vmDt, reg1 = resultReg, reg2 = addressReg)
|
||||
@ -524,7 +524,7 @@ class CodeGen(internal val program: PtProgram,
|
||||
code += VmCodeInstruction(memOp, vmDt, value=variableAddr)
|
||||
} else {
|
||||
val indexReg = vmRegisters.nextFree()
|
||||
code += expressionEval.translateExpression(array.index, indexReg, 99999)
|
||||
code += expressionEval.translateExpression(array.index, indexReg, -1)
|
||||
code += VmCodeInstruction(Opcode.LOADX, vmDt, reg1=resultReg, reg2=indexReg, value=variableAddr)
|
||||
code += VmCodeInstruction(operation, vmDt, reg1=resultReg)
|
||||
code += VmCodeInstruction(Opcode.STOREX, vmDt, reg1=resultReg, reg2=indexReg, value=variableAddr)
|
||||
@ -548,7 +548,7 @@ class CodeGen(internal val program: PtProgram,
|
||||
val code = VmCodeChunk()
|
||||
val counterReg = vmRegisters.nextFree()
|
||||
val vmDt = vmType(repeat.count.type)
|
||||
code += expressionEval.translateExpression(repeat.count, counterReg, 99999)
|
||||
code += expressionEval.translateExpression(repeat.count, counterReg, -1)
|
||||
val repeatLabel = createLabelName()
|
||||
code += VmCodeLabel(repeatLabel)
|
||||
code += translateNode(repeat.statements)
|
||||
@ -582,20 +582,30 @@ class CodeGen(internal val program: PtProgram,
|
||||
if(assignment.target.children.single() is PtMachineRegister)
|
||||
throw AssemblyError("assigning to a register should be done by just evaluating the expression into resultregister")
|
||||
val code = VmCodeChunk()
|
||||
val resultRegister = if(assignment.value is PtMachineRegister) {
|
||||
(assignment.value as PtMachineRegister).register
|
||||
} else {
|
||||
val reg = vmRegisters.nextFree()
|
||||
code += expressionEval.translateExpression(assignment.value, reg, 99999)
|
||||
reg
|
||||
}
|
||||
val ident = assignment.target.identifier
|
||||
val memory = assignment.target.memory
|
||||
val array = assignment.target.array
|
||||
val vmDt = vmType(assignment.value.type)
|
||||
var resultRegister = -1
|
||||
var resultFpRegister = -1
|
||||
if(vmDt==VmDataType.FLOAT) {
|
||||
resultFpRegister = vmRegisters.nextFreeFloat()
|
||||
code += expressionEval.translateExpression(assignment.value, -1, resultFpRegister)
|
||||
} else {
|
||||
resultRegister = if (assignment.value is PtMachineRegister) {
|
||||
(assignment.value as PtMachineRegister).register
|
||||
} else {
|
||||
val reg = vmRegisters.nextFree()
|
||||
code += expressionEval.translateExpression(assignment.value, reg, -1)
|
||||
reg
|
||||
}
|
||||
}
|
||||
if(ident!=null) {
|
||||
val address = allocations.get(ident.targetName)
|
||||
code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1=resultRegister, value=address)
|
||||
code += if(vmDt==VmDataType.FLOAT)
|
||||
VmCodeInstruction(Opcode.STOREM, vmDt, fpReg1=resultFpRegister, value=address)
|
||||
else
|
||||
VmCodeInstruction(Opcode.STOREM, vmDt, reg1=resultRegister, value=address)
|
||||
}
|
||||
else if(array!=null) {
|
||||
val variable = array.variable.targetName
|
||||
@ -608,7 +618,7 @@ class CodeGen(internal val program: PtProgram,
|
||||
code += VmCodeInstruction(Opcode.STOREM, vmDtArrayIdx, reg1 = resultRegister, value=variableAddr)
|
||||
} else {
|
||||
val indexReg = vmRegisters.nextFree()
|
||||
code += expressionEval.translateExpression(array.index, indexReg, 99999)
|
||||
code += expressionEval.translateExpression(array.index, indexReg, -1)
|
||||
code += VmCodeInstruction(Opcode.STOREX, vmDtArrayIdx, reg1 = resultRegister, reg2=indexReg, value=variableAddr)
|
||||
}
|
||||
}
|
||||
@ -618,7 +628,7 @@ class CodeGen(internal val program: PtProgram,
|
||||
code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1=resultRegister, value=(memory.address as PtNumber).number.toInt())
|
||||
} else {
|
||||
val addressReg = vmRegisters.nextFree()
|
||||
code += expressionEval.translateExpression(memory.address, addressReg, 99999)
|
||||
code += expressionEval.translateExpression(memory.address, addressReg, -1)
|
||||
code += VmCodeInstruction(Opcode.STOREI, vmDt, reg1=resultRegister, reg2=addressReg)
|
||||
}
|
||||
}
|
||||
@ -631,8 +641,11 @@ class CodeGen(internal val program: PtProgram,
|
||||
val code = VmCodeChunk()
|
||||
val value = ret.value
|
||||
if(value!=null) {
|
||||
// Call Convention: return value is always returned in r0
|
||||
code += expressionEval.translateExpression(value, 0, 99999)
|
||||
// Call Convention: return value is always returned in r0 (or fr0 if float)
|
||||
code += if(value.type==DataType.FLOAT)
|
||||
expressionEval.translateExpression(value, -1, 0)
|
||||
else
|
||||
expressionEval.translateExpression(value, 0, -1)
|
||||
}
|
||||
code += VmCodeInstruction(Opcode.RETURN)
|
||||
return code
|
||||
|
@ -26,13 +26,19 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
}
|
||||
is PtNumber -> {
|
||||
val vmDt = codeGen.vmType(expr.type)
|
||||
code += VmCodeInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=expr.number.toInt())
|
||||
code += if(vmDt==VmDataType.FLOAT)
|
||||
VmCodeInstruction(Opcode.LOAD, vmDt, fpReg1 = resultFpRegister, fpValue = expr.number.toFloat())
|
||||
else
|
||||
VmCodeInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=expr.number.toInt())
|
||||
}
|
||||
is PtIdentifier -> {
|
||||
val vmDt = codeGen.vmType(expr.type)
|
||||
val mem = codeGen.allocations.get(expr.targetName)
|
||||
code += if (expr.type in PassByValueDatatypes) {
|
||||
VmCodeInstruction(Opcode.LOADM, vmDt, reg1 = resultRegister, value = mem)
|
||||
if(vmDt==VmDataType.FLOAT)
|
||||
VmCodeInstruction(Opcode.LOADM, vmDt, fpReg1 = resultFpRegister, value = mem)
|
||||
else
|
||||
VmCodeInstruction(Opcode.LOADM, vmDt, reg1 = resultRegister, value = mem)
|
||||
} else {
|
||||
// for strings and arrays etc., load the *address* of the value instead
|
||||
VmCodeInstruction(Opcode.LOAD, vmDt, reg1 = resultRegister, value = mem)
|
||||
@ -49,7 +55,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
code += VmCodeInstruction(Opcode.LOADM, VmDataType.BYTE, reg1=resultRegister, value = address)
|
||||
} else {
|
||||
val addressRegister = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(expr.address, addressRegister, 99999)
|
||||
code += translateExpression(expr.address, addressRegister, -1)
|
||||
code += VmCodeInstruction(Opcode.LOADI, VmDataType.BYTE, reg1=resultRegister, reg2=addressRegister)
|
||||
}
|
||||
}
|
||||
@ -58,8 +64,8 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
is PtArrayIndexer -> code += translate(expr, resultRegister)
|
||||
is PtBinaryExpression -> code += translate(expr, resultRegister)
|
||||
is PtBuiltinFunctionCall -> code += codeGen.translateBuiltinFunc(expr, resultRegister)
|
||||
is PtFunctionCall -> code += translate(expr, resultRegister)
|
||||
is PtContainmentCheck -> code += translate(expr, resultRegister)
|
||||
is PtFunctionCall -> code += translate(expr, resultRegister, resultFpRegister)
|
||||
is PtContainmentCheck -> code += translate(expr, resultRegister, resultFpRegister)
|
||||
is PtPipe -> code += translate(expr, resultRegister)
|
||||
is PtRange,
|
||||
is PtArray,
|
||||
@ -91,7 +97,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
}
|
||||
|
||||
val code = VmCodeChunk()
|
||||
code += translateExpression(segments[0], valueReg, 99999)
|
||||
code += translateExpression(segments[0], valueReg, -1)
|
||||
for (segment in segments.subList(1, segments.size-1)) {
|
||||
val sourceReg = valueReg
|
||||
val sourceDt = valueDt
|
||||
@ -100,37 +106,37 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
valueReg = codeGen.vmRegisters.nextFree()
|
||||
}
|
||||
val segmentWithImplicitArgument = addImplicitArgToSegment(segment, sourceReg, sourceDt)
|
||||
code += translateExpression(segmentWithImplicitArgument, valueReg, 99999)
|
||||
code += translateExpression(segmentWithImplicitArgument, valueReg, -1)
|
||||
}
|
||||
val segWithArg = addImplicitArgToSegment(segments.last(), valueReg, valueDt)
|
||||
code += translateExpression(segWithArg, resultRegister, 99999)
|
||||
code += translateExpression(segWithArg, resultRegister, -1)
|
||||
return code
|
||||
}
|
||||
|
||||
private fun translate(check: PtContainmentCheck, resultRegister: Int): VmCodeChunk {
|
||||
private fun translate(check: PtContainmentCheck, resultRegister: Int, resultFpRegister: Int): VmCodeChunk {
|
||||
val code = VmCodeChunk()
|
||||
code += translateExpression(check.element, resultRegister, 99999) // load the element to check in resultRegister
|
||||
code += translateExpression(check.element, resultRegister, -1) // load the element to check in resultRegister
|
||||
val iterable = codeGen.symbolTable.flat.getValue(check.iterable.targetName) as StStaticVariable
|
||||
when(iterable.dt) {
|
||||
DataType.STR -> {
|
||||
val call = PtFunctionCall(listOf("prog8_lib", "string_contains"), false, DataType.UBYTE, check.position)
|
||||
call.children.add(check.element)
|
||||
call.children.add(check.iterable)
|
||||
code += translate(call, resultRegister)
|
||||
code += translate(call, resultRegister, resultFpRegister)
|
||||
}
|
||||
DataType.ARRAY_UB, DataType.ARRAY_B -> {
|
||||
val call = PtFunctionCall(listOf("prog8_lib", "bytearray_contains"), false, DataType.UBYTE, check.position)
|
||||
call.children.add(check.element)
|
||||
call.children.add(check.iterable)
|
||||
call.children.add(PtNumber(DataType.UBYTE, iterable.length!!.toDouble(), iterable.position))
|
||||
code += translate(call, resultRegister)
|
||||
code += translate(call, resultRegister, resultFpRegister)
|
||||
}
|
||||
DataType.ARRAY_UW, DataType.ARRAY_W -> {
|
||||
val call = PtFunctionCall(listOf("prog8_lib", "wordarray_contains"), false, DataType.UBYTE, check.position)
|
||||
call.children.add(check.element)
|
||||
call.children.add(check.iterable)
|
||||
call.children.add(PtNumber(DataType.UBYTE, iterable.length!!.toDouble(), iterable.position))
|
||||
code += translate(call, resultRegister)
|
||||
code += translate(call, resultRegister, resultFpRegister)
|
||||
}
|
||||
DataType.ARRAY_F -> TODO("containment check in float-array")
|
||||
else -> throw AssemblyError("weird iterable dt ${iterable.dt} for ${check.iterable.targetName}")
|
||||
@ -149,7 +155,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
val memOffset = (arrayIx.index as PtNumber).number.toInt() * eltSize
|
||||
code += VmCodeInstruction(Opcode.LOADM, vmDt, reg1=resultRegister, value=arrayLocation+memOffset)
|
||||
} else {
|
||||
code += translateExpression(arrayIx.index, idxReg, 99999)
|
||||
code += translateExpression(arrayIx.index, idxReg, -1)
|
||||
if(eltSize>1)
|
||||
code += codeGen.multiplyByConst(VmDataType.BYTE, idxReg, eltSize)
|
||||
code += VmCodeInstruction(Opcode.LOADX, vmDt, reg1=resultRegister, reg2=idxReg, value = arrayLocation)
|
||||
@ -159,7 +165,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
|
||||
private fun translate(expr: PtPrefix, resultRegister: Int): VmCodeChunk {
|
||||
val code = VmCodeChunk()
|
||||
code += translateExpression(expr.value, resultRegister, 99999)
|
||||
code += translateExpression(expr.value, resultRegister, -1)
|
||||
val vmDt = codeGen.vmType(expr.type)
|
||||
when(expr.operator) {
|
||||
"+" -> { }
|
||||
@ -190,7 +196,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
val code = VmCodeChunk()
|
||||
if(cast.type==cast.value.type)
|
||||
return code
|
||||
code += translateExpression(cast.value, resultRegister, 99999)
|
||||
code += translateExpression(cast.value, resultRegister, -1)
|
||||
when(cast.type) {
|
||||
DataType.UBYTE -> {
|
||||
when(cast.value.type) {
|
||||
@ -297,8 +303,8 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
val code = VmCodeChunk()
|
||||
val leftResultReg = codeGen.vmRegisters.nextFree()
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, leftResultReg, 99999)
|
||||
code += translateExpression(binExpr.right, rightResultReg, 99999)
|
||||
code += translateExpression(binExpr.left, leftResultReg, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
val ins = if(signed) {
|
||||
if(greaterEquals) Opcode.SGES else Opcode.SGTS
|
||||
} else {
|
||||
@ -318,8 +324,8 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
val code = VmCodeChunk()
|
||||
val leftResultReg = codeGen.vmRegisters.nextFree()
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, leftResultReg, 99999)
|
||||
code += translateExpression(binExpr.right, rightResultReg, 99999)
|
||||
code += translateExpression(binExpr.left, leftResultReg, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
val ins = if(signed) {
|
||||
if(lessEquals) Opcode.SLES else Opcode.SLTS
|
||||
} else {
|
||||
@ -333,8 +339,8 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
val code = VmCodeChunk()
|
||||
val leftResultReg = codeGen.vmRegisters.nextFree()
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, leftResultReg, 99999)
|
||||
code += translateExpression(binExpr.right, rightResultReg, 99999)
|
||||
code += translateExpression(binExpr.left, leftResultReg, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
val opcode = if(notEquals) Opcode.SNE else Opcode.SEQ
|
||||
code += VmCodeInstruction(opcode, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
||||
return code
|
||||
@ -344,8 +350,8 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
val code = VmCodeChunk()
|
||||
val leftResultReg = codeGen.vmRegisters.nextFree()
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, leftResultReg, 99999)
|
||||
code += translateExpression(binExpr.right, rightResultReg, 99999)
|
||||
code += translateExpression(binExpr.left, leftResultReg, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
val opc = if(signed) Opcode.ASRX else Opcode.LSRX
|
||||
code += VmCodeInstruction(opc, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
||||
return code
|
||||
@ -355,8 +361,8 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
val code = VmCodeChunk()
|
||||
val leftResultReg = codeGen.vmRegisters.nextFree()
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, leftResultReg, 99999)
|
||||
code += translateExpression(binExpr.right, rightResultReg, 99999)
|
||||
code += translateExpression(binExpr.left, leftResultReg, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += VmCodeInstruction(Opcode.LSLX, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
||||
return code
|
||||
}
|
||||
@ -365,8 +371,8 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
val code = VmCodeChunk()
|
||||
val leftResultReg = codeGen.vmRegisters.nextFree()
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, leftResultReg, 99999)
|
||||
code += translateExpression(binExpr.right, rightResultReg, 99999)
|
||||
code += translateExpression(binExpr.left, leftResultReg, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += VmCodeInstruction(Opcode.XOR, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
||||
return code
|
||||
}
|
||||
@ -375,8 +381,8 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
val code = VmCodeChunk()
|
||||
val leftResultReg = codeGen.vmRegisters.nextFree()
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, leftResultReg, 99999)
|
||||
code += translateExpression(binExpr.right, rightResultReg, 99999)
|
||||
code += translateExpression(binExpr.left, leftResultReg, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += VmCodeInstruction(Opcode.AND, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
||||
return code
|
||||
}
|
||||
@ -385,8 +391,8 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
val code = VmCodeChunk()
|
||||
val leftResultReg = codeGen.vmRegisters.nextFree()
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, leftResultReg, 99999)
|
||||
code += translateExpression(binExpr.right, rightResultReg, 99999)
|
||||
code += translateExpression(binExpr.left, leftResultReg, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += VmCodeInstruction(Opcode.OR, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
||||
return code
|
||||
}
|
||||
@ -395,8 +401,8 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
val code = VmCodeChunk()
|
||||
val leftResultReg = codeGen.vmRegisters.nextFree()
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, leftResultReg, 99999)
|
||||
code += translateExpression(binExpr.right, rightResultReg, 99999)
|
||||
code += translateExpression(binExpr.left, leftResultReg, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += VmCodeInstruction(Opcode.MOD, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
||||
return code
|
||||
}
|
||||
@ -405,14 +411,14 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
val code = VmCodeChunk()
|
||||
val constFactorRight = binExpr.right as? PtNumber
|
||||
if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) {
|
||||
code += translateExpression(binExpr.left, resultRegister, 99999)
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
val factor = constFactorRight.number.toInt()
|
||||
code += codeGen.divideByConst(vmDt, resultRegister, factor)
|
||||
} else {
|
||||
val leftResultReg = codeGen.vmRegisters.nextFree()
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, leftResultReg, 99999)
|
||||
code += translateExpression(binExpr.right, rightResultReg, 99999)
|
||||
code += translateExpression(binExpr.left, leftResultReg, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += VmCodeInstruction(Opcode.DIV, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
||||
}
|
||||
return code
|
||||
@ -423,18 +429,18 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
val constFactorLeft = binExpr.left as? PtNumber
|
||||
val constFactorRight = binExpr.right as? PtNumber
|
||||
if(constFactorLeft!=null && constFactorLeft.type!=DataType.FLOAT) {
|
||||
code += translateExpression(binExpr.right, resultRegister, 99999)
|
||||
code += translateExpression(binExpr.right, resultRegister, -1)
|
||||
val factor = constFactorLeft.number.toInt()
|
||||
code += codeGen.multiplyByConst(vmDt, resultRegister, factor)
|
||||
} else if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) {
|
||||
code += translateExpression(binExpr.left, resultRegister, 99999)
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
val factor = constFactorRight.number.toInt()
|
||||
code += codeGen.multiplyByConst(vmDt, resultRegister, factor)
|
||||
} else {
|
||||
val leftResultReg = codeGen.vmRegisters.nextFree()
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, leftResultReg, 99999)
|
||||
code += translateExpression(binExpr.right, rightResultReg, 99999)
|
||||
code += translateExpression(binExpr.left, leftResultReg, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += VmCodeInstruction(Opcode.MUL, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
||||
}
|
||||
return code
|
||||
@ -443,14 +449,14 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
private fun operatorMinus(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
|
||||
val code = VmCodeChunk()
|
||||
if((binExpr.right as? PtNumber)?.number==1.0) {
|
||||
code += translateExpression(binExpr.left, resultRegister, 99999)
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += VmCodeInstruction(Opcode.DEC, vmDt, reg1=resultRegister)
|
||||
}
|
||||
else {
|
||||
val leftResultReg = codeGen.vmRegisters.nextFree()
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, leftResultReg, 99999)
|
||||
code += translateExpression(binExpr.right, rightResultReg, 99999)
|
||||
code += translateExpression(binExpr.left, leftResultReg, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += VmCodeInstruction(Opcode.SUB, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
||||
}
|
||||
return code
|
||||
@ -459,37 +465,51 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
private fun operatorPlus(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
|
||||
val code = VmCodeChunk()
|
||||
if((binExpr.left as? PtNumber)?.number==1.0) {
|
||||
code += translateExpression(binExpr.right, resultRegister, 99999)
|
||||
code += translateExpression(binExpr.right, resultRegister, -1)
|
||||
code += VmCodeInstruction(Opcode.INC, vmDt, reg1=resultRegister)
|
||||
}
|
||||
else if((binExpr.right as? PtNumber)?.number==1.0) {
|
||||
code += translateExpression(binExpr.left, resultRegister, 99999)
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += VmCodeInstruction(Opcode.INC, vmDt, reg1=resultRegister)
|
||||
}
|
||||
else {
|
||||
val leftResultReg = codeGen.vmRegisters.nextFree()
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, leftResultReg, 99999)
|
||||
code += translateExpression(binExpr.right, rightResultReg, 99999)
|
||||
code += translateExpression(binExpr.left, leftResultReg, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
code += VmCodeInstruction(Opcode.ADD, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
||||
fun translate(fcall: PtFunctionCall, resultRegister: Int): VmCodeChunk {
|
||||
fun translate(fcall: PtFunctionCall, resultRegister: Int, resultFpRegister: Int): VmCodeChunk {
|
||||
val subroutine = codeGen.symbolTable.flat.getValue(fcall.functionName) as StSub
|
||||
val code = VmCodeChunk()
|
||||
for ((arg, parameter) in fcall.args.zip(subroutine.parameters)) {
|
||||
val argReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(arg, argReg, 99999)
|
||||
val vmDt = codeGen.vmType(parameter.type)
|
||||
val mem = codeGen.allocations.get(fcall.functionName + parameter.name)
|
||||
code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1=argReg, value=mem)
|
||||
val paramDt = codeGen.vmType(parameter.type)
|
||||
if(paramDt==VmDataType.FLOAT) {
|
||||
val argFpReg = codeGen.vmRegisters.nextFreeFloat()
|
||||
code += translateExpression(arg, -1, argFpReg)
|
||||
val mem = codeGen.allocations.get(fcall.functionName + parameter.name)
|
||||
code += VmCodeInstruction(Opcode.STOREM, paramDt, fpReg1 = argFpReg, value = mem)
|
||||
} else {
|
||||
val argReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(arg, argReg, -1)
|
||||
val mem = codeGen.allocations.get(fcall.functionName + parameter.name)
|
||||
code += VmCodeInstruction(Opcode.STOREM, paramDt, reg1 = argReg, value = mem)
|
||||
}
|
||||
}
|
||||
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.
|
||||
code += VmCodeInstruction(Opcode.LOADR, codeGen.vmType(fcall.type), reg1=resultRegister, reg2=0)
|
||||
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 += VmCodeInstruction(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 += VmCodeInstruction(Opcode.LOADR, codeGen.vmType(fcall.type), reg1 = resultRegister, reg2 = 0)
|
||||
}
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ class VariableAllocator(private val st: SymbolTable, private val program: PtProg
|
||||
}
|
||||
else -> throw InternalCompilerException("weird dt")
|
||||
}
|
||||
mm.add(Pair(variable.scopedName, "${location.toHex()} $typeStr $value"))
|
||||
mm.add(Pair(variable.scopedName, "$location $typeStr $value"))
|
||||
}
|
||||
return mm
|
||||
}
|
||||
|
@ -11,84 +11,84 @@ floats {
|
||||
|
||||
sub print_f(float value) {
|
||||
; ---- prints the floating point value (without a newline).
|
||||
; TODO
|
||||
void syscall1fp(sys.SC_PRINTF, value)
|
||||
}
|
||||
|
||||
sub pow(float value, float power) -> float {
|
||||
; TODO
|
||||
return 0.0
|
||||
return -42.42
|
||||
}
|
||||
|
||||
sub fabs(float value) -> float {
|
||||
; TODO
|
||||
return 0.0
|
||||
return -42.42
|
||||
}
|
||||
|
||||
sub sin(float angle) -> float {
|
||||
; TODO
|
||||
return 0.0
|
||||
return -42.42
|
||||
}
|
||||
|
||||
sub cos(float angle) -> float {
|
||||
; TODO
|
||||
return 0.0
|
||||
return -42.42
|
||||
}
|
||||
|
||||
sub tan(float value) -> float {
|
||||
; TODO
|
||||
return 0.0
|
||||
return -42.42
|
||||
}
|
||||
|
||||
sub atan(float value) -> float {
|
||||
; TODO
|
||||
return 0.0
|
||||
return -42.42
|
||||
}
|
||||
|
||||
sub ln(float value) -> float {
|
||||
; TODO
|
||||
return 0.0
|
||||
return -42.42
|
||||
}
|
||||
|
||||
sub log2(float value) -> float {
|
||||
; TODO
|
||||
return 0.0
|
||||
return -42.42
|
||||
}
|
||||
|
||||
sub sqrt(float value) -> float {
|
||||
; TODO
|
||||
return 0.0
|
||||
return -42.42
|
||||
}
|
||||
|
||||
sub rad(float angle) -> float {
|
||||
; -- convert degrees to radians (d * pi / 180)
|
||||
; TODO
|
||||
return 0.0
|
||||
return -42.42
|
||||
}
|
||||
|
||||
sub deg(float angle) -> float {
|
||||
; -- convert radians to degrees (d * (1/ pi * 180))
|
||||
; TODO
|
||||
return 0.0
|
||||
return -42.42
|
||||
}
|
||||
|
||||
sub round(float value) -> float {
|
||||
; TODO
|
||||
return 0.0
|
||||
return -42.42
|
||||
}
|
||||
|
||||
sub floor(float value) -> float {
|
||||
; TODO
|
||||
return 0.0
|
||||
return -42.42
|
||||
}
|
||||
|
||||
sub ceil(float value) -> float {
|
||||
; -- ceil: tr = int(f); if tr==f -> return else return tr+1
|
||||
; TODO
|
||||
return 0.0
|
||||
return -42.42
|
||||
}
|
||||
|
||||
sub rndf() -> float {
|
||||
; TODO
|
||||
return 0.0
|
||||
return -42.42
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ sys {
|
||||
|
||||
const ubyte target = 255 ; compilation target specifier. 64 = C64, 128 = C128, 16 = CommanderX16, 8 = atari800XL, 255 = virtual
|
||||
|
||||
; SYSCALLS
|
||||
; Syscalls table, taken from Syscall enumeration
|
||||
; 0 = reset ; resets system
|
||||
; 1 = exit ; stops program and returns statuscode from r0.w
|
||||
; 2 = print_c ; print single character
|
||||
@ -20,8 +20,8 @@ sys {
|
||||
; 8 = gfx_enable ; enable graphics window r0.b = 0 -> lores 320x240, r0.b = 1 -> hires 640x480
|
||||
; 9 = gfx_clear ; clear graphics window with shade in r0.b
|
||||
; 10 = gfx_plot ; plot pixel in graphics window, r0.w/r1.w contain X and Y coordinates, r2.b contains brightness
|
||||
; 11 = rnd ; random BYTE
|
||||
; 12 = rndw ; random WORD
|
||||
; 11 = set_carry status flag
|
||||
; 12 = clear_carry status flag
|
||||
; 13 = wait ; wait certain amount of jiffies (1/60 sec)
|
||||
; 14 = waitvsync ; wait on vsync
|
||||
; 15 = sort_ubyte array
|
||||
@ -44,26 +44,23 @@ sys {
|
||||
; 32 = all_word array
|
||||
; 33 = reverse_bytes array
|
||||
; 34 = reverse_words array
|
||||
; 35 = set_carry status flag
|
||||
; 36 = clear_carry status flag
|
||||
|
||||
; 35 = printf (float arg in fpReg0)
|
||||
const ubyte SC_RESET = 0
|
||||
const ubyte SC_EXIT = 1
|
||||
const ubyte SC_PRINT_C = 2
|
||||
const ubyte SC_PRINT_S = 3
|
||||
const ubyte SC_PRINT_U8 = 4
|
||||
const ubyte SC_PRINT_u16 = 5
|
||||
const ubyte SC_PRINT_U16 = 5
|
||||
const ubyte SC_INPUT = 6
|
||||
const ubyte SC_SLEEP = 7
|
||||
const ubyte SC_GFX_ENABLE = 8
|
||||
const ubyte SC_GFX_CLEAR = 9
|
||||
const ubyte SC_GFX_PLOT = 10
|
||||
const ubyte SC_RND = 11
|
||||
const ubyte SC_RNDW = 12
|
||||
const ubyte SC_SET_CARRY = 11
|
||||
const ubyte SC_CLEAR_CARRY = 12
|
||||
const ubyte SC_WAIT = 13
|
||||
const ubyte SC_WAITVSYNC = 14
|
||||
const ubyte SC_SET_CARRY = 35
|
||||
const ubyte SC_CLEAR_CARRY = 36
|
||||
const ubyte SC_PRINTF = 35
|
||||
|
||||
|
||||
sub reset_system() {
|
||||
|
@ -125,6 +125,7 @@ private val functionSignatures: List<FSignature> = listOf(
|
||||
FSignature("callrom" , false, listOf(FParam("bank", arrayOf(DataType.UBYTE)), FParam("address", arrayOf(DataType.UWORD)), FParam("arg", arrayOf(DataType.UWORD))), null),
|
||||
FSignature("syscall" , false, listOf(FParam("callnr", arrayOf(DataType.UBYTE))), DataType.UWORD, null),
|
||||
FSignature("syscall1" , false, listOf(FParam("callnr", arrayOf(DataType.UBYTE)), FParam("arg1", arrayOf(DataType.UWORD))), DataType.UWORD, null),
|
||||
FSignature("syscall1fp" , false, listOf(FParam("callnr", arrayOf(DataType.UBYTE)), FParam("arg1", arrayOf(DataType.FLOAT))), DataType.FLOAT, null),
|
||||
FSignature("syscall2" , false, listOf(FParam("callnr", arrayOf(DataType.UBYTE)), FParam("arg1", arrayOf(DataType.UWORD)), FParam("arg2", arrayOf(DataType.UWORD))), DataType.UWORD, null),
|
||||
FSignature("syscall3" , false, listOf(FParam("callnr", arrayOf(DataType.UBYTE)), FParam("arg1", arrayOf(DataType.UWORD)), FParam("arg2", arrayOf(DataType.UWORD)), FParam("arg3", arrayOf(DataType.UWORD))), DataType.UWORD, null),
|
||||
)
|
||||
|
@ -3,7 +3,8 @@ TODO
|
||||
|
||||
For next release
|
||||
^^^^^^^^^^^^^^^^
|
||||
- vm: implement floating point
|
||||
- vm: allow inline "asm" where the assembly is vm-code instead of 6502 -- then get rid of the syscall() functions in prog8
|
||||
- vm: implement missing floating point functions
|
||||
- pipe operator: allow non-unary function calls in the pipe that specify the other argument(s) in the calls.
|
||||
- allow "xxx" * constexpr (where constexpr is not a number literal), now gives expression error not same type
|
||||
- make it possible to inline non-asmsub routines that just contain a single statement (return, functioncall, assignment)
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
txt.print("float tests: ")
|
||||
float f1 = 1.2345
|
||||
float f2 = -9.99
|
||||
float f3
|
||||
|
@ -166,23 +166,18 @@ class Assembler {
|
||||
if (value < -32768 || value > 65535)
|
||||
throw IllegalArgumentException("value out of range for word: $value")
|
||||
}
|
||||
VmDataType.FLOAT -> {
|
||||
throw IllegalArgumentException("can't use float here")
|
||||
}
|
||||
VmDataType.FLOAT -> {}
|
||||
null -> {}
|
||||
}
|
||||
}
|
||||
var floatValue: Float? = null
|
||||
var intValue: Int? = null
|
||||
if(type==VmDataType.FLOAT)
|
||||
floatValue = value // TODO NOT ALWAYS CORRECT, SOMETIMES IT IS THE INT VALUE
|
||||
else
|
||||
intValue = value?.toInt()
|
||||
|
||||
if(!format.value && intValue!=null)
|
||||
throw IllegalArgumentException("invalid int value for $line")
|
||||
if(!format.fpValue && floatValue!=null)
|
||||
throw IllegalArgumentException("invalid float value for $line")
|
||||
if(format.value)
|
||||
intValue = value!!.toInt()
|
||||
if(format.fpValue)
|
||||
floatValue = value!!
|
||||
|
||||
program.add(Instruction(opcode, type, reg1, reg2, reg3, fpReg1, fpReg2, fpReg3, value = intValue, fpValue = floatValue))
|
||||
}
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ SYSCALLS:
|
||||
32 = all_word array
|
||||
33 = reverse_bytes array
|
||||
34 = reverse_words array
|
||||
35 = print_f (floating point value in fpReg0)
|
||||
*/
|
||||
|
||||
enum class Syscall {
|
||||
@ -77,7 +78,8 @@ enum class Syscall {
|
||||
ALL_BYTE,
|
||||
ALL_WORD,
|
||||
REVERSE_BYTES,
|
||||
REVERSE_WORDS
|
||||
REVERSE_WORDS,
|
||||
PRINT_F
|
||||
}
|
||||
|
||||
object SysCalls {
|
||||
@ -297,6 +299,10 @@ object SysCalls {
|
||||
}
|
||||
Syscall.SET_CARRY -> vm.statusCarry = true
|
||||
Syscall.CLEAR_CARRY -> vm.statusCarry = false
|
||||
Syscall.PRINT_F -> {
|
||||
val value = vm.registers.getFloat(0)
|
||||
print(value)
|
||||
}
|
||||
else -> TODO("syscall ${call.name}")
|
||||
}
|
||||
}
|
||||
|
@ -231,7 +231,10 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
}
|
||||
|
||||
private fun InsLOAD(i: Instruction) {
|
||||
setResultReg(i.reg1!!, i.value!!, i.type!!)
|
||||
if(i.type==VmDataType.FLOAT)
|
||||
registers.setFloat(i.fpReg1!!, i.fpValue!!)
|
||||
else
|
||||
setResultReg(i.reg1!!, i.value!!, i.type!!)
|
||||
pc++
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user