mirror of
https://github.com/irmen/prog8.git
synced 2024-11-26 11:49:22 +00:00
fix vm signed comparisons
This commit is contained in:
parent
f07065bf84
commit
3e1a7c6102
@ -92,6 +92,13 @@ internal class BuiltinFuncGen(val codeGen: CodeGen, val exprGen: ExpressionGen)
|
||||
code += exprGen.translateExpression(call.args.single(), addressReg, regUsage)
|
||||
code += VmCodeInstruction(Instruction(Opcode.LOADI, VmDataType.WORD, reg1 = resultRegister, reg2=addressReg))
|
||||
}
|
||||
"mkword" -> {
|
||||
val msbReg = regUsage.nextFree()
|
||||
val lsbReg = regUsage.nextFree()
|
||||
code += exprGen.translateExpression(call.args[0], msbReg, regUsage)
|
||||
code += exprGen.translateExpression(call.args[1], lsbReg, regUsage)
|
||||
code += VmCodeInstruction(Instruction(Opcode.CONCAT, VmDataType.BYTE, reg1=resultRegister, reg2=msbReg, reg3=lsbReg))
|
||||
}
|
||||
else -> {
|
||||
TODO("builtinfunc ${call.name}")
|
||||
// code += VmCodeInstruction(Instruction(Opcode.NOP))
|
||||
|
@ -233,7 +233,8 @@ internal class ExpressionGen(val codeGen: CodeGen) {
|
||||
val rightCode = translateExpression(binExpr.right, rightResultReg, regUsage)
|
||||
code += leftCode
|
||||
code += rightCode
|
||||
val vmDt = codeGen.vmType(binExpr.type)
|
||||
val vmDt = codeGen.vmType(binExpr.left.type)
|
||||
val signed = binExpr.left.type in SignedDatatypes
|
||||
when(binExpr.operator) {
|
||||
"+" -> {
|
||||
code += VmCodeInstruction(Instruction(Opcode.ADD, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
|
||||
@ -263,7 +264,8 @@ internal class ExpressionGen(val codeGen: CodeGen) {
|
||||
code += VmCodeInstruction(Instruction(Opcode.LSL, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
|
||||
}
|
||||
">>" -> {
|
||||
code += VmCodeInstruction(Instruction(Opcode.LSR, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
|
||||
val opc = if(signed) Opcode.ASR else Opcode.LSR
|
||||
code += VmCodeInstruction(Instruction(opc, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
|
||||
}
|
||||
"==" -> {
|
||||
code += VmCodeInstruction(Instruction(Opcode.SEQ, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
|
||||
@ -272,19 +274,19 @@ internal class ExpressionGen(val codeGen: CodeGen) {
|
||||
code += VmCodeInstruction(Instruction(Opcode.SNE, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
|
||||
}
|
||||
"<" -> {
|
||||
val ins = if(binExpr.type in SignedDatatypes) Opcode.SLTS else Opcode.SLT
|
||||
val ins = if(signed) 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
|
||||
val ins = if(signed) 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
|
||||
val ins = if(signed) 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
|
||||
val ins = if(signed) Opcode.SGES else Opcode.SGE
|
||||
code += VmCodeInstruction(Instruction(ins, vmDt, reg1=resultRegister, reg2=leftResultReg, reg3=rightResultReg))
|
||||
}
|
||||
else -> throw AssemblyError("weird operator ${binExpr.operator}")
|
||||
|
@ -32,6 +32,9 @@ sys {
|
||||
const ubyte SC_GFX_ENABLE = 8
|
||||
const ubyte SC_GFX_CLEAR = 9
|
||||
const ubyte SC_GFX_PLOT = 10
|
||||
const ubyte SC_RND = 11
|
||||
const ubyte SC_WAIT = 12
|
||||
const ubyte SC_WAITVSYNC = 13
|
||||
|
||||
|
||||
sub reset_system() {
|
||||
@ -41,24 +44,34 @@ sys {
|
||||
|
||||
sub wait(uword jiffies) {
|
||||
; --- wait approximately the given number of jiffies (1/60th seconds)
|
||||
; TODO
|
||||
syscall1(SC_WAIT, jiffies)
|
||||
}
|
||||
|
||||
sub waitvsync() {
|
||||
; --- busy wait till the next vsync has occurred (approximately), without depending on custom irq handling.
|
||||
; TODO
|
||||
syscall(SC_WAITVSYNC)
|
||||
}
|
||||
|
||||
sub memcopy(uword source, uword target, uword count) {
|
||||
; TODO
|
||||
repeat count {
|
||||
@(target) = @(source)
|
||||
source++
|
||||
target++
|
||||
}
|
||||
}
|
||||
|
||||
sub memset(uword mem, uword numbytes, ubyte value) {
|
||||
; TODO
|
||||
repeat numbytes {
|
||||
@(mem) = value
|
||||
mem++
|
||||
}
|
||||
}
|
||||
|
||||
sub memsetw(uword mem, uword numwords, uword value) {
|
||||
; TODO
|
||||
repeat numwords {
|
||||
pokew(mem, value)
|
||||
mem+=2
|
||||
}
|
||||
}
|
||||
|
||||
sub exit(ubyte returnvalue) {
|
||||
|
@ -3,7 +3,6 @@ TODO
|
||||
|
||||
For next release
|
||||
^^^^^^^^^^^^^^^^
|
||||
- vm codegen: fix ifelse comparisons such as if x< 0
|
||||
- vm codegen: fix primes endless loop stuck on '2'
|
||||
- x16: check additional FP lib changes https://github.com/commanderx16/x16-rom/commit/ae608673f0210953172d6837acfbb231d62ddbd1
|
||||
and https://github.com/commanderx16/x16-docs/commit/21238aedc641da91df88e04c4ce9bf3324a3c12d
|
||||
@ -13,6 +12,7 @@ For next release
|
||||
broken examples: amiga, colorbars, cube3d, highresbitmap, rasterbars, tehtriz, testgfx2, testvtui
|
||||
can we make the code read the new layout from vera registers instead of hardcoding it?
|
||||
- x16: check new ZP free addresses https://github.com/commanderx16/x16-docs/commit/541f2ce9e61d1d0d0e157d7f52fe16bc0895e6f0
|
||||
and https://www.commanderx16.com/forum/index.php?/topic/363-keep-zero-page-empty-as-much-as-possible/#comment-18561
|
||||
- x16: optimize diskio load_raw because headerless files are now supported https://github.com/commanderx16/x16-rom/pull/216
|
||||
note: must still work on c64/c128 that don't have this!
|
||||
- major compiler version bump once X16 r39 rom is officially finalized
|
||||
@ -23,6 +23,7 @@ For next release
|
||||
- vm codegen: postincrdecr arrayvalue
|
||||
- vm: support no globals re-init option
|
||||
- vm: how to remove all unused subroutines? (for asm, 64tass used to do this)
|
||||
- vm: rather than being able to jump to any 'address' (IPTR), use 'blocks'
|
||||
- vm codegen/assembler: variable memory locations should also be referenced by the variable name instead of just the address
|
||||
- when the vm is stable and *if* its language can get promoted to prog8 IL, the variable allocation should be changed.
|
||||
It's now done before the vm code generation, but the IL should probably not depend on the allocations already performed.
|
||||
|
@ -4,39 +4,13 @@
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
|
||||
byte bb = -9
|
||||
word ww = -1234
|
||||
if bb<0 {
|
||||
txt.print("bb <0!\n")
|
||||
} else {
|
||||
txt.print("comparison error!\n")
|
||||
}
|
||||
if ww<0 {
|
||||
txt.print("ww <0!\n")
|
||||
} else {
|
||||
txt.print("comparison error!\n")
|
||||
}
|
||||
if bb>0 {
|
||||
txt.print("comparison error!\n")
|
||||
} else {
|
||||
txt.print("bb not >0\n")
|
||||
}
|
||||
if ww>0 {
|
||||
txt.print("comparison error!\n")
|
||||
} else {
|
||||
txt.print("ww not >0\n")
|
||||
}
|
||||
|
||||
txt.print_w(ww)
|
||||
txt.spc()
|
||||
ww <<= 3
|
||||
txt.print_w(ww)
|
||||
ubyte x1 = $ea
|
||||
ubyte x2 = $31
|
||||
uword uw = mkword(x1, $99)
|
||||
txt.print_uwhex(uw, true)
|
||||
txt.nl()
|
||||
txt.print_b(bb)
|
||||
txt.spc()
|
||||
bb <<= 3
|
||||
txt.print_b(bb)
|
||||
uw = mkword(x1, x2)
|
||||
txt.print_uwhex(uw, true)
|
||||
txt.nl()
|
||||
|
||||
sys.exit(99)
|
||||
@ -80,6 +54,7 @@ main {
|
||||
; sys.exit(99)
|
||||
|
||||
|
||||
; the "pixelshader":
|
||||
; syscall1(8, 0) ; enable lo res creen
|
||||
; ubyte shifter
|
||||
;
|
||||
|
@ -32,14 +32,14 @@ class Assembler {
|
||||
"ubyte", "byte" -> {
|
||||
val array = values.split(',').map { parseValue(it.trim(), 0) }
|
||||
for (value in array) {
|
||||
memory.setB(address, value.toUByte())
|
||||
memory.setUB(address, value.toUByte())
|
||||
address++
|
||||
}
|
||||
}
|
||||
"uword", "word" -> {
|
||||
val array = values.split(',').map { parseValue(it.trim(), 0) }
|
||||
for (value in array) {
|
||||
memory.setW(address, value.toUShort())
|
||||
memory.setUW(address, value.toUShort())
|
||||
address++
|
||||
}
|
||||
}
|
||||
|
@ -115,11 +115,11 @@ 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
|
||||
lsr reg1, reg2, reg3 - reg1 = shift reg2 right by reg3 bits
|
||||
asr reg1, reg2, reg3 - reg1 = shift reg2 right by reg3 bits (signed)
|
||||
lsl reg1, reg2, reg3 - reg1 = shift reg2 left by reg3 bits
|
||||
ror reg1, reg2, reg3 - reg1 = rotate reg2 right by reg3 bits, not using carry
|
||||
rol reg1, reg2, reg3 - reg1 = rotate reg2 left by reg3 bits, not using carry
|
||||
|
||||
TODO add asr? (arithmetical shift right, so with sign bit)
|
||||
TODO also add ror/rol variants using the carry bit? These do map directly on 6502 and 68k instructions.
|
||||
|
||||
|
||||
@ -131,6 +131,7 @@ 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
|
||||
swap [b, w] reg1, reg2 - reg1 = swapped lsb and msb from register reg2 (16 bits) or lsw and msw (32 bits)
|
||||
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
|
||||
|
||||
@ -143,7 +144,6 @@ enum class Opcode {
|
||||
LOADI,
|
||||
LOADX,
|
||||
LOADR,
|
||||
SWAPREG,
|
||||
STOREM,
|
||||
STOREI,
|
||||
STOREX,
|
||||
@ -194,6 +194,7 @@ enum class Opcode {
|
||||
AND,
|
||||
OR,
|
||||
XOR,
|
||||
ASR,
|
||||
LSR,
|
||||
LSL,
|
||||
ROR,
|
||||
@ -202,6 +203,8 @@ enum class Opcode {
|
||||
PUSH,
|
||||
POP,
|
||||
SWAP,
|
||||
SWAPREG,
|
||||
CONCAT,
|
||||
COPY,
|
||||
COPYZ,
|
||||
BREAKPOINT
|
||||
@ -321,6 +324,7 @@ val instructionFormats = mutableMapOf(
|
||||
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.ASR to InstructionFormat(BW, true, true, true, false),
|
||||
Opcode.LSR to InstructionFormat(BW, true, true, true, false),
|
||||
Opcode.LSL to InstructionFormat(BW, true, true, true, false),
|
||||
Opcode.ROR to InstructionFormat(BW, true, true, true, false),
|
||||
@ -331,5 +335,6 @@ val instructionFormats = mutableMapOf(
|
||||
Opcode.SWAP 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.BREAKPOINT to InstructionFormat(NN, false, false, false, false)
|
||||
)
|
||||
|
@ -10,23 +10,41 @@ class Memory {
|
||||
mem.fill(0u)
|
||||
}
|
||||
|
||||
fun getB(address: Int): UByte {
|
||||
fun getUB(address: Int): UByte {
|
||||
return mem[address]
|
||||
}
|
||||
|
||||
fun setB(address: Int, value: UByte) {
|
||||
fun getSB(address: Int): Byte {
|
||||
return mem[address].toByte()
|
||||
}
|
||||
|
||||
fun setUB(address: Int, value: UByte) {
|
||||
mem[address] = value
|
||||
}
|
||||
|
||||
fun getW(address: Int): UShort {
|
||||
fun setSB(address: Int, value: Byte) {
|
||||
mem[address] = value.toUByte()
|
||||
}
|
||||
|
||||
fun getUW(address: Int): UShort {
|
||||
return (256u*mem[address] + mem[address+1]).toUShort()
|
||||
}
|
||||
|
||||
fun setW(address: Int, value: UShort) {
|
||||
fun getSW(address: Int): Short {
|
||||
return (mem[address].toInt()*256 + mem[address+1].toInt()).toShort()
|
||||
}
|
||||
|
||||
fun setUW(address: Int, value: UShort) {
|
||||
mem[address] = (value.toInt() ushr 8).toUByte()
|
||||
mem[address+1] = value.toUByte()
|
||||
}
|
||||
|
||||
fun setSW(address: Int, value: Short) {
|
||||
val uv = value.toUShort()
|
||||
mem[address] = (uv.toInt() ushr 8).toUByte()
|
||||
mem[address+1] = uv.toUByte()
|
||||
}
|
||||
|
||||
// for now, no LONG 32-bits and no FLOAT support.
|
||||
// fun getL(address: Int): UInt {
|
||||
// return mem[address+3] + 256u*mem[address+2] + 65536u*mem[address+1] + 16777216u*mem[address]
|
||||
|
@ -10,15 +10,27 @@ class Registers {
|
||||
registers.fill(0u)
|
||||
}
|
||||
|
||||
fun setB(reg: Int, value: UByte) {
|
||||
fun setUB(reg: Int, value: UByte) {
|
||||
registers[reg] = registers[reg] and 0xff00u or value.toUShort()
|
||||
}
|
||||
|
||||
fun setW(reg: Int, value: UShort) {
|
||||
fun setSB(reg: Int, value: Byte) {
|
||||
registers[reg] = registers[reg] and 0xff00u or (value.toUShort() and 0x00ffu)
|
||||
}
|
||||
|
||||
fun setUW(reg: Int, value: UShort) {
|
||||
registers[reg] = value
|
||||
}
|
||||
|
||||
fun getB(reg: Int) = registers[reg].toUByte()
|
||||
fun setSW(reg: Int, value: Short) {
|
||||
registers[reg] = value.toUShort()
|
||||
}
|
||||
|
||||
fun getW(reg: Int) = registers[reg]
|
||||
}
|
||||
fun getUB(reg: Int) = registers[reg].toUByte()
|
||||
|
||||
fun getSB(reg: Int) = registers[reg].toByte()
|
||||
|
||||
fun getUW(reg: Int) = registers[reg]
|
||||
|
||||
fun getSW(reg: Int) = registers[reg].toShort()
|
||||
}
|
||||
|
@ -17,7 +17,9 @@ SYSCALLS:
|
||||
8 = gfx_enable ; enable graphics window r0.b = 0 -> lores 320x240, r0.b = 1 -> hires 640x480
|
||||
9 = gfx_clear ; clear graphics window with shade in r0.b
|
||||
10 = gfx_plot ; plot pixel in graphics window, r0.w/r1.w contain X and Y coordinates, r2.b contains brightness
|
||||
11 = rnd ; random BYTE
|
||||
11 = rnd ; random BYTE
|
||||
12 = wait ; wait certain amount of jiffies (1/60 sec)
|
||||
13 = waitvsync ; wait on vsync
|
||||
*/
|
||||
|
||||
enum class Syscall {
|
||||
@ -33,6 +35,8 @@ enum class Syscall {
|
||||
GFX_CLEAR,
|
||||
GFX_PLOT,
|
||||
RND,
|
||||
WAIT,
|
||||
WAITVSYNC
|
||||
}
|
||||
|
||||
object SysCalls {
|
||||
@ -45,13 +49,13 @@ object SysCalls {
|
||||
vm.exit()
|
||||
}
|
||||
Syscall.PRINT_C -> {
|
||||
val char = vm.registers.getB(0).toInt()
|
||||
val char = vm.registers.getUB(0).toInt()
|
||||
print(Char(char))
|
||||
}
|
||||
Syscall.PRINT_S -> {
|
||||
var addr = vm.registers.getW(0).toInt()
|
||||
var addr = vm.registers.getUW(0).toInt()
|
||||
while(true) {
|
||||
val char = vm.memory.getB(addr).toInt()
|
||||
val char = vm.memory.getUB(addr).toInt()
|
||||
if(char==0)
|
||||
break
|
||||
print(Char(char))
|
||||
@ -59,29 +63,34 @@ object SysCalls {
|
||||
}
|
||||
}
|
||||
Syscall.PRINT_U8 -> {
|
||||
print(vm.registers.getB(0))
|
||||
print(vm.registers.getUB(0))
|
||||
}
|
||||
Syscall.PRINT_U16 -> {
|
||||
print(vm.registers.getW(0))
|
||||
print(vm.registers.getUW(0))
|
||||
}
|
||||
Syscall.INPUT -> {
|
||||
var input = readln()
|
||||
val maxlen = vm.registers.getB(1).toInt()
|
||||
val maxlen = vm.registers.getUB(1).toInt()
|
||||
if(maxlen>0)
|
||||
input = input.substring(0, min(input.length, maxlen))
|
||||
vm.memory.setString(vm.registers.getW(0).toInt(), input, true)
|
||||
vm.registers.setW(65535, input.length.toUShort())
|
||||
vm.memory.setString(vm.registers.getUW(0).toInt(), input, true)
|
||||
vm.registers.setUW(65535, input.length.toUShort())
|
||||
}
|
||||
Syscall.SLEEP -> {
|
||||
val duration = vm.registers.getW(0).toLong()
|
||||
val duration = vm.registers.getUW(0).toLong()
|
||||
Thread.sleep(duration)
|
||||
}
|
||||
Syscall.GFX_ENABLE -> vm.gfx_enable()
|
||||
Syscall.GFX_CLEAR -> vm.gfx_clear()
|
||||
Syscall.GFX_PLOT -> vm.gfx_plot()
|
||||
Syscall.RND -> {
|
||||
vm.registers.setB(0, (Random.nextInt() ushr 3).toUByte())
|
||||
vm.registers.setUB(0, (Random.nextInt() ushr 3).toUByte())
|
||||
}
|
||||
Syscall.WAIT -> {
|
||||
val millis = vm.registers.getUW(0).toLong() * 1000/60
|
||||
Thread.sleep(millis)
|
||||
}
|
||||
Syscall.WAITVSYNC -> vm.waitvsync()
|
||||
else -> TODO("syscall ${call.name}")
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package prog8.vm
|
||||
|
||||
import java.awt.Toolkit
|
||||
import java.util.*
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
@ -60,7 +61,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
}
|
||||
|
||||
fun exit() {
|
||||
throw ProgramExitException(registers.getW(0).toInt())
|
||||
throw ProgramExitException(registers.getUW(0).toInt())
|
||||
}
|
||||
|
||||
fun step(count: Int=1) {
|
||||
@ -132,11 +133,13 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
Opcode.AND -> InsAND(ins)
|
||||
Opcode.OR -> InsOR(ins)
|
||||
Opcode.XOR -> InsXOR(ins)
|
||||
Opcode.ASR -> InsASR(ins)
|
||||
Opcode.LSR -> InsLSR(ins)
|
||||
Opcode.LSL -> InsLSL(ins)
|
||||
Opcode.ROR -> InsROR(ins)
|
||||
Opcode.ROL -> InsROL(ins)
|
||||
Opcode.SWAP -> InsSWAP(ins)
|
||||
Opcode.CONCAT -> InsCONCAT(ins)
|
||||
Opcode.PUSH -> InsPUSH(ins)
|
||||
Opcode.POP -> InsPOP(ins)
|
||||
Opcode.COPY -> InsCOPY(ins)
|
||||
@ -148,8 +151,8 @@ class VirtualMachine(val memory: Memory, program: List<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())
|
||||
VmDataType.BYTE -> registers.setUB(reg, value.toUByte())
|
||||
VmDataType.WORD -> registers.setUW(reg, value.toUShort())
|
||||
}
|
||||
}
|
||||
|
||||
@ -158,8 +161,8 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
throw StackOverflowError("valuestack limit 128 exceeded")
|
||||
|
||||
val value = when(i.type!!) {
|
||||
VmDataType.BYTE -> registers.getB(i.reg1!!).toInt()
|
||||
VmDataType.WORD -> registers.getW(i.reg1!!).toInt()
|
||||
VmDataType.BYTE -> registers.getUB(i.reg1!!).toInt()
|
||||
VmDataType.WORD -> registers.getUW(i.reg1!!).toInt()
|
||||
}
|
||||
valueStack.push(value)
|
||||
pc++
|
||||
@ -189,32 +192,32 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
|
||||
private fun InsLOADM(i: Instruction) {
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> registers.setB(i.reg1!!, memory.getB(i.value!!))
|
||||
VmDataType.WORD -> registers.setW(i.reg1!!, memory.getW(i.value!!))
|
||||
VmDataType.BYTE -> registers.setUB(i.reg1!!, memory.getUB(i.value!!))
|
||||
VmDataType.WORD -> registers.setUW(i.reg1!!, memory.getUW(i.value!!))
|
||||
}
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsLOADI(i: Instruction) {
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> registers.setB(i.reg1!!, memory.getB(registers.getW(i.reg2!!).toInt()))
|
||||
VmDataType.WORD -> registers.setW(i.reg1!!, memory.getW(registers.getW(i.reg2!!).toInt()))
|
||||
VmDataType.BYTE -> registers.setUB(i.reg1!!, memory.getUB(registers.getUW(i.reg2!!).toInt()))
|
||||
VmDataType.WORD -> registers.setUW(i.reg1!!, memory.getUW(registers.getUW(i.reg2!!).toInt()))
|
||||
}
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsLOADX(i: Instruction) {
|
||||
when (i.type!!) {
|
||||
VmDataType.BYTE -> registers.setB(i.reg1!!, memory.getB(i.value!! + registers.getW(i.reg2!!).toInt()))
|
||||
VmDataType.WORD -> registers.setW(i.reg1!!, memory.getW(i.value!! + registers.getW(i.reg2!!).toInt()))
|
||||
VmDataType.BYTE -> registers.setUB(i.reg1!!, memory.getUB(i.value!! + registers.getUW(i.reg2!!).toInt()))
|
||||
VmDataType.WORD -> registers.setUW(i.reg1!!, memory.getUW(i.value!! + registers.getUW(i.reg2!!).toInt()))
|
||||
}
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsLOADR(i: Instruction) {
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> registers.setB(i.reg1!!, registers.getB(i.reg2!!))
|
||||
VmDataType.WORD -> registers.setW(i.reg1!!, registers.getW(i.reg2!!))
|
||||
VmDataType.BYTE -> registers.setUB(i.reg1!!, registers.getUB(i.reg2!!))
|
||||
VmDataType.WORD -> registers.setUW(i.reg1!!, registers.getUW(i.reg2!!))
|
||||
}
|
||||
pc++
|
||||
}
|
||||
@ -222,14 +225,14 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
private fun InsSWAPREG(i: Instruction) {
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> {
|
||||
val oldR2 = registers.getB(i.reg2!!)
|
||||
registers.setB(i.reg2, registers.getB(i.reg1!!))
|
||||
registers.setB(i.reg1, oldR2)
|
||||
val oldR2 = registers.getUB(i.reg2!!)
|
||||
registers.setUB(i.reg2, registers.getUB(i.reg1!!))
|
||||
registers.setUB(i.reg1, oldR2)
|
||||
}
|
||||
VmDataType.WORD -> {
|
||||
val oldR2 = registers.getW(i.reg2!!)
|
||||
registers.setW(i.reg2, registers.getW(i.reg1!!))
|
||||
registers.setW(i.reg1, oldR2)
|
||||
val oldR2 = registers.getUW(i.reg2!!)
|
||||
registers.setUW(i.reg2, registers.getUW(i.reg1!!))
|
||||
registers.setUW(i.reg1, oldR2)
|
||||
}
|
||||
}
|
||||
pc++
|
||||
@ -237,47 +240,47 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
|
||||
private fun InsSTOREM(i: Instruction) {
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> memory.setB(i.value!!, registers.getB(i.reg1!!))
|
||||
VmDataType.WORD -> memory.setW(i.value!!, registers.getW(i.reg1!!))
|
||||
VmDataType.BYTE -> memory.setUB(i.value!!, registers.getUB(i.reg1!!))
|
||||
VmDataType.WORD -> memory.setUW(i.value!!, registers.getUW(i.reg1!!))
|
||||
}
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsSTOREI(i: Instruction) {
|
||||
when (i.type!!) {
|
||||
VmDataType.BYTE -> memory.setB(registers.getW(i.reg2!!).toInt(), registers.getB(i.reg1!!))
|
||||
VmDataType.WORD -> memory.setW(registers.getW(i.reg2!!).toInt(), registers.getW(i.reg1!!))
|
||||
VmDataType.BYTE -> memory.setUB(registers.getUW(i.reg2!!).toInt(), registers.getUB(i.reg1!!))
|
||||
VmDataType.WORD -> memory.setUW(registers.getUW(i.reg2!!).toInt(), registers.getUW(i.reg1!!))
|
||||
}
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsSTOREX(i: Instruction) {
|
||||
when (i.type!!) {
|
||||
VmDataType.BYTE -> memory.setB(registers.getW(i.reg2!!).toInt() + i.value!!, registers.getB(i.reg1!!))
|
||||
VmDataType.WORD -> memory.setW(registers.getW(i.reg2!!).toInt() + i.value!!, registers.getW(i.reg1!!))
|
||||
VmDataType.BYTE -> memory.setUB(registers.getUW(i.reg2!!).toInt() + i.value!!, registers.getUB(i.reg1!!))
|
||||
VmDataType.WORD -> memory.setUW(registers.getUW(i.reg2!!).toInt() + i.value!!, registers.getUW(i.reg1!!))
|
||||
}
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsSTOREZ(i: Instruction) {
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> memory.setB(i.value!!, 0u)
|
||||
VmDataType.WORD -> memory.setW(i.value!!, 0u)
|
||||
VmDataType.BYTE -> memory.setUB(i.value!!, 0u)
|
||||
VmDataType.WORD -> memory.setUW(i.value!!, 0u)
|
||||
}
|
||||
}
|
||||
|
||||
private fun InsSTOREZI(i: Instruction) {
|
||||
when (i.type!!) {
|
||||
VmDataType.BYTE -> memory.setB(registers.getW(i.reg2!!).toInt(), 0u)
|
||||
VmDataType.WORD -> memory.setW(registers.getW(i.reg2!!).toInt(), 0u)
|
||||
VmDataType.BYTE -> memory.setUB(registers.getUW(i.reg2!!).toInt(), 0u)
|
||||
VmDataType.WORD -> memory.setUW(registers.getUW(i.reg2!!).toInt(), 0u)
|
||||
}
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsSTOREZX(i: Instruction) {
|
||||
when (i.type!!) {
|
||||
VmDataType.BYTE -> memory.setB(registers.getW(i.reg2!!).toInt() + i.value!!, 0u)
|
||||
VmDataType.WORD -> memory.setW(registers.getW(i.reg2!!).toInt() + i.value!!, 0u)
|
||||
VmDataType.BYTE -> memory.setUB(registers.getUW(i.reg2!!).toInt() + i.value!!, 0u)
|
||||
VmDataType.WORD -> memory.setUW(registers.getUW(i.reg2!!).toInt() + i.value!!, 0u)
|
||||
}
|
||||
pc++
|
||||
}
|
||||
@ -287,7 +290,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
}
|
||||
|
||||
private fun InsJUMPI(i: Instruction) {
|
||||
pc = registers.getW(i.reg1!!).toInt()
|
||||
pc = registers.getUW(i.reg1!!).toInt()
|
||||
}
|
||||
|
||||
private fun InsCALL(i: Instruction) {
|
||||
@ -297,7 +300,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
|
||||
private fun InsCALLI(i: Instruction) {
|
||||
callStack.push(pc+1)
|
||||
pc = registers.getW(i.reg1!!).toInt()
|
||||
pc = registers.getUW(i.reg1!!).toInt()
|
||||
}
|
||||
|
||||
private fun InsRETURN() {
|
||||
@ -310,13 +313,13 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
private fun InsBZ(i: Instruction) {
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> {
|
||||
if(registers.getB(i.reg1!!)==0.toUByte())
|
||||
if(registers.getUB(i.reg1!!)==0.toUByte())
|
||||
pc = i.value!!
|
||||
else
|
||||
pc++
|
||||
}
|
||||
VmDataType.WORD -> {
|
||||
if(registers.getW(i.reg1!!)==0.toUShort())
|
||||
if(registers.getUW(i.reg1!!)==0.toUShort())
|
||||
pc = i.value!!
|
||||
else
|
||||
pc++
|
||||
@ -327,13 +330,13 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
private fun InsBNZ(i: Instruction) {
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> {
|
||||
if(registers.getB(i.reg1!!)!=0.toUByte())
|
||||
if(registers.getUB(i.reg1!!)!=0.toUByte())
|
||||
pc = i.value!!
|
||||
else
|
||||
pc++
|
||||
}
|
||||
VmDataType.WORD -> {
|
||||
if(registers.getW(i.reg1!!)!=0.toUShort())
|
||||
if(registers.getUW(i.reg1!!)!=0.toUShort())
|
||||
pc = i.value!!
|
||||
else
|
||||
pc++
|
||||
@ -498,24 +501,24 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
|
||||
private fun InsINC(i: Instruction) {
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> registers.setB(i.reg1!!, (registers.getB(i.reg1)+1u).toUByte())
|
||||
VmDataType.WORD -> registers.setW(i.reg1!!, (registers.getW(i.reg1)+1u).toUShort())
|
||||
VmDataType.BYTE -> registers.setUB(i.reg1!!, (registers.getUB(i.reg1)+1u).toUByte())
|
||||
VmDataType.WORD -> registers.setUW(i.reg1!!, (registers.getUW(i.reg1)+1u).toUShort())
|
||||
}
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsDEC(i: Instruction) {
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> registers.setB(i.reg1!!, (registers.getB(i.reg1)-1u).toUByte())
|
||||
VmDataType.WORD -> registers.setW(i.reg1!!, (registers.getW(i.reg1)-1u).toUShort())
|
||||
VmDataType.BYTE -> registers.setUB(i.reg1!!, (registers.getUB(i.reg1)-1u).toUByte())
|
||||
VmDataType.WORD -> registers.setUW(i.reg1!!, (registers.getUW(i.reg1)-1u).toUShort())
|
||||
}
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsNEG(i: Instruction) {
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> registers.setB(i.reg1!!, (-registers.getB(i.reg1).toInt()).toUByte())
|
||||
VmDataType.WORD -> registers.setW(i.reg1!!, (-registers.getW(i.reg1).toInt()).toUShort())
|
||||
VmDataType.BYTE -> registers.setUB(i.reg1!!, (-registers.getUB(i.reg1).toInt()).toUByte())
|
||||
VmDataType.WORD -> registers.setUW(i.reg1!!, (-registers.getUW(i.reg1).toInt()).toUShort())
|
||||
}
|
||||
pc++
|
||||
}
|
||||
@ -553,8 +556,8 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
}
|
||||
|
||||
private fun arithByte(operator: String, reg1: Int, reg2: Int, reg3: Int?, value: UByte?) {
|
||||
val left = registers.getB(reg2)
|
||||
val right = value ?: registers.getB(reg3!!)
|
||||
val left = registers.getUB(reg2)
|
||||
val right = value ?: registers.getUB(reg3!!)
|
||||
val result = when(operator) {
|
||||
"+" -> left + right
|
||||
"-" -> left - right
|
||||
@ -569,12 +572,12 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
}
|
||||
else -> TODO("operator $operator")
|
||||
}
|
||||
registers.setB(reg1, result.toUByte())
|
||||
registers.setUB(reg1, result.toUByte())
|
||||
}
|
||||
|
||||
private fun arithWord(operator: String, reg1: Int, reg2: Int, reg3: Int?, value: UShort?) {
|
||||
val left = registers.getW(reg2)
|
||||
val right = value ?: registers.getW(reg3!!)
|
||||
val left = registers.getUW(reg2)
|
||||
val right = value ?: registers.getUW(reg3!!)
|
||||
val result = when(operator) {
|
||||
"+" -> left + right
|
||||
"-" -> left - right
|
||||
@ -589,7 +592,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
}
|
||||
else -> TODO("operator $operator")
|
||||
}
|
||||
registers.setW(reg1, result.toUShort())
|
||||
registers.setUW(reg1, result.toUShort())
|
||||
}
|
||||
|
||||
private fun InsSUB(i: Instruction) {
|
||||
@ -602,7 +605,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
|
||||
private fun InsEXT(i: Instruction) {
|
||||
when(i.type!!){
|
||||
VmDataType.BYTE -> registers.setW(i.reg1!!, registers.getB(i.reg1).toUShort())
|
||||
VmDataType.BYTE -> registers.setUW(i.reg1!!, registers.getUB(i.reg1).toUShort())
|
||||
VmDataType.WORD -> TODO("ext.w requires 32 bits registers")
|
||||
}
|
||||
pc++
|
||||
@ -610,7 +613,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
|
||||
private fun InsEXTS(i: Instruction) {
|
||||
when(i.type!!){
|
||||
VmDataType.BYTE -> registers.setW(i.reg1!!, (registers.getB(i.reg1).toByte()).toUShort())
|
||||
VmDataType.BYTE -> registers.setSW(i.reg1!!, registers.getSB(i.reg1).toShort())
|
||||
VmDataType.WORD -> TODO("ext.w requires 32 bits registers")
|
||||
}
|
||||
pc++
|
||||
@ -619,8 +622,8 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
private fun InsAND(i: Instruction) {
|
||||
val (left: UInt, right: UInt) = getLogicalOperandsU(i)
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> registers.setB(i.reg1!!, (left and right).toUByte())
|
||||
VmDataType.WORD -> registers.setW(i.reg1!!, (left and right).toUShort())
|
||||
VmDataType.BYTE -> registers.setUB(i.reg1!!, (left and right).toUByte())
|
||||
VmDataType.WORD -> registers.setUW(i.reg1!!, (left and right).toUShort())
|
||||
}
|
||||
pc++
|
||||
}
|
||||
@ -628,8 +631,8 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
private fun InsOR(i: Instruction) {
|
||||
val (left: UInt, right: UInt) = getLogicalOperandsU(i)
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> registers.setB(i.reg1!!, (left or right).toUByte())
|
||||
VmDataType.WORD -> registers.setW(i.reg1!!, (left or right).toUShort())
|
||||
VmDataType.BYTE -> registers.setUB(i.reg1!!, (left or right).toUByte())
|
||||
VmDataType.WORD -> registers.setUW(i.reg1!!, (left or right).toUShort())
|
||||
}
|
||||
pc++
|
||||
}
|
||||
@ -637,8 +640,17 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
private fun InsXOR(i: Instruction) {
|
||||
val (left: UInt, right: UInt) = getLogicalOperandsU(i)
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> registers.setB(i.reg1!!, (left xor right).toUByte())
|
||||
VmDataType.WORD -> registers.setW(i.reg1!!, (left xor right).toUShort())
|
||||
VmDataType.BYTE -> registers.setUB(i.reg1!!, (left xor right).toUByte())
|
||||
VmDataType.WORD -> registers.setUW(i.reg1!!, (left xor right).toUShort())
|
||||
}
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsASR(i: Instruction) {
|
||||
val (left: Int, right: Int) = getLogicalOperandsS(i)
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> registers.setSB(i.reg1!!, (left shr right).toByte())
|
||||
VmDataType.WORD -> registers.setSW(i.reg1!!, (left shr right).toShort())
|
||||
}
|
||||
pc++
|
||||
}
|
||||
@ -646,8 +658,8 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
private fun InsLSR(i: Instruction) {
|
||||
val (left: UInt, right: UInt) = getLogicalOperandsU(i)
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> registers.setB(i.reg1!!, (left shr right.toInt()).toUByte())
|
||||
VmDataType.WORD -> registers.setW(i.reg1!!, (left shr right.toInt()).toUShort())
|
||||
VmDataType.BYTE -> registers.setUB(i.reg1!!, (left shr right.toInt()).toUByte())
|
||||
VmDataType.WORD -> registers.setUW(i.reg1!!, (left shr right.toInt()).toUShort())
|
||||
}
|
||||
pc++
|
||||
}
|
||||
@ -655,8 +667,8 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
private fun InsLSL(i: Instruction) {
|
||||
val (left: UInt, right: UInt) = getLogicalOperandsU(i)
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> registers.setB(i.reg1!!, (left shl right.toInt()).toUByte())
|
||||
VmDataType.WORD -> registers.setW(i.reg1!!, (left shl right.toInt()).toUShort())
|
||||
VmDataType.BYTE -> registers.setUB(i.reg1!!, (left shl right.toInt()).toUByte())
|
||||
VmDataType.WORD -> registers.setUW(i.reg1!!, (left shl right.toInt()).toUShort())
|
||||
}
|
||||
pc++
|
||||
}
|
||||
@ -664,8 +676,8 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
private fun InsROR(i: Instruction) {
|
||||
val (left: UInt, right: UInt) = getLogicalOperandsU(i)
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> registers.setB(i.reg1!!, (left.rotateRight(right.toInt()).toUByte()))
|
||||
VmDataType.WORD -> registers.setW(i.reg1!!, (left.rotateRight(right.toInt()).toUShort()))
|
||||
VmDataType.BYTE -> registers.setUB(i.reg1!!, (left.rotateRight(right.toInt()).toUByte()))
|
||||
VmDataType.WORD -> registers.setUW(i.reg1!!, (left.rotateRight(right.toInt()).toUShort()))
|
||||
}
|
||||
pc++
|
||||
}
|
||||
@ -673,8 +685,8 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
private fun InsROL(i: Instruction) {
|
||||
val (left: UInt, right: UInt) = getLogicalOperandsU(i)
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> registers.setB(i.reg1!!, (left.rotateLeft(right.toInt()).toUByte()))
|
||||
VmDataType.WORD -> registers.setW(i.reg1!!, (left.rotateLeft(right.toInt()).toUShort()))
|
||||
VmDataType.BYTE -> registers.setUB(i.reg1!!, (left.rotateLeft(right.toInt()).toUByte()))
|
||||
VmDataType.WORD -> registers.setUW(i.reg1!!, (left.rotateLeft(right.toInt()).toUShort()))
|
||||
}
|
||||
pc++
|
||||
}
|
||||
@ -682,9 +694,21 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
private fun InsSWAP(i: Instruction) {
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> {
|
||||
val value = registers.getW(i.reg2!!)
|
||||
val value = registers.getUW(i.reg2!!)
|
||||
val newValue = value.toUByte()*256u + (value.toInt() ushr 8).toUInt()
|
||||
registers.setW(i.reg1!!, newValue.toUShort())
|
||||
registers.setUW(i.reg1!!, newValue.toUShort())
|
||||
}
|
||||
VmDataType.WORD -> TODO("swap.w requires 32-bits registers")
|
||||
}
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsCONCAT(i: Instruction) {
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> {
|
||||
val msb = registers.getUB(i.reg2!!)
|
||||
val lsb = registers.getUB(i.reg3!!)
|
||||
registers.setUW(i.reg1!!, ((msb.toInt() shl 8) or lsb.toInt()).toUShort())
|
||||
}
|
||||
VmDataType.WORD -> TODO("swap.w requires 32-bits registers")
|
||||
}
|
||||
@ -696,13 +720,13 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
private fun InsCOPYZ(i: Instruction) = doCopy(i.reg1!!, i.reg2!!, null, true)
|
||||
|
||||
private fun doCopy(reg1: Int, reg2: Int, length: Int?, untilzero: Boolean) {
|
||||
var from = registers.getW(reg1).toInt()
|
||||
var to = registers.getW(reg2).toInt()
|
||||
var from = registers.getUW(reg1).toInt()
|
||||
var to = registers.getUW(reg2).toInt()
|
||||
if(untilzero) {
|
||||
while(true) {
|
||||
val char = memory.getB(from).toInt()
|
||||
memory.setB(to, char.toUByte())
|
||||
if(char==0)
|
||||
val char = memory.getUB(from)
|
||||
memory.setUB(to, char)
|
||||
if(char.toInt()==0)
|
||||
break
|
||||
from++
|
||||
to++
|
||||
@ -710,8 +734,8 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
} else {
|
||||
var len = length!!
|
||||
while(len>0) {
|
||||
val char = memory.getB(from).toInt()
|
||||
memory.setB(to, char.toUByte())
|
||||
val char = memory.getUB(from)
|
||||
memory.setUB(to, char)
|
||||
from++
|
||||
to++
|
||||
len--
|
||||
@ -722,40 +746,49 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
|
||||
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())
|
||||
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())
|
||||
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())
|
||||
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())
|
||||
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())
|
||||
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())
|
||||
null -> throw IllegalArgumentException("need type for logical instruction")
|
||||
}
|
||||
}
|
||||
|
||||
private fun getLogicalOperandsS(i: Instruction): Pair<Int, Int> {
|
||||
return when(i.type) {
|
||||
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())
|
||||
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())
|
||||
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())
|
||||
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())
|
||||
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())
|
||||
null -> throw IllegalArgumentException("need type for branch instruction")
|
||||
}
|
||||
}
|
||||
@ -763,7 +796,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
private var window: GraphicsWindow? = null
|
||||
|
||||
fun gfx_enable() {
|
||||
window = when(registers.getB(0).toInt()) {
|
||||
window = when(registers.getUB(0).toInt()) {
|
||||
0 -> GraphicsWindow(320, 240, 3)
|
||||
1 -> GraphicsWindow(640, 480, 2)
|
||||
else -> throw IllegalArgumentException("invalid screen mode")
|
||||
@ -772,14 +805,18 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
}
|
||||
|
||||
fun gfx_clear() {
|
||||
window?.clear(registers.getB(0).toInt())
|
||||
window?.clear(registers.getUB(0).toInt())
|
||||
}
|
||||
|
||||
fun gfx_plot() {
|
||||
window?.plot(registers.getW(0).toInt(), registers.getW(1).toInt(), registers.getB(2).toInt())
|
||||
window?.plot(registers.getUW(0).toInt(), registers.getUW(1).toInt(), registers.getUB(2).toInt())
|
||||
}
|
||||
|
||||
fun gfx_close() {
|
||||
window?.close()
|
||||
}
|
||||
|
||||
fun waitvsync() {
|
||||
Toolkit.getDefaultToolkit().sync() // not really the same as wait on vsync, but there's noting else
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user