diff --git a/codeGenVirtual/src/prog8/codegen/virtual/AssemblyProgram.kt b/codeGenVirtual/src/prog8/codegen/virtual/AssemblyProgram.kt index 09d8537be..cd4f5f74a 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/AssemblyProgram.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/AssemblyProgram.kt @@ -1,5 +1,6 @@ package prog8.codegen.virtual +import prog8.code.core.AssemblyError import prog8.code.core.CompilationOptions import prog8.code.core.IAssemblyProgram import prog8.vm.Instruction @@ -46,6 +47,13 @@ internal class AssemblyProgram(override val name: String, write(line.ins.toString() + "\n") } is VmCodeLabel -> write("_" + line.name.joinToString(".") + ":\n") + is VmCodeInlineAsm -> { + val asm = line.assembly.replace("""\{[a-zA-Z\d_\.]+\}""".toRegex()) { matchResult -> + val name = matchResult.value.substring(1, matchResult.value.length-1).split('.') + allocations.get(name).toString() } + write(asm+"\n") + } + else -> throw AssemblyError("invalid vm code line") } } @@ -118,4 +126,8 @@ internal class VmCodeChunk(initial: VmCodeLine? = null) { operator fun plusAssign(chunk: VmCodeChunk) { lines.addAll(chunk.lines) } -} \ No newline at end of file +} + +internal class VmCodeInlineAsm(asm: String): VmCodeLine() { + val assembly: String = asm.trimIndent() +} diff --git a/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt b/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt index ab35e7136..53c21a0c6 100644 --- a/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt +++ b/codeGenVirtual/src/prog8/codegen/virtual/CodeGen.kt @@ -91,6 +91,7 @@ class CodeGen(internal val program: PtProgram, is PtLabel -> VmCodeChunk(VmCodeLabel(node.scopedName)) is PtBreakpoint -> VmCodeChunk(VmCodeInstruction(Opcode.BREAKPOINT)) is PtConditionalBranch -> translate(node) + is PtInlineAssembly -> VmCodeChunk(VmCodeInlineAsm(node.assembly)) is PtAddressOf, is PtContainmentCheck, is PtMemoryByte, @@ -108,7 +109,6 @@ class CodeGen(internal val program: PtProgram, is PtArray, is PtString -> throw AssemblyError("should not occur as separate statement node ${node.position}") is PtAsmSub -> throw AssemblyError("asmsub not supported on virtual machine target ${node.position}") - is PtInlineAssembly -> throw AssemblyError("inline assembly not supported on virtual machine target ${node.position}") is PtIncludeBinary -> throw AssemblyError("inline binary data not supported on virtual machine target ${node.position}") else -> TODO("missing codegen for $node") } diff --git a/compiler/res/prog8lib/virtual/floats.p8 b/compiler/res/prog8lib/virtual/floats.p8 index e79616ff5..b41877b5a 100644 --- a/compiler/res/prog8lib/virtual/floats.p8 +++ b/compiler/res/prog8lib/virtual/floats.p8 @@ -11,7 +11,11 @@ floats { sub print_f(float value) { ; ---- prints the floating point value (without a newline). - void syscall1fp(sys.SC_PRINTF, value) + %asm {{ + loadm.f fr0,{floats.print_f.value} + syscall 35 + return + }} } sub pow(float value, float power) -> float { @@ -25,8 +29,12 @@ sub fabs(float value) -> float { } sub sin(float angle) -> float { - ; TODO - return -42.42 + ; TODO sin.f instruction + %asm {{ + loadm.f fr0,{floats.sin.angle} + sin.f fr0,fr0 + return + }} } sub cos(float angle) -> float { diff --git a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt index 38722b475..3e2f9e21a 100644 --- a/compiler/src/prog8/compiler/astprocessing/AstChecker.kt +++ b/compiler/src/prog8/compiler/astprocessing/AstChecker.kt @@ -244,9 +244,18 @@ internal class AstChecker(private val program: Program, override fun visit(inlineAssembly: InlineAssembly) { val assembly = inlineAssembly.assembly - if(" rti" in assembly || "\trti" in assembly || " rts" in assembly || "\trts" in assembly || - " jmp" in assembly || "\tjmp" in assembly || " bra" in assembly || "\tbra" in assembly ) - count++ + if(compilerOptions.compTarget.name!=VMTarget.NAME) { + if (" rti" in assembly || "\trti" in assembly || " rts" in assembly || "\trts" in assembly || + " jmp" in assembly || "\tjmp" in assembly || " bra" in assembly || "\tbra" in assembly + ) + count++ + } else { + if(" return" in assembly || "\treturn" in assembly + || " jump" in assembly || "\tjump" in assembly + || " jumpi" in assembly || "\tjumpi" in assembly + ) + count++ + } } } diff --git a/docs/source/todo.rst b/docs/source/todo.rst index dc9a7a9b3..1228059ed 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -3,8 +3,9 @@ TODO For next release ^^^^^^^^^^^^^^^^ -- vm: allow inline "asm" where the assembly is vm-code instead of 6502 -- then get rid of the syscall() functions in prog8 +- vm: get rid of the syscall() functions in prog8 via inline assembly - vm: implement missing floating point functions +- vm: get rid of intermediate floats.xxx() functions somehow, instead generate the float instructions directly? - pipe operator: allow non-unary function calls in the pipe that specify the other argument(s) in the calls. - allow "xxx" * constexpr (where constexpr is not a number literal), now gives expression error not same type - make it possible to inline non-asmsub routines that just contain a single statement (return, functioncall, assignment) diff --git a/examples/test.p8 b/examples/test.p8 index 75bcbd4f9..6d6977776 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -9,6 +9,7 @@ main { sub start() { txt.print("float tests: ") + floats.print_f(-42.42) float f1 = 1.2345 float f2 = -9.99 float f3