mirror of
				https://github.com/irmen/prog8.git
				synced 2025-11-03 19:16:13 +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