mirror of
https://github.com/irmen/prog8.git
synced 2025-08-09 03:25:24 +00:00
workin on vm issues
This commit is contained in:
@@ -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()
|
||||
|
||||
|
120
codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt
Normal file
120
codeGenVirtual/src/prog8/codegen/virtual/BuiltinFuncGen.kt
Normal 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
|
||||
}
|
||||
|
||||
}
|
@@ -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)
|
||||
}
|
||||
|
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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 {
|
||||
|
@@ -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
|
||||
|
136
examples/test.p8
136
examples/test.p8
@@ -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()
|
||||
; }
|
||||
}
|
||||
}
|
||||
|
@@ -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())
|
||||
|
@@ -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()
|
||||
|
Reference in New Issue
Block a user