workin on vm issues

This commit is contained in:
Irmen de Jong
2022-03-28 01:49:43 +02:00
parent e166329f34
commit 6d79903eb3
9 changed files with 248 additions and 188 deletions

View File

@@ -39,15 +39,7 @@ internal class AssemblyProgram(override val name: String,
when(line) {
is VmCodeComment -> write("; ${line.comment}\n")
is VmCodeInstruction -> {
write(line.ins.toString())
if(line.labelArg!=null) {
if (line.ins.reg1 != null || line.ins.reg2 != null || line.ins.reg3 != null || line.ins.value != null)
write(",")
else
write(" ")
write("_" + line.labelArg.joinToString("."))
}
write("\n")
write(line.ins.toString() + "\n")
}
is VmCodeLabel -> write("_" + line.name.joinToString(".") + ":\n")
}
@@ -59,7 +51,7 @@ internal class AssemblyProgram(override val name: String,
internal sealed class VmCodeLine
internal class VmCodeInstruction(val ins: Instruction, val labelArg: List<String>?=null): VmCodeLine()
internal class VmCodeInstruction(val ins: Instruction): VmCodeLine()
internal class VmCodeLabel(val name: List<String>): VmCodeLine()
internal class VmCodeComment(val comment: String): VmCodeLine()

View File

@@ -0,0 +1,120 @@
package prog8.codegen.virtual
import prog8.code.ast.PtBuiltinFunctionCall
import prog8.code.ast.PtNumber
import prog8.code.ast.PtString
import prog8.vm.Instruction
import prog8.vm.Opcode
import prog8.vm.Syscall
import prog8.vm.VmDataType
internal class BuiltinFuncGen(val codeGen: CodeGen, val exprGen: ExpressionGen) {
fun translate(call: PtBuiltinFunctionCall, resultRegister: Int, regUsage: RegisterUsage): VmCodeChunk {
val code = VmCodeChunk()
when(call.name) {
"syscall" -> {
val vExpr = call.args.single() as PtNumber
code += VmCodeInstruction(Instruction(Opcode.SYSCALL, value=vExpr.number.toInt()))
}
"syscall1" -> {
code += VmCodeInstruction(Instruction(Opcode.PUSH, VmDataType.BYTE, reg1 = 0))
val callNr = (call.args[0] as PtNumber).number.toInt()
code += exprGen.translateExpression(call.args[1], 0, regUsage)
code += VmCodeInstruction(Instruction(Opcode.SYSCALL, value=callNr))
code += VmCodeInstruction(Instruction(Opcode.POP, VmDataType.BYTE, reg1 = 0))
}
"syscall2" -> {
code += VmCodeInstruction(Instruction(Opcode.PUSH, VmDataType.BYTE, reg1 = 0))
code += VmCodeInstruction(Instruction(Opcode.PUSH, VmDataType.WORD, reg1 = 1))
while(regUsage.firstFree<2) {
regUsage.nextFree()
}
val callNr = (call.args[0] as PtNumber).number.toInt()
code += exprGen.translateExpression(call.args[1], 0, regUsage)
code += exprGen.translateExpression(call.args[2], 1, regUsage)
code += VmCodeInstruction(Instruction(Opcode.SYSCALL, value=callNr))
code += VmCodeInstruction(Instruction(Opcode.POP, VmDataType.WORD, reg1 = 1))
code += VmCodeInstruction(Instruction(Opcode.POP, VmDataType.BYTE, reg1 = 0))
}
"syscall3" -> {
code += VmCodeInstruction(Instruction(Opcode.PUSH, VmDataType.BYTE, reg1 = 0))
code += VmCodeInstruction(Instruction(Opcode.PUSH, VmDataType.WORD, reg1 = 1))
code += VmCodeInstruction(Instruction(Opcode.PUSH, VmDataType.WORD, reg1 = 2))
while(regUsage.firstFree<3) {
regUsage.nextFree()
}
val callNr = (call.args[0] as PtNumber).number.toInt()
code += exprGen.translateExpression(call.args[1], 0, regUsage)
code += exprGen.translateExpression(call.args[2], 1, regUsage)
code += exprGen.translateExpression(call.args[3], 2, regUsage)
code += VmCodeInstruction(Instruction(Opcode.SYSCALL, value=callNr))
code += VmCodeInstruction(Instruction(Opcode.POP, VmDataType.WORD, reg1 = 2))
code += VmCodeInstruction(Instruction(Opcode.POP, VmDataType.WORD, reg1 = 1))
code += VmCodeInstruction(Instruction(Opcode.POP, VmDataType.BYTE, reg1 = 0))
}
"msb" -> {
code += exprGen.translateExpression(call.args.single(), resultRegister, regUsage)
code += VmCodeInstruction(Instruction(Opcode.SWAP, VmDataType.BYTE, reg1 = resultRegister, reg2=resultRegister))
// note: if a word result is needed, the upper byte is cleared by the typecast that follows. No need to do it here.
}
"lsb" -> {
code += exprGen.translateExpression(call.args.single(), resultRegister, regUsage)
// note: if a word result is needed, the upper byte is cleared by the typecast that follows. No need to do it here.
}
"memory" -> {
val name = (call.args[0] as PtString).value
val size = (call.args[1] as PtNumber).number.toUInt()
val align = (call.args[2] as PtNumber).number.toUInt()
val existing = codeGen.allocations.getMemorySlab(name)
val address = if(existing==null)
codeGen.allocations.allocateMemorySlab(name, size, align)
else if(existing.second!=size || existing.third!=align) {
codeGen.errors.err("memory slab '$name' already exists with a different size or alignment", call.position)
return VmCodeChunk()
}
else
existing.first
code += VmCodeInstruction(Instruction(Opcode.LOAD, VmDataType.WORD, reg1=resultRegister, value=address.toInt()))
}
"rnd" -> {
code += VmCodeInstruction(Instruction(Opcode.SYSCALL, value= Syscall.RND.ordinal))
if(resultRegister!=0)
code += VmCodeInstruction(Instruction(Opcode.LOADR, VmDataType.BYTE, reg1=resultRegister, reg2=0))
}
"peek" -> {
val addressReg = regUsage.nextFree()
code += exprGen.translateExpression(call.args.single(), addressReg, regUsage)
code += VmCodeInstruction(Instruction(Opcode.LOADI, VmDataType.BYTE, reg1 = resultRegister, reg2=addressReg))
}
"peekw" -> {
val addressReg = regUsage.nextFree()
code += exprGen.translateExpression(call.args.single(), addressReg, regUsage)
code += VmCodeInstruction(Instruction(Opcode.LOADI, VmDataType.WORD, reg1 = resultRegister, reg2=addressReg))
}
else -> {
TODO("builtinfunc ${call.name}")
// code += VmCodeInstruction(Instruction(Opcode.NOP))
// for (arg in call.args) {
// code += translateExpression(arg, resultRegister, regUsage)
// code += when(arg.type) {
// in ByteDatatypes -> VmCodeInstruction(Instruction(Opcode.PUSH, VmDataType.BYTE, reg1=resultRegister))
// in WordDatatypes -> VmCodeInstruction(Instruction(Opcode.PUSH, VmDataType.WORD, reg1=resultRegister))
// else -> throw AssemblyError("weird arg dt")
// }
// }
// code += VmCodeInstruction(Instruction(Opcode.CALL), labelArg = listOf("_prog8_builtin", call.name))
// for (arg in call.args) {
// code += when(arg.type) {
// in ByteDatatypes -> VmCodeInstruction(Instruction(Opcode.POP, VmDataType.BYTE, reg1=resultRegister))
// in WordDatatypes -> VmCodeInstruction(Instruction(Opcode.POP, VmDataType.WORD, reg1=resultRegister))
// else -> throw AssemblyError("weird arg dt")
// }
// }
// code += VmCodeInstruction(Instruction(Opcode.NOP))
}
}
return code
}
}

View File

@@ -17,6 +17,7 @@ class CodeGen(internal val program: PtProgram,
internal val allocations = VariableAllocator(symbolTable, program, errors)
private val expressionEval = ExpressionGen(this)
private val builtinFuncGen = BuiltinFuncGen(this, expressionEval)
init {
if(options.dontReinitGlobals)
@@ -52,7 +53,7 @@ class CodeGen(internal val program: PtProgram,
is PtConstant -> VmCodeChunk() // constants have all been folded into the code
is PtAssignment -> translate(node, regUsage)
is PtNodeGroup -> translateGroup(node.children, regUsage)
is PtBuiltinFunctionCall -> expressionEval.translate(node, regUsage.nextFree(), regUsage)
is PtBuiltinFunctionCall -> translateBuiltinFunc(node, regUsage.nextFree(), regUsage)
is PtFunctionCall -> expressionEval.translate(node, regUsage.nextFree(), regUsage)
is PtNop -> VmCodeChunk()
is PtReturn -> translate(node)
@@ -140,16 +141,16 @@ class CodeGen(internal val program: PtProgram,
// if and else parts
val elseLabel = createLabelName()
val afterIfLabel = createLabelName()
code += VmCodeInstruction(Instruction(branch, vmDt, reg1=conditionReg), labelArg = elseLabel)
code += VmCodeInstruction(Instruction(branch, vmDt, reg1=conditionReg, symbol = elseLabel))
code += translateNode(ifElse.ifScope, regUsage)
code += VmCodeInstruction(Instruction(Opcode.JUMP), labelArg = afterIfLabel)
code += VmCodeInstruction(Instruction(Opcode.JUMP, symbol = afterIfLabel))
code += VmCodeLabel(elseLabel)
code += translateNode(ifElse.elseScope, regUsage)
code += VmCodeLabel(afterIfLabel)
} else {
// only if part
val afterIfLabel = createLabelName()
code += VmCodeInstruction(Instruction(branch, vmDt, reg1=conditionReg), labelArg = afterIfLabel)
code += VmCodeInstruction(Instruction(branch, vmDt, reg1=conditionReg, symbol = afterIfLabel))
code += translateNode(ifElse.ifScope, regUsage)
code += VmCodeLabel(afterIfLabel)
}
@@ -205,7 +206,7 @@ class CodeGen(internal val program: PtProgram,
code += VmCodeLabel(repeatLabel)
code += translateNode(repeat.statements, regUsage)
code += VmCodeInstruction(Instruction(Opcode.DEC, vmDt, reg1=counterReg))
code += VmCodeInstruction(Instruction(Opcode.BNZ, vmDt, reg1=counterReg), labelArg = repeatLabel)
code += VmCodeInstruction(Instruction(Opcode.BNZ, vmDt, reg1=counterReg, symbol = repeatLabel))
return code
}
@@ -214,9 +215,9 @@ class CodeGen(internal val program: PtProgram,
if(jump.address!=null)
throw AssemblyError("cannot jump to memory location in the vm target")
code += if(jump.generatedLabel!=null)
VmCodeInstruction(Instruction(Opcode.JUMP), labelArg = listOf(jump.generatedLabel!!))
VmCodeInstruction(Instruction(Opcode.JUMP, symbol = listOf(jump.generatedLabel!!)))
else if(jump.identifier!=null)
VmCodeInstruction(Instruction(Opcode.JUMP), labelArg = jump.identifier!!.targetName)
VmCodeInstruction(Instruction(Opcode.JUMP, symbol = jump.identifier!!.targetName))
else
throw AssemblyError("weird jump")
return code
@@ -325,4 +326,7 @@ class CodeGen(internal val program: PtProgram,
labelSequenceNumber++
return listOf("generated$labelSequenceNumber")
}
internal fun translateBuiltinFunc(call: PtBuiltinFunctionCall, resultRegister: Int, regUsage: RegisterUsage): VmCodeChunk =
builtinFuncGen.translate(call, resultRegister, regUsage)
}

View File

@@ -3,10 +3,12 @@ package prog8.codegen.virtual
import prog8.code.StStaticVariable
import prog8.code.StSub
import prog8.code.ast.*
import prog8.code.core.*
import prog8.code.core.AssemblyError
import prog8.code.core.DataType
import prog8.code.core.PassByValueDatatypes
import prog8.code.core.SignedDatatypes
import prog8.vm.Instruction
import prog8.vm.Opcode
import prog8.vm.Syscall
import prog8.vm.VmDataType
@@ -52,7 +54,7 @@ internal class ExpressionGen(val codeGen: CodeGen) {
is PtPrefix -> code += translate(expr, resultRegister, regUsage)
is PtArrayIndexer -> code += translate(expr, resultRegister, regUsage)
is PtBinaryExpression -> code += translate(expr, resultRegister, regUsage)
is PtBuiltinFunctionCall -> code += translate(expr, resultRegister, regUsage)
is PtBuiltinFunctionCall -> code += codeGen.translateBuiltinFunc(expr, resultRegister, regUsage)
is PtFunctionCall -> code += translate(expr, resultRegister, regUsage)
is PtContainmentCheck -> code += translate(expr, resultRegister, regUsage)
is PtPipe -> code += translate(expr, resultRegister, regUsage)
@@ -132,7 +134,7 @@ internal class ExpressionGen(val codeGen: CodeGen) {
}
"not" -> {
val label = codeGen.createLabelName()
code += VmCodeInstruction(Instruction(Opcode.BZ, vmDt, reg1=resultRegister), labelArg = label)
code += VmCodeInstruction(Instruction(Opcode.BZ, vmDt, reg1=resultRegister, symbol = label))
code += VmCodeInstruction(Instruction(Opcode.LOAD, vmDt, reg1=resultRegister, value=1))
code += VmCodeLabel(label)
val regMask = regUsage.nextFree()
@@ -300,7 +302,7 @@ internal class ExpressionGen(val codeGen: CodeGen) {
val mem = codeGen.allocations.get(fcall.functionName + parameter.name)
code += VmCodeInstruction(Instruction(Opcode.STOREM, vmDt, reg1=argReg, value=mem))
}
code += VmCodeInstruction(Instruction(Opcode.CALL), labelArg=fcall.functionName)
code += VmCodeInstruction(Instruction(Opcode.CALL, symbol=fcall.functionName))
if(!fcall.void && resultRegister!=0) {
// Call convention: result value is in r0, so put it in the required register instead. TODO does this work correctly?
code += VmCodeInstruction(Instruction(Opcode.LOADR, codeGen.vmType(fcall.type), reg1=resultRegister, reg2=0))
@@ -308,111 +310,4 @@ internal class ExpressionGen(val codeGen: CodeGen) {
return code
}
fun translate(call: PtBuiltinFunctionCall, resultRegister: Int, regUsage: RegisterUsage): VmCodeChunk {
val code = VmCodeChunk()
when(call.name) {
"syscall" -> {
val vExpr = call.args.single() as PtNumber
code += VmCodeInstruction(Instruction(Opcode.SYSCALL, value=vExpr.number.toInt()))
}
"syscall1" -> {
code += VmCodeInstruction(Instruction(Opcode.PUSH, VmDataType.BYTE, reg1 = 0))
val callNr = (call.args[0] as PtNumber).number.toInt()
code += translateExpression(call.args[1], 0, regUsage)
code += VmCodeInstruction(Instruction(Opcode.SYSCALL, value=callNr))
code += VmCodeInstruction(Instruction(Opcode.POP, VmDataType.BYTE, reg1 = 0))
}
"syscall2" -> {
code += VmCodeInstruction(Instruction(Opcode.PUSH, VmDataType.BYTE, reg1 = 0))
code += VmCodeInstruction(Instruction(Opcode.PUSH, VmDataType.WORD, reg1 = 1))
while(regUsage.firstFree<2) {
regUsage.nextFree()
}
val callNr = (call.args[0] as PtNumber).number.toInt()
code += translateExpression(call.args[1], 0, regUsage)
code += translateExpression(call.args[2], 1, regUsage)
code += VmCodeInstruction(Instruction(Opcode.SYSCALL, value=callNr))
code += VmCodeInstruction(Instruction(Opcode.POP, VmDataType.WORD, reg1 = 1))
code += VmCodeInstruction(Instruction(Opcode.POP, VmDataType.BYTE, reg1 = 0))
}
"syscall3" -> {
code += VmCodeInstruction(Instruction(Opcode.PUSH, VmDataType.BYTE, reg1 = 0))
code += VmCodeInstruction(Instruction(Opcode.PUSH, VmDataType.WORD, reg1 = 1))
code += VmCodeInstruction(Instruction(Opcode.PUSH, VmDataType.WORD, reg1 = 2))
while(regUsage.firstFree<3) {
regUsage.nextFree()
}
val callNr = (call.args[0] as PtNumber).number.toInt()
code += translateExpression(call.args[1], 0, regUsage)
code += translateExpression(call.args[2], 1, regUsage)
code += translateExpression(call.args[3], 2, regUsage)
code += VmCodeInstruction(Instruction(Opcode.SYSCALL, value=callNr))
code += VmCodeInstruction(Instruction(Opcode.POP, VmDataType.WORD, reg1 = 2))
code += VmCodeInstruction(Instruction(Opcode.POP, VmDataType.WORD, reg1 = 1))
code += VmCodeInstruction(Instruction(Opcode.POP, VmDataType.BYTE, reg1 = 0))
}
"msb" -> {
code += translateExpression(call.args.single(), resultRegister, regUsage)
code += VmCodeInstruction(Instruction(Opcode.SWAP, VmDataType.BYTE, reg1 = resultRegister, reg2=resultRegister))
// note: if a word result is needed, the upper byte is cleared by the typecast that follows. No need to do it here.
}
"lsb" -> {
code += translateExpression(call.args.single(), resultRegister, regUsage)
// note: if a word result is needed, the upper byte is cleared by the typecast that follows. No need to do it here.
}
"memory" -> {
val name = (call.args[0] as PtString).value
val size = (call.args[1] as PtNumber).number.toUInt()
val align = (call.args[2] as PtNumber).number.toUInt()
val existing = codeGen.allocations.getMemorySlab(name)
val address = if(existing==null)
codeGen.allocations.allocateMemorySlab(name, size, align)
else if(existing.second!=size || existing.third!=align) {
codeGen.errors.err("memory slab '$name' already exists with a different size or alignment", call.position)
return VmCodeChunk()
}
else
existing.first
code += VmCodeInstruction(Instruction(Opcode.LOAD, VmDataType.WORD, reg1=resultRegister, value=address.toInt()))
}
"rnd" -> {
code += VmCodeInstruction(Instruction(Opcode.SYSCALL, value=Syscall.RND.ordinal))
if(resultRegister!=0)
code += VmCodeInstruction(Instruction(Opcode.LOADR, VmDataType.BYTE, reg1=resultRegister, reg2=0))
}
"peek" -> {
val addressReg = regUsage.nextFree()
code += translateExpression(call.args.single(), addressReg, regUsage)
code += VmCodeInstruction(Instruction(Opcode.LOADI, VmDataType.BYTE, reg1 = resultRegister, reg2=addressReg))
}
"peekw" -> {
val addressReg = regUsage.nextFree()
code += translateExpression(call.args.single(), addressReg, regUsage)
code += VmCodeInstruction(Instruction(Opcode.LOADI, VmDataType.WORD, reg1 = resultRegister, reg2=addressReg))
}
else -> {
TODO("builtinfunc ${call.name}")
// code += VmCodeInstruction(Instruction(Opcode.NOP))
// for (arg in call.args) {
// code += translateExpression(arg, resultRegister, regUsage)
// code += when(arg.type) {
// in ByteDatatypes -> VmCodeInstruction(Instruction(Opcode.PUSH, VmDataType.BYTE, reg1=resultRegister))
// in WordDatatypes -> VmCodeInstruction(Instruction(Opcode.PUSH, VmDataType.WORD, reg1=resultRegister))
// else -> throw AssemblyError("weird arg dt")
// }
// }
// code += VmCodeInstruction(Instruction(Opcode.CALL), labelArg = listOf("_prog8_builtin", call.name))
// for (arg in call.args) {
// code += when(arg.type) {
// in ByteDatatypes -> VmCodeInstruction(Instruction(Opcode.POP, VmDataType.BYTE, reg1=resultRegister))
// in WordDatatypes -> VmCodeInstruction(Instruction(Opcode.POP, VmDataType.WORD, reg1=resultRegister))
// else -> throw AssemblyError("weird arg dt")
// }
// }
// code += VmCodeInstruction(Instruction(Opcode.NOP))
}
}
return code
}
}

View File

@@ -69,7 +69,11 @@ print_ones:
sub print_b (byte value) {
; ---- print the byte in decimal form, without left padding 0s
; TODO use conv module?
if value<0 {
chrout('-')
value = -value
}
print_ub(value as ubyte)
}
str hex_digits = "0123456789abcdef"
@@ -150,7 +154,11 @@ print_ones:
sub print_w (word value) {
; ---- print the (signed) word in decimal form, without left padding 0's
; TODO use conv module?
if value<0 {
chrout('-')
value = -value
}
print_uw(value as uword)
}
sub input_chars (uword buffer) -> ubyte {

View File

@@ -3,6 +3,7 @@ TODO
For next release
^^^^^^^^^^^^^^^^
- vm codegen: fix ifelse comparisons such as if x< 0
- vm codegen: fix primes endless loop stuck on '2'
- x16: check joystick support (petaxian, own stuff) because of api change in r39 kernal https://github.com/commanderx16/x16-docs/blob/master/Commander%20X16%20Programmer's%20Reference%20Guide.md#function-name-joystick_get
- x16: screen_set_mode -> screen_mode + other args https://github.com/commanderx16/x16-docs/blob/master/Commander%20X16%20Programmer's%20Reference%20Guide.md#function-name-screen_mode

View File

@@ -4,66 +4,102 @@
main {
sub start() {
txt.clear_screen()
txt.print("Welcome to a prog8 pixel shader :-)\n")
uword ww = 0
ubyte bc
uword wc
for bc in "irmen" {
; +5 -> 17
txt.chrout(bc)
ww++
byte bb = -9
word ww = -1234
if bb<0 {
txt.print("bb <0!\n")
} else {
txt.print("comparison error!\n")
}
txt.print_uw(ww)
txt.nl()
for wc in [1000,1111,1222] {
txt.print_uw(wc)
txt.spc()
ww++ ; +3 -> 20
if ww<0 {
txt.print("ww <0!\n")
} else {
txt.print("comparison error!\n")
}
txt.print_uw(ww)
txt.nl()
for bc in 10 to 20 step 3 {
; 10,13,16,19 -> 4
ww++
if bb>0 {
txt.print("comparison error!\n")
} else {
txt.print("bb not >0\n")
}
txt.print_uw(ww)
txt.nl()
for bc in 30 to 10 step -4 {
; 30,26,22,18,14,10,6,2 -> +8 -> 12
ww++
if ww>0 {
txt.print("comparison error!\n")
} else {
txt.print("ww not >0\n")
}
txt.print_uw(ww)
txt.nl()
txt.print_w(ww)
txt.spc()
ww <<= 3
txt.print_w(ww)
txt.nl()
txt.print_b(bb)
txt.spc()
bb <<= 3
txt.print_b(bb)
txt.nl()
sys.exit(99)
; txt.clear_screen()
; txt.print("Welcome to a prog8 pixel shader :-)\n")
; uword ww = 0
; ubyte bc
; uword wc
;
; for bc in "irmen" {
; ; +5 -> 17
; txt.chrout(bc)
; ww++
; }
; txt.print_uw(ww)
; txt.nl()
;
; for wc in [1000,1111,1222] {
; txt.print_uw(wc)
; txt.spc()
; ww++ ; +3 -> 20
; }
; txt.print_uw(ww)
; txt.nl()
;
; for bc in 10 to 20 step 3 {
; ; 10,13,16,19 -> 4
; ww++
; }
; txt.print_uw(ww)
; txt.nl()
; for bc in 30 to 10 step -4 {
; ; 30,26,22,18,14,10,6,2 -> +8 -> 12
; ww++
; }
; txt.print_uw(ww)
; txt.nl()
;
;
; sys.exit(99)
syscall1(8, 0) ; enable lo res creen
ubyte shifter
shifter >>= 1
repeat {
uword xx
uword yy = 0
repeat 240 {
xx = 0
repeat 320 {
syscall3(10, xx, yy, xx*yy + shifter) ; plot pixel
xx++
}
yy++
}
shifter+=4
txt.print_ub(shifter)
txt.nl()
}
; syscall1(8, 0) ; enable lo res creen
; ubyte shifter
;
; shifter >>= 1
;
; repeat {
; uword xx
; uword yy = 0
; repeat 240 {
; xx = 0
; repeat 320 {
; syscall3(10, xx, yy, xx*yy + shifter) ; plot pixel
; xx++
; }
; yy++
; }
; shifter+=4
;
; txt.print_ub(shifter)
; txt.nl()
; }
}
}

View File

@@ -29,14 +29,14 @@ class Assembler {
val string = unescape(values.trim('"'))
memory.setString(address, string, true)
}
"ubyte" -> {
"ubyte", "byte" -> {
val array = values.split(',').map { parseValue(it.trim(), 0) }
for (value in array) {
memory.setB(address, value.toUByte())
address++
}
}
"uword" -> {
"uword", "word" -> {
val array = values.split(',').map { parseValue(it.trim(), 0) }
for (value in array) {
memory.setW(address, value.toUShort())

View File

@@ -216,11 +216,11 @@ enum class VmDataType {
data class Instruction(
val opcode: Opcode,
val type: VmDataType?=null,
val reg1: Int?=null, // 0-$ffff
val reg2: Int?=null, // 0-$ffff
val reg3: Int?=null, // 0-$ffff
val value: Int?=null, // 0-$ffff
// TODO add string symbol here as alternative to value
val reg1: Int?=null, // 0-$ffff
val reg2: Int?=null, // 0-$ffff
val reg3: Int?=null, // 0-$ffff
val value: Int?=null, // 0-$ffff
val symbol: List<String>?=null // alternative to value
) {
override fun toString(): String {
val result = mutableListOf(opcode.name.lowercase())
@@ -246,6 +246,10 @@ data class Instruction(
}
value?.let {
result.add(it.toString())
result.add(",")
}
symbol?.let {
result.add("_" + it.joinToString("."))
}
if(result.last() == ",")
result.removeLast()