mirror of
https://github.com/irmen/prog8.git
synced 2026-04-26 05:17:54 +00:00
implement mklong(a,b,c,d) and mklong2(w1,w2)
This commit is contained in:
@@ -117,6 +117,8 @@ val BuiltinFunctions: Map<String, FSignature> = mapOf(
|
||||
"msb" to FSignature(true, BaseDataType.UBYTE, 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)),
|
||||
"mklong2" to FSignature(true, BaseDataType.LONG, FParam("msw", BaseDataType.UWORD), FParam("lsw", BaseDataType.UWORD)),
|
||||
"clamp" to FSignature(true, null, FParam("value", BaseDataType.BYTE), FParam("minimum", BaseDataType.BYTE), FParam("maximum", BaseDataType.BYTE)),
|
||||
"clamp__byte" to FSignature(true, BaseDataType.BYTE, FParam("value", BaseDataType.BYTE), FParam("minimum", BaseDataType.BYTE), FParam("maximum", BaseDataType.BYTE)),
|
||||
"clamp__ubyte" to FSignature(true, BaseDataType.UBYTE, FParam("value", BaseDataType.UBYTE), FParam("minimum", BaseDataType.UBYTE), FParam("maximum", BaseDataType.UBYTE)),
|
||||
|
||||
@@ -32,6 +32,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
"msb" -> funcMsb(fcall, resultRegister)
|
||||
"lsb" -> funcLsb(fcall, resultRegister)
|
||||
"mkword" -> funcMkword(fcall, resultRegister)
|
||||
"mklong", "mklong2" -> funcMklong(fcall) // result is in R0:R1
|
||||
"clamp__byte", "clamp__ubyte", "clamp__word", "clamp__uword" -> funcClamp(fcall, resultRegister)
|
||||
"min__byte", "min__ubyte", "min__word", "min__uword" -> funcMin(fcall, resultRegister)
|
||||
"max__byte", "max__ubyte", "max__word", "max__uword" -> funcMax(fcall, resultRegister)
|
||||
@@ -1115,6 +1116,40 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
}
|
||||
}
|
||||
|
||||
private fun funcMklong(fcall: PtBuiltinFunctionCall) {
|
||||
// result long in R0:R1 (r0=lsw, r1=msw)
|
||||
|
||||
fun isArgRegister(expression: PtExpression, reg: RegisterOrPair): Boolean {
|
||||
if(expression !is PtIdentifier)
|
||||
return false
|
||||
return expression.name.startsWith("cx16.${reg.name.lowercase()}")
|
||||
}
|
||||
|
||||
if(fcall.args.size==2) {
|
||||
// mklong2(msw, lsw)
|
||||
if(isArgRegister(fcall.args[0], RegisterOrPair.R0) || isArgRegister(fcall.args[0], RegisterOrPair.R1) ||
|
||||
isArgRegister(fcall.args[1], RegisterOrPair.R0) || isArgRegister(fcall.args[1], RegisterOrPair.R1)) {
|
||||
error("cannot use R0 and/or R1 as arguments for mklong2 because the result should go into R0:R1 ${fcall.position}")
|
||||
} else {
|
||||
assignAsmGen.assignExpressionToVariable(fcall.args[0], "cx16.r1", DataType.UWORD)
|
||||
assignAsmGen.assignExpressionToVariable(fcall.args[1], "cx16.r0", DataType.UWORD)
|
||||
}
|
||||
} else {
|
||||
// mklong(msb, b2, b1, lsb)
|
||||
if(isArgRegister(fcall.args[0], RegisterOrPair.R0) || isArgRegister(fcall.args[0], RegisterOrPair.R1) ||
|
||||
isArgRegister(fcall.args[1], RegisterOrPair.R0) || isArgRegister(fcall.args[1], RegisterOrPair.R1) ||
|
||||
isArgRegister(fcall.args[2], RegisterOrPair.R0) || isArgRegister(fcall.args[2], RegisterOrPair.R1) ||
|
||||
isArgRegister(fcall.args[3], RegisterOrPair.R0) || isArgRegister(fcall.args[3], RegisterOrPair.R1)) {
|
||||
error("cannot use R0 and/or R1 as arguments for mklong because the result should go into R0:R1 ${fcall.position}")
|
||||
} else {
|
||||
assignAsmGen.assignExpressionToVariable(fcall.args[0], "cx16.r1H", DataType.UBYTE)
|
||||
assignAsmGen.assignExpressionToVariable(fcall.args[1], "cx16.r1L", DataType.UBYTE)
|
||||
assignAsmGen.assignExpressionToVariable(fcall.args[2], "cx16.r0H", DataType.UBYTE)
|
||||
assignAsmGen.assignExpressionToVariable(fcall.args[3], "cx16.r0L", DataType.UBYTE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun funcMkword(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?) {
|
||||
val reg = resultRegister ?: RegisterOrPair.AY
|
||||
var needAsaveForArg0 = asmgen.needAsaveForExpr(fcall.args[0])
|
||||
|
||||
@@ -206,8 +206,11 @@ internal class FunctionCallAsmGen(private val program: PtProgram, private val as
|
||||
is PtBuiltinFunctionCall -> {
|
||||
if (arg.name in arrayOf("lsb", "msb", "lsw", "msw"))
|
||||
return usesOtherRegistersWhileEvaluating(arg.args[0])
|
||||
if (arg.name == "mkword")
|
||||
if (arg.name == "mkword" || arg.name == "mklong2")
|
||||
return usesOtherRegistersWhileEvaluating(arg.args[0]) || usesOtherRegistersWhileEvaluating(arg.args[1])
|
||||
if (arg.name == "mklong")
|
||||
return usesOtherRegistersWhileEvaluating(arg.args[0]) || usesOtherRegistersWhileEvaluating(arg.args[1]) ||
|
||||
usesOtherRegistersWhileEvaluating(arg.args[2]) || usesOtherRegistersWhileEvaluating(arg.args[3])
|
||||
return !arg.isSimple()
|
||||
}
|
||||
is PtAddressOf -> false
|
||||
|
||||
@@ -653,6 +653,10 @@ internal class AssignmentAsmGen(
|
||||
else -> throw AssemblyError("str return value type mismatch with target")
|
||||
}
|
||||
}
|
||||
returnDt== BaseDataType.LONG -> {
|
||||
// longs are in R0:R1 (r0=lsw, r1=msw)
|
||||
assignRegisterLong(target, RegisterOrPair.R0, RegisterOrPair.R1)
|
||||
}
|
||||
returnDt==BaseDataType.FLOAT -> {
|
||||
// float result from function sits in FAC1
|
||||
assignFAC1float(target)
|
||||
@@ -3506,6 +3510,29 @@ $endLabel""")
|
||||
}
|
||||
}
|
||||
|
||||
internal fun assignRegisterLong(target: AsmAssignTarget, lsw: RegisterOrPair, msw: RegisterOrPair) {
|
||||
when(target.kind) {
|
||||
TargetStorageKind.VARIABLE -> {
|
||||
asmgen.out("""
|
||||
lda cx16.r0L
|
||||
sta ${target.asmVarname}
|
||||
lda cx16.r0H
|
||||
sta ${target.asmVarname}+1
|
||||
lda cx16.r1L
|
||||
sta ${target.asmVarname}+2
|
||||
lda cx16.r1H
|
||||
sta ${target.asmVarname}+3""")
|
||||
}
|
||||
TargetStorageKind.ARRAY -> {
|
||||
TODO("assign 32 bits int in R0:R1 into array ${target.position}")
|
||||
}
|
||||
TargetStorageKind.MEMORY -> throw AssemblyError("memory is bytes not long ${target.position}")
|
||||
TargetStorageKind.REGISTER -> TODO("32 bits register assign? (we have no 32 bits registers right now) ${target.position}")
|
||||
TargetStorageKind.POINTER -> throw AssemblyError("can't assign long to pointer, pointers are 16 bits ${target.position}")
|
||||
TargetStorageKind.VOID -> { /* do nothing */ }
|
||||
}
|
||||
}
|
||||
|
||||
internal fun assignRegisterByte(target: AsmAssignTarget, register: CpuRegister, signed: Boolean, extendWord: Boolean) {
|
||||
val assignAsWord = target.datatype.isWord
|
||||
|
||||
|
||||
@@ -40,6 +40,7 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
"pokef" -> funcPoke(call, IRDataType.FLOAT)
|
||||
"pokemon" -> funcPokemon(call)
|
||||
"mkword" -> funcMkword(call)
|
||||
"mklong", "mklong2" -> funcMklong(call)
|
||||
"clamp__byte", "clamp__ubyte", "clamp__word", "clamp__uword" -> funcClamp(call)
|
||||
"min__byte", "min__ubyte", "min__word", "min__uword" -> funcMin(call)
|
||||
"max__byte", "max__ubyte", "max__word", "max__uword" -> funcMax(call)
|
||||
@@ -283,6 +284,52 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
return ExpressionCodeResult(result, IRDataType.WORD, resultReg, -1)
|
||||
}
|
||||
|
||||
private fun funcMklong(call: PtBuiltinFunctionCall): ExpressionCodeResult {
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
val resultReg = codeGen.registers.next(IRDataType.LONG)
|
||||
if(call.args.size==2) {
|
||||
// mklong2(word, word)
|
||||
if((call.args[0] as? PtNumber)?.number == 0.0) {
|
||||
// msw is 0, use EXT
|
||||
val lswTr = exprGen.translateExpression(call.args[1])
|
||||
addToResult(result, lswTr, lswTr.resultReg, -1)
|
||||
addInstr(result, IRInstruction(Opcode.EXT, IRDataType.WORD, reg1=resultReg, reg2 = lswTr.resultReg), null)
|
||||
} else {
|
||||
val mswTr = exprGen.translateExpression(call.args[0])
|
||||
addToResult(result, mswTr, mswTr.resultReg, -1)
|
||||
val lswTr = exprGen.translateExpression(call.args[1])
|
||||
addToResult(result, lswTr, lswTr.resultReg, -1)
|
||||
addInstr(result, IRInstruction(Opcode.CONCAT, IRDataType.WORD, reg1=resultReg, reg2 = mswTr.resultReg, reg3 = lswTr.resultReg), null)
|
||||
}
|
||||
} else {
|
||||
// mklong(msb, b3, b2, lsb)
|
||||
if((call.args[0] as? PtNumber)?.number == 0.0 && (call.args[1] as? PtNumber)?.number == 0.0 && (call.args[2] as? PtNumber)?.number == 0.0) {
|
||||
// use EXT.b + EXT.w
|
||||
val lsbTr = exprGen.translateExpression(call.args[3])
|
||||
addToResult(result, lsbTr, lsbTr.resultReg, -1)
|
||||
val wordReg = codeGen.registers.next(IRDataType.WORD)
|
||||
addInstr(result, IRInstruction(Opcode.EXT, IRDataType.BYTE, reg1=wordReg, reg2 = lsbTr.resultReg), null)
|
||||
addInstr(result, IRInstruction(Opcode.EXT, IRDataType.WORD, reg1=resultReg, reg2 = wordReg), null)
|
||||
} else {
|
||||
val msbTr = exprGen.translateExpression(call.args[0])
|
||||
val b2Tr = exprGen.translateExpression(call.args[1])
|
||||
val b1Tr = exprGen.translateExpression(call.args[2])
|
||||
val lsbTr = exprGen.translateExpression(call.args[3])
|
||||
addToResult(result, msbTr, msbTr.resultReg, -1)
|
||||
addToResult(result, b2Tr, b2Tr.resultReg, -1)
|
||||
addToResult(result, b1Tr, b1Tr.resultReg, -1)
|
||||
addToResult(result, lsbTr, lsbTr.resultReg, -1)
|
||||
val lswReg = codeGen.registers.next(IRDataType.WORD)
|
||||
val mswReg = codeGen.registers.next(IRDataType.WORD)
|
||||
addInstr(result, IRInstruction(Opcode.CONCAT, IRDataType.BYTE, reg1=mswReg, reg2 = msbTr.resultReg, reg3 = b2Tr.resultReg), null)
|
||||
addInstr(result, IRInstruction(Opcode.CONCAT, IRDataType.BYTE, reg1=lswReg, reg2 = b1Tr.resultReg, reg3 = lsbTr.resultReg), null)
|
||||
addInstr(result, IRInstruction(Opcode.CONCAT, IRDataType.WORD, reg1=resultReg, reg2 = mswReg, reg3 = lswReg), null)
|
||||
}
|
||||
|
||||
}
|
||||
return ExpressionCodeResult(result, IRDataType.LONG, resultReg, -1)
|
||||
}
|
||||
|
||||
private fun funcClamp(call: PtBuiltinFunctionCall): ExpressionCodeResult {
|
||||
val result = mutableListOf<IRCodeChunkBase>()
|
||||
val type = irType(call.type)
|
||||
|
||||
@@ -26,6 +26,8 @@ internal val constEvaluatorsForBuiltinFuncs: Map<String, ConstExpressionCaller>
|
||||
"msb" to { a, p, prg -> oneIntArgOutputInt(a, p, prg, true) { x: Int -> (x ushr 8 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,
|
||||
"mklong2" to ::builtinMklong,
|
||||
"clamp__ubyte" to ::builtinClampUByte,
|
||||
"clamp__byte" to ::builtinClampByte,
|
||||
"clamp__uword" to ::builtinClampUWord,
|
||||
@@ -203,6 +205,29 @@ private fun builtinMkword(args: List<Expression>, position: Position, program: P
|
||||
return NumericLiteral(BaseDataType.UWORD, result.toDouble(), position)
|
||||
}
|
||||
|
||||
private fun builtinMklong(args: List<Expression>, position: Position, program: Program): NumericLiteral {
|
||||
when(args.size) {
|
||||
2 -> {
|
||||
val constMsw = args[0].constValue(program) ?: throw NotConstArgumentException()
|
||||
val constLsw = args[1].constValue(program) ?: throw NotConstArgumentException()
|
||||
val result = (constMsw.number.toInt() shl 16) or constLsw.number.toInt()
|
||||
return NumericLiteral(BaseDataType.LONG, result.toDouble(), position)
|
||||
}
|
||||
4 -> {
|
||||
val constMsb = args[0].constValue(program) ?: throw NotConstArgumentException()
|
||||
val constB2 = args[1].constValue(program) ?: throw NotConstArgumentException()
|
||||
val constB1 = args[2].constValue(program) ?: throw NotConstArgumentException()
|
||||
val constLsb = args[3].constValue(program) ?: throw NotConstArgumentException()
|
||||
val result = (constMsb.number.toInt() shl 24) or
|
||||
(constB2.number.toInt() shl 16) or
|
||||
(constB1.number.toInt() shl 8) or
|
||||
constLsb.number.toInt()
|
||||
return NumericLiteral(BaseDataType.LONG, result.toDouble(), position)
|
||||
}
|
||||
else -> throw SyntaxError("mkword requires msw and lsw, or msb,b2,b1,lsb arguments", position)
|
||||
}
|
||||
}
|
||||
|
||||
private fun builtinSgn(args: List<Expression>, position: Position, program: Program): NumericLiteral {
|
||||
if (args.size != 1)
|
||||
throw SyntaxError("sgn requires one argument", position)
|
||||
|
||||
@@ -172,7 +172,7 @@ private fun integrateDefers(subdefers: Map<PtSub, List<PtDefer>>, program: PtPro
|
||||
is PtAddressOf -> value.arrayIndexExpr == null || notComplex(value.arrayIndexExpr!!)
|
||||
is PtBuiltinFunctionCall -> {
|
||||
when (value.name) {
|
||||
in arrayOf("msb", "lsb", "msw", "lsw", "mkword", "set_carry", "set_irqd", "clear_carry", "clear_irqd") -> value.args.all { notComplex(it) }
|
||||
in arrayOf("msb", "lsb", "msw", "lsw", "mkword", "mklong", "mklong2", "set_carry", "set_irqd", "clear_carry", "clear_irqd") -> value.args.all { notComplex(it) }
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1498,7 +1498,7 @@ class FunctionCallExpression(override var target: IdentifierReference,
|
||||
|
||||
override fun copy() = FunctionCallExpression(target.copy(), args.map { it.copy() }.toMutableList(), position)
|
||||
override val isSimple = when (target.nameInSource.singleOrNull()) {
|
||||
in arrayOf("msb", "lsb", "mkword", "set_carry", "set_irqd", "clear_carry", "clear_irqd") -> this.args.all { it.isSimple }
|
||||
in arrayOf("msb", "lsb", "mkword", "mklong", "mklong2", "set_carry", "set_irqd", "clear_carry", "clear_irqd") -> this.args.all { it.isSimple }
|
||||
else -> false
|
||||
}
|
||||
override fun replaceChildNode(node: Node, replacement: Node) {
|
||||
|
||||
+60
-45
@@ -14,53 +14,68 @@ main {
|
||||
; }
|
||||
|
||||
sub start() {
|
||||
long[] array = [-1999888777, -999, 42, 0, 77, 123456, 999999999]
|
||||
long xx
|
||||
for xx in array {
|
||||
txt.print_uw(msw(xx))
|
||||
txt.spc()
|
||||
txt.print_uw(lsw(xx))
|
||||
txt.nl()
|
||||
}
|
||||
txt.print_l(mklong2($a000,$bbbb))
|
||||
txt.spc()
|
||||
txt.print_l(mklong(9,8,7,6))
|
||||
txt.nl()
|
||||
cx16.r8 = $a000
|
||||
cx16.r9 = $bbbb
|
||||
cx16.r2L = 9
|
||||
cx16.r3L = 8
|
||||
cx16.r4L = 7
|
||||
cx16.r5L = 6
|
||||
txt.print_l(mklong2(cx16.r8, cx16.r9))
|
||||
txt.spc()
|
||||
txt.print_l(mklong(cx16.r2L,cx16.r3L,cx16.r4L,cx16.r5L))
|
||||
txt.nl()
|
||||
array[2] = 0
|
||||
array[3] = 222222222
|
||||
array[4] = bignum
|
||||
array[5]++
|
||||
array[6]--
|
||||
|
||||
txt.print_l(-1999888777)
|
||||
txt.spc()
|
||||
txt.print_l(-999)
|
||||
txt.spc()
|
||||
txt.print_l(-42)
|
||||
txt.spc()
|
||||
txt.print_l(0)
|
||||
txt.spc()
|
||||
txt.print_l(bignum)
|
||||
txt.nl()
|
||||
txt.print_l(bignum2)
|
||||
txt.nl()
|
||||
txt.print_l(-bignum2)
|
||||
txt.nl()
|
||||
bignum2 = -bignum2
|
||||
bignum2++
|
||||
bignum2++
|
||||
txt.print_l(bignum2)
|
||||
txt.nl()
|
||||
bignum2--
|
||||
bignum2--
|
||||
txt.print_l(bignum2)
|
||||
txt.spc()
|
||||
txt.print_l(bignum)
|
||||
txt.nl()
|
||||
txt.nl()
|
||||
bignum2 += bignum
|
||||
txt.print_l(bignum2)
|
||||
txt.nl()
|
||||
bignum2 -= bignum
|
||||
txt.print_l(bignum2)
|
||||
txt.nl()
|
||||
; long[] array = [-1999888777, -999, 42, 0, 77, 123456, 999999999]
|
||||
; long xx
|
||||
; for xx in array {
|
||||
; txt.print_uw(msw(xx))
|
||||
; txt.spc()
|
||||
; txt.print_uw(lsw(xx))
|
||||
; txt.nl()
|
||||
; }
|
||||
; txt.nl()
|
||||
; array[2] = 0
|
||||
; array[3] = 222222222
|
||||
; array[4] = bignum
|
||||
; array[5]++
|
||||
; array[6]--
|
||||
;
|
||||
; txt.print_l(-1999888777)
|
||||
; txt.spc()
|
||||
; txt.print_l(-999)
|
||||
; txt.spc()
|
||||
; txt.print_l(-42)
|
||||
; txt.spc()
|
||||
; txt.print_l(0)
|
||||
; txt.spc()
|
||||
; txt.print_l(bignum)
|
||||
; txt.nl()
|
||||
; txt.print_l(bignum2)
|
||||
; txt.nl()
|
||||
; txt.print_l(-bignum2)
|
||||
; txt.nl()
|
||||
; bignum2 = -bignum2
|
||||
; bignum2++
|
||||
; bignum2++
|
||||
; txt.print_l(bignum2)
|
||||
; txt.nl()
|
||||
; bignum2--
|
||||
; bignum2--
|
||||
; txt.print_l(bignum2)
|
||||
; txt.spc()
|
||||
; txt.print_l(bignum)
|
||||
; txt.nl()
|
||||
; txt.nl()
|
||||
; bignum2 += bignum
|
||||
; txt.print_l(bignum2)
|
||||
; txt.nl()
|
||||
; bignum2 -= bignum
|
||||
; txt.print_l(bignum2)
|
||||
; txt.nl()
|
||||
|
||||
; ^^Node test = []
|
||||
;
|
||||
|
||||
@@ -124,7 +124,7 @@ sealed class PtExpression(val type: DataType, position: Position) : PtNode(posit
|
||||
is PtBinaryExpression -> false
|
||||
is PtBuiltinFunctionCall -> {
|
||||
when (name) {
|
||||
in arrayOf("msb", "lsb", "msw", "lsw", "mkword", "set_carry", "set_irqd", "clear_carry", "clear_irqd") -> this.args.all { it.isSimple() }
|
||||
in arrayOf("msb", "lsb", "msw", "lsw", "mkword", "mklong", "mklong2", "set_carry", "set_irqd", "clear_carry", "clear_irqd") -> this.args.all { it.isSimple() }
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user