added missing register pair assignments. fixed compiler crashes

This commit is contained in:
Irmen de Jong 2020-10-07 02:22:25 +02:00
parent e22b4cbb67
commit 5099525e24
12 changed files with 118 additions and 50 deletions

View File

@ -543,30 +543,48 @@ internal class AsmGen(private val program: Program,
private val saveRegisterLabels = Stack<String>();
internal fun saveRegister(register: CpuRegister) {
when(register) {
CpuRegister.A -> out(" pha")
CpuRegister.X -> {
if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) out(" phx")
else out(" stx _prog8_regsave${register.name}")
internal fun saveRegister(register: CpuRegister, dontUseStack: Boolean) {
if(dontUseStack) {
when (register) {
CpuRegister.A -> out(" sta _prog8_regsaveA")
CpuRegister.X -> out(" stx _prog8_regsaveX")
CpuRegister.Y -> out(" sty _prog8_regsaveY")
}
CpuRegister.Y -> {
if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) out(" phy")
else out(" sty _prog8_regsave${register.name}")
} else {
when (register) {
CpuRegister.A -> out(" pha")
CpuRegister.X -> {
if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) out(" phx")
else out(" stx _prog8_regsaveX")
}
CpuRegister.Y -> {
if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) out(" phy")
else out(" sty _prog8_regsaveY")
}
}
}
}
internal fun restoreRegister(register: CpuRegister) {
when(register) {
CpuRegister.A -> out(" pla")
CpuRegister.X -> {
if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) out(" plx")
else out(" ldx _prog8_regsave${register.name}")
internal fun restoreRegister(register: CpuRegister, dontUseStack: Boolean) {
if(dontUseStack) {
when (register) {
CpuRegister.A -> out(" sta _prog8_regsaveA")
CpuRegister.X -> out(" ldx _prog8_regsaveX")
CpuRegister.Y -> out(" ldy _prog8_regsaveY")
}
CpuRegister.Y -> {
if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) out(" ply")
else out(" ldy _prog8_regsave${register.name}")
} else {
when (register) {
CpuRegister.A -> out(" pla")
CpuRegister.X -> {
if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) out(" plx")
else out(" ldx _prog8_regsaveX")
}
CpuRegister.Y -> {
if (CompilationTarget.instance.machine.cpu == CpuType.CPU65c02) out(" ply")
else out(" ldy _prog8_regsaveY")
}
}
}
}
@ -811,6 +829,7 @@ internal class AsmGen(private val program: Program,
out("; variables")
out("""
; register saves
_prog8_regsaveA .byte 0
_prog8_regsaveX .byte 0
_prog8_regsaveY .byte 0""") // TODO only generate these bytes if they're actually used by saveRegister()
vardecls2asm(sub.statements)

View File

@ -19,7 +19,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
val sub = stmt.target.targetSubroutine(program.namespace) ?: throw AssemblyError("undefined subroutine ${stmt.target}")
val saveX = CpuRegister.X in sub.asmClobbers || sub.regXasResult() || sub.regXasParam()
if(saveX)
asmgen.saveRegister(CpuRegister.X)
asmgen.saveRegister(CpuRegister.X, preserveStatusRegisterAfterCall)
val subName = asmgen.asmSymbolName(stmt.target)
if(stmt.args.isNotEmpty()) {
@ -64,7 +64,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
}
if(saveX)
asmgen.restoreRegister(CpuRegister.X)
asmgen.restoreRegister(CpuRegister.X, preserveStatusRegisterAfterCall)
}
private fun registerArgsViaStackEvaluation(stmt: IFunctionCall, sub: Subroutine) {

View File

@ -97,7 +97,7 @@ internal class PostIncrDecrAsmGen(private val program: Program, private val asmg
}
else -> {
asmgen.loadScaledArrayIndexIntoRegister(targetArrayIdx, elementDt, CpuRegister.A)
asmgen.saveRegister(CpuRegister.X)
asmgen.saveRegister(CpuRegister.X, false)
asmgen.out(" tax")
when(elementDt) {
in ByteDatatypes -> {
@ -125,7 +125,7 @@ internal class PostIncrDecrAsmGen(private val program: Program, private val asmg
}
else -> throw AssemblyError("weird array elt dt")
}
asmgen.restoreRegister(CpuRegister.X)
asmgen.restoreRegister(CpuRegister.X, false)
}
}
}

View File

@ -127,7 +127,16 @@ internal class AsmAssignSource(val kind: SourceStorageKind,
0 -> throw AssemblyError("can't translate zero return values in assignment")
1 -> {
// assignment generation itself must make sure the status register is correct after the subroutine call, if status register is involved!
return AsmAssignSource(SourceStorageKind.EXPRESSION, program, DataType.UBYTE, expression = value)
val reg = asmSub.asmReturnvaluesRegisters.single { rr->rr.registerOrPair!=null }.registerOrPair!!
val dt = when(reg) {
RegisterOrPair.A,
RegisterOrPair.X,
RegisterOrPair.Y -> DataType.UBYTE
RegisterOrPair.AX,
RegisterOrPair.AY,
RegisterOrPair.XY -> DataType.UWORD
}
return AsmAssignSource(SourceStorageKind.EXPRESSION, program, dt, expression = value)
}
else -> throw AssemblyError("can't translate multiple return values in assignment")
}
@ -177,6 +186,8 @@ internal class AsmAssignment(val source: AsmAssignSource,
init {
if(target.register !in setOf(RegisterOrPair.XY, RegisterOrPair.AX, RegisterOrPair.AY))
require(source.datatype != DataType.STRUCT) { "must not be placeholder datatype" }
require(source.datatype.memorySize() == target.datatype.memorySize()) { "source and target datatype must be same storage class" }
require(source.datatype.memorySize() <= target.datatype.memorySize()) {
"source storage size must be less or equal to target datatype storage size"
}
}
}

View File

@ -133,6 +133,9 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
RegisterOrPair.A -> assignRegisterByte(assign.target, CpuRegister.A)
RegisterOrPair.X -> assignRegisterByte(assign.target, CpuRegister.X)
RegisterOrPair.Y -> assignRegisterByte(assign.target, CpuRegister.Y)
RegisterOrPair.AX -> assignRegisterpairWord(assign.target, RegisterOrPair.AX)
RegisterOrPair.AY -> assignRegisterpairWord(assign.target, RegisterOrPair.AY)
RegisterOrPair.XY -> assignRegisterpairWord(assign.target, RegisterOrPair.XY)
else -> throw AssemblyError("should be just one register byte result value")
}
if(preserveStatusRegisterAfterCall)
@ -685,9 +688,9 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
asmgen.out(" ldy ${asmgen.asmVariableName(index)} | sta ${target.asmVarname},y")
}
else -> {
asmgen.saveRegister(register)
asmgen.saveRegister(register, false)
asmgen.translateExpression(index)
asmgen.restoreRegister(register)
asmgen.restoreRegister(register, false)
when (register) {
CpuRegister.A -> asmgen.out(" sta P8ZP_SCRATCH_B1")
CpuRegister.X -> asmgen.out(" stx P8ZP_SCRATCH_B1")
@ -741,6 +744,54 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
}
}
private fun assignRegisterpairWord(target: AsmAssignTarget, regs: RegisterOrPair) {
require(target.datatype in WordDatatypes)
when(target.kind) {
TargetStorageKind.VARIABLE -> {
when(regs) {
RegisterOrPair.AX -> asmgen.out(" sta ${target.asmVarname} | stx ${target.asmVarname}+1")
RegisterOrPair.AY -> asmgen.out(" sta ${target.asmVarname} | sty ${target.asmVarname}+1")
RegisterOrPair.XY -> asmgen.out(" stx ${target.asmVarname} | sty ${target.asmVarname}+1")
else -> throw AssemblyError("expected reg pair")
}
}
TargetStorageKind.ARRAY -> {
TODO("store register pair $regs into word-array ${target.array}")
}
TargetStorageKind.REGISTER -> {
when(regs) {
RegisterOrPair.AX -> when(target.register!!) {
RegisterOrPair.AY -> { asmgen.out(" stx P8ZP_SCRATCH_REG | ldy P8ZP_SCRATCH_REG") }
RegisterOrPair.AX -> { }
RegisterOrPair.XY -> { asmgen.out(" stx P8ZP_SCRATCH_REG | ldy P8ZP_SCRATCH_REG | tax") }
else -> throw AssemblyError("expected reg pair")
}
RegisterOrPair.AY -> when(target.register!!) {
RegisterOrPair.AY -> { }
RegisterOrPair.AX -> { asmgen.out(" sty P8ZP_SCRATCH_REG | ldx P8ZP_SCRATCH_REG") }
RegisterOrPair.XY -> { asmgen.out(" tax") }
else -> throw AssemblyError("expected reg pair")
}
RegisterOrPair.XY -> when(target.register!!) {
RegisterOrPair.AY -> { asmgen.out(" txa") }
RegisterOrPair.AX -> { asmgen.out(" txa | sty P8ZP_SCRATCH_REG | ldx P8ZP_SCRATCH_REG") }
RegisterOrPair.XY -> { }
else -> throw AssemblyError("expected reg pair")
}
else -> throw AssemblyError("expected reg pair")
}
}
TargetStorageKind.STACK -> {
when(regs) {
RegisterOrPair.AY -> asmgen.out(" sta P8ESTACK_LO,x | sty P8ESTACK_HI,x | dex")
RegisterOrPair.AX, RegisterOrPair.XY -> throw AssemblyError("can't use X here")
else -> throw AssemblyError("expected reg pair")
}
}
TargetStorageKind.MEMORY -> throw AssemblyError("can't store word into memory byte")
}
}
private fun assignConstantWord(target: AsmAssignTarget, word: Int) {
when(target.kind) {
TargetStorageKind.VARIABLE -> {
@ -1136,9 +1187,9 @@ internal class AssignmentAsmGen(private val program: Program, private val asmgen
asmgen.storeByteIntoPointer(addressExpr, null)
}
else -> {
asmgen.saveRegister(register)
asmgen.saveRegister(register, false)
asmgen.translateExpression(addressExpr)
asmgen.restoreRegister(CpuRegister.A)
asmgen.restoreRegister(CpuRegister.A, false)
asmgen.out("""
inx
ldy P8ESTACK_LO,x

View File

@ -1258,7 +1258,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
println("warning: slow stack evaluation used (2): $name $operator= ${value::class.simpleName} at ${value.position}") // TODO
asmgen.translateExpression(value)
asmgen.out(" jsr floats.pop_float_fac1")
asmgen.saveRegister(CpuRegister.X)
asmgen.saveRegister(CpuRegister.X, false)
when (operator) {
"**" -> {
asmgen.out("""
@ -1303,7 +1303,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
ldy #>$name
jsr floats.MOVMF
""")
asmgen.restoreRegister(CpuRegister.X)
asmgen.restoreRegister(CpuRegister.X, false)
}
private fun inplaceModification_float_variable_to_variable(name: String, operator: String, ident: IdentifierReference) {
@ -1312,7 +1312,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
throw AssemblyError("float variable expected")
val otherName = asmgen.asmVariableName(ident)
asmgen.saveRegister(CpuRegister.X)
asmgen.saveRegister(CpuRegister.X, false)
when (operator) {
"**" -> {
asmgen.out("""
@ -1372,12 +1372,12 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
ldy #>$name
jsr floats.MOVMF
""")
asmgen.restoreRegister(CpuRegister.X)
asmgen.restoreRegister(CpuRegister.X, false)
}
private fun inplaceModification_float_litval_to_variable(name: String, operator: String, value: Double) {
val constValueName = asmgen.getFloatAsmConst(value)
asmgen.saveRegister(CpuRegister.X)
asmgen.saveRegister(CpuRegister.X, false)
when (operator) {
"**" -> {
asmgen.out("""
@ -1444,7 +1444,7 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
ldy #>$name
jsr floats.MOVMF
""")
asmgen.restoreRegister(CpuRegister.X)
asmgen.restoreRegister(CpuRegister.X, false)
}
private fun inplaceCast(target: AsmAssignTarget, cast: TypecastExpression, position: Position) {

View File

@ -4,8 +4,6 @@
; TODO add all other Elite's ships, show their name, advance to next ship on keypress
; TODO fix crash
main {
; storage for rotated coordinates

View File

@ -3,8 +3,6 @@
%import floats
%zeropage basicsafe
; TODO fix crash
main {
const uword width = 256
const uword height = 200

View File

@ -3,8 +3,6 @@
%target cx16
%zeropage basicsafe
; TODO fix crash
main {

View File

@ -4,7 +4,7 @@
%zeropage basicsafe
; This example shows the directory contents of disk drive 8.
; Note: this program is compatible with C64 and CX16. TODO not yet on cx16, fix the crash
; Note: this program is compatible with C64 and CX16.
main {
sub start() {
@ -37,11 +37,9 @@ main {
txt.chrout(char)
} until char==0
txt.chrout('\n')
repeat 2 {
void c64.CHRIN() ; skip 2 bytes
}
void c64.CHRIN() ; skip 2 bytes
void c64.CHRIN()
status = c64.READST()
c64.STOP()
if_nz
break

View File

@ -8,9 +8,6 @@
; Note: this program is compatible with C64 and CX16.
; TODO fix compiler crash
main {
const ubyte width = 255
const ubyte height = 200

View File

@ -2,8 +2,6 @@
%zeropage basicsafe
%option no_sysinit
; TODO fix compiler crash
main {
sub start() {
txt.lowercase()