mirror of
https://github.com/irmen/prog8.git
synced 2025-08-18 19:33:18 +00:00
vm: added cmp() and most of the status-branch instructions
This commit is contained in:
@@ -102,16 +102,16 @@ enum class Statusflag {
|
|||||||
enum class BranchCondition {
|
enum class BranchCondition {
|
||||||
CS,
|
CS,
|
||||||
CC,
|
CC,
|
||||||
EQ,
|
EQ, // EQ == Z
|
||||||
Z,
|
Z,
|
||||||
NE,
|
NE, // NE == NZ
|
||||||
NZ,
|
NZ,
|
||||||
|
MI, // MI == NEG
|
||||||
|
NEG,
|
||||||
|
PL, // PL == POS
|
||||||
|
POS,
|
||||||
VS,
|
VS,
|
||||||
VC,
|
VC,
|
||||||
MI,
|
|
||||||
NEG,
|
|
||||||
PL,
|
|
||||||
POS
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -16,7 +16,7 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
"any" -> funcAny(call, resultRegister)
|
"any" -> funcAny(call, resultRegister)
|
||||||
"all" -> funcAll(call, resultRegister)
|
"all" -> funcAll(call, resultRegister)
|
||||||
"abs" -> TODO("abs once we can compare plus minus")
|
"abs" -> TODO("abs once we can compare plus minus")
|
||||||
"cmp" -> TODO("cmp() can't be used on vm because no processor status bits implemented")
|
"cmp" -> funcCmp(call)
|
||||||
"sgn" -> funcSgn(call, resultRegister)
|
"sgn" -> funcSgn(call, resultRegister)
|
||||||
"sin" -> TODO("floats not yet implemented")
|
"sin" -> TODO("floats not yet implemented")
|
||||||
"cos" -> TODO("floats not yet implemented")
|
"cos" -> TODO("floats not yet implemented")
|
||||||
@@ -68,6 +68,16 @@ internal class BuiltinFuncGen(private val codeGen: CodeGen, private val exprGen:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun funcCmp(call: PtBuiltinFunctionCall): VmCodeChunk {
|
||||||
|
val code = VmCodeChunk()
|
||||||
|
val leftRegister = codeGen.vmRegisters.nextFree()
|
||||||
|
val rightRegister = codeGen.vmRegisters.nextFree()
|
||||||
|
code += exprGen.translateExpression(call.args[0], leftRegister)
|
||||||
|
code += exprGen.translateExpression(call.args[1], rightRegister)
|
||||||
|
code += VmCodeInstruction(Opcode.CMP, codeGen.vmType(call.args[0].type), reg1=leftRegister, reg2=rightRegister)
|
||||||
|
return code
|
||||||
|
}
|
||||||
|
|
||||||
private fun funcAny(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
private fun funcAny(call: PtBuiltinFunctionCall, resultRegister: Int): VmCodeChunk {
|
||||||
val arrayName = call.args[0] as PtIdentifier
|
val arrayName = call.args[0] as PtIdentifier
|
||||||
val array = codeGen.symbolTable.flat.getValue(arrayName.targetName) as StStaticVariable
|
val array = codeGen.symbolTable.flat.getValue(arrayName.targetName) as StStaticVariable
|
||||||
|
@@ -110,16 +110,16 @@ class CodeGen(internal val program: PtProgram,
|
|||||||
private fun translate(branch: PtConditionalBranch): VmCodeChunk {
|
private fun translate(branch: PtConditionalBranch): VmCodeChunk {
|
||||||
val code = VmCodeChunk()
|
val code = VmCodeChunk()
|
||||||
val elseLabel = createLabelName()
|
val elseLabel = createLabelName()
|
||||||
when(branch.condition) {
|
// note that the branch opcode used is the opposite as the branch condition, because the generated code jumps to the 'else' part
|
||||||
BranchCondition.CS -> {
|
code += when(branch.condition) {
|
||||||
code += VmCodeInstruction(Opcode.BSTCC, symbol = elseLabel)
|
BranchCondition.CS -> VmCodeInstruction(Opcode.BSTCC, symbol = elseLabel)
|
||||||
}
|
BranchCondition.CC -> VmCodeInstruction(Opcode.BSTCS, symbol = elseLabel)
|
||||||
BranchCondition.CC -> {
|
BranchCondition.EQ, BranchCondition.Z -> VmCodeInstruction(Opcode.BSTNE, symbol = elseLabel)
|
||||||
code += VmCodeInstruction(Opcode.BSTCS, symbol = elseLabel)
|
BranchCondition.NE, BranchCondition.NZ -> VmCodeInstruction(Opcode.BSTEQ, symbol = elseLabel)
|
||||||
}
|
BranchCondition.MI, BranchCondition.NEG -> VmCodeInstruction(Opcode.BSTPOS, symbol = elseLabel)
|
||||||
else -> {
|
BranchCondition.PL, BranchCondition.POS -> VmCodeInstruction(Opcode.BSTNEG, symbol = elseLabel)
|
||||||
throw AssemblyError("conditional branch ${branch.condition} not supported in vm target due to lack of cpu flags ${branch.position}")
|
BranchCondition.VC,
|
||||||
}
|
BranchCondition.VS -> throw AssemblyError("conditional branch ${branch.condition} not supported in vm target due to lack of cpu V flag ${branch.position}")
|
||||||
}
|
}
|
||||||
code += translateNode(branch.trueScope)
|
code += translateNode(branch.trueScope)
|
||||||
if(branch.falseScope.children.isNotEmpty()) {
|
if(branch.falseScope.children.isNotEmpty()) {
|
||||||
|
@@ -15,11 +15,37 @@ sys {
|
|||||||
; 3 = print_s ; print 0-terminated string from memory
|
; 3 = print_s ; print 0-terminated string from memory
|
||||||
; 4 = print_u8 ; print unsigned int byte
|
; 4 = print_u8 ; print unsigned int byte
|
||||||
; 5 = print_u16 ; print unsigned int word
|
; 5 = print_u16 ; print unsigned int word
|
||||||
; 6 = input ; reads a line of text entered by the user, r0.w = memory buffer, r1.b = maxlength (0-255, 0=unlimited). Zero-terminates the string. Returns length in r65535.w
|
; 6 = input ; reads a line of text entered by the user, r0.w = memory buffer, r1.b = maxlength (0-255, 0=unlimited). Zero-terminates the string. Returns length in r0.w
|
||||||
; 7 = sleep ; sleep amount of milliseconds
|
; 7 = sleep ; sleep amount of milliseconds
|
||||||
; 8 = gfx_enable ; enable graphics window r0.b = 0 -> lores 320x240, r0.b = 1 -> hires 640x480
|
; 8 = gfx_enable ; enable graphics window r0.b = 0 -> lores 320x240, r0.b = 1 -> hires 640x480
|
||||||
; 9 = gfx_clear ; clear graphics window with shade in r0.b
|
; 9 = gfx_clear ; clear graphics window with shade in r0.b
|
||||||
; 10 = gfx_plot ; plot pixel in graphics window, r0.w/r1.w contain X and Y coordinates, r2.b contains brightness
|
; 10 = gfx_plot ; plot pixel in graphics window, r0.w/r1.w contain X and Y coordinates, r2.b contains brightness
|
||||||
|
; 11 = rnd ; random BYTE
|
||||||
|
; 12 = rndw ; random WORD
|
||||||
|
; 13 = wait ; wait certain amount of jiffies (1/60 sec)
|
||||||
|
; 14 = waitvsync ; wait on vsync
|
||||||
|
; 15 = sort_ubyte array
|
||||||
|
; 16 = sort_byte array
|
||||||
|
; 17 = sort_uword array
|
||||||
|
; 18 = sort_word array
|
||||||
|
; 19 = max_ubyte array
|
||||||
|
; 20 = max_byte array
|
||||||
|
; 21 = max_uword array
|
||||||
|
; 22 = max_word array
|
||||||
|
; 23 = min_ubyte array
|
||||||
|
; 24 = min_byte array
|
||||||
|
; 25 = min_uword array
|
||||||
|
; 26 = min_word array
|
||||||
|
; 27 = sum_byte array
|
||||||
|
; 28 = sum_word array
|
||||||
|
; 29 = any_byte array
|
||||||
|
; 30 = any_word array
|
||||||
|
; 31 = all_byte array
|
||||||
|
; 32 = all_word array
|
||||||
|
; 33 = reverse_bytes array
|
||||||
|
; 34 = reverse_words array
|
||||||
|
; 35 = set_carry status flag
|
||||||
|
; 36 = clear_carry status flag
|
||||||
|
|
||||||
const ubyte SC_RESET = 0
|
const ubyte SC_RESET = 0
|
||||||
const ubyte SC_EXIT = 1
|
const ubyte SC_EXIT = 1
|
||||||
@@ -33,8 +59,11 @@ sys {
|
|||||||
const ubyte SC_GFX_CLEAR = 9
|
const ubyte SC_GFX_CLEAR = 9
|
||||||
const ubyte SC_GFX_PLOT = 10
|
const ubyte SC_GFX_PLOT = 10
|
||||||
const ubyte SC_RND = 11
|
const ubyte SC_RND = 11
|
||||||
const ubyte SC_WAIT = 12
|
const ubyte SC_RNDW = 12
|
||||||
const ubyte SC_WAITVSYNC = 13
|
const ubyte SC_WAIT = 13
|
||||||
|
const ubyte SC_WAITVSYNC = 14
|
||||||
|
const ubyte SC_SET_CARRY = 35
|
||||||
|
const ubyte SC_CLEAR_CARRY = 36
|
||||||
|
|
||||||
|
|
||||||
sub reset_system() {
|
sub reset_system() {
|
||||||
@@ -78,6 +107,14 @@ sys {
|
|||||||
; -- immediately exit the program with a return code in the A register
|
; -- immediately exit the program with a return code in the A register
|
||||||
void syscall1(SC_EXIT, returnvalue)
|
void syscall1(SC_EXIT, returnvalue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub clear_carry() {
|
||||||
|
void syscall(SC_CLEAR_CARRY)
|
||||||
|
}
|
||||||
|
|
||||||
|
sub set_carry() {
|
||||||
|
void syscall(SC_SET_CARRY)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cx16 {
|
cx16 {
|
||||||
|
@@ -3,6 +3,7 @@ TODO
|
|||||||
|
|
||||||
For next release
|
For next release
|
||||||
^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^
|
||||||
|
- vm: add abs().
|
||||||
- pipe operator: allow non-unary function calls in the pipe that specify the other argument(s) in the calls.
|
- pipe operator: allow non-unary function calls in the pipe that specify the other argument(s) in the calls.
|
||||||
- createAssemblyAndAssemble(): make it possible to actually get rid of the VarDecl nodes by fixing the rest of the code mentioned there.
|
- createAssemblyAndAssemble(): make it possible to actually get rid of the VarDecl nodes by fixing the rest of the code mentioned there.
|
||||||
- allow "xxx" * constexpr (where constexpr is not a number literal), now gives expression error not same type
|
- allow "xxx" * constexpr (where constexpr is not a number literal), now gives expression error not same type
|
||||||
@@ -11,7 +12,6 @@ For next release
|
|||||||
If we can do that why not perhaps also able to inline multi-line subroutines? Why would it be limited to just 1 line? Maybe to protect against code size bloat.
|
If we can do that why not perhaps also able to inline multi-line subroutines? Why would it be limited to just 1 line? Maybe to protect against code size bloat.
|
||||||
Inlined subroutines cannot contain further nested subroutines!
|
Inlined subroutines cannot contain further nested subroutines!
|
||||||
Once this works, look for library subroutines that should be inlined.
|
Once this works, look for library subroutines that should be inlined.
|
||||||
- vm: add support for status bits, status-branch instructions, and cmp() and abs() functions.
|
|
||||||
- floats: remove all floating point builtin functions and move them to the floats module instead,
|
- floats: remove all floating point builtin functions and move them to the floats module instead,
|
||||||
note: first try to move only sin and cos and see if the various examples still work!
|
note: first try to move only sin and cos and see if the various examples still work!
|
||||||
|
|
||||||
|
@@ -7,6 +7,16 @@
|
|||||||
main {
|
main {
|
||||||
sub start() {
|
sub start() {
|
||||||
|
|
||||||
|
byte v1 = -10
|
||||||
|
byte v2 = 20
|
||||||
|
|
||||||
|
cmp(v1,v2)
|
||||||
|
;sys.clear_carry()
|
||||||
|
if_cc
|
||||||
|
txt.print("cc\n")
|
||||||
|
if_cs
|
||||||
|
txt.print("cs\n")
|
||||||
|
|
||||||
; uword ww = 100
|
; uword ww = 100
|
||||||
; uword vv
|
; uword vv
|
||||||
; vv = ww+1
|
; vv = ww+1
|
||||||
@@ -16,24 +26,24 @@ main {
|
|||||||
; txt.print_uw(vv)
|
; txt.print_uw(vv)
|
||||||
; txt.nl()
|
; txt.nl()
|
||||||
|
|
||||||
; a "pixelshader":
|
; ; a "pixelshader":
|
||||||
void syscall1(8, 0) ; enable lo res creen
|
; void syscall1(8, 0) ; enable lo res creen
|
||||||
ubyte shifter
|
; ubyte shifter
|
||||||
|
;
|
||||||
; pokemon(1,0)
|
; ; pokemon(1,0)
|
||||||
|
;
|
||||||
repeat {
|
; repeat {
|
||||||
uword xx
|
; uword xx
|
||||||
uword yy = 0
|
; uword yy = 0
|
||||||
repeat 240 {
|
; repeat 240 {
|
||||||
xx = 0
|
; xx = 0
|
||||||
repeat 320 {
|
; repeat 320 {
|
||||||
syscall3(10, xx, yy, xx*yy + shifter) ; plot pixel
|
; syscall3(10, xx, yy, xx*yy + shifter) ; plot pixel
|
||||||
xx++
|
; xx++
|
||||||
}
|
; }
|
||||||
yy++
|
; yy++
|
||||||
}
|
; }
|
||||||
shifter+=4
|
; shifter+=4
|
||||||
}
|
; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -64,6 +64,10 @@ All have type b or w except the branches that only check status bits.
|
|||||||
|
|
||||||
bstcc location - branch to location if Status bit Carry is Clear
|
bstcc location - branch to location if Status bit Carry is Clear
|
||||||
bstcs location - branch to location if Status bit Carry is Set
|
bstcs location - branch to location if Status bit Carry is Set
|
||||||
|
bsteq location - branch to location if Status bit Zero is set
|
||||||
|
bstne location - branch to location if Status bit Zero is not set
|
||||||
|
bstneg location - branch to location if Status bit Negative is not set
|
||||||
|
bstpos location - branch to location if Status bit Negative is not set
|
||||||
bz reg1, location - branch to location if reg1 is zero
|
bz reg1, location - branch to location if reg1 is zero
|
||||||
bnz reg1, location - branch to location if reg1 is not zero
|
bnz reg1, location - branch to location if reg1 is not zero
|
||||||
beq reg1, reg2, location - jump to location in program given by location, if reg1 == reg2
|
beq reg1, reg2, location - jump to location in program given by location, if reg1 == reg2
|
||||||
@@ -109,6 +113,7 @@ div reg1, reg2, reg3 - unsigned division reg1=reg2/reg3
|
|||||||
mod reg1, reg2, reg3 - remainder (modulo) of unsigned division reg1=reg2%reg3 note: division by zero yields max signed int $ff/$ffff
|
mod reg1, reg2, reg3 - remainder (modulo) of unsigned division reg1=reg2%reg3 note: division by zero yields max signed int $ff/$ffff
|
||||||
sqrt reg1, reg2 - reg1 is the square root of reg2 (for .w and .b both , the result is a byte)
|
sqrt reg1, reg2 - reg1 is the square root of reg2 (for .w and .b both , the result is a byte)
|
||||||
sgn reg1, reg2 - reg1 is the sign of reg2 (0, 1 or -1)
|
sgn reg1, reg2 - reg1 is the sign of reg2 (0, 1 or -1)
|
||||||
|
cmp reg1, reg2 - set processor status bits C, N, Z according to comparison of reg1 with reg2. (semantics taken from 6502/68000 CMP instruction)
|
||||||
|
|
||||||
NOTE: because mul/div are constrained (truncated) to remain in 8 or 16 bits, there is NO NEED for separate signed/unsigned mul and div instructions. The result is identical.
|
NOTE: because mul/div are constrained (truncated) to remain in 8 or 16 bits, there is NO NEED for separate signed/unsigned mul and div instructions. The result is identical.
|
||||||
|
|
||||||
@@ -172,6 +177,10 @@ enum class Opcode {
|
|||||||
|
|
||||||
BSTCC,
|
BSTCC,
|
||||||
BSTCS,
|
BSTCS,
|
||||||
|
BSTEQ,
|
||||||
|
BSTNE,
|
||||||
|
BSTNEG,
|
||||||
|
BSTPOS,
|
||||||
BZ,
|
BZ,
|
||||||
BNZ,
|
BNZ,
|
||||||
BEQ,
|
BEQ,
|
||||||
@@ -207,6 +216,7 @@ enum class Opcode {
|
|||||||
MOD,
|
MOD,
|
||||||
SQRT,
|
SQRT,
|
||||||
SGN,
|
SGN,
|
||||||
|
CMP,
|
||||||
EXT,
|
EXT,
|
||||||
EXTS,
|
EXTS,
|
||||||
|
|
||||||
@@ -341,6 +351,10 @@ val instructionFormats = mutableMapOf(
|
|||||||
|
|
||||||
Opcode.BSTCC to InstructionFormat(NN, false, false,false, true ),
|
Opcode.BSTCC to InstructionFormat(NN, false, false,false, true ),
|
||||||
Opcode.BSTCS to InstructionFormat(NN, false, false,false, true ),
|
Opcode.BSTCS to InstructionFormat(NN, false, false,false, true ),
|
||||||
|
Opcode.BSTEQ to InstructionFormat(NN, false, false,false, true ),
|
||||||
|
Opcode.BSTNE to InstructionFormat(NN, false, false,false, true ),
|
||||||
|
Opcode.BSTNEG to InstructionFormat(NN, false, false,false, true ),
|
||||||
|
Opcode.BSTPOS to InstructionFormat(NN, false, false,false, true ),
|
||||||
Opcode.BZ to InstructionFormat(BW, true, false, false, true ),
|
Opcode.BZ to InstructionFormat(BW, true, false, false, true ),
|
||||||
Opcode.BNZ to InstructionFormat(BW, true, false, false, true ),
|
Opcode.BNZ to InstructionFormat(BW, true, false, false, true ),
|
||||||
Opcode.BEQ to InstructionFormat(BW, true, true, false, true ),
|
Opcode.BEQ to InstructionFormat(BW, true, true, false, true ),
|
||||||
@@ -376,6 +390,7 @@ val instructionFormats = mutableMapOf(
|
|||||||
Opcode.MOD to InstructionFormat(BW, true, true, true, false),
|
Opcode.MOD to InstructionFormat(BW, true, true, true, false),
|
||||||
Opcode.SQRT to InstructionFormat(BW, true, true, false, false),
|
Opcode.SQRT to InstructionFormat(BW, true, true, false, false),
|
||||||
Opcode.SGN to InstructionFormat(BW, true, true, false, false),
|
Opcode.SGN to InstructionFormat(BW, true, true, false, false),
|
||||||
|
Opcode.CMP to InstructionFormat(BW, true, true, false, false),
|
||||||
Opcode.EXT to InstructionFormat(BW, true, false, false, false),
|
Opcode.EXT to InstructionFormat(BW, true, false, false, false),
|
||||||
Opcode.EXTS to InstructionFormat(BW, true, false, false, false),
|
Opcode.EXTS to InstructionFormat(BW, true, false, false, false),
|
||||||
|
|
||||||
|
@@ -41,6 +41,8 @@ SYSCALLS:
|
|||||||
32 = all_word array
|
32 = all_word array
|
||||||
33 = reverse_bytes array
|
33 = reverse_bytes array
|
||||||
34 = reverse_words array
|
34 = reverse_words array
|
||||||
|
35 = set_carry status flag
|
||||||
|
36 = clear_carry status flag
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enum class Syscall {
|
enum class Syscall {
|
||||||
@@ -78,7 +80,9 @@ enum class Syscall {
|
|||||||
ALL_BYTE,
|
ALL_BYTE,
|
||||||
ALL_WORD,
|
ALL_WORD,
|
||||||
REVERSE_BYTES,
|
REVERSE_BYTES,
|
||||||
REVERSE_WORDS
|
REVERSE_WORDS,
|
||||||
|
SET_CARRY,
|
||||||
|
CLEAR_CARRY
|
||||||
}
|
}
|
||||||
|
|
||||||
object SysCalls {
|
object SysCalls {
|
||||||
@@ -302,6 +306,8 @@ object SysCalls {
|
|||||||
else
|
else
|
||||||
vm.registers.setUB(0, 0u)
|
vm.registers.setUB(0, 0u)
|
||||||
}
|
}
|
||||||
|
Syscall.SET_CARRY -> vm.statusCarry = true
|
||||||
|
Syscall.CLEAR_CARRY -> vm.statusCarry = false
|
||||||
else -> TODO("syscall ${call.name}")
|
else -> TODO("syscall ${call.name}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -23,6 +23,8 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
var pc = 0
|
var pc = 0
|
||||||
var stepCount = 0
|
var stepCount = 0
|
||||||
var statusCarry = false
|
var statusCarry = false
|
||||||
|
var statusZero = false
|
||||||
|
var statusNegative = false
|
||||||
|
|
||||||
init {
|
init {
|
||||||
if(program.size>65536)
|
if(program.size>65536)
|
||||||
@@ -104,6 +106,10 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
Opcode.RETURN -> InsRETURN()
|
Opcode.RETURN -> InsRETURN()
|
||||||
Opcode.BSTCC -> InsBSTCC(ins)
|
Opcode.BSTCC -> InsBSTCC(ins)
|
||||||
Opcode.BSTCS -> InsBSTCS(ins)
|
Opcode.BSTCS -> InsBSTCS(ins)
|
||||||
|
Opcode.BSTEQ -> InsBSTEQ(ins)
|
||||||
|
Opcode.BSTNE -> InsBSTNE(ins)
|
||||||
|
Opcode.BSTNEG -> InsBSTNEG(ins)
|
||||||
|
Opcode.BSTPOS -> InsBSTPOS(ins)
|
||||||
Opcode.BZ -> InsBZ(ins)
|
Opcode.BZ -> InsBZ(ins)
|
||||||
Opcode.BNZ -> InsBNZ(ins)
|
Opcode.BNZ -> InsBNZ(ins)
|
||||||
Opcode.BEQ -> InsBEQ(ins)
|
Opcode.BEQ -> InsBEQ(ins)
|
||||||
@@ -139,6 +145,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
Opcode.MOD -> InsMOD(ins)
|
Opcode.MOD -> InsMOD(ins)
|
||||||
Opcode.SQRT -> InsSQRT(ins)
|
Opcode.SQRT -> InsSQRT(ins)
|
||||||
Opcode.SGN -> InsSGN(ins)
|
Opcode.SGN -> InsSGN(ins)
|
||||||
|
Opcode.CMP -> InsCMP(ins)
|
||||||
Opcode.EXT -> InsEXT(ins)
|
Opcode.EXT -> InsEXT(ins)
|
||||||
Opcode.EXTS -> InsEXTS(ins)
|
Opcode.EXTS -> InsEXTS(ins)
|
||||||
Opcode.AND -> InsAND(ins)
|
Opcode.AND -> InsAND(ins)
|
||||||
@@ -353,6 +360,34 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
pc++
|
pc++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun InsBSTEQ(i: Instruction) {
|
||||||
|
if(statusZero)
|
||||||
|
pc = i.value!!
|
||||||
|
else
|
||||||
|
pc++
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun InsBSTNE(i: Instruction) {
|
||||||
|
if(!statusZero)
|
||||||
|
pc = i.value!!
|
||||||
|
else
|
||||||
|
pc++
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun InsBSTNEG(i: Instruction) {
|
||||||
|
if(statusNegative)
|
||||||
|
pc = i.value!!
|
||||||
|
else
|
||||||
|
pc++
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun InsBSTPOS(i: Instruction) {
|
||||||
|
if(!statusNegative)
|
||||||
|
pc = i.value!!
|
||||||
|
else
|
||||||
|
pc++
|
||||||
|
}
|
||||||
|
|
||||||
private fun InsBZ(i: Instruction) {
|
private fun InsBZ(i: Instruction) {
|
||||||
when(i.type!!) {
|
when(i.type!!) {
|
||||||
VmDataType.BYTE -> {
|
VmDataType.BYTE -> {
|
||||||
@@ -630,6 +665,35 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
|||||||
pc++
|
pc++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun InsCMP(i: Instruction) {
|
||||||
|
val comparison: Int
|
||||||
|
when(i.type!!) {
|
||||||
|
VmDataType.BYTE -> {
|
||||||
|
val reg1 = registers.getUB(i.reg1!!)
|
||||||
|
val reg2 = registers.getUB(i.reg2!!)
|
||||||
|
comparison = reg1.toInt() - reg2.toInt()
|
||||||
|
statusNegative = (comparison and 0x80)==0x80
|
||||||
|
}
|
||||||
|
VmDataType.WORD -> {
|
||||||
|
val reg1 = registers.getUW(i.reg1!!)
|
||||||
|
val reg2 = registers.getUW(i.reg2!!)
|
||||||
|
comparison = reg1.toInt() - reg2.toInt()
|
||||||
|
statusNegative = (comparison and 0x8000)==0x8000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(comparison==0){
|
||||||
|
statusZero = true
|
||||||
|
statusCarry = true
|
||||||
|
} else if(comparison>0) {
|
||||||
|
statusZero = false
|
||||||
|
statusCarry = true
|
||||||
|
} else {
|
||||||
|
statusZero = false
|
||||||
|
statusCarry = false
|
||||||
|
}
|
||||||
|
pc++
|
||||||
|
}
|
||||||
|
|
||||||
private fun arithByte(operator: String, reg1: Int, reg2: Int, reg3: Int?, value: UByte?) {
|
private fun arithByte(operator: String, reg1: Int, reg2: Int, reg3: Int?, value: UByte?) {
|
||||||
val left = registers.getUB(reg2)
|
val left = registers.getUB(reg2)
|
||||||
val right = value ?: registers.getUB(reg3!!)
|
val right = value ?: registers.getUB(reg3!!)
|
||||||
|
Reference in New Issue
Block a user