start with introducing LONG datatype (32 bits signed integer)

This commit is contained in:
Irmen de Jong
2025-09-17 01:04:26 +02:00
parent 44f70da113
commit a2b9d78cf3
15 changed files with 591 additions and 149 deletions

View File

@@ -7,6 +7,7 @@ internal class RegisterPool {
// everything from 99000 onwards is reserved for special purposes:
// 99000 - 99099 : WORD registers for syscall arguments and response value(s)
// 99100 - 99199 : BYTE registers for syscall arguments and response value(s)
// 99200 - 99299 : LONG registers for syscall arguments and response value(s)
private var nextRegister: Int=1
private val registerTypes: MutableMap<Int, IRDataType> = mutableMapOf()
@@ -18,6 +19,8 @@ internal class RegisterPool {
registerTypes[i] = IRDataType.WORD
for(i in 99100..99199)
registerTypes[i] = IRDataType.BYTE
for(i in 99200..99299)
registerTypes[i] = IRDataType.LONG
}
fun next(type: IRDataType): Int {

View File

@@ -35,7 +35,7 @@ class ConstantFoldingOptimizer(private val program: Program, private val errors:
override fun after(numLiteral: NumericLiteral, parent: Node): Iterable<IAstModification> {
if(numLiteral.type==BaseDataType.LONG) {
if(numLiteral.type==BaseDataType.LONG && parent !is Assignment) {
// see if LONG values may be reduced to something smaller
val smaller = NumericLiteral.optimalInteger(numLiteral.number.toInt(), numLiteral.position)
if(smaller.type!=BaseDataType.LONG) {

View File

@@ -228,6 +228,22 @@ asmsub str_w (word value @ AY) clobbers(X) -> str @AY {
}}
}
asmsub str_l (uword msw @ R0, uword lsw @ R1) clobbers(X) -> str @AY {
; ---- convert the long in R0:R1 into decimal string form, without left padding 0s
%asm {{
lda #'?'
sta string_out
lda #'?'
sta string_out+1
lda #0
sta string_out+2
; TODO implement this!
sta string_out
lda #<string_out
ldy #>string_out
rts
}}
}
; ---- string conversion to numbers -----

View File

@@ -165,6 +165,11 @@ _allzero lda #'0'
}}
}
sub print_l (long value) {
; ---- print the (signed) long in decimal form, without left padding 0's
print(conv.str_l(msw(value), lsw(value)))
}
asmsub input_chars (^^ubyte buffer @ AY) clobbers(A) -> ubyte @ Y {
; ---- Input a string (max. 80 chars) from the keyboard, in PETSCII encoding.
; Returns length in Y. (string is terminated with a 0 byte as well)

View File

@@ -141,7 +141,7 @@ sub str_uw (uword value) -> str {
}
sub str_w (word value) -> str {
; ---- convert the (signed) word in A/Y in decimal string form, without left padding 0's
; ---- convert the (signed) word into decimal string form, without left padding 0's
^^ubyte out_ptr = &string_out
if value<0 {
@(out_ptr) = '-'
@@ -152,6 +152,16 @@ sub str_w (word value) -> str {
return string_out
}
sub str_l (long value) -> str {
; ---- convert the (signed) long into decimal string form, without left padding 0's
%ir {{
loadm.l r99200,conv.str_l.value
load.w r99000,conv.string_out
syscall 60 (r99200.l, r99000.w) : r99000.w
returnr.w r99000
}}
}
sub internal_str_uw(uword value, str out_ptr) {
uword value2 = value/10
ubyte digits = value-value2*10 as ubyte

View File

@@ -151,6 +151,14 @@ sub print_w (word value) {
print(conv.str_w(value))
}
sub print_l (long value) {
; ---- print the (signed) long in decimal form, without left padding 0's
%ir {{
loadm.l r99200,txt.print_l.value
syscall 59 (r99200.l)
}}
}
sub input_chars (str buffer) -> ubyte {
; ---- Input a string (max. 80 chars) from the keyboard. Returns length of input. (string is terminated with a 0 byte as well)
; It assumes the keyboard is selected as I/O channel!

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) {
@@ -363,10 +362,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
{
@@ -813,7 +808,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)
@@ -862,8 +856,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)
@@ -1329,7 +1321,6 @@ internal class AstChecker(private val program: Program,
}
}
checkLongType(expr)
val dt = expr.expression.inferType(program).getOrUndef()
if(!dt.isUndefined) {
@@ -1474,8 +1465,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) {
@@ -1614,7 +1603,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)
@@ -1671,7 +1659,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}")
@@ -1905,7 +1892,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)
}
@@ -1918,7 +1904,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)
@@ -2164,17 +2149,6 @@ internal class AstChecker(private val program: Program,
super.visit(deref)
}
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,11 +1,39 @@
main {
sub start() {
func()
%import textio
main {
long bignum = 12345678
long bignum2 = -999999
struct Node {
ubyte id
str name
long array
bool flag
long counter
}
sub func() {
if cx16.r0<10 or cx16.r0>319 {
cx16.r1++
}
sub start() {
^^Node test = []
bignum++
bignum2--
txt.print_l(bignum)
txt.spc()
txt.print_l(bignum2)
txt.nl()
str output = "...................."
txt.print(conv.str_l(bignum))
txt.nl()
bignum = 999999
bignum-- ; TODO this works in the current VM...
bignum = -888888
test.counter = 0
test.counter ++ ; TODO ... why doesn't this? (requires plusMinusMultAnyLong routine)
test.counter = bignum2
test.counter --
}
}

View File

@@ -136,8 +136,8 @@ ARITHMETIC
----------
All have type b or w or f. Note: result types are the same as operand types! E.g. byte*byte->byte.
exts reg1, reg2 - reg1 = signed extension of reg2 (byte to word, or word to long) (note: unlike M68k, exts.b -> word and exts.w -> long. The latter is not yet implemented yet as we don't have longs yet)
ext reg1, reg2 - reg1 = unsigned extension of reg2 (which in practice just means clearing the MSB / MSW) (note: unlike M68k, ext.b -> word and ext.w -> long. The latter is not yet implemented yet as we don't have longs yet)
exts reg1, reg2 - reg1 = signed extension of reg2 (byte to word, or word to long) (note: unlike M68k, exts.b -> word and exts.w -> long.)
ext reg1, reg2 - reg1 = unsigned extension of reg2 (which in practice just means clearing the MSB / MSW) (note: unlike M68k, ext.b -> word and ext.w -> long. )
inc reg1 - reg1 = reg1+1
incm address - memory at address += 1
dec reg1 - reg1 = reg1-1
@@ -247,9 +247,9 @@ sei - set interrupt disable flag
nop - do nothing
breakpoint - trigger a breakpoint
align alignmentvalue - represents a memory alignment directive
lsig [b, w] reg1, reg2 - reg1 becomes the least significant byte (or word) of the word (or int) in reg2 (.w not yet implemented; requires 32 bits regs)
msig [b, w] reg1, reg2 - reg1 becomes the most significant byte (or word) of the word (or int) in reg2 (.w not yet implemented; requires 32 bits regs)
concat [b, w] reg1, reg2, reg3 - reg1.w = 'concatenate' two registers: lsb/lsw of reg2 (as msb) and lsb/lsw of reg3 (as lsb) into word or int (int not yet implemented; requires 32bits regs)
lsig [b, w] reg1, reg2 - reg1 becomes the least significant byte (or word) of the word (or int) in reg2
msig [b, w] reg1, reg2 - reg1 becomes the most significant byte (or word) of the word (or int) in reg2
concat [b, w] reg1, reg2, reg3 - reg1.w/l = 'concatenate' two registers: lsb/lsw of reg2 (as msb) and lsb/lsw of reg3 (as lsb) into word or int)
push [b, w, f] reg1 - push value in reg1 on the stack
pop [b, w, f] reg1 - pop value from stack into reg1
pushst - push status register bits to stack
@@ -559,8 +559,8 @@ val OpcodesThatSetStatusbits = OpcodesThatSetStatusbitsButNotCarry + OpcodesThat
enum class IRDataType {
BYTE,
WORD,
FLOAT
// TODO add INT (32-bit)? INT24 (24-bit)?
FLOAT,
LONG // 32 bits integer
}
enum class OperandDirection {
@@ -623,6 +623,8 @@ data class InstructionFormat(val datatype: IRDataType?,
result[IRDataType.BYTE] = InstructionFormat(IRDataType.BYTE, reg1, reg2, reg3, fpreg1, fpreg2, address, immediate, funcCall, sysCall)
if('W' in typespec)
result[IRDataType.WORD] = InstructionFormat(IRDataType.WORD, reg1, reg2, reg3, fpreg1, fpreg2, address, immediate, funcCall, sysCall)
if('L' in typespec)
result[IRDataType.LONG] = InstructionFormat(IRDataType.LONG, reg1, reg2, reg3, fpreg1, fpreg2, address, immediate, funcCall, sysCall)
if('F' in typespec)
result[IRDataType.FLOAT] = InstructionFormat(IRDataType.FLOAT, reg1, reg2, reg3, fpreg1, fpreg2, address, immediate, funcCall, sysCall)
}
@@ -643,12 +645,12 @@ data class InstructionFormat(val datatype: IRDataType?,
*/
val instructionFormats = mutableMapOf(
Opcode.NOP to InstructionFormat.from("N"),
Opcode.LOAD to InstructionFormat.from("BW,>r1,<i | F,>fr1,<i"),
Opcode.LOADM to InstructionFormat.from("BW,>r1,<a | F,>fr1,<a"),
Opcode.LOADI to InstructionFormat.from("BW,>r1,<r2 | F,>fr1,<r1"),
Opcode.LOADX to InstructionFormat.from("BW,>r1,<r2,<a | F,>fr1,<r1,<a"),
Opcode.LOADIX to InstructionFormat.from("BW,>r1,<r2,<a | F,>fr1,<r1,<a"),
Opcode.LOADR to InstructionFormat.from("BW,>r1,<r2 | F,>fr1,<fr2"),
Opcode.LOAD to InstructionFormat.from("BWL,>r1,<i | F,>fr1,<i"),
Opcode.LOADM to InstructionFormat.from("BWL,>r1,<a | F,>fr1,<a"),
Opcode.LOADI to InstructionFormat.from("BWL,>r1,<r2 | F,>fr1,<r1"),
Opcode.LOADX to InstructionFormat.from("BWL,>r1,<r2,<a | F,>fr1,<r1,<a"),
Opcode.LOADIX to InstructionFormat.from("BWL,>r1,<r2,<a | F,>fr1,<r1,<a"),
Opcode.LOADR to InstructionFormat.from("BWL,>r1,<r2 | F,>fr1,<fr2"),
Opcode.LOADHA to InstructionFormat.from("B,>r1"),
Opcode.LOADHA to InstructionFormat.from("B,>r1"),
Opcode.LOADHX to InstructionFormat.from("B,>r1"),
@@ -656,16 +658,16 @@ val instructionFormats = mutableMapOf(
Opcode.LOADHAX to InstructionFormat.from("W,>r1"),
Opcode.LOADHAY to InstructionFormat.from("W,>r1"),
Opcode.LOADHXY to InstructionFormat.from("W,>r1"),
Opcode.LOADFIELD to InstructionFormat.from("BW,>r1,<r2,<i | F,>fr1,<r1,<i"),
Opcode.LOADFIELD to InstructionFormat.from("BWL,>r1,<r2,<i | F,>fr1,<r1,<i"),
Opcode.LOADHFACZERO to InstructionFormat.from("F,>fr1"),
Opcode.LOADHFACONE to InstructionFormat.from("F,>fr1"),
Opcode.STOREM to InstructionFormat.from("BW,<r1,>a | F,<fr1,>a"),
Opcode.STOREI to InstructionFormat.from("BW,<r1,<r2 | F,<fr1,<r1"),
Opcode.STOREX to InstructionFormat.from("BW,<r1,<r2,>a | F,<fr1,<r1,>a"),
Opcode.STOREIX to InstructionFormat.from("BW,<r1,<r2,>a | F,<fr1,<r1,>a"),
Opcode.STOREZM to InstructionFormat.from("BW,>a | F,>a"),
Opcode.STOREZI to InstructionFormat.from("BW,<r1 | F,<r1"),
Opcode.STOREZX to InstructionFormat.from("BW,<r1,>a | F,<r1,>a"),
Opcode.STOREM to InstructionFormat.from("BWL,<r1,>a | F,<fr1,>a"),
Opcode.STOREI to InstructionFormat.from("BWL,<r1,<r2 | F,<fr1,<r1"),
Opcode.STOREX to InstructionFormat.from("BWL,<r1,<r2,>a | F,<fr1,<r1,>a"),
Opcode.STOREIX to InstructionFormat.from("BWL,<r1,<r2,>a | F,<fr1,<r1,>a"),
Opcode.STOREZM to InstructionFormat.from("BWL,>a | F,>a"),
Opcode.STOREZI to InstructionFormat.from("BWL,<r1 | F,<r1"),
Opcode.STOREZX to InstructionFormat.from("BWL,<r1,>a | F,<r1,>a"),
Opcode.STOREHA to InstructionFormat.from("B,<r1"),
Opcode.STOREHA to InstructionFormat.from("B,<r1"),
Opcode.STOREHX to InstructionFormat.from("B,<r1"),
@@ -673,7 +675,7 @@ val instructionFormats = mutableMapOf(
Opcode.STOREHAX to InstructionFormat.from("W,<r1"),
Opcode.STOREHAY to InstructionFormat.from("W,<r1"),
Opcode.STOREHXY to InstructionFormat.from("W,<r1"),
Opcode.STOREFIELD to InstructionFormat.from("BW,<r1,<r2,<i | F,<fr1,<r1,<i"),
Opcode.STOREFIELD to InstructionFormat.from("BWL,<r1,<r2,<i | F,<fr1,<r1,<i"),
Opcode.STOREHFACZERO to InstructionFormat.from("F,<fr1"),
Opcode.STOREHFACONE to InstructionFormat.from("F,<fr1"),
Opcode.JUMP to InstructionFormat.from("N,<a"),
@@ -684,8 +686,8 @@ val instructionFormats = mutableMapOf(
Opcode.CALLFARVB to InstructionFormat.from("N,<r1,<a"),
Opcode.SYSCALL to InstructionFormat.from("N,syscall"),
Opcode.RETURN to InstructionFormat.from("N"),
Opcode.RETURNR to InstructionFormat.from("BW,<r1 | F,<fr1"),
Opcode.RETURNI to InstructionFormat.from("BW,<i | F,<i"),
Opcode.RETURNR to InstructionFormat.from("BWL,<r1 | F,<fr1"),
Opcode.RETURNI to InstructionFormat.from("BWL,<i | F,<i"),
Opcode.BSTCC to InstructionFormat.from("N,<a"),
Opcode.BSTCS to InstructionFormat.from("N,<a"),
Opcode.BSTEQ to InstructionFormat.from("N,<a"),
@@ -694,84 +696,84 @@ val instructionFormats = mutableMapOf(
Opcode.BSTPOS to InstructionFormat.from("N,<a"),
Opcode.BSTVC to InstructionFormat.from("N,<a"),
Opcode.BSTVS to InstructionFormat.from("N,<a"),
Opcode.BGTR to InstructionFormat.from("BW,<r1,<r2,<a"),
Opcode.BGT to InstructionFormat.from("BW,<r1,<i,<a"),
Opcode.BLT to InstructionFormat.from("BW,<r1,<i,<a"),
Opcode.BGTSR to InstructionFormat.from("BW,<r1,<r2,<a"),
Opcode.BGTS to InstructionFormat.from("BW,<r1,<i,<a"),
Opcode.BLTS to InstructionFormat.from("BW,<r1,<i,<a"),
Opcode.BGER to InstructionFormat.from("BW,<r1,<r2,<a"),
Opcode.BGE to InstructionFormat.from("BW,<r1,<i,<a"),
Opcode.BLE to InstructionFormat.from("BW,<r1,<i,<a"),
Opcode.BGESR to InstructionFormat.from("BW,<r1,<r2,<a"),
Opcode.BGES to InstructionFormat.from("BW,<r1,<i,<a"),
Opcode.BLES to InstructionFormat.from("BW,<r1,<i,<a"),
Opcode.INC to InstructionFormat.from("BW,<>r1 | F,<>fr1"),
Opcode.INCM to InstructionFormat.from("BW,<>a | F,<>a"),
Opcode.DEC to InstructionFormat.from("BW,<>r1 | F,<>fr1"),
Opcode.DECM to InstructionFormat.from("BW,<>a | F,<>a"),
Opcode.NEG to InstructionFormat.from("BW,<>r1 | F,<>fr1"),
Opcode.NEGM to InstructionFormat.from("BW,<>a | F,<>a"),
Opcode.ADDR to InstructionFormat.from("BW,<>r1,<r2 | F,<>fr1,<fr2"),
Opcode.ADD to InstructionFormat.from("BW,<>r1,<i | F,<>fr1,<i"),
Opcode.ADDM to InstructionFormat.from("BW,<r1,<>a | F,<fr1,<>a"),
Opcode.SUBR to InstructionFormat.from("BW,<>r1,<r2 | F,<>fr1,<fr2"),
Opcode.SUB to InstructionFormat.from("BW,<>r1,<i | F,<>fr1,<i"),
Opcode.SUBM to InstructionFormat.from("BW,<r1,<>a | F,<fr1,<>a"),
Opcode.BGTR to InstructionFormat.from("BWL,<r1,<r2,<a"),
Opcode.BGT to InstructionFormat.from("BWL,<r1,<i,<a"),
Opcode.BLT to InstructionFormat.from("BWL,<r1,<i,<a"),
Opcode.BGTSR to InstructionFormat.from("BWL,<r1,<r2,<a"),
Opcode.BGTS to InstructionFormat.from("BWL,<r1,<i,<a"),
Opcode.BLTS to InstructionFormat.from("BWL,<r1,<i,<a"),
Opcode.BGER to InstructionFormat.from("BWL,<r1,<r2,<a"),
Opcode.BGE to InstructionFormat.from("BWL,<r1,<i,<a"),
Opcode.BLE to InstructionFormat.from("BWL,<r1,<i,<a"),
Opcode.BGESR to InstructionFormat.from("BWL,<r1,<r2,<a"),
Opcode.BGES to InstructionFormat.from("BWL,<r1,<i,<a"),
Opcode.BLES to InstructionFormat.from("BWL,<r1,<i,<a"),
Opcode.INC to InstructionFormat.from("BWL,<>r1 | F,<>fr1"),
Opcode.INCM to InstructionFormat.from("BWL,<>a | F,<>a"),
Opcode.DEC to InstructionFormat.from("BWL,<>r1 | F,<>fr1"),
Opcode.DECM to InstructionFormat.from("BWL,<>a | F,<>a"),
Opcode.NEG to InstructionFormat.from("BWL,<>r1 | F,<>fr1"),
Opcode.NEGM to InstructionFormat.from("BWL,<>a | F,<>a"),
Opcode.ADDR to InstructionFormat.from("BWL,<>r1,<r2 | F,<>fr1,<fr2"),
Opcode.ADD to InstructionFormat.from("BWL,<>r1,<i | F,<>fr1,<i"),
Opcode.ADDM to InstructionFormat.from("BWL,<r1,<>a | F,<fr1,<>a"),
Opcode.SUBR to InstructionFormat.from("BWL,<>r1,<r2 | F,<>fr1,<fr2"),
Opcode.SUB to InstructionFormat.from("BWL,<>r1,<i | F,<>fr1,<i"),
Opcode.SUBM to InstructionFormat.from("BWL,<r1,<>a | F,<fr1,<>a"),
Opcode.MULR to InstructionFormat.from("BW,<>r1,<r2 | F,<>fr1,<fr2"),
Opcode.MUL to InstructionFormat.from("BW,<>r1,<i | F,<>fr1,<i"),
Opcode.MULM to InstructionFormat.from("BW,<r1,<>a | F,<fr1,<>a"),
Opcode.MULSR to InstructionFormat.from("BW,<>r1,<r2 | F,<>fr1,<fr2"),
Opcode.MULS to InstructionFormat.from("BW,<>r1,<i | F,<>fr1,<i"),
Opcode.MULSM to InstructionFormat.from("BW,<r1,<>a | F,<fr1,<>a"),
Opcode.MULSR to InstructionFormat.from("BWL,<>r1,<r2 | F,<>fr1,<fr2"),
Opcode.MULS to InstructionFormat.from("BWL,<>r1,<i | F,<>fr1,<i"),
Opcode.MULSM to InstructionFormat.from("BWL,<r1,<>a | F,<fr1,<>a"),
Opcode.DIVR to InstructionFormat.from("BW,<>r1,<r2 | F,<>fr1,<fr2"),
Opcode.DIV to InstructionFormat.from("BW,<>r1,<i | F,<>fr1,<i"),
Opcode.DIVM to InstructionFormat.from("BW,<r1,<>a | F,<fr1,<>a"),
Opcode.DIVSR to InstructionFormat.from("BW,<>r1,<r2 | F,<>fr1,<fr2"),
Opcode.DIVS to InstructionFormat.from("BW,<>r1,<i | F,<>fr1,<i"),
Opcode.DIVSM to InstructionFormat.from("BW,<r1,<>a | F,<fr1,<>a"),
Opcode.SQRT to InstructionFormat.from("BW,>r1,<r2 | F,>fr1,<fr2"),
Opcode.SQUARE to InstructionFormat.from("BW,>r1,<r2 | F,>fr1,<fr2"),
Opcode.SGN to InstructionFormat.from("BW,>r1,<r2 | F,>r1,<fr1"),
Opcode.DIVSR to InstructionFormat.from("BWL,<>r1,<r2 | F,<>fr1,<fr2"),
Opcode.DIVS to InstructionFormat.from("BWL,<>r1,<i | F,<>fr1,<i"),
Opcode.DIVSM to InstructionFormat.from("BWL,<r1,<>a | F,<fr1,<>a"),
Opcode.SQRT to InstructionFormat.from("BWL,>r1,<r2 | F,>fr1,<fr2"),
Opcode.SQUARE to InstructionFormat.from("BWL,>r1,<r2 | F,>fr1,<fr2"),
Opcode.SGN to InstructionFormat.from("BWL,>r1,<r2 | F,>r1,<fr1"),
Opcode.MODR to InstructionFormat.from("BW,<>r1,<r2"),
Opcode.MOD to InstructionFormat.from("BW,<>r1,<i"),
Opcode.DIVMODR to InstructionFormat.from("BW,<>r1,<r2"),
Opcode.DIVMOD to InstructionFormat.from("BW,<>r1,<i"),
Opcode.CMP to InstructionFormat.from("BW,<r1,<r2"),
Opcode.CMPI to InstructionFormat.from("BW,<r1,<i"),
Opcode.EXT to InstructionFormat.from("BW,>r1,<r2"),
Opcode.EXTS to InstructionFormat.from("BW,>r1,<r2"),
Opcode.ANDR to InstructionFormat.from("BW,<>r1,<r2"),
Opcode.AND to InstructionFormat.from("BW,<>r1,<i"),
Opcode.ANDM to InstructionFormat.from("BW,<r1,<>a"),
Opcode.ORR to InstructionFormat.from("BW,<>r1,<r2"),
Opcode.OR to InstructionFormat.from("BW,<>r1,<i"),
Opcode.ORM to InstructionFormat.from("BW,<r1,<>a"),
Opcode.XORR to InstructionFormat.from("BW,<>r1,<r2"),
Opcode.XOR to InstructionFormat.from("BW,<>r1,<i"),
Opcode.XORM to InstructionFormat.from("BW,<r1,<>a"),
Opcode.INV to InstructionFormat.from("BW,<>r1"),
Opcode.INVM to InstructionFormat.from("BW,<>a"),
Opcode.ASRN to InstructionFormat.from("BW,<>r1,<r2"),
Opcode.ASRNM to InstructionFormat.from("BW,<r1,<>a"),
Opcode.LSRN to InstructionFormat.from("BW,<>r1,<r2"),
Opcode.LSRNM to InstructionFormat.from("BW,<r1,<>a"),
Opcode.LSLN to InstructionFormat.from("BW,<>r1,<r2"),
Opcode.LSLNM to InstructionFormat.from("BW,<r1,<>a"),
Opcode.ASR to InstructionFormat.from("BW,<>r1"),
Opcode.ASRM to InstructionFormat.from("BW,<>a"),
Opcode.LSR to InstructionFormat.from("BW,<>r1"),
Opcode.LSRM to InstructionFormat.from("BW,<>a"),
Opcode.LSL to InstructionFormat.from("BW,<>r1"),
Opcode.LSLM to InstructionFormat.from("BW,<>a"),
Opcode.ROR to InstructionFormat.from("BW,<>r1"),
Opcode.RORM to InstructionFormat.from("BW,<>a"),
Opcode.ROXR to InstructionFormat.from("BW,<>r1"),
Opcode.ROXRM to InstructionFormat.from("BW,<>a"),
Opcode.ROL to InstructionFormat.from("BW,<>r1"),
Opcode.ROLM to InstructionFormat.from("BW,<>a"),
Opcode.ROXL to InstructionFormat.from("BW,<>r1"),
Opcode.ROXLM to InstructionFormat.from("BW,<>a"),
Opcode.CMP to InstructionFormat.from("BWL,<r1,<r2"),
Opcode.CMPI to InstructionFormat.from("BWL,<r1,<i"),
Opcode.EXT to InstructionFormat.from("BWL,>r1,<r2"),
Opcode.EXTS to InstructionFormat.from("BWL,>r1,<r2"),
Opcode.ANDR to InstructionFormat.from("BWL,<>r1,<r2"),
Opcode.AND to InstructionFormat.from("BWL,<>r1,<i"),
Opcode.ANDM to InstructionFormat.from("BWL,<r1,<>a"),
Opcode.ORR to InstructionFormat.from("BWL,<>r1,<r2"),
Opcode.OR to InstructionFormat.from("BWL,<>r1,<i"),
Opcode.ORM to InstructionFormat.from("BWL,<r1,<>a"),
Opcode.XORR to InstructionFormat.from("BWL,<>r1,<r2"),
Opcode.XOR to InstructionFormat.from("BWL,<>r1,<i"),
Opcode.XORM to InstructionFormat.from("BWL,<r1,<>a"),
Opcode.INV to InstructionFormat.from("BWL,<>r1"),
Opcode.INVM to InstructionFormat.from("BWL,<>a"),
Opcode.ASRN to InstructionFormat.from("BWL,<>r1,<r2"),
Opcode.ASRNM to InstructionFormat.from("BWL,<r1,<>a"),
Opcode.LSRN to InstructionFormat.from("BWL,<>r1,<r2"),
Opcode.LSRNM to InstructionFormat.from("BWL,<r1,<>a"),
Opcode.LSLN to InstructionFormat.from("BWL,<>r1,<r2"),
Opcode.LSLNM to InstructionFormat.from("BWL,<r1,<>a"),
Opcode.ASR to InstructionFormat.from("BWL,<>r1"),
Opcode.ASRM to InstructionFormat.from("BWL,<>a"),
Opcode.LSR to InstructionFormat.from("BWL,<>r1"),
Opcode.LSRM to InstructionFormat.from("BWL,<>a"),
Opcode.LSL to InstructionFormat.from("BWL,<>r1"),
Opcode.LSLM to InstructionFormat.from("BWL,<>a"),
Opcode.ROR to InstructionFormat.from("BWL,<>r1"),
Opcode.RORM to InstructionFormat.from("BWL,<>a"),
Opcode.ROXR to InstructionFormat.from("BWL,<>r1"),
Opcode.ROXRM to InstructionFormat.from("BWL,<>a"),
Opcode.ROL to InstructionFormat.from("BWL,<>r1"),
Opcode.ROLM to InstructionFormat.from("BWL,<>a"),
Opcode.ROXL to InstructionFormat.from("BWL,<>r1"),
Opcode.ROXLM to InstructionFormat.from("BWL,<>a"),
Opcode.BIT to InstructionFormat.from("B,<a"),
Opcode.FFROMUB to InstructionFormat.from("F,>fr1,<r1"),
@@ -797,8 +799,8 @@ val instructionFormats = mutableMapOf(
Opcode.LSIG to InstructionFormat.from("BW,>r1,<r2"),
Opcode.MSIG to InstructionFormat.from("BW,>r1,<r2"),
Opcode.PUSH to InstructionFormat.from("BW,<r1 | F,<fr1"),
Opcode.POP to InstructionFormat.from("BW,>r1 | F,>fr1"),
Opcode.PUSH to InstructionFormat.from("BWL,<r1 | F,<fr1"),
Opcode.POP to InstructionFormat.from("BWL,>r1 | F,>fr1"),
Opcode.PUSHST to InstructionFormat.from("N"),
Opcode.POPST to InstructionFormat.from("N"),
Opcode.CONCAT to InstructionFormat.from("BW,<>r1,<r2,<r3"),
@@ -903,6 +905,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 -> {}
}
}
@@ -1083,8 +1086,7 @@ data class IRInstruction(
// some word instructions have byte reg1
return when (opcode) {
Opcode.STOREZX, Opcode.SQRT -> IRDataType.BYTE
Opcode.EXT, Opcode.EXTS -> TODO("ext.w into long type")
Opcode.CONCAT -> TODO("concat.w into long type")
Opcode.EXT, Opcode.EXTS, Opcode.CONCAT -> IRDataType.LONG
else -> IRDataType.WORD
}
}
@@ -1107,7 +1109,7 @@ data class IRInstruction(
if(opcode==Opcode.MSIG || opcode==Opcode.LSIG)
return when(type) {
IRDataType.BYTE -> IRDataType.WORD
IRDataType.WORD -> TODO("msig/lsig.w from long type")
IRDataType.WORD -> IRDataType.LONG
else -> null
}
if(opcode==Opcode.ASRN || opcode==Opcode.LSRN || opcode==Opcode.LSLN)
@@ -1125,6 +1127,7 @@ data class IRInstruction(
when(type) {
IRDataType.BYTE -> result.add(".b ")
IRDataType.WORD -> result.add(".w ")
IRDataType.LONG -> result.add(".l ")
IRDataType.FLOAT -> result.add(".f ")
else -> result.add(" ")
}
@@ -1154,6 +1157,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,")
}
}
@@ -1175,12 +1179,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

@@ -53,6 +53,7 @@ fun convertIRType(typestr: String): IRDataType? {
"" -> null
".b" -> IRDataType.BYTE
".w" -> IRDataType.WORD
".l" -> IRDataType.LONG
".f" -> IRDataType.FLOAT
else -> throw IRParseException("invalid type $typestr")
}
@@ -78,7 +79,7 @@ fun parseIRValue(value: String): Double {
}
private val instructionPattern = Regex("""([a-z]+)(\.b|\.w|\.f)?(.*)""", RegexOption.IGNORE_CASE)
private val instructionPattern = Regex("""([a-z]+)(\.b|\.w|\.l|\.f)?(.*)""", RegexOption.IGNORE_CASE)
private val labelPattern = Regex("""_([a-zA-Z\d\._]+):""")
fun parseIRCodeLine(line: String): Either<IRInstruction, String> {
@@ -207,6 +208,10 @@ 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 -> {
if (immediateInt!=null && immediateInt < -2147483647)
throw IRParseException("immediate value out of range for long: $immediateInt")
}
IRDataType.FLOAT -> {}
null -> {}
}
@@ -271,6 +276,7 @@ private fun parseCall(rest: String): ParsedCall {
val type = when(match.groups[2]!!.value) {
"b" -> IRDataType.BYTE
"w" -> IRDataType.WORD
"l" -> IRDataType.LONG
"f" -> IRDataType.FLOAT
else -> throw IRParseException("invalid type spec in $reg")
}
@@ -359,6 +365,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 -> throw AssemblyError("no support for struct instances yet so no IR datatype for $type")
else -> throw AssemblyError("no IR datatype for $type")

View File

@@ -32,6 +32,10 @@ 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()
}
@@ -47,6 +51,14 @@ class Memory {
mem[address] = uv.toUByte()
}
fun setSL(address: Int, value: Int) {
val uv = value.toUInt()
mem[address+3] = (uv shr 24).toUByte()
mem[address+2] = (uv shr 16).toUByte()
mem[address+1] = (uv shr 8).toUByte()
mem[address] = uv.toUByte()
}
fun setFloat(address: Int, value: Double) {
var bits = value.toBits()
mem[address] = bits.toUByte()

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,29 +21,35 @@ 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 getSW(reg: Int) = registers[reg].toShort()
fun getSL(reg: Int) = registers[reg]
fun getFloat(reg:Int) = floatRegisters[reg]
fun setFloat(reg:Int, value: Double) {

View File

@@ -68,6 +68,9 @@ SYSCALLS: DO NOT RENUMBER THESE OR YOU WILL BREAK EXISTING CODE
56 = CLOSE_FILE
57 = CLOSE_FILE_WRITE
58 = ncompare strings
59 = print_i32 ; print signed 32 bits integer (prog8 long)
60 = i32 to string ; put string representation of signed 32 bits integer (prog8 long) into memory
61 = decimal string to prog8 long (i32 signed)
*/
enum class Syscall {
@@ -130,6 +133,9 @@ enum class Syscall {
CLOSE_FILE,
CLOSE_FILE_WRITE,
NCOMPARE_STRINGS,
PRINT_I32,
I32_TO_STRING,
STR_TO_LONG,
;
companion object {
@@ -143,6 +149,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 +171,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)
}
}
@@ -200,6 +208,10 @@ object SysCalls {
val value = getArgValues(callspec.arguments, vm).single()
print(value)
}
Syscall.PRINT_I32 -> {
val value = getArgValues(callspec.arguments, vm).single()
print(value)
}
Syscall.INPUT -> {
val (address, maxlen) = getArgValues(callspec.arguments, vm)
var input = readln()
@@ -263,6 +275,17 @@ object SysCalls {
}
return returnValue(callspec.returns.single(), value, vm)
}
Syscall.STR_TO_LONG -> {
val stringAddr = getArgValues(callspec.arguments, vm).single() as UShort
val memstring = vm.memory.getString(stringAddr.toInt())
val match = Regex("^[+-]?\\d+").find(memstring) ?: return returnValue(callspec.returns.single(), 0, vm)
val value = try {
match.value.toInt()
} catch(_: NumberFormatException) {
0
}
return returnValue(callspec.returns.single(), value, vm)
}
Syscall.STR_TO_FLOAT -> {
val stringAddr = getArgValues(callspec.arguments, vm).single() as UShort
val memstring = vm.memory.getString(stringAddr.toInt()).replace(" ", "")
@@ -634,6 +657,10 @@ object SysCalls {
}
Syscall.CLOSE_FILE -> vm.close_file_read()
Syscall.CLOSE_FILE_WRITE -> vm.close_file_write()
Syscall.I32_TO_STRING -> {
val (number, stringbuffer) = getArgValues(callspec.arguments, vm)
vm.memory.setString((stringbuffer as UShort).toInt(), number.toString(), true)
}
}
}
}

View File

@@ -353,12 +353,17 @@ class VirtualMachine(irProgram: IRProgram) {
IRDataType.BYTE -> {
registers.setUB(reg, value.toUByte())
statusZero = value==0
statusNegative = value>=0x80
statusNegative = value<0 || value>=0x80
}
IRDataType.WORD -> {
registers.setUW(reg, value.toUShort())
statusZero = value==0
statusNegative = value>=0x8000
statusNegative = value<0 || 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, 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.toInt(), 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()
@@ -619,6 +665,10 @@ class VirtualMachine(irProgram: IRProgram) {
val pointer = memory.getUW(i.address!!) + registers.getUB(i.reg2!!)
memory.setUW(pointer.toInt(), registers.getUW(i.reg1!!))
}
IRDataType.LONG -> {
val pointer = memory.getUW(i.address!!) + registers.getUB(i.reg2!!)
memory.setSL(pointer.toInt(), registers.getSL(i.reg1!!))
}
IRDataType.FLOAT -> {
val pointer = memory.getUW(i.address!!) + registers.getUB(i.reg1!!)
memory.setFloat(pointer.toInt(), registers.getFloat(i.fpReg1!!))
@@ -631,6 +681,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 +691,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 +701,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()
@@ -675,6 +728,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(arg.reg.dt) {
IRDataType.BYTE -> memory.setUB(arg.address!!, registers.getUB(arg.reg.registerNum))
IRDataType.WORD -> memory.setUW(arg.address!!, registers.getUW(arg.reg.registerNum))
IRDataType.LONG -> memory.setSL(arg.address!!, registers.getSL(arg.reg.registerNum))
IRDataType.FLOAT -> memory.setFloat(arg.address!!, registers.getFloat(arg.reg.registerNum))
}
}
@@ -719,6 +773,15 @@ class VirtualMachine(irProgram: IRProgram) {
throw IllegalArgumentException("missing return value reg")
}
}
IRDataType.LONG -> {
if(returns.isNotEmpty())
registers.setSL(returns.single().registerNum, i.immediate!!)
else {
val callInstr = context.returnChunk.instructions[context.returnIndex-1]
if(callInstr.opcode!=Opcode.CALL)
throw IllegalArgumentException("missing return value reg")
}
}
IRDataType.FLOAT -> {
if(returns.isNotEmpty())
registers.setFloat(returns.single().registerNum, i.immediateFp!!)
@@ -759,6 +822,15 @@ class VirtualMachine(irProgram: IRProgram) {
throw IllegalArgumentException("missing return value reg")
}
}
IRDataType.LONG -> {
if(returns.isNotEmpty())
registers.setSL(returns.single().registerNum, registers.getSL(i.reg1!!))
else {
val callInstr = context.returnChunk.instructions[context.returnIndex-1]
if(callInstr.opcode!=Opcode.CALL)
throw IllegalArgumentException("missing return value reg")
}
}
IRDataType.FLOAT -> {
if(returns.isNotEmpty())
registers.setFloat(returns.single().registerNum, registers.getFloat(i.fpReg1!!))
@@ -938,6 +1010,11 @@ class VirtualMachine(irProgram: IRProgram) {
registers.setUW(i.reg1!!, value)
statusbitsNZ(value.toInt(), i.type!!)
}
IRDataType.LONG -> {
val value = registers.getSL(i.reg1!!)+1
registers.setSL(i.reg1!!, value)
statusbitsNZ(value, i.type!!)
}
IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, registers.getFloat(i.fpReg1!!)+1f)
}
nextPc()
@@ -956,6 +1033,11 @@ class VirtualMachine(irProgram: IRProgram) {
memory.setUW(address, value)
statusbitsNZ(value.toInt(), i.type!!)
}
IRDataType.LONG -> {
val value = memory.getSL(address)+1
memory.setSL(address, value)
statusbitsNZ(value, i.type!!)
}
IRDataType.FLOAT -> memory.setFloat(address, memory.getFloat(address)+1f)
}
nextPc()
@@ -973,6 +1055,11 @@ class VirtualMachine(irProgram: IRProgram) {
registers.setUW(i.reg1!!, value)
statusbitsNZ(value.toInt(), i.type!!)
}
IRDataType.LONG -> {
val value = registers.getSL(i.reg1!!)-1
registers.setSL(i.reg1!!, value)
statusbitsNZ(value, i.type!!)
}
IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, registers.getFloat(i.fpReg1!!)-1f)
}
nextPc()
@@ -990,6 +1077,11 @@ class VirtualMachine(irProgram: IRProgram) {
memory.setUW(i.address!!, value)
statusbitsNZ(value.toInt(), i.type!!)
}
IRDataType.LONG -> {
val value = memory.getSL(i.address!!)-1
memory.setSL(i.address!!, value)
statusbitsNZ(value, i.type!!)
}
IRDataType.FLOAT -> memory.setFloat(i.address!!, memory.getFloat(i.address!!)-1f)
}
nextPc()
@@ -1007,6 +1099,11 @@ class VirtualMachine(irProgram: IRProgram) {
registers.setUW(i.reg1!!, value.toUShort())
statusbitsNZ(value, IRDataType.WORD)
}
IRDataType.LONG -> {
val value = -registers.getSL(i.reg1!!)
registers.setSL(i.reg1!!, value)
statusbitsNZ(value, IRDataType.LONG)
}
IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, -registers.getFloat(i.fpReg1!!))
}
nextPc()
@@ -1025,6 +1122,11 @@ class VirtualMachine(irProgram: IRProgram) {
memory.setUW(address, value.toUShort())
statusbitsNZ(value, IRDataType.WORD)
}
IRDataType.LONG -> {
val value = -memory.getSL(address)
memory.setSL(address, value)
statusbitsNZ(value, IRDataType.LONG)
}
IRDataType.FLOAT -> memory.setFloat(address, -memory.getFloat(address))
}
nextPc()
@@ -1034,6 +1136,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) {
IRDataType.BYTE -> plusMinusMultAnyByte("+", i.reg1!!, i.reg2!!)
IRDataType.WORD -> plusMinusMultAnyWord("+", i.reg1!!, i.reg2!!)
IRDataType.LONG -> plusMinusMultAnyLong("+", i.reg1!!, i.reg2!!)
IRDataType.FLOAT -> {
val left = registers.getFloat(i.fpReg1!!)
val right = registers.getFloat(i.fpReg2!!)
@@ -1048,6 +1151,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) {
IRDataType.BYTE -> plusMinusMultConstByte("+", i.reg1!!, i.immediate!!.toUByte())
IRDataType.WORD -> plusMinusMultConstWord("+", i.reg1!!, i.immediate!!.toUShort())
IRDataType.LONG -> plusMinusMultConstLong("+", i.reg1!!, i.immediate!!)
IRDataType.FLOAT -> {
val left = registers.getFloat(i.fpReg1!!)
val result = arithFloat(left, "+", i.immediateFp!!)
@@ -1062,6 +1166,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) {
IRDataType.BYTE -> plusMinusMultAnyByteInplace("+", i.reg1!!, address)
IRDataType.WORD -> plusMinusMultAnyWordInplace("+", i.reg1!!, address)
IRDataType.LONG -> plusMinusMultAnyLongInplace("+", i.reg1!!, address)
IRDataType.FLOAT -> {
val left = memory.getFloat(address)
val right = registers.getFloat(i.fpReg1!!)
@@ -1076,6 +1181,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) {
IRDataType.BYTE -> plusMinusMultAnyByte("-", i.reg1!!, i.reg2!!)
IRDataType.WORD -> plusMinusMultAnyWord("-", i.reg1!!, i.reg2!!)
IRDataType.LONG -> plusMinusMultAnyLong("-", i.reg1!!, i.reg2!!)
IRDataType.FLOAT -> {
val left = registers.getFloat(i.fpReg1!!)
val right = registers.getFloat(i.fpReg2!!)
@@ -1090,6 +1196,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) {
IRDataType.BYTE -> plusMinusMultConstByte("-", i.reg1!!, i.immediate!!.toUByte())
IRDataType.WORD -> plusMinusMultConstWord("-", i.reg1!!, i.immediate!!.toUShort())
IRDataType.LONG -> plusMinusMultConstLong("-", i.reg1!!, i.immediate!!)
IRDataType.FLOAT -> {
val left = registers.getFloat(i.fpReg1!!)
val result = arithFloat(left, "-", i.immediateFp!!)
@@ -1104,6 +1211,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) {
IRDataType.BYTE -> plusMinusMultAnyByteInplace("-", i.reg1!!, address)
IRDataType.WORD -> plusMinusMultAnyWordInplace("-", i.reg1!!, address)
IRDataType.LONG -> plusMinusMultAnyLongInplace("-", i.reg1!!, address)
IRDataType.FLOAT -> {
val left = memory.getFloat(address)
val right = registers.getFloat(i.fpReg1!!)
@@ -1118,6 +1226,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) {
IRDataType.BYTE -> plusMinusMultAnyByte("*", i.reg1!!, i.reg2!!)
IRDataType.WORD -> plusMinusMultAnyWord("*", i.reg1!!, i.reg2!!)
IRDataType.LONG -> throw IllegalArgumentException("mulr unsigned long not supported")
IRDataType.FLOAT -> {
val left = registers.getFloat(i.fpReg1!!)
val right = registers.getFloat(i.fpReg2!!)
@@ -1132,6 +1241,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) {
IRDataType.BYTE -> plusMinusMultConstByte("*", i.reg1!!, i.immediate!!.toUByte())
IRDataType.WORD -> plusMinusMultConstWord("*", i.reg1!!, i.immediate!!.toUShort())
IRDataType.LONG -> throw IllegalArgumentException("mul unsigned long not supported")
IRDataType.FLOAT -> {
val left = registers.getFloat(i.fpReg1!!)
val result = arithFloat(left, "*", i.immediateFp!!)
@@ -1146,6 +1256,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) {
IRDataType.BYTE -> plusMinusMultAnyByteInplace("*", i.reg1!!, address)
IRDataType.WORD -> plusMinusMultAnyWordInplace("*", i.reg1!!, address)
IRDataType.LONG -> throw IllegalArgumentException("mulm unsigned long not supported")
IRDataType.FLOAT -> {
val left = memory.getFloat(address)
val right = registers.getFloat(i.fpReg1!!)
@@ -1160,6 +1271,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) {
IRDataType.BYTE -> plusMinusMultAnyByteSigned("*", i.reg1!!, i.reg2!!)
IRDataType.WORD -> plusMinusMultAnyWordSigned("*", i.reg1!!, i.reg2!!)
IRDataType.LONG -> plusMinusMultAnyLongSigned("*", i.reg1!!, i.reg2!!)
IRDataType.FLOAT -> {
val left = registers.getFloat(i.fpReg1!!)
val right = registers.getFloat(i.fpReg2!!)
@@ -1174,6 +1286,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) {
IRDataType.BYTE -> plusMinusMultConstByteSigned("*", i.reg1!!, i.immediate!!.toByte())
IRDataType.WORD -> plusMinusMultConstWordSigned("*", i.reg1!!, i.immediate!!.toShort())
IRDataType.LONG -> plusMinusMultConstLongSigned("*", i.reg1!!, i.immediate!!)
IRDataType.FLOAT -> {
val left = registers.getFloat(i.fpReg1!!)
val result = arithFloat(left, "*", i.immediateFp!!)
@@ -1188,6 +1301,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) {
IRDataType.BYTE -> plusMinusMultAnyByteSignedInplace("*", i.reg1!!, address)
IRDataType.WORD -> plusMinusMultAnyWordSignedInplace("*", i.reg1!!, address)
IRDataType.LONG -> plusMinusMultAnyLongSignedInplace("*", i.reg1!!, address)
IRDataType.FLOAT -> {
val left = memory.getFloat(address)
val right = registers.getFloat(i.fpReg1!!)
@@ -1202,6 +1316,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) {
IRDataType.BYTE -> divOrModByteUnsigned("/", i.reg1!!, i.reg2!!)
IRDataType.WORD -> divOrModWordUnsigned("/", i.reg1!!, i.reg2!!)
IRDataType.LONG -> throw IllegalArgumentException("divr unsigned long not supported")
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
nextPc()
@@ -1211,6 +1326,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) {
IRDataType.BYTE -> divOrModConstByteUnsigned("/", i.reg1!!, i.immediate!!.toUByte())
IRDataType.WORD -> divOrModConstWordUnsigned("/", i.reg1!!, i.immediate!!.toUShort())
IRDataType.LONG -> throw IllegalArgumentException("div unsigned long not supported")
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
nextPc()
@@ -1221,6 +1337,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) {
IRDataType.BYTE -> divModByteUnsignedInplace("/", i.reg1!!, address)
IRDataType.WORD -> divModWordUnsignedInplace("/", i.reg1!!, address)
IRDataType.LONG -> throw IllegalArgumentException("divm unsigned long not supported")
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
nextPc()
@@ -1230,6 +1347,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) {
IRDataType.BYTE -> divModByteSigned("/", i.reg1!!, i.reg2!!)
IRDataType.WORD -> divModWordSigned("/", i.reg1!!, i.reg2!!)
IRDataType.LONG -> divModLongSigned("/", i.reg1!!, i.reg2!!)
IRDataType.FLOAT -> {
val left = registers.getFloat(i.fpReg1!!)
val right = registers.getFloat(i.fpReg2!!)
@@ -1244,6 +1362,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) {
IRDataType.BYTE -> divModConstByteSigned("/", i.reg1!!, i.immediate!!.toByte())
IRDataType.WORD -> divModConstWordSigned("/", i.reg1!!, i.immediate!!.toShort())
IRDataType.LONG -> divModConstLongSigned("/", i.reg1!!, i.immediate!!)
IRDataType.FLOAT -> {
val left = registers.getFloat(i.fpReg1!!)
val result = arithFloat(left, "/", i.immediateFp!!)
@@ -1258,6 +1377,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) {
IRDataType.BYTE -> divModByteSignedInplace("/", i.reg1!!, address)
IRDataType.WORD -> divModWordSignedInplace("/", i.reg1!!, address)
IRDataType.LONG -> divModLongSignedInplace("/", i.reg1!!, address)
IRDataType.FLOAT -> {
val left = memory.getFloat(address)
val right = registers.getFloat(i.fpReg1!!)
@@ -1272,6 +1392,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) {
IRDataType.BYTE -> divOrModByteUnsigned("%", i.reg1!!, i.reg2!!)
IRDataType.WORD -> divOrModWordUnsigned("%", i.reg1!!, i.reg2!!)
IRDataType.LONG -> throw IllegalArgumentException("modr unsigned long not supported")
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
nextPc()
@@ -1281,6 +1402,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) {
IRDataType.BYTE -> divOrModConstByteUnsigned("%", i.reg1!!, i.immediate!!.toUByte())
IRDataType.WORD -> divOrModConstWordUnsigned("%", i.reg1!!, i.immediate!!.toUShort())
IRDataType.LONG -> throw IllegalArgumentException("mod unsigned long not supported")
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
nextPc()
@@ -1290,6 +1412,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) {
IRDataType.BYTE -> divAndModUByte(i.reg1!!, i.reg2!!) // division+remainder results on value stack
IRDataType.WORD -> divAndModUWord(i.reg1!!, i.reg2!!) // division+remainder results on value stack
IRDataType.LONG -> throw IllegalArgumentException("divmodr unsigned long not supported")
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
nextPc()
@@ -1299,6 +1422,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) {
IRDataType.BYTE -> divAndModConstUByte(i.reg1!!, i.immediate!!.toUByte()) // division+remainder results on value stack
IRDataType.WORD -> divAndModConstUWord(i.reg1!!, i.immediate!!.toUShort()) // division+remainder results on value stack
IRDataType.LONG -> throw IllegalArgumentException("divmod unsigned long not supported")
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
nextPc()
@@ -1308,6 +1432,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) {
IRDataType.BYTE -> registers.setSB(i.reg1!!, registers.getSB(i.reg2!!).toInt().sign.toByte())
IRDataType.WORD -> registers.setSB(i.reg1!!, registers.getSW(i.reg2!!).toInt().sign.toByte())
IRDataType.LONG -> registers.setSB(i.reg1!!, registers.getSL(i.reg2!!).sign.toByte())
IRDataType.FLOAT -> registers.setSB(i.reg1!!, registers.getFloat(i.fpReg1!!).sign.toInt().toByte())
}
nextPc()
@@ -1317,6 +1442,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(i.type!!) {
IRDataType.BYTE -> registers.setUB(i.reg1!!, sqrt(registers.getUB(i.reg2!!).toDouble()).toInt().toUByte())
IRDataType.WORD -> registers.setUB(i.reg1!!, sqrt(registers.getUW(i.reg2!!).toDouble()).toInt().toUByte())
IRDataType.LONG -> TODO("long sqrt")
IRDataType.FLOAT -> registers.setFloat(i.fpReg1!!, sqrt(registers.getFloat(i.fpReg2!!)))
}
nextPc()
@@ -1325,13 +1451,17 @@ class VirtualMachine(irProgram: IRProgram) {
private fun InsSQUARE(i: IRInstruction) {
when(i.type!!) {
IRDataType.BYTE -> {
val value = registers.getUB(i.reg2!!).toDouble().toInt()
val value = registers.getUB(i.reg2!!).toInt()
registers.setUB(i.reg1!!, (value*value).toUByte())
}
IRDataType.WORD -> {
val value = registers.getUW(i.reg2!!).toDouble().toInt()
val value = registers.getUW(i.reg2!!).toInt()
registers.setUW(i.reg1!!, (value*value).toUShort())
}
IRDataType.LONG -> {
val value = registers.getSL(i.reg2!!)
registers.setSL(i.reg1!!, value*value)
}
IRDataType.FLOAT -> {
val value = registers.getFloat(i.fpReg2!!)
registers.setFloat(i.fpReg1!!, value*value)
@@ -1352,6 +1482,11 @@ class VirtualMachine(irProgram: IRProgram) {
val reg2 = registers.getUW(i.reg2!!)
reg1.toInt() - reg2.toInt()
}
IRDataType.LONG -> {
val reg1 = registers.getSL(i.reg1!!)
val reg2 = registers.getSL(i.reg2!!)
reg1 - reg2
}
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
statusbitsComparison(comparison, i.type!!)
@@ -1368,6 +1503,10 @@ class VirtualMachine(irProgram: IRProgram) {
val reg1 = registers.getUW(i.reg1!!)
reg1.toInt() - (i.immediate!! and 65535)
}
IRDataType.LONG -> {
val reg1 = registers.getSL(i.reg1!!)
reg1 - i.immediate!!
}
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
statusbitsComparison(comparison, i.type!!)
@@ -1400,6 +1539,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(type) {
IRDataType.BYTE -> statusNegative = (value and 0x80)==0x80
IRDataType.WORD -> statusNegative = (value and 0x8000)==0x8000
IRDataType.LONG -> statusNegative = value<0
IRDataType.FLOAT -> { /* floats don't change the status bits */ }
}
}
@@ -1418,6 +1558,7 @@ class VirtualMachine(irProgram: IRProgram) {
when(type) {
IRDataType.BYTE -> statusNegative = (comparison and 0x80)!=0
IRDataType.WORD -> statusNegative = (comparison and 0x8000)!=0
IRDataType.LONG -> statusNegative = comparison<0
IRDataType.FLOAT -> { /* floats don't change the status bits */ }
}
// TODO determine statusOverflow in comparison
@@ -1850,7 +1991,8 @@ class VirtualMachine(irProgram: IRProgram) {
private fun InsEXT(i: IRInstruction) {
when(i.type!!){
IRDataType.BYTE -> registers.setUW(i.reg1!!, registers.getUB(i.reg2!!).toUShort())
IRDataType.WORD -> throw IllegalArgumentException("ext.w not yet supported, requires 32 bits registers")
IRDataType.WORD -> registers.setSL(i.reg1!!, registers.getUW(i.reg2!!).toInt())
IRDataType.LONG -> throw IllegalArgumentException("ext.l makes no sense, 32 bits is already the widest you can get")
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
nextPc()
@@ -1859,7 +2001,8 @@ class VirtualMachine(irProgram: IRProgram) {
private fun InsEXTS(i: IRInstruction) {
when(i.type!!){
IRDataType.BYTE -> registers.setSW(i.reg1!!, registers.getSB(i.reg2!!).toShort())
IRDataType.WORD -> throw IllegalArgumentException("exts.w not yet supported, requires 32 bits registers")
IRDataType.WORD -> registers.setSL(i.reg1!!, registers.getSW(i.reg2!!).toInt())
IRDataType.LONG -> throw IllegalArgumentException("exts.l makes no sense, 32 bits is already the widest you can get")
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
nextPc()
@@ -1871,6 +2014,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!!)
@@ -1888,6 +2032,10 @@ class VirtualMachine(irProgram: IRProgram) {
value = registers.getUW(i.reg1!!).toInt() and i.immediate!!
registers.setUW(i.reg1!!, value.toUShort())
}
IRDataType.LONG -> {
value = registers.getSL(i.reg1!!) and i.immediate!!
registers.setSL(i.reg1!!, value)
}
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
statusbitsNZ(value, i.type!!)
@@ -1910,6 +2058,12 @@ class VirtualMachine(irProgram: IRProgram) {
value = left.toInt() and right.toInt()
memory.setUW(address, value.toUShort())
}
IRDataType.LONG -> {
val left = memory.getSL(address)
val right = registers.getSL(i.reg1!!)
value = left and right
memory.setSL(address, value)
}
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
statusbitsNZ(value, i.type!!)
@@ -1922,6 +2076,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!!)
@@ -1939,6 +2094,10 @@ class VirtualMachine(irProgram: IRProgram) {
value = registers.getUW(i.reg1!!).toInt() or i.immediate!!
registers.setUW(i.reg1!!, value.toUShort())
}
IRDataType.LONG -> {
value = registers.getSL(i.reg1!!) or i.immediate!!
registers.setSL(i.reg1!!, value)
}
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
statusbitsNZ(value, i.type!!)
@@ -1961,6 +2120,12 @@ class VirtualMachine(irProgram: IRProgram) {
value = left.toInt() or right.toInt()
memory.setUW(address, value.toUShort())
}
IRDataType.LONG -> {
val left = memory.getSL(address)
val right = registers.getSL(i.reg1!!)
value = left or right
memory.setSL(address, value)
}
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
statusbitsNZ(value, i.type!!)
@@ -1973,6 +2138,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!!)
@@ -1990,6 +2156,10 @@ class VirtualMachine(irProgram: IRProgram) {
value = registers.getUW(i.reg1!!).toInt() xor i.immediate!!
registers.setUW(i.reg1!!, value.toUShort())
}
IRDataType.LONG -> {
value = registers.getSL(i.reg1!!) xor i.immediate!!
registers.setSL(i.reg1!!, value)
}
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
statusbitsNZ(value, i.type!!)
@@ -2012,6 +2182,12 @@ class VirtualMachine(irProgram: IRProgram) {
value = left.toInt() xor right.toInt()
memory.setUW(address, value.toUShort())
}
IRDataType.LONG -> {
val left = memory.getSL(address)
val right = registers.getSL(i.reg1!!)
value = left xor right
memory.setSL(address, value)
}
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
statusbitsNZ(value, i.type!!)
@@ -2022,6 +2198,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 +2209,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 +2220,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()
@@ -2059,6 +2238,10 @@ class VirtualMachine(irProgram: IRProgram) {
val memvalue = memory.getSW(address).toInt()
memory.setSW(address, (memvalue shr operand).toShort())
}
IRDataType.LONG -> {
val memvalue = memory.getSL(address)
memory.setSL(address, memvalue shr operand)
}
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
nextPc()
@@ -2076,6 +2259,11 @@ class VirtualMachine(irProgram: IRProgram) {
statusCarry = (value and 1)!=0
registers.setSW(i.reg1!!, (value shr 1).toShort())
}
IRDataType.LONG -> {
val value = registers.getSL(i.reg1!!)
statusCarry = (value and 1)!=0
registers.setSL(i.reg1!!, value shr 1)
}
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
nextPc()
@@ -2094,6 +2282,11 @@ class VirtualMachine(irProgram: IRProgram) {
statusCarry = (value and 1)!=0
memory.setSW(address, (value shr 1).toShort())
}
IRDataType.LONG -> {
val value = memory.getSL(address)
statusCarry = (value and 1)!=0
memory.setSL(address, value shr 1)
}
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
nextPc()
@@ -2104,6 +2297,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()
@@ -2121,6 +2315,10 @@ class VirtualMachine(irProgram: IRProgram) {
val memvalue = memory.getUW(address).toInt()
memory.setUW(address, (memvalue shr operand).toUShort())
}
IRDataType.LONG -> {
val memvalue = memory.getSL(address)
memory.setSL(address, memvalue shr operand)
}
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
nextPc()
@@ -2138,6 +2336,11 @@ class VirtualMachine(irProgram: IRProgram) {
statusCarry = (value and 1)!=0
registers.setUW(i.reg1!!, (value shr 1).toUShort())
}
IRDataType.LONG -> {
val value = registers.getSL(i.reg1!!)
statusCarry = (value and 1)!=0
registers.setSL(i.reg1!!, value shr 1)
}
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
nextPc()
@@ -2156,6 +2359,11 @@ class VirtualMachine(irProgram: IRProgram) {
statusCarry = (value and 1)!=0
memory.setUW(address, (value shr 1).toUShort())
}
IRDataType.LONG -> {
val value = memory.getSL(address)
statusCarry = (value and 1)!=0
memory.setSL(address, value shr 1)
}
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
nextPc()
@@ -2170,6 +2378,9 @@ class VirtualMachine(irProgram: IRProgram) {
IRDataType.WORD -> {
registers.setUW(i.reg1!!, (left shl right.toInt()).toUShort())
}
IRDataType.LONG -> {
registers.setSL(i.reg1!!, (left shl right.toInt()).toInt())
}
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
nextPc()
@@ -2187,6 +2398,10 @@ class VirtualMachine(irProgram: IRProgram) {
val memvalue = memory.getUW(address).toInt()
memory.setUW(address, (memvalue shl operand).toUShort())
}
IRDataType.LONG -> {
val memvalue = memory.getSL(address)
memory.setSL(address, memvalue shl operand)
}
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
nextPc()
@@ -2204,6 +2419,11 @@ class VirtualMachine(irProgram: IRProgram) {
statusCarry = (value and 0x8000)!=0
registers.setUW(i.reg1!!, (value shl 1).toUShort())
}
IRDataType.LONG -> {
val value = registers.getSL(i.reg1!!)
statusCarry = value<0
registers.setSL(i.reg1!!, value shl 1)
}
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
nextPc()
@@ -2222,6 +2442,11 @@ class VirtualMachine(irProgram: IRProgram) {
statusCarry = (value and 0x8000)!=0
memory.setUW(address, (value shl 1).toUShort())
}
IRDataType.LONG -> {
val value = memory.getSL(address)
statusCarry = value<0
memory.setSL(address, value shl 1)
}
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
nextPc()
@@ -2250,6 +2475,16 @@ class VirtualMachine(irProgram: IRProgram) {
orig.rotateRight(1)
registers.setUW(i.reg1!!, rotated)
}
IRDataType.LONG -> {
val orig = registers.getSL(i.reg1!!).toUInt()
newStatusCarry = (orig and 1u) != 0u
val rotated: UInt = if (useCarry) {
val carry = if (statusCarry) 0x80000000u else 0u
(orig.rotateRight(1) or carry)
} else
orig.rotateRight(1)
registers.setSL(i.reg1!!, rotated.toInt())
}
IRDataType.FLOAT -> {
throw IllegalArgumentException("can't ROR a float")
}
@@ -2282,6 +2517,16 @@ class VirtualMachine(irProgram: IRProgram) {
orig.rotateRight(1)
memory.setUW(address, rotated)
}
IRDataType.LONG -> {
val orig = memory.getSL(address).toUInt()
newStatusCarry = (orig and 1u) != 0u
val rotated: UInt = (if (useCarry) {
val carry = if (statusCarry) 0x80000000u else 0u
(orig.rotateRight(1) or carry)
} else
orig.rotateRight(1))
memory.setSL(address, rotated.toInt())
}
IRDataType.FLOAT -> {
throw IllegalArgumentException("can't ROR a float")
}
@@ -2313,6 +2558,16 @@ class VirtualMachine(irProgram: IRProgram) {
orig.rotateLeft(1)
registers.setUW(i.reg1!!, rotated)
}
IRDataType.LONG -> {
val orig = registers.getSL(i.reg1!!).toUInt()
newStatusCarry = (orig and 0x80000000u) != 0u
val rotated: UInt = (if (useCarry) {
val carry = if (statusCarry) 1u else 0u
(orig.toUInt().rotateLeft(1) or carry)
} else
orig.rotateLeft(1))
registers.setSL(i.reg1!!, rotated.toInt())
}
IRDataType.FLOAT -> {
throw IllegalArgumentException("can't ROL a float")
}
@@ -2345,6 +2600,16 @@ class VirtualMachine(irProgram: IRProgram) {
orig.rotateLeft(1)
memory.setUW(address, rotated)
}
IRDataType.LONG -> {
val orig = memory.getSL(address).toUInt()
newStatusCarry = (orig and 0x80000000u) != 0u
val rotated: UInt = (if (useCarry) {
val carry = if (statusCarry) 1u else 0u
(orig.rotateLeft(1) or carry)
} else
orig.rotateLeft(1))
memory.setSL(address, rotated.toInt())
}
IRDataType.FLOAT -> {
throw IllegalArgumentException("can't ROL a float")
}
@@ -2360,7 +2625,11 @@ class VirtualMachine(irProgram: IRProgram) {
registers.setUB(i.reg1!!, value.toUByte())
statusbitsNZ(value.toInt(), i.type!!)
}
IRDataType.WORD -> throw IllegalArgumentException("lsig.w not yet supported, requires 32-bits registers")
IRDataType.WORD -> {
val value = registers.getSL(i.reg2!!)
registers.setUW(i.reg1!!, value.toUShort())
}
IRDataType.LONG -> throw IllegalArgumentException("lsig.l makes no sense, 32 bits is already the widest")
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
nextPc()
@@ -2374,7 +2643,12 @@ class VirtualMachine(irProgram: IRProgram) {
statusbitsNZ(newValue, i.type!!)
registers.setUB(i.reg1!!, newValue.toUByte())
}
IRDataType.WORD -> throw IllegalArgumentException("msig.w not yet supported, requires 32-bits registers")
IRDataType.WORD -> {
val value = registers.getSL(i.reg2!!)
val newValue = value ushr 16
registers.setUW(i.reg1!!, newValue.toUShort())
}
IRDataType.LONG -> throw IllegalArgumentException("lsig.l makes no sense, 32 bits is already the widest")
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
nextPc()
@@ -2389,7 +2663,12 @@ class VirtualMachine(irProgram: IRProgram) {
registers.setUW(i.reg1!!, value.toUShort())
statusbitsNZ(value.toInt(), i.type!!)
}
IRDataType.WORD -> throw IllegalArgumentException("concat.w not yet supported, requires 32-bits registers")
IRDataType.WORD -> {
val msw = registers.getUW(i.reg2!!)
val lsw = registers.getUW(i.reg3!!)
registers.setSL(i.reg1!!, ((msw.toInt() shl 16) or lsw.toInt()))
}
IRDataType.LONG -> throw IllegalArgumentException("concat.l makes no sense, 32 bits is already the widest")
IRDataType.FLOAT -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
nextPc()
@@ -2586,6 +2865,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")
}
@@ -2597,6 +2877,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")
}
@@ -2608,6 +2889,7 @@ 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.LONG -> Pair(registers.getSL(i.reg1!!).toUInt(), registers.getSL(i.reg2!!).toUInt())
IRDataType.FLOAT -> {
throw IllegalArgumentException("can't use float here")
}
@@ -2619,6 +2901,7 @@ 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.LONG -> Pair(registers.getSL(i.reg1!!).toUInt(), i.immediate!!.toUInt())
IRDataType.FLOAT -> {
throw IllegalArgumentException("can't use float here")
}
@@ -2630,6 +2913,7 @@ 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.LONG -> Pair(registers.getSL(i.reg1!!).toUInt(), registers.getSL(i.reg2!!).toUInt())
IRDataType.FLOAT -> {
throw IllegalArgumentException("can't use float here")
}
@@ -2641,6 +2925,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")
}
@@ -2648,6 +2933,43 @@ class VirtualMachine(irProgram: IRProgram) {
}
}
private fun plusMinusMultAnyLong(operator: String, reg1: Int, reg2: Int) {
TODO("Not yet implemented")
}
private fun plusMinusMultConstLong(operator: String, reg1: Int, value: Int) {
TODO("Not yet implemented")
}
private fun plusMinusMultAnyLongInplace(operator: String, reg1: Int, address: Int) {
TODO("Not yet implemented")
}
private fun plusMinusMultAnyLongSigned(operator: String, reg1: Int, reg2: Int) {
TODO("Not yet implemented")
}
private fun plusMinusMultConstLongSigned(operator: String, reg1: Int, value: Int) {
TODO("Not yet implemented")
}
private fun plusMinusMultAnyLongSignedInplace(operator: String, reg1: Int, address: Int) {
TODO("Not yet implemented")
}
private fun divModLongSigned(operator: String, reg1: Int, reg2: Int) {
TODO("Not yet implemented")
}
private fun divModConstLongSigned(operator: String, reg1: Int, immediate: Int) {
TODO("Not yet implemented")
}
private fun divModLongSignedInplace(operator: String, reg1: Int, address: Int) {
TODO("Not yet implemented")
}
private var window: GraphicsWindow? = null
fun gfx_enable(mode: UByte) {
@@ -2754,6 +3076,14 @@ internal fun ArrayDeque<UByte>.pushw(value: UShort) {
add((value.toInt() ushr 8).toUByte())
}
internal fun ArrayDeque<UByte>.pushl(value: Int) {
val uint = value.toUInt()
add((uint and 255u).toUByte())
add((uint shr 8 and 255u).toUByte())
add((uint shr 16 and 255u).toUByte())
add((uint shr 24 and 255u).toUByte())
}
internal fun ArrayDeque<UByte>.pushf(value: Double) {
// push float; lsb first, msb last
var bits = value.toBits()
@@ -2780,6 +3110,14 @@ internal fun ArrayDeque<UByte>.popw(): UShort {
return ((msb.toInt() shl 8) + lsb.toInt()).toUShort()
}
internal fun ArrayDeque<UByte>.popl(): Int {
val b0 = removeLast().toUInt()
val b1 = removeLast().toUInt()
val b2 = removeLast().toUInt()
val b3 = removeLast().toUInt()
return (b0 shl 24 or b1 shl 16 or b2 shl 8 or b3).toInt()
}
internal fun ArrayDeque<UByte>.popf(): Double {
// pop float; lsb is on bottom, msb on top
val b0 = removeLast().toLong()

View File

@@ -236,6 +236,7 @@ class VmProgramLoader {
dt.isSignedByte -> memory.setSB(addr, 0)
dt.isUnsignedWord || dt.isPointer -> memory.setUW(addr, 0u)
dt.isSignedWord -> memory.setSW(addr, 0)
dt.isLong -> memory.setSL(addr, 0)
dt.isFloat -> memory.setFloat(addr, 0.0)
else -> throw IRParseException("invalid dt")
}
@@ -248,6 +249,7 @@ class VmProgramLoader {
variable.dt.isSignedByte -> memory.setSB(addr, it.toInt().toByte())
variable.dt.isUnsignedWord -> memory.setUW(addr, it.toInt().toUShort())
variable.dt.isSignedWord -> memory.setSW(addr, it.toInt().toShort())
variable.dt.isLong -> memory.setSL(addr, it.toInt())
variable.dt.isFloat -> memory.setFloat(addr, it)
else -> throw IRParseException("invalid dt")
}