optimizing X register saving for 65c02 using phx/plx instead of zp location

This commit is contained in:
Irmen de Jong 2020-08-28 22:11:33 +02:00
parent 0b55372b3b
commit 9154d8bd37
5 changed files with 41 additions and 42 deletions

View File

@ -42,7 +42,7 @@ asmsub print (str text @ AY) clobbers(A,Y) {
asmsub print_ub0 (ubyte value @ A) clobbers(A,Y) { asmsub print_ub0 (ubyte value @ A) clobbers(A,Y) {
; ---- print the ubyte in A in decimal form, with left padding 0s (3 positions total) ; ---- print the ubyte in A in decimal form, with left padding 0s (3 positions total)
%asm {{ %asm {{
stx P8ZP_SCRATCH_REG_X phx
jsr conv.ubyte2decimal jsr conv.ubyte2decimal
pha pha
tya tya
@ -51,7 +51,7 @@ asmsub print_ub0 (ubyte value @ A) clobbers(A,Y) {
jsr c64.CHROUT jsr c64.CHROUT
txa txa
jsr c64.CHROUT jsr c64.CHROUT
ldx P8ZP_SCRATCH_REG_X plx
rts rts
}} }}
} }
@ -59,7 +59,7 @@ asmsub print_ub0 (ubyte value @ A) clobbers(A,Y) {
asmsub print_ub (ubyte value @ A) clobbers(A,Y) { asmsub print_ub (ubyte value @ A) clobbers(A,Y) {
; ---- print the ubyte in A in decimal form, without left padding 0s ; ---- print the ubyte in A in decimal form, without left padding 0s
%asm {{ %asm {{
stx P8ZP_SCRATCH_REG_X phx
jsr conv.ubyte2decimal jsr conv.ubyte2decimal
_print_byte_digits _print_byte_digits
pha pha
@ -76,7 +76,7 @@ _print_byte_digits
jsr c64.CHROUT jsr c64.CHROUT
_ones txa _ones txa
jsr c64.CHROUT jsr c64.CHROUT
ldx P8ZP_SCRATCH_REG_X plx
rts rts
}} }}
} }
@ -84,7 +84,7 @@ _ones txa
asmsub print_b (byte value @ A) clobbers(A,Y) { asmsub print_b (byte value @ A) clobbers(A,Y) {
; ---- print the byte in A in decimal form, without left padding 0s ; ---- print the byte in A in decimal form, without left padding 0s
%asm {{ %asm {{
stx P8ZP_SCRATCH_REG_X phx
pha pha
cmp #0 cmp #0
bpl + bpl +
@ -93,7 +93,7 @@ asmsub print_b (byte value @ A) clobbers(A,Y) {
+ pla + pla
jsr conv.byte2decimal jsr conv.byte2decimal
jsr print_ub._print_byte_digits jsr print_ub._print_byte_digits
ldx P8ZP_SCRATCH_REG_X plx
rts rts
}} }}
} }
@ -101,7 +101,7 @@ asmsub print_b (byte value @ A) clobbers(A,Y) {
asmsub print_ubhex (ubyte value @ A, ubyte prefix @ Pc) clobbers(A,Y) { asmsub print_ubhex (ubyte value @ A, ubyte prefix @ Pc) clobbers(A,Y) {
; ---- print the ubyte in A in hex form (if Carry is set, a radix prefix '$' is printed as well) ; ---- print the ubyte in A in hex form (if Carry is set, a radix prefix '$' is printed as well)
%asm {{ %asm {{
stx P8ZP_SCRATCH_REG_X phx
bcc + bcc +
pha pha
lda #'$' lda #'$'
@ -111,7 +111,7 @@ asmsub print_ubhex (ubyte value @ A, ubyte prefix @ Pc) clobbers(A,Y) {
jsr c64.CHROUT jsr c64.CHROUT
tya tya
jsr c64.CHROUT jsr c64.CHROUT
ldx P8ZP_SCRATCH_REG_X plx
rts rts
}} }}
} }
@ -119,7 +119,7 @@ asmsub print_ubhex (ubyte value @ A, ubyte prefix @ Pc) clobbers(A,Y) {
asmsub print_ubbin (ubyte value @ A, ubyte prefix @ Pc) clobbers(A,Y) { asmsub print_ubbin (ubyte value @ A, ubyte prefix @ Pc) clobbers(A,Y) {
; ---- print the ubyte in A in binary form (if Carry is set, a radix prefix '%' is printed as well) ; ---- print the ubyte in A in binary form (if Carry is set, a radix prefix '%' is printed as well)
%asm {{ %asm {{
stx P8ZP_SCRATCH_REG_X phx
sta P8ZP_SCRATCH_B1 sta P8ZP_SCRATCH_B1
bcc + bcc +
lda #'%' lda #'%'
@ -132,7 +132,7 @@ asmsub print_ubbin (ubyte value @ A, ubyte prefix @ Pc) clobbers(A,Y) {
+ jsr c64.CHROUT + jsr c64.CHROUT
dey dey
bne - bne -
ldx P8ZP_SCRATCH_REG_X plx
rts rts
}} }}
} }
@ -165,7 +165,7 @@ asmsub print_uwhex (uword value @ AY, ubyte prefix @ Pc) clobbers(A,Y) {
asmsub print_uw0 (uword value @ AY) clobbers(A,Y) { asmsub print_uw0 (uword value @ AY) clobbers(A,Y) {
; ---- print the uword in A/Y in decimal form, with left padding 0s (5 positions total) ; ---- print the uword in A/Y in decimal form, with left padding 0s (5 positions total)
%asm {{ %asm {{
stx P8ZP_SCRATCH_REG_X phx
jsr conv.uword2decimal jsr conv.uword2decimal
ldy #0 ldy #0
- lda conv.uword2decimal.decTenThousands,y - lda conv.uword2decimal.decTenThousands,y
@ -173,7 +173,7 @@ asmsub print_uw0 (uword value @ AY) clobbers(A,Y) {
jsr c64.CHROUT jsr c64.CHROUT
iny iny
bne - bne -
+ ldx P8ZP_SCRATCH_REG_X + plx
rts rts
}} }}
} }
@ -181,9 +181,9 @@ asmsub print_uw0 (uword value @ AY) clobbers(A,Y) {
asmsub print_uw (uword value @ AY) clobbers(A,Y) { asmsub print_uw (uword value @ AY) clobbers(A,Y) {
; ---- print the uword in A/Y in decimal form, without left padding 0s ; ---- print the uword in A/Y in decimal form, without left padding 0s
%asm {{ %asm {{
stx P8ZP_SCRATCH_REG_X phx
jsr conv.uword2decimal jsr conv.uword2decimal
ldx P8ZP_SCRATCH_REG_X plx
ldy #0 ldy #0
- lda conv.uword2decimal.decTenThousands,y - lda conv.uword2decimal.decTenThousands,y
beq _allzero beq _allzero
@ -228,11 +228,11 @@ asmsub print_w (word value @ AY) clobbers(A,Y) {
asmsub plot (ubyte col @ Y, ubyte row @ A) clobbers(A) { asmsub plot (ubyte col @ Y, ubyte row @ A) clobbers(A) {
; ---- safe wrapper around PLOT kernel routine, to save the X register. ; ---- safe wrapper around PLOT kernel routine, to save the X register.
%asm {{ %asm {{
stx P8ZP_SCRATCH_REG_X phx
tax tax
clc clc
jsr c64.PLOT jsr c64.PLOT
ldx P8ZP_SCRATCH_REG_X plx
rts rts
}} }}
} }

View File

@ -551,7 +551,12 @@ internal class AsmGen(private val program: Program,
internal fun saveRegister(register: CpuRegister) { internal fun saveRegister(register: CpuRegister) {
when(register) { when(register) {
CpuRegister.A -> out(" pha") CpuRegister.A -> out(" pha")
CpuRegister.X -> out(" txa | pha") CpuRegister.X -> {
if(CompilationTarget.machine.cpu == CpuType.CPU65c02)
out(" phx")
else
out(" stx P8ZP_SCRATCH_REG_X")
}
CpuRegister.Y -> out(" tya | pha") CpuRegister.Y -> out(" tya | pha")
} }
} }
@ -559,7 +564,12 @@ internal class AsmGen(private val program: Program,
internal fun restoreRegister(register: CpuRegister) { internal fun restoreRegister(register: CpuRegister) {
when(register) { when(register) {
CpuRegister.A -> out(" pla") CpuRegister.A -> out(" pla")
CpuRegister.X -> out(" pla | tax") CpuRegister.X -> {
if(CompilationTarget.machine.cpu == CpuType.CPU65c02)
out(" plx")
else
out(" ldx P8ZP_SCRATCH_REG_X")
}
CpuRegister.Y -> out(" pla | tay") CpuRegister.Y -> out(" pla | tay")
} }
} }

View File

@ -18,7 +18,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 sub = stmt.target.targetSubroutine(program.namespace) ?: throw AssemblyError("undefined subroutine ${stmt.target}")
val saveX = CpuRegister.X in sub.asmClobbers || sub.regXasResult() || sub.regXasParam() val saveX = CpuRegister.X in sub.asmClobbers || sub.regXasResult() || sub.regXasParam()
if(saveX) if(saveX)
asmgen.out(" stx P8ZP_SCRATCH_REG_X") // we only save X for now (required! is the eval stack pointer), screw A and Y... asmgen.saveRegister(CpuRegister.X) // we only save X for now (required! is the eval stack pointer), screw A and Y...
val subName = asmgen.asmSymbolName(stmt.target) val subName = asmgen.asmSymbolName(stmt.target)
if(stmt.args.isNotEmpty()) { if(stmt.args.isNotEmpty()) {
@ -57,7 +57,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
asmgen.out(" jsr $subName") asmgen.out(" jsr $subName")
if(saveX) if(saveX)
asmgen.out(" ldx P8ZP_SCRATCH_REG_X") // restore X again asmgen.restoreRegister(CpuRegister.X)
} }
private fun registerArgsViaStackEvaluation(stmt: IFunctionCall, sub: Subroutine) { private fun registerArgsViaStackEvaluation(stmt: IFunctionCall, sub: Subroutine) {

View File

@ -97,7 +97,8 @@ internal class PostIncrDecrAsmGen(private val program: Program, private val asmg
} }
else -> { else -> {
asmgen.loadScaledArrayIndexIntoRegister(targetArrayIdx, elementDt, CpuRegister.A) asmgen.loadScaledArrayIndexIntoRegister(targetArrayIdx, elementDt, CpuRegister.A)
asmgen.out(" stx P8ZP_SCRATCH_REG_X | tax") asmgen.saveRegister(CpuRegister.X)
asmgen.out(" tax")
when(elementDt) { when(elementDt) {
in ByteDatatypes -> { in ByteDatatypes -> {
asmgen.out(if(incr) " inc $asmArrayvarname,x" else " dec $asmArrayvarname,x") asmgen.out(if(incr) " inc $asmArrayvarname,x" else " dec $asmArrayvarname,x")
@ -124,7 +125,7 @@ internal class PostIncrDecrAsmGen(private val program: Program, private val asmg
} }
else -> throw AssemblyError("weird array elt dt") else -> throw AssemblyError("weird array elt dt")
} }
asmgen.out(" ldx P8ZP_SCRATCH_REG_X") asmgen.restoreRegister(CpuRegister.X)
} }
} }
} }

View File

@ -1059,11 +1059,11 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
// because the value is evaluated onto the eval stack (=slow). // because the value is evaluated onto the eval stack (=slow).
println("warning: slow stack evaluation used (2): $name $operator= ${value::class.simpleName} at ${value.position}") // TODO println("warning: slow stack evaluation used (2): $name $operator= ${value::class.simpleName} at ${value.position}") // TODO
asmgen.translateExpression(value) asmgen.translateExpression(value)
asmgen.saveRegister(CpuRegister.X)
when (operator) { when (operator) {
"**" -> { "**" -> {
asmgen.out(""" asmgen.out("""
jsr c64flt.pop_float_fac1 jsr c64flt.pop_float_fac1
stx P8ZP_SCRATCH_REG_X
lda #<$name lda #<$name
ldy #>$name ldy #>$name
jsr c64flt.CONUPK jsr c64flt.CONUPK
@ -1073,7 +1073,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
"+" -> { "+" -> {
asmgen.out(""" asmgen.out("""
jsr c64flt.pop_float_fac1 jsr c64flt.pop_float_fac1
stx P8ZP_SCRATCH_REG_X
lda #<$name lda #<$name
ldy #>$name ldy #>$name
jsr c64flt.FADD jsr c64flt.FADD
@ -1082,7 +1081,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
"-" -> { "-" -> {
asmgen.out(""" asmgen.out("""
jsr c64flt.pop_float_fac1 jsr c64flt.pop_float_fac1
stx P8ZP_SCRATCH_REG_X
lda #<$name lda #<$name
ldy #>$name ldy #>$name
jsr c64flt.FSUB jsr c64flt.FSUB
@ -1091,7 +1089,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
"*" -> { "*" -> {
asmgen.out(""" asmgen.out("""
jsr c64flt.pop_float_fac1 jsr c64flt.pop_float_fac1
stx P8ZP_SCRATCH_REG_X
lda #<$name lda #<$name
ldy #>$name ldy #>$name
jsr c64flt.FMULT jsr c64flt.FMULT
@ -1100,7 +1097,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
"/" -> { "/" -> {
asmgen.out(""" asmgen.out("""
jsr c64flt.pop_float_fac1 jsr c64flt.pop_float_fac1
stx P8ZP_SCRATCH_REG_X
lda #<$name lda #<$name
ldy #>$name ldy #>$name
jsr c64flt.FDIV jsr c64flt.FDIV
@ -1113,8 +1109,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
ldx #<$name ldx #<$name
ldy #>$name ldy #>$name
jsr c64flt.MOVMF jsr c64flt.MOVMF
ldx P8ZP_SCRATCH_REG_X
""") """)
asmgen.restoreRegister(CpuRegister.X)
} }
private fun inplaceModification_float_variable_to_variable(name: String, operator: String, ident: IdentifierReference) { private fun inplaceModification_float_variable_to_variable(name: String, operator: String, ident: IdentifierReference) {
@ -1123,10 +1119,10 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
throw AssemblyError("float variable expected") throw AssemblyError("float variable expected")
val otherName = asmgen.asmVariableName(ident) val otherName = asmgen.asmVariableName(ident)
asmgen.saveRegister(CpuRegister.X)
when (operator) { when (operator) {
"**" -> { "**" -> {
asmgen.out(""" asmgen.out("""
stx P8ZP_SCRATCH_REG_X
lda #<$name lda #<$name
ldy #>$name ldy #>$name
jsr c64flt.CONUPK jsr c64flt.CONUPK
@ -1137,7 +1133,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
} }
"+" -> { "+" -> {
asmgen.out(""" asmgen.out("""
stx P8ZP_SCRATCH_REG_X
lda #<$name lda #<$name
ldy #>$name ldy #>$name
jsr c64flt.MOVFM jsr c64flt.MOVFM
@ -1148,7 +1143,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
} }
"-" -> { "-" -> {
asmgen.out(""" asmgen.out("""
stx P8ZP_SCRATCH_REG_X
lda #<$otherName lda #<$otherName
ldy #>$otherName ldy #>$otherName
jsr c64flt.MOVFM jsr c64flt.MOVFM
@ -1159,7 +1153,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
} }
"*" -> { "*" -> {
asmgen.out(""" asmgen.out("""
stx P8ZP_SCRATCH_REG_X
lda #<$name lda #<$name
ldy #>$name ldy #>$name
jsr c64flt.MOVFM jsr c64flt.MOVFM
@ -1170,7 +1163,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
} }
"/" -> { "/" -> {
asmgen.out(""" asmgen.out("""
stx P8ZP_SCRATCH_REG_X
lda #<$otherName lda #<$otherName
ldy #>$otherName ldy #>$otherName
jsr c64flt.MOVFM jsr c64flt.MOVFM
@ -1186,16 +1178,16 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
ldx #<$name ldx #<$name
ldy #>$name ldy #>$name
jsr c64flt.MOVMF jsr c64flt.MOVMF
ldx P8ZP_SCRATCH_REG_X
""") """)
asmgen.restoreRegister(CpuRegister.X)
} }
private fun inplaceModification_float_litval_to_variable(name: String, operator: String, value: Double) { private fun inplaceModification_float_litval_to_variable(name: String, operator: String, value: Double) {
val constValueName = asmgen.getFloatAsmConst(value) val constValueName = asmgen.getFloatAsmConst(value)
asmgen.saveRegister(CpuRegister.X)
when (operator) { when (operator) {
"**" -> { "**" -> {
asmgen.out(""" asmgen.out("""
stx P8ZP_SCRATCH_REG_X
lda #<$name lda #<$name
ldy #>$name ldy #>$name
jsr c64flt.CONUPK jsr c64flt.CONUPK
@ -1208,7 +1200,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
if (value == 0.0) if (value == 0.0)
return return
asmgen.out(""" asmgen.out("""
stx P8ZP_SCRATCH_REG_X
lda #<$name lda #<$name
ldy #>$name ldy #>$name
jsr c64flt.MOVFM jsr c64flt.MOVFM
@ -1221,7 +1212,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
if (value == 0.0) if (value == 0.0)
return return
asmgen.out(""" asmgen.out("""
stx P8ZP_SCRATCH_REG_X
lda #<$constValueName lda #<$constValueName
ldy #>$constValueName ldy #>$constValueName
jsr c64flt.MOVFM jsr c64flt.MOVFM
@ -1232,7 +1222,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
} }
"*" -> { "*" -> {
asmgen.out(""" asmgen.out("""
stx P8ZP_SCRATCH_REG_X
lda #<$name lda #<$name
ldy #>$name ldy #>$name
jsr c64flt.MOVFM jsr c64flt.MOVFM
@ -1245,7 +1234,6 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
if (value == 0.0) if (value == 0.0)
throw AssemblyError("division by zero") throw AssemblyError("division by zero")
asmgen.out(""" asmgen.out("""
stx P8ZP_SCRATCH_REG_X
lda #<$constValueName lda #<$constValueName
ldy #>$constValueName ldy #>$constValueName
jsr c64flt.MOVFM jsr c64flt.MOVFM
@ -1261,8 +1249,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
ldx #<$name ldx #<$name
ldy #>$name ldy #>$name
jsr c64flt.MOVMF jsr c64flt.MOVMF
ldx P8ZP_SCRATCH_REG_X
""") """)
asmgen.restoreRegister(CpuRegister.X)
} }
private fun inplaceCast(target: AsmAssignTarget, cast: TypecastExpression, position: Position) { private fun inplaceCast(target: AsmAssignTarget, cast: TypecastExpression, position: Position) {
@ -1499,8 +1487,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
DataType.FLOAT -> { DataType.FLOAT -> {
when(target.kind) { when(target.kind) {
TargetStorageKind.VARIABLE -> { TargetStorageKind.VARIABLE -> {
asmgen.saveRegister(CpuRegister.X)
asmgen.out(""" asmgen.out("""
stx P8ZP_SCRATCH_REG_X
lda #<${target.asmVarname} lda #<${target.asmVarname}
ldy #>${target.asmVarname} ldy #>${target.asmVarname}
jsr c64flt.MOVFM jsr c64flt.MOVFM
@ -1508,8 +1496,8 @@ internal class AugmentableAssignmentAsmGen(private val program: Program,
ldx #<${target.asmVarname} ldx #<${target.asmVarname}
ldy #>${target.asmVarname} ldy #>${target.asmVarname}
jsr c64flt.MOVMF jsr c64flt.MOVMF
ldx P8ZP_SCRATCH_REG_X
""") """)
asmgen.restoreRegister(CpuRegister.X)
} }
TargetStorageKind.ARRAY -> TODO("in-place negate float array") TargetStorageKind.ARRAY -> TODO("in-place negate float array")
TargetStorageKind.STACK -> TODO("stack float negate") TargetStorageKind.STACK -> TODO("stack float negate")