From 29aa5322b2ac92f6de72d1e5fd6bc404b1322490 Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Fri, 31 May 2019 01:56:59 +0200 Subject: [PATCH] Fixed issue with const/label. --- .../kickc/passes/Pass4CodeGeneration.java | 54 +- .../dk/camelot64/kickc/test/TestPrograms.java | 5 + src/test/kc/robozzle64-label-problem.kc | 11 + src/test/ref/robozzle64-label-problem.asm | 87 ++ src/test/ref/robozzle64-label-problem.cfg | 61 + src/test/ref/robozzle64-label-problem.log | 1148 +++++++++++++++++ src/test/ref/robozzle64-label-problem.sym | 1 + 7 files changed, 1339 insertions(+), 28 deletions(-) create mode 100644 src/test/kc/robozzle64-label-problem.kc create mode 100644 src/test/ref/robozzle64-label-problem.asm create mode 100644 src/test/ref/robozzle64-label-problem.cfg create mode 100644 src/test/ref/robozzle64-label-problem.log create mode 100644 src/test/ref/robozzle64-label-problem.sym diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java index a76817163..35d0cf175 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass4CodeGeneration.java @@ -51,7 +51,7 @@ public class Pass4CodeGeneration { generateComments(asm, program.getFileComments()); Number programPc; - if(program.getProgramPc()!=null) { + if(program.getProgramPc() != null) { programPc = program.getProgramPc(); } else { programPc = 0x080d; @@ -306,40 +306,38 @@ public class Pass4CodeGeneration { Collection constRefStatements = program.getVariableReferenceInfos().getConstRefStatements(constantVar.getRef()); if(constRefStatements != null) { for(Integer constRefStmtIdx : constRefStatements) { + Statement statement = program.getStatementInfos().getStatement(constRefStmtIdx); ScopeRef refScope = program.getStatementInfos().getBlock(constRefStmtIdx).getScope(); - if(!refScope.equals(scopeRef)) { - Statement statement = program.getStatementInfos().getStatement(constRefStmtIdx); - if(statement instanceof StatementPhiBlock) { - // Const reference in PHI block - examine if the only predecessor is current scope - boolean found = false; - for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) { - for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) { - RValue phiRRValue = phiRValue.getrValue(); - Collection phiRValueConstRefs = PassNVariableReferenceInfos.getReferencedConsts(phiRRValue); - for(ConstantRef phiRValueConstRef : phiRValueConstRefs) { - if(phiRValueConstRef.equals(constantVar.getRef())) { - found = true; - // Found the constant - LabelRef pred = phiRValue.getPredecessor(); - ControlFlowBlock predBlock = program.getGraph().getBlock(pred); - ScopeRef predScope = predBlock.getScope(); - if(!predScope.equals(scopeRef)) { - // Scopes in PHI RValue differs from const scope - generate label - useLabel = true; - } + if(statement instanceof StatementPhiBlock) { + // Const reference in PHI block - examine if the only predecessor is current scope + boolean found = false; + for(StatementPhiBlock.PhiVariable phiVariable : ((StatementPhiBlock) statement).getPhiVariables()) { + for(StatementPhiBlock.PhiRValue phiRValue : phiVariable.getValues()) { + RValue phiRRValue = phiRValue.getrValue(); + Collection phiRValueConstRefs = PassNVariableReferenceInfos.getReferencedConsts(phiRRValue); + for(ConstantRef phiRValueConstRef : phiRValueConstRefs) { + if(phiRValueConstRef.equals(constantVar.getRef())) { + found = true; + // Found the constant + LabelRef pred = phiRValue.getPredecessor(); + ControlFlowBlock predBlock = program.getGraph().getBlock(pred); + ScopeRef predScope = predBlock.getScope(); + if(!predScope.equals(scopeRef)) { + // Scopes in PHI RValue differs from const scope - generate label + useLabel = true; } } } } - if(!found) { - // PHI-reference is complex - generate label - program.getLog().append("Warning: Complex PHI-value using constant. Using .label as fallback. " + statement); - useLabel = true; - } - } else { - // Used in a non-PHI statement in another scope - generate label + } + if(!found) { + // PHI-reference is complex - generate label + program.getLog().append("Warning: Complex PHI-value using constant. Using .label as fallback. " + statement); useLabel = true; } + } else if(!refScope.equals(scopeRef)) { + // Used in a non-PHI statement in another scope - generate label + useLabel = true; } } } diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index c53ea9c5c..04dabae5a 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -32,6 +32,11 @@ public class TestPrograms { public TestPrograms() { } + @Test + public void testRobozzleLabelProblem() throws IOException, URISyntaxException { + compileAndCompare("robozzle64-label-problem", log()); + } + @Test public void testGlobalPc() throws IOException, URISyntaxException { compileAndCompare("global-pc"); diff --git a/src/test/kc/robozzle64-label-problem.kc b/src/test/kc/robozzle64-label-problem.kc new file mode 100644 index 000000000..c3edd60e4 --- /dev/null +++ b/src/test/kc/robozzle64-label-problem.kc @@ -0,0 +1,11 @@ +import "multiply.kc" + +void main() { + word* screen = 0x0400; + for( byte y: 0..5) { + word z1 = mul8u(y,40); + *screen++ = z1; + word z2 = mul8u(y,40); + *screen++ = z2; + } +} diff --git a/src/test/ref/robozzle64-label-problem.asm b/src/test/ref/robozzle64-label-problem.asm new file mode 100644 index 000000000..798444697 --- /dev/null +++ b/src/test/ref/robozzle64-label-problem.asm @@ -0,0 +1,87 @@ +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + .const SIZEOF_WORD = 2 +main: { + .label z1 = 5 + .label screen = 3 + .label z2 = 5 + .label y = 2 + lda #<$400 + sta screen + lda #>$400 + sta screen+1 + lda #0 + sta y + b1: + ldx y + lda #mul8u.b + sta mul8u.mb + lda #0 + sta mul8u.mb+1 + jsr mul8u + ldy #0 + lda z1 + sta (screen),y + iny + lda z1+1 + sta (screen),y + ldx y + lda #mul8u.b + sta mul8u.mb + lda #0 + sta mul8u.mb+1 + jsr mul8u + ldy #SIZEOF_WORD + lda z2 + sta (screen),y + iny + lda z2+1 + sta (screen),y + lda #SIZEOF_WORD+SIZEOF_WORD + clc + adc screen + sta screen + bcc !+ + inc screen+1 + !: + inc y + lda #6 + cmp y + bne b1 + rts +} +// Perform binary multiplication of two unsigned 8-bit bytes into a 16-bit unsigned word +// mul8u(byte register(X) a) +mul8u: { + .label b = $28 + .label mb = 7 + .label res = 5 + .label return = 5 + lda #0 + sta res + sta res+1 + b1: + cpx #0 + bne b2 + rts + b2: + txa + and #1 + cmp #0 + beq b3 + lda res + clc + adc mb + sta res + lda res+1 + adc mb+1 + sta res+1 + b3: + txa + lsr + tax + asl mb + rol mb+1 + jmp b1 +} diff --git a/src/test/ref/robozzle64-label-problem.cfg b/src/test/ref/robozzle64-label-problem.cfg new file mode 100644 index 000000000..41b30833b --- /dev/null +++ b/src/test/ref/robozzle64-label-problem.cfg @@ -0,0 +1,61 @@ +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] phi() + [2] call main + to:@end +@end: scope:[] from @1 + [3] phi() +main: scope:[main] from @1 + [4] phi() + to:main::@1 +main::@1: scope:[main] from main main::@3 + [5] (word*) main::screen#1 ← phi( main/(word*) 1024 main::@3/(word*) main::screen#2 ) + [5] (byte) main::y#2 ← phi( main/(byte) 0 main::@3/(byte) main::y#1 ) + [6] (byte) mul8u::a#1 ← (byte) main::y#2 + [7] call mul8u + [8] (word) mul8u::return#2 ← (word) mul8u::res#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + [9] (word) main::z1#0 ← (word) mul8u::return#2 + [10] *((word*) main::screen#1) ← (word) main::z1#0 + [11] (byte) mul8u::a#2 ← (byte) main::y#2 + [12] call mul8u + [13] (word) mul8u::return#3 ← (word) mul8u::res#2 + to:main::@3 +main::@3: scope:[main] from main::@2 + [14] (word) main::z2#0 ← (word) mul8u::return#3 + [15] *((word*) main::screen#1 + (const byte) SIZEOF_WORD) ← (word) main::z2#0 + [16] (word*) main::screen#2 ← (word*) main::screen#1 + (const byte) SIZEOF_WORD+(const byte) SIZEOF_WORD + [17] (byte) main::y#1 ← ++ (byte) main::y#2 + [18] if((byte) main::y#1!=(byte) 6) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@3 + [19] return + to:@return +mul8u: scope:[mul8u] from main::@1 main::@2 + [20] (byte) mul8u::a#6 ← phi( main::@1/(byte) mul8u::a#1 main::@2/(byte) mul8u::a#2 ) + [20] (word) mul8u::mb#0 ← phi( main::@1/(const byte) mul8u::b#0 main::@2/(const byte) mul8u::b#1 ) + to:mul8u::@1 +mul8u::@1: scope:[mul8u] from mul8u mul8u::@3 + [21] (word) mul8u::mb#2 ← phi( mul8u/(word) mul8u::mb#0 mul8u::@3/(word) mul8u::mb#1 ) + [21] (word) mul8u::res#2 ← phi( mul8u/(byte) 0 mul8u::@3/(word) mul8u::res#6 ) + [21] (byte) mul8u::a#3 ← phi( mul8u/(byte) mul8u::a#6 mul8u::@3/(byte) mul8u::a#0 ) + [22] if((byte) mul8u::a#3!=(byte) 0) goto mul8u::@2 + to:mul8u::@return +mul8u::@return: scope:[mul8u] from mul8u::@1 + [23] return + to:@return +mul8u::@2: scope:[mul8u] from mul8u::@1 + [24] (byte~) mul8u::$1 ← (byte) mul8u::a#3 & (byte) 1 + [25] if((byte~) mul8u::$1==(byte) 0) goto mul8u::@3 + to:mul8u::@4 +mul8u::@4: scope:[mul8u] from mul8u::@2 + [26] (word) mul8u::res#1 ← (word) mul8u::res#2 + (word) mul8u::mb#2 + to:mul8u::@3 +mul8u::@3: scope:[mul8u] from mul8u::@2 mul8u::@4 + [27] (word) mul8u::res#6 ← phi( mul8u::@2/(word) mul8u::res#2 mul8u::@4/(word) mul8u::res#1 ) + [28] (byte) mul8u::a#0 ← (byte) mul8u::a#3 >> (byte) 1 + [29] (word) mul8u::mb#1 ← (word) mul8u::mb#2 << (byte) 1 + to:mul8u::@1 diff --git a/src/test/ref/robozzle64-label-problem.log b/src/test/ref/robozzle64-label-problem.log new file mode 100644 index 000000000..0f878318c --- /dev/null +++ b/src/test/ref/robozzle64-label-problem.log @@ -0,0 +1,1148 @@ +Fixing pointer increment (word*) main::screen ← ++ (word*) main::screen +Fixing pointer increment (word*) main::screen ← ++ (word*) main::screen +Adding pointer type conversion cast (word*) main::screen in (word*) main::screen ← (number) $400 +Culled Empty Block (label) mul8u::@5 +Culled Empty Block (label) mul8u::@6 +Culled Empty Block (label) mul8u::@8 +Culled Empty Block (label) mul8u::@9 +Culled Empty Block (label) @1 +Culled Empty Block (label) @2 +Culled Empty Block (label) @3 +Culled Empty Block (label) @4 +Culled Empty Block (label) @5 +Culled Empty Block (label) main::@2 + +CONTROL FLOW GRAPH SSA +@begin: scope:[] from + to:@6 +mul8u: scope:[mul8u] from main::@1 main::@3 + (byte) mul8u::a#6 ← phi( main::@1/(byte) mul8u::a#1 main::@3/(byte) mul8u::a#2 ) + (byte) mul8u::b#2 ← phi( main::@1/(byte) mul8u::b#0 main::@3/(byte) mul8u::b#1 ) + (word) mul8u::res#0 ← (number) 0 + (word) mul8u::mb#0 ← (byte) mul8u::b#2 + to:mul8u::@1 +mul8u::@1: scope:[mul8u] from mul8u mul8u::@4 + (word) mul8u::mb#5 ← phi( mul8u/(word) mul8u::mb#0 mul8u::@4/(word) mul8u::mb#1 ) + (word) mul8u::res#4 ← phi( mul8u/(word) mul8u::res#0 mul8u::@4/(word) mul8u::res#6 ) + (byte) mul8u::a#3 ← phi( mul8u/(byte) mul8u::a#6 mul8u::@4/(byte) mul8u::a#0 ) + (bool~) mul8u::$0 ← (byte) mul8u::a#3 != (number) 0 + if((bool~) mul8u::$0) goto mul8u::@2 + to:mul8u::@3 +mul8u::@2: scope:[mul8u] from mul8u::@1 + (word) mul8u::res#5 ← phi( mul8u::@1/(word) mul8u::res#4 ) + (word) mul8u::mb#4 ← phi( mul8u::@1/(word) mul8u::mb#5 ) + (byte) mul8u::a#4 ← phi( mul8u::@1/(byte) mul8u::a#3 ) + (number~) mul8u::$1 ← (byte) mul8u::a#4 & (number) 1 + (bool~) mul8u::$2 ← (number~) mul8u::$1 != (number) 0 + (bool~) mul8u::$3 ← ! (bool~) mul8u::$2 + if((bool~) mul8u::$3) goto mul8u::@4 + to:mul8u::@7 +mul8u::@3: scope:[mul8u] from mul8u::@1 + (word) mul8u::res#2 ← phi( mul8u::@1/(word) mul8u::res#4 ) + (word) mul8u::return#0 ← (word) mul8u::res#2 + to:mul8u::@return +mul8u::@4: scope:[mul8u] from mul8u::@2 mul8u::@7 + (word) mul8u::res#6 ← phi( mul8u::@2/(word) mul8u::res#5 mul8u::@7/(word) mul8u::res#1 ) + (word) mul8u::mb#2 ← phi( mul8u::@2/(word) mul8u::mb#4 mul8u::@7/(word) mul8u::mb#3 ) + (byte) mul8u::a#5 ← phi( mul8u::@2/(byte) mul8u::a#4 mul8u::@7/(byte) mul8u::a#7 ) + (byte~) mul8u::$5 ← (byte) mul8u::a#5 >> (number) 1 + (byte) mul8u::a#0 ← (byte~) mul8u::$5 + (word~) mul8u::$6 ← (word) mul8u::mb#2 << (number) 1 + (word) mul8u::mb#1 ← (word~) mul8u::$6 + to:mul8u::@1 +mul8u::@7: scope:[mul8u] from mul8u::@2 + (byte) mul8u::a#7 ← phi( mul8u::@2/(byte) mul8u::a#4 ) + (word) mul8u::mb#3 ← phi( mul8u::@2/(word) mul8u::mb#4 ) + (word) mul8u::res#3 ← phi( mul8u::@2/(word) mul8u::res#5 ) + (word~) mul8u::$4 ← (word) mul8u::res#3 + (word) mul8u::mb#3 + (word) mul8u::res#1 ← (word~) mul8u::$4 + to:mul8u::@4 +mul8u::@return: scope:[mul8u] from mul8u::@3 + (word) mul8u::return#4 ← phi( mul8u::@3/(word) mul8u::return#0 ) + (word) mul8u::return#1 ← (word) mul8u::return#4 + return + to:@return +main: scope:[main] from @6 + (word*) main::screen#0 ← ((word*)) (number) $400 + (byte) main::y#0 ← (number) 0 + to:main::@1 +main::@1: scope:[main] from main main::@4 + (word*) main::screen#5 ← phi( main/(word*) main::screen#0 main::@4/(word*) main::screen#2 ) + (byte) main::y#2 ← phi( main/(byte) main::y#0 main::@4/(byte) main::y#1 ) + (byte) mul8u::a#1 ← (byte) main::y#2 + (byte) mul8u::b#0 ← (number) $28 + call mul8u + (word) mul8u::return#2 ← (word) mul8u::return#1 + to:main::@3 +main::@3: scope:[main] from main::@1 + (byte) main::y#3 ← phi( main::@1/(byte) main::y#2 ) + (word*) main::screen#3 ← phi( main::@1/(word*) main::screen#5 ) + (word) mul8u::return#5 ← phi( main::@1/(word) mul8u::return#2 ) + (word~) main::$0 ← (word) mul8u::return#5 + (word) main::z1#0 ← (word~) main::$0 + *((word*) main::screen#3) ← (word) main::z1#0 + (word*) main::screen#1 ← (word*) main::screen#3 + (const byte) SIZEOF_WORD + (byte) mul8u::a#2 ← (byte) main::y#3 + (byte) mul8u::b#1 ← (number) $28 + call mul8u + (word) mul8u::return#3 ← (word) mul8u::return#1 + to:main::@4 +main::@4: scope:[main] from main::@3 + (byte) main::y#4 ← phi( main::@3/(byte) main::y#3 ) + (word*) main::screen#4 ← phi( main::@3/(word*) main::screen#1 ) + (word) mul8u::return#6 ← phi( main::@3/(word) mul8u::return#3 ) + (word~) main::$1 ← (word) mul8u::return#6 + (word) main::z2#0 ← (word~) main::$1 + *((word*) main::screen#4) ← (word) main::z2#0 + (word*) main::screen#2 ← (word*) main::screen#4 + (const byte) SIZEOF_WORD + (byte) main::y#1 ← (byte) main::y#4 + rangenext(0,5) + (bool~) main::$2 ← (byte) main::y#1 != rangelast(0,5) + if((bool~) main::$2) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@4 + return + to:@return +@6: scope:[] from @begin + call main + to:@7 +@7: scope:[] from @6 + to:@end +@end: scope:[] from @7 + +SYMBOL TABLE SSA +(label) @6 +(label) @7 +(label) @begin +(label) @end +(const byte) SIZEOF_WORD = (byte) 2 +(void()) main() +(word~) main::$0 +(word~) main::$1 +(bool~) main::$2 +(label) main::@1 +(label) main::@3 +(label) main::@4 +(label) main::@return +(word*) main::screen +(word*) main::screen#0 +(word*) main::screen#1 +(word*) main::screen#2 +(word*) main::screen#3 +(word*) main::screen#4 +(word*) main::screen#5 +(byte) main::y +(byte) main::y#0 +(byte) main::y#1 +(byte) main::y#2 +(byte) main::y#3 +(byte) main::y#4 +(word) main::z1 +(word) main::z1#0 +(word) main::z2 +(word) main::z2#0 +(word()) mul8u((byte) mul8u::a , (byte) mul8u::b) +(bool~) mul8u::$0 +(number~) mul8u::$1 +(bool~) mul8u::$2 +(bool~) mul8u::$3 +(word~) mul8u::$4 +(byte~) mul8u::$5 +(word~) mul8u::$6 +(label) mul8u::@1 +(label) mul8u::@2 +(label) mul8u::@3 +(label) mul8u::@4 +(label) mul8u::@7 +(label) mul8u::@return +(byte) mul8u::a +(byte) mul8u::a#0 +(byte) mul8u::a#1 +(byte) mul8u::a#2 +(byte) mul8u::a#3 +(byte) mul8u::a#4 +(byte) mul8u::a#5 +(byte) mul8u::a#6 +(byte) mul8u::a#7 +(byte) mul8u::b +(byte) mul8u::b#0 +(byte) mul8u::b#1 +(byte) mul8u::b#2 +(word) mul8u::mb +(word) mul8u::mb#0 +(word) mul8u::mb#1 +(word) mul8u::mb#2 +(word) mul8u::mb#3 +(word) mul8u::mb#4 +(word) mul8u::mb#5 +(word) mul8u::res +(word) mul8u::res#0 +(word) mul8u::res#1 +(word) mul8u::res#2 +(word) mul8u::res#3 +(word) mul8u::res#4 +(word) mul8u::res#5 +(word) mul8u::res#6 +(word) mul8u::return +(word) mul8u::return#0 +(word) mul8u::return#1 +(word) mul8u::return#2 +(word) mul8u::return#3 +(word) mul8u::return#4 +(word) mul8u::return#5 +(word) mul8u::return#6 + +Adding number conversion cast (unumber) 0 in (word) mul8u::res#0 ← (number) 0 +Adding number conversion cast (unumber) 0 in (bool~) mul8u::$0 ← (byte) mul8u::a#3 != (number) 0 +Adding number conversion cast (unumber) 1 in (number~) mul8u::$1 ← (byte) mul8u::a#4 & (number) 1 +Adding number conversion cast (unumber) mul8u::$1 in (number~) mul8u::$1 ← (byte) mul8u::a#4 & (unumber)(number) 1 +Adding number conversion cast (unumber) 0 in (bool~) mul8u::$2 ← (unumber~) mul8u::$1 != (number) 0 +Adding number conversion cast (unumber) 1 in (byte~) mul8u::$5 ← (byte) mul8u::a#5 >> (number) 1 +Adding number conversion cast (unumber) 1 in (word~) mul8u::$6 ← (word) mul8u::mb#2 << (number) 1 +Adding number conversion cast (unumber) 0 in (byte) main::y#0 ← (number) 0 +Adding number conversion cast (unumber) $28 in (byte) mul8u::b#0 ← (number) $28 +Adding number conversion cast (unumber) $28 in (byte) mul8u::b#1 ← (number) $28 +Successful SSA optimization PassNAddNumberTypeConversions +Inlining cast (word) mul8u::res#0 ← (unumber)(number) 0 +Inlining cast (word*) main::screen#0 ← (word*)(number) $400 +Inlining cast (byte) main::y#0 ← (unumber)(number) 0 +Inlining cast (byte) mul8u::b#0 ← (unumber)(number) $28 +Inlining cast (byte) mul8u::b#1 ← (unumber)(number) $28 +Successful SSA optimization Pass2InlineCast +Simplifying constant integer cast 0 +Simplifying constant integer cast 0 +Simplifying constant integer cast 1 +Simplifying constant integer cast 0 +Simplifying constant integer cast 1 +Simplifying constant integer cast 1 +Simplifying constant pointer cast (word*) 1024 +Simplifying constant integer cast 0 +Simplifying constant integer cast $28 +Simplifying constant integer cast $28 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (byte) 1 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (byte) 1 +Finalized unsigned number type (byte) 1 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (byte) $28 +Finalized unsigned number type (byte) $28 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Inferred type updated to byte in (unumber~) mul8u::$1 ← (byte) mul8u::a#4 & (byte) 1 +Inversing boolean not [9] (bool~) mul8u::$3 ← (byte~) mul8u::$1 == (byte) 0 from [8] (bool~) mul8u::$2 ← (byte~) mul8u::$1 != (byte) 0 +Successful SSA optimization Pass2UnaryNotSimplification +Alias (word) mul8u::mb#0 = (byte) mul8u::b#2 +Alias (byte) mul8u::a#3 = (byte) mul8u::a#4 (byte) mul8u::a#7 +Alias (word) mul8u::mb#3 = (word) mul8u::mb#4 (word) mul8u::mb#5 +Alias (word) mul8u::res#2 = (word) mul8u::res#5 (word) mul8u::res#4 (word) mul8u::return#0 (word) mul8u::res#3 (word) mul8u::return#4 (word) mul8u::return#1 +Alias (byte) mul8u::a#0 = (byte~) mul8u::$5 +Alias (word) mul8u::mb#1 = (word~) mul8u::$6 +Alias (word) mul8u::res#1 = (word~) mul8u::$4 +Alias (word) mul8u::return#2 = (word) mul8u::return#5 +Alias (word*) main::screen#3 = (word*) main::screen#5 +Alias (byte) main::y#2 = (byte) main::y#3 (byte) main::y#4 +Alias (word) main::z1#0 = (word~) main::$0 +Alias (word) mul8u::return#3 = (word) mul8u::return#6 +Alias (word*) main::screen#1 = (word*) main::screen#4 +Alias (word) main::z2#0 = (word~) main::$1 +Successful SSA optimization Pass2AliasElimination +Alias (byte) mul8u::a#3 = (byte) mul8u::a#5 +Alias (word) mul8u::mb#2 = (word) mul8u::mb#3 +Successful SSA optimization Pass2AliasElimination +Simple Condition (bool~) mul8u::$0 [5] if((byte) mul8u::a#3!=(byte) 0) goto mul8u::@2 +Simple Condition (bool~) mul8u::$3 [10] if((byte~) mul8u::$1==(byte) 0) goto mul8u::@4 +Simple Condition (bool~) main::$2 [47] if((byte) main::y#1!=rangelast(0,5)) goto main::@1 +Successful SSA optimization Pass2ConditionalJumpSimplification +Constant (const word) mul8u::res#0 = 0 +Constant (const word*) main::screen#0 = (word*) 1024 +Constant (const byte) main::y#0 = 0 +Constant (const byte) mul8u::b#0 = $28 +Constant (const byte) mul8u::b#1 = $28 +Successful SSA optimization Pass2ConstantIdentification +Resolved ranged next value [45] main::y#1 ← ++ main::y#2 to ++ +Resolved ranged comparison value [47] if(main::y#1!=rangelast(0,5)) goto main::@1 to (number) 6 +Converting *(pointer+n) to pointer[n] [43] *((word*) main::screen#1) ← (word) main::z2#0 -- *(main::screen#3 + SIZEOF_WORD) +Successful SSA optimization Pass2InlineDerefIdx +Adding number conversion cast (unumber) 6 in if((byte) main::y#1!=(number) 6) goto main::@1 +Successful SSA optimization PassNAddNumberTypeConversions +Simplifying constant integer cast 6 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (byte) 6 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Inlining constant with var siblings (const word) mul8u::res#0 +Inlining constant with var siblings (const word*) main::screen#0 +Inlining constant with var siblings (const byte) main::y#0 +Constant inlined main::screen#0 = (word*) 1024 +Constant inlined mul8u::res#0 = (byte) 0 +Constant inlined main::y#0 = (byte) 0 +Successful SSA optimization Pass2ConstantInlining +Consolidated constant in assignment main::screen#2 +Successful SSA optimization Pass2ConstantAdditionElimination +Alias (word*) main::screen#1 = (word*) main::screen#3 +Successful SSA optimization Pass2AliasElimination +Added new block during phi lifting mul8u::@10(between mul8u::@2 and mul8u::@4) +Added new block during phi lifting main::@5(between main::@4 and main::@1) +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @6 +Adding NOP phi() at start of @7 +Adding NOP phi() at start of @end +Adding NOP phi() at start of main +Adding NOP phi() at start of mul8u::@3 +CALL GRAPH +Calls in [] to main:2 +Calls in [main] to mul8u:9 mul8u:15 + +Created 8 initial phi equivalence classes +Coalesced [8] mul8u::a#8 ← mul8u::a#1 +Coalesced [14] mul8u::a#9 ← mul8u::a#2 +Coalesced [23] main::y#5 ← main::y#1 +Coalesced [24] main::screen#6 ← main::screen#2 +Coalesced [26] mul8u::a#10 ← mul8u::a#6 +Coalesced [27] mul8u::mb#6 ← mul8u::mb#0 +Coalesced [35] mul8u::res#9 ← mul8u::res#1 +Coalesced [39] mul8u::a#11 ← mul8u::a#0 +Coalesced [40] mul8u::res#7 ← mul8u::res#6 +Coalesced [41] mul8u::mb#7 ← mul8u::mb#1 +Coalesced (already) [42] mul8u::res#8 ← mul8u::res#2 +Coalesced down to 5 phi equivalence classes +Culled Empty Block (label) @7 +Culled Empty Block (label) main::@5 +Culled Empty Block (label) mul8u::@3 +Culled Empty Block (label) mul8u::@10 +Renumbering block @6 to @1 +Renumbering block mul8u::@4 to mul8u::@3 +Renumbering block mul8u::@7 to mul8u::@4 +Renumbering block main::@3 to main::@2 +Renumbering block main::@4 to main::@3 +Adding NOP phi() at start of @begin +Adding NOP phi() at start of @1 +Adding NOP phi() at start of @end +Adding NOP phi() at start of main + +FINAL CONTROL FLOW GRAPH +@begin: scope:[] from + [0] phi() + to:@1 +@1: scope:[] from @begin + [1] phi() + [2] call main + to:@end +@end: scope:[] from @1 + [3] phi() +main: scope:[main] from @1 + [4] phi() + to:main::@1 +main::@1: scope:[main] from main main::@3 + [5] (word*) main::screen#1 ← phi( main/(word*) 1024 main::@3/(word*) main::screen#2 ) + [5] (byte) main::y#2 ← phi( main/(byte) 0 main::@3/(byte) main::y#1 ) + [6] (byte) mul8u::a#1 ← (byte) main::y#2 + [7] call mul8u + [8] (word) mul8u::return#2 ← (word) mul8u::res#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + [9] (word) main::z1#0 ← (word) mul8u::return#2 + [10] *((word*) main::screen#1) ← (word) main::z1#0 + [11] (byte) mul8u::a#2 ← (byte) main::y#2 + [12] call mul8u + [13] (word) mul8u::return#3 ← (word) mul8u::res#2 + to:main::@3 +main::@3: scope:[main] from main::@2 + [14] (word) main::z2#0 ← (word) mul8u::return#3 + [15] *((word*) main::screen#1 + (const byte) SIZEOF_WORD) ← (word) main::z2#0 + [16] (word*) main::screen#2 ← (word*) main::screen#1 + (const byte) SIZEOF_WORD+(const byte) SIZEOF_WORD + [17] (byte) main::y#1 ← ++ (byte) main::y#2 + [18] if((byte) main::y#1!=(byte) 6) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@3 + [19] return + to:@return +mul8u: scope:[mul8u] from main::@1 main::@2 + [20] (byte) mul8u::a#6 ← phi( main::@1/(byte) mul8u::a#1 main::@2/(byte) mul8u::a#2 ) + [20] (word) mul8u::mb#0 ← phi( main::@1/(const byte) mul8u::b#0 main::@2/(const byte) mul8u::b#1 ) + to:mul8u::@1 +mul8u::@1: scope:[mul8u] from mul8u mul8u::@3 + [21] (word) mul8u::mb#2 ← phi( mul8u/(word) mul8u::mb#0 mul8u::@3/(word) mul8u::mb#1 ) + [21] (word) mul8u::res#2 ← phi( mul8u/(byte) 0 mul8u::@3/(word) mul8u::res#6 ) + [21] (byte) mul8u::a#3 ← phi( mul8u/(byte) mul8u::a#6 mul8u::@3/(byte) mul8u::a#0 ) + [22] if((byte) mul8u::a#3!=(byte) 0) goto mul8u::@2 + to:mul8u::@return +mul8u::@return: scope:[mul8u] from mul8u::@1 + [23] return + to:@return +mul8u::@2: scope:[mul8u] from mul8u::@1 + [24] (byte~) mul8u::$1 ← (byte) mul8u::a#3 & (byte) 1 + [25] if((byte~) mul8u::$1==(byte) 0) goto mul8u::@3 + to:mul8u::@4 +mul8u::@4: scope:[mul8u] from mul8u::@2 + [26] (word) mul8u::res#1 ← (word) mul8u::res#2 + (word) mul8u::mb#2 + to:mul8u::@3 +mul8u::@3: scope:[mul8u] from mul8u::@2 mul8u::@4 + [27] (word) mul8u::res#6 ← phi( mul8u::@2/(word) mul8u::res#2 mul8u::@4/(word) mul8u::res#1 ) + [28] (byte) mul8u::a#0 ← (byte) mul8u::a#3 >> (byte) 1 + [29] (word) mul8u::mb#1 ← (word) mul8u::mb#2 << (byte) 1 + to:mul8u::@1 + + +VARIABLE REGISTER WEIGHTS +(void()) main() +(word*) main::screen +(word*) main::screen#1 4.0 +(word*) main::screen#2 7.333333333333333 +(byte) main::y +(byte) main::y#1 16.5 +(byte) main::y#2 3.6666666666666665 +(word) main::z1 +(word) main::z1#0 22.0 +(word) main::z2 +(word) main::z2#0 22.0 +(word()) mul8u((byte) mul8u::a , (byte) mul8u::b) +(byte~) mul8u::$1 202.0 +(byte) mul8u::a +(byte) mul8u::a#0 101.0 +(byte) mul8u::a#1 22.0 +(byte) mul8u::a#2 22.0 +(byte) mul8u::a#3 67.66666666666666 +(byte) mul8u::a#6 24.0 +(byte) mul8u::b +(word) mul8u::mb +(word) mul8u::mb#0 2.0 +(word) mul8u::mb#1 202.0 +(word) mul8u::mb#2 43.57142857142858 +(word) mul8u::res +(word) mul8u::res#1 202.0 +(word) mul8u::res#2 46.42857142857143 +(word) mul8u::res#6 101.0 +(word) mul8u::return +(word) mul8u::return#2 22.0 +(word) mul8u::return#3 22.0 + +Initial phi equivalence classes +[ main::y#2 main::y#1 ] +[ main::screen#1 main::screen#2 ] +[ mul8u::a#3 mul8u::a#6 mul8u::a#1 mul8u::a#2 mul8u::a#0 ] +[ mul8u::res#2 mul8u::res#6 mul8u::res#1 ] +[ mul8u::mb#2 mul8u::mb#0 mul8u::mb#1 ] +Added variable mul8u::return#2 to zero page equivalence class [ mul8u::return#2 ] +Added variable main::z1#0 to zero page equivalence class [ main::z1#0 ] +Added variable mul8u::return#3 to zero page equivalence class [ mul8u::return#3 ] +Added variable main::z2#0 to zero page equivalence class [ main::z2#0 ] +Added variable mul8u::$1 to zero page equivalence class [ mul8u::$1 ] +Complete equivalence classes +[ main::y#2 main::y#1 ] +[ main::screen#1 main::screen#2 ] +[ mul8u::a#3 mul8u::a#6 mul8u::a#1 mul8u::a#2 mul8u::a#0 ] +[ mul8u::res#2 mul8u::res#6 mul8u::res#1 ] +[ mul8u::mb#2 mul8u::mb#0 mul8u::mb#1 ] +[ mul8u::return#2 ] +[ main::z1#0 ] +[ mul8u::return#3 ] +[ main::z2#0 ] +[ mul8u::$1 ] +Allocated zp ZP_BYTE:2 [ main::y#2 main::y#1 ] +Allocated zp ZP_WORD:3 [ main::screen#1 main::screen#2 ] +Allocated zp ZP_BYTE:5 [ mul8u::a#3 mul8u::a#6 mul8u::a#1 mul8u::a#2 mul8u::a#0 ] +Allocated zp ZP_WORD:6 [ mul8u::res#2 mul8u::res#6 mul8u::res#1 ] +Allocated zp ZP_WORD:8 [ mul8u::mb#2 mul8u::mb#0 mul8u::mb#1 ] +Allocated zp ZP_WORD:10 [ mul8u::return#2 ] +Allocated zp ZP_WORD:12 [ main::z1#0 ] +Allocated zp ZP_WORD:14 [ mul8u::return#3 ] +Allocated zp ZP_WORD:16 [ main::z2#0 ] +Allocated zp ZP_BYTE:18 [ mul8u::$1 ] + +INITIAL ASM +//SEG0 File Comments +//SEG1 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(bbegin) +.pc = $80d "Program" +//SEG2 Global Constants & labels + .const SIZEOF_WORD = 2 +//SEG3 @begin +bbegin: +//SEG4 [1] phi from @begin to @1 [phi:@begin->@1] +b1_from_bbegin: + jmp b1 +//SEG5 @1 +b1: +//SEG6 [2] call main +//SEG7 [4] phi from @1 to main [phi:@1->main] +main_from_b1: + jsr main +//SEG8 [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend +//SEG9 @end +bend: +//SEG10 main +main: { + .label z1 = $c + .label screen = 3 + .label z2 = $10 + .label y = 2 + //SEG11 [5] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + //SEG12 [5] phi (word*) main::screen#1 = (word*) 1024 [phi:main->main::@1#0] -- pwuz1=pwuc1 + lda #<$400 + sta screen + lda #>$400 + sta screen+1 + //SEG13 [5] phi (byte) main::y#2 = (byte) 0 [phi:main->main::@1#1] -- vbuz1=vbuc1 + lda #0 + sta y + jmp b1 + //SEG14 [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1] + b1_from_b3: + //SEG15 [5] phi (word*) main::screen#1 = (word*) main::screen#2 [phi:main::@3->main::@1#0] -- register_copy + //SEG16 [5] phi (byte) main::y#2 = (byte) main::y#1 [phi:main::@3->main::@1#1] -- register_copy + jmp b1 + //SEG17 main::@1 + b1: + //SEG18 [6] (byte) mul8u::a#1 ← (byte) main::y#2 -- vbuz1=vbuz2 + lda y + sta mul8u.a + //SEG19 [7] call mul8u + //SEG20 [20] phi from main::@1 to mul8u [phi:main::@1->mul8u] + mul8u_from_b1: + //SEG21 [20] phi (byte) mul8u::a#6 = (byte) mul8u::a#1 [phi:main::@1->mul8u#0] -- register_copy + //SEG22 [20] phi (word) mul8u::mb#0 = (const byte) mul8u::b#0 [phi:main::@1->mul8u#1] -- vwuz1=vbuc1 + lda #mul8u.b + sta mul8u.mb + lda #0 + sta mul8u.mb+1 + jsr mul8u + //SEG23 [8] (word) mul8u::return#2 ← (word) mul8u::res#2 -- vwuz1=vwuz2 + lda mul8u.res + sta mul8u.return + lda mul8u.res+1 + sta mul8u.return+1 + jmp b2 + //SEG24 main::@2 + b2: + //SEG25 [9] (word) main::z1#0 ← (word) mul8u::return#2 -- vwuz1=vwuz2 + lda mul8u.return + sta z1 + lda mul8u.return+1 + sta z1+1 + //SEG26 [10] *((word*) main::screen#1) ← (word) main::z1#0 -- _deref_pwuz1=vwuz2 + ldy #0 + lda z1 + sta (screen),y + iny + lda z1+1 + sta (screen),y + //SEG27 [11] (byte) mul8u::a#2 ← (byte) main::y#2 -- vbuz1=vbuz2 + lda y + sta mul8u.a + //SEG28 [12] call mul8u + //SEG29 [20] phi from main::@2 to mul8u [phi:main::@2->mul8u] + mul8u_from_b2: + //SEG30 [20] phi (byte) mul8u::a#6 = (byte) mul8u::a#2 [phi:main::@2->mul8u#0] -- register_copy + //SEG31 [20] phi (word) mul8u::mb#0 = (const byte) mul8u::b#1 [phi:main::@2->mul8u#1] -- vwuz1=vbuc1 + lda #mul8u.b + sta mul8u.mb + lda #0 + sta mul8u.mb+1 + jsr mul8u + //SEG32 [13] (word) mul8u::return#3 ← (word) mul8u::res#2 -- vwuz1=vwuz2 + lda mul8u.res + sta mul8u.return_3 + lda mul8u.res+1 + sta mul8u.return_3+1 + jmp b3 + //SEG33 main::@3 + b3: + //SEG34 [14] (word) main::z2#0 ← (word) mul8u::return#3 -- vwuz1=vwuz2 + lda mul8u.return_3 + sta z2 + lda mul8u.return_3+1 + sta z2+1 + //SEG35 [15] *((word*) main::screen#1 + (const byte) SIZEOF_WORD) ← (word) main::z2#0 -- pwuz1_derefidx_vbuc1=vwuz2 + ldy #SIZEOF_WORD + lda z2 + sta (screen),y + iny + lda z2+1 + sta (screen),y + //SEG36 [16] (word*) main::screen#2 ← (word*) main::screen#1 + (const byte) SIZEOF_WORD+(const byte) SIZEOF_WORD -- pwuz1=pwuz1_plus_vbuc1 + lda #SIZEOF_WORD+SIZEOF_WORD + clc + adc screen + sta screen + bcc !+ + inc screen+1 + !: + //SEG37 [17] (byte) main::y#1 ← ++ (byte) main::y#2 -- vbuz1=_inc_vbuz1 + inc y + //SEG38 [18] if((byte) main::y#1!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 + lda #6 + cmp y + bne b1_from_b3 + jmp breturn + //SEG39 main::@return + breturn: + //SEG40 [19] return + rts +} +//SEG41 mul8u +// Perform binary multiplication of two unsigned 8-bit bytes into a 16-bit unsigned word +// mul8u(byte zeropage(5) a) +mul8u: { + .label b = $28 + .label _1 = $12 + .label mb = 8 + .label a = 5 + .label res = 6 + .label return = $a + .label return_3 = $e + //SEG42 [21] phi from mul8u to mul8u::@1 [phi:mul8u->mul8u::@1] + b1_from_mul8u: + //SEG43 [21] phi (word) mul8u::mb#2 = (word) mul8u::mb#0 [phi:mul8u->mul8u::@1#0] -- register_copy + //SEG44 [21] phi (word) mul8u::res#2 = (byte) 0 [phi:mul8u->mul8u::@1#1] -- vwuz1=vbuc1 + lda #0 + sta res + lda #0 + sta res+1 + //SEG45 [21] phi (byte) mul8u::a#3 = (byte) mul8u::a#6 [phi:mul8u->mul8u::@1#2] -- register_copy + jmp b1 + //SEG46 mul8u::@1 + b1: + //SEG47 [22] if((byte) mul8u::a#3!=(byte) 0) goto mul8u::@2 -- vbuz1_neq_0_then_la1 + lda a + cmp #0 + bne b2 + jmp breturn + //SEG48 mul8u::@return + breturn: + //SEG49 [23] return + rts + //SEG50 mul8u::@2 + b2: + //SEG51 [24] (byte~) mul8u::$1 ← (byte) mul8u::a#3 & (byte) 1 -- vbuz1=vbuz2_band_vbuc1 + lda #1 + and a + sta _1 + //SEG52 [25] if((byte~) mul8u::$1==(byte) 0) goto mul8u::@3 -- vbuz1_eq_0_then_la1 + lda _1 + cmp #0 + beq b3_from_b2 + jmp b4 + //SEG53 mul8u::@4 + b4: + //SEG54 [26] (word) mul8u::res#1 ← (word) mul8u::res#2 + (word) mul8u::mb#2 -- vwuz1=vwuz1_plus_vwuz2 + lda res + clc + adc mb + sta res + lda res+1 + adc mb+1 + sta res+1 + //SEG55 [27] phi from mul8u::@2 mul8u::@4 to mul8u::@3 [phi:mul8u::@2/mul8u::@4->mul8u::@3] + b3_from_b2: + b3_from_b4: + //SEG56 [27] phi (word) mul8u::res#6 = (word) mul8u::res#2 [phi:mul8u::@2/mul8u::@4->mul8u::@3#0] -- register_copy + jmp b3 + //SEG57 mul8u::@3 + b3: + //SEG58 [28] (byte) mul8u::a#0 ← (byte) mul8u::a#3 >> (byte) 1 -- vbuz1=vbuz1_ror_1 + lsr a + //SEG59 [29] (word) mul8u::mb#1 ← (word) mul8u::mb#2 << (byte) 1 -- vwuz1=vwuz1_rol_1 + asl mb + rol mb+1 + //SEG60 [21] phi from mul8u::@3 to mul8u::@1 [phi:mul8u::@3->mul8u::@1] + b1_from_b3: + //SEG61 [21] phi (word) mul8u::mb#2 = (word) mul8u::mb#1 [phi:mul8u::@3->mul8u::@1#0] -- register_copy + //SEG62 [21] phi (word) mul8u::res#2 = (word) mul8u::res#6 [phi:mul8u::@3->mul8u::@1#1] -- register_copy + //SEG63 [21] phi (byte) mul8u::a#3 = (byte) mul8u::a#0 [phi:mul8u::@3->mul8u::@1#2] -- register_copy + jmp b1 +} + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [8] (word) mul8u::return#2 ← (word) mul8u::res#2 [ main::y#2 main::screen#1 mul8u::return#2 ] ( main:2 [ main::y#2 main::screen#1 mul8u::return#2 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::y#2 main::y#1 ] +Statement [9] (word) main::z1#0 ← (word) mul8u::return#2 [ main::y#2 main::screen#1 main::z1#0 ] ( main:2 [ main::y#2 main::screen#1 main::z1#0 ] ) always clobbers reg byte a +Statement [10] *((word*) main::screen#1) ← (word) main::z1#0 [ main::y#2 main::screen#1 ] ( main:2 [ main::y#2 main::screen#1 ] ) always clobbers reg byte a reg byte y +Removing always clobbered register reg byte y as potential for zp ZP_BYTE:2 [ main::y#2 main::y#1 ] +Statement [13] (word) mul8u::return#3 ← (word) mul8u::res#2 [ main::y#2 main::screen#1 mul8u::return#3 ] ( main:2 [ main::y#2 main::screen#1 mul8u::return#3 ] ) always clobbers reg byte a +Statement [14] (word) main::z2#0 ← (word) mul8u::return#3 [ main::y#2 main::screen#1 main::z2#0 ] ( main:2 [ main::y#2 main::screen#1 main::z2#0 ] ) always clobbers reg byte a +Statement [15] *((word*) main::screen#1 + (const byte) SIZEOF_WORD) ← (word) main::z2#0 [ main::y#2 main::screen#1 ] ( main:2 [ main::y#2 main::screen#1 ] ) always clobbers reg byte a reg byte y +Statement [16] (word*) main::screen#2 ← (word*) main::screen#1 + (const byte) SIZEOF_WORD+(const byte) SIZEOF_WORD [ main::y#2 main::screen#2 ] ( main:2 [ main::y#2 main::screen#2 ] ) always clobbers reg byte a +Statement [26] (word) mul8u::res#1 ← (word) mul8u::res#2 + (word) mul8u::mb#2 [ mul8u::a#3 mul8u::mb#2 mul8u::res#1 ] ( main:2::mul8u:7 [ main::y#2 main::screen#1 mul8u::a#3 mul8u::mb#2 mul8u::res#1 ] main:2::mul8u:12 [ main::y#2 main::screen#1 mul8u::a#3 mul8u::mb#2 mul8u::res#1 ] ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp ZP_BYTE:5 [ mul8u::a#3 mul8u::a#6 mul8u::a#1 mul8u::a#2 mul8u::a#0 ] +Statement [8] (word) mul8u::return#2 ← (word) mul8u::res#2 [ main::y#2 main::screen#1 mul8u::return#2 ] ( main:2 [ main::y#2 main::screen#1 mul8u::return#2 ] ) always clobbers reg byte a +Statement [9] (word) main::z1#0 ← (word) mul8u::return#2 [ main::y#2 main::screen#1 main::z1#0 ] ( main:2 [ main::y#2 main::screen#1 main::z1#0 ] ) always clobbers reg byte a +Statement [10] *((word*) main::screen#1) ← (word) main::z1#0 [ main::y#2 main::screen#1 ] ( main:2 [ main::y#2 main::screen#1 ] ) always clobbers reg byte a reg byte y +Statement [13] (word) mul8u::return#3 ← (word) mul8u::res#2 [ main::y#2 main::screen#1 mul8u::return#3 ] ( main:2 [ main::y#2 main::screen#1 mul8u::return#3 ] ) always clobbers reg byte a +Statement [14] (word) main::z2#0 ← (word) mul8u::return#3 [ main::y#2 main::screen#1 main::z2#0 ] ( main:2 [ main::y#2 main::screen#1 main::z2#0 ] ) always clobbers reg byte a +Statement [15] *((word*) main::screen#1 + (const byte) SIZEOF_WORD) ← (word) main::z2#0 [ main::y#2 main::screen#1 ] ( main:2 [ main::y#2 main::screen#1 ] ) always clobbers reg byte a reg byte y +Statement [16] (word*) main::screen#2 ← (word*) main::screen#1 + (const byte) SIZEOF_WORD+(const byte) SIZEOF_WORD [ main::y#2 main::screen#2 ] ( main:2 [ main::y#2 main::screen#2 ] ) always clobbers reg byte a +Statement [24] (byte~) mul8u::$1 ← (byte) mul8u::a#3 & (byte) 1 [ mul8u::res#2 mul8u::a#3 mul8u::mb#2 mul8u::$1 ] ( main:2::mul8u:7 [ main::y#2 main::screen#1 mul8u::res#2 mul8u::a#3 mul8u::mb#2 mul8u::$1 ] main:2::mul8u:12 [ main::y#2 main::screen#1 mul8u::res#2 mul8u::a#3 mul8u::mb#2 mul8u::$1 ] ) always clobbers reg byte a +Statement [26] (word) mul8u::res#1 ← (word) mul8u::res#2 + (word) mul8u::mb#2 [ mul8u::a#3 mul8u::mb#2 mul8u::res#1 ] ( main:2::mul8u:7 [ main::y#2 main::screen#1 mul8u::a#3 mul8u::mb#2 mul8u::res#1 ] main:2::mul8u:12 [ main::y#2 main::screen#1 mul8u::a#3 mul8u::mb#2 mul8u::res#1 ] ) always clobbers reg byte a +Potential registers zp ZP_BYTE:2 [ main::y#2 main::y#1 ] : zp ZP_BYTE:2 , reg byte x , +Potential registers zp ZP_WORD:3 [ main::screen#1 main::screen#2 ] : zp ZP_WORD:3 , +Potential registers zp ZP_BYTE:5 [ mul8u::a#3 mul8u::a#6 mul8u::a#1 mul8u::a#2 mul8u::a#0 ] : zp ZP_BYTE:5 , reg byte x , reg byte y , +Potential registers zp ZP_WORD:6 [ mul8u::res#2 mul8u::res#6 mul8u::res#1 ] : zp ZP_WORD:6 , +Potential registers zp ZP_WORD:8 [ mul8u::mb#2 mul8u::mb#0 mul8u::mb#1 ] : zp ZP_WORD:8 , +Potential registers zp ZP_WORD:10 [ mul8u::return#2 ] : zp ZP_WORD:10 , +Potential registers zp ZP_WORD:12 [ main::z1#0 ] : zp ZP_WORD:12 , +Potential registers zp ZP_WORD:14 [ mul8u::return#3 ] : zp ZP_WORD:14 , +Potential registers zp ZP_WORD:16 [ main::z2#0 ] : zp ZP_WORD:16 , +Potential registers zp ZP_BYTE:18 [ mul8u::$1 ] : zp ZP_BYTE:18 , reg byte a , reg byte x , reg byte y , + +REGISTER UPLIFT SCOPES +Uplift Scope [mul8u] 349.43: zp ZP_WORD:6 [ mul8u::res#2 mul8u::res#6 mul8u::res#1 ] 247.57: zp ZP_WORD:8 [ mul8u::mb#2 mul8u::mb#0 mul8u::mb#1 ] 236.67: zp ZP_BYTE:5 [ mul8u::a#3 mul8u::a#6 mul8u::a#1 mul8u::a#2 mul8u::a#0 ] 202: zp ZP_BYTE:18 [ mul8u::$1 ] 22: zp ZP_WORD:10 [ mul8u::return#2 ] 22: zp ZP_WORD:14 [ mul8u::return#3 ] +Uplift Scope [main] 22: zp ZP_WORD:12 [ main::z1#0 ] 22: zp ZP_WORD:16 [ main::z2#0 ] 20.17: zp ZP_BYTE:2 [ main::y#2 main::y#1 ] 11.33: zp ZP_WORD:3 [ main::screen#1 main::screen#2 ] +Uplift Scope [] + +Uplifting [mul8u] best 9036 combination zp ZP_WORD:6 [ mul8u::res#2 mul8u::res#6 mul8u::res#1 ] zp ZP_WORD:8 [ mul8u::mb#2 mul8u::mb#0 mul8u::mb#1 ] reg byte x [ mul8u::a#3 mul8u::a#6 mul8u::a#1 mul8u::a#2 mul8u::a#0 ] reg byte a [ mul8u::$1 ] zp ZP_WORD:10 [ mul8u::return#2 ] zp ZP_WORD:14 [ mul8u::return#3 ] +Uplifting [main] best 9036 combination zp ZP_WORD:12 [ main::z1#0 ] zp ZP_WORD:16 [ main::z2#0 ] zp ZP_BYTE:2 [ main::y#2 main::y#1 ] zp ZP_WORD:3 [ main::screen#1 main::screen#2 ] +Uplifting [] best 9036 combination +Attempting to uplift remaining variables inzp ZP_BYTE:2 [ main::y#2 main::y#1 ] +Uplifting [main] best 9036 combination zp ZP_BYTE:2 [ main::y#2 main::y#1 ] +Coalescing zero page register with common assignment [ zp ZP_WORD:6 [ mul8u::res#2 mul8u::res#6 mul8u::res#1 ] ] with [ zp ZP_WORD:10 [ mul8u::return#2 ] ] - score: 1 +Coalescing zero page register with common assignment [ zp ZP_WORD:6 [ mul8u::res#2 mul8u::res#6 mul8u::res#1 mul8u::return#2 ] ] with [ zp ZP_WORD:14 [ mul8u::return#3 ] ] - score: 1 +Coalescing zero page register with common assignment [ zp ZP_WORD:6 [ mul8u::res#2 mul8u::res#6 mul8u::res#1 mul8u::return#2 mul8u::return#3 ] ] with [ zp ZP_WORD:12 [ main::z1#0 ] ] - score: 1 +Coalescing zero page register with common assignment [ zp ZP_WORD:6 [ mul8u::res#2 mul8u::res#6 mul8u::res#1 mul8u::return#2 mul8u::return#3 main::z1#0 ] ] with [ zp ZP_WORD:16 [ main::z2#0 ] ] - score: 1 +Allocated (was zp ZP_WORD:6) zp ZP_WORD:5 [ mul8u::res#2 mul8u::res#6 mul8u::res#1 mul8u::return#2 mul8u::return#3 main::z1#0 main::z2#0 ] +Allocated (was zp ZP_WORD:8) zp ZP_WORD:7 [ mul8u::mb#2 mul8u::mb#0 mul8u::mb#1 ] + +ASSEMBLER BEFORE OPTIMIZATION +//SEG0 File Comments +//SEG1 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(bbegin) +.pc = $80d "Program" +//SEG2 Global Constants & labels + .const SIZEOF_WORD = 2 +//SEG3 @begin +bbegin: +//SEG4 [1] phi from @begin to @1 [phi:@begin->@1] +b1_from_bbegin: + jmp b1 +//SEG5 @1 +b1: +//SEG6 [2] call main +//SEG7 [4] phi from @1 to main [phi:@1->main] +main_from_b1: + jsr main +//SEG8 [3] phi from @1 to @end [phi:@1->@end] +bend_from_b1: + jmp bend +//SEG9 @end +bend: +//SEG10 main +main: { + .label z1 = 5 + .label screen = 3 + .label z2 = 5 + .label y = 2 + //SEG11 [5] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + //SEG12 [5] phi (word*) main::screen#1 = (word*) 1024 [phi:main->main::@1#0] -- pwuz1=pwuc1 + lda #<$400 + sta screen + lda #>$400 + sta screen+1 + //SEG13 [5] phi (byte) main::y#2 = (byte) 0 [phi:main->main::@1#1] -- vbuz1=vbuc1 + lda #0 + sta y + jmp b1 + //SEG14 [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1] + b1_from_b3: + //SEG15 [5] phi (word*) main::screen#1 = (word*) main::screen#2 [phi:main::@3->main::@1#0] -- register_copy + //SEG16 [5] phi (byte) main::y#2 = (byte) main::y#1 [phi:main::@3->main::@1#1] -- register_copy + jmp b1 + //SEG17 main::@1 + b1: + //SEG18 [6] (byte) mul8u::a#1 ← (byte) main::y#2 -- vbuxx=vbuz1 + ldx y + //SEG19 [7] call mul8u + //SEG20 [20] phi from main::@1 to mul8u [phi:main::@1->mul8u] + mul8u_from_b1: + //SEG21 [20] phi (byte) mul8u::a#6 = (byte) mul8u::a#1 [phi:main::@1->mul8u#0] -- register_copy + //SEG22 [20] phi (word) mul8u::mb#0 = (const byte) mul8u::b#0 [phi:main::@1->mul8u#1] -- vwuz1=vbuc1 + lda #mul8u.b + sta mul8u.mb + lda #0 + sta mul8u.mb+1 + jsr mul8u + //SEG23 [8] (word) mul8u::return#2 ← (word) mul8u::res#2 + jmp b2 + //SEG24 main::@2 + b2: + //SEG25 [9] (word) main::z1#0 ← (word) mul8u::return#2 + //SEG26 [10] *((word*) main::screen#1) ← (word) main::z1#0 -- _deref_pwuz1=vwuz2 + ldy #0 + lda z1 + sta (screen),y + iny + lda z1+1 + sta (screen),y + //SEG27 [11] (byte) mul8u::a#2 ← (byte) main::y#2 -- vbuxx=vbuz1 + ldx y + //SEG28 [12] call mul8u + //SEG29 [20] phi from main::@2 to mul8u [phi:main::@2->mul8u] + mul8u_from_b2: + //SEG30 [20] phi (byte) mul8u::a#6 = (byte) mul8u::a#2 [phi:main::@2->mul8u#0] -- register_copy + //SEG31 [20] phi (word) mul8u::mb#0 = (const byte) mul8u::b#1 [phi:main::@2->mul8u#1] -- vwuz1=vbuc1 + lda #mul8u.b + sta mul8u.mb + lda #0 + sta mul8u.mb+1 + jsr mul8u + //SEG32 [13] (word) mul8u::return#3 ← (word) mul8u::res#2 + jmp b3 + //SEG33 main::@3 + b3: + //SEG34 [14] (word) main::z2#0 ← (word) mul8u::return#3 + //SEG35 [15] *((word*) main::screen#1 + (const byte) SIZEOF_WORD) ← (word) main::z2#0 -- pwuz1_derefidx_vbuc1=vwuz2 + ldy #SIZEOF_WORD + lda z2 + sta (screen),y + iny + lda z2+1 + sta (screen),y + //SEG36 [16] (word*) main::screen#2 ← (word*) main::screen#1 + (const byte) SIZEOF_WORD+(const byte) SIZEOF_WORD -- pwuz1=pwuz1_plus_vbuc1 + lda #SIZEOF_WORD+SIZEOF_WORD + clc + adc screen + sta screen + bcc !+ + inc screen+1 + !: + //SEG37 [17] (byte) main::y#1 ← ++ (byte) main::y#2 -- vbuz1=_inc_vbuz1 + inc y + //SEG38 [18] if((byte) main::y#1!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 + lda #6 + cmp y + bne b1_from_b3 + jmp breturn + //SEG39 main::@return + breturn: + //SEG40 [19] return + rts +} +//SEG41 mul8u +// Perform binary multiplication of two unsigned 8-bit bytes into a 16-bit unsigned word +// mul8u(byte register(X) a) +mul8u: { + .label b = $28 + .label mb = 7 + .label res = 5 + .label return = 5 + //SEG42 [21] phi from mul8u to mul8u::@1 [phi:mul8u->mul8u::@1] + b1_from_mul8u: + //SEG43 [21] phi (word) mul8u::mb#2 = (word) mul8u::mb#0 [phi:mul8u->mul8u::@1#0] -- register_copy + //SEG44 [21] phi (word) mul8u::res#2 = (byte) 0 [phi:mul8u->mul8u::@1#1] -- vwuz1=vbuc1 + lda #0 + sta res + lda #0 + sta res+1 + //SEG45 [21] phi (byte) mul8u::a#3 = (byte) mul8u::a#6 [phi:mul8u->mul8u::@1#2] -- register_copy + jmp b1 + //SEG46 mul8u::@1 + b1: + //SEG47 [22] if((byte) mul8u::a#3!=(byte) 0) goto mul8u::@2 -- vbuxx_neq_0_then_la1 + cpx #0 + bne b2 + jmp breturn + //SEG48 mul8u::@return + breturn: + //SEG49 [23] return + rts + //SEG50 mul8u::@2 + b2: + //SEG51 [24] (byte~) mul8u::$1 ← (byte) mul8u::a#3 & (byte) 1 -- vbuaa=vbuxx_band_vbuc1 + txa + and #1 + //SEG52 [25] if((byte~) mul8u::$1==(byte) 0) goto mul8u::@3 -- vbuaa_eq_0_then_la1 + cmp #0 + beq b3_from_b2 + jmp b4 + //SEG53 mul8u::@4 + b4: + //SEG54 [26] (word) mul8u::res#1 ← (word) mul8u::res#2 + (word) mul8u::mb#2 -- vwuz1=vwuz1_plus_vwuz2 + lda res + clc + adc mb + sta res + lda res+1 + adc mb+1 + sta res+1 + //SEG55 [27] phi from mul8u::@2 mul8u::@4 to mul8u::@3 [phi:mul8u::@2/mul8u::@4->mul8u::@3] + b3_from_b2: + b3_from_b4: + //SEG56 [27] phi (word) mul8u::res#6 = (word) mul8u::res#2 [phi:mul8u::@2/mul8u::@4->mul8u::@3#0] -- register_copy + jmp b3 + //SEG57 mul8u::@3 + b3: + //SEG58 [28] (byte) mul8u::a#0 ← (byte) mul8u::a#3 >> (byte) 1 -- vbuxx=vbuxx_ror_1 + txa + lsr + tax + //SEG59 [29] (word) mul8u::mb#1 ← (word) mul8u::mb#2 << (byte) 1 -- vwuz1=vwuz1_rol_1 + asl mb + rol mb+1 + //SEG60 [21] phi from mul8u::@3 to mul8u::@1 [phi:mul8u::@3->mul8u::@1] + b1_from_b3: + //SEG61 [21] phi (word) mul8u::mb#2 = (word) mul8u::mb#1 [phi:mul8u::@3->mul8u::@1#0] -- register_copy + //SEG62 [21] phi (word) mul8u::res#2 = (word) mul8u::res#6 [phi:mul8u::@3->mul8u::@1#1] -- register_copy + //SEG63 [21] phi (byte) mul8u::a#3 = (byte) mul8u::a#0 [phi:mul8u::@3->mul8u::@1#2] -- register_copy + jmp b1 +} + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp b1 +Removing instruction jmp bend +Removing instruction jmp b1 +Removing instruction jmp b2 +Removing instruction jmp b3 +Removing instruction jmp breturn +Removing instruction jmp b1 +Removing instruction jmp breturn +Removing instruction jmp b4 +Removing instruction jmp b3 +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction lda #0 +Succesful ASM optimization Pass5UnnecesaryLoadElimination +Replacing label b1_from_b3 with b1 +Replacing label b3_from_b2 with b3 +Removing instruction b1_from_bbegin: +Removing instruction b1: +Removing instruction main_from_b1: +Removing instruction bend_from_b1: +Removing instruction b1_from_b3: +Removing instruction b3_from_b2: +Removing instruction b3_from_b4: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction bend: +Removing instruction b1_from_main: +Removing instruction mul8u_from_b1: +Removing instruction b2: +Removing instruction mul8u_from_b2: +Removing instruction b3: +Removing instruction breturn: +Removing instruction b1_from_mul8u: +Removing instruction breturn: +Removing instruction b4: +Removing instruction b1_from_b3: +Succesful ASM optimization Pass5UnusedLabelElimination +Updating BasicUpstart to call main directly +Removing instruction jsr main +Succesful ASM optimization Pass5SkipBegin +Removing instruction jmp b1 +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction bbegin: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +(label) @1 +(label) @begin +(label) @end +(const byte) SIZEOF_WORD SIZEOF_WORD = (byte) 2 +(void()) main() +(label) main::@1 +(label) main::@2 +(label) main::@3 +(label) main::@return +(word*) main::screen +(word*) main::screen#1 screen zp ZP_WORD:3 4.0 +(word*) main::screen#2 screen zp ZP_WORD:3 7.333333333333333 +(byte) main::y +(byte) main::y#1 y zp ZP_BYTE:2 16.5 +(byte) main::y#2 y zp ZP_BYTE:2 3.6666666666666665 +(word) main::z1 +(word) main::z1#0 z1 zp ZP_WORD:5 22.0 +(word) main::z2 +(word) main::z2#0 z2 zp ZP_WORD:5 22.0 +(word()) mul8u((byte) mul8u::a , (byte) mul8u::b) +(byte~) mul8u::$1 reg byte a 202.0 +(label) mul8u::@1 +(label) mul8u::@2 +(label) mul8u::@3 +(label) mul8u::@4 +(label) mul8u::@return +(byte) mul8u::a +(byte) mul8u::a#0 reg byte x 101.0 +(byte) mul8u::a#1 reg byte x 22.0 +(byte) mul8u::a#2 reg byte x 22.0 +(byte) mul8u::a#3 reg byte x 67.66666666666666 +(byte) mul8u::a#6 reg byte x 24.0 +(byte) mul8u::b +(const byte) mul8u::b#0 b = (byte) $28 +(const byte) mul8u::b#1 b = (byte) $28 +(word) mul8u::mb +(word) mul8u::mb#0 mb zp ZP_WORD:7 2.0 +(word) mul8u::mb#1 mb zp ZP_WORD:7 202.0 +(word) mul8u::mb#2 mb zp ZP_WORD:7 43.57142857142858 +(word) mul8u::res +(word) mul8u::res#1 res zp ZP_WORD:5 202.0 +(word) mul8u::res#2 res zp ZP_WORD:5 46.42857142857143 +(word) mul8u::res#6 res zp ZP_WORD:5 101.0 +(word) mul8u::return +(word) mul8u::return#2 return zp ZP_WORD:5 22.0 +(word) mul8u::return#3 return zp ZP_WORD:5 22.0 + +zp ZP_BYTE:2 [ main::y#2 main::y#1 ] +zp ZP_WORD:3 [ main::screen#1 main::screen#2 ] +reg byte x [ mul8u::a#3 mul8u::a#6 mul8u::a#1 mul8u::a#2 mul8u::a#0 ] +zp ZP_WORD:5 [ mul8u::res#2 mul8u::res#6 mul8u::res#1 mul8u::return#2 mul8u::return#3 main::z1#0 main::z2#0 ] +zp ZP_WORD:7 [ mul8u::mb#2 mul8u::mb#0 mul8u::mb#1 ] +reg byte a [ mul8u::$1 ] + + +FINAL ASSEMBLER +Score: 6994 + +//SEG0 File Comments +//SEG1 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG2 Global Constants & labels + .const SIZEOF_WORD = 2 +//SEG3 @begin +//SEG4 [1] phi from @begin to @1 [phi:@begin->@1] +//SEG5 @1 +//SEG6 [2] call main +//SEG7 [4] phi from @1 to main [phi:@1->main] +//SEG8 [3] phi from @1 to @end [phi:@1->@end] +//SEG9 @end +//SEG10 main +main: { + .label z1 = 5 + .label screen = 3 + .label z2 = 5 + .label y = 2 + //SEG11 [5] phi from main to main::@1 [phi:main->main::@1] + //SEG12 [5] phi (word*) main::screen#1 = (word*) 1024 [phi:main->main::@1#0] -- pwuz1=pwuc1 + lda #<$400 + sta screen + lda #>$400 + sta screen+1 + //SEG13 [5] phi (byte) main::y#2 = (byte) 0 [phi:main->main::@1#1] -- vbuz1=vbuc1 + lda #0 + sta y + //SEG14 [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1] + //SEG15 [5] phi (word*) main::screen#1 = (word*) main::screen#2 [phi:main::@3->main::@1#0] -- register_copy + //SEG16 [5] phi (byte) main::y#2 = (byte) main::y#1 [phi:main::@3->main::@1#1] -- register_copy + //SEG17 main::@1 + b1: + //SEG18 [6] (byte) mul8u::a#1 ← (byte) main::y#2 -- vbuxx=vbuz1 + ldx y + //SEG19 [7] call mul8u + //SEG20 [20] phi from main::@1 to mul8u [phi:main::@1->mul8u] + //SEG21 [20] phi (byte) mul8u::a#6 = (byte) mul8u::a#1 [phi:main::@1->mul8u#0] -- register_copy + //SEG22 [20] phi (word) mul8u::mb#0 = (const byte) mul8u::b#0 [phi:main::@1->mul8u#1] -- vwuz1=vbuc1 + lda #mul8u.b + sta mul8u.mb + lda #0 + sta mul8u.mb+1 + jsr mul8u + //SEG23 [8] (word) mul8u::return#2 ← (word) mul8u::res#2 + //SEG24 main::@2 + //SEG25 [9] (word) main::z1#0 ← (word) mul8u::return#2 + //SEG26 [10] *((word*) main::screen#1) ← (word) main::z1#0 -- _deref_pwuz1=vwuz2 + ldy #0 + lda z1 + sta (screen),y + iny + lda z1+1 + sta (screen),y + //SEG27 [11] (byte) mul8u::a#2 ← (byte) main::y#2 -- vbuxx=vbuz1 + ldx y + //SEG28 [12] call mul8u + //SEG29 [20] phi from main::@2 to mul8u [phi:main::@2->mul8u] + //SEG30 [20] phi (byte) mul8u::a#6 = (byte) mul8u::a#2 [phi:main::@2->mul8u#0] -- register_copy + //SEG31 [20] phi (word) mul8u::mb#0 = (const byte) mul8u::b#1 [phi:main::@2->mul8u#1] -- vwuz1=vbuc1 + lda #mul8u.b + sta mul8u.mb + lda #0 + sta mul8u.mb+1 + jsr mul8u + //SEG32 [13] (word) mul8u::return#3 ← (word) mul8u::res#2 + //SEG33 main::@3 + //SEG34 [14] (word) main::z2#0 ← (word) mul8u::return#3 + //SEG35 [15] *((word*) main::screen#1 + (const byte) SIZEOF_WORD) ← (word) main::z2#0 -- pwuz1_derefidx_vbuc1=vwuz2 + ldy #SIZEOF_WORD + lda z2 + sta (screen),y + iny + lda z2+1 + sta (screen),y + //SEG36 [16] (word*) main::screen#2 ← (word*) main::screen#1 + (const byte) SIZEOF_WORD+(const byte) SIZEOF_WORD -- pwuz1=pwuz1_plus_vbuc1 + lda #SIZEOF_WORD+SIZEOF_WORD + clc + adc screen + sta screen + bcc !+ + inc screen+1 + !: + //SEG37 [17] (byte) main::y#1 ← ++ (byte) main::y#2 -- vbuz1=_inc_vbuz1 + inc y + //SEG38 [18] if((byte) main::y#1!=(byte) 6) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 + lda #6 + cmp y + bne b1 + //SEG39 main::@return + //SEG40 [19] return + rts +} +//SEG41 mul8u +// Perform binary multiplication of two unsigned 8-bit bytes into a 16-bit unsigned word +// mul8u(byte register(X) a) +mul8u: { + .label b = $28 + .label mb = 7 + .label res = 5 + .label return = 5 + //SEG42 [21] phi from mul8u to mul8u::@1 [phi:mul8u->mul8u::@1] + //SEG43 [21] phi (word) mul8u::mb#2 = (word) mul8u::mb#0 [phi:mul8u->mul8u::@1#0] -- register_copy + //SEG44 [21] phi (word) mul8u::res#2 = (byte) 0 [phi:mul8u->mul8u::@1#1] -- vwuz1=vbuc1 + lda #0 + sta res + sta res+1 + //SEG45 [21] phi (byte) mul8u::a#3 = (byte) mul8u::a#6 [phi:mul8u->mul8u::@1#2] -- register_copy + //SEG46 mul8u::@1 + b1: + //SEG47 [22] if((byte) mul8u::a#3!=(byte) 0) goto mul8u::@2 -- vbuxx_neq_0_then_la1 + cpx #0 + bne b2 + //SEG48 mul8u::@return + //SEG49 [23] return + rts + //SEG50 mul8u::@2 + b2: + //SEG51 [24] (byte~) mul8u::$1 ← (byte) mul8u::a#3 & (byte) 1 -- vbuaa=vbuxx_band_vbuc1 + txa + and #1 + //SEG52 [25] if((byte~) mul8u::$1==(byte) 0) goto mul8u::@3 -- vbuaa_eq_0_then_la1 + cmp #0 + beq b3 + //SEG53 mul8u::@4 + //SEG54 [26] (word) mul8u::res#1 ← (word) mul8u::res#2 + (word) mul8u::mb#2 -- vwuz1=vwuz1_plus_vwuz2 + lda res + clc + adc mb + sta res + lda res+1 + adc mb+1 + sta res+1 + //SEG55 [27] phi from mul8u::@2 mul8u::@4 to mul8u::@3 [phi:mul8u::@2/mul8u::@4->mul8u::@3] + //SEG56 [27] phi (word) mul8u::res#6 = (word) mul8u::res#2 [phi:mul8u::@2/mul8u::@4->mul8u::@3#0] -- register_copy + //SEG57 mul8u::@3 + b3: + //SEG58 [28] (byte) mul8u::a#0 ← (byte) mul8u::a#3 >> (byte) 1 -- vbuxx=vbuxx_ror_1 + txa + lsr + tax + //SEG59 [29] (word) mul8u::mb#1 ← (word) mul8u::mb#2 << (byte) 1 -- vwuz1=vwuz1_rol_1 + asl mb + rol mb+1 + //SEG60 [21] phi from mul8u::@3 to mul8u::@1 [phi:mul8u::@3->mul8u::@1] + //SEG61 [21] phi (word) mul8u::mb#2 = (word) mul8u::mb#1 [phi:mul8u::@3->mul8u::@1#0] -- register_copy + //SEG62 [21] phi (word) mul8u::res#2 = (word) mul8u::res#6 [phi:mul8u::@3->mul8u::@1#1] -- register_copy + //SEG63 [21] phi (byte) mul8u::a#3 = (byte) mul8u::a#0 [phi:mul8u::@3->mul8u::@1#2] -- register_copy + jmp b1 +} + diff --git a/src/test/ref/robozzle64-label-problem.sym b/src/test/ref/robozzle64-label-problem.sym new file mode 100644 index 000000000..1daabbadc --- /dev/null +++ b/src/test/ref/robozzle64-label-problem.sym @@ -0,0 +1 @@ +program \ No newline at end of file