fix memory pointer variables in the StackVm

This commit is contained in:
Irmen de Jong 2018-12-02 23:53:09 +01:00
parent 89ac374db9
commit 711d6f4ee5
9 changed files with 290 additions and 186 deletions

View File

@ -27,31 +27,34 @@ sub start() {
; }
float[10] farr
float f = 3.3
memory float mflt = $c000
memory float[10] mfarr = $d000
ubyte i=3
mflt = 55.44 ; @todo fix memory variables for stackvm???! (or proper error)
mfarr[2] = 44.44 ; @todo fix memory variables for stackvm???! (or proper error)
farr[2] = 4.44
farr[2] = f
farr[2] = mflt
farr[2] = farr[3]
farr[2] = mfarr[3]
farr[Y] = 4.44
farr[Y] = f
farr[Y] = mflt
farr[Y] = farr[3]
farr[Y] = mfarr[3]
farr[i] = 4.44
farr[i] = f
farr[i] = mflt
farr[i] = farr[3]
farr[i] = mfarr[3]
ubyte bv = 99
word wv = 14443
float fv = 3.14
memory ubyte mb = $c000
memory word mw = $c100
memory float mf = $c200
memory ubyte[10] mba = $d000
memory word[10] mwa = $d100
memory float[10] mfa = $d200
memory str mstr = $d300
memory str_p mstrp = $d300
memory str_s mstrs = $d300
memory str_ps mstrps = $d300
mb = 5
mb = Y
mb = bv
mw = 22334
mw = wv
mf = 4.45
mf = fv
mba[9] = 5
mba[9] = Y
mba[9] = bv
mwa[9] = 22334
mwa[9] = wv
mfa[9] = 5.667
mfa[9] = fv
return
}

View File

@ -755,7 +755,7 @@ class AstChecker(private val namespace: INameScope,
// check out of bounds
val index = (arrayIndexedExpression.arrayspec.x as? LiteralValue)?.asIntegerValue
if(index!=null && (index<0 || index>=arraysize))
checkResult.add(ExpressionError("arrayspec index out of bounds", arrayIndexedExpression.arrayspec.position))
checkResult.add(ExpressionError("array index out of bounds", arrayIndexedExpression.arrayspec.position))
} else if(target.datatype in StringDatatypes) {
// check string lengths
val heapId = (target.value as LiteralValue).heapId!!
@ -896,9 +896,9 @@ class AstChecker(private val namespace: INameScope,
return err("initializer arrayspec size mismatch (expecting $expectedSize, got $arraySize)")
return true
}
return err("invalid byte arrayspec size, must be 1-256")
return err("invalid byte array size, must be 1-256")
}
return err("invalid byte arrayspec initialization value ${value.type}, expected $targetDt")
return err("invalid byte array initialization value ${value.type}, expected $targetDt")
}
DataType.ARRAY_UW, DataType.ARRAY_W -> {
// value may be either a single word, or a word arrayspec

View File

@ -177,7 +177,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
if(subroutine.isNotEmpty())
throw CompilerException("kernel subroutines (with memory address) can't have a body: $subroutine")
prog.symbolDef(subroutine.scopedname, subroutine.asmAddress)
prog.memoryPointer(subroutine.scopedname, subroutine.asmAddress, DataType.UBYTE) // the datatype is a bit of a dummy in this case
}
return super.process(subroutine)
}
@ -555,9 +555,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
}
is IdentifierReference -> translate(expr)
is ArrayIndexedExpression -> translate(expr, false)
is RangeExpr -> {
TODO("TRANSLATE range $expr")
}
is RangeExpr -> throw CompilerException("it's not possible to just have a range expression that has to be translated")
else -> {
val lv = expr.constValue(namespace, heap) ?: throw CompilerException("constant expression required, not $expr")
when(lv.type) {
@ -800,59 +798,68 @@ private class StatementTranslator(private val prog: IntermediateProgram,
val valueA: IExpression
val valueX: IExpression
val paramDt = arg.first.resultingDatatype(namespace, heap)
if(paramDt==DataType.UBYTE) {
valueA=arg.first
valueX=LiteralValue.optimalInteger(0, callPosition)
val assignA = Assignment(listOf(AssignTarget(Register.A, null, null, callPosition)), null, valueA, callPosition)
val assignX = Assignment(listOf(AssignTarget(Register.X, null, null, callPosition)), null, valueX, callPosition)
assignA.linkParents(arguments[0].parent)
assignX.linkParents(arguments[0].parent)
translate(assignA)
translate(assignX)
} else if(paramDt==DataType.UWORD) {
translate(arg.first)
prog.instr(Opcode.POP_REGAX_WORD)
} else
TODO("pass parameter of type $paramDt in registers ${arg.second.registerOrPair}")
when (paramDt) {
DataType.UBYTE -> {
valueA=arg.first
valueX=LiteralValue.optimalInteger(0, callPosition)
val assignA = Assignment(listOf(AssignTarget(Register.A, null, null, callPosition)), null, valueA, callPosition)
val assignX = Assignment(listOf(AssignTarget(Register.X, null, null, callPosition)), null, valueX, callPosition)
assignA.linkParents(arguments[0].parent)
assignX.linkParents(arguments[0].parent)
translate(assignA)
translate(assignX)
}
DataType.UWORD -> {
translate(arg.first)
prog.instr(Opcode.POP_REGAX_WORD)
}
else -> TODO("pass parameter of type $paramDt in registers ${arg.second.registerOrPair}")
}
}
AY -> {
val valueA: IExpression
val valueY: IExpression
val paramDt = arg.first.resultingDatatype(namespace, heap)
if(paramDt==DataType.UBYTE) {
valueA=arg.first
valueY=LiteralValue.optimalInteger(0, callPosition)
val assignA = Assignment(listOf(AssignTarget(Register.A, null, null, callPosition)), null, valueA, callPosition)
val assignY = Assignment(listOf(AssignTarget(Register.Y, null, null, callPosition)), null, valueY, callPosition)
assignA.linkParents(arguments[0].parent)
assignY.linkParents(arguments[0].parent)
translate(assignA)
translate(assignY)
} else if(paramDt==DataType.UWORD) {
translate(arg.first)
prog.instr(Opcode.POP_REGAY_WORD)
} else
TODO("pass parameter of type $paramDt in registers ${arg.second.registerOrPair}")
when (paramDt) {
DataType.UBYTE -> {
valueA=arg.first
valueY=LiteralValue.optimalInteger(0, callPosition)
val assignA = Assignment(listOf(AssignTarget(Register.A, null, null, callPosition)), null, valueA, callPosition)
val assignY = Assignment(listOf(AssignTarget(Register.Y, null, null, callPosition)), null, valueY, callPosition)
assignA.linkParents(arguments[0].parent)
assignY.linkParents(arguments[0].parent)
translate(assignA)
translate(assignY)
}
DataType.UWORD -> {
translate(arg.first)
prog.instr(Opcode.POP_REGAY_WORD)
}
else -> TODO("pass parameter of type $paramDt in registers ${arg.second.registerOrPair}")
}
}
XY -> {
// TODO: save X on stack & restore after call
val valueX: IExpression
val valueY: IExpression
val paramDt = arg.first.resultingDatatype(namespace, heap)
if(paramDt==DataType.UBYTE) {
valueX=arg.first
valueY=LiteralValue.optimalInteger(0, callPosition)
val assignX = Assignment(listOf(AssignTarget(Register.X, null, null, callPosition)), null, valueX, callPosition)
val assignY = Assignment(listOf(AssignTarget(Register.Y, null, null, callPosition)), null, valueY, callPosition)
assignX.linkParents(arguments[0].parent)
assignY.linkParents(arguments[0].parent)
translate(assignX)
translate(assignY)
} else if(paramDt==DataType.UWORD) {
translate(arg.first)
prog.instr(Opcode.POP_REGXY_WORD)
} else
TODO("pass parameter of type $paramDt in registers ${arg.second.registerOrPair}")
when (paramDt) {
DataType.UBYTE -> {
valueX=arg.first
valueY=LiteralValue.optimalInteger(0, callPosition)
val assignX = Assignment(listOf(AssignTarget(Register.X, null, null, callPosition)), null, valueX, callPosition)
val assignY = Assignment(listOf(AssignTarget(Register.Y, null, null, callPosition)), null, valueY, callPosition)
assignX.linkParents(arguments[0].parent)
assignY.linkParents(arguments[0].parent)
translate(assignX)
translate(assignY)
}
DataType.UWORD -> {
translate(arg.first)
prog.instr(Opcode.POP_REGXY_WORD)
}
else -> TODO("pass parameter of type $paramDt in registers ${arg.second.registerOrPair}")
}
}
}
}
@ -1226,7 +1233,6 @@ private class StatementTranslator(private val prog: IntermediateProgram,
else -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
}
}
// todo: maybe if you assign byte or word to arrayspec, clear it with that value?
DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.ARRAY_UW, DataType.ARRAY_W, DataType.ARRAY_F -> throw CompilerException("incompatible data types valueDt=$valueDt targetDt=$targetDt at $stmt")
null -> throw CompilerException("could not determine targetdt")
@ -1793,7 +1799,7 @@ private class StatementTranslator(private val prog: IntermediateProgram,
val postIncr = PostIncrDecr(makeAssignmentTarget(), "--", range.position)
postIncr.linkParents(range.parent)
translate(postIncr)
TODO("signed numbers and/or special condition are needed for decreasing for loop. Try an increasing loop and/or constant loop values instead? At: ${range.position}")
TODO("signed numbers and/or special condition are needed for decreasing for loop. Try an increasing loop and/or constant loop values instead? At: ${range.position}") // fix with signed numbers
}
else -> {
TODO("non-literal-const or other-than-one step increment code At: ${range.position}")

View File

@ -13,7 +13,7 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
var address: Int?,
val instructions: MutableList<Instruction> = mutableListOf(),
val variables: MutableMap<String, Value> = mutableMapOf(),
val integerConstants: MutableMap<String, Int> = mutableMapOf(),
val memoryPointers: MutableMap<String, Pair<Int, DataType>> = mutableMapOf(),
val labels: MutableMap<String, Instruction> = mutableMapOf())
{
val numVariables: Int
@ -276,7 +276,10 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
}
VarDeclType.CONST -> {} // constants are all folded away
VarDeclType.MEMORY -> {
currentBlock.integerConstants[scopedname] = (decl.value as LiteralValue).asIntegerValue!!
val lv = decl.value as LiteralValue
if(lv.type!=DataType.UWORD && lv.type!=DataType.UBYTE)
throw CompilerException("expected integer memory address $lv")
currentBlock.memoryPointers[scopedname] = Pair(lv.asIntegerValue!!, decl.datatype)
}
}
}
@ -299,8 +302,8 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
currentBlock.instructions.removeAt(currentBlock.instructions.lastIndex)
}
fun symbolDef(name: String, value: Int) {
currentBlock.integerConstants[name] = value
fun memoryPointer(name: String, address: Int, datatype: DataType) {
currentBlock.memoryPointers[name] = Pair(address, datatype)
}
fun newBlock(scopedname: String, shortname: String, address: Int?) {
@ -337,6 +340,11 @@ class IntermediateProgram(val name: String, var loadAddress: Int, val heap: Heap
out.println("${variable.key} ${variable.value.type.toString().toLowerCase()} $valuestr")
}
out.println("%end_variables")
out.println("%memorypointers")
for(iconst in blk.memoryPointers) {
out.println("${iconst.key} ${iconst.value.second.toString().toLowerCase()} uw:${iconst.value.first.toString(16)}")
}
out.println("%end_memorypointers")
out.println("%instructions")
val labels = blk.labels.entries.associateBy({it.value}) {it.key}
for(instr in blk.instructions) {

View File

@ -42,7 +42,7 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
callLabel2 = if (it.callLabel2 != null) symname(it.callLabel2, block) else null)
}
}.toMutableList()
val newConstants = block.integerConstants.map { symname(it.key, block) to it.value }.toMap().toMutableMap()
val newConstants = block.memoryPointers.map { symname(it.key, block) to it.value }.toMap().toMutableMap()
newblocks.add(IntermediateProgram.ProgramBlock(
block.scopedname,
block.shortname,
@ -216,8 +216,8 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
}
private fun memdefs2asm(block: IntermediateProgram.ProgramBlock) {
for(m in block.integerConstants) {
out("\t${m.key} = ${m.value.toHex()}")
for(m in block.memoryPointers) {
out("\t${m.key} = ${m.value.first.toHex()}")
}
}
@ -473,10 +473,10 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
}
Opcode.READ_INDEXED_VAR_BYTE -> {
TODO("$ins")
TODO("$ins") // byte[i]
}
Opcode.READ_INDEXED_VAR_WORD -> {
TODO("$ins")
TODO("$ins") // word[i]
}
Opcode.READ_INDEXED_VAR_FLOAT -> {
"""
@ -486,10 +486,10 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram,
"""
}
Opcode.WRITE_INDEXED_VAR_BYTE -> {
TODO("$ins")
TODO("$ins") // byte[i]=...
}
Opcode.WRITE_INDEXED_VAR_WORD -> {
TODO("$ins")
TODO("$ins") // word[i]=...
}
Opcode.WRITE_INDEXED_VAR_FLOAT -> {
"""

View File

@ -10,6 +10,7 @@ import java.util.regex.Pattern
class Program (val name: String,
val program: MutableList<Instruction>,
val variables: Map<String, Value>,
val memoryPointers: Map<String, Pair<Int, DataType>>,
val labels: Map<String, Instruction>,
val memory: Map<Int, List<Value>>,
val heap: HeapValues)
@ -29,6 +30,7 @@ class Program (val name: String,
val heap = HeapValues()
val program = mutableListOf<Instruction>()
val variables = mutableMapOf<String, Value>()
val memoryPointers = mutableMapOf<String, Pair<Int, DataType>>()
val labels = mutableMapOf<String, Instruction>()
while(lines.hasNext()) {
@ -40,16 +42,17 @@ class Program (val name: String,
else if(line=="%heap")
loadHeap(lines, heap)
else if(line.startsWith("%block "))
loadBlock(lines, heap, program, variables, labels)
loadBlock(lines, heap, program, variables, memoryPointers, labels)
else throw VmExecutionException("syntax error at line ${lineNr + 1}")
}
return Program(filename, program, variables, labels, memory, heap)
return Program(filename, program, variables, memoryPointers, labels, memory, heap)
}
private fun loadBlock(lines: Iterator<IndexedValue<String>>,
heap: HeapValues,
program: MutableList<Instruction>,
variables: MutableMap<String, Value>,
memoryPointers: MutableMap<String, Pair<Int, DataType>>,
labels: MutableMap<String, Instruction>)
{
while(true) {
@ -60,6 +63,8 @@ class Program (val name: String,
return
else if(line=="%variables")
loadVars(lines, variables)
else if(line=="%memorypointers")
loadMemoryPointers(lines, memoryPointers, heap)
else if(line=="%instructions") {
val (blockInstructions, blockLabels) = loadInstructions(lines, heap)
program.addAll(blockInstructions)
@ -177,12 +182,12 @@ class Program (val name: String,
}
private fun loadVars(lines: Iterator<IndexedValue<String>>,
vars: MutableMap<String, Value>): Map<String, Value> {
vars: MutableMap<String, Value>) {
val splitpattern = Pattern.compile("\\s+")
while(true) {
val (_, line) = lines.next()
if(line=="%end_variables")
return vars
return
val (name, typeStr, valueStr) = line.split(splitpattern, limit = 3)
if(valueStr[0] !='"' && ':' !in valueStr)
throw VmExecutionException("missing value type character")
@ -220,6 +225,23 @@ class Program (val name: String,
}
}
private fun loadMemoryPointers(lines: Iterator<IndexedValue<String>>,
pointers: MutableMap<String, Pair<Int, DataType>>,
heap: HeapValues) {
val splitpattern = Pattern.compile("\\s+")
while(true) {
val (_, line) = lines.next()
if(line=="%end_memorypointers")
return
val (name, typeStr, valueStr) = line.split(splitpattern, limit = 3)
if(valueStr[0] !='"' && ':' !in valueStr)
throw VmExecutionException("missing value type character")
val type = DataType.valueOf(typeStr.toUpperCase())
val value = getArgValue(valueStr, heap)!!.integerValue()
pointers[name] = Pair(value, type)
}
}
private fun loadMemory(lines: Iterator<IndexedValue<String>>, memory: MutableMap<Int, List<Value>>): Map<Int, List<Value>> {
while(true) {
val (lineNr, line) = lines.next()

View File

@ -104,6 +104,8 @@ class StackVm(private var traceOutputFile: String?) {
private set
var variables = mutableMapOf<String, Value>() // all variables (set of all vars used by all blocks/subroutines) key = their fully scoped name
private set
var memoryPointers = mutableMapOf<String, Pair<Int, DataType>>() // all named pointers
private set
var evalstack = MyStack<Value>()
private set
var callstack = MyStack<Instruction>()
@ -125,6 +127,7 @@ class StackVm(private var traceOutputFile: String?) {
this.canvas = canvas
canvas?.requestFocusInWindow()
variables = program.variables.toMutableMap()
memoryPointers = program.memoryPointers.toMutableMap()
if("A" in variables || "X" in variables || "Y" in variables)
throw VmExecutionException("program contains variable(s) for the reserved registers A/X/Y")
@ -218,6 +221,15 @@ class StackVm(private var traceOutputFile: String?) {
}
private fun getVar(name: String): Value {
val result = variables[name]
if(result!=null)
return result
if(name in memoryPointers)
throw VmExecutionException("variable is memory-mapped: $name = ${memoryPointers[name]}")
throw VmExecutionException("unknown variable: $name")
}
private fun dispatch(ins: Instruction) : Instruction {
traceOutput?.println("\n$ins")
when (ins.opcode) {
@ -749,17 +761,17 @@ class StackVm(private var traceOutputFile: String?) {
return callstack.pop()
}
Opcode.PUSH_VAR_BYTE -> {
val value = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val value = getVar(ins.callLabel!!)
checkDt(value, DataType.UBYTE, DataType.BYTE)
evalstack.push(value)
}
Opcode.PUSH_VAR_WORD -> {
val value = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val value = getVar(ins.callLabel!!)
checkDt(value, *(setOf(DataType.UWORD, DataType.WORD) + IterableDatatypes).toTypedArray())
evalstack.push(value)
}
Opcode.PUSH_VAR_FLOAT -> {
val value = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val value = getVar(ins.callLabel!!)
checkDt(value, DataType.FLOAT)
evalstack.push(value)
}
@ -796,145 +808,145 @@ class StackVm(private var traceOutputFile: String?) {
Opcode.POP_VAR_BYTE -> {
val value = evalstack.pop()
checkDt(value, DataType.UBYTE, DataType.BYTE)
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.UBYTE, DataType.BYTE)
if(value.type!=variable.type)
throw VmExecutionException("datatype mismatch")
variables[ins.callLabel!!] = value
variables[ins.callLabel] = value
}
Opcode.POP_VAR_WORD -> {
val value = evalstack.pop()
checkDt(value, DataType.UWORD, DataType.WORD, DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS)
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.UWORD, DataType.WORD, DataType.STR, DataType.STR_P, DataType.STR_S, DataType.STR_PS)
if(value.type!=variable.type)
throw VmExecutionException("datatype mismatch")
variables[ins.callLabel!!] = value
variables[ins.callLabel] = value
}
Opcode.POP_VAR_FLOAT -> {
val value = evalstack.pop()
checkDt(value, DataType.FLOAT)
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.FLOAT)
variables[ins.callLabel!!] = value
variables[ins.callLabel] = value
}
Opcode.SHL_VAR_BYTE -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.UBYTE)
variables[ins.callLabel!!] = variable.shl()
variables[ins.callLabel] =variable.shl()
}
Opcode.SHL_VAR_WORD -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.UWORD)
variables[ins.callLabel!!] = variable.shl()
variables[ins.callLabel] =variable.shl()
}
Opcode.SHR_VAR_BYTE -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.UBYTE)
variables[ins.callLabel!!] = variable.shr()
variables[ins.callLabel] =variable.shr()
}
Opcode.SHR_VAR_WORD -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.UWORD)
variables[ins.callLabel!!] = variable.shr()
variables[ins.callLabel] =variable.shr()
}
Opcode.ROL_VAR_BYTE -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.UBYTE)
val (newValue, newCarry) = variable.rol(P_carry)
variables[ins.callLabel!!] = newValue
variables[ins.callLabel] =newValue
P_carry = newCarry
}
Opcode.ROL_VAR_WORD -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.UWORD)
val (newValue, newCarry) = variable.rol(P_carry)
variables[ins.callLabel!!] = newValue
variables[ins.callLabel] =newValue
P_carry = newCarry
}
Opcode.ROR_VAR_BYTE -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.UBYTE)
val (newValue, newCarry) = variable.ror(P_carry)
variables[ins.callLabel!!] = newValue
variables[ins.callLabel] =newValue
P_carry = newCarry
}
Opcode.ROR_VAR_WORD -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.UWORD)
val (newValue, newCarry) = variable.ror(P_carry)
variables[ins.callLabel!!] = newValue
variables[ins.callLabel] =newValue
P_carry = newCarry
}
Opcode.ROL2_VAR_BYTE -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.UBYTE)
variables[ins.callLabel!!] = variable.rol2()
variables[ins.callLabel] =variable.rol2()
}
Opcode.ROL2_VAR_WORD -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.UWORD)
variables[ins.callLabel!!] = variable.rol2()
variables[ins.callLabel] =variable.rol2()
}
Opcode.ROR2_VAR_BYTE -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.UBYTE)
variables[ins.callLabel!!] = variable.ror2()
variables[ins.callLabel] =variable.ror2()
}
Opcode.ROR2_VAR_WORD -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.UWORD)
variables[ins.callLabel!!] = variable.ror2()
variables[ins.callLabel] =variable.ror2()
}
Opcode.INC_VAR_UB -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.UBYTE)
variables[ins.callLabel!!] = variable.inc()
variables[ins.callLabel] =variable.inc()
}
Opcode.INC_VAR_B -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.BYTE)
variables[ins.callLabel!!] = variable.inc()
variables[ins.callLabel] =variable.inc()
}
Opcode.INC_VAR_UW -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.UWORD)
variables[ins.callLabel!!] = variable.inc()
variables[ins.callLabel] =variable.inc()
}
Opcode.INC_VAR_W -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.WORD)
variables[ins.callLabel!!] = variable.inc()
variables[ins.callLabel] =variable.inc()
}
Opcode.INC_VAR_F -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.FLOAT)
variables[ins.callLabel!!] = variable.inc()
variables[ins.callLabel] =variable.inc()
}
Opcode.DEC_VAR_UB -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.UBYTE)
variables[ins.callLabel!!] = variable.dec()
variables[ins.callLabel] =variable.dec()
}
Opcode.DEC_VAR_B -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.BYTE)
variables[ins.callLabel!!] = variable.dec()
variables[ins.callLabel] =variable.dec()
}
Opcode.DEC_VAR_UW -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.UWORD)
variables[ins.callLabel!!] = variable.dec()
variables[ins.callLabel] =variable.dec()
}
Opcode.DEC_VAR_W -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.WORD)
variables[ins.callLabel!!] = variable.dec()
variables[ins.callLabel] =variable.dec()
}
Opcode.DEC_VAR_F -> {
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
checkDt(variable, DataType.FLOAT)
variables[ins.callLabel!!] = variable.dec()
variables[ins.callLabel] =variable.dec()
}
Opcode.LSB -> {
val v = evalstack.pop()
@ -1194,7 +1206,7 @@ class StackVm(private var traceOutputFile: String?) {
Opcode.READ_INDEXED_VAR_BYTE -> {
// put the byte value of variable[index] onto the stack
val index = evalstack.pop().integerValue()
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
if(variable.type==DataType.UWORD) {
// assume the variable is a pointer (address) and get the ubyte value from that memory location
evalstack.push(Value(DataType.UBYTE, mem.getUByte(variable.integerValue())))
@ -1212,7 +1224,7 @@ class StackVm(private var traceOutputFile: String?) {
Opcode.READ_INDEXED_VAR_WORD -> {
// put the word value of variable[index] onto the stack
val index = evalstack.pop().integerValue()
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
if(variable.type==DataType.UWORD) {
// assume the variable is a pointer (address) and get the word value from that memory location
evalstack.push(Value(DataType.UWORD, mem.getUWord(variable.integerValue())))
@ -1229,7 +1241,7 @@ class StackVm(private var traceOutputFile: String?) {
Opcode.READ_INDEXED_VAR_FLOAT -> {
// put the f;pat value of variable[index] onto the stack
val index = evalstack.pop().integerValue()
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
val variable = getVar(ins.callLabel!!)
if(variable.type==DataType.UWORD) {
// assume the variable is a pointer (address) and get the float value from that memory location
evalstack.push(Value(DataType.UWORD, mem.getFloat(variable.integerValue())))
@ -1246,25 +1258,44 @@ class StackVm(private var traceOutputFile: String?) {
val index = evalstack.pop().integerValue()
val value = evalstack.pop()
checkDt(value, DataType.UBYTE, DataType.BYTE)
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
if(variable.type==DataType.UWORD) {
// assume the variable is a pointer (address) and write the byte value to that memory location
mem.setUByte(variable.integerValue(), value.integerValue().toShort())
val varname = ins.callLabel!!
val memloc = memoryPointers[varname]
if(memloc!=null) {
// variable is the name of a pointer, write the byte value to that memory location
if(value.type==DataType.UBYTE) {
if(memloc.second!=DataType.ARRAY_UB)
throw VmExecutionException("invalid memory pointer type $memloc")
mem.setUByte(memloc.first, value.integerValue().toShort())
}
else {
if(memloc.second!=DataType.ARRAY_B)
throw VmExecutionException("invalid memory pointer type $memloc")
mem.setSByte(memloc.first, value.integerValue().toShort())
}
} else {
// set indexed byte element in the arrayspec
val array = heap.get(variable.heapId)
when(array.type) {
DataType.ARRAY_UB -> array.array!![index] = value.integerValue()
DataType.ARRAY_B -> array.array!![index] = value.integerValue()
DataType.STR,
DataType.STR_P,
DataType.STR_S,
DataType.STR_PS -> {
val chars = array.str!!.toCharArray()
chars[index] = Petscii.decodePetscii(listOf(value.integerValue().toShort()), true)[0]
heap.update(variable.heapId, chars.joinToString(""))
val variable = getVar(varname)
if (variable.type == DataType.UWORD) {
// assume the variable is a pointer (address) and write the byte value to that memory location
if(value.type==DataType.UBYTE)
mem.setUByte(variable.integerValue(), value.integerValue().toShort())
else
mem.setSByte(variable.integerValue(), value.integerValue().toShort())
} else {
// set indexed byte element in the arrayspec
val array = heap.get(variable.heapId)
when (array.type) {
DataType.ARRAY_UB -> array.array!![index] = value.integerValue()
DataType.ARRAY_B -> array.array!![index] = value.integerValue()
DataType.STR,
DataType.STR_P,
DataType.STR_S,
DataType.STR_PS -> {
val chars = array.str!!.toCharArray()
chars[index] = Petscii.decodePetscii(listOf(value.integerValue().toShort()), true)[0]
heap.update(variable.heapId, chars.joinToString(""))
}
else -> throw VmExecutionException("not a proper array/string var with byte elements")
}
else -> throw VmExecutionException("not a proper array/string var with byte elements")
}
}
}
@ -1273,19 +1304,37 @@ class StackVm(private var traceOutputFile: String?) {
val index = evalstack.pop().integerValue()
val value = evalstack.pop()
checkDt(value, DataType.UWORD, DataType.WORD)
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
if(variable.type==DataType.UWORD) {
// assume the variable is a pointer (address) and write the word value to that memory location
mem.setUWord(variable.integerValue(), value.integerValue())
} else {
// set indexed word element in the arrayspec
val array = heap.get(variable.heapId)
when(array.type) {
DataType.ARRAY_UW -> array.array!![index] = value.integerValue()
DataType.ARRAY_W -> array.array!![index] = value.integerValue()
else -> throw VmExecutionException("not a proper arrayspec var with word elements")
val varname = ins.callLabel!!
val memloc = memoryPointers[varname]
if(memloc!=null) {
// variable is the name of a pointer, write the word value to that memory location
if(value.type==DataType.UWORD) {
if(memloc.second!=DataType.ARRAY_UW)
throw VmExecutionException("invalid memory pointer type $memloc")
mem.setUWord(memloc.first, value.integerValue())
}
else {
if(memloc.second!=DataType.ARRAY_W)
throw VmExecutionException("invalid memory pointer type $memloc")
mem.setSWord(memloc.first, value.integerValue())
}
} else {
val variable = getVar(varname)
if (variable.type == DataType.UWORD) {
// assume the variable is a pointer (address) and write the word value to that memory location
if(value.type==DataType.UWORD)
mem.setUWord(variable.integerValue(), value.integerValue())
else
mem.setSWord(variable.integerValue(), value.integerValue())
} else {
// set indexed word element in the arrayspec
val array = heap.get(variable.heapId)
when (array.type) {
DataType.ARRAY_UW -> array.array!![index] = value.integerValue()
DataType.ARRAY_W -> array.array!![index] = value.integerValue()
else -> throw VmExecutionException("not a proper arrayspec var with word elements")
}
}
}
}
Opcode.WRITE_INDEXED_VAR_FLOAT -> {
@ -1293,16 +1342,25 @@ class StackVm(private var traceOutputFile: String?) {
val index = evalstack.pop().integerValue()
val value = evalstack.pop()
checkDt(value, DataType.FLOAT)
val variable = variables[ins.callLabel] ?: throw VmExecutionException("unknown variable: ${ins.callLabel}")
if(variable.type==DataType.UWORD) {
// assume the variable is a pointer (address) and write the float value to that memory location
mem.setFloat(variable.integerValue(), value.numericValue().toDouble())
val varname = ins.callLabel!!
val memloc = memoryPointers[varname]
if(memloc!=null) {
// variable is the name of a pointer, write the float value to that memory location
if(memloc.second!=DataType.ARRAY_F)
throw VmExecutionException("invalid memory pointer type $memloc")
mem.setFloat(memloc.first, value.numericValue().toDouble())
} else {
// set indexed float element in the arrayspec
val array = heap.get(variable.heapId)
if(array.type!=DataType.ARRAY_F)
throw VmExecutionException("not a proper arrayspec var with float elements")
array.doubleArray!![index] = value.numericValue().toDouble()
val variable = getVar(varname)
if (variable.type == DataType.UWORD) {
// assume the variable is a pointer (address) and write the float value to that memory location
mem.setFloat(variable.integerValue(), value.numericValue().toDouble())
} else {
// set indexed float element in the arrayspec
val array = heap.get(variable.heapId)
if (array.type != DataType.ARRAY_F)
throw VmExecutionException("not a proper arrayspec var with float elements")
array.doubleArray!![index] = value.numericValue().toDouble()
}
}
}
Opcode.RSAVE -> {

View File

@ -51,12 +51,13 @@ class TestStackVmOpcodes {
private val vm = StackVm(null)
fun makeProg(ins: MutableList<Instruction>,
private fun makeProg(ins: MutableList<Instruction>,
vars: Map<String, Value>?=null,
memoryPointers: Map<String, Pair<Int, DataType>>?=null,
labels: Map<String, Instruction>?=null,
mem: Map<Int, List<Value>>?=null) : Program {
val heap = HeapValues()
return Program("test", ins, vars ?: mapOf(), labels ?: mapOf(), mem ?: mapOf(), heap)
return Program("test", ins, vars ?: mapOf(), memoryPointers ?: mapOf(), labels ?: mapOf(), mem ?: mapOf(), heap)
}
@Test

View File

@ -45,9 +45,15 @@ w2float
push_float
rts
push_float_from_indexed_var
rts
pop_var_float
rts
pop_float_to_indexed_var
rts
pop_mem_float
rts