remove eval stack assignment source and targets

This commit is contained in:
Irmen de Jong 2023-07-15 11:37:36 +02:00
parent 84925ab69c
commit 708e296774
10 changed files with 240 additions and 722 deletions

View File

@ -207,8 +207,7 @@ class AsmGen6502Internal (
private val postincrdecrAsmGen = PostIncrDecrAsmGen(program, this)
private val functioncallAsmGen = FunctionCallAsmGen(program, this)
private val programGen = ProgramAndVarsGen(program, options, errors, symbolTable, functioncallAsmGen, this, allocator, zeropage)
private val assignmentAsmGen = AssignmentAsmGen(program, symbolTable, this, allocator)
private val expressionsAsmGen = ExpressionsAsmGen(program, this, allocator)
private val assignmentAsmGen = AssignmentAsmGen(program, this, allocator)
private val builtinFunctionsAsmGen = BuiltinFunctionsAsmGen(program, this, assignmentAsmGen)
fun compileToAssembly(): IAssemblyProgram? {
@ -581,8 +580,8 @@ class AsmGen6502Internal (
}
}
internal fun translateBuiltinFunctionCallExpression(bfc: PtBuiltinFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?): DataType? =
builtinFunctionsAsmGen.translateFunctioncallExpression(bfc, resultToStack, resultRegister)
internal fun translateBuiltinFunctionCallExpression(bfc: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?): DataType? =
builtinFunctionsAsmGen.translateFunctioncallExpression(bfc, resultRegister)
internal fun translateFunctionCall(functionCallExpr: PtFunctionCall) =
functioncallAsmGen.translateFunctionCall(functionCallExpr)
@ -1081,20 +1080,6 @@ $repeatLabel""")
}
}
internal fun signExtendStackLsb(valueDt: DataType) {
// sign extend signed byte on stack to signed word on stack
when(valueDt) {
DataType.UBYTE -> {
if(isTargetCpu(CpuType.CPU65c02))
out(" stz P8ESTACK_HI+1,x")
else
out(" lda #0 | sta P8ESTACK_HI+1,x")
}
DataType.BYTE -> out(" jsr prog8_lib.sign_extend_stack_byte")
else -> throw AssemblyError("need byte type")
}
}
internal fun signExtendVariableLsb(asmvar: String, valueDt: DataType) {
// sign extend signed byte in a var to a full word in that variable
when(valueDt) {
@ -1723,7 +1708,7 @@ $repeatLabel""")
}
else if (left is PtMemoryByte) {
return if(rightConstVal.number.toInt()!=0) {
translateDirectMemReadExpressionToRegAorStack(left, false)
translateDirectMemReadExpressionToRegA(left)
code("#${rightConstVal.number.toInt()}")
}
else
@ -1870,7 +1855,7 @@ $repeatLabel""")
out(" beq $jumpIfFalseLabel")
}
else if (left is PtMemoryByte) {
translateDirectMemReadExpressionToRegAorStack(left, false)
translateDirectMemReadExpressionToRegA(left)
return if(rightConstVal.number.toInt()!=0)
code("#${rightConstVal.number.toInt()}")
else
@ -2031,7 +2016,7 @@ $repeatLabel""")
out(" bne $jumpIfFalseLabel")
}
else if (left is PtMemoryByte) {
translateDirectMemReadExpressionToRegAorStack(left, false)
translateDirectMemReadExpressionToRegA(left)
return if(rightConstVal.number.toInt()!=0)
code("#${rightConstVal.number.toInt()}")
else
@ -2195,7 +2180,7 @@ $repeatLabel""")
}
else if (left is PtMemoryByte) {
if(rightConstVal.number.toInt()!=0) {
translateDirectMemReadExpressionToRegAorStack(left, false)
translateDirectMemReadExpressionToRegA(left)
code("#${rightConstVal.number.toInt()}")
}
return
@ -2358,7 +2343,7 @@ $repeatLabel""")
out(" bne $jumpIfFalseLabel")
}
else if (left is PtMemoryByte) {
translateDirectMemReadExpressionToRegAorStack(left, false)
translateDirectMemReadExpressionToRegA(left)
return if(rightConstVal.number.toInt()!=0)
code("#${rightConstVal.number.toInt()}")
else
@ -2404,7 +2389,7 @@ $repeatLabel""")
out(" beq $jumpIfFalseLabel")
}
else if (left is PtMemoryByte) {
translateDirectMemReadExpressionToRegAorStack(left, false)
translateDirectMemReadExpressionToRegA(left)
return if(rightConstVal.number.toInt()!=0)
code("#${rightConstVal.number.toInt()}")
else
@ -2860,22 +2845,14 @@ $repeatLabel""")
+""")
}
internal fun translateDirectMemReadExpressionToRegAorStack(expr: PtMemoryByte, pushResultOnEstack: Boolean) {
internal fun translateDirectMemReadExpressionToRegA(expr: PtMemoryByte) {
fun assignViaExprEval() {
assignExpressionToVariable(expr.address, "P8ZP_SCRATCH_W2", DataType.UWORD)
if (isTargetCpu(CpuType.CPU65c02)) {
if (pushResultOnEstack) {
out(" lda (P8ZP_SCRATCH_W2) | dex | sta P8ESTACK_LO+1,x")
} else {
out(" lda (P8ZP_SCRATCH_W2)")
}
out(" lda (P8ZP_SCRATCH_W2)")
} else {
if (pushResultOnEstack) {
out(" ldy #0 | lda (P8ZP_SCRATCH_W2),y | dex | sta P8ESTACK_LO+1,x")
} else {
out(" ldy #0 | lda (P8ZP_SCRATCH_W2),y")
}
out(" ldy #0 | lda (P8ZP_SCRATCH_W2),y")
}
}
@ -2883,21 +2860,14 @@ $repeatLabel""")
is PtNumber -> {
val address = (expr.address as PtNumber).number.toInt()
out(" lda ${address.toHex()}")
if(pushResultOnEstack)
out(" sta P8ESTACK_LO,x | dex")
}
is PtIdentifier -> {
// the identifier is a pointer variable, so read the value from the address in it
loadByteFromPointerIntoA(expr.address as PtIdentifier)
if(pushResultOnEstack)
out(" sta P8ESTACK_LO,x | dex")
}
is PtBinaryExpression -> {
val addrExpr = expr.address as PtBinaryExpression
if(tryOptimizedPointerAccessWithA(addrExpr, addrExpr.operator, false)) {
if(pushResultOnEstack)
out(" sta P8ESTACK_LO,x | dex")
} else {
if(!tryOptimizedPointerAccessWithA(addrExpr, addrExpr.operator, false)) {
assignViaExprEval()
}
}

View File

@ -15,14 +15,7 @@ internal fun optimizeAssembly(lines: MutableList<String>, machine: IMachineDefin
var linesByFour = getLinesBy(lines, 4)
var mods = optimizeUselessStackByteWrites(linesByFour)
if(mods.isNotEmpty()) {
apply(mods, lines)
linesByFour = getLinesBy(lines, 4)
numberOfOptimizations++
}
mods = optimizeIncDec(linesByFour)
var mods = optimizeIncDec(linesByFour)
if(mods.isNotEmpty()) {
apply(mods, lines)
linesByFour = getLinesBy(lines, 4)
@ -107,31 +100,14 @@ private fun optimizeCmpSequence(linesByFour: List<List<IndexedValue<String>>>):
// beq check_prog8_s73choice_33
// the repeated lda can be removed
val mods = mutableListOf<Modification>()
for(lines in linesByFour) {
if(lines[0].value.trim()=="lda P8ESTACK_LO+1,x" &&
lines[1].value.trim().startsWith("cmp ") &&
lines[2].value.trim().startsWith("beq ") &&
lines[3].value.trim()=="lda P8ESTACK_LO+1,x") {
mods.add(Modification(lines[3].index, true, null)) // remove the second lda
}
}
return mods
}
private fun optimizeUselessStackByteWrites(linesByFour: List<List<IndexedValue<String>>>): List<Modification> {
// sta on stack, dex, inx, lda from stack -> eliminate this useless stack byte write
// this is a lot harder for word values because the instruction sequence varies.
val mods = mutableListOf<Modification>()
for(lines in linesByFour) {
if(lines[0].value.trim()=="sta P8ESTACK_LO,x" &&
lines[1].value.trim()=="dex" &&
lines[2].value.trim()=="inx" &&
lines[3].value.trim()=="lda P8ESTACK_LO,x") {
mods.add(Modification(lines[1].index, true, null))
mods.add(Modification(lines[2].index, true, null))
mods.add(Modification(lines[3].index, true, null))
}
}
// for(lines in linesByFour) {
// if(lines[0].value.trim()=="lda P8ESTACK_LO+1,x" &&
// lines[1].value.trim().startsWith("cmp ") &&
// lines[2].value.trim().startsWith("beq ") &&
// lines[3].value.trim()=="lda P8ESTACK_LO+1,x") {
// mods.add(Modification(lines[3].index, true, null)) // remove the second lda
// }
// }
return mods
}

View File

@ -10,34 +10,31 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
private val asmgen: AsmGen6502Internal,
private val assignAsmGen: AssignmentAsmGen) {
internal fun translateFunctioncallExpression(fcall: PtBuiltinFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?): DataType? {
return translateFunctioncall(fcall, discardResult = false, resultToStack = resultToStack, resultRegister = resultRegister)
internal fun translateFunctioncallExpression(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?): DataType? {
return translateFunctioncall(fcall, discardResult = false, resultRegister = resultRegister)
}
internal fun translateFunctioncallStatement(fcall: PtBuiltinFunctionCall) {
translateFunctioncall(fcall, discardResult = true, resultToStack = false, resultRegister = null)
translateFunctioncall(fcall, discardResult = true, resultRegister = null)
}
private fun translateFunctioncall(fcall: PtBuiltinFunctionCall, discardResult: Boolean, resultToStack: Boolean, resultRegister: RegisterOrPair?): DataType? {
private fun translateFunctioncall(fcall: PtBuiltinFunctionCall, discardResult: Boolean, resultRegister: RegisterOrPair?): DataType? {
if (discardResult && fcall.hasNoSideEffects)
return null // can just ignore the whole function call altogether
if(discardResult && resultToStack)
throw AssemblyError("cannot both discard the result AND put it onto stack")
val sscope = fcall.definingISub()
when (fcall.name) {
"msb" -> funcMsb(fcall, resultToStack, resultRegister)
"lsb" -> funcLsb(fcall, resultToStack, resultRegister)
"mkword" -> funcMkword(fcall, resultToStack, resultRegister)
"clamp__byte", "clamp__ubyte", "clamp__word", "clamp__uword" -> funcClamp(fcall, resultToStack, resultRegister)
"min__byte", "min__ubyte", "min__word", "min__uword" -> funcMin(fcall, resultToStack, resultRegister)
"max__byte", "max__ubyte", "max__word", "max__uword" -> funcMax(fcall, resultToStack, resultRegister)
"abs__byte", "abs__word", "abs__float" -> funcAbs(fcall, resultToStack, resultRegister, sscope)
"any", "all" -> funcAnyAll(fcall, resultToStack, resultRegister, sscope)
"sgn" -> funcSgn(fcall, resultToStack, resultRegister, sscope)
"sqrt__ubyte", "sqrt__uword", "sqrt__float" -> funcSqrt(fcall, resultToStack, resultRegister, sscope)
"msb" -> funcMsb(fcall, resultRegister)
"lsb" -> funcLsb(fcall, resultRegister)
"mkword" -> funcMkword(fcall, resultRegister)
"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)
"abs__byte", "abs__word", "abs__float" -> funcAbs(fcall, resultRegister, sscope)
"any", "all" -> funcAnyAll(fcall, resultRegister, sscope)
"sgn" -> funcSgn(fcall, resultRegister, sscope)
"sqrt__ubyte", "sqrt__uword", "sqrt__float" -> funcSqrt(fcall, resultRegister, sscope)
"divmod__ubyte" -> funcDivmod(fcall)
"divmod__uword" -> funcDivmodW(fcall)
"rol" -> funcRol(fcall)
@ -46,8 +43,8 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
"ror2" -> funcRor2(fcall)
"sort" -> funcSort(fcall)
"reverse" -> funcReverse(fcall)
"memory" -> funcMemory(fcall, discardResult, resultToStack, resultRegister)
"peekw" -> funcPeekW(fcall, resultToStack, resultRegister)
"memory" -> funcMemory(fcall, discardResult, resultRegister)
"peekw" -> funcPeekW(fcall, resultRegister)
"peek" -> throw AssemblyError("peek() should have been replaced by @()")
"pokew" -> funcPokeW(fcall)
"pokemon" -> { /* meme function */ }
@ -76,7 +73,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
"rrestorex" -> funcRrestoreX()
"cmp" -> funcCmp(fcall)
"callfar" -> funcCallFar(fcall)
"prog8_lib_stringcompare" -> funcStringCompare(fcall, resultToStack)
"prog8_lib_stringcompare" -> funcStringCompare(fcall)
else -> throw AssemblyError("missing asmgen for builtin func ${fcall.name}")
}
@ -115,11 +112,9 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
sty $remainderVar+1""")
}
private fun funcStringCompare(fcall: PtBuiltinFunctionCall, resultToStack: Boolean) {
private fun funcStringCompare(fcall: PtBuiltinFunctionCall) {
asmgen.assignWordOperandsToAYAndVar(fcall.args[0], fcall.args[1], "P8ZP_SCRATCH_W2")
asmgen.out(" jsr prog8_lib.strcmp_mem")
if(resultToStack)
asmgen.out(" sta P8ESTACK_LO,x | dex")
}
private fun funcRsave() {
@ -253,7 +248,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
}
}
private fun funcMemory(fcall: PtBuiltinFunctionCall, discardResult: Boolean, resultToStack: Boolean, resultRegister: RegisterOrPair?) {
private fun funcMemory(fcall: PtBuiltinFunctionCall, discardResult: Boolean, resultRegister: RegisterOrPair?) {
if(discardResult)
throw AssemblyError("should not discard result of memory allocation at $fcall")
val name = (fcall.args[0] as PtString).value
@ -263,41 +258,25 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
addressOf.add(slabname)
addressOf.parent = fcall
val src = AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, DataType.UWORD, expression = addressOf)
val target =
if(resultToStack)
AsmAssignTarget(TargetStorageKind.STACK, asmgen, DataType.UWORD, null, fcall.position)
else
AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, false, fcall.position, null, asmgen)
val target = AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, false, fcall.position, null, asmgen)
val assign = AsmAssignment(src, target, program.memsizer, fcall.position)
asmgen.translateNormalAssignment(assign, fcall.definingISub())
}
private fun funcSqrt(fcall: PtBuiltinFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?, scope: IPtSubroutine?) {
private fun funcSqrt(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?, scope: IPtSubroutine?) {
translateArguments(fcall, scope)
when(fcall.args[0].type) {
DataType.UBYTE -> {
if(resultToStack)
asmgen.out(" ldy #0 | jsr prog8_lib.func_sqrt16_stack")
else {
asmgen.out(" ldy #0 | jsr prog8_lib.func_sqrt16_into_A")
assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A, false)
}
asmgen.out(" ldy #0 | jsr prog8_lib.func_sqrt16_into_A")
assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A, false)
}
DataType.UWORD -> {
if(resultToStack)
asmgen.out(" jsr prog8_lib.func_sqrt16_stack")
else {
asmgen.out(" jsr prog8_lib.func_sqrt16_into_A")
assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A, false)
}
asmgen.out(" jsr prog8_lib.func_sqrt16_into_A")
assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A, false)
}
DataType.FLOAT -> {
asmgen.out(" jsr floats.func_sqrt_into_FAC1")
if(resultToStack)
assignAsmGen.assignFAC1float(AsmAssignTarget(TargetStorageKind.STACK, asmgen, DataType.FLOAT, scope, fcall.position))
else {
assignAsmGen.assignFAC1float(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.FAC1, true, fcall.position, scope, asmgen))
}
assignAsmGen.assignFAC1float(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.FAC1, true, fcall.position, scope, asmgen))
}
else -> throw AssemblyError("weird dt")
}
@ -633,88 +612,56 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
asmgen.assignExpressionToVariable(indexer.index, "prog8_lib.${operation}_array_u${dt}._arg_index", DataType.UBYTE)
}
private fun funcSgn(fcall: PtBuiltinFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?, scope: IPtSubroutine?) {
private fun funcSgn(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?, scope: IPtSubroutine?) {
translateArguments(fcall, scope)
val dt = fcall.args.single().type
if(resultToStack) {
when (dt) {
DataType.UBYTE -> asmgen.out(" jsr prog8_lib.func_sign_ub_stack")
DataType.BYTE -> asmgen.out(" jsr prog8_lib.func_sign_b_stack")
DataType.UWORD -> asmgen.out(" jsr prog8_lib.func_sign_uw_stack")
DataType.WORD -> asmgen.out(" jsr prog8_lib.func_sign_w_stack")
DataType.FLOAT -> asmgen.out(" jsr floats.func_sign_f_stack")
else -> throw AssemblyError("weird type $dt")
}
} else {
when (dt) {
DataType.UBYTE -> asmgen.out(" jsr prog8_lib.func_sign_ub_into_A")
DataType.BYTE -> asmgen.out(" jsr prog8_lib.func_sign_b_into_A")
DataType.UWORD -> asmgen.out(" jsr prog8_lib.func_sign_uw_into_A")
DataType.WORD -> asmgen.out(" jsr prog8_lib.func_sign_w_into_A")
DataType.FLOAT -> asmgen.out(" jsr floats.func_sign_f_into_A")
else -> throw AssemblyError("weird type $dt")
}
assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A, true)
when (dt) {
DataType.UBYTE -> asmgen.out(" jsr prog8_lib.func_sign_ub_into_A")
DataType.BYTE -> asmgen.out(" jsr prog8_lib.func_sign_b_into_A")
DataType.UWORD -> asmgen.out(" jsr prog8_lib.func_sign_uw_into_A")
DataType.WORD -> asmgen.out(" jsr prog8_lib.func_sign_w_into_A")
DataType.FLOAT -> asmgen.out(" jsr floats.func_sign_f_into_A")
else -> throw AssemblyError("weird type $dt")
}
assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A, true)
}
private fun funcAnyAll(fcall: PtBuiltinFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?, scope: IPtSubroutine?) {
private fun funcAnyAll(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?, scope: IPtSubroutine?) {
outputAddressAndLenghtOfArray(fcall.args[0])
val dt = fcall.args.single().type
if(resultToStack) {
when (dt) {
DataType.ARRAY_B, DataType.ARRAY_UB, DataType.STR -> asmgen.out(" jsr prog8_lib.func_${fcall.name}_b_stack")
DataType.ARRAY_UW, DataType.ARRAY_W -> asmgen.out(" jsr prog8_lib.func_${fcall.name}_w_stack")
DataType.ARRAY_F -> asmgen.out(" jsr floats.func_${fcall.name}_f_stack")
in SplitWordArrayTypes -> TODO("split word any/all")
else -> throw AssemblyError("weird type $dt")
}
} else {
when (dt) {
DataType.ARRAY_B, DataType.ARRAY_UB, DataType.STR -> asmgen.out(" jsr prog8_lib.func_${fcall.name}_b_into_A | ldy #0")
DataType.ARRAY_UW, DataType.ARRAY_W -> asmgen.out(" jsr prog8_lib.func_${fcall.name}_w_into_A | ldy #0")
DataType.ARRAY_F -> asmgen.out(" jsr floats.func_${fcall.name}_f_into_A | ldy #0")
in SplitWordArrayTypes -> TODO("split word any/all")
else -> throw AssemblyError("weird type $dt")
}
assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A, dt in SignedDatatypes)
when (dt) {
DataType.ARRAY_B, DataType.ARRAY_UB, DataType.STR -> asmgen.out(" jsr prog8_lib.func_${fcall.name}_b_into_A | ldy #0")
DataType.ARRAY_UW, DataType.ARRAY_W -> asmgen.out(" jsr prog8_lib.func_${fcall.name}_w_into_A | ldy #0")
DataType.ARRAY_F -> asmgen.out(" jsr floats.func_${fcall.name}_f_into_A | ldy #0")
in SplitWordArrayTypes -> TODO("split word any/all")
else -> throw AssemblyError("weird type $dt")
}
assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A, dt in SignedDatatypes)
}
private fun funcAbs(fcall: PtBuiltinFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?, scope: IPtSubroutine?) {
private fun funcAbs(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?, scope: IPtSubroutine?) {
translateArguments(fcall, scope)
val dt = fcall.args.single().type
if(resultToStack) {
when (dt) {
DataType.BYTE -> asmgen.out(" jsr prog8_lib.abs_b_stack")
DataType.WORD -> asmgen.out(" jsr prog8_lib.abs_w_stack")
else -> {
asmgen.out(" jsr floats.func_abs_f_into_FAC1")
assignAsmGen.assignFAC1float(AsmAssignTarget(TargetStorageKind.STACK, asmgen, DataType.FLOAT, scope, fcall.position))
}
when (dt) {
DataType.BYTE -> {
asmgen.out(" jsr prog8_lib.abs_b_into_A")
assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A,false)
}
} else {
when (dt) {
DataType.BYTE -> {
asmgen.out(" jsr prog8_lib.abs_b_into_A")
assignAsmGen.assignRegisterByte(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, false, fcall.position, scope, asmgen), CpuRegister.A,false)
}
DataType.WORD -> {
asmgen.out(" jsr prog8_lib.abs_w_into_AY")
assignAsmGen.assignRegisterpairWord(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, false, fcall.position, scope, asmgen), RegisterOrPair.AY)
}
DataType.FLOAT -> {
asmgen.out(" jsr floats.func_abs_f_into_FAC1")
assignAsmGen.assignFAC1float(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.FAC1, true, fcall.position, scope, asmgen))
}
DataType.UBYTE -> {
asmgen.assignRegister(RegisterOrPair.A, AsmAssignTarget.fromRegisters(resultRegister?:RegisterOrPair.A, false, fcall.position, scope, asmgen))
}
DataType.UWORD -> {
asmgen.assignRegister(RegisterOrPair.AY, AsmAssignTarget.fromRegisters(resultRegister?:RegisterOrPair.AY, false, fcall.position, scope, asmgen))
}
else -> throw AssemblyError("weird type")
DataType.WORD -> {
asmgen.out(" jsr prog8_lib.abs_w_into_AY")
assignAsmGen.assignRegisterpairWord(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, false, fcall.position, scope, asmgen), RegisterOrPair.AY)
}
DataType.FLOAT -> {
asmgen.out(" jsr floats.func_abs_f_into_FAC1")
assignAsmGen.assignFAC1float(AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.FAC1, true, fcall.position, scope, asmgen))
}
DataType.UBYTE -> {
asmgen.assignRegister(RegisterOrPair.A, AsmAssignTarget.fromRegisters(resultRegister?:RegisterOrPair.A, false, fcall.position, scope, asmgen))
}
DataType.UWORD -> {
asmgen.assignRegister(RegisterOrPair.AY, AsmAssignTarget.fromRegisters(resultRegister?:RegisterOrPair.AY, false, fcall.position, scope, asmgen))
}
else -> throw AssemblyError("weird type")
}
}
@ -779,7 +726,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
asmgen.out(" jsr prog8_lib.func_pokew")
}
private fun funcPeekW(fcall: PtBuiltinFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?) {
private fun funcPeekW(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?) {
fun fallback() {
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.AY)
asmgen.out(" jsr prog8_lib.func_peekw")
@ -830,23 +777,19 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
else -> fallback()
}
if(resultToStack){
asmgen.out(" sta P8ESTACK_LO,x | tya | sta P8ESTACK_HI,x | dex")
} else {
when(resultRegister ?: RegisterOrPair.AY) {
RegisterOrPair.AY -> {}
RegisterOrPair.AX -> asmgen.out(" sty P8ZP_SCRATCH_REG | ldx P8ZP_SCRATCH_REG")
RegisterOrPair.XY -> asmgen.out(" tax")
in Cx16VirtualRegisters -> asmgen.out(
" sta cx16.${
resultRegister.toString().lowercase()
} | sty cx16.${resultRegister.toString().lowercase()}+1")
else -> throw AssemblyError("invalid reg")
}
when(resultRegister ?: RegisterOrPair.AY) {
RegisterOrPair.AY -> {}
RegisterOrPair.AX -> asmgen.out(" sty P8ZP_SCRATCH_REG | ldx P8ZP_SCRATCH_REG")
RegisterOrPair.XY -> asmgen.out(" tax")
in Cx16VirtualRegisters -> asmgen.out(
" sta cx16.${
resultRegister.toString().lowercase()
} | sty cx16.${resultRegister.toString().lowercase()}+1")
else -> throw AssemblyError("invalid reg")
}
}
private fun funcClamp(fcall: PtBuiltinFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?) {
private fun funcClamp(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?) {
val signed = fcall.type in SignedDatatypes
when(fcall.type) {
in ByteDatatypes -> {
@ -854,30 +797,22 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
assignAsmGen.assignExpressionToVariable(fcall.args[2], "P8ZP_SCRATCH_W1+1", fcall.args[2].type) // maximum
assignAsmGen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.A, signed) // value
asmgen.out(" jsr prog8_lib.func_clamp_${fcall.type.toString().lowercase()}")
if(resultToStack) {
asmgen.out(" sta P8ESTACK_LO,x | dex")
} else {
val targetReg = AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, signed, fcall.position, fcall.definingISub(), asmgen)
assignAsmGen.assignRegisterByte(targetReg, CpuRegister.A, signed)
}
val targetReg = AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, signed, fcall.position, fcall.definingISub(), asmgen)
assignAsmGen.assignRegisterByte(targetReg, CpuRegister.A, signed)
}
in WordDatatypes -> {
assignAsmGen.assignExpressionToVariable(fcall.args[1], "P8ZP_SCRATCH_W1", fcall.args[1].type) // minimum
assignAsmGen.assignExpressionToVariable(fcall.args[2], "P8ZP_SCRATCH_W2", fcall.args[2].type) // maximum
assignAsmGen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.AY, signed) // value
asmgen.out(" jsr prog8_lib.func_clamp_${fcall.type.toString().lowercase()}")
if(resultToStack) {
asmgen.out(" sta P8ESTACK_LO,x | sty P8ESTACK_HI,x | dex")
} else {
val targetReg = AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, signed, fcall.position, fcall.definingISub(), asmgen)
assignAsmGen.assignRegisterpairWord(targetReg, RegisterOrPair.AY)
}
val targetReg = AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, signed, fcall.position, fcall.definingISub(), asmgen)
assignAsmGen.assignRegisterpairWord(targetReg, RegisterOrPair.AY)
}
else -> throw AssemblyError("invalid dt")
}
}
private fun funcMin(fcall: PtBuiltinFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?) {
private fun funcMin(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?) {
val signed = fcall.type in SignedDatatypes
if(fcall.type in ByteDatatypes) {
asmgen.assignExpressionToVariable(fcall.args[1], "P8ZP_SCRATCH_B1", fcall.type) // right
@ -887,12 +822,8 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
asmgen.out("""
lda P8ZP_SCRATCH_B1
+""")
if(resultToStack) {
asmgen.out(" sta P8ESTACK_LO,x | dex")
} else {
val targetReg = AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, signed, fcall.position, fcall.definingISub(), asmgen)
asmgen.assignRegister(RegisterOrPair.A, targetReg)
}
val targetReg = AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, signed, fcall.position, fcall.definingISub(), asmgen)
asmgen.assignRegister(RegisterOrPair.A, targetReg)
} else if(fcall.type in WordDatatypes) {
asmgen.assignExpressionToVariable(fcall.args[0], "P8ZP_SCRATCH_W1", fcall.type) // left
asmgen.assignExpressionToVariable(fcall.args[1], "P8ZP_SCRATCH_W2", fcall.type) // right
@ -928,18 +859,14 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
ldy P8ZP_SCRATCH_W1+1
+""")
}
if(resultToStack) {
asmgen.out(" sta P8ESTACK_LO,x | sty P8ESTACK_HI,x | dex")
} else {
val targetReg = AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, signed, fcall.position, fcall.definingISub(), asmgen)
asmgen.assignRegister(RegisterOrPair.AY, targetReg)
}
val targetReg = AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, signed, fcall.position, fcall.definingISub(), asmgen)
asmgen.assignRegister(RegisterOrPair.AY, targetReg)
} else {
throw AssemblyError("min float not supported")
}
}
private fun funcMax(fcall: PtBuiltinFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?) {
private fun funcMax(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?) {
val signed = fcall.type in SignedDatatypes
if(fcall.type in ByteDatatypes) {
asmgen.assignExpressionToVariable(fcall.args[0], "P8ZP_SCRATCH_B1", fcall.type) // left
@ -949,12 +876,8 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
asmgen.out("""
lda P8ZP_SCRATCH_B1
+""")
if(resultToStack) {
asmgen.out(" sta P8ESTACK_LO,x | dex")
} else {
val targetReg = AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, signed, fcall.position, fcall.definingISub(), asmgen)
asmgen.assignRegister(RegisterOrPair.A, targetReg)
}
val targetReg = AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.A, signed, fcall.position, fcall.definingISub(), asmgen)
asmgen.assignRegister(RegisterOrPair.A, targetReg)
} else if(fcall.type in WordDatatypes) {
asmgen.assignExpressionToVariable(fcall.args[0], "P8ZP_SCRATCH_W1", fcall.type) // left
asmgen.assignExpressionToVariable(fcall.args[1], "P8ZP_SCRATCH_W2", fcall.type) // right
@ -990,72 +913,61 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
ldy P8ZP_SCRATCH_W2+1
+""")
}
if(resultToStack) {
asmgen.out(" sta P8ESTACK_LO,x | sty P8ESTACK_HI,x | dex")
} else {
val targetReg = AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, signed, fcall.position, fcall.definingISub(), asmgen)
asmgen.assignRegister(RegisterOrPair.AY, targetReg)
}
val targetReg = AsmAssignTarget.fromRegisters(resultRegister ?: RegisterOrPair.AY, signed, fcall.position, fcall.definingISub(), asmgen)
asmgen.assignRegister(RegisterOrPair.AY, targetReg)
} else {
throw AssemblyError("max float not supported")
}
}
private fun funcMkword(fcall: PtBuiltinFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?) {
if(resultToStack) {
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.A) // msb
asmgen.out(" pha")
asmgen.assignExpressionToRegister(fcall.args[1], RegisterOrPair.A) // lsb
asmgen.out(" sta P8ESTACK_LO,x | pla | sta P8ESTACK_HI,x | dex")
} else {
val reg = resultRegister ?: RegisterOrPair.AY
var needAsave = asmgen.needAsaveForExpr(fcall.args[0])
if(!needAsave) {
val mr0 = fcall.args[0] as? PtMemoryByte
val mr1 = fcall.args[1] as? PtMemoryByte
if (mr0 != null)
needAsave = mr0.address !is PtNumber
if (mr1 != null)
needAsave = needAsave or (mr1.address !is PtNumber)
private fun funcMkword(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?) {
val reg = resultRegister ?: RegisterOrPair.AY
var needAsave = asmgen.needAsaveForExpr(fcall.args[0])
if(!needAsave) {
val mr0 = fcall.args[0] as? PtMemoryByte
val mr1 = fcall.args[1] as? PtMemoryByte
if (mr0 != null)
needAsave = mr0.address !is PtNumber
if (mr1 != null)
needAsave = needAsave or (mr1.address !is PtNumber)
}
when(reg) {
RegisterOrPair.AX -> {
asmgen.assignExpressionToRegister(fcall.args[1], RegisterOrPair.A) // lsb
if(needAsave)
asmgen.out(" pha")
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.X) // msb
if(needAsave)
asmgen.out(" pla")
}
when(reg) {
RegisterOrPair.AX -> {
asmgen.assignExpressionToRegister(fcall.args[1], RegisterOrPair.A) // lsb
if(needAsave)
asmgen.out(" pha")
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.X) // msb
if(needAsave)
asmgen.out(" pla")
}
RegisterOrPair.AY -> {
asmgen.assignExpressionToRegister(fcall.args[1], RegisterOrPair.A) // lsb
if(needAsave)
asmgen.out(" pha")
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.Y) // msb
if(needAsave)
asmgen.out(" pla")
}
RegisterOrPair.XY -> {
asmgen.assignExpressionToRegister(fcall.args[1], RegisterOrPair.A) // lsb
if(needAsave)
asmgen.out(" pha")
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.Y) // msb
if(needAsave)
asmgen.out(" pla")
asmgen.out(" tax")
}
in Cx16VirtualRegisters -> {
asmgen.assignExpressionToRegister(fcall.args[1], RegisterOrPair.A) // lsb
asmgen.out(" sta cx16.${reg.toString().lowercase()}")
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.A) // msb
asmgen.out(" sta cx16.${reg.toString().lowercase()}+1")
}
else -> throw AssemblyError("invalid mkword target reg")
RegisterOrPair.AY -> {
asmgen.assignExpressionToRegister(fcall.args[1], RegisterOrPair.A) // lsb
if(needAsave)
asmgen.out(" pha")
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.Y) // msb
if(needAsave)
asmgen.out(" pla")
}
RegisterOrPair.XY -> {
asmgen.assignExpressionToRegister(fcall.args[1], RegisterOrPair.A) // lsb
if(needAsave)
asmgen.out(" pha")
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.Y) // msb
if(needAsave)
asmgen.out(" pla")
asmgen.out(" tax")
}
in Cx16VirtualRegisters -> {
asmgen.assignExpressionToRegister(fcall.args[1], RegisterOrPair.A) // lsb
asmgen.out(" sta cx16.${reg.toString().lowercase()}")
asmgen.assignExpressionToRegister(fcall.args[0], RegisterOrPair.A) // msb
asmgen.out(" sta cx16.${reg.toString().lowercase()}+1")
}
else -> throw AssemblyError("invalid mkword target reg")
}
}
private fun funcMsb(fcall: PtBuiltinFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?) {
private fun funcMsb(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?) {
val arg = fcall.args.single()
if (arg.type !in WordDatatypes)
throw AssemblyError("msb required word argument")
@ -1063,53 +975,44 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
throw AssemblyError("msb(const) should have been const-folded away")
if (arg is PtIdentifier) {
val sourceName = asmgen.asmVariableName(arg)
if(resultToStack) {
asmgen.out(" lda $sourceName+1 | sta P8ESTACK_LO,x | dex")
} else {
when(resultRegister) {
null, RegisterOrPair.A -> asmgen.out(" lda $sourceName+1")
RegisterOrPair.X -> asmgen.out(" ldx $sourceName+1")
RegisterOrPair.Y -> asmgen.out(" ldy $sourceName+1")
RegisterOrPair.AX -> asmgen.out(" lda $sourceName+1 | ldx #0")
RegisterOrPair.AY -> asmgen.out(" lda $sourceName+1 | ldy #0")
RegisterOrPair.XY -> asmgen.out(" ldx $sourceName+1 | ldy #0")
in Cx16VirtualRegisters -> {
val regname = resultRegister.name.lowercase()
if(asmgen.isTargetCpu(CpuType.CPU65c02))
asmgen.out(" lda $sourceName+1 | sta cx16.$regname | stz cx16.$regname+1")
else
asmgen.out(" lda $sourceName+1 | sta cx16.$regname | lda #0 | sta cx16.$regname+1")
}
else -> throw AssemblyError("invalid reg")
when(resultRegister) {
null, RegisterOrPair.A -> asmgen.out(" lda $sourceName+1")
RegisterOrPair.X -> asmgen.out(" ldx $sourceName+1")
RegisterOrPair.Y -> asmgen.out(" ldy $sourceName+1")
RegisterOrPair.AX -> asmgen.out(" lda $sourceName+1 | ldx #0")
RegisterOrPair.AY -> asmgen.out(" lda $sourceName+1 | ldy #0")
RegisterOrPair.XY -> asmgen.out(" ldx $sourceName+1 | ldy #0")
in Cx16VirtualRegisters -> {
val regname = resultRegister.name.lowercase()
if(asmgen.isTargetCpu(CpuType.CPU65c02))
asmgen.out(" lda $sourceName+1 | sta cx16.$regname | stz cx16.$regname+1")
else
asmgen.out(" lda $sourceName+1 | sta cx16.$regname | lda #0 | sta cx16.$regname+1")
}
else -> throw AssemblyError("invalid reg")
}
} else {
if(resultToStack) {
asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.AY)
asmgen.out(" tya | sta P8ESTACK_LO,x | dex")
} else {
when(resultRegister) {
null, RegisterOrPair.A -> {
asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.AY)
asmgen.out(" tya")
}
RegisterOrPair.X -> {
asmgen.out(" pha")
asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.AX)
asmgen.out(" pla")
}
RegisterOrPair.Y -> {
asmgen.out(" pha")
asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.AY)
asmgen.out(" pla")
}
else -> throw AssemblyError("invalid reg")
when(resultRegister) {
null, RegisterOrPair.A -> {
asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.AY)
asmgen.out(" tya")
}
RegisterOrPair.X -> {
asmgen.out(" pha")
asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.AX)
asmgen.out(" pla")
}
RegisterOrPair.Y -> {
asmgen.out(" pha")
asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.AY)
asmgen.out(" pla")
}
else -> throw AssemblyError("invalid reg")
}
}
}
private fun funcLsb(fcall: PtBuiltinFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?) {
private fun funcLsb(fcall: PtBuiltinFunctionCall, resultRegister: RegisterOrPair?) {
val arg = fcall.args.single()
if (arg.type !in WordDatatypes)
throw AssemblyError("lsb required word argument")
@ -1118,54 +1021,42 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
if (arg is PtIdentifier) {
val sourceName = asmgen.asmVariableName(arg)
if(resultToStack) {
asmgen.out(" lda $sourceName | sta P8ESTACK_LO,x | dex")
} else {
when(resultRegister) {
null, RegisterOrPair.A -> asmgen.out(" lda $sourceName")
RegisterOrPair.X -> asmgen.out(" ldx $sourceName")
RegisterOrPair.Y -> asmgen.out(" ldy $sourceName")
RegisterOrPair.AX -> asmgen.out(" lda $sourceName | ldx #0")
RegisterOrPair.AY -> asmgen.out(" lda $sourceName | ldy #0")
RegisterOrPair.XY -> asmgen.out(" ldx $sourceName | ldy #0")
in Cx16VirtualRegisters -> {
val regname = resultRegister.name.lowercase()
if(asmgen.isTargetCpu(CpuType.CPU65c02))
asmgen.out(" lda $sourceName | sta cx16.$regname | stz cx16.$regname+1")
else
asmgen.out(" lda $sourceName | sta cx16.$regname | lda #0 | sta cx16.$regname+1")
}
else -> throw AssemblyError("invalid reg")
when(resultRegister) {
null, RegisterOrPair.A -> asmgen.out(" lda $sourceName")
RegisterOrPair.X -> asmgen.out(" ldx $sourceName")
RegisterOrPair.Y -> asmgen.out(" ldy $sourceName")
RegisterOrPair.AX -> asmgen.out(" lda $sourceName | ldx #0")
RegisterOrPair.AY -> asmgen.out(" lda $sourceName | ldy #0")
RegisterOrPair.XY -> asmgen.out(" ldx $sourceName | ldy #0")
in Cx16VirtualRegisters -> {
val regname = resultRegister.name.lowercase()
if(asmgen.isTargetCpu(CpuType.CPU65c02))
asmgen.out(" lda $sourceName | sta cx16.$regname | stz cx16.$regname+1")
else
asmgen.out(" lda $sourceName | sta cx16.$regname | lda #0 | sta cx16.$regname+1")
}
else -> throw AssemblyError("invalid reg")
}
} else {
if(resultToStack) {
asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.AY)
// NOTE: we rely on the fact that the above assignment to AY, assigns the Lsb to A as the last instruction.
// this is required because the compiler assumes the status bits are set according to what A is (lsb)
// and will not generate another cmp when lsb() is directly used inside a comparison expression.
asmgen.out(" sta P8ESTACK_LO,x | dex")
} else {
when(resultRegister) {
null, RegisterOrPair.A -> {
asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.AY)
// NOTE: we rely on the fact that the above assignment to AY, assigns the Lsb to A as the last instruction.
// this is required because the compiler assumes the status bits are set according to what A is (lsb)
// and will not generate another cmp when lsb() is directly used inside a comparison expression.
}
RegisterOrPair.X -> {
asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.XY)
// NOTE: we rely on the fact that the above assignment to XY, assigns the Lsb to X as the last instruction.
// this is required because the compiler assumes the status bits are set according to what X is (lsb)
// and will not generate another cmp when lsb() is directly used inside a comparison expression.
}
RegisterOrPair.Y -> {
asmgen.out(" pha")
asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.AY)
asmgen.out(" tay | pla | cpy #0")
}
else -> throw AssemblyError("invalid reg")
when(resultRegister) {
null, RegisterOrPair.A -> {
asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.AY)
// NOTE: we rely on the fact that the above assignment to AY, assigns the Lsb to A as the last instruction.
// this is required because the compiler assumes the status bits are set according to what A is (lsb)
// and will not generate another cmp when lsb() is directly used inside a comparison expression.
}
RegisterOrPair.X -> {
asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.XY)
// NOTE: we rely on the fact that the above assignment to XY, assigns the Lsb to X as the last instruction.
// this is required because the compiler assumes the status bits are set according to what X is (lsb)
// and will not generate another cmp when lsb() is directly used inside a comparison expression.
}
RegisterOrPair.Y -> {
asmgen.out(" pha")
asmgen.assignExpressionToRegister(fcall.args.single(), RegisterOrPair.AY)
asmgen.out(" tay | pla | cpy #0")
}
else -> throw AssemblyError("invalid reg")
}
}
}

View File

@ -24,11 +24,11 @@ internal class ExpressionsAsmGen(private val program: PtProgram,
is PtArrayIndexer -> translateExpression(expression)
is PtTypeCast -> translateExpression(expression)
is PtAddressOf -> translateExpression(expression)
is PtMemoryByte -> asmgen.translateDirectMemReadExpressionToRegAorStack(expression, true)
is PtMemoryByte -> asmgen.translateDirectMemReadExpressionToRegA(expression)
is PtNumber -> translateExpression(expression)
is PtIdentifier -> translateExpression(expression)
is PtFunctionCall -> translateFunctionCallResultOntoStack(expression)
is PtBuiltinFunctionCall -> asmgen.translateBuiltinFunctionCallExpression(expression, true, null)
is PtBuiltinFunctionCall -> asmgen.translateBuiltinFunctionCallExpression(expression, RegisterOrPair.A)
is PtContainmentCheck -> translateContainmentCheck(expression)
is PtArray, is PtString -> throw AssemblyError("string/array literal value assignment should have been replaced by a variable")
is PtRange -> throw AssemblyError("range expression should have been changed into array values")
@ -154,7 +154,7 @@ internal class ExpressionsAsmGen(private val program: PtProgram,
DataType.BYTE -> {
when(typecast.type) {
DataType.UBYTE, DataType.BYTE -> {}
DataType.UWORD, DataType.WORD -> asmgen.signExtendStackLsb(DataType.BYTE)
DataType.UWORD, DataType.WORD -> TODO("asmgen.signExtendStackLsb(DataType.BYTE)")
DataType.FLOAT -> asmgen.out(" jsr floats.stack_b2float")
in PassByReferenceDatatypes -> throw AssemblyError("cannot cast to a pass-by-reference datatype")
else -> throw AssemblyError("weird type")

View File

@ -10,8 +10,7 @@ internal enum class TargetStorageKind {
VARIABLE,
ARRAY,
MEMORY,
REGISTER,
STACK
REGISTER
}
internal enum class SourceStorageKind {
@ -20,7 +19,6 @@ internal enum class SourceStorageKind {
ARRAY,
MEMORY,
REGISTER,
STACK, // value is already present on stack
EXPRESSION, // expression in ast-form, still to be evaluated
}
@ -120,7 +118,7 @@ internal class AsmAssignTarget(val kind: TargetStorageKind,
TargetStorageKind.MEMORY -> {
left isSameAs memory!!
}
TargetStorageKind.REGISTER, TargetStorageKind.STACK -> {
TargetStorageKind.REGISTER -> {
false
}
}

View File

@ -1,6 +1,5 @@
package prog8.codegen.cpu6502.assignment
import prog8.code.SymbolTable
import prog8.code.ast.*
import prog8.code.core.*
import prog8.codegen.cpu6502.AsmGen6502Internal
@ -9,7 +8,6 @@ import prog8.codegen.cpu6502.returnsWhatWhere
internal class AssignmentAsmGen(private val program: PtProgram,
private val symbolTable: SymbolTable,
private val asmgen: AsmGen6502Internal,
private val allocator: VariableAllocator) {
private val augmentableAsmGen = AugmentableAssignmentAsmGen(program, this, asmgen, allocator)
@ -252,7 +250,7 @@ internal class AssignmentAsmGen(private val program: PtProgram,
}
}
is PtBuiltinFunctionCall -> {
val returnDt = asmgen.translateBuiltinFunctionCallExpression(value, false, assign.target.register)
val returnDt = asmgen.translateBuiltinFunctionCallExpression(value, assign.target.register)
if(assign.target.register==null) {
// still need to assign the result to the target variable/etc.
when(returnDt) {
@ -1452,16 +1450,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
assignExpressionToRegister(value, target.register!!, targetDt==DataType.WORD)
return
}
TargetStorageKind.STACK -> {
// byte to word, just assign to registers first, then push onto stack
assignExpressionToRegister(value, RegisterOrPair.AY, targetDt==DataType.WORD)
asmgen.out("""
sta P8ESTACK_LO,x
tya
sta P8ESTACK_HI,x
dex""")
return
}
else -> throw AssemblyError("weird target")
}
}
@ -1787,170 +1775,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
}
}
private fun assignStackValue(target: AsmAssignTarget) {
when(target.kind) {
TargetStorageKind.VARIABLE -> {
when (target.datatype) {
DataType.UBYTE, DataType.BYTE -> {
asmgen.out(" inx | lda P8ESTACK_LO,x | sta ${target.asmVarname}")
}
DataType.UWORD, DataType.WORD -> {
asmgen.out("""
inx
lda P8ESTACK_LO,x
sta ${target.asmVarname}
lda P8ESTACK_HI,x
sta ${target.asmVarname}+1
""")
}
DataType.FLOAT -> {
asmgen.out("""
lda #<${target.asmVarname}
ldy #>${target.asmVarname}
jsr floats.pop_float
""")
}
DataType.STR -> {
asmgen.out("""
lda #<${target.asmVarname}
ldy #>${target.asmVarname}
sta P8ZP_SCRATCH_W1
sty P8ZP_SCRATCH_W1+1
inx
lda P8ESTACK_HI,x
tay
lda P8ESTACK_LO,x
jsr prog8_lib.strcpy""")
}
else -> throw AssemblyError("weird target variable type ${target.datatype}")
}
}
TargetStorageKind.MEMORY -> {
asmgen.out(" inx | lda P8ESTACK_LO,x")
storeRegisterAInMemoryAddress(target.memory!!)
}
TargetStorageKind.ARRAY -> {
if(target.constArrayIndexValue!=null) {
val scaledIdx = target.constArrayIndexValue!! * program.memsizer.memorySize(target.datatype).toUInt()
when(target.datatype) {
in ByteDatatypes -> {
asmgen.out(" inx | lda P8ESTACK_LO,x | sta ${target.asmVarname}+$scaledIdx")
}
in WordDatatypes -> {
if(target.array!!.splitWords)
asmgen.out("""
inx
lda P8ESTACK_LO,x
sta ${target.asmVarname}_lsb+$scaledIdx
lda P8ESTACK_HI,x
sta ${target.asmVarname}_msb+$scaledIdx""")
else
asmgen.out("""
inx
lda P8ESTACK_LO,x
sta ${target.asmVarname}+$scaledIdx
lda P8ESTACK_HI,x
sta ${target.asmVarname}+$scaledIdx+1""")
}
DataType.FLOAT -> {
asmgen.out("""
lda #<(${target.asmVarname}+$scaledIdx)
ldy #>(${target.asmVarname}+$scaledIdx)
jsr floats.pop_float""")
}
else -> throw AssemblyError("weird target variable type ${target.datatype}")
}
}
else
{
target.array!!
when(target.datatype) {
DataType.UBYTE, DataType.BYTE -> {
asmgen.loadScaledArrayIndexIntoRegister(target.array, target.datatype, CpuRegister.Y)
asmgen.out(" inx | lda P8ESTACK_LO,x | sta ${target.asmVarname},y")
}
DataType.UWORD, DataType.WORD -> {
if(target.array.splitWords)
TODO("assign into split words ${target.position}")
asmgen.loadScaledArrayIndexIntoRegister(target.array, target.datatype, CpuRegister.Y)
asmgen.out("""
inx
lda P8ESTACK_LO,x
sta ${target.asmVarname},y
lda P8ESTACK_HI,x
sta ${target.asmVarname}+1,y
""")
}
DataType.FLOAT -> {
asmgen.loadScaledArrayIndexIntoRegister(target.array, target.datatype, CpuRegister.A)
asmgen.out("""
ldy #>${target.asmVarname}
clc
adc #<${target.asmVarname}
bcc +
iny
+ jsr floats.pop_float""")
}
else -> throw AssemblyError("weird dt")
}
}
}
TargetStorageKind.REGISTER -> {
when (target.datatype) {
DataType.UBYTE, DataType.BYTE -> {
when(target.register!!) {
RegisterOrPair.A -> asmgen.out(" inx | lda P8ESTACK_LO,x")
RegisterOrPair.X -> throw AssemblyError("can't load X from stack here - use intermediary var? ${target.position}")
RegisterOrPair.Y -> asmgen.out(" inx | ldy P8ESTACK_LO,x")
RegisterOrPair.AX -> asmgen.out(" inx | txy | ldx #0 | lda P8ESTACK_LO,y")
RegisterOrPair.AY -> asmgen.out(" inx | ldy #0 | lda P8ESTACK_LO,x")
in Cx16VirtualRegisters -> {
asmgen.out(
"""
inx
lda P8ESTACK_LO,x
sta cx16.${target.register.toString().lowercase()}
lda #0
sta cx16.${target.register.toString().lowercase()}+1
""")
}
else -> throw AssemblyError("can't assign byte from stack to register pair XY")
}
}
DataType.UWORD, DataType.WORD, in PassByReferenceDatatypes -> {
when(target.register!!) {
RegisterOrPair.AX -> throw AssemblyError("can't load X from stack here - use intermediary var? ${target.position}")
RegisterOrPair.AY-> asmgen.out(" inx | ldy P8ESTACK_HI,x | lda P8ESTACK_LO,x")
RegisterOrPair.XY-> throw AssemblyError("can't load X from stack here - use intermediary var? ${target.position}")
in Cx16VirtualRegisters -> {
asmgen.out(
"""
inx
lda P8ESTACK_LO,x
sta cx16.${target.register.toString().lowercase()}
lda P8ESTACK_HI,x
sta cx16.${target.register.toString().lowercase()}+1
""")
}
else -> throw AssemblyError("can't assign word to single byte register")
}
}
DataType.FLOAT -> {
when(target.register!!) {
RegisterOrPair.FAC1 -> asmgen.out(" jsr floats.pop_float_fac1")
RegisterOrPair.FAC2 -> asmgen.out(" jsr floats.pop_float_fac2")
else -> throw AssemblyError("can only assign float to Fac1 or 2")
}
}
else -> throw AssemblyError("weird dt")
}
}
TargetStorageKind.STACK -> {}
}
}
private fun assignAddressOf(target: AsmAssignTarget, sourceName: String) {
when(target.kind) {
TargetStorageKind.VARIABLE -> {
@ -1985,14 +1809,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
else -> throw AssemblyError("can't load address in a single 8-bit register")
}
}
TargetStorageKind.STACK -> {
asmgen.out("""
lda #<$sourceName
sta P8ESTACK_LO,x
lda #>$sourceName
sta P8ESTACK_HI,x
dex""")
}
}
}
@ -2021,15 +1837,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
else -> throw AssemblyError("assign string to incompatible variable type")
}
}
TargetStorageKind.STACK -> {
asmgen.out("""
lda #<$sourceName
ldy #>$sourceName+1
sta P8ESTACK_LO,x
tya
sta P8ESTACK_HI,x
dex""")
}
else -> throw AssemblyError("string-assign to weird target")
}
}
@ -2138,14 +1945,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
else -> throw AssemblyError("can't load word in a single 8-bit register")
}
}
TargetStorageKind.STACK -> {
asmgen.out("""
lda $sourceName
sta P8ESTACK_LO,x
lda $sourceName+1
sta P8ESTACK_HI,x
dex""")
}
}
}
@ -2185,7 +1984,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
if (target.register!! != RegisterOrPair.FAC1)
throw AssemblyError("can't assign Fac1 float to another register")
}
TargetStorageKind.STACK -> asmgen.out(" jsr floats.push_fac1")
}
}
@ -2224,7 +2022,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
else -> throw AssemblyError("can only assign float to Fac1 or 2")
}
}
TargetStorageKind.STACK -> asmgen.out(" jsr floats.push_float")
}
}
@ -2267,7 +2064,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
else -> throw AssemblyError("can only assign float to Fac1 or 2")
}
}
TargetStorageKind.STACK -> asmgen.out(" lda #<$sourceName | ldy #>$sourceName | jsr floats.push_float")
}
}
@ -2332,12 +2128,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
else -> throw AssemblyError("weird register")
}
}
TargetStorageKind.STACK -> {
asmgen.out("""
lda $sourceName
sta P8ESTACK_LO,x
dex""")
}
}
}
@ -2410,16 +2200,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
else -> throw AssemblyError("only reg pairs allowed as word target ${wordtarget.register}")
}
}
TargetStorageKind.STACK -> {
asmgen.out("""
lda $sourceName
sta P8ESTACK_LO,x
ora #$7f
bmi +
lda #0
+ sta P8ESTACK_HI,x
dex""")
}
else -> throw AssemblyError("target type isn't word")
}
}
@ -2487,13 +2267,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
else -> throw AssemblyError("only reg pairs allowed as word target")
}
}
TargetStorageKind.STACK -> {
asmgen.out(" lda $sourceName | sta P8ESTACK_LO,x")
if(asmgen.isTargetCpu(CpuType.CPU65c02))
asmgen.out(" stz P8ESTACK_HI,x | dex")
else
asmgen.out(" lda #0 | sta P8ESTACK_HI,x | dex")
}
else -> throw AssemblyError("target type isn't word")
}
}
@ -2689,15 +2462,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
}
}
}
TargetStorageKind.STACK -> {
if(assignAsWord)
TODO("assign register as word onto Stack not yet supported")
when(register) {
CpuRegister.A -> asmgen.out(" sta P8ESTACK_LO,x | dex")
CpuRegister.X -> throw AssemblyError("can't use X here")
CpuRegister.Y -> asmgen.out(" tya | sta P8ESTACK_LO,x | dex")
}
}
}
}
@ -2877,22 +2641,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
else -> throw AssemblyError("expected reg pair or cx16 virtual 16-bit register")
}
}
TargetStorageKind.STACK -> {
when(regs) {
RegisterOrPair.AY -> asmgen.out(" sta P8ESTACK_LO,x | tya | sta P8ESTACK_HI,x | dex")
RegisterOrPair.AX, RegisterOrPair.XY -> throw AssemblyError("can't use X here")
in Cx16VirtualRegisters -> {
val srcReg = asmgen.asmSymbolName(regs)
asmgen.out("""
lda $srcReg
sta P8ESTACK_LO,x
lda $srcReg+1
sta P8ESTACK_HI,x
dex""")
}
else -> throw AssemblyError("expected reg pair or cx16 virtual 16-bit register")
}
}
TargetStorageKind.MEMORY -> throw AssemblyError("can't store word into memory byte")
}
}
@ -2934,9 +2682,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
else -> throw AssemblyError("invalid register for word value")
}
}
TargetStorageKind.STACK -> {
asmgen.out(" stz P8ESTACK_LO,x | stz P8ESTACK_HI,x | dex")
}
}
return
@ -2996,14 +2741,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
else -> throw AssemblyError("invalid register for word value")
}
}
TargetStorageKind.STACK -> {
asmgen.out("""
lda #<${word.toHex()}
sta P8ESTACK_LO,x
lda #>${word.toHex()}
sta P8ESTACK_HI,x
dex""")
}
}
}
@ -3059,9 +2796,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
}
else -> throw AssemblyError("weird register")
}
TargetStorageKind.STACK -> {
asmgen.out(" stz P8ESTACK_LO,x | dex")
}
}
return
@ -3127,12 +2861,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
}
else -> throw AssemblyError("weird register")
}
TargetStorageKind.STACK -> {
asmgen.out("""
lda #${byte.toHex()}
sta P8ESTACK_LO,x
dex""")
}
}
}
@ -3201,10 +2929,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
else -> throw AssemblyError("can only assign float to Fac1 or 2")
}
}
TargetStorageKind.STACK -> {
val floatConst = allocator.getFloatAsmConst(float)
asmgen.out(" lda #<$floatConst | ldy #>$floatConst | jsr floats.push_float")
}
}
} else {
// non-zero value
@ -3258,10 +2982,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
else -> throw AssemblyError("can only assign float to Fac1 or 2")
}
}
TargetStorageKind.STACK -> {
val floatConst = allocator.getFloatAsmConst(float)
asmgen.out(" lda #<$floatConst | ldy #>$floatConst | jsr floats.push_float")
}
}
}
}
@ -3302,12 +3022,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
}
else -> throw AssemblyError("weird register")
}
TargetStorageKind.STACK -> {
asmgen.out("""
lda ${address.toHex()}
sta P8ESTACK_LO,x
dex""")
}
}
} else if (identifier != null) {
when(target.kind) {
@ -3344,10 +3058,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
else -> throw AssemblyError("weird register")
}
}
TargetStorageKind.STACK -> {
asmgen.loadByteFromPointerIntoA(identifier)
asmgen.out(" sta P8ESTACK_LO,x | dex")
}
}
}
}
@ -3379,13 +3089,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
}
else -> throw AssemblyError("word regs can only be pair")
}
TargetStorageKind.STACK -> {
asmgen.out(" lda ${address.toHex()} | sta P8ESTACK_LO,x")
if(asmgen.isTargetCpu(CpuType.CPU65c02))
asmgen.out(" stz P8ESTACK_HI,x | dex")
else
asmgen.out(" lda #0 | sta P8ESTACK_HI,x | dex")
}
else -> throw AssemblyError("other types aren't word")
}
} else if (identifier != null) {
@ -3419,14 +3122,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
else -> throw AssemblyError("word regs can only be pair")
}
}
TargetStorageKind.STACK -> {
asmgen.loadByteFromPointerIntoA(identifier)
asmgen.out(" sta P8ESTACK_LO,x")
if(asmgen.isTargetCpu(CpuType.CPU65c02))
asmgen.out(" stz P8ESTACK_HI,x | dex")
else
asmgen.out(" lda #0 | sta P8ESTACK_HI,x | dex")
}
else -> throw AssemblyError("other types aren't word")
}
}
@ -3536,7 +3231,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
else -> throw AssemblyError("invalid reg dt for byte invert")
}
}
TargetStorageKind.STACK -> TODO("no asm gen for byte stack invert")
TargetStorageKind.ARRAY -> assignPrefixedExpressionToArrayElt(makePrefixedExprFromArrayExprAssign("~", assign), scope)
else -> throw AssemblyError("weird target")
}
@ -3561,7 +3255,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
else -> throw AssemblyError("invalid reg dt for word invert")
}
}
TargetStorageKind.STACK -> TODO("no asm gen for word stack invert")
TargetStorageKind.ARRAY -> assignPrefixedExpressionToArrayElt(makePrefixedExprFromArrayExprAssign("~", assign), scope)
else -> throw AssemblyError("weird target")
}
@ -3604,7 +3297,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
}
}
TargetStorageKind.MEMORY -> throw AssemblyError("memory is ubyte, can't negate that")
TargetStorageKind.STACK -> TODO("no asm gen for byte stack negate")
TargetStorageKind.ARRAY -> assignPrefixedExpressionToArrayElt(makePrefixedExprFromArrayExprAssign("-", assign), scope)
else -> throw AssemblyError("weird target")
}
@ -3664,7 +3356,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
}
}
TargetStorageKind.MEMORY -> throw AssemblyError("memory is ubyte, can't negate that")
TargetStorageKind.STACK -> TODO("no asm gen for word stack negate")
TargetStorageKind.ARRAY -> assignPrefixedExpressionToArrayElt(makePrefixedExprFromArrayExprAssign("-", assign), scope)
else -> throw AssemblyError("weird target")
}
@ -3686,7 +3377,6 @@ internal class AssignmentAsmGen(private val program: PtProgram,
sta ${target.asmVarname}+1
""")
}
TargetStorageKind.STACK -> TODO("no asm gen for float stack negate")
TargetStorageKind.ARRAY -> assignPrefixedExpressionToArrayElt(makePrefixedExprFromArrayExprAssign("-", assign), scope)
else -> throw AssemblyError("weird target for in-place float negation")
}

View File

@ -166,8 +166,8 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
}
}
else -> {
// TODO use some other evaluation here; don't use the estack to transfer the address to read/write from
asmgen.assignExpressionTo(memory.address, AsmAssignTarget(TargetStorageKind.STACK, asmgen, DataType.UWORD, memory.definingISub(), target.position))
TODO("use some other evaluation here; there's no evalstack anymore to transfer the address to read/write from")
// TODO: asmgen.assignExpressionTo(memory.address, AsmAssignTarget(TargetStorageKind.STACK, asmgen, DataType.UWORD, memory.definingISub(), target.position))
asmgen.out(" jsr prog8_lib.read_byte_from_address_on_stack | sta P8ZP_SCRATCH_B1")
when(value.kind) {
SourceStorageKind.LITERALNUMBER -> inplaceModification_byte_litval_to_variable("P8ZP_SCRATCH_B1", DataType.UBYTE, operator, value.number!!.number.toInt())
@ -372,7 +372,6 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
}
}
TargetStorageKind.REGISTER -> throw AssemblyError("no asm gen for reg in-place modification")
TargetStorageKind.STACK -> throw AssemblyError("no asm gen for stack in-place modification")
}
}
@ -592,8 +591,6 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
}
private fun inplaceModification_byte_value_to_variable(name: String, dt: DataType, operator: String, value: PtExpression) {
// this should be the last resort for code generation for this,
// because the value is evaluated onto the eval stack (=slow).
when (operator) {
"+" -> {
asmgen.assignExpressionToRegister(value, RegisterOrPair.A)
@ -1071,14 +1068,14 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
private fun inplaceModification_byte_memread_to_variable(name: String, dt: DataType, operator: String, memread: PtMemoryByte) {
when (operator) {
"+" -> {
asmgen.translateDirectMemReadExpressionToRegAorStack(memread, false)
asmgen.translateDirectMemReadExpressionToRegA(memread)
asmgen.out("""
clc
adc $name
sta $name""")
}
"-" -> {
asmgen.translateDirectMemReadExpressionToRegAorStack(memread, false)
asmgen.translateDirectMemReadExpressionToRegA(memread)
val tmpByte = if(name!="P8ZP_SCRATCH_B1") "P8ZP_SCRATCH_B1" else "P8ZP_SCRATCH_REG"
asmgen.out("""
sta $tmpByte
@ -1088,15 +1085,15 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
sta $name""")
}
"|" -> {
asmgen.translateDirectMemReadExpressionToRegAorStack(memread, false)
asmgen.translateDirectMemReadExpressionToRegA(memread)
asmgen.out(" ora $name | sta $name")
}
"&" -> {
asmgen.translateDirectMemReadExpressionToRegAorStack(memread, false)
asmgen.translateDirectMemReadExpressionToRegA(memread)
asmgen.out(" and $name | sta $name")
}
"^" -> {
asmgen.translateDirectMemReadExpressionToRegAorStack(memread, false)
asmgen.translateDirectMemReadExpressionToRegA(memread)
asmgen.out(" eor $name | sta $name")
}
else -> {
@ -1108,7 +1105,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
private fun inplaceModification_word_memread_to_variable(name: String, dt: DataType, operator: String, memread: PtMemoryByte) {
when (operator) {
"+" -> {
asmgen.translateDirectMemReadExpressionToRegAorStack(memread, false)
asmgen.translateDirectMemReadExpressionToRegA(memread)
asmgen.out("""
clc
adc $name
@ -1118,7 +1115,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
+""")
}
"-" -> {
asmgen.translateDirectMemReadExpressionToRegAorStack(memread, false)
asmgen.translateDirectMemReadExpressionToRegA(memread)
val tmpByte = if(name!="P8ZP_SCRATCH_B1") "P8ZP_SCRATCH_B1" else "P8ZP_SCRATCH_REG"
asmgen.out("""
sta $tmpByte
@ -1131,11 +1128,11 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
+""")
}
"|" -> {
asmgen.translateDirectMemReadExpressionToRegAorStack(memread, false)
asmgen.translateDirectMemReadExpressionToRegA(memread)
asmgen.out(" ora $name | sta $name")
}
"&" -> {
asmgen.translateDirectMemReadExpressionToRegAorStack(memread, false)
asmgen.translateDirectMemReadExpressionToRegA(memread)
asmgen.out(" and $name | sta $name")
if(dt in WordDatatypes) {
if(asmgen.isTargetCpu(CpuType.CPU65c02))
@ -1145,7 +1142,7 @@ internal class AugmentableAssignmentAsmGen(private val program: PtProgram,
}
}
"^" -> {
asmgen.translateDirectMemReadExpressionToRegAorStack(memread, false)
asmgen.translateDirectMemReadExpressionToRegA(memread)
asmgen.out(" eor $name | sta $name")
}
else -> {

View File

@ -27,8 +27,6 @@ class AstPreprocessor(val program: Program,
}
private fun relocateCx16VirtualRegisters(program: Program, baseAddress: UInt) {
// reset the address of the virtual registers to be inside the evaluation stack.
// (we don't do this on CommanderX16 itself as the registers have a fixed location in Zeropage there)
val cx16block = program.allBlocks.single { it.name == "cx16" }
val memVars = cx16block.statements
.filterIsInstance<VarDecl>()

View File

@ -151,10 +151,6 @@ One or more .p8 module files
Note that it is possible to use the watch mode with multiple modules as well, but it will
recompile everything in that list even if only one of the files got updated.
``-slowwarn``
Shows debug warnings about slow or problematic assembly code generation.
Ideally, the compiler should use as few stack based evaluations as possible.
``-quietasm``
Don't print assembler output results.
@ -176,12 +172,6 @@ One or more .p8 module files
Add this user-defined symbol directly to the beginning of the generated assembly file.
Can be repeated to define multiple symbols.
``-esa <address>``
Override the base address of the evaluation stack. Has to be page-aligned.
You can specify an integer or hexadecimal address.
When not compiling for the Commander X16 target, the location of the 16 virtual registers cx16.r0..r15
is changed accordingly (to keep them in the same memory space as the evaluation stack).
``-varshigh <rambank>``
Places the non-zeropage variables in a separate high memory area, instead of inside the program itself.
This results in an increase of the amount of system ram available for the program

View File

@ -1,6 +1,14 @@
TODO
====
- (branch): remove all evalstack references from p8 code files
- (branch): remove all evalstack references from asm code files
- (branch): remove ExpressionsAsmGen.kt altogether
- (branch): clean up all X register special handling
- (branch): fix optimizeCmpSequence in AsmOptimizer
- (branch): fix inplaceModification TODO in AugmentableAssignmentAsmGen
- (branch): clean up docs about eval stack and X register
- IR: instructions that do type conversion (SZ etc, CONCAT, SGN) should put the result in a DIFFERENT register.
- IR: reduce the number of branch instructions (gradually), replace with CMP(I) + status branch instruction