implement missing long typecasts

This commit is contained in:
Irmen de Jong
2025-10-07 17:43:28 +02:00
parent 0f564b301d
commit 396fcbc927
6 changed files with 103 additions and 27 deletions

View File

@@ -1620,7 +1620,17 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
else -> throw AssemblyError("invalid reg")
}
} else {
TODO("msw(expression) ${fcall.position} - use a temporary variable for now")
asmgen.assignExpressionToRegister(arg, RegisterOrPair.R0R1_32, true)
when(resultRegister) {
RegisterOrPair.AX -> asmgen.out(" lda cx16.r1 | ldx cx16.r1+1")
null, RegisterOrPair.AY -> asmgen.out(" lda cx16.r1 | ldy cx16.r1+1")
RegisterOrPair.XY -> asmgen.out(" ldx cx16.r1 | ldy cx16.r1+1")
in Cx16VirtualRegisters -> {
val regname = resultRegister.name.lowercase()
asmgen.out(" lda cx16.r1 | sta cx16.$regname | lda cx16.r1+1 | sta cx16.$regname+1")
}
else -> throw AssemblyError("invalid reg")
}
}
}
@@ -1643,7 +1653,19 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
else -> throw AssemblyError("invalid reg")
}
} else {
TODO("lsw(expression) ${fcall.position} - use a temporary variable for now")
asmgen.assignExpressionToRegister(arg, RegisterOrPair.R0R1_32, true)
when(resultRegister) {
RegisterOrPair.AX -> asmgen.out(" lda cx16.r0 | ldx cx16.r0+1")
null, RegisterOrPair.AY -> asmgen.out(" lda cx16.r0 | ldy cx16.r0+1")
RegisterOrPair.XY -> asmgen.out(" ldx cx16.r0 | ldy cx16.r0+1")
in Cx16VirtualRegisters -> {
if(resultRegister!=RegisterOrPair.R0) {
val regname = resultRegister.name.lowercase()
asmgen.out(" lda cx16.r0 | sta cx16.$regname | lda cx16.r0+1 | sta cx16.$regname+1")
}
}
else -> throw AssemblyError("invalid reg")
}
}
}

View File

@@ -2455,7 +2455,7 @@ $endLabel""")
is PtArrayIndexer -> {
if(targetDt.isByte && valueDt.isWord) {
// just assign the lsb from the array value
return assignCastViaLsbFunc(value, target)
return assignCastWordViaLsbFunc(value, target)
} else if(targetDt.isBool && valueDt.isWord) {
return assignWordToBool(value, target)
}
@@ -2513,7 +2513,7 @@ $endLabel""")
if(parentTc!=null && parentTc.type.isUnsignedWord) {
// typecast a word value to ubyte and directly back to uword
// generate code for lsb(value) here instead of the ubyte typecast
return assignCastViaLsbFunc(value, target)
return assignCastWordViaLsbFunc(value, target)
}
}
@@ -2545,7 +2545,7 @@ $endLabel""")
else
// cast an uword to a byte register, do this via lsb(value)
// generate code for lsb(value) here instead of the ubyte typecast
assignCastViaLsbFunc(value, target)
assignCastWordViaLsbFunc(value, target)
}
RegisterOrPair.AX,
RegisterOrPair.AY,
@@ -2569,7 +2569,7 @@ $endLabel""")
if(!(valueDt isAssignableTo targetDt)) {
return if(valueDt.isWord && targetDt.isByte) {
// word to byte, just take the lsb
assignCastViaLsbFunc(value, target)
assignCastWordViaLsbFunc(value, target)
} else if(valueDt.isWord && targetDt.isBool) {
// word to bool
assignWordToBool(value, target)
@@ -2582,6 +2582,12 @@ $endLabel""")
} else if(valueDt.isByteOrBool && targetDt.isWord) {
// byte to word, just assign
assignExpressionToRegister(value, target.register!!, valueDt.isSigned)
} else if(valueDt.isLong && targetDt.isByte) {
// long to byte, just take the lsb
assignCastLongToByte(value, target)
} else if(valueDt.isLong && targetDt.isWord) {
// long to word, just take the lsw
assignCastViaLswFunc(value, target)
} else
throw AssemblyError("can't cast $valueDt to $targetDt, this should have been checked in the astchecker")
}
@@ -2664,7 +2670,24 @@ $endLabel""")
asmgen.assignExpressionTo(origTypeCastExpression, target)
}
private fun assignCastViaLsbFunc(value: PtExpression, target: AsmAssignTarget) {
private fun assignCastLongToByte(value: PtExpression, target: AsmAssignTarget) {
// long to byte, can't use lsb() because that only works on words
when(value) {
is PtIdentifier -> {
val longvar = asmgen.asmVariableName(value)
asmgen.out(" lda $longvar")
assignRegisterByte(target, CpuRegister.A, true, false)
}
is PtNumber -> throw AssemblyError("casting a long number to byte should have been const-folded away ${value.position}")
else -> {
assignExpressionToRegister(value, RegisterOrPair.R0R1_32, true)
asmgen.out(" lda cx16.r0")
assignRegisterByte(target, CpuRegister.A, true, false)
}
}
}
private fun assignCastWordViaLsbFunc(value: PtExpression, target: AsmAssignTarget) {
val lsb = PtBuiltinFunctionCall("lsb", false, true, DataType.UBYTE, value.position)
lsb.parent = value.parent
lsb.add(value)
@@ -2673,6 +2696,15 @@ $endLabel""")
translateNormalAssignment(assign, value.definingISub())
}
private fun assignCastViaLswFunc(value: PtExpression, target: AsmAssignTarget) {
val lsb = PtBuiltinFunctionCall("lsw", false, true, DataType.UWORD, value.position)
lsb.parent = value.parent
lsb.add(value)
val src = AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, DataType.UWORD, expression = lsb)
val assign = AsmAssignment(src, listOf(target), program.memsizer, value.position)
translateNormalAssignment(assign, value.definingISub())
}
private fun assignWordToBool(value: PtExpression, target: AsmAssignTarget) {
assignExpressionToRegister(value, RegisterOrPair.AY, false)
asmgen.out("""