mirror of
https://github.com/irmen/prog8.git
synced 2024-09-07 19:54:26 +00:00
made a lot more opcodes type-specific
This commit is contained in:
parent
42e4891fcf
commit
e8ba21d3ba
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 -> {
|
||||
|
@ -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),
|
||||
|
Loading…
Reference in New Issue
Block a user