mirror of
https://github.com/irmen/prog8.git
synced 2025-02-20 03:29:01 +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)
|
require(arraysize == initialArrayValue.size)
|
||||||
if(arraysize!=null || initialArrayValue!=null)
|
if(arraysize!=null || initialArrayValue!=null)
|
||||||
require(initialStringValue==null && initialNumericValue==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() {
|
override fun printProperties() {
|
||||||
|
@ -58,8 +58,8 @@ class PtBinaryExpression(val operator: String, type: DataType, position: Positio
|
|||||||
class PtContainmentCheck(position: Position): PtExpression(DataType.UBYTE, position) {
|
class PtContainmentCheck(position: Position): PtExpression(DataType.UBYTE, position) {
|
||||||
val element: PtExpression
|
val element: PtExpression
|
||||||
get() = children[0] as PtExpression
|
get() = children[0] as PtExpression
|
||||||
val iterable: PtExpression
|
val iterable: PtIdentifier
|
||||||
get() = children[0] as PtExpression
|
get() = children[0] as PtIdentifier
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
package prog8.codegen.virtual
|
package prog8.codegen.virtual
|
||||||
|
|
||||||
|
import prog8.code.StStaticVariable
|
||||||
import prog8.code.StSub
|
import prog8.code.StSub
|
||||||
import prog8.code.ast.*
|
import prog8.code.ast.*
|
||||||
import prog8.code.core.AssemblyError
|
import prog8.code.core.AssemblyError
|
||||||
import prog8.code.core.DataType
|
import prog8.code.core.DataType
|
||||||
import prog8.code.core.PassByValueDatatypes
|
import prog8.code.core.PassByValueDatatypes
|
||||||
|
import prog8.code.core.SignedDatatypes
|
||||||
import prog8.vm.Instruction
|
import prog8.vm.Instruction
|
||||||
import prog8.vm.Opcode
|
import prog8.vm.Opcode
|
||||||
import prog8.vm.VmDataType
|
import prog8.vm.VmDataType
|
||||||
@ -54,7 +56,7 @@ internal class ExpressionGen(val codeGen: CodeGen) {
|
|||||||
is PtBinaryExpression -> code += translate(expr, resultRegister, regUsage)
|
is PtBinaryExpression -> code += translate(expr, resultRegister, regUsage)
|
||||||
is PtBuiltinFunctionCall -> code += translate(expr, resultRegister, regUsage)
|
is PtBuiltinFunctionCall -> code += translate(expr, resultRegister, regUsage)
|
||||||
is PtFunctionCall -> 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 PtPipe -> TODO()
|
||||||
is PtRange,
|
is PtRange,
|
||||||
is PtArrayLiteral,
|
is PtArrayLiteral,
|
||||||
@ -64,6 +66,21 @@ internal class ExpressionGen(val codeGen: CodeGen) {
|
|||||||
return code
|
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 {
|
private fun translate(arrayIx: PtArrayIndexer, resultRegister: Int, regUsage: RegisterUsage): VmCodeChunk {
|
||||||
val eltSize = codeGen.program.memsizer.memorySize(arrayIx.type)
|
val eltSize = codeGen.program.memsizer.memorySize(arrayIx.type)
|
||||||
val vmDt = codeGen.vmType(arrayIx.type)
|
val vmDt = codeGen.vmType(arrayIx.type)
|
||||||
@ -194,9 +211,9 @@ internal class ExpressionGen(val codeGen: CodeGen) {
|
|||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
val leftResultReg = regUsage.nextFree()
|
val leftResultReg = regUsage.nextFree()
|
||||||
val rightResultReg = 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 leftCode = translateExpression(binExpr.left, leftResultReg, regUsage)
|
||||||
val rightCode = translateExpression(binExpr.right, rightResultReg, 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 += leftCode
|
||||||
code += rightCode
|
code += rightCode
|
||||||
val vmDt = codeGen.vmType(binExpr.type)
|
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))
|
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}")
|
else -> TODO("operator ${binExpr.operator}")
|
||||||
}
|
}
|
||||||
return code
|
return code
|
||||||
|
@ -6,6 +6,8 @@ import prog8.ast.expressions.*
|
|||||||
import prog8.ast.statements.*
|
import prog8.ast.statements.*
|
||||||
import prog8.ast.walk.IAstVisitor
|
import prog8.ast.walk.IAstVisitor
|
||||||
import prog8.code.*
|
import prog8.code.*
|
||||||
|
import prog8.code.core.ArrayDatatypes
|
||||||
|
import prog8.code.core.ElementToArrayTypes
|
||||||
import prog8.code.core.Position
|
import prog8.code.core.Position
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@ -59,6 +61,8 @@ internal class SymbolTableMaker: IAstVisitor {
|
|||||||
val initialString = if(initialStringLit==null) null else Pair(initialStringLit.value, initialStringLit.encoding)
|
val initialString = if(initialStringLit==null) null else Pair(initialStringLit.value, initialStringLit.encoding)
|
||||||
val initialArrayLit = decl.value as? ArrayLiteral
|
val initialArrayLit = decl.value as? ArrayLiteral
|
||||||
val initialArray = makeInitialArray(initialArrayLit)
|
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)
|
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)
|
VarDeclType.CONST -> StConstant(decl.name, decl.datatype, (decl.value as NumericLiteral).number, decl.position)
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
%import floats
|
|
||||||
%import textio
|
%import textio
|
||||||
|
|
||||||
; NOTE: meant to test to virtual machine output target (use -target vitual)
|
; NOTE: meant to test to virtual machine output target (use -target vitual)
|
||||||
@ -7,34 +6,43 @@ main {
|
|||||||
sub start() {
|
sub start() {
|
||||||
txt.clear_screen()
|
txt.clear_screen()
|
||||||
txt.print("Welcome to a prog8 pixel shader :-)\n")
|
txt.print("Welcome to a prog8 pixel shader :-)\n")
|
||||||
float fl = 9.9
|
ubyte bb = 4
|
||||||
fl = floats.pow(fl, 3.0)
|
ubyte[] array = [1,2,3,4,5,6]
|
||||||
txt.print("fl=")
|
str tekst = "test"
|
||||||
floats.print_f(fl)
|
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()
|
txt.nl()
|
||||||
sys.exit(99)
|
sys.exit(99)
|
||||||
|
|
||||||
|
|
||||||
; syscall1(8, 0) ; enable lo res creen
|
syscall1(8, 0) ; enable lo res creen
|
||||||
; ubyte shifter
|
ubyte shifter
|
||||||
;
|
|
||||||
; shifter >>= 1
|
shifter >>= 1
|
||||||
;
|
|
||||||
; 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
|
||||||
;
|
|
||||||
; txt.print_ub(shifter)
|
txt.print_ub(shifter)
|
||||||
; txt.nl()
|
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)
|
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)
|
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)
|
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.)
|
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
|
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,
|
BLES,
|
||||||
BGE,
|
BGE,
|
||||||
BGES,
|
BGES,
|
||||||
|
SEQ,
|
||||||
|
SNE,
|
||||||
|
SLT,
|
||||||
|
SLTS,
|
||||||
|
SGT,
|
||||||
|
SGTS,
|
||||||
|
SLE,
|
||||||
|
SLES,
|
||||||
|
SGE,
|
||||||
|
SGES,
|
||||||
|
|
||||||
INC,
|
INC,
|
||||||
DEC,
|
DEC,
|
||||||
@ -271,6 +291,16 @@ val instructionFormats = mutableMapOf(
|
|||||||
Opcode.BLES 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.BGE to InstructionFormat(BW, true, true, false, true ),
|
||||||
Opcode.BGES 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.INC to InstructionFormat(BW, true, false, false, false),
|
||||||
Opcode.DEC 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.BLES -> InsBLES(ins)
|
||||||
Opcode.BGE -> InsBGEU(ins)
|
Opcode.BGE -> InsBGEU(ins)
|
||||||
Opcode.BGES -> InsBGES(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.INC -> InsINC(ins)
|
||||||
Opcode.DEC -> InsDEC(ins)
|
Opcode.DEC -> InsDEC(ins)
|
||||||
Opcode.NEG -> InsNEG(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)
|
if(valueStack.size>=128)
|
||||||
throw StackOverflowError("valuestack limit 128 exceeded")
|
throw StackOverflowError("valuestack limit 128 exceeded")
|
||||||
|
|
||||||
val value = when(ins.type!!) {
|
val value = when(i.type!!) {
|
||||||
VmDataType.BYTE -> {
|
VmDataType.BYTE -> registers.getB(i.reg1!!).toInt()
|
||||||
registers.getB(ins.reg1!!).toInt()
|
VmDataType.WORD -> registers.getW(i.reg1!!).toInt()
|
||||||
}
|
|
||||||
VmDataType.WORD -> {
|
|
||||||
registers.getW(ins.reg1!!).toInt()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
valueStack.push(value)
|
valueStack.push(value)
|
||||||
pc++
|
pc++
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun InsPOP(ins: Instruction) {
|
private fun InsPOP(i: Instruction) {
|
||||||
val value = valueStack.pop()
|
val value = valueStack.pop()
|
||||||
when(ins.type!!) {
|
setResultReg(i.reg1!!, value, i.type!!)
|
||||||
VmDataType.BYTE -> {
|
|
||||||
registers.setB(ins.reg1!!, value.toUByte())
|
|
||||||
}
|
|
||||||
VmDataType.WORD -> {
|
|
||||||
registers.setW(ins.reg1!!, value.toUShort())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pc++
|
pc++
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun InsSYSCALL(ins: Instruction) {
|
private fun InsSYSCALL(i: Instruction) {
|
||||||
val call = Syscall.values()[ins.value!!]
|
val call = Syscall.values()[i.value!!]
|
||||||
SysCalls.call(call, this)
|
SysCalls.call(call, this)
|
||||||
pc++
|
pc++
|
||||||
}
|
}
|
||||||
@ -176,10 +183,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun InsLOAD(i: Instruction) {
|
private fun InsLOAD(i: Instruction) {
|
||||||
when(i.type!!) {
|
setResultReg(i.reg1!!, i.value!!, i.type!!)
|
||||||
VmDataType.BYTE -> registers.setB(i.reg1!!, i.value!!.toUByte())
|
|
||||||
VmDataType.WORD -> registers.setW(i.reg1!!, i.value!!.toUShort())
|
|
||||||
}
|
|
||||||
pc++
|
pc++
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,6 +202,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
}
|
}
|
||||||
pc++
|
pc++
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun InsLOADX(i: Instruction) {
|
private fun InsLOADX(i: Instruction) {
|
||||||
when (i.type!!) {
|
when (i.type!!) {
|
||||||
VmDataType.BYTE -> registers.setB(i.reg1!!, memory.getB(i.value!! + registers.getW(i.reg2!!).toInt()))
|
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++
|
pc++
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun InsSTOREZX(i: Instruction) {
|
private fun InsSTOREZX(i: Instruction) {
|
||||||
when (i.type!!) {
|
when (i.type!!) {
|
||||||
VmDataType.BYTE -> memory.setB(registers.getW(i.reg2!!).toInt() + i.value!!, 0u)
|
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++
|
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) {
|
private fun InsBNE(i: Instruction) {
|
||||||
val (left: Int, right: Int) = getBranchOperands(i)
|
val (left: Int, right: Int) = getBranchOperands(i)
|
||||||
if(left!=right)
|
if(left!=right)
|
||||||
@ -442,6 +424,78 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
pc++
|
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) {
|
private fun InsINC(i: Instruction) {
|
||||||
when(i.type!!) {
|
when(i.type!!) {
|
||||||
VmDataType.BYTE -> registers.setB(i.reg1!!, (registers.getB(i.reg1)+1u).toUByte())
|
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++
|
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 InsCOPY(i: Instruction) = doCopy(i.reg1!!, i.reg2!!, i.reg3!!, false)
|
||||||
|
|
||||||
private fun InsCOPYZ(i: Instruction) = doCopy(i.reg1!!, i.reg2!!, null, true)
|
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++
|
pc++
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun InsSWAP(i: Instruction) {
|
private fun getBranchOperands(i: Instruction): Pair<Int, Int> {
|
||||||
when(i.type!!) {
|
return when(i.type) {
|
||||||
VmDataType.BYTE -> {
|
VmDataType.BYTE -> Pair(registers.getB(i.reg1!!).toInt(), registers.getB(i.reg2!!).toInt())
|
||||||
val value = registers.getW(i.reg2!!)
|
VmDataType.WORD -> Pair(registers.getW(i.reg1!!).toInt(), registers.getW(i.reg2!!).toInt())
|
||||||
val newValue = value.toUByte()*256u + (value.toInt() ushr 8).toUInt()
|
null -> throw IllegalArgumentException("need type for branch instruction")
|
||||||
registers.setW(i.reg1!!, newValue.toUShort())
|
|
||||||
}
|
}
|
||||||
VmDataType.WORD -> TODO("swap.w requires 32-bits registers")
|
|
||||||
}
|
}
|
||||||
pc++
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var window: GraphicsWindow? = null
|
private var window: GraphicsWindow? = null
|
||||||
|
Loading…
x
Reference in New Issue
Block a user