vm: actually use the store-zero instructions in codegen

This commit is contained in:
Irmen de Jong 2022-05-11 15:13:44 +02:00
parent 627aa61184
commit d43ad849d1
7 changed files with 202 additions and 140 deletions

View File

@ -2,7 +2,6 @@ package prog8.codegen.virtual
import prog8.code.StStaticVariable
import prog8.code.ast.*
import prog8.code.core.ArrayToElementTypes
import prog8.code.core.AssemblyError
import prog8.code.core.DataType
import prog8.vm.Opcode
@ -241,32 +240,54 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
private fun funcPokeW(call: PtBuiltinFunctionCall): VmCodeChunk {
val code = VmCodeChunk()
val valueReg = codeGen.vmRegisters.nextFree()
if(call.args[0] is PtNumber) {
val address = (call.args[0] as PtNumber).number.toInt()
code += exprGen.translateExpression(call.args[1], valueReg, -1)
code += VmCodeInstruction(Opcode.STOREM, VmDataType.WORD, reg1 = valueReg, value=address)
if(codeGen.isZero(call.args[1])) {
if (call.args[0] is PtNumber) {
val address = (call.args[0] as PtNumber).number.toInt()
code += VmCodeInstruction(Opcode.STOREZM, VmDataType.WORD, value = address)
} else {
val addressReg = codeGen.vmRegisters.nextFree()
code += exprGen.translateExpression(call.args[0], addressReg, -1)
code += VmCodeInstruction(Opcode.STOREZI, VmDataType.WORD, reg2 = addressReg)
}
} else {
val addressReg = codeGen.vmRegisters.nextFree()
code += exprGen.translateExpression(call.args[0], addressReg, -1)
code += exprGen.translateExpression(call.args[1], valueReg, -1)
code += VmCodeInstruction(Opcode.STOREI, VmDataType.WORD, reg1 = valueReg, reg2 = addressReg)
val valueReg = codeGen.vmRegisters.nextFree()
if (call.args[0] is PtNumber) {
val address = (call.args[0] as PtNumber).number.toInt()
code += exprGen.translateExpression(call.args[1], valueReg, -1)
code += VmCodeInstruction(Opcode.STOREM, VmDataType.WORD, reg1 = valueReg, value = address)
} else {
val addressReg = codeGen.vmRegisters.nextFree()
code += exprGen.translateExpression(call.args[0], addressReg, -1)
code += exprGen.translateExpression(call.args[1], valueReg, -1)
code += VmCodeInstruction(Opcode.STOREI, VmDataType.WORD, reg1 = valueReg, reg2 = addressReg)
}
}
return code
}
private fun funcPoke(call: PtBuiltinFunctionCall): VmCodeChunk {
val code = VmCodeChunk()
val valueReg = codeGen.vmRegisters.nextFree()
if(call.args[0] is PtNumber) {
val address = (call.args[0] as PtNumber).number.toInt()
code += exprGen.translateExpression(call.args[1], valueReg, -1)
code += VmCodeInstruction(Opcode.STOREM, VmDataType.BYTE, reg1 = valueReg, value=address)
if(codeGen.isZero(call.args[1])) {
if (call.args[0] is PtNumber) {
val address = (call.args[0] as PtNumber).number.toInt()
code += VmCodeInstruction(Opcode.STOREZM, VmDataType.BYTE, value = address)
} else {
val addressReg = codeGen.vmRegisters.nextFree()
code += exprGen.translateExpression(call.args[0], addressReg, -1)
code += VmCodeInstruction(Opcode.STOREZI, VmDataType.BYTE, reg2 = addressReg)
}
} else {
val addressReg = codeGen.vmRegisters.nextFree()
code += exprGen.translateExpression(call.args[0], addressReg, -1)
code += exprGen.translateExpression(call.args[1], valueReg, -1)
code += VmCodeInstruction(Opcode.STOREI, VmDataType.BYTE, reg1 = valueReg, reg2 = addressReg)
val valueReg = codeGen.vmRegisters.nextFree()
if (call.args[0] is PtNumber) {
val address = (call.args[0] as PtNumber).number.toInt()
code += exprGen.translateExpression(call.args[1], valueReg, -1)
code += VmCodeInstruction(Opcode.STOREM, VmDataType.BYTE, reg1 = valueReg, value = address)
} else {
val addressReg = codeGen.vmRegisters.nextFree()
code += exprGen.translateExpression(call.args[0], addressReg, -1)
code += exprGen.translateExpression(call.args[1], valueReg, -1)
code += VmCodeInstruction(Opcode.STOREI, VmDataType.BYTE, reg1 = valueReg, reg2 = addressReg)
}
}
return code
}
@ -361,5 +382,4 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
code += codeGen.translateNode(assignment)
return code
}
}

View File

@ -6,7 +6,6 @@ import prog8.code.ast.*
import prog8.code.core.*
import prog8.vm.Opcode
import prog8.vm.VmDataType
import java.nio.file.Path
import kotlin.math.pow
@ -410,7 +409,7 @@ class CodeGen(internal val program: PtProgram,
// just shift multiple bits
val pow2reg = vmRegisters.nextFree()
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2)
code += VmCodeInstruction(Opcode.LSLX, dt, reg1=reg, reg2=reg, reg3=pow2reg)
code += VmCodeInstruction(Opcode.LSLN, dt, reg1=reg, reg2=reg, reg3=pow2reg)
} else {
if (factor == 0) {
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0)
@ -451,7 +450,7 @@ class CodeGen(internal val program: PtProgram,
// just shift multiple bits
val pow2reg = vmRegisters.nextFree()
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=pow2reg, value=pow2)
code += VmCodeInstruction(Opcode.LSRX, dt, reg1=reg, reg2=reg, reg3=pow2reg)
code += VmCodeInstruction(Opcode.LSRN, dt, reg1=reg, reg2=reg, reg3=pow2reg)
} else {
if (factor == 0) {
code += VmCodeInstruction(Opcode.LOAD, dt, reg1=reg, value=0xffff)
@ -615,24 +614,32 @@ class CodeGen(internal val program: PtProgram,
val vmDt = vmType(assignment.value.type)
var resultRegister = -1
var resultFpRegister = -1
if(vmDt==VmDataType.FLOAT) {
resultFpRegister = vmRegisters.nextFreeFloat()
code += expressionEval.translateExpression(assignment.value, -1, resultFpRegister)
} else {
resultRegister = if (assignment.value is PtMachineRegister) {
(assignment.value as PtMachineRegister).register
val zero = isZero(assignment.value)
if(!zero) {
// calculate the assignment value
if (vmDt == VmDataType.FLOAT) {
resultFpRegister = vmRegisters.nextFreeFloat()
code += expressionEval.translateExpression(assignment.value, -1, resultFpRegister)
} else {
val reg = vmRegisters.nextFree()
code += expressionEval.translateExpression(assignment.value, reg, -1)
reg
resultRegister = if (assignment.value is PtMachineRegister) {
(assignment.value as PtMachineRegister).register
} else {
val reg = vmRegisters.nextFree()
code += expressionEval.translateExpression(assignment.value, reg, -1)
reg
}
}
}
if(ident!=null) {
val address = allocations.get(ident.targetName)
code += if(vmDt==VmDataType.FLOAT)
VmCodeInstruction(Opcode.STOREM, vmDt, fpReg1=resultFpRegister, value=address)
else
VmCodeInstruction(Opcode.STOREM, vmDt, reg1=resultRegister, value=address)
code += if(zero) {
VmCodeInstruction(Opcode.STOREZM, vmDt, value = address)
} else {
if (vmDt == VmDataType.FLOAT)
VmCodeInstruction(Opcode.STOREM, vmDt, fpReg1 = resultFpRegister, value = address)
else
VmCodeInstruction(Opcode.STOREM, vmDt, reg1 = resultRegister, value = address)
}
}
else if(array!=null) {
val variable = array.variable.targetName
@ -640,23 +647,45 @@ class CodeGen(internal val program: PtProgram,
val itemsize = program.memsizer.memorySize(array.type)
val fixedIndex = constIntValue(array.index)
val vmDtArrayIdx = vmType(array.type)
if(fixedIndex!=null) {
variableAddr += fixedIndex*itemsize
code += VmCodeInstruction(Opcode.STOREM, vmDtArrayIdx, reg1 = resultRegister, value=variableAddr)
// TODO floating point array incorrect?
if(zero) {
if(fixedIndex!=null) {
variableAddr += fixedIndex*itemsize
code += VmCodeInstruction(Opcode.STOREZM, vmDtArrayIdx, value=variableAddr)
} else {
val indexReg = vmRegisters.nextFree()
code += expressionEval.translateExpression(array.index, indexReg, -1)
code += VmCodeInstruction(Opcode.STOREZX, vmDtArrayIdx, reg1=indexReg, value=variableAddr)
}
} else {
val indexReg = vmRegisters.nextFree()
code += expressionEval.translateExpression(array.index, indexReg, -1)
code += VmCodeInstruction(Opcode.STOREX, vmDtArrayIdx, reg1 = resultRegister, reg2=indexReg, value=variableAddr)
if(fixedIndex!=null) {
variableAddr += fixedIndex*itemsize
code += VmCodeInstruction(Opcode.STOREM, vmDtArrayIdx, reg1 = resultRegister, value=variableAddr)
} else {
val indexReg = vmRegisters.nextFree()
code += expressionEval.translateExpression(array.index, indexReg, -1)
code += VmCodeInstruction(Opcode.STOREX, vmDtArrayIdx, reg1 = resultRegister, reg2=indexReg, value=variableAddr)
}
}
}
else if(memory!=null) {
require(vmDt==VmDataType.BYTE)
if(memory.address is PtNumber) {
code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1=resultRegister, value=(memory.address as PtNumber).number.toInt())
if(zero) {
if(memory.address is PtNumber) {
code += VmCodeInstruction(Opcode.STOREZM, vmDt, value=(memory.address as PtNumber).number.toInt())
} else {
val addressReg = vmRegisters.nextFree()
code += expressionEval.translateExpression(memory.address, addressReg, -1)
code += VmCodeInstruction(Opcode.STOREZI, vmDt, reg1=addressReg)
}
} else {
val addressReg = vmRegisters.nextFree()
code += expressionEval.translateExpression(memory.address, addressReg, -1)
code += VmCodeInstruction(Opcode.STOREI, vmDt, reg1=resultRegister, reg2=addressReg)
if(memory.address is PtNumber) {
code += VmCodeInstruction(Opcode.STOREM, vmDt, reg1=resultRegister, value=(memory.address as PtNumber).number.toInt())
} else {
val addressReg = vmRegisters.nextFree()
code += expressionEval.translateExpression(memory.address, addressReg, -1)
code += VmCodeInstruction(Opcode.STOREI, vmDt, reg1=resultRegister, reg2=addressReg)
}
}
}
else
@ -722,4 +751,6 @@ class CodeGen(internal val program: PtProgram,
internal fun translateBuiltinFunc(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk =
builtinFuncGen.translate(call, resultRegister)
internal fun isZero(expression: PtExpression): Boolean = expression is PtNumber && expression.number==0.0
}

View File

@ -9,7 +9,6 @@ import prog8.code.core.PassByValueDatatypes
import prog8.code.core.SignedDatatypes
import prog8.vm.Opcode
import prog8.vm.VmDataType
import java.nio.channels.FileLock
internal class ExpressionGen(private val codeGen: CodeGen) {
@ -174,6 +173,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
private fun translate(expr: PtPrefix, resultRegister: Int): VmCodeChunk {
val code = VmCodeChunk()
// TODO if the value is a variable or memory read, use memory-versions of the opcodes instead of using intermediary register
code += translateExpression(expr.value, resultRegister, -1)
val vmDt = codeGen.vmType(expr.type)
when(expr.operator) {
@ -363,22 +363,24 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
private fun operatorShiftRight(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int, signed: Boolean): VmCodeChunk {
val code = VmCodeChunk()
// TODO if shift is 1, use ASR/LSR instruction instead of multishift
val leftResultReg = codeGen.vmRegisters.nextFree()
val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, leftResultReg, -1)
code += translateExpression(binExpr.right, rightResultReg, -1)
val opc = if(signed) Opcode.ASRX else Opcode.LSRX
val opc = if(signed) Opcode.ASRN else Opcode.LSRN
code += VmCodeInstruction(opc, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
return code
}
private fun operatorShiftLeft(binExpr: PtBinaryExpression, vmDt: VmDataType, resultRegister: Int): VmCodeChunk {
val code = VmCodeChunk()
// TODO if shift is 1, use LSL instruction instead of multishift
val leftResultReg = codeGen.vmRegisters.nextFree()
val rightResultReg = codeGen.vmRegisters.nextFree()
code += translateExpression(binExpr.left, leftResultReg, -1)
code += translateExpression(binExpr.right, rightResultReg, -1)
code += VmCodeInstruction(Opcode.LSLX, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
code += VmCodeInstruction(Opcode.LSLN, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg)
return code
}
@ -568,16 +570,26 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
val code = VmCodeChunk()
for ((arg, parameter) in fcall.args.zip(subroutine.parameters)) {
val paramDt = codeGen.vmType(parameter.type)
if(paramDt==VmDataType.FLOAT) {
val argFpReg = codeGen.vmRegisters.nextFreeFloat()
code += translateExpression(arg, -1, argFpReg)
val mem = codeGen.allocations.get(fcall.functionName + parameter.name)
code += VmCodeInstruction(Opcode.STOREM, paramDt, fpReg1 = argFpReg, value = mem)
if(codeGen.isZero(arg)) {
if (paramDt == VmDataType.FLOAT) {
val mem = codeGen.allocations.get(fcall.functionName + parameter.name)
code += VmCodeInstruction(Opcode.STOREZM, paramDt, value = mem)
} else {
val mem = codeGen.allocations.get(fcall.functionName + parameter.name)
code += VmCodeInstruction(Opcode.STOREZM, paramDt, value = mem)
}
} else {
val argReg = codeGen.vmRegisters.nextFree()
code += translateExpression(arg, argReg, -1)
val mem = codeGen.allocations.get(fcall.functionName + parameter.name)
code += VmCodeInstruction(Opcode.STOREM, paramDt, reg1 = argReg, value = mem)
if (paramDt == VmDataType.FLOAT) {
val argFpReg = codeGen.vmRegisters.nextFreeFloat()
code += translateExpression(arg, -1, argFpReg)
val mem = codeGen.allocations.get(fcall.functionName + parameter.name)
code += VmCodeInstruction(Opcode.STOREM, paramDt, fpReg1 = argFpReg, value = mem)
} else {
val argReg = codeGen.vmRegisters.nextFree()
code += translateExpression(arg, argReg, -1)
val mem = codeGen.allocations.get(fcall.functionName + parameter.name)
code += VmCodeInstruction(Opcode.STOREM, paramDt, reg1 = argReg, value = mem)
}
}
}
code += VmCodeInstruction(Opcode.CALL, symbol=fcall.functionName)

View File

@ -3,7 +3,11 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- vm: add way more instructions operating directly on memory instead of only registers
- vm: assignment to float array is not correct? also zero?
- vm: use more instructions in codegen: shift one
- vm: use more instructions in codegen: branching
- vm: add more instructions operating directly on memory instead of only registers?
- in-place modifiying functions (rol, ror, ..) don't accept a memory address but require a memory-read expression. that is weird.
- complete the Inliner
- add McCarthy evaluation to shortcircuit and/or expressions. First do ifs by splitting them up? Then do expressions that compute a value?

View File

@ -6,21 +6,57 @@
; NOTE: meant to test to virtual machine output target (use -target vitual)
main {
ubyte value = 42
; ubyte value = 42
;
; sub inline_candidate() -> ubyte {
; return math.sin8u(value)
; }
;
; sub add(ubyte first, ubyte second) -> ubyte {
; return first + second
; }
;
; sub mul(ubyte first, ubyte second) -> ubyte {
; return first * second
; }
sub derp() -> ubyte {
return math.sin8u(value)
sub ding(uword arg) {
arg++
txt.print_uw(arg)
}
sub start() {
ubyte value = derp()
txt.print_ub(value)
ding(0)
txt.nl()
txt.print_ub(derp())
ding(2)
txt.nl()
; TODO: test with builtin function using multiple args (such as mkword)
; ubyte value = add(3,4) |> add(10) |> mul(2) |> math.sin8u() ; TODO should not work yet on vm codegen, but it compiles.... :/
; ubyte value = inline_candidate()
; byte svalue = 99
; svalue = -svalue
; @($5000) = not @($5000)
; rol(value)
; rol(@($5000))
; ror(value)
; ror(@($5000))
; rol2(value)
; rol2(@($5000))
; ror2(value)
; ror2(@($5000))
; @($5000) <<= 1
; @($5000) >>= 1
; value <<= 1
; value >>= 1
; @($5000) <<= 3
; @($5000) >>= 3
; value <<= 3
; value >>= 3
; txt.print_ub(value)
; txt.nl()
; txt.print_ub(inline_candidate())
; txt.nl()
; ubyte value = add(3,4) |> add(10) |> mul(2) |> math.sin8u()
; txt.print_ub(value)
; txt.nl()
; uword wvalue = add(3,4) |> add($30) |> mkword($ea)

View File

@ -31,7 +31,7 @@ loadr reg1, reg2 - load reg1 with value at register reg2
storem reg1, address - store reg1 at memory address
storei reg1, reg2 - store reg1 at memory indirect, memory pointed to by reg2
storex reg1, reg2, address - store reg1 at memory address, indexed by value in reg2
storez address - store zero at memory address
storezm address - store zero at memory address
storezi reg1 - store zero at memory pointed to by reg1
storezx reg1, address - store zero at memory address, indexed by value in reg
@ -89,8 +89,8 @@ ARITHMETIC
----------
All have type b or w or f. 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)
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)
ext reg1 - reg1 = unsigned extension of reg1 (which in practice just means clearing the MSB / MSW) (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: ext.w is not yet implemented as we don't have longs yet)
inc reg1 - reg1 = reg1+1
incm address - memory at address += 1
dec reg1 - reg1 = reg1-1
@ -116,9 +116,9 @@ All have type b or w.
and reg1, reg2, reg3 - reg1 = reg2 bitwise and reg3
or reg1, reg2, reg3 - reg1 = reg2 bitwise or reg3
xor reg1, reg2, reg3 - reg1 = reg2 bitwise xor reg3
lsrx reg1, reg2, reg3 - reg1 = multi-shift reg2 right by reg3 bits + set Carry to shifted bit
asrx reg1, reg2, reg3 - reg1 = multi-shift reg2 right by reg3 bits (signed) + set Carry to shifted bit
lslx reg1, reg2, reg3 - reg1 = multi-shift reg2 left by reg3 bits + set Carry to shifted bit
lsrn reg1, reg2, reg3 - reg1 = multi-shift reg2 right by reg3 bits + set Carry to shifted bit
asrn reg1, reg2, reg3 - reg1 = multi-shift reg2 right by reg3 bits (signed) + set Carry to shifted bit
lsln reg1, reg2, reg3 - reg1 = multi-shift reg2 left by reg3 bits + set Carry to shifted bit
lsr reg1 - shift reg1 right by 1 bits + set Carry to shifted bit
asr reg1 - shift reg1 right by 1 bits (signed) + set Carry to shifted bit
lsl reg1 - shift reg1 left by 1 bits + set Carry to shifted bit
@ -149,10 +149,7 @@ clc - clear Carry status bit
sec - set Carry status bit
nop - do nothing
breakpoint - trigger a breakpoint
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
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
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
pop [b, w] reg1 - pop value from stack into reg1
@ -169,14 +166,12 @@ enum class Opcode {
STOREM,
STOREI,
STOREX,
STOREZ,
STOREZM,
STOREZI,
STOREZX,
JUMP,
JUMPI,
CALL,
CALLI,
SYSCALL,
RETURN,
@ -190,14 +185,14 @@ enum class Opcode {
BNZ,
BEQ,
BNE,
BLT,
BLTS,
BGT,
BGTS,
BLE,
BLES,
BGE,
BGES,
BLT, // TODO not used in codegen??? <
BLTS, // TODO not used in codegen??? <
BGT, // TODO not used in codegen??? >
BGTS, // TODO not used in codegen??? >
BLE, // TODO should be used in codegen conditional branch too
BLES, // TODO should be used in codegen conditional branch too
BGE, // TODO not used in codegen??? >=
BGES, // TODO not used in codegen??? >=
SEQ,
SNE,
SLT,
@ -229,12 +224,12 @@ enum class Opcode {
AND,
OR,
XOR,
ASRX,
LSRX,
LSLX,
ASR,
LSR,
LSL,
ASRN,
LSRN,
LSLN,
ASR, // TODO not used in codegen of shift 1
LSR, // TODO not used in codegen of shift 1
LSL, // TODO not used in codegen of shift 1
ROR,
ROXR,
ROL,
@ -266,7 +261,6 @@ enum class Opcode {
PUSH,
POP,
MSIG,
SWAPREG,
CONCAT,
BREAKPOINT
}
@ -276,7 +270,7 @@ val OpcodesWithAddress = setOf(
Opcode.LOADX,
Opcode.STOREM,
Opcode.STOREX,
Opcode.STOREZ,
Opcode.STOREZM,
Opcode.STOREZX
)
@ -443,17 +437,14 @@ val instructionFormats = mutableMapOf(
Opcode.LOADI to InstructionFormat.from("BW,r1,r2 | F,fr1,r1"),
Opcode.LOADX to InstructionFormat.from("BW,r1,r2,v | F,fr1,r1,v"),
Opcode.LOADR to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
Opcode.SWAPREG to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
Opcode.STOREM to InstructionFormat.from("BW,r1,v | F,fr1,v"),
Opcode.STOREI to InstructionFormat.from("BW,r1,r2 | F,fr1,r1"),
Opcode.STOREX to InstructionFormat.from("BW,r1,r2,v | F,fr1,r1,v"),
Opcode.STOREZ to InstructionFormat.from("BW,v | F,v"),
Opcode.STOREZM to InstructionFormat.from("BW,v | F,v"),
Opcode.STOREZI to InstructionFormat.from("BW,r1 | F,r1"),
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"),
@ -503,9 +494,9 @@ val instructionFormats = mutableMapOf(
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.ASRN to InstructionFormat.from("BW,r1,r2,r3"),
Opcode.LSRN to InstructionFormat.from("BW,r1,r2,r3"),
Opcode.LSLN 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"),

View File

@ -92,17 +92,14 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
Opcode.LOADX -> InsLOADX(ins)
Opcode.LOADI -> InsLOADI(ins)
Opcode.LOADR -> InsLOADR(ins)
Opcode.SWAPREG -> InsSWAPREG(ins)
Opcode.STOREM -> InsSTOREM(ins)
Opcode.STOREX -> InsSTOREX(ins)
Opcode.STOREI -> InsSTOREI(ins)
Opcode.STOREZ -> InsSTOREZ(ins)
Opcode.STOREZM -> InsSTOREZ(ins)
Opcode.STOREZX -> InsSTOREZX(ins)
Opcode.STOREZI -> InsSTOREZI(ins)
Opcode.JUMP -> InsJUMP(ins)
Opcode.JUMPI -> InsJUMPI(ins)
Opcode.CALL -> InsCALL(ins)
Opcode.CALLI -> InsCALLI(ins)
Opcode.SYSCALL -> InsSYSCALL(ins)
Opcode.RETURN -> InsRETURN()
Opcode.BSTCC -> InsBSTCC(ins)
@ -153,9 +150,9 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
Opcode.AND -> InsAND(ins)
Opcode.OR -> InsOR(ins)
Opcode.XOR -> InsXOR(ins)
Opcode.ASRX -> InsASRM(ins)
Opcode.LSRX -> InsLSRM(ins)
Opcode.LSLX -> InsLSLM(ins)
Opcode.ASRN -> InsASRM(ins)
Opcode.LSRN -> InsLSRM(ins)
Opcode.LSLN -> InsLSLM(ins)
Opcode.ASR -> InsASR(ins)
Opcode.LSR -> InsLSR(ins)
Opcode.LSL -> InsLSL(ins)
@ -297,27 +294,6 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
pc++
}
private fun InsSWAPREG(i: Instruction) {
when(i.type!!) {
VmDataType.BYTE -> {
val oldR2 = registers.getUB(i.reg2!!)
registers.setUB(i.reg2, registers.getUB(i.reg1!!))
registers.setUB(i.reg1, oldR2)
}
VmDataType.WORD -> {
val oldR2 = registers.getUW(i.reg2!!)
registers.setUW(i.reg2, registers.getUW(i.reg1!!))
registers.setUW(i.reg1, oldR2)
}
VmDataType.FLOAT -> {
val oldR2 = registers.getFloat(i.fpReg2!!)
registers.setFloat(i.fpReg2, registers.getFloat(i.fpReg1!!))
registers.setFloat(i.fpReg1, oldR2)
}
}
pc++
}
private fun InsSTOREM(i: Instruction) {
when(i.type!!) {
VmDataType.BYTE -> memory.setUB(i.value!!, registers.getUB(i.reg1!!))
@ -351,6 +327,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
VmDataType.WORD -> memory.setUW(i.value!!, 0u)
VmDataType.FLOAT -> memory.setFloat(i.value!!, 0f)
}
pc++
}
private fun InsSTOREZI(i: Instruction) {
@ -375,20 +352,11 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
pc = i.value!!
}
private fun InsJUMPI(i: Instruction) {
pc = registers.getUW(i.reg1!!).toInt()
}
private fun InsCALL(i: Instruction) {
callStack.push(pc+1)
pc = i.value!!
}
private fun InsCALLI(i: Instruction) {
callStack.push(pc+1)
pc = registers.getUW(i.reg1!!).toInt()
}
private fun InsRETURN() {
if(callStack.isEmpty())
exit()