mirror of
https://github.com/irmen/prog8.git
synced 2024-11-29 17:50:35 +00:00
vm: some preparations for floating point
This commit is contained in:
parent
6471c0c536
commit
625d5b2313
@ -14,7 +14,7 @@ class VirtualMachineDefinition: IMachineDefinition {
|
|||||||
|
|
||||||
override val FLOAT_MAX_POSITIVE = Float.MAX_VALUE.toDouble()
|
override val FLOAT_MAX_POSITIVE = Float.MAX_VALUE.toDouble()
|
||||||
override val FLOAT_MAX_NEGATIVE = -Float.MAX_VALUE.toDouble()
|
override val FLOAT_MAX_NEGATIVE = -Float.MAX_VALUE.toDouble()
|
||||||
override val FLOAT_MEM_SIZE = 4
|
override val FLOAT_MEM_SIZE = 4 // 32-bits floating point
|
||||||
override val PROGRAM_LOAD_ADDRESS = 0u // not actually used
|
override val PROGRAM_LOAD_ADDRESS = 0u // not actually used
|
||||||
|
|
||||||
override val ESTACK_LO = 0u // not actually used
|
override val ESTACK_LO = 0u // not actually used
|
||||||
|
@ -61,10 +61,14 @@ internal class VmCodeInstruction(
|
|||||||
reg1: Int?=null, // 0-$ffff
|
reg1: Int?=null, // 0-$ffff
|
||||||
reg2: Int?=null, // 0-$ffff
|
reg2: Int?=null, // 0-$ffff
|
||||||
reg3: Int?=null, // 0-$ffff
|
reg3: Int?=null, // 0-$ffff
|
||||||
|
fpReg1: Int?=null, // 0-$ffff
|
||||||
|
fpReg2: Int?=null, // 0-$ffff
|
||||||
|
fpReg3: Int?=null, // 0-$ffff
|
||||||
value: Int?=null, // 0-$ffff
|
value: Int?=null, // 0-$ffff
|
||||||
|
fpValue: Float?=null,
|
||||||
symbol: List<String>?=null // alternative to value
|
symbol: List<String>?=null // alternative to value
|
||||||
): VmCodeLine() {
|
): VmCodeLine() {
|
||||||
val ins = Instruction(opcode, type, reg1, reg2, reg3, value, symbol)
|
val ins = Instruction(opcode, type, reg1, reg2, reg3, fpReg1, fpReg2, fpReg3, value, fpValue, symbol)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if(value!=null && opcode !in OpcodesWithAddress) {
|
if(value!=null && opcode !in OpcodesWithAddress) {
|
||||||
@ -77,11 +81,12 @@ internal class VmCodeInstruction(
|
|||||||
if (value < -32768 || value > 65535)
|
if (value < -32768 || value > 65535)
|
||||||
throw IllegalArgumentException("value out of range for word: $value")
|
throw IllegalArgumentException("value out of range for word: $value")
|
||||||
}
|
}
|
||||||
null -> {}
|
VmDataType.FLOAT, null -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal class VmCodeLabel(val name: List<String>): VmCodeLine()
|
internal class VmCodeLabel(val name: List<String>): VmCodeLine()
|
||||||
internal class VmCodeComment(val comment: String): VmCodeLine()
|
internal class VmCodeComment(val comment: String): VmCodeLine()
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import prog8.code.ast.*
|
|||||||
import prog8.code.core.ArrayToElementTypes
|
import prog8.code.core.ArrayToElementTypes
|
||||||
import prog8.code.core.AssemblyError
|
import prog8.code.core.AssemblyError
|
||||||
import prog8.code.core.DataType
|
import prog8.code.core.DataType
|
||||||
|
import prog8.code.core.WordDatatypes
|
||||||
import prog8.vm.Opcode
|
import prog8.vm.Opcode
|
||||||
import prog8.vm.Syscall
|
import prog8.vm.Syscall
|
||||||
import prog8.vm.VmDataType
|
import prog8.vm.VmDataType
|
||||||
@ -59,8 +60,8 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
val leftRegister = codeGen.vmRegisters.nextFree()
|
val leftRegister = codeGen.vmRegisters.nextFree()
|
||||||
val rightRegister = codeGen.vmRegisters.nextFree()
|
val rightRegister = codeGen.vmRegisters.nextFree()
|
||||||
code += exprGen.translateExpression(call.args[0], leftRegister)
|
code += exprGen.translateExpression(call.args[0], leftRegister, 99999)
|
||||||
code += exprGen.translateExpression(call.args[1], rightRegister)
|
code += exprGen.translateExpression(call.args[1], rightRegister, 99999)
|
||||||
code += VmCodeInstruction(Opcode.CMP, codeGen.vmType(call.args[0].type), reg1=leftRegister, reg2=rightRegister)
|
code += VmCodeInstruction(Opcode.CMP, codeGen.vmType(call.args[0].type), reg1=leftRegister, reg2=rightRegister)
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
@ -79,7 +80,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
else -> throw IllegalArgumentException("weird type")
|
else -> throw IllegalArgumentException("weird type")
|
||||||
}
|
}
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
code += exprGen.translateExpression(call.args[0], 0)
|
code += exprGen.translateExpression(call.args[0], 0, 99999)
|
||||||
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
|
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
|
||||||
code += VmCodeInstruction(Opcode.SYSCALL, value=syscall.ordinal)
|
code += VmCodeInstruction(Opcode.SYSCALL, value=syscall.ordinal)
|
||||||
if(resultRegister!=0)
|
if(resultRegister!=0)
|
||||||
@ -101,7 +102,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
else -> throw IllegalArgumentException("weird type")
|
else -> throw IllegalArgumentException("weird type")
|
||||||
}
|
}
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
code += exprGen.translateExpression(call.args[0], 0)
|
code += exprGen.translateExpression(call.args[0], 0, 99999)
|
||||||
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
|
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
|
||||||
code += VmCodeInstruction(Opcode.SYSCALL, value=syscall.ordinal)
|
code += VmCodeInstruction(Opcode.SYSCALL, value=syscall.ordinal)
|
||||||
if(resultRegister!=0)
|
if(resultRegister!=0)
|
||||||
@ -113,7 +114,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
val sourceDt = call.args.single().type
|
val sourceDt = call.args.single().type
|
||||||
if(sourceDt!=DataType.UWORD) {
|
if(sourceDt!=DataType.UWORD) {
|
||||||
code += exprGen.translateExpression(call.args[0], resultRegister)
|
code += exprGen.translateExpression(call.args[0], resultRegister, 99999)
|
||||||
when (sourceDt) {
|
when (sourceDt) {
|
||||||
DataType.UBYTE -> {
|
DataType.UBYTE -> {
|
||||||
code += VmCodeInstruction(Opcode.EXT, VmDataType.BYTE, reg1=resultRegister)
|
code += VmCodeInstruction(Opcode.EXT, VmDataType.BYTE, reg1=resultRegister)
|
||||||
@ -145,14 +146,14 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
|
|
||||||
private fun funcSgn(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
private fun funcSgn(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
code += exprGen.translateExpression(call.args.single(), 0)
|
code += exprGen.translateExpression(call.args.single(), 0, 99999)
|
||||||
code += VmCodeInstruction(Opcode.SGN, codeGen.vmType(call.type), reg1=resultRegister, reg2=0)
|
code += VmCodeInstruction(Opcode.SGN, codeGen.vmType(call.type), reg1=resultRegister, reg2=0)
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun funcSqrt16(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
private fun funcSqrt16(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
code += exprGen.translateExpression(call.args.single(), 0)
|
code += exprGen.translateExpression(call.args.single(), 0, 99999)
|
||||||
code += VmCodeInstruction(Opcode.SQRT, VmDataType.WORD, reg1=resultRegister, reg2=0)
|
code += VmCodeInstruction(Opcode.SQRT, VmDataType.WORD, reg1=resultRegister, reg2=0)
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
@ -173,14 +174,14 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
|
|
||||||
private fun funcPush(call: PtBuiltinFunctionCall): VmCodeChunk {
|
private fun funcPush(call: PtBuiltinFunctionCall): VmCodeChunk {
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
code += exprGen.translateExpression(call.args.single(), 0)
|
code += exprGen.translateExpression(call.args.single(), 0, 99999)
|
||||||
code += VmCodeInstruction(Opcode.PUSH, VmDataType.BYTE, reg1=0)
|
code += VmCodeInstruction(Opcode.PUSH, VmDataType.BYTE, reg1=0)
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun funcPushw(call: PtBuiltinFunctionCall): VmCodeChunk {
|
private fun funcPushw(call: PtBuiltinFunctionCall): VmCodeChunk {
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
code += exprGen.translateExpression(call.args.single(), 0)
|
code += exprGen.translateExpression(call.args.single(), 0, 99999)
|
||||||
code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1=0)
|
code += VmCodeInstruction(Opcode.PUSH, VmDataType.WORD, reg1=0)
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
@ -191,8 +192,8 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
val leftReg = codeGen.vmRegisters.nextFree()
|
val leftReg = codeGen.vmRegisters.nextFree()
|
||||||
val rightReg = codeGen.vmRegisters.nextFree()
|
val rightReg = codeGen.vmRegisters.nextFree()
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
code += exprGen.translateExpression(left, leftReg)
|
code += exprGen.translateExpression(left, leftReg, 99999)
|
||||||
code += exprGen.translateExpression(right, rightReg)
|
code += exprGen.translateExpression(right, rightReg, 99999)
|
||||||
code += assignRegisterTo(left, rightReg)
|
code += assignRegisterTo(left, rightReg)
|
||||||
code += assignRegisterTo(right, leftReg)
|
code += assignRegisterTo(right, leftReg)
|
||||||
return code
|
return code
|
||||||
@ -209,7 +210,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
else -> throw IllegalArgumentException("weird type to reverse")
|
else -> throw IllegalArgumentException("weird type to reverse")
|
||||||
}
|
}
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
code += exprGen.translateExpression(call.args[0], 0)
|
code += exprGen.translateExpression(call.args[0], 0, 99999)
|
||||||
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
|
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
|
||||||
code += VmCodeInstruction(Opcode.SYSCALL, value=sortSyscall.ordinal)
|
code += VmCodeInstruction(Opcode.SYSCALL, value=sortSyscall.ordinal)
|
||||||
return code
|
return code
|
||||||
@ -229,7 +230,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
else -> throw IllegalArgumentException("weird type to sort")
|
else -> throw IllegalArgumentException("weird type to sort")
|
||||||
}
|
}
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
code += exprGen.translateExpression(call.args[0], 0)
|
code += exprGen.translateExpression(call.args[0], 0, 99999)
|
||||||
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
|
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
|
||||||
code += VmCodeInstruction(Opcode.SYSCALL, value=sortSyscall.ordinal)
|
code += VmCodeInstruction(Opcode.SYSCALL, value=sortSyscall.ordinal)
|
||||||
return code
|
return code
|
||||||
@ -239,8 +240,8 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
val msbReg = codeGen.vmRegisters.nextFree()
|
val msbReg = codeGen.vmRegisters.nextFree()
|
||||||
val lsbReg = codeGen.vmRegisters.nextFree()
|
val lsbReg = codeGen.vmRegisters.nextFree()
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
code += exprGen.translateExpression(call.args[0], msbReg)
|
code += exprGen.translateExpression(call.args[0], msbReg, 99999)
|
||||||
code += exprGen.translateExpression(call.args[1], lsbReg)
|
code += exprGen.translateExpression(call.args[1], lsbReg, 99999)
|
||||||
code += VmCodeInstruction(Opcode.CONCAT, VmDataType.BYTE, reg1=resultRegister, reg2=msbReg, reg3=lsbReg)
|
code += VmCodeInstruction(Opcode.CONCAT, VmDataType.BYTE, reg1=resultRegister, reg2=msbReg, reg3=lsbReg)
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
@ -250,12 +251,12 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
val valueReg = codeGen.vmRegisters.nextFree()
|
val valueReg = codeGen.vmRegisters.nextFree()
|
||||||
if(call.args[0] is PtNumber) {
|
if(call.args[0] is PtNumber) {
|
||||||
val address = (call.args[0] as PtNumber).number.toInt()
|
val address = (call.args[0] as PtNumber).number.toInt()
|
||||||
code += exprGen.translateExpression(call.args[1], valueReg)
|
code += exprGen.translateExpression(call.args[1], valueReg, 99999)
|
||||||
code += VmCodeInstruction(Opcode.STOREM, VmDataType.WORD, reg1 = valueReg, value=address)
|
code += VmCodeInstruction(Opcode.STOREM, VmDataType.WORD, reg1 = valueReg, value=address)
|
||||||
} else {
|
} else {
|
||||||
val addressReg = codeGen.vmRegisters.nextFree()
|
val addressReg = codeGen.vmRegisters.nextFree()
|
||||||
code += exprGen.translateExpression(call.args[0], addressReg)
|
code += exprGen.translateExpression(call.args[0], addressReg, 99999)
|
||||||
code += exprGen.translateExpression(call.args[1], valueReg)
|
code += exprGen.translateExpression(call.args[1], valueReg, 99999)
|
||||||
code += VmCodeInstruction(Opcode.STOREI, VmDataType.WORD, reg1 = valueReg, reg2 = addressReg)
|
code += VmCodeInstruction(Opcode.STOREI, VmDataType.WORD, reg1 = valueReg, reg2 = addressReg)
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
@ -266,12 +267,12 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
val valueReg = codeGen.vmRegisters.nextFree()
|
val valueReg = codeGen.vmRegisters.nextFree()
|
||||||
if(call.args[0] is PtNumber) {
|
if(call.args[0] is PtNumber) {
|
||||||
val address = (call.args[0] as PtNumber).number.toInt()
|
val address = (call.args[0] as PtNumber).number.toInt()
|
||||||
code += exprGen.translateExpression(call.args[1], valueReg)
|
code += exprGen.translateExpression(call.args[1], valueReg, 99999)
|
||||||
code += VmCodeInstruction(Opcode.STOREM, VmDataType.BYTE, reg1 = valueReg, value=address)
|
code += VmCodeInstruction(Opcode.STOREM, VmDataType.BYTE, reg1 = valueReg, value=address)
|
||||||
} else {
|
} else {
|
||||||
val addressReg = codeGen.vmRegisters.nextFree()
|
val addressReg = codeGen.vmRegisters.nextFree()
|
||||||
code += exprGen.translateExpression(call.args[0], addressReg)
|
code += exprGen.translateExpression(call.args[0], addressReg, 99999)
|
||||||
code += exprGen.translateExpression(call.args[1], valueReg)
|
code += exprGen.translateExpression(call.args[1], valueReg, 99999)
|
||||||
code += VmCodeInstruction(Opcode.STOREI, VmDataType.BYTE, reg1 = valueReg, reg2 = addressReg)
|
code += VmCodeInstruction(Opcode.STOREI, VmDataType.BYTE, reg1 = valueReg, reg2 = addressReg)
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
@ -284,7 +285,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
code += VmCodeInstruction(Opcode.LOADM, VmDataType.WORD, reg1 = resultRegister, value = address)
|
code += VmCodeInstruction(Opcode.LOADM, VmDataType.WORD, reg1 = resultRegister, value = address)
|
||||||
} else {
|
} else {
|
||||||
val addressReg = codeGen.vmRegisters.nextFree()
|
val addressReg = codeGen.vmRegisters.nextFree()
|
||||||
code += exprGen.translateExpression(call.args.single(), addressReg)
|
code += exprGen.translateExpression(call.args.single(), addressReg, 99999)
|
||||||
code += VmCodeInstruction(Opcode.LOADI, VmDataType.WORD, reg1 = resultRegister, reg2 = addressReg)
|
code += VmCodeInstruction(Opcode.LOADI, VmDataType.WORD, reg1 = resultRegister, reg2 = addressReg)
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
@ -297,7 +298,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
code += VmCodeInstruction(Opcode.LOADM, VmDataType.BYTE, reg1 = resultRegister, value = address)
|
code += VmCodeInstruction(Opcode.LOADM, VmDataType.BYTE, reg1 = resultRegister, value = address)
|
||||||
} else {
|
} else {
|
||||||
val addressReg = codeGen.vmRegisters.nextFree()
|
val addressReg = codeGen.vmRegisters.nextFree()
|
||||||
code += exprGen.translateExpression(call.args.single(), addressReg)
|
code += exprGen.translateExpression(call.args.single(), addressReg, 99999)
|
||||||
code += VmCodeInstruction(Opcode.LOADI, VmDataType.BYTE, reg1 = resultRegister, reg2 = addressReg)
|
code += VmCodeInstruction(Opcode.LOADI, VmDataType.BYTE, reg1 = resultRegister, reg2 = addressReg)
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
@ -305,17 +306,13 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
|
|
||||||
private fun funcRnd(resultRegister: Int): VmCodeChunk {
|
private fun funcRnd(resultRegister: Int): VmCodeChunk {
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
code += VmCodeInstruction(Opcode.SYSCALL, value= Syscall.RND.ordinal)
|
code += VmCodeInstruction(Opcode.RND, VmDataType.BYTE, reg1=resultRegister)
|
||||||
if(resultRegister!=0)
|
|
||||||
code += VmCodeInstruction(Opcode.LOADR, VmDataType.BYTE, reg1=resultRegister, reg2=0)
|
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun funcRndw(resultRegister: Int): VmCodeChunk {
|
private fun funcRndw(resultRegister: Int): VmCodeChunk {
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
code += VmCodeInstruction(Opcode.SYSCALL, value= Syscall.RNDW.ordinal)
|
code += VmCodeInstruction(Opcode.RND, VmDataType.WORD, reg1=resultRegister)
|
||||||
if(resultRegister!=0)
|
|
||||||
code += VmCodeInstruction(Opcode.LOADR, VmDataType.WORD, reg1=resultRegister, reg2=0)
|
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,14 +336,14 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
|
|
||||||
private fun funcLsb(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
private fun funcLsb(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
code += exprGen.translateExpression(call.args.single(), resultRegister)
|
code += exprGen.translateExpression(call.args.single(), resultRegister, 99999)
|
||||||
// note: if a word result is needed, the upper byte is cleared by the typecast that follows. No need to do it here.
|
// 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
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun funcMsb(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
private fun funcMsb(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
code += exprGen.translateExpression(call.args.single(), resultRegister)
|
code += exprGen.translateExpression(call.args.single(), resultRegister, 99999)
|
||||||
code += VmCodeInstruction(Opcode.MSIG, VmDataType.BYTE, reg1 = resultRegister, reg2=resultRegister)
|
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.
|
// 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
|
return code
|
||||||
@ -362,7 +359,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
private fun funcSyscall1(call: PtBuiltinFunctionCall): VmCodeChunk {
|
private fun funcSyscall1(call: PtBuiltinFunctionCall): VmCodeChunk {
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
val callNr = (call.args[0] as PtNumber).number.toInt()
|
val callNr = (call.args[0] as PtNumber).number.toInt()
|
||||||
code += exprGen.translateExpression(call.args[1], 0)
|
code += exprGen.translateExpression(call.args[1], 0, 99999)
|
||||||
code += VmCodeInstruction(Opcode.SYSCALL, value=callNr)
|
code += VmCodeInstruction(Opcode.SYSCALL, value=callNr)
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
@ -374,8 +371,8 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
codeGen.vmRegisters.nextFree()
|
codeGen.vmRegisters.nextFree()
|
||||||
}
|
}
|
||||||
val callNr = (call.args[0] as PtNumber).number.toInt()
|
val callNr = (call.args[0] as PtNumber).number.toInt()
|
||||||
code += exprGen.translateExpression(call.args[1], 0)
|
code += exprGen.translateExpression(call.args[1], 0, 99999)
|
||||||
code += exprGen.translateExpression(call.args[2], 1)
|
code += exprGen.translateExpression(call.args[2], 1, 99999)
|
||||||
code += VmCodeInstruction(Opcode.SYSCALL, value=callNr)
|
code += VmCodeInstruction(Opcode.SYSCALL, value=callNr)
|
||||||
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 1)
|
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 1)
|
||||||
return code
|
return code
|
||||||
@ -389,9 +386,9 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
codeGen.vmRegisters.nextFree()
|
codeGen.vmRegisters.nextFree()
|
||||||
}
|
}
|
||||||
val callNr = (call.args[0] as PtNumber).number.toInt()
|
val callNr = (call.args[0] as PtNumber).number.toInt()
|
||||||
code += exprGen.translateExpression(call.args[1], 0)
|
code += exprGen.translateExpression(call.args[1], 0, 99999)
|
||||||
code += exprGen.translateExpression(call.args[2], 1)
|
code += exprGen.translateExpression(call.args[2], 1, 99999)
|
||||||
code += exprGen.translateExpression(call.args[3], 2)
|
code += exprGen.translateExpression(call.args[3], 2, 99999)
|
||||||
code += VmCodeInstruction(Opcode.SYSCALL, value=callNr)
|
code += VmCodeInstruction(Opcode.SYSCALL, value=callNr)
|
||||||
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 2)
|
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 2)
|
||||||
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 1)
|
code += VmCodeInstruction(Opcode.POP, VmDataType.WORD, reg1 = 1)
|
||||||
@ -401,7 +398,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
private fun funcRolRor2(opcode: Opcode, call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
private fun funcRolRor2(opcode: Opcode, call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
||||||
val vmDt = codeGen.vmType(call.args[0].type)
|
val vmDt = codeGen.vmType(call.args[0].type)
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
code += exprGen.translateExpression(call.args[0], resultRegister)
|
code += exprGen.translateExpression(call.args[0], resultRegister, 99999)
|
||||||
code += VmCodeInstruction(opcode, vmDt, reg1=resultRegister)
|
code += VmCodeInstruction(opcode, vmDt, reg1=resultRegister)
|
||||||
code += assignRegisterTo(call.args[0], resultRegister)
|
code += assignRegisterTo(call.args[0], resultRegister)
|
||||||
return code
|
return code
|
||||||
|
@ -10,15 +10,25 @@ import kotlin.math.pow
|
|||||||
|
|
||||||
|
|
||||||
internal class VmRegisterPool {
|
internal class VmRegisterPool {
|
||||||
private var firstFree: Int=3 // registers 0,1,2 are reserved
|
private var firstFree: Int=3 // integer registers 0,1,2 are reserved
|
||||||
|
private var firstFreeFloat: Int=0
|
||||||
|
|
||||||
fun peekNext() = firstFree
|
fun peekNext() = firstFree
|
||||||
|
fun peekNextFloat() = firstFreeFloat
|
||||||
|
|
||||||
fun nextFree(): Int {
|
fun nextFree(): Int {
|
||||||
val result = firstFree
|
val result = firstFree
|
||||||
firstFree++
|
firstFree++
|
||||||
if(firstFree>65535)
|
if(firstFree>65535)
|
||||||
throw AssemblyError("out of virtual registers")
|
throw AssemblyError("out of virtual registers (int)")
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun nextFreeFloat(): Int {
|
||||||
|
val result = firstFreeFloat
|
||||||
|
firstFreeFloat++
|
||||||
|
if(firstFreeFloat>65535)
|
||||||
|
throw AssemblyError("out of virtual registers (fp)")
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -141,7 +151,7 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
val valueReg = vmRegisters.nextFree()
|
val valueReg = vmRegisters.nextFree()
|
||||||
val choiceReg = vmRegisters.nextFree()
|
val choiceReg = vmRegisters.nextFree()
|
||||||
val valueDt = vmType(whenStmt.value.type)
|
val valueDt = vmType(whenStmt.value.type)
|
||||||
code += expressionEval.translateExpression(whenStmt.value, valueReg)
|
code += expressionEval.translateExpression(whenStmt.value, valueReg, 99999)
|
||||||
val choices = whenStmt.choices.children.map {it as PtWhenChoice }
|
val choices = whenStmt.choices.children.map {it as PtWhenChoice }
|
||||||
val endLabel = createLabelName()
|
val endLabel = createLabelName()
|
||||||
for (choice in choices) {
|
for (choice in choices) {
|
||||||
@ -239,8 +249,8 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
val loopLabel = createLabelName()
|
val loopLabel = createLabelName()
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
|
|
||||||
code += expressionEval.translateExpression(iterable.to, endvalueReg)
|
code += expressionEval.translateExpression(iterable.to, endvalueReg, 99999)
|
||||||
code += expressionEval.translateExpression(iterable.from, indexReg)
|
code += expressionEval.translateExpression(iterable.from, indexReg, 99999)
|
||||||
code += VmCodeInstruction(Opcode.STOREM, loopvarDt, reg1=indexReg, value=loopvarAddress)
|
code += VmCodeInstruction(Opcode.STOREM, loopvarDt, reg1=indexReg, value=loopvarAddress)
|
||||||
code += VmCodeLabel(loopLabel)
|
code += VmCodeLabel(loopLabel)
|
||||||
code += translateNode(forLoop.statements)
|
code += translateNode(forLoop.statements)
|
||||||
@ -448,7 +458,7 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
val conditionReg = vmRegisters.nextFree()
|
val conditionReg = vmRegisters.nextFree()
|
||||||
val vmDt = vmType(condition.type)
|
val vmDt = vmType(condition.type)
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
code += expressionEval.translateExpression(condition, conditionReg)
|
code += expressionEval.translateExpression(condition, conditionReg, 99999)
|
||||||
if(ifElse.elseScope.children.isNotEmpty()) {
|
if(ifElse.elseScope.children.isNotEmpty()) {
|
||||||
// if and else parts
|
// if and else parts
|
||||||
val elseLabel = createLabelName()
|
val elseLabel = createLabelName()
|
||||||
@ -494,7 +504,7 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1 = resultReg, value=address)
|
code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1 = resultReg, value=address)
|
||||||
} else {
|
} else {
|
||||||
val addressReg = vmRegisters.nextFree()
|
val addressReg = vmRegisters.nextFree()
|
||||||
code += expressionEval.translateExpression(memory.address, addressReg)
|
code += expressionEval.translateExpression(memory.address, addressReg, 99999)
|
||||||
code += VmCodeInstruction(Opcode.LOADI, vmDt, reg1 = resultReg, reg2 = addressReg)
|
code += VmCodeInstruction(Opcode.LOADI, vmDt, reg1 = resultReg, reg2 = addressReg)
|
||||||
code += VmCodeInstruction(operation, vmDt, reg1 = resultReg)
|
code += VmCodeInstruction(operation, vmDt, reg1 = resultReg)
|
||||||
code += VmCodeInstruction(Opcode.STOREI, vmDt, reg1 = resultReg, reg2 = addressReg)
|
code += VmCodeInstruction(Opcode.STOREI, vmDt, reg1 = resultReg, reg2 = addressReg)
|
||||||
@ -514,7 +524,7 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
code += VmCodeInstruction(memOp, vmDt, value=variableAddr)
|
code += VmCodeInstruction(memOp, vmDt, value=variableAddr)
|
||||||
} else {
|
} else {
|
||||||
val indexReg = vmRegisters.nextFree()
|
val indexReg = vmRegisters.nextFree()
|
||||||
code += expressionEval.translateExpression(array.index, indexReg)
|
code += expressionEval.translateExpression(array.index, indexReg, 99999)
|
||||||
code += VmCodeInstruction(Opcode.LOADX, vmDt, reg1=resultReg, reg2=indexReg, value=variableAddr)
|
code += VmCodeInstruction(Opcode.LOADX, vmDt, reg1=resultReg, reg2=indexReg, value=variableAddr)
|
||||||
code += VmCodeInstruction(operation, vmDt, reg1=resultReg)
|
code += VmCodeInstruction(operation, vmDt, reg1=resultReg)
|
||||||
code += VmCodeInstruction(Opcode.STOREX, vmDt, reg1=resultReg, reg2=indexReg, value=variableAddr)
|
code += VmCodeInstruction(Opcode.STOREX, vmDt, reg1=resultReg, reg2=indexReg, value=variableAddr)
|
||||||
@ -538,7 +548,7 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
val counterReg = vmRegisters.nextFree()
|
val counterReg = vmRegisters.nextFree()
|
||||||
val vmDt = vmType(repeat.count.type)
|
val vmDt = vmType(repeat.count.type)
|
||||||
code += expressionEval.translateExpression(repeat.count, counterReg)
|
code += expressionEval.translateExpression(repeat.count, counterReg, 99999)
|
||||||
val repeatLabel = createLabelName()
|
val repeatLabel = createLabelName()
|
||||||
code += VmCodeLabel(repeatLabel)
|
code += VmCodeLabel(repeatLabel)
|
||||||
code += translateNode(repeat.statements)
|
code += translateNode(repeat.statements)
|
||||||
@ -576,7 +586,7 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
(assignment.value as PtMachineRegister).register
|
(assignment.value as PtMachineRegister).register
|
||||||
} else {
|
} else {
|
||||||
val reg = vmRegisters.nextFree()
|
val reg = vmRegisters.nextFree()
|
||||||
code += expressionEval.translateExpression(assignment.value, reg)
|
code += expressionEval.translateExpression(assignment.value, reg, 99999)
|
||||||
reg
|
reg
|
||||||
}
|
}
|
||||||
val ident = assignment.target.identifier
|
val ident = assignment.target.identifier
|
||||||
@ -598,7 +608,7 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
code += VmCodeInstruction(Opcode.STOREM, vmDtArrayIdx, reg1 = resultRegister, value=variableAddr)
|
code += VmCodeInstruction(Opcode.STOREM, vmDtArrayIdx, reg1 = resultRegister, value=variableAddr)
|
||||||
} else {
|
} else {
|
||||||
val indexReg = vmRegisters.nextFree()
|
val indexReg = vmRegisters.nextFree()
|
||||||
code += expressionEval.translateExpression(array.index, indexReg)
|
code += expressionEval.translateExpression(array.index, indexReg, 99999)
|
||||||
code += VmCodeInstruction(Opcode.STOREX, vmDtArrayIdx, reg1 = resultRegister, reg2=indexReg, value=variableAddr)
|
code += VmCodeInstruction(Opcode.STOREX, vmDtArrayIdx, reg1 = resultRegister, reg2=indexReg, value=variableAddr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -608,7 +618,7 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1=resultRegister, value=(memory.address as PtNumber).number.toInt())
|
code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1=resultRegister, value=(memory.address as PtNumber).number.toInt())
|
||||||
} else {
|
} else {
|
||||||
val addressReg = vmRegisters.nextFree()
|
val addressReg = vmRegisters.nextFree()
|
||||||
code += expressionEval.translateExpression(memory.address, addressReg)
|
code += expressionEval.translateExpression(memory.address, addressReg, 99999)
|
||||||
code += VmCodeInstruction(Opcode.STOREI, vmDt, reg1=resultRegister, reg2=addressReg)
|
code += VmCodeInstruction(Opcode.STOREI, vmDt, reg1=resultRegister, reg2=addressReg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -622,7 +632,7 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
val value = ret.value
|
val value = ret.value
|
||||||
if(value!=null) {
|
if(value!=null) {
|
||||||
// Call Convention: return value is always returned in r0
|
// Call Convention: return value is always returned in r0
|
||||||
code += expressionEval.translateExpression(value, 0)
|
code += expressionEval.translateExpression(value, 0, 99999)
|
||||||
}
|
}
|
||||||
code += VmCodeInstruction(Opcode.RETURN)
|
code += VmCodeInstruction(Opcode.RETURN)
|
||||||
return code
|
return code
|
||||||
@ -658,6 +668,7 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
DataType.BYTE -> VmDataType.BYTE
|
DataType.BYTE -> VmDataType.BYTE
|
||||||
DataType.UWORD,
|
DataType.UWORD,
|
||||||
DataType.WORD -> VmDataType.WORD
|
DataType.WORD -> VmDataType.WORD
|
||||||
|
DataType.FLOAT -> VmDataType.FLOAT
|
||||||
in PassByReferenceDatatypes -> VmDataType.WORD
|
in PassByReferenceDatatypes -> VmDataType.WORD
|
||||||
else -> throw AssemblyError("no vm datatype for $type")
|
else -> throw AssemblyError("no vm datatype for $type")
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ import prog8.vm.VmDataType
|
|||||||
|
|
||||||
|
|
||||||
internal class ExpressionGen(private val codeGen: CodeGen) {
|
internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||||
fun translateExpression(expr: PtExpression, resultRegister: Int): VmCodeChunk {
|
fun translateExpression(expr: PtExpression, resultRegister: Int, resultFpRegister: Int): VmCodeChunk {
|
||||||
require(codeGen.vmRegisters.peekNext() > resultRegister)
|
require(codeGen.vmRegisters.peekNext() > resultRegister)
|
||||||
|
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
@ -49,7 +49,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
code += VmCodeInstruction(Opcode.LOADM, VmDataType.BYTE, reg1=resultRegister, value = address)
|
code += VmCodeInstruction(Opcode.LOADM, VmDataType.BYTE, reg1=resultRegister, value = address)
|
||||||
} else {
|
} else {
|
||||||
val addressRegister = codeGen.vmRegisters.nextFree()
|
val addressRegister = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(expr.address, addressRegister)
|
code += translateExpression(expr.address, addressRegister, 99999)
|
||||||
code += VmCodeInstruction(Opcode.LOADI, VmDataType.BYTE, reg1=resultRegister, reg2=addressRegister)
|
code += VmCodeInstruction(Opcode.LOADI, VmDataType.BYTE, reg1=resultRegister, reg2=addressRegister)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -91,7 +91,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
code += translateExpression(segments[0], valueReg)
|
code += translateExpression(segments[0], valueReg, 99999)
|
||||||
for (segment in segments.subList(1, segments.size-1)) {
|
for (segment in segments.subList(1, segments.size-1)) {
|
||||||
val sourceReg = valueReg
|
val sourceReg = valueReg
|
||||||
val sourceDt = valueDt
|
val sourceDt = valueDt
|
||||||
@ -100,16 +100,16 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
valueReg = codeGen.vmRegisters.nextFree()
|
valueReg = codeGen.vmRegisters.nextFree()
|
||||||
}
|
}
|
||||||
val segmentWithImplicitArgument = addImplicitArgToSegment(segment, sourceReg, sourceDt)
|
val segmentWithImplicitArgument = addImplicitArgToSegment(segment, sourceReg, sourceDt)
|
||||||
code += translateExpression(segmentWithImplicitArgument, valueReg)
|
code += translateExpression(segmentWithImplicitArgument, valueReg, 99999)
|
||||||
}
|
}
|
||||||
val segWithArg = addImplicitArgToSegment(segments.last(), valueReg, valueDt)
|
val segWithArg = addImplicitArgToSegment(segments.last(), valueReg, valueDt)
|
||||||
code += translateExpression(segWithArg, resultRegister)
|
code += translateExpression(segWithArg, resultRegister, 99999)
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun translate(check: PtContainmentCheck, resultRegister: Int): VmCodeChunk {
|
private fun translate(check: PtContainmentCheck, resultRegister: Int): VmCodeChunk {
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
code += translateExpression(check.element, resultRegister) // load the element to check in resultRegister
|
code += translateExpression(check.element, resultRegister, 99999) // load the element to check in resultRegister
|
||||||
val iterable = codeGen.symbolTable.flat.getValue(check.iterable.targetName) as StStaticVariable
|
val iterable = codeGen.symbolTable.flat.getValue(check.iterable.targetName) as StStaticVariable
|
||||||
when(iterable.dt) {
|
when(iterable.dt) {
|
||||||
DataType.STR -> {
|
DataType.STR -> {
|
||||||
@ -149,7 +149,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
val memOffset = (arrayIx.index as PtNumber).number.toInt() * eltSize
|
val memOffset = (arrayIx.index as PtNumber).number.toInt() * eltSize
|
||||||
code += VmCodeInstruction(Opcode.LOADM, vmDt, reg1=resultRegister, value=arrayLocation+memOffset)
|
code += VmCodeInstruction(Opcode.LOADM, vmDt, reg1=resultRegister, value=arrayLocation+memOffset)
|
||||||
} else {
|
} else {
|
||||||
code += translateExpression(arrayIx.index, idxReg)
|
code += translateExpression(arrayIx.index, idxReg, 99999)
|
||||||
if(eltSize>1)
|
if(eltSize>1)
|
||||||
code += codeGen.multiplyByConst(VmDataType.BYTE, idxReg, eltSize)
|
code += codeGen.multiplyByConst(VmDataType.BYTE, idxReg, eltSize)
|
||||||
code += VmCodeInstruction(Opcode.LOADX, vmDt, reg1=resultRegister, reg2=idxReg, value = arrayLocation)
|
code += VmCodeInstruction(Opcode.LOADX, vmDt, reg1=resultRegister, reg2=idxReg, value = arrayLocation)
|
||||||
@ -159,7 +159,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
|
|
||||||
private fun translate(expr: PtPrefix, resultRegister: Int): VmCodeChunk {
|
private fun translate(expr: PtPrefix, resultRegister: Int): VmCodeChunk {
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
code += translateExpression(expr.value, resultRegister)
|
code += translateExpression(expr.value, resultRegister, 99999)
|
||||||
val vmDt = codeGen.vmType(expr.type)
|
val vmDt = codeGen.vmType(expr.type)
|
||||||
when(expr.operator) {
|
when(expr.operator) {
|
||||||
"+" -> { }
|
"+" -> { }
|
||||||
@ -190,7 +190,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
if(cast.type==cast.value.type)
|
if(cast.type==cast.value.type)
|
||||||
return code
|
return code
|
||||||
code += translateExpression(cast.value, resultRegister)
|
code += translateExpression(cast.value, resultRegister, 99999)
|
||||||
when(cast.type) {
|
when(cast.type) {
|
||||||
DataType.UBYTE -> {
|
DataType.UBYTE -> {
|
||||||
when(cast.value.type) {
|
when(cast.value.type) {
|
||||||
@ -297,8 +297,8 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
val leftResultReg = codeGen.vmRegisters.nextFree()
|
val leftResultReg = codeGen.vmRegisters.nextFree()
|
||||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(binExpr.left, leftResultReg)
|
code += translateExpression(binExpr.left, leftResultReg, 99999)
|
||||||
code += translateExpression(binExpr.right, rightResultReg)
|
code += translateExpression(binExpr.right, rightResultReg, 99999)
|
||||||
val ins = if(signed) {
|
val ins = if(signed) {
|
||||||
if(greaterEquals) Opcode.SGES else Opcode.SGTS
|
if(greaterEquals) Opcode.SGES else Opcode.SGTS
|
||||||
} else {
|
} else {
|
||||||
@ -318,8 +318,8 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
val leftResultReg = codeGen.vmRegisters.nextFree()
|
val leftResultReg = codeGen.vmRegisters.nextFree()
|
||||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(binExpr.left, leftResultReg)
|
code += translateExpression(binExpr.left, leftResultReg, 99999)
|
||||||
code += translateExpression(binExpr.right, rightResultReg)
|
code += translateExpression(binExpr.right, rightResultReg, 99999)
|
||||||
val ins = if(signed) {
|
val ins = if(signed) {
|
||||||
if(lessEquals) Opcode.SLES else Opcode.SLTS
|
if(lessEquals) Opcode.SLES else Opcode.SLTS
|
||||||
} else {
|
} else {
|
||||||
@ -333,8 +333,8 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
val leftResultReg = codeGen.vmRegisters.nextFree()
|
val leftResultReg = codeGen.vmRegisters.nextFree()
|
||||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(binExpr.left, leftResultReg)
|
code += translateExpression(binExpr.left, leftResultReg, 99999)
|
||||||
code += translateExpression(binExpr.right, rightResultReg)
|
code += translateExpression(binExpr.right, rightResultReg, 99999)
|
||||||
val opcode = if(notEquals) Opcode.SNE else Opcode.SEQ
|
val opcode = if(notEquals) Opcode.SNE else Opcode.SEQ
|
||||||
code += VmCodeInstruction(opcode, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
code += VmCodeInstruction(opcode, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
||||||
return code
|
return code
|
||||||
@ -344,8 +344,8 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
val leftResultReg = codeGen.vmRegisters.nextFree()
|
val leftResultReg = codeGen.vmRegisters.nextFree()
|
||||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(binExpr.left, leftResultReg)
|
code += translateExpression(binExpr.left, leftResultReg, 99999)
|
||||||
code += translateExpression(binExpr.right, rightResultReg)
|
code += translateExpression(binExpr.right, rightResultReg, 99999)
|
||||||
val opc = if(signed) Opcode.ASRX else Opcode.LSRX
|
val opc = if(signed) Opcode.ASRX else Opcode.LSRX
|
||||||
code += VmCodeInstruction(opc, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
code += VmCodeInstruction(opc, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
||||||
return code
|
return code
|
||||||
@ -355,8 +355,8 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
val leftResultReg = codeGen.vmRegisters.nextFree()
|
val leftResultReg = codeGen.vmRegisters.nextFree()
|
||||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(binExpr.left, leftResultReg)
|
code += translateExpression(binExpr.left, leftResultReg, 99999)
|
||||||
code += translateExpression(binExpr.right, rightResultReg)
|
code += translateExpression(binExpr.right, rightResultReg, 99999)
|
||||||
code += VmCodeInstruction(Opcode.LSLX, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
code += VmCodeInstruction(Opcode.LSLX, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
@ -365,8 +365,8 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
val leftResultReg = codeGen.vmRegisters.nextFree()
|
val leftResultReg = codeGen.vmRegisters.nextFree()
|
||||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(binExpr.left, leftResultReg)
|
code += translateExpression(binExpr.left, leftResultReg, 99999)
|
||||||
code += translateExpression(binExpr.right, rightResultReg)
|
code += translateExpression(binExpr.right, rightResultReg, 99999)
|
||||||
code += VmCodeInstruction(Opcode.XOR, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
code += VmCodeInstruction(Opcode.XOR, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
@ -375,8 +375,8 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
val leftResultReg = codeGen.vmRegisters.nextFree()
|
val leftResultReg = codeGen.vmRegisters.nextFree()
|
||||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(binExpr.left, leftResultReg)
|
code += translateExpression(binExpr.left, leftResultReg, 99999)
|
||||||
code += translateExpression(binExpr.right, rightResultReg)
|
code += translateExpression(binExpr.right, rightResultReg, 99999)
|
||||||
code += VmCodeInstruction(Opcode.AND, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
code += VmCodeInstruction(Opcode.AND, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
@ -385,8 +385,8 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
val leftResultReg = codeGen.vmRegisters.nextFree()
|
val leftResultReg = codeGen.vmRegisters.nextFree()
|
||||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(binExpr.left, leftResultReg)
|
code += translateExpression(binExpr.left, leftResultReg, 99999)
|
||||||
code += translateExpression(binExpr.right, rightResultReg)
|
code += translateExpression(binExpr.right, rightResultReg, 99999)
|
||||||
code += VmCodeInstruction(Opcode.OR, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
code += VmCodeInstruction(Opcode.OR, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
@ -395,8 +395,8 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
val leftResultReg = codeGen.vmRegisters.nextFree()
|
val leftResultReg = codeGen.vmRegisters.nextFree()
|
||||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(binExpr.left, leftResultReg)
|
code += translateExpression(binExpr.left, leftResultReg, 99999)
|
||||||
code += translateExpression(binExpr.right, rightResultReg)
|
code += translateExpression(binExpr.right, rightResultReg, 99999)
|
||||||
code += VmCodeInstruction(Opcode.MOD, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
code += VmCodeInstruction(Opcode.MOD, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
||||||
return code
|
return code
|
||||||
}
|
}
|
||||||
@ -405,14 +405,14 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
val constFactorRight = binExpr.right as? PtNumber
|
val constFactorRight = binExpr.right as? PtNumber
|
||||||
if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) {
|
if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) {
|
||||||
code += translateExpression(binExpr.left, resultRegister)
|
code += translateExpression(binExpr.left, resultRegister, 99999)
|
||||||
val factor = constFactorRight.number.toInt()
|
val factor = constFactorRight.number.toInt()
|
||||||
code += codeGen.divideByConst(vmDt, resultRegister, factor)
|
code += codeGen.divideByConst(vmDt, resultRegister, factor)
|
||||||
} else {
|
} else {
|
||||||
val leftResultReg = codeGen.vmRegisters.nextFree()
|
val leftResultReg = codeGen.vmRegisters.nextFree()
|
||||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(binExpr.left, leftResultReg)
|
code += translateExpression(binExpr.left, leftResultReg, 99999)
|
||||||
code += translateExpression(binExpr.right, rightResultReg)
|
code += translateExpression(binExpr.right, rightResultReg, 99999)
|
||||||
code += VmCodeInstruction(Opcode.DIV, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
code += VmCodeInstruction(Opcode.DIV, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
@ -423,18 +423,18 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
val constFactorLeft = binExpr.left as? PtNumber
|
val constFactorLeft = binExpr.left as? PtNumber
|
||||||
val constFactorRight = binExpr.right as? PtNumber
|
val constFactorRight = binExpr.right as? PtNumber
|
||||||
if(constFactorLeft!=null && constFactorLeft.type!=DataType.FLOAT) {
|
if(constFactorLeft!=null && constFactorLeft.type!=DataType.FLOAT) {
|
||||||
code += translateExpression(binExpr.right, resultRegister)
|
code += translateExpression(binExpr.right, resultRegister, 99999)
|
||||||
val factor = constFactorLeft.number.toInt()
|
val factor = constFactorLeft.number.toInt()
|
||||||
code += codeGen.multiplyByConst(vmDt, resultRegister, factor)
|
code += codeGen.multiplyByConst(vmDt, resultRegister, factor)
|
||||||
} else if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) {
|
} else if(constFactorRight!=null && constFactorRight.type!=DataType.FLOAT) {
|
||||||
code += translateExpression(binExpr.left, resultRegister)
|
code += translateExpression(binExpr.left, resultRegister, 99999)
|
||||||
val factor = constFactorRight.number.toInt()
|
val factor = constFactorRight.number.toInt()
|
||||||
code += codeGen.multiplyByConst(vmDt, resultRegister, factor)
|
code += codeGen.multiplyByConst(vmDt, resultRegister, factor)
|
||||||
} else {
|
} else {
|
||||||
val leftResultReg = codeGen.vmRegisters.nextFree()
|
val leftResultReg = codeGen.vmRegisters.nextFree()
|
||||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(binExpr.left, leftResultReg)
|
code += translateExpression(binExpr.left, leftResultReg, 99999)
|
||||||
code += translateExpression(binExpr.right, rightResultReg)
|
code += translateExpression(binExpr.right, rightResultReg, 99999)
|
||||||
code += VmCodeInstruction(Opcode.MUL, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
code += VmCodeInstruction(Opcode.MUL, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
@ -443,14 +443,14 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
private fun operatorMinus(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
|
private fun operatorMinus(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
if((binExpr.right as? PtNumber)?.number==1.0) {
|
if((binExpr.right as? PtNumber)?.number==1.0) {
|
||||||
code += translateExpression(binExpr.left, resultRegister)
|
code += translateExpression(binExpr.left, resultRegister, 99999)
|
||||||
code += VmCodeInstruction(Opcode.DEC, vmDt, reg1=resultRegister)
|
code += VmCodeInstruction(Opcode.DEC, vmDt, reg1=resultRegister)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val leftResultReg = codeGen.vmRegisters.nextFree()
|
val leftResultReg = codeGen.vmRegisters.nextFree()
|
||||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(binExpr.left, leftResultReg)
|
code += translateExpression(binExpr.left, leftResultReg, 99999)
|
||||||
code += translateExpression(binExpr.right, rightResultReg)
|
code += translateExpression(binExpr.right, rightResultReg, 99999)
|
||||||
code += VmCodeInstruction(Opcode.SUB, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
code += VmCodeInstruction(Opcode.SUB, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
@ -459,18 +459,18 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
private fun operatorPlus(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
|
private fun operatorPlus(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
if((binExpr.left as? PtNumber)?.number==1.0) {
|
if((binExpr.left as? PtNumber)?.number==1.0) {
|
||||||
code += translateExpression(binExpr.right, resultRegister)
|
code += translateExpression(binExpr.right, resultRegister, 99999)
|
||||||
code += VmCodeInstruction(Opcode.INC, vmDt, reg1=resultRegister)
|
code += VmCodeInstruction(Opcode.INC, vmDt, reg1=resultRegister)
|
||||||
}
|
}
|
||||||
else if((binExpr.right as? PtNumber)?.number==1.0) {
|
else if((binExpr.right as? PtNumber)?.number==1.0) {
|
||||||
code += translateExpression(binExpr.left, resultRegister)
|
code += translateExpression(binExpr.left, resultRegister, 99999)
|
||||||
code += VmCodeInstruction(Opcode.INC, vmDt, reg1=resultRegister)
|
code += VmCodeInstruction(Opcode.INC, vmDt, reg1=resultRegister)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val leftResultReg = codeGen.vmRegisters.nextFree()
|
val leftResultReg = codeGen.vmRegisters.nextFree()
|
||||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(binExpr.left, leftResultReg)
|
code += translateExpression(binExpr.left, leftResultReg, 99999)
|
||||||
code += translateExpression(binExpr.right, rightResultReg)
|
code += translateExpression(binExpr.right, rightResultReg, 99999)
|
||||||
code += VmCodeInstruction(Opcode.ADD, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
code += VmCodeInstruction(Opcode.ADD, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
@ -481,7 +481,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
|||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
for ((arg, parameter) in fcall.args.zip(subroutine.parameters)) {
|
for ((arg, parameter) in fcall.args.zip(subroutine.parameters)) {
|
||||||
val argReg = codeGen.vmRegisters.nextFree()
|
val argReg = codeGen.vmRegisters.nextFree()
|
||||||
code += translateExpression(arg, argReg)
|
code += translateExpression(arg, argReg, 99999)
|
||||||
val vmDt = codeGen.vmType(parameter.type)
|
val vmDt = codeGen.vmType(parameter.type)
|
||||||
val mem = codeGen.allocations.get(fcall.functionName + parameter.name)
|
val mem = codeGen.allocations.get(fcall.functionName + parameter.name)
|
||||||
code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1=argReg, value=mem)
|
code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1=argReg, value=mem)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
%import textio
|
%import textio
|
||||||
; %import floats
|
;%import floats
|
||||||
%import conv
|
%import conv
|
||||||
%zeropage dontuse
|
%zeropage dontuse
|
||||||
|
|
||||||
@ -7,39 +7,34 @@
|
|||||||
; NOTE: meant to test to virtual machine output target (use -target vitual)
|
; NOTE: meant to test to virtual machine output target (use -target vitual)
|
||||||
|
|
||||||
main {
|
main {
|
||||||
sub newstring() -> str {
|
|
||||||
return "new"
|
|
||||||
}
|
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
str name = "irmen\n"
|
uword uw = 15555
|
||||||
txt.print(name)
|
uword squw = sqrt16(uw)
|
||||||
name = "pipo\n"
|
txt.print_uw(squw)
|
||||||
txt.print(name)
|
|
||||||
|
|
||||||
ubyte cc
|
|
||||||
ubyte[] array = [11,22,33,44]
|
|
||||||
for cc in array {
|
|
||||||
txt.print_ub(cc)
|
|
||||||
txt.spc()
|
|
||||||
}
|
|
||||||
txt.nl()
|
|
||||||
array = [99,88,77,66]
|
|
||||||
for cc in array {
|
|
||||||
txt.print_ub(cc)
|
|
||||||
txt.spc()
|
|
||||||
}
|
|
||||||
txt.nl()
|
txt.nl()
|
||||||
|
|
||||||
txt.print_ub0(99)
|
squw = rndw()
|
||||||
|
txt.print_uw(squw)
|
||||||
txt.spc()
|
txt.spc()
|
||||||
txt.print_ub(99)
|
squw = rndw()
|
||||||
|
txt.print_uw(squw)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
txt.print_uw0(9988)
|
|
||||||
|
squw = rnd()
|
||||||
|
txt.print_uw(squw)
|
||||||
txt.spc()
|
txt.spc()
|
||||||
txt.print_uw(9988)
|
squw = rnd()
|
||||||
|
txt.print_uw(squw)
|
||||||
txt.nl()
|
txt.nl()
|
||||||
|
|
||||||
|
; float f1 = 1.2345
|
||||||
|
; float f2 = -9.99
|
||||||
|
; float f3 = f1 % f2
|
||||||
|
; floats.print_f(f3)
|
||||||
|
; f3 = floats.sin(f3)
|
||||||
|
; floats.print_f(f3)
|
||||||
|
; txt.nl()
|
||||||
|
|
||||||
; float f1 = 1.555
|
; float f1 = 1.555
|
||||||
; floats.print_f(floats.sin(f1))
|
; floats.print_f(floats.sin(f1))
|
||||||
; txt.nl()
|
; txt.nl()
|
||||||
@ -71,24 +66,24 @@ main {
|
|||||||
; "ln", "log2", "sqrt", "rad",
|
; "ln", "log2", "sqrt", "rad",
|
||||||
; "deg", "round", "floor", "ceil", "rndf"
|
; "deg", "round", "floor", "ceil", "rndf"
|
||||||
|
|
||||||
; ; a "pixelshader":
|
; a "pixelshader":
|
||||||
; void syscall1(8, 0) ; enable lo res creen
|
void syscall1(8, 0) ; enable lo res creen
|
||||||
; ubyte shifter
|
ubyte shifter
|
||||||
;
|
|
||||||
; ; pokemon(1,0)
|
; pokemon(1,0)
|
||||||
;
|
|
||||||
; repeat {
|
repeat {
|
||||||
; uword xx
|
uword xx
|
||||||
; uword yy = 0
|
uword yy = 0
|
||||||
; repeat 240 {
|
repeat 240 {
|
||||||
; xx = 0
|
xx = 0
|
||||||
; repeat 320 {
|
repeat 320 {
|
||||||
; syscall3(10, xx, yy, xx*yy + shifter) ; plot pixel
|
syscall3(10, xx, yy, xx*yy + shifter) ; plot pixel
|
||||||
; xx++
|
xx++
|
||||||
; }
|
}
|
||||||
; yy++
|
yy++
|
||||||
; }
|
}
|
||||||
; shifter+=4
|
shifter+=4
|
||||||
; }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,13 @@ class Assembler {
|
|||||||
address += 2
|
address += 2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
"float" -> {
|
||||||
|
val array = values.split(',').map { it.toFloat() }
|
||||||
|
for (value in array) {
|
||||||
|
memory.setFloat(address, value)
|
||||||
|
address += 4 // 32-bits floats
|
||||||
|
}
|
||||||
|
}
|
||||||
else -> throw IllegalArgumentException("mem instr $what")
|
else -> throw IllegalArgumentException("mem instr $what")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,10 +120,18 @@ class Assembler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val format = instructionFormats.getValue(opcode)
|
val formats = instructionFormats.getValue(opcode)
|
||||||
if(type==null && format.datatypes.isNotEmpty())
|
val format: InstructionFormat
|
||||||
type= VmDataType.BYTE
|
if(type !in formats) {
|
||||||
if(type!=null && type !in format.datatypes)
|
type = VmDataType.BYTE
|
||||||
|
format = if(type !in formats)
|
||||||
|
formats.getValue(null)
|
||||||
|
else
|
||||||
|
formats.getValue(type)
|
||||||
|
} else {
|
||||||
|
format = formats.getValue(type)
|
||||||
|
}
|
||||||
|
if(type!=null && type !in formats)
|
||||||
throw IllegalArgumentException("invalid type code for $line")
|
throw IllegalArgumentException("invalid type code for $line")
|
||||||
if(format.reg1 && reg1==null)
|
if(format.reg1 && reg1==null)
|
||||||
throw IllegalArgumentException("needs reg1 for $line")
|
throw IllegalArgumentException("needs reg1 for $line")
|
||||||
@ -144,10 +159,13 @@ class Assembler {
|
|||||||
if (value < -32768 || value > 65535)
|
if (value < -32768 || value > 65535)
|
||||||
throw IllegalArgumentException("value out of range for word: $value")
|
throw IllegalArgumentException("value out of range for word: $value")
|
||||||
}
|
}
|
||||||
|
VmDataType.FLOAT -> {
|
||||||
|
throw IllegalArgumentException("can't use float here")
|
||||||
|
}
|
||||||
null -> {}
|
null -> {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
program.add(Instruction(opcode, type, reg1, reg2, reg3, value))
|
program.add(Instruction(opcode, type, reg1, reg2, reg3, value=value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,42 +5,37 @@ package prog8.vm
|
|||||||
Virtual machine:
|
Virtual machine:
|
||||||
|
|
||||||
65536 virtual registers, 16 bits wide, can also be used as 8 bits. r0-r65535
|
65536 virtual registers, 16 bits wide, can also be used as 8 bits. r0-r65535
|
||||||
|
65536 virtual floating point registers (32 bits single precision floats) fr0-fr65535
|
||||||
65536 bytes of memory. Thus memory pointers (addresses) are limited to 16 bits.
|
65536 bytes of memory. Thus memory pointers (addresses) are limited to 16 bits.
|
||||||
Value stack, max 128 entries of 1 byte each.
|
Value stack, max 128 entries of 1 byte each.
|
||||||
Status registers: Carry.
|
Status registers: Carry, Zero, Negative.
|
||||||
|
|
||||||
|
Most instructions have an associated data type 'b','w','f'. (omitting it means 'b'/byte).
|
||||||
Instruction serialization format possibility:
|
Currently NO support for 24 or 32 bits integers.
|
||||||
|
Floating point operations are just 'f' typed regular instructions, and additionally there are
|
||||||
OPCODE: 1 byte
|
a few fp conversion instructions to
|
||||||
TYPECODE: 1 byte
|
|
||||||
REGISTER 1: 2 bytes
|
|
||||||
REGISTER 2: 2 bytes
|
|
||||||
REG3/MEMORY/VALUE: 2 bytes
|
|
||||||
|
|
||||||
Instructions with Type come in variants 'b' and 'w' (omitting it in the instruction means 'b' by default)
|
|
||||||
Currently NO support for 24 or 32 bits, and FLOATING POINT is not implemented yet either. FP would be
|
|
||||||
a separate set of registers and instructions/routines anyway.
|
|
||||||
|
|
||||||
*only* LOAD AND STORE instructions have a possible memory operand, all other instructions use only registers or immediate value.
|
*only* LOAD AND STORE instructions have a possible memory operand, all other instructions use only registers or immediate value.
|
||||||
|
|
||||||
|
|
||||||
|
TODO all floating point arithmethic functions as fp-instructions.
|
||||||
|
|
||||||
LOAD/STORE
|
LOAD/STORE
|
||||||
----------
|
----------
|
||||||
All have type b or w.
|
All have type b or w or f.
|
||||||
|
|
||||||
load reg1, value - load immediate value into register
|
load reg1, value - load immediate value into register
|
||||||
loadm reg1, address - load reg1 with value in memory address
|
loadm reg1, address - load reg1 with value at memory address
|
||||||
loadi reg1, reg2 - load reg1 with value in memory indirect, memory pointed to by reg2
|
loadi reg1, reg2 - load reg1 with value at memory indirect, memory pointed to by reg2
|
||||||
loadx reg1, reg2, address - load reg1 with value in memory address, indexed by value in reg2
|
loadx reg1, reg2, address - load reg1 with value at memory address, indexed by value in reg2
|
||||||
loadr reg1, reg2 - load reg1 with value in register reg2
|
loadr reg1, reg2 - load reg1 with value at register reg2
|
||||||
|
|
||||||
storem reg1, address - store reg1 in memory address
|
storem reg1, address - store reg1 at memory address
|
||||||
storei reg1, reg2 - store reg1 in memory indirect, memory pointed to by reg2
|
storei reg1, reg2 - store reg1 at memory indirect, memory pointed to by reg2
|
||||||
storex reg1, reg2, address - store reg1 in memory address, indexed by value in reg2
|
storex reg1, reg2, address - store reg1 at memory address, indexed by value in reg2
|
||||||
storez address - store zero in memory address
|
storez address - store zero at memory address
|
||||||
storezi reg1 - store zero in memory pointed to by reg1
|
storezi reg1 - store zero at memory pointed to by reg1
|
||||||
storezx reg1, address - store zero in memory address, indexed by value in reg
|
storezx reg1, address - store zero at memory address, indexed by value in reg
|
||||||
|
|
||||||
|
|
||||||
CONTROL FLOW
|
CONTROL FLOW
|
||||||
@ -91,13 +86,10 @@ sgts reg1, reg2, reg3 - set reg=1 if reg2 > reg3 (signed), ot
|
|||||||
sge reg1, reg2, reg3 - set reg=1 if reg2 >= reg3 (unsigned), otherwise set reg1=0
|
sge reg1, reg2, reg3 - set reg=1 if reg2 >= reg3 (unsigned), otherwise set reg1=0
|
||||||
sges reg1, reg2, reg3 - set reg=1 if reg2 >= reg3 (signed), otherwise set reg1=0
|
sges reg1, reg2, reg3 - set reg=1 if reg2 >= reg3 (signed), otherwise set reg1=0
|
||||||
|
|
||||||
TODO: support for the other prog8 special branching instructions if_XX (bpl, bmi etc.)
|
|
||||||
but we don't have any 'processor flags' whatsoever in the vm so it's a bit weird
|
|
||||||
|
|
||||||
|
ARITHMETIC
|
||||||
INTEGER ARITHMETIC
|
----------
|
||||||
------------------
|
All have type b or w or f. Note: result types are the same as operand types! E.g. byte*byte->byte.
|
||||||
All have type b or w. Note: result types are the same as operand types! E.g. byte*byte->byte.
|
|
||||||
|
|
||||||
ext reg1 - reg1 = unsigned extension of reg1 (which in practice just means clearing the MSB / MSW) (latter not yet implemented as we don't have longs yet)
|
ext reg1 - reg1 = unsigned extension of reg1 (which in practice just means clearing the MSB / MSW) (latter not yet implemented as we don't have longs yet)
|
||||||
exts reg1 - reg1 = signed extension of reg1 (byte to word, or word to long) (note: latter ext.w, not yet implemented as we don't have longs yet)
|
exts reg1 - reg1 = signed extension of reg1 (byte to word, or word to long) (note: latter ext.w, not yet implemented as we don't have longs yet)
|
||||||
@ -111,9 +103,10 @@ sub reg1, reg2, reg3 - reg1 = reg2-reg3 (unsigned + signe
|
|||||||
mul reg1, reg2, reg3 - unsigned multiply reg1=reg2*reg3 note: byte*byte->byte, no type extension to word!
|
mul reg1, reg2, reg3 - unsigned multiply reg1=reg2*reg3 note: byte*byte->byte, no type extension to word!
|
||||||
div reg1, reg2, reg3 - unsigned division reg1=reg2/reg3 note: division by zero yields max signed int $ff/$ffff
|
div reg1, reg2, reg3 - unsigned division reg1=reg2/reg3 note: division by zero yields max signed int $ff/$ffff
|
||||||
mod reg1, reg2, reg3 - remainder (modulo) of unsigned division reg1=reg2%reg3 note: division by zero yields max signed int $ff/$ffff
|
mod reg1, reg2, reg3 - remainder (modulo) of unsigned division reg1=reg2%reg3 note: division by zero yields max signed int $ff/$ffff
|
||||||
sqrt reg1, reg2 - reg1 is the square root of reg2 (for .w and .b both , the result is a byte)
|
sqrt reg1, reg2 - reg1 is the square root of reg2
|
||||||
sgn reg1, reg2 - reg1 is the sign of reg2 (0, 1 or -1)
|
sgn reg1, reg2 - reg1 is the sign of reg2 (0, 1 or -1)
|
||||||
cmp reg1, reg2 - set processor status bits C, N, Z according to comparison of reg1 with reg2. (semantics taken from 6502/68000 CMP instruction)
|
cmp reg1, reg2 - set processor status bits C, N, Z according to comparison of reg1 with reg2. (semantics taken from 6502/68000 CMP instruction)
|
||||||
|
rnd reg1 - get a random number (byte, word or float)
|
||||||
|
|
||||||
NOTE: because mul/div are constrained (truncated) to remain in 8 or 16 bits, there is NO NEED for separate signed/unsigned mul and div instructions. The result is identical.
|
NOTE: because mul/div are constrained (truncated) to remain in 8 or 16 bits, there is NO NEED for separate signed/unsigned mul and div instructions. The result is identical.
|
||||||
|
|
||||||
@ -137,20 +130,32 @@ rol reg1 - rotate reg1 left by 1bits, not us
|
|||||||
roxl reg1 - rotate reg1 left by 1bits, using carry, + set Carry to shifted bit
|
roxl reg1 - rotate reg1 left by 1bits, using carry, + set Carry to shifted bit
|
||||||
|
|
||||||
|
|
||||||
|
FLOATING POINT CONVERSIONS
|
||||||
|
--------------------------
|
||||||
|
ffromub fpreg1, reg1 - fpreg1 = reg1 from usigned byte
|
||||||
|
ffromsb fpreg1, reg1 - fpreg1 = reg1 from signed byte
|
||||||
|
ffromuw fpreg1, reg1 - fpreg1 = reg1 from unsigned word
|
||||||
|
ffromsw fpreg1, reg1 - fpreg1 = reg1 from signed word
|
||||||
|
ftoub reg1, fpreg1 - reg1 = fpreg1 as unsigned byte
|
||||||
|
ftosb reg1, fpreg1 - reg1 = fpreg1 as signed byte
|
||||||
|
ftouw reg1, fpreg1 - reg1 = fpreg1 as unsigned word
|
||||||
|
ftosw reg1, fpreg1 - reg1 = fpreg1 as signed word
|
||||||
|
|
||||||
|
|
||||||
MISC
|
MISC
|
||||||
----
|
----
|
||||||
|
|
||||||
clc - clear Carry status bit
|
clc - clear Carry status bit
|
||||||
sec - set Carry status bit
|
sec - set Carry status bit
|
||||||
nop - do nothing
|
nop - do nothing
|
||||||
breakpoint - trigger a breakpoint
|
breakpoint - trigger a breakpoint
|
||||||
copy reg1, reg2, length - copy memory from ptrs in reg1 to reg3, length bytes
|
copy reg1, reg2, length - copy memory from ptrs in reg1 to reg3, length bytes
|
||||||
copyz reg1, reg2 - copy memory from ptrs in reg1 to reg3, stop after first 0-byte
|
copyz reg1, reg2 - copy memory from ptrs in reg1 to reg3, stop after first 0-byte
|
||||||
msig [b, w] reg1, reg2 - reg1 becomes the most significant byte (or word) of the word (or int) in reg2 (.w not yet implemented; requires 32 bits regs)
|
msig [b, w] reg1, reg2 - reg1 becomes the most significant byte (or word) of the word (or int) in reg2 (.w not yet implemented; requires 32 bits regs)
|
||||||
swapreg reg1, reg2 - swap values in reg1 and reg2
|
swapreg reg1, reg2 - swap values in reg1 and reg2
|
||||||
concat [b, w] reg1, reg2, reg3 - reg1 = concatenated lsb/lsw of reg2 and lsb/lsw of reg3 into new word or int (int not yet implemented; requires 32bits regs)
|
concat [b, w] reg1, reg2, reg3 - reg1 = concatenated lsb/lsw of reg2 and lsb/lsw of reg3 into new word or int (int not yet implemented; requires 32bits regs)
|
||||||
push [b, w] reg1 - push value in reg1 on the stack
|
push [b, w] reg1 - push value in reg1 on the stack
|
||||||
pop [b, w] reg1 - pop value from stack into reg1
|
pop [b, w] reg1 - pop value from stack into reg1
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -217,6 +222,7 @@ enum class Opcode {
|
|||||||
SQRT,
|
SQRT,
|
||||||
SGN,
|
SGN,
|
||||||
CMP,
|
CMP,
|
||||||
|
RND,
|
||||||
EXT,
|
EXT,
|
||||||
EXTS,
|
EXTS,
|
||||||
|
|
||||||
@ -234,6 +240,15 @@ enum class Opcode {
|
|||||||
ROL,
|
ROL,
|
||||||
ROXL,
|
ROXL,
|
||||||
|
|
||||||
|
FFROMUB,
|
||||||
|
FFROMSB,
|
||||||
|
FFROMUW,
|
||||||
|
FFROMSW,
|
||||||
|
FTOUB,
|
||||||
|
FTOSB,
|
||||||
|
FTOUW,
|
||||||
|
FTOSW,
|
||||||
|
|
||||||
CLC,
|
CLC,
|
||||||
SEC,
|
SEC,
|
||||||
PUSH,
|
PUSH,
|
||||||
@ -256,7 +271,8 @@ val OpcodesWithAddress = setOf(
|
|||||||
|
|
||||||
enum class VmDataType {
|
enum class VmDataType {
|
||||||
BYTE,
|
BYTE,
|
||||||
WORD
|
WORD,
|
||||||
|
FLOAT
|
||||||
// TODO add INT (32-bit)? INT24 (24-bit)?
|
// TODO add INT (32-bit)? INT24 (24-bit)?
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,14 +282,19 @@ data class Instruction(
|
|||||||
val reg1: Int?=null, // 0-$ffff
|
val reg1: Int?=null, // 0-$ffff
|
||||||
val reg2: Int?=null, // 0-$ffff
|
val reg2: Int?=null, // 0-$ffff
|
||||||
val reg3: Int?=null, // 0-$ffff
|
val reg3: Int?=null, // 0-$ffff
|
||||||
|
val fpReg1: Int?=null, // 0-$ffff
|
||||||
|
val fpReg2: Int?=null, // 0-$ffff
|
||||||
|
val fpReg3: Int?=null, // 0-$ffff
|
||||||
val value: Int?=null, // 0-$ffff
|
val value: Int?=null, // 0-$ffff
|
||||||
|
val fpValue: Float?=null,
|
||||||
val symbol: List<String>?=null // alternative to value
|
val symbol: List<String>?=null // alternative to value
|
||||||
) {
|
) {
|
||||||
init {
|
init {
|
||||||
val format = instructionFormats.getValue(opcode)
|
val formats = instructionFormats.getValue(opcode)
|
||||||
if(format.datatypes.isNotEmpty() && type==null)
|
if(type==null && !formats.containsKey(null))
|
||||||
throw IllegalArgumentException("missing type")
|
throw IllegalArgumentException("missing type")
|
||||||
|
|
||||||
|
val format = formats.getValue(type)
|
||||||
if(format.reg1 && reg1==null ||
|
if(format.reg1 && reg1==null ||
|
||||||
format.reg2 && reg2==null ||
|
format.reg2 && reg2==null ||
|
||||||
format.reg3 && reg3==null)
|
format.reg3 && reg3==null)
|
||||||
@ -284,8 +305,18 @@ data class Instruction(
|
|||||||
!format.reg3 && reg3!=null)
|
!format.reg3 && reg3!=null)
|
||||||
throw IllegalArgumentException("too many registers")
|
throw IllegalArgumentException("too many registers")
|
||||||
|
|
||||||
if(format.value && (value==null && symbol==null))
|
|
||||||
throw IllegalArgumentException("missing a value or symbol")
|
if (type==VmDataType.FLOAT) {
|
||||||
|
if(format.value && (fpValue==null && symbol==null))
|
||||||
|
throw IllegalArgumentException("$opcode: missing a fp-value or symbol")
|
||||||
|
if (reg1 != null || reg2 != null || reg3 != null)
|
||||||
|
throw java.lang.IllegalArgumentException("$opcode: floating point instruction can't use integer registers")
|
||||||
|
} else {
|
||||||
|
if(format.value && (value==null && symbol==null))
|
||||||
|
throw IllegalArgumentException("$opcode: missing a value or symbol")
|
||||||
|
if (fpReg1 != null || fpReg2 != null || fpReg3 != null)
|
||||||
|
throw java.lang.IllegalArgumentException("$opcode: integer point instruction can't use floating point registers")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
@ -308,10 +339,26 @@ data class Instruction(
|
|||||||
result.add("r$it")
|
result.add("r$it")
|
||||||
result.add(",")
|
result.add(",")
|
||||||
}
|
}
|
||||||
|
fpReg1?.let {
|
||||||
|
result.add("fr$it")
|
||||||
|
result.add(",")
|
||||||
|
}
|
||||||
|
fpReg2?.let {
|
||||||
|
result.add("fr$it")
|
||||||
|
result.add(",")
|
||||||
|
}
|
||||||
|
fpReg3?.let {
|
||||||
|
result.add("fr$it")
|
||||||
|
result.add(",")
|
||||||
|
}
|
||||||
value?.let {
|
value?.let {
|
||||||
result.add(it.toString())
|
result.add(it.toString())
|
||||||
result.add(",")
|
result.add(",")
|
||||||
}
|
}
|
||||||
|
fpValue?.let {
|
||||||
|
result.add(it.toString())
|
||||||
|
result.add(",")
|
||||||
|
}
|
||||||
symbol?.let {
|
symbol?.let {
|
||||||
result.add("_" + it.joinToString("."))
|
result.add("_" + it.joinToString("."))
|
||||||
}
|
}
|
||||||
@ -321,98 +368,146 @@ data class Instruction(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class InstructionFormat(val datatypes: Set<VmDataType>, val reg1: Boolean, val reg2: Boolean, val reg3: Boolean, val value: Boolean)
|
data class InstructionFormat(val datatype: VmDataType?,
|
||||||
|
val reg1: Boolean, val reg2: Boolean, val reg3: Boolean,
|
||||||
|
val fpReg1: Boolean, val fpReg2: Boolean, val fpReg3: Boolean,
|
||||||
|
val value: Boolean,
|
||||||
|
val fpValue: Boolean) {
|
||||||
|
companion object {
|
||||||
|
fun from(spec: String): Map<VmDataType?, InstructionFormat> {
|
||||||
|
val result = mutableMapOf<VmDataType?, InstructionFormat>()
|
||||||
|
var reg1 = false
|
||||||
|
var reg2 = false
|
||||||
|
var reg3 = false
|
||||||
|
var fpreg1 = false
|
||||||
|
var fpreg2 = false
|
||||||
|
var fpreg3 = false
|
||||||
|
var value = false
|
||||||
|
var fpvalue = false
|
||||||
|
for(part in spec.split('|').map{ it.trim() }) {
|
||||||
|
val splits = part.splitToSequence(',').iterator()
|
||||||
|
val typespec = splits.next()
|
||||||
|
while(splits.hasNext()) {
|
||||||
|
when(splits.next()) {
|
||||||
|
"r1" -> reg1=true
|
||||||
|
"r2" -> reg2=true
|
||||||
|
"r3" -> reg3=true
|
||||||
|
"fr1" -> fpreg1=true
|
||||||
|
"fr2" -> fpreg2=true
|
||||||
|
"fr3" -> fpreg3=true
|
||||||
|
"v" -> value = true
|
||||||
|
"fv" -> fpvalue = true
|
||||||
|
else -> throw IllegalArgumentException(spec)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(typespec=="N")
|
||||||
|
result[null] = InstructionFormat(null, reg1=reg1, reg2=reg2, reg3=reg3, fpReg1=fpreg1, fpReg2=fpreg2, fpReg3=fpreg3, value=value, fpValue=fpvalue)
|
||||||
|
if('B' in typespec)
|
||||||
|
result[VmDataType.BYTE] = InstructionFormat(VmDataType.BYTE, reg1=reg1, reg2=reg2, reg3=reg3, fpReg1=fpreg1, fpReg2=fpreg2, fpReg3=fpreg3, value=value, fpValue=fpvalue)
|
||||||
|
if('W' in typespec)
|
||||||
|
result[VmDataType.WORD] = InstructionFormat(VmDataType.WORD, reg1=reg1, reg2=reg2, reg3=reg3, fpReg1=fpreg1, fpReg2=fpreg2, fpReg3=fpreg3, value=value, fpValue=fpvalue)
|
||||||
|
if('F' in typespec)
|
||||||
|
result[VmDataType.FLOAT] = InstructionFormat(VmDataType.FLOAT, reg1=reg1, reg2=reg2, reg3=reg3, fpReg1=fpreg1, fpReg2=fpreg2, fpReg3=fpreg3, value=value, fpValue=fpvalue)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val NN = emptySet<VmDataType>()
|
|
||||||
private val BW = setOf(VmDataType.BYTE, VmDataType.WORD)
|
|
||||||
|
|
||||||
@Suppress("BooleanLiteralArgument")
|
@Suppress("BooleanLiteralArgument")
|
||||||
val instructionFormats = mutableMapOf(
|
val instructionFormats = mutableMapOf(
|
||||||
Opcode.NOP to InstructionFormat(NN, false, false, false, false),
|
Opcode.NOP to InstructionFormat.from("N"),
|
||||||
Opcode.LOAD to InstructionFormat(BW, true, false, false, true ),
|
Opcode.LOAD to InstructionFormat.from("BW,r1,v | F,fr1,fv"),
|
||||||
Opcode.LOADM to InstructionFormat(BW, true, false, false, true ),
|
Opcode.LOADM to InstructionFormat.from("BW,r1,v | F,fr1,v"),
|
||||||
Opcode.LOADI to InstructionFormat(BW, true, true, false, false),
|
Opcode.LOADI to InstructionFormat.from("BW,r1,r2 | F,fr1,r1"),
|
||||||
Opcode.LOADX to InstructionFormat(BW, true, true, false, true ),
|
Opcode.LOADX to InstructionFormat.from("BW,r1,r2,v | F,fr1,r1,v"),
|
||||||
Opcode.LOADR to InstructionFormat(BW, true, true, false, false),
|
Opcode.LOADR to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
||||||
Opcode.SWAPREG to InstructionFormat(BW, true, true, false, false),
|
Opcode.SWAPREG to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
||||||
Opcode.STOREM to InstructionFormat(BW, true, false, false, true ),
|
Opcode.STOREM to InstructionFormat.from("BW,r1,v | F,fr1,v"),
|
||||||
Opcode.STOREI to InstructionFormat(BW, true, true, false, false),
|
Opcode.STOREI to InstructionFormat.from("BW,r1,r2 | F,fr1,r1"),
|
||||||
Opcode.STOREX to InstructionFormat(BW, true, true, false, true ),
|
Opcode.STOREX to InstructionFormat.from("BW,r1,r2,v | F,fr1,r1,v"),
|
||||||
Opcode.STOREZ to InstructionFormat(BW, false, false, false, true ),
|
Opcode.STOREZ to InstructionFormat.from("BW,v | F,v"),
|
||||||
Opcode.STOREZI to InstructionFormat(BW, true, false, false, false),
|
Opcode.STOREZI to InstructionFormat.from("BW,r1 | F,r1"),
|
||||||
Opcode.STOREZX to InstructionFormat(BW, true, false, false, true ),
|
Opcode.STOREZX to InstructionFormat.from("BW,r1,v | F,r1,v"),
|
||||||
|
Opcode.JUMP to InstructionFormat.from("N,v"),
|
||||||
|
Opcode.JUMPI to InstructionFormat.from("N,r1"),
|
||||||
|
Opcode.CALL to InstructionFormat.from("N,v"),
|
||||||
|
Opcode.CALLI to InstructionFormat.from("N,r1"),
|
||||||
|
Opcode.SYSCALL to InstructionFormat.from("N,v"),
|
||||||
|
Opcode.RETURN to InstructionFormat.from("N"),
|
||||||
|
Opcode.BSTCC to InstructionFormat.from("N,v"),
|
||||||
|
Opcode.BSTCS to InstructionFormat.from("N,v"),
|
||||||
|
Opcode.BSTEQ to InstructionFormat.from("N,v"),
|
||||||
|
Opcode.BSTNE to InstructionFormat.from("N,v"),
|
||||||
|
Opcode.BSTNEG to InstructionFormat.from("N,v"),
|
||||||
|
Opcode.BSTPOS to InstructionFormat.from("N,v"),
|
||||||
|
Opcode.BZ to InstructionFormat.from("BW,r1,v"),
|
||||||
|
Opcode.BNZ to InstructionFormat.from("BW,r1,v"),
|
||||||
|
Opcode.BEQ to InstructionFormat.from("BW,r1,r2,v"),
|
||||||
|
Opcode.BNE to InstructionFormat.from("BW,r1,r2,v"),
|
||||||
|
Opcode.BLT to InstructionFormat.from("BW,r1,r2,v"),
|
||||||
|
Opcode.BLTS to InstructionFormat.from("BW,r1,r2,v"),
|
||||||
|
Opcode.BGT to InstructionFormat.from("BW,r1,r2,v"),
|
||||||
|
Opcode.BGTS to InstructionFormat.from("BW,r1,r2,v"),
|
||||||
|
Opcode.BLE to InstructionFormat.from("BW,r1,r2,v"),
|
||||||
|
Opcode.BLES to InstructionFormat.from("BW,r1,r2,v"),
|
||||||
|
Opcode.BGE to InstructionFormat.from("BW,r1,r2,v"),
|
||||||
|
Opcode.BGES to InstructionFormat.from("BW,r1,r2,v"),
|
||||||
|
Opcode.SEQ to InstructionFormat.from("BW,r1,r2,r3"),
|
||||||
|
Opcode.SNE to InstructionFormat.from("BW,r1,r2,r3"),
|
||||||
|
Opcode.SLT to InstructionFormat.from("BW,r1,r2,r3"),
|
||||||
|
Opcode.SLTS to InstructionFormat.from("BW,r1,r2,r3"),
|
||||||
|
Opcode.SGT to InstructionFormat.from("BW,r1,r2,r3"),
|
||||||
|
Opcode.SGTS to InstructionFormat.from("BW,r1,r2,r3"),
|
||||||
|
Opcode.SLE to InstructionFormat.from("BW,r1,r2,r3"),
|
||||||
|
Opcode.SLES to InstructionFormat.from("BW,r1,r2,r3"),
|
||||||
|
Opcode.SGE to InstructionFormat.from("BW,r1,r2,r3"),
|
||||||
|
Opcode.SGES to InstructionFormat.from("BW,r1,r2,r3"),
|
||||||
|
Opcode.INC to InstructionFormat.from("BW,r1"),
|
||||||
|
Opcode.INCM to InstructionFormat.from("BW,v"),
|
||||||
|
Opcode.DEC to InstructionFormat.from("BW,r1"),
|
||||||
|
Opcode.DECM to InstructionFormat.from("BW,v"),
|
||||||
|
Opcode.NEG to InstructionFormat.from("BW,r1 | F,fr1"),
|
||||||
|
Opcode.ADD to InstructionFormat.from("BW,r1,r2,r3 | F,fr1,fr2,fr3"),
|
||||||
|
Opcode.SUB to InstructionFormat.from("BW,r1,r2,r3 | F,fr1,fr2,fr3"),
|
||||||
|
Opcode.MUL to InstructionFormat.from("BW,r1,r2,r3 | F,fr1,fr2,fr3"),
|
||||||
|
Opcode.DIV to InstructionFormat.from("BW,r1,r2,r3 | F,fr1,fr2,fr3"),
|
||||||
|
Opcode.SQRT to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
||||||
|
Opcode.SGN to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
||||||
|
Opcode.RND to InstructionFormat.from("BW,r1 | F,fr1"),
|
||||||
|
Opcode.MOD to InstructionFormat.from("BW,r1,r2,r3"),
|
||||||
|
Opcode.CMP to InstructionFormat.from("BW,r1,r2"),
|
||||||
|
Opcode.EXT to InstructionFormat.from("BW,r1"),
|
||||||
|
Opcode.EXTS to InstructionFormat.from("BW,r1"),
|
||||||
|
Opcode.AND to InstructionFormat.from("BW,r1,r2,r3"),
|
||||||
|
Opcode.OR to InstructionFormat.from("BW,r1,r2,r3"),
|
||||||
|
Opcode.XOR to InstructionFormat.from("BW,r1,r2,r3"),
|
||||||
|
Opcode.ASRX to InstructionFormat.from("BW,r1,r2,r3"),
|
||||||
|
Opcode.LSRX to InstructionFormat.from("BW,r1,r2,r3"),
|
||||||
|
Opcode.LSLX to InstructionFormat.from("BW,r1,r2,r3"),
|
||||||
|
Opcode.ASR to InstructionFormat.from("BW,r1"),
|
||||||
|
Opcode.LSR to InstructionFormat.from("BW,r1"),
|
||||||
|
Opcode.LSL to InstructionFormat.from("BW,r1"),
|
||||||
|
Opcode.ROR to InstructionFormat.from("BW,r1"),
|
||||||
|
Opcode.ROXR to InstructionFormat.from("BW,r1"),
|
||||||
|
Opcode.ROL to InstructionFormat.from("BW,r1"),
|
||||||
|
Opcode.ROXL to InstructionFormat.from("BW,r1"),
|
||||||
|
|
||||||
Opcode.JUMP to InstructionFormat(NN, false, false, false, true ),
|
Opcode.FFROMUB to InstructionFormat.from("F,fr1,r1"),
|
||||||
Opcode.JUMPI to InstructionFormat(NN, true, false, false, false),
|
Opcode.FFROMSB to InstructionFormat.from("F,fr1,r1"),
|
||||||
Opcode.CALL to InstructionFormat(NN, false, false, false, true ),
|
Opcode.FFROMUW to InstructionFormat.from("F,fr1,r1"),
|
||||||
Opcode.CALLI to InstructionFormat(NN, true, false, false, false),
|
Opcode.FFROMSW to InstructionFormat.from("F,fr1,r1"),
|
||||||
Opcode.SYSCALL to InstructionFormat(NN, false, false, false, true ),
|
Opcode.FTOUB to InstructionFormat.from("F,r1,fr1"),
|
||||||
Opcode.RETURN to InstructionFormat(NN, false, false, false, false),
|
Opcode.FTOSB to InstructionFormat.from("F,r1,fr1"),
|
||||||
|
Opcode.FTOUW to InstructionFormat.from("F,r1,fr1"),
|
||||||
|
Opcode.FTOSW to InstructionFormat.from("F,r1,fr1"),
|
||||||
|
|
||||||
Opcode.BSTCC to InstructionFormat(NN, false, false,false, true ),
|
Opcode.MSIG to InstructionFormat.from("BW,r1,r2"),
|
||||||
Opcode.BSTCS to InstructionFormat(NN, false, false,false, true ),
|
Opcode.PUSH to InstructionFormat.from("BW,r1"),
|
||||||
Opcode.BSTEQ to InstructionFormat(NN, false, false,false, true ),
|
Opcode.POP to InstructionFormat.from("BW,r1"),
|
||||||
Opcode.BSTNE to InstructionFormat(NN, false, false,false, true ),
|
Opcode.CONCAT to InstructionFormat.from("BW,r1,r2,r3"),
|
||||||
Opcode.BSTNEG to InstructionFormat(NN, false, false,false, true ),
|
Opcode.CLC to InstructionFormat.from("N"),
|
||||||
Opcode.BSTPOS to InstructionFormat(NN, false, false,false, true ),
|
Opcode.SEC to InstructionFormat.from("N"),
|
||||||
Opcode.BZ to InstructionFormat(BW, true, false, false, true ),
|
Opcode.BREAKPOINT to InstructionFormat.from("N"),
|
||||||
Opcode.BNZ to InstructionFormat(BW, true, false, false, true ),
|
|
||||||
Opcode.BEQ to InstructionFormat(BW, true, true, false, true ),
|
|
||||||
Opcode.BNE to InstructionFormat(BW, true, true, false, true ),
|
|
||||||
Opcode.BLT to InstructionFormat(BW, true, true, false, true ),
|
|
||||||
Opcode.BLTS to InstructionFormat(BW, true, true, false, true ),
|
|
||||||
Opcode.BGT to InstructionFormat(BW, true, true, false, true ),
|
|
||||||
Opcode.BGTS to InstructionFormat(BW, true, true, false, true ),
|
|
||||||
Opcode.BLE to InstructionFormat(BW, true, true, false, true ),
|
|
||||||
Opcode.BLES to InstructionFormat(BW, true, true, false, true ),
|
|
||||||
Opcode.BGE to InstructionFormat(BW, true, true, false, true ),
|
|
||||||
Opcode.BGES to InstructionFormat(BW, true, true, false, true ),
|
|
||||||
Opcode.SEQ to InstructionFormat(BW, true, true, true, false),
|
|
||||||
Opcode.SNE to InstructionFormat(BW, true, true, true, false),
|
|
||||||
Opcode.SLT to InstructionFormat(BW, true, true, true, false),
|
|
||||||
Opcode.SLTS to InstructionFormat(BW, true, true, true, false),
|
|
||||||
Opcode.SGT to InstructionFormat(BW, true, true, true, false),
|
|
||||||
Opcode.SGTS to InstructionFormat(BW, true, true, true, false),
|
|
||||||
Opcode.SLE to InstructionFormat(BW, true, true, true, false),
|
|
||||||
Opcode.SLES to InstructionFormat(BW, true, true, true, false),
|
|
||||||
Opcode.SGE to InstructionFormat(BW, true, true, true, false),
|
|
||||||
Opcode.SGES to InstructionFormat(BW, true, true, true, false),
|
|
||||||
|
|
||||||
Opcode.INC to InstructionFormat(BW, true, false, false, false),
|
|
||||||
Opcode.INCM to InstructionFormat(BW, false, false, false, true ),
|
|
||||||
Opcode.DEC to InstructionFormat(BW, true, false, false, false),
|
|
||||||
Opcode.DECM to InstructionFormat(BW, false, false, false, true ),
|
|
||||||
Opcode.NEG to InstructionFormat(BW, true, false, false, false),
|
|
||||||
Opcode.ADD to InstructionFormat(BW, true, true, true, false),
|
|
||||||
Opcode.SUB to InstructionFormat(BW, true, true, true, false),
|
|
||||||
Opcode.MUL to InstructionFormat(BW, true, true, true, false),
|
|
||||||
Opcode.DIV to InstructionFormat(BW, true, true, true, false),
|
|
||||||
Opcode.MOD to InstructionFormat(BW, true, true, true, false),
|
|
||||||
Opcode.SQRT to InstructionFormat(BW, true, true, false, false),
|
|
||||||
Opcode.SGN to InstructionFormat(BW, true, true, false, false),
|
|
||||||
Opcode.CMP to InstructionFormat(BW, true, true, false, false),
|
|
||||||
Opcode.EXT to InstructionFormat(BW, true, false, false, false),
|
|
||||||
Opcode.EXTS to InstructionFormat(BW, true, false, false, false),
|
|
||||||
|
|
||||||
Opcode.AND to InstructionFormat(BW, true, true, true, false),
|
|
||||||
Opcode.OR to InstructionFormat(BW, true, true, true, false),
|
|
||||||
Opcode.XOR to InstructionFormat(BW, true, true, true, false),
|
|
||||||
Opcode.ASRX to InstructionFormat(BW, true, true, true, false),
|
|
||||||
Opcode.LSRX to InstructionFormat(BW, true, true, true, false),
|
|
||||||
Opcode.LSLX to InstructionFormat(BW, true, true, true, false),
|
|
||||||
Opcode.ASR to InstructionFormat(BW, true, false, false, false),
|
|
||||||
Opcode.LSR to InstructionFormat(BW, true, false, false, false),
|
|
||||||
Opcode.LSL to InstructionFormat(BW, true, false, false, false),
|
|
||||||
Opcode.ROR to InstructionFormat(BW, true, false, false, false),
|
|
||||||
Opcode.ROXR to InstructionFormat(BW, true, false, false, false),
|
|
||||||
Opcode.ROL to InstructionFormat(BW, true, false, false, false),
|
|
||||||
Opcode.ROXL to InstructionFormat(BW, true, false, false, false),
|
|
||||||
|
|
||||||
Opcode.MSIG to InstructionFormat(BW, true, true, false, false),
|
|
||||||
Opcode.PUSH to InstructionFormat(BW, true, false, false, false),
|
|
||||||
Opcode.POP to InstructionFormat(BW, true, false, false, false),
|
|
||||||
Opcode.CONCAT to InstructionFormat(BW, true, true, true, false),
|
|
||||||
Opcode.CLC to InstructionFormat(NN, false, false, false, false),
|
|
||||||
Opcode.SEC to InstructionFormat(NN, false, false, false, false),
|
|
||||||
Opcode.BREAKPOINT to InstructionFormat(NN, false, false, false, false)
|
|
||||||
)
|
)
|
||||||
|
@ -27,11 +27,11 @@ class Memory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getUW(address: Int): UShort {
|
fun getUW(address: Int): UShort {
|
||||||
return (256u*mem[address+1] + mem[address]).toUShort()
|
return (mem[address] + 256u*mem[address+1]).toUShort()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSW(address: Int): Short {
|
fun getSW(address: Int): Short {
|
||||||
return (mem[address+1].toInt()*256 + mem[address].toInt()).toShort()
|
return (mem[address].toInt() + mem[address+1].toInt()*256).toShort()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setUW(address: Int, value: UShort) {
|
fun setUW(address: Int, value: UShort) {
|
||||||
@ -45,6 +45,22 @@ class Memory {
|
|||||||
mem[address] = uv.toUByte()
|
mem[address] = uv.toUByte()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setFloat(address: Int, value: Float) {
|
||||||
|
var bits = value.toBits()
|
||||||
|
mem[address] = bits.toUByte()
|
||||||
|
bits = bits ushr 8
|
||||||
|
mem[address+1] = bits.toUByte()
|
||||||
|
bits = bits ushr 8
|
||||||
|
mem[address+2] = bits.toUByte()
|
||||||
|
bits = bits ushr 8
|
||||||
|
mem[address+3] = bits.toUByte()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getFloat(address: Int): Float {
|
||||||
|
val bits = mem[address] + 256u*mem[address+1] + 65536u*mem[address+2] + 16777216u*mem[address+3]
|
||||||
|
return Float.fromBits(bits.toInt())
|
||||||
|
}
|
||||||
|
|
||||||
// for now, no LONG 32-bits and no FLOAT support.
|
// for now, no LONG 32-bits and no FLOAT support.
|
||||||
// fun getL(address: Int): UInt {
|
// fun getL(address: Int): UInt {
|
||||||
// return mem[address+3] + 256u*mem[address+2] + 65536u*mem[address+1] + 16777216u*mem[address]
|
// return mem[address+3] + 256u*mem[address+2] + 65536u*mem[address+1] + 16777216u*mem[address]
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
package prog8.vm
|
package prog8.vm
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 65536 virtual registers of 16 bits wide.
|
* 65536 virtual integer registers of 16 bits wide.
|
||||||
|
* 65536 virtual float registers of 32 bits wide.
|
||||||
*/
|
*/
|
||||||
class Registers {
|
class Registers {
|
||||||
private val registers = Array<UShort>(65536) { 0u }
|
private val registers = Array<UShort>(65536) { 0u }
|
||||||
|
private val floatRegisters = Array<Float>(65535) { 0f }
|
||||||
|
|
||||||
fun reset() {
|
fun reset() {
|
||||||
registers.fill(0u)
|
registers.fill(0u)
|
||||||
|
floatRegisters.fill(0f)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setUB(reg: Int, value: UByte) {
|
fun setUB(reg: Int, value: UByte) {
|
||||||
@ -33,4 +36,10 @@ class Registers {
|
|||||||
fun getUW(reg: Int) = registers[reg]
|
fun getUW(reg: Int) = registers[reg]
|
||||||
|
|
||||||
fun getSW(reg: Int) = registers[reg].toShort()
|
fun getSW(reg: Int) = registers[reg].toShort()
|
||||||
|
|
||||||
|
fun getFloat(reg:Int) = floatRegisters[reg]
|
||||||
|
|
||||||
|
fun setFloat(reg:Int, value: Float) {
|
||||||
|
floatRegisters[reg] = value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package prog8.vm
|
package prog8.vm
|
||||||
|
|
||||||
import kotlin.math.*
|
import kotlin.math.*
|
||||||
import kotlin.random.Random
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
SYSCALLS:
|
SYSCALLS:
|
||||||
@ -17,8 +16,8 @@ SYSCALLS:
|
|||||||
8 = gfx_enable ; enable graphics window r0.b = 0 -> lores 320x240, r0.b = 1 -> hires 640x480
|
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
|
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
|
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
|
11 = set_carry status flag
|
||||||
12 = rndw ; random WORD
|
12 = clear_carry status flag
|
||||||
13 = wait ; wait certain amount of jiffies (1/60 sec)
|
13 = wait ; wait certain amount of jiffies (1/60 sec)
|
||||||
14 = waitvsync ; wait on vsync
|
14 = waitvsync ; wait on vsync
|
||||||
15 = sort_ubyte array
|
15 = sort_ubyte array
|
||||||
@ -41,8 +40,6 @@ SYSCALLS:
|
|||||||
32 = all_word array
|
32 = all_word array
|
||||||
33 = reverse_bytes array
|
33 = reverse_bytes array
|
||||||
34 = reverse_words array
|
34 = reverse_words array
|
||||||
35 = set_carry status flag
|
|
||||||
36 = clear_carry status flag
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enum class Syscall {
|
enum class Syscall {
|
||||||
@ -57,8 +54,8 @@ enum class Syscall {
|
|||||||
GFX_ENABLE,
|
GFX_ENABLE,
|
||||||
GFX_CLEAR,
|
GFX_CLEAR,
|
||||||
GFX_PLOT,
|
GFX_PLOT,
|
||||||
RND,
|
SET_CARRY,
|
||||||
RNDW,
|
CLEAR_CARRY,
|
||||||
WAIT,
|
WAIT,
|
||||||
WAITVSYNC,
|
WAITVSYNC,
|
||||||
SORT_UBYTE,
|
SORT_UBYTE,
|
||||||
@ -80,9 +77,7 @@ enum class Syscall {
|
|||||||
ALL_BYTE,
|
ALL_BYTE,
|
||||||
ALL_WORD,
|
ALL_WORD,
|
||||||
REVERSE_BYTES,
|
REVERSE_BYTES,
|
||||||
REVERSE_WORDS,
|
REVERSE_WORDS
|
||||||
SET_CARRY,
|
|
||||||
CLEAR_CARRY
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object SysCalls {
|
object SysCalls {
|
||||||
@ -129,12 +124,6 @@ object SysCalls {
|
|||||||
Syscall.GFX_ENABLE -> vm.gfx_enable()
|
Syscall.GFX_ENABLE -> vm.gfx_enable()
|
||||||
Syscall.GFX_CLEAR -> vm.gfx_clear()
|
Syscall.GFX_CLEAR -> vm.gfx_clear()
|
||||||
Syscall.GFX_PLOT -> vm.gfx_plot()
|
Syscall.GFX_PLOT -> vm.gfx_plot()
|
||||||
Syscall.RND -> {
|
|
||||||
vm.registers.setUB(0, Random.nextInt().toUByte())
|
|
||||||
}
|
|
||||||
Syscall.RNDW -> {
|
|
||||||
vm.registers.setUW(0, Random.nextInt().toUShort())
|
|
||||||
}
|
|
||||||
Syscall.WAIT -> {
|
Syscall.WAIT -> {
|
||||||
val millis = vm.registers.getUW(0).toLong() * 1000/60
|
val millis = vm.registers.getUW(0).toLong() * 1000/60
|
||||||
Thread.sleep(millis)
|
Thread.sleep(millis)
|
||||||
|
@ -6,6 +6,7 @@ import java.util.*
|
|||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
import kotlin.math.sign
|
import kotlin.math.sign
|
||||||
import kotlin.math.sqrt
|
import kotlin.math.sqrt
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
|
||||||
class ProgramExitException(val status: Int): Exception()
|
class ProgramExitException(val status: Int): Exception()
|
||||||
@ -143,9 +144,10 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
Opcode.MUL -> InsMUL(ins)
|
Opcode.MUL -> InsMUL(ins)
|
||||||
Opcode.DIV -> InsDIV(ins)
|
Opcode.DIV -> InsDIV(ins)
|
||||||
Opcode.MOD -> InsMOD(ins)
|
Opcode.MOD -> InsMOD(ins)
|
||||||
Opcode.SQRT -> InsSQRT(ins)
|
|
||||||
Opcode.SGN -> InsSGN(ins)
|
Opcode.SGN -> InsSGN(ins)
|
||||||
Opcode.CMP -> InsCMP(ins)
|
Opcode.CMP -> InsCMP(ins)
|
||||||
|
Opcode.RND -> InsRND(ins)
|
||||||
|
Opcode.SQRT -> InsSQRT(ins)
|
||||||
Opcode.EXT -> InsEXT(ins)
|
Opcode.EXT -> InsEXT(ins)
|
||||||
Opcode.EXTS -> InsEXTS(ins)
|
Opcode.EXTS -> InsEXTS(ins)
|
||||||
Opcode.AND -> InsAND(ins)
|
Opcode.AND -> InsAND(ins)
|
||||||
@ -191,6 +193,9 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
valueStack.push((value and 255u).toUByte())
|
valueStack.push((value and 255u).toUByte())
|
||||||
valueStack.push((value.toInt() ushr 8).toUByte())
|
valueStack.push((value.toInt() ushr 8).toUByte())
|
||||||
}
|
}
|
||||||
|
VmDataType.FLOAT -> {
|
||||||
|
throw IllegalArgumentException("can't PUSH a float")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pc++
|
pc++
|
||||||
}
|
}
|
||||||
@ -205,6 +210,9 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
val lsb = valueStack.pop()
|
val lsb = valueStack.pop()
|
||||||
(msb.toInt() shl 8) + lsb.toInt()
|
(msb.toInt() shl 8) + lsb.toInt()
|
||||||
}
|
}
|
||||||
|
VmDataType.FLOAT -> {
|
||||||
|
throw IllegalArgumentException("can't POP a float")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
setResultReg(i.reg1!!, value, i.type)
|
setResultReg(i.reg1!!, value, i.type)
|
||||||
pc++
|
pc++
|
||||||
@ -649,14 +657,6 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
pc++
|
pc++
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun InsSQRT(i: Instruction) {
|
|
||||||
when(i.type!!) {
|
|
||||||
VmDataType.BYTE -> registers.setUB(i.reg1!!, sqrt(registers.getUB(i.reg2!!).toDouble()).toInt().toUByte())
|
|
||||||
VmDataType.WORD -> registers.setUB(i.reg1!!, sqrt(registers.getUW(i.reg2!!).toDouble()).toInt().toUByte())
|
|
||||||
}
|
|
||||||
pc++
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun InsSGN(i: Instruction) {
|
private fun InsSGN(i: Instruction) {
|
||||||
when(i.type!!) {
|
when(i.type!!) {
|
||||||
VmDataType.BYTE -> registers.setSB(i.reg1!!, registers.getSB(i.reg2!!).toInt().sign.toByte())
|
VmDataType.BYTE -> registers.setSB(i.reg1!!, registers.getSB(i.reg2!!).toInt().sign.toByte())
|
||||||
@ -665,6 +665,24 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
pc++
|
pc++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun InsSQRT(i: Instruction) {
|
||||||
|
when(i.type!!) {
|
||||||
|
VmDataType.BYTE -> registers.setUB(i.reg1!!, sqrt(registers.getUB(i.reg2!!).toDouble()).toInt().toUByte())
|
||||||
|
VmDataType.WORD -> registers.setUB(i.reg1!!, sqrt(registers.getUW(i.reg2!!).toDouble()).toInt().toUByte())
|
||||||
|
VmDataType.FLOAT -> registers.setFloat(i.fpReg1!!, sqrt(registers.getFloat(i.fpReg2!!)))
|
||||||
|
}
|
||||||
|
pc++
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun InsRND(i: Instruction) {
|
||||||
|
when(i.type!!) {
|
||||||
|
VmDataType.BYTE -> registers.setUB(i.reg1!!, Random.nextInt().toUByte())
|
||||||
|
VmDataType.WORD -> registers.setUW(i.reg1!!, Random.nextInt().toUShort())
|
||||||
|
VmDataType.FLOAT -> registers.setFloat(i.fpReg1!!, Random.nextFloat())
|
||||||
|
}
|
||||||
|
pc++
|
||||||
|
}
|
||||||
|
|
||||||
private fun InsCMP(i: Instruction) {
|
private fun InsCMP(i: Instruction) {
|
||||||
val comparison: Int
|
val comparison: Int
|
||||||
when(i.type!!) {
|
when(i.type!!) {
|
||||||
@ -680,6 +698,9 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
comparison = reg1.toInt() - reg2.toInt()
|
comparison = reg1.toInt() - reg2.toInt()
|
||||||
statusNegative = (comparison and 0x8000)==0x8000
|
statusNegative = (comparison and 0x8000)==0x8000
|
||||||
}
|
}
|
||||||
|
VmDataType.FLOAT -> {
|
||||||
|
TODO("CMP float")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if(comparison==0){
|
if(comparison==0){
|
||||||
statusZero = true
|
statusZero = true
|
||||||
@ -891,6 +912,9 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
orig.rotateRight(1)
|
orig.rotateRight(1)
|
||||||
registers.setUW(i.reg1, rotated)
|
registers.setUW(i.reg1, rotated)
|
||||||
}
|
}
|
||||||
|
VmDataType.FLOAT -> {
|
||||||
|
throw IllegalArgumentException("can't ROR a float")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pc++
|
pc++
|
||||||
statusCarry = newStatusCarry
|
statusCarry = newStatusCarry
|
||||||
@ -919,6 +943,9 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
orig.rotateLeft(1)
|
orig.rotateLeft(1)
|
||||||
registers.setUW(i.reg1, rotated)
|
registers.setUW(i.reg1, rotated)
|
||||||
}
|
}
|
||||||
|
VmDataType.FLOAT -> {
|
||||||
|
throw IllegalArgumentException("can't ROL a float")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pc++
|
pc++
|
||||||
statusCarry = newStatusCarry
|
statusCarry = newStatusCarry
|
||||||
@ -952,6 +979,9 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
return when(i.type) {
|
return when(i.type) {
|
||||||
VmDataType.BYTE -> Pair(registers.getSB(i.reg1!!).toInt(), registers.getSB(i.reg2!!).toInt())
|
VmDataType.BYTE -> Pair(registers.getSB(i.reg1!!).toInt(), registers.getSB(i.reg2!!).toInt())
|
||||||
VmDataType.WORD -> Pair(registers.getSW(i.reg1!!).toInt(), registers.getSW(i.reg2!!).toInt())
|
VmDataType.WORD -> Pair(registers.getSW(i.reg1!!).toInt(), registers.getSW(i.reg2!!).toInt())
|
||||||
|
VmDataType.FLOAT -> {
|
||||||
|
throw IllegalArgumentException("can't use float here")
|
||||||
|
}
|
||||||
null -> throw IllegalArgumentException("need type for branch instruction")
|
null -> throw IllegalArgumentException("need type for branch instruction")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -960,6 +990,9 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
return when(i.type) {
|
return when(i.type) {
|
||||||
VmDataType.BYTE -> Pair(registers.getUB(i.reg1!!).toUInt(), registers.getUB(i.reg2!!).toUInt())
|
VmDataType.BYTE -> Pair(registers.getUB(i.reg1!!).toUInt(), registers.getUB(i.reg2!!).toUInt())
|
||||||
VmDataType.WORD -> Pair(registers.getUW(i.reg1!!).toUInt(), registers.getUW(i.reg2!!).toUInt())
|
VmDataType.WORD -> Pair(registers.getUW(i.reg1!!).toUInt(), registers.getUW(i.reg2!!).toUInt())
|
||||||
|
VmDataType.FLOAT -> {
|
||||||
|
throw IllegalArgumentException("can't use float here")
|
||||||
|
}
|
||||||
null -> throw IllegalArgumentException("need type for branch instruction")
|
null -> throw IllegalArgumentException("need type for branch instruction")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -968,6 +1001,9 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
return when(i.type) {
|
return when(i.type) {
|
||||||
VmDataType.BYTE -> Pair(registers.getUB(i.reg2!!).toUInt(), registers.getUB(i.reg3!!).toUInt())
|
VmDataType.BYTE -> Pair(registers.getUB(i.reg2!!).toUInt(), registers.getUB(i.reg3!!).toUInt())
|
||||||
VmDataType.WORD -> Pair(registers.getUW(i.reg2!!).toUInt(), registers.getUW(i.reg3!!).toUInt())
|
VmDataType.WORD -> Pair(registers.getUW(i.reg2!!).toUInt(), registers.getUW(i.reg3!!).toUInt())
|
||||||
|
VmDataType.FLOAT -> {
|
||||||
|
throw IllegalArgumentException("can't use float here")
|
||||||
|
}
|
||||||
null -> throw IllegalArgumentException("need type for logical instruction")
|
null -> throw IllegalArgumentException("need type for logical instruction")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -976,6 +1012,9 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
return when(i.type) {
|
return when(i.type) {
|
||||||
VmDataType.BYTE -> Pair(registers.getSB(i.reg2!!).toInt(), registers.getSB(i.reg3!!).toInt())
|
VmDataType.BYTE -> Pair(registers.getSB(i.reg2!!).toInt(), registers.getSB(i.reg3!!).toInt())
|
||||||
VmDataType.WORD -> Pair(registers.getSW(i.reg2!!).toInt(), registers.getSW(i.reg3!!).toInt())
|
VmDataType.WORD -> Pair(registers.getSW(i.reg2!!).toInt(), registers.getSW(i.reg3!!).toInt())
|
||||||
|
VmDataType.FLOAT -> {
|
||||||
|
throw IllegalArgumentException("can't use float here")
|
||||||
|
}
|
||||||
null -> throw IllegalArgumentException("need type for logical instruction")
|
null -> throw IllegalArgumentException("need type for logical instruction")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -985,6 +1024,9 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
return when(ins.type) {
|
return when(ins.type) {
|
||||||
VmDataType.BYTE -> Triple(ins.reg1!!, registers.getSB(ins.reg2!!).toInt(), registers.getSB(ins.reg3!!).toInt())
|
VmDataType.BYTE -> Triple(ins.reg1!!, registers.getSB(ins.reg2!!).toInt(), registers.getSB(ins.reg3!!).toInt())
|
||||||
VmDataType.WORD -> Triple(ins.reg1!!, registers.getSW(ins.reg2!!).toInt(), registers.getSW(ins.reg3!!).toInt())
|
VmDataType.WORD -> Triple(ins.reg1!!, registers.getSW(ins.reg2!!).toInt(), registers.getSW(ins.reg3!!).toInt())
|
||||||
|
VmDataType.FLOAT -> {
|
||||||
|
throw IllegalArgumentException("can't use float here")
|
||||||
|
}
|
||||||
null -> throw IllegalArgumentException("need type for branch instruction")
|
null -> throw IllegalArgumentException("need type for branch instruction")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -993,6 +1035,9 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
return when(ins.type) {
|
return when(ins.type) {
|
||||||
VmDataType.BYTE -> Triple(ins.reg1!!, registers.getUB(ins.reg2!!).toUInt(), registers.getUB(ins.reg3!!).toUInt())
|
VmDataType.BYTE -> Triple(ins.reg1!!, registers.getUB(ins.reg2!!).toUInt(), registers.getUB(ins.reg3!!).toUInt())
|
||||||
VmDataType.WORD -> Triple(ins.reg1!!, registers.getUW(ins.reg2!!).toUInt(), registers.getUW(ins.reg3!!).toUInt())
|
VmDataType.WORD -> Triple(ins.reg1!!, registers.getUW(ins.reg2!!).toUInt(), registers.getUW(ins.reg3!!).toUInt())
|
||||||
|
VmDataType.FLOAT -> {
|
||||||
|
throw IllegalArgumentException("can't use float here")
|
||||||
|
}
|
||||||
null -> throw IllegalArgumentException("need type for branch instruction")
|
null -> throw IllegalArgumentException("need type for branch instruction")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,13 @@ class TestMemory: FunSpec({
|
|||||||
mem.getUB(1001) shouldBe 0xeau
|
mem.getUB(1001) shouldBe 0xeau
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test("32 bits float access") {
|
||||||
|
val mem = Memory()
|
||||||
|
mem.getFloat(1000) shouldBe 0.0
|
||||||
|
mem.setFloat(1000, -9.876543f)
|
||||||
|
mem.getFloat(1000) shouldBe -9.876543f
|
||||||
|
}
|
||||||
|
|
||||||
test("setstring and getstring") {
|
test("setstring and getstring") {
|
||||||
val mem = Memory()
|
val mem = Memory()
|
||||||
mem.setString(1000, "******************", false)
|
mem.setString(1000, "******************", false)
|
||||||
|
Loading…
Reference in New Issue
Block a user