prog8/virtualmachine/test/TestVm.kt

150 lines
4.9 KiB
Kotlin
Raw Normal View History

import io.kotest.assertions.throwables.shouldThrowWithMessage
2022-09-21 00:59:36 +00:00
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.collections.shouldBeEmpty
import io.kotest.matchers.shouldBe
2022-09-26 17:03:54 +00:00
import prog8.code.core.*
import prog8.code.target.VMTarget
import prog8.intermediate.*
2022-09-21 00:59:36 +00:00
import prog8.vm.VirtualMachine
import prog8.vm.VmRunner
class TestVm: FunSpec( {
2022-09-26 17:03:54 +00:00
fun getTestOptions(): CompilationOptions {
val target = VMTarget()
return CompilationOptions(
OutputType.RAW,
CbmPrgLauncherType.NONE,
ZeropageType.DONTUSE,
zpReserved = emptyList(),
floats = true,
noSysInit = false,
compTarget = target,
loadAddress = target.machine.PROGRAM_LOAD_ADDRESS
)
}
2022-09-21 00:59:36 +00:00
test("vm execution: empty program") {
2022-09-26 17:03:54 +00:00
val program = IRProgram("test", IRSymbolTable(null), getTestOptions(), VMTarget())
val vm = VirtualMachine(program)
2022-09-21 00:59:36 +00:00
vm.callStack.shouldBeEmpty()
vm.valueStack.shouldBeEmpty()
2022-10-16 16:30:14 +00:00
vm.pcIndex shouldBe 0
2022-09-21 00:59:36 +00:00
vm.stepCount shouldBe 0
2022-09-24 14:00:25 +00:00
vm.run()
2022-09-21 00:59:36 +00:00
vm.callStack.shouldBeEmpty()
vm.valueStack.shouldBeEmpty()
2022-10-16 16:30:14 +00:00
vm.pcIndex shouldBe 0
vm.stepCount shouldBe 0
2022-09-21 00:59:36 +00:00
}
test("vm execution: modify memory") {
2022-09-26 17:03:54 +00:00
val program = IRProgram("test", IRSymbolTable(null), getTestOptions(), VMTarget())
val block = IRBlock("testmain", null, IRBlock.BlockAlignment.NONE, Position.DUMMY)
val startSub = IRSubroutine("testmain.testsub", emptyList(), null, Position.DUMMY)
val code = IRCodeChunk(startSub.name, null)
code += IRInstruction(Opcode.NOP)
code += IRInstruction(Opcode.LOAD, IRDataType.WORD, reg1=1, value=12345)
code += IRInstruction(Opcode.STOREM, IRDataType.WORD, reg1=1, value=1000)
code += IRInstruction(Opcode.RETURN)
2022-09-26 17:03:54 +00:00
startSub += code
block += startSub
program.addBlock(block)
val vm = VirtualMachine(program)
2022-09-21 00:59:36 +00:00
2022-09-26 17:03:54 +00:00
vm.memory.getUW(1000) shouldBe 0u
2022-09-21 00:59:36 +00:00
vm.callStack.shouldBeEmpty()
vm.valueStack.shouldBeEmpty()
2022-10-16 16:30:14 +00:00
vm.pcIndex shouldBe 0
2022-09-21 00:59:36 +00:00
vm.stepCount shouldBe 0
2022-09-24 14:00:25 +00:00
vm.run()
2022-10-16 16:30:14 +00:00
vm.stepCount shouldBe 4
2022-09-26 17:03:54 +00:00
vm.memory.getUW(1000) shouldBe 12345u
2022-09-21 00:59:36 +00:00
vm.callStack.shouldBeEmpty()
vm.valueStack.shouldBeEmpty()
2022-10-16 16:30:14 +00:00
vm.pcIndex shouldBe code.instructions.size-1
2022-10-04 20:54:14 +00:00
vm.stepCount shouldBe code.instructions.size
}
2022-10-16 16:30:14 +00:00
test("vm asmbinary not supported") {
2022-09-27 15:45:26 +00:00
val program = IRProgram("test", IRSymbolTable(null), getTestOptions(), VMTarget())
val block = IRBlock("testmain", null, IRBlock.BlockAlignment.NONE, Position.DUMMY)
val startSub = IRSubroutine("testmain.testsub", emptyList(), null, Position.DUMMY)
val code = IRCodeChunk(startSub.name, null)
2022-09-27 15:45:26 +00:00
code += IRInstruction(Opcode.BINARYDATA, binaryData = listOf(1u,2u,3u))
code += IRInstruction(Opcode.RETURN)
startSub += code
block += startSub
program.addBlock(block)
val vm = VirtualMachine(program)
shouldThrowWithMessage<NotImplementedError>("An operation is not implemented: BINARYDATA not yet supported in VM") {
vm.run()
}
}
test("non-IR asmsub not supported in vm") {
val program = IRProgram("test", IRSymbolTable(null), getTestOptions(), VMTarget())
val block = IRBlock("main", null, IRBlock.BlockAlignment.NONE, Position.DUMMY)
val startSub = IRAsmSubroutine(
"main.asmstart",
0x2000u,
emptySet(),
emptyList(),
emptyList(),
IRInlineAsmChunk("main.asmstart", "inlined asm here", false, null),
2022-10-31 22:59:33 +00:00
Position.DUMMY
)
block += startSub
program.addBlock(block)
shouldThrowWithMessage<IRParseException>("vm currently does not support non-IR asmsubs: main.asmstart") {
VirtualMachine(program)
}
2022-09-21 00:59:36 +00:00
}
test("IR asmsub ok in vm") {
val program = IRProgram("test", IRSymbolTable(null), getTestOptions(), VMTarget())
val block = IRBlock("main", null, IRBlock.BlockAlignment.NONE, Position.DUMMY)
val startSub = IRAsmSubroutine(
"main.start",
0x2000u,
emptySet(),
emptyList(),
emptyList(),
IRInlineAsmChunk("main.start", "return", true, null),
Position.DUMMY
)
block += startSub
program.addBlock(block)
VirtualMachine(program).run()
}
2022-09-21 00:59:36 +00:00
test("vmrunner") {
val runner = VmRunner()
2022-11-11 22:35:52 +00:00
val irSource="""<?xml version="1.0" encoding="utf-8"?>
<PROGRAM NAME="test">
2022-09-26 17:03:54 +00:00
<OPTIONS>
</OPTIONS>
<ASMSYMBOLS>
</ASMSYMBOLS>
2022-09-26 17:03:54 +00:00
<VARIABLES>
</VARIABLES>
<MEMORYMAPPEDVARIABLES>
</MEMORYMAPPEDVARIABLES>
<MEMORYSLABS>
</MEMORYSLABS>
<INITGLOBALS>
</INITGLOBALS>
2022-11-11 22:35:52 +00:00
<BLOCK NAME="main" ADDRESS="null" ALIGN="NONE" POS="[unittest: line 42 col 1-9]">
2022-09-26 17:03:54 +00:00
</BLOCK>
</PROGRAM>
"""
runner.runProgram(irSource)
2022-09-21 00:59:36 +00:00
}
})