mirror of
https://github.com/irmen/prog8.git
synced 2024-11-26 11:49:22 +00:00
vm: fixed string comparisons, added missing vm string module
This commit is contained in:
parent
6e31eebfb5
commit
4dc9b45297
@ -3,10 +3,7 @@ package prog8.codegen.virtual
|
||||
import prog8.code.StStaticVariable
|
||||
import prog8.code.StSub
|
||||
import prog8.code.ast.*
|
||||
import prog8.code.core.AssemblyError
|
||||
import prog8.code.core.DataType
|
||||
import prog8.code.core.PassByValueDatatypes
|
||||
import prog8.code.core.SignedDatatypes
|
||||
import prog8.code.core.*
|
||||
import prog8.vm.Opcode
|
||||
import prog8.vm.VmDataType
|
||||
|
||||
@ -187,13 +184,7 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
code += VmCodeInstruction(Opcode.XOR, vmDt, reg1=resultRegister, reg2=regMask)
|
||||
}
|
||||
"not" -> {
|
||||
val label = codeGen.createLabelName()
|
||||
code += VmCodeInstruction(Opcode.BZ, vmDt, reg1=resultRegister, symbol = label)
|
||||
code += VmCodeInstruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=1)
|
||||
code += VmCodeLabel(label)
|
||||
val regMask = codeGen.vmRegisters.nextFree()
|
||||
code += VmCodeInstruction(Opcode.LOAD, vmDt, reg1=regMask, value=1)
|
||||
code += VmCodeInstruction(Opcode.XOR, vmDt, reg1=resultRegister, reg2=regMask)
|
||||
code += VmCodeInstruction(Opcode.NOT, vmDt, reg1=resultRegister)
|
||||
}
|
||||
else -> throw AssemblyError("weird prefix operator")
|
||||
}
|
||||
@ -330,15 +321,28 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
}
|
||||
code += VmCodeInstruction(ins, VmDataType.BYTE, reg1 = resultRegister, reg2 = zeroRegister)
|
||||
} else {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
val ins = if (signed) {
|
||||
if (greaterEquals) Opcode.SGES else Opcode.SGTS
|
||||
if(binExpr.left.type==DataType.STR && binExpr.right.type==DataType.STR) {
|
||||
val comparisonCall = PtFunctionCall(listOf("prog8_lib", "string_compare"), false, DataType.BYTE, Position.DUMMY)
|
||||
comparisonCall.children.add(binExpr.left)
|
||||
comparisonCall.children.add(binExpr.right)
|
||||
code += translate(comparisonCall, resultRegister, -1)
|
||||
val zeroRegister = codeGen.vmRegisters.nextFree()
|
||||
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=zeroRegister, value=0)
|
||||
code += if(greaterEquals)
|
||||
VmCodeInstruction(Opcode.SGES, VmDataType.BYTE, reg1=resultRegister, reg2=zeroRegister)
|
||||
else
|
||||
VmCodeInstruction(Opcode.SGTS, VmDataType.BYTE, reg1=resultRegister, reg2=zeroRegister)
|
||||
} else {
|
||||
if (greaterEquals) Opcode.SGE else Opcode.SGT
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
val ins = if (signed) {
|
||||
if (greaterEquals) Opcode.SGES else Opcode.SGTS
|
||||
} else {
|
||||
if (greaterEquals) Opcode.SGE else Opcode.SGT
|
||||
}
|
||||
code += VmCodeInstruction(ins, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
}
|
||||
code += VmCodeInstruction(ins, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
}
|
||||
return code
|
||||
}
|
||||
@ -366,15 +370,28 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
}
|
||||
code += VmCodeInstruction(ins, VmDataType.BYTE, reg1 = resultRegister, reg2 = zeroRegister)
|
||||
} else {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
val ins = if (signed) {
|
||||
if (lessEquals) Opcode.SLES else Opcode.SLTS
|
||||
if(binExpr.left.type==DataType.STR && binExpr.right.type==DataType.STR) {
|
||||
val comparisonCall = PtFunctionCall(listOf("prog8_lib", "string_compare"), false, DataType.BYTE, Position.DUMMY)
|
||||
comparisonCall.children.add(binExpr.left)
|
||||
comparisonCall.children.add(binExpr.right)
|
||||
code += translate(comparisonCall, resultRegister, -1)
|
||||
val zeroRegister = codeGen.vmRegisters.nextFree()
|
||||
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=zeroRegister, value=0)
|
||||
code += if(lessEquals)
|
||||
VmCodeInstruction(Opcode.SLES, VmDataType.BYTE, reg1=resultRegister, reg2=zeroRegister)
|
||||
else
|
||||
VmCodeInstruction(Opcode.SLTS, VmDataType.BYTE, reg1=resultRegister, reg2=zeroRegister)
|
||||
} else {
|
||||
if (lessEquals) Opcode.SLE else Opcode.SLT
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
val ins = if (signed) {
|
||||
if (lessEquals) Opcode.SLES else Opcode.SLTS
|
||||
} else {
|
||||
if (lessEquals) Opcode.SLE else Opcode.SLT
|
||||
}
|
||||
code += VmCodeInstruction(ins, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
}
|
||||
code += VmCodeInstruction(ins, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
}
|
||||
return code
|
||||
}
|
||||
@ -386,22 +403,37 @@ internal class ExpressionGen(private val codeGen: CodeGen) {
|
||||
val rightFpReg = codeGen.vmRegisters.nextFreeFloat()
|
||||
code += translateExpression(binExpr.left, -1, leftFpReg)
|
||||
code += translateExpression(binExpr.right, -1, rightFpReg)
|
||||
code += VmCodeInstruction(Opcode.FCOMP, VmDataType.FLOAT, reg1=resultRegister, fpReg1 = leftFpReg, fpReg2 = rightFpReg)
|
||||
if(!notEquals) {
|
||||
if (notEquals) {
|
||||
code += VmCodeInstruction(Opcode.FCOMP, VmDataType.FLOAT, reg1=resultRegister, fpReg1 = leftFpReg, fpReg2 = rightFpReg)
|
||||
} else {
|
||||
val label = codeGen.createLabelName()
|
||||
code += VmCodeInstruction(Opcode.BZ, VmDataType.BYTE, reg1=resultRegister, symbol = label)
|
||||
val valueReg = codeGen.vmRegisters.nextFree()
|
||||
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=resultRegister, value=1)
|
||||
code += VmCodeInstruction(Opcode.FCOMP, VmDataType.FLOAT, reg1=valueReg, fpReg1 = leftFpReg, fpReg2 = rightFpReg)
|
||||
code += VmCodeInstruction(Opcode.BZ, VmDataType.BYTE, reg1=valueReg, symbol = label)
|
||||
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=resultRegister, value=0)
|
||||
code += VmCodeLabel(label)
|
||||
val regMask = codeGen.vmRegisters.nextFree()
|
||||
code += VmCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=regMask, value=1)
|
||||
code += VmCodeInstruction(Opcode.XOR, VmDataType.BYTE, reg1=resultRegister, reg2=regMask)
|
||||
}
|
||||
} else {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
val opcode = if (notEquals) Opcode.SNE else Opcode.SEQ
|
||||
code += VmCodeInstruction(opcode, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
if(binExpr.left.type==DataType.STR && binExpr.right.type==DataType.STR) {
|
||||
val comparisonCall = PtFunctionCall(listOf("prog8_lib", "string_compare"), false, DataType.BYTE, Position.DUMMY)
|
||||
comparisonCall.children.add(binExpr.left)
|
||||
comparisonCall.children.add(binExpr.right)
|
||||
code += translate(comparisonCall, resultRegister, -1)
|
||||
if(notEquals) {
|
||||
val maskReg = codeGen.vmRegisters.nextFree()
|
||||
code += VmCodeInstruction(Opcode.LOAD, vmDt, reg1=maskReg, value=1)
|
||||
code += VmCodeInstruction(Opcode.AND, vmDt, reg1=resultRegister, reg2=maskReg)
|
||||
} else {
|
||||
code += VmCodeInstruction(Opcode.NOT, vmDt, reg1=resultRegister)
|
||||
}
|
||||
} else {
|
||||
val rightResultReg = codeGen.vmRegisters.nextFree()
|
||||
code += translateExpression(binExpr.left, resultRegister, -1)
|
||||
code += translateExpression(binExpr.right, rightResultReg, -1)
|
||||
val opcode = if (notEquals) Opcode.SNE else Opcode.SEQ
|
||||
code += VmCodeInstruction(opcode, vmDt, reg1 = resultRegister, reg2 = rightResultReg)
|
||||
}
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
@ -37,4 +37,19 @@ prog8_lib {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
sub string_compare(str st1, str st2) -> byte {
|
||||
; Compares two strings for sorting.
|
||||
; Returns -1 (255), 0 or 1 depending on wether string1 sorts before, equal or after string2.
|
||||
; Note that you can also directly compare strings and string values with eachother using
|
||||
; comparison operators ==, < etcetera (it will use strcmp for you under water automatically).
|
||||
%asm {{
|
||||
loadm.w r0, {prog8_lib.string_compare.st1}
|
||||
loadm.w r1, {prog8_lib.string_compare.st2}
|
||||
syscall 29
|
||||
return
|
||||
}}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
119
compiler/res/prog8lib/virtual/string.p8
Normal file
119
compiler/res/prog8lib/virtual/string.p8
Normal file
@ -0,0 +1,119 @@
|
||||
; 0-terminated string manipulation routines. For the Virtual Machine target.
|
||||
;
|
||||
; Written by Irmen de Jong (irmen@razorvine.net) - license: GNU GPL 3.0
|
||||
|
||||
|
||||
string {
|
||||
sub length(str st) -> ubyte {
|
||||
; Returns the number of bytes in the string.
|
||||
; This value is determined during runtime and counts upto the first terminating 0 byte in the string,
|
||||
; regardless of the size of the string during compilation time. Don’t confuse this with len and sizeof!
|
||||
ubyte count = 0
|
||||
while st[count]
|
||||
count++
|
||||
return count
|
||||
}
|
||||
|
||||
sub left(str source, ubyte slen, str target) {
|
||||
; Copies the left side of the source string of the given length to target string.
|
||||
; It is assumed the target string buffer is large enough to contain the result.
|
||||
; Also, you have to make sure yourself that length is smaller or equal to the length of the source string.
|
||||
; Modifies in-place, doesn’t return a value (so can’t be used in an expression).
|
||||
target[slen] = 0
|
||||
ubyte ix
|
||||
for ix in 0 to slen-1 {
|
||||
target[ix] = source[ix]
|
||||
}
|
||||
}
|
||||
|
||||
sub right(str source, ubyte slen, str target) {
|
||||
; Copies the right side of the source string of the given length to target string.
|
||||
; It is assumed the target string buffer is large enough to contain the result.
|
||||
; Also, you have to make sure yourself that length is smaller or equal to the length of the source string.
|
||||
; Modifies in-place, doesn’t return a value (so can’t be used in an expression).
|
||||
ubyte offset = length(source)-slen
|
||||
ubyte ix
|
||||
for ix in 0 to slen-1 {
|
||||
target[ix] = source[ix+offset]
|
||||
}
|
||||
target[ix]=0
|
||||
}
|
||||
|
||||
sub slice(str source, ubyte start, ubyte slen, str target) {
|
||||
; Copies a segment from the source string, starting at the given index,
|
||||
; and of the given length to target string.
|
||||
; It is assumed the target string buffer is large enough to contain the result.
|
||||
; Also, you have to make sure yourself that start and length are within bounds of the strings.
|
||||
; Modifies in-place, doesn’t return a value (so can’t be used in an expression).
|
||||
ubyte ix
|
||||
for ix in 0 to slen-1 {
|
||||
target[ix] = source[ix+start]
|
||||
}
|
||||
target[ix]=0
|
||||
}
|
||||
|
||||
sub find(str st, ubyte character) -> ubyte {
|
||||
; Locates the first position of the given character in the string,
|
||||
; returns Carry set if found + index in A, or Carry clear if not found.
|
||||
ubyte ix
|
||||
for ix in 0 to length(st)-1 {
|
||||
if st[ix]==character {
|
||||
sys.set_carry()
|
||||
return ix
|
||||
}
|
||||
}
|
||||
sys.clear_carry()
|
||||
return 0
|
||||
}
|
||||
|
||||
sub copy(str source, str target) -> ubyte {
|
||||
; Copy a string to another, overwriting that one.
|
||||
; Returns the length of the string that was copied.
|
||||
; Often you don’t have to call this explicitly and can just write string1 = string2
|
||||
; but this function is useful if you’re dealing with addresses for instance.
|
||||
ubyte ix
|
||||
repeat {
|
||||
ubyte char=source[ix]
|
||||
target[ix]=char
|
||||
if not char
|
||||
return ix
|
||||
ix++
|
||||
}
|
||||
}
|
||||
|
||||
sub compare(str st1, str st2) -> byte {
|
||||
; Compares two strings for sorting.
|
||||
; Returns -1 (255), 0 or 1 depending on wether string1 sorts before, equal or after string2.
|
||||
; Note that you can also directly compare strings and string values with eachother using
|
||||
; comparison operators ==, < etcetera (it will use strcmp for you under water automatically).
|
||||
return prog8_lib.string_compare(st1, st2)
|
||||
}
|
||||
|
||||
sub lower(str st) -> ubyte {
|
||||
; Lowercases the petscii string in-place. Returns length of the string.
|
||||
; (for efficiency, non-letter characters > 128 will also not be left intact,
|
||||
; but regular text doesn't usually contain those characters anyway.)
|
||||
ubyte ix
|
||||
repeat {
|
||||
ubyte char=st[ix]
|
||||
if not char
|
||||
return ix
|
||||
if char >= 'A' and char <= 'Z'
|
||||
st[ix] = char | %00100000
|
||||
ix++
|
||||
}
|
||||
}
|
||||
|
||||
sub upper(str st) -> ubyte {
|
||||
; Uppercases the petscii string in-place. Returns length of the string.
|
||||
ubyte ix
|
||||
repeat {
|
||||
ubyte char=st[ix]
|
||||
if not char
|
||||
return ix
|
||||
if char >= 97 and char <= 122
|
||||
st[ix] = char & %11011111
|
||||
ix++
|
||||
}
|
||||
}
|
||||
}
|
@ -388,8 +388,8 @@ private fun createAssemblyAndAssemble(program: Program,
|
||||
// to help clean up the code that still depends on them.
|
||||
// removeAllVardeclsFromAst(program)
|
||||
|
||||
// println("*********** AST RIGHT BEFORE ASM GENERATION *************")
|
||||
// printProgram(program)
|
||||
println("*********** AST RIGHT BEFORE ASM GENERATION *************")
|
||||
printProgram(program)
|
||||
|
||||
val assembly = asmGeneratorFor(program, errors, symbolTable, compilerOptions).compileToAssembly()
|
||||
errors.report()
|
||||
|
@ -889,7 +889,7 @@ internal class AstChecker(private val program: Program,
|
||||
if(rightDt!in NumericDatatypes && rightDt != DataType.STR)
|
||||
errors.err("right operand is not numeric or str", expr.right.position)
|
||||
if(leftDt!=rightDt) {
|
||||
if(leftDt==DataType.STR && rightDt in IntegerDatatypes) {
|
||||
if(leftDt==DataType.STR && rightDt in IntegerDatatypes && expr.operator=="*") {
|
||||
// only exception allowed: str * constvalue
|
||||
if(expr.right.constValue(program)==null)
|
||||
errors.err("can only use string repeat with a constant number value", expr.left.position)
|
||||
|
@ -3,9 +3,10 @@ TODO
|
||||
|
||||
For next release
|
||||
^^^^^^^^^^^^^^^^
|
||||
- vm: get rid of all the conditional set instructions
|
||||
- vm: add more instructions operating directly on memory instead of only registers?
|
||||
- c64 target: after exit, switching charset case is still disabled. Don't disable this by default in startup?
|
||||
- vm: check array type in PtAssignTarget
|
||||
- vm: animals example game breaks after adding first new animal...
|
||||
- vm: add more instructions operating directly on memory instead of only registers? (translate assignment self-assigns)
|
||||
- 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?
|
||||
|
@ -1,5 +1,6 @@
|
||||
%import textio
|
||||
%import math
|
||||
%import string
|
||||
%import floats
|
||||
%zeropage dontuse
|
||||
|
||||
@ -25,37 +26,44 @@ main {
|
||||
|
||||
ubyte @shared value = inline_candidate()
|
||||
|
||||
ubyte lowb = 4
|
||||
ubyte highb = $ea
|
||||
str name = "irmen123ABC"
|
||||
str other = "zrmen123ABC"
|
||||
|
||||
if lowb+4
|
||||
lowb++
|
||||
if math.sin8u(lowb)
|
||||
lowb++
|
||||
if lowb
|
||||
lowb++
|
||||
txt.print_ub(string.upper(name))
|
||||
txt.print(name)
|
||||
txt.nl()
|
||||
txt.print_ub(string.lower(name))
|
||||
txt.print(name)
|
||||
txt.nl()
|
||||
|
||||
if lowb==0
|
||||
lowb++
|
||||
uword otheraddr = &other
|
||||
txt.print_ub(name!=other)
|
||||
txt.spc()
|
||||
txt.print_ub(name==other)
|
||||
txt.nl()
|
||||
txt.print_ub(name>other)
|
||||
txt.spc()
|
||||
txt.print_ub(name>=other)
|
||||
txt.nl()
|
||||
txt.print_ub(name<other)
|
||||
txt.spc()
|
||||
txt.print_ub(name<=other)
|
||||
txt.nl()
|
||||
txt.nl()
|
||||
other[0]='i'
|
||||
txt.print_ub(name!=other)
|
||||
txt.spc()
|
||||
txt.print_ub(name==other)
|
||||
txt.nl()
|
||||
txt.print_ub(name>other)
|
||||
txt.spc()
|
||||
txt.print_ub(name>=other)
|
||||
txt.nl()
|
||||
txt.print_ub(name<other)
|
||||
txt.spc()
|
||||
txt.print_ub(name<=other)
|
||||
txt.nl()
|
||||
|
||||
if lowb!=0
|
||||
lowb++
|
||||
|
||||
if lowb==3
|
||||
lowb++
|
||||
|
||||
if lowb!=3
|
||||
lowb++
|
||||
|
||||
if lowb==3
|
||||
lowb++
|
||||
else
|
||||
lowb--
|
||||
|
||||
if lowb!=3
|
||||
lowb++
|
||||
else
|
||||
lowb--
|
||||
|
||||
; txt.print_ub(inline_candidate())
|
||||
; txt.nl()
|
||||
|
@ -116,6 +116,7 @@ All have type b or w.
|
||||
and reg1, reg2 - reg1 = reg1 bitwise and reg2
|
||||
or reg1, reg2 - reg1 = reg1 bitwise or reg2
|
||||
xor reg1, reg2 - reg1 = reg1 bitwise xor reg2
|
||||
not reg1 - reg1 = boolean not of reg1 (0->1 , ~0 -> 0)
|
||||
lsrn reg1, reg2 - reg1 = multi-shift reg1 right by reg2 bits + set Carry to shifted bit
|
||||
asrn reg1, reg2 - reg1 = multi-shift reg1 right by reg2 bits (signed) + set Carry to shifted bit
|
||||
lsln reg1, reg2 - reg1 = multi-shift reg1 left by reg2 bits + set Carry to shifted bit
|
||||
@ -225,6 +226,7 @@ enum class Opcode {
|
||||
AND,
|
||||
OR,
|
||||
XOR,
|
||||
NOT,
|
||||
ASRN,
|
||||
LSRN,
|
||||
LSLN,
|
||||
@ -273,7 +275,9 @@ val OpcodesWithAddress = setOf(
|
||||
Opcode.STOREM,
|
||||
Opcode.STOREX,
|
||||
Opcode.STOREZM,
|
||||
Opcode.STOREZX
|
||||
Opcode.STOREZX,
|
||||
Opcode.INCM,
|
||||
Opcode.DECM
|
||||
)
|
||||
|
||||
|
||||
@ -474,6 +478,7 @@ val instructionFormats = mutableMapOf(
|
||||
Opcode.AND to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.OR to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.XOR to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.NOT to InstructionFormat.from("BW,r1"),
|
||||
Opcode.ASRN to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.LSRN to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.LSLN to InstructionFormat.from("BW,r1,r2"),
|
||||
|
@ -34,6 +34,7 @@ SYSCALLS:
|
||||
26 = reverse_bytes array
|
||||
27 = reverse_words array
|
||||
28 = reverse_floats array
|
||||
29 = compare strings
|
||||
*/
|
||||
|
||||
enum class Syscall {
|
||||
@ -66,6 +67,7 @@ enum class Syscall {
|
||||
REVERSE_BYTES,
|
||||
REVERSE_WORDS,
|
||||
REVERSE_FLOATS,
|
||||
COMPARE_STRINGS
|
||||
}
|
||||
|
||||
object SysCalls {
|
||||
@ -255,6 +257,14 @@ object SysCalls {
|
||||
val string = vm.memory.getString(stringAddr.toInt())
|
||||
vm.registers.setSW(0, string.toShort())
|
||||
}
|
||||
Syscall.COMPARE_STRINGS -> {
|
||||
val firstAddr = vm.registers.getUW(0)
|
||||
val secondAddr = vm.registers.getUW(1)
|
||||
val first = vm.memory.getString(firstAddr.toInt())
|
||||
val second = vm.memory.getString(secondAddr.toInt())
|
||||
val comparison = first.compareTo(second)
|
||||
vm.registers.setSB(0, comparison.toByte())
|
||||
}
|
||||
else -> TODO("syscall ${call.name}")
|
||||
}
|
||||
}
|
||||
|
@ -150,6 +150,7 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
Opcode.AND -> InsAND(ins)
|
||||
Opcode.OR -> InsOR(ins)
|
||||
Opcode.XOR -> InsXOR(ins)
|
||||
Opcode.NOT -> InsNOT(ins)
|
||||
Opcode.ASRN -> InsASRM(ins)
|
||||
Opcode.LSRN -> InsLSRM(ins)
|
||||
Opcode.LSLN -> InsLSLM(ins)
|
||||
@ -852,6 +853,15 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsNOT(i: Instruction) {
|
||||
when(i.type!!) {
|
||||
VmDataType.BYTE -> registers.setUB(i.reg1!!, if(registers.getUB(i.reg1)==0.toUByte()) 1u else 0u)
|
||||
VmDataType.WORD -> registers.setUW(i.reg1!!, if(registers.getUW(i.reg1)==0.toUShort()) 1u else 0u)
|
||||
VmDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
|
||||
}
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsASRM(i: Instruction) {
|
||||
val (left: Int, right: Int) = getLogicalOperandsS(i)
|
||||
statusCarry = (left and 1)!=0
|
||||
|
Loading…
Reference in New Issue
Block a user