mirror of
https://github.com/irmen/prog8.git
synced 2024-12-23 09:32:43 +00:00
vm instructions now contain info on input/output registers
This commit is contained in:
parent
1e441c2ddf
commit
e560e2ab3f
@ -68,7 +68,7 @@ class CodeGen(internal val program: PtProgram,
|
||||
}
|
||||
|
||||
if(options.optimize) {
|
||||
val optimizer = VmPeepholeOptimizer(vmprog, allocations)
|
||||
val optimizer = VmPeepholeOptimizer(vmprog)
|
||||
optimizer.optimize()
|
||||
}
|
||||
|
||||
|
@ -4,10 +4,8 @@ import prog8.vm.Instruction
|
||||
import prog8.vm.Opcode
|
||||
import prog8.vm.VmDataType
|
||||
|
||||
internal class VmOptimizerException(msg: String): Exception(msg)
|
||||
|
||||
|
||||
class VmPeepholeOptimizer(private val vmprog: AssemblyProgram, private val allocations: VariableAllocator) {
|
||||
class VmPeepholeOptimizer(private val vmprog: AssemblyProgram) {
|
||||
fun optimize() {
|
||||
vmprog.getBlocks().forEach { block ->
|
||||
do {
|
||||
|
@ -26,19 +26,19 @@ class TestVmPeepholeOpt: FunSpec({
|
||||
fun AssemblyProgram.lines(): List<VmCodeLine> = this.getBlocks().flatMap { it.lines }
|
||||
|
||||
test("remove nops") {
|
||||
val(asm, allocations) = makeVmProgram(listOf(
|
||||
val(asm, _) = makeVmProgram(listOf(
|
||||
VmCodeInstruction(Opcode.JUMP, labelSymbol = listOf("dummy")),
|
||||
VmCodeInstruction(Opcode.NOP),
|
||||
VmCodeInstruction(Opcode.NOP)
|
||||
))
|
||||
asm.lines().size shouldBe 3
|
||||
val opt = VmPeepholeOptimizer(asm, allocations)
|
||||
val opt = VmPeepholeOptimizer(asm)
|
||||
opt.optimize()
|
||||
asm.lines().size shouldBe 1
|
||||
}
|
||||
|
||||
test("remove jmp to label below") {
|
||||
val(asm, allocations) = makeVmProgram(listOf(
|
||||
val(asm, _) = makeVmProgram(listOf(
|
||||
VmCodeInstruction(Opcode.JUMP, labelSymbol = listOf("label")), // removed
|
||||
VmCodeLabel(listOf("label")),
|
||||
VmCodeInstruction(Opcode.JUMP, labelSymbol = listOf("label2")), // removed
|
||||
@ -49,7 +49,7 @@ class TestVmPeepholeOpt: FunSpec({
|
||||
VmCodeLabel(listOf("label3"))
|
||||
))
|
||||
asm.lines().size shouldBe 8
|
||||
val opt = VmPeepholeOptimizer(asm, allocations)
|
||||
val opt = VmPeepholeOptimizer(asm)
|
||||
opt.optimize()
|
||||
val lines = asm.lines()
|
||||
lines.size shouldBe 5
|
||||
@ -61,7 +61,7 @@ class TestVmPeepholeOpt: FunSpec({
|
||||
}
|
||||
|
||||
test("remove double sec/clc") {
|
||||
val(asm, allocations) = makeVmProgram(listOf(
|
||||
val(asm, _) = makeVmProgram(listOf(
|
||||
VmCodeInstruction(Opcode.SEC),
|
||||
VmCodeInstruction(Opcode.SEC),
|
||||
VmCodeInstruction(Opcode.SEC),
|
||||
@ -70,7 +70,7 @@ class TestVmPeepholeOpt: FunSpec({
|
||||
VmCodeInstruction(Opcode.CLC)
|
||||
))
|
||||
asm.lines().size shouldBe 6
|
||||
val opt = VmPeepholeOptimizer(asm, allocations)
|
||||
val opt = VmPeepholeOptimizer(asm)
|
||||
opt.optimize()
|
||||
val lines = asm.lines()
|
||||
lines.size shouldBe 1
|
||||
@ -78,14 +78,14 @@ class TestVmPeepholeOpt: FunSpec({
|
||||
}
|
||||
|
||||
test("push followed by pop") {
|
||||
val(asm, allocations) = makeVmProgram(listOf(
|
||||
val(asm, _) = makeVmProgram(listOf(
|
||||
VmCodeInstruction(Opcode.PUSH, VmDataType.BYTE, reg1=42),
|
||||
VmCodeInstruction(Opcode.POP, VmDataType.BYTE, reg1=42),
|
||||
VmCodeInstruction(Opcode.PUSH, VmDataType.BYTE, reg1=99),
|
||||
VmCodeInstruction(Opcode.POP, VmDataType.BYTE, reg1=222)
|
||||
))
|
||||
asm.lines().size shouldBe 4
|
||||
val opt = VmPeepholeOptimizer(asm, allocations)
|
||||
val opt = VmPeepholeOptimizer(asm)
|
||||
opt.optimize()
|
||||
val lines = asm.lines()
|
||||
lines.size shouldBe 1
|
||||
@ -95,7 +95,7 @@ class TestVmPeepholeOpt: FunSpec({
|
||||
}
|
||||
|
||||
test("remove useless div/mul, add/sub") {
|
||||
val(asm, allocations) = makeVmProgram(listOf(
|
||||
val(asm, _) = makeVmProgram(listOf(
|
||||
VmCodeInstruction(Opcode.DIV, VmDataType.BYTE, reg1=42, value = 1),
|
||||
VmCodeInstruction(Opcode.DIVS, VmDataType.BYTE, reg1=42, value = 1),
|
||||
VmCodeInstruction(Opcode.MUL, VmDataType.BYTE, reg1=42, value = 1),
|
||||
@ -108,19 +108,19 @@ class TestVmPeepholeOpt: FunSpec({
|
||||
VmCodeInstruction(Opcode.SUB, VmDataType.BYTE, reg1=42, value = 0)
|
||||
))
|
||||
asm.lines().size shouldBe 10
|
||||
val opt = VmPeepholeOptimizer(asm, allocations)
|
||||
val opt = VmPeepholeOptimizer(asm)
|
||||
opt.optimize()
|
||||
val lines = asm.lines()
|
||||
lines.size shouldBe 4
|
||||
}
|
||||
|
||||
test("replace add/sub 1 by inc/dec") {
|
||||
val(asm, allocations) = makeVmProgram(listOf(
|
||||
val(asm, _) = makeVmProgram(listOf(
|
||||
VmCodeInstruction(Opcode.ADD, VmDataType.BYTE, reg1=42, value = 1),
|
||||
VmCodeInstruction(Opcode.SUB, VmDataType.BYTE, reg1=42, value = 1)
|
||||
))
|
||||
asm.lines().size shouldBe 2
|
||||
val opt = VmPeepholeOptimizer(asm, allocations)
|
||||
val opt = VmPeepholeOptimizer(asm)
|
||||
opt.optimize()
|
||||
val lines = asm.lines()
|
||||
lines.size shouldBe 2
|
||||
@ -129,7 +129,7 @@ class TestVmPeepholeOpt: FunSpec({
|
||||
}
|
||||
|
||||
test("remove useless and/or/xor") {
|
||||
val(asm, allocations) = makeVmProgram(listOf(
|
||||
val(asm, _) = makeVmProgram(listOf(
|
||||
VmCodeInstruction(Opcode.AND, VmDataType.BYTE, reg1=42, value = 255),
|
||||
VmCodeInstruction(Opcode.AND, VmDataType.WORD, reg1=42, value = 65535),
|
||||
VmCodeInstruction(Opcode.OR, VmDataType.BYTE, reg1=42, value = 0),
|
||||
@ -140,21 +140,21 @@ class TestVmPeepholeOpt: FunSpec({
|
||||
VmCodeInstruction(Opcode.XOR, VmDataType.BYTE, reg1=42, value = 1)
|
||||
))
|
||||
asm.lines().size shouldBe 8
|
||||
val opt = VmPeepholeOptimizer(asm, allocations)
|
||||
val opt = VmPeepholeOptimizer(asm)
|
||||
opt.optimize()
|
||||
val lines = asm.lines()
|
||||
lines.size shouldBe 4
|
||||
}
|
||||
|
||||
test("replace and/or/xor by constant number") {
|
||||
val(asm, allocations) = makeVmProgram(listOf(
|
||||
val(asm, _) = makeVmProgram(listOf(
|
||||
VmCodeInstruction(Opcode.AND, VmDataType.BYTE, reg1=42, value = 0),
|
||||
VmCodeInstruction(Opcode.AND, VmDataType.WORD, reg1=42, value = 0),
|
||||
VmCodeInstruction(Opcode.OR, VmDataType.BYTE, reg1=42, value = 255),
|
||||
VmCodeInstruction(Opcode.OR, VmDataType.WORD, reg1=42, value = 65535)
|
||||
))
|
||||
asm.lines().size shouldBe 4
|
||||
val opt = VmPeepholeOptimizer(asm, allocations)
|
||||
val opt = VmPeepholeOptimizer(asm)
|
||||
opt.optimize()
|
||||
val lines = asm.lines()
|
||||
lines.size shouldBe 4
|
||||
|
@ -84,7 +84,7 @@ sub log2(float value) -> float {
|
||||
sub sqrt(float value) -> float {
|
||||
%asm {{
|
||||
loadm.f fr0,{floats.sqrt.value}
|
||||
fsqrt.f fr0,fr0
|
||||
sqrt.f fr0,fr0
|
||||
return
|
||||
}}
|
||||
}
|
||||
|
@ -16,7 +16,6 @@ Need help with
|
||||
Future Things and Ideas
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Compiler:
|
||||
- vm Instructions needs to know what the read-registers/memory are, and what the write-register/memory is. This info is needed for more advanced optimizations and later code generation steps.
|
||||
- vm: implement remaining sin/cos functions in math.p8
|
||||
- vm: find a solution for the cx16.r0..r15 that "overlap" (r0, r0L, r0H etc) but in the vm each get their own separate variable location now
|
||||
- vm: encode romsub & romsub call in VM IR (but just crash in virtualmachine itself.) ExpressionGen.kt
|
||||
@ -29,7 +28,7 @@ Compiler:
|
||||
How is it for the vm target? -> just 2 special cases in CodeGen.
|
||||
- when the vm is stable and *if* its language can get promoted to prog8 IL, the variable allocation should be changed.
|
||||
It's now done before the vm code generation, but the IL should probably not depend on the allocations already performed.
|
||||
So the CodeGen doesn't do VariableAlloc *before* the codegen, but as a last step.
|
||||
So the CodeGen doesn't do VariableAlloc *before* the codegen, but as a last step instead.
|
||||
- generate WASM from the new ast (or from vm code?) to run prog8 on a browser canvas?
|
||||
- createAssemblyAndAssemble(): make it possible to actually get rid of the VarDecl nodes by fixing the rest of the code mentioned there.
|
||||
but probably better to rewrite the 6502 codegen on top of the new Ast.
|
||||
|
@ -208,7 +208,7 @@ class Assembler {
|
||||
if(format.fpValue)
|
||||
floatValue = value!!
|
||||
|
||||
program.add(Instruction(opcode, type, reg1, reg2, fpReg1, fpReg2, value = intValue, fpValue = floatValue))
|
||||
program.add(Instruction(opcode, type, reg1, reg2, fpReg1, fpReg2, intValue, floatValue))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,31 +128,31 @@ All have type b or w.
|
||||
|
||||
andr reg1, reg2 - reg1 = reg1 bitwise and reg2
|
||||
and reg1, value - reg1 = reg1 bitwise and value
|
||||
andm reg1 address - memory = memory bitwise and reg1
|
||||
orr reg1, reg2 - reg1 = reg1 bitwise or reg2
|
||||
or reg1, value - reg1 = reg1 bitwise or value
|
||||
orm reg1, address - memory = memory bitwise or reg1
|
||||
xorr reg1, reg2 - reg1 = reg1 bitwise xor reg2
|
||||
xor reg1, value - reg1 = reg1 bitwise xor value
|
||||
xorm reg1, address - memory = memory bitwise xor reg1
|
||||
inv reg1 - reg1 = bitwise invert of reg1 (all bits flipped)
|
||||
lsrn reg1, reg2 - reg1 = multi-shift reg1 right by reg2 bits + set Carry to shifted bit
|
||||
invm address - memory = bitwise invert of that memory (all bits flipped)
|
||||
asrn reg1, reg2 - reg1 = multi-shift reg1 right by reg2 bits (signed) + set Carry to shifted bit
|
||||
lsrn reg1, reg2 - reg1 = multi-shift reg1 right by reg2 bits + set Carry to shifted bit
|
||||
lsln reg1, reg2 - reg1 = multi-shift reg1 left by reg2 bits + set Carry to shifted bit
|
||||
lsr reg1 - shift reg1 right by 1 bits + set Carry to shifted bit
|
||||
asrnm reg1, address - multi-shift memory right by reg1 bits (signed) + set Carry to shifted bit
|
||||
lsrnm reg1, address - multi-shift memoryright by reg1 bits + set Carry to shifted bit
|
||||
lslnm reg1, address - multi-shift memory left by reg1 bits + set Carry to shifted bit
|
||||
asr reg1 - shift reg1 right by 1 bits (signed) + set Carry to shifted bit
|
||||
lsr reg1 - shift reg1 right by 1 bits + set Carry to shifted bit
|
||||
lsl reg1 - shift reg1 left by 1 bits + set Carry to shifted bit
|
||||
lsrm address - shift memory right by 1 bits + set Carry to shifted bit
|
||||
asrm address - shift memory right by 1 bits (signed) + set Carry to shifted bit
|
||||
lslm address - shift memory left by 1 bits + set Carry to shifted bit
|
||||
ror reg1 - rotate reg1 right by 1 bits, not using carry + set Carry to shifted bit
|
||||
roxr reg1 - rotate reg1 right by 1 bits, using carry + set Carry to shifted bit
|
||||
rol reg1 - rotate reg1 left by 1 bits, not using carry + set Carry to shifted bit
|
||||
roxl reg1 - rotate reg1 left by 1 bits, using carry, + set Carry to shifted bit
|
||||
andm reg1 address - memory = memory bitwise and reg1
|
||||
orm reg1, address - memory = memory bitwise or reg1
|
||||
xorm reg1, address - memory = memory bitwise xor reg1
|
||||
invm address - memory = bitwise invert of that memory (all bits flipped)
|
||||
lsrnm reg1, address - multi-shift memoryright by reg1 bits + set Carry to shifted bit
|
||||
asrnm reg1, address - multi-shift memory right by reg1 bits (signed) + set Carry to shifted bit
|
||||
lslnm reg1, address - multi-shift memory left by reg1 bits + set Carry to shifted bit
|
||||
lsrm address - shift memory right by 1 bits + set Carry to shifted bit
|
||||
asrm address - shift memory right by 1 bits (signed) + set Carry to shifted bit
|
||||
lslm address - shift memory left by 1 bits + set Carry to shifted bit
|
||||
rorm address - rotate memory right by 1 bits, not using carry + set Carry to shifted bit
|
||||
roxrm address - rotate memory right by 1 bits, using carry + set Carry to shifted bit
|
||||
rolm address - rotate memory left by 1 bits, not using carry + set Carry to shifted bit
|
||||
@ -172,6 +172,15 @@ ftosw reg1, fpreg1 - reg1 = fpreg1 as signed word
|
||||
fpow fpreg1, fpreg2 - fpreg1 = fpreg1 to the power of fpreg2
|
||||
fabs fpreg1, fpreg2 - fpreg1 = abs(fpreg2)
|
||||
fcomp reg1, fpreg1, fpreg2 - reg1 = result of comparison of fpreg1 and fpreg2: 0=equal, 1=fpreg1 is greater, -1=fpreg1 is smaller
|
||||
fsin fpreg1, fpreg2 - fpreg1 = sin(fpreg2)
|
||||
fcos fpreg1, fpreg2 - fpreg1 = cos(fpreg2)
|
||||
ftan fpreg1, fpreg2 - fpreg1 = tan(fpreg2)
|
||||
fatan fpreg1, fpreg2 - fpreg1 = atan(fpreg2)
|
||||
fln fpreg1, fpreg2 - fpreg1 = ln(fpreg2) ; natural logarithm
|
||||
flog fpreg1, fpreg2 - fpreg1 = log(fpreg2) ; base 2 logarithm
|
||||
fround fpreg1, fpreg2 - fpreg1 = round(fpreg2)
|
||||
ffloor fpreg1, fpreg2 - fpreg1 = floor(fpreg2)
|
||||
fceil fpreg1, fpreg2 - fpreg1 = ceil(fpreg2)
|
||||
|
||||
|
||||
MISC
|
||||
@ -316,7 +325,6 @@ enum class Opcode {
|
||||
FATAN,
|
||||
FLN,
|
||||
FLOG,
|
||||
FSQRT,
|
||||
FROUND,
|
||||
FFLOOR,
|
||||
FCEIL,
|
||||
@ -382,6 +390,11 @@ data class Instruction(
|
||||
val fpValue: Float?=null,
|
||||
val labelSymbol: List<String>?=null // symbolic label name as alternative to value (so only for Branch/jump/call Instructions!)
|
||||
) {
|
||||
// reg1 and fpreg1 can be IN/OUT/INOUT (all others are readonly INPUT)
|
||||
// This knowledge is useful in IL assembly optimizers to see how registers are used.
|
||||
val reg1direction: OperandDirection
|
||||
val fpReg1direction: OperandDirection
|
||||
|
||||
init {
|
||||
val formats = instructionFormats.getValue(opcode)
|
||||
if(type==null && !formats.containsKey(null))
|
||||
@ -410,6 +423,9 @@ data class Instruction(
|
||||
throw IllegalArgumentException("$opcode: integer point instruction can't use floating point registers")
|
||||
}
|
||||
|
||||
reg1direction = format.reg1direction
|
||||
fpReg1direction = format.fpReg1direction
|
||||
|
||||
if(opcode in setOf(Opcode.BEQ, Opcode.BNE, Opcode.BLT, Opcode.BLTS,
|
||||
Opcode.BGT, Opcode.BGTS, Opcode.BLE, Opcode.BLES,
|
||||
Opcode.BGE, Opcode.BGES,
|
||||
@ -464,184 +480,203 @@ data class Instruction(
|
||||
}
|
||||
}
|
||||
|
||||
enum class OperandDirection {
|
||||
INPUT,
|
||||
OUTPUT,
|
||||
INOUT
|
||||
}
|
||||
|
||||
data class InstructionFormat(val datatype: VmDataType?,
|
||||
val reg1: Boolean, val reg2: Boolean,
|
||||
val fpReg1: Boolean, val fpReg2: Boolean,
|
||||
val value: Boolean,
|
||||
val fpValue: Boolean) {
|
||||
val reg1: Boolean, val reg1direction: OperandDirection, // reg1 can be IN/OUT/INOUT
|
||||
val reg2: Boolean, // always only IN
|
||||
val fpReg1: Boolean, val fpReg1direction: OperandDirection, // fpreg1 can be IN/OUT/INOUT
|
||||
val fpReg2: Boolean, // always only IN
|
||||
val value: Boolean, // always only IN
|
||||
val fpValue: Boolean // always only IN
|
||||
) {
|
||||
companion object {
|
||||
fun from(spec: String): Map<VmDataType?, InstructionFormat> {
|
||||
val result = mutableMapOf<VmDataType?, InstructionFormat>()
|
||||
for(part in spec.split('|').map{ it.trim() }) {
|
||||
var reg1 = false
|
||||
var reg2 = false
|
||||
var fpreg1 = false
|
||||
var fpreg2 = false
|
||||
var value = false
|
||||
var fpvalue = false
|
||||
var reg1 = false // read/write/modify possible
|
||||
var reg1Direction = OperandDirection.INPUT
|
||||
var reg2 = false // strictly read-only
|
||||
var fpreg1 = false // read/write/modify possible
|
||||
var fpreg1Direction = OperandDirection.INPUT
|
||||
var fpreg2 = false // strictly read-only
|
||||
var value = false // strictly read-only
|
||||
var fpvalue = false // strictly read-only
|
||||
val splits = part.splitToSequence(',').iterator()
|
||||
val typespec = splits.next()
|
||||
while(splits.hasNext()) {
|
||||
when(splits.next()) {
|
||||
"r1" -> reg1=true
|
||||
"r2" -> reg2=true
|
||||
"fr1" -> fpreg1=true
|
||||
"fr2" -> fpreg2=true
|
||||
"v" -> value = true
|
||||
"fv" -> fpvalue = true
|
||||
"<r1" -> { reg1=true; reg1Direction=OperandDirection.INPUT }
|
||||
">r1" -> { reg1=true; reg1Direction=OperandDirection.OUTPUT }
|
||||
"<>r1" -> { reg1=true; reg1Direction=OperandDirection.INOUT }
|
||||
"<r2" -> reg2 = true
|
||||
"<fr1" -> { fpreg1=true; fpreg1Direction=OperandDirection.INPUT }
|
||||
">fr1" -> { fpreg1=true; fpreg1Direction=OperandDirection.OUTPUT }
|
||||
"<>fr1" -> { fpreg1=true; fpreg1Direction=OperandDirection.INOUT }
|
||||
"<fr2" -> fpreg2=true
|
||||
"<v" -> value = true
|
||||
"<fv" -> fpvalue = true
|
||||
else -> throw IllegalArgumentException(spec)
|
||||
}
|
||||
}
|
||||
if(typespec=="N")
|
||||
result[null] = InstructionFormat(null, reg1=reg1, reg2=reg2, fpReg1=fpreg1, fpReg2=fpreg2, value=value, fpValue=fpvalue)
|
||||
result[null] = InstructionFormat(null, reg1, reg1Direction, reg2, fpreg1, fpreg1Direction, fpreg2, value, fpvalue)
|
||||
if('B' in typespec)
|
||||
result[VmDataType.BYTE] = InstructionFormat(VmDataType.BYTE, reg1=reg1, reg2=reg2, fpReg1=fpreg1, fpReg2=fpreg2, value=value, fpValue=fpvalue)
|
||||
result[VmDataType.BYTE] = InstructionFormat(VmDataType.BYTE, reg1, reg1Direction, reg2, fpreg1, fpreg1Direction, fpreg2, value, fpvalue)
|
||||
if('W' in typespec)
|
||||
result[VmDataType.WORD] = InstructionFormat(VmDataType.WORD, reg1=reg1, reg2=reg2, fpReg1=fpreg1, fpReg2=fpreg2, value=value, fpValue=fpvalue)
|
||||
result[VmDataType.WORD] = InstructionFormat(VmDataType.WORD, reg1, reg1Direction, reg2, fpreg1, fpreg1Direction, fpreg2, value, fpvalue)
|
||||
if('F' in typespec)
|
||||
result[VmDataType.FLOAT] = InstructionFormat(VmDataType.FLOAT, reg1=reg1, reg2=reg2, fpReg1=fpreg1, fpReg2=fpreg2, value=value, fpValue=fpvalue)
|
||||
result[VmDataType.FLOAT] = InstructionFormat(VmDataType.FLOAT, reg1, reg1Direction, reg2, fpreg1, fpreg1Direction, fpreg2, value, fpvalue)
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
<X = X is not modified (input/readonly value)
|
||||
>X = X is overwritten with output value (output value)
|
||||
<>X = X is modified (input + output)
|
||||
TODO: also encode if memory is read/written/modified?
|
||||
*/
|
||||
@Suppress("BooleanLiteralArgument")
|
||||
val instructionFormats = mutableMapOf(
|
||||
Opcode.NOP to InstructionFormat.from("N"),
|
||||
Opcode.LOAD to InstructionFormat.from("BW,r1,v | F,fr1,fv"),
|
||||
Opcode.LOADM to InstructionFormat.from("BW,r1,v | F,fr1,v"),
|
||||
Opcode.LOADI to InstructionFormat.from("BW,r1,r2 | F,fr1,r1"),
|
||||
Opcode.LOADX to InstructionFormat.from("BW,r1,r2,v | F,fr1,r1,v"),
|
||||
Opcode.LOADIX to InstructionFormat.from("BW,r1,r2,v | F,fr1,r1,v"),
|
||||
Opcode.LOADR to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
||||
Opcode.STOREM to InstructionFormat.from("BW,r1,v | F,fr1,v"),
|
||||
Opcode.STOREI to InstructionFormat.from("BW,r1,r2 | F,fr1,r1"),
|
||||
Opcode.STOREX to InstructionFormat.from("BW,r1,r2,v | F,fr1,r1,v"),
|
||||
Opcode.STOREIX to InstructionFormat.from("BW,r1,r2,v | F,fr1,r1,v"),
|
||||
Opcode.STOREZM to InstructionFormat.from("BW,v | F,v"),
|
||||
Opcode.STOREZI to InstructionFormat.from("BW,r1 | F,r1"),
|
||||
Opcode.STOREZX to InstructionFormat.from("BW,r1,v | F,r1,v"),
|
||||
Opcode.JUMP to InstructionFormat.from("N,v"),
|
||||
Opcode.CALL to InstructionFormat.from("N,v"),
|
||||
Opcode.SYSCALL to InstructionFormat.from("N,v"),
|
||||
Opcode.LOAD to InstructionFormat.from("BW,>r1,<v | F,>fr1,<fv"),
|
||||
Opcode.LOADM to InstructionFormat.from("BW,>r1,<v | F,>fr1,<v"),
|
||||
Opcode.LOADI to InstructionFormat.from("BW,>r1,<r2 | F,>fr1,<r1"),
|
||||
Opcode.LOADX to InstructionFormat.from("BW,>r1,<r2,<v | F,>fr1,<r1,<v"),
|
||||
Opcode.LOADIX to InstructionFormat.from("BW,>r1,<r2,<v | F,>fr1,<r1,<v"),
|
||||
Opcode.LOADR to InstructionFormat.from("BW,>r1,<r2 | F,>fr1,<fr2"),
|
||||
Opcode.STOREM to InstructionFormat.from("BW,<r1,<v | F,<fr1,<v"),
|
||||
Opcode.STOREI to InstructionFormat.from("BW,<r1,<r2 | F,<fr1,<r1"),
|
||||
Opcode.STOREX to InstructionFormat.from("BW,<r1,<r2,<v | F,<fr1,<r1,<v"),
|
||||
Opcode.STOREIX to InstructionFormat.from("BW,<r1,<r2,<v | F,<fr1,<r1,<v"),
|
||||
Opcode.STOREZM to InstructionFormat.from("BW,<v | F,<v"),
|
||||
Opcode.STOREZI to InstructionFormat.from("BW,<r1 | F,<r1"),
|
||||
Opcode.STOREZX to InstructionFormat.from("BW,<r1,<v | F,<r1,<v"),
|
||||
Opcode.JUMP to InstructionFormat.from("N,<v"),
|
||||
Opcode.CALL to InstructionFormat.from("N,<v"),
|
||||
Opcode.SYSCALL to InstructionFormat.from("N,<v"),
|
||||
Opcode.RETURN to InstructionFormat.from("N"),
|
||||
Opcode.BSTCC to InstructionFormat.from("N,v"),
|
||||
Opcode.BSTCS to InstructionFormat.from("N,v"),
|
||||
Opcode.BSTEQ to InstructionFormat.from("N,v"),
|
||||
Opcode.BSTNE to InstructionFormat.from("N,v"),
|
||||
Opcode.BSTNEG to InstructionFormat.from("N,v"),
|
||||
Opcode.BSTPOS to InstructionFormat.from("N,v"),
|
||||
Opcode.BZ to InstructionFormat.from("BW,r1,v"),
|
||||
Opcode.BNZ to InstructionFormat.from("BW,r1,v"),
|
||||
Opcode.BEQ to InstructionFormat.from("BW,r1,r2,v"),
|
||||
Opcode.BNE to InstructionFormat.from("BW,r1,r2,v"),
|
||||
Opcode.BLT to InstructionFormat.from("BW,r1,r2,v"),
|
||||
Opcode.BLTS to InstructionFormat.from("BW,r1,r2,v"),
|
||||
Opcode.BGT to InstructionFormat.from("BW,r1,r2,v"),
|
||||
Opcode.BGTS to InstructionFormat.from("BW,r1,r2,v"),
|
||||
Opcode.BLE to InstructionFormat.from("BW,r1,r2,v"),
|
||||
Opcode.BLES to InstructionFormat.from("BW,r1,r2,v"),
|
||||
Opcode.BGE to InstructionFormat.from("BW,r1,r2,v"),
|
||||
Opcode.BGES to InstructionFormat.from("BW,r1,r2,v"),
|
||||
Opcode.SEQ to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.SNE to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.SLT to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.SLTS to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.SGT to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.SGTS to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.SLE to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.SLES to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.SGE to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.SGES to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.INC to InstructionFormat.from("BW,r1"),
|
||||
Opcode.INCM to InstructionFormat.from("BW,v"),
|
||||
Opcode.DEC to InstructionFormat.from("BW,r1"),
|
||||
Opcode.DECM to InstructionFormat.from("BW,v"),
|
||||
Opcode.NEG to InstructionFormat.from("BW,r1 | F,fr1"),
|
||||
Opcode.NEGM to InstructionFormat.from("BW,v | F,v"),
|
||||
Opcode.ADDR to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
||||
Opcode.ADD to InstructionFormat.from("BW,r1,v | F,fr1,v"),
|
||||
Opcode.ADDM to InstructionFormat.from("BW,r1,v | F,fr1,v"),
|
||||
Opcode.SUBR to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
||||
Opcode.SUB to InstructionFormat.from("BW,r1,v | F,fr1,v"),
|
||||
Opcode.SUBM to InstructionFormat.from("BW,r1,v | F,fr1,v"),
|
||||
Opcode.MULR to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
||||
Opcode.MUL to InstructionFormat.from("BW,r1,v | F,fr1,v"),
|
||||
Opcode.MULM to InstructionFormat.from("BW,r1,v | F,fr1,v"),
|
||||
Opcode.DIVR to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.DIV to InstructionFormat.from("BW,r1,v"),
|
||||
Opcode.DIVM to InstructionFormat.from("BW,r1,v"),
|
||||
Opcode.DIVSR to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
||||
Opcode.DIVS to InstructionFormat.from("BW,r1,v | F,fr1,v"),
|
||||
Opcode.DIVSM to InstructionFormat.from("BW,r1,v | F,fr1,v"),
|
||||
Opcode.SQRT to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
||||
Opcode.SGN to InstructionFormat.from("BW,r1,r2 | F,fr1,fr2"),
|
||||
Opcode.RND to InstructionFormat.from("BW,r1 | F,fr1"),
|
||||
Opcode.MODR to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.MOD to InstructionFormat.from("BW,r1,v"),
|
||||
Opcode.CMP to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.EXT to InstructionFormat.from("BW,r1"),
|
||||
Opcode.EXTS to InstructionFormat.from("BW,r1"),
|
||||
Opcode.ANDR to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.AND to InstructionFormat.from("BW,r1,v"),
|
||||
Opcode.ANDM to InstructionFormat.from("BW,r1,v"),
|
||||
Opcode.ORR to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.OR to InstructionFormat.from("BW,r1,v"),
|
||||
Opcode.ORM to InstructionFormat.from("BW,r1,v"),
|
||||
Opcode.XORR to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.XOR to InstructionFormat.from("BW,r1,v"),
|
||||
Opcode.XORM to InstructionFormat.from("BW,r1,v"),
|
||||
Opcode.INV to InstructionFormat.from("BW,r1"),
|
||||
Opcode.INVM to InstructionFormat.from("BW,v"),
|
||||
Opcode.ASRN to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.ASRNM to InstructionFormat.from("BW,r1,v"),
|
||||
Opcode.LSRN to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.LSRNM to InstructionFormat.from("BW,r1,v"),
|
||||
Opcode.LSLN to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.LSLNM to InstructionFormat.from("BW,r1,v"),
|
||||
Opcode.ASR to InstructionFormat.from("BW,r1"),
|
||||
Opcode.ASRM to InstructionFormat.from("BW,v"),
|
||||
Opcode.LSR to InstructionFormat.from("BW,r1"),
|
||||
Opcode.LSRM to InstructionFormat.from("BW,v"),
|
||||
Opcode.LSL to InstructionFormat.from("BW,r1"),
|
||||
Opcode.LSLM to InstructionFormat.from("BW,v"),
|
||||
Opcode.ROR to InstructionFormat.from("BW,r1"),
|
||||
Opcode.RORM to InstructionFormat.from("BW,v"),
|
||||
Opcode.ROXR to InstructionFormat.from("BW,r1"),
|
||||
Opcode.ROXRM to InstructionFormat.from("BW,v"),
|
||||
Opcode.ROL to InstructionFormat.from("BW,r1"),
|
||||
Opcode.ROLM to InstructionFormat.from("BW,v"),
|
||||
Opcode.ROXL to InstructionFormat.from("BW,r1"),
|
||||
Opcode.ROXLM to InstructionFormat.from("BW,v"),
|
||||
Opcode.BSTCC to InstructionFormat.from("N,<v"),
|
||||
Opcode.BSTCS to InstructionFormat.from("N,<v"),
|
||||
Opcode.BSTEQ to InstructionFormat.from("N,<v"),
|
||||
Opcode.BSTNE to InstructionFormat.from("N,<v"),
|
||||
Opcode.BSTNEG to InstructionFormat.from("N,<v"),
|
||||
Opcode.BSTPOS to InstructionFormat.from("N,<v"),
|
||||
Opcode.BZ to InstructionFormat.from("BW,<r1,<v"),
|
||||
Opcode.BNZ to InstructionFormat.from("BW,<r1,<v"),
|
||||
Opcode.BEQ to InstructionFormat.from("BW,<r1,<r2,<v"),
|
||||
Opcode.BNE to InstructionFormat.from("BW,<r1,<r2,<v"),
|
||||
Opcode.BLT to InstructionFormat.from("BW,<r1,<r2,<v"),
|
||||
Opcode.BLTS to InstructionFormat.from("BW,<r1,<r2,<v"),
|
||||
Opcode.BGT to InstructionFormat.from("BW,<r1,<r2,<v"),
|
||||
Opcode.BGTS to InstructionFormat.from("BW,<r1,<r2,<v"),
|
||||
Opcode.BLE to InstructionFormat.from("BW,<r1,<r2,<v"),
|
||||
Opcode.BLES to InstructionFormat.from("BW,<r1,<r2,<v"),
|
||||
Opcode.BGE to InstructionFormat.from("BW,<r1,<r2,<v"),
|
||||
Opcode.BGES to InstructionFormat.from("BW,<r1,<r2,<v"),
|
||||
Opcode.SEQ to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.SNE to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.SLT to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.SLTS to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.SGT to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.SGTS to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.SLE to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.SLES to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.SGE to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.SGES to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.INC to InstructionFormat.from("BW,<>r1"),
|
||||
Opcode.INCM to InstructionFormat.from("BW,<v"),
|
||||
Opcode.DEC to InstructionFormat.from("BW,<>r1"),
|
||||
Opcode.DECM to InstructionFormat.from("BW,<v"),
|
||||
Opcode.NEG to InstructionFormat.from("BW,<>r1 | F,<>fr1"),
|
||||
Opcode.NEGM to InstructionFormat.from("BW,<v | F,<v"),
|
||||
Opcode.ADDR to InstructionFormat.from("BW,<>r1,<r2 | F,<>fr1,<fr2"),
|
||||
Opcode.ADD to InstructionFormat.from("BW,<>r1,<v | F,<>fr1,<v"),
|
||||
Opcode.ADDM to InstructionFormat.from("BW,<r1,<v | F,<fr1,<v"),
|
||||
Opcode.SUBR to InstructionFormat.from("BW,<>r1,<r2 | F,<>fr1,<fr2"),
|
||||
Opcode.SUB to InstructionFormat.from("BW,<>r1,<v | F,<>fr1,<v"),
|
||||
Opcode.SUBM to InstructionFormat.from("BW,<r1,<v | F,<fr1,<v"),
|
||||
Opcode.MULR to InstructionFormat.from("BW,<>r1,<r2 | F,<>fr1,<fr2"),
|
||||
Opcode.MUL to InstructionFormat.from("BW,<>r1,<v | F,<>fr1,<v"),
|
||||
Opcode.MULM to InstructionFormat.from("BW,<r1,<v | F,<fr1,<v"),
|
||||
Opcode.DIVR to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.DIV to InstructionFormat.from("BW,<>r1,<v"),
|
||||
Opcode.DIVM to InstructionFormat.from("BW,<r1,<v"),
|
||||
Opcode.DIVSR to InstructionFormat.from("BW,<>r1,<r2 | F,<>fr1,<fr2"),
|
||||
Opcode.DIVS to InstructionFormat.from("BW,<>r1,<v | F,<>fr1,<v"),
|
||||
Opcode.DIVSM to InstructionFormat.from("BW,<r1,<v | F,<fr1,<v"),
|
||||
Opcode.SQRT to InstructionFormat.from("BW,>r1,<r2 | F,>fr1,<fr2"),
|
||||
Opcode.SGN to InstructionFormat.from("BW,>r1,<r2 | F,>fr1,<fr2"),
|
||||
Opcode.RND to InstructionFormat.from("BW,>r1 | F,>fr1"),
|
||||
Opcode.MODR to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.MOD to InstructionFormat.from("BW,<>r1,<v"),
|
||||
Opcode.CMP to InstructionFormat.from("BW,<r1,<r2"),
|
||||
Opcode.EXT to InstructionFormat.from("BW,<>r1"),
|
||||
Opcode.EXTS to InstructionFormat.from("BW,<>r1"),
|
||||
Opcode.ANDR to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.AND to InstructionFormat.from("BW,<>r1,<v"),
|
||||
Opcode.ANDM to InstructionFormat.from("BW,<r1,<v"),
|
||||
Opcode.ORR to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.OR to InstructionFormat.from("BW,<>r1,<v"),
|
||||
Opcode.ORM to InstructionFormat.from("BW,<r1,<v"),
|
||||
Opcode.XORR to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.XOR to InstructionFormat.from("BW,<>r1,<v"),
|
||||
Opcode.XORM to InstructionFormat.from("BW,<r1,<v"),
|
||||
Opcode.INV to InstructionFormat.from("BW,<>r1"),
|
||||
Opcode.INVM to InstructionFormat.from("BW,<v"),
|
||||
Opcode.ASRN to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.ASRNM to InstructionFormat.from("BW,<r1,<v"),
|
||||
Opcode.LSRN to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.LSRNM to InstructionFormat.from("BW,<r1,<v"),
|
||||
Opcode.LSLN to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.LSLNM to InstructionFormat.from("BW,<r1,<v"),
|
||||
Opcode.ASR to InstructionFormat.from("BW,<>r1"),
|
||||
Opcode.ASRM to InstructionFormat.from("BW,<v"),
|
||||
Opcode.LSR to InstructionFormat.from("BW,<>r1"),
|
||||
Opcode.LSRM to InstructionFormat.from("BW,<v"),
|
||||
Opcode.LSL to InstructionFormat.from("BW,<>r1"),
|
||||
Opcode.LSLM to InstructionFormat.from("BW,<v"),
|
||||
Opcode.ROR to InstructionFormat.from("BW,<>r1"),
|
||||
Opcode.RORM to InstructionFormat.from("BW,<v"),
|
||||
Opcode.ROXR to InstructionFormat.from("BW,<>r1"),
|
||||
Opcode.ROXRM to InstructionFormat.from("BW,<v"),
|
||||
Opcode.ROL to InstructionFormat.from("BW,<>r1"),
|
||||
Opcode.ROLM to InstructionFormat.from("BW,<v"),
|
||||
Opcode.ROXL to InstructionFormat.from("BW,<>r1"),
|
||||
Opcode.ROXLM to InstructionFormat.from("BW,<v"),
|
||||
|
||||
Opcode.FFROMUB to InstructionFormat.from("F,fr1,r1"),
|
||||
Opcode.FFROMSB to InstructionFormat.from("F,fr1,r1"),
|
||||
Opcode.FFROMUW to InstructionFormat.from("F,fr1,r1"),
|
||||
Opcode.FFROMSW to InstructionFormat.from("F,fr1,r1"),
|
||||
Opcode.FTOUB to InstructionFormat.from("F,r1,fr1"),
|
||||
Opcode.FTOSB to InstructionFormat.from("F,r1,fr1"),
|
||||
Opcode.FTOUW to InstructionFormat.from("F,r1,fr1"),
|
||||
Opcode.FTOSW to InstructionFormat.from("F,r1,fr1"),
|
||||
Opcode.FPOW to InstructionFormat.from("F,fr1,fr2"),
|
||||
Opcode.FABS to InstructionFormat.from("F,fr1,fr2"),
|
||||
Opcode.FSIN to InstructionFormat.from("F,fr1,fr2"),
|
||||
Opcode.FCOS to InstructionFormat.from("F,fr1,fr2"),
|
||||
Opcode.FTAN to InstructionFormat.from("F,fr1,fr2"),
|
||||
Opcode.FATAN to InstructionFormat.from("F,fr1,fr2"),
|
||||
Opcode.FLN to InstructionFormat.from("F,fr1,fr2"),
|
||||
Opcode.FLOG to InstructionFormat.from("F,fr1,fr2"),
|
||||
Opcode.FSQRT to InstructionFormat.from("F,fr1,fr2"),
|
||||
Opcode.FROUND to InstructionFormat.from("F,fr1,fr2"),
|
||||
Opcode.FFLOOR to InstructionFormat.from("F,fr1,fr2"),
|
||||
Opcode.FCEIL to InstructionFormat.from("F,fr1,fr2"),
|
||||
Opcode.FCOMP to InstructionFormat.from("F,r1,fr1,fr2"),
|
||||
Opcode.FFROMUB to InstructionFormat.from("F,>fr1,<r1"),
|
||||
Opcode.FFROMSB to InstructionFormat.from("F,>fr1,<r1"),
|
||||
Opcode.FFROMUW to InstructionFormat.from("F,>fr1,<r1"),
|
||||
Opcode.FFROMSW to InstructionFormat.from("F,>fr1,<r1"),
|
||||
Opcode.FTOUB to InstructionFormat.from("F,>r1,<fr1"),
|
||||
Opcode.FTOSB to InstructionFormat.from("F,>r1,<fr1"),
|
||||
Opcode.FTOUW to InstructionFormat.from("F,>r1,<fr1"),
|
||||
Opcode.FTOSW to InstructionFormat.from("F,>r1,<fr1"),
|
||||
Opcode.FPOW to InstructionFormat.from("F,<>fr1,<fr2"),
|
||||
Opcode.FABS to InstructionFormat.from("F,>fr1,<fr2"),
|
||||
Opcode.FCOMP to InstructionFormat.from("F,>r1,<fr1,<fr2"),
|
||||
Opcode.FSIN to InstructionFormat.from("F,>fr1,<fr2"),
|
||||
Opcode.FCOS to InstructionFormat.from("F,>fr1,<fr2"),
|
||||
Opcode.FTAN to InstructionFormat.from("F,>fr1,<fr2"),
|
||||
Opcode.FATAN to InstructionFormat.from("F,>fr1,<fr2"),
|
||||
Opcode.FLN to InstructionFormat.from("F,>fr1,<fr2"),
|
||||
Opcode.FLOG to InstructionFormat.from("F,>fr1,<fr2"),
|
||||
Opcode.FROUND to InstructionFormat.from("F,>fr1,<fr2"),
|
||||
Opcode.FFLOOR to InstructionFormat.from("F,>fr1,<fr2"),
|
||||
Opcode.FCEIL to InstructionFormat.from("F,>fr1,<fr2"),
|
||||
|
||||
Opcode.MSIG to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.PUSH to InstructionFormat.from("BW,r1"),
|
||||
Opcode.POP to InstructionFormat.from("BW,r1"),
|
||||
Opcode.CONCAT to InstructionFormat.from("BW,r1,r2"),
|
||||
Opcode.MSIG to InstructionFormat.from("BW,>r1,<r2"),
|
||||
Opcode.PUSH to InstructionFormat.from("BW,<r1"),
|
||||
Opcode.POP to InstructionFormat.from("BW,>r1"),
|
||||
Opcode.CONCAT to InstructionFormat.from("BW,<>r1,<r2"),
|
||||
Opcode.CLC to InstructionFormat.from("N"),
|
||||
Opcode.SEC to InstructionFormat.from("N"),
|
||||
Opcode.BREAKPOINT to InstructionFormat.from("N"),
|
||||
|
@ -218,7 +218,6 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
Opcode.FATAN -> InsFATAN(ins)
|
||||
Opcode.FLN -> InsFLN(ins)
|
||||
Opcode.FLOG -> InsFLOG(ins)
|
||||
Opcode.FSQRT -> InsFSQRT(ins)
|
||||
Opcode.FROUND -> InsFROUND(ins)
|
||||
Opcode.FFLOOR -> InsFFLOOR(ins)
|
||||
Opcode.FCEIL -> InsFCEIL(ins)
|
||||
@ -1887,12 +1886,6 @@ class VirtualMachine(val memory: Memory, program: List<Instruction>) {
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsFSQRT(i: Instruction) {
|
||||
val value = registers.getFloat(i.fpReg2!!)
|
||||
registers.setFloat(i.fpReg1!!, sqrt(value))
|
||||
pc++
|
||||
}
|
||||
|
||||
private fun InsFCOMP(i: Instruction) {
|
||||
val left = registers.getFloat(i.fpReg1!!)
|
||||
val right = registers.getFloat(i.fpReg2!!)
|
||||
|
@ -2,10 +2,7 @@ import io.kotest.assertions.throwables.shouldThrow
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.kotest.matchers.shouldNotBe
|
||||
import prog8.vm.Instruction
|
||||
import prog8.vm.Opcode
|
||||
import prog8.vm.VmDataType
|
||||
import prog8.vm.instructionFormats
|
||||
import prog8.vm.*
|
||||
|
||||
|
||||
class TestInstructions: FunSpec({
|
||||
@ -18,6 +15,8 @@ class TestInstructions: FunSpec({
|
||||
ins.reg2 shouldBe null
|
||||
ins.value shouldBe null
|
||||
ins.labelSymbol shouldBe null
|
||||
ins.reg1direction shouldBe OperandDirection.INPUT
|
||||
ins.fpReg1direction shouldBe OperandDirection.INPUT
|
||||
ins.toString() shouldBe "nop"
|
||||
}
|
||||
|
||||
@ -29,6 +28,8 @@ class TestInstructions: FunSpec({
|
||||
ins.reg2 shouldBe null
|
||||
ins.value shouldBe 9999
|
||||
ins.labelSymbol shouldBe null
|
||||
ins.reg1direction shouldBe OperandDirection.INPUT
|
||||
ins.fpReg1direction shouldBe OperandDirection.INPUT
|
||||
ins.toString() shouldBe "bz.b r42,9999"
|
||||
}
|
||||
|
||||
@ -40,9 +41,36 @@ class TestInstructions: FunSpec({
|
||||
ins.reg2 shouldBe null
|
||||
ins.value shouldBe null
|
||||
ins.labelSymbol shouldBe listOf("a","b","c")
|
||||
ins.reg1direction shouldBe OperandDirection.INPUT
|
||||
ins.fpReg1direction shouldBe OperandDirection.INPUT
|
||||
ins.toString() shouldBe "bz.w r11,_a.b.c"
|
||||
}
|
||||
|
||||
test("with output registers") {
|
||||
val ins = Instruction(Opcode.ADDR, VmDataType.WORD, reg1=11, reg2=22)
|
||||
ins.opcode shouldBe Opcode.ADDR
|
||||
ins.type shouldBe VmDataType.WORD
|
||||
ins.reg1 shouldBe 11
|
||||
ins.reg2 shouldBe 22
|
||||
ins.value shouldBe null
|
||||
ins.labelSymbol shouldBe null
|
||||
ins.reg1direction shouldBe OperandDirection.INOUT
|
||||
ins.fpReg1direction shouldBe OperandDirection.INPUT
|
||||
ins.toString() shouldBe "addr.w r11,r22"
|
||||
|
||||
val ins2 = Instruction(Opcode.SQRT, VmDataType.BYTE, reg1=11, reg2=22)
|
||||
ins2.opcode shouldBe Opcode.SQRT
|
||||
ins2.type shouldBe VmDataType.BYTE
|
||||
ins2.reg1 shouldBe 11
|
||||
ins2.reg2 shouldBe 22
|
||||
ins2.value shouldBe null
|
||||
ins2.labelSymbol shouldBe null
|
||||
ins2.reg1direction shouldBe OperandDirection.OUTPUT
|
||||
ins2.fpReg1direction shouldBe OperandDirection.INPUT
|
||||
ins2.toString() shouldBe "sqrt.b r11,r22"
|
||||
}
|
||||
|
||||
|
||||
test("missing type should fail") {
|
||||
shouldThrow<IllegalArgumentException> {
|
||||
Instruction(Opcode.BZ, reg1=42, value=9999)
|
||||
|
Loading…
Reference in New Issue
Block a user