mirror of
https://github.com/irmen/prog8.git
synced 2025-11-02 13:16:07 +00:00
changed (and fixed) msb(long) and lsb(long)
This commit is contained in:
@@ -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)),
|
||||
|
||||
@@ -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")
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,42 +2581,66 @@ 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 16
|
||||
registers.setUW(i.reg1!!, newValue.toUShort())
|
||||
val newValue = value ushr 24
|
||||
statusbitsNZ(newValue, i.type!!)
|
||||
registers.setUB(i.reg1!!, newValue.toUByte())
|
||||
}
|
||||
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()
|
||||
}
|
||||
|
||||
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())
|
||||
}
|
||||
else throw IllegalArgumentException("invalid float type for this instruction $i")
|
||||
nextPc()
|
||||
}
|
||||
|
||||
private fun InsCONCAT(i: IRInstruction) {
|
||||
when(i.type!!) {
|
||||
IRDataType.BYTE -> {
|
||||
|
||||
Reference in New Issue
Block a user