Compare commits

..

1 Commits

Author SHA1 Message Date
Irmen de Jong
df56be32b2 working on long variable type 2025-07-15 20:28:03 +02:00
8 changed files with 117 additions and 69 deletions

View File

@@ -82,7 +82,6 @@ internal class AstChecker(private val program: Program,
} }
} }
checkLongType(identifier)
val stmt = identifier.targetStatement(program.builtinFunctions) val stmt = identifier.targetStatement(program.builtinFunctions)
if(stmt==null) { if(stmt==null) {
if(identifier.parent is ArrayIndexedExpression) { if(identifier.parent is ArrayIndexedExpression) {
@@ -362,10 +361,6 @@ internal class AstChecker(private val program: Program,
super.visit(label) super.visit(label)
} }
override fun visit(numLiteral: NumericLiteral) {
checkLongType(numLiteral)
}
private fun hasReturnOrExternalJumpOrRts(scope: IStatementContainer): Boolean { private fun hasReturnOrExternalJumpOrRts(scope: IStatementContainer): Boolean {
class Searcher: IAstVisitor class Searcher: IAstVisitor
{ {
@@ -807,7 +802,6 @@ internal class AstChecker(private val program: Program,
} }
override fun visit(addressOf: AddressOf) { override fun visit(addressOf: AddressOf) {
checkLongType(addressOf)
val variable=addressOf.identifier?.targetVarDecl() val variable=addressOf.identifier?.targetVarDecl()
if (variable!=null) { if (variable!=null) {
if (variable.type == VarDeclType.CONST && addressOf.arrayIndex == null) if (variable.type == VarDeclType.CONST && addressOf.arrayIndex == null)
@@ -840,8 +834,6 @@ internal class AstChecker(private val program: Program,
if(decl.names.size>1) if(decl.names.size>1)
throw InternalCompilerException("vardecls with multiple names should have been converted into individual vardecls") throw InternalCompilerException("vardecls with multiple names should have been converted into individual vardecls")
if(decl.datatype.isLong && decl.type!=VarDeclType.CONST)
errors.err("cannot use long type for variables; only for constants", decl.position)
if(decl.type==VarDeclType.MEMORY) { if(decl.type==VarDeclType.MEMORY) {
if (decl.datatype.isString) if (decl.datatype.isString)
errors.err("strings cannot be memory-mapped", decl.position) errors.err("strings cannot be memory-mapped", decl.position)
@@ -1283,7 +1275,6 @@ internal class AstChecker(private val program: Program,
} }
} }
checkLongType(expr)
val dt = expr.expression.inferType(program).getOrUndef() val dt = expr.expression.inferType(program).getOrUndef()
if(!dt.isUndefined) { if(!dt.isUndefined) {
@@ -1418,8 +1409,6 @@ internal class AstChecker(private val program: Program,
return return
} }
checkLongType(expr)
val leftIDt = expr.left.inferType(program) val leftIDt = expr.left.inferType(program)
val rightIDt = expr.right.inferType(program) val rightIDt = expr.right.inferType(program)
if(!leftIDt.isKnown || !rightIDt.isKnown) { if(!leftIDt.isKnown || !rightIDt.isKnown) {
@@ -1547,7 +1536,6 @@ internal class AstChecker(private val program: Program,
} }
override fun visit(typecast: TypecastExpression) { override fun visit(typecast: TypecastExpression) {
checkLongType(typecast)
if(typecast.type.isPassByRef) if(typecast.type.isPassByRef)
errors.err("cannot type cast to string or array type", typecast.position) errors.err("cannot type cast to string or array type", typecast.position)
@@ -1604,7 +1592,6 @@ internal class AstChecker(private val program: Program,
} }
override fun visit(functionCallExpr: FunctionCallExpression) { override fun visit(functionCallExpr: FunctionCallExpression) {
checkLongType(functionCallExpr)
// this function call is (part of) an expression, which should be in a statement somewhere. // this function call is (part of) an expression, which should be in a statement somewhere.
val stmtOfExpression = findParentNode<Statement>(functionCallExpr) val stmtOfExpression = findParentNode<Statement>(functionCallExpr)
?: throw FatalAstException("cannot determine statement scope of function call expression at ${functionCallExpr.position}") ?: throw FatalAstException("cannot determine statement scope of function call expression at ${functionCallExpr.position}")
@@ -1857,7 +1844,6 @@ internal class AstChecker(private val program: Program,
} }
args.forEach{ args.forEach{
checkLongType(it)
if(it.inferType(program).isStructInstance) if(it.inferType(program).isStructInstance)
errors.err("structs can only be passed via a pointer", it.position) errors.err("structs can only be passed via a pointer", it.position)
} }
@@ -1870,7 +1856,6 @@ internal class AstChecker(private val program: Program,
} }
override fun visit(arrayIndexedExpression: ArrayIndexedExpression) { override fun visit(arrayIndexedExpression: ArrayIndexedExpression) {
checkLongType(arrayIndexedExpression)
val target = arrayIndexedExpression.plainarrayvar?.targetStatement(program.builtinFunctions) val target = arrayIndexedExpression.plainarrayvar?.targetStatement(program.builtinFunctions)
if(target is VarDecl) { if(target is VarDecl) {
if (!target.datatype.isIterable && !target.datatype.isUnsignedWord && !target.datatype.isPointer) if (!target.datatype.isIterable && !target.datatype.isUnsignedWord && !target.datatype.isPointer)
@@ -2092,17 +2077,6 @@ internal class AstChecker(private val program: Program,
errors.err("unable to determine type of dereferenced pointer expression", deref.position) errors.err("unable to determine type of dereferenced pointer expression", deref.position)
} }
private fun checkLongType(expression: Expression) {
if(expression.inferType(program) issimpletype BaseDataType.LONG) {
if((expression.parent as? VarDecl)?.type!=VarDeclType.CONST) {
if (expression.parent !is RepeatLoop) {
if (errors.noErrorForLine(expression.position))
errors.err("integer overflow", expression.position)
}
}
}
}
private fun checkValueTypeAndRangeString(targetDt: DataType, value: StringLiteral) : Boolean { private fun checkValueTypeAndRangeString(targetDt: DataType, value: StringLiteral) : Boolean {
return if (targetDt.isString) { return if (targetDt.isString) {
when { when {

View File

@@ -1,31 +1,8 @@
%option no_sysinit
%zeropage basicsafe %zeropage basicsafe
%import textio
main { main {
sub start() { sub start() {
ubyte @shared index = 3 long @shared num = 123456789
ubyte[10] array
alias curframe = array
cx16.r0 = &curframe
cx16.r1 = &curframe[3]
cx16.r2 = &curframe + 3
cx16.r3 = &curframe[index]
cx16.r4 = &curframe + index
txt.print_uw(cx16.r0)
txt.nl()
txt.print_uw(cx16.r1)
txt.spc()
txt.print_uw(cx16.r2)
txt.nl()
txt.print_uw(cx16.r3)
txt.spc()
txt.print_uw(cx16.r4)
txt.nl()
} }
} }
; code sizes on 11.5: 6502: $20a virt: 140 instr
; code sizes on 12.0: 6502: ???? virt: ??? instr (BORKED!)

View File

@@ -23,8 +23,7 @@ Status flags: Carry, Zero, Negative. NOTE: status flags are only affected by t
Instruction set is mostly a load/store architecture, there are few instructions operating on memory directly. Instruction set is mostly a load/store architecture, there are few instructions operating on memory directly.
Value types: integers (.b=byte=8 bits, .w=word=16 bits) and float (.f=64 bits). Omitting it defaults to b if the instruction requires a type. Value types: integers (.b=byte=8 bits, .w=word=16 bits, .l=long=32 bits) and float (.f=64 bits). Omitting it defaults to b if the instruction requires a type.
Currently ther is NO support for 24 or 32 bits integers.
There is no distinction between signed and unsigned integers. There is no distinction between signed and unsigned integers.
Instead, a different instruction is used if a distinction should be made (for example div and divs). Instead, a different instruction is used if a distinction should be made (for example div and divs).
Floating point operations are just 'f' typed regular instructions, however there are a few unique fp conversion instructions. Floating point operations are just 'f' typed regular instructions, however there are a few unique fp conversion instructions.
@@ -34,7 +33,7 @@ NOTE: Labels in source text should always start with an underscore.
LOAD/STORE LOAD/STORE
---------- ----------
All have type b or w or f. All have type b or w or l or f.
load reg1, value - load immediate value into register. If you supply a symbol, loads the *address* of the symbol! (variable values are loaded from memory via the loadm instruction) load reg1, value - load immediate value into register. If you supply a symbol, loads the *address* of the symbol! (variable values are loaded from memory via the loadm instruction)
loadm reg1, address - load reg1 with value at memory address loadm reg1, address - load reg1 with value at memory address
@@ -518,8 +517,8 @@ val OpcodesThatSetStatusbits = OpcodesThatSetStatusbitsButNotCarry + OpcodesThat
enum class IRDataType { enum class IRDataType {
BYTE, BYTE,
WORD, WORD,
LONG,
FLOAT FLOAT
// TODO add INT (32-bit)? INT24 (24-bit)?
} }
enum class OperandDirection { enum class OperandDirection {
@@ -862,6 +861,7 @@ data class IRInstruction(
when (type) { when (type) {
IRDataType.BYTE -> require(immediate in -128..255) { "immediate value out of range for byte: $immediate" } IRDataType.BYTE -> require(immediate in -128..255) { "immediate value out of range for byte: $immediate" }
IRDataType.WORD -> require(immediate in -32768..65535) { "immediate value out of range for word: $immediate" } IRDataType.WORD -> require(immediate in -32768..65535) { "immediate value out of range for word: $immediate" }
IRDataType.LONG -> require(immediate in -2147483647..2147483647) { "immediate value out of range for long: $immediate" }
IRDataType.FLOAT, null -> {} IRDataType.FLOAT, null -> {}
} }
} }
@@ -1115,6 +1115,7 @@ data class IRInstruction(
when(it.reg.dt) { when(it.reg.dt) {
IRDataType.BYTE -> result.add("${location}r${it.reg.registerNum}.b$cpuReg,") IRDataType.BYTE -> result.add("${location}r${it.reg.registerNum}.b$cpuReg,")
IRDataType.WORD -> result.add("${location}r${it.reg.registerNum}.w$cpuReg,") IRDataType.WORD -> result.add("${location}r${it.reg.registerNum}.w$cpuReg,")
IRDataType.LONG -> result.add("${location}r${it.reg.registerNum}.l$cpuReg,")
IRDataType.FLOAT -> result.add("${location}fr${it.reg.registerNum}.f$cpuReg,") IRDataType.FLOAT -> result.add("${location}fr${it.reg.registerNum}.f$cpuReg,")
} }
} }
@@ -1136,12 +1137,14 @@ data class IRInstruction(
when (returnspec.dt) { when (returnspec.dt) {
IRDataType.BYTE -> "r${returnspec.registerNum}.b" IRDataType.BYTE -> "r${returnspec.registerNum}.b"
IRDataType.WORD -> "r${returnspec.registerNum}.w" IRDataType.WORD -> "r${returnspec.registerNum}.w"
IRDataType.LONG -> "r${returnspec.registerNum}.l"
IRDataType.FLOAT -> "fr${returnspec.registerNum}.f" IRDataType.FLOAT -> "fr${returnspec.registerNum}.f"
} }
} else { } else {
when (returnspec.dt) { when (returnspec.dt) {
IRDataType.BYTE -> "r${returnspec.registerNum}.b@" + cpuReg IRDataType.BYTE -> "r${returnspec.registerNum}.b@" + cpuReg
IRDataType.WORD -> "r${returnspec.registerNum}.w@" + cpuReg IRDataType.WORD -> "r${returnspec.registerNum}.w@" + cpuReg
IRDataType.LONG -> "r${returnspec.registerNum}.l@" + cpuReg
IRDataType.FLOAT -> "r${returnspec.registerNum}.f@" + cpuReg IRDataType.FLOAT -> "r${returnspec.registerNum}.f@" + cpuReg
} }
} }

View File

@@ -216,6 +216,7 @@ fun parseIRCodeLine(line: String): Either<IRInstruction, String> {
if (immediateInt!=null && (immediateInt < -32768 || immediateInt > 65535)) if (immediateInt!=null && (immediateInt < -32768 || immediateInt > 65535))
throw IRParseException("immediate value out of range for word: $immediateInt") throw IRParseException("immediate value out of range for word: $immediateInt")
} }
IRDataType.LONG -> {}
IRDataType.FLOAT -> {} IRDataType.FLOAT -> {}
null -> {} null -> {}
} }
@@ -368,6 +369,7 @@ fun irType(type: DataType): IRDataType {
BaseDataType.UBYTE, BaseDataType.UBYTE,
BaseDataType.BYTE -> IRDataType.BYTE BaseDataType.BYTE -> IRDataType.BYTE
BaseDataType.UWORD, BaseDataType.WORD, BaseDataType.POINTER -> IRDataType.WORD BaseDataType.UWORD, BaseDataType.WORD, BaseDataType.POINTER -> IRDataType.WORD
BaseDataType.LONG -> IRDataType.LONG
BaseDataType.FLOAT -> IRDataType.FLOAT BaseDataType.FLOAT -> IRDataType.FLOAT
BaseDataType.STRUCT_INSTANCE -> TODO("IR datatype for struct instances") BaseDataType.STRUCT_INSTANCE -> TODO("IR datatype for struct instances")
else -> throw AssemblyError("no IR datatype for $type") else -> throw AssemblyError("no IR datatype for $type")

View File

@@ -32,19 +32,30 @@ class Memory {
return (mem[address] + 256u*mem[address+1]).toUShort() return (mem[address] + 256u*mem[address+1]).toUShort()
} }
fun getSL(address: Int): Int {
return (mem[address] + 256u*mem[address+1] + 65536u*mem[address+2] + 16777216u*mem[address+3]).toInt()
}
fun getSW(address: Int): Short { fun getSW(address: Int): Short {
return (mem[address].toInt() + mem[address+1].toInt()*256).toShort() return (mem[address].toInt() + mem[address+1].toInt()*256).toShort()
} }
fun setUW(address: Int, value: UShort) { fun setUW(address: Int, value: UShort) {
mem[address+1] = (value.toInt() ushr 8).toUByte()
mem[address] = value.toUByte() mem[address] = value.toUByte()
mem[address+1] = (value.toInt() ushr 8).toUByte()
}
fun setSL(address: Int, value: Int) {
mem[address] = value.toUByte()
mem[address+1] = (value ushr 8).toUByte()
mem[address+2] = (value ushr 16).toUByte()
mem[address+3] = (value ushr 24).toUByte()
} }
fun setSW(address: Int, value: Short) { fun setSW(address: Int, value: Short) {
val uv = value.toUShort() val uv = value.toUShort()
mem[address+1] = (uv.toInt() ushr 8).toUByte()
mem[address] = uv.toUByte() mem[address] = uv.toUByte()
mem[address+1] = (uv.toInt() ushr 8).toUByte()
} }
fun setFloat(address: Int, value: Double) { fun setFloat(address: Int, value: Double) {

View File

@@ -6,14 +6,14 @@ package prog8.vm
* A,X and Y "physical" 6502 registers. * A,X and Y "physical" 6502 registers.
*/ */
class Registers { class Registers {
private val registers = Array<UShort>(99999) { 0u } private val registers = Array<Int>(99999) { 0 }
private val floatRegisters = Array(99999) { 0.0 } private val floatRegisters = Array(99999) { 0.0 }
var cpuA: UByte = 0u var cpuA: UByte = 0u
var cpuX: UByte = 0u var cpuX: UByte = 0u
var cpuY: UByte = 0u var cpuY: UByte = 0u
fun reset() { fun reset() {
registers.fill(0u) registers.fill(0)
floatRegisters.fill(0.0) floatRegisters.fill(0.0)
cpuA = 0u cpuA = 0u
cpuX = 0u cpuX = 0u
@@ -21,26 +21,32 @@ class Registers {
} }
fun setUB(reg: Int, value: UByte) { fun setUB(reg: Int, value: UByte) {
registers[reg] = registers[reg] and 0xff00u or value.toUShort() registers[reg] = value.toInt()
} }
fun setSB(reg: Int, value: Byte) { fun setSB(reg: Int, value: Byte) {
registers[reg] = registers[reg] and 0xff00u or (value.toUShort() and 0x00ffu) registers[reg] = value.toInt()
} }
fun setUW(reg: Int, value: UShort) { fun setUW(reg: Int, value: UShort) {
registers[reg] = value registers[reg] = value.toInt()
} }
fun setSW(reg: Int, value: Short) { fun setSW(reg: Int, value: Short) {
registers[reg] = value.toUShort() registers[reg] = value.toInt()
}
fun setSL(reg: Int, value: Int) {
registers[reg] = value
} }
fun getUB(reg: Int) = registers[reg].toUByte() fun getUB(reg: Int) = registers[reg].toUByte()
fun getSB(reg: Int) = registers[reg].toByte() fun getSB(reg: Int) = registers[reg].toByte()
fun getUW(reg: Int) = registers[reg] fun getUW(reg: Int) = registers[reg].toUShort()
fun getSL(reg: Int) = registers[reg]
fun getSW(reg: Int) = registers[reg].toShort() fun getSW(reg: Int) = registers[reg].toShort()

View File

@@ -143,6 +143,7 @@ object SysCalls {
when(it.reg.dt) { when(it.reg.dt) {
IRDataType.BYTE -> vm.registers.getUB(it.reg.registerNum) IRDataType.BYTE -> vm.registers.getUB(it.reg.registerNum)
IRDataType.WORD -> vm.registers.getUW(it.reg.registerNum) IRDataType.WORD -> vm.registers.getUW(it.reg.registerNum)
IRDataType.LONG -> vm.registers.getSL(it.reg.registerNum)
IRDataType.FLOAT -> vm.registers.getFloat(it.reg.registerNum) IRDataType.FLOAT -> vm.registers.getFloat(it.reg.registerNum)
} }
} }
@@ -164,6 +165,7 @@ object SysCalls {
when(returns.dt) { when(returns.dt) {
IRDataType.BYTE -> vm.registers.setUB(returns.registerNum, vv.toInt().toUByte()) IRDataType.BYTE -> vm.registers.setUB(returns.registerNum, vv.toInt().toUByte())
IRDataType.WORD -> vm.registers.setUW(returns.registerNum, vv.toInt().toUShort()) IRDataType.WORD -> vm.registers.setUW(returns.registerNum, vv.toInt().toUShort())
IRDataType.LONG -> vm.registers.setSL(returns.registerNum, vv.toInt())
IRDataType.FLOAT -> vm.registers.setFloat(returns.registerNum, vv) IRDataType.FLOAT -> vm.registers.setFloat(returns.registerNum, vv)
} }
} }

View File

@@ -360,6 +360,11 @@ class VirtualMachine(irProgram: IRProgram) {
statusZero = value==0 statusZero = value==0
statusNegative = value>=0x8000 statusNegative = value>=0x8000
} }
IRDataType.LONG -> {
registers.setSL(reg, value)
statusZero = value==0
statusNegative = value<0
}
IRDataType.FLOAT -> throw IllegalArgumentException("attempt to set integer result register but float type") IRDataType.FLOAT -> throw IllegalArgumentException("attempt to set integer result register but float type")
} }
} }
@@ -377,6 +382,10 @@ class VirtualMachine(irProgram: IRProgram) {
val value = registers.getUW(i.reg1!!) val value = registers.getUW(i.reg1!!)
valueStack.pushw(value) valueStack.pushw(value)
} }
IRDataType.LONG -> {
val value = registers.getSL(i.reg1!!)
valueStack.pushl(value)
}
IRDataType.FLOAT -> { IRDataType.FLOAT -> {
val value = registers.getFloat(i.fpReg1!!) val value = registers.getFloat(i.fpReg1!!)
valueStack.pushf(value) valueStack.pushf(value)
@@ -389,6 +398,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) { when(i.type!!) {
IRDataType.BYTE -> setResultReg(i.reg1!!, valueStack.removeLast().toInt(), i.type!!) IRDataType.BYTE -> setResultReg(i.reg1!!, valueStack.removeLast().toInt(), i.type!!)
IRDataType.WORD -> setResultReg(i.reg1!!, valueStack.popw().toInt(), i.type!!) IRDataType.WORD -> setResultReg(i.reg1!!, valueStack.popw().toInt(), i.type!!)
IRDataType.LONG -> setResultReg(i.reg1!!, valueStack.popl(), i.type!!)
IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, valueStack.popf()) IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, valueStack.popf())
} }
nextPc() nextPc()
@@ -425,6 +435,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(value.dt!!) { when(value.dt!!) {
IRDataType.BYTE -> valueStack.add(value.value as UByte) IRDataType.BYTE -> valueStack.add(value.value as UByte)
IRDataType.WORD -> valueStack.pushw(value.value as UShort) IRDataType.WORD -> valueStack.pushw(value.value as UShort)
IRDataType.LONG -> valueStack.pushl(value.value as Int)
IRDataType.FLOAT -> valueStack.pushf(value.value as Double) IRDataType.FLOAT -> valueStack.pushf(value.value as Double)
} }
value.dt=null value.dt=null
@@ -472,6 +483,11 @@ class VirtualMachine(irProgram: IRProgram) {
registers.setUW(i.reg1!!, value) registers.setUW(i.reg1!!, value)
statusbitsNZ(value.toInt(), i.type!!) statusbitsNZ(value.toInt(), i.type!!)
} }
IRDataType.LONG -> {
val value = memory.getSL(i.address!!)
registers.setSL(i.reg1!!, value)
statusbitsNZ(value, i.type!!)
}
IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, memory.getFloat(i.address!!)) IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, memory.getFloat(i.address!!))
} }
nextPc() nextPc()
@@ -489,6 +505,11 @@ class VirtualMachine(irProgram: IRProgram) {
registers.setUW(i.reg1!!, value) registers.setUW(i.reg1!!, value)
statusbitsNZ(value.toInt(), i.type!!) statusbitsNZ(value.toInt(), i.type!!)
} }
IRDataType.LONG -> {
val value = memory.getSL(registers.getUW(i.reg2!!).toInt())
registers.setSL(i.reg1!!, value)
statusbitsNZ(value, i.type!!)
}
IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, memory.getFloat(registers.getUW(i.reg1!!).toInt())) IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, memory.getFloat(registers.getUW(i.reg1!!).toInt()))
} }
nextPc() nextPc()
@@ -508,6 +529,11 @@ class VirtualMachine(irProgram: IRProgram) {
registers.setUW(i.reg1!!, value) registers.setUW(i.reg1!!, value)
statusbitsNZ(value.toInt(), i.type!!) statusbitsNZ(value.toInt(), i.type!!)
} }
IRDataType.LONG -> {
val value = memory.getSL(registers.getUW(i.reg2!!).toInt() + offset)
registers.setSL(i.reg1!!, value)
statusbitsNZ(value.toInt(), i.type!!)
}
IRDataType.FLOAT -> { IRDataType.FLOAT -> {
registers.setFloat(i.fpReg1!!, memory.getFloat(registers.getUW(i.reg1!!).toInt() + offset)) registers.setFloat(i.fpReg1!!, memory.getFloat(registers.getUW(i.reg1!!).toInt() + offset))
} }
@@ -527,6 +553,11 @@ class VirtualMachine(irProgram: IRProgram) {
registers.setUW(i.reg1!!, value) registers.setUW(i.reg1!!, value)
statusbitsNZ(value.toInt(), i.type!!) statusbitsNZ(value.toInt(), i.type!!)
} }
IRDataType.LONG -> {
val value = memory.getSL(i.address!! + registers.getUB(i.reg2!!).toInt())
registers.setSL(i.reg1!!, value)
statusbitsNZ(value, i.type!!)
}
IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, memory.getFloat(i.address!! + registers.getUB(i.reg1!!).toInt())) IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, memory.getFloat(i.address!! + registers.getUB(i.reg1!!).toInt()))
} }
nextPc() nextPc()
@@ -546,6 +577,12 @@ class VirtualMachine(irProgram: IRProgram) {
registers.setUW(i.reg1!!, value) registers.setUW(i.reg1!!, value)
statusbitsNZ(value.toInt(), i.type!!) statusbitsNZ(value.toInt(), i.type!!)
} }
IRDataType.LONG -> {
val pointer = memory.getUW(i.address!!) + registers.getUB(i.reg2!!)
val value = memory.getSL(pointer.toInt())
registers.setSL(i.reg1!!, value)
statusbitsNZ(value, i.type!!)
}
IRDataType.FLOAT -> { IRDataType.FLOAT -> {
val pointer = memory.getUW(i.address!!) + registers.getUB(i.reg1!!) val pointer = memory.getUW(i.address!!) + registers.getUB(i.reg1!!)
registers.setFloat(i.fpReg1!!, memory.getFloat(pointer.toInt())) registers.setFloat(i.fpReg1!!, memory.getFloat(pointer.toInt()))
@@ -566,6 +603,11 @@ class VirtualMachine(irProgram: IRProgram) {
registers.setUW(i.reg1!!, value) registers.setUW(i.reg1!!, value)
statusbitsNZ(value.toInt(), i.type!!) statusbitsNZ(value.toInt(), i.type!!)
} }
IRDataType.LONG -> {
val value = registers.getSL(i.reg2!!)
registers.setSL(i.reg1!!, value)
statusbitsNZ(value, i.type!!)
}
IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, registers.getFloat(i.fpReg2!!)) IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, registers.getFloat(i.fpReg2!!))
} }
nextPc() nextPc()
@@ -575,6 +617,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) { when(i.type!!) {
IRDataType.BYTE -> memory.setUB(i.address!!, registers.getUB(i.reg1!!)) IRDataType.BYTE -> memory.setUB(i.address!!, registers.getUB(i.reg1!!))
IRDataType.WORD -> memory.setUW(i.address!!, registers.getUW(i.reg1!!)) IRDataType.WORD -> memory.setUW(i.address!!, registers.getUW(i.reg1!!))
IRDataType.LONG -> memory.setSL(i.address!!, registers.getSL(i.reg1!!))
IRDataType.FLOAT -> memory.setFloat(i.address!!, registers.getFloat(i.fpReg1!!)) IRDataType.FLOAT -> memory.setFloat(i.address!!, registers.getFloat(i.fpReg1!!))
} }
nextPc() nextPc()
@@ -584,6 +627,7 @@ class VirtualMachine(irProgram: IRProgram) {
when (i.type!!) { when (i.type!!) {
IRDataType.BYTE -> memory.setUB(registers.getUW(i.reg2!!).toInt(), registers.getUB(i.reg1!!)) IRDataType.BYTE -> memory.setUB(registers.getUW(i.reg2!!).toInt(), registers.getUB(i.reg1!!))
IRDataType.WORD -> memory.setUW(registers.getUW(i.reg2!!).toInt(), registers.getUW(i.reg1!!)) IRDataType.WORD -> memory.setUW(registers.getUW(i.reg2!!).toInt(), registers.getUW(i.reg1!!))
IRDataType.LONG -> memory.setSL(registers.getUW(i.reg2!!).toInt(), registers.getSL(i.reg1!!))
IRDataType.FLOAT -> memory.setFloat(registers.getUW(i.reg1!!).toInt(), registers.getFloat(i.fpReg1!!)) IRDataType.FLOAT -> memory.setFloat(registers.getUW(i.reg1!!).toInt(), registers.getFloat(i.fpReg1!!))
} }
nextPc() nextPc()
@@ -595,6 +639,7 @@ class VirtualMachine(irProgram: IRProgram) {
when (i.type!!) { when (i.type!!) {
IRDataType.BYTE -> memory.setUB(registers.getUW(i.reg2!!).toInt() + offset, registers.getUB(i.reg1!!)) IRDataType.BYTE -> memory.setUB(registers.getUW(i.reg2!!).toInt() + offset, registers.getUB(i.reg1!!))
IRDataType.WORD -> memory.setUW(registers.getUW(i.reg2!!).toInt() + offset, registers.getUW(i.reg1!!)) IRDataType.WORD -> memory.setUW(registers.getUW(i.reg2!!).toInt() + offset, registers.getUW(i.reg1!!))
IRDataType.LONG -> memory.setSL(registers.getUW(i.reg2!!).toInt() + offset, registers.getSL(i.reg1!!))
IRDataType.FLOAT -> memory.setFloat(registers.getUW(i.reg1!!).toInt() + offset, registers.getFloat(i.fpReg1!!)) IRDataType.FLOAT -> memory.setFloat(registers.getUW(i.reg1!!).toInt() + offset, registers.getFloat(i.fpReg1!!))
} }
nextPc() nextPc()
@@ -604,6 +649,7 @@ class VirtualMachine(irProgram: IRProgram) {
when (i.type!!) { when (i.type!!) {
IRDataType.BYTE -> memory.setUB(i.address!! + registers.getUB(i.reg2!!).toInt(), registers.getUB(i.reg1!!)) IRDataType.BYTE -> memory.setUB(i.address!! + registers.getUB(i.reg2!!).toInt(), registers.getUB(i.reg1!!))
IRDataType.WORD -> memory.setUW(i.address!! + registers.getUB(i.reg2!!).toInt(), registers.getUW(i.reg1!!)) IRDataType.WORD -> memory.setUW(i.address!! + registers.getUB(i.reg2!!).toInt(), registers.getUW(i.reg1!!))
IRDataType.LONG -> memory.setSL(i.address!! + registers.getUB(i.reg2!!).toInt(), registers.getSL(i.reg1!!))
IRDataType.FLOAT -> memory.setFloat(i.address!! + registers.getUB(i.reg1!!).toInt(), registers.getFloat(i.fpReg1!!)) IRDataType.FLOAT -> memory.setFloat(i.address!! + registers.getUB(i.reg1!!).toInt(), registers.getFloat(i.fpReg1!!))
} }
nextPc() nextPc()
@@ -631,6 +677,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) { when(i.type!!) {
IRDataType.BYTE -> memory.setUB(i.address!!, 0u) IRDataType.BYTE -> memory.setUB(i.address!!, 0u)
IRDataType.WORD -> memory.setUW(i.address!!, 0u) IRDataType.WORD -> memory.setUW(i.address!!, 0u)
IRDataType.LONG -> memory.setSL(i.address!!, 0)
IRDataType.FLOAT -> memory.setFloat(i.address!!, 0.0) IRDataType.FLOAT -> memory.setFloat(i.address!!, 0.0)
} }
nextPc() nextPc()
@@ -640,6 +687,7 @@ class VirtualMachine(irProgram: IRProgram) {
when (i.type!!) { when (i.type!!) {
IRDataType.BYTE -> memory.setUB(registers.getUW(i.reg1!!).toInt(), 0u) IRDataType.BYTE -> memory.setUB(registers.getUW(i.reg1!!).toInt(), 0u)
IRDataType.WORD -> memory.setUW(registers.getUW(i.reg1!!).toInt(), 0u) IRDataType.WORD -> memory.setUW(registers.getUW(i.reg1!!).toInt(), 0u)
IRDataType.LONG -> memory.setSL(registers.getUW(i.reg1!!).toInt(), 0)
IRDataType.FLOAT -> memory.setFloat(registers.getUW(i.reg1!!).toInt(), 0.0) IRDataType.FLOAT -> memory.setFloat(registers.getUW(i.reg1!!).toInt(), 0.0)
} }
nextPc() nextPc()
@@ -649,6 +697,7 @@ class VirtualMachine(irProgram: IRProgram) {
when (i.type!!) { when (i.type!!) {
IRDataType.BYTE -> memory.setUB(i.address!! + registers.getUB(i.reg1!!).toInt(), 0u) IRDataType.BYTE -> memory.setUB(i.address!! + registers.getUB(i.reg1!!).toInt(), 0u)
IRDataType.WORD -> memory.setUW(i.address!! + registers.getUB(i.reg1!!).toInt(), 0u) IRDataType.WORD -> memory.setUW(i.address!! + registers.getUB(i.reg1!!).toInt(), 0u)
IRDataType.LONG -> memory.setSL(i.address!! + registers.getUB(i.reg1!!).toInt(), 0)
IRDataType.FLOAT -> memory.setFloat(i.address!! + registers.getUB(i.reg1!!).toInt(), 0.0) IRDataType.FLOAT -> memory.setFloat(i.address!! + registers.getUB(i.reg1!!).toInt(), 0.0)
} }
nextPc() nextPc()
@@ -1922,6 +1971,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) { when(i.type!!) {
IRDataType.BYTE -> registers.setUB(i.reg1!!, value.toUByte()) IRDataType.BYTE -> registers.setUB(i.reg1!!, value.toUByte())
IRDataType.WORD -> registers.setUW(i.reg1!!, value.toUShort()) IRDataType.WORD -> registers.setUW(i.reg1!!, value.toUShort())
IRDataType.LONG -> registers.setSL(i.reg1!!, value)
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i") IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
} }
statusbitsNZ(value, i.type!!) statusbitsNZ(value, i.type!!)
@@ -1973,6 +2023,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) { when(i.type!!) {
IRDataType.BYTE -> registers.setUB(i.reg1!!, value.toUByte()) IRDataType.BYTE -> registers.setUB(i.reg1!!, value.toUByte())
IRDataType.WORD -> registers.setUW(i.reg1!!, value.toUShort()) IRDataType.WORD -> registers.setUW(i.reg1!!, value.toUShort())
IRDataType.LONG -> registers.setSL(i.reg1!!, value)
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i") IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
} }
statusbitsNZ(value, i.type!!) statusbitsNZ(value, i.type!!)
@@ -2022,6 +2073,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) { when(i.type!!) {
IRDataType.BYTE -> registers.setUB(i.reg1!!, registers.getUB(i.reg1!!).inv()) IRDataType.BYTE -> registers.setUB(i.reg1!!, registers.getUB(i.reg1!!).inv())
IRDataType.WORD -> registers.setUW(i.reg1!!, registers.getUW(i.reg1!!).inv()) IRDataType.WORD -> registers.setUW(i.reg1!!, registers.getUW(i.reg1!!).inv())
IRDataType.LONG -> registers.setSL(i.reg1!!, registers.getSL(i.reg1!!).inv())
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i") IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
} }
nextPc() nextPc()
@@ -2032,6 +2084,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) { when(i.type!!) {
IRDataType.BYTE -> memory.setUB(address, memory.getUB(address).inv()) IRDataType.BYTE -> memory.setUB(address, memory.getUB(address).inv())
IRDataType.WORD -> memory.setUW(address, memory.getUW(address).inv()) IRDataType.WORD -> memory.setUW(address, memory.getUW(address).inv())
IRDataType.LONG -> memory.setSL(address, memory.getSL(address).inv())
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i") IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
} }
nextPc() nextPc()
@@ -2042,6 +2095,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) { when(i.type!!) {
IRDataType.BYTE -> registers.setSB(i.reg1!!, (left shr right).toByte()) IRDataType.BYTE -> registers.setSB(i.reg1!!, (left shr right).toByte())
IRDataType.WORD -> registers.setSW(i.reg1!!, (left shr right).toShort()) IRDataType.WORD -> registers.setSW(i.reg1!!, (left shr right).toShort())
IRDataType.LONG -> registers.setSL(i.reg1!!, (left shr right))
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i") IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
} }
nextPc() nextPc()
@@ -2104,6 +2158,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) { when(i.type!!) {
IRDataType.BYTE -> registers.setUB(i.reg1!!, (left shr right.toInt()).toUByte()) IRDataType.BYTE -> registers.setUB(i.reg1!!, (left shr right.toInt()).toUByte())
IRDataType.WORD -> registers.setUW(i.reg1!!, (left shr right.toInt()).toUShort()) IRDataType.WORD -> registers.setUW(i.reg1!!, (left shr right.toInt()).toUShort())
IRDataType.LONG -> registers.setSL(i.reg1!!, (left shr right.toInt()).toInt())
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i") IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
} }
nextPc() nextPc()
@@ -2582,6 +2637,7 @@ class VirtualMachine(irProgram: IRProgram) {
return when(i.type) { return when(i.type) {
IRDataType.BYTE -> Pair(registers.getSB(i.reg1!!).toInt(), registers.getSB(i.reg2!!).toInt()) IRDataType.BYTE -> Pair(registers.getSB(i.reg1!!).toInt(), registers.getSB(i.reg2!!).toInt())
IRDataType.WORD -> Pair(registers.getSW(i.reg1!!).toInt(), registers.getSW(i.reg2!!).toInt()) IRDataType.WORD -> Pair(registers.getSW(i.reg1!!).toInt(), registers.getSW(i.reg2!!).toInt())
IRDataType.LONG -> Pair(registers.getSL(i.reg1!!), registers.getSL(i.reg2!!))
IRDataType.FLOAT -> { IRDataType.FLOAT -> {
throw IllegalArgumentException("can't use float here") throw IllegalArgumentException("can't use float here")
} }
@@ -2593,6 +2649,7 @@ class VirtualMachine(irProgram: IRProgram) {
return when(i.type) { return when(i.type) {
IRDataType.BYTE -> Pair(registers.getSB(i.reg1!!).toInt(), i.immediate!!) IRDataType.BYTE -> Pair(registers.getSB(i.reg1!!).toInt(), i.immediate!!)
IRDataType.WORD -> Pair(registers.getSW(i.reg1!!).toInt(), i.immediate!!) IRDataType.WORD -> Pair(registers.getSW(i.reg1!!).toInt(), i.immediate!!)
IRDataType.LONG -> Pair(registers.getSL(i.reg1!!), i.immediate!!)
IRDataType.FLOAT -> { IRDataType.FLOAT -> {
throw IllegalArgumentException("can't use float here") throw IllegalArgumentException("can't use float here")
} }
@@ -2604,8 +2661,8 @@ class VirtualMachine(irProgram: IRProgram) {
return when(i.type) { return when(i.type) {
IRDataType.BYTE -> Pair(registers.getUB(i.reg1!!).toUInt(), registers.getUB(i.reg2!!).toUInt()) IRDataType.BYTE -> Pair(registers.getUB(i.reg1!!).toUInt(), registers.getUB(i.reg2!!).toUInt())
IRDataType.WORD -> Pair(registers.getUW(i.reg1!!).toUInt(), registers.getUW(i.reg2!!).toUInt()) IRDataType.WORD -> Pair(registers.getUW(i.reg1!!).toUInt(), registers.getUW(i.reg2!!).toUInt())
IRDataType.FLOAT -> { IRDataType.LONG, IRDataType.FLOAT -> {
throw IllegalArgumentException("can't use float here") throw IllegalArgumentException("can't use long or float here")
} }
null -> throw IllegalArgumentException("need type for branch instruction") null -> throw IllegalArgumentException("need type for branch instruction")
} }
@@ -2615,8 +2672,8 @@ class VirtualMachine(irProgram: IRProgram) {
return when(i.type) { return when(i.type) {
IRDataType.BYTE -> Pair(registers.getUB(i.reg1!!).toUInt(), i.immediate!!.toUInt()) IRDataType.BYTE -> Pair(registers.getUB(i.reg1!!).toUInt(), i.immediate!!.toUInt())
IRDataType.WORD -> Pair(registers.getUW(i.reg1!!).toUInt(), i.immediate!!.toUInt()) IRDataType.WORD -> Pair(registers.getUW(i.reg1!!).toUInt(), i.immediate!!.toUInt())
IRDataType.FLOAT -> { IRDataType.LONG, IRDataType.FLOAT -> {
throw IllegalArgumentException("can't use float here") throw IllegalArgumentException("can't use long or float here")
} }
null -> throw IllegalArgumentException("need type for branch instruction") null -> throw IllegalArgumentException("need type for branch instruction")
} }
@@ -2626,8 +2683,8 @@ class VirtualMachine(irProgram: IRProgram) {
return when(i.type) { return when(i.type) {
IRDataType.BYTE -> Pair(registers.getUB(i.reg1!!).toUInt(), registers.getUB(i.reg2!!).toUInt()) IRDataType.BYTE -> Pair(registers.getUB(i.reg1!!).toUInt(), registers.getUB(i.reg2!!).toUInt())
IRDataType.WORD -> Pair(registers.getUW(i.reg1!!).toUInt(), registers.getUW(i.reg2!!).toUInt()) IRDataType.WORD -> Pair(registers.getUW(i.reg1!!).toUInt(), registers.getUW(i.reg2!!).toUInt())
IRDataType.FLOAT -> { IRDataType.LONG, IRDataType.FLOAT -> {
throw IllegalArgumentException("can't use float here") throw IllegalArgumentException("can't use long or float here")
} }
null -> throw IllegalArgumentException("need type for logical instruction") null -> throw IllegalArgumentException("need type for logical instruction")
} }
@@ -2637,6 +2694,7 @@ class VirtualMachine(irProgram: IRProgram) {
return when(i.type) { return when(i.type) {
IRDataType.BYTE -> Pair(registers.getSB(i.reg1!!).toInt(), registers.getSB(i.reg2!!).toInt()) IRDataType.BYTE -> Pair(registers.getSB(i.reg1!!).toInt(), registers.getSB(i.reg2!!).toInt())
IRDataType.WORD -> Pair(registers.getSW(i.reg1!!).toInt(), registers.getSW(i.reg2!!).toInt()) IRDataType.WORD -> Pair(registers.getSW(i.reg1!!).toInt(), registers.getSW(i.reg2!!).toInt())
IRDataType.LONG -> Pair(registers.getSL(i.reg1!!), registers.getSL(i.reg2!!))
IRDataType.FLOAT -> { IRDataType.FLOAT -> {
throw IllegalArgumentException("can't use float here") throw IllegalArgumentException("can't use float here")
} }
@@ -2750,6 +2808,13 @@ internal fun ArrayDeque<UByte>.pushw(value: UShort) {
add((value.toInt() ushr 8).toUByte()) add((value.toInt() ushr 8).toUByte())
} }
internal fun ArrayDeque<UByte>.pushl(value: Int) {
add((value and 255).toUByte())
add((value ushr 8).toUByte())
add((value ushr 16).toUByte())
add((value ushr 24).toUByte())
}
internal fun ArrayDeque<UByte>.pushf(value: Double) { internal fun ArrayDeque<UByte>.pushf(value: Double) {
// push float; lsb first, msb last // push float; lsb first, msb last
var bits = value.toBits() var bits = value.toBits()
@@ -2776,6 +2841,14 @@ internal fun ArrayDeque<UByte>.popw(): UShort {
return ((msb.toInt() shl 8) + lsb.toInt()).toUShort() return ((msb.toInt() shl 8) + lsb.toInt()).toUShort()
} }
internal fun ArrayDeque<UByte>.popl(): Int {
val msb24 = removeLast()
val msb16 = removeLast()
val msb = removeLast()
val lsb = removeLast()
return (msb24.toInt() shl 24) + (msb16.toInt() shl 16) + (msb.toInt() shl 8) + lsb.toInt()
}
internal fun ArrayDeque<UByte>.popf(): Double { internal fun ArrayDeque<UByte>.popf(): Double {
// pop float; lsb is on bottom, msb on top // pop float; lsb is on bottom, msb on top
val b0 = removeLast().toLong() val b0 = removeLast().toLong()