mirror of
https://github.com/irmen/prog8.git
synced 2024-11-19 11:32:17 +00:00
added some cpu stack related assembly-level optimizations
This commit is contained in:
parent
f0dadc4a43
commit
47c2c0376a
@ -7,10 +7,6 @@ import prog8.ast.statements.VarDecl
|
|||||||
import prog8.compilerinterface.IMachineDefinition
|
import prog8.compilerinterface.IMachineDefinition
|
||||||
|
|
||||||
|
|
||||||
// TODO optimize subsequent pha/pla, phx/plx, phy/ply pairs
|
|
||||||
// TODO optimize pha/plx -> tax, pha/ply -> tay, etc.
|
|
||||||
|
|
||||||
|
|
||||||
// note: see https://wiki.nesdev.org/w/index.php/6502_assembly_optimisations
|
// note: see https://wiki.nesdev.org/w/index.php/6502_assembly_optimisations
|
||||||
|
|
||||||
|
|
||||||
@ -357,6 +353,31 @@ private fun optimizeStoreLoadSame(linesByFour: List<List<IndexedValue<String>>>,
|
|||||||
mods.add(Modification(lines[2].index, true, null))
|
mods.add(Modification(lines[2].index, true, null))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if(first=="pha" && second=="pla" ||
|
||||||
|
first=="phx" && second=="plx" ||
|
||||||
|
first=="phy" && second=="ply" ||
|
||||||
|
first=="php" && second=="plp") {
|
||||||
|
mods.add(Modification(lines[1].index, true, null))
|
||||||
|
mods.add(Modification(lines[2].index, true, null))
|
||||||
|
} else if(first=="pha" && second=="plx") {
|
||||||
|
mods.add(Modification(lines[1].index, true, null))
|
||||||
|
mods.add(Modification(lines[2].index, false, " tax"))
|
||||||
|
} else if(first=="pha" && second=="ply") {
|
||||||
|
mods.add(Modification(lines[1].index, true, null))
|
||||||
|
mods.add(Modification(lines[2].index, false, " tay"))
|
||||||
|
} else if(first=="phx" && second=="pla") {
|
||||||
|
mods.add(Modification(lines[1].index, true, null))
|
||||||
|
mods.add(Modification(lines[2].index, false, " txa"))
|
||||||
|
} else if(first=="phx" && second=="ply") {
|
||||||
|
mods.add(Modification(lines[1].index, true, null))
|
||||||
|
mods.add(Modification(lines[2].index, false, " txy"))
|
||||||
|
} else if(first=="phy" && second=="pla") {
|
||||||
|
mods.add(Modification(lines[1].index, true, null))
|
||||||
|
mods.add(Modification(lines[2].index, false, " tya"))
|
||||||
|
} else if(first=="phy" && second=="plx") {
|
||||||
|
mods.add(Modification(lines[1].index, true, null))
|
||||||
|
mods.add(Modification(lines[2].index, false, " tyx"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return mods
|
return mods
|
||||||
}
|
}
|
||||||
|
@ -143,21 +143,6 @@ class StatementOptimizer(private val program: Program,
|
|||||||
return noModifications
|
return noModifications
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO WHAT TO DO WITH THIS:
|
|
||||||
// override fun before(functionCall: FunctionCall, parent: Node): Iterable<IAstModification> {
|
|
||||||
// // if the first instruction in the called subroutine is a return statement with constant value, replace with the constant value
|
|
||||||
// val subroutine = functionCall.target.targetSubroutine(program)
|
|
||||||
// if(subroutine!=null) {
|
|
||||||
// val first = subroutine.statements.asSequence().filterNot { it is VarDecl || it is Directive }.firstOrNull()
|
|
||||||
// if(first is Return && first.value!=null) {
|
|
||||||
// val constval = first.value?.constValue(program)
|
|
||||||
// if(constval!=null)
|
|
||||||
// return listOf(IAstModification.ReplaceNode(functionCall, constval, parent))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return noModifications
|
|
||||||
// }
|
|
||||||
|
|
||||||
override fun after(ifStatement: IfStatement, parent: Node): Iterable<IAstModification> {
|
override fun after(ifStatement: IfStatement, parent: Node): Iterable<IAstModification> {
|
||||||
// remove empty if statements
|
// remove empty if statements
|
||||||
if(ifStatement.truepart.isEmpty() && ifStatement.elsepart.isEmpty())
|
if(ifStatement.truepart.isEmpty() && ifStatement.elsepart.isEmpty())
|
||||||
|
@ -412,9 +412,9 @@ internal class StatementReorderer(val program: Program,
|
|||||||
}
|
}
|
||||||
return listOf(IAstModification.ReplaceNode(call, scope, parent))
|
return listOf(IAstModification.ReplaceNode(call, scope, parent))
|
||||||
} else if(!options.compTarget.asmsubArgsHaveRegisterClobberRisk(call.args)) {
|
} else if(!options.compTarget.asmsubArgsHaveRegisterClobberRisk(call.args)) {
|
||||||
// no register clobber risk, let the asmgen assign values to the registers directly.
|
// No register clobber risk, let the asmgen assign values to the registers directly.
|
||||||
// this is more efficient than first evaluating them to the stack
|
// this is more efficient than first evaluating them to the stack.
|
||||||
// TODO but what about complex expressions?
|
// As complex expressions will be flagged as a clobber-risk, these will be simplified below.
|
||||||
return noModifications
|
return noModifications
|
||||||
} else {
|
} else {
|
||||||
// clobber risk; evaluate the arguments on the CPU stack first (in reverse order)...
|
// clobber risk; evaluate the arguments on the CPU stack first (in reverse order)...
|
||||||
|
@ -1,40 +1,19 @@
|
|||||||
%import textio
|
%import textio
|
||||||
%import string
|
|
||||||
%import test_stack
|
%import test_stack
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
|
||||||
ubyte[23] savedata
|
|
||||||
ubyte[17] cargohold = 0
|
|
||||||
uword filenameptr = $c000
|
|
||||||
|
|
||||||
sub start() {
|
sub start() {
|
||||||
test_stack.test()
|
test_stack.test()
|
||||||
|
|
||||||
save(8, "wob", 0, 10)
|
ubyte x1 = 10
|
||||||
|
ubyte x2 = 20
|
||||||
|
ubyte x3 = 30
|
||||||
|
|
||||||
uword @shared uw
|
x1 += x2+x3 ; TODO WHY SLOW EVAL????
|
||||||
ubyte @shared ub
|
x1 += x2-x3 ; TODO WHY SLOW EVAL????
|
||||||
word @shared ww
|
|
||||||
byte @shared bb
|
|
||||||
|
|
||||||
push(ub+1)
|
txt.print_ub(x1)
|
||||||
pop(ub)
|
|
||||||
txt.print_ub(ub)
|
|
||||||
txt.nl()
|
|
||||||
pushw(32767)
|
|
||||||
popw(uw)
|
|
||||||
txt.print_uw(uw)
|
|
||||||
txt.nl()
|
|
||||||
|
|
||||||
single(ub+1)
|
|
||||||
|
|
||||||
; uw=10000
|
|
||||||
; routines(44,uw+123)
|
|
||||||
; routines2(44,uw+123)
|
|
||||||
;
|
|
||||||
; routine(uw+123, 22,33, true, 44)
|
|
||||||
; routine2(uw+123, 22,33, true, 44)
|
|
||||||
|
|
||||||
test_stack.test()
|
test_stack.test()
|
||||||
|
|
||||||
@ -42,58 +21,4 @@ main {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub save(ubyte drivenumber, uword filenameptr, uword address, uword size) {
|
|
||||||
c64.SETNAM(string.length(filenameptr), filenameptr)
|
|
||||||
}
|
|
||||||
|
|
||||||
sub single(ubyte num) {
|
|
||||||
num++
|
|
||||||
}
|
|
||||||
|
|
||||||
sub routine(uword num, ubyte a1, ubyte a2, ubyte switch, byte a3) {
|
|
||||||
txt.print_uw(num)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_ub(a1)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_ub(a2)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_ub(switch)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_b(a3)
|
|
||||||
txt.nl()
|
|
||||||
}
|
|
||||||
|
|
||||||
sub routines(ubyte bb, uword num) {
|
|
||||||
txt.print_ub(bb)
|
|
||||||
txt.spc()
|
|
||||||
txt.print_uw(num)
|
|
||||||
txt.nl()
|
|
||||||
}
|
|
||||||
|
|
||||||
asmsub routine2(uword num @AY, ubyte a1 @R1, ubyte a2 @R0, ubyte switch @Pc, ubyte a3 @X) {
|
|
||||||
%asm {{
|
|
||||||
sta routine.num
|
|
||||||
sty routine.num+1
|
|
||||||
lda #0
|
|
||||||
adc #0
|
|
||||||
sta routine.switch
|
|
||||||
lda cx16.r0
|
|
||||||
sta routine.a2
|
|
||||||
lda cx16.r1
|
|
||||||
sta routine.a1
|
|
||||||
stx routine.a3
|
|
||||||
jmp routine
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
asmsub routines2(ubyte bb @X, uword num @AY) {
|
|
||||||
%asm {{
|
|
||||||
sta routines.num
|
|
||||||
sty routines.num+1
|
|
||||||
stx routines.bb
|
|
||||||
jmp routines
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user