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__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)), "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)), "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" 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)), "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)), "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)), "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) "msw" -> funcMsw(fcall, resultRegister)
"lsw" -> funcLsw(fcall, resultRegister) "lsw" -> funcLsw(fcall, resultRegister)
"msb" -> funcMsb(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) "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) "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) "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) "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?) { private fun funcMsb(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?) {
val arg = fcall.args.single() val arg = fcall.args.single()
if (!arg.type.isWord) 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() val arg = fcall.args.single()
if (!arg.type.isWord) if(fromLong) {
throw AssemblyError("lsb required word argument") if (!arg.type.isLong) throw AssemblyError("lsb__long requires long")
} else {
if (!arg.type.isWord) throw AssemblyError("lsb requires word")
}
if (arg is PtNumber) if (arg is PtNumber)
throw AssemblyError("lsb(const) should have been const-folded away") 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 { val chunk = IRCodeChunk(null, null).also {
if(targetArray.splitWords) { if(targetArray.splitWords) {
val lsbmsbReg = codeGen.registers.next(IRDataType.BYTE) 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.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) it += IRInstruction(Opcode.STOREM, IRDataType.BYTE, reg1 = lsbmsbReg, immediate = arrayLength, labelSymbol = "${variable}_msb", symbolOffset = fixedIndex)
} }
else else
@@ -717,9 +717,9 @@ internal class AssignmentGen(private val codeGen: IRCodeGen, private val express
result += IRCodeChunk(null, null).also { result += IRCodeChunk(null, null).also {
if(targetArray.splitWords) { if(targetArray.splitWords) {
val lsbmsbReg = codeGen.registers.next(IRDataType.BYTE) 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.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") it += IRInstruction(Opcode.STOREX, IRDataType.BYTE, reg1 = lsbmsbReg, reg2=indexReg, immediate = arrayLength, labelSymbol = "${variable}_msb")
} }
else else

View File

@@ -26,8 +26,10 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
"call" -> funcCall(call) "call" -> funcCall(call)
"msw" -> funcMsw(call) "msw" -> funcMsw(call)
"lsw" -> funcLsw(call) "lsw" -> funcLsw(call)
"msb" -> funcMsb(call) "msb" -> funcMsb(call, false)
"lsb" -> funcLsb(call) "msb__long" -> funcMsb(call, true)
"lsb" -> funcLsb(call, false)
"lsb__long" -> funcLsb(call, true)
"memory" -> funcMemory(call) "memory" -> funcMemory(call)
"peek" -> funcPeek(call, IRDataType.BYTE) "peek" -> funcPeek(call, IRDataType.BYTE)
"peekbool" -> 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) 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 result = mutableListOf<IRCodeChunkBase>()
val tr = exprGen.translateExpression(call.args.single()) val tr = exprGen.translateExpression(call.args.single())
addToResult(result, tr, tr.resultReg, -1) addToResult(result, tr, tr.resultReg, -1)
val resultReg = codeGen.registers.next(IRDataType.BYTE) 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. // 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) 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()) val tr = exprGen.translateExpression(call.args.single())
addToResult(result, tr, tr.resultReg, -1) addToResult(result, tr, tr.resultReg, -1)
val resultReg = codeGen.registers.next(IRDataType.WORD) 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) 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 result = mutableListOf<IRCodeChunkBase>()
val tr = exprGen.translateExpression(call.args.single()) val tr = exprGen.translateExpression(call.args.single())
addToResult(result, tr, tr.resultReg, -1) addToResult(result, tr, tr.resultReg, -1)
val resultReg = codeGen.registers.next(IRDataType.BYTE) 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. // 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) 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()) val tr = exprGen.translateExpression(call.args.single())
addToResult(result, tr, tr.resultReg, -1) addToResult(result, tr, tr.resultReg, -1)
val resultReg = codeGen.registers.next(IRDataType.WORD) 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) return ExpressionCodeResult(result, IRDataType.WORD, resultReg, -1)
} }

View File

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

View File

@@ -254,6 +254,15 @@ class VarConstantValueTypeAdjuster(
functionCallExpr)) 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 return noModifications
} }

View File

@@ -8,7 +8,7 @@ txt {
sub width() -> ubyte { sub width() -> ubyte {
%ir {{ %ir {{
syscall 46 (): r99000.w syscall 46 (): r99000.w
lsig.b r99100,r99000 lsigb.w r99100,r99000
returnr.b r99100 returnr.b r99100
}} }}
} }
@@ -16,7 +16,7 @@ sub width() -> ubyte {
sub height() -> ubyte { sub height() -> ubyte {
%ir {{ %ir {{
syscall 46 (): r99000.w syscall 46 (): r99000.w
msig.b r99100,r99000 msigb.w r99100,r99000
returnr.b r99100 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__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) } }, "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" 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() } }, "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" 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()} }, "msw" to { a, p, prg -> oneIntArgOutputInt(a, p, prg, true) { x: Int -> (x ushr 16 and 65535).toDouble()} },
"mkword" to ::builtinMkword, "mkword" to ::builtinMkword,
"mklong" to ::builtinMklong, "mklong" to ::builtinMklong,

View File

@@ -91,16 +91,13 @@ cmp (x,y)
Normally you should just use a comparison expression (``x < y``) Normally you should just use a comparison expression (``x < y``)
lsb (x) 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) 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) msb (x)
Get the most significant (higher) byte of the word value x. Get the most significant (highest) byte of the word or long 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.
msw (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. 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 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 $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?) - 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 - 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. - 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() { sub start() {
long @shared lv1 = $12345678 long @shared lv1 = $12345678
; TODO support long+1 / -1 expressions.... txt.print_ubhex(msb(lv1), true)
cx16.r4 = msw(lv1-1) txt.spc()
cx16.r5 = lsw(lv1-1) txt.print_ubhex(lsb(lv1), true)
txt.print_uwhex(cx16.r4, true) txt.spc()
txt.print_uwhex(cx16.r5, true) 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.nl()
txt.print_ubhex((lv1-1) as ubyte, true) ; ; TODO support long+1 / -1 expressions....
txt.nl() ; 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 nop - do nothing
breakpoint - trigger a breakpoint breakpoint - trigger a breakpoint
align alignmentvalue - represents a memory alignment directive 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 lsigb [w, l] reg1, reg2 - reg1 becomes the least significant byte of the word (or long) in reg2
msig [b, w] reg1, reg2 - reg1 becomes the most significant byte (or word) of the word (or int) 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) 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 push [b, w, f] reg1 - push value in reg1 on the stack
pop [b, w, f] reg1 - pop value from stack into reg1 pop [b, w, f] reg1 - pop value from stack into reg1
@@ -421,8 +423,10 @@ enum class Opcode {
POP, POP,
PUSHST, PUSHST,
POPST, POPST,
LSIG, LSIGB,
MSIG, LSIGW,
MSIGB,
MSIGW,
CONCAT, CONCAT,
BREAKPOINT, BREAKPOINT,
ALIGN ALIGN
@@ -521,8 +525,10 @@ val OpcodesThatSetStatusbitsButNotCarry = arrayOf(
Opcode.XORM, Opcode.XORM,
Opcode.XORR, Opcode.XORR,
Opcode.XOR, Opcode.XOR,
Opcode.LSIG, Opcode.LSIGB,
Opcode.MSIG, Opcode.LSIGW,
Opcode.MSIGB,
Opcode.MSIGW,
Opcode.CONCAT Opcode.CONCAT
) )
@@ -798,8 +804,10 @@ val instructionFormats = mutableMapOf(
Opcode.FFLOOR to InstructionFormat.from("F,>fr1,<fr2"), Opcode.FFLOOR to InstructionFormat.from("F,>fr1,<fr2"),
Opcode.FCEIL to InstructionFormat.from("F,>fr1,<fr2"), Opcode.FCEIL to InstructionFormat.from("F,>fr1,<fr2"),
Opcode.LSIG to InstructionFormat.from("BW,>r1,<r2"), Opcode.LSIGB to InstructionFormat.from("WL,>r1,<r2"),
Opcode.MSIG to InstructionFormat.from("BW,>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.PUSH to InstructionFormat.from("BWL,<r1 | F,<fr1"),
Opcode.POP to InstructionFormat.from("BWL,>r1 | F,>fr1"), Opcode.POP to InstructionFormat.from("BWL,>r1 | F,>fr1"),
Opcode.PUSHST to InstructionFormat.from("N"), Opcode.PUSHST to InstructionFormat.from("N"),
@@ -1095,13 +1103,13 @@ data class IRInstruction(
if(opcode==Opcode.SGN) if(opcode==Opcode.SGN)
return IRDataType.BYTE 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 return IRDataType.WORD
if(opcode==Opcode.EXT || opcode==Opcode.EXTS) if(opcode==Opcode.EXT || opcode==Opcode.EXTS)
return if (type == IRDataType.BYTE) IRDataType.WORD else null return if (type == IRDataType.BYTE) IRDataType.WORD else null
if(opcode==Opcode.CONCAT) if(opcode==Opcode.CONCAT)
return if (type == IRDataType.BYTE) IRDataType.WORD else null 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 IRDataType.BYTE
return this.type return this.type
} }
@@ -1111,12 +1119,6 @@ data class IRInstruction(
return IRDataType.BYTE return IRDataType.BYTE
if(opcode==Opcode.LOADI || opcode==Opcode.STOREI || opcode==Opcode.LOADFIELD || opcode==Opcode.STOREFIELD) if(opcode==Opcode.LOADI || opcode==Opcode.STOREI || opcode==Opcode.LOADFIELD || opcode==Opcode.STOREFIELD)
return IRDataType.WORD 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) if(opcode==Opcode.ASRN || opcode==Opcode.LSRN || opcode==Opcode.LSLN)
return IRDataType.BYTE return IRDataType.BYTE
return this.type return this.type

View File

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