mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-04-22 03:38:31 +00:00
Added missing RTS after jsr main
This commit is contained in:
parent
9ccc5d828f
commit
ca9453346b
src
main/java/dk/camelot64/kickc
test
java/dk/camelot64/kickc/test
kc
ref
clobber-a-problem.asmclobber-a-problem.log
complex/tetris
const-early-identification.asmconst-early-identification.logfunction-pointer-noarg-call-2.asmfunction-pointer-noarg-call-2.logfunction-pointer-noarg-call-2.symfunction-pointer-noarg-call-3.asmfunction-pointer-noarg-call-3.logfunction-pointer-noarg-call-3.symfunction-pointer-noarg-call-4.asmfunction-pointer-noarg-call-4.logfunction-pointer-noarg-call-4.symfunction-pointer-noarg-call-5.asmfunction-pointer-noarg-call-5.logfunction-pointer-noarg-call-5.symfunction-pointer-noarg-call-6.logfunction-pointer-noarg-call-7.asmfunction-pointer-noarg-call-7.cfgfunction-pointer-noarg-call-7.logfunction-pointer-noarg-call-7.symfunction-pointer-noarg-call-8.asmfunction-pointer-noarg-call-8.cfgfunction-pointer-noarg-call-8.logfunction-pointer-noarg-call-8.symfunction-pointer-noarg-call.loginit-volatiles.asminit-volatiles.loginterrupt-volatile-reuse-problem1.asminterrupt-volatile-reuse-problem1.loginterrupt-volatile-reuse-problem2.asminterrupt-volatile-reuse-problem2.logirq-idx-problem.asmirq-idx-problem.logirq-volatile-bool-problem.asmirq-volatile-bool-problem.loglongbranch-interrupt-problem.asmlongbranch-interrupt-problem.logmultiplexer-irq
test-interrupt-volatile-write.asmtest-interrupt-volatile-write.logtest-interrupt-volatile.asmtest-interrupt-volatile.log@ -249,6 +249,7 @@ public class Compiler {
|
||||
optimizations.add(new Pass2NopCastElimination(program));
|
||||
optimizations.add(new Pass2EliminateUnusedBlocks(program));
|
||||
optimizations.add(new Pass2RangeResolving(program));
|
||||
// optimizations.add(new Pass2ConstantCallPointerIdentification(program));
|
||||
pass2Execute(optimizations);
|
||||
}
|
||||
|
||||
@ -487,6 +488,8 @@ public class Compiler {
|
||||
pass5Optimizations.add(new Pass5DoubleJumpElimination(program));
|
||||
pass5Optimizations.add(new Pass5UnreachableCodeElimination(program));
|
||||
pass5Optimizations.add(new Pass5RelabelLongLabels(program));
|
||||
pass5Optimizations.add(new Pass5SkipBegin(program));
|
||||
pass5Optimizations.add(new Pass5AddMainRts(program));
|
||||
boolean asmOptimized = true;
|
||||
while(asmOptimized) {
|
||||
asmOptimized = false;
|
||||
|
@ -17,9 +17,9 @@ public class StatementCall extends StatementBase implements StatementLValue {
|
||||
|
||||
/** The variable being assigned a value by the call. Can be null. */
|
||||
private LValue lValue;
|
||||
/** The name of the procedure called (if the call is simple). Null if the called procedure is calculated through an expression. */
|
||||
/** The name of the procedure called */
|
||||
private String procedureName;
|
||||
/** The procedure called (if the call is simple). Null if the called procedure is calculated through an expression. */
|
||||
/** The procedure called. */
|
||||
private ProcedureRef procedure;
|
||||
/** The parameter values passed to the procedure. */
|
||||
private List<RValue> parameters;
|
||||
|
@ -249,7 +249,8 @@ public class Pass1GenerateSingleStaticAssignmentForm extends Pass1Base {
|
||||
List<ControlFlowBlock> predecessors = getGraph().getPredecessors(block);
|
||||
Symbol symbol = getScope().getSymbol(block.getLabel());
|
||||
if(symbol instanceof Procedure) {
|
||||
if(((Procedure) symbol).getInterruptType()!=null) {
|
||||
Procedure procedure = (Procedure) symbol;
|
||||
if(procedure.getInterruptType()!=null || Pass2ConstantIdentification.isAddressOfUsed(procedure.getRef(), getProgram())) {
|
||||
// Find all root-level predecessors to the main block
|
||||
ControlFlowBlock mainBlock = getGraph().getBlock(new LabelRef(SymbolRef.MAIN_PROC_NAME));
|
||||
List<ControlFlowBlock> mainPredecessors = getGraph().getPredecessors(mainBlock);
|
||||
|
@ -0,0 +1,74 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.model.ControlFlowBlock;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.statements.Statement;
|
||||
import dk.camelot64.kickc.model.statements.StatementCall;
|
||||
import dk.camelot64.kickc.model.statements.StatementCallPointer;
|
||||
import dk.camelot64.kickc.model.symbols.ConstantVar;
|
||||
import dk.camelot64.kickc.model.types.SymbolType;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypePointer;
|
||||
import dk.camelot64.kickc.model.types.SymbolTypeProcedure;
|
||||
import dk.camelot64.kickc.model.values.*;
|
||||
|
||||
import java.util.ListIterator;
|
||||
|
||||
/** Pass that identified indirect calls to constant function pointers */
|
||||
public class Pass2ConstantCallPointerIdentification extends Pass2SsaOptimization {
|
||||
|
||||
public Pass2ConstantCallPointerIdentification(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean step() {
|
||||
boolean optimized = false;
|
||||
for(ControlFlowBlock block : getGraph().getAllBlocks()) {
|
||||
ListIterator<Statement> statementsIt = block.getStatements().listIterator();
|
||||
while(statementsIt.hasNext()) {
|
||||
Statement statement = statementsIt.next();
|
||||
if(statement instanceof StatementCallPointer) {
|
||||
StatementCallPointer callPointer = (StatementCallPointer) statement;
|
||||
RValue procedure = callPointer.getProcedure();
|
||||
if(procedure instanceof PointerDereferenceSimple) {
|
||||
RValue pointer = ((PointerDereferenceSimple) procedure).getPointer();
|
||||
ProcedureRef constProcedureRef = findConstProcedure(pointer);
|
||||
if(constProcedureRef != null) {
|
||||
statementsIt.remove();
|
||||
StatementCall call = new StatementCall(callPointer.getlValue(), constProcedureRef.getFullName(), callPointer.getParameters(), callPointer.getSource(), callPointer.getComments());
|
||||
call.setProcedure(constProcedureRef);
|
||||
call.setIndex(callPointer.getIndex());
|
||||
block.setCallSuccessor(constProcedureRef.getLabelRef());
|
||||
statementsIt.add(call);
|
||||
getLog().append("Replacing constant pointer function " + call.toString(getProgram(), false));
|
||||
}
|
||||
} else if(procedure instanceof ConstantRef) {
|
||||
ConstantVar procedureVariable = getScope().getConstant((ConstantRef) procedure);
|
||||
SymbolType procedureVariableType = procedureVariable.getType();
|
||||
if(procedureVariableType instanceof SymbolTypePointer) {
|
||||
if(((SymbolTypePointer) procedureVariableType).getElementType() instanceof SymbolTypeProcedure) {
|
||||
optimized = true;
|
||||
throw new RuntimeException("not implemented!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return optimized;
|
||||
}
|
||||
|
||||
private ProcedureRef findConstProcedure(RValue procedurePointer) {
|
||||
if(procedurePointer instanceof ConstantRef) {
|
||||
ConstantVar constant = getScope().getConstant((ConstantRef) procedurePointer);
|
||||
return findConstProcedure(constant.getValue());
|
||||
} else if(procedurePointer instanceof ConstantSymbolPointer) {
|
||||
ConstantSymbolPointer pointer = (ConstantSymbolPointer) procedurePointer;
|
||||
if(pointer.getToSymbol() instanceof ProcedureRef) {
|
||||
return (ProcedureRef) pointer.getToSymbol();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@ -61,7 +61,7 @@ public class Pass3LiveRangesEffectiveAnalysis extends Pass2Base {
|
||||
if(callPaths == null) {
|
||||
callPaths = new LiveRangeVariablesEffective.CallPaths(procedureRef);
|
||||
|
||||
if(procedure.getInterruptType()!=null) {
|
||||
if(procedure.getInterruptType()!=null || Pass2ConstantIdentification.isAddressOfUsed(procedureRef, getProgram())) {
|
||||
// Interrupt is called outside procedure scope - create initial call-path.
|
||||
ArrayList<CallGraph.CallBlock.Call> rootPath = new ArrayList<>();
|
||||
ArrayList<VariableRef> rootAlive = new ArrayList<>();
|
||||
|
@ -639,6 +639,9 @@ public class Pass4CodeGeneration {
|
||||
}
|
||||
}
|
||||
}
|
||||
if(supported) {
|
||||
asm.getCurrentSegment().setClobberOverwrite(AsmClobber.CLOBBER_ALL);
|
||||
}
|
||||
if(!supported) {
|
||||
throw new RuntimeException("Call Pointer not supported " + statement);
|
||||
}
|
||||
|
59
src/main/java/dk/camelot64/kickc/passes/Pass5AddMainRts.java
Normal file
59
src/main/java/dk/camelot64/kickc/passes/Pass5AddMainRts.java
Normal file
@ -0,0 +1,59 @@
|
||||
package dk.camelot64.kickc.passes;
|
||||
|
||||
import dk.camelot64.kickc.asm.*;
|
||||
import dk.camelot64.kickc.model.Program;
|
||||
import dk.camelot64.kickc.model.values.ScopeRef;
|
||||
import dk.camelot64.kickc.model.values.SymbolRef;
|
||||
|
||||
import java.util.ListIterator;
|
||||
|
||||
/**
|
||||
* If the main method is called by JSR this adds an additional RTS
|
||||
*/
|
||||
public class Pass5AddMainRts extends Pass5AsmOptimization {
|
||||
|
||||
public Pass5AddMainRts(Program program) {
|
||||
super(program);
|
||||
}
|
||||
|
||||
public boolean optimize() {
|
||||
for(AsmSegment segment : getAsmProgram().getSegments()) {
|
||||
String scopeLabel = segment.getScopeLabel();
|
||||
if(scopeLabel.equals(ScopeRef.ROOT.getFullName())) {
|
||||
ListIterator<AsmLine> lineIterator = segment.getLines().listIterator();
|
||||
while(lineIterator.hasNext()) {
|
||||
AsmLine line = lineIterator.next();
|
||||
if(line instanceof AsmInstruction) {
|
||||
AsmInstruction instruction = (AsmInstruction) line;
|
||||
if(instruction.getType().getMnemnonic().equals("jsr")) {
|
||||
if(instruction.getParameter().equals(SymbolRef.MAIN_PROC_NAME)) {
|
||||
// Add RTS if it is missing
|
||||
if(!lineIterator.hasNext()) {
|
||||
addRts(lineIterator);
|
||||
return true;
|
||||
}
|
||||
AsmLine nextLine = lineIterator.next();
|
||||
if(!(nextLine instanceof AsmInstruction)) {
|
||||
addRts(lineIterator);
|
||||
return true;
|
||||
}
|
||||
AsmInstruction nextInstruction = (AsmInstruction) nextLine;
|
||||
if(!nextInstruction.getType().getMnemnonic().equals("rts")) {
|
||||
addRts(lineIterator);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void addRts(ListIterator<AsmLine> lineIterator) {
|
||||
lineIterator.add(new AsmInstruction(AsmInstructionSet.getInstructionType("rts", AsmAddressingMode.NON, false), null));
|
||||
getLog().append("Adding RTS to root block ");
|
||||
}
|
||||
|
||||
}
|
@ -42,6 +42,16 @@ public class TestPrograms {
|
||||
compileAndCompare("pointer-pointer-1" );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionPointerNoargCall8() throws IOException, URISyntaxException {
|
||||
compileAndCompare("function-pointer-noarg-call-8");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionPointerNoargCall7() throws IOException, URISyntaxException {
|
||||
compileAndCompare("function-pointer-noarg-call-7");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionPointerNoargCall6() throws IOException, URISyntaxException {
|
||||
compileAndCompare("function-pointer-noarg-call-6");
|
||||
|
26
src/test/kc/function-pointer-noarg-call-7.kc
Normal file
26
src/test/kc/function-pointer-noarg-call-7.kc
Normal file
@ -0,0 +1,26 @@
|
||||
// Tests calling into a function pointer with local variables
|
||||
|
||||
|
||||
void main() {
|
||||
void()* f = &hello;
|
||||
do10(f);
|
||||
}
|
||||
|
||||
void do10(void()* fn) {
|
||||
for( byte i: 0..9)
|
||||
(*fn)();
|
||||
}
|
||||
|
||||
const byte* SCREEN = $0400;
|
||||
const byte[] msg = "hello @";
|
||||
|
||||
volatile byte idx = 0;
|
||||
|
||||
void hello() {
|
||||
byte i=0;
|
||||
do {
|
||||
SCREEN[idx++] = msg[i++];
|
||||
} while(msg[i]!='@');
|
||||
}
|
||||
|
||||
|
31
src/test/kc/function-pointer-noarg-call-8.kc
Normal file
31
src/test/kc/function-pointer-noarg-call-8.kc
Normal file
@ -0,0 +1,31 @@
|
||||
// Tests calling into a function pointer with local variables
|
||||
|
||||
|
||||
void main() {
|
||||
void()* f = &hello;
|
||||
msg = msg1;
|
||||
do10(f);
|
||||
msg = msg2;
|
||||
do10(f);
|
||||
}
|
||||
|
||||
void do10(void()* fn) {
|
||||
for( byte i: 0..9)
|
||||
(*fn)();
|
||||
}
|
||||
|
||||
const byte* SCREEN = $0400;
|
||||
|
||||
const byte[] msg1 = "hello @";
|
||||
const byte[] msg2 = "world @";
|
||||
volatile byte* msg;
|
||||
volatile byte idx = 0;
|
||||
|
||||
void hello() {
|
||||
byte i=0;
|
||||
do {
|
||||
SCREEN[idx++] = msg[i++];
|
||||
} while(msg[i]!='@');
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ bbegin:
|
||||
lda #0
|
||||
sta irq_raster_next
|
||||
jsr main
|
||||
rts
|
||||
main: {
|
||||
lda #<irq
|
||||
sta KERNEL_IRQ
|
||||
|
@ -463,6 +463,8 @@ Removing instruction bend:
|
||||
Removing instruction breturn:
|
||||
Removing instruction b2:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Adding RTS to root block
|
||||
Succesful ASM optimization Pass5AddMainRts
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
@ -500,7 +502,7 @@ reg byte a [ irq::$0 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 153
|
||||
Score: 159
|
||||
|
||||
//SEG0 File Comments
|
||||
//SEG1 Basic Upstart
|
||||
@ -524,6 +526,7 @@ bbegin:
|
||||
//SEG7 @2
|
||||
//SEG8 [3] call main
|
||||
jsr main
|
||||
rts
|
||||
//SEG9 [4] phi from @2 to @end [phi:@2->@end]
|
||||
//SEG10 @end
|
||||
//SEG11 main
|
||||
|
@ -84,6 +84,7 @@ bbegin:
|
||||
lda #0
|
||||
sta irq_cnt
|
||||
jsr main
|
||||
rts
|
||||
main: {
|
||||
.const toSpritePtr2_return = SIN_SPRITE>>6
|
||||
.const vicSelectGfxBank1_toDd001_return = 3^(>PLAYFIELD_SCREEN_1)>>6
|
||||
|
@ -3781,6 +3781,8 @@ Removing instruction b6:
|
||||
Removing instruction b7:
|
||||
Removing instruction b11:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Adding RTS to root block
|
||||
Succesful ASM optimization Pass5AddMainRts
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp b4
|
||||
Removing instruction jmp b1
|
||||
@ -4104,7 +4106,7 @@ reg byte a [ sprites_irq::ptr#2 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 7304
|
||||
Score: 7310
|
||||
|
||||
//SEG0 File Comments
|
||||
//SEG1 Basic Upstart
|
||||
@ -4214,6 +4216,7 @@ bbegin:
|
||||
//SEG20 [11] call main
|
||||
//SEG21 [13] phi from @4 to main [phi:@4->main]
|
||||
jsr main
|
||||
rts
|
||||
//SEG22 [12] phi from @4 to @end [phi:@4->@end]
|
||||
//SEG23 @end
|
||||
//SEG24 main
|
||||
|
@ -183,6 +183,7 @@ bbegin:
|
||||
lda #0
|
||||
sta irq_cnt
|
||||
jsr main
|
||||
rts
|
||||
main: {
|
||||
jsr sid_rnd_init
|
||||
sei
|
||||
|
@ -22376,6 +22376,8 @@ Relabelling long label b1_from_b20 to b4
|
||||
Relabelling long label b9_from_b10 to b5
|
||||
Relabelling long label b9_from_b19 to b6
|
||||
Succesful ASM optimization Pass5RelabelLongLabels
|
||||
Adding RTS to root block
|
||||
Succesful ASM optimization Pass5AddMainRts
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp b3
|
||||
Removing instruction jmp b4
|
||||
@ -23740,7 +23742,7 @@ reg byte a [ sprites_irq::ptr#2 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 3350872
|
||||
Score: 3350878
|
||||
|
||||
//SEG0 File Comments
|
||||
// Tetris Game for the Commodore 64
|
||||
@ -23950,6 +23952,7 @@ bbegin:
|
||||
//SEG21 [12] call main
|
||||
//SEG22 [14] phi from @4 to main [phi:@4->main]
|
||||
jsr main
|
||||
rts
|
||||
//SEG23 [13] phi from @4 to @end [phi:@4->@end]
|
||||
//SEG24 @end
|
||||
//SEG25 main
|
||||
|
@ -9,6 +9,7 @@ bbegin:
|
||||
lda #'a'
|
||||
sta A
|
||||
jsr main
|
||||
rts
|
||||
main: {
|
||||
.const B = 'b'
|
||||
.label addrA = A
|
||||
|
@ -324,6 +324,8 @@ Removing instruction bend:
|
||||
Removing instruction breturn:
|
||||
Removing instruction breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Adding RTS to root block
|
||||
Succesful ASM optimization Pass5AddMainRts
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
@ -351,7 +353,7 @@ reg byte x [ sub::D#0 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 65
|
||||
Score: 71
|
||||
|
||||
//SEG0 File Comments
|
||||
// Tests that constants are identified early
|
||||
@ -372,6 +374,7 @@ bbegin:
|
||||
//SEG6 @1
|
||||
//SEG7 [2] call main
|
||||
jsr main
|
||||
rts
|
||||
//SEG8 [3] phi from @1 to @end [phi:@1->@end]
|
||||
//SEG9 @end
|
||||
//SEG10 main
|
||||
|
@ -3,12 +3,14 @@
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
main: {
|
||||
.label f = 2
|
||||
ldx #0
|
||||
.label i = 2
|
||||
.label f = 3
|
||||
lda #0
|
||||
sta i
|
||||
b2:
|
||||
inx
|
||||
txa
|
||||
and #1
|
||||
inc i
|
||||
lda #1
|
||||
and i
|
||||
cmp #0
|
||||
beq b1
|
||||
lda #<fn2
|
||||
|
@ -326,7 +326,13 @@ fn1: {
|
||||
}
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 , reg byte a , reg byte x , reg byte y ,
|
||||
Statement [11] call *((void()*) main::f#3) [ main::i#1 ] ( main:2 [ main::i#1 ] ) always clobbers reg byte a reg byte x reg byte y
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Removing always clobbered register reg byte x as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Statement [7] (byte~) main::$0 ← (byte) main::i#1 & (byte/signed byte/word/signed word/dword/signed dword) 1 [ main::i#1 main::$0 ] ( main:2 [ main::i#1 main::$0 ] ) always clobbers reg byte a
|
||||
Statement [11] call *((void()*) main::f#3) [ main::i#1 ] ( main:2 [ main::i#1 ] ) always clobbers reg byte a reg byte x reg byte y
|
||||
Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 ,
|
||||
Potential registers zp ZP_WORD:3 [ main::f#3 ] : zp ZP_WORD:3 ,
|
||||
Potential registers zp ZP_BYTE:5 [ main::$0 ] : zp ZP_BYTE:5 , reg byte a , reg byte x , reg byte y ,
|
||||
|
||||
@ -336,11 +342,12 @@ Uplift Scope [fn1]
|
||||
Uplift Scope [fn2]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 657 combination reg byte x [ main::i#2 main::i#1 ] reg byte a [ main::$0 ] zp ZP_WORD:3 [ main::f#3 ]
|
||||
Uplifting [fn1] best 657 combination
|
||||
Uplifting [fn2] best 657 combination
|
||||
Uplifting [] best 657 combination
|
||||
Allocated (was zp ZP_WORD:3) zp ZP_WORD:2 [ main::f#3 ]
|
||||
Uplifting [main] best 727 combination zp ZP_BYTE:2 [ main::i#2 main::i#1 ] reg byte a [ main::$0 ] zp ZP_WORD:3 [ main::f#3 ]
|
||||
Uplifting [fn1] best 727 combination
|
||||
Uplifting [fn2] best 727 combination
|
||||
Uplifting [] best 727 combination
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Uplifting [main] best 727 combination zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
//SEG0 File Comments
|
||||
@ -368,22 +375,24 @@ bend_from_b1:
|
||||
bend:
|
||||
//SEG10 main
|
||||
main: {
|
||||
.label f = 2
|
||||
.label i = 2
|
||||
.label f = 3
|
||||
//SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
b1_from_main:
|
||||
//SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
//SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta i
|
||||
jmp b1
|
||||
//SEG13 main::@1
|
||||
b1:
|
||||
jmp b2
|
||||
//SEG14 main::@2
|
||||
b2:
|
||||
//SEG15 [6] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
//SEG16 [7] (byte~) main::$0 ← (byte) main::i#1 & (byte/signed byte/word/signed word/dword/signed dword) 1 -- vbuaa=vbuxx_band_vbuc1
|
||||
txa
|
||||
and #1
|
||||
//SEG15 [6] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc i
|
||||
//SEG16 [7] (byte~) main::$0 ← (byte) main::i#1 & (byte/signed byte/word/signed word/dword/signed dword) 1 -- vbuaa=vbuz1_band_vbuc1
|
||||
lda #1
|
||||
and i
|
||||
//SEG17 [8] if((byte~) main::$0==(byte/signed byte/word/signed word/dword/signed dword) 0) goto main::@3 -- vbuaa_eq_0_then_la1
|
||||
cmp #0
|
||||
beq b3_from_b2
|
||||
@ -496,18 +505,18 @@ FINAL SYMBOL TABLE
|
||||
(label) main::@4
|
||||
(byte*) main::SCREEN
|
||||
(void()*) main::f
|
||||
(void()*) main::f#3 f zp ZP_WORD:2
|
||||
(void()*) main::f#3 f zp ZP_WORD:3
|
||||
(byte) main::i
|
||||
(byte) main::i#1 reg byte x 5.5
|
||||
(byte) main::i#2 reg byte x 22.0
|
||||
(byte) main::i#1 i zp ZP_BYTE:2 5.5
|
||||
(byte) main::i#2 i zp ZP_BYTE:2 22.0
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
||||
zp ZP_WORD:2 [ main::f#3 ]
|
||||
zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
zp ZP_WORD:3 [ main::f#3 ]
|
||||
reg byte a [ main::$0 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 519
|
||||
Score: 589
|
||||
|
||||
//SEG0 File Comments
|
||||
// Tests creating, assigning and calling pointers to non-args no-return functions
|
||||
@ -525,18 +534,20 @@ Score: 519
|
||||
//SEG9 @end
|
||||
//SEG10 main
|
||||
main: {
|
||||
.label f = 2
|
||||
.label i = 2
|
||||
.label f = 3
|
||||
//SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
//SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
//SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta i
|
||||
//SEG13 main::@1
|
||||
//SEG14 main::@2
|
||||
b2:
|
||||
//SEG15 [6] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
//SEG16 [7] (byte~) main::$0 ← (byte) main::i#1 & (byte/signed byte/word/signed word/dword/signed dword) 1 -- vbuaa=vbuxx_band_vbuc1
|
||||
txa
|
||||
and #1
|
||||
//SEG15 [6] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc i
|
||||
//SEG16 [7] (byte~) main::$0 ← (byte) main::i#1 & (byte/signed byte/word/signed word/dword/signed dword) 1 -- vbuaa=vbuz1_band_vbuc1
|
||||
lda #1
|
||||
and i
|
||||
//SEG17 [8] if((byte~) main::$0==(byte/signed byte/word/signed word/dword/signed dword) 0) goto main::@3 -- vbuaa_eq_0_then_la1
|
||||
cmp #0
|
||||
beq b1
|
||||
|
@ -17,11 +17,11 @@
|
||||
(label) main::@4
|
||||
(byte*) main::SCREEN
|
||||
(void()*) main::f
|
||||
(void()*) main::f#3 f zp ZP_WORD:2
|
||||
(void()*) main::f#3 f zp ZP_WORD:3
|
||||
(byte) main::i
|
||||
(byte) main::i#1 reg byte x 5.5
|
||||
(byte) main::i#2 reg byte x 22.0
|
||||
(byte) main::i#1 i zp ZP_BYTE:2 5.5
|
||||
(byte) main::i#2 i zp ZP_BYTE:2 22.0
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
||||
zp ZP_WORD:2 [ main::f#3 ]
|
||||
zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
zp ZP_WORD:3 [ main::f#3 ]
|
||||
reg byte a [ main::$0 ]
|
||||
|
@ -3,11 +3,13 @@
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
main: {
|
||||
.label _1 = 2
|
||||
ldx #0
|
||||
.label _1 = 3
|
||||
.label i = 2
|
||||
lda #0
|
||||
sta i
|
||||
b2:
|
||||
inx
|
||||
txa
|
||||
inc i
|
||||
lda i
|
||||
jsr getfn
|
||||
jsr bi__1
|
||||
jmp b2
|
||||
@ -16,7 +18,7 @@ main: {
|
||||
}
|
||||
// getfn(byte register(A) b)
|
||||
getfn: {
|
||||
.label return = 2
|
||||
.label return = 3
|
||||
and #1
|
||||
cmp #0
|
||||
beq b1
|
||||
|
@ -390,9 +390,13 @@ REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [9] (void()*) getfn::return#0 ← (void()*) getfn::return#3 [ main::i#1 getfn::return#0 ] ( main:2 [ main::i#1 getfn::return#0 ] ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Statement [10] (void()*~) main::$1 ← (void()*) getfn::return#0 [ main::i#1 main::$1 ] ( main:2 [ main::i#1 main::$1 ] ) always clobbers reg byte a
|
||||
Statement [11] call (void()*~) main::$1 [ main::i#1 ] ( main:2 [ main::i#1 ] ) always clobbers reg byte a reg byte x reg byte y
|
||||
Removing always clobbered register reg byte x as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Statement [9] (void()*) getfn::return#0 ← (void()*) getfn::return#3 [ main::i#1 getfn::return#0 ] ( main:2 [ main::i#1 getfn::return#0 ] ) always clobbers reg byte a
|
||||
Statement [10] (void()*~) main::$1 ← (void()*) getfn::return#0 [ main::i#1 main::$1 ] ( main:2 [ main::i#1 main::$1 ] ) always clobbers reg byte a
|
||||
Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 , reg byte x , reg byte y ,
|
||||
Statement [11] call (void()*~) main::$1 [ main::i#1 ] ( main:2 [ main::i#1 ] ) always clobbers reg byte a reg byte x reg byte y
|
||||
Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 ,
|
||||
Potential registers zp ZP_WORD:3 [ getfn::return#3 ] : zp ZP_WORD:3 ,
|
||||
Potential registers zp ZP_BYTE:5 [ getfn::b#0 ] : zp ZP_BYTE:5 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_WORD:6 [ getfn::return#0 ] : zp ZP_WORD:6 ,
|
||||
@ -407,13 +411,14 @@ Uplift Scope [fn2]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [getfn] best 743 combination zp ZP_WORD:6 [ getfn::return#0 ] reg byte a [ getfn::b#0 ] reg byte a [ getfn::$0 ] zp ZP_WORD:3 [ getfn::return#3 ]
|
||||
Uplifting [main] best 673 combination reg byte x [ main::i#2 main::i#1 ] zp ZP_WORD:8 [ main::$1 ]
|
||||
Uplifting [fn1] best 673 combination
|
||||
Uplifting [fn2] best 673 combination
|
||||
Uplifting [] best 673 combination
|
||||
Uplifting [main] best 743 combination zp ZP_BYTE:2 [ main::i#2 main::i#1 ] zp ZP_WORD:8 [ main::$1 ]
|
||||
Uplifting [fn1] best 743 combination
|
||||
Uplifting [fn2] best 743 combination
|
||||
Uplifting [] best 743 combination
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Uplifting [main] best 743 combination zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Coalescing zero page register with common assignment [ zp ZP_WORD:3 [ getfn::return#3 ] ] with [ zp ZP_WORD:6 [ getfn::return#0 ] ] - score: 1
|
||||
Coalescing zero page register with common assignment [ zp ZP_WORD:3 [ getfn::return#3 getfn::return#0 ] ] with [ zp ZP_WORD:8 [ main::$1 ] ] - score: 1
|
||||
Allocated (was zp ZP_WORD:3) zp ZP_WORD:2 [ getfn::return#3 getfn::return#0 main::$1 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
//SEG0 File Comments
|
||||
@ -441,21 +446,23 @@ bend_from_b1:
|
||||
bend:
|
||||
//SEG10 main
|
||||
main: {
|
||||
.label _1 = 2
|
||||
.label _1 = 3
|
||||
.label i = 2
|
||||
//SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
b1_from_main:
|
||||
//SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
//SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta i
|
||||
jmp b1
|
||||
//SEG13 main::@1
|
||||
b1:
|
||||
jmp b2
|
||||
//SEG14 main::@2
|
||||
b2:
|
||||
//SEG15 [6] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
//SEG16 [7] (byte) getfn::b#0 ← (byte) main::i#1 -- vbuaa=vbuxx
|
||||
txa
|
||||
//SEG15 [6] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc i
|
||||
//SEG16 [7] (byte) getfn::b#0 ← (byte) main::i#1 -- vbuaa=vbuz1
|
||||
lda i
|
||||
//SEG17 [8] call getfn
|
||||
jsr getfn
|
||||
//SEG18 [9] (void()*) getfn::return#0 ← (void()*) getfn::return#3
|
||||
@ -475,7 +482,7 @@ main: {
|
||||
//SEG24 getfn
|
||||
// getfn(byte register(A) b)
|
||||
getfn: {
|
||||
.label return = 2
|
||||
.label return = 3
|
||||
//SEG25 [12] (byte~) getfn::$0 ← (byte) getfn::b#0 & (byte/signed byte/word/signed word/dword/signed dword) 1 -- vbuaa=vbuaa_band_vbuc1
|
||||
and #1
|
||||
//SEG26 [13] if((byte~) getfn::$0==(byte/signed byte/word/signed word/dword/signed dword) 0) goto getfn::@return -- vbuaa_eq_0_then_la1
|
||||
@ -585,25 +592,25 @@ FINAL SYMBOL TABLE
|
||||
(byte) getfn::b
|
||||
(byte) getfn::b#0 reg byte a 13.0
|
||||
(void()*) getfn::return
|
||||
(void()*) getfn::return#0 return zp ZP_WORD:2 22.0
|
||||
(void()*) getfn::return#3 return zp ZP_WORD:2 3.6666666666666665
|
||||
(void()*) getfn::return#0 return zp ZP_WORD:3 22.0
|
||||
(void()*) getfn::return#3 return zp ZP_WORD:3 3.6666666666666665
|
||||
(void()) main()
|
||||
(void()*~) main::$1 $1 zp ZP_WORD:2 11.0
|
||||
(void()*~) main::$1 $1 zp ZP_WORD:3 11.0
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@3
|
||||
(byte) main::i
|
||||
(byte) main::i#1 reg byte x 5.5
|
||||
(byte) main::i#2 reg byte x 22.0
|
||||
(byte) main::i#1 i zp ZP_BYTE:2 5.5
|
||||
(byte) main::i#2 i zp ZP_BYTE:2 22.0
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
||||
zp ZP_WORD:2 [ getfn::return#3 getfn::return#0 main::$1 ]
|
||||
zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
zp ZP_WORD:3 [ getfn::return#3 getfn::return#0 main::$1 ]
|
||||
reg byte a [ getfn::b#0 ]
|
||||
reg byte a [ getfn::$0 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 319
|
||||
Score: 389
|
||||
|
||||
//SEG0 File Comments
|
||||
// Tests creating, assigning returning and calling pointers to non-args no-return functions
|
||||
@ -621,17 +628,19 @@ Score: 319
|
||||
//SEG9 @end
|
||||
//SEG10 main
|
||||
main: {
|
||||
.label _1 = 2
|
||||
.label _1 = 3
|
||||
.label i = 2
|
||||
//SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
//SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
//SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta i
|
||||
//SEG13 main::@1
|
||||
//SEG14 main::@2
|
||||
b2:
|
||||
//SEG15 [6] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
//SEG16 [7] (byte) getfn::b#0 ← (byte) main::i#1 -- vbuaa=vbuxx
|
||||
txa
|
||||
//SEG15 [6] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc i
|
||||
//SEG16 [7] (byte) getfn::b#0 ← (byte) main::i#1 -- vbuaa=vbuz1
|
||||
lda i
|
||||
//SEG17 [8] call getfn
|
||||
jsr getfn
|
||||
//SEG18 [9] (void()*) getfn::return#0 ← (void()*) getfn::return#3
|
||||
@ -648,7 +657,7 @@ main: {
|
||||
//SEG24 getfn
|
||||
// getfn(byte register(A) b)
|
||||
getfn: {
|
||||
.label return = 2
|
||||
.label return = 3
|
||||
//SEG25 [12] (byte~) getfn::$0 ← (byte) getfn::b#0 & (byte/signed byte/word/signed word/dword/signed dword) 1 -- vbuaa=vbuaa_band_vbuc1
|
||||
and #1
|
||||
//SEG26 [13] if((byte~) getfn::$0==(byte/signed byte/word/signed word/dword/signed dword) 0) goto getfn::@return -- vbuaa_eq_0_then_la1
|
||||
|
@ -16,18 +16,18 @@
|
||||
(byte) getfn::b
|
||||
(byte) getfn::b#0 reg byte a 13.0
|
||||
(void()*) getfn::return
|
||||
(void()*) getfn::return#0 return zp ZP_WORD:2 22.0
|
||||
(void()*) getfn::return#3 return zp ZP_WORD:2 3.6666666666666665
|
||||
(void()*) getfn::return#0 return zp ZP_WORD:3 22.0
|
||||
(void()*) getfn::return#3 return zp ZP_WORD:3 3.6666666666666665
|
||||
(void()) main()
|
||||
(void()*~) main::$1 $1 zp ZP_WORD:2 11.0
|
||||
(void()*~) main::$1 $1 zp ZP_WORD:3 11.0
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@3
|
||||
(byte) main::i
|
||||
(byte) main::i#1 reg byte x 5.5
|
||||
(byte) main::i#2 reg byte x 22.0
|
||||
(byte) main::i#1 i zp ZP_BYTE:2 5.5
|
||||
(byte) main::i#2 i zp ZP_BYTE:2 22.0
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
||||
zp ZP_WORD:2 [ getfn::return#3 getfn::return#0 main::$1 ]
|
||||
zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
zp ZP_WORD:3 [ getfn::return#3 getfn::return#0 main::$1 ]
|
||||
reg byte a [ getfn::b#0 ]
|
||||
reg byte a [ getfn::$0 ]
|
||||
|
@ -3,10 +3,12 @@
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
main: {
|
||||
.label i = 2
|
||||
lda #0
|
||||
sta i
|
||||
b2:
|
||||
clc
|
||||
adc #1
|
||||
inc i
|
||||
lda i
|
||||
jsr getfn
|
||||
jsr getfn.return
|
||||
jmp b2
|
||||
|
@ -267,7 +267,12 @@ fn1: {
|
||||
}
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 , reg byte a , reg byte x , reg byte y ,
|
||||
Statement [9] call (const void()*) getfn::return#1 [ main::i#1 ] ( main:2 [ main::i#1 ] ) always clobbers reg byte a reg byte x reg byte y
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Removing always clobbered register reg byte x as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Statement [9] call (const void()*) getfn::return#1 [ main::i#1 ] ( main:2 [ main::i#1 ] ) always clobbers reg byte a reg byte x reg byte y
|
||||
Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 ,
|
||||
Potential registers zp ZP_BYTE:3 [ getfn::b#0 ] : zp ZP_BYTE:3 , reg byte a , reg byte x , reg byte y ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
@ -277,9 +282,11 @@ Uplift Scope [fn1]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [getfn] best 352 combination reg byte a [ getfn::b#0 ]
|
||||
Uplifting [main] best 282 combination reg byte a [ main::i#2 main::i#1 ]
|
||||
Uplifting [fn1] best 282 combination
|
||||
Uplifting [] best 282 combination
|
||||
Uplifting [main] best 352 combination zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Uplifting [fn1] best 352 combination
|
||||
Uplifting [] best 352 combination
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Uplifting [main] best 352 combination zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
//SEG0 File Comments
|
||||
@ -307,20 +314,22 @@ bend_from_b1:
|
||||
bend:
|
||||
//SEG10 main
|
||||
main: {
|
||||
.label i = 2
|
||||
//SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
b1_from_main:
|
||||
//SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuaa=vbuc1
|
||||
//SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta i
|
||||
jmp b1
|
||||
//SEG13 main::@1
|
||||
b1:
|
||||
jmp b2
|
||||
//SEG14 main::@2
|
||||
b2:
|
||||
//SEG15 [6] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuaa=_inc_vbuaa
|
||||
clc
|
||||
adc #1
|
||||
//SEG16 [7] (byte) getfn::b#0 ← (byte) main::i#1
|
||||
//SEG15 [6] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc i
|
||||
//SEG16 [7] (byte) getfn::b#0 ← (byte) main::i#1 -- vbuaa=vbuz1
|
||||
lda i
|
||||
//SEG17 [8] call getfn
|
||||
//SEG18 [10] phi from main::@2 to getfn [phi:main::@2->getfn]
|
||||
getfn_from_b2:
|
||||
@ -406,15 +415,15 @@ FINAL SYMBOL TABLE
|
||||
(label) main::@2
|
||||
(label) main::@3
|
||||
(byte) main::i
|
||||
(byte) main::i#1 reg byte a 8.25
|
||||
(byte) main::i#2 reg byte a 22.0
|
||||
(byte) main::i#1 i zp ZP_BYTE:2 8.25
|
||||
(byte) main::i#2 i zp ZP_BYTE:2 22.0
|
||||
|
||||
reg byte a [ main::i#2 main::i#1 ]
|
||||
zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
reg byte a [ getfn::b#0 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 174
|
||||
Score: 244
|
||||
|
||||
//SEG0 File Comments
|
||||
// Tests creating, assigning returning and calling pointers to non-args no-return functions
|
||||
@ -432,16 +441,18 @@ Score: 174
|
||||
//SEG9 @end
|
||||
//SEG10 main
|
||||
main: {
|
||||
.label i = 2
|
||||
//SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
//SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuaa=vbuc1
|
||||
//SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta i
|
||||
//SEG13 main::@1
|
||||
//SEG14 main::@2
|
||||
b2:
|
||||
//SEG15 [6] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuaa=_inc_vbuaa
|
||||
clc
|
||||
adc #1
|
||||
//SEG16 [7] (byte) getfn::b#0 ← (byte) main::i#1
|
||||
//SEG15 [6] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc i
|
||||
//SEG16 [7] (byte) getfn::b#0 ← (byte) main::i#1 -- vbuaa=vbuz1
|
||||
lda i
|
||||
//SEG17 [8] call getfn
|
||||
//SEG18 [10] phi from main::@2 to getfn [phi:main::@2->getfn]
|
||||
jsr getfn
|
||||
|
@ -16,8 +16,8 @@
|
||||
(label) main::@2
|
||||
(label) main::@3
|
||||
(byte) main::i
|
||||
(byte) main::i#1 reg byte a 8.25
|
||||
(byte) main::i#2 reg byte a 22.0
|
||||
(byte) main::i#1 i zp ZP_BYTE:2 8.25
|
||||
(byte) main::i#2 i zp ZP_BYTE:2 22.0
|
||||
|
||||
reg byte a [ main::i#2 main::i#1 ]
|
||||
zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
reg byte a [ getfn::b#0 ]
|
||||
|
@ -3,12 +3,14 @@
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
main: {
|
||||
.label f = 2
|
||||
ldx #0
|
||||
.label i = 2
|
||||
.label f = 3
|
||||
lda #0
|
||||
sta i
|
||||
b2:
|
||||
inx
|
||||
txa
|
||||
and #1
|
||||
inc i
|
||||
lda #1
|
||||
and i
|
||||
asl
|
||||
tay
|
||||
lda fns,y
|
||||
|
@ -275,10 +275,14 @@ REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [8] (byte~) main::$1 ← (byte~) main::$0 << (byte/signed byte/word/signed word/dword/signed dword) 1 [ main::i#1 main::$1 ] ( main:2 [ main::i#1 main::$1 ] ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Statement [9] (void()*) main::f#0 ← *((const void()*[2]) fns#0 + (byte~) main::$1) [ main::i#1 main::f#0 ] ( main:2 [ main::i#1 main::f#0 ] ) always clobbers reg byte a
|
||||
Statement [10] call *((void()*) main::f#0) [ main::i#1 ] ( main:2 [ main::i#1 ] ) always clobbers reg byte a reg byte x reg byte y
|
||||
Removing always clobbered register reg byte x as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Statement [7] (byte~) main::$0 ← (byte) main::i#1 & (byte/signed byte/word/signed word/dword/signed dword) 1 [ main::i#1 main::$0 ] ( main:2 [ main::i#1 main::$0 ] ) always clobbers reg byte a
|
||||
Statement [8] (byte~) main::$1 ← (byte~) main::$0 << (byte/signed byte/word/signed word/dword/signed dword) 1 [ main::i#1 main::$1 ] ( main:2 [ main::i#1 main::$1 ] ) always clobbers reg byte a
|
||||
Statement [9] (void()*) main::f#0 ← *((const void()*[2]) fns#0 + (byte~) main::$1) [ main::i#1 main::f#0 ] ( main:2 [ main::i#1 main::f#0 ] ) always clobbers reg byte a
|
||||
Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 , reg byte x , reg byte y ,
|
||||
Statement [10] call *((void()*) main::f#0) [ main::i#1 ] ( main:2 [ main::i#1 ] ) always clobbers reg byte a reg byte x reg byte y
|
||||
Potential registers zp ZP_BYTE:2 [ main::i#2 main::i#1 ] : zp ZP_BYTE:2 ,
|
||||
Potential registers zp ZP_BYTE:3 [ main::$0 ] : zp ZP_BYTE:3 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:4 [ main::$1 ] : zp ZP_BYTE:4 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_WORD:5 [ main::f#0 ] : zp ZP_WORD:5 ,
|
||||
@ -289,11 +293,13 @@ Uplift Scope [fn1]
|
||||
Uplift Scope [fn2]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 512 combination reg byte x [ main::i#2 main::i#1 ] reg byte a [ main::$0 ] reg byte a [ main::$1 ] zp ZP_WORD:5 [ main::f#0 ]
|
||||
Uplifting [fn1] best 512 combination
|
||||
Uplifting [fn2] best 512 combination
|
||||
Uplifting [] best 512 combination
|
||||
Allocated (was zp ZP_WORD:5) zp ZP_WORD:2 [ main::f#0 ]
|
||||
Uplifting [main] best 582 combination zp ZP_BYTE:2 [ main::i#2 main::i#1 ] reg byte a [ main::$0 ] reg byte a [ main::$1 ] zp ZP_WORD:5 [ main::f#0 ]
|
||||
Uplifting [fn1] best 582 combination
|
||||
Uplifting [fn2] best 582 combination
|
||||
Uplifting [] best 582 combination
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Uplifting [main] best 582 combination zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
Allocated (was zp ZP_WORD:5) zp ZP_WORD:3 [ main::f#0 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
//SEG0 File Comments
|
||||
@ -321,22 +327,24 @@ bend_from_b1:
|
||||
bend:
|
||||
//SEG10 main
|
||||
main: {
|
||||
.label f = 2
|
||||
.label i = 2
|
||||
.label f = 3
|
||||
//SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
b1_from_main:
|
||||
//SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
//SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta i
|
||||
jmp b1
|
||||
//SEG13 main::@1
|
||||
b1:
|
||||
jmp b2
|
||||
//SEG14 main::@2
|
||||
b2:
|
||||
//SEG15 [6] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
//SEG16 [7] (byte~) main::$0 ← (byte) main::i#1 & (byte/signed byte/word/signed word/dword/signed dword) 1 -- vbuaa=vbuxx_band_vbuc1
|
||||
txa
|
||||
and #1
|
||||
//SEG15 [6] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc i
|
||||
//SEG16 [7] (byte~) main::$0 ← (byte) main::i#1 & (byte/signed byte/word/signed word/dword/signed dword) 1 -- vbuaa=vbuz1_band_vbuc1
|
||||
lda #1
|
||||
and i
|
||||
//SEG17 [8] (byte~) main::$1 ← (byte~) main::$0 << (byte/signed byte/word/signed word/dword/signed dword) 1 -- vbuaa=vbuaa_rol_1
|
||||
asl
|
||||
//SEG18 [9] (void()*) main::f#0 ← *((const void()*[2]) fns#0 + (byte~) main::$1) -- pprz1=pptc1_derefidx_vbuaa
|
||||
@ -425,19 +433,19 @@ FINAL SYMBOL TABLE
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(void()*) main::f
|
||||
(void()*) main::f#0 f zp ZP_WORD:2 11.0
|
||||
(void()*) main::f#0 f zp ZP_WORD:3 11.0
|
||||
(byte) main::i
|
||||
(byte) main::i#1 reg byte x 6.6000000000000005
|
||||
(byte) main::i#2 reg byte x 22.0
|
||||
(byte) main::i#1 i zp ZP_BYTE:2 6.6000000000000005
|
||||
(byte) main::i#2 i zp ZP_BYTE:2 22.0
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
||||
zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
reg byte a [ main::$0 ]
|
||||
reg byte a [ main::$1 ]
|
||||
zp ZP_WORD:2 [ main::f#0 ]
|
||||
zp ZP_WORD:3 [ main::f#0 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 434
|
||||
Score: 504
|
||||
|
||||
//SEG0 File Comments
|
||||
// Tests calling into arrays of pointers to non-args no-return functions
|
||||
@ -455,18 +463,20 @@ Score: 434
|
||||
//SEG9 @end
|
||||
//SEG10 main
|
||||
main: {
|
||||
.label f = 2
|
||||
.label i = 2
|
||||
.label f = 3
|
||||
//SEG11 [5] phi from main to main::@1 [phi:main->main::@1]
|
||||
//SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
//SEG12 [5] phi (byte) main::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:main->main::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta i
|
||||
//SEG13 main::@1
|
||||
//SEG14 main::@2
|
||||
b2:
|
||||
//SEG15 [6] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
//SEG16 [7] (byte~) main::$0 ← (byte) main::i#1 & (byte/signed byte/word/signed word/dword/signed dword) 1 -- vbuaa=vbuxx_band_vbuc1
|
||||
txa
|
||||
and #1
|
||||
//SEG15 [6] (byte) main::i#1 ← ++ (byte) main::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc i
|
||||
//SEG16 [7] (byte~) main::$0 ← (byte) main::i#1 & (byte/signed byte/word/signed word/dword/signed dword) 1 -- vbuaa=vbuz1_band_vbuc1
|
||||
lda #1
|
||||
and i
|
||||
//SEG17 [8] (byte~) main::$1 ← (byte~) main::$0 << (byte/signed byte/word/signed word/dword/signed dword) 1 -- vbuaa=vbuaa_rol_1
|
||||
asl
|
||||
//SEG18 [9] (void()*) main::f#0 ← *((const void()*[2]) fns#0 + (byte~) main::$1) -- pprz1=pptc1_derefidx_vbuaa
|
||||
|
@ -17,12 +17,12 @@
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(void()*) main::f
|
||||
(void()*) main::f#0 f zp ZP_WORD:2 11.0
|
||||
(void()*) main::f#0 f zp ZP_WORD:3 11.0
|
||||
(byte) main::i
|
||||
(byte) main::i#1 reg byte x 6.6000000000000005
|
||||
(byte) main::i#2 reg byte x 22.0
|
||||
(byte) main::i#1 i zp ZP_BYTE:2 6.6000000000000005
|
||||
(byte) main::i#2 i zp ZP_BYTE:2 22.0
|
||||
|
||||
reg byte x [ main::i#2 main::i#1 ]
|
||||
zp ZP_BYTE:2 [ main::i#2 main::i#1 ]
|
||||
reg byte a [ main::$0 ]
|
||||
reg byte a [ main::$1 ]
|
||||
zp ZP_WORD:2 [ main::f#0 ]
|
||||
zp ZP_WORD:3 [ main::f#0 ]
|
||||
|
@ -291,10 +291,11 @@ fn1: {
|
||||
}
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [6] call *((const void()*) main::cls#0) [ main::cols#2 ] ( main:2 [ main::cols#2 ] ) always clobbers reg byte a reg byte x reg byte y
|
||||
Statement [7] *((byte*) main::cols#2) ← ++ *((byte*) main::cols#2) [ main::cols#2 ] ( main:2 [ main::cols#2 ] ) always clobbers reg byte a reg byte y
|
||||
Statement [9] if((byte*) main::cols#1<(word/dword/signed dword) $d800+(word/signed word/dword/signed dword) $3e8) goto main::@1 [ main::cols#1 ] ( main:2 [ main::cols#1 ] ) always clobbers reg byte a
|
||||
Statement [13] *((byte*) fn1::screen#2) ← ++ *((byte*) fn1::screen#2) [ fn1::screen#2 ] ( ) always clobbers reg byte a reg byte y
|
||||
Statement [15] if((byte*) fn1::screen#1<(word/signed word/dword/signed dword) $400+(word/signed word/dword/signed dword) $3e8) goto fn1::@1 [ fn1::screen#1 ] ( ) always clobbers reg byte a
|
||||
Statement [13] *((byte*) fn1::screen#2) ← ++ *((byte*) fn1::screen#2) [ fn1::screen#2 ] ( [ fn1::screen#2 ] ) always clobbers reg byte a reg byte y
|
||||
Statement [15] if((byte*) fn1::screen#1<(word/signed word/dword/signed dword) $400+(word/signed word/dword/signed dword) $3e8) goto fn1::@1 [ fn1::screen#1 ] ( [ fn1::screen#1 ] ) always clobbers reg byte a
|
||||
Potential registers zp ZP_WORD:2 [ main::cols#2 main::cols#1 ] : zp ZP_WORD:2 ,
|
||||
Potential registers zp ZP_WORD:4 [ fn1::screen#2 fn1::screen#1 ] : zp ZP_WORD:4 ,
|
||||
|
||||
|
42
src/test/ref/function-pointer-noarg-call-7.asm
Normal file
42
src/test/ref/function-pointer-noarg-call-7.asm
Normal file
@ -0,0 +1,42 @@
|
||||
// Tests calling into a function pointer with local variables
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
.label SCREEN = $400
|
||||
.label idx = 3
|
||||
bbegin:
|
||||
lda #0
|
||||
sta idx
|
||||
jsr main
|
||||
rts
|
||||
main: {
|
||||
.label f = hello
|
||||
jsr do10
|
||||
rts
|
||||
}
|
||||
do10: {
|
||||
.label i = 2
|
||||
lda #0
|
||||
sta i
|
||||
b1:
|
||||
jsr main.f
|
||||
inc i
|
||||
lda #$a
|
||||
cmp i
|
||||
bne b1
|
||||
rts
|
||||
}
|
||||
hello: {
|
||||
ldx #0
|
||||
b1:
|
||||
lda msg,x
|
||||
ldy idx
|
||||
sta SCREEN,y
|
||||
inc idx
|
||||
inx
|
||||
lda msg,x
|
||||
cmp #'@'
|
||||
bne b1
|
||||
rts
|
||||
}
|
||||
msg: .text "hello @"
|
45
src/test/ref/function-pointer-noarg-call-7.cfg
Normal file
45
src/test/ref/function-pointer-noarg-call-7.cfg
Normal file
@ -0,0 +1,45 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] (byte) idx#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
[2] phi()
|
||||
[3] call main
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
[4] phi()
|
||||
main: scope:[main] from @2
|
||||
[5] phi()
|
||||
[6] call do10
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[7] return
|
||||
to:@return
|
||||
do10: scope:[do10] from main
|
||||
[8] phi()
|
||||
to:do10::@1
|
||||
do10::@1: scope:[do10] from do10 do10::@1
|
||||
[9] (byte) do10::i#2 ← phi( do10/(byte/signed byte/word/signed word/dword/signed dword) 0 do10::@1/(byte) do10::i#1 )
|
||||
[10] call *((const void()*) main::f#0)
|
||||
[11] (byte) do10::i#1 ← ++ (byte) do10::i#2
|
||||
[12] if((byte) do10::i#1!=(byte/signed byte/word/signed word/dword/signed dword) $a) goto do10::@1
|
||||
to:do10::@return
|
||||
do10::@return: scope:[do10] from do10::@1
|
||||
[13] return
|
||||
to:@return
|
||||
hello: scope:[hello] from
|
||||
[14] phi()
|
||||
to:hello::@1
|
||||
hello::@1: scope:[hello] from hello hello::@1
|
||||
[15] (byte) idx#3 ← phi( hello/(byte) idx#0 hello::@1/(byte) idx#1 )
|
||||
[15] (byte) hello::i#2 ← phi( hello/(byte/signed byte/word/signed word/dword/signed dword) 0 hello::@1/(byte) hello::i#1 )
|
||||
[16] *((const byte*) SCREEN#0 + (byte) idx#3) ← *((const byte[]) msg#0 + (byte) hello::i#2)
|
||||
[17] (byte) idx#1 ← ++ (byte) idx#3
|
||||
[18] (byte) hello::i#1 ← ++ (byte) hello::i#2
|
||||
[19] if(*((const byte[]) msg#0 + (byte) hello::i#1)!=(byte) '@') goto hello::@1
|
||||
to:hello::@return
|
||||
hello::@return: scope:[hello] from hello::@1
|
||||
[20] return
|
||||
to:@return
|
664
src/test/ref/function-pointer-noarg-call-7.log
Normal file
664
src/test/ref/function-pointer-noarg-call-7.log
Normal file
@ -0,0 +1,664 @@
|
||||
Resolved forward reference hello to (void()) hello()
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
to:@2
|
||||
main: scope:[main] from @3
|
||||
(void()*~) main::$0 ← & (void()) hello()
|
||||
(void()*) main::f#0 ← (void()*~) main::$0
|
||||
(void()*) do10::fn#0 ← (void()*) main::f#0
|
||||
call do10
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
return
|
||||
to:@return
|
||||
do10: scope:[do10] from main
|
||||
(void()*) do10::fn#2 ← phi( main/(void()*) do10::fn#0 )
|
||||
(byte) do10::i#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
to:do10::@1
|
||||
do10::@1: scope:[do10] from do10 do10::@1
|
||||
(byte) do10::i#2 ← phi( do10/(byte) do10::i#0 do10::@1/(byte) do10::i#1 )
|
||||
(void()*) do10::fn#1 ← phi( do10/(void()*) do10::fn#2 do10::@1/(void()*) do10::fn#1 )
|
||||
call *((void()*) do10::fn#1)
|
||||
(byte) do10::i#1 ← (byte) do10::i#2 + rangenext(0,9)
|
||||
(bool~) do10::$1 ← (byte) do10::i#1 != rangelast(0,9)
|
||||
if((bool~) do10::$1) goto do10::@1
|
||||
to:do10::@return
|
||||
do10::@return: scope:[do10] from do10::@1
|
||||
return
|
||||
to:@return
|
||||
@2: scope:[] from @begin
|
||||
(byte*) SCREEN#0 ← ((byte*)) (word/signed word/dword/signed dword) $400
|
||||
(byte[]) msg#0 ← (const string) $0
|
||||
(byte) idx#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
to:@3
|
||||
hello: scope:[hello] from
|
||||
(byte) idx#5 ← phi( @3/(byte) idx#6 )
|
||||
(byte) hello::i#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
to:hello::@1
|
||||
hello::@1: scope:[hello] from hello hello::@1
|
||||
(byte) idx#3 ← phi( hello/(byte) idx#5 hello::@1/(byte) idx#1 )
|
||||
(byte) hello::i#2 ← phi( hello/(byte) hello::i#0 hello::@1/(byte) hello::i#1 )
|
||||
*((byte*) SCREEN#0 + (byte) idx#3) ← *((byte[]) msg#0 + (byte) hello::i#2)
|
||||
(byte) idx#1 ← ++ (byte) idx#3
|
||||
(byte) hello::i#1 ← ++ (byte) hello::i#2
|
||||
(bool~) hello::$0 ← *((byte[]) msg#0 + (byte) hello::i#1) != (byte) '@'
|
||||
if((bool~) hello::$0) goto hello::@1
|
||||
to:hello::@return
|
||||
hello::@return: scope:[hello] from hello::@1
|
||||
(byte) idx#4 ← phi( hello::@1/(byte) idx#1 )
|
||||
(byte) idx#2 ← (byte) idx#4
|
||||
return
|
||||
to:@return
|
||||
@3: scope:[] from @2
|
||||
(byte) idx#6 ← phi( @2/(byte) idx#0 )
|
||||
call main
|
||||
to:@4
|
||||
@4: scope:[] from @3
|
||||
to:@end
|
||||
@end: scope:[] from @4
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(const string) $0 = (string) "hello @"
|
||||
(label) @2
|
||||
(label) @3
|
||||
(label) @4
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte*) SCREEN
|
||||
(byte*) SCREEN#0
|
||||
(void()) do10((void()*) do10::fn)
|
||||
(bool~) do10::$1
|
||||
(label) do10::@1
|
||||
(label) do10::@return
|
||||
(void()*) do10::fn
|
||||
(void()*) do10::fn#0
|
||||
(void()*) do10::fn#1
|
||||
(void()*) do10::fn#2
|
||||
(byte) do10::i
|
||||
(byte) do10::i#0
|
||||
(byte) do10::i#1
|
||||
(byte) do10::i#2
|
||||
(void()) hello()
|
||||
(bool~) hello::$0
|
||||
(label) hello::@1
|
||||
(label) hello::@return
|
||||
(byte) hello::i
|
||||
(byte) hello::i#0
|
||||
(byte) hello::i#1
|
||||
(byte) hello::i#2
|
||||
(byte) idx
|
||||
(byte) idx#0
|
||||
(byte) idx#1
|
||||
(byte) idx#2
|
||||
(byte) idx#3
|
||||
(byte) idx#4
|
||||
(byte) idx#5
|
||||
(byte) idx#6
|
||||
(void()) main()
|
||||
(void()*~) main::$0
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(void()*) main::f
|
||||
(void()*) main::f#0
|
||||
(byte[]) msg
|
||||
(byte[]) msg#0
|
||||
|
||||
Culled Empty Block (label) main::@1
|
||||
Culled Empty Block (label) @4
|
||||
Successful SSA optimization Pass2CullEmptyBlocks
|
||||
Alias (void()*) main::f#0 = (void()*~) main::$0
|
||||
Alias (byte) idx#1 = (byte) idx#4 (byte) idx#2
|
||||
Alias (byte) idx#0 = (byte) idx#6
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Self Phi Eliminated (void()*) do10::fn#1
|
||||
Successful SSA optimization Pass2SelfPhiElimination
|
||||
Redundant Phi (void()*) do10::fn#2 (void()*) do10::fn#0
|
||||
Redundant Phi (void()*) do10::fn#1 (void()*) do10::fn#2
|
||||
Redundant Phi (byte) idx#5 (byte) idx#0
|
||||
Successful SSA optimization Pass2RedundantPhiElimination
|
||||
Simple Condition (bool~) do10::$1 [11] if((byte) do10::i#1!=rangelast(0,9)) goto do10::@1
|
||||
Simple Condition (bool~) hello::$0 [23] if(*((byte[]) msg#0 + (byte) hello::i#1)!=(byte) '@') goto hello::@1
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Constant (const void()*) main::f#0 = &hello
|
||||
Constant (const byte) do10::i#0 = 0
|
||||
Constant (const byte*) SCREEN#0 = ((byte*))$400
|
||||
Constant (const byte[]) msg#0 = $0
|
||||
Constant (const byte) hello::i#0 = 0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant (const void()*) do10::fn#0 = main::f#0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Resolved ranged next value do10::i#1 ← ++ do10::i#2 to ++
|
||||
Resolved ranged comparison value if(do10::i#1!=rangelast(0,9)) goto do10::@1 to (byte/signed byte/word/signed word/dword/signed dword) $a
|
||||
Inlining constant with var siblings (const byte) do10::i#0
|
||||
Inlining constant with var siblings (const byte) hello::i#0
|
||||
Constant inlined hello::i#0 = (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
Constant inlined do10::i#0 = (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
Constant inlined do10::fn#0 = (const void()*) main::f#0
|
||||
Constant inlined $0 = (const byte[]) msg#0
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Added new block during phi lifting do10::@3(between do10::@1 and do10::@1)
|
||||
Added new block during phi lifting hello::@3(between hello::@1 and hello::@1)
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @3
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main
|
||||
Adding NOP phi() at start of do10
|
||||
CALL GRAPH
|
||||
Calls in [] to main:3
|
||||
Calls in [main] to do10:6
|
||||
|
||||
Created 3 initial phi equivalence classes
|
||||
Coalesced [14] do10::i#3 ← do10::i#1
|
||||
Coalesced [15] idx#7 ← idx#0
|
||||
Coalesced [22] hello::i#3 ← hello::i#1
|
||||
Coalesced [23] idx#8 ← idx#1
|
||||
Coalesced down to 3 phi equivalence classes
|
||||
Culled Empty Block (label) do10::@3
|
||||
Culled Empty Block (label) hello::@3
|
||||
Renumbering block @2 to @1
|
||||
Renumbering block @3 to @2
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main
|
||||
Adding NOP phi() at start of do10
|
||||
Adding NOP phi() at start of hello
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] (byte) idx#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
[2] phi()
|
||||
[3] call main
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
[4] phi()
|
||||
main: scope:[main] from @2
|
||||
[5] phi()
|
||||
[6] call do10
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main
|
||||
[7] return
|
||||
to:@return
|
||||
do10: scope:[do10] from main
|
||||
[8] phi()
|
||||
to:do10::@1
|
||||
do10::@1: scope:[do10] from do10 do10::@1
|
||||
[9] (byte) do10::i#2 ← phi( do10/(byte/signed byte/word/signed word/dword/signed dword) 0 do10::@1/(byte) do10::i#1 )
|
||||
[10] call *((const void()*) main::f#0)
|
||||
[11] (byte) do10::i#1 ← ++ (byte) do10::i#2
|
||||
[12] if((byte) do10::i#1!=(byte/signed byte/word/signed word/dword/signed dword) $a) goto do10::@1
|
||||
to:do10::@return
|
||||
do10::@return: scope:[do10] from do10::@1
|
||||
[13] return
|
||||
to:@return
|
||||
hello: scope:[hello] from
|
||||
[14] phi()
|
||||
to:hello::@1
|
||||
hello::@1: scope:[hello] from hello hello::@1
|
||||
[15] (byte) idx#3 ← phi( hello/(byte) idx#0 hello::@1/(byte) idx#1 )
|
||||
[15] (byte) hello::i#2 ← phi( hello/(byte/signed byte/word/signed word/dword/signed dword) 0 hello::@1/(byte) hello::i#1 )
|
||||
[16] *((const byte*) SCREEN#0 + (byte) idx#3) ← *((const byte[]) msg#0 + (byte) hello::i#2)
|
||||
[17] (byte) idx#1 ← ++ (byte) idx#3
|
||||
[18] (byte) hello::i#1 ← ++ (byte) hello::i#2
|
||||
[19] if(*((const byte[]) msg#0 + (byte) hello::i#1)!=(byte) '@') goto hello::@1
|
||||
to:hello::@return
|
||||
hello::@return: scope:[hello] from hello::@1
|
||||
[20] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte*) SCREEN
|
||||
(void()) do10((void()*) do10::fn)
|
||||
(void()*) do10::fn
|
||||
(byte) do10::i
|
||||
(byte) do10::i#1 16.5
|
||||
(byte) do10::i#2 11.0
|
||||
(void()) hello()
|
||||
(byte) hello::i
|
||||
(byte) hello::i#1 16.5
|
||||
(byte) hello::i#2 11.0
|
||||
(byte) idx
|
||||
(byte) idx#0 4.0
|
||||
(byte) idx#1 7.333333333333333
|
||||
(byte) idx#3 17.5
|
||||
(void()) main()
|
||||
(void()*) main::f
|
||||
(byte[]) msg
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ do10::i#2 do10::i#1 ]
|
||||
[ hello::i#2 hello::i#1 ]
|
||||
[ idx#3 idx#0 idx#1 ]
|
||||
Complete equivalence classes
|
||||
[ do10::i#2 do10::i#1 ]
|
||||
[ hello::i#2 hello::i#1 ]
|
||||
[ idx#3 idx#0 idx#1 ]
|
||||
Allocated zp ZP_BYTE:2 [ do10::i#2 do10::i#1 ]
|
||||
Allocated zp ZP_BYTE:3 [ hello::i#2 hello::i#1 ]
|
||||
Allocated zp ZP_BYTE:4 [ idx#3 idx#0 idx#1 ]
|
||||
|
||||
INITIAL ASM
|
||||
//SEG0 File Comments
|
||||
// Tests calling into a function pointer with local variables
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.label idx = 4
|
||||
//SEG3 @begin
|
||||
bbegin:
|
||||
jmp b1
|
||||
//SEG4 @1
|
||||
b1:
|
||||
//SEG5 [1] (byte) idx#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta idx
|
||||
//SEG6 [2] phi from @1 to @2 [phi:@1->@2]
|
||||
b2_from_b1:
|
||||
jmp b2
|
||||
//SEG7 @2
|
||||
b2:
|
||||
//SEG8 [3] call main
|
||||
//SEG9 [5] phi from @2 to main [phi:@2->main]
|
||||
main_from_b2:
|
||||
jsr main
|
||||
//SEG10 [4] phi from @2 to @end [phi:@2->@end]
|
||||
bend_from_b2:
|
||||
jmp bend
|
||||
//SEG11 @end
|
||||
bend:
|
||||
//SEG12 main
|
||||
main: {
|
||||
.label f = hello
|
||||
//SEG13 [6] call do10
|
||||
//SEG14 [8] phi from main to do10 [phi:main->do10]
|
||||
do10_from_main:
|
||||
jsr do10
|
||||
jmp breturn
|
||||
//SEG15 main::@return
|
||||
breturn:
|
||||
//SEG16 [7] return
|
||||
rts
|
||||
}
|
||||
//SEG17 do10
|
||||
do10: {
|
||||
.label i = 2
|
||||
//SEG18 [9] phi from do10 to do10::@1 [phi:do10->do10::@1]
|
||||
b1_from_do10:
|
||||
//SEG19 [9] phi (byte) do10::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:do10->do10::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta i
|
||||
jmp b1
|
||||
//SEG20 [9] phi from do10::@1 to do10::@1 [phi:do10::@1->do10::@1]
|
||||
b1_from_b1:
|
||||
//SEG21 [9] phi (byte) do10::i#2 = (byte) do10::i#1 [phi:do10::@1->do10::@1#0] -- register_copy
|
||||
jmp b1
|
||||
//SEG22 do10::@1
|
||||
b1:
|
||||
//SEG23 [10] call *((const void()*) main::f#0)
|
||||
jsr main.f
|
||||
//SEG24 [11] (byte) do10::i#1 ← ++ (byte) do10::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc i
|
||||
//SEG25 [12] if((byte) do10::i#1!=(byte/signed byte/word/signed word/dword/signed dword) $a) goto do10::@1 -- vbuz1_neq_vbuc1_then_la1
|
||||
lda #$a
|
||||
cmp i
|
||||
bne b1_from_b1
|
||||
jmp breturn
|
||||
//SEG26 do10::@return
|
||||
breturn:
|
||||
//SEG27 [13] return
|
||||
rts
|
||||
}
|
||||
//SEG28 hello
|
||||
hello: {
|
||||
.label i = 3
|
||||
//SEG29 [15] phi from hello to hello::@1 [phi:hello->hello::@1]
|
||||
b1_from_hello:
|
||||
//SEG30 [15] phi (byte) idx#3 = (byte) idx#0 [phi:hello->hello::@1#0] -- register_copy
|
||||
//SEG31 [15] phi (byte) hello::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:hello->hello::@1#1] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta i
|
||||
jmp b1
|
||||
//SEG32 [15] phi from hello::@1 to hello::@1 [phi:hello::@1->hello::@1]
|
||||
b1_from_b1:
|
||||
//SEG33 [15] phi (byte) idx#3 = (byte) idx#1 [phi:hello::@1->hello::@1#0] -- register_copy
|
||||
//SEG34 [15] phi (byte) hello::i#2 = (byte) hello::i#1 [phi:hello::@1->hello::@1#1] -- register_copy
|
||||
jmp b1
|
||||
//SEG35 hello::@1
|
||||
b1:
|
||||
//SEG36 [16] *((const byte*) SCREEN#0 + (byte) idx#3) ← *((const byte[]) msg#0 + (byte) hello::i#2) -- pbuc1_derefidx_vbuz1=pbuc2_derefidx_vbuz2
|
||||
ldy i
|
||||
lda msg,y
|
||||
ldy idx
|
||||
sta SCREEN,y
|
||||
//SEG37 [17] (byte) idx#1 ← ++ (byte) idx#3 -- vbuz1=_inc_vbuz1
|
||||
inc idx
|
||||
//SEG38 [18] (byte) hello::i#1 ← ++ (byte) hello::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc i
|
||||
//SEG39 [19] if(*((const byte[]) msg#0 + (byte) hello::i#1)!=(byte) '@') goto hello::@1 -- pbuc1_derefidx_vbuz1_neq_vbuc2_then_la1
|
||||
lda #'@'
|
||||
ldy i
|
||||
cmp msg,y
|
||||
bne b1_from_b1
|
||||
jmp breturn
|
||||
//SEG40 hello::@return
|
||||
breturn:
|
||||
//SEG41 [20] return
|
||||
rts
|
||||
}
|
||||
msg: .text "hello @"
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [1] (byte) idx#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 [ ] ( ) always clobbers reg byte a
|
||||
Statement [10] call *((const void()*) main::f#0) [ do10::i#2 ] ( main:3::do10:6 [ do10::i#2 ] ) always clobbers reg byte a reg byte x reg byte y
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ do10::i#2 do10::i#1 ]
|
||||
Removing always clobbered register reg byte x as potential for zp ZP_BYTE:2 [ do10::i#2 do10::i#1 ]
|
||||
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:2 [ do10::i#2 do10::i#1 ]
|
||||
Statement [12] if((byte) do10::i#1!=(byte/signed byte/word/signed word/dword/signed dword) $a) goto do10::@1 [ do10::i#1 ] ( main:3::do10:6 [ do10::i#1 ] ) always clobbers reg byte a
|
||||
Statement [16] *((const byte*) SCREEN#0 + (byte) idx#3) ← *((const byte[]) msg#0 + (byte) hello::i#2) [ hello::i#2 idx#3 ] ( [ hello::i#2 idx#3 ] ) always clobbers reg byte a reg byte y
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:3 [ hello::i#2 hello::i#1 ]
|
||||
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:3 [ hello::i#2 hello::i#1 ]
|
||||
Statement [19] if(*((const byte[]) msg#0 + (byte) hello::i#1)!=(byte) '@') goto hello::@1 [ hello::i#1 idx#1 ] ( [ hello::i#1 idx#1 ] ) always clobbers reg byte a
|
||||
Statement [1] (byte) idx#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 [ ] ( ) always clobbers reg byte a
|
||||
Statement [10] call *((const void()*) main::f#0) [ do10::i#2 ] ( main:3::do10:6 [ do10::i#2 ] ) always clobbers reg byte a reg byte x reg byte y
|
||||
Statement [12] if((byte) do10::i#1!=(byte/signed byte/word/signed word/dword/signed dword) $a) goto do10::@1 [ do10::i#1 ] ( main:3::do10:6 [ do10::i#1 ] ) always clobbers reg byte a
|
||||
Statement [16] *((const byte*) SCREEN#0 + (byte) idx#3) ← *((const byte[]) msg#0 + (byte) hello::i#2) [ hello::i#2 idx#3 ] ( [ hello::i#2 idx#3 ] ) always clobbers reg byte a reg byte y
|
||||
Statement [19] if(*((const byte[]) msg#0 + (byte) hello::i#1)!=(byte) '@') goto hello::@1 [ hello::i#1 idx#1 ] ( [ hello::i#1 idx#1 ] ) always clobbers reg byte a
|
||||
Potential registers zp ZP_BYTE:2 [ do10::i#2 do10::i#1 ] : zp ZP_BYTE:2 ,
|
||||
Potential registers zp ZP_BYTE:3 [ hello::i#2 hello::i#1 ] : zp ZP_BYTE:3 , reg byte x ,
|
||||
Potential registers zp ZP_BYTE:4 [ idx#3 idx#0 idx#1 ] : zp ZP_BYTE:4 ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [] 28.83: zp ZP_BYTE:4 [ idx#3 idx#0 idx#1 ]
|
||||
Uplift Scope [do10] 27.5: zp ZP_BYTE:2 [ do10::i#2 do10::i#1 ]
|
||||
Uplift Scope [hello] 27.5: zp ZP_BYTE:3 [ hello::i#2 hello::i#1 ]
|
||||
Uplift Scope [main]
|
||||
|
||||
Uplifting [] best 914 combination zp ZP_BYTE:4 [ idx#3 idx#0 idx#1 ]
|
||||
Uplifting [do10] best 914 combination zp ZP_BYTE:2 [ do10::i#2 do10::i#1 ]
|
||||
Uplifting [hello] best 794 combination reg byte x [ hello::i#2 hello::i#1 ]
|
||||
Uplifting [main] best 794 combination
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:4 [ idx#3 idx#0 idx#1 ]
|
||||
Uplifting [] best 794 combination zp ZP_BYTE:4 [ idx#3 idx#0 idx#1 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:2 [ do10::i#2 do10::i#1 ]
|
||||
Uplifting [do10] best 794 combination zp ZP_BYTE:2 [ do10::i#2 do10::i#1 ]
|
||||
Allocated (was zp ZP_BYTE:4) zp ZP_BYTE:3 [ idx#3 idx#0 idx#1 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
//SEG0 File Comments
|
||||
// Tests calling into a function pointer with local variables
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.label idx = 3
|
||||
//SEG3 @begin
|
||||
bbegin:
|
||||
jmp b1
|
||||
//SEG4 @1
|
||||
b1:
|
||||
//SEG5 [1] (byte) idx#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta idx
|
||||
//SEG6 [2] phi from @1 to @2 [phi:@1->@2]
|
||||
b2_from_b1:
|
||||
jmp b2
|
||||
//SEG7 @2
|
||||
b2:
|
||||
//SEG8 [3] call main
|
||||
//SEG9 [5] phi from @2 to main [phi:@2->main]
|
||||
main_from_b2:
|
||||
jsr main
|
||||
//SEG10 [4] phi from @2 to @end [phi:@2->@end]
|
||||
bend_from_b2:
|
||||
jmp bend
|
||||
//SEG11 @end
|
||||
bend:
|
||||
//SEG12 main
|
||||
main: {
|
||||
.label f = hello
|
||||
//SEG13 [6] call do10
|
||||
//SEG14 [8] phi from main to do10 [phi:main->do10]
|
||||
do10_from_main:
|
||||
jsr do10
|
||||
jmp breturn
|
||||
//SEG15 main::@return
|
||||
breturn:
|
||||
//SEG16 [7] return
|
||||
rts
|
||||
}
|
||||
//SEG17 do10
|
||||
do10: {
|
||||
.label i = 2
|
||||
//SEG18 [9] phi from do10 to do10::@1 [phi:do10->do10::@1]
|
||||
b1_from_do10:
|
||||
//SEG19 [9] phi (byte) do10::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:do10->do10::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta i
|
||||
jmp b1
|
||||
//SEG20 [9] phi from do10::@1 to do10::@1 [phi:do10::@1->do10::@1]
|
||||
b1_from_b1:
|
||||
//SEG21 [9] phi (byte) do10::i#2 = (byte) do10::i#1 [phi:do10::@1->do10::@1#0] -- register_copy
|
||||
jmp b1
|
||||
//SEG22 do10::@1
|
||||
b1:
|
||||
//SEG23 [10] call *((const void()*) main::f#0)
|
||||
jsr main.f
|
||||
//SEG24 [11] (byte) do10::i#1 ← ++ (byte) do10::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc i
|
||||
//SEG25 [12] if((byte) do10::i#1!=(byte/signed byte/word/signed word/dword/signed dword) $a) goto do10::@1 -- vbuz1_neq_vbuc1_then_la1
|
||||
lda #$a
|
||||
cmp i
|
||||
bne b1_from_b1
|
||||
jmp breturn
|
||||
//SEG26 do10::@return
|
||||
breturn:
|
||||
//SEG27 [13] return
|
||||
rts
|
||||
}
|
||||
//SEG28 hello
|
||||
hello: {
|
||||
//SEG29 [15] phi from hello to hello::@1 [phi:hello->hello::@1]
|
||||
b1_from_hello:
|
||||
//SEG30 [15] phi (byte) idx#3 = (byte) idx#0 [phi:hello->hello::@1#0] -- register_copy
|
||||
//SEG31 [15] phi (byte) hello::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:hello->hello::@1#1] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
jmp b1
|
||||
//SEG32 [15] phi from hello::@1 to hello::@1 [phi:hello::@1->hello::@1]
|
||||
b1_from_b1:
|
||||
//SEG33 [15] phi (byte) idx#3 = (byte) idx#1 [phi:hello::@1->hello::@1#0] -- register_copy
|
||||
//SEG34 [15] phi (byte) hello::i#2 = (byte) hello::i#1 [phi:hello::@1->hello::@1#1] -- register_copy
|
||||
jmp b1
|
||||
//SEG35 hello::@1
|
||||
b1:
|
||||
//SEG36 [16] *((const byte*) SCREEN#0 + (byte) idx#3) ← *((const byte[]) msg#0 + (byte) hello::i#2) -- pbuc1_derefidx_vbuz1=pbuc2_derefidx_vbuxx
|
||||
lda msg,x
|
||||
ldy idx
|
||||
sta SCREEN,y
|
||||
//SEG37 [17] (byte) idx#1 ← ++ (byte) idx#3 -- vbuz1=_inc_vbuz1
|
||||
inc idx
|
||||
//SEG38 [18] (byte) hello::i#1 ← ++ (byte) hello::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
//SEG39 [19] if(*((const byte[]) msg#0 + (byte) hello::i#1)!=(byte) '@') goto hello::@1 -- pbuc1_derefidx_vbuxx_neq_vbuc2_then_la1
|
||||
lda msg,x
|
||||
cmp #'@'
|
||||
bne b1_from_b1
|
||||
jmp breturn
|
||||
//SEG40 hello::@return
|
||||
breturn:
|
||||
//SEG41 [20] return
|
||||
rts
|
||||
}
|
||||
msg: .text "hello @"
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp b2
|
||||
Removing instruction jmp bend
|
||||
Removing instruction jmp breturn
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp breturn
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Replacing label b1_from_b1 with b1
|
||||
Replacing label b1_from_b1 with b1
|
||||
Removing instruction b1:
|
||||
Removing instruction b2_from_b1:
|
||||
Removing instruction main_from_b2:
|
||||
Removing instruction bend_from_b2:
|
||||
Removing instruction b1_from_b1:
|
||||
Removing instruction b1_from_b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction b2:
|
||||
Removing instruction bend:
|
||||
Removing instruction do10_from_main:
|
||||
Removing instruction breturn:
|
||||
Removing instruction b1_from_do10:
|
||||
Removing instruction breturn:
|
||||
Removing instruction b1_from_hello:
|
||||
Removing instruction breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Adding RTS to root block
|
||||
Succesful ASM optimization Pass5AddMainRts
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp b1
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte*) SCREEN
|
||||
(const byte*) SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) $400
|
||||
(void()) do10((void()*) do10::fn)
|
||||
(label) do10::@1
|
||||
(label) do10::@return
|
||||
(void()*) do10::fn
|
||||
(byte) do10::i
|
||||
(byte) do10::i#1 i zp ZP_BYTE:2 16.5
|
||||
(byte) do10::i#2 i zp ZP_BYTE:2 11.0
|
||||
(void()) hello()
|
||||
(label) hello::@1
|
||||
(label) hello::@return
|
||||
(byte) hello::i
|
||||
(byte) hello::i#1 reg byte x 16.5
|
||||
(byte) hello::i#2 reg byte x 11.0
|
||||
(byte) idx
|
||||
(byte) idx#0 idx zp ZP_BYTE:3 4.0
|
||||
(byte) idx#1 idx zp ZP_BYTE:3 7.333333333333333
|
||||
(byte) idx#3 idx zp ZP_BYTE:3 17.5
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(void()*) main::f
|
||||
(const void()*) main::f#0 f = &(void()) hello()
|
||||
(byte[]) msg
|
||||
(const byte[]) msg#0 msg = (string) "hello @"
|
||||
|
||||
zp ZP_BYTE:2 [ do10::i#2 do10::i#1 ]
|
||||
reg byte x [ hello::i#2 hello::i#1 ]
|
||||
zp ZP_BYTE:3 [ idx#3 idx#0 idx#1 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 581
|
||||
|
||||
//SEG0 File Comments
|
||||
// Tests calling into a function pointer with local variables
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.label idx = 3
|
||||
//SEG3 @begin
|
||||
bbegin:
|
||||
//SEG4 @1
|
||||
//SEG5 [1] (byte) idx#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta idx
|
||||
//SEG6 [2] phi from @1 to @2 [phi:@1->@2]
|
||||
//SEG7 @2
|
||||
//SEG8 [3] call main
|
||||
//SEG9 [5] phi from @2 to main [phi:@2->main]
|
||||
jsr main
|
||||
rts
|
||||
//SEG10 [4] phi from @2 to @end [phi:@2->@end]
|
||||
//SEG11 @end
|
||||
//SEG12 main
|
||||
main: {
|
||||
.label f = hello
|
||||
//SEG13 [6] call do10
|
||||
//SEG14 [8] phi from main to do10 [phi:main->do10]
|
||||
jsr do10
|
||||
//SEG15 main::@return
|
||||
//SEG16 [7] return
|
||||
rts
|
||||
}
|
||||
//SEG17 do10
|
||||
do10: {
|
||||
.label i = 2
|
||||
//SEG18 [9] phi from do10 to do10::@1 [phi:do10->do10::@1]
|
||||
//SEG19 [9] phi (byte) do10::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:do10->do10::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta i
|
||||
//SEG20 [9] phi from do10::@1 to do10::@1 [phi:do10::@1->do10::@1]
|
||||
//SEG21 [9] phi (byte) do10::i#2 = (byte) do10::i#1 [phi:do10::@1->do10::@1#0] -- register_copy
|
||||
//SEG22 do10::@1
|
||||
b1:
|
||||
//SEG23 [10] call *((const void()*) main::f#0)
|
||||
jsr main.f
|
||||
//SEG24 [11] (byte) do10::i#1 ← ++ (byte) do10::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc i
|
||||
//SEG25 [12] if((byte) do10::i#1!=(byte/signed byte/word/signed word/dword/signed dword) $a) goto do10::@1 -- vbuz1_neq_vbuc1_then_la1
|
||||
lda #$a
|
||||
cmp i
|
||||
bne b1
|
||||
//SEG26 do10::@return
|
||||
//SEG27 [13] return
|
||||
rts
|
||||
}
|
||||
//SEG28 hello
|
||||
hello: {
|
||||
//SEG29 [15] phi from hello to hello::@1 [phi:hello->hello::@1]
|
||||
//SEG30 [15] phi (byte) idx#3 = (byte) idx#0 [phi:hello->hello::@1#0] -- register_copy
|
||||
//SEG31 [15] phi (byte) hello::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:hello->hello::@1#1] -- vbuxx=vbuc1
|
||||
ldx #0
|
||||
//SEG32 [15] phi from hello::@1 to hello::@1 [phi:hello::@1->hello::@1]
|
||||
//SEG33 [15] phi (byte) idx#3 = (byte) idx#1 [phi:hello::@1->hello::@1#0] -- register_copy
|
||||
//SEG34 [15] phi (byte) hello::i#2 = (byte) hello::i#1 [phi:hello::@1->hello::@1#1] -- register_copy
|
||||
//SEG35 hello::@1
|
||||
b1:
|
||||
//SEG36 [16] *((const byte*) SCREEN#0 + (byte) idx#3) ← *((const byte[]) msg#0 + (byte) hello::i#2) -- pbuc1_derefidx_vbuz1=pbuc2_derefidx_vbuxx
|
||||
lda msg,x
|
||||
ldy idx
|
||||
sta SCREEN,y
|
||||
//SEG37 [17] (byte) idx#1 ← ++ (byte) idx#3 -- vbuz1=_inc_vbuz1
|
||||
inc idx
|
||||
//SEG38 [18] (byte) hello::i#1 ← ++ (byte) hello::i#2 -- vbuxx=_inc_vbuxx
|
||||
inx
|
||||
//SEG39 [19] if(*((const byte[]) msg#0 + (byte) hello::i#1)!=(byte) '@') goto hello::@1 -- pbuc1_derefidx_vbuxx_neq_vbuc2_then_la1
|
||||
lda msg,x
|
||||
cmp #'@'
|
||||
bne b1
|
||||
//SEG40 hello::@return
|
||||
//SEG41 [20] return
|
||||
rts
|
||||
}
|
||||
msg: .text "hello @"
|
||||
|
33
src/test/ref/function-pointer-noarg-call-7.sym
Normal file
33
src/test/ref/function-pointer-noarg-call-7.sym
Normal file
@ -0,0 +1,33 @@
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte*) SCREEN
|
||||
(const byte*) SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) $400
|
||||
(void()) do10((void()*) do10::fn)
|
||||
(label) do10::@1
|
||||
(label) do10::@return
|
||||
(void()*) do10::fn
|
||||
(byte) do10::i
|
||||
(byte) do10::i#1 i zp ZP_BYTE:2 16.5
|
||||
(byte) do10::i#2 i zp ZP_BYTE:2 11.0
|
||||
(void()) hello()
|
||||
(label) hello::@1
|
||||
(label) hello::@return
|
||||
(byte) hello::i
|
||||
(byte) hello::i#1 reg byte x 16.5
|
||||
(byte) hello::i#2 reg byte x 11.0
|
||||
(byte) idx
|
||||
(byte) idx#0 idx zp ZP_BYTE:3 4.0
|
||||
(byte) idx#1 idx zp ZP_BYTE:3 7.333333333333333
|
||||
(byte) idx#3 idx zp ZP_BYTE:3 17.5
|
||||
(void()) main()
|
||||
(label) main::@return
|
||||
(void()*) main::f
|
||||
(const void()*) main::f#0 f = &(void()) hello()
|
||||
(byte[]) msg
|
||||
(const byte[]) msg#0 msg = (string) "hello @"
|
||||
|
||||
zp ZP_BYTE:2 [ do10::i#2 do10::i#1 ]
|
||||
reg byte x [ hello::i#2 hello::i#1 ]
|
||||
zp ZP_BYTE:3 [ idx#3 idx#0 idx#1 ]
|
55
src/test/ref/function-pointer-noarg-call-8.asm
Normal file
55
src/test/ref/function-pointer-noarg-call-8.asm
Normal file
@ -0,0 +1,55 @@
|
||||
// Tests calling into a function pointer with local variables
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
.label SCREEN = $400
|
||||
.label msg = 4
|
||||
.label idx = 3
|
||||
bbegin:
|
||||
lda #<0
|
||||
sta msg
|
||||
sta msg+1
|
||||
sta idx
|
||||
jsr main
|
||||
rts
|
||||
main: {
|
||||
.label f = hello
|
||||
lda #<msg1
|
||||
sta msg
|
||||
lda #>msg1
|
||||
sta msg+1
|
||||
jsr do10
|
||||
lda #<msg2
|
||||
sta msg
|
||||
lda #>msg2
|
||||
sta msg+1
|
||||
jsr do10
|
||||
rts
|
||||
}
|
||||
do10: {
|
||||
.label i = 2
|
||||
lda #0
|
||||
sta i
|
||||
b1:
|
||||
jsr main.f
|
||||
inc i
|
||||
lda #$a
|
||||
cmp i
|
||||
bne b1
|
||||
rts
|
||||
}
|
||||
hello: {
|
||||
ldy #0
|
||||
b1:
|
||||
lda (msg),y
|
||||
ldx idx
|
||||
sta SCREEN,x
|
||||
inc idx
|
||||
iny
|
||||
lda (msg),y
|
||||
cmp #'@'
|
||||
bne b1
|
||||
rts
|
||||
}
|
||||
msg1: .text "hello @"
|
||||
msg2: .text "world @"
|
50
src/test/ref/function-pointer-noarg-call-8.cfg
Normal file
50
src/test/ref/function-pointer-noarg-call-8.cfg
Normal file
@ -0,0 +1,50 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] (byte*) msg#10 ← (byte*) 0
|
||||
[2] (byte) idx#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
[3] phi()
|
||||
[4] call main
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
[5] phi()
|
||||
main: scope:[main] from @2
|
||||
[6] (byte*) msg#0 ← (const byte[]) msg1#0
|
||||
[7] call do10
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[8] (byte*) msg#1 ← (const byte[]) msg2#0
|
||||
[9] call do10
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[10] return
|
||||
to:@return
|
||||
do10: scope:[do10] from main main::@1
|
||||
[11] phi()
|
||||
to:do10::@1
|
||||
do10::@1: scope:[do10] from do10 do10::@1
|
||||
[12] (byte) do10::i#2 ← phi( do10/(byte/signed byte/word/signed word/dword/signed dword) 0 do10::@1/(byte) do10::i#1 )
|
||||
[13] call *((const void()*) main::f#0)
|
||||
[14] (byte) do10::i#1 ← ++ (byte) do10::i#2
|
||||
[15] if((byte) do10::i#1!=(byte/signed byte/word/signed word/dword/signed dword) $a) goto do10::@1
|
||||
to:do10::@return
|
||||
do10::@return: scope:[do10] from do10::@1
|
||||
[16] return
|
||||
to:@return
|
||||
hello: scope:[hello] from
|
||||
[17] phi()
|
||||
to:hello::@1
|
||||
hello::@1: scope:[hello] from hello hello::@1
|
||||
[18] (byte) idx#3 ← phi( hello/(byte) idx#0 hello::@1/(byte) idx#1 )
|
||||
[18] (byte) hello::i#2 ← phi( hello/(byte/signed byte/word/signed word/dword/signed dword) 0 hello::@1/(byte) hello::i#1 )
|
||||
[19] *((const byte*) SCREEN#0 + (byte) idx#3) ← *((byte*) msg#10 + (byte) hello::i#2)
|
||||
[20] (byte) idx#1 ← ++ (byte) idx#3
|
||||
[21] (byte) hello::i#1 ← ++ (byte) hello::i#2
|
||||
[22] if(*((byte*) msg#10 + (byte) hello::i#1)!=(byte) '@') goto hello::@1
|
||||
to:hello::@return
|
||||
hello::@return: scope:[hello] from hello::@1
|
||||
[23] return
|
||||
to:@return
|
823
src/test/ref/function-pointer-noarg-call-8.log
Normal file
823
src/test/ref/function-pointer-noarg-call-8.log
Normal file
@ -0,0 +1,823 @@
|
||||
Resolved forward reference hello to (void()) hello()
|
||||
Resolved forward reference msg1 to (byte[]) msg1
|
||||
Resolved forward reference msg to (byte*) msg
|
||||
Resolved forward reference msg2 to (byte[]) msg2
|
||||
Resolved forward reference msg to (byte*) msg
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
to:@2
|
||||
main: scope:[main] from @3
|
||||
(void()*~) main::$0 ← & (void()) hello()
|
||||
(void()*) main::f#0 ← (void()*~) main::$0
|
||||
(byte*) msg#0 ← (byte[]) msg1#0
|
||||
(void()*) do10::fn#0 ← (void()*) main::f#0
|
||||
call do10
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
(void()*) main::f#1 ← phi( main/(void()*) main::f#0 )
|
||||
(byte*) msg#1 ← (byte[]) msg2#0
|
||||
(void()*) do10::fn#1 ← (void()*) main::f#1
|
||||
call do10
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1
|
||||
(byte*) msg#8 ← phi( main::@1/(byte*) msg#1 )
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@2
|
||||
(byte*) msg#5 ← phi( main::@2/(byte*) msg#8 )
|
||||
(byte*) msg#2 ← (byte*) msg#5
|
||||
return
|
||||
to:@return
|
||||
do10: scope:[do10] from main main::@1
|
||||
(void()*) do10::fn#3 ← phi( main/(void()*) do10::fn#0 main::@1/(void()*) do10::fn#1 )
|
||||
(byte) do10::i#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
to:do10::@1
|
||||
do10::@1: scope:[do10] from do10 do10::@1
|
||||
(byte) do10::i#2 ← phi( do10/(byte) do10::i#0 do10::@1/(byte) do10::i#1 )
|
||||
(void()*) do10::fn#2 ← phi( do10/(void()*) do10::fn#3 do10::@1/(void()*) do10::fn#2 )
|
||||
call *((void()*) do10::fn#2)
|
||||
(byte) do10::i#1 ← (byte) do10::i#2 + rangenext(0,9)
|
||||
(bool~) do10::$1 ← (byte) do10::i#1 != rangelast(0,9)
|
||||
if((bool~) do10::$1) goto do10::@1
|
||||
to:do10::@return
|
||||
do10::@return: scope:[do10] from do10::@1
|
||||
return
|
||||
to:@return
|
||||
@2: scope:[] from @begin
|
||||
(byte*) SCREEN#0 ← ((byte*)) (word/signed word/dword/signed dword) $400
|
||||
(byte[]) msg1#0 ← (const string) $0
|
||||
(byte[]) msg2#0 ← (const string) $1
|
||||
(byte*) msg#3 ← (byte*) 0
|
||||
(byte) idx#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
to:@3
|
||||
hello: scope:[hello] from
|
||||
(byte) idx#5 ← phi( @3/(byte) idx#6 )
|
||||
(byte*) msg#9 ← phi( @3/(byte*) msg#10 )
|
||||
(byte) hello::i#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
to:hello::@1
|
||||
hello::@1: scope:[hello] from hello hello::@1
|
||||
(byte) idx#3 ← phi( hello/(byte) idx#5 hello::@1/(byte) idx#1 )
|
||||
(byte) hello::i#2 ← phi( hello/(byte) hello::i#0 hello::@1/(byte) hello::i#1 )
|
||||
(byte*) msg#6 ← phi( hello/(byte*) msg#9 hello::@1/(byte*) msg#6 )
|
||||
*((byte*) SCREEN#0 + (byte) idx#3) ← *((byte*) msg#6 + (byte) hello::i#2)
|
||||
(byte) idx#1 ← ++ (byte) idx#3
|
||||
(byte) hello::i#1 ← ++ (byte) hello::i#2
|
||||
(bool~) hello::$0 ← *((byte*) msg#6 + (byte) hello::i#1) != (byte) '@'
|
||||
if((bool~) hello::$0) goto hello::@1
|
||||
to:hello::@return
|
||||
hello::@return: scope:[hello] from hello::@1
|
||||
(byte) idx#4 ← phi( hello::@1/(byte) idx#1 )
|
||||
(byte) idx#2 ← (byte) idx#4
|
||||
return
|
||||
to:@return
|
||||
@3: scope:[] from @2
|
||||
(byte) idx#6 ← phi( @2/(byte) idx#0 )
|
||||
(byte*) msg#10 ← phi( @2/(byte*) msg#3 )
|
||||
call main
|
||||
to:@4
|
||||
@4: scope:[] from @3
|
||||
(byte*) msg#7 ← phi( @3/(byte*) msg#2 )
|
||||
(byte*) msg#4 ← (byte*) msg#7
|
||||
to:@end
|
||||
@end: scope:[] from @4
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(const string) $0 = (string) "hello @"
|
||||
(const string) $1 = (string) "world @"
|
||||
(label) @2
|
||||
(label) @3
|
||||
(label) @4
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte*) SCREEN
|
||||
(byte*) SCREEN#0
|
||||
(void()) do10((void()*) do10::fn)
|
||||
(bool~) do10::$1
|
||||
(label) do10::@1
|
||||
(label) do10::@return
|
||||
(void()*) do10::fn
|
||||
(void()*) do10::fn#0
|
||||
(void()*) do10::fn#1
|
||||
(void()*) do10::fn#2
|
||||
(void()*) do10::fn#3
|
||||
(byte) do10::i
|
||||
(byte) do10::i#0
|
||||
(byte) do10::i#1
|
||||
(byte) do10::i#2
|
||||
(void()) hello()
|
||||
(bool~) hello::$0
|
||||
(label) hello::@1
|
||||
(label) hello::@return
|
||||
(byte) hello::i
|
||||
(byte) hello::i#0
|
||||
(byte) hello::i#1
|
||||
(byte) hello::i#2
|
||||
(byte) idx
|
||||
(byte) idx#0
|
||||
(byte) idx#1
|
||||
(byte) idx#2
|
||||
(byte) idx#3
|
||||
(byte) idx#4
|
||||
(byte) idx#5
|
||||
(byte) idx#6
|
||||
(void()) main()
|
||||
(void()*~) main::$0
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@return
|
||||
(void()*) main::f
|
||||
(void()*) main::f#0
|
||||
(void()*) main::f#1
|
||||
(byte*) msg
|
||||
(byte*) msg#0
|
||||
(byte*) msg#1
|
||||
(byte*) msg#10
|
||||
(byte*) msg#2
|
||||
(byte*) msg#3
|
||||
(byte*) msg#4
|
||||
(byte*) msg#5
|
||||
(byte*) msg#6
|
||||
(byte*) msg#7
|
||||
(byte*) msg#8
|
||||
(byte*) msg#9
|
||||
(byte[]) msg1
|
||||
(byte[]) msg1#0
|
||||
(byte[]) msg2
|
||||
(byte[]) msg2#0
|
||||
|
||||
Alias (void()*) main::f#0 = (void()*~) main::$0 (void()*) main::f#1
|
||||
Alias (byte*) msg#1 = (byte*) msg#8 (byte*) msg#5 (byte*) msg#2
|
||||
Alias (byte) idx#1 = (byte) idx#4 (byte) idx#2
|
||||
Alias (byte*) msg#10 = (byte*) msg#3
|
||||
Alias (byte) idx#0 = (byte) idx#6
|
||||
Alias (byte*) msg#4 = (byte*) msg#7
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Self Phi Eliminated (void()*) do10::fn#2
|
||||
Self Phi Eliminated (byte*) msg#6
|
||||
Successful SSA optimization Pass2SelfPhiElimination
|
||||
Redundant Phi (void()*) do10::fn#2 (void()*) do10::fn#3
|
||||
Redundant Phi (byte*) msg#9 (byte*) msg#10
|
||||
Redundant Phi (byte) idx#5 (byte) idx#0
|
||||
Redundant Phi (byte*) msg#6 (byte*) msg#9
|
||||
Redundant Phi (byte*) msg#4 (byte*) msg#1
|
||||
Successful SSA optimization Pass2RedundantPhiElimination
|
||||
Simple Condition (bool~) do10::$1 [19] if((byte) do10::i#1!=rangelast(0,9)) goto do10::@1
|
||||
Simple Condition (bool~) hello::$0 [33] if(*((byte*) msg#10 + (byte) hello::i#1)!=(byte) '@') goto hello::@1
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Constant (const void()*) main::f#0 = &hello
|
||||
Constant (const byte) do10::i#0 = 0
|
||||
Constant (const byte*) SCREEN#0 = ((byte*))$400
|
||||
Constant (const byte[]) msg1#0 = $0
|
||||
Constant (const byte[]) msg2#0 = $1
|
||||
Constant (const byte) hello::i#0 = 0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant (const void()*) do10::fn#0 = main::f#0
|
||||
Constant (const void()*) do10::fn#1 = main::f#0
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Resolved ranged next value do10::i#1 ← ++ do10::i#2 to ++
|
||||
Resolved ranged comparison value if(do10::i#1!=rangelast(0,9)) goto do10::@1 to (byte/signed byte/word/signed word/dword/signed dword) $a
|
||||
Culled Empty Block (label) main::@2
|
||||
Culled Empty Block (label) @4
|
||||
Successful SSA optimization Pass2CullEmptyBlocks
|
||||
Inlining constant with var siblings (const byte) do10::i#0
|
||||
Inlining constant with var siblings (const void()*) do10::fn#0
|
||||
Inlining constant with var siblings (const void()*) do10::fn#1
|
||||
Inlining constant with var siblings (const byte) hello::i#0
|
||||
Constant inlined hello::i#0 = (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
Constant inlined do10::i#0 = (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
Constant inlined do10::fn#1 = (const void()*) main::f#0
|
||||
Constant inlined do10::fn#0 = (const void()*) main::f#0
|
||||
Constant inlined $0 = (const byte[]) msg1#0
|
||||
Constant inlined $1 = (const byte[]) msg2#0
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Identical Phi Values (void()*) do10::fn#3 (const void()*) main::f#0
|
||||
Successful SSA optimization Pass2IdenticalPhiElimination
|
||||
Added new block during phi lifting do10::@3(between do10::@1 and do10::@1)
|
||||
Added new block during phi lifting hello::@3(between hello::@1 and hello::@1)
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @3
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of do10
|
||||
CALL GRAPH
|
||||
Calls in [] to main:4
|
||||
Calls in [main] to do10:7 do10:9
|
||||
|
||||
Created 3 initial phi equivalence classes
|
||||
Coalesced [17] do10::i#3 ← do10::i#1
|
||||
Coalesced [18] idx#7 ← idx#0
|
||||
Coalesced [25] hello::i#3 ← hello::i#1
|
||||
Coalesced [26] idx#8 ← idx#1
|
||||
Coalesced down to 3 phi equivalence classes
|
||||
Culled Empty Block (label) do10::@3
|
||||
Culled Empty Block (label) hello::@3
|
||||
Renumbering block @2 to @1
|
||||
Renumbering block @3 to @2
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of do10
|
||||
Adding NOP phi() at start of hello
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] (byte*) msg#10 ← (byte*) 0
|
||||
[2] (byte) idx#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
[3] phi()
|
||||
[4] call main
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
[5] phi()
|
||||
main: scope:[main] from @2
|
||||
[6] (byte*) msg#0 ← (const byte[]) msg1#0
|
||||
[7] call do10
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[8] (byte*) msg#1 ← (const byte[]) msg2#0
|
||||
[9] call do10
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[10] return
|
||||
to:@return
|
||||
do10: scope:[do10] from main main::@1
|
||||
[11] phi()
|
||||
to:do10::@1
|
||||
do10::@1: scope:[do10] from do10 do10::@1
|
||||
[12] (byte) do10::i#2 ← phi( do10/(byte/signed byte/word/signed word/dword/signed dword) 0 do10::@1/(byte) do10::i#1 )
|
||||
[13] call *((const void()*) main::f#0)
|
||||
[14] (byte) do10::i#1 ← ++ (byte) do10::i#2
|
||||
[15] if((byte) do10::i#1!=(byte/signed byte/word/signed word/dword/signed dword) $a) goto do10::@1
|
||||
to:do10::@return
|
||||
do10::@return: scope:[do10] from do10::@1
|
||||
[16] return
|
||||
to:@return
|
||||
hello: scope:[hello] from
|
||||
[17] phi()
|
||||
to:hello::@1
|
||||
hello::@1: scope:[hello] from hello hello::@1
|
||||
[18] (byte) idx#3 ← phi( hello/(byte) idx#0 hello::@1/(byte) idx#1 )
|
||||
[18] (byte) hello::i#2 ← phi( hello/(byte/signed byte/word/signed word/dword/signed dword) 0 hello::@1/(byte) hello::i#1 )
|
||||
[19] *((const byte*) SCREEN#0 + (byte) idx#3) ← *((byte*) msg#10 + (byte) hello::i#2)
|
||||
[20] (byte) idx#1 ← ++ (byte) idx#3
|
||||
[21] (byte) hello::i#1 ← ++ (byte) hello::i#2
|
||||
[22] if(*((byte*) msg#10 + (byte) hello::i#1)!=(byte) '@') goto hello::@1
|
||||
to:hello::@return
|
||||
hello::@return: scope:[hello] from hello::@1
|
||||
[23] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte*) SCREEN
|
||||
(void()) do10((void()*) do10::fn)
|
||||
(void()*) do10::fn
|
||||
(byte) do10::i
|
||||
(byte) do10::i#1 16.5
|
||||
(byte) do10::i#2 11.0
|
||||
(void()) hello()
|
||||
(byte) hello::i
|
||||
(byte) hello::i#1 16.5
|
||||
(byte) hello::i#2 11.0
|
||||
(byte) idx
|
||||
(byte) idx#0 4.0
|
||||
(byte) idx#1 7.333333333333333
|
||||
(byte) idx#3 17.5
|
||||
(void()) main()
|
||||
(void()*) main::f
|
||||
(byte*) msg
|
||||
(byte*) msg#0 20.0
|
||||
(byte*) msg#1 20.0
|
||||
(byte*) msg#10 4.0
|
||||
(byte[]) msg1
|
||||
(byte[]) msg2
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ do10::i#2 do10::i#1 ]
|
||||
[ hello::i#2 hello::i#1 ]
|
||||
[ idx#3 idx#0 idx#1 ]
|
||||
Added variable msg#10 to zero page equivalence class [ msg#10 ]
|
||||
Added variable msg#0 to zero page equivalence class [ msg#0 ]
|
||||
Added variable msg#1 to zero page equivalence class [ msg#1 ]
|
||||
Complete equivalence classes
|
||||
[ do10::i#2 do10::i#1 ]
|
||||
[ hello::i#2 hello::i#1 ]
|
||||
[ idx#3 idx#0 idx#1 ]
|
||||
[ msg#10 ]
|
||||
[ msg#0 ]
|
||||
[ msg#1 ]
|
||||
Allocated zp ZP_BYTE:2 [ do10::i#2 do10::i#1 ]
|
||||
Allocated zp ZP_BYTE:3 [ hello::i#2 hello::i#1 ]
|
||||
Allocated zp ZP_BYTE:4 [ idx#3 idx#0 idx#1 ]
|
||||
Allocated zp ZP_WORD:5 [ msg#10 ]
|
||||
Allocated zp ZP_WORD:7 [ msg#0 ]
|
||||
Allocated zp ZP_WORD:9 [ msg#1 ]
|
||||
|
||||
INITIAL ASM
|
||||
//SEG0 File Comments
|
||||
// Tests calling into a function pointer with local variables
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.label msg = 7
|
||||
.label msg_1 = 9
|
||||
.label idx = 4
|
||||
.label msg_10 = 5
|
||||
//SEG3 @begin
|
||||
bbegin:
|
||||
jmp b1
|
||||
//SEG4 @1
|
||||
b1:
|
||||
//SEG5 [1] (byte*) msg#10 ← (byte*) 0 -- pbuz1=pbuc1
|
||||
lda #<0
|
||||
sta msg_10
|
||||
lda #>0
|
||||
sta msg_10+1
|
||||
//SEG6 [2] (byte) idx#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta idx
|
||||
//SEG7 [3] phi from @1 to @2 [phi:@1->@2]
|
||||
b2_from_b1:
|
||||
jmp b2
|
||||
//SEG8 @2
|
||||
b2:
|
||||
//SEG9 [4] call main
|
||||
jsr main
|
||||
//SEG10 [5] phi from @2 to @end [phi:@2->@end]
|
||||
bend_from_b2:
|
||||
jmp bend
|
||||
//SEG11 @end
|
||||
bend:
|
||||
//SEG12 main
|
||||
main: {
|
||||
.label f = hello
|
||||
//SEG13 [6] (byte*) msg#0 ← (const byte[]) msg1#0 -- pbuz1=pbuc1
|
||||
lda #<msg1
|
||||
sta msg
|
||||
lda #>msg1
|
||||
sta msg+1
|
||||
//SEG14 [7] call do10
|
||||
//SEG15 [11] phi from main to do10 [phi:main->do10]
|
||||
do10_from_main:
|
||||
jsr do10
|
||||
jmp b1
|
||||
//SEG16 main::@1
|
||||
b1:
|
||||
//SEG17 [8] (byte*) msg#1 ← (const byte[]) msg2#0 -- pbuz1=pbuc1
|
||||
lda #<msg2
|
||||
sta msg_1
|
||||
lda #>msg2
|
||||
sta msg_1+1
|
||||
//SEG18 [9] call do10
|
||||
//SEG19 [11] phi from main::@1 to do10 [phi:main::@1->do10]
|
||||
do10_from_b1:
|
||||
jsr do10
|
||||
jmp breturn
|
||||
//SEG20 main::@return
|
||||
breturn:
|
||||
//SEG21 [10] return
|
||||
rts
|
||||
}
|
||||
//SEG22 do10
|
||||
do10: {
|
||||
.label i = 2
|
||||
//SEG23 [12] phi from do10 to do10::@1 [phi:do10->do10::@1]
|
||||
b1_from_do10:
|
||||
//SEG24 [12] phi (byte) do10::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:do10->do10::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta i
|
||||
jmp b1
|
||||
//SEG25 [12] phi from do10::@1 to do10::@1 [phi:do10::@1->do10::@1]
|
||||
b1_from_b1:
|
||||
//SEG26 [12] phi (byte) do10::i#2 = (byte) do10::i#1 [phi:do10::@1->do10::@1#0] -- register_copy
|
||||
jmp b1
|
||||
//SEG27 do10::@1
|
||||
b1:
|
||||
//SEG28 [13] call *((const void()*) main::f#0)
|
||||
jsr main.f
|
||||
//SEG29 [14] (byte) do10::i#1 ← ++ (byte) do10::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc i
|
||||
//SEG30 [15] if((byte) do10::i#1!=(byte/signed byte/word/signed word/dword/signed dword) $a) goto do10::@1 -- vbuz1_neq_vbuc1_then_la1
|
||||
lda #$a
|
||||
cmp i
|
||||
bne b1_from_b1
|
||||
jmp breturn
|
||||
//SEG31 do10::@return
|
||||
breturn:
|
||||
//SEG32 [16] return
|
||||
rts
|
||||
}
|
||||
//SEG33 hello
|
||||
hello: {
|
||||
.label i = 3
|
||||
//SEG34 [18] phi from hello to hello::@1 [phi:hello->hello::@1]
|
||||
b1_from_hello:
|
||||
//SEG35 [18] phi (byte) idx#3 = (byte) idx#0 [phi:hello->hello::@1#0] -- register_copy
|
||||
//SEG36 [18] phi (byte) hello::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:hello->hello::@1#1] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta i
|
||||
jmp b1
|
||||
//SEG37 [18] phi from hello::@1 to hello::@1 [phi:hello::@1->hello::@1]
|
||||
b1_from_b1:
|
||||
//SEG38 [18] phi (byte) idx#3 = (byte) idx#1 [phi:hello::@1->hello::@1#0] -- register_copy
|
||||
//SEG39 [18] phi (byte) hello::i#2 = (byte) hello::i#1 [phi:hello::@1->hello::@1#1] -- register_copy
|
||||
jmp b1
|
||||
//SEG40 hello::@1
|
||||
b1:
|
||||
//SEG41 [19] *((const byte*) SCREEN#0 + (byte) idx#3) ← *((byte*) msg#10 + (byte) hello::i#2) -- pbuc1_derefidx_vbuz1=pbuz2_derefidx_vbuz3
|
||||
ldx idx
|
||||
ldy i
|
||||
lda (msg_10),y
|
||||
sta SCREEN,x
|
||||
//SEG42 [20] (byte) idx#1 ← ++ (byte) idx#3 -- vbuz1=_inc_vbuz1
|
||||
inc idx
|
||||
//SEG43 [21] (byte) hello::i#1 ← ++ (byte) hello::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc i
|
||||
//SEG44 [22] if(*((byte*) msg#10 + (byte) hello::i#1)!=(byte) '@') goto hello::@1 -- pbuz1_derefidx_vbuz2_neq_vbuc1_then_la1
|
||||
ldy i
|
||||
lda (msg_10),y
|
||||
cmp #'@'
|
||||
bne b1_from_b1
|
||||
jmp breturn
|
||||
//SEG45 hello::@return
|
||||
breturn:
|
||||
//SEG46 [23] return
|
||||
rts
|
||||
}
|
||||
msg1: .text "hello @"
|
||||
msg2: .text "world @"
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [1] (byte*) msg#10 ← (byte*) 0 [ ] ( ) always clobbers reg byte a
|
||||
Statement [2] (byte) idx#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 [ ] ( ) always clobbers reg byte a
|
||||
Statement [6] (byte*) msg#0 ← (const byte[]) msg1#0 [ ] ( main:4 [ ] ) always clobbers reg byte a
|
||||
Statement [8] (byte*) msg#1 ← (const byte[]) msg2#0 [ ] ( main:4 [ ] ) always clobbers reg byte a
|
||||
Statement [13] call *((const void()*) main::f#0) [ do10::i#2 ] ( main:4::do10:7 [ do10::i#2 ] main:4::do10:9 [ do10::i#2 ] ) always clobbers reg byte a reg byte x reg byte y
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ do10::i#2 do10::i#1 ]
|
||||
Removing always clobbered register reg byte x as potential for zp ZP_BYTE:2 [ do10::i#2 do10::i#1 ]
|
||||
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:2 [ do10::i#2 do10::i#1 ]
|
||||
Statement [15] if((byte) do10::i#1!=(byte/signed byte/word/signed word/dword/signed dword) $a) goto do10::@1 [ do10::i#1 ] ( main:4::do10:7 [ do10::i#1 ] main:4::do10:9 [ do10::i#1 ] ) always clobbers reg byte a
|
||||
Statement [19] *((const byte*) SCREEN#0 + (byte) idx#3) ← *((byte*) msg#10 + (byte) hello::i#2) [ msg#10 hello::i#2 idx#3 ] ( [ msg#10 hello::i#2 idx#3 ] ) always clobbers reg byte a reg byte x
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:3 [ hello::i#2 hello::i#1 ]
|
||||
Removing always clobbered register reg byte x as potential for zp ZP_BYTE:3 [ hello::i#2 hello::i#1 ]
|
||||
Statement [22] if(*((byte*) msg#10 + (byte) hello::i#1)!=(byte) '@') goto hello::@1 [ msg#10 hello::i#1 idx#1 ] ( [ msg#10 hello::i#1 idx#1 ] ) always clobbers reg byte a
|
||||
Statement [1] (byte*) msg#10 ← (byte*) 0 [ ] ( ) always clobbers reg byte a
|
||||
Statement [2] (byte) idx#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 [ ] ( ) always clobbers reg byte a
|
||||
Statement [6] (byte*) msg#0 ← (const byte[]) msg1#0 [ ] ( main:4 [ ] ) always clobbers reg byte a
|
||||
Statement [8] (byte*) msg#1 ← (const byte[]) msg2#0 [ ] ( main:4 [ ] ) always clobbers reg byte a
|
||||
Statement [13] call *((const void()*) main::f#0) [ do10::i#2 ] ( main:4::do10:7 [ do10::i#2 ] main:4::do10:9 [ do10::i#2 ] ) always clobbers reg byte a reg byte x reg byte y
|
||||
Statement [15] if((byte) do10::i#1!=(byte/signed byte/word/signed word/dword/signed dword) $a) goto do10::@1 [ do10::i#1 ] ( main:4::do10:7 [ do10::i#1 ] main:4::do10:9 [ do10::i#1 ] ) always clobbers reg byte a
|
||||
Statement [19] *((const byte*) SCREEN#0 + (byte) idx#3) ← *((byte*) msg#10 + (byte) hello::i#2) [ msg#10 hello::i#2 idx#3 ] ( [ msg#10 hello::i#2 idx#3 ] ) always clobbers reg byte a reg byte x
|
||||
Statement [22] if(*((byte*) msg#10 + (byte) hello::i#1)!=(byte) '@') goto hello::@1 [ msg#10 hello::i#1 idx#1 ] ( [ msg#10 hello::i#1 idx#1 ] ) always clobbers reg byte a
|
||||
Potential registers zp ZP_BYTE:2 [ do10::i#2 do10::i#1 ] : zp ZP_BYTE:2 ,
|
||||
Potential registers zp ZP_BYTE:3 [ hello::i#2 hello::i#1 ] : zp ZP_BYTE:3 , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:4 [ idx#3 idx#0 idx#1 ] : zp ZP_BYTE:4 ,
|
||||
Potential registers zp ZP_WORD:5 [ msg#10 ] : zp ZP_WORD:5 ,
|
||||
Potential registers zp ZP_WORD:7 [ msg#0 ] : zp ZP_WORD:7 ,
|
||||
Potential registers zp ZP_WORD:9 [ msg#1 ] : zp ZP_WORD:9 ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [] 28.83: zp ZP_BYTE:4 [ idx#3 idx#0 idx#1 ] 20: zp ZP_WORD:7 [ msg#0 ] 20: zp ZP_WORD:9 [ msg#1 ] 4: zp ZP_WORD:5 [ msg#10 ]
|
||||
Uplift Scope [do10] 27.5: zp ZP_BYTE:2 [ do10::i#2 do10::i#1 ]
|
||||
Uplift Scope [hello] 27.5: zp ZP_BYTE:3 [ hello::i#2 hello::i#1 ]
|
||||
Uplift Scope [main]
|
||||
|
||||
Uplifting [] best 973 combination zp ZP_BYTE:4 [ idx#3 idx#0 idx#1 ] zp ZP_WORD:7 [ msg#0 ] zp ZP_WORD:9 [ msg#1 ] zp ZP_WORD:5 [ msg#10 ]
|
||||
Uplifting [do10] best 973 combination zp ZP_BYTE:2 [ do10::i#2 do10::i#1 ]
|
||||
Uplifting [hello] best 853 combination reg byte y [ hello::i#2 hello::i#1 ]
|
||||
Uplifting [main] best 853 combination
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:4 [ idx#3 idx#0 idx#1 ]
|
||||
Uplifting [] best 853 combination zp ZP_BYTE:4 [ idx#3 idx#0 idx#1 ]
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:2 [ do10::i#2 do10::i#1 ]
|
||||
Uplifting [do10] best 853 combination zp ZP_BYTE:2 [ do10::i#2 do10::i#1 ]
|
||||
Coalescing zero page register [ zp ZP_WORD:5 [ msg#10 ] ] with [ zp ZP_WORD:7 [ msg#0 ] ]
|
||||
Coalescing zero page register [ zp ZP_WORD:5 [ msg#10 msg#0 ] ] with [ zp ZP_WORD:9 [ msg#1 ] ]
|
||||
Allocated (was zp ZP_BYTE:4) zp ZP_BYTE:3 [ idx#3 idx#0 idx#1 ]
|
||||
Allocated (was zp ZP_WORD:5) zp ZP_WORD:4 [ msg#10 msg#0 msg#1 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
//SEG0 File Comments
|
||||
// Tests calling into a function pointer with local variables
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.label msg = 4
|
||||
.label idx = 3
|
||||
//SEG3 @begin
|
||||
bbegin:
|
||||
jmp b1
|
||||
//SEG4 @1
|
||||
b1:
|
||||
//SEG5 [1] (byte*) msg#10 ← (byte*) 0 -- pbuz1=pbuc1
|
||||
lda #<0
|
||||
sta msg
|
||||
lda #>0
|
||||
sta msg+1
|
||||
//SEG6 [2] (byte) idx#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta idx
|
||||
//SEG7 [3] phi from @1 to @2 [phi:@1->@2]
|
||||
b2_from_b1:
|
||||
jmp b2
|
||||
//SEG8 @2
|
||||
b2:
|
||||
//SEG9 [4] call main
|
||||
jsr main
|
||||
//SEG10 [5] phi from @2 to @end [phi:@2->@end]
|
||||
bend_from_b2:
|
||||
jmp bend
|
||||
//SEG11 @end
|
||||
bend:
|
||||
//SEG12 main
|
||||
main: {
|
||||
.label f = hello
|
||||
//SEG13 [6] (byte*) msg#0 ← (const byte[]) msg1#0 -- pbuz1=pbuc1
|
||||
lda #<msg1
|
||||
sta msg
|
||||
lda #>msg1
|
||||
sta msg+1
|
||||
//SEG14 [7] call do10
|
||||
//SEG15 [11] phi from main to do10 [phi:main->do10]
|
||||
do10_from_main:
|
||||
jsr do10
|
||||
jmp b1
|
||||
//SEG16 main::@1
|
||||
b1:
|
||||
//SEG17 [8] (byte*) msg#1 ← (const byte[]) msg2#0 -- pbuz1=pbuc1
|
||||
lda #<msg2
|
||||
sta msg
|
||||
lda #>msg2
|
||||
sta msg+1
|
||||
//SEG18 [9] call do10
|
||||
//SEG19 [11] phi from main::@1 to do10 [phi:main::@1->do10]
|
||||
do10_from_b1:
|
||||
jsr do10
|
||||
jmp breturn
|
||||
//SEG20 main::@return
|
||||
breturn:
|
||||
//SEG21 [10] return
|
||||
rts
|
||||
}
|
||||
//SEG22 do10
|
||||
do10: {
|
||||
.label i = 2
|
||||
//SEG23 [12] phi from do10 to do10::@1 [phi:do10->do10::@1]
|
||||
b1_from_do10:
|
||||
//SEG24 [12] phi (byte) do10::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:do10->do10::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta i
|
||||
jmp b1
|
||||
//SEG25 [12] phi from do10::@1 to do10::@1 [phi:do10::@1->do10::@1]
|
||||
b1_from_b1:
|
||||
//SEG26 [12] phi (byte) do10::i#2 = (byte) do10::i#1 [phi:do10::@1->do10::@1#0] -- register_copy
|
||||
jmp b1
|
||||
//SEG27 do10::@1
|
||||
b1:
|
||||
//SEG28 [13] call *((const void()*) main::f#0)
|
||||
jsr main.f
|
||||
//SEG29 [14] (byte) do10::i#1 ← ++ (byte) do10::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc i
|
||||
//SEG30 [15] if((byte) do10::i#1!=(byte/signed byte/word/signed word/dword/signed dword) $a) goto do10::@1 -- vbuz1_neq_vbuc1_then_la1
|
||||
lda #$a
|
||||
cmp i
|
||||
bne b1_from_b1
|
||||
jmp breturn
|
||||
//SEG31 do10::@return
|
||||
breturn:
|
||||
//SEG32 [16] return
|
||||
rts
|
||||
}
|
||||
//SEG33 hello
|
||||
hello: {
|
||||
//SEG34 [18] phi from hello to hello::@1 [phi:hello->hello::@1]
|
||||
b1_from_hello:
|
||||
//SEG35 [18] phi (byte) idx#3 = (byte) idx#0 [phi:hello->hello::@1#0] -- register_copy
|
||||
//SEG36 [18] phi (byte) hello::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:hello->hello::@1#1] -- vbuyy=vbuc1
|
||||
ldy #0
|
||||
jmp b1
|
||||
//SEG37 [18] phi from hello::@1 to hello::@1 [phi:hello::@1->hello::@1]
|
||||
b1_from_b1:
|
||||
//SEG38 [18] phi (byte) idx#3 = (byte) idx#1 [phi:hello::@1->hello::@1#0] -- register_copy
|
||||
//SEG39 [18] phi (byte) hello::i#2 = (byte) hello::i#1 [phi:hello::@1->hello::@1#1] -- register_copy
|
||||
jmp b1
|
||||
//SEG40 hello::@1
|
||||
b1:
|
||||
//SEG41 [19] *((const byte*) SCREEN#0 + (byte) idx#3) ← *((byte*) msg#10 + (byte) hello::i#2) -- pbuc1_derefidx_vbuz1=pbuz2_derefidx_vbuyy
|
||||
lda (msg),y
|
||||
ldx idx
|
||||
sta SCREEN,x
|
||||
//SEG42 [20] (byte) idx#1 ← ++ (byte) idx#3 -- vbuz1=_inc_vbuz1
|
||||
inc idx
|
||||
//SEG43 [21] (byte) hello::i#1 ← ++ (byte) hello::i#2 -- vbuyy=_inc_vbuyy
|
||||
iny
|
||||
//SEG44 [22] if(*((byte*) msg#10 + (byte) hello::i#1)!=(byte) '@') goto hello::@1 -- pbuz1_derefidx_vbuyy_neq_vbuc1_then_la1
|
||||
lda (msg),y
|
||||
cmp #'@'
|
||||
bne b1_from_b1
|
||||
jmp breturn
|
||||
//SEG45 hello::@return
|
||||
breturn:
|
||||
//SEG46 [23] return
|
||||
rts
|
||||
}
|
||||
msg1: .text "hello @"
|
||||
msg2: .text "world @"
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp b2
|
||||
Removing instruction jmp bend
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp breturn
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp breturn
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction lda #>0
|
||||
Removing instruction lda #0
|
||||
Succesful ASM optimization Pass5UnnecesaryLoadElimination
|
||||
Replacing label b1_from_b1 with b1
|
||||
Replacing label b1_from_b1 with b1
|
||||
Removing instruction b1:
|
||||
Removing instruction b2_from_b1:
|
||||
Removing instruction bend_from_b2:
|
||||
Removing instruction b1_from_b1:
|
||||
Removing instruction b1_from_b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction b2:
|
||||
Removing instruction bend:
|
||||
Removing instruction do10_from_main:
|
||||
Removing instruction b1:
|
||||
Removing instruction do10_from_b1:
|
||||
Removing instruction breturn:
|
||||
Removing instruction b1_from_do10:
|
||||
Removing instruction breturn:
|
||||
Removing instruction b1_from_hello:
|
||||
Removing instruction breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Adding RTS to root block
|
||||
Succesful ASM optimization Pass5AddMainRts
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp b1
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte*) SCREEN
|
||||
(const byte*) SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) $400
|
||||
(void()) do10((void()*) do10::fn)
|
||||
(label) do10::@1
|
||||
(label) do10::@return
|
||||
(void()*) do10::fn
|
||||
(byte) do10::i
|
||||
(byte) do10::i#1 i zp ZP_BYTE:2 16.5
|
||||
(byte) do10::i#2 i zp ZP_BYTE:2 11.0
|
||||
(void()) hello()
|
||||
(label) hello::@1
|
||||
(label) hello::@return
|
||||
(byte) hello::i
|
||||
(byte) hello::i#1 reg byte y 16.5
|
||||
(byte) hello::i#2 reg byte y 11.0
|
||||
(byte) idx
|
||||
(byte) idx#0 idx zp ZP_BYTE:3 4.0
|
||||
(byte) idx#1 idx zp ZP_BYTE:3 7.333333333333333
|
||||
(byte) idx#3 idx zp ZP_BYTE:3 17.5
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(void()*) main::f
|
||||
(const void()*) main::f#0 f = &(void()) hello()
|
||||
(byte*) msg
|
||||
(byte*) msg#0 msg zp ZP_WORD:4 20.0
|
||||
(byte*) msg#1 msg zp ZP_WORD:4 20.0
|
||||
(byte*) msg#10 msg zp ZP_WORD:4 4.0
|
||||
(byte[]) msg1
|
||||
(const byte[]) msg1#0 msg1 = (string) "hello @"
|
||||
(byte[]) msg2
|
||||
(const byte[]) msg2#0 msg2 = (string) "world @"
|
||||
|
||||
zp ZP_BYTE:2 [ do10::i#2 do10::i#1 ]
|
||||
reg byte y [ hello::i#2 hello::i#1 ]
|
||||
zp ZP_BYTE:3 [ idx#3 idx#0 idx#1 ]
|
||||
zp ZP_WORD:4 [ msg#10 msg#0 msg#1 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 633
|
||||
|
||||
//SEG0 File Comments
|
||||
// Tests calling into a function pointer with local variables
|
||||
//SEG1 Basic Upstart
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(bbegin)
|
||||
.pc = $80d "Program"
|
||||
//SEG2 Global Constants & labels
|
||||
.label SCREEN = $400
|
||||
.label msg = 4
|
||||
.label idx = 3
|
||||
//SEG3 @begin
|
||||
bbegin:
|
||||
//SEG4 @1
|
||||
//SEG5 [1] (byte*) msg#10 ← (byte*) 0 -- pbuz1=pbuc1
|
||||
lda #<0
|
||||
sta msg
|
||||
sta msg+1
|
||||
//SEG6 [2] (byte) idx#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 -- vbuz1=vbuc1
|
||||
sta idx
|
||||
//SEG7 [3] phi from @1 to @2 [phi:@1->@2]
|
||||
//SEG8 @2
|
||||
//SEG9 [4] call main
|
||||
jsr main
|
||||
rts
|
||||
//SEG10 [5] phi from @2 to @end [phi:@2->@end]
|
||||
//SEG11 @end
|
||||
//SEG12 main
|
||||
main: {
|
||||
.label f = hello
|
||||
//SEG13 [6] (byte*) msg#0 ← (const byte[]) msg1#0 -- pbuz1=pbuc1
|
||||
lda #<msg1
|
||||
sta msg
|
||||
lda #>msg1
|
||||
sta msg+1
|
||||
//SEG14 [7] call do10
|
||||
//SEG15 [11] phi from main to do10 [phi:main->do10]
|
||||
jsr do10
|
||||
//SEG16 main::@1
|
||||
//SEG17 [8] (byte*) msg#1 ← (const byte[]) msg2#0 -- pbuz1=pbuc1
|
||||
lda #<msg2
|
||||
sta msg
|
||||
lda #>msg2
|
||||
sta msg+1
|
||||
//SEG18 [9] call do10
|
||||
//SEG19 [11] phi from main::@1 to do10 [phi:main::@1->do10]
|
||||
jsr do10
|
||||
//SEG20 main::@return
|
||||
//SEG21 [10] return
|
||||
rts
|
||||
}
|
||||
//SEG22 do10
|
||||
do10: {
|
||||
.label i = 2
|
||||
//SEG23 [12] phi from do10 to do10::@1 [phi:do10->do10::@1]
|
||||
//SEG24 [12] phi (byte) do10::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:do10->do10::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta i
|
||||
//SEG25 [12] phi from do10::@1 to do10::@1 [phi:do10::@1->do10::@1]
|
||||
//SEG26 [12] phi (byte) do10::i#2 = (byte) do10::i#1 [phi:do10::@1->do10::@1#0] -- register_copy
|
||||
//SEG27 do10::@1
|
||||
b1:
|
||||
//SEG28 [13] call *((const void()*) main::f#0)
|
||||
jsr main.f
|
||||
//SEG29 [14] (byte) do10::i#1 ← ++ (byte) do10::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc i
|
||||
//SEG30 [15] if((byte) do10::i#1!=(byte/signed byte/word/signed word/dword/signed dword) $a) goto do10::@1 -- vbuz1_neq_vbuc1_then_la1
|
||||
lda #$a
|
||||
cmp i
|
||||
bne b1
|
||||
//SEG31 do10::@return
|
||||
//SEG32 [16] return
|
||||
rts
|
||||
}
|
||||
//SEG33 hello
|
||||
hello: {
|
||||
//SEG34 [18] phi from hello to hello::@1 [phi:hello->hello::@1]
|
||||
//SEG35 [18] phi (byte) idx#3 = (byte) idx#0 [phi:hello->hello::@1#0] -- register_copy
|
||||
//SEG36 [18] phi (byte) hello::i#2 = (byte/signed byte/word/signed word/dword/signed dword) 0 [phi:hello->hello::@1#1] -- vbuyy=vbuc1
|
||||
ldy #0
|
||||
//SEG37 [18] phi from hello::@1 to hello::@1 [phi:hello::@1->hello::@1]
|
||||
//SEG38 [18] phi (byte) idx#3 = (byte) idx#1 [phi:hello::@1->hello::@1#0] -- register_copy
|
||||
//SEG39 [18] phi (byte) hello::i#2 = (byte) hello::i#1 [phi:hello::@1->hello::@1#1] -- register_copy
|
||||
//SEG40 hello::@1
|
||||
b1:
|
||||
//SEG41 [19] *((const byte*) SCREEN#0 + (byte) idx#3) ← *((byte*) msg#10 + (byte) hello::i#2) -- pbuc1_derefidx_vbuz1=pbuz2_derefidx_vbuyy
|
||||
lda (msg),y
|
||||
ldx idx
|
||||
sta SCREEN,x
|
||||
//SEG42 [20] (byte) idx#1 ← ++ (byte) idx#3 -- vbuz1=_inc_vbuz1
|
||||
inc idx
|
||||
//SEG43 [21] (byte) hello::i#1 ← ++ (byte) hello::i#2 -- vbuyy=_inc_vbuyy
|
||||
iny
|
||||
//SEG44 [22] if(*((byte*) msg#10 + (byte) hello::i#1)!=(byte) '@') goto hello::@1 -- pbuz1_derefidx_vbuyy_neq_vbuc1_then_la1
|
||||
lda (msg),y
|
||||
cmp #'@'
|
||||
bne b1
|
||||
//SEG45 hello::@return
|
||||
//SEG46 [23] return
|
||||
rts
|
||||
}
|
||||
msg1: .text "hello @"
|
||||
msg2: .text "world @"
|
||||
|
41
src/test/ref/function-pointer-noarg-call-8.sym
Normal file
41
src/test/ref/function-pointer-noarg-call-8.sym
Normal file
@ -0,0 +1,41 @@
|
||||
(label) @1
|
||||
(label) @2
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte*) SCREEN
|
||||
(const byte*) SCREEN#0 SCREEN = ((byte*))(word/signed word/dword/signed dword) $400
|
||||
(void()) do10((void()*) do10::fn)
|
||||
(label) do10::@1
|
||||
(label) do10::@return
|
||||
(void()*) do10::fn
|
||||
(byte) do10::i
|
||||
(byte) do10::i#1 i zp ZP_BYTE:2 16.5
|
||||
(byte) do10::i#2 i zp ZP_BYTE:2 11.0
|
||||
(void()) hello()
|
||||
(label) hello::@1
|
||||
(label) hello::@return
|
||||
(byte) hello::i
|
||||
(byte) hello::i#1 reg byte y 16.5
|
||||
(byte) hello::i#2 reg byte y 11.0
|
||||
(byte) idx
|
||||
(byte) idx#0 idx zp ZP_BYTE:3 4.0
|
||||
(byte) idx#1 idx zp ZP_BYTE:3 7.333333333333333
|
||||
(byte) idx#3 idx zp ZP_BYTE:3 17.5
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@return
|
||||
(void()*) main::f
|
||||
(const void()*) main::f#0 f = &(void()) hello()
|
||||
(byte*) msg
|
||||
(byte*) msg#0 msg zp ZP_WORD:4 20.0
|
||||
(byte*) msg#1 msg zp ZP_WORD:4 20.0
|
||||
(byte*) msg#10 msg zp ZP_WORD:4 4.0
|
||||
(byte[]) msg1
|
||||
(const byte[]) msg1#0 msg1 = (string) "hello @"
|
||||
(byte[]) msg2
|
||||
(const byte[]) msg2#0 msg2 = (string) "world @"
|
||||
|
||||
zp ZP_BYTE:2 [ do10::i#2 do10::i#1 ]
|
||||
reg byte y [ hello::i#2 hello::i#1 ]
|
||||
zp ZP_BYTE:3 [ idx#3 idx#0 idx#1 ]
|
||||
zp ZP_WORD:4 [ msg#10 msg#0 msg#1 ]
|
@ -139,6 +139,7 @@ fn1: {
|
||||
}
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [4] call *((const void()*) main::f#0) [ ] ( main:2 [ ] ) always clobbers reg byte a reg byte x reg byte y
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main]
|
||||
|
@ -7,6 +7,7 @@ bbegin:
|
||||
lda #$c
|
||||
sta x
|
||||
jsr main
|
||||
rts
|
||||
main: {
|
||||
b1:
|
||||
inc x
|
||||
|
@ -280,6 +280,8 @@ Removing instruction bend:
|
||||
Removing instruction b2:
|
||||
Removing instruction breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Adding RTS to root block
|
||||
Succesful ASM optimization Pass5AddMainRts
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
@ -299,7 +301,7 @@ zp ZP_BYTE:2 [ x#5 x#0 x#1 x#2 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 147
|
||||
Score: 153
|
||||
|
||||
//SEG0 File Comments
|
||||
// Illustrates a problem where volatiles with initializers are initialized outside the main()-routine
|
||||
@ -319,6 +321,7 @@ bbegin:
|
||||
//SEG7 [2] call main
|
||||
//SEG8 [4] phi from @1 to main [phi:@1->main]
|
||||
jsr main
|
||||
rts
|
||||
//SEG9 [3] phi from @1 to @end [phi:@1->@end]
|
||||
//SEG10 @end
|
||||
//SEG11 main
|
||||
|
@ -12,6 +12,7 @@ bbegin:
|
||||
lda #8
|
||||
sta col2
|
||||
jsr main
|
||||
rts
|
||||
main: {
|
||||
lda #<irq
|
||||
sta KERNEL_IRQ
|
||||
|
@ -334,6 +334,8 @@ Removing instruction bend:
|
||||
Removing instruction breturn:
|
||||
Removing instruction breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Adding RTS to root block
|
||||
Succesful ASM optimization Pass5AddMainRts
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
@ -359,7 +361,7 @@ zp ZP_BYTE:3 [ col2#0 col2#1 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 61
|
||||
Score: 67
|
||||
|
||||
//SEG0 File Comments
|
||||
// Illustrates problem where volatiles reuse the same ZP addresses for multiple overlapping volatiles
|
||||
@ -384,6 +386,7 @@ bbegin:
|
||||
//SEG7 @1
|
||||
//SEG8 [3] call main
|
||||
jsr main
|
||||
rts
|
||||
//SEG9 [4] phi from @1 to @end [phi:@1->@end]
|
||||
//SEG10 @end
|
||||
//SEG11 main
|
||||
|
@ -10,6 +10,7 @@ bbegin:
|
||||
lda #0
|
||||
sta col1
|
||||
jsr main
|
||||
rts
|
||||
main: {
|
||||
.label y = 2
|
||||
lda #<irq
|
||||
|
@ -647,6 +647,8 @@ Skipping double jump to b1 in bne b6
|
||||
Succesful ASM optimization Pass5DoubleJumpElimination
|
||||
Relabelling long label b1_from_b5 to b4
|
||||
Succesful ASM optimization Pass5RelabelLongLabels
|
||||
Adding RTS to root block
|
||||
Succesful ASM optimization Pass5AddMainRts
|
||||
Removing instruction jmp b2
|
||||
Removing instruction jmp b3
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
@ -697,7 +699,7 @@ reg byte a [ main::$1 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 223698
|
||||
Score: 223704
|
||||
|
||||
//SEG0 File Comments
|
||||
// Illustrates problem where volatiles reuse ZP addresses of other variables
|
||||
@ -719,6 +721,7 @@ bbegin:
|
||||
//SEG6 @1
|
||||
//SEG7 [2] call main
|
||||
jsr main
|
||||
rts
|
||||
//SEG8 [3] phi from @1 to @end [phi:@1->@end]
|
||||
//SEG9 @end
|
||||
//SEG10 main
|
||||
|
@ -25,6 +25,7 @@ bbegin:
|
||||
lda #0
|
||||
sta irq_idx
|
||||
jsr main
|
||||
rts
|
||||
main: {
|
||||
sei
|
||||
// Disable CIA 1 Timer IRQ
|
||||
|
@ -1115,9 +1115,11 @@ Removing instruction b6:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Skipping double jump to $ea81 in bcs breturn
|
||||
Succesful ASM optimization Pass5DoubleJumpElimination
|
||||
Adding RTS to root block
|
||||
Succesful ASM optimization Pass5AddMainRts
|
||||
Removing instruction breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Fixing long branch [67] bcs $ea81 to bcc
|
||||
Fixing long branch [68] bcs $ea81 to bcc
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
@ -1249,7 +1251,7 @@ reg byte x [ table_driven_irq::val#0 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 598
|
||||
Score: 604
|
||||
|
||||
//SEG0 File Comments
|
||||
// Test interrupt routine using a variable between calls (irq_idx)
|
||||
@ -1287,6 +1289,7 @@ bbegin:
|
||||
//SEG7 @2
|
||||
//SEG8 [3] call main
|
||||
jsr main
|
||||
rts
|
||||
//SEG9 [4] phi from @2 to @end [phi:@2->@end]
|
||||
//SEG10 @end
|
||||
//SEG11 main
|
||||
|
@ -17,6 +17,7 @@ bbegin:
|
||||
lda #0
|
||||
sta framedone
|
||||
jsr main
|
||||
rts
|
||||
main: {
|
||||
sei
|
||||
// Disable CIA 1 Timer IRQ
|
||||
|
@ -537,6 +537,8 @@ Removing instruction b2:
|
||||
Removing instruction b2:
|
||||
Removing instruction breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Adding RTS to root block
|
||||
Succesful ASM optimization Pass5AddMainRts
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
@ -577,7 +579,7 @@ zp ZP_BOOL:2 [ framedone#11 framedone#0 framedone#3 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 1022
|
||||
Score: 1028
|
||||
|
||||
//SEG0 File Comments
|
||||
// Illustrates a problem where a volatile bool modified at the end of an IRQ is not stored properly
|
||||
@ -607,6 +609,7 @@ bbegin:
|
||||
//SEG7 @2
|
||||
//SEG8 [3] call main
|
||||
jsr main
|
||||
rts
|
||||
//SEG9 [4] phi from @2 to @end [phi:@2->@end]
|
||||
//SEG10 @end
|
||||
//SEG11 main
|
||||
|
@ -9,6 +9,7 @@ bbegin:
|
||||
lda #0
|
||||
sta col
|
||||
jsr main
|
||||
rts
|
||||
main: {
|
||||
lda #<irq
|
||||
sta KERNEL_IRQ
|
||||
|
@ -432,13 +432,15 @@ Skipping double jump to $ea81 in beq breturn
|
||||
Succesful ASM optimization Pass5DoubleJumpElimination
|
||||
Relabelling long label b1_from_b3 to b1
|
||||
Succesful ASM optimization Pass5RelabelLongLabels
|
||||
Adding RTS to root block
|
||||
Succesful ASM optimization Pass5AddMainRts
|
||||
Removing instruction jmp b2
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction b1:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Fixing long branch [30] beq $ea81 to bne
|
||||
Fixing long branch [31] beq $ea81 to bne
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
@ -465,7 +467,7 @@ zp ZP_BYTE:2 [ col#12 col#0 col#1 col#3 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 882
|
||||
Score: 888
|
||||
|
||||
//SEG0 File Comments
|
||||
// Tests that long branch fixing works with interrupt exits (to $ea81)
|
||||
@ -486,6 +488,7 @@ bbegin:
|
||||
//SEG6 @1
|
||||
//SEG7 [2] call main
|
||||
jsr main
|
||||
rts
|
||||
//SEG8 [3] phi from @1 to @end [phi:@1->@end]
|
||||
//SEG9 @end
|
||||
//SEG10 main
|
||||
|
@ -57,6 +57,7 @@ bbegin:
|
||||
lda #1
|
||||
sta framedone
|
||||
jsr main
|
||||
rts
|
||||
main: {
|
||||
sei
|
||||
jsr init
|
||||
|
@ -4274,6 +4274,8 @@ Removing instruction b5:
|
||||
Removing instruction b3:
|
||||
Removing instruction b4:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Adding RTS to root block
|
||||
Succesful ASM optimization Pass5AddMainRts
|
||||
Removing instruction jmp b4
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp plexFreePrepare1_b1
|
||||
@ -4585,7 +4587,7 @@ reg byte x [ plexShowSprite::$6 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 47272
|
||||
Score: 47278
|
||||
|
||||
//SEG0 File Comments
|
||||
// A simple usage of the flexible sprite multiplexer routine
|
||||
@ -4664,6 +4666,7 @@ bbegin:
|
||||
//SEG16 @5
|
||||
//SEG17 [9] call main
|
||||
jsr main
|
||||
rts
|
||||
//SEG18 [10] phi from @5 to @end [phi:@5->@end]
|
||||
//SEG19 @end
|
||||
//SEG20 main
|
||||
|
@ -10,6 +10,7 @@ bbegin:
|
||||
lda #0
|
||||
sta col
|
||||
jsr main
|
||||
rts
|
||||
main: {
|
||||
lda #<irq
|
||||
sta KERNEL_IRQ
|
||||
|
@ -461,6 +461,8 @@ Skipping double jump to $ea81 in jmp breturn
|
||||
Succesful ASM optimization Pass5DoubleJumpElimination
|
||||
Relabelling long label b1_from_b3 to b1
|
||||
Succesful ASM optimization Pass5RelabelLongLabels
|
||||
Adding RTS to root block
|
||||
Succesful ASM optimization Pass5AddMainRts
|
||||
Removing instruction jmp b2
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction lda col
|
||||
@ -497,7 +499,7 @@ zp ZP_BYTE:2 [ col#14 col#0 col#1 col#4 col#3 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 889
|
||||
Score: 895
|
||||
|
||||
//SEG0 File Comments
|
||||
// Tests that volatile variables can be both read & written inside & outside interrupts
|
||||
@ -519,6 +521,7 @@ bbegin:
|
||||
//SEG6 @1
|
||||
//SEG7 [2] call main
|
||||
jsr main
|
||||
rts
|
||||
//SEG8 [3] phi from @1 to @end [phi:@1->@end]
|
||||
//SEG9 @end
|
||||
//SEG10 main
|
||||
|
@ -8,6 +8,7 @@ bbegin:
|
||||
lda #0
|
||||
sta col
|
||||
jsr main
|
||||
rts
|
||||
main: {
|
||||
lda #<irq
|
||||
sta KERNEL_IRQ
|
||||
|
@ -310,6 +310,8 @@ Removing instruction b1:
|
||||
Removing instruction bend:
|
||||
Removing instruction breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Adding RTS to root block
|
||||
Succesful ASM optimization Pass5AddMainRts
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
@ -333,7 +335,7 @@ zp ZP_BYTE:2 [ col#2 col#0 col#1 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 117
|
||||
Score: 123
|
||||
|
||||
//SEG0 File Comments
|
||||
//SEG1 Basic Upstart
|
||||
@ -353,6 +355,7 @@ bbegin:
|
||||
//SEG6 @1
|
||||
//SEG7 [2] call main
|
||||
jsr main
|
||||
rts
|
||||
//SEG8 [3] phi from @1 to @end [phi:@1->@end]
|
||||
//SEG9 @end
|
||||
//SEG10 main
|
||||
|
Loading…
x
Reference in New Issue
Block a user