mirror of
https://github.com/irmen/prog8.git
synced 2025-02-16 22:30:46 +00:00
added missing register pair assignments. fixed compiler crashes
This commit is contained in:
parent
e22b4cbb67
commit
5099525e24
@ -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)
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -3,8 +3,6 @@
|
||||
%import floats
|
||||
%zeropage basicsafe
|
||||
|
||||
; TODO fix crash
|
||||
|
||||
main {
|
||||
const uword width = 256
|
||||
const uword height = 200
|
||||
|
@ -3,8 +3,6 @@
|
||||
%target cx16
|
||||
%zeropage basicsafe
|
||||
|
||||
; TODO fix crash
|
||||
|
||||
|
||||
main {
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -2,8 +2,6 @@
|
||||
%zeropage basicsafe
|
||||
%option no_sysinit
|
||||
|
||||
; TODO fix compiler crash
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
txt.lowercase()
|
||||
|
Loading…
x
Reference in New Issue
Block a user