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

View File

@ -551,7 +551,12 @@ internal class AsmGen(private val program: Program,
internal fun saveRegister(register: CpuRegister) {
when(register) {
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")
}
}
@ -559,7 +564,12 @@ internal class AsmGen(private val program: Program,
internal fun restoreRegister(register: CpuRegister) {
when(register) {
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")
}
}

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 saveX = CpuRegister.X in sub.asmClobbers || sub.regXasResult() || sub.regXasParam()
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)
if(stmt.args.isNotEmpty()) {
@ -57,7 +57,7 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
asmgen.out(" jsr $subName")
if(saveX)
asmgen.out(" ldx P8ZP_SCRATCH_REG_X") // restore X again
asmgen.restoreRegister(CpuRegister.X)
}
private fun registerArgsViaStackEvaluation(stmt: IFunctionCall, sub: Subroutine) {

View File

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