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)
if(stmt==null) {
if(identifier.parent is ArrayIndexedExpression) {
@@ -362,10 +361,6 @@ internal class AstChecker(private val program: Program,
super.visit(label)
}
override fun visit(numLiteral: NumericLiteral) {
checkLongType(numLiteral)
}
private fun hasReturnOrExternalJumpOrRts(scope: IStatementContainer): Boolean {
class Searcher: IAstVisitor
{
@@ -807,7 +802,6 @@ internal class AstChecker(private val program: Program,
}
override fun visit(addressOf: AddressOf) {
checkLongType(addressOf)
val variable=addressOf.identifier?.targetVarDecl()
if (variable!=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)
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.datatype.isString)
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()
if(!dt.isUndefined) {
@@ -1418,8 +1409,6 @@ internal class AstChecker(private val program: Program,
return
}
checkLongType(expr)
val leftIDt = expr.left.inferType(program)
val rightIDt = expr.right.inferType(program)
if(!leftIDt.isKnown || !rightIDt.isKnown) {
@@ -1547,7 +1536,6 @@ internal class AstChecker(private val program: Program,
}
override fun visit(typecast: TypecastExpression) {
checkLongType(typecast)
if(typecast.type.isPassByRef)
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) {
checkLongType(functionCallExpr)
// this function call is (part of) an expression, which should be in a statement somewhere.
val stmtOfExpression = findParentNode<Statement>(functionCallExpr)
?: 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{
checkLongType(it)
if(it.inferType(program).isStructInstance)
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) {
checkLongType(arrayIndexedExpression)
val target = arrayIndexedExpression.plainarrayvar?.targetStatement(program.builtinFunctions)
if(target is VarDecl) {
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)
}
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 {
return if (targetDt.isString) {
when {

View File

@@ -1,31 +1,8 @@
%option no_sysinit
%zeropage basicsafe
%import textio
main {
sub start() {
ubyte @shared index = 3
ubyte[10] array
alias curframe = array
long @shared num = 123456789
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.
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.
Currently ther is NO support for 24 or 32 bits integers.
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.
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).
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
----------
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)
loadm reg1, address - load reg1 with value at memory address
@@ -518,8 +517,8 @@ val OpcodesThatSetStatusbits = OpcodesThatSetStatusbitsButNotCarry + OpcodesThat
enum class IRDataType {
BYTE,
WORD,
LONG,
FLOAT
// TODO add INT (32-bit)? INT24 (24-bit)?
}
enum class OperandDirection {
@@ -862,6 +861,7 @@ data class IRInstruction(
when (type) {
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.LONG -> require(immediate in -2147483647..2147483647) { "immediate value out of range for long: $immediate" }
IRDataType.FLOAT, null -> {}
}
}
@@ -1115,6 +1115,7 @@ data class IRInstruction(
when(it.reg.dt) {
IRDataType.BYTE -> result.add("${location}r${it.reg.registerNum}.b$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,")
}
}
@@ -1136,12 +1137,14 @@ data class IRInstruction(
when (returnspec.dt) {
IRDataType.BYTE -> "r${returnspec.registerNum}.b"
IRDataType.WORD -> "r${returnspec.registerNum}.w"
IRDataType.LONG -> "r${returnspec.registerNum}.l"
IRDataType.FLOAT -> "fr${returnspec.registerNum}.f"
}
} else {
when (returnspec.dt) {
IRDataType.BYTE -> "r${returnspec.registerNum}.b@" + cpuReg
IRDataType.WORD -> "r${returnspec.registerNum}.w@" + cpuReg
IRDataType.LONG -> "r${returnspec.registerNum}.l@" + 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))
throw IRParseException("immediate value out of range for word: $immediateInt")
}
IRDataType.LONG -> {}
IRDataType.FLOAT -> {}
null -> {}
}
@@ -368,6 +369,7 @@ fun irType(type: DataType): IRDataType {
BaseDataType.UBYTE,
BaseDataType.BYTE -> IRDataType.BYTE
BaseDataType.UWORD, BaseDataType.WORD, BaseDataType.POINTER -> IRDataType.WORD
BaseDataType.LONG -> IRDataType.LONG
BaseDataType.FLOAT -> IRDataType.FLOAT
BaseDataType.STRUCT_INSTANCE -> TODO("IR datatype for struct instances")
else -> throw AssemblyError("no IR datatype for $type")

View File

@@ -32,19 +32,30 @@ class Memory {
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 {
return (mem[address].toInt() + mem[address+1].toInt()*256).toShort()
}
fun setUW(address: Int, value: UShort) {
mem[address+1] = (value.toInt() ushr 8).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) {
val uv = value.toUShort()
mem[address+1] = (uv.toInt() ushr 8).toUByte()
mem[address] = uv.toUByte()
mem[address+1] = (uv.toInt() ushr 8).toUByte()
}
fun setFloat(address: Int, value: Double) {

View File

@@ -6,14 +6,14 @@ package prog8.vm
* A,X and Y "physical" 6502 registers.
*/
class Registers {
private val registers = Array<UShort>(99999) { 0u }
private val registers = Array<Int>(99999) { 0 }
private val floatRegisters = Array(99999) { 0.0 }
var cpuA: UByte = 0u
var cpuX: UByte = 0u
var cpuY: UByte = 0u
fun reset() {
registers.fill(0u)
registers.fill(0)
floatRegisters.fill(0.0)
cpuA = 0u
cpuX = 0u
@@ -21,26 +21,32 @@ class Registers {
}
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) {
registers[reg] = registers[reg] and 0xff00u or (value.toUShort() and 0x00ffu)
registers[reg] = value.toInt()
}
fun setUW(reg: Int, value: UShort) {
registers[reg] = value
registers[reg] = value.toInt()
}
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 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()

View File

@@ -143,6 +143,7 @@ object SysCalls {
when(it.reg.dt) {
IRDataType.BYTE -> vm.registers.getUB(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)
}
}
@@ -164,6 +165,7 @@ object SysCalls {
when(returns.dt) {
IRDataType.BYTE -> vm.registers.setUB(returns.registerNum, vv.toInt().toUByte())
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)
}
}

View File

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