mirror of
https://github.com/irmen/prog8.git
synced 2024-11-26 11:49:22 +00:00
working on vm
This commit is contained in:
parent
ed30108961
commit
e41d6787bb
@ -161,6 +161,12 @@ class StStaticVariable(name: String,
|
||||
require(arraysize == initialArrayValue.size)
|
||||
if(arraysize!=null || initialArrayValue!=null)
|
||||
require(initialStringValue==null && initialNumericValue==null)
|
||||
if(initialNumericValue!=null)
|
||||
require(dt in NumericDatatypes)
|
||||
if(initialArrayValue!=null || arraysize!=null)
|
||||
require(dt in ArrayDatatypes)
|
||||
if(initialStringValue!=null)
|
||||
require(dt == DataType.STR)
|
||||
}
|
||||
|
||||
override fun printProperties() {
|
||||
|
@ -58,8 +58,8 @@ class PtBinaryExpression(val operator: String, type: DataType, position: Positio
|
||||
class PtContainmentCheck(position: Position): PtExpression(DataType.UBYTE, position) {
|
||||
val element: PtExpression
|
||||
get() = children[0] as PtExpression
|
||||
val iterable: PtExpression
|
||||
get() = children[0] as PtExpression
|
||||
val iterable: PtIdentifier
|
||||
get() = children[0] as PtIdentifier
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,10 +1,12 @@
|
||||
package prog8.codegen.virtual
|
||||
|
||||
import prog8.code.StStaticVariable
|
||||
import prog8.code.StSub
|
||||
import prog8.code.ast.*
|
||||
import prog8.code.core.AssemblyError
|
||||
import prog8.code.core.DataType
|
||||
import prog8.code.core.PassByValueDatatypes
|
||||
import prog8.code.core.SignedDatatypes
|
||||
import prog8.vm.Instruction
|
||||
import prog8.vm.Opcode
|
||||
import prog8.vm.VmDataType
|
||||
@ -54,7 +56,7 @@ internal class ExpressionGen(val codeGen: CodeGen) {
|
||||
is PtBinaryExpression -> code += translate(expr, resultRegister, regUsage)
|
||||
is PtBuiltinFunctionCall -> code += translate(expr, resultRegister, regUsage)
|
||||
is PtFunctionCall -> code += translate(expr, resultRegister, regUsage)
|
||||
is PtContainmentCheck -> TODO()
|
||||
is PtContainmentCheck -> code += translate(expr, resultRegister, regUsage)
|
||||
is PtPipe -> TODO()
|
||||
is PtRange,
|
||||
is PtArrayLiteral,
|
||||
@ -64,6 +66,21 @@ internal class ExpressionGen(val codeGen: CodeGen) {
|
||||
return code
|
||||
}
|
||||
|
||||
private fun translate(check: PtContainmentCheck, resultRegister: Int, regUsage: RegisterUsage): VmCodeChunk {
|
||||
val iterableIdent = check.iterable
|
||||
val iterable = codeGen.symbolTable.flat.getValue(iterableIdent.targetName) as StStaticVariable
|
||||
when(iterable.dt) {
|
||||
DataType.STR -> println("CONTAINMENT CHECK ${check.element} in string $iterable ${iterable.initialStringValue}")
|
||||
DataType.ARRAY_UB -> println("CONTAINMENT CHECK ${check.element} in UB-array $iterable ${iterable.initialArrayValue}")
|
||||
DataType.ARRAY_B -> println("CONTAINMENT CHECK ${check.element} in B-array $iterable ${iterable.initialArrayValue}")
|
||||
DataType.ARRAY_UW -> println("CONTAINMENT CHECK ${check.element} in UW-array $iterable ${iterable.initialArrayValue}")
|
||||
DataType.ARRAY_W -> println("CONTAINMENT CHECK ${check.element} in W-array $iterable ${iterable.initialArrayValue}")
|
||||
DataType.ARRAY_F -> TODO("containment check in float-array")
|
||||
else -> throw AssemblyError("weird iterable dt ${iterable.dt} for ${iterableIdent.targetName}")
|
||||
}
|
||||
return VmCodeChunk()
|
||||
}
|
||||
|
||||
private fun translate(arrayIx: PtArrayIndexer, resultRegister: Int, regUsage: RegisterUsage): VmCodeChunk {
|
||||
val eltSize = codeGen.program.memsizer.memorySize(arrayIx.type)
|
||||
val vmDt = codeGen.vmType(arrayIx.type)
|
||||
@ -194,9 +211,9 @@ internal class ExpressionGen(val codeGen: CodeGen) {
|
||||
val code = VmCodeChunk()
|
||||
val leftResultReg = regUsage.nextFree()
|
||||
val rightResultReg = regUsage.nextFree()
|
||||
// TODO: optimized codegen when left or right operand is known 0 or 1 or whatever.
|
||||
val leftCode = translateExpression(binExpr.left, leftResultReg, regUsage)
|
||||
val rightCode = translateExpression(binExpr.right, rightResultReg, regUsage)
|
||||
// TODO: optimized codegen when left or right operand is known 0 or 1 or whatever.
|
||||
code += leftCode
|
||||
code += rightCode
|
||||
val vmDt = codeGen.vmType(binExpr.type)
|
||||
@ -231,7 +248,28 @@ internal class ExpressionGen(val codeGen: CodeGen) {
|
||||
">>" -> {
|
||||
code += VmCodeInstruction(Instruction(Opcode.LSR, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
|
||||
}
|
||||
// TODO the other operators: "==", "!=", "<", ">", "<=", ">="
|
||||
"==" -> {
|
||||
code += VmCodeInstruction(Instruction(Opcode.SEQ, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
|
||||
}
|
||||
"!=" -> {
|
||||
code += VmCodeInstruction(Instruction(Opcode.SNE, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
|
||||
}
|
||||
"<" -> {
|
||||
val ins = if(binExpr.type in SignedDatatypes) Opcode.SLTS else Opcode.SLT
|
||||
code += VmCodeInstruction(Instruction(ins, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
|
||||
}
|
||||
">" -> {
|
||||
val ins = if(binExpr.type in SignedDatatypes) Opcode.SGTS else Opcode.SGT
|
||||
code += VmCodeInstruction(Instruction(ins, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
|
||||
}
|
||||
"<=" -> {
|
||||
val ins = if(binExpr.type in SignedDatatypes) Opcode.SLES else Opcode.SLE
|
||||
code += VmCodeInstruction(Instruction(ins, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
|
||||
}
|
||||
">=" -> {
|
||||
val ins = if(binExpr.type in SignedDatatypes) Opcode.SGES else Opcode.SGE
|
||||
code += VmCodeInstruction(Instruction(ins, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
|
||||
}
|
||||
else -> TODO("operator ${binExpr.operator}")
|
||||
}
|
||||
return code
|
||||
|
@ -6,6 +6,8 @@ import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.*
|
||||
import prog8.ast.walk.IAstVisitor
|
||||
import prog8.code.*
|
||||
import prog8.code.core.ArrayDatatypes
|
||||
import prog8.code.core.ElementToArrayTypes
|
||||
import prog8.code.core.Position
|
||||
import java.util.*
|
||||
|
||||
@ -59,6 +61,8 @@ internal class SymbolTableMaker: IAstVisitor {
|
||||
val initialString = if(initialStringLit==null) null else Pair(initialStringLit.value, initialStringLit.encoding)
|
||||
val initialArrayLit = decl.value as? ArrayLiteral
|
||||
val initialArray = makeInitialArray(initialArrayLit)
|
||||
if(decl.isArray && decl.datatype !in ArrayDatatypes)
|
||||
throw FatalAstException("array vardecl has mismatched dt ${decl.datatype}")
|
||||
StStaticVariable(decl.name, decl.datatype, initialNumeric, initialString, initialArray, decl.arraysize?.constIndex(), decl.zeropage, decl.position)
|
||||
}
|
||||
VarDeclType.CONST -> StConstant(decl.name, decl.datatype, (decl.value as NumericLiteral).number, decl.position)
|
||||
|
@ -1,4 +1,3 @@
|
||||
%import floats
|
||||
%import textio
|
||||
|
||||
; NOTE: meant to test to virtual machine output target (use -target vitual)
|
||||
@ -7,34 +6,43 @@ main {
|
||||
sub start() {
|
||||
txt.clear_screen()
|
||||
txt.print("Welcome to a prog8 pixel shader :-)\n")
|
||||
float fl = 9.9
|
||||
fl = floats.pow(fl, 3.0)
|
||||
txt.print("fl=")
|
||||
floats.print_f(fl)
|
||||
ubyte bb = 4
|
||||
ubyte[] array = [1,2,3,4,5,6]
|
||||
str tekst = "test"
|
||||
uword ww = 19
|
||||
bb = bb in "teststring"
|
||||
bb++
|
||||
bb = bb in [1,2,3,4,5,6]
|
||||
bb++
|
||||
bb = bb in array
|
||||
bb++
|
||||
bb = bb in tekst
|
||||
txt.print("bb=")
|
||||
txt.print_ub(bb)
|
||||
txt.nl()
|
||||
sys.exit(99)
|
||||
|
||||
|
||||
; syscall1(8, 0) ; enable lo res creen
|
||||
; ubyte shifter
|
||||
;
|
||||
; shifter >>= 1
|
||||
;
|
||||
; repeat {
|
||||
; uword xx
|
||||
; uword yy = 0
|
||||
; repeat 240 {
|
||||
; xx = 0
|
||||
; repeat 320 {
|
||||
; syscall3(10, xx, yy, xx*yy + shifter) ; plot pixel
|
||||
; xx++
|
||||
; }
|
||||
; yy++
|
||||
; }
|
||||
; shifter+=4
|
||||
;
|
||||
; txt.print_ub(shifter)
|
||||
; txt.nl()
|
||||
; }
|
||||
syscall1(8, 0) ; enable lo res creen
|
||||
ubyte shifter
|
||||
|
||||
shifter >>= 1
|
||||
|
||||
repeat {
|
||||
uword xx
|
||||
uword yy = 0
|
||||
repeat 240 {
|
||||
xx = 0
|
||||
repeat 320 {
|
||||
syscall3(10, xx, yy, xx*yy + shifter) ; plot pixel
|
||||
xx++
|
||||
}
|
||||
yy++
|
||||
}
|
||||
shifter+=4
|
||||
|
||||
txt.print_ub(shifter)
|
||||
txt.nl()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -74,6 +74,16 @@ bgt reg1, reg2, value - jump to location in program given by val
|
||||
bgts reg1, reg2, value - jump to location in program given by value, if reg1 > reg2 (signed)
|
||||
bge reg1, reg2, value - jump to location in program given by value, if reg1 >= reg2 (unsigned)
|
||||
bges reg1, reg2, value - jump to location in program given by value, if reg1 >= reg2 (signed)
|
||||
seq reg1, reg2, reg3 - set reg=1 if reg2 == reg3, otherwise set reg1=0
|
||||
sne reg1, reg2, reg3 - set reg=1 if reg2 != reg3, otherwise set reg1=0
|
||||
slt reg1, reg2, reg3 - set reg=1 if reg2 < reg3 (unsigned), otherwise set reg1=0
|
||||
slts reg1, reg2, reg3 - set reg=1 if reg2 < reg3 (signed), otherwise set reg1=0
|
||||
sle reg1, reg2, reg3 - set reg=1 if reg2 <= reg3 (unsigned), otherwise set reg1=0
|
||||
sles reg1, reg2, reg3 - set reg=1 if reg2 <= reg3 (signed), otherwise set reg1=0
|
||||
sgt reg1, reg2, reg3 - set reg=1 if reg2 > reg3 (unsigned), otherwise set reg1=0
|
||||
sgts reg1, reg2, reg3 - set reg=1 if reg2 > reg3 (signed), 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
|
||||
|
||||
TODO: support for the prog8 special branching instructions if_XX (bcc, bcs etc.)
|
||||
but we don't have any 'processor flags' whatsoever in the vm so it's a bit weird
|
||||
@ -159,6 +169,16 @@ enum class Opcode {
|
||||
BLES,
|
||||
BGE,
|
||||
BGES,
|
||||
SEQ,
|
||||
SNE,
|
||||
SLT,
|
||||
SLTS,
|
||||
SGT,
|
||||
SGTS,
|
||||
SLE,
|
||||
SLES,
|
||||
SGE,
|
||||
SGES,
|
||||
|
||||
INC,
|
||||
DEC,
|
||||
@ -271,6 +291,16 @@ val instructionFormats = mutableMapOf(
|
||||
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.DEC to InstructionFormat(BW, true, false, false, false),
|
||||
|
@ -108,6 +108,17 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
Opcode.BLES -> InsBLES(ins)
|
||||
Opcode.BGE -> InsBGEU(ins)
|
||||
Opcode.BGES -> InsBGES(ins)
|
||||
Opcode.SEQ -> InsSEQ(ins)
|
||||
Opcode.SNE -> InsSNE(ins)
|
||||
Opcode.SLT -> InsSLT(ins)
|
||||
Opcode.SLTS -> InsSLTS(ins)
|
||||
Opcode.SGT -> InsSGT(ins)
|
||||
Opcode.SGTS -> InsSGTS(ins)
|
||||
Opcode.SLE -> InsSLE(ins)
|
||||
Opcode.SLES -> InsSLES(ins)
|
||||
Opcode.SGE -> InsSGE(ins)
|
||||
Opcode.SGES -> InsSGES(ins)
|
||||
|
||||
Opcode.INC -> InsINC(ins)
|
||||
Opcode.DEC -> InsDEC(ins)
|
||||
Opcode.NEG -> InsNEG(ins)
|
||||
@ -135,37 +146,33 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
}
|
||||
}
|
||||
|
||||
private fun InsPUSH(ins: Instruction) {
|
||||
private inline fun setResultReg(reg: Int, value: Int, type: VmDataType) {
|
||||
when(type) {
|
||||
VmDataType.BYTE -> registers.setB(reg, value.toUByte())
|
||||
VmDataType.WORD -> registers.setW(reg, value.toUShort())
|
||||
}
|
||||
}
|
||||
|
||||
private fun InsPUSH(i: Instruction) {
|
||||
if(valueStack.size>=128)
|
||||
throw StackOverflowError("valuestack limit 128 exceeded")
|
||||
|
||||
val value = when(ins.type!!) {
|
||||
VmDataType.BYTE -> {
|
||||
registers.getB(ins.reg1!!).toInt()
|
||||
}
|
||||
VmDataType.WORD -> {
|
||||
registers.getW(ins.reg1!!).toInt()
|
||||
}
|
||||
val value = when(i.type!!) {
|
||||
VmDataType.BYTE -> registers.getB(i.reg1!!).toInt()
|
||||
VmDataType.WORD -> registers.getW(i.reg1!!).toInt()
|
||||
}
|
||||
valueStack.push(value)
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsPOP(ins: Instruction) {
|
||||
private fun InsPOP(i: Instruction) {
|
||||
val value = valueStack.pop()
|
||||
when(ins.type!!) {
|
||||
VmDataType.BYTE -> {
|
||||
registers.setB(ins.reg1!!, value.toUByte())
|
||||
}
|
||||
VmDataType.WORD -> {
|
||||
registers.setW(ins.reg1!!, value.toUShort())
|
||||
}
|
||||
}
|
||||
setResultReg(i.reg1!!, value, i.type!!)
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsSYSCALL(ins: Instruction) {
|
||||
val call = Syscall.values()[ins.value!!]
|
||||
private fun InsSYSCALL(i: Instruction) {
|
||||
val call = Syscall.values()[i.value!!]
|
||||
SysCalls.call(call, this)
|
||||
pc++
|
||||
}
|
||||
@ -176,10 +183,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
}
|
||||
|
||||
private fun InsLOAD(i: Instruction) {
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> registers.setB(i.reg1!!, i.value!!.toUByte())
|
||||
VmDataType.WORD -> registers.setW(i.reg1!!, i.value!!.toUShort())
|
||||
}
|
||||
setResultReg(i.reg1!!, i.value!!, i.type!!)
|
||||
pc++
|
||||
}
|
||||
|
||||
@ -198,6 +202,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
}
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsLOADX(i: Instruction) {
|
||||
when (i.type!!) {
|
||||
VmDataType.BYTE -> registers.setB(i.reg1!!, memory.getB(i.value!! + registers.getW(i.reg2!!).toInt()))
|
||||
@ -268,6 +273,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
}
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsSTOREZX(i: Instruction) {
|
||||
when (i.type!!) {
|
||||
VmDataType.BYTE -> memory.setB(registers.getW(i.reg2!!).toInt() + i.value!!, 0u)
|
||||
@ -343,30 +349,6 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun getBranchOperands(i: Instruction): Pair<Int, Int> {
|
||||
return when(i.type) {
|
||||
VmDataType.BYTE -> Pair(registers.getB(i.reg1!!).toInt(), registers.getB(i.reg2!!).toInt())
|
||||
VmDataType.WORD -> Pair(registers.getW(i.reg1!!).toInt(), registers.getW(i.reg2!!).toInt())
|
||||
null -> throw IllegalArgumentException("need type for branch instruction")
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBranchOperandsU(i: Instruction): Pair<UInt, UInt> {
|
||||
return when(i.type) {
|
||||
VmDataType.BYTE -> Pair(registers.getB(i.reg1!!).toUInt(), registers.getB(i.reg2!!).toUInt())
|
||||
VmDataType.WORD -> Pair(registers.getW(i.reg1!!).toUInt(), registers.getW(i.reg2!!).toUInt())
|
||||
null -> throw IllegalArgumentException("need type for branch instruction")
|
||||
}
|
||||
}
|
||||
|
||||
private fun getLogicalOperandsU(i: Instruction): Pair<UInt, UInt> {
|
||||
return when(i.type) {
|
||||
VmDataType.BYTE -> Pair(registers.getB(i.reg2!!).toUInt(), registers.getB(i.reg3!!).toUInt())
|
||||
VmDataType.WORD -> Pair(registers.getW(i.reg2!!).toUInt(), registers.getW(i.reg3!!).toUInt())
|
||||
null -> throw IllegalArgumentException("need type for logical instruction")
|
||||
}
|
||||
}
|
||||
|
||||
private fun InsBNE(i: Instruction) {
|
||||
val (left: Int, right: Int) = getBranchOperands(i)
|
||||
if(left!=right)
|
||||
@ -442,6 +424,78 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsSEQ(i: Instruction) {
|
||||
val (resultReg: Int, left: Int, right: Int) = getSetOnConditionOperands(i)
|
||||
val value = if(left==right) 1 else 0
|
||||
setResultReg(resultReg, value, i.type!!)
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsSNE(i: Instruction) {
|
||||
val (resultReg: Int, left: Int, right: Int) = getSetOnConditionOperands(i)
|
||||
val value = if(left!=right) 1 else 0
|
||||
setResultReg(resultReg, value, i.type!!)
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsSLT(i: Instruction) {
|
||||
val (resultReg, left, right) = getSetOnConditionOperandsU(i)
|
||||
val value = if(left<right) 1 else 0
|
||||
setResultReg(resultReg, value, i.type!!)
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsSLTS(i: Instruction) {
|
||||
val (resultReg, left, right) = getSetOnConditionOperands(i)
|
||||
val value = if(left<right) 1 else 0
|
||||
setResultReg(resultReg, value, i.type!!)
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsSGT(i: Instruction) {
|
||||
val (resultReg, left, right) = getSetOnConditionOperandsU(i)
|
||||
val value = if(left>right) 1 else 0
|
||||
setResultReg(resultReg, value, i.type!!)
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsSGTS(i: Instruction) {
|
||||
val (resultReg, left, right) = getSetOnConditionOperands(i)
|
||||
val value = if(left>right) 1 else 0
|
||||
setResultReg(resultReg, value, i.type!!)
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsSLE(i: Instruction) {
|
||||
val (resultReg, left, right) = getSetOnConditionOperandsU(i)
|
||||
val value = if(left<=right) 1 else 0
|
||||
setResultReg(resultReg, value, i.type!!)
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsSLES(i: Instruction) {
|
||||
val (resultReg, left, right) = getSetOnConditionOperands(i)
|
||||
val value = if(left<=right) 1 else 0
|
||||
setResultReg(resultReg, value, i.type!!)
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsSGE(i: Instruction) {
|
||||
val (resultReg, left, right) = getSetOnConditionOperandsU(i)
|
||||
val value = if(left>=right) 1 else 0
|
||||
setResultReg(resultReg, value, i.type!!)
|
||||
pc++
|
||||
|
||||
}
|
||||
|
||||
private fun InsSGES(i: Instruction) {
|
||||
val (resultReg, left, right) = getSetOnConditionOperands(i)
|
||||
val value = if(left>=right) 1 else 0
|
||||
setResultReg(resultReg, value, i.type!!)
|
||||
pc++
|
||||
|
||||
}
|
||||
|
||||
private fun InsINC(i: Instruction) {
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> registers.setB(i.reg1!!, (registers.getB(i.reg1)+1u).toUByte())
|
||||
@ -625,6 +679,18 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsSWAP(i: Instruction) {
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> {
|
||||
val value = registers.getW(i.reg2!!)
|
||||
val newValue = value.toUByte()*256u + (value.toInt() ushr 8).toUInt()
|
||||
registers.setW(i.reg1!!, newValue.toUShort())
|
||||
}
|
||||
VmDataType.WORD -> TODO("swap.w requires 32-bits registers")
|
||||
}
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsCOPY(i: Instruction) = doCopy(i.reg1!!, i.reg2!!, i.reg3!!, false)
|
||||
|
||||
private fun InsCOPYZ(i: Instruction) = doCopy(i.reg1!!, i.reg2!!, null, true)
|
||||
@ -654,16 +720,44 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsSWAP(i: Instruction) {
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> {
|
||||
val value = registers.getW(i.reg2!!)
|
||||
val newValue = value.toUByte()*256u + (value.toInt() ushr 8).toUInt()
|
||||
registers.setW(i.reg1!!, newValue.toUShort())
|
||||
}
|
||||
VmDataType.WORD -> TODO("swap.w requires 32-bits registers")
|
||||
private fun getBranchOperands(i: Instruction): Pair<Int, Int> {
|
||||
return when(i.type) {
|
||||
VmDataType.BYTE -> Pair(registers.getB(i.reg1!!).toInt(), registers.getB(i.reg2!!).toInt())
|
||||
VmDataType.WORD -> Pair(registers.getW(i.reg1!!).toInt(), registers.getW(i.reg2!!).toInt())
|
||||
null -> throw IllegalArgumentException("need type for branch instruction")
|
||||
}
|
||||
}
|
||||
|
||||
private fun getBranchOperandsU(i: Instruction): Pair<UInt, UInt> {
|
||||
return when(i.type) {
|
||||
VmDataType.BYTE -> Pair(registers.getB(i.reg1!!).toUInt(), registers.getB(i.reg2!!).toUInt())
|
||||
VmDataType.WORD -> Pair(registers.getW(i.reg1!!).toUInt(), registers.getW(i.reg2!!).toUInt())
|
||||
null -> throw IllegalArgumentException("need type for branch instruction")
|
||||
}
|
||||
}
|
||||
|
||||
private fun getLogicalOperandsU(i: Instruction): Pair<UInt, UInt> {
|
||||
return when(i.type) {
|
||||
VmDataType.BYTE -> Pair(registers.getB(i.reg2!!).toUInt(), registers.getB(i.reg3!!).toUInt())
|
||||
VmDataType.WORD -> Pair(registers.getW(i.reg2!!).toUInt(), registers.getW(i.reg3!!).toUInt())
|
||||
null -> throw IllegalArgumentException("need type for logical instruction")
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSetOnConditionOperands(ins: Instruction): Triple<Int, Int, Int> {
|
||||
return when(ins.type) {
|
||||
VmDataType.BYTE -> Triple(ins.reg1!!, registers.getB(ins.reg2!!).toInt(), registers.getB(ins.reg3!!).toInt())
|
||||
VmDataType.WORD -> Triple(ins.reg1!!, registers.getW(ins.reg2!!).toInt(), registers.getW(ins.reg3!!).toInt())
|
||||
null -> throw IllegalArgumentException("need type for branch instruction")
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSetOnConditionOperandsU(ins: Instruction): Triple<Int, UInt, UInt> {
|
||||
return when(ins.type) {
|
||||
VmDataType.BYTE -> Triple(ins.reg1!!, registers.getB(ins.reg2!!).toUInt(), registers.getB(ins.reg3!!).toUInt())
|
||||
VmDataType.WORD -> Triple(ins.reg1!!, registers.getW(ins.reg2!!).toUInt(), registers.getW(ins.reg3!!).toUInt())
|
||||
null -> throw IllegalArgumentException("need type for branch instruction")
|
||||
}
|
||||
pc++
|
||||
}
|
||||
|
||||
private var window: GraphicsWindow? = null
|
||||
|
Loading…
Reference in New Issue
Block a user