changed (and fixed) msb(long) and lsb(long)

This commit is contained in:
Irmen de Jong
2025-10-13 21:34:03 +02:00
parent 6286035d89
commit 68066acdec
13 changed files with 170 additions and 78 deletions

View File

@@ -117,8 +117,10 @@ val BuiltinFunctions: Map<String, FSignature> = mapOf(
"divmod__ubyte" to FSignature(false, null, FParam("dividend", BaseDataType.UBYTE), FParam("divisor", BaseDataType.UBYTE), FParam("quotient", BaseDataType.UBYTE), FParam("remainder", BaseDataType.UBYTE)),
"divmod__uword" to FSignature(false, null, FParam("dividend", BaseDataType.UWORD), FParam("divisor", BaseDataType.UWORD), FParam("quotient", BaseDataType.UWORD), FParam("remainder", BaseDataType.UWORD)),
"lsb" to FSignature(true, BaseDataType.UBYTE, FParam("value", BaseDataType.UWORD, BaseDataType.WORD, BaseDataType.LONG)),
"lsw" to FSignature(true, BaseDataType.UWORD, FParam("value", BaseDataType.UWORD, BaseDataType.WORD, BaseDataType.LONG)),
"lsb__long" to FSignature(true, BaseDataType.UBYTE, FParam("value", BaseDataType.LONG)),
"msb" to FSignature(true, BaseDataType.UBYTE, FParam("value", BaseDataType.UWORD, BaseDataType.WORD, BaseDataType.LONG)),
"msb__long" to FSignature(true, BaseDataType.UBYTE, FParam("value", BaseDataType.LONG)),
"lsw" to FSignature(true, BaseDataType.UWORD, FParam("value", BaseDataType.UWORD, BaseDataType.WORD, BaseDataType.LONG)),
"msw" to FSignature(true, BaseDataType.UWORD, FParam("value", BaseDataType.UWORD, BaseDataType.WORD, BaseDataType.LONG)),
"mkword" to FSignature(true, BaseDataType.UWORD, FParam("msb", BaseDataType.UBYTE), FParam("lsb", BaseDataType.UBYTE)),
"mklong" to FSignature(true, BaseDataType.LONG, FParam("msb", BaseDataType.UBYTE), FParam("b2", BaseDataType.UBYTE), FParam("b1", BaseDataType.UBYTE), FParam("lsb", BaseDataType.UBYTE)),

View File

@@ -30,9 +30,11 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
"msw" -> funcMsw(fcall, resultRegister)
"lsw" -> funcLsw(fcall, resultRegister)
"msb" -> funcMsb(fcall, resultRegister)
"lsb" -> funcLsb(fcall, resultRegister)
"msb__long" -> funcMsbLong(fcall, resultRegister)
"lsb" -> funcLsb(fcall, resultRegister, false)
"lsb__long" -> funcLsb(fcall, resultRegister, true)
"mkword" -> funcMkword(fcall, resultRegister)
"mklong", "mklong2" -> funcMklong(fcall) // result is in R0:R1
"mklong", "mklong2" -> funcMklong(fcall) // result is in R14:R15
"clamp__byte", "clamp__ubyte", "clamp__word", "clamp__uword", "clamp__long" -> funcClamp(fcall, resultRegister)
"min__byte", "min__ubyte", "min__word", "min__uword", "min__long" -> funcMin(fcall, resultRegister)
"max__byte", "max__ubyte", "max__word", "max__uword", "max__long" -> funcMax(fcall, resultRegister)
@@ -1458,6 +1460,39 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
}
}
private fun funcMsbLong(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?) {
val arg = fcall.args.single()
if (!arg.type.isLong)
throw AssemblyError("msb__long requires long argument")
if (arg is PtNumber)
throw AssemblyError("msb(const) should have been const-folded away")
if (arg is PtIdentifier) {
val sourceName = asmgen.asmVariableName(arg)
when(resultRegister) {
null, RegisterOrPair.A -> asmgen.out(" lda $sourceName+3")
RegisterOrPair.X -> asmgen.out(" ldx $sourceName+3")
RegisterOrPair.Y -> asmgen.out(" ldy $sourceName+3")
RegisterOrPair.AX -> asmgen.out(" lda $sourceName+3 | ldx #0")
RegisterOrPair.AY -> asmgen.out(" lda $sourceName+3 | ldy #0")
RegisterOrPair.XY -> asmgen.out(" ldx $sourceName+3 | ldy #0")
in Cx16VirtualRegisters -> {
val regname = resultRegister.name.lowercase()
if(asmgen.isTargetCpu(CpuType.CPU65C02))
asmgen.out(" lda $sourceName+3 | sta cx16.$regname | stz cx16.$regname+1")
else
asmgen.out(" lda $sourceName+3 | sta cx16.$regname | lda #0 | sta cx16.$regname+1")
}
in combinedLongRegisters -> {
TODO("msb__long into long register ${fcall.position}")
}
else -> throw AssemblyError("invalid reg")
}
} else {
TODO("msb__long from $arg ${fcall.position}")
}
}
private fun funcMsb(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?) {
val arg = fcall.args.single()
if (!arg.type.isWord)
@@ -1567,10 +1602,13 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
}
}
private fun funcLsb(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?) {
private fun funcLsb(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?, fromLong: Boolean) {
val arg = fcall.args.single()
if (!arg.type.isWord)
throw AssemblyError("lsb required word argument")
if(fromLong) {
if (!arg.type.isLong) throw AssemblyError("lsb__long requires long")
} else {
if (!arg.type.isWord) throw AssemblyError("lsb requires word")
}
if (arg is PtNumber)
throw AssemblyError("lsb(const) should have been const-folded away")

View File

@@ -702,9 +702,9 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
val chunk = IRCodeChunk(null, null).also {
if(targetArray.splitWords) {
val lsbmsbReg = codeGen.registers.next(IRDataType.BYTE)
it += IRInstruction(Opcode.LSIG, IRDataType.BYTE, reg1 = lsbmsbReg, reg2 = valueRegister)
it += IRInstruction(Opcode.LSIGB, IRDataType.WORD, reg1 = lsbmsbReg, reg2 = valueRegister)
it += IRInstruction(Opcode.STOREM, IRDataType.BYTE, reg1 = lsbmsbReg, immediate = arrayLength, labelSymbol = "${variable}_lsb", symbolOffset = fixedIndex)
it += IRInstruction(Opcode.MSIG, IRDataType.BYTE, reg1 = lsbmsbReg, reg2 = valueRegister)
it += IRInstruction(Opcode.MSIGB, IRDataType.WORD, reg1 = lsbmsbReg, reg2 = valueRegister)
it += IRInstruction(Opcode.STOREM, IRDataType.BYTE, reg1 = lsbmsbReg, immediate = arrayLength, labelSymbol = "${variable}_msb", symbolOffset = fixedIndex)
}
else
@@ -717,9 +717,9 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
result += IRCodeChunk(null, null).also {
if(targetArray.splitWords) {
val lsbmsbReg = codeGen.registers.next(IRDataType.BYTE)
it += IRInstruction(Opcode.LSIG, IRDataType.BYTE, reg1 = lsbmsbReg, reg2 = valueRegister)
it += IRInstruction(Opcode.LSIGB, IRDataType.WORD, reg1 = lsbmsbReg, reg2 = valueRegister)
it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1 = lsbmsbReg, reg2=indexReg, immediate = arrayLength, labelSymbol = "${variable}_lsb")
it += IRInstruction(Opcode.MSIG, IRDataType.BYTE, reg1 = lsbmsbReg, reg2 = valueRegister)
it += IRInstruction(Opcode.MSIGB, IRDataType.WORD, reg1 = lsbmsbReg, reg2 = valueRegister)
it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1 = lsbmsbReg, reg2=indexReg, immediate = arrayLength, labelSymbol = "${variable}_msb")
}
else

View File

@@ -26,8 +26,10 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
"call" -> funcCall(call)
"msw" -> funcMsw(call)
"lsw" -> funcLsw(call)
"msb" -> funcMsb(call)
"lsb" -> funcLsb(call)
"msb" -> funcMsb(call, false)
"msb__long" -> funcMsb(call, true)
"lsb" -> funcLsb(call, false)
"lsb__long" -> funcLsb(call, true)
"memory" -> funcMemory(call)
"peek" -> funcPeek(call, IRDataType.BYTE)
"peekbool" -> funcPeek(call, IRDataType.BYTE)
@@ -584,12 +586,15 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
return ExpressionCodeResult(code, IRDataType.WORD, resultReg, -1)
}
private fun funcLsb(call: PtBuiltinFunctionCall): ExpressionCodeResult {
private fun funcLsb(call: PtBuiltinFunctionCall, fromLong: Boolean): ExpressionCodeResult {
val result = mutableListOf<IRCodeChunkBase>()
val tr = exprGen.translateExpression(call.args.single())
addToResult(result, tr, tr.resultReg, -1)
val resultReg = codeGen.registers.next(IRDataType.BYTE)
addInstr(result, IRInstruction(Opcode.LSIG, IRDataType.BYTE, reg1 = resultReg, reg2 = tr.resultReg), null)
if(fromLong)
addInstr(result, IRInstruction(Opcode.LSIGB, IRDataType.LONG, reg1 = resultReg, reg2 = tr.resultReg), null)
else
addInstr(result, IRInstruction(Opcode.LSIGB, IRDataType.WORD, reg1 = resultReg, reg2 = tr.resultReg), null)
// note: if a word result is needed, the upper byte is cleared by the typecast that follows. No need to do it here.
return ExpressionCodeResult(result, IRDataType.BYTE, resultReg, -1)
}
@@ -599,16 +604,19 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
val tr = exprGen.translateExpression(call.args.single())
addToResult(result, tr, tr.resultReg, -1)
val resultReg = codeGen.registers.next(IRDataType.WORD)
addInstr(result, IRInstruction(Opcode.LSIG, IRDataType.WORD, reg1 = resultReg, reg2 = tr.resultReg), null)
addInstr(result, IRInstruction(Opcode.LSIGW, IRDataType.LONG, reg1 = resultReg, reg2 = tr.resultReg), null)
return ExpressionCodeResult(result, IRDataType.WORD, resultReg, -1)
}
private fun funcMsb(call: PtBuiltinFunctionCall): ExpressionCodeResult {
private fun funcMsb(call: PtBuiltinFunctionCall, fromLong: Boolean): ExpressionCodeResult {
val result = mutableListOf<IRCodeChunkBase>()
val tr = exprGen.translateExpression(call.args.single())
addToResult(result, tr, tr.resultReg, -1)
val resultReg = codeGen.registers.next(IRDataType.BYTE)
addInstr(result, IRInstruction(Opcode.MSIG, IRDataType.BYTE, reg1 = resultReg, reg2 = tr.resultReg), null)
if(fromLong)
addInstr(result, IRInstruction(Opcode.MSIGB, IRDataType.LONG, reg1 = resultReg, reg2 = tr.resultReg), null)
else
addInstr(result, IRInstruction(Opcode.MSIGB, IRDataType.WORD, reg1 = resultReg, reg2 = tr.resultReg), null)
// note: if a word result is needed, the upper byte is cleared by the typecast that follows. No need to do it here.
return ExpressionCodeResult(result, IRDataType.BYTE, resultReg, -1)
}
@@ -618,7 +626,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
val tr = exprGen.translateExpression(call.args.single())
addToResult(result, tr, tr.resultReg, -1)
val resultReg = codeGen.registers.next(IRDataType.WORD)
addInstr(result, IRInstruction(Opcode.MSIG, IRDataType.WORD, reg1 = resultReg, reg2 = tr.resultReg), null)
addInstr(result, IRInstruction(Opcode.MSIGW, IRDataType.LONG, reg1 = resultReg, reg2 = tr.resultReg), null)
return ExpressionCodeResult(result, IRDataType.WORD, resultReg, -1)
}

View File

@@ -707,13 +707,11 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
}
BaseDataType.UWORD, BaseDataType.WORD -> {
actualResultReg2 = codeGen.registers.next(IRDataType.BYTE)
addInstr(result, IRInstruction(Opcode.LSIG, IRDataType.BYTE, reg1=actualResultReg2, reg2=tr.resultReg, immediate = 0), null)
addInstr(result, IRInstruction(Opcode.LSIGB, IRDataType.WORD, reg1=actualResultReg2, reg2=tr.resultReg, immediate = 0), null)
}
BaseDataType.LONG -> {
actualResultReg2 = codeGen.registers.next(IRDataType.BYTE)
val wordReg = codeGen.registers.next(IRDataType.WORD)
addInstr(result, IRInstruction(Opcode.LSIG, IRDataType.WORD, reg1=wordReg, reg2=tr.resultReg, immediate = 0), null)
addInstr(result, IRInstruction(Opcode.LSIG, IRDataType.BYTE, reg1=actualResultReg2, reg2=wordReg, immediate = 0), null)
addInstr(result, IRInstruction(Opcode.LSIGB, IRDataType.LONG, reg1=actualResultReg2, reg2=tr.resultReg, immediate = 0), null)
}
BaseDataType.FLOAT -> {
actualResultReg2 = codeGen.registers.next(IRDataType.BYTE)
@@ -729,13 +727,11 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
}
BaseDataType.UWORD, BaseDataType.WORD -> {
actualResultReg2 = codeGen.registers.next(IRDataType.BYTE)
addInstr(result, IRInstruction(Opcode.LSIG, IRDataType.BYTE, reg1=actualResultReg2, reg2=tr.resultReg, immediate = 0), null)
addInstr(result, IRInstruction(Opcode.LSIGB, IRDataType.WORD, reg1=actualResultReg2, reg2=tr.resultReg, immediate = 0), null)
}
BaseDataType.LONG -> {
actualResultReg2 = codeGen.registers.next(IRDataType.BYTE)
val wordReg = codeGen.registers.next(IRDataType.WORD)
addInstr(result, IRInstruction(Opcode.LSIG, IRDataType.WORD, reg1=wordReg, reg2=tr.resultReg, immediate = 0), null)
addInstr(result, IRInstruction(Opcode.LSIG, IRDataType.BYTE, reg1=actualResultReg2, reg2=wordReg, immediate = 0), null)
addInstr(result, IRInstruction(Opcode.LSIGB, IRDataType.LONG, reg1=actualResultReg2, reg2=tr.resultReg, immediate = 0), null)
}
BaseDataType.FLOAT -> {
actualResultReg2 = codeGen.registers.next(IRDataType.BYTE)
@@ -761,7 +757,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
}
BaseDataType.LONG -> {
actualResultReg2 = codeGen.registers.next(IRDataType.WORD)
addInstr(result, IRInstruction(Opcode.LSIG, IRDataType.WORD, reg1=actualResultReg2, reg2=tr.resultReg, immediate = 0), null)
addInstr(result, IRInstruction(Opcode.LSIGW, IRDataType.LONG, reg1=actualResultReg2, reg2=tr.resultReg, immediate = 0), null)
}
BaseDataType.FLOAT -> {
actualResultReg2 = codeGen.registers.next(IRDataType.WORD)
@@ -790,7 +786,7 @@ internal class ExpressionGen(private val codeGen: IRCodeGen) {
}
BaseDataType.LONG -> {
actualResultReg2 = codeGen.registers.next(IRDataType.WORD)
addInstr(result, IRInstruction(Opcode.LSIG, IRDataType.WORD, reg1=actualResultReg2, reg2=tr.resultReg, immediate = 0), null)
addInstr(result, IRInstruction(Opcode.LSIGW, IRDataType.LONG, reg1=actualResultReg2, reg2=tr.resultReg, immediate = 0), null)
}
BaseDataType.FLOAT -> {
actualResultReg2 = codeGen.registers.next(IRDataType.WORD)

View File

@@ -254,6 +254,15 @@ class VarConstantValueTypeAdjuster(
functionCallExpr))
}
}
else if(func==listOf("lsb") || func==listOf("msb")) {
val t1 = functionCallExpr.args[0].inferType(program)
if(t1.isLong) {
val replaceFunc = func[0]+"__long"
return listOf(IAstModification.SetExpression({functionCallExpr.target = it as IdentifierReference},
IdentifierReference(listOf(replaceFunc), functionCallExpr.target.position),
functionCallExpr))
}
}
return noModifications
}

View File

@@ -8,7 +8,7 @@ txt {
sub width() -> ubyte {
%ir {{
syscall 46 (): r99000.w
lsig.b r99100,r99000
lsigb.w r99100,r99000
returnr.b r99100
}}
}
@@ -16,7 +16,7 @@ sub width() -> ubyte {
sub height() -> ubyte {
%ir {{
syscall 46 (): r99000.w
msig.b r99100,r99000
msigb.w r99100,r99000
returnr.b r99100
}}
}

View File

@@ -22,8 +22,10 @@ internal val constEvaluatorsForBuiltinFuncs: Map<String, ConstExpressionCaller>
"sqrt__uword" to { a, p, prg -> oneIntArgOutputInt(a, p, prg, false) { sqrt(it.toDouble()) } },
"sqrt__float" to { a, p, prg -> oneFloatArgOutputFloat(a, p, prg) { sqrt(it) } },
"lsb" to { a, p, prg -> oneIntArgOutputInt(a, p, prg, true) { x: Int -> (x and 255).toDouble() } },
"lsb__long" to { a, p, prg -> oneIntArgOutputInt(a, p, prg, true) { x: Int -> (x and 255).toDouble() } },
"lsw" to { a, p, prg -> oneIntArgOutputInt(a, p, prg, true) { x: Int -> (x and 65535).toDouble() } },
"msb" to { a, p, prg -> oneIntArgOutputInt(a, p, prg, true) { x: Int -> (x ushr 8 and 255).toDouble()} },
"msb__long" to { a, p, prg -> oneIntArgOutputInt(a, p, prg, true) { x: Int -> (x ushr 24 and 255).toDouble()} },
"msw" to { a, p, prg -> oneIntArgOutputInt(a, p, prg, true) { x: Int -> (x ushr 16 and 65535).toDouble()} },
"mkword" to ::builtinMkword,
"mklong" to ::builtinMklong,

View File

@@ -91,16 +91,13 @@ cmp (x,y)
Normally you should just use a comparison expression (``x < y``)
lsb (x)
Get the least significant (lower) byte of the value x. Equivalent to ``x & 255``.
Get the least significant (lower) byte of the value x. Equivalent to ``x & 255`` or even ``x as ubyte``.
lsw (x)
Get the least significant (lower) word of the value x. Equivalent to ``x & 65535``.
Get the least significant (lower) word of the value x. Equivalent to ``x & 65535`` or even ``x as uword``.
msb (x)
Get the most significant (higher) byte of the word value x.
If x is a value greater than a word, it will not actually return the *highest* byte of this value,
but it will only look a the lower word part of this value and return the higher byte from that.
So you're always getting bits 8-16 of the value x: ``msb($1234)`` is $12, whereas ``msb($123456)`` is $34.
Get the most significant (highest) byte of the word or long value x.
msw (x)
Get the most significant (higher) word of the value x. For all word and byte numbers this will always result in 0.

View File

@@ -31,6 +31,7 @@ STRUCTS and TYPED POINTERS
Future Things and Ideas
^^^^^^^^^^^^^^^^^^^^^^^
- make $8000000 a valid long integer (-2147483648) this is more involved than you think. To make this work: long |= $80000000
- make memory mapped variables support more constant expressions such as: &uword MyHigh = &mylong1+2
- fix the line, cols in Position, sometimes they count from 0 sometimes from 1, should both always be 1-based (is this the reason some source lines end up missing in the IR file?)
- handle Alias in a general way in LiteralsToAutoVarsAndRecombineIdentifiers instead of replacing it scattered over multiple functions
- After long variable type is completed: make all constants long by default (remove type name altogether), reduce to target type implictly if the actual value fits.

View File

@@ -6,14 +6,25 @@ main {
sub start() {
long @shared lv1 = $12345678
; TODO support long+1 / -1 expressions....
cx16.r4 = msw(lv1-1)
cx16.r5 = lsw(lv1-1)
txt.print_uwhex(cx16.r4, true)
txt.print_uwhex(cx16.r5, true)
txt.print_ubhex(msb(lv1), true)
txt.spc()
txt.print_ubhex(lsb(lv1), true)
txt.spc()
txt.print_ubhex(lv1 as ubyte, true)
txt.nl()
txt.print_uwhex(msw(lv1), true)
txt.spc()
txt.print_uwhex(lsw(lv1), true)
txt.nl()
txt.print_ubhex((lv1-1) as ubyte, true)
txt.nl()
; ; TODO support long+1 / -1 expressions....
; cx16.r4 = msw(lv1-1)
; cx16.r5 = lsw(lv1-1)
; txt.print_uwhex(cx16.r4, true)
; txt.print_uwhex(cx16.r5, true)
; txt.nl()
;
; txt.print_ubhex((lv1-1) as ubyte, true)
; txt.nl()
}
}

View File

@@ -248,8 +248,10 @@ 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
msig [b, w] reg1, reg2 - reg1 becomes the most significant byte (or word) of the word (or int) in reg2
lsigb [w, l] reg1, reg2 - reg1 becomes the least significant byte of the word (or long) in reg2
lsigw [l] reg1, reg2 - reg1 becomes the least significant word of the long in reg2
msigb [w, l] reg1, reg2 - reg1 becomes the most significant byte of the word (or long) in reg2
msigw [l] reg1, reg2 - reg1 becomes the most significant word of the long 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
@@ -421,8 +423,10 @@ enum class Opcode {
POP,
PUSHST,
POPST,
LSIG,
MSIG,
LSIGB,
LSIGW,
MSIGB,
MSIGW,
CONCAT,
BREAKPOINT,
ALIGN
@@ -521,8 +525,10 @@ val OpcodesThatSetStatusbitsButNotCarry = arrayOf(
Opcode.XORM,
Opcode.XORR,
Opcode.XOR,
Opcode.LSIG,
Opcode.MSIG,
Opcode.LSIGB,
Opcode.LSIGW,
Opcode.MSIGB,
Opcode.MSIGW,
Opcode.CONCAT
)
@@ -798,8 +804,10 @@ val instructionFormats = mutableMapOf(
Opcode.FFLOOR to InstructionFormat.from("F,>fr1,<fr2"),
Opcode.FCEIL to InstructionFormat.from("F,>fr1,<fr2"),
Opcode.LSIG to InstructionFormat.from("BW,>r1,<r2"),
Opcode.MSIG to InstructionFormat.from("BW,>r1,<r2"),
Opcode.LSIGB to InstructionFormat.from("WL,>r1,<r2"),
Opcode.LSIGW to InstructionFormat.from("L,>r1,<r2"),
Opcode.MSIGB to InstructionFormat.from("WL,>r1,<r2"),
Opcode.MSIGW to InstructionFormat.from("L,>r1,<r2"),
Opcode.PUSH to InstructionFormat.from("BWL,<r1 | F,<fr1"),
Opcode.POP to InstructionFormat.from("BWL,>r1 | F,>fr1"),
Opcode.PUSHST to InstructionFormat.from("N"),
@@ -1095,13 +1103,13 @@ data class IRInstruction(
if(opcode==Opcode.SGN)
return IRDataType.BYTE
}
if(opcode==Opcode.JUMPI || opcode==Opcode.CALLI || opcode==Opcode.STOREZI)
if(opcode==Opcode.JUMPI || opcode==Opcode.CALLI || opcode==Opcode.STOREZI || opcode==Opcode.LSIGW || opcode==Opcode.MSIGW)
return IRDataType.WORD
if(opcode==Opcode.EXT || opcode==Opcode.EXTS)
return if (type == IRDataType.BYTE) IRDataType.WORD else null
if(opcode==Opcode.CONCAT)
return if (type == IRDataType.BYTE) IRDataType.WORD else null
if(opcode==Opcode.ASRNM || opcode==Opcode.LSRNM || opcode==Opcode.LSLNM || opcode==Opcode.SQRT)
if(opcode==Opcode.ASRNM || opcode==Opcode.LSRNM || opcode==Opcode.LSLNM || opcode==Opcode.SQRT || opcode==Opcode.LSIGB || opcode==Opcode.MSIGB)
return IRDataType.BYTE
return this.type
}
@@ -1111,12 +1119,6 @@ data class IRInstruction(
return IRDataType.BYTE
if(opcode==Opcode.LOADI || opcode==Opcode.STOREI || opcode==Opcode.LOADFIELD || opcode==Opcode.STOREFIELD)
return IRDataType.WORD
if(opcode==Opcode.MSIG || opcode==Opcode.LSIG)
return when(type) {
IRDataType.BYTE -> IRDataType.WORD
IRDataType.WORD -> IRDataType.LONG
else -> null
}
if(opcode==Opcode.ASRN || opcode==Opcode.LSRN || opcode==Opcode.LSLN)
return IRDataType.BYTE
return this.type

View File

@@ -311,8 +311,10 @@ class VirtualMachine(irProgram: IRProgram) {
Opcode.ROLM -> InsROLM(ins, false)
Opcode.ROXL -> InsROL(ins, true)
Opcode.ROXLM -> InsROLM(ins, true)
Opcode.LSIG -> InsLSIG(ins)
Opcode.MSIG -> InsMSIG(ins)
Opcode.LSIGB -> InsLSIGB(ins)
Opcode.LSIGW -> InsLSIGW(ins)
Opcode.MSIGB -> InsMSIGB(ins)
Opcode.MSIGW -> InsMSIGW(ins)
Opcode.CONCAT -> InsCONCAT(ins)
Opcode.PUSH -> InsPUSH(ins)
Opcode.POP -> InsPOP(ins)
@@ -2579,39 +2581,63 @@ class VirtualMachine(irProgram: IRProgram) {
statusCarry = newStatusCarry
}
private fun InsLSIG(i: IRInstruction) {
private fun InsLSIGB(i: IRInstruction) {
when(i.type!!) {
IRDataType.BYTE -> {
val value = registers.getUW(i.reg2!!)
registers.setUB(i.reg1!!, value.toUByte())
statusbitsNZ(value.toInt(), i.type!!)
}
IRDataType.WORD -> {
val value = registers.getSL(i.reg2!!)
registers.setUW(i.reg1!!, value.toUShort())
val value = registers.getUW(i.reg2!!)
val byte = value.toUByte()
registers.setUB(i.reg1!!, byte)
statusbitsNZ(byte.toInt(), i.type!!)
}
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")
IRDataType.LONG -> {
val value = registers.getSL(i.reg2!!)
val byte = value.toUByte()
registers.setUB(i.reg1!!, byte)
statusbitsNZ(byte.toInt(), i.type!!)
}
else -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
nextPc()
}
private fun InsMSIG(i: IRInstruction) {
private fun InsLSIGW(i: IRInstruction) {
if (i.type!! == IRDataType.LONG) {
val value = registers.getSL(i.reg2!!)
val word = value.toUShort()
registers.setUW(i.reg1!!, word)
statusbitsNZ(word.toInt(), i.type!!)
}
else throw IllegalArgumentException("invalid float type for this instruction $i")
nextPc()
}
private fun InsMSIGB(i: IRInstruction) {
when(i.type!!) {
IRDataType.BYTE -> {
IRDataType.WORD -> {
val value = registers.getUW(i.reg2!!)
val newValue = value.toInt() ushr 8
statusbitsNZ(newValue, i.type!!)
registers.setUB(i.reg1!!, newValue.toUByte())
}
IRDataType.WORD -> {
IRDataType.LONG -> {
val value = registers.getSL(i.reg2!!)
val newValue = value ushr 24
statusbitsNZ(newValue, i.type!!)
registers.setUB(i.reg1!!, newValue.toUByte())
}
else -> throw IllegalArgumentException("invalid float type for this instruction $i")
}
nextPc()
}
private fun InsMSIGW(i: IRInstruction) {
if (i.type!! == IRDataType.LONG) {
val value = registers.getSL(i.reg2!!)
val newValue = value ushr 16
statusbitsNZ(newValue, i.type!!)
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")
}
else throw IllegalArgumentException("invalid float type for this instruction $i")
nextPc()
}