60hz irq implemented in stackvm

This commit is contained in:
Irmen de Jong 2018-09-27 22:45:57 +02:00
parent 99d63b13a8
commit 7f28f8be11
6 changed files with 220 additions and 124 deletions

13
compiler/examples/irq.p8 Normal file
View File

@ -0,0 +1,13 @@
~ main {
sub start() -> () {
byte jiffyclockHi = $a0
byte jiffyclockMid = $a1
byte jiffyclockLo = $a2
_vm_gfx_pixel(2,2,jiffyclockHi)
_vm_gfx_pixel(4,2,jiffyclockMid)
_vm_gfx_pixel(6,2,jiffyclockLo)
}
}

View File

@ -17,9 +17,11 @@ fun main(args: Array<String>) {
}
val program = Program.load(args.first())
//val irqProgram = Program("irq", mutableListOf(), emptyMap(), emptyMap(), emptyMap())
val irqProgram = Program.load("irq_stackvm.txt")
val vm = StackVm(traceOutputFile = null)
val dialog = ScreenDialog()
vm.load(program, dialog.canvas)
vm.load(program, irqProgram, dialog.canvas)
EventQueue.invokeLater {
dialog.pack()
dialog.isVisible = true
@ -36,6 +38,10 @@ fun main(args: Array<String>) {
(a.source as Timer).stop()
}
}
val irqTimer = Timer(1000/60) { a -> vm.irq(a.`when`) }
programTimer.start()
irqTimer.start()
}
}

View File

@ -0,0 +1,64 @@
package prog8.stackvm
import prog8.compiler.target.c64.Mflpt5
import prog8.compiler.target.c64.Petscii
class Memory {
private val mem = ShortArray(65536) // shorts because byte is signed and we store values 0..255
fun getByte(address: Int): Short {
return mem[address]
}
fun setByte(address: Int, value: Short) {
if(value<0 || value>255) throw VmExecutionException("byte value not 0..255")
mem[address] = value
}
fun getWord(address: Int): Int {
return mem[address] + 256*mem[address+1]
}
fun setWord(address: Int, value: Int) {
if(value<0 || value>65535) throw VmExecutionException("word value not 0..65535")
mem[address] = value.and(255).toShort()
mem[address+1] = (value / 256).toShort()
}
fun setFloat(address: Int, value: Double) {
val mflpt5 = Mflpt5.fromNumber(value)
mem[address] = mflpt5.b0
mem[address+1] = mflpt5.b1
mem[address+2] = mflpt5.b2
mem[address+3] = mflpt5.b3
mem[address+4] = mflpt5.b4
}
fun getFloat(address: Int): Double {
return Mflpt5(mem[address], mem[address + 1], mem[address + 2], mem[address + 3], mem[address + 4]).toDouble()
}
fun setString(address: Int, str: String) {
// lowercase PETSCII
val petscii = Petscii.encodePetscii(str, true)
var addr = address
for (c in petscii) mem[addr++] = c
mem[addr] = 0
}
fun getString(strAddress: Int): String {
// lowercase PETSCII
val petscii = mutableListOf<Short>()
var addr = strAddress
while(true) {
val byte = mem[addr++]
if(byte==0.toShort()) break
petscii.add(byte)
}
return Petscii.decodePetscii(petscii, true)
}
fun clear() {
for(i in 0..65535) mem[i]=0
}
}

View File

@ -45,7 +45,7 @@ class BitmapScreenPanel : JPanel() {
companion object {
const val SCREENWIDTH = 320
const val SCREENHEIGHT = 256
const val SCREENHEIGHT = 200
const val SCALING = 3
val palette = listOf( // this is Pepto's Commodore-64 palette http://www.pepto.de/projects/colorvic/
Color(0x000000), // 0 = black

View File

@ -1,7 +1,6 @@
package prog8.stackvm
import prog8.ast.DataType
import prog8.compiler.target.c64.Mflpt5
import prog8.compiler.target.c64.Petscii
import java.io.File
import java.io.PrintStream
@ -165,66 +164,6 @@ enum class Syscall(val callNr: Short) {
// some of them are straight opcodes (such as MSB, LSB, LSL, LSR, ROL, ROR, ROL2, ROR2, and FLT)!
}
class Memory {
private val mem = ShortArray(65536) // shorts because byte is signed and we store values 0..255
fun getByte(address: Int): Short {
return mem[address]
}
fun setByte(address: Int, value: Short) {
if(value<0 || value>255) throw VmExecutionException("byte value not 0..255")
mem[address] = value
}
fun getWord(address: Int): Int {
return mem[address] + 256*mem[address+1]
}
fun setWord(address: Int, value: Int) {
if(value<0 || value>65535) throw VmExecutionException("word value not 0..65535")
mem[address] = value.and(255).toShort()
mem[address+1] = (value / 256).toShort()
}
fun setFloat(address: Int, value: Double) {
val mflpt5 = Mflpt5.fromNumber(value)
mem[address] = mflpt5.b0
mem[address+1] = mflpt5.b1
mem[address+2] = mflpt5.b2
mem[address+3] = mflpt5.b3
mem[address+4] = mflpt5.b4
}
fun getFloat(address: Int): Double {
return Mflpt5(mem[address], mem[address+1], mem[address+2], mem[address+3], mem[address+4]).toDouble()
}
fun setString(address: Int, str: String) {
// lowercase PETSCII
val petscii = Petscii.encodePetscii(str, true)
var addr = address
for (c in petscii) mem[addr++] = c
mem[addr] = 0
}
fun getString(strAddress: Int): String {
// lowercase PETSCII
val petscii = mutableListOf<Short>()
var addr = strAddress
while(true) {
val byte = mem[addr++]
if(byte==0.toShort()) break
petscii.add(byte)
}
return Petscii.decodePetscii(petscii, true)
}
fun clear() {
for(i in 0..65535) mem[i]=0
}
}
class Value(val type: DataType, numericvalue: Number?, val stringvalue: String?=null, val arrayvalue: IntArray?=null) {
private var byteval: Short? = null
@ -912,10 +851,6 @@ class Program (val name: String,
class StackVm(val traceOutputFile: String?) {
val mem = Memory()
val evalstack = MyStack<Value>() // evaluation stack
val callstack = MyStack<Instruction>() // subroutine call stack
var sourceLine = "" // meta info about current line in source file
private set
var P_carry: Boolean = false
private set
var P_irqd: Boolean = false
@ -923,22 +858,39 @@ class StackVm(val traceOutputFile: String?) {
var variables = mutableMapOf<String, Value>() // all variables (set of all vars used by all blocks/subroutines) key = their fully scoped name
private set
private var program = listOf<Instruction>()
private var irqProgram = listOf<Instruction>()
var evalstack = MyStack<Value>()
private set
var callstack = MyStack<Instruction>()
private set
private var traceOutput = if(traceOutputFile!=null) PrintStream(File(traceOutputFile), "utf-8") else null
private lateinit var currentIns: Instruction
private var canvas: BitmapScreenPanel? = null
private val rnd = Random()
private val bootTime = System.currentTimeMillis()
private lateinit var currentIns: Instruction
var sourceLine: String = ""
private set
fun load(program: Program, canvas: BitmapScreenPanel?) {
fun load(program: Program, irqProgram: Program?, canvas: BitmapScreenPanel?) {
this.program = program.program
this.irqProgram = irqProgram?.program ?: mutableListOf(Instruction(Opcode.NOP))
this.canvas = canvas
variables = program.variables.toMutableMap()
if(this.variables.contains("A") ||
irqCurrentVariables = irqProgram?.variables?.toMutableMap() ?: mutableMapOf()
if(variables.contains("A") ||
variables.contains("X") ||
variables.contains("Y") ||
variables.contains("XY") ||
variables.contains("AX") ||
variables.contains("AY"))
throw VmExecutionException("program contains variable(s) for the reserved registers A,X,...")
if(irqCurrentVariables.contains("A") ||
irqCurrentVariables.contains("X") ||
irqCurrentVariables.contains("Y") ||
irqCurrentVariables.contains("XY") ||
irqCurrentVariables.contains("AX") ||
irqCurrentVariables.contains("AY"))
throw VmExecutionException("irqProgram contains variable(s) for the reserved registers A,X,...")
// define the 'registers'
variables["A"] = Value(DataType.BYTE, 0)
variables["X"] = Value(DataType.BYTE, 0)
@ -946,14 +898,24 @@ class StackVm(val traceOutputFile: String?) {
variables["AX"] = Value(DataType.WORD, 0)
variables["AY"] = Value(DataType.WORD, 0)
variables["XY"] = Value(DataType.WORD, 0)
irqCurrentVariables["A"] = Value(DataType.BYTE, 0)
irqCurrentVariables["X"] = Value(DataType.BYTE, 0)
irqCurrentVariables["Y"] = Value(DataType.BYTE, 0)
irqCurrentVariables["AX"] = Value(DataType.WORD, 0)
irqCurrentVariables["AY"] = Value(DataType.WORD, 0)
irqCurrentVariables["XY"] = Value(DataType.WORD, 0)
initMemory(program.memory)
evalstack.clear()
callstack.clear()
irqEvalStack.clear()
irqCallStack.clear()
P_carry = false
P_irqd = false
sourceLine = ""
irqCurrentLine = ""
currentIns = this.program[0]
irqCurrentIns = this.irqProgram[0]
}
fun step(instructionCount: Int = 10000) {
@ -1568,4 +1530,55 @@ class StackVm(val traceOutputFile: String?) {
return ins.next
}
fun irq(timestamp: Long) {
// 60hz IRQ handling
if(P_irqd)
return // interrupt is disabled
P_irqd=true
swapIrqExecutionContexts(true)
val jiffies = min((timestamp-bootTime)*60/1000, 24*3600*60-1)
// update the C-64 60hz jiffy clock in the ZP addresses:
mem.setByte(0x00a0, (jiffies ushr 16).toShort())
mem.setByte(0x00a1, (jiffies ushr 8 and 255).toShort())
mem.setByte(0x00a2, (jiffies and 255).toShort())
try {
// execute the irq routine
this.step(Int.MAX_VALUE)
} catch(vmt: VmTerminationException) {
// irq routine ended
}
if(evalstack.isNotEmpty())
throw VmExecutionException("irq: eval stack is not empty at exit from irq program")
if(callstack.isNotEmpty())
throw VmExecutionException("irq: call stack is not empty at exit from irq program")
swapIrqExecutionContexts(false)
P_irqd=false
}
private lateinit var irqCurrentIns: Instruction
private var irqCurrentVariables = mutableMapOf<String, Value>()
private var irqCurrentLine: String = ""
private var irqEvalStack = MyStack<Value>()
private var irqCallStack = MyStack<Instruction>()
private var irqCarry = false
private fun swapIrqExecutionContexts(startingIrq: Boolean) {
irqCarry = P_carry.also { P_carry = irqCarry }
irqProgram = program.also { program = irqProgram }
irqCurrentIns = currentIns.also { currentIns = irqCurrentIns }
irqCurrentVariables = variables.also {variables = irqCurrentVariables }
irqCurrentLine = sourceLine.also { sourceLine = irqCurrentLine }
irqEvalStack = evalstack.also { evalstack = irqEvalStack }
irqCallStack = callstack.also { callstack = irqCallStack }
if(startingIrq) {
currentIns = program.first()
sourceLine = ""
P_carry = false
}
}
}

View File

@ -50,7 +50,7 @@ class TestStackVmOpcodes {
@Test
fun testInitAndNop() {
val ins = mutableListOf(Instruction(Opcode.NOP))
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
assertEquals(6, vm.variables.size)
assertTrue(vm.variables.containsKey("XY"))
assertTrue(vm.variables.containsKey("A"))
@ -65,7 +65,7 @@ class TestStackVmOpcodes {
@Test
fun testBreakpoint() {
val ins = mutableListOf(Instruction(Opcode.BREAKPOINT))
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
assertFailsWith<VmBreakpointException> {
vm.step()
}
@ -76,7 +76,7 @@ class TestStackVmOpcodes {
@Test
fun testLine() {
val ins = mutableListOf(Instruction(Opcode.LINE, Value(DataType.STR, null, "line 99")))
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
assertEquals("", vm.sourceLine)
vm.step(1)
assertEquals("line 99", vm.sourceLine)
@ -85,7 +85,7 @@ class TestStackVmOpcodes {
@Test
fun testSECandSEIandCLCandCLI() {
val ins = mutableListOf(Instruction(Opcode.SEC), Instruction(Opcode.SEI), Instruction(Opcode.CLC), Instruction(Opcode.CLI))
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
assertFalse(vm.P_carry)
assertFalse(vm.P_irqd)
vm.step(1)
@ -105,7 +105,7 @@ class TestStackVmOpcodes {
@Test
fun testPush() {
val ins = mutableListOf(Instruction(Opcode.PUSH, Value(DataType.FLOAT, 42.999)))
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
assertThat(vm.evalstack, empty())
vm.step(1)
assertEquals(1, vm.evalstack.size)
@ -122,7 +122,7 @@ class TestStackVmOpcodes {
val mem=mapOf(0x2000 to listOf(Value(DataType.WORD, 0x42ea)),
0x3000 to listOf(Value(DataType.WORD, 0x42ea)),
0x4000 to listOf(Value(DataType.FLOAT, 42.25)))
vm.load(makeProg(ins, mem=mem), null)
vm.load(makeProg(ins, mem=mem), null, null)
assertEquals(0xea, vm.mem.getByte(0x2000))
assertEquals(0x42, vm.mem.getByte(0x2001))
assertEquals(0xea, vm.mem.getByte(0x3000))
@ -141,7 +141,7 @@ class TestStackVmOpcodes {
@Test
fun testPushVar() {
val ins = mutableListOf(Instruction(Opcode.PUSH_VAR, Value(DataType.STR, null, "varname")))
vm.load(makeProg(ins, mapOf("varname" to Value(DataType.FLOAT, 42.999))), null)
vm.load(makeProg(ins, mapOf("varname" to Value(DataType.FLOAT, 42.999))), null, null)
assertEquals(7, vm.variables.size)
assertTrue(vm.variables.containsKey("varname"))
assertTrue(vm.variables.containsKey("XY"))
@ -159,7 +159,7 @@ class TestStackVmOpcodes {
val ins = mutableListOf(
Instruction(Opcode.PUSH, Value(DataType.FLOAT, 42.999)),
Instruction(Opcode.DUP))
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
assertThat(vm.evalstack, empty())
vm.step(2)
assertEquals(2, vm.evalstack.size)
@ -174,7 +174,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.PUSH, Value(DataType.WORD, 9999)),
Instruction(Opcode.SWAP)
)
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
assertThat(vm.evalstack, empty())
vm.step(3)
assertEquals(2, vm.evalstack.size)
@ -188,7 +188,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.PUSH, Value(DataType.FLOAT, 42.999)),
Instruction(Opcode.PUSH, Value(DataType.FLOAT, 3.1415)),
Instruction(Opcode.DISCARD))
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
assertThat(vm.evalstack, empty())
vm.step(2)
assertEquals(2, vm.evalstack.size)
@ -204,7 +204,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.PUSH, Value(DataType.WORD, 222)),
Instruction(Opcode.PUSH, Value(DataType.WORD, 333)),
Instruction(Opcode.ARRAY, Value(DataType.WORD, 2)))
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
assertThat(vm.evalstack, empty())
vm.step(4)
assertEquals(2, vm.evalstack.size)
@ -218,7 +218,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.PUSH, Value(DataType.BYTE, 22)),
Instruction(Opcode.PUSH, Value(DataType.BYTE, 33)),
Instruction(Opcode.ARRAY, Value(DataType.WORD, 2)))
vm.load(makeProg(ins2), null)
vm.load(makeProg(ins2), null, null)
assertThat(vm.evalstack, empty())
vm.step(4)
assertEquals(2, vm.evalstack.size)
@ -232,7 +232,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.PUSH, Value(DataType.WORD, 222)),
Instruction(Opcode.PUSH, Value(DataType.FLOAT, 333.33)),
Instruction(Opcode.ARRAY, Value(DataType.WORD, 2)))
vm.load(makeProg(ins3), null)
vm.load(makeProg(ins3), null, null)
assertFailsWith<VmExecutionException> {
vm.step(4)
}
@ -247,7 +247,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.POP_MEM, Value(DataType.WORD, 0x2000)),
Instruction(Opcode.POP_MEM, Value(DataType.WORD, 0x3000)),
Instruction(Opcode.POP_MEM, Value(DataType.WORD, 0x4000)))
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
assertEquals(0, vm.mem.getWord(0x2000))
assertEquals(0, vm.mem.getWord(0x3000))
assertEquals(0.0, vm.mem.getFloat(0x4000))
@ -274,7 +274,7 @@ class TestStackVmOpcodes {
"var2" to Value(DataType.WORD, 0),
"var3" to Value(DataType.FLOAT, 0)
)
vm.load(makeProg(ins, vars), null)
vm.load(makeProg(ins, vars), null, null)
assertEquals(9, vm.variables.size)
vm.step(6)
assertEquals(Value(DataType.BYTE, 123), vm.variables["var1"])
@ -287,7 +287,7 @@ class TestStackVmOpcodes {
val vars2 = mapOf(
"var1" to Value(DataType.BYTE, 0)
)
vm.load(makeProg(ins2, vars2), null)
vm.load(makeProg(ins2, vars2), null, null)
assertEquals(7, vm.variables.size)
assertFailsWith<VmExecutionException> {
vm.step(2)
@ -597,7 +597,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.NEG),
Instruction(Opcode.NEG)
)
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
assertThat(vm.evalstack, empty())
vm.step(2)
assertEquals(1, vm.evalstack.size)
@ -610,7 +610,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.PUSH, Value(DataType.WORD, 1234)),
Instruction(Opcode.NEG)
)
vm.load(makeProg(ins2), null)
vm.load(makeProg(ins2), null, null)
vm.step(2)
assertEquals(Value(DataType.WORD, 64302), vm.evalstack.pop())
@ -618,7 +618,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.PUSH, Value(DataType.BYTE, 12)),
Instruction(Opcode.NEG)
)
vm.load(makeProg(ins3), null)
vm.load(makeProg(ins3), null, null)
vm.step(2)
assertEquals(Value(DataType.BYTE, 244), vm.evalstack.pop())
}
@ -632,7 +632,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.INV),
Instruction(Opcode.INV)
)
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
assertThat(vm.evalstack, empty())
vm.step(3)
assertEquals(2, vm.evalstack.size)
@ -645,7 +645,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.PUSH, Value(DataType.FLOAT, 1234.33)),
Instruction(Opcode.INV)
)
vm.load(makeProg(ins2), null)
vm.load(makeProg(ins2), null, null)
assertFailsWith<VmExecutionException> {
vm.step(2)
}
@ -661,7 +661,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.LSB),
Instruction(Opcode.LSB)
)
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
vm.step(4)
assertEquals(Value(DataType.BYTE, 0x31), vm.evalstack.pop())
vm.step(1)
@ -681,7 +681,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.MSB),
Instruction(Opcode.MSB)
)
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
vm.step(4)
assertEquals(Value(DataType.BYTE, 0xea), vm.evalstack.pop())
vm.step(1)
@ -699,7 +699,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.B2WORD),
Instruction(Opcode.B2WORD)
)
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
vm.step(3)
assertEquals(Value(DataType.WORD, 0x0045), vm.evalstack.pop())
assertFailsWith<VmExecutionException> {
@ -715,7 +715,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.MSB2WORD),
Instruction(Opcode.MSB2WORD)
)
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
vm.step(3)
assertEquals(Value(DataType.WORD, 0x4500), vm.evalstack.pop())
assertFailsWith<VmExecutionException> {
@ -731,7 +731,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.B2FLOAT),
Instruction(Opcode.B2FLOAT)
)
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
vm.step(3)
assertEquals(Value(DataType.FLOAT, 123.0), vm.evalstack.pop())
assertFailsWith<VmExecutionException> {
@ -747,7 +747,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.W2FLOAT),
Instruction(Opcode.W2FLOAT)
)
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
vm.step(3)
assertEquals(Value(DataType.FLOAT, 12345.0), vm.evalstack.pop())
assertFailsWith<VmExecutionException> {
@ -765,7 +765,7 @@ class TestStackVmOpcodes {
)
val mem=mapOf(0x2000 to listOf(Value(DataType.BYTE, 100), Value(DataType.BYTE, 255)),
0x3000 to listOf(Value(DataType.WORD, 0x42ea), Value(DataType.WORD, 0xffff)))
vm.load(makeProg(ins, mem=mem), null)
vm.load(makeProg(ins, mem=mem), null, null)
vm.step(4)
assertEquals(101, vm.mem.getByte(0x2000))
assertEquals(0, vm.mem.getByte(0x2001))
@ -782,7 +782,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.INC_VAR, Value(DataType.STR, null, "var2")))
val vars = mapOf("var1" to Value(DataType.WORD, 65534),
"var2" to Value(DataType.BYTE, 254))
vm.load(makeProg(ins, vars = vars), null)
vm.load(makeProg(ins, vars = vars), null, null)
vm.step(2)
assertEquals(Value(DataType.WORD, 65535), vm.variables["var1"])
assertEquals(Value(DataType.BYTE, 255), vm.variables["var2"])
@ -800,7 +800,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.DEC_VAR, Value(DataType.STR, null, "var2")))
val vars = mapOf("var1" to Value(DataType.WORD,1),
"var2" to Value(DataType.BYTE, 1))
vm.load(makeProg(ins, vars = vars), null)
vm.load(makeProg(ins, vars = vars), null, null)
vm.step(2)
assertEquals(Value(DataType.WORD, 0), vm.variables["var1"])
assertEquals(Value(DataType.BYTE, 0), vm.variables["var2"])
@ -819,7 +819,7 @@ class TestStackVmOpcodes {
)
val mem=mapOf(0x2000 to listOf(Value(DataType.BYTE, 100), Value(DataType.BYTE, 0)),
0x3000 to listOf(Value(DataType.WORD, 0x42ea), Value(DataType.WORD, 0)))
vm.load(makeProg(ins, mem=mem), null)
vm.load(makeProg(ins, mem=mem), null, null)
vm.step(4)
assertEquals(99, vm.mem.getByte(0x2000))
assertEquals(255, vm.mem.getByte(0x2001))
@ -838,7 +838,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.PUSH, Value(DataType.WORD, 25544)),
Instruction(Opcode.SYSCALL, Value(DataType.BYTE, Syscall.FUNC_SIN.callNr))
)
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
vm.step(4)
val rndb1 = vm.evalstack.pop()
@ -1047,7 +1047,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.TERMINATE),
Instruction(Opcode.LINE, Value(DataType.STR, null, stringvalue = "string2")))
val labels = mapOf("label" to ins.last()) // points to the second LINE instruction
vm.load(makeProg(ins, labels=labels), null)
vm.load(makeProg(ins, labels=labels), null, null)
vm.step(2)
assertEquals("", vm.sourceLine)
vm.step(3)
@ -1067,7 +1067,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.TERMINATE),
Instruction(Opcode.LINE, Value(DataType.STR, null, stringvalue = "string2")))
val labels = mapOf("label" to ins.last()) // points to the second LINE instruction
vm.load(makeProg(ins, labels=labels), null)
vm.load(makeProg(ins, labels=labels), null, null)
assertFalse(vm.P_carry)
vm.step(2)
assertEquals("", vm.sourceLine)
@ -1088,7 +1088,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.TERMINATE),
Instruction(Opcode.LINE, Value(DataType.STR, null, stringvalue = "string2")))
val labels = mapOf("label" to ins.last()) // points to the second LINE instruction
vm.load(makeProg(ins, labels=labels), null)
vm.load(makeProg(ins, labels=labels), null, null)
vm.step(2)
assertEquals("", vm.sourceLine)
vm.step(3)
@ -1108,7 +1108,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.TERMINATE),
Instruction(Opcode.LINE, Value(DataType.STR, null, stringvalue = "string2")))
val labels = mapOf("label" to ins.last()) // points to the second LINE instruction
vm.load(makeProg(ins, labels=labels), null)
vm.load(makeProg(ins, labels=labels), null, null)
vm.step(2)
assertEquals("", vm.sourceLine)
vm.step(3)
@ -1130,7 +1130,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.TERMINATE),
Instruction(Opcode.LINE, Value(DataType.STR, null, stringvalue = "string2")))
val labels = mapOf("label" to ins.last()) // points to the second LINE instruction
vm.load(makeProg(ins, labels=labels), null)
vm.load(makeProg(ins, labels=labels), null, null)
vm.step(2)
assertEquals("", vm.sourceLine)
vm.step(2)
@ -1152,7 +1152,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.TERMINATE),
Instruction(Opcode.LINE, Value(DataType.STR, null, stringvalue = "string2")))
val labels = mapOf("label" to ins.last()) // points to the second LINE instruction
vm.load(makeProg(ins, labels=labels), null)
vm.load(makeProg(ins, labels=labels), null, null)
vm.step(2)
assertEquals("", vm.sourceLine)
vm.step(3)
@ -1169,7 +1169,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.TERMINATE),
Instruction(Opcode.LINE, Value(DataType.STR, null, stringvalue = "string2")))
val labels = mapOf("label" to ins.last()) // points to the second LINE instruction
vm.load(makeProg(ins, labels=labels), null)
vm.load(makeProg(ins, labels=labels), null, null)
vm.step(2)
assertEquals("string2", vm.sourceLine)
assertEquals(0, vm.callstack.size)
@ -1184,7 +1184,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.TERMINATE),
Instruction(Opcode.LINE, Value(DataType.STR, null, stringvalue = "string1"))
)
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
assertFailsWith<VmTerminationException> {
vm.step(1)
}
@ -1208,7 +1208,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.RETURN)
)
val labels = mapOf("label" to ins[3]) // points to the LINE instruction
vm.load(makeProg(ins, labels = labels), null)
vm.load(makeProg(ins, labels = labels), null, null)
vm.step(1)
assertEquals("", vm.sourceLine)
assertEquals(1, vm.callstack.size)
@ -1244,7 +1244,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.DISCARD),
Instruction(Opcode.SHR) // error
)
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
vm.step(6)
assertEquals(Value(DataType.BYTE, 124), vm.evalstack.peek())
vm.step(2)
@ -1282,7 +1282,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.DISCARD),
Instruction(Opcode.SHL) // error
)
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
vm.step(6)
assertEquals(Value(DataType.BYTE, 242), vm.evalstack.peek())
vm.step(2)
@ -1313,7 +1313,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.ROR), // 0b00100110 c=1
Instruction(Opcode.ROR) // 0b10010011 c=0 (original value after 9 rors)
)
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
vm.step(2)
assertEquals(Value(DataType.BYTE, 0b01001001), vm.evalstack.peek())
assertTrue(vm.P_carry)
@ -1351,7 +1351,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.ROR),
Instruction(Opcode.ROR) // 0b1001001100001101 c=0 (original value after 17 rors)
)
vm.load(makeProg(ins2), null)
vm.load(makeProg(ins2), null, null)
vm.step(3)
assertEquals(Value(DataType.WORD, 0b0100100110000110), vm.evalstack.peek())
assertTrue(vm.P_carry)
@ -1378,7 +1378,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.ROL), // 0b01001001 c=1
Instruction(Opcode.ROL) // 0b10010011 c=0 (original value after 9 rors)
)
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
vm.step(2)
assertEquals(Value(DataType.BYTE, 0b00100110), vm.evalstack.peek())
assertTrue(vm.P_carry)
@ -1416,7 +1416,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.ROL),
Instruction(Opcode.ROL) // 0b1001001100001101 c=0 (original value after 17 rors)
)
vm.load(makeProg(ins2), null)
vm.load(makeProg(ins2), null, null)
vm.step(3)
assertEquals(Value(DataType.WORD, 0b0010011000011010), vm.evalstack.peek())
assertTrue(vm.P_carry)
@ -1442,7 +1442,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.ROR2),
Instruction(Opcode.ROR2) // 0b10010011 (original value after 8 rors)
)
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
vm.step(2)
assertEquals(Value(DataType.BYTE, 0b11001001), vm.evalstack.peek())
assertFalse(vm.P_carry)
@ -1472,7 +1472,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.ROR2),
Instruction(Opcode.ROR2) // 0b1001001100001101 (original value after 16 rors)
)
vm.load(makeProg(ins2), null)
vm.load(makeProg(ins2), null, null)
vm.step(2)
assertEquals(Value(DataType.WORD, 0b1100100110000110), vm.evalstack.peek())
assertFalse(vm.P_carry)
@ -1496,7 +1496,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.ROL2),
Instruction(Opcode.ROL2) // 0b10010011 (original value after 8 rols)
)
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
vm.step(2)
assertEquals(Value(DataType.BYTE, 0b00100111), vm.evalstack.peek())
assertFalse(vm.P_carry)
@ -1524,7 +1524,7 @@ class TestStackVmOpcodes {
Instruction(Opcode.ROL2),
Instruction(Opcode.ROL2) // 0b1001001100001101 (original value after 16 rols)
)
vm.load(makeProg(ins2), null)
vm.load(makeProg(ins2), null, null)
vm.step(2)
assertEquals(Value(DataType.WORD, 0b0010011000011011), vm.evalstack.peek())
assertFalse(vm.P_carry)
@ -1544,7 +1544,7 @@ class TestStackVmOpcodes {
ins.add(Instruction(Opcode.PUSH, vars.next()))
ins.add(Instruction(operator))
}
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
for(expectedValue in expected) {
vm.step(3)
assertEquals(Value(DataType.BYTE, expectedValue), vm.evalstack.pop())
@ -1558,7 +1558,7 @@ class TestStackVmOpcodes {
ins.add(Instruction(Opcode.PUSH, value))
for (i in 1 until values.size)
ins.add(Instruction(operator))
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
vm.step(values.size)
assertEquals(values.size, vm.evalstack.size)
for (expectedVal in expected) {
@ -1579,7 +1579,7 @@ class TestStackVmOpcodes {
ins.add(Instruction(operator))
ins.add(Instruction(Opcode.DISCARD))
}
vm.load(makeProg(ins), null)
vm.load(makeProg(ins), null, null)
vm.step(values.size)
assertEquals(values.size, vm.evalstack.size)
for (expectedVal in expected) {