diff --git a/compiler/src/prog8/compiler/Compiler.kt b/compiler/src/prog8/compiler/Compiler.kt index b566b86a9..b8d9271c0 100644 --- a/compiler/src/prog8/compiler/Compiler.kt +++ b/compiler/src/prog8/compiler/Compiler.kt @@ -2169,7 +2169,11 @@ internal class Compiler(private val rootModule: Module, } private fun translateAsmBinary(args: List) { - TODO("asmbinary not implemented yet $args") + val offset = if(args.size>=2) Value(DataType.UWORD, args[1].int!!) else null + val length = if(args.size==3) Value(DataType.UWORD, args[2].int!!) else null + val filename = args[0].str!! + // reading the actual data is not performed by the compiler but is delegated to the assembler + prog.instr(Opcode.INCLUDE_FILE, offset, length, filename) } } diff --git a/compiler/src/prog8/compiler/intermediate/Instruction.kt b/compiler/src/prog8/compiler/intermediate/Instruction.kt index 89a9c0451..177a2362a 100644 --- a/compiler/src/prog8/compiler/intermediate/Instruction.kt +++ b/compiler/src/prog8/compiler/intermediate/Instruction.kt @@ -23,6 +23,9 @@ open class Instruction(val opcode: Opcode, else "inline_assembly" } + opcode==Opcode.INCLUDE_FILE -> { + "include_file \"$callLabel\" $arg $arg2" + } opcode==Opcode.SYSCALL -> { val syscall = Syscall.values().find { it.callNr==arg!!.numericValue() } "syscall $syscall" diff --git a/compiler/src/prog8/compiler/intermediate/Opcode.kt b/compiler/src/prog8/compiler/intermediate/Opcode.kt index 43b9ba8d9..3d7719d4a 100644 --- a/compiler/src/prog8/compiler/intermediate/Opcode.kt +++ b/compiler/src/prog8/compiler/intermediate/Opcode.kt @@ -262,7 +262,8 @@ enum class Opcode { BREAKPOINT, // breakpoint TERMINATE, // end the program LINE, // track source file line number - INLINE_ASSEMBLY // container to hold inline raw assembly code + INLINE_ASSEMBLY, // container to hold inline raw assembly code + INCLUDE_FILE // directive to include a file at this position in the memory of the program } val opcodesWithVarArgument = setOf( diff --git a/compiler/src/prog8/compiler/target/c64/AsmGen.kt b/compiler/src/prog8/compiler/target/c64/AsmGen.kt index 6971c8990..4050eae9f 100644 --- a/compiler/src/prog8/compiler/target/c64/AsmGen.kt +++ b/compiler/src/prog8/compiler/target/c64/AsmGen.kt @@ -472,6 +472,11 @@ class AsmGen(val options: CompilationOptions, val program: IntermediateProgram, Opcode.DISCARD_WORD -> " inx" Opcode.DISCARD_FLOAT -> " inx | inx | inx" Opcode.INLINE_ASSEMBLY -> "@inline@" + (ins.callLabel2 ?: "") // All of the inline assembly is stored in the calllabel2 property. the '@inline@' is a special marker to process it. + Opcode.INCLUDE_FILE -> { + val offset = if(ins.arg==null) "" else ", ${ins.arg.integerValue()}" + val length = if(ins.arg2==null) "" else ", ${ins.arg2.integerValue()}" + " .binary \"${ins.callLabel}\" $offset $length" + } Opcode.SYSCALL -> { if (ins.arg!!.numericValue() in syscallsForStackVm.map { it.callNr }) throw CompilerException("cannot translate vm syscalls to real assembly calls - use *real* subroutine calls instead. Syscall ${ins.arg.numericValue()}") diff --git a/compiler/src/prog8/stackvm/Program.kt b/compiler/src/prog8/stackvm/Program.kt index 562cd0609..9cb65bc08 100644 --- a/compiler/src/prog8/stackvm/Program.kt +++ b/compiler/src/prog8/stackvm/Program.kt @@ -170,6 +170,13 @@ class Program (val name: String, } } } + Opcode.INCLUDE_FILE -> { + val argparts = args!!.split(' ') + val filename = argparts[0] + val offset = if(argparts.size>=2 && argparts[1]!="null") getArgValue(argparts[1], heap) else null + val length = if(argparts.size>=3 && argparts[2]!="null") getArgValue(argparts[2], heap) else null + Instruction(opcode, offset, length, filename) + } else -> { Instruction(opcode, getArgValue(args, heap)) } diff --git a/compiler/src/prog8/stackvm/StackVm.kt b/compiler/src/prog8/stackvm/StackVm.kt index bc9c0741f..a19980c21 100644 --- a/compiler/src/prog8/stackvm/StackVm.kt +++ b/compiler/src/prog8/stackvm/StackVm.kt @@ -1836,6 +1836,7 @@ class StackVm(private var traceOutputFile: String?) { Opcode.RSAVEX -> registerSaveX = variables.getValue("X") Opcode.RRESTOREX -> variables["X"] = registerSaveX Opcode.INLINE_ASSEMBLY -> throw VmExecutionException("stackVm doesn't support executing inline assembly code $ins") + Opcode.INCLUDE_FILE -> throw VmExecutionException("stackVm doesn't support including a file $ins") Opcode.PUSH_ADDR_HEAPVAR -> { val heapId = variables.getValue(ins.callLabel!!).heapId if(heapId<0) diff --git a/docs/source/syntaxreference.rst b/docs/source/syntaxreference.rst index d6aca343a..cf203e408 100644 --- a/docs/source/syntaxreference.rst +++ b/docs/source/syntaxreference.rst @@ -123,8 +123,7 @@ Directives This directive can only be used inside a block. The assembler will include the file as binary bytes at this point, prog8 will not process this at all. The optional offset and length can be used to select a particular piece of the file. - The compiler first looks for the file relative to the same directory as the module containing this statement is in, - if the file can't be found there it is searched relative to the current directory. + The file is located relative to the current working directory! .. data:: %asminclude "", "scopelabel" diff --git a/docs/source/todo.rst b/docs/source/todo.rst index f89350245..0f6d9040a 100644 --- a/docs/source/todo.rst +++ b/docs/source/todo.rst @@ -74,5 +74,4 @@ of values together (and use it multiple times). Something like:: Misc ^^^^ -- implement %asmbinary - are there any other missing instructions in the code generator? diff --git a/examples/test.p8 b/examples/test.p8 index a4885af26..e7e9ad93a 100644 --- a/examples/test.p8 +++ b/examples/test.p8 @@ -4,7 +4,6 @@ sub start() { - %asminclude "primes.p8", "derp" - %asmbinary "primes.p8", 10, 20 + %asmbinary "LICENSE", 100, 200 } }