diff --git a/codeCore/src/prog8/code/ast/AstExpressions.kt b/codeCore/src/prog8/code/ast/AstExpressions.kt index 60a6a8a15..b811cf22c 100644 --- a/codeCore/src/prog8/code/ast/AstExpressions.kt +++ b/codeCore/src/prog8/code/ast/AstExpressions.kt @@ -44,7 +44,7 @@ sealed class PtExpression(val type: DataType, position: Position) : PtNode(posit } is PtContainmentCheck -> other is PtContainmentCheck && other.type==type && other.element isSameAs element && other.iterable isSameAs iterable is PtIdentifier -> other is PtIdentifier && other.type==type && other.name==name - is PtMachineRegister -> other is PtMachineRegister && other.type==type && other.register==register + is PtIrRegister -> other is PtIrRegister && other.type==type && other.register==register is PtMemoryByte -> other is PtMemoryByte && other.address isSameAs address is PtNumber -> other is PtNumber && other.type==type && other.number==number is PtBool -> other is PtBool && other.value==value @@ -87,7 +87,7 @@ sealed class PtExpression(val type: DataType, position: Position) : PtNode(posit is PtContainmentCheck -> false is PtFunctionCall -> false is PtIdentifier -> true - is PtMachineRegister -> true + is PtIrRegister -> true is PtMemoryByte -> address is PtNumber || address is PtIdentifier is PtBool -> true is PtNumber -> true @@ -354,7 +354,7 @@ class PtTypeCast(type: DataType, position: Position) : PtExpression(type, positi // special node that isn't created from compiling user code, but used internally in the Intermediate Code -class PtMachineRegister(val register: Int, type: DataType, position: Position) : PtExpression(type, position) +class PtIrRegister(val register: Int, type: DataType, position: Position) : PtExpression(type, position) fun constValue(expr: PtExpression): Double? = if(expr is PtNumber) expr.number else if(expr is PtBool) expr.asInt().toDouble() else null diff --git a/codeCore/src/prog8/code/ast/AstPrinter.kt b/codeCore/src/prog8/code/ast/AstPrinter.kt index e0dea1077..cfc4d8d58 100644 --- a/codeCore/src/prog8/code/ast/AstPrinter.kt +++ b/codeCore/src/prog8/code/ast/AstPrinter.kt @@ -34,7 +34,7 @@ fun printAst(root: PtNode, skipLibraries: Boolean, output: (text: String) -> Uni str + node.name + "()" } is PtIdentifier -> "${node.name} ${type(node.type)}" - is PtMachineRegister -> "VMREG#${node.register} ${type(node.type)}" + is PtIrRegister -> "VMREG#${node.register} ${type(node.type)}" is PtMemoryByte -> "@()" is PtNumber -> { val numstr = if(node.type == DataType.FLOAT) node.number.toString() else node.number.toHex() diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt index 69c72db4f..f4272161a 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/FunctionCallAsmGen.kt @@ -81,7 +81,7 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as } is PtAddressOf -> false is PtIdentifier -> false - is PtMachineRegister -> false + is PtIrRegister -> false is PtMemoryByte -> return usesOtherRegistersWhileEvaluating(arg.address) is PtNumber -> false is PtBool -> false diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/IfElseAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/IfElseAsmGen.kt index 5c5063463..fdfa3e21e 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/IfElseAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/IfElseAsmGen.kt @@ -70,7 +70,7 @@ internal class IfElseAsmGen(private val program: PtProgram, is PtNumber, is PtBool, is PtIdentifier, - is PtMachineRegister, + is PtIrRegister, is PtArrayIndexer, is PtPrefix, is PtBinaryExpression -> { /* no cmp necessary the lda has been done just prior */ } diff --git a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt index e5775599b..38e228aa5 100644 --- a/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt +++ b/codeGenCpu6502/src/prog8/codegen/cpu6502/assignment/AssignmentAsmGen.kt @@ -667,7 +667,7 @@ internal class AssignmentAsmGen(private val program: PtProgram, internal fun directIntoY(expr: PtExpression): Boolean { return when(expr) { is PtIdentifier -> true - is PtMachineRegister -> true + is PtIrRegister -> true is PtNumber -> true is PtBuiltinFunctionCall -> expr.name in arrayOf("lsb", "msb") else -> false diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt index 92cf32e75..9c8bbe908 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/AssignmentGen.kt @@ -8,7 +8,7 @@ import prog8.intermediate.* internal class AssignmentGen(private val codeGen: IRCodeGen, private val expressionEval: ExpressionGen) { internal fun translate(assignment: PtAssignment): IRCodeChunks { - if(assignment.target.children.single() is PtMachineRegister) + if(assignment.target.children.single() is PtIrRegister) throw AssemblyError("assigning to a register should be done by just evaluating the expression into resultregister") val chunks = translateRegularAssign(assignment) @@ -17,7 +17,7 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express } internal fun translate(augAssign: PtAugmentedAssign): IRCodeChunks { - if(augAssign.target.children.single() is PtMachineRegister) + if(augAssign.target.children.single() is PtIrRegister) throw AssemblyError("assigning to a register should be done by just evaluating the expression into resultregister") val target = augAssign.target @@ -270,11 +270,11 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express else throw AssemblyError("assignment value and target dt mismatch") } else false - if (assignment.value is PtMachineRegister) { - valueRegister = (assignment.value as PtMachineRegister).register + if (assignment.value is PtIrRegister) { + valueRegister = (assignment.value as PtIrRegister).register if(extendByteToWord) { valueRegister = codeGen.registers.nextFree() - addInstr(result, IRInstruction(Opcode.EXT, IRDataType.BYTE, reg1=valueRegister, reg2=(assignment.value as PtMachineRegister).register), null) + addInstr(result, IRInstruction(Opcode.EXT, IRDataType.BYTE, reg1=valueRegister, reg2=(assignment.value as PtIrRegister).register), null) } } else { val tr = expressionEval.translateExpression(assignment.value) diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt index 1b7bb09be..bc66cf4ed 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt @@ -857,7 +857,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe val assignTarget = PtAssignTarget(target.position) assignTarget.children.add(target) assignment.children.add(assignTarget) - assignment.children.add(PtMachineRegister(register, target.type, target.position)) + assignment.children.add(PtIrRegister(register, target.type, target.position)) val result = mutableListOf() result += codeGen.translateNode(assignment) return result diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt index 9936d8bf9..dc0140da8 100644 --- a/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt +++ b/codeGenIntermediate/src/prog8/codegen/intermediate/ExpressionGen.kt @@ -24,7 +24,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { fun translateExpression(expr: PtExpression): ExpressionCodeResult { return when (expr) { - is PtMachineRegister -> { + is PtIrRegister -> { ExpressionCodeResult(emptyList(), irType(expr.type), expr.register, -1) } is PtBool -> { @@ -505,8 +505,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) { if(returnIrType==IRDataType.FLOAT) FunctionCallArgs.RegSpec(returnIrType, codeGen.registers.nextFreeFloat(), returns.register) else { - statusFlagResult = returns.register.statusflag - val returnRegister = if(statusFlagResult==null) codeGen.registers.nextFree() else -1 + val returnRegister = codeGen.registers.nextFree() FunctionCallArgs.RegSpec(returnIrType, returnRegister, returns.register) } } else { diff --git a/examples/test.p8 b/examples/test.p8 index 2141683f4..916a98edf 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -3,16 +3,17 @@ %option no_sysinit main { - str scanline_buf = "?"* 20 - sub start() { - if diskio.f_open("test.prg") and diskio.f_read(scanline_buf, 2)==2 - cx16.r0++ + bool @shared flag - if diskio.f_open("test.prg") or diskio.f_read(scanline_buf, 2)==2 - cx16.r0++ + cx16.r0L = test(12345, flag, -42) - if diskio.f_open("test.prg") xor diskio.f_read(scanline_buf, 2)==2 - cx16.r0++ + } + + asmsub test(uword arg @AY, bool flag @Pc, byte value @X) -> ubyte @A, bool @Pc { + %asm {{ + txa + rts + }} } } diff --git a/intermediate/src/prog8/intermediate/IRFileReader.kt b/intermediate/src/prog8/intermediate/IRFileReader.kt index 2da03a42d..435d39e06 100644 --- a/intermediate/src/prog8/intermediate/IRFileReader.kt +++ b/intermediate/src/prog8/intermediate/IRFileReader.kt @@ -497,7 +497,7 @@ class IRFileReader { private fun parseDatatype(type: String, isArray: Boolean): DataType { if(isArray) { return when(type) { - // note: there are no BOOLEANS anymore in the IR. Only UBYTE. + // note: there are no BOOLEANS arrays anymore in the IR. Only UBYTE. "byte" -> DataType.ARRAY_B "ubyte", "str" -> DataType.ARRAY_UB "word" -> DataType.ARRAY_W @@ -509,7 +509,7 @@ class IRFileReader { } } else { return when(type) { - // note: there are no BOOLEANS anymore in the IR. Only UBYTE. + "bool" -> DataType.BOOL "byte" -> DataType.BYTE "ubyte" -> DataType.UBYTE "word" -> DataType.WORD diff --git a/intermediate/src/prog8/intermediate/IRInstructions.kt b/intermediate/src/prog8/intermediate/IRInstructions.kt index 1239ed69c..8372b284e 100644 --- a/intermediate/src/prog8/intermediate/IRInstructions.kt +++ b/intermediate/src/prog8/intermediate/IRInstructions.kt @@ -41,6 +41,12 @@ loadi reg1, reg2 - load reg1 with value at memory indirect, loadx reg1, reg2, address - load reg1 with value at memory address indexed by value in reg2 (only the lsb part used for indexing) loadix reg1, reg2, pointeraddr - load reg1 with value at memory indirect, pointed to by pointeraddr indexed by value in reg2 (only the lsb part used for indexing) loadr reg1, reg2 - load reg1 with value in register reg2 +loadha reg1 - load cpu hardware register A into reg1.b +loadhx reg1 - load cpu hardware register X into reg1.b +loadhy reg1 - load cpu hardware register Y into reg1.b +loadhax reg1 - load cpu hardware register pair AX into reg1.w +loadhay reg1 - load cpu hardware register pair AY into reg1.w +loadhxy reg1 - load cpu hardware register pair XY into reg1.w storem reg1, address - store reg1 at memory address storei reg1, reg2 - store reg1 at memory indirect, memory pointed to by reg2 storex reg1, reg2, address - store reg1 at memory address, indexed by value in reg2 (only the lsb part used for indexing) @@ -48,6 +54,12 @@ storeix reg1, reg2, pointeraddr - store reg1 at memory indirect, pointed t storezm address - store zero at memory address storezi reg1 - store zero at memory pointed to by reg1 storezx reg1, address - store zero at memory address, indexed by value in reg1 (only the lsb part used for indexing) +storeha reg1 - store reg1.b into cpu hardware register A +storehx reg1 - store reg1.b into cpu hardware register X +storehy reg1 - store reg1.b into cpu hardware register Y +storehax reg1 - store reg1.w into cpu hardware register pair AX +storehay reg1 - store reg1.w into cpu hardware register pair AY +storehxy reg1 - store reg1.w into cpu hardware register pair XY CONTROL FLOW @@ -247,6 +259,12 @@ enum class Opcode { LOADX, LOADIX, LOADR, + LOADHA, + LOADHX, + LOADHY, + LOADHAX, + LOADHAY, + LOADHXY, STOREM, STOREI, STOREX, @@ -254,6 +272,12 @@ enum class Opcode { STOREZM, STOREZI, STOREZX, + STOREHA, + STOREHX, + STOREHY, + STOREHAX, + STOREHAY, + STOREHXY, JUMP, JUMPI, @@ -444,6 +468,12 @@ val OpcodesThatSetStatusbitsButNotCarry = arrayOf( Opcode.LOADX, Opcode.LOADIX, Opcode.LOADR, + Opcode.LOADHA, + Opcode.LOADHX, + Opcode.LOADHY, + Opcode.LOADHAX, + Opcode.LOADHAY, + Opcode.LOADHXY, Opcode.NEG, Opcode.NEGM, Opcode.INC, @@ -585,6 +615,13 @@ val instructionFormats = mutableMapOf( Opcode.LOADX to InstructionFormat.from("BW,>r1,fr1,r1,fr1,r1,fr1,r1"), + Opcode.LOADHA to InstructionFormat.from("B,>r1"), + Opcode.LOADHX to InstructionFormat.from("B,>r1"), + Opcode.LOADHY to InstructionFormat.from("B,>r1"), + Opcode.LOADHAX to InstructionFormat.from("W,>r1"), + Opcode.LOADHAY to InstructionFormat.from("W,>r1"), + Opcode.LOADHXY to InstructionFormat.from("W,>r1"), Opcode.STOREM to InstructionFormat.from("BW,a | F,a"), Opcode.STOREI to InstructionFormat.from("BW,a | F,a"), @@ -592,6 +629,13 @@ val instructionFormats = mutableMapOf( Opcode.STOREZM to InstructionFormat.from("BW,>a | F,>a"), Opcode.STOREZI to InstructionFormat.from("BW,a | F,a"), + Opcode.STOREHA to InstructionFormat.from("B, result.add("fr${returns.registerNum}.f") } } else { - result.add("@" + cpuReg) - if(returns.cpuRegister?.statusflag==null) { - when (returns.dt) { - IRDataType.BYTE -> result.add(".b") - IRDataType.WORD -> result.add(".w") - IRDataType.FLOAT -> result.add(".f") - } + when(returns.dt) { + IRDataType.BYTE -> result.add("r${returns.registerNum}.b@" + cpuReg) + IRDataType.WORD -> result.add("r${returns.registerNum}.w@" + cpuReg) + IRDataType.FLOAT -> result.add("r${returns.registerNum}.f@" + cpuReg) } } } diff --git a/virtualmachine/src/prog8/vm/VirtualMachine.kt b/virtualmachine/src/prog8/vm/VirtualMachine.kt index 422075dd4..b34f56a52 100644 --- a/virtualmachine/src/prog8/vm/VirtualMachine.kt +++ b/virtualmachine/src/prog8/vm/VirtualMachine.kt @@ -178,6 +178,12 @@ class VirtualMachine(irProgram: IRProgram) { Opcode.LOADI -> InsLOADI(ins) Opcode.LOADIX -> InsLOADIX(ins) Opcode.LOADR -> InsLOADR(ins) + Opcode.LOADHA, + Opcode.LOADHX, + Opcode.LOADHY, + Opcode.LOADHAX, + Opcode.LOADHAY, + Opcode.LOADHXY -> throw IllegalArgumentException("VM cannot access actual CPU hardware register") Opcode.STOREM -> InsSTOREM(ins) Opcode.STOREX -> InsSTOREX(ins) Opcode.STOREIX -> InsSTOREIX(ins) @@ -185,10 +191,16 @@ class VirtualMachine(irProgram: IRProgram) { Opcode.STOREZM -> InsSTOREZM(ins) Opcode.STOREZX -> InsSTOREZX(ins) Opcode.STOREZI -> InsSTOREZI(ins) + Opcode.STOREHA, + Opcode.STOREHX, + Opcode.STOREHY, + Opcode.STOREHAX, + Opcode.STOREHAY, + Opcode.STOREHXY -> throw IllegalArgumentException("VM cannot access actual CPU hardware register") Opcode.JUMP -> InsJUMP(ins) Opcode.JUMPI -> InsJUMPI(ins) Opcode.PREPARECALL -> nextPc() - Opcode.CALLI -> throw IllegalArgumentException("VM cannot run code from memory") + Opcode.CALLI -> throw IllegalArgumentException("VM cannot run code from memory bytes") Opcode.CALL -> InsCALL(ins) Opcode.SYSCALL -> InsSYSCALL(ins) Opcode.RETURN -> InsRETURN() @@ -319,6 +331,7 @@ class VirtualMachine(irProgram: IRProgram) { Opcode.FFLOOR -> InsFFLOOR(ins) Opcode.FCEIL -> InsFCEIL(ins) Opcode.FCOMP -> InsFCOMP(ins) + else -> throw IllegalArgumentException("invalid opcode ${ins.opcode}") } } diff --git a/virtualmachine/src/prog8/vm/VmProgramLoader.kt b/virtualmachine/src/prog8/vm/VmProgramLoader.kt index 48056063b..c83cf897d 100644 --- a/virtualmachine/src/prog8/vm/VmProgramLoader.kt +++ b/virtualmachine/src/prog8/vm/VmProgramLoader.kt @@ -44,7 +44,7 @@ class VmProgramLoader { block.children.forEach { child -> when(child) { - is IRAsmSubroutine -> throw IRParseException("vm does not support non-inlined asmsubs (use normal sub): ${child.label}") + is IRAsmSubroutine -> throw IRParseException("vm does not support asmsubs (use normal sub): ${child.label}") is IRCodeChunk -> programChunks += child is IRInlineAsmChunk -> throw IRParseException("encountered unconverted inline assembly chunk") is IRInlineBinaryChunk -> throw IRParseException("inline binary data not yet supported in the VM") diff --git a/virtualmachine/test/TestVm.kt b/virtualmachine/test/TestVm.kt index 924d1b062..489e2f1e1 100644 --- a/virtualmachine/test/TestVm.kt +++ b/virtualmachine/test/TestVm.kt @@ -85,7 +85,7 @@ class TestVm: FunSpec( { ) block += startSub program.addBlock(block) - shouldThrowWithMessage("vm does not support non-inlined asmsubs (use normal sub): main.asmstart") { + shouldThrowWithMessage("vm does not support asmsubs (use normal sub): main.asmstart") { VirtualMachine(program) } }