diff --git a/codeCore/src/prog8/code/target/virtual/VirtualMachineDefinition.kt b/codeCore/src/prog8/code/target/virtual/VirtualMachineDefinition.kt
index 6f4e5aec4..20fdec132 100644
--- a/codeCore/src/prog8/code/target/virtual/VirtualMachineDefinition.kt
+++ b/codeCore/src/prog8/code/target/virtual/VirtualMachineDefinition.kt
@@ -32,7 +32,7 @@ class VirtualMachineDefinition: IMachineDefinition {
override fun launchEmulator(selectedEmulator: Int, programNameWithPath: Path) {
println("\nStarting Virtual Machine...")
- // to not have external module dependencies we launch the virtual machine via reflection
+ // to not have external module dependencies in our own module, we launch the virtual machine via reflection
val vm = Class.forName("prog8.vm.VmRunner").getDeclaredConstructor().newInstance() as IVirtualMachineRunner
val filename = programNameWithPath.name
if(filename.endsWith(".p8virt")) {
diff --git a/codeGenIntermediate/build.gradle b/codeGenIntermediate/build.gradle
index d0181b0ec..95b41d291 100644
--- a/codeGenIntermediate/build.gradle
+++ b/codeGenIntermediate/build.gradle
@@ -26,7 +26,6 @@ compileTestKotlin {
dependencies {
implementation project(':codeCore')
implementation project(':intermediate')
- implementation project(':virtualmachine')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
// implementation "org.jetbrains.kotlin:kotlin-reflect"
implementation "com.michael-bull.kotlin-result:kotlin-result-jvm:1.1.16"
diff --git a/codeGenIntermediate/codeGenIntermediate.iml b/codeGenIntermediate/codeGenIntermediate.iml
index 0016695ca..893f7df14 100644
--- a/codeGenIntermediate/codeGenIntermediate.iml
+++ b/codeGenIntermediate/codeGenIntermediate.iml
@@ -12,7 +12,6 @@
-
diff --git a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt
index c1dbdebb1..3676ad40d 100644
--- a/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt
+++ b/codeGenIntermediate/src/prog8/codegen/intermediate/BuiltinFuncGen.kt
@@ -6,7 +6,6 @@ import prog8.code.core.AssemblyError
import prog8.code.core.DataType
import prog8.code.core.Position
import prog8.intermediate.*
-import prog8.vm.Syscall
internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGen: ExpressionGen) {
@@ -67,10 +66,10 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
val syscall =
when (array.dt) {
DataType.ARRAY_UB,
- DataType.ARRAY_B -> Syscall.ANY_BYTE
+ DataType.ARRAY_B -> IMSyscall.ANY_BYTE
DataType.ARRAY_UW,
- DataType.ARRAY_W -> Syscall.ANY_WORD
- DataType.ARRAY_F -> Syscall.ANY_FLOAT
+ DataType.ARRAY_W -> IMSyscall.ANY_WORD
+ DataType.ARRAY_F -> IMSyscall.ANY_FLOAT
else -> throw IllegalArgumentException("weird type")
}
code += exprGen.translateExpression(call.args[0], 0, -1)
@@ -87,10 +86,10 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
val syscall =
when(array.dt) {
DataType.ARRAY_UB,
- DataType.ARRAY_B -> Syscall.ALL_BYTE
+ DataType.ARRAY_B -> IMSyscall.ALL_BYTE
DataType.ARRAY_UW,
- DataType.ARRAY_W -> Syscall.ALL_WORD
- DataType.ARRAY_F -> Syscall.ALL_FLOAT
+ DataType.ARRAY_W -> IMSyscall.ALL_WORD
+ DataType.ARRAY_F -> IMSyscall.ALL_FLOAT
else -> throw IllegalArgumentException("weird type")
}
val code = IRCodeChunk(call.position)
@@ -187,37 +186,37 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
private fun funcReverse(call: PtBuiltinFunctionCall): IRCodeChunk {
val arrayName = call.args[0] as PtIdentifier
val array = codeGen.symbolTable.flat.getValue(arrayName.targetName) as StStaticVariable
- val sortSyscall =
+ val syscall =
when(array.dt) {
- DataType.ARRAY_UB, DataType.ARRAY_B, DataType.STR -> Syscall.REVERSE_BYTES
- DataType.ARRAY_UW, DataType.ARRAY_W -> Syscall.REVERSE_WORDS
- DataType.ARRAY_F -> Syscall.REVERSE_FLOATS
+ DataType.ARRAY_UB, DataType.ARRAY_B, DataType.STR -> IMSyscall.REVERSE_BYTES
+ DataType.ARRAY_UW, DataType.ARRAY_W -> IMSyscall.REVERSE_WORDS
+ DataType.ARRAY_F -> IMSyscall.REVERSE_FLOATS
else -> throw IllegalArgumentException("weird type to reverse")
}
val code = IRCodeChunk(call.position)
code += exprGen.translateExpression(call.args[0], 0, -1)
code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
- code += IRCodeInstruction(Opcode.SYSCALL, value=sortSyscall.ordinal)
+ code += IRCodeInstruction(Opcode.SYSCALL, value=syscall.ordinal)
return code
}
private fun funcSort(call: PtBuiltinFunctionCall): IRCodeChunk {
val arrayName = call.args[0] as PtIdentifier
val array = codeGen.symbolTable.flat.getValue(arrayName.targetName) as StStaticVariable
- val sortSyscall =
+ val syscall =
when(array.dt) {
- DataType.ARRAY_UB -> Syscall.SORT_UBYTE
- DataType.ARRAY_B -> Syscall.SORT_BYTE
- DataType.ARRAY_UW -> Syscall.SORT_UWORD
- DataType.ARRAY_W -> Syscall.SORT_WORD
- DataType.STR -> Syscall.SORT_UBYTE
+ DataType.ARRAY_UB -> IMSyscall.SORT_UBYTE
+ DataType.ARRAY_B -> IMSyscall.SORT_BYTE
+ DataType.ARRAY_UW -> IMSyscall.SORT_UWORD
+ DataType.ARRAY_W -> IMSyscall.SORT_WORD
+ DataType.STR -> IMSyscall.SORT_UBYTE
DataType.ARRAY_F -> throw IllegalArgumentException("sorting a floating point array is not supported")
else -> throw IllegalArgumentException("weird type to sort")
}
val code = IRCodeChunk(call.position)
code += exprGen.translateExpression(call.args[0], 0, -1)
code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
- code += IRCodeInstruction(Opcode.SYSCALL, value=sortSyscall.ordinal)
+ code += IRCodeInstruction(Opcode.SYSCALL, value=syscall.ordinal)
return code
}
diff --git a/codeGenVirtual/build.gradle b/codeGenVirtual/build.gradle
index e8005360e..d2803c867 100644
--- a/codeGenVirtual/build.gradle
+++ b/codeGenVirtual/build.gradle
@@ -28,6 +28,7 @@ dependencies {
implementation project(':codeCore')
implementation project(':intermediate')
implementation project(':codeGenIntermediate')
+ implementation project(':virtualmachine')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
// implementation "org.jetbrains.kotlin:kotlin-reflect"
implementation "com.michael-bull.kotlin-result:kotlin-result-jvm:1.1.16"
diff --git a/codeGenVirtual/codeGenVirtual.iml b/codeGenVirtual/codeGenVirtual.iml
index 74eb9baf8..8a466fb93 100644
--- a/codeGenVirtual/codeGenVirtual.iml
+++ b/codeGenVirtual/codeGenVirtual.iml
@@ -16,5 +16,6 @@
+
\ No newline at end of file
diff --git a/codeGenVirtual/src/prog8/codegen/virtual/VmAssemblyProgram.kt b/codeGenVirtual/src/prog8/codegen/virtual/VmAssemblyProgram.kt
index 2e2673fd7..b1ca60f17 100644
--- a/codeGenVirtual/src/prog8/codegen/virtual/VmAssemblyProgram.kt
+++ b/codeGenVirtual/src/prog8/codegen/virtual/VmAssemblyProgram.kt
@@ -4,6 +4,7 @@ import prog8.code.core.AssemblyError
import prog8.code.core.CompilationOptions
import prog8.code.core.IAssemblyProgram
import prog8.intermediate.*
+import prog8.vm.Syscall
import java.io.BufferedWriter
import kotlin.io.path.bufferedWriter
import kotlin.io.path.div
@@ -84,7 +85,28 @@ private fun BufferedWriter.writeLine(line: IRCodeLine) {
write("; ${line.comment}\n")
}
is IRCodeInstruction -> {
- write(line.ins.toString() + "\n")
+ if(line.ins.opcode==Opcode.SYSCALL) {
+ // convert IM Syscall to VM Syscall
+ val vmSyscall = when(line.ins.value!!) {
+ IMSyscall.SORT_UBYTE.ordinal -> Syscall.SORT_UBYTE
+ IMSyscall.SORT_BYTE.ordinal -> Syscall.SORT_BYTE
+ IMSyscall.SORT_UWORD.ordinal -> Syscall.SORT_UWORD
+ IMSyscall.SORT_WORD.ordinal -> Syscall.SORT_WORD
+ IMSyscall.ANY_BYTE.ordinal -> Syscall.ANY_BYTE
+ IMSyscall.ANY_WORD.ordinal -> Syscall.ANY_WORD
+ IMSyscall.ANY_FLOAT.ordinal -> Syscall.ANY_FLOAT
+ IMSyscall.ALL_BYTE.ordinal -> Syscall.ALL_BYTE
+ IMSyscall.ALL_WORD.ordinal -> Syscall.ALL_WORD
+ IMSyscall.ALL_FLOAT.ordinal -> Syscall.ALL_FLOAT
+ IMSyscall.REVERSE_BYTES.ordinal -> Syscall.REVERSE_BYTES
+ IMSyscall.REVERSE_WORDS.ordinal -> Syscall.REVERSE_WORDS
+ IMSyscall.REVERSE_FLOATS.ordinal -> Syscall.REVERSE_FLOATS
+ else -> throw IllegalArgumentException("invalid IM syscall number ${line.ins.value}")
+ }
+ val newIns = line.ins.copy(value = vmSyscall.ordinal)
+ write(newIns.toString() + "\n")
+ } else
+ write(line.ins.toString() + "\n")
}
is IRCodeInlineBinary -> {
write("!binary ")
diff --git a/compiler/build.gradle b/compiler/build.gradle
index 12fa1af93..c74d14b12 100644
--- a/compiler/build.gradle
+++ b/compiler/build.gradle
@@ -33,6 +33,7 @@ dependencies {
implementation project(':codeGenCpu6502')
implementation project(':codeGenVirtual')
implementation project(':codeGenExperimental')
+ implementation project(':virtualmachine')
implementation 'org.antlr:antlr4-runtime:4.10.1'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
// implementation "org.jetbrains.kotlin:kotlin-reflect"
diff --git a/compiler/compiler.iml b/compiler/compiler.iml
index c2b444f50..7d5c118e1 100644
--- a/compiler/compiler.iml
+++ b/compiler/compiler.iml
@@ -22,5 +22,6 @@
+
\ No newline at end of file
diff --git a/compiler/test/TestLaunchEmu.kt b/compiler/test/TestLaunchEmu.kt
new file mode 100644
index 000000000..c27600eaf
--- /dev/null
+++ b/compiler/test/TestLaunchEmu.kt
@@ -0,0 +1,18 @@
+package prog8tests
+
+import io.kotest.core.spec.style.FunSpec
+import prog8.code.target.VMTarget
+import kotlin.io.path.deleteExisting
+import kotlin.io.path.writeText
+
+
+class TestLaunchEmu: FunSpec({
+
+ test("test launch virtualmachine via target") {
+ val target = VMTarget()
+ val tmpfile = kotlin.io.path.createTempFile(suffix=".p8virt")
+ tmpfile.writeText(";comment\n------PROGRAM------\n;comment\n")
+ target.machine.launchEmulator(0, tmpfile)
+ tmpfile.deleteExisting()
+ }
+})
diff --git a/docs/source/todo.rst b/docs/source/todo.rst
index 7a7033704..94a2f1f08 100644
--- a/docs/source/todo.rst
+++ b/docs/source/todo.rst
@@ -17,7 +17,6 @@ Future Things and Ideas
^^^^^^^^^^^^^^^^^^^^^^^
Compiler:
-- vm/ir: all(), any(), reverse() and sort() still depend on a VM Syscall. Get rid of this. (maybe use a IR 'builtin' function?)
- vm/ir: put variables and arrays in BSS section (unless -noreinit is specified)
- vm: Jumps go to a code block rather than a specific address(label) -> also helps future dead code elimination?
- vm: the above means that every label introduces a new code block. This eliminates the use of actual labels altogether.
@@ -51,8 +50,8 @@ Libraries:
- fix the problems in atari target, and flesh out its libraries.
- c64: make the graphics.BITMAP_ADDRESS configurable (VIC banking)
- optimize several inner loops in gfx2 even further?
-- add modes 3 and perhaps even 2 to gfx2 (16 color and 4 color)?
-- add a flood fill routine to gfx2?
+- add modes 3 and perhaps even 2 to gfx2 (lores 16 color and 4 color)?
+- add a flood fill (span fill/scanline fill) routine to gfx2?
Expressions:
diff --git a/examples/test.p8 b/examples/test.p8
index 73a08f559..ff45dfe83 100644
--- a/examples/test.p8
+++ b/examples/test.p8
@@ -1,115 +1,32 @@
+%import textio
+%zeropage basicsafe
main {
sub start() {
- %asm {{
- loadcpu.b r1,_a
- loadcpu.b r1,_x
- loadcpu.b r1,_y
- loadcpu.w r1,_ax
- loadcpu.w r1,_ay
- loadcpu.w r1,_xy
- loadcpu.b r1,_pc
- loadcpu.b r1,_pn
- loadcpu.b r1,_pz
- loadcpu.w r1,_r0
- loadcpu.w r1,_r15
+ uword[] words = [1111,2222,0,4444,3333]
+
+ txt.print_ub(all(words))
+ txt.nl()
+ txt.print_ub(any(words))
+ txt.nl()
+ sort(words)
+
+ uword ww
+ for ww in words {
+ txt.print_uw(ww)
+ txt.spc()
+ }
+ txt.nl()
+
+ reverse(words)
+ for ww in words {
+ txt.print_uw(ww)
+ txt.spc()
+ }
+ txt.nl()
- storezcpu.b _a
- storezcpu.b _x
- storezcpu.b _y
- storezcpu.w _ax
- storezcpu.w _ay
- storezcpu.w _xy
- storezcpu.b _pc
- storezcpu.b _pn
- storezcpu.b _pz
- storezcpu.b _r0
- storezcpu.w _r15
- }}
}
}
-; uword @shared global1 = 1234
-; str @shared globalstring = "irmen"
-;
-; %asm {{
-; nop
-; nop
-; return
-; }}
-;
-; romsub $ee33 = myromsub(ubyte arg1 @A) clobbers() -> ubyte @Y
-; romsub $ee44 = myromsubmulti(ubyte arg1 @A) clobbers() -> ubyte @Y, ubyte @X, ubyte @Pc
-;
-; asmsub testasmsub(ubyte arg1 @A) clobbers(Y) -> uword @AX {
-; %asm {{
-; nop
-; return
-; }}
-; }
-;
-; sub start() {
-; void myromsubmulti(44)
-; global1 = myromsub(44)
-; sys.wait(1)
-;
-; cx16.r0 = 11111
-; cx16.r0L = 22
-; cx16.r0H = 33
-;
-; %asm {{
-; nop
-; jump main.start.a_label
-; }}
-;a_label:
-;
-; %asmbinary "LICENSE", 200, 513
-;
-;; TODO add proper memory SLAB support to IR+VM
-; uword @shared slab1 = memory("slab 1", 2000, 0)
-; uword @shared slab2 = memory("slab 1", 2000, 0)
-; uword @shared slab3 = memory("other # slab", 2000, 64)
-;
-; &uword mapped = $c000
-; &ubyte[20] mappedarray = $c100
-;
-; uword @shared zz
-; zz = slab1+slab2+slab3
-;
-; uword @shared @zp qq = zz
-; uword @shared @zp qq2 = &zz
-;
-; str @shared namestring = "irmen"
-; uword[] @shared wordarray1 = [1111,2222,3333,4444]
-; uword[4] @shared wordarray2 = 12345
-; uword[4] @shared wordzeroarray
-;
-; qq=4242 ; TODO should generate symbol not allocated address????
-; mapped = 99 ; TODO wrong VMASM code generated... should generate mapped memory address?????
-; mappedarray[1]=99 ; TODO check code????
-;
-; qq=global1
-; qq=other.global2
-; nested(11,22)
-; main.start.nested.nested2()
-;
-; sub nested(ubyte a1, ubyte a2) {
-; qq++
-; txt.print("zzz")
-; nested2()
-;
-; sub nested2() {
-; txt.print("zzz2")
-; qq++
-; }
-; }
-; }
-;}
-;
-;other {
-;
-; uword global2 = 9999
-;
-;}
diff --git a/intermediate/src/prog8/intermediate/IMSyscall.kt b/intermediate/src/prog8/intermediate/IMSyscall.kt
new file mode 100644
index 000000000..df2ee468e
--- /dev/null
+++ b/intermediate/src/prog8/intermediate/IMSyscall.kt
@@ -0,0 +1,20 @@
+package prog8.intermediate
+
+// calls to builtin operations that are too complex to be implemented as an IR instruction
+// these use the SYSCALL instruction instead.
+
+enum class IMSyscall {
+ SORT_UBYTE,
+ SORT_BYTE,
+ SORT_UWORD,
+ SORT_WORD,
+ ANY_BYTE,
+ ANY_WORD,
+ ANY_FLOAT,
+ ALL_BYTE,
+ ALL_WORD,
+ ALL_FLOAT,
+ REVERSE_BYTES,
+ REVERSE_WORDS,
+ REVERSE_FLOATS
+}
\ No newline at end of file
diff --git a/intermediate/test/TestInstructions.kt b/intermediate/test/TestInstructions.kt
index 814fb154e..a3f3b5313 100644
--- a/intermediate/test/TestInstructions.kt
+++ b/intermediate/test/TestInstructions.kt
@@ -2,7 +2,6 @@ import io.kotest.assertions.throwables.shouldThrow
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
-import org.junit.jupiter.api.fail
import prog8.intermediate.*