diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/pwuc1_derefidx_vbuxx=vwuz1.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/pwuc1_derefidx_vbuxx=vwuz1.asm new file mode 100644 index 000000000..dcb4c0bff --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/fragment/asm/pwuc1_derefidx_vbuxx=vwuz1.asm @@ -0,0 +1,4 @@ +lda {z1} +sta {c1},x +lda {z1}+1 +sta {c1}+1,x \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/pwuc1_derefidx_vbuyy=vwuz1.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/pwuc1_derefidx_vbuyy=vwuz1.asm new file mode 100644 index 000000000..95167d258 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/fragment/asm/pwuc1_derefidx_vbuyy=vwuz1.asm @@ -0,0 +1,4 @@ +lda {z1} +sta {c1},y +lda {z1}+1 +sta {c1}+1,y \ No newline at end of file diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/vwuz1=pwuc1_derefidx_vbuxx_rol_4.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/vwuz1=pwuc1_derefidx_vbuxx_rol_4.asm new file mode 100644 index 000000000..663dd9a98 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/fragment/asm/vwuz1=pwuc1_derefidx_vbuxx_rol_4.asm @@ -0,0 +1,13 @@ +lda {c1},x +sta {z1} +lda {c1}+1,x +sta {z1}+1 +asl {z1} +rol {z1}+1 +asl {z1} +rol {z1}+1 +asl {z1} +rol {z1}+1 +asl {z1} +rol {z1}+1 + diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/vwuz1=pwuc1_derefidx_vbuyy_rol_4.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/vwuz1=pwuc1_derefidx_vbuyy_rol_4.asm new file mode 100644 index 000000000..5e26fc490 --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/fragment/asm/vwuz1=pwuc1_derefidx_vbuyy_rol_4.asm @@ -0,0 +1,13 @@ +lda {c1},y +sta {z1} +lda {c1}+1,y +sta {z1}+1 +asl {z1} +rol {z1}+1 +asl {z1} +rol {z1}+1 +asl {z1} +rol {z1}+1 +asl {z1} +rol {z1}+1 + diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/vwuz1=vwuz1_rol_4.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/vwuz1=vwuz1_rol_4.asm new file mode 100644 index 000000000..1f57fe39e --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/fragment/asm/vwuz1=vwuz1_rol_4.asm @@ -0,0 +1,8 @@ +asl {z1} +rol {z1}+1 +asl {z1} +rol {z1}+1 +asl {z1} +rol {z1}+1 +asl {z1} +rol {z1}+1 diff --git a/src/main/java/dk/camelot64/kickc/fragment/asm/vwuz1=vwuz2_rol_4.asm b/src/main/java/dk/camelot64/kickc/fragment/asm/vwuz1=vwuz2_rol_4.asm new file mode 100644 index 000000000..1fc0aa63d --- /dev/null +++ b/src/main/java/dk/camelot64/kickc/fragment/asm/vwuz1=vwuz2_rol_4.asm @@ -0,0 +1,12 @@ +lda {z2} +asl +sta {z1} +lda {z2}+1 +rol +sta {z1}+1 +asl {z1} +rol {z1}+1 +asl {z1} +rol {z1}+1 +asl {z1} +rol {z1}+1 diff --git a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java index 0ecce332e..5a6bc3c98 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestPrograms.java +++ b/src/test/java/dk/camelot64/kickc/test/TestPrograms.java @@ -44,6 +44,11 @@ public class TestPrograms { AsmFragmentTemplateUsages.logUsages(log, false, false, false, false, false, false); } + @Test + public void testLineAnim() throws IOException, URISyntaxException { + compileAndCompare("line-anim"); + } + @Test public void testInlineFunctionLevel2() throws IOException, URISyntaxException { compileAndCompare("inline-function-level2"); diff --git a/src/test/java/dk/camelot64/kickc/test/kc/line-anim.kc b/src/test/java/dk/camelot64/kickc/test/kc/line-anim.kc new file mode 100644 index 000000000..5af807723 --- /dev/null +++ b/src/test/java/dk/camelot64/kickc/test/kc/line-anim.kc @@ -0,0 +1,37 @@ +// Animated lines drawn on a single color bitmap + +// The number of points +const byte SIZE = 4; + +// The coordinates of the lines to animate +word[4] x_start = { 10, 20, 30, 30 }; +byte[4] y_start = { 10, 10, 10, 20 }; +word[4] x_end = { 20, 10, 20, 20 }; +byte[4] y_end = { 20, 20, 10, 20 }; + +// Current x position fixed point [12.4] +word[4] x_cur; +// Current y position fixed point [12.4] +word[4] y_cur; +// X position addition per frame s[3.4] +signed byte[4] x_add; +// Y position addition per frame s[3.4] +signed byte[4] y_add; +// Frame delay (counted down to 0) +byte[4] delay; +// Frame number (counted down to 0) +byte[4] frame; + +void main() { + for( byte i=0; i!=8; i+=2) { + init(i); + } + +} + +void init(byte point_idx) { + x_cur[point_idx] = x_start[point_idx]<<4; + y_cur[point_idx] = ((word)y_start[point_idx>>1])<<4; +} + + diff --git a/src/test/java/dk/camelot64/kickc/test/ref/line-anim.asm b/src/test/java/dk/camelot64/kickc/test/ref/line-anim.asm new file mode 100644 index 000000000..8cfd079c3 --- /dev/null +++ b/src/test/java/dk/camelot64/kickc/test/ref/line-anim.asm @@ -0,0 +1,59 @@ +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" + jsr main +main: { + ldx #0 + b1: + jsr init + inx + inx + cpx #8 + bne b1 + rts +} +init: { + .label _0 = 2 + .label _2 = 2 + .label _3 = 2 + lda x_start,x + sta _0 + lda x_start+1,x + sta _0+1 + asl _0 + rol _0+1 + asl _0 + rol _0+1 + asl _0 + rol _0+1 + asl _0 + rol _0+1 + lda _0 + sta x_cur,x + lda _0+1 + sta x_cur+1,x + txa + lsr + tay + lda y_start,y + sta _2 + lda #0 + sta _2+1 + asl _3 + rol _3+1 + asl _3 + rol _3+1 + asl _3 + rol _3+1 + asl _3 + rol _3+1 + lda _3 + sta y_cur,x + lda _3+1 + sta y_cur+1,x + rts +} + x_start: .word $a, $14, $1e, $1e + y_start: .byte $a, $a, $a, $14 + x_cur: .fill 8, 0 + y_cur: .fill 8, 0 diff --git a/src/test/java/dk/camelot64/kickc/test/ref/line-anim.cfg b/src/test/java/dk/camelot64/kickc/test/ref/line-anim.cfg new file mode 100644 index 000000000..d356e48bf --- /dev/null +++ b/src/test/java/dk/camelot64/kickc/test/ref/line-anim.cfg @@ -0,0 +1,35 @@ +@begin: scope:[] from + [0] phi() [ ] ( ) + to:@2 +@2: scope:[] from @begin + [1] phi() [ ] ( ) + [2] call main [ ] ( ) + to:@end +@end: scope:[] from @2 + [3] phi() [ ] ( ) +main: scope:[main] from @2 + [4] phi() [ ] ( main:2 [ ] ) + to:main::@1 +main::@1: scope:[main] from main main::@3 + [5] (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@3/(byte) main::i#1 ) [ main::i#2 ] ( main:2 [ main::i#2 ] ) + [6] (byte) init::point_idx#0 ← (byte) main::i#2 [ main::i#2 init::point_idx#0 ] ( main:2 [ main::i#2 init::point_idx#0 ] ) + [7] call init [ main::i#2 ] ( main:2 [ main::i#2 ] ) + to:main::@3 +main::@3: scope:[main] from main::@1 + [8] (byte) main::i#1 ← (byte) main::i#2 + (byte/signed byte/word/signed word/dword/signed dword) 2 [ main::i#1 ] ( main:2 [ main::i#1 ] ) + [9] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) 8) goto main::@1 [ main::i#1 ] ( main:2 [ main::i#1 ] ) + to:main::@return +main::@return: scope:[main] from main::@3 + [10] return [ ] ( main:2 [ ] ) + to:@return +init: scope:[init] from main::@1 + [11] (word~) init::$0 ← *((const word[4]) x_start#0 + (byte) init::point_idx#0) << (byte/signed byte/word/signed word/dword/signed dword) 4 [ init::point_idx#0 init::$0 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$0 ] ) + [12] *((const word[4]) x_cur#0 + (byte) init::point_idx#0) ← (word~) init::$0 [ init::point_idx#0 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 ] ) + [13] (byte~) init::$1 ← (byte) init::point_idx#0 >> (byte/signed byte/word/signed word/dword/signed dword) 1 [ init::point_idx#0 init::$1 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$1 ] ) + [14] (word~) init::$2 ← ((word)) *((const byte[4]) y_start#0 + (byte~) init::$1) [ init::point_idx#0 init::$2 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$2 ] ) + [15] (word~) init::$3 ← (word~) init::$2 << (byte/signed byte/word/signed word/dword/signed dword) 4 [ init::point_idx#0 init::$3 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$3 ] ) + [16] *((const word[4]) y_cur#0 + (byte) init::point_idx#0) ← (word~) init::$3 [ ] ( main:2::init:7 [ main::i#2 ] ) + to:init::@return +init::@return: scope:[init] from init + [17] return [ ] ( main:2::init:7 [ main::i#2 ] ) + to:@return diff --git a/src/test/java/dk/camelot64/kickc/test/ref/line-anim.log b/src/test/java/dk/camelot64/kickc/test/ref/line-anim.log new file mode 100644 index 000000000..be0e48e9f --- /dev/null +++ b/src/test/java/dk/camelot64/kickc/test/ref/line-anim.log @@ -0,0 +1,785 @@ +PARSING src/test/java/dk/camelot64/kickc/test/kc/line-anim.kc +// Animated lines drawn on a single color bitmap + +// The number of points +const byte SIZE = 4; + +// The coordinates of the lines to animate +word[4] x_start = { 10, 20, 30, 30 }; +byte[4] y_start = { 10, 10, 10, 20 }; +word[4] x_end = { 20, 10, 20, 20 }; +byte[4] y_end = { 20, 20, 10, 20 }; + +// Current x position fixed point [12.4] +word[4] x_cur; +// Current y position fixed point [12.4] +word[4] y_cur; +// X position addition per frame s[3.4] +signed byte[4] x_add; +// Y position addition per frame s[3.4] +signed byte[4] y_add; +// Frame delay (counted down to 0) +byte[4] delay; +// Frame number (counted down to 0) +byte[4] frame; + +void main() { + for( byte i=0; i!=8; i+=2) { + init(i); + } + +} + +void init(byte point_idx) { + x_cur[point_idx] = x_start[point_idx]<<4; + y_cur[point_idx] = ((word)y_start[point_idx>>1])<<4; +} + + + +SYMBOLS +(label) @1 +(label) @2 +(label) @begin +(label) @end +(byte) SIZE +(byte[4]) delay +(byte[4]) frame +(void()) init((byte) init::point_idx) +(word~) init::$0 +(byte~) init::$1 +(word~) init::$2 +(word~) init::$3 +(label) init::@return +(byte) init::point_idx +(void()) main() +(void~) main::$0 +(bool~) main::$1 +(label) main::@1 +(label) main::@2 +(label) main::@return +(byte) main::i +(signed byte[4]) x_add +(word[4]) x_cur +(word[4]) x_end +(word[4]) x_start +(signed byte[4]) y_add +(word[4]) y_cur +(byte[4]) y_end +(byte[4]) y_start + +INITIAL CONTROL FLOW GRAPH +@begin: scope:[] from + (byte) SIZE ← (byte/signed byte/word/signed word/dword/signed dword) 4 + (word[4]) x_start ← { (byte/signed byte/word/signed word/dword/signed dword) 10, (byte/signed byte/word/signed word/dword/signed dword) 20, (byte/signed byte/word/signed word/dword/signed dword) 30, (byte/signed byte/word/signed word/dword/signed dword) 30 } + (byte[4]) y_start ← { (byte/signed byte/word/signed word/dword/signed dword) 10, (byte/signed byte/word/signed word/dword/signed dword) 10, (byte/signed byte/word/signed word/dword/signed dword) 10, (byte/signed byte/word/signed word/dword/signed dword) 20 } + (word[4]) x_end ← { (byte/signed byte/word/signed word/dword/signed dword) 20, (byte/signed byte/word/signed word/dword/signed dword) 10, (byte/signed byte/word/signed word/dword/signed dword) 20, (byte/signed byte/word/signed word/dword/signed dword) 20 } + (byte[4]) y_end ← { (byte/signed byte/word/signed word/dword/signed dword) 20, (byte/signed byte/word/signed word/dword/signed dword) 20, (byte/signed byte/word/signed word/dword/signed dword) 10, (byte/signed byte/word/signed word/dword/signed dword) 20 } + (word[4]) x_cur ← { fill( 4, 0) } + (word[4]) y_cur ← { fill( 4, 0) } + (signed byte[4]) x_add ← { fill( 4, 0) } + (signed byte[4]) y_add ← { fill( 4, 0) } + (byte[4]) delay ← { fill( 4, 0) } + (byte[4]) frame ← { fill( 4, 0) } + to:@1 +main: scope:[main] from + (byte) main::i ← (byte/signed byte/word/signed word/dword/signed dword) 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + (void~) main::$0 ← call init (byte) main::i + (byte) main::i ← (byte) main::i + (byte/signed byte/word/signed word/dword/signed dword) 2 + (bool~) main::$1 ← (byte) main::i != (byte/signed byte/word/signed word/dword/signed dword) 8 + if((bool~) main::$1) goto main::@1 + to:main::@2 +main::@2: scope:[main] from main::@1 + to:main::@return +main::@return: scope:[main] from main::@2 + return + to:@return +@1: scope:[] from @begin + to:@2 +init: scope:[init] from + (word~) init::$0 ← *((word[4]) x_start + (byte) init::point_idx) << (byte/signed byte/word/signed word/dword/signed dword) 4 + *((word[4]) x_cur + (byte) init::point_idx) ← (word~) init::$0 + (byte~) init::$1 ← (byte) init::point_idx >> (byte/signed byte/word/signed word/dword/signed dword) 1 + (word~) init::$2 ← ((word)) *((byte[4]) y_start + (byte~) init::$1) + (word~) init::$3 ← (word~) init::$2 << (byte/signed byte/word/signed word/dword/signed dword) 4 + *((word[4]) y_cur + (byte) init::point_idx) ← (word~) init::$3 + to:init::@return +init::@return: scope:[init] from init + return + to:@return +@2: scope:[] from @1 + call main + to:@end +@end: scope:[] from @2 + +Eliminating unused variable (byte) SIZE and assignment [0] (byte) SIZE ← (byte/signed byte/word/signed word/dword/signed dword) 4 +Eliminating unused variable (word[4]) x_end and assignment [3] (word[4]) x_end ← { (byte/signed byte/word/signed word/dword/signed dword) 20, (byte/signed byte/word/signed word/dword/signed dword) 10, (byte/signed byte/word/signed word/dword/signed dword) 20, (byte/signed byte/word/signed word/dword/signed dword) 20 } +Eliminating unused variable (byte[4]) y_end and assignment [4] (byte[4]) y_end ← { (byte/signed byte/word/signed word/dword/signed dword) 20, (byte/signed byte/word/signed word/dword/signed dword) 20, (byte/signed byte/word/signed word/dword/signed dword) 10, (byte/signed byte/word/signed word/dword/signed dword) 20 } +Eliminating unused variable (signed byte[4]) x_add and assignment [7] (signed byte[4]) x_add ← { fill( 4, 0) } +Eliminating unused variable (signed byte[4]) y_add and assignment [8] (signed byte[4]) y_add ← { fill( 4, 0) } +Eliminating unused variable (byte[4]) delay and assignment [9] (byte[4]) delay ← { fill( 4, 0) } +Eliminating unused variable (byte[4]) frame and assignment [10] (byte[4]) frame ← { fill( 4, 0) } +Eliminating unused variable - keeping the call (void~) main::$0 +Removing empty block main::@2 +Removing empty block @1 +PROCEDURE MODIFY VARIABLE ANALYSIS + +Completing Phi functions... + +CONTROL FLOW GRAPH SSA WITH ASSIGNMENT CALL & RETURN +@begin: scope:[] from + (word[4]) x_start#0 ← { (byte/signed byte/word/signed word/dword/signed dword) 10, (byte/signed byte/word/signed word/dword/signed dword) 20, (byte/signed byte/word/signed word/dword/signed dword) 30, (byte/signed byte/word/signed word/dword/signed dword) 30 } + (byte[4]) y_start#0 ← { (byte/signed byte/word/signed word/dword/signed dword) 10, (byte/signed byte/word/signed word/dword/signed dword) 10, (byte/signed byte/word/signed word/dword/signed dword) 10, (byte/signed byte/word/signed word/dword/signed dword) 20 } + (word[4]) x_cur#0 ← { fill( 4, 0) } + (word[4]) y_cur#0 ← { fill( 4, 0) } + to:@2 +main: scope:[main] from @2 + (byte) main::i#0 ← (byte/signed byte/word/signed word/dword/signed dword) 0 + to:main::@1 +main::@1: scope:[main] from main main::@3 + (byte) main::i#2 ← phi( main/(byte) main::i#0 main::@3/(byte) main::i#1 ) + (byte) init::point_idx#0 ← (byte) main::i#2 + call init + to:main::@3 +main::@3: scope:[main] from main::@1 + (byte) main::i#3 ← phi( main::@1/(byte) main::i#2 ) + (byte) main::i#1 ← (byte) main::i#3 + (byte/signed byte/word/signed word/dword/signed dword) 2 + (bool~) main::$1 ← (byte) main::i#1 != (byte/signed byte/word/signed word/dword/signed dword) 8 + if((bool~) main::$1) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@3 + return + to:@return +init: scope:[init] from main::@1 + (byte) init::point_idx#1 ← phi( main::@1/(byte) init::point_idx#0 ) + (word~) init::$0 ← *((word[4]) x_start#0 + (byte) init::point_idx#1) << (byte/signed byte/word/signed word/dword/signed dword) 4 + *((word[4]) x_cur#0 + (byte) init::point_idx#1) ← (word~) init::$0 + (byte~) init::$1 ← (byte) init::point_idx#1 >> (byte/signed byte/word/signed word/dword/signed dword) 1 + (word~) init::$2 ← ((word)) *((byte[4]) y_start#0 + (byte~) init::$1) + (word~) init::$3 ← (word~) init::$2 << (byte/signed byte/word/signed word/dword/signed dword) 4 + *((word[4]) y_cur#0 + (byte) init::point_idx#1) ← (word~) init::$3 + to:init::@return +init::@return: scope:[init] from init + return + to:@return +@2: scope:[] from @begin + call main + to:@3 +@3: scope:[] from @2 + to:@end +@end: scope:[] from @3 + +SYMBOL TABLE SSA +(label) @2 +(label) @3 +(label) @begin +(label) @end +(void()) init((byte) init::point_idx) +(word~) init::$0 +(byte~) init::$1 +(word~) init::$2 +(word~) init::$3 +(label) init::@return +(byte) init::point_idx +(byte) init::point_idx#0 +(byte) init::point_idx#1 +(void()) main() +(bool~) main::$1 +(label) main::@1 +(label) main::@3 +(label) main::@return +(byte) main::i +(byte) main::i#0 +(byte) main::i#1 +(byte) main::i#2 +(byte) main::i#3 +(word[4]) x_cur +(word[4]) x_cur#0 +(word[4]) x_start +(word[4]) x_start#0 +(word[4]) y_cur +(word[4]) y_cur#0 +(byte[4]) y_start +(byte[4]) y_start#0 + +OPTIMIZING CONTROL FLOW GRAPH +Culled Empty Block (label) @3 +Succesful SSA optimization Pass2CullEmptyBlocks +Not aliassing across scopes: init::point_idx#0 main::i#2 +Not aliassing across scopes: init::point_idx#1 init::point_idx#0 +Alias (byte) main::i#2 = (byte) main::i#3 +Succesful SSA optimization Pass2AliasElimination +Not aliassing across scopes: init::point_idx#0 main::i#2 +Not aliassing across scopes: init::point_idx#1 init::point_idx#0 +Redundant Phi (byte) init::point_idx#1 (byte) init::point_idx#0 +Succesful SSA optimization Pass2RedundantPhiElimination +Simple Condition (bool~) main::$1 if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) 8) goto main::@1 +Succesful SSA optimization Pass2ConditionalJumpSimplification +Constant (const word[4]) x_start#0 = { 10, 20, 30, 30 } +Constant (const byte[4]) y_start#0 = { 10, 10, 10, 20 } +Constant (const word[4]) x_cur#0 = { fill( 4, 0) } +Constant (const word[4]) y_cur#0 = { fill( 4, 0) } +Constant (const byte) main::i#0 = 0 +Succesful SSA optimization Pass2ConstantIdentification +Not aliassing across scopes: init::point_idx#0 main::i#2 +OPTIMIZING CONTROL FLOW GRAPH +Inlining constant with var siblings (const byte) main::i#0 +Inlining constant with var siblings (const byte) main::i#0 +Constant inlined main::i#0 = (byte/signed byte/word/signed word/dword/signed dword) 0 +Succesful SSA optimization Pass2ConstantInlining +Block Sequence Planned @begin @2 @end main main::@1 main::@3 main::@return init init::@return +Added new block during phi lifting main::@4(between main::@3 and main::@1) +Block Sequence Planned @begin @2 @end main main::@1 main::@3 main::@return main::@4 init init::@return +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 +CALL GRAPH +Calls in [] to main:2 +Calls in [main] to init:7 + +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Created 1 initial phi equivalence classes +Coalesced [11] main::i#4 ← main::i#1 +Coalesced down to 1 phi equivalence classes +Culled Empty Block (label) main::@4 +Block Sequence Planned @begin @2 @end main main::@1 main::@3 main::@return init init::@return +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 +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... +Propagating live ranges... + +FINAL CONTROL FLOW GRAPH +@begin: scope:[] from + [0] phi() [ ] ( ) + to:@2 +@2: scope:[] from @begin + [1] phi() [ ] ( ) + [2] call main [ ] ( ) + to:@end +@end: scope:[] from @2 + [3] phi() [ ] ( ) +main: scope:[main] from @2 + [4] phi() [ ] ( main:2 [ ] ) + to:main::@1 +main::@1: scope:[main] from main main::@3 + [5] (byte) main::i#2 ← phi( main/(byte/signed byte/word/signed word/dword/signed dword) 0 main::@3/(byte) main::i#1 ) [ main::i#2 ] ( main:2 [ main::i#2 ] ) + [6] (byte) init::point_idx#0 ← (byte) main::i#2 [ main::i#2 init::point_idx#0 ] ( main:2 [ main::i#2 init::point_idx#0 ] ) + [7] call init [ main::i#2 ] ( main:2 [ main::i#2 ] ) + to:main::@3 +main::@3: scope:[main] from main::@1 + [8] (byte) main::i#1 ← (byte) main::i#2 + (byte/signed byte/word/signed word/dword/signed dword) 2 [ main::i#1 ] ( main:2 [ main::i#1 ] ) + [9] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) 8) goto main::@1 [ main::i#1 ] ( main:2 [ main::i#1 ] ) + to:main::@return +main::@return: scope:[main] from main::@3 + [10] return [ ] ( main:2 [ ] ) + to:@return +init: scope:[init] from main::@1 + [11] (word~) init::$0 ← *((const word[4]) x_start#0 + (byte) init::point_idx#0) << (byte/signed byte/word/signed word/dword/signed dword) 4 [ init::point_idx#0 init::$0 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$0 ] ) + [12] *((const word[4]) x_cur#0 + (byte) init::point_idx#0) ← (word~) init::$0 [ init::point_idx#0 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 ] ) + [13] (byte~) init::$1 ← (byte) init::point_idx#0 >> (byte/signed byte/word/signed word/dword/signed dword) 1 [ init::point_idx#0 init::$1 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$1 ] ) + [14] (word~) init::$2 ← ((word)) *((const byte[4]) y_start#0 + (byte~) init::$1) [ init::point_idx#0 init::$2 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$2 ] ) + [15] (word~) init::$3 ← (word~) init::$2 << (byte/signed byte/word/signed word/dword/signed dword) 4 [ init::point_idx#0 init::$3 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$3 ] ) + [16] *((const word[4]) y_cur#0 + (byte) init::point_idx#0) ← (word~) init::$3 [ ] ( main:2::init:7 [ main::i#2 ] ) + to:init::@return +init::@return: scope:[init] from init + [17] return [ ] ( main:2::init:7 [ main::i#2 ] ) + to:@return + +DOMINATORS +@begin dominated by @begin +@2 dominated by @2 @begin +@end dominated by @2 @begin @end +main dominated by @2 @begin main +main::@1 dominated by @2 @begin main::@1 main +main::@3 dominated by @2 @begin main::@1 main main::@3 +main::@return dominated by main::@return @2 @begin main::@1 main main::@3 +init dominated by init @2 @begin main::@1 main +init::@return dominated by init @2 @begin main::@1 init::@return main + +NATURAL LOOPS +Found back edge: Loop head: main::@1 tails: main::@3 blocks: null +Populated: Loop head: main::@1 tails: main::@3 blocks: main::@3 main::@1 +Loop head: main::@1 tails: main::@3 blocks: main::@3 main::@1 + +NATURAL LOOPS WITH DEPTH +Found 0 loops in scope [] +Found 1 loops in scope [main] + Loop head: main::@1 tails: main::@3 blocks: main::@3 main::@1 +Found 0 loops in scope [init] +Loop head: main::@1 tails: main::@3 blocks: main::@3 main::@1 depth: 1 + + +VARIABLE REGISTER WEIGHTS +(void()) init((byte) init::point_idx) +(word~) init::$0 4.0 +(byte~) init::$1 4.0 +(word~) init::$2 4.0 +(word~) init::$3 4.0 +(byte) init::point_idx +(byte) init::point_idx#0 3.166666666666667 +(void()) main() +(byte) main::i +(byte) main::i#1 16.5 +(byte) main::i#2 11.0 +(word[4]) x_cur +(word[4]) x_start +(word[4]) y_cur +(byte[4]) y_start + +Initial phi equivalence classes +[ main::i#2 main::i#1 ] +Added variable init::point_idx#0 to zero page equivalence class [ init::point_idx#0 ] +Added variable init::$0 to zero page equivalence class [ init::$0 ] +Added variable init::$1 to zero page equivalence class [ init::$1 ] +Added variable init::$2 to zero page equivalence class [ init::$2 ] +Added variable init::$3 to zero page equivalence class [ init::$3 ] +Complete equivalence classes +[ main::i#2 main::i#1 ] +[ init::point_idx#0 ] +[ init::$0 ] +[ init::$1 ] +[ init::$2 ] +[ init::$3 ] +Allocated zp ZP_BYTE:2 [ main::i#2 main::i#1 ] +Allocated zp ZP_BYTE:3 [ init::point_idx#0 ] +Allocated zp ZP_WORD:4 [ init::$0 ] +Allocated zp ZP_BYTE:6 [ init::$1 ] +Allocated zp ZP_WORD:7 [ init::$2 ] +Allocated zp ZP_WORD:9 [ init::$3 ] + +INITIAL ASM +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels +//SEG2 @begin +bbegin: +//SEG3 [1] phi from @begin to @2 [phi:@begin->@2] +b2_from_bbegin: + jmp b2 +//SEG4 @2 +b2: +//SEG5 [2] call main [ ] ( ) +//SEG6 [4] phi from @2 to main [phi:@2->main] +main_from_b2: + jsr main +//SEG7 [3] phi from @2 to @end [phi:@2->@end] +bend_from_b2: + jmp bend +//SEG8 @end +bend: +//SEG9 main +main: { + .label i = 2 + //SEG10 [5] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + //SEG11 [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 + //SEG12 [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1] + b1_from_b3: + //SEG13 [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@3->main::@1#0] -- register_copy + jmp b1 + //SEG14 main::@1 + b1: + //SEG15 [6] (byte) init::point_idx#0 ← (byte) main::i#2 [ main::i#2 init::point_idx#0 ] ( main:2 [ main::i#2 init::point_idx#0 ] ) -- vbuz1=vbuz2 + lda i + sta init.point_idx + //SEG16 [7] call init [ main::i#2 ] ( main:2 [ main::i#2 ] ) + jsr init + jmp b3 + //SEG17 main::@3 + b3: + //SEG18 [8] (byte) main::i#1 ← (byte) main::i#2 + (byte/signed byte/word/signed word/dword/signed dword) 2 [ main::i#1 ] ( main:2 [ main::i#1 ] ) -- vbuz1=vbuz1_plus_2 + lda i + clc + adc #2 + sta i + //SEG19 [9] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) 8) goto main::@1 [ main::i#1 ] ( main:2 [ main::i#1 ] ) -- vbuz1_neq_vbuc1_then_la1 + lda i + cmp #8 + bne b1_from_b3 + jmp breturn + //SEG20 main::@return + breturn: + //SEG21 [10] return [ ] ( main:2 [ ] ) + rts +} +//SEG22 init +init: { + .label _0 = 4 + .label _1 = 6 + .label _2 = 7 + .label _3 = 9 + .label point_idx = 3 + //SEG23 [11] (word~) init::$0 ← *((const word[4]) x_start#0 + (byte) init::point_idx#0) << (byte/signed byte/word/signed word/dword/signed dword) 4 [ init::point_idx#0 init::$0 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$0 ] ) -- vwuz1=pwuc1_derefidx_vbuz2_rol_4 + ldy point_idx + lda x_start,y + sta _0 + lda x_start+1,y + sta _0+1 + asl _0 + rol _0+1 + asl _0 + rol _0+1 + asl _0 + rol _0+1 + asl _0 + rol _0+1 + //SEG24 [12] *((const word[4]) x_cur#0 + (byte) init::point_idx#0) ← (word~) init::$0 [ init::point_idx#0 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 ] ) -- pwuc1_derefidx_vbuz1=vwuz2 + ldy point_idx + lda _0 + sta x_cur,y + lda _0+1 + sta x_cur+1,y + //SEG25 [13] (byte~) init::$1 ← (byte) init::point_idx#0 >> (byte/signed byte/word/signed word/dword/signed dword) 1 [ init::point_idx#0 init::$1 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$1 ] ) -- vbuz1=vbuz2_ror_1 + lda point_idx + lsr + sta _1 + //SEG26 [14] (word~) init::$2 ← ((word)) *((const byte[4]) y_start#0 + (byte~) init::$1) [ init::point_idx#0 init::$2 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$2 ] ) -- vwuz1=_word_pbuc1_derefidx_vbuz2 + ldy _1 + lda y_start,y + sta _2 + lda #0 + sta _2+1 + //SEG27 [15] (word~) init::$3 ← (word~) init::$2 << (byte/signed byte/word/signed word/dword/signed dword) 4 [ init::point_idx#0 init::$3 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$3 ] ) -- vwuz1=vwuz2_rol_4 + lda _2 + asl + sta _3 + lda _2+1 + rol + sta _3+1 + asl _3 + rol _3+1 + asl _3 + rol _3+1 + asl _3 + rol _3+1 + //SEG28 [16] *((const word[4]) y_cur#0 + (byte) init::point_idx#0) ← (word~) init::$3 [ ] ( main:2::init:7 [ main::i#2 ] ) -- pwuc1_derefidx_vbuz1=vwuz2 + ldy point_idx + lda _3 + sta y_cur,y + lda _3+1 + sta y_cur+1,y + jmp breturn + //SEG29 init::@return + breturn: + //SEG30 [17] return [ ] ( main:2::init:7 [ main::i#2 ] ) + rts +} + x_start: .word $a, $14, $1e, $1e + y_start: .byte $a, $a, $a, $14 + x_cur: .fill 8, 0 + y_cur: .fill 8, 0 + +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [11] (word~) init::$0 ← *((const word[4]) x_start#0 + (byte) init::point_idx#0) << (byte/signed byte/word/signed word/dword/signed dword) 4 [ init::point_idx#0 init::$0 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$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 ] +Removing always clobbered register reg byte a as potential for zp ZP_BYTE:3 [ init::point_idx#0 ] +Statement [12] *((const word[4]) x_cur#0 + (byte) init::point_idx#0) ← (word~) init::$0 [ init::point_idx#0 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 ] ) always clobbers reg byte a +Statement [13] (byte~) init::$1 ← (byte) init::point_idx#0 >> (byte/signed byte/word/signed word/dword/signed dword) 1 [ init::point_idx#0 init::$1 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$1 ] ) always clobbers reg byte a +Statement [14] (word~) init::$2 ← ((word)) *((const byte[4]) y_start#0 + (byte~) init::$1) [ init::point_idx#0 init::$2 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$2 ] ) always clobbers reg byte a +Statement [15] (word~) init::$3 ← (word~) init::$2 << (byte/signed byte/word/signed word/dword/signed dword) 4 [ init::point_idx#0 init::$3 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$3 ] ) always clobbers reg byte a +Statement [16] *((const word[4]) y_cur#0 + (byte) init::point_idx#0) ← (word~) init::$3 [ ] ( main:2::init:7 [ main::i#2 ] ) always clobbers reg byte a +Statement [11] (word~) init::$0 ← *((const word[4]) x_start#0 + (byte) init::point_idx#0) << (byte/signed byte/word/signed word/dword/signed dword) 4 [ init::point_idx#0 init::$0 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$0 ] ) always clobbers reg byte a +Statement [12] *((const word[4]) x_cur#0 + (byte) init::point_idx#0) ← (word~) init::$0 [ init::point_idx#0 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 ] ) always clobbers reg byte a +Statement [13] (byte~) init::$1 ← (byte) init::point_idx#0 >> (byte/signed byte/word/signed word/dword/signed dword) 1 [ init::point_idx#0 init::$1 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$1 ] ) always clobbers reg byte a +Statement [14] (word~) init::$2 ← ((word)) *((const byte[4]) y_start#0 + (byte~) init::$1) [ init::point_idx#0 init::$2 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$2 ] ) always clobbers reg byte a +Statement [15] (word~) init::$3 ← (word~) init::$2 << (byte/signed byte/word/signed word/dword/signed dword) 4 [ init::point_idx#0 init::$3 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$3 ] ) always clobbers reg byte a +Statement [16] *((const word[4]) y_cur#0 + (byte) init::point_idx#0) ← (word~) init::$3 [ ] ( main:2::init:7 [ main::i#2 ] ) 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 , +Potential registers zp ZP_BYTE:3 [ init::point_idx#0 ] : zp ZP_BYTE:3 , reg byte x , reg byte y , +Potential registers zp ZP_WORD:4 [ init::$0 ] : zp ZP_WORD:4 , +Potential registers zp ZP_BYTE:6 [ init::$1 ] : zp ZP_BYTE:6 , reg byte a , reg byte x , reg byte y , +Potential registers zp ZP_WORD:7 [ init::$2 ] : zp ZP_WORD:7 , +Potential registers zp ZP_WORD:9 [ init::$3 ] : zp ZP_WORD:9 , + +REGISTER UPLIFT SCOPES +Uplift Scope [main] 27.5: zp ZP_BYTE:2 [ main::i#2 main::i#1 ] +Uplift Scope [init] 4: zp ZP_WORD:4 [ init::$0 ] 4: zp ZP_BYTE:6 [ init::$1 ] 4: zp ZP_WORD:7 [ init::$2 ] 4: zp ZP_WORD:9 [ init::$3 ] 3.17: zp ZP_BYTE:3 [ init::point_idx#0 ] +Uplift Scope [] + +Uplifting [main] best 507 combination reg byte x [ main::i#2 main::i#1 ] +Uplifting [init] best 463 combination zp ZP_WORD:4 [ init::$0 ] reg byte a [ init::$1 ] zp ZP_WORD:7 [ init::$2 ] zp ZP_WORD:9 [ init::$3 ] reg byte x [ init::point_idx#0 ] +Uplifting [] best 463 combination +Coalescing zero page register with common assignment [ zp ZP_WORD:7 [ init::$2 ] ] with [ zp ZP_WORD:9 [ init::$3 ] ] - score: 1 +Coalescing zero page register [ zp ZP_WORD:4 [ init::$0 ] ] with [ zp ZP_WORD:7 [ init::$2 init::$3 ] ] +Allocated (was zp ZP_WORD:4) zp ZP_WORD:2 [ init::$0 init::$2 init::$3 ] + +ASSEMBLER BEFORE OPTIMIZATION +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels +//SEG2 @begin +bbegin: +//SEG3 [1] phi from @begin to @2 [phi:@begin->@2] +b2_from_bbegin: + jmp b2 +//SEG4 @2 +b2: +//SEG5 [2] call main [ ] ( ) +//SEG6 [4] phi from @2 to main [phi:@2->main] +main_from_b2: + jsr main +//SEG7 [3] phi from @2 to @end [phi:@2->@end] +bend_from_b2: + jmp bend +//SEG8 @end +bend: +//SEG9 main +main: { + //SEG10 [5] phi from main to main::@1 [phi:main->main::@1] + b1_from_main: + //SEG11 [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 + jmp b1 + //SEG12 [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1] + b1_from_b3: + //SEG13 [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@3->main::@1#0] -- register_copy + jmp b1 + //SEG14 main::@1 + b1: + //SEG15 [6] (byte) init::point_idx#0 ← (byte) main::i#2 [ main::i#2 init::point_idx#0 ] ( main:2 [ main::i#2 init::point_idx#0 ] ) + // (byte) init::point_idx#0 = (byte) main::i#2 // register copy reg byte x + //SEG16 [7] call init [ main::i#2 ] ( main:2 [ main::i#2 ] ) + jsr init + jmp b3 + //SEG17 main::@3 + b3: + //SEG18 [8] (byte) main::i#1 ← (byte) main::i#2 + (byte/signed byte/word/signed word/dword/signed dword) 2 [ main::i#1 ] ( main:2 [ main::i#1 ] ) -- vbuxx=vbuxx_plus_2 + inx + inx + //SEG19 [9] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) 8) goto main::@1 [ main::i#1 ] ( main:2 [ main::i#1 ] ) -- vbuxx_neq_vbuc1_then_la1 + cpx #8 + bne b1_from_b3 + jmp breturn + //SEG20 main::@return + breturn: + //SEG21 [10] return [ ] ( main:2 [ ] ) + rts +} +//SEG22 init +init: { + .label _0 = 2 + .label _2 = 2 + .label _3 = 2 + //SEG23 [11] (word~) init::$0 ← *((const word[4]) x_start#0 + (byte) init::point_idx#0) << (byte/signed byte/word/signed word/dword/signed dword) 4 [ init::point_idx#0 init::$0 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$0 ] ) -- vwuz1=pwuc1_derefidx_vbuxx_rol_4 + lda x_start,x + sta _0 + lda x_start+1,x + sta _0+1 + asl _0 + rol _0+1 + asl _0 + rol _0+1 + asl _0 + rol _0+1 + asl _0 + rol _0+1 + //SEG24 [12] *((const word[4]) x_cur#0 + (byte) init::point_idx#0) ← (word~) init::$0 [ init::point_idx#0 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 ] ) -- pwuc1_derefidx_vbuxx=vwuz1 + lda _0 + sta x_cur,x + lda _0+1 + sta x_cur+1,x + //SEG25 [13] (byte~) init::$1 ← (byte) init::point_idx#0 >> (byte/signed byte/word/signed word/dword/signed dword) 1 [ init::point_idx#0 init::$1 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$1 ] ) -- vbuaa=vbuxx_ror_1 + txa + lsr + //SEG26 [14] (word~) init::$2 ← ((word)) *((const byte[4]) y_start#0 + (byte~) init::$1) [ init::point_idx#0 init::$2 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$2 ] ) -- vwuz1=_word_pbuc1_derefidx_vbuaa + tay + lda y_start,y + sta _2 + lda #0 + sta _2+1 + //SEG27 [15] (word~) init::$3 ← (word~) init::$2 << (byte/signed byte/word/signed word/dword/signed dword) 4 [ init::point_idx#0 init::$3 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$3 ] ) -- vwuz1=vwuz1_rol_4 + asl _3 + rol _3+1 + asl _3 + rol _3+1 + asl _3 + rol _3+1 + asl _3 + rol _3+1 + //SEG28 [16] *((const word[4]) y_cur#0 + (byte) init::point_idx#0) ← (word~) init::$3 [ ] ( main:2::init:7 [ main::i#2 ] ) -- pwuc1_derefidx_vbuxx=vwuz1 + lda _3 + sta y_cur,x + lda _3+1 + sta y_cur+1,x + jmp breturn + //SEG29 init::@return + breturn: + //SEG30 [17] return [ ] ( main:2::init:7 [ main::i#2 ] ) + rts +} + x_start: .word $a, $14, $1e, $1e + y_start: .byte $a, $a, $a, $14 + x_cur: .fill 8, 0 + y_cur: .fill 8, 0 + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp b2 +Removing instruction jmp bend +Removing instruction jmp b1 +Removing instruction jmp b3 +Removing instruction jmp breturn +Removing instruction jmp breturn +Succesful ASM optimization Pass5NextJumpElimination +Replacing label b1_from_b3 with b1 +Removing instruction bbegin: +Removing instruction b2_from_bbegin: +Removing instruction main_from_b2: +Removing instruction bend_from_b2: +Removing instruction b1_from_b3: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction b2: +Removing instruction bend: +Removing instruction b1_from_main: +Removing instruction b3: +Removing instruction breturn: +Removing instruction breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Removing instruction jmp b1 +Succesful ASM optimization Pass5NextJumpElimination + +FINAL SYMBOL TABLE +(label) @2 +(label) @begin +(label) @end +(void()) init((byte) init::point_idx) +(word~) init::$0 $0 zp ZP_WORD:2 4.0 +(byte~) init::$1 reg byte a 4.0 +(word~) init::$2 $2 zp ZP_WORD:2 4.0 +(word~) init::$3 $3 zp ZP_WORD:2 4.0 +(label) init::@return +(byte) init::point_idx +(byte) init::point_idx#0 reg byte x 3.166666666666667 +(void()) main() +(label) main::@1 +(label) main::@3 +(label) main::@return +(byte) main::i +(byte) main::i#1 reg byte x 16.5 +(byte) main::i#2 reg byte x 11.0 +(word[4]) x_cur +(const word[4]) x_cur#0 x_cur = { fill( 4, 0) } +(word[4]) x_start +(const word[4]) x_start#0 x_start = { (byte/signed byte/word/signed word/dword/signed dword) 10, (byte/signed byte/word/signed word/dword/signed dword) 20, (byte/signed byte/word/signed word/dword/signed dword) 30, (byte/signed byte/word/signed word/dword/signed dword) 30 } +(word[4]) y_cur +(const word[4]) y_cur#0 y_cur = { fill( 4, 0) } +(byte[4]) y_start +(const byte[4]) y_start#0 y_start = { (byte/signed byte/word/signed word/dword/signed dword) 10, (byte/signed byte/word/signed word/dword/signed dword) 10, (byte/signed byte/word/signed word/dword/signed dword) 10, (byte/signed byte/word/signed word/dword/signed dword) 20 } + +reg byte x [ main::i#2 main::i#1 ] +reg byte x [ init::point_idx#0 ] +zp ZP_WORD:2 [ init::$0 init::$2 init::$3 ] +reg byte a [ init::$1 ] + + +FINAL ASSEMBLER +Score: 328 + +//SEG0 Basic Upstart +.pc = $801 "Basic" +:BasicUpstart(main) +.pc = $80d "Program" +//SEG1 Global Constants & labels +//SEG2 @begin +//SEG3 [1] phi from @begin to @2 [phi:@begin->@2] +//SEG4 @2 +//SEG5 [2] call main [ ] ( ) +//SEG6 [4] phi from @2 to main [phi:@2->main] + jsr main +//SEG7 [3] phi from @2 to @end [phi:@2->@end] +//SEG8 @end +//SEG9 main +main: { + //SEG10 [5] phi from main to main::@1 [phi:main->main::@1] + //SEG11 [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 from main::@3 to main::@1 [phi:main::@3->main::@1] + //SEG13 [5] phi (byte) main::i#2 = (byte) main::i#1 [phi:main::@3->main::@1#0] -- register_copy + //SEG14 main::@1 + b1: + //SEG15 [6] (byte) init::point_idx#0 ← (byte) main::i#2 [ main::i#2 init::point_idx#0 ] ( main:2 [ main::i#2 init::point_idx#0 ] ) + // (byte) init::point_idx#0 = (byte) main::i#2 // register copy reg byte x + //SEG16 [7] call init [ main::i#2 ] ( main:2 [ main::i#2 ] ) + jsr init + //SEG17 main::@3 + //SEG18 [8] (byte) main::i#1 ← (byte) main::i#2 + (byte/signed byte/word/signed word/dword/signed dword) 2 [ main::i#1 ] ( main:2 [ main::i#1 ] ) -- vbuxx=vbuxx_plus_2 + inx + inx + //SEG19 [9] if((byte) main::i#1!=(byte/signed byte/word/signed word/dword/signed dword) 8) goto main::@1 [ main::i#1 ] ( main:2 [ main::i#1 ] ) -- vbuxx_neq_vbuc1_then_la1 + cpx #8 + bne b1 + //SEG20 main::@return + //SEG21 [10] return [ ] ( main:2 [ ] ) + rts +} +//SEG22 init +init: { + .label _0 = 2 + .label _2 = 2 + .label _3 = 2 + //SEG23 [11] (word~) init::$0 ← *((const word[4]) x_start#0 + (byte) init::point_idx#0) << (byte/signed byte/word/signed word/dword/signed dword) 4 [ init::point_idx#0 init::$0 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$0 ] ) -- vwuz1=pwuc1_derefidx_vbuxx_rol_4 + lda x_start,x + sta _0 + lda x_start+1,x + sta _0+1 + asl _0 + rol _0+1 + asl _0 + rol _0+1 + asl _0 + rol _0+1 + asl _0 + rol _0+1 + //SEG24 [12] *((const word[4]) x_cur#0 + (byte) init::point_idx#0) ← (word~) init::$0 [ init::point_idx#0 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 ] ) -- pwuc1_derefidx_vbuxx=vwuz1 + lda _0 + sta x_cur,x + lda _0+1 + sta x_cur+1,x + //SEG25 [13] (byte~) init::$1 ← (byte) init::point_idx#0 >> (byte/signed byte/word/signed word/dword/signed dword) 1 [ init::point_idx#0 init::$1 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$1 ] ) -- vbuaa=vbuxx_ror_1 + txa + lsr + //SEG26 [14] (word~) init::$2 ← ((word)) *((const byte[4]) y_start#0 + (byte~) init::$1) [ init::point_idx#0 init::$2 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$2 ] ) -- vwuz1=_word_pbuc1_derefidx_vbuaa + tay + lda y_start,y + sta _2 + lda #0 + sta _2+1 + //SEG27 [15] (word~) init::$3 ← (word~) init::$2 << (byte/signed byte/word/signed word/dword/signed dword) 4 [ init::point_idx#0 init::$3 ] ( main:2::init:7 [ main::i#2 init::point_idx#0 init::$3 ] ) -- vwuz1=vwuz1_rol_4 + asl _3 + rol _3+1 + asl _3 + rol _3+1 + asl _3 + rol _3+1 + asl _3 + rol _3+1 + //SEG28 [16] *((const word[4]) y_cur#0 + (byte) init::point_idx#0) ← (word~) init::$3 [ ] ( main:2::init:7 [ main::i#2 ] ) -- pwuc1_derefidx_vbuxx=vwuz1 + lda _3 + sta y_cur,x + lda _3+1 + sta y_cur+1,x + //SEG29 init::@return + //SEG30 [17] return [ ] ( main:2::init:7 [ main::i#2 ] ) + rts +} + x_start: .word $a, $14, $1e, $1e + y_start: .byte $a, $a, $a, $14 + x_cur: .fill 8, 0 + y_cur: .fill 8, 0 + diff --git a/src/test/java/dk/camelot64/kickc/test/ref/line-anim.sym b/src/test/java/dk/camelot64/kickc/test/ref/line-anim.sym new file mode 100644 index 000000000..ad0da12a5 --- /dev/null +++ b/src/test/java/dk/camelot64/kickc/test/ref/line-anim.sym @@ -0,0 +1,31 @@ +(label) @2 +(label) @begin +(label) @end +(void()) init((byte) init::point_idx) +(word~) init::$0 $0 zp ZP_WORD:2 4.0 +(byte~) init::$1 reg byte a 4.0 +(word~) init::$2 $2 zp ZP_WORD:2 4.0 +(word~) init::$3 $3 zp ZP_WORD:2 4.0 +(label) init::@return +(byte) init::point_idx +(byte) init::point_idx#0 reg byte x 3.166666666666667 +(void()) main() +(label) main::@1 +(label) main::@3 +(label) main::@return +(byte) main::i +(byte) main::i#1 reg byte x 16.5 +(byte) main::i#2 reg byte x 11.0 +(word[4]) x_cur +(const word[4]) x_cur#0 x_cur = { fill( 4, 0) } +(word[4]) x_start +(const word[4]) x_start#0 x_start = { (byte/signed byte/word/signed word/dword/signed dword) 10, (byte/signed byte/word/signed word/dword/signed dword) 20, (byte/signed byte/word/signed word/dword/signed dword) 30, (byte/signed byte/word/signed word/dword/signed dword) 30 } +(word[4]) y_cur +(const word[4]) y_cur#0 y_cur = { fill( 4, 0) } +(byte[4]) y_start +(const byte[4]) y_start#0 y_start = { (byte/signed byte/word/signed word/dword/signed dword) 10, (byte/signed byte/word/signed word/dword/signed dword) 10, (byte/signed byte/word/signed word/dword/signed dword) 10, (byte/signed byte/word/signed word/dword/signed dword) 20 } + +reg byte x [ main::i#2 main::i#1 ] +reg byte x [ init::point_idx#0 ] +zp ZP_WORD:2 [ init::$0 init::$2 init::$3 ] +reg byte a [ init::$1 ]