made a lot more opcodes type-specific

This commit is contained in:
Irmen de Jong 2018-10-05 13:58:37 +02:00
parent 42e4891fcf
commit e8ba21d3ba
6 changed files with 622 additions and 371 deletions

View File

@ -3,7 +3,6 @@ package prog8.ast
import org.antlr.v4.runtime.ParserRuleContext import org.antlr.v4.runtime.ParserRuleContext
import org.antlr.v4.runtime.tree.TerminalNode import org.antlr.v4.runtime.tree.TerminalNode
import prog8.compiler.HeapValues import prog8.compiler.HeapValues
import prog8.compiler.target.c64.Mflpt5
import prog8.compiler.target.c64.Petscii import prog8.compiler.target.c64.Petscii
import prog8.compiler.unescape import prog8.compiler.unescape
import prog8.functions.BuiltinFunctions import prog8.functions.BuiltinFunctions

View File

@ -635,12 +635,54 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
} }
"msb" -> stackvmProg.instr(Opcode.MSB) "msb" -> stackvmProg.instr(Opcode.MSB)
"lsb" -> stackvmProg.instr(Opcode.LSB) "lsb" -> stackvmProg.instr(Opcode.LSB)
"lsl" -> stackvmProg.instr(Opcode.SHL) "lsl" -> {
"lsr" -> stackvmProg.instr(Opcode.SHR) val arg = args.single()
"rol" -> stackvmProg.instr(Opcode.ROL) when (arg.resultingDatatype(namespace, heap)) {
"ror" -> stackvmProg.instr(Opcode.ROR) DataType.BYTE -> stackvmProg.instr(Opcode.SHL)
"rol2" -> stackvmProg.instr(Opcode.ROL2) DataType.WORD -> stackvmProg.instr(Opcode.SHL_W)
"ror2" -> stackvmProg.instr(Opcode.ROR2) else -> throw CompilerException("wrong datatype")
}
}
"lsr" -> {
val arg = args.single()
when (arg.resultingDatatype(namespace, heap)) {
DataType.BYTE -> stackvmProg.instr(Opcode.SHR)
DataType.WORD -> stackvmProg.instr(Opcode.SHR_W)
else -> throw CompilerException("wrong datatype")
}
}
"rol" -> {
val arg = args.single()
when (arg.resultingDatatype(namespace, heap)) {
DataType.BYTE -> stackvmProg.instr(Opcode.ROL)
DataType.WORD -> stackvmProg.instr(Opcode.ROL_W)
else -> throw CompilerException("wrong datatype")
}
}
"ror" -> {
val arg = args.single()
when (arg.resultingDatatype(namespace, heap)) {
DataType.BYTE -> stackvmProg.instr(Opcode.ROR)
DataType.WORD -> stackvmProg.instr(Opcode.ROR_W)
else -> throw CompilerException("wrong datatype")
}
}
"rol2" -> {
val arg = args.single()
when (arg.resultingDatatype(namespace, heap)) {
DataType.BYTE -> stackvmProg.instr(Opcode.ROL2)
DataType.WORD -> stackvmProg.instr(Opcode.ROL2_W)
else -> throw CompilerException("wrong datatype")
}
}
"ror2" -> {
val arg = args.single()
when (arg.resultingDatatype(namespace, heap)) {
DataType.BYTE -> stackvmProg.instr(Opcode.ROR2)
DataType.WORD -> stackvmProg.instr(Opcode.ROR2_W)
else -> throw CompilerException("wrong datatype")
}
}
"set_carry" -> stackvmProg.instr(Opcode.SEC) "set_carry" -> stackvmProg.instr(Opcode.SEC)
"clear_carry" -> stackvmProg.instr(Opcode.CLC) "clear_carry" -> stackvmProg.instr(Opcode.CLC)
"set_irqd" -> stackvmProg.instr(Opcode.SEI) "set_irqd" -> stackvmProg.instr(Opcode.SEI)
@ -666,6 +708,8 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
val validDt = setOf(DataType.BYTE, DataType.WORD, DataType.FLOAT) val validDt = setOf(DataType.BYTE, DataType.WORD, DataType.FLOAT)
if(leftDt !in validDt || rightDt !in validDt) if(leftDt !in validDt || rightDt !in validDt)
throw CompilerException("invalid datatype(s) for operand(s)") throw CompilerException("invalid datatype(s) for operand(s)")
if(leftDt!=rightDt)
throw CompilerException("operands have different datatypes")
val opcode = when(operator) { val opcode = when(operator) {
// todo variants depending on leftdt/rightdt (b/w/f) // todo variants depending on leftdt/rightdt (b/w/f)
"+" -> Opcode.ADD "+" -> Opcode.ADD
@ -675,18 +719,96 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
"//" -> Opcode.FLOORDIV "//" -> Opcode.FLOORDIV
"%" -> Opcode.REMAINDER "%" -> Opcode.REMAINDER
"**" -> Opcode.POW "**" -> Opcode.POW
"&" -> Opcode.BITAND "&" -> {
"|" -> Opcode.BITOR when(leftDt) {
"^" -> Opcode.BITXOR DataType.BYTE -> Opcode.BITAND
"and" -> Opcode.AND DataType.WORD -> Opcode.BITAND_W
"or" -> Opcode.OR else -> throw CompilerException("only byte/word possible")
"xor" -> Opcode.XOR }
"<" -> Opcode.LESS }
">" -> Opcode.GREATER "|" -> {
"<=" -> Opcode.LESSEQ when(leftDt) {
">=" -> Opcode.GREATEREQ DataType.BYTE -> Opcode.BITOR
"==" -> Opcode.EQUAL DataType.WORD -> Opcode.BITOR_W
"!=" -> Opcode.NOTEQUAL else -> throw CompilerException("only byte/word possible")
}
}
"^" -> {
when(leftDt) {
DataType.BYTE -> Opcode.BITXOR
DataType.WORD -> Opcode.BITXOR_W
else -> throw CompilerException("only byte/word possible")
}
}
"and" -> {
when(leftDt) {
DataType.BYTE -> Opcode.AND
DataType.WORD -> Opcode.AND_W
else -> throw CompilerException("only byte/word possible")
}
}
"or" -> {
when(leftDt) {
DataType.BYTE -> Opcode.OR
DataType.WORD -> Opcode.OR_W
else -> throw CompilerException("only byte/word possible")
}
}
"xor" -> {
when(leftDt) {
DataType.BYTE -> Opcode.XOR
DataType.WORD -> Opcode.XOR_W
else -> throw CompilerException("only byte/word possible")
}
}
"<" -> {
when(leftDt) {
DataType.BYTE -> Opcode.LESS
DataType.WORD -> Opcode.LESS_W
DataType.FLOAT -> Opcode.LESS_F
else -> throw CompilerException("only byte/word/lfoat possible")
}
}
">" -> {
when(leftDt) {
DataType.BYTE -> Opcode.GREATER
DataType.WORD -> Opcode.GREATER_W
DataType.FLOAT -> Opcode.GREATER_F
else -> throw CompilerException("only byte/word/lfoat possible")
}
}
"<=" -> {
when(leftDt) {
DataType.BYTE -> Opcode.LESSEQ
DataType.WORD -> Opcode.LESSEQ_W
DataType.FLOAT -> Opcode.LESSEQ_F
else -> throw CompilerException("only byte/word/lfoat possible")
}
}
">=" -> {
when(leftDt) {
DataType.BYTE -> Opcode.GREATEREQ
DataType.WORD -> Opcode.GREATEREQ_W
DataType.FLOAT -> Opcode.GREATEREQ_F
else -> throw CompilerException("only byte/word/lfoat possible")
}
}
"==" -> {
when (leftDt) {
DataType.BYTE -> Opcode.EQUAL
DataType.WORD -> Opcode.EQUAL_W
DataType.FLOAT -> Opcode.EQUAL_F
else -> throw CompilerException("only byte/word/lfoat possible")
}
}
"!=" -> {
when (leftDt) {
DataType.BYTE -> Opcode.NOTEQUAL
DataType.WORD -> Opcode.NOTEQUAL_W
DataType.FLOAT -> Opcode.NOTEQUAL_F
else -> throw CompilerException("only byte/word/lfoat possible")
}
}
else -> throw FatalAstException("const evaluation for invalid operator $operator") else -> throw FatalAstException("const evaluation for invalid operator $operator")
} }
stackvmProg.instr(opcode) stackvmProg.instr(opcode)
@ -698,8 +820,20 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
val opcode = when(operator) { val opcode = when(operator) {
"+" -> Opcode.NOP "+" -> Opcode.NOP
"-" -> Opcode.NEG // todo b/w/f "-" -> Opcode.NEG // todo b/w/f
"~" -> Opcode.INV // todo b/w "~" -> {
"not" -> Opcode.NOT // todo b/w (convert float to byte) when(operandDt) {
DataType.BYTE -> Opcode.INV
DataType.WORD -> Opcode.INV_W
else -> throw CompilerException("only byte/word possible")
}
}
"not" -> {
when(operandDt) {
DataType.BYTE -> Opcode.NOT
DataType.WORD -> Opcode.NOT_W
else -> throw CompilerException("only byte/word possible")
}
}
else -> throw FatalAstException("const evaluation for invalid prefix operator $operator") else -> throw FatalAstException("const evaluation for invalid prefix operator $operator")
} }
stackvmProg.instr(opcode) stackvmProg.instr(opcode)
@ -844,7 +978,7 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
stmt.target.arrayindexed!=null -> translate(stmt.target.arrayindexed!!, false) stmt.target.arrayindexed!=null -> translate(stmt.target.arrayindexed!!, false)
} }
translateAugAssignOperator(stmt.aug_op) translateAugAssignOperator(stmt.aug_op, stmt.value.resultingDatatype(namespace, heap))
} }
// pop the result value back into the assignment target // pop the result value back into the assignment target
@ -867,7 +1001,12 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
} }
} }
private fun translateAugAssignOperator(aug_op: String) { private fun translateAugAssignOperator(aug_op: String, valueDt: DataType?) {
if(valueDt==null)
throw CompilerException("value datatype not known")
val validDt = setOf(DataType.BYTE, DataType.WORD, DataType.FLOAT)
if(valueDt !in validDt)
throw CompilerException("invalid datatype(s) for operand(s)")
val opcode = when(aug_op) { val opcode = when(aug_op) {
"+=" -> Opcode.ADD "+=" -> Opcode.ADD
"-=" -> Opcode.SUB "-=" -> Opcode.SUB
@ -875,9 +1014,27 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
"//=" -> Opcode.FLOORDIV "//=" -> Opcode.FLOORDIV
"*=" -> Opcode.MUL "*=" -> Opcode.MUL
"**=" -> Opcode.POW "**=" -> Opcode.POW
"&=" -> Opcode.BITAND "&=" -> {
"|=" -> Opcode.BITOR when(valueDt) {
"^=" -> Opcode.BITXOR DataType.BYTE -> Opcode.BITAND
DataType.WORD -> Opcode.BITAND_W
else -> throw CompilerException("only byte/word possible")
}
}
"|=" -> {
when(valueDt) {
DataType.BYTE -> Opcode.BITOR
DataType.WORD -> Opcode.BITOR_W
else -> throw CompilerException("only byte/word possible")
}
}
"^=" -> {
when(valueDt) {
DataType.BYTE -> Opcode.BITXOR
DataType.WORD -> Opcode.BITXOR_W
else -> throw CompilerException("only byte/word possible")
}
}
else -> throw CompilerException("invalid aug assignment operator $aug_op") else -> throw CompilerException("invalid aug assignment operator $aug_op")
} }
stackvmProg.instr(opcode) stackvmProg.instr(opcode)

View File

@ -1,13 +1,12 @@
// Generated from /home/irmen/Projects/prog8/compiler/antlr/prog8.g4 by ANTLR 4.7 // Generated from /home/irmen/Projects/prog8/compiler/antlr/prog8.g4 by ANTLR 4.7
package prog8.parser; package prog8.parser;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.*; import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.atn.*; import org.antlr.v4.runtime.atn.ATN;
import org.antlr.v4.runtime.atn.ATNDeserializer;
import org.antlr.v4.runtime.atn.LexerATNSimulator;
import org.antlr.v4.runtime.atn.PredictionContextCache;
import org.antlr.v4.runtime.dfa.DFA; import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.misc.*;
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) @SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public class prog8Lexer extends Lexer { public class prog8Lexer extends Lexer {

View File

@ -1,13 +1,15 @@
// Generated from /home/irmen/Projects/prog8/compiler/antlr/prog8.g4 by ANTLR 4.7 // Generated from /home/irmen/Projects/prog8/compiler/antlr/prog8.g4 by ANTLR 4.7
package prog8.parser; package prog8.parser;
import org.antlr.v4.runtime.atn.*;
import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.*; import org.antlr.v4.runtime.*;
import org.antlr.v4.runtime.misc.*; import org.antlr.v4.runtime.atn.ATN;
import org.antlr.v4.runtime.tree.*; import org.antlr.v4.runtime.atn.ATNDeserializer;
import org.antlr.v4.runtime.atn.ParserATNSimulator;
import org.antlr.v4.runtime.atn.PredictionContextCache;
import org.antlr.v4.runtime.dfa.DFA;
import org.antlr.v4.runtime.tree.TerminalNode;
import java.util.List; import java.util.List;
import java.util.Iterator;
import java.util.ArrayList;
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"}) @SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public class prog8Parser extends Parser { public class prog8Parser extends Parser {

View File

@ -43,34 +43,50 @@ enum class Opcode {
NEG, // todo b/w/f NEG, // todo b/w/f
// bit shifts and bitwise arithmetic // bit shifts and bitwise arithmetic
SHL, // todo b/w SHL,
SHL_W,
SHL_MEM, SHL_MEM,
SHL_MEM_W, SHL_MEM_W,
SHL_VAR, // todo b/w SHL_VAR,
SHR, // todo b/w SHL_VAR_W,
SHR,
SHR_W,
SHR_MEM, SHR_MEM,
SHR_MEM_W, SHR_MEM_W,
SHR_VAR, // todo b/w SHR_VAR,
ROL, // todo b/w SHR_VAR_W,
ROL,
ROL_W,
ROL_MEM, ROL_MEM,
ROL_MEM_W, ROL_MEM_W,
ROL_VAR, // todo b/w ROL_VAR,
ROR, // todo b/w ROL_VAR_W,
ROR,
ROR_W,
ROR_MEM, ROR_MEM,
ROR_MEM_W, ROR_MEM_W,
ROR_VAR, // todo b/w ROR_VAR,
ROL2, // todo b/w ROR_VAR_W,
ROL2,
ROL2_W,
ROL2_MEM, ROL2_MEM,
ROL2_MEM_W, ROL2_MEM_W,
ROL2_VAR, // todo b/w ROL2_VAR,
ROR2, // todo b/w ROL2_VAR_W,
ROR2,
ROR2_W,
ROR2_MEM, ROR2_MEM,
ROR2_MEM_W, ROR2_MEM_W,
ROR2_VAR, // todo b/w ROR2_VAR,
BITAND, // todo b/w ROR2_VAR_W,
BITOR, // todo b/w BITAND,
BITXOR, // todo b/w BITAND_W,
INV, // todo b/w BITOR,
BITOR_W,
BITXOR,
BITXOR_W,
INV,
INV_W,
LSB, LSB,
MSB, MSB,
@ -81,10 +97,14 @@ enum class Opcode {
W2FLOAT, // convert word into floating point W2FLOAT, // convert word into floating point
// logical operations // logical operations
AND, // todo b/w (convert float to byte) AND,
OR, // todo b/w (convert float to byte) AND_W,
XOR, // todo b/w (convert float to byte) OR,
NOT, // todo b/w (convert float to byte) OR_W,
XOR,
XOR_W,
NOT,
NOT_W,
// increment, decrement // increment, decrement
INC, INC,
@ -101,12 +121,24 @@ enum class Opcode {
DEC_VAR_F, DEC_VAR_F,
// comparisons // comparisons
LESS, // todo b/w/f ? LESS,
GREATER, // todo b/w/f ? LESS_W,
LESSEQ, // todo b/w/f ? LESS_F,
GREATEREQ, // todo b/w/f ? GREATER,
EQUAL, // todo b/w/f ? GREATER_W,
NOTEQUAL, // todo b/w/f ? GREATER_F,
LESSEQ,
LESSEQ_W,
LESSEQ_F,
GREATEREQ,
GREATEREQ_W,
GREATEREQ_F,
EQUAL,
EQUAL_W,
EQUAL_F,
NOTEQUAL,
NOTEQUAL_W,
NOTEQUAL_F,
// array access // array access
READ_INDEXED_VAR, READ_INDEXED_VAR,
@ -145,8 +177,9 @@ enum class Opcode {
val opcodesWithVarArgument = setOf( val opcodesWithVarArgument = setOf(
Opcode.INC_VAR, Opcode.INC_VAR_W, Opcode.DEC_VAR, Opcode.DEC_VAR_W, Opcode.INC_VAR, Opcode.INC_VAR_W, Opcode.DEC_VAR, Opcode.DEC_VAR_W,
Opcode.SHR_VAR, Opcode.SHL_VAR, Opcode.ROL_VAR, Opcode.ROR_VAR, Opcode.SHR_VAR, Opcode.SHR_VAR_W, Opcode.SHL_VAR, Opcode.SHL_VAR_W,
Opcode.ROL2_VAR, Opcode.ROR2_VAR, Opcode.ROL_VAR, Opcode.ROL_VAR_W, Opcode.ROR_VAR, Opcode.ROR_VAR_W,
Opcode.ROL2_VAR, Opcode.ROL2_VAR_W, Opcode.ROR2_VAR, Opcode.ROR2_VAR_W,
Opcode.POP_VAR, Opcode.POP_VAR_W, Opcode.POP_VAR_F, Opcode.POP_VAR, Opcode.POP_VAR_W, Opcode.POP_VAR_F,
Opcode.PUSH_VAR, Opcode.PUSH_VAR_W, Opcode.PUSH_VAR_F, Opcode.PUSH_VAR, Opcode.PUSH_VAR_W, Opcode.PUSH_VAR_F,
Opcode.READ_INDEXED_VAR, Opcode.READ_INDEXED_VAR_W, Opcode.READ_INDEXED_VAR_F, Opcode.READ_INDEXED_VAR, Opcode.READ_INDEXED_VAR_W, Opcode.READ_INDEXED_VAR_F,
@ -479,56 +512,116 @@ class StackVm(private var traceOutputFile: String?) {
} }
Opcode.SHL -> { Opcode.SHL -> {
val v = evalstack.pop() val v = evalstack.pop()
// todo b/w checkDt(v, DataType.BYTE)
evalstack.push(v.shl())
}
Opcode.SHL_W -> {
val v = evalstack.pop()
checkDt(v, DataType.WORD)
evalstack.push(v.shl()) evalstack.push(v.shl())
} }
Opcode.SHR -> { Opcode.SHR -> {
val v = evalstack.pop() val v = evalstack.pop()
// todo b/w checkDt(v, DataType.BYTE)
evalstack.push(v.shr())
}
Opcode.SHR_W -> {
val v = evalstack.pop()
checkDt(v, DataType.WORD)
evalstack.push(v.shr()) evalstack.push(v.shr())
} }
Opcode.ROL -> { Opcode.ROL -> {
val v = evalstack.pop() val v = evalstack.pop()
// todo b/w checkDt(v, DataType.BYTE)
val (result, newCarry) = v.rol(P_carry)
this.P_carry = newCarry
evalstack.push(result)
}
Opcode.ROL_W -> {
val v = evalstack.pop()
checkDt(v, DataType.WORD)
val (result, newCarry) = v.rol(P_carry) val (result, newCarry) = v.rol(P_carry)
this.P_carry = newCarry this.P_carry = newCarry
evalstack.push(result) evalstack.push(result)
} }
Opcode.ROL2 -> { Opcode.ROL2 -> {
val v = evalstack.pop() val v = evalstack.pop()
// todo b/w checkDt(v, DataType.BYTE)
evalstack.push(v.rol2())
}
Opcode.ROL2_W -> {
val v = evalstack.pop()
checkDt(v, DataType.WORD)
evalstack.push(v.rol2()) evalstack.push(v.rol2())
} }
Opcode.ROR -> { Opcode.ROR -> {
val v = evalstack.pop() val v = evalstack.pop()
// todo b/w checkDt(v, DataType.BYTE)
val (result, newCarry) = v.ror(P_carry)
this.P_carry = newCarry
evalstack.push(result)
}
Opcode.ROR_W -> {
val v = evalstack.pop()
checkDt(v, DataType.WORD)
val (result, newCarry) = v.ror(P_carry) val (result, newCarry) = v.ror(P_carry)
this.P_carry = newCarry this.P_carry = newCarry
evalstack.push(result) evalstack.push(result)
} }
Opcode.ROR2 -> { Opcode.ROR2 -> {
val v = evalstack.pop() val v = evalstack.pop()
// todo b/w checkDt(v, DataType.BYTE)
evalstack.push(v.ror2())
}
Opcode.ROR2_W -> {
val v = evalstack.pop()
checkDt(v, DataType.WORD)
evalstack.push(v.ror2()) evalstack.push(v.ror2())
} }
Opcode.BITAND -> { Opcode.BITAND -> {
val (top, second) = evalstack.pop2() val (top, second) = evalstack.pop2()
// todo b/w checkDt(top, DataType.BYTE)
checkDt(second, DataType.BYTE)
evalstack.push(second.bitand(top))
}
Opcode.BITAND_W -> {
val (top, second) = evalstack.pop2()
checkDt(top, DataType.WORD)
checkDt(second, DataType.WORD)
evalstack.push(second.bitand(top)) evalstack.push(second.bitand(top))
} }
Opcode.BITOR -> { Opcode.BITOR -> {
val (top, second) = evalstack.pop2() val (top, second) = evalstack.pop2()
// todo b/w checkDt(top, DataType.BYTE)
checkDt(second, DataType.BYTE)
evalstack.push(second.bitor(top))
}
Opcode.BITOR_W -> {
val (top, second) = evalstack.pop2()
checkDt(top, DataType.WORD)
checkDt(second, DataType.WORD)
evalstack.push(second.bitor(top)) evalstack.push(second.bitor(top))
} }
Opcode.BITXOR -> { Opcode.BITXOR -> {
val (top, second) = evalstack.pop2() val (top, second) = evalstack.pop2()
// todo b/w checkDt(top, DataType.BYTE)
checkDt(second, DataType.BYTE)
evalstack.push(second.bitxor(top))
}
Opcode.BITXOR_W -> {
val (top, second) = evalstack.pop2()
checkDt(top, DataType.WORD)
checkDt(second, DataType.WORD)
evalstack.push(second.bitxor(top)) evalstack.push(second.bitxor(top))
} }
Opcode.INV -> { Opcode.INV -> {
val v = evalstack.pop() val v = evalstack.pop()
// todo b/w checkDt(v, DataType.BYTE)
evalstack.push(v.inv())
}
Opcode.INV_W -> {
val v = evalstack.pop()
checkDt(v, DataType.WORD)
evalstack.push(v.inv()) evalstack.push(v.inv())
} }
Opcode.INC -> { Opcode.INC -> {
@ -705,36 +798,70 @@ class StackVm(private var traceOutputFile: String?) {
} }
Opcode.SHL_VAR -> { Opcode.SHL_VAR -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}") val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
// todo b/w checkDt(variable, DataType.BYTE)
variables[ins.callLabel!!] = variable.shl()
}
Opcode.SHL_VAR_W -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
checkDt(variable, DataType.WORD)
variables[ins.callLabel!!] = variable.shl() variables[ins.callLabel!!] = variable.shl()
} }
Opcode.SHR_VAR -> { Opcode.SHR_VAR -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}") val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
// todo b/w checkDt(variable, DataType.BYTE)
variables[ins.callLabel!!] = variable.shr()
}
Opcode.SHR_VAR_W -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
checkDt(variable, DataType.WORD)
variables[ins.callLabel!!] = variable.shr() variables[ins.callLabel!!] = variable.shr()
} }
Opcode.ROL_VAR -> { Opcode.ROL_VAR -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}") val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
// todo b/w checkDt(variable, DataType.BYTE)
val (newValue, newCarry) = variable.rol(P_carry)
variables[ins.callLabel!!] = newValue
P_carry = newCarry
}
Opcode.ROL_VAR_W -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
checkDt(variable, DataType.WORD)
val (newValue, newCarry) = variable.rol(P_carry) val (newValue, newCarry) = variable.rol(P_carry)
variables[ins.callLabel!!] = newValue variables[ins.callLabel!!] = newValue
P_carry = newCarry P_carry = newCarry
} }
Opcode.ROR_VAR -> { Opcode.ROR_VAR -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}") val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
// todo b/w checkDt(variable, DataType.BYTE)
val (newValue, newCarry) = variable.ror(P_carry)
variables[ins.callLabel!!] = newValue
P_carry = newCarry
}
Opcode.ROR_VAR_W -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
checkDt(variable, DataType.WORD)
val (newValue, newCarry) = variable.ror(P_carry) val (newValue, newCarry) = variable.ror(P_carry)
variables[ins.callLabel!!] = newValue variables[ins.callLabel!!] = newValue
P_carry = newCarry P_carry = newCarry
} }
Opcode.ROL2_VAR -> { Opcode.ROL2_VAR -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}") val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
// todo b/w checkDt(variable, DataType.BYTE)
variables[ins.callLabel!!] = variable.rol2()
}
Opcode.ROL2_VAR_W -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
checkDt(variable, DataType.WORD)
variables[ins.callLabel!!] = variable.rol2() variables[ins.callLabel!!] = variable.rol2()
} }
Opcode.ROR2_VAR -> { Opcode.ROR2_VAR -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}") val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
// todo b/w checkDt(variable, DataType.BYTE)
variables[ins.callLabel!!] = variable.ror2()
}
Opcode.ROR2_VAR_W -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
checkDt(variable, DataType.WORD)
variables[ins.callLabel!!] = variable.ror2() variables[ins.callLabel!!] = variable.ror2()
} }
Opcode.INC_VAR -> { Opcode.INC_VAR -> {
@ -779,52 +906,156 @@ class StackVm(private var traceOutputFile: String?) {
} }
Opcode.AND -> { Opcode.AND -> {
val (top, second) = evalstack.pop2() val (top, second) = evalstack.pop2()
// todo b/w checkDt(top, DataType.BYTE)
checkDt(second, DataType.BYTE)
evalstack.push(second.and(top))
}
Opcode.AND_W -> {
val (top, second) = evalstack.pop2()
checkDt(top, DataType.WORD)
checkDt(second, DataType.WORD)
evalstack.push(second.and(top)) evalstack.push(second.and(top))
} }
Opcode.OR -> { Opcode.OR -> {
val (top, second) = evalstack.pop2() val (top, second) = evalstack.pop2()
// todo b/w checkDt(top, DataType.BYTE)
checkDt(second, DataType.BYTE)
evalstack.push(second.or(top))
}
Opcode.OR_W -> {
val (top, second) = evalstack.pop2()
checkDt(top, DataType.WORD)
checkDt(second, DataType.WORD)
evalstack.push(second.or(top)) evalstack.push(second.or(top))
} }
Opcode.XOR -> { Opcode.XOR -> {
val (top, second) = evalstack.pop2() val (top, second) = evalstack.pop2()
// todo b/w checkDt(top, DataType.BYTE)
checkDt(second, DataType.BYTE)
evalstack.push(second.xor(top))
}
Opcode.XOR_W -> {
val (top, second) = evalstack.pop2()
checkDt(top, DataType.WORD)
checkDt(second, DataType.WORD)
evalstack.push(second.xor(top)) evalstack.push(second.xor(top))
} }
Opcode.NOT -> { Opcode.NOT -> {
val value = evalstack.pop() val value = evalstack.pop()
// todo b/w checkDt(value, DataType.BYTE)
evalstack.push(value.not())
}
Opcode.NOT_W -> {
val value = evalstack.pop()
checkDt(value, DataType.WORD)
evalstack.push(value.not()) evalstack.push(value.not())
} }
Opcode.LESS -> { Opcode.LESS -> {
val (top, second) = evalstack.pop2() val (top, second) = evalstack.pop2()
// todo b/w/f? checkDt(top, DataType.BYTE)
checkDt(second, DataType.BYTE)
evalstack.push(Value(DataType.BYTE, if(second < top) 1 else 0))
}
Opcode.LESS_W -> {
val (top, second) = evalstack.pop2()
checkDt(top, DataType.WORD)
checkDt(second, DataType.WORD)
evalstack.push(Value(DataType.BYTE, if(second < top) 1 else 0))
}
Opcode.LESS_F -> {
val (top, second) = evalstack.pop2()
checkDt(top, DataType.FLOAT)
checkDt(second, DataType.FLOAT)
evalstack.push(Value(DataType.BYTE, if(second < top) 1 else 0)) evalstack.push(Value(DataType.BYTE, if(second < top) 1 else 0))
} }
Opcode.GREATER -> { Opcode.GREATER -> {
val (top, second) = evalstack.pop2() val (top, second) = evalstack.pop2()
// todo b/w/f? checkDt(top, DataType.BYTE)
checkDt(second, DataType.BYTE)
evalstack.push(Value(DataType.BYTE, if(second > top) 1 else 0))
}
Opcode.GREATER_W -> {
val (top, second) = evalstack.pop2()
checkDt(top, DataType.WORD)
checkDt(second, DataType.WORD)
evalstack.push(Value(DataType.BYTE, if(second > top) 1 else 0))
}
Opcode.GREATER_F -> {
val (top, second) = evalstack.pop2()
checkDt(top, DataType.FLOAT)
checkDt(second, DataType.FLOAT)
evalstack.push(Value(DataType.BYTE, if(second > top) 1 else 0)) evalstack.push(Value(DataType.BYTE, if(second > top) 1 else 0))
} }
Opcode.LESSEQ -> { Opcode.LESSEQ -> {
val (top, second) = evalstack.pop2() val (top, second) = evalstack.pop2()
// todo b/w/f? checkDt(top, DataType.BYTE)
checkDt(second, DataType.BYTE)
evalstack.push(Value(DataType.BYTE, if(second <= top) 1 else 0))
}
Opcode.LESSEQ_W -> {
val (top, second) = evalstack.pop2()
checkDt(top, DataType.WORD)
checkDt(second, DataType.WORD)
evalstack.push(Value(DataType.BYTE, if(second <= top) 1 else 0))
}
Opcode.LESSEQ_F -> {
val (top, second) = evalstack.pop2()
checkDt(top, DataType.FLOAT)
checkDt(second, DataType.FLOAT)
evalstack.push(Value(DataType.BYTE, if(second <= top) 1 else 0)) evalstack.push(Value(DataType.BYTE, if(second <= top) 1 else 0))
} }
Opcode.GREATEREQ -> { Opcode.GREATEREQ -> {
val (top, second) = evalstack.pop2() val (top, second) = evalstack.pop2()
// todo b/w/f? checkDt(top, DataType.BYTE)
checkDt(second, DataType.BYTE)
evalstack.push(Value(DataType.BYTE, if(second >= top) 1 else 0))
}
Opcode.GREATEREQ_W -> {
val (top, second) = evalstack.pop2()
checkDt(top, DataType.WORD)
checkDt(second, DataType.WORD)
evalstack.push(Value(DataType.BYTE, if(second >= top) 1 else 0))
}
Opcode.GREATEREQ_F -> {
val (top, second) = evalstack.pop2()
checkDt(top, DataType.FLOAT)
checkDt(second, DataType.FLOAT)
evalstack.push(Value(DataType.BYTE, if(second >= top) 1 else 0)) evalstack.push(Value(DataType.BYTE, if(second >= top) 1 else 0))
} }
Opcode.EQUAL -> { Opcode.EQUAL -> {
val (top, second) = evalstack.pop2() val (top, second) = evalstack.pop2()
// todo b/w/f? checkDt(top, DataType.BYTE)
checkDt(second, DataType.BYTE)
evalstack.push(Value(DataType.BYTE, if(second == top) 1 else 0))
}
Opcode.EQUAL_W -> {
val (top, second) = evalstack.pop2()
checkDt(top, DataType.WORD)
checkDt(second, DataType.WORD)
evalstack.push(Value(DataType.BYTE, if(second == top) 1 else 0))
}
Opcode.EQUAL_F -> {
val (top, second) = evalstack.pop2()
checkDt(top, DataType.FLOAT)
checkDt(second, DataType.FLOAT)
evalstack.push(Value(DataType.BYTE, if(second == top) 1 else 0)) evalstack.push(Value(DataType.BYTE, if(second == top) 1 else 0))
} }
Opcode.NOTEQUAL -> { Opcode.NOTEQUAL -> {
val (top, second) = evalstack.pop2() val (top, second) = evalstack.pop2()
// todo b/w/f? checkDt(top, DataType.BYTE)
checkDt(second, DataType.BYTE)
evalstack.push(Value(DataType.BYTE, if(second != top) 1 else 0))
}
Opcode.NOTEQUAL_W -> {
val (top, second) = evalstack.pop2()
checkDt(top, DataType.WORD)
checkDt(second, DataType.WORD)
evalstack.push(Value(DataType.BYTE, if(second != top) 1 else 0))
}
Opcode.NOTEQUAL_F -> {
val (top, second) = evalstack.pop2()
checkDt(top, DataType.FLOAT)
checkDt(second, DataType.FLOAT)
evalstack.push(Value(DataType.BYTE, if(second != top) 1 else 0)) evalstack.push(Value(DataType.BYTE, if(second != top) 1 else 0))
} }
Opcode.B2WORD -> { Opcode.B2WORD -> {

View File

@ -17,21 +17,27 @@ import kotlin.test.*
SHL_MEM, SHL_MEM,
SHL_MEM_W, SHL_MEM_W,
SHL_VAR, SHL_VAR,
SHL_VAR_W,
SHR_MEM, SHR_MEM,
SHR_MEM_W, SHR_MEM_W,
SHR_VAR, SHR_VAR,
SHR_VAR_W,
ROL_MEM, ROL_MEM,
ROL_MEM_W, ROL_MEM_W,
ROL_VAR, ROL_VAR,
ROL_VAR_W,
ROR_MEM, ROR_MEM,
ROR_MEM_W, ROR_MEM_W,
ROR_VAR, ROR_VAR,
ROR_VAR_W,
ROL2_MEM, ROL2_MEM,
ROL2_MEM_W, ROL2_MEM_W,
ROL2_VAR, ROL2_VAR,
ROL2_VAR_W,
ROR2_MEM, ROR2_MEM,
ROR2_MEM_W, ROR2_MEM_W,
ROR2_VAR, ROR2_VAR,
ROR2_VAR_W
**/ **/
@ -306,19 +312,19 @@ class TestStackVmOpcodes {
@Test @Test
fun testBitand() { fun testBitand() {
testBinaryOperator(Value(DataType.BYTE, 0b10011111), Opcode.BITAND, Value(DataType.BYTE, 0b11111101), Value(DataType.BYTE, 0b10011101)) testBinaryOperator(Value(DataType.BYTE, 0b10011111), Opcode.BITAND, Value(DataType.BYTE, 0b11111101), Value(DataType.BYTE, 0b10011101))
testBinaryOperator(Value(DataType.WORD, 0b0011001011110001), Opcode.BITAND, Value(DataType.BYTE, 0b10011101), Value(DataType.WORD, 0b0000000010010001)) testBinaryOperator(Value(DataType.WORD, 0b0011001011110001), Opcode.BITAND_W, Value(DataType.WORD, 0b1110000010011101), Value(DataType.WORD, 0b0010000010010001))
} }
@Test @Test
fun testBitor() { fun testBitor() {
testBinaryOperator(Value(DataType.BYTE, 0b00011101), Opcode.BITOR, Value(DataType.BYTE, 0b10010001), Value(DataType.BYTE, 0b10011101)) testBinaryOperator(Value(DataType.BYTE, 0b00011101), Opcode.BITOR, Value(DataType.BYTE, 0b10010001), Value(DataType.BYTE, 0b10011101))
testBinaryOperator(Value(DataType.WORD, 0b0011001011100000), Opcode.BITOR, Value(DataType.BYTE, 0b10011101), Value(DataType.WORD, 0b0011001011111101)) testBinaryOperator(Value(DataType.WORD, 0b0011001011100000), Opcode.BITOR_W, Value(DataType.WORD, 0b1000000010011101), Value(DataType.WORD, 0b1011001011111101))
} }
@Test @Test
fun testBitxor() { fun testBitxor() {
testBinaryOperator(Value(DataType.BYTE, 0b00011101), Opcode.BITXOR, Value(DataType.BYTE, 0b10010001), Value(DataType.BYTE, 0b10001100)) testBinaryOperator(Value(DataType.BYTE, 0b00011101), Opcode.BITXOR, Value(DataType.BYTE, 0b10010001), Value(DataType.BYTE, 0b10001100))
testBinaryOperator(Value(DataType.WORD, 0b0011001011100000), Opcode.BITXOR, Value(DataType.BYTE, 0b10001100), Value(DataType.WORD, 0b0011001001101100)) testBinaryOperator(Value(DataType.WORD, 0b0011001011100000), Opcode.BITXOR_W, Value(DataType.WORD, 0b1000000010001100), Value(DataType.WORD, 0b1011001001101100))
} }
@Test @Test
@ -326,14 +332,9 @@ class TestStackVmOpcodes {
testBinaryOperator(Value(DataType.BYTE, 200), Opcode.AND, Value(DataType.BYTE, 1), Value(DataType.BYTE, 1)) testBinaryOperator(Value(DataType.BYTE, 200), Opcode.AND, Value(DataType.BYTE, 1), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.BYTE, 200), Opcode.AND, Value(DataType.BYTE, 0), Value(DataType.BYTE, 0)) testBinaryOperator(Value(DataType.BYTE, 200), Opcode.AND, Value(DataType.BYTE, 0), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.BYTE, 0), Opcode.AND, Value(DataType.BYTE, 101), Value(DataType.BYTE, 0)) testBinaryOperator(Value(DataType.BYTE, 0), Opcode.AND, Value(DataType.BYTE, 101), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.WORD, 200), Opcode.AND, Value(DataType.WORD, 13455), Value(DataType.BYTE, 1)) testBinaryOperator(Value(DataType.WORD, 200), Opcode.AND_W, Value(DataType.WORD, 13455), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.WORD, 200), Opcode.AND, Value(DataType.WORD, 0), Value(DataType.BYTE, 0)) testBinaryOperator(Value(DataType.WORD, 200), Opcode.AND_W, Value(DataType.WORD, 0), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.WORD, 0), Opcode.AND, Value(DataType.WORD, 101), Value(DataType.BYTE, 0)) testBinaryOperator(Value(DataType.WORD, 0), Opcode.AND_W, Value(DataType.WORD, 101), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.FLOAT, 200.22), Opcode.AND, Value(DataType.FLOAT, 13455.55), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.FLOAT, 200.22), Opcode.AND, Value(DataType.FLOAT, 0.0), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.FLOAT, 0.0), Opcode.AND, Value(DataType.FLOAT, 101.11), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.STR, 222), Opcode.AND, Value(DataType.STR, 333), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.ARRAY, 444), Opcode.AND, Value(DataType.ARRAY, 444), Value(DataType.BYTE, 1))
} }
@Test @Test
@ -341,14 +342,9 @@ class TestStackVmOpcodes {
testBinaryOperator(Value(DataType.BYTE, 200), Opcode.OR, Value(DataType.BYTE, 1), Value(DataType.BYTE, 1)) testBinaryOperator(Value(DataType.BYTE, 200), Opcode.OR, Value(DataType.BYTE, 1), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.BYTE, 200), Opcode.OR, Value(DataType.BYTE, 0), Value(DataType.BYTE, 1)) testBinaryOperator(Value(DataType.BYTE, 200), Opcode.OR, Value(DataType.BYTE, 0), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.BYTE, 0), Opcode.OR, Value(DataType.BYTE, 0), Value(DataType.BYTE, 0)) testBinaryOperator(Value(DataType.BYTE, 0), Opcode.OR, Value(DataType.BYTE, 0), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.WORD, 200), Opcode.OR, Value(DataType.WORD, 13455), Value(DataType.BYTE, 1)) testBinaryOperator(Value(DataType.WORD, 200), Opcode.OR_W, Value(DataType.WORD, 13455), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.WORD, 200), Opcode.OR, Value(DataType.WORD, 0), Value(DataType.BYTE, 1)) testBinaryOperator(Value(DataType.WORD, 200), Opcode.OR_W, Value(DataType.WORD, 0), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.WORD, 0), Opcode.OR, Value(DataType.WORD, 0), Value(DataType.BYTE, 0)) testBinaryOperator(Value(DataType.WORD, 0), Opcode.OR_W, Value(DataType.WORD, 0), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.FLOAT, 200.22), Opcode.OR, Value(DataType.FLOAT, 13455.55), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.FLOAT, 200.22), Opcode.OR, Value(DataType.FLOAT, 0.0), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.FLOAT, 0.0), Opcode.OR, Value(DataType.FLOAT, 0.0), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.STR, 222), Opcode.OR, Value(DataType.STR, 333), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.ARRAY, 444), Opcode.OR, Value(DataType.ARRAY, 444), Value(DataType.BYTE, 1))
} }
@Test @Test
@ -356,24 +352,17 @@ class TestStackVmOpcodes {
testBinaryOperator(Value(DataType.BYTE, 200), Opcode.XOR, Value(DataType.BYTE, 1), Value(DataType.BYTE, 0)) testBinaryOperator(Value(DataType.BYTE, 200), Opcode.XOR, Value(DataType.BYTE, 1), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.BYTE, 200), Opcode.XOR, Value(DataType.BYTE, 0), Value(DataType.BYTE, 1)) testBinaryOperator(Value(DataType.BYTE, 200), Opcode.XOR, Value(DataType.BYTE, 0), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.BYTE, 0), Opcode.XOR, Value(DataType.BYTE, 0), Value(DataType.BYTE, 0)) testBinaryOperator(Value(DataType.BYTE, 0), Opcode.XOR, Value(DataType.BYTE, 0), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.WORD, 200), Opcode.XOR, Value(DataType.WORD, 13455), Value(DataType.BYTE, 0)) testBinaryOperator(Value(DataType.WORD, 200), Opcode.XOR_W, Value(DataType.WORD, 13455), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.WORD, 200), Opcode.XOR, Value(DataType.WORD, 0), Value(DataType.BYTE, 1)) testBinaryOperator(Value(DataType.WORD, 200), Opcode.XOR_W, Value(DataType.WORD, 0), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.WORD, 0), Opcode.XOR, Value(DataType.WORD, 0), Value(DataType.BYTE, 0)) testBinaryOperator(Value(DataType.WORD, 0), Opcode.XOR_W, Value(DataType.WORD, 0), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.FLOAT, 200.22), Opcode.XOR, Value(DataType.FLOAT, 13455.55), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.FLOAT, 200.22), Opcode.XOR, Value(DataType.FLOAT, 0.0), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.FLOAT, 0.0), Opcode.XOR, Value(DataType.FLOAT, 0.0), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.STR, 222), Opcode.XOR, Value(DataType.STR, 333), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.ARRAY, 444), Opcode.XOR, Value(DataType.ARRAY, 444), Value(DataType.BYTE, 0))
} }
@Test @Test
fun testNot() { fun testNot() {
testUnaryOperator(Value(DataType.BYTE, 0), Opcode.NOT, Value(DataType.BYTE, 1)) testUnaryOperator(Value(DataType.BYTE, 0), Opcode.NOT, Value(DataType.BYTE, 1))
testUnaryOperator(Value(DataType.BYTE, 20), Opcode.NOT, Value(DataType.BYTE, 0)) testUnaryOperator(Value(DataType.BYTE, 20), Opcode.NOT, Value(DataType.BYTE, 0))
testUnaryOperator(Value(DataType.WORD, 0), Opcode.NOT, Value(DataType.BYTE, 1)) testUnaryOperator(Value(DataType.WORD, 0), Opcode.NOT_W, Value(DataType.BYTE, 1))
testUnaryOperator(Value(DataType.WORD, 5000), Opcode.NOT, Value(DataType.BYTE, 0)) testUnaryOperator(Value(DataType.WORD, 5000), Opcode.NOT_W, Value(DataType.BYTE, 0))
testUnaryOperator(Value(DataType.FLOAT, 0.0), Opcode.NOT, Value(DataType.BYTE, 1))
testUnaryOperator(Value(DataType.FLOAT, 5000.0), Opcode.NOT, Value(DataType.BYTE, 0))
} }
@Test @Test
@ -406,7 +395,7 @@ class TestStackVmOpcodes {
@Test @Test
fun testInv() { fun testInv() {
testUnaryOperator(Value(DataType.BYTE, 123), Opcode.INV, Value(DataType.BYTE, 0x84)) testUnaryOperator(Value(DataType.BYTE, 123), Opcode.INV, Value(DataType.BYTE, 0x84))
testUnaryOperator(Value(DataType.WORD, 4044), Opcode.INV, Value(DataType.WORD, 0xf033)) testUnaryOperator(Value(DataType.WORD, 4044), Opcode.INV_W, Value(DataType.WORD, 0xf033))
} }
@Test @Test
@ -586,182 +575,74 @@ class TestStackVmOpcodes {
@Test @Test
fun testLess() { fun testLess() {
val values = listOf( testBinaryOperator(Value(DataType.BYTE, 0), Opcode.LESS, Value(DataType.BYTE, 1), Value(DataType.BYTE, 1))
Value(DataType.BYTE, 0), testBinaryOperator(Value(DataType.BYTE, 1), Opcode.LESS, Value(DataType.BYTE, 1), Value(DataType.BYTE, 0))
Value(DataType.BYTE, 1), // 1 testBinaryOperator(Value(DataType.WORD, 2), Opcode.LESS_W, Value(DataType.WORD, 20), Value(DataType.BYTE, 1))
Value(DataType.BYTE, 1), testBinaryOperator(Value(DataType.WORD, 20), Opcode.LESS_W, Value(DataType.WORD, 21), Value(DataType.BYTE, 1))
Value(DataType.BYTE, 1), // 0 testBinaryOperator(Value(DataType.WORD, 21), Opcode.LESS_W, Value(DataType.WORD, 21), Value(DataType.BYTE, 0))
Value(DataType.BYTE, 2), testBinaryOperator(Value(DataType.WORD, 21), Opcode.LESS_W, Value(DataType.WORD, 21), Value(DataType.BYTE, 0))
Value(DataType.WORD, 20), // 1 testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.LESS_F, Value(DataType.FLOAT, 21.0), Value(DataType.BYTE, 0))
Value(DataType.WORD, 20), testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.LESS_F, Value(DataType.FLOAT, 21.001), Value(DataType.BYTE, 1))
Value(DataType.BYTE, 21), // 1
Value(DataType.WORD, 21),
Value(DataType.BYTE, 21), // 0
Value(DataType.BYTE, 21),
Value(DataType.FLOAT, 21), // 0
Value(DataType.BYTE, 21),
Value(DataType.FLOAT, 21.0001) // 1
)
val expected = listOf(1, 0, 1, 1, 0, 0, 1)
testComparisonOperator(values, expected, Opcode.LESS)
val valuesInvalid = listOf(
Value(DataType.STR, 333),
Value(DataType.STR, 333)
)
assertFailsWith<VmExecutionException> {
testComparisonOperator(valuesInvalid, listOf(0), Opcode.LESS) // can't order strings
}
} }
@Test @Test
fun testLessEq() { fun testLessEq() {
val values = listOf( testBinaryOperator(Value(DataType.BYTE, 0), Opcode.LESSEQ, Value(DataType.BYTE, 1), Value(DataType.BYTE, 1))
Value(DataType.BYTE, 0), testBinaryOperator(Value(DataType.BYTE, 1), Opcode.LESSEQ, Value(DataType.BYTE, 1), Value(DataType.BYTE, 1))
Value(DataType.BYTE, 1), // 1 testBinaryOperator(Value(DataType.WORD, 2), Opcode.LESSEQ_W, Value(DataType.WORD, 20), Value(DataType.BYTE, 1))
Value(DataType.BYTE, 1), testBinaryOperator(Value(DataType.WORD, 20), Opcode.LESSEQ_W, Value(DataType.WORD, 21), Value(DataType.BYTE, 1))
Value(DataType.BYTE, 1), // 1 testBinaryOperator(Value(DataType.WORD, 21), Opcode.LESSEQ_W, Value(DataType.WORD, 21), Value(DataType.BYTE, 1))
Value(DataType.BYTE, 21), testBinaryOperator(Value(DataType.WORD, 21), Opcode.LESSEQ_W, Value(DataType.WORD, 20), Value(DataType.BYTE, 0))
Value(DataType.WORD, 20), // 0 testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.LESSEQ_F, Value(DataType.FLOAT, 21.0), Value(DataType.BYTE, 1))
Value(DataType.WORD, 20), testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.LESSEQ_F, Value(DataType.FLOAT, 20.999), Value(DataType.BYTE, 0))
Value(DataType.BYTE, 21), // 1
Value(DataType.WORD, 21),
Value(DataType.BYTE, 22), // 1
Value(DataType.BYTE, 21),
Value(DataType.FLOAT, 21), // 1
Value(DataType.BYTE, 22),
Value(DataType.FLOAT, 21.999) // 0
)
val expected = listOf(1,1,0,1,1,1,0)
testComparisonOperator(values, expected, Opcode.LESSEQ)
val valuesInvalid = listOf(
Value(DataType.STR, 333),
Value(DataType.STR, 333)
)
assertFailsWith<VmExecutionException> {
testComparisonOperator(valuesInvalid, listOf(0), Opcode.LESSEQ) // can't order strings
}
} }
@Test @Test
fun testGreater() { fun testGreater() {
val values = listOf( testBinaryOperator(Value(DataType.BYTE, 0), Opcode.GREATER, Value(DataType.BYTE, 1), Value(DataType.BYTE, 0))
Value(DataType.BYTE, 0), testBinaryOperator(Value(DataType.BYTE, 1), Opcode.GREATER, Value(DataType.BYTE, 1), Value(DataType.BYTE, 0))
Value(DataType.BYTE, 1), // 0 testBinaryOperator(Value(DataType.WORD, 2), Opcode.GREATER_W, Value(DataType.WORD, 20), Value(DataType.BYTE, 0))
Value(DataType.BYTE, 1), testBinaryOperator(Value(DataType.WORD, 20), Opcode.GREATER_W, Value(DataType.WORD, 21), Value(DataType.BYTE, 0))
Value(DataType.BYTE, 1), // 0 testBinaryOperator(Value(DataType.WORD, 21), Opcode.GREATER_W, Value(DataType.WORD, 20), Value(DataType.BYTE, 1))
Value(DataType.BYTE, 20), testBinaryOperator(Value(DataType.WORD, 21), Opcode.GREATER_W, Value(DataType.WORD, 21), Value(DataType.BYTE, 0))
Value(DataType.WORD, 2), // 1 testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.GREATER_F, Value(DataType.FLOAT, 21.0), Value(DataType.BYTE, 0))
Value(DataType.WORD, 20), testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.GREATER_F, Value(DataType.FLOAT, 20.999), Value(DataType.BYTE, 1))
Value(DataType.BYTE, 21), // 0
Value(DataType.WORD, 21),
Value(DataType.BYTE, 20), // 1
Value(DataType.BYTE, 21),
Value(DataType.FLOAT, 21), // 0
Value(DataType.BYTE, 21),
Value(DataType.FLOAT, 20.9999) // 1
)
val expected = listOf(0, 0, 1, 0, 1, 0, 1)
testComparisonOperator(values, expected, Opcode.GREATER)
val valuesInvalid = listOf(
Value(DataType.STR, 333),
Value(DataType.STR, 333)
)
assertFailsWith<VmExecutionException> {
testComparisonOperator(valuesInvalid, listOf(0), Opcode.GREATER) // can't order strings
}
} }
@Test @Test
fun testGreaterEq() { fun testGreaterEq() {
val values = listOf( testBinaryOperator(Value(DataType.BYTE, 0), Opcode.GREATEREQ, Value(DataType.BYTE, 1), Value(DataType.BYTE, 0))
Value(DataType.BYTE, 0), testBinaryOperator(Value(DataType.BYTE, 1), Opcode.GREATEREQ, Value(DataType.BYTE, 1), Value(DataType.BYTE, 1))
Value(DataType.BYTE, 1), // 0 testBinaryOperator(Value(DataType.WORD, 2), Opcode.GREATEREQ_W, Value(DataType.WORD, 20), Value(DataType.BYTE, 0))
Value(DataType.BYTE, 1), testBinaryOperator(Value(DataType.WORD, 20), Opcode.GREATEREQ_W, Value(DataType.WORD, 21), Value(DataType.BYTE, 0))
Value(DataType.BYTE, 1), // 1 testBinaryOperator(Value(DataType.WORD, 21), Opcode.GREATEREQ_W, Value(DataType.WORD, 20), Value(DataType.BYTE, 1))
Value(DataType.BYTE, 21), testBinaryOperator(Value(DataType.WORD, 21), Opcode.GREATEREQ_W, Value(DataType.WORD, 21), Value(DataType.BYTE, 1))
Value(DataType.WORD, 20), // 1 testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.GREATEREQ_F, Value(DataType.FLOAT, 21.0), Value(DataType.BYTE, 1))
Value(DataType.WORD, 20), testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.GREATEREQ_F, Value(DataType.FLOAT, 21.001), Value(DataType.BYTE, 0))
Value(DataType.BYTE, 21), // 0
Value(DataType.WORD, 21),
Value(DataType.BYTE, 22), // 0
Value(DataType.BYTE, 21),
Value(DataType.FLOAT, 21), // 1
Value(DataType.BYTE, 22),
Value(DataType.FLOAT, 21.999) // 1
)
val expected = listOf(0,1,1,0,0,1,1)
testComparisonOperator(values, expected, Opcode.GREATEREQ)
val valuesInvalid = listOf(
Value(DataType.STR, 333),
Value(DataType.STR, 333)
)
assertFailsWith<VmExecutionException> {
testComparisonOperator(valuesInvalid, listOf(0), Opcode.GREATEREQ) // can't order strings
}
} }
@Test @Test
fun testEqual() { fun testEqual() {
val values = listOf( testBinaryOperator(Value(DataType.BYTE, 0), Opcode.EQUAL, Value(DataType.BYTE, 1), Value(DataType.BYTE, 0))
Value(DataType.BYTE, 0), testBinaryOperator(Value(DataType.BYTE, 1), Opcode.EQUAL, Value(DataType.BYTE, 1), Value(DataType.BYTE, 1))
Value(DataType.BYTE, 1), // 0 testBinaryOperator(Value(DataType.WORD, 2), Opcode.EQUAL_W, Value(DataType.WORD, 20), Value(DataType.BYTE, 0))
Value(DataType.BYTE, 1), testBinaryOperator(Value(DataType.WORD, 20), Opcode.EQUAL_W, Value(DataType.WORD, 21), Value(DataType.BYTE, 0))
Value(DataType.BYTE, 1), // 1 testBinaryOperator(Value(DataType.WORD, 21), Opcode.EQUAL_W, Value(DataType.WORD, 20), Value(DataType.BYTE, 0))
Value(DataType.BYTE, 21), testBinaryOperator(Value(DataType.WORD, 21), Opcode.EQUAL_W, Value(DataType.WORD, 21), Value(DataType.BYTE, 1))
Value(DataType.WORD, 20), // 0 testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.EQUAL_F, Value(DataType.FLOAT, 21.0), Value(DataType.BYTE, 1))
Value(DataType.WORD, 20), testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.EQUAL_F, Value(DataType.FLOAT, 21.001), Value(DataType.BYTE, 0))
Value(DataType.BYTE, 21), // 0
Value(DataType.WORD, 21),
Value(DataType.BYTE, 21), // 1
Value(DataType.BYTE, 21),
Value(DataType.FLOAT, 21), // 1
Value(DataType.BYTE, 22),
Value(DataType.FLOAT, 21.999) // 0
)
val expected = listOf(0,1,0,0,1,1,0)
testComparisonOperator(values, expected, Opcode.EQUAL)
val valuesInvalid = listOf(
Value(DataType.STR, 111),
Value(DataType.STR, 222), // 0
Value(DataType.STR, 333),
Value(DataType.STR, 333) // 1
)
testComparisonOperator(valuesInvalid, listOf(0, 1), Opcode.EQUAL)
} }
@Test @Test
fun testNotEqual() { fun testNotEqual() {
val values = listOf( testBinaryOperator(Value(DataType.BYTE, 0), Opcode.NOTEQUAL, Value(DataType.BYTE, 1), Value(DataType.BYTE, 1))
Value(DataType.BYTE, 0), testBinaryOperator(Value(DataType.BYTE, 1), Opcode.NOTEQUAL, Value(DataType.BYTE, 1), Value(DataType.BYTE, 0))
Value(DataType.BYTE, 1), // 1 testBinaryOperator(Value(DataType.WORD, 2), Opcode.NOTEQUAL_W, Value(DataType.WORD, 20), Value(DataType.BYTE, 1))
Value(DataType.BYTE, 1), testBinaryOperator(Value(DataType.WORD, 20), Opcode.NOTEQUAL_W, Value(DataType.WORD, 21), Value(DataType.BYTE, 1))
Value(DataType.BYTE, 1), // 0 testBinaryOperator(Value(DataType.WORD, 21), Opcode.NOTEQUAL_W, Value(DataType.WORD, 20), Value(DataType.BYTE, 1))
Value(DataType.BYTE, 21), testBinaryOperator(Value(DataType.WORD, 21), Opcode.NOTEQUAL_W, Value(DataType.WORD, 21), Value(DataType.BYTE, 0))
Value(DataType.WORD, 20), // 1 testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.NOTEQUAL_F, Value(DataType.FLOAT, 21.0), Value(DataType.BYTE, 0))
Value(DataType.WORD, 20), testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.NOTEQUAL_F, Value(DataType.FLOAT, 21.001), Value(DataType.BYTE, 1))
Value(DataType.BYTE, 21), // 1
Value(DataType.WORD, 21),
Value(DataType.BYTE, 21), // 0
Value(DataType.BYTE, 21),
Value(DataType.FLOAT, 21), // 0
Value(DataType.BYTE, 22),
Value(DataType.FLOAT, 21.999) // 1
)
val expected = listOf(1,0,1,1,0,0,1)
testComparisonOperator(values, expected, Opcode.NOTEQUAL)
val valuesInvalid = listOf(
Value(DataType.STR, 111),
Value(DataType.STR, 222), // 1
Value(DataType.STR, 333),
Value(DataType.STR, 333) // 0
)
testComparisonOperator(valuesInvalid, listOf(1, 0), Opcode.NOTEQUAL)
} }
@Test @Test
@ -964,11 +845,11 @@ class TestStackVmOpcodes {
Instruction(Opcode.SHR), // 0 Instruction(Opcode.SHR), // 0
Instruction(Opcode.SHR), // 0 Instruction(Opcode.SHR), // 0
Instruction(Opcode.DISCARD), Instruction(Opcode.DISCARD),
Instruction(Opcode.SHR), // 30502 Instruction(Opcode.SHR_W), // 30502
Instruction(Opcode.DISCARD_W), Instruction(Opcode.DISCARD_W),
Instruction(Opcode.SHR), // 1 Instruction(Opcode.SHR_W), // 1
Instruction(Opcode.SHR), // 0 Instruction(Opcode.SHR_W), // 0
Instruction(Opcode.SHR), // 0 Instruction(Opcode.SHR_W), // 0
Instruction(Opcode.DISCARD_W), Instruction(Opcode.DISCARD_W),
Instruction(Opcode.SHR) // error on float Instruction(Opcode.SHR) // error on float
) )
@ -1004,11 +885,11 @@ class TestStackVmOpcodes {
Instruction(Opcode.DISCARD), Instruction(Opcode.DISCARD),
Instruction(Opcode.SHL), // 6 Instruction(Opcode.SHL), // 6
Instruction(Opcode.DISCARD), Instruction(Opcode.DISCARD),
Instruction(Opcode.SHL), // 56474 Instruction(Opcode.SHL_W), // 56474
Instruction(Opcode.DISCARD_W), Instruction(Opcode.DISCARD_W),
Instruction(Opcode.SHL), // 6 Instruction(Opcode.SHL_W), // 6
Instruction(Opcode.DISCARD_W), Instruction(Opcode.DISCARD_W),
Instruction(Opcode.SHL) // error on float Instruction(Opcode.SHL_W) // error on float
) )
vm.load(makeProg(ins), null) vm.load(makeProg(ins), null)
vm.step(6) vm.step(6)
@ -1061,23 +942,23 @@ class TestStackVmOpcodes {
val ins2 = mutableListOf( val ins2 = mutableListOf(
Instruction(Opcode.CLC), Instruction(Opcode.CLC),
Instruction(Opcode.PUSH_W, Value(DataType.WORD, 0b1001001100001101)), Instruction(Opcode.PUSH_W, Value(DataType.WORD, 0b1001001100001101)),
Instruction(Opcode.ROR), // 0b0100100110000110 c=1 Instruction(Opcode.ROR_W), // 0b0100100110000110 c=1
Instruction(Opcode.ROR), // 0b1010010011000011 c=0 Instruction(Opcode.ROR_W), // 0b1010010011000011 c=0
Instruction(Opcode.ROR), Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR), Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR), Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR), Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR), Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR), Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR), Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR), Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR), Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR), Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR), Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR), Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR), Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR), Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR) // 0b1001001100001101 c=0 (original value after 17 rors) Instruction(Opcode.ROR_W) // 0b1001001100001101 c=0 (original value after 17 rors)
) )
vm.load(makeProg(ins2), null) vm.load(makeProg(ins2), null)
vm.step(3) vm.step(3)
@ -1126,23 +1007,23 @@ class TestStackVmOpcodes {
val ins2 = mutableListOf( val ins2 = mutableListOf(
Instruction(Opcode.CLC), Instruction(Opcode.CLC),
Instruction(Opcode.PUSH_W, Value(DataType.WORD, 0b1001001100001101)), Instruction(Opcode.PUSH_W, Value(DataType.WORD, 0b1001001100001101)),
Instruction(Opcode.ROL), // 0b0010011000011010 c=1 Instruction(Opcode.ROL_W), // 0b0010011000011010 c=1
Instruction(Opcode.ROL), // 0b0100110000110101 c=0 Instruction(Opcode.ROL_W), // 0b0100110000110101 c=0
Instruction(Opcode.ROL), Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL), Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL), Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL), Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL), Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL), Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL), Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL), Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL), Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL), Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL), Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL), Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL), Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL), Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL) // 0b1001001100001101 c=0 (original value after 17 rors) Instruction(Opcode.ROL_W) // 0b1001001100001101 c=0 (original value after 17 rors)
) )
vm.load(makeProg(ins2), null) vm.load(makeProg(ins2), null)
vm.step(3) vm.step(3)
@ -1183,22 +1064,22 @@ class TestStackVmOpcodes {
val ins2 = mutableListOf( val ins2 = mutableListOf(
Instruction(Opcode.PUSH_W, Value(DataType.WORD, 0b1001001100001101)), Instruction(Opcode.PUSH_W, Value(DataType.WORD, 0b1001001100001101)),
Instruction(Opcode.ROR2), // 0b1100100110000110 Instruction(Opcode.ROR2_W), // 0b1100100110000110
Instruction(Opcode.ROR2), // 0b0110010011000011 Instruction(Opcode.ROR2_W), // 0b0110010011000011
Instruction(Opcode.ROR2), Instruction(Opcode.ROR2_W),
Instruction(Opcode.ROR2), Instruction(Opcode.ROR2_W),
Instruction(Opcode.ROR2), Instruction(Opcode.ROR2_W),
Instruction(Opcode.ROR2), Instruction(Opcode.ROR2_W),
Instruction(Opcode.ROR2), Instruction(Opcode.ROR2_W),
Instruction(Opcode.ROR2), Instruction(Opcode.ROR2_W),
Instruction(Opcode.ROR2), Instruction(Opcode.ROR2_W),
Instruction(Opcode.ROR2), Instruction(Opcode.ROR2_W),
Instruction(Opcode.ROR2), Instruction(Opcode.ROR2_W),
Instruction(Opcode.ROR2), Instruction(Opcode.ROR2_W),
Instruction(Opcode.ROR2), Instruction(Opcode.ROR2_W),
Instruction(Opcode.ROR2), Instruction(Opcode.ROR2_W),
Instruction(Opcode.ROR2), Instruction(Opcode.ROR2_W),
Instruction(Opcode.ROR2) // 0b1001001100001101 (original value after 16 rors) Instruction(Opcode.ROR2_W) // 0b1001001100001101 (original value after 16 rors)
) )
vm.load(makeProg(ins2), null) vm.load(makeProg(ins2), null)
vm.step(2) vm.step(2)
@ -1235,22 +1116,22 @@ class TestStackVmOpcodes {
val ins2 = mutableListOf( val ins2 = mutableListOf(
Instruction(Opcode.PUSH_W, Value(DataType.WORD, 0b1001001100001101)), Instruction(Opcode.PUSH_W, Value(DataType.WORD, 0b1001001100001101)),
Instruction(Opcode.ROL2), // 0b0010011000011011 Instruction(Opcode.ROL2_W), // 0b0010011000011011
Instruction(Opcode.ROL2), // 0b0100110000110110 Instruction(Opcode.ROL2_W), // 0b0100110000110110
Instruction(Opcode.ROL2), Instruction(Opcode.ROL2_W),
Instruction(Opcode.ROL2), Instruction(Opcode.ROL2_W),
Instruction(Opcode.ROL2), Instruction(Opcode.ROL2_W),
Instruction(Opcode.ROL2), Instruction(Opcode.ROL2_W),
Instruction(Opcode.ROL2), Instruction(Opcode.ROL2_W),
Instruction(Opcode.ROL2), Instruction(Opcode.ROL2_W),
Instruction(Opcode.ROL2), Instruction(Opcode.ROL2_W),
Instruction(Opcode.ROL2), Instruction(Opcode.ROL2_W),
Instruction(Opcode.ROL2), Instruction(Opcode.ROL2_W),
Instruction(Opcode.ROL2), Instruction(Opcode.ROL2_W),
Instruction(Opcode.ROL2), Instruction(Opcode.ROL2_W),
Instruction(Opcode.ROL2), Instruction(Opcode.ROL2_W),
Instruction(Opcode.ROL2), Instruction(Opcode.ROL2_W),
Instruction(Opcode.ROL2) // 0b1001001100001101 (original value after 16 rols) Instruction(Opcode.ROL2_W) // 0b1001001100001101 (original value after 16 rols)
) )
vm.load(makeProg(ins2), null) vm.load(makeProg(ins2), null)
vm.step(2) vm.step(2)
@ -1273,24 +1154,6 @@ class TestStackVmOpcodes {
} }
} }
private fun testComparisonOperator(values: List<Value>, expected: List<Int>, operator: Opcode) {
assertEquals(values.size, expected.size*2)
val ins = mutableListOf<Instruction>()
val vars = values.iterator()
while(vars.hasNext()) {
var nextvar = vars.next()
ins.add(Instruction(pushOpcode(nextvar.type), nextvar))
nextvar = vars.next()
ins.add(Instruction(pushOpcode(nextvar.type), nextvar))
ins.add(Instruction(operator))
}
vm.load(makeProg(ins), null)
for(expectedValue in expected) {
vm.step(3)
assertEquals(Value(DataType.BYTE, expectedValue), vm.evalstack.pop())
}
}
private fun testBinaryOperator(left: Value, operator: Opcode, right: Value, result: Value) { private fun testBinaryOperator(left: Value, operator: Opcode, right: Value, result: Value) {
val program=makeProg(mutableListOf( val program=makeProg(mutableListOf(
Instruction(pushOpcode(left.type), left), Instruction(pushOpcode(left.type), left),