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.tree.TerminalNode
import prog8.compiler.HeapValues
import prog8.compiler.target.c64.Mflpt5
import prog8.compiler.target.c64.Petscii
import prog8.compiler.unescape
import prog8.functions.BuiltinFunctions

View File

@ -635,12 +635,54 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
}
"msb" -> stackvmProg.instr(Opcode.MSB)
"lsb" -> stackvmProg.instr(Opcode.LSB)
"lsl" -> stackvmProg.instr(Opcode.SHL)
"lsr" -> stackvmProg.instr(Opcode.SHR)
"rol" -> stackvmProg.instr(Opcode.ROL)
"ror" -> stackvmProg.instr(Opcode.ROR)
"rol2" -> stackvmProg.instr(Opcode.ROL2)
"ror2" -> stackvmProg.instr(Opcode.ROR2)
"lsl" -> {
val arg = args.single()
when (arg.resultingDatatype(namespace, heap)) {
DataType.BYTE -> stackvmProg.instr(Opcode.SHL)
DataType.WORD -> stackvmProg.instr(Opcode.SHL_W)
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)
"clear_carry" -> stackvmProg.instr(Opcode.CLC)
"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)
if(leftDt !in validDt || rightDt !in validDt)
throw CompilerException("invalid datatype(s) for operand(s)")
if(leftDt!=rightDt)
throw CompilerException("operands have different datatypes")
val opcode = when(operator) {
// todo variants depending on leftdt/rightdt (b/w/f)
"+" -> Opcode.ADD
@ -675,18 +719,96 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
"//" -> Opcode.FLOORDIV
"%" -> Opcode.REMAINDER
"**" -> Opcode.POW
"&" -> Opcode.BITAND
"|" -> Opcode.BITOR
"^" -> Opcode.BITXOR
"and" -> Opcode.AND
"or" -> Opcode.OR
"xor" -> Opcode.XOR
"<" -> Opcode.LESS
">" -> Opcode.GREATER
"<=" -> Opcode.LESSEQ
">=" -> Opcode.GREATEREQ
"==" -> Opcode.EQUAL
"!=" -> Opcode.NOTEQUAL
"&" -> {
when(leftDt) {
DataType.BYTE -> Opcode.BITAND
DataType.WORD -> Opcode.BITAND_W
else -> throw CompilerException("only byte/word possible")
}
}
"|" -> {
when(leftDt) {
DataType.BYTE -> Opcode.BITOR
DataType.WORD -> Opcode.BITOR_W
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")
}
stackvmProg.instr(opcode)
@ -698,8 +820,20 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
val opcode = when(operator) {
"+" -> Opcode.NOP
"-" -> 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")
}
stackvmProg.instr(opcode)
@ -844,7 +978,7 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
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
@ -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) {
"+=" -> Opcode.ADD
"-=" -> Opcode.SUB
@ -875,9 +1014,27 @@ private class StatementTranslator(private val stackvmProg: StackVmProgram,
"//=" -> Opcode.FLOORDIV
"*=" -> Opcode.MUL
"**=" -> Opcode.POW
"&=" -> Opcode.BITAND
"|=" -> Opcode.BITOR
"^=" -> Opcode.BITXOR
"&=" -> {
when(valueDt) {
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")
}
stackvmProg.instr(opcode)

View File

@ -1,13 +1,12 @@
// Generated from /home/irmen/Projects/prog8/compiler/antlr/prog8.g4 by ANTLR 4.7
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.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.misc.*;
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
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
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.misc.*;
import org.antlr.v4.runtime.tree.*;
import org.antlr.v4.runtime.atn.ATN;
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.Iterator;
import java.util.ArrayList;
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast"})
public class prog8Parser extends Parser {

View File

@ -43,34 +43,50 @@ enum class Opcode {
NEG, // todo b/w/f
// bit shifts and bitwise arithmetic
SHL, // todo b/w
SHL,
SHL_W,
SHL_MEM,
SHL_MEM_W,
SHL_VAR, // todo b/w
SHR, // todo b/w
SHL_VAR,
SHL_VAR_W,
SHR,
SHR_W,
SHR_MEM,
SHR_MEM_W,
SHR_VAR, // todo b/w
ROL, // todo b/w
SHR_VAR,
SHR_VAR_W,
ROL,
ROL_W,
ROL_MEM,
ROL_MEM_W,
ROL_VAR, // todo b/w
ROR, // todo b/w
ROL_VAR,
ROL_VAR_W,
ROR,
ROR_W,
ROR_MEM,
ROR_MEM_W,
ROR_VAR, // todo b/w
ROL2, // todo b/w
ROR_VAR,
ROR_VAR_W,
ROL2,
ROL2_W,
ROL2_MEM,
ROL2_MEM_W,
ROL2_VAR, // todo b/w
ROR2, // todo b/w
ROL2_VAR,
ROL2_VAR_W,
ROR2,
ROR2_W,
ROR2_MEM,
ROR2_MEM_W,
ROR2_VAR, // todo b/w
BITAND, // todo b/w
BITOR, // todo b/w
BITXOR, // todo b/w
INV, // todo b/w
ROR2_VAR,
ROR2_VAR_W,
BITAND,
BITAND_W,
BITOR,
BITOR_W,
BITXOR,
BITXOR_W,
INV,
INV_W,
LSB,
MSB,
@ -81,10 +97,14 @@ enum class Opcode {
W2FLOAT, // convert word into floating point
// logical operations
AND, // todo b/w (convert float to byte)
OR, // todo b/w (convert float to byte)
XOR, // todo b/w (convert float to byte)
NOT, // todo b/w (convert float to byte)
AND,
AND_W,
OR,
OR_W,
XOR,
XOR_W,
NOT,
NOT_W,
// increment, decrement
INC,
@ -101,12 +121,24 @@ enum class Opcode {
DEC_VAR_F,
// comparisons
LESS, // todo b/w/f ?
GREATER, // todo b/w/f ?
LESSEQ, // todo b/w/f ?
GREATEREQ, // todo b/w/f ?
EQUAL, // todo b/w/f ?
NOTEQUAL, // todo b/w/f ?
LESS,
LESS_W,
LESS_F,
GREATER,
GREATER_W,
GREATER_F,
LESSEQ,
LESSEQ_W,
LESSEQ_F,
GREATEREQ,
GREATEREQ_W,
GREATEREQ_F,
EQUAL,
EQUAL_W,
EQUAL_F,
NOTEQUAL,
NOTEQUAL_W,
NOTEQUAL_F,
// array access
READ_INDEXED_VAR,
@ -145,8 +177,9 @@ enum class Opcode {
val opcodesWithVarArgument = setOf(
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.ROL2_VAR, Opcode.ROR2_VAR,
Opcode.SHR_VAR, Opcode.SHR_VAR_W, Opcode.SHL_VAR, Opcode.SHL_VAR_W,
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.PUSH_VAR, Opcode.PUSH_VAR_W, Opcode.PUSH_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 -> {
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())
}
Opcode.SHR -> {
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())
}
Opcode.ROL -> {
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)
this.P_carry = newCarry
evalstack.push(result)
}
Opcode.ROL2 -> {
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())
}
Opcode.ROR -> {
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)
this.P_carry = newCarry
evalstack.push(result)
}
Opcode.ROR2 -> {
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())
}
Opcode.BITAND -> {
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))
}
Opcode.BITOR -> {
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))
}
Opcode.BITXOR -> {
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))
}
Opcode.INV -> {
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())
}
Opcode.INC -> {
@ -705,36 +798,70 @@ class StackVm(private var traceOutputFile: String?) {
}
Opcode.SHL_VAR -> {
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()
}
Opcode.SHR_VAR -> {
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()
}
Opcode.ROL_VAR -> {
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)
variables[ins.callLabel!!] = newValue
P_carry = newCarry
}
Opcode.ROR_VAR -> {
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)
variables[ins.callLabel!!] = newValue
P_carry = newCarry
}
Opcode.ROL2_VAR -> {
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()
}
Opcode.ROR2_VAR -> {
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()
}
Opcode.INC_VAR -> {
@ -779,52 +906,156 @@ class StackVm(private var traceOutputFile: String?) {
}
Opcode.AND -> {
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))
}
Opcode.OR -> {
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))
}
Opcode.XOR -> {
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))
}
Opcode.NOT -> {
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())
}
Opcode.LESS -> {
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))
}
Opcode.GREATER -> {
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))
}
Opcode.LESSEQ -> {
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))
}
Opcode.GREATEREQ -> {
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))
}
Opcode.EQUAL -> {
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))
}
Opcode.NOTEQUAL -> {
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))
}
Opcode.B2WORD -> {

View File

@ -17,21 +17,27 @@ import kotlin.test.*
SHL_MEM,
SHL_MEM_W,
SHL_VAR,
SHL_VAR_W,
SHR_MEM,
SHR_MEM_W,
SHR_VAR,
SHR_VAR_W,
ROL_MEM,
ROL_MEM_W,
ROL_VAR,
ROL_VAR_W,
ROR_MEM,
ROR_MEM_W,
ROR_VAR,
ROR_VAR_W,
ROL2_MEM,
ROL2_MEM_W,
ROL2_VAR,
ROL2_VAR_W,
ROR2_MEM,
ROR2_MEM_W,
ROR2_VAR,
ROR2_VAR_W
**/
@ -306,19 +312,19 @@ class TestStackVmOpcodes {
@Test
fun testBitand() {
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
fun testBitor() {
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
fun testBitxor() {
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
@ -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, 0), 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, 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.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))
testBinaryOperator(Value(DataType.WORD, 200), Opcode.AND_W, Value(DataType.WORD, 13455), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.WORD, 200), Opcode.AND_W, Value(DataType.WORD, 0), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.WORD, 0), Opcode.AND_W, Value(DataType.WORD, 101), Value(DataType.BYTE, 0))
}
@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, 0), Value(DataType.BYTE, 1))
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, 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.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))
testBinaryOperator(Value(DataType.WORD, 200), Opcode.OR_W, Value(DataType.WORD, 13455), 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_W, Value(DataType.WORD, 0), Value(DataType.BYTE, 0))
}
@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, 0), Value(DataType.BYTE, 1))
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, 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.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))
testBinaryOperator(Value(DataType.WORD, 200), Opcode.XOR_W, Value(DataType.WORD, 13455), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.WORD, 200), Opcode.XOR_W, Value(DataType.WORD, 0), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.WORD, 0), Opcode.XOR_W, Value(DataType.WORD, 0), Value(DataType.BYTE, 0))
}
@Test
fun testNot() {
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.WORD, 0), Opcode.NOT, Value(DataType.BYTE, 1))
testUnaryOperator(Value(DataType.WORD, 5000), Opcode.NOT, 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))
testUnaryOperator(Value(DataType.WORD, 0), Opcode.NOT_W, Value(DataType.BYTE, 1))
testUnaryOperator(Value(DataType.WORD, 5000), Opcode.NOT_W, Value(DataType.BYTE, 0))
}
@Test
@ -406,7 +395,7 @@ class TestStackVmOpcodes {
@Test
fun testInv() {
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
@ -586,182 +575,74 @@ class TestStackVmOpcodes {
@Test
fun testLess() {
val values = listOf(
Value(DataType.BYTE, 0),
Value(DataType.BYTE, 1), // 1
Value(DataType.BYTE, 1),
Value(DataType.BYTE, 1), // 0
Value(DataType.BYTE, 2),
Value(DataType.WORD, 20), // 1
Value(DataType.WORD, 20),
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
}
testBinaryOperator(Value(DataType.BYTE, 0), Opcode.LESS, Value(DataType.BYTE, 1), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.BYTE, 1), Opcode.LESS, Value(DataType.BYTE, 1), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.WORD, 2), Opcode.LESS_W, Value(DataType.WORD, 20), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.WORD, 20), Opcode.LESS_W, Value(DataType.WORD, 21), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.WORD, 21), Opcode.LESS_W, Value(DataType.WORD, 21), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.WORD, 21), Opcode.LESS_W, Value(DataType.WORD, 21), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.LESS_F, Value(DataType.FLOAT, 21.0), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.LESS_F, Value(DataType.FLOAT, 21.001), Value(DataType.BYTE, 1))
}
@Test
fun testLessEq() {
val values = listOf(
Value(DataType.BYTE, 0),
Value(DataType.BYTE, 1), // 1
Value(DataType.BYTE, 1),
Value(DataType.BYTE, 1), // 1
Value(DataType.BYTE, 21),
Value(DataType.WORD, 20), // 0
Value(DataType.WORD, 20),
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
}
testBinaryOperator(Value(DataType.BYTE, 0), Opcode.LESSEQ, Value(DataType.BYTE, 1), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.BYTE, 1), Opcode.LESSEQ, Value(DataType.BYTE, 1), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.WORD, 2), Opcode.LESSEQ_W, Value(DataType.WORD, 20), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.WORD, 20), Opcode.LESSEQ_W, Value(DataType.WORD, 21), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.WORD, 21), Opcode.LESSEQ_W, Value(DataType.WORD, 21), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.WORD, 21), Opcode.LESSEQ_W, Value(DataType.WORD, 20), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.LESSEQ_F, Value(DataType.FLOAT, 21.0), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.LESSEQ_F, Value(DataType.FLOAT, 20.999), Value(DataType.BYTE, 0))
}
@Test
fun testGreater() {
val values = listOf(
Value(DataType.BYTE, 0),
Value(DataType.BYTE, 1), // 0
Value(DataType.BYTE, 1),
Value(DataType.BYTE, 1), // 0
Value(DataType.BYTE, 20),
Value(DataType.WORD, 2), // 1
Value(DataType.WORD, 20),
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
}
testBinaryOperator(Value(DataType.BYTE, 0), Opcode.GREATER, Value(DataType.BYTE, 1), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.BYTE, 1), Opcode.GREATER, Value(DataType.BYTE, 1), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.WORD, 2), Opcode.GREATER_W, Value(DataType.WORD, 20), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.WORD, 20), Opcode.GREATER_W, Value(DataType.WORD, 21), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.WORD, 21), Opcode.GREATER_W, Value(DataType.WORD, 20), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.WORD, 21), Opcode.GREATER_W, Value(DataType.WORD, 21), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.GREATER_F, Value(DataType.FLOAT, 21.0), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.GREATER_F, Value(DataType.FLOAT, 20.999), Value(DataType.BYTE, 1))
}
@Test
fun testGreaterEq() {
val values = listOf(
Value(DataType.BYTE, 0),
Value(DataType.BYTE, 1), // 0
Value(DataType.BYTE, 1),
Value(DataType.BYTE, 1), // 1
Value(DataType.BYTE, 21),
Value(DataType.WORD, 20), // 1
Value(DataType.WORD, 20),
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
}
testBinaryOperator(Value(DataType.BYTE, 0), Opcode.GREATEREQ, Value(DataType.BYTE, 1), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.BYTE, 1), Opcode.GREATEREQ, Value(DataType.BYTE, 1), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.WORD, 2), Opcode.GREATEREQ_W, Value(DataType.WORD, 20), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.WORD, 20), Opcode.GREATEREQ_W, Value(DataType.WORD, 21), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.WORD, 21), Opcode.GREATEREQ_W, Value(DataType.WORD, 20), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.WORD, 21), Opcode.GREATEREQ_W, Value(DataType.WORD, 21), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.GREATEREQ_F, Value(DataType.FLOAT, 21.0), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.GREATEREQ_F, Value(DataType.FLOAT, 21.001), Value(DataType.BYTE, 0))
}
@Test
fun testEqual() {
val values = listOf(
Value(DataType.BYTE, 0),
Value(DataType.BYTE, 1), // 0
Value(DataType.BYTE, 1),
Value(DataType.BYTE, 1), // 1
Value(DataType.BYTE, 21),
Value(DataType.WORD, 20), // 0
Value(DataType.WORD, 20),
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)
testBinaryOperator(Value(DataType.BYTE, 0), Opcode.EQUAL, Value(DataType.BYTE, 1), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.BYTE, 1), Opcode.EQUAL, Value(DataType.BYTE, 1), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.WORD, 2), Opcode.EQUAL_W, Value(DataType.WORD, 20), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.WORD, 20), Opcode.EQUAL_W, Value(DataType.WORD, 21), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.WORD, 21), Opcode.EQUAL_W, Value(DataType.WORD, 20), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.WORD, 21), Opcode.EQUAL_W, Value(DataType.WORD, 21), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.EQUAL_F, Value(DataType.FLOAT, 21.0), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.EQUAL_F, Value(DataType.FLOAT, 21.001), Value(DataType.BYTE, 0))
}
@Test
fun testNotEqual() {
val values = listOf(
Value(DataType.BYTE, 0),
Value(DataType.BYTE, 1), // 1
Value(DataType.BYTE, 1),
Value(DataType.BYTE, 1), // 0
Value(DataType.BYTE, 21),
Value(DataType.WORD, 20), // 1
Value(DataType.WORD, 20),
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)
testBinaryOperator(Value(DataType.BYTE, 0), Opcode.NOTEQUAL, Value(DataType.BYTE, 1), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.BYTE, 1), Opcode.NOTEQUAL, Value(DataType.BYTE, 1), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.WORD, 2), Opcode.NOTEQUAL_W, Value(DataType.WORD, 20), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.WORD, 20), Opcode.NOTEQUAL_W, Value(DataType.WORD, 21), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.WORD, 21), Opcode.NOTEQUAL_W, Value(DataType.WORD, 20), Value(DataType.BYTE, 1))
testBinaryOperator(Value(DataType.WORD, 21), Opcode.NOTEQUAL_W, Value(DataType.WORD, 21), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.NOTEQUAL_F, Value(DataType.FLOAT, 21.0), Value(DataType.BYTE, 0))
testBinaryOperator(Value(DataType.FLOAT, 21.0), Opcode.NOTEQUAL_F, Value(DataType.FLOAT, 21.001), Value(DataType.BYTE, 1))
}
@Test
@ -964,11 +845,11 @@ class TestStackVmOpcodes {
Instruction(Opcode.SHR), // 0
Instruction(Opcode.SHR), // 0
Instruction(Opcode.DISCARD),
Instruction(Opcode.SHR), // 30502
Instruction(Opcode.SHR_W), // 30502
Instruction(Opcode.DISCARD_W),
Instruction(Opcode.SHR), // 1
Instruction(Opcode.SHR), // 0
Instruction(Opcode.SHR), // 0
Instruction(Opcode.SHR_W), // 1
Instruction(Opcode.SHR_W), // 0
Instruction(Opcode.SHR_W), // 0
Instruction(Opcode.DISCARD_W),
Instruction(Opcode.SHR) // error on float
)
@ -1004,11 +885,11 @@ class TestStackVmOpcodes {
Instruction(Opcode.DISCARD),
Instruction(Opcode.SHL), // 6
Instruction(Opcode.DISCARD),
Instruction(Opcode.SHL), // 56474
Instruction(Opcode.SHL_W), // 56474
Instruction(Opcode.DISCARD_W),
Instruction(Opcode.SHL), // 6
Instruction(Opcode.SHL_W), // 6
Instruction(Opcode.DISCARD_W),
Instruction(Opcode.SHL) // error on float
Instruction(Opcode.SHL_W) // error on float
)
vm.load(makeProg(ins), null)
vm.step(6)
@ -1061,23 +942,23 @@ class TestStackVmOpcodes {
val ins2 = mutableListOf(
Instruction(Opcode.CLC),
Instruction(Opcode.PUSH_W, Value(DataType.WORD, 0b1001001100001101)),
Instruction(Opcode.ROR), // 0b0100100110000110 c=1
Instruction(Opcode.ROR), // 0b1010010011000011 c=0
Instruction(Opcode.ROR),
Instruction(Opcode.ROR),
Instruction(Opcode.ROR),
Instruction(Opcode.ROR),
Instruction(Opcode.ROR),
Instruction(Opcode.ROR),
Instruction(Opcode.ROR),
Instruction(Opcode.ROR),
Instruction(Opcode.ROR),
Instruction(Opcode.ROR),
Instruction(Opcode.ROR),
Instruction(Opcode.ROR),
Instruction(Opcode.ROR),
Instruction(Opcode.ROR),
Instruction(Opcode.ROR) // 0b1001001100001101 c=0 (original value after 17 rors)
Instruction(Opcode.ROR_W), // 0b0100100110000110 c=1
Instruction(Opcode.ROR_W), // 0b1010010011000011 c=0
Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR_W),
Instruction(Opcode.ROR_W) // 0b1001001100001101 c=0 (original value after 17 rors)
)
vm.load(makeProg(ins2), null)
vm.step(3)
@ -1126,23 +1007,23 @@ class TestStackVmOpcodes {
val ins2 = mutableListOf(
Instruction(Opcode.CLC),
Instruction(Opcode.PUSH_W, Value(DataType.WORD, 0b1001001100001101)),
Instruction(Opcode.ROL), // 0b0010011000011010 c=1
Instruction(Opcode.ROL), // 0b0100110000110101 c=0
Instruction(Opcode.ROL),
Instruction(Opcode.ROL),
Instruction(Opcode.ROL),
Instruction(Opcode.ROL),
Instruction(Opcode.ROL),
Instruction(Opcode.ROL),
Instruction(Opcode.ROL),
Instruction(Opcode.ROL),
Instruction(Opcode.ROL),
Instruction(Opcode.ROL),
Instruction(Opcode.ROL),
Instruction(Opcode.ROL),
Instruction(Opcode.ROL),
Instruction(Opcode.ROL),
Instruction(Opcode.ROL) // 0b1001001100001101 c=0 (original value after 17 rors)
Instruction(Opcode.ROL_W), // 0b0010011000011010 c=1
Instruction(Opcode.ROL_W), // 0b0100110000110101 c=0
Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL_W),
Instruction(Opcode.ROL_W) // 0b1001001100001101 c=0 (original value after 17 rors)
)
vm.load(makeProg(ins2), null)
vm.step(3)
@ -1183,22 +1064,22 @@ class TestStackVmOpcodes {
val ins2 = mutableListOf(
Instruction(Opcode.PUSH_W, Value(DataType.WORD, 0b1001001100001101)),
Instruction(Opcode.ROR2), // 0b1100100110000110
Instruction(Opcode.ROR2), // 0b0110010011000011
Instruction(Opcode.ROR2),
Instruction(Opcode.ROR2),
Instruction(Opcode.ROR2),
Instruction(Opcode.ROR2),
Instruction(Opcode.ROR2),
Instruction(Opcode.ROR2),
Instruction(Opcode.ROR2),
Instruction(Opcode.ROR2),
Instruction(Opcode.ROR2),
Instruction(Opcode.ROR2),
Instruction(Opcode.ROR2),
Instruction(Opcode.ROR2),
Instruction(Opcode.ROR2),
Instruction(Opcode.ROR2) // 0b1001001100001101 (original value after 16 rors)
Instruction(Opcode.ROR2_W), // 0b1100100110000110
Instruction(Opcode.ROR2_W), // 0b0110010011000011
Instruction(Opcode.ROR2_W),
Instruction(Opcode.ROR2_W),
Instruction(Opcode.ROR2_W),
Instruction(Opcode.ROR2_W),
Instruction(Opcode.ROR2_W),
Instruction(Opcode.ROR2_W),
Instruction(Opcode.ROR2_W),
Instruction(Opcode.ROR2_W),
Instruction(Opcode.ROR2_W),
Instruction(Opcode.ROR2_W),
Instruction(Opcode.ROR2_W),
Instruction(Opcode.ROR2_W),
Instruction(Opcode.ROR2_W),
Instruction(Opcode.ROR2_W) // 0b1001001100001101 (original value after 16 rors)
)
vm.load(makeProg(ins2), null)
vm.step(2)
@ -1235,22 +1116,22 @@ class TestStackVmOpcodes {
val ins2 = mutableListOf(
Instruction(Opcode.PUSH_W, Value(DataType.WORD, 0b1001001100001101)),
Instruction(Opcode.ROL2), // 0b0010011000011011
Instruction(Opcode.ROL2), // 0b0100110000110110
Instruction(Opcode.ROL2),
Instruction(Opcode.ROL2),
Instruction(Opcode.ROL2),
Instruction(Opcode.ROL2),
Instruction(Opcode.ROL2),
Instruction(Opcode.ROL2),
Instruction(Opcode.ROL2),
Instruction(Opcode.ROL2),
Instruction(Opcode.ROL2),
Instruction(Opcode.ROL2),
Instruction(Opcode.ROL2),
Instruction(Opcode.ROL2),
Instruction(Opcode.ROL2),
Instruction(Opcode.ROL2) // 0b1001001100001101 (original value after 16 rols)
Instruction(Opcode.ROL2_W), // 0b0010011000011011
Instruction(Opcode.ROL2_W), // 0b0100110000110110
Instruction(Opcode.ROL2_W),
Instruction(Opcode.ROL2_W),
Instruction(Opcode.ROL2_W),
Instruction(Opcode.ROL2_W),
Instruction(Opcode.ROL2_W),
Instruction(Opcode.ROL2_W),
Instruction(Opcode.ROL2_W),
Instruction(Opcode.ROL2_W),
Instruction(Opcode.ROL2_W),
Instruction(Opcode.ROL2_W),
Instruction(Opcode.ROL2_W),
Instruction(Opcode.ROL2_W),
Instruction(Opcode.ROL2_W),
Instruction(Opcode.ROL2_W) // 0b1001001100001101 (original value after 16 rols)
)
vm.load(makeProg(ins2), null)
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) {
val program=makeProg(mutableListOf(
Instruction(pushOpcode(left.type), left),