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()
|
|
|
|
vm.pc shouldBe 0
|
|
|
|
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()
|
|
|
|
vm.pc shouldBe 0
|
|
|
|
vm.stepCount shouldBe 1
|
|
|
|
}
|
|
|
|
|
|
|
|
test("vm execution: modify memory") {
|
2022-09-26 17:03:54 +00:00
|
|
|
val program = IRProgram("test", IRSymbolTable(null), getTestOptions(), VMTarget())
|
|
|
|
val block = IRBlock("main", null, IRBlock.BlockAlignment.NONE, Position.DUMMY)
|
|
|
|
val startSub = IRSubroutine("main.start2222", emptyList(), null, Position.DUMMY) // TODO proper name main.start
|
|
|
|
val code = IRCodeChunk(Position.DUMMY)
|
2022-09-26 17:46:44 +00:00
|
|
|
code += IRInstruction(Opcode.LOAD, VmDataType.WORD, reg1=1, value=12345)
|
|
|
|
code += IRInstruction(Opcode.STOREM, VmDataType.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()
|
|
|
|
vm.pc shouldBe 0
|
|
|
|
vm.stepCount shouldBe 0
|
2022-09-24 14:00:25 +00:00
|
|
|
vm.run()
|
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()
|
|
|
|
vm.pc shouldBe 2
|
|
|
|
vm.stepCount shouldBe 3
|
|
|
|
}
|
|
|
|
|
|
|
|
test("vmrunner") {
|
|
|
|
val runner = VmRunner()
|
2022-09-26 17:03:54 +00:00
|
|
|
val irSource="""<PROGRAM NAME=test>
|
|
|
|
<OPTIONS>
|
|
|
|
</OPTIONS>
|
|
|
|
|
|
|
|
<VARIABLES>
|
|
|
|
</VARIABLES>
|
|
|
|
|
|
|
|
<MEMORYMAPPEDVARIABLES>
|
|
|
|
</MEMORYMAPPEDVARIABLES>
|
|
|
|
|
|
|
|
<MEMORYSLABS>
|
|
|
|
</MEMORYSLABS>
|
|
|
|
|
|
|
|
<INITGLOBALS>
|
|
|
|
</INITGLOBALS>
|
|
|
|
|
|
|
|
<BLOCK NAME=main ADDRESS=null ALIGN=NONE POS=[unittest: line 42 col 1-9]>
|
|
|
|
</BLOCK>
|
|
|
|
</PROGRAM>
|
|
|
|
"""
|
|
|
|
runner.runProgram(irSource)
|
2022-09-21 00:59:36 +00:00
|
|
|
}
|
|
|
|
})
|