From 6da048ba4c4377444979e55fb2934a6db82b43b3 Mon Sep 17 00:00:00 2001 From: Irmen de Jong Date: Sat, 15 Sep 2018 03:25:56 +0200 Subject: [PATCH] some type conversion opcodes added --- docs/source/programming.rst | 6 ++--- il65/src/il65/Main.kt | 21 +++++++-------- il65/src/il65/stackvm/StackVm.kt | 46 ++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 14 deletions(-) diff --git a/docs/source/programming.rst b/docs/source/programming.rst index cddd9c537..79205ec55 100644 --- a/docs/source/programming.rst +++ b/docs/source/programming.rst @@ -367,9 +367,9 @@ Defining a subroutine Subroutines are parts of the code that can be repeatedly invoked using a subroutine call from elsewhere. Their definition, using the sub statement, includes the specification of the required input- and output parameters. -For now, only register based parameters are supported (A, X, Y and paired registers, -the carry status bit SC and the interrupt disable bit SI as specials). -For subroutine return values, the special SZ register is also available, it means the zero status bit. +For now, only register based parameters are supported (A, X, Y and paired registers AX, AY and XY, +and various flags of the status register P: Pc (carry), Pz (zero), Pn (negative), Pv (overflow). +For subroutine return values, it is the same (registers, status flags). Subroutines can be defined in a Block, but also nested inside another subroutine. Everything is scoped accordingly. diff --git a/il65/src/il65/Main.kt b/il65/src/il65/Main.kt index cd4a8c798..f05a62c37 100644 --- a/il65/src/il65/Main.kt +++ b/il65/src/il65/Main.kt @@ -11,19 +11,18 @@ import kotlin.system.exitProcess fun main(args: Array) { + println("\nIL65 compiler by Irmen de Jong (irmen@razorvine.net)") + println("This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html\n") + if(args.size != 1) { + System.err.println("requires one argument: name of module file") + exitProcess(1) + } + + val startTime = System.currentTimeMillis() + val filepath = Paths.get(args[0]).normalize() + try { - println("\nIL65 compiler by Irmen de Jong (irmen@razorvine.net)") - println("This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html\n") - // import main module and process additional imports - - if(args.size != 1) { - System.err.println("module filename argument missing") - exitProcess(1) - } - - val startTime = System.currentTimeMillis() - val filepath = Paths.get(args[0]).normalize() val moduleAst = importModule(filepath) moduleAst.linkParents() val globalNameSpaceBeforeOptimization = moduleAst.definingScope() diff --git a/il65/src/il65/stackvm/StackVm.kt b/il65/src/il65/stackvm/StackVm.kt index cde1c0cdc..8a6a6af44 100644 --- a/il65/src/il65/stackvm/StackVm.kt +++ b/il65/src/il65/stackvm/StackVm.kt @@ -11,6 +11,7 @@ import java.util.regex.Pattern import javax.swing.Timer import kotlin.math.max import kotlin.math.pow +import kotlin.system.exitProcess enum class Opcode { @@ -66,6 +67,12 @@ enum class Opcode { LSB, MSB, + // numeric type conversions not covered by other opcodes + B2WORD, // convert a byte into a word where it is the lower eight bits $00xx + MSB2WORD, // convert a byte into a word where it is the upper eight bits $xx00 + B2FLOAT, // convert byte into floating point + W2FLOAT, // convert word into floating point + // logical operations AND, OR, @@ -1221,6 +1228,38 @@ class StackVm(val traceOutputFile: String?) { val (top, second) = evalstack.pop2() evalstack.push(second.compareNotEqual(top)) } + Opcode.B2WORD -> { + val byte = evalstack.pop() + if(byte.type==DataType.BYTE) { + evalstack.push(Value(DataType.WORD, byte.integerValue())) + } else { + throw VmExecutionException("attempt to make a word from a non-byte value $byte") + } + } + Opcode.MSB2WORD -> { + val byte = evalstack.pop() + if(byte.type==DataType.BYTE) { + evalstack.push(Value(DataType.WORD, byte.integerValue() * 256)) + } else { + throw VmExecutionException("attempt to make a word from a non-byte value $byte") + } + } + Opcode.B2FLOAT -> { + val byte = evalstack.pop() + if(byte.type==DataType.BYTE) { + evalstack.push(Value(DataType.FLOAT, byte.integerValue())) + } else { + throw VmExecutionException("attempt to make a float from a non-byte value $byte") + } + } + Opcode.W2FLOAT -> { + val byte = evalstack.pop() + if(byte.type==DataType.WORD) { + evalstack.push(Value(DataType.FLOAT, byte.integerValue())) + } else { + throw VmExecutionException("attempt to make a float from a non-word value $byte") + } + } else -> throw VmExecutionException("unimplemented opcode: ${ins.opcode}") } @@ -1235,6 +1274,13 @@ class StackVm(val traceOutputFile: String?) { fun main(args: Array) { + println("\nStackVM by Irmen de Jong (irmen@razorvine.net)") + println("This software is licensed under the GNU GPL 3.0, see https://www.gnu.org/licenses/gpl.html\n") + if(args.size != 1) { + System.err.println("requires one argument: name of stackvm sourcecode file") + exitProcess(1) + } + val program = Program.load(args.first()) val vm = StackVm(traceOutputFile = null) val dialog = ScreenDialog()