diff --git a/src/test/java/dk/camelot64/kickc/test/TestProgramsFast.java b/src/test/java/dk/camelot64/kickc/test/TestProgramsFast.java index a9aabb89f..1e1da9720 100644 --- a/src/test/java/dk/camelot64/kickc/test/TestProgramsFast.java +++ b/src/test/java/dk/camelot64/kickc/test/TestProgramsFast.java @@ -1496,68 +1496,63 @@ public class TestProgramsFast extends TestPrograms { } @Test - public void testProcedureCallingConventionPhiFarx() throws IOException { - compileAndCompare("procedure-callingconvention-phi-far-x.c"); + public void testProcedureCallingConventionPhiBank0() throws IOException { + compileAndCompare("procedure-callingconvention-phi-bank-0.c"); } @Test - public void testProcedureCallingConventionPhiFar0() throws IOException { - compileAndCompare("procedure-callingconvention-phi-far-0.c"); + public void testProcedureCallingConventionPhiBank1() throws IOException { + compileAndCompare("procedure-callingconvention-phi-bank-1.c"); } @Test - public void testProcedureCallingConventionPhiFar1() throws IOException { - compileAndCompare("procedure-callingconvention-phi-far-1.c"); + public void testProcedureCallingConventionPhiBank2() throws IOException { + compileAndCompare("procedure-callingconvention-phi-bank-2.c"); } @Test - public void testProcedureCallingConventionPhiFar2() throws IOException { - compileAndCompare("procedure-callingconvention-phi-far-2.c"); + public void testProcedureCallingConventionPhiBank3() throws IOException { + compileAndCompare("procedure-callingconvention-phi-bank-3.c"); } @Test - public void testProcedureCallingConventionPhiFar3() throws IOException { - compileAndCompare("procedure-callingconvention-phi-far-3.c"); + public void testProcedureCallingConventionPhiBank4() throws IOException { + compileAndCompare("procedure-callingconvention-phi-bank-4.c"); } @Test - public void testProcedureCallingConventionPhiFar4() throws IOException { - compileAndCompare("procedure-callingconvention-phi-far-4.c"); + public void testProcedureCallingConventionPhiBank5() throws IOException { + compileAndCompare("procedure-callingconvention-phi-bank-5.c"); } @Test - public void testProcedureCallingConventionPhiFar5() throws IOException { - compileAndCompare("procedure-callingconvention-phi-far-5.c"); + public void testProcedureCallingConventionStackBank5() throws IOException { + compileAndCompare("procedure-callingconvention-stack-bank-5.c"); } @Test - public void testProcedureCallingConventionStackFar5() throws IOException { - compileAndCompare("procedure-callingconvention-stack-far-5.c"); + public void testProcedureCallingConventionStackBank4() throws IOException { + compileAndCompare("procedure-callingconvention-stack-bank-4.c"); } @Test - public void testProcedureCallingConventionStackFar4() throws IOException { - compileAndCompare("procedure-callingconvention-stack-far-4.c"); + public void testProcedureCallingConventionStackBank3() throws IOException { + compileAndCompare("procedure-callingconvention-stack-bank-3.c"); } @Test - public void testProcedureCallingConventionStackFar3() throws IOException { - compileAndCompare("procedure-callingconvention-stack-far-3.c"); + public void testProcedureCallingConventionStackBank2() throws IOException { + compileAndCompare("procedure-callingconvention-stack-bank-2.c"); } @Test - public void testProcedureCallingConventionStackFar2() throws IOException { - compileAndCompare("procedure-callingconvention-stack-far-2.c"); + public void testProcedureCallingConventionStackBank1() throws IOException { + compileAndCompare("procedure-callingconvention-stack-bank-1.c"); } @Test - public void testProcedureCallingConventionStackFar1() throws IOException { - compileAndCompare("procedure-callingconvention-stack-far-1.c"); - } - - @Test - public void testProcedureCallingConventionStackFar0() throws IOException { - compileAndCompare("procedure-callingconvention-stack-far-0.c"); + public void testProcedureCallingConventionStackBank0() throws IOException { + compileAndCompare("procedure-callingconvention-stack-bank-0.c"); } @Test diff --git a/src/test/kc/procedure-callingconvention-phi-bank-0.c b/src/test/kc/procedure-callingconvention-phi-bank-0.c index 54243fc55..2ab91f28b 100644 --- a/src/test/kc/procedure-callingconvention-phi-bank-0.c +++ b/src/test/kc/procedure-callingconvention-phi-bank-0.c @@ -1,12 +1,15 @@ // Test a procedure with calling convention stack +#pragma code_seg(stage) +#pragma link("procedure-callingconvention-phi-bank.ld") +#pragma target(cx16) + char* const SCREEN = (char*)0x0400; void main(void) { SCREEN[0] = plus('0', 7); } -#pragma code_seg(stage) char __bank(ram,2) plus(char a, char b) { return a+b; } diff --git a/src/test/kc/procedure-callingconvention-phi-bank-1.c b/src/test/kc/procedure-callingconvention-phi-bank-1.c index 585ab0f82..f534c13e7 100644 --- a/src/test/kc/procedure-callingconvention-phi-bank-1.c +++ b/src/test/kc/procedure-callingconvention-phi-bank-1.c @@ -1,5 +1,9 @@ // Test a far call procedure with a calling convention sp +#pragma code_seg(stage) +#pragma link("procedure-callingconvention-phi-bank.ld") +#pragma target(cx16) + char* const SCREEN = (char*)0x0400; void main(void) { diff --git a/src/test/kc/procedure-callingconvention-phi-bank-2.c b/src/test/kc/procedure-callingconvention-phi-bank-2.c index e56b218aa..790978c7d 100644 --- a/src/test/kc/procedure-callingconvention-phi-bank-2.c +++ b/src/test/kc/procedure-callingconvention-phi-bank-2.c @@ -1,5 +1,9 @@ // Test a far call procedure with a calling convention sp +#pragma code_seg(stage) +#pragma link("procedure-callingconvention-phi-bank.ld") +#pragma target(cx16) + char* const SCREEN = (char*)0x0400; void main(void) { diff --git a/src/test/kc/procedure-callingconvention-phi-bank-3.c b/src/test/kc/procedure-callingconvention-phi-bank-3.c index 655f28876..fc48b2e5e 100644 --- a/src/test/kc/procedure-callingconvention-phi-bank-3.c +++ b/src/test/kc/procedure-callingconvention-phi-bank-3.c @@ -1,5 +1,9 @@ // Test a far call procedure with a calling convention sp +#pragma code_seg(stage) +#pragma link("procedure-callingconvention-phi-bank.ld") +#pragma target(cx16) + char* const SCREEN = (char*)0x0400; void main(void) { diff --git a/src/test/kc/procedure-callingconvention-phi-bank-4.c b/src/test/kc/procedure-callingconvention-phi-bank-4.c index 0459fcaa0..b6e49a3a1 100644 --- a/src/test/kc/procedure-callingconvention-phi-bank-4.c +++ b/src/test/kc/procedure-callingconvention-phi-bank-4.c @@ -1,5 +1,9 @@ // Test a far call procedure with a calling convention phi +#pragma code_seg(stage) +#pragma link("procedure-callingconvention-phi-bank.ld") +#pragma target(cx16) + char* const SCREEN = (char*)0x0400; #pragma code_seg(stage) diff --git a/src/test/kc/procedure-callingconvention-phi-bank-5.c b/src/test/kc/procedure-callingconvention-phi-bank-5.c index 9e8021010..c8b8aa399 100644 --- a/src/test/kc/procedure-callingconvention-phi-bank-5.c +++ b/src/test/kc/procedure-callingconvention-phi-bank-5.c @@ -1,8 +1,12 @@ // Test a far call procedure with a calling convention phi +#pragma code_seg(stage) +#pragma link("procedure-callingconvention-phi-bank.ld") +#pragma target(cx16) + char* const SCREEN = (char*)0x0400; -#pragma code_seg(bank_1) +#pragma code_seg(stage) #pragma bank(ram, 1) char func_bank1_a(char a, char b) { @@ -19,7 +23,7 @@ char func_bank1_d(char a, char b) { return func_bank2_a(a,b); } -#pragma code_seg(bank_2) +#pragma code_seg(platform) #pragma bank(ram, 2) char func_bank2_a(char a, char b) { @@ -47,7 +51,7 @@ char func_bank2_f(char a, char b) { return func_bank1_b(a,b); } -#pragma nobank +#pragma nobank(dummy) char __bank(ram, 1) func_bank1_b(char a, char b) { return a+b; @@ -57,7 +61,7 @@ char __bank(ram, 2) func_bank2_b(char a, char b) { return a+b; } -#pragma nobank +#pragma nobank(dummy) char func_bank1_e(char a, char b) { // this should be a far call, because the call is to bank 1. diff --git a/src/test/kc/procedure-callingconvention-phi-bank.ld b/src/test/kc/procedure-callingconvention-phi-bank.ld new file mode 100644 index 000000000..130604424 --- /dev/null +++ b/src/test/kc/procedure-callingconvention-phi-bank.ld @@ -0,0 +1,7 @@ +.segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=%P] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + diff --git a/src/test/kc/procedure-callingconvention-stack-bank-0.c b/src/test/kc/procedure-callingconvention-stack-bank-0.c index 3801b0673..d0394b9d1 100644 --- a/src/test/kc/procedure-callingconvention-stack-bank-0.c +++ b/src/test/kc/procedure-callingconvention-stack-bank-0.c @@ -1,12 +1,16 @@ // Test a procedure with calling convention stack +#pragma code_seg(stage) +#pragma link("procedure-callingconvention-stack-bank.ld") +#pragma target(cx16) + char* const SCREEN = (char*)0x0400; void main(void) { SCREEN[0] = plus('0', 7); } -#pragma code_seg(test) +#pragma code_seg(stage) char __bank(ram, 2) __stackcall plus(char a, char b) { return a+b; } \ No newline at end of file diff --git a/src/test/kc/procedure-callingconvention-stack-bank-1.c b/src/test/kc/procedure-callingconvention-stack-bank-1.c index da246a882..c1ac83207 100644 --- a/src/test/kc/procedure-callingconvention-stack-bank-1.c +++ b/src/test/kc/procedure-callingconvention-stack-bank-1.c @@ -1,5 +1,9 @@ // Test a procedure with calling convention stack +#pragma code_seg(stage) +#pragma link("procedure-callingconvention-stack-bank.ld") +#pragma target(cx16) + char* const SCREEN = (char*)0x0400; void main(void) { @@ -7,7 +11,7 @@ void main(void) { } #pragma calling(__stackcall) -#pragma code_seg(test) +#pragma code_seg(stage) char __bank(ram,20) plus(char a, char b) { return a+b; diff --git a/src/test/kc/procedure-callingconvention-stack-bank-2.c b/src/test/kc/procedure-callingconvention-stack-bank-2.c index cb8a3bc86..cba3de4b9 100644 --- a/src/test/kc/procedure-callingconvention-stack-bank-2.c +++ b/src/test/kc/procedure-callingconvention-stack-bank-2.c @@ -1,6 +1,10 @@ // Test a procedure with calling convention stack // A slightly more complex call +#pragma code_seg(stage) +#pragma link("procedure-callingconvention-stack-bank.ld") +#pragma target(cx16) + char* const SCREEN = (char*)0x0400; char i = 0; diff --git a/src/test/kc/procedure-callingconvention-stack-bank-3.c b/src/test/kc/procedure-callingconvention-stack-bank-3.c index 6ab8d136f..129824bb7 100644 --- a/src/test/kc/procedure-callingconvention-stack-bank-3.c +++ b/src/test/kc/procedure-callingconvention-stack-bank-3.c @@ -3,6 +3,10 @@ #pragma calling(__stackcall) +#pragma code_seg(stage) +#pragma link("procedure-callingconvention-stack-bank.ld") +#pragma target(cx16) + char* const SCREEN = (char*)0x0400; char val = 0; diff --git a/src/test/kc/procedure-callingconvention-stack-bank-4.c b/src/test/kc/procedure-callingconvention-stack-bank-4.c index 76c66aa26..bb3ebc6e8 100644 --- a/src/test/kc/procedure-callingconvention-stack-bank-4.c +++ b/src/test/kc/procedure-callingconvention-stack-bank-4.c @@ -4,6 +4,10 @@ #pragma calling(__stackcall) #pragma struct_model(classic) +#pragma code_seg(stage) +#pragma link("procedure-callingconvention-stack-bank.ld") +#pragma target(cx16) + char* const SCREEN = (char*)0x0400; char idx = 0; diff --git a/src/test/kc/procedure-callingconvention-stack-bank-5.c b/src/test/kc/procedure-callingconvention-stack-bank-5.c index 3bfac0ef3..ce0701c6f 100644 --- a/src/test/kc/procedure-callingconvention-stack-bank-5.c +++ b/src/test/kc/procedure-callingconvention-stack-bank-5.c @@ -1,6 +1,10 @@ // Test a procedure with calling convention stack // Recursion that works (no local variables) +#pragma code_seg(stage) +#pragma link("procedure-callingconvention-stack-bank.ld") +#pragma platform(cx16) + char* const SCREEN = (char*)0x0400; void main(void) { diff --git a/src/test/kc/procedure-callingconvention-stack-bank.ld b/src/test/kc/procedure-callingconvention-stack-bank.ld new file mode 100644 index 000000000..3e9cecaee --- /dev/null +++ b/src/test/kc/procedure-callingconvention-stack-bank.ld @@ -0,0 +1,6 @@ +.segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=%P] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] diff --git a/src/test/ref/asm-culling-jmp.asm b/src/test/ref/asm-culling-jmp.asm index 39c886fa8..152a669fe 100644 --- a/src/test/ref/asm-culling-jmp.asm +++ b/src/test/ref/asm-culling-jmp.asm @@ -12,7 +12,7 @@ main: { // asm jmp qwe - .byte 0, 25, 51, 76, 102, 128, 153, 179, 204, 230 + .byte 0, $19, $33, $4c, $66, $80, $99, $b3, $cc, $e6 qwe: lda #$32 // *((char*)0x0400) = 'c' diff --git a/src/test/ref/asm-culling-jmp.log b/src/test/ref/asm-culling-jmp.log index 8f295f1ae..9870ae91e 100644 --- a/src/test/ref/asm-culling-jmp.log +++ b/src/test/ref/asm-culling-jmp.log @@ -83,7 +83,7 @@ ASSEMBLER BEFORE OPTIMIZATION main: { // asm { jmpqwe .byte0,25,51,76,102,128,153,179,204,230 qwe: lda#50 } jmp qwe - .byte 0, 25, 51, 76, 102, 128, 153, 179, 204, 230 + .byte 0, $19, $33, $4c, $66, $80, $99, $b3, $cc, $e6 qwe: lda #$32 // [1] *((char *) 1024) = 'c' -- _deref_pbuc1=vbuc2 @@ -130,7 +130,7 @@ main: { // asm // asm { jmpqwe .byte0,25,51,76,102,128,153,179,204,230 qwe: lda#50 } jmp qwe - .byte 0, 25, 51, 76, 102, 128, 153, 179, 204, 230 + .byte 0, $19, $33, $4c, $66, $80, $99, $b3, $cc, $e6 qwe: lda #$32 // *((char*)0x0400) = 'c' diff --git a/src/test/ref/c64dtv-8bppcharstretch.asm b/src/test/ref/c64dtv-8bppcharstretch.asm index 13c88352a..8fadfc7eb 100644 --- a/src/test/ref/c64dtv-8bppcharstretch.asm +++ b/src/test/ref/c64dtv-8bppcharstretch.asm @@ -457,7 +457,7 @@ dtvSetCpuBankSegment1: { // asm .byte $32, $dd lda.z $ff - .byte $32, $00 + .byte $32, 0 // } rts } diff --git a/src/test/ref/c64dtv-8bppcharstretch.log b/src/test/ref/c64dtv-8bppcharstretch.log index 4c5a4bc2e..9e674183c 100644 --- a/src/test/ref/c64dtv-8bppcharstretch.log +++ b/src/test/ref/c64dtv-8bppcharstretch.log @@ -1872,7 +1872,7 @@ dtvSetCpuBankSegment1: { // asm { .byte$32,$dd lda$ff .byte$32,$00 } .byte $32, $dd lda.z $ff - .byte $32, $00 + .byte $32, 0 jmp __breturn // dtvSetCpuBankSegment1::@return __breturn: @@ -2714,7 +2714,7 @@ dtvSetCpuBankSegment1: { // asm { .byte$32,$dd lda$ff .byte$32,$00 } .byte $32, $dd lda.z $ff - .byte $32, $00 + .byte $32, 0 // dtvSetCpuBankSegment1::@return // } // [87] return diff --git a/src/test/ref/c64dtv-8bppchunkystretch.asm b/src/test/ref/c64dtv-8bppchunkystretch.asm index 7ebe19652..becb0cb59 100644 --- a/src/test/ref/c64dtv-8bppchunkystretch.asm +++ b/src/test/ref/c64dtv-8bppchunkystretch.asm @@ -365,7 +365,7 @@ dtvSetCpuBankSegment1: { // asm .byte $32, $dd lda.z $ff - .byte $32, $00 + .byte $32, 0 // } rts } diff --git a/src/test/ref/c64dtv-8bppchunkystretch.log b/src/test/ref/c64dtv-8bppchunkystretch.log index cc100204f..932a1908c 100644 --- a/src/test/ref/c64dtv-8bppchunkystretch.log +++ b/src/test/ref/c64dtv-8bppchunkystretch.log @@ -1260,7 +1260,7 @@ dtvSetCpuBankSegment1: { // asm { .byte$32,$dd lda$ff .byte$32,$00 } .byte $32, $dd lda.z $ff - .byte $32, $00 + .byte $32, 0 jmp __breturn // dtvSetCpuBankSegment1::@return __breturn: @@ -1881,7 +1881,7 @@ dtvSetCpuBankSegment1: { // asm { .byte$32,$dd lda$ff .byte$32,$00 } .byte $32, $dd lda.z $ff - .byte $32, $00 + .byte $32, 0 // dtvSetCpuBankSegment1::@return // } // [57] return diff --git a/src/test/ref/procedure-callingconvention-phi-bank-0.asm b/src/test/ref/procedure-callingconvention-phi-bank-0.asm new file mode 100644 index 000000000..2bb668af6 --- /dev/null +++ b/src/test/ref/procedure-callingconvention-phi-bank-0.asm @@ -0,0 +1,28 @@ +// Test a procedure with calling convention stack +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + + .label SCREEN = $400 +.segment stage +main: { + // plus('0', 7) + jsr plus + // SCREEN[0] = plus('0', 7) + lda #plus.return + sta SCREEN + // } + rts +} +// char plus(char a, char b) +plus: { + .const a = '0' + .const b = 7 + .label return = a+b + rts +} diff --git a/src/test/ref/procedure-callingconvention-phi-bank-0.cfg b/src/test/ref/procedure-callingconvention-phi-bank-0.cfg new file mode 100644 index 000000000..bfaa7082a --- /dev/null +++ b/src/test/ref/procedure-callingconvention-phi-bank-0.cfg @@ -0,0 +1,20 @@ + +void main() +main: scope:[main] from + [0] phi() + [1] call plus + to:main::@1 +main::@1: scope:[main] from main + [2] *SCREEN = plus::return#1 + to:main::@return +main::@return: scope:[main] from main::@1 + [3] return + to:@return + +char plus(char a , char b) +plus: scope:[plus] from main + [4] phi() + to:plus::@return +plus::@return: scope:[plus] from plus + [5] return + to:@return diff --git a/src/test/ref/procedure-callingconvention-phi-bank-0.log b/src/test/ref/procedure-callingconvention-phi-bank-0.log new file mode 100644 index 000000000..58a2a2fd0 --- /dev/null +++ b/src/test/ref/procedure-callingconvention-phi-bank-0.log @@ -0,0 +1,275 @@ +Loading link script "procedure-callingconvention-phi-bank.ld" + +CONTROL FLOW GRAPH SSA + +void main() +main: scope:[main] from __start + plus::a#0 = '0' + plus::b#0 = 7 + call plus + plus::return#0 = plus::return#2 + to:main::@1 +main::@1: scope:[main] from main + plus::return#3 = phi( main/plus::return#0 ) + main::$0 = plus::return#3 + SCREEN[0] = main::$0 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return + +char plus(char a , char b) +plus: scope:[plus] from main + plus::b#1 = phi( main/plus::b#0 ) + plus::a#1 = phi( main/plus::a#0 ) + plus::$0 = plus::a#1 + plus::b#1 + plus::return#1 = plus::$0 + to:plus::@return +plus::@return: scope:[plus] from plus + plus::return#4 = phi( plus/plus::return#1 ) + plus::return#2 = plus::return#4 + return + to:@return + +void __start() +__start: scope:[__start] from + call main + to:__start::@1 +__start::@1: scope:[__start] from __start + to:__start::@return +__start::@return: scope:[__start] from __start::@1 + return + to:@return + +SYMBOL TABLE SSA +__constant char * const SCREEN = (char *)$400 +void __start() +void main() +char main::$0 +char plus(char a , char b) +char plus::$0 +char plus::a +char plus::a#0 +char plus::a#1 +char plus::b +char plus::b#0 +char plus::b#1 +char plus::return +char plus::return#0 +char plus::return#1 +char plus::return#2 +char plus::return#3 +char plus::return#4 + +Adding number conversion cast (unumber) 7 in plus::b#0 = 7 +Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$0 +Successful SSA optimization PassNAddNumberTypeConversions +Inlining cast plus::b#0 = (unumber)7 +Successful SSA optimization Pass2InlineCast +Simplifying constant pointer cast (char *) 1024 +Simplifying constant integer cast 7 +Simplifying constant integer cast 0 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (char) 7 +Finalized unsigned number type (char) 0 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Alias plus::return#0 = plus::return#3 +Alias plus::return#1 = plus::$0 plus::return#4 plus::return#2 +Successful SSA optimization Pass2AliasElimination +Identical Phi Values plus::a#1 plus::a#0 +Identical Phi Values plus::b#1 plus::b#0 +Successful SSA optimization Pass2IdenticalPhiElimination +Constant plus::a#0 = '0' +Constant plus::b#0 = 7 +Successful SSA optimization Pass2ConstantIdentification +Simplifying expression containing zero SCREEN in [5] SCREEN[0] = main::$0 +Successful SSA optimization PassNSimplifyExpressionWithZero +Removing unused procedure __start +Removing unused procedure block __start +Removing unused procedure block __start::@1 +Removing unused procedure block __start::@return +Successful SSA optimization PassNEliminateEmptyStart +Constant right-side identified [5] plus::return#1 = plus::a#0 + plus::b#0 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant plus::return#1 = plus::a#0+plus::b#0 +Successful SSA optimization Pass2ConstantIdentification +Constant plus::return#0 = plus::return#1 +Successful SSA optimization Pass2ConstantIdentification +Constant main::$0 = plus::return#0 +Successful SSA optimization Pass2ConstantIdentification +Inlining constant with different constant siblings plus::return#0 +Constant inlined plus::return#0 = plus::return#1 +Constant inlined main::$0 = plus::return#1 +Successful SSA optimization Pass2ConstantInlining +Adding NOP phi() at start of main +Adding NOP phi() at start of plus +CALL GRAPH +Calls in [main] to plus:1 + +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes +Adding NOP phi() at start of main +Adding NOP phi() at start of plus + +FINAL CONTROL FLOW GRAPH + +void main() +main: scope:[main] from + [0] phi() + [1] call plus + to:main::@1 +main::@1: scope:[main] from main + [2] *SCREEN = plus::return#1 + to:main::@return +main::@return: scope:[main] from main::@1 + [3] return + to:@return + +char plus(char a , char b) +plus: scope:[plus] from main + [4] phi() + to:plus::@return +plus::@return: scope:[plus] from plus + [5] return + to:@return + + +VARIABLE REGISTER WEIGHTS +void main() +char plus(char a , char b) +char plus::a +char plus::b +char plus::return + +Initial phi equivalence classes +Complete equivalence classes +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [2] *SCREEN = plus::return#1 [ ] ( [ ] { } ) always clobbers reg byte a + +REGISTER UPLIFT SCOPES +Uplift Scope [main] +Uplift Scope [plus] +Uplift Scope [] + +Uplifting [main] best 60 combination +Uplifting [plus] best 60 combination +Uplifting [] best 60 combination + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Test a procedure with calling convention stack + // Upstart +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + + // Global Constants & labels + .label SCREEN = $400 +.segment stage + // main +main: { + // [1] call plus + // [4] phi from main to plus [phi:main->plus] + plus_from_main: + jsr plus + jmp __b1 + // main::@1 + __b1: + // [2] *SCREEN = plus::return#1 -- _deref_pbuc1=vbuc2 + lda #plus.return + sta SCREEN + jmp __breturn + // main::@return + __breturn: + // [3] return + rts +} + // plus +// char plus(char a, char b) +plus: { + .const a = '0' + .const b = 7 + .label return = a+b + jmp __breturn + // plus::@return + __breturn: + // [5] return + rts +} + // File Data + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction plus_from_main: +Removing instruction __b1: +Removing instruction __breturn: +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +__constant char * const SCREEN = (char *) 1024 +void main() +char plus(char a , char b) +char plus::a +__constant char plus::a#0 = '0' // a +char plus::b +__constant char plus::b#0 = 7 // b +char plus::return +__constant char plus::return#1 = plus::a#0+plus::b#0 // return + + + +FINAL ASSEMBLER +Score: 24 + + // File Comments +// Test a procedure with calling convention stack + // Upstart +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + + // Global Constants & labels + .label SCREEN = $400 +.segment stage + // main +main: { + // plus('0', 7) + // [1] call plus + // [4] phi from main to plus [phi:main->plus] + jsr plus + // main::@1 + // SCREEN[0] = plus('0', 7) + // [2] *SCREEN = plus::return#1 -- _deref_pbuc1=vbuc2 + lda #plus.return + sta SCREEN + // main::@return + // } + // [3] return + rts +} + // plus +// char plus(char a, char b) +plus: { + .const a = '0' + .const b = 7 + .label return = a+b + // plus::@return + // [5] return + rts +} + // File Data + diff --git a/src/test/ref/procedure-callingconvention-phi-bank-0.sym b/src/test/ref/procedure-callingconvention-phi-bank-0.sym new file mode 100644 index 000000000..70d3c4d1f --- /dev/null +++ b/src/test/ref/procedure-callingconvention-phi-bank-0.sym @@ -0,0 +1,10 @@ +__constant char * const SCREEN = (char *) 1024 +void main() +char plus(char a , char b) +char plus::a +__constant char plus::a#0 = '0' // a +char plus::b +__constant char plus::b#0 = 7 // b +char plus::return +__constant char plus::return#1 = plus::a#0+plus::b#0 // return + diff --git a/src/test/ref/procedure-callingconvention-phi-bank-1.asm b/src/test/ref/procedure-callingconvention-phi-bank-1.asm new file mode 100644 index 000000000..ea53aa852 --- /dev/null +++ b/src/test/ref/procedure-callingconvention-phi-bank-1.asm @@ -0,0 +1,31 @@ +// Test a far call procedure with a calling convention sp +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + + .label SCREEN = $400 +.segment stage +main: { + // plus('0', 7) + jsr $ff6e + .byte plus + .byte 1 + // SCREEN[0] = plus('0', 7) + lda #plus.return + sta SCREEN + // } + rts +} +// char plus(char a, char b) +plus: { + .const a = '0' + .const b = 7 + .label return = a+b + rts +} diff --git a/src/test/ref/procedure-callingconvention-phi-bank-1.cfg b/src/test/ref/procedure-callingconvention-phi-bank-1.cfg new file mode 100644 index 000000000..1701ea88d --- /dev/null +++ b/src/test/ref/procedure-callingconvention-phi-bank-1.cfg @@ -0,0 +1,20 @@ + +void main() +main: scope:[main] from + [0] phi() + [1] call plus + to:main::@1 +main::@1: scope:[main] from main + [2] *SCREEN = plus::return#1 + to:main::@return +main::@return: scope:[main] from main::@1 + [3] return + to:@return + +__bank(bank) char plus(char a , char b) +plus: scope:[plus] from main + [4] phi() + to:plus::@return +plus::@return: scope:[plus] from plus + [5] return + to:@return diff --git a/src/test/ref/procedure-callingconvention-phi-bank-1.log b/src/test/ref/procedure-callingconvention-phi-bank-1.log new file mode 100644 index 000000000..5484d90f9 --- /dev/null +++ b/src/test/ref/procedure-callingconvention-phi-bank-1.log @@ -0,0 +1,281 @@ +Loading link script "procedure-callingconvention-phi-bank.ld" + +CONTROL FLOW GRAPH SSA + +void main() +main: scope:[main] from __start + plus::a#0 = '0' + plus::b#0 = 7 + call plus + plus::return#0 = plus::return#2 + to:main::@1 +main::@1: scope:[main] from main + plus::return#3 = phi( main/plus::return#0 ) + main::$0 = plus::return#3 + SCREEN[0] = main::$0 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return + +__bank(bank) char plus(char a , char b) +plus: scope:[plus] from main + plus::b#1 = phi( main/plus::b#0 ) + plus::a#1 = phi( main/plus::a#0 ) + plus::$0 = plus::a#1 + plus::b#1 + plus::return#1 = plus::$0 + to:plus::@return +plus::@return: scope:[plus] from plus + plus::return#4 = phi( plus/plus::return#1 ) + plus::return#2 = plus::return#4 + return + to:@return + +void __start() +__start: scope:[__start] from + call main + to:__start::@1 +__start::@1: scope:[__start] from __start + to:__start::@return +__start::@return: scope:[__start] from __start::@1 + return + to:@return + +SYMBOL TABLE SSA +__constant char * const SCREEN = (char *)$400 +void __start() +void main() +char main::$0 +__bank(bank) char plus(char a , char b) +char plus::$0 +char plus::a +char plus::a#0 +char plus::a#1 +char plus::b +char plus::b#0 +char plus::b#1 +char plus::return +char plus::return#0 +char plus::return#1 +char plus::return#2 +char plus::return#3 +char plus::return#4 + +Adding number conversion cast (unumber) 7 in plus::b#0 = 7 +Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$0 +Successful SSA optimization PassNAddNumberTypeConversions +Inlining cast plus::b#0 = (unumber)7 +Successful SSA optimization Pass2InlineCast +Simplifying constant pointer cast (char *) 1024 +Simplifying constant integer cast 7 +Simplifying constant integer cast 0 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (char) 7 +Finalized unsigned number type (char) 0 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Alias plus::return#0 = plus::return#3 +Alias plus::return#1 = plus::$0 plus::return#4 plus::return#2 +Successful SSA optimization Pass2AliasElimination +Identical Phi Values plus::a#1 plus::a#0 +Identical Phi Values plus::b#1 plus::b#0 +Successful SSA optimization Pass2IdenticalPhiElimination +Constant plus::a#0 = '0' +Constant plus::b#0 = 7 +Successful SSA optimization Pass2ConstantIdentification +Simplifying expression containing zero SCREEN in [5] SCREEN[0] = main::$0 +Successful SSA optimization PassNSimplifyExpressionWithZero +Removing unused procedure __start +Removing unused procedure block __start +Removing unused procedure block __start::@1 +Removing unused procedure block __start::@return +Successful SSA optimization PassNEliminateEmptyStart +Constant right-side identified [5] plus::return#1 = plus::a#0 + plus::b#0 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant plus::return#1 = plus::a#0+plus::b#0 +Successful SSA optimization Pass2ConstantIdentification +Constant plus::return#0 = plus::return#1 +Successful SSA optimization Pass2ConstantIdentification +Constant main::$0 = plus::return#0 +Successful SSA optimization Pass2ConstantIdentification +Inlining constant with different constant siblings plus::return#0 +Constant inlined plus::return#0 = plus::return#1 +Constant inlined main::$0 = plus::return#1 +Successful SSA optimization Pass2ConstantInlining +Adding NOP phi() at start of main +Adding NOP phi() at start of plus +CALL GRAPH +Calls in [main] to plus:1 + +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes +Adding NOP phi() at start of main +Adding NOP phi() at start of plus + +FINAL CONTROL FLOW GRAPH + +void main() +main: scope:[main] from + [0] phi() + [1] call plus + to:main::@1 +main::@1: scope:[main] from main + [2] *SCREEN = plus::return#1 + to:main::@return +main::@return: scope:[main] from main::@1 + [3] return + to:@return + +__bank(bank) char plus(char a , char b) +plus: scope:[plus] from main + [4] phi() + to:plus::@return +plus::@return: scope:[plus] from plus + [5] return + to:@return + + +VARIABLE REGISTER WEIGHTS +void main() +__bank(bank) char plus(char a , char b) +char plus::a +char plus::b +char plus::return + +Initial phi equivalence classes +Complete equivalence classes +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [2] *SCREEN = plus::return#1 [ ] ( [ ] { } ) always clobbers reg byte a + +REGISTER UPLIFT SCOPES +Uplift Scope [main] +Uplift Scope [plus] +Uplift Scope [] + +Uplifting [main] best 60 combination +Uplifting [plus] best 60 combination +Uplifting [] best 60 combination + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Test a far call procedure with a calling convention sp + // Upstart +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + + // Global Constants & labels + .label SCREEN = $400 +.segment stage + // main +main: { + // [1] call plus + // [4] phi from main to plus [phi:main->plus] -- call_far_cx16_ram_finalize + plus_from_main: + jsr $ff6e + .byte plus + .byte 1 + jmp __b1 + // main::@1 + __b1: + // [2] *SCREEN = plus::return#1 -- _deref_pbuc1=vbuc2 + lda #plus.return + sta SCREEN + jmp __breturn + // main::@return + __breturn: + // [3] return + rts +} + // plus +// char plus(char a, char b) +plus: { + .const a = '0' + .const b = 7 + .label return = a+b + jmp __breturn + // plus::@return + __breturn: + // [5] return + rts +} + // File Data + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction plus_from_main: +Removing instruction __b1: +Removing instruction __breturn: +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +__constant char * const SCREEN = (char *) 1024 +void main() +__bank(bank) char plus(char a , char b) +char plus::a +__constant char plus::a#0 = '0' // a +char plus::b +__constant char plus::b#0 = 7 // b +char plus::return +__constant char plus::return#1 = plus::a#0+plus::b#0 // return + + + +FINAL ASSEMBLER +Score: 24 + + // File Comments +// Test a far call procedure with a calling convention sp + // Upstart +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + + // Global Constants & labels + .label SCREEN = $400 +.segment stage + // main +main: { + // plus('0', 7) + // [1] call plus + // [4] phi from main to plus [phi:main->plus] -- call_far_cx16_ram_finalize + jsr $ff6e + .byte plus + .byte 1 + // main::@1 + // SCREEN[0] = plus('0', 7) + // [2] *SCREEN = plus::return#1 -- _deref_pbuc1=vbuc2 + lda #plus.return + sta SCREEN + // main::@return + // } + // [3] return + rts +} + // plus +// char plus(char a, char b) +plus: { + .const a = '0' + .const b = 7 + .label return = a+b + // plus::@return + // [5] return + rts +} + // File Data + diff --git a/src/test/ref/procedure-callingconvention-phi-bank-1.sym b/src/test/ref/procedure-callingconvention-phi-bank-1.sym new file mode 100644 index 000000000..c79872a57 --- /dev/null +++ b/src/test/ref/procedure-callingconvention-phi-bank-1.sym @@ -0,0 +1,10 @@ +__constant char * const SCREEN = (char *) 1024 +void main() +__bank(bank) char plus(char a , char b) +char plus::a +__constant char plus::a#0 = '0' // a +char plus::b +__constant char plus::b#0 = 7 // b +char plus::return +__constant char plus::return#1 = plus::a#0+plus::b#0 // return + diff --git a/src/test/ref/procedure-callingconvention-phi-bank-2.asm b/src/test/ref/procedure-callingconvention-phi-bank-2.asm new file mode 100644 index 000000000..1e4b59461 --- /dev/null +++ b/src/test/ref/procedure-callingconvention-phi-bank-2.asm @@ -0,0 +1,28 @@ +// Test a far call procedure with a calling convention sp +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + + .label SCREEN = $400 +.segment stage +main: { + // plus('0', 7) + .assert "Missing ASM fragment Fragment not found call_far_cx16_rubbish_prepare. Attempted variations call_far_cx16_rubbish_prepare ", 0, 1 + // SCREEN[0] = plus('0', 7) + lda #plus.return + sta SCREEN + // } + rts +} +// char plus(char a, char b) +plus: { + .const a = '0' + .const b = 7 + .label return = a+b + rts +} diff --git a/src/test/ref/procedure-callingconvention-phi-bank-2.cfg b/src/test/ref/procedure-callingconvention-phi-bank-2.cfg new file mode 100644 index 000000000..1701ea88d --- /dev/null +++ b/src/test/ref/procedure-callingconvention-phi-bank-2.cfg @@ -0,0 +1,20 @@ + +void main() +main: scope:[main] from + [0] phi() + [1] call plus + to:main::@1 +main::@1: scope:[main] from main + [2] *SCREEN = plus::return#1 + to:main::@return +main::@return: scope:[main] from main::@1 + [3] return + to:@return + +__bank(bank) char plus(char a , char b) +plus: scope:[plus] from main + [4] phi() + to:plus::@return +plus::@return: scope:[plus] from plus + [5] return + to:@return diff --git a/src/test/ref/procedure-callingconvention-phi-bank-2.log b/src/test/ref/procedure-callingconvention-phi-bank-2.log new file mode 100644 index 000000000..9b0d446f2 --- /dev/null +++ b/src/test/ref/procedure-callingconvention-phi-bank-2.log @@ -0,0 +1,294 @@ +Loading link script "procedure-callingconvention-phi-bank.ld" + +CONTROL FLOW GRAPH SSA + +void main() +main: scope:[main] from __start + plus::a#0 = '0' + plus::b#0 = 7 + call plus + plus::return#0 = plus::return#2 + to:main::@1 +main::@1: scope:[main] from main + plus::return#3 = phi( main/plus::return#0 ) + main::$0 = plus::return#3 + SCREEN[0] = main::$0 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return + +__bank(bank) char plus(char a , char b) +plus: scope:[plus] from main + plus::b#1 = phi( main/plus::b#0 ) + plus::a#1 = phi( main/plus::a#0 ) + plus::$0 = plus::a#1 + plus::b#1 + plus::return#1 = plus::$0 + to:plus::@return +plus::@return: scope:[plus] from plus + plus::return#4 = phi( plus/plus::return#1 ) + plus::return#2 = plus::return#4 + return + to:@return + +void __start() +__start: scope:[__start] from + call main + to:__start::@1 +__start::@1: scope:[__start] from __start + to:__start::@return +__start::@return: scope:[__start] from __start::@1 + return + to:@return + +SYMBOL TABLE SSA +__constant char * const SCREEN = (char *)$400 +void __start() +void main() +char main::$0 +__bank(bank) char plus(char a , char b) +char plus::$0 +char plus::a +char plus::a#0 +char plus::a#1 +char plus::b +char plus::b#0 +char plus::b#1 +char plus::return +char plus::return#0 +char plus::return#1 +char plus::return#2 +char plus::return#3 +char plus::return#4 + +Adding number conversion cast (unumber) 7 in plus::b#0 = 7 +Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$0 +Successful SSA optimization PassNAddNumberTypeConversions +Inlining cast plus::b#0 = (unumber)7 +Successful SSA optimization Pass2InlineCast +Simplifying constant pointer cast (char *) 1024 +Simplifying constant integer cast 7 +Simplifying constant integer cast 0 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (char) 7 +Finalized unsigned number type (char) 0 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Alias plus::return#0 = plus::return#3 +Alias plus::return#1 = plus::$0 plus::return#4 plus::return#2 +Successful SSA optimization Pass2AliasElimination +Identical Phi Values plus::a#1 plus::a#0 +Identical Phi Values plus::b#1 plus::b#0 +Successful SSA optimization Pass2IdenticalPhiElimination +Constant plus::a#0 = '0' +Constant plus::b#0 = 7 +Successful SSA optimization Pass2ConstantIdentification +Simplifying expression containing zero SCREEN in [5] SCREEN[0] = main::$0 +Successful SSA optimization PassNSimplifyExpressionWithZero +Removing unused procedure __start +Removing unused procedure block __start +Removing unused procedure block __start::@1 +Removing unused procedure block __start::@return +Successful SSA optimization PassNEliminateEmptyStart +Constant right-side identified [5] plus::return#1 = plus::a#0 + plus::b#0 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant plus::return#1 = plus::a#0+plus::b#0 +Successful SSA optimization Pass2ConstantIdentification +Constant plus::return#0 = plus::return#1 +Successful SSA optimization Pass2ConstantIdentification +Constant main::$0 = plus::return#0 +Successful SSA optimization Pass2ConstantIdentification +Inlining constant with different constant siblings plus::return#0 +Constant inlined plus::return#0 = plus::return#1 +Constant inlined main::$0 = plus::return#1 +Successful SSA optimization Pass2ConstantInlining +Adding NOP phi() at start of main +Adding NOP phi() at start of plus +CALL GRAPH +Calls in [main] to plus:1 + +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes +Adding NOP phi() at start of main +Adding NOP phi() at start of plus + +FINAL CONTROL FLOW GRAPH + +void main() +main: scope:[main] from + [0] phi() + [1] call plus + to:main::@1 +main::@1: scope:[main] from main + [2] *SCREEN = plus::return#1 + to:main::@return +main::@return: scope:[main] from main::@1 + [3] return + to:@return + +__bank(bank) char plus(char a , char b) +plus: scope:[plus] from main + [4] phi() + to:plus::@return +plus::@return: scope:[plus] from plus + [5] return + to:@return + + +VARIABLE REGISTER WEIGHTS +void main() +__bank(bank) char plus(char a , char b) +char plus::a +char plus::b +char plus::return + +Initial phi equivalence classes +Complete equivalence classes +Warning! Unknown fragment for statement [1] call plus +Missing ASM fragment Fragment not found call_far_cx16_rubbish_prepare. Attempted variations call_far_cx16_rubbish_prepare +D:\Users\svenv\OneDrive\Documents\GitHub\kickc\src\test\kc\procedure-callingconvention-phi-bank-2.c:10:17: +REGISTER UPLIFT POTENTIAL REGISTERS +Potential register analysis [1] call plus missing fragment Fragment not found call_far_cx16_rubbish_prepare. Attempted variations call_far_cx16_rubbish_prepare allocation: +MISSING FRAGMENTS + Fragment not found call_far_cx16_rubbish_prepare. Attempted variations call_far_cx16_rubbish_prepare +Statement [1] call plus [ ] ( [ ] { } ) always clobbers reg byte a reg byte x reg byte y +Statement [2] *SCREEN = plus::return#1 [ ] ( [ ] { } ) always clobbers reg byte a + +REGISTER UPLIFT SCOPES +Uplift Scope [main] +Uplift Scope [plus] +Uplift Scope [] + +Warning! Unknown fragment for statement [1] call plus +Missing ASM fragment Fragment not found call_far_cx16_rubbish_prepare. Attempted variations call_far_cx16_rubbish_prepare +D:\Users\svenv\OneDrive\Documents\GitHub\kickc\src\test\kc\procedure-callingconvention-phi-bank-2.c:10:17: +Uplifting [main] best 54 combination +Warning! Unknown fragment for statement [1] call plus +Missing ASM fragment Fragment not found call_far_cx16_rubbish_prepare. Attempted variations call_far_cx16_rubbish_prepare +D:\Users\svenv\OneDrive\Documents\GitHub\kickc\src\test\kc\procedure-callingconvention-phi-bank-2.c:10:17: +Uplifting [plus] best 54 combination +Warning! Unknown fragment for statement [1] call plus +Missing ASM fragment Fragment not found call_far_cx16_rubbish_prepare. Attempted variations call_far_cx16_rubbish_prepare +D:\Users\svenv\OneDrive\Documents\GitHub\kickc\src\test\kc\procedure-callingconvention-phi-bank-2.c:10:17: +Uplifting [] best 54 combination +Warning! Unknown fragment for statement [1] call plus +Missing ASM fragment Fragment not found call_far_cx16_rubbish_prepare. Attempted variations call_far_cx16_rubbish_prepare +D:\Users\svenv\OneDrive\Documents\GitHub\kickc\src\test\kc\procedure-callingconvention-phi-bank-2.c:10:17: + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Test a far call procedure with a calling convention sp + // Upstart +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + + // Global Constants & labels + .label SCREEN = $400 +.segment stage + // main +main: { + // [1] call plus + // [4] phi from main to plus [phi:main->plus] + plus_from_main: + .assert "Missing ASM fragment Fragment not found call_far_cx16_rubbish_prepare. Attempted variations call_far_cx16_rubbish_prepare ", 0, 1 + jmp __b1 + // main::@1 + __b1: + // [2] *SCREEN = plus::return#1 -- _deref_pbuc1=vbuc2 + lda #plus.return + sta SCREEN + jmp __breturn + // main::@return + __breturn: + // [3] return + rts +} + // plus +// char plus(char a, char b) +plus: { + .const a = '0' + .const b = 7 + .label return = a+b + jmp __breturn + // plus::@return + __breturn: + // [5] return + rts +} + // File Data + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction plus_from_main: +Removing instruction __b1: +Removing instruction __breturn: +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +__constant char * const SCREEN = (char *) 1024 +void main() +__bank(bank) char plus(char a , char b) +char plus::a +__constant char plus::a#0 = '0' // a +char plus::b +__constant char plus::b#0 = 7 // b +char plus::return +__constant char plus::return#1 = plus::a#0+plus::b#0 // return + + + +FINAL ASSEMBLER +Score: 18 + + // File Comments +// Test a far call procedure with a calling convention sp + // Upstart +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + + // Global Constants & labels + .label SCREEN = $400 +.segment stage + // main +main: { + // plus('0', 7) + // [1] call plus + // [4] phi from main to plus [phi:main->plus] + .assert "Missing ASM fragment Fragment not found call_far_cx16_rubbish_prepare. Attempted variations call_far_cx16_rubbish_prepare ", 0, 1 + // main::@1 + // SCREEN[0] = plus('0', 7) + // [2] *SCREEN = plus::return#1 -- _deref_pbuc1=vbuc2 + lda #plus.return + sta SCREEN + // main::@return + // } + // [3] return + rts +} + // plus +// char plus(char a, char b) +plus: { + .const a = '0' + .const b = 7 + .label return = a+b + // plus::@return + // [5] return + rts +} + // File Data + diff --git a/src/test/ref/procedure-callingconvention-phi-bank-2.sym b/src/test/ref/procedure-callingconvention-phi-bank-2.sym new file mode 100644 index 000000000..c79872a57 --- /dev/null +++ b/src/test/ref/procedure-callingconvention-phi-bank-2.sym @@ -0,0 +1,10 @@ +__constant char * const SCREEN = (char *) 1024 +void main() +__bank(bank) char plus(char a , char b) +char plus::a +__constant char plus::a#0 = '0' // a +char plus::b +__constant char plus::b#0 = 7 // b +char plus::return +__constant char plus::return#1 = plus::a#0+plus::b#0 // return + diff --git a/src/test/ref/procedure-callingconvention-phi-bank-3.asm b/src/test/ref/procedure-callingconvention-phi-bank-3.asm new file mode 100644 index 000000000..14b4c8f88 --- /dev/null +++ b/src/test/ref/procedure-callingconvention-phi-bank-3.asm @@ -0,0 +1,28 @@ +// Test a far call procedure with a calling convention sp +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + + .label SCREEN = $400 +.segment stage +main: { + // plus('0', 7) + .assert "Missing ASM fragment Fragment not found call_far_cx16_stage_prepare. Attempted variations call_far_cx16_stage_prepare ", 0, 1 + // SCREEN[0] = plus('0', 7) + lda #plus.return + sta SCREEN + // } + rts +} +// char plus(char a, char b) +plus: { + .const a = '0' + .const b = 7 + .label return = a+b + rts +} diff --git a/src/test/ref/procedure-callingconvention-phi-bank-3.cfg b/src/test/ref/procedure-callingconvention-phi-bank-3.cfg new file mode 100644 index 000000000..1701ea88d --- /dev/null +++ b/src/test/ref/procedure-callingconvention-phi-bank-3.cfg @@ -0,0 +1,20 @@ + +void main() +main: scope:[main] from + [0] phi() + [1] call plus + to:main::@1 +main::@1: scope:[main] from main + [2] *SCREEN = plus::return#1 + to:main::@return +main::@return: scope:[main] from main::@1 + [3] return + to:@return + +__bank(bank) char plus(char a , char b) +plus: scope:[plus] from main + [4] phi() + to:plus::@return +plus::@return: scope:[plus] from plus + [5] return + to:@return diff --git a/src/test/ref/procedure-callingconvention-phi-bank-3.log b/src/test/ref/procedure-callingconvention-phi-bank-3.log new file mode 100644 index 000000000..edbe990fa --- /dev/null +++ b/src/test/ref/procedure-callingconvention-phi-bank-3.log @@ -0,0 +1,294 @@ +Loading link script "procedure-callingconvention-phi-bank.ld" + +CONTROL FLOW GRAPH SSA + +void main() +main: scope:[main] from __start + plus::a#0 = '0' + plus::b#0 = 7 + call plus + plus::return#0 = plus::return#2 + to:main::@1 +main::@1: scope:[main] from main + plus::return#3 = phi( main/plus::return#0 ) + main::$0 = plus::return#3 + SCREEN[0] = main::$0 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return + +__bank(bank) char plus(char a , char b) +plus: scope:[plus] from main + plus::b#1 = phi( main/plus::b#0 ) + plus::a#1 = phi( main/plus::a#0 ) + plus::$0 = plus::a#1 + plus::b#1 + plus::return#1 = plus::$0 + to:plus::@return +plus::@return: scope:[plus] from plus + plus::return#4 = phi( plus/plus::return#1 ) + plus::return#2 = plus::return#4 + return + to:@return + +void __start() +__start: scope:[__start] from + call main + to:__start::@1 +__start::@1: scope:[__start] from __start + to:__start::@return +__start::@return: scope:[__start] from __start::@1 + return + to:@return + +SYMBOL TABLE SSA +__constant char * const SCREEN = (char *)$400 +void __start() +void main() +char main::$0 +__bank(bank) char plus(char a , char b) +char plus::$0 +char plus::a +char plus::a#0 +char plus::a#1 +char plus::b +char plus::b#0 +char plus::b#1 +char plus::return +char plus::return#0 +char plus::return#1 +char plus::return#2 +char plus::return#3 +char plus::return#4 + +Adding number conversion cast (unumber) 7 in plus::b#0 = 7 +Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$0 +Successful SSA optimization PassNAddNumberTypeConversions +Inlining cast plus::b#0 = (unumber)7 +Successful SSA optimization Pass2InlineCast +Simplifying constant pointer cast (char *) 1024 +Simplifying constant integer cast 7 +Simplifying constant integer cast 0 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (char) 7 +Finalized unsigned number type (char) 0 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Alias plus::return#0 = plus::return#3 +Alias plus::return#1 = plus::$0 plus::return#4 plus::return#2 +Successful SSA optimization Pass2AliasElimination +Identical Phi Values plus::a#1 plus::a#0 +Identical Phi Values plus::b#1 plus::b#0 +Successful SSA optimization Pass2IdenticalPhiElimination +Constant plus::a#0 = '0' +Constant plus::b#0 = 7 +Successful SSA optimization Pass2ConstantIdentification +Simplifying expression containing zero SCREEN in [5] SCREEN[0] = main::$0 +Successful SSA optimization PassNSimplifyExpressionWithZero +Removing unused procedure __start +Removing unused procedure block __start +Removing unused procedure block __start::@1 +Removing unused procedure block __start::@return +Successful SSA optimization PassNEliminateEmptyStart +Constant right-side identified [5] plus::return#1 = plus::a#0 + plus::b#0 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant plus::return#1 = plus::a#0+plus::b#0 +Successful SSA optimization Pass2ConstantIdentification +Constant plus::return#0 = plus::return#1 +Successful SSA optimization Pass2ConstantIdentification +Constant main::$0 = plus::return#0 +Successful SSA optimization Pass2ConstantIdentification +Inlining constant with different constant siblings plus::return#0 +Constant inlined plus::return#0 = plus::return#1 +Constant inlined main::$0 = plus::return#1 +Successful SSA optimization Pass2ConstantInlining +Adding NOP phi() at start of main +Adding NOP phi() at start of plus +CALL GRAPH +Calls in [main] to plus:1 + +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes +Adding NOP phi() at start of main +Adding NOP phi() at start of plus + +FINAL CONTROL FLOW GRAPH + +void main() +main: scope:[main] from + [0] phi() + [1] call plus + to:main::@1 +main::@1: scope:[main] from main + [2] *SCREEN = plus::return#1 + to:main::@return +main::@return: scope:[main] from main::@1 + [3] return + to:@return + +__bank(bank) char plus(char a , char b) +plus: scope:[plus] from main + [4] phi() + to:plus::@return +plus::@return: scope:[plus] from plus + [5] return + to:@return + + +VARIABLE REGISTER WEIGHTS +void main() +__bank(bank) char plus(char a , char b) +char plus::a +char plus::b +char plus::return + +Initial phi equivalence classes +Complete equivalence classes +Warning! Unknown fragment for statement [1] call plus +Missing ASM fragment Fragment not found call_far_cx16_stage_prepare. Attempted variations call_far_cx16_stage_prepare +D:\Users\svenv\OneDrive\Documents\GitHub\kickc\src\test\kc\procedure-callingconvention-phi-bank-3.c:10:17: +REGISTER UPLIFT POTENTIAL REGISTERS +Potential register analysis [1] call plus missing fragment Fragment not found call_far_cx16_stage_prepare. Attempted variations call_far_cx16_stage_prepare allocation: +MISSING FRAGMENTS + Fragment not found call_far_cx16_stage_prepare. Attempted variations call_far_cx16_stage_prepare +Statement [1] call plus [ ] ( [ ] { } ) always clobbers reg byte a reg byte x reg byte y +Statement [2] *SCREEN = plus::return#1 [ ] ( [ ] { } ) always clobbers reg byte a + +REGISTER UPLIFT SCOPES +Uplift Scope [main] +Uplift Scope [plus] +Uplift Scope [] + +Warning! Unknown fragment for statement [1] call plus +Missing ASM fragment Fragment not found call_far_cx16_stage_prepare. Attempted variations call_far_cx16_stage_prepare +D:\Users\svenv\OneDrive\Documents\GitHub\kickc\src\test\kc\procedure-callingconvention-phi-bank-3.c:10:17: +Uplifting [main] best 54 combination +Warning! Unknown fragment for statement [1] call plus +Missing ASM fragment Fragment not found call_far_cx16_stage_prepare. Attempted variations call_far_cx16_stage_prepare +D:\Users\svenv\OneDrive\Documents\GitHub\kickc\src\test\kc\procedure-callingconvention-phi-bank-3.c:10:17: +Uplifting [plus] best 54 combination +Warning! Unknown fragment for statement [1] call plus +Missing ASM fragment Fragment not found call_far_cx16_stage_prepare. Attempted variations call_far_cx16_stage_prepare +D:\Users\svenv\OneDrive\Documents\GitHub\kickc\src\test\kc\procedure-callingconvention-phi-bank-3.c:10:17: +Uplifting [] best 54 combination +Warning! Unknown fragment for statement [1] call plus +Missing ASM fragment Fragment not found call_far_cx16_stage_prepare. Attempted variations call_far_cx16_stage_prepare +D:\Users\svenv\OneDrive\Documents\GitHub\kickc\src\test\kc\procedure-callingconvention-phi-bank-3.c:10:17: + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Test a far call procedure with a calling convention sp + // Upstart +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + + // Global Constants & labels + .label SCREEN = $400 +.segment stage + // main +main: { + // [1] call plus + // [4] phi from main to plus [phi:main->plus] + plus_from_main: + .assert "Missing ASM fragment Fragment not found call_far_cx16_stage_prepare. Attempted variations call_far_cx16_stage_prepare ", 0, 1 + jmp __b1 + // main::@1 + __b1: + // [2] *SCREEN = plus::return#1 -- _deref_pbuc1=vbuc2 + lda #plus.return + sta SCREEN + jmp __breturn + // main::@return + __breturn: + // [3] return + rts +} + // plus +// char plus(char a, char b) +plus: { + .const a = '0' + .const b = 7 + .label return = a+b + jmp __breturn + // plus::@return + __breturn: + // [5] return + rts +} + // File Data + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction plus_from_main: +Removing instruction __b1: +Removing instruction __breturn: +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +__constant char * const SCREEN = (char *) 1024 +void main() +__bank(bank) char plus(char a , char b) +char plus::a +__constant char plus::a#0 = '0' // a +char plus::b +__constant char plus::b#0 = 7 // b +char plus::return +__constant char plus::return#1 = plus::a#0+plus::b#0 // return + + + +FINAL ASSEMBLER +Score: 18 + + // File Comments +// Test a far call procedure with a calling convention sp + // Upstart +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + + // Global Constants & labels + .label SCREEN = $400 +.segment stage + // main +main: { + // plus('0', 7) + // [1] call plus + // [4] phi from main to plus [phi:main->plus] + .assert "Missing ASM fragment Fragment not found call_far_cx16_stage_prepare. Attempted variations call_far_cx16_stage_prepare ", 0, 1 + // main::@1 + // SCREEN[0] = plus('0', 7) + // [2] *SCREEN = plus::return#1 -- _deref_pbuc1=vbuc2 + lda #plus.return + sta SCREEN + // main::@return + // } + // [3] return + rts +} + // plus +// char plus(char a, char b) +plus: { + .const a = '0' + .const b = 7 + .label return = a+b + // plus::@return + // [5] return + rts +} + // File Data + diff --git a/src/test/ref/procedure-callingconvention-phi-bank-3.sym b/src/test/ref/procedure-callingconvention-phi-bank-3.sym new file mode 100644 index 000000000..c79872a57 --- /dev/null +++ b/src/test/ref/procedure-callingconvention-phi-bank-3.sym @@ -0,0 +1,10 @@ +__constant char * const SCREEN = (char *) 1024 +void main() +__bank(bank) char plus(char a , char b) +char plus::a +__constant char plus::a#0 = '0' // a +char plus::b +__constant char plus::b#0 = 7 // b +char plus::return +__constant char plus::return#1 = plus::a#0+plus::b#0 // return + diff --git a/src/test/ref/procedure-callingconvention-phi-bank-4.asm b/src/test/ref/procedure-callingconvention-phi-bank-4.asm new file mode 100644 index 000000000..e67cb058e --- /dev/null +++ b/src/test/ref/procedure-callingconvention-phi-bank-4.asm @@ -0,0 +1,28 @@ +// Test a far call procedure with a calling convention phi +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + + .label SCREEN = $400 +.segment stage +main: { + // plus('0', 7) + jsr plus + // SCREEN[0] = plus('0', 7) + lda #plus.return + sta SCREEN + // } + rts +} +// char plus(char a, char b) +plus: { + .const a = '0' + .const b = 7 + .label return = a+b + rts +} diff --git a/src/test/ref/procedure-callingconvention-phi-bank-4.cfg b/src/test/ref/procedure-callingconvention-phi-bank-4.cfg new file mode 100644 index 000000000..2cc5e64ff --- /dev/null +++ b/src/test/ref/procedure-callingconvention-phi-bank-4.cfg @@ -0,0 +1,20 @@ + +__bank(bank) void main() +main: scope:[main] from + [0] phi() + [1] call plus + to:main::@1 +main::@1: scope:[main] from main + [2] *SCREEN = plus::return#0 + to:main::@return +main::@return: scope:[main] from main::@1 + [3] return + to:@return + +__bank(bank) char plus(char a , char b) +plus: scope:[plus] from main + [4] phi() + to:plus::@return +plus::@return: scope:[plus] from plus + [5] return + to:@return diff --git a/src/test/ref/procedure-callingconvention-phi-bank-4.log b/src/test/ref/procedure-callingconvention-phi-bank-4.log new file mode 100644 index 000000000..80ecb72df --- /dev/null +++ b/src/test/ref/procedure-callingconvention-phi-bank-4.log @@ -0,0 +1,275 @@ +Loading link script "procedure-callingconvention-phi-bank.ld" + +CONTROL FLOW GRAPH SSA + +__bank(bank) char plus(char a , char b) +plus: scope:[plus] from main + plus::b#1 = phi( main/plus::b#0 ) + plus::a#1 = phi( main/plus::a#0 ) + plus::$0 = plus::a#1 + plus::b#1 + plus::return#0 = plus::$0 + to:plus::@return +plus::@return: scope:[plus] from plus + plus::return#3 = phi( plus/plus::return#0 ) + plus::return#1 = plus::return#3 + return + to:@return + +__bank(bank) void main() +main: scope:[main] from __start + plus::a#0 = '0' + plus::b#0 = 7 + call plus + plus::return#2 = plus::return#1 + to:main::@1 +main::@1: scope:[main] from main + plus::return#4 = phi( main/plus::return#2 ) + main::$0 = plus::return#4 + SCREEN[0] = main::$0 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return + +void __start() +__start: scope:[__start] from + call main + to:__start::@1 +__start::@1: scope:[__start] from __start + to:__start::@return +__start::@return: scope:[__start] from __start::@1 + return + to:@return + +SYMBOL TABLE SSA +__constant char * const SCREEN = (char *)$400 +void __start() +__bank(bank) void main() +char main::$0 +__bank(bank) char plus(char a , char b) +char plus::$0 +char plus::a +char plus::a#0 +char plus::a#1 +char plus::b +char plus::b#0 +char plus::b#1 +char plus::return +char plus::return#0 +char plus::return#1 +char plus::return#2 +char plus::return#3 +char plus::return#4 + +Adding number conversion cast (unumber) 7 in plus::b#0 = 7 +Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$0 +Successful SSA optimization PassNAddNumberTypeConversions +Inlining cast plus::b#0 = (unumber)7 +Successful SSA optimization Pass2InlineCast +Simplifying constant pointer cast (char *) 1024 +Simplifying constant integer cast 7 +Simplifying constant integer cast 0 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (char) 7 +Finalized unsigned number type (char) 0 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Alias plus::return#0 = plus::$0 plus::return#3 plus::return#1 +Alias plus::return#2 = plus::return#4 +Successful SSA optimization Pass2AliasElimination +Identical Phi Values plus::a#1 plus::a#0 +Identical Phi Values plus::b#1 plus::b#0 +Successful SSA optimization Pass2IdenticalPhiElimination +Constant plus::a#0 = '0' +Constant plus::b#0 = 7 +Successful SSA optimization Pass2ConstantIdentification +Simplifying expression containing zero SCREEN in [8] SCREEN[0] = main::$0 +Successful SSA optimization PassNSimplifyExpressionWithZero +Removing unused procedure __start +Removing unused procedure block __start +Removing unused procedure block __start::@1 +Removing unused procedure block __start::@return +Successful SSA optimization PassNEliminateEmptyStart +Constant right-side identified [0] plus::return#0 = plus::a#0 + plus::b#0 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant plus::return#0 = plus::a#0+plus::b#0 +Successful SSA optimization Pass2ConstantIdentification +Constant plus::return#2 = plus::return#0 +Successful SSA optimization Pass2ConstantIdentification +Constant main::$0 = plus::return#2 +Successful SSA optimization Pass2ConstantIdentification +Inlining constant with different constant siblings plus::return#2 +Constant inlined plus::return#2 = plus::return#0 +Constant inlined main::$0 = plus::return#0 +Successful SSA optimization Pass2ConstantInlining +Adding NOP phi() at start of main +Adding NOP phi() at start of plus +CALL GRAPH +Calls in [main] to plus:1 + +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes +Adding NOP phi() at start of main +Adding NOP phi() at start of plus + +FINAL CONTROL FLOW GRAPH + +__bank(bank) void main() +main: scope:[main] from + [0] phi() + [1] call plus + to:main::@1 +main::@1: scope:[main] from main + [2] *SCREEN = plus::return#0 + to:main::@return +main::@return: scope:[main] from main::@1 + [3] return + to:@return + +__bank(bank) char plus(char a , char b) +plus: scope:[plus] from main + [4] phi() + to:plus::@return +plus::@return: scope:[plus] from plus + [5] return + to:@return + + +VARIABLE REGISTER WEIGHTS +__bank(bank) void main() +__bank(bank) char plus(char a , char b) +char plus::a +char plus::b +char plus::return + +Initial phi equivalence classes +Complete equivalence classes +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [2] *SCREEN = plus::return#0 [ ] ( [ ] { } ) always clobbers reg byte a + +REGISTER UPLIFT SCOPES +Uplift Scope [plus] +Uplift Scope [main] +Uplift Scope [] + +Uplifting [plus] best 60 combination +Uplifting [main] best 60 combination +Uplifting [] best 60 combination + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Test a far call procedure with a calling convention phi + // Upstart +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + + // Global Constants & labels + .label SCREEN = $400 +.segment stage + // main +main: { + // [1] call plus + // [4] phi from main to plus [phi:main->plus] + plus_from_main: + jsr plus + jmp __b1 + // main::@1 + __b1: + // [2] *SCREEN = plus::return#0 -- _deref_pbuc1=vbuc2 + lda #plus.return + sta SCREEN + jmp __breturn + // main::@return + __breturn: + // [3] return + rts +} + // plus +// char plus(char a, char b) +plus: { + .const a = '0' + .const b = 7 + .label return = a+b + jmp __breturn + // plus::@return + __breturn: + // [5] return + rts +} + // File Data + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction plus_from_main: +Removing instruction __b1: +Removing instruction __breturn: +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +__constant char * const SCREEN = (char *) 1024 +__bank(bank) void main() +__bank(bank) char plus(char a , char b) +char plus::a +__constant char plus::a#0 = '0' // a +char plus::b +__constant char plus::b#0 = 7 // b +char plus::return +__constant char plus::return#0 = plus::a#0+plus::b#0 // return + + + +FINAL ASSEMBLER +Score: 24 + + // File Comments +// Test a far call procedure with a calling convention phi + // Upstart +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + + // Global Constants & labels + .label SCREEN = $400 +.segment stage + // main +main: { + // plus('0', 7) + // [1] call plus + // [4] phi from main to plus [phi:main->plus] + jsr plus + // main::@1 + // SCREEN[0] = plus('0', 7) + // [2] *SCREEN = plus::return#0 -- _deref_pbuc1=vbuc2 + lda #plus.return + sta SCREEN + // main::@return + // } + // [3] return + rts +} + // plus +// char plus(char a, char b) +plus: { + .const a = '0' + .const b = 7 + .label return = a+b + // plus::@return + // [5] return + rts +} + // File Data + diff --git a/src/test/ref/procedure-callingconvention-phi-bank-4.sym b/src/test/ref/procedure-callingconvention-phi-bank-4.sym new file mode 100644 index 000000000..303e3a74d --- /dev/null +++ b/src/test/ref/procedure-callingconvention-phi-bank-4.sym @@ -0,0 +1,10 @@ +__constant char * const SCREEN = (char *) 1024 +__bank(bank) void main() +__bank(bank) char plus(char a , char b) +char plus::a +__constant char plus::a#0 = '0' // a +char plus::b +__constant char plus::b#0 = 7 // b +char plus::return +__constant char plus::return#0 = plus::a#0+plus::b#0 // return + diff --git a/src/test/ref/procedure-callingconvention-phi-bank-5.asm b/src/test/ref/procedure-callingconvention-phi-bank-5.asm new file mode 100644 index 000000000..f04dd9403 --- /dev/null +++ b/src/test/ref/procedure-callingconvention-phi-bank-5.asm @@ -0,0 +1,268 @@ +// Test a far call procedure with a calling convention phi +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + + .label SCREEN = $400 +.segment Code +main: { + // func_bank1_a('0', 7) + lda #7 + ldx #'0' + jsr $ff6e + .byte func_bank1_a + .byte 1 + // func_bank1_a('0', 7) + // SCREEN[0] = func_bank1_a('0', 7) + // far call + sta SCREEN + // func_bank1_b('0', 7) + lda #7 + ldx #'0' + jsr func_bank1_b + // func_bank1_b('0', 7) + // SCREEN[0] = func_bank1_b('0', 7) + // far call + sta SCREEN + // func_bank1_c('0', 7) + jsr $ff6e + .byte func_bank1_c + .byte 1 + // func_bank1_c('0', 7) + // SCREEN[0] = func_bank1_c('0', 7) + // far call + sta SCREEN + // func_bank1_d('0', 7) + jsr $ff6e + .byte func_bank1_d + .byte 1 + // func_bank1_d('0', 7) + // SCREEN[0] = func_bank1_d('0', 7) + // far call + sta SCREEN + // func_bank1_e('0', 7) + jsr func_bank1_e + // func_bank1_e('0', 7) + // SCREEN[0] = func_bank1_e('0', 7) + // near call + sta SCREEN + // func_bank1_f('0', 7) + jsr func_bank1_f + // func_bank1_f('0', 7) + // SCREEN[0] = func_bank1_f('0', 7) + // near call + sta SCREEN + // func_bank2_a('0', 7) + lda #7 + ldx #'0' + jsr $ff6e + .byte func_bank2_a + .byte 2 + // func_bank2_a('0', 7) + // SCREEN[0] = func_bank2_a('0', 7) + // far call + sta SCREEN + // func_bank2_b('0', 7) + lda #7 + ldx #'0' + jsr func_bank2_b + // func_bank2_b('0', 7) + // SCREEN[0] = func_bank2_b('0', 7) + // far call + sta SCREEN + // func_bank2_c('0', 7) + jsr $ff6e + .byte func_bank2_c + .byte 2 + // func_bank2_c('0', 7) + // SCREEN[0] = func_bank2_c('0', 7) + // far call + sta SCREEN + // func_bank2_d('0', 7) + jsr $ff6e + .byte func_bank2_d + .byte 2 + // func_bank2_d('0', 7) + // SCREEN[0] = func_bank2_d('0', 7) + // far call + sta SCREEN + // func_bank2_e('0', 7) + jsr $ff6e + .byte func_bank2_e + .byte 2 + // func_bank2_e('0', 7) + // SCREEN[0] = func_bank2_e('0', 7) + // far call + sta SCREEN + // func_bank2_f('0', 7) + jsr $ff6e + .byte func_bank2_f + .byte 2 + // func_bank2_f('0', 7) + // SCREEN[0] = func_bank2_f('0', 7) + // far call + sta SCREEN + // } + rts +} +.segment stage +// __register(A) char func_bank1_a(__register(X) char a, __register(A) char b) +func_bank1_a: { + // a+b + stx.z $ff + clc + adc.z $ff + // } + rts +} +.segment platform +// __register(A) char func_bank1_b(__register(X) char a, __register(A) char b) +func_bank1_b: { + // a+b + stx.z $ff + clc + adc.z $ff + // } + rts +} +.segment stage +// __register(A) char func_bank1_c(char a, char b) +func_bank1_c: { + .const a = '0' + .const b = 7 + // func_bank1_a(a,b) + lda #b + ldx #a + jsr func_bank1_a + // func_bank1_a(a,b) + // } + rts +} +// __register(A) char func_bank1_d(char a, char b) +func_bank1_d: { + .const a = '0' + .const b = 7 + // func_bank2_a(a,b) + lda #b + ldx #a + jsr $ff6e + .byte func_bank2_a + .byte 2 + // func_bank2_a(a,b) + // } + rts +} +.segment platform +// __register(A) char func_bank1_e(char a, char b) +func_bank1_e: { + .const a = '0' + .const b = 7 + // func_bank1_a(a,b) + lda #b + ldx #a + jsr $ff6e + .byte func_bank1_a + .byte 1 + // func_bank1_a(a,b) + // } + rts +} +// __register(A) char func_bank1_f(char a, char b) +func_bank1_f: { + .const a = '0' + .const b = 7 + // func_bank2_a(a,b) + lda #b + ldx #a + jsr $ff6e + .byte func_bank2_a + .byte 2 + // func_bank2_a(a,b) + // } + rts +} +// __register(A) char func_bank2_a(__register(X) char a, __register(A) char b) +func_bank2_a: { + // a+b + stx.z $ff + clc + adc.z $ff + // } + rts +} +// __register(A) char func_bank2_b(__register(X) char a, __register(A) char b) +func_bank2_b: { + // a+b + stx.z $ff + clc + adc.z $ff + // } + rts +} +// __register(A) char func_bank2_c(char a, char b) +func_bank2_c: { + .const a = '0' + .const b = 7 + // func_bank1_a(a,b) + lda #b + ldx #a + jsr $ff6e + .byte func_bank1_a + .byte 1 + // func_bank1_a(a,b) + // } + rts +} +// __register(A) char func_bank2_d(char a, char b) +func_bank2_d: { + .const a = '0' + .const b = 7 + // func_bank2_a(a,b) + lda #b + ldx #a + jsr func_bank2_a + // func_bank2_a(a,b) + // } + rts +} +// __register(A) char func_bank2_e(char a, char b) +func_bank2_e: { + .const a = '0' + .const b = 7 + // func_bank2_b(a,b) + lda #b + ldx #a + jsr func_bank2_b + // func_bank2_b(a,b) + // } + rts +} +// __register(A) char func_bank2_f(char a, char b) +func_bank2_f: { + .const a = '0' + .const b = 7 + // func_bank1_b(a,b) + lda #b + ldx #a + jsr func_bank1_b + // func_bank1_b(a,b) + // } + rts +} diff --git a/src/test/ref/procedure-callingconvention-phi-bank-5.cfg b/src/test/ref/procedure-callingconvention-phi-bank-5.cfg new file mode 100644 index 000000000..39617047b --- /dev/null +++ b/src/test/ref/procedure-callingconvention-phi-bank-5.cfg @@ -0,0 +1,224 @@ + +void main() +main: scope:[main] from + [0] phi() + [1] call func_bank1_a + [2] func_bank1_a::return#10 = func_bank1_a::return#0 + to:main::@1 +main::@1: scope:[main] from main + [3] main::$0 = func_bank1_a::return#10 + [4] *SCREEN = main::$0 + [5] call func_bank1_b + [6] func_bank1_b::return#3 = func_bank1_b::return#1 + to:main::@2 +main::@2: scope:[main] from main::@1 + [7] main::$1 = func_bank1_b::return#3 + [8] *SCREEN = main::$1 + [9] call func_bank1_c + [10] func_bank1_c::return#2 = func_bank1_c::return#0 + to:main::@3 +main::@3: scope:[main] from main::@2 + [11] main::$2 = func_bank1_c::return#2 + [12] *SCREEN = main::$2 + [13] call func_bank1_d + [14] func_bank1_d::return#2 = func_bank1_d::return#0 + to:main::@4 +main::@4: scope:[main] from main::@3 + [15] main::$3 = func_bank1_d::return#2 + [16] *SCREEN = main::$3 + [17] call func_bank1_e + [18] func_bank1_e::return#2 = func_bank1_e::return#0 + to:main::@5 +main::@5: scope:[main] from main::@4 + [19] main::$4 = func_bank1_e::return#2 + [20] *SCREEN = main::$4 + [21] call func_bank1_f + [22] func_bank1_f::return#2 = func_bank1_f::return#0 + to:main::@6 +main::@6: scope:[main] from main::@5 + [23] main::$5 = func_bank1_f::return#2 + [24] *SCREEN = main::$5 + [25] call func_bank2_a + [26] func_bank2_a::return#10 = func_bank2_a::return#1 + to:main::@7 +main::@7: scope:[main] from main::@6 + [27] main::$6 = func_bank2_a::return#10 + [28] *SCREEN = main::$6 + [29] call func_bank2_b + [30] func_bank2_b::return#3 = func_bank2_b::return#1 + to:main::@8 +main::@8: scope:[main] from main::@7 + [31] main::$7 = func_bank2_b::return#3 + [32] *SCREEN = main::$7 + [33] call func_bank2_c + [34] func_bank2_c::return#2 = func_bank2_c::return#0 + to:main::@9 +main::@9: scope:[main] from main::@8 + [35] main::$8 = func_bank2_c::return#2 + [36] *SCREEN = main::$8 + [37] call func_bank2_d + [38] func_bank2_d::return#2 = func_bank2_d::return#0 + to:main::@10 +main::@10: scope:[main] from main::@9 + [39] main::$9 = func_bank2_d::return#2 + [40] *SCREEN = main::$9 + [41] call func_bank2_e + [42] func_bank2_e::return#2 = func_bank2_e::return#0 + to:main::@11 +main::@11: scope:[main] from main::@10 + [43] main::$10 = func_bank2_e::return#2 + [44] *SCREEN = main::$10 + [45] call func_bank2_f + [46] func_bank2_f::return#2 = func_bank2_f::return#0 + to:main::@12 +main::@12: scope:[main] from main::@11 + [47] main::$11 = func_bank2_f::return#2 + [48] *SCREEN = main::$11 + to:main::@return +main::@return: scope:[main] from main::@12 + [49] return + to:@return + +__bank(bank) char func_bank1_a(char a , char b) +func_bank1_a: scope:[func_bank1_a] from func_bank1_c func_bank1_e func_bank2_c main + [50] func_bank1_a::b#4 = phi( func_bank1_c/func_bank1_c::b#0, func_bank1_e/func_bank1_e::b#0, func_bank2_c/func_bank2_c::b#0, main/7 ) + [50] func_bank1_a::a#4 = phi( func_bank1_c/func_bank1_c::a#0, func_bank1_e/func_bank1_e::a#0, func_bank2_c/func_bank2_c::a#0, main/'0' ) + [51] func_bank1_a::return#0 = func_bank1_a::a#4 + func_bank1_a::b#4 + to:func_bank1_a::@return +func_bank1_a::@return: scope:[func_bank1_a] from func_bank1_a + [52] return + to:@return + +char func_bank1_b(char a , char b) +func_bank1_b: scope:[func_bank1_b] from func_bank2_f main::@1 + [53] func_bank1_b::b#2 = phi( func_bank2_f/func_bank2_f::b#0, main::@1/7 ) + [53] func_bank1_b::a#2 = phi( func_bank2_f/func_bank2_f::a#0, main::@1/'0' ) + [54] func_bank1_b::return#1 = func_bank1_b::a#2 + func_bank1_b::b#2 + to:func_bank1_b::@return +func_bank1_b::@return: scope:[func_bank1_b] from func_bank1_b + [55] return + to:@return + +__bank(bank) char func_bank1_c(char a , char b) +func_bank1_c: scope:[func_bank1_c] from main::@2 + [56] phi() + [57] call func_bank1_a + [58] func_bank1_a::return#2 = func_bank1_a::return#0 + to:func_bank1_c::@1 +func_bank1_c::@1: scope:[func_bank1_c] from func_bank1_c + [59] func_bank1_c::return#0 = func_bank1_a::return#2 + to:func_bank1_c::@return +func_bank1_c::@return: scope:[func_bank1_c] from func_bank1_c::@1 + [60] return + to:@return + +__bank(bank) char func_bank1_d(char a , char b) +func_bank1_d: scope:[func_bank1_d] from main::@3 + [61] phi() + [62] call func_bank2_a + [63] func_bank2_a::return#0 = func_bank2_a::return#1 + to:func_bank1_d::@1 +func_bank1_d::@1: scope:[func_bank1_d] from func_bank1_d + [64] func_bank1_d::return#0 = func_bank2_a::return#0 + to:func_bank1_d::@return +func_bank1_d::@return: scope:[func_bank1_d] from func_bank1_d::@1 + [65] return + to:@return + +char func_bank1_e(char a , char b) +func_bank1_e: scope:[func_bank1_e] from main::@4 + [66] phi() + [67] call func_bank1_a + [68] func_bank1_a::return#4 = func_bank1_a::return#0 + to:func_bank1_e::@1 +func_bank1_e::@1: scope:[func_bank1_e] from func_bank1_e + [69] func_bank1_e::return#0 = func_bank1_a::return#4 + to:func_bank1_e::@return +func_bank1_e::@return: scope:[func_bank1_e] from func_bank1_e::@1 + [70] return + to:@return + +char func_bank1_f(char a , char b) +func_bank1_f: scope:[func_bank1_f] from main::@5 + [71] phi() + [72] call func_bank2_a + [73] func_bank2_a::return#4 = func_bank2_a::return#1 + to:func_bank1_f::@1 +func_bank1_f::@1: scope:[func_bank1_f] from func_bank1_f + [74] func_bank1_f::return#0 = func_bank2_a::return#4 + to:func_bank1_f::@return +func_bank1_f::@return: scope:[func_bank1_f] from func_bank1_f::@1 + [75] return + to:@return + +__bank(bank) char func_bank2_a(char a , char b) +func_bank2_a: scope:[func_bank2_a] from func_bank1_d func_bank1_f func_bank2_d main::@6 + [76] func_bank2_a::b#4 = phi( func_bank1_d/func_bank1_d::b#0, func_bank1_f/func_bank1_f::b#0, func_bank2_d/func_bank2_d::b#0, main::@6/7 ) + [76] func_bank2_a::a#4 = phi( func_bank1_d/func_bank1_d::a#0, func_bank1_f/func_bank1_f::a#0, func_bank2_d/func_bank2_d::a#0, main::@6/'0' ) + [77] func_bank2_a::return#1 = func_bank2_a::a#4 + func_bank2_a::b#4 + to:func_bank2_a::@return +func_bank2_a::@return: scope:[func_bank2_a] from func_bank2_a + [78] return + to:@return + +char func_bank2_b(char a , char b) +func_bank2_b: scope:[func_bank2_b] from func_bank2_e main::@7 + [79] func_bank2_b::b#2 = phi( func_bank2_e/func_bank2_e::b#0, main::@7/7 ) + [79] func_bank2_b::a#2 = phi( func_bank2_e/func_bank2_e::a#0, main::@7/'0' ) + [80] func_bank2_b::return#1 = func_bank2_b::a#2 + func_bank2_b::b#2 + to:func_bank2_b::@return +func_bank2_b::@return: scope:[func_bank2_b] from func_bank2_b + [81] return + to:@return + +__bank(bank) char func_bank2_c(char a , char b) +func_bank2_c: scope:[func_bank2_c] from main::@8 + [82] phi() + [83] call func_bank1_a + [84] func_bank1_a::return#3 = func_bank1_a::return#0 + to:func_bank2_c::@1 +func_bank2_c::@1: scope:[func_bank2_c] from func_bank2_c + [85] func_bank2_c::return#0 = func_bank1_a::return#3 + to:func_bank2_c::@return +func_bank2_c::@return: scope:[func_bank2_c] from func_bank2_c::@1 + [86] return + to:@return + +__bank(bank) char func_bank2_d(char a , char b) +func_bank2_d: scope:[func_bank2_d] from main::@9 + [87] phi() + [88] call func_bank2_a + [89] func_bank2_a::return#3 = func_bank2_a::return#1 + to:func_bank2_d::@1 +func_bank2_d::@1: scope:[func_bank2_d] from func_bank2_d + [90] func_bank2_d::return#0 = func_bank2_a::return#3 + to:func_bank2_d::@return +func_bank2_d::@return: scope:[func_bank2_d] from func_bank2_d::@1 + [91] return + to:@return + +__bank(bank) char func_bank2_e(char a , char b) +func_bank2_e: scope:[func_bank2_e] from main::@10 + [92] phi() + [93] call func_bank2_b + [94] func_bank2_b::return#0 = func_bank2_b::return#1 + to:func_bank2_e::@1 +func_bank2_e::@1: scope:[func_bank2_e] from func_bank2_e + [95] func_bank2_e::return#0 = func_bank2_b::return#0 + to:func_bank2_e::@return +func_bank2_e::@return: scope:[func_bank2_e] from func_bank2_e::@1 + [96] return + to:@return + +__bank(bank) char func_bank2_f(char a , char b) +func_bank2_f: scope:[func_bank2_f] from main::@11 + [97] phi() + [98] call func_bank1_b + [99] func_bank1_b::return#0 = func_bank1_b::return#1 + to:func_bank2_f::@1 +func_bank2_f::@1: scope:[func_bank2_f] from func_bank2_f + [100] func_bank2_f::return#0 = func_bank1_b::return#0 + to:func_bank2_f::@return +func_bank2_f::@return: scope:[func_bank2_f] from func_bank2_f::@1 + [101] return + to:@return diff --git a/src/test/ref/procedure-callingconvention-phi-bank-5.log b/src/test/ref/procedure-callingconvention-phi-bank-5.log new file mode 100644 index 000000000..1e374e133 --- /dev/null +++ b/src/test/ref/procedure-callingconvention-phi-bank-5.log @@ -0,0 +1,2642 @@ +Loading link script "procedure-callingconvention-phi-bank.ld" + +CONTROL FLOW GRAPH SSA + +__bank(bank) char func_bank1_a(char a , char b) +func_bank1_a: scope:[func_bank1_a] from func_bank1_c func_bank1_e func_bank2_c main + func_bank1_a::b#4 = phi( func_bank1_c/func_bank1_a::b#0, func_bank1_e/func_bank1_a::b#2, func_bank2_c/func_bank1_a::b#1, main/func_bank1_a::b#3 ) + func_bank1_a::a#4 = phi( func_bank1_c/func_bank1_a::a#0, func_bank1_e/func_bank1_a::a#2, func_bank2_c/func_bank1_a::a#1, main/func_bank1_a::a#3 ) + func_bank1_a::$0 = func_bank1_a::a#4 + func_bank1_a::b#4 + func_bank1_a::return#0 = func_bank1_a::$0 + to:func_bank1_a::@return +func_bank1_a::@return: scope:[func_bank1_a] from func_bank1_a + func_bank1_a::return#6 = phi( func_bank1_a/func_bank1_a::return#0 ) + func_bank1_a::return#1 = func_bank1_a::return#6 + return + to:@return + +__bank(bank) char func_bank1_c(char a , char b) +func_bank1_c: scope:[func_bank1_c] from main::@2 + func_bank1_c::b#1 = phi( main::@2/func_bank1_c::b#0 ) + func_bank1_c::a#1 = phi( main::@2/func_bank1_c::a#0 ) + func_bank1_a::a#0 = func_bank1_c::a#1 + func_bank1_a::b#0 = func_bank1_c::b#1 + call func_bank1_a + func_bank1_a::return#2 = func_bank1_a::return#1 + to:func_bank1_c::@1 +func_bank1_c::@1: scope:[func_bank1_c] from func_bank1_c + func_bank1_a::return#7 = phi( func_bank1_c/func_bank1_a::return#2 ) + func_bank1_c::$0 = func_bank1_a::return#7 + func_bank1_c::return#0 = func_bank1_c::$0 + to:func_bank1_c::@return +func_bank1_c::@return: scope:[func_bank1_c] from func_bank1_c::@1 + func_bank1_c::return#3 = phi( func_bank1_c::@1/func_bank1_c::return#0 ) + func_bank1_c::return#1 = func_bank1_c::return#3 + return + to:@return + +__bank(bank) char func_bank1_d(char a , char b) +func_bank1_d: scope:[func_bank1_d] from main::@3 + func_bank1_d::b#1 = phi( main::@3/func_bank1_d::b#0 ) + func_bank1_d::a#1 = phi( main::@3/func_bank1_d::a#0 ) + func_bank2_a::a#0 = func_bank1_d::a#1 + func_bank2_a::b#0 = func_bank1_d::b#1 + call func_bank2_a + func_bank2_a::return#0 = func_bank2_a::return#2 + to:func_bank1_d::@1 +func_bank1_d::@1: scope:[func_bank1_d] from func_bank1_d + func_bank2_a::return#6 = phi( func_bank1_d/func_bank2_a::return#0 ) + func_bank1_d::$0 = func_bank2_a::return#6 + func_bank1_d::return#0 = func_bank1_d::$0 + to:func_bank1_d::@return +func_bank1_d::@return: scope:[func_bank1_d] from func_bank1_d::@1 + func_bank1_d::return#3 = phi( func_bank1_d::@1/func_bank1_d::return#0 ) + func_bank1_d::return#1 = func_bank1_d::return#3 + return + to:@return + +__bank(bank) char func_bank2_a(char a , char b) +func_bank2_a: scope:[func_bank2_a] from func_bank1_d func_bank1_f func_bank2_d main::@6 + func_bank2_a::b#4 = phi( func_bank1_d/func_bank2_a::b#0, func_bank1_f/func_bank2_a::b#2, func_bank2_d/func_bank2_a::b#1, main::@6/func_bank2_a::b#3 ) + func_bank2_a::a#4 = phi( func_bank1_d/func_bank2_a::a#0, func_bank1_f/func_bank2_a::a#2, func_bank2_d/func_bank2_a::a#1, main::@6/func_bank2_a::a#3 ) + func_bank2_a::$0 = func_bank2_a::a#4 + func_bank2_a::b#4 + func_bank2_a::return#1 = func_bank2_a::$0 + to:func_bank2_a::@return +func_bank2_a::@return: scope:[func_bank2_a] from func_bank2_a + func_bank2_a::return#7 = phi( func_bank2_a/func_bank2_a::return#1 ) + func_bank2_a::return#2 = func_bank2_a::return#7 + return + to:@return + +__bank(bank) char func_bank2_c(char a , char b) +func_bank2_c: scope:[func_bank2_c] from main::@8 + func_bank2_c::b#1 = phi( main::@8/func_bank2_c::b#0 ) + func_bank2_c::a#1 = phi( main::@8/func_bank2_c::a#0 ) + func_bank1_a::a#1 = func_bank2_c::a#1 + func_bank1_a::b#1 = func_bank2_c::b#1 + call func_bank1_a + func_bank1_a::return#3 = func_bank1_a::return#1 + to:func_bank2_c::@1 +func_bank2_c::@1: scope:[func_bank2_c] from func_bank2_c + func_bank1_a::return#8 = phi( func_bank2_c/func_bank1_a::return#3 ) + func_bank2_c::$0 = func_bank1_a::return#8 + func_bank2_c::return#0 = func_bank2_c::$0 + to:func_bank2_c::@return +func_bank2_c::@return: scope:[func_bank2_c] from func_bank2_c::@1 + func_bank2_c::return#3 = phi( func_bank2_c::@1/func_bank2_c::return#0 ) + func_bank2_c::return#1 = func_bank2_c::return#3 + return + to:@return + +__bank(bank) char func_bank2_d(char a , char b) +func_bank2_d: scope:[func_bank2_d] from main::@9 + func_bank2_d::b#1 = phi( main::@9/func_bank2_d::b#0 ) + func_bank2_d::a#1 = phi( main::@9/func_bank2_d::a#0 ) + func_bank2_a::a#1 = func_bank2_d::a#1 + func_bank2_a::b#1 = func_bank2_d::b#1 + call func_bank2_a + func_bank2_a::return#3 = func_bank2_a::return#2 + to:func_bank2_d::@1 +func_bank2_d::@1: scope:[func_bank2_d] from func_bank2_d + func_bank2_a::return#8 = phi( func_bank2_d/func_bank2_a::return#3 ) + func_bank2_d::$0 = func_bank2_a::return#8 + func_bank2_d::return#0 = func_bank2_d::$0 + to:func_bank2_d::@return +func_bank2_d::@return: scope:[func_bank2_d] from func_bank2_d::@1 + func_bank2_d::return#3 = phi( func_bank2_d::@1/func_bank2_d::return#0 ) + func_bank2_d::return#1 = func_bank2_d::return#3 + return + to:@return + +__bank(bank) char func_bank2_e(char a , char b) +func_bank2_e: scope:[func_bank2_e] from main::@10 + func_bank2_e::b#1 = phi( main::@10/func_bank2_e::b#0 ) + func_bank2_e::a#1 = phi( main::@10/func_bank2_e::a#0 ) + func_bank2_b::a#0 = func_bank2_e::a#1 + func_bank2_b::b#0 = func_bank2_e::b#1 + call func_bank2_b + func_bank2_b::return#0 = func_bank2_b::return#2 + to:func_bank2_e::@1 +func_bank2_e::@1: scope:[func_bank2_e] from func_bank2_e + func_bank2_b::return#4 = phi( func_bank2_e/func_bank2_b::return#0 ) + func_bank2_e::$0 = func_bank2_b::return#4 + func_bank2_e::return#0 = func_bank2_e::$0 + to:func_bank2_e::@return +func_bank2_e::@return: scope:[func_bank2_e] from func_bank2_e::@1 + func_bank2_e::return#3 = phi( func_bank2_e::@1/func_bank2_e::return#0 ) + func_bank2_e::return#1 = func_bank2_e::return#3 + return + to:@return + +__bank(bank) char func_bank2_f(char a , char b) +func_bank2_f: scope:[func_bank2_f] from main::@11 + func_bank2_f::b#1 = phi( main::@11/func_bank2_f::b#0 ) + func_bank2_f::a#1 = phi( main::@11/func_bank2_f::a#0 ) + func_bank1_b::a#0 = func_bank2_f::a#1 + func_bank1_b::b#0 = func_bank2_f::b#1 + call func_bank1_b + func_bank1_b::return#0 = func_bank1_b::return#2 + to:func_bank2_f::@1 +func_bank2_f::@1: scope:[func_bank2_f] from func_bank2_f + func_bank1_b::return#4 = phi( func_bank2_f/func_bank1_b::return#0 ) + func_bank2_f::$0 = func_bank1_b::return#4 + func_bank2_f::return#0 = func_bank2_f::$0 + to:func_bank2_f::@return +func_bank2_f::@return: scope:[func_bank2_f] from func_bank2_f::@1 + func_bank2_f::return#3 = phi( func_bank2_f::@1/func_bank2_f::return#0 ) + func_bank2_f::return#1 = func_bank2_f::return#3 + return + to:@return + +char func_bank1_b(char a , char b) +func_bank1_b: scope:[func_bank1_b] from func_bank2_f main::@1 + func_bank1_b::b#2 = phi( func_bank2_f/func_bank1_b::b#0, main::@1/func_bank1_b::b#1 ) + func_bank1_b::a#2 = phi( func_bank2_f/func_bank1_b::a#0, main::@1/func_bank1_b::a#1 ) + func_bank1_b::$0 = func_bank1_b::a#2 + func_bank1_b::b#2 + func_bank1_b::return#1 = func_bank1_b::$0 + to:func_bank1_b::@return +func_bank1_b::@return: scope:[func_bank1_b] from func_bank1_b + func_bank1_b::return#5 = phi( func_bank1_b/func_bank1_b::return#1 ) + func_bank1_b::return#2 = func_bank1_b::return#5 + return + to:@return + +char func_bank2_b(char a , char b) +func_bank2_b: scope:[func_bank2_b] from func_bank2_e main::@7 + func_bank2_b::b#2 = phi( func_bank2_e/func_bank2_b::b#0, main::@7/func_bank2_b::b#1 ) + func_bank2_b::a#2 = phi( func_bank2_e/func_bank2_b::a#0, main::@7/func_bank2_b::a#1 ) + func_bank2_b::$0 = func_bank2_b::a#2 + func_bank2_b::b#2 + func_bank2_b::return#1 = func_bank2_b::$0 + to:func_bank2_b::@return +func_bank2_b::@return: scope:[func_bank2_b] from func_bank2_b + func_bank2_b::return#5 = phi( func_bank2_b/func_bank2_b::return#1 ) + func_bank2_b::return#2 = func_bank2_b::return#5 + return + to:@return + +char func_bank1_e(char a , char b) +func_bank1_e: scope:[func_bank1_e] from main::@4 + func_bank1_e::b#1 = phi( main::@4/func_bank1_e::b#0 ) + func_bank1_e::a#1 = phi( main::@4/func_bank1_e::a#0 ) + func_bank1_a::a#2 = func_bank1_e::a#1 + func_bank1_a::b#2 = func_bank1_e::b#1 + call func_bank1_a + func_bank1_a::return#4 = func_bank1_a::return#1 + to:func_bank1_e::@1 +func_bank1_e::@1: scope:[func_bank1_e] from func_bank1_e + func_bank1_a::return#9 = phi( func_bank1_e/func_bank1_a::return#4 ) + func_bank1_e::$0 = func_bank1_a::return#9 + func_bank1_e::return#0 = func_bank1_e::$0 + to:func_bank1_e::@return +func_bank1_e::@return: scope:[func_bank1_e] from func_bank1_e::@1 + func_bank1_e::return#3 = phi( func_bank1_e::@1/func_bank1_e::return#0 ) + func_bank1_e::return#1 = func_bank1_e::return#3 + return + to:@return + +char func_bank1_f(char a , char b) +func_bank1_f: scope:[func_bank1_f] from main::@5 + func_bank1_f::b#1 = phi( main::@5/func_bank1_f::b#0 ) + func_bank1_f::a#1 = phi( main::@5/func_bank1_f::a#0 ) + func_bank2_a::a#2 = func_bank1_f::a#1 + func_bank2_a::b#2 = func_bank1_f::b#1 + call func_bank2_a + func_bank2_a::return#4 = func_bank2_a::return#2 + to:func_bank1_f::@1 +func_bank1_f::@1: scope:[func_bank1_f] from func_bank1_f + func_bank2_a::return#9 = phi( func_bank1_f/func_bank2_a::return#4 ) + func_bank1_f::$0 = func_bank2_a::return#9 + func_bank1_f::return#0 = func_bank1_f::$0 + to:func_bank1_f::@return +func_bank1_f::@return: scope:[func_bank1_f] from func_bank1_f::@1 + func_bank1_f::return#3 = phi( func_bank1_f::@1/func_bank1_f::return#0 ) + func_bank1_f::return#1 = func_bank1_f::return#3 + return + to:@return + +void main() +main: scope:[main] from __start + func_bank1_a::a#3 = '0' + func_bank1_a::b#3 = 7 + call func_bank1_a + func_bank1_a::return#5 = func_bank1_a::return#1 + to:main::@1 +main::@1: scope:[main] from main + func_bank1_a::return#10 = phi( main/func_bank1_a::return#5 ) + main::$0 = func_bank1_a::return#10 + SCREEN[0] = main::$0 + func_bank1_b::a#1 = '0' + func_bank1_b::b#1 = 7 + call func_bank1_b + func_bank1_b::return#3 = func_bank1_b::return#2 + to:main::@2 +main::@2: scope:[main] from main::@1 + func_bank1_b::return#6 = phi( main::@1/func_bank1_b::return#3 ) + main::$1 = func_bank1_b::return#6 + SCREEN[0] = main::$1 + func_bank1_c::a#0 = '0' + func_bank1_c::b#0 = 7 + call func_bank1_c + func_bank1_c::return#2 = func_bank1_c::return#1 + to:main::@3 +main::@3: scope:[main] from main::@2 + func_bank1_c::return#4 = phi( main::@2/func_bank1_c::return#2 ) + main::$2 = func_bank1_c::return#4 + SCREEN[0] = main::$2 + func_bank1_d::a#0 = '0' + func_bank1_d::b#0 = 7 + call func_bank1_d + func_bank1_d::return#2 = func_bank1_d::return#1 + to:main::@4 +main::@4: scope:[main] from main::@3 + func_bank1_d::return#4 = phi( main::@3/func_bank1_d::return#2 ) + main::$3 = func_bank1_d::return#4 + SCREEN[0] = main::$3 + func_bank1_e::a#0 = '0' + func_bank1_e::b#0 = 7 + call func_bank1_e + func_bank1_e::return#2 = func_bank1_e::return#1 + to:main::@5 +main::@5: scope:[main] from main::@4 + func_bank1_e::return#4 = phi( main::@4/func_bank1_e::return#2 ) + main::$4 = func_bank1_e::return#4 + SCREEN[0] = main::$4 + func_bank1_f::a#0 = '0' + func_bank1_f::b#0 = 7 + call func_bank1_f + func_bank1_f::return#2 = func_bank1_f::return#1 + to:main::@6 +main::@6: scope:[main] from main::@5 + func_bank1_f::return#4 = phi( main::@5/func_bank1_f::return#2 ) + main::$5 = func_bank1_f::return#4 + SCREEN[0] = main::$5 + func_bank2_a::a#3 = '0' + func_bank2_a::b#3 = 7 + call func_bank2_a + func_bank2_a::return#5 = func_bank2_a::return#2 + to:main::@7 +main::@7: scope:[main] from main::@6 + func_bank2_a::return#10 = phi( main::@6/func_bank2_a::return#5 ) + main::$6 = func_bank2_a::return#10 + SCREEN[0] = main::$6 + func_bank2_b::a#1 = '0' + func_bank2_b::b#1 = 7 + call func_bank2_b + func_bank2_b::return#3 = func_bank2_b::return#2 + to:main::@8 +main::@8: scope:[main] from main::@7 + func_bank2_b::return#6 = phi( main::@7/func_bank2_b::return#3 ) + main::$7 = func_bank2_b::return#6 + SCREEN[0] = main::$7 + func_bank2_c::a#0 = '0' + func_bank2_c::b#0 = 7 + call func_bank2_c + func_bank2_c::return#2 = func_bank2_c::return#1 + to:main::@9 +main::@9: scope:[main] from main::@8 + func_bank2_c::return#4 = phi( main::@8/func_bank2_c::return#2 ) + main::$8 = func_bank2_c::return#4 + SCREEN[0] = main::$8 + func_bank2_d::a#0 = '0' + func_bank2_d::b#0 = 7 + call func_bank2_d + func_bank2_d::return#2 = func_bank2_d::return#1 + to:main::@10 +main::@10: scope:[main] from main::@9 + func_bank2_d::return#4 = phi( main::@9/func_bank2_d::return#2 ) + main::$9 = func_bank2_d::return#4 + SCREEN[0] = main::$9 + func_bank2_e::a#0 = '0' + func_bank2_e::b#0 = 7 + call func_bank2_e + func_bank2_e::return#2 = func_bank2_e::return#1 + to:main::@11 +main::@11: scope:[main] from main::@10 + func_bank2_e::return#4 = phi( main::@10/func_bank2_e::return#2 ) + main::$10 = func_bank2_e::return#4 + SCREEN[0] = main::$10 + func_bank2_f::a#0 = '0' + func_bank2_f::b#0 = 7 + call func_bank2_f + func_bank2_f::return#2 = func_bank2_f::return#1 + to:main::@12 +main::@12: scope:[main] from main::@11 + func_bank2_f::return#4 = phi( main::@11/func_bank2_f::return#2 ) + main::$11 = func_bank2_f::return#4 + SCREEN[0] = main::$11 + to:main::@return +main::@return: scope:[main] from main::@12 + return + to:@return + +void __start() +__start: scope:[__start] from + call main + to:__start::@1 +__start::@1: scope:[__start] from __start + to:__start::@return +__start::@return: scope:[__start] from __start::@1 + return + to:@return + +SYMBOL TABLE SSA +__constant char * const SCREEN = (char *)$400 +void __start() +__bank(bank) char func_bank1_a(char a , char b) +char func_bank1_a::$0 +char func_bank1_a::a +char func_bank1_a::a#0 +char func_bank1_a::a#1 +char func_bank1_a::a#2 +char func_bank1_a::a#3 +char func_bank1_a::a#4 +char func_bank1_a::b +char func_bank1_a::b#0 +char func_bank1_a::b#1 +char func_bank1_a::b#2 +char func_bank1_a::b#3 +char func_bank1_a::b#4 +char func_bank1_a::return +char func_bank1_a::return#0 +char func_bank1_a::return#1 +char func_bank1_a::return#10 +char func_bank1_a::return#2 +char func_bank1_a::return#3 +char func_bank1_a::return#4 +char func_bank1_a::return#5 +char func_bank1_a::return#6 +char func_bank1_a::return#7 +char func_bank1_a::return#8 +char func_bank1_a::return#9 +char func_bank1_b(char a , char b) +char func_bank1_b::$0 +char func_bank1_b::a +char func_bank1_b::a#0 +char func_bank1_b::a#1 +char func_bank1_b::a#2 +char func_bank1_b::b +char func_bank1_b::b#0 +char func_bank1_b::b#1 +char func_bank1_b::b#2 +char func_bank1_b::return +char func_bank1_b::return#0 +char func_bank1_b::return#1 +char func_bank1_b::return#2 +char func_bank1_b::return#3 +char func_bank1_b::return#4 +char func_bank1_b::return#5 +char func_bank1_b::return#6 +__bank(bank) char func_bank1_c(char a , char b) +char func_bank1_c::$0 +char func_bank1_c::a +char func_bank1_c::a#0 +char func_bank1_c::a#1 +char func_bank1_c::b +char func_bank1_c::b#0 +char func_bank1_c::b#1 +char func_bank1_c::return +char func_bank1_c::return#0 +char func_bank1_c::return#1 +char func_bank1_c::return#2 +char func_bank1_c::return#3 +char func_bank1_c::return#4 +__bank(bank) char func_bank1_d(char a , char b) +char func_bank1_d::$0 +char func_bank1_d::a +char func_bank1_d::a#0 +char func_bank1_d::a#1 +char func_bank1_d::b +char func_bank1_d::b#0 +char func_bank1_d::b#1 +char func_bank1_d::return +char func_bank1_d::return#0 +char func_bank1_d::return#1 +char func_bank1_d::return#2 +char func_bank1_d::return#3 +char func_bank1_d::return#4 +char func_bank1_e(char a , char b) +char func_bank1_e::$0 +char func_bank1_e::a +char func_bank1_e::a#0 +char func_bank1_e::a#1 +char func_bank1_e::b +char func_bank1_e::b#0 +char func_bank1_e::b#1 +char func_bank1_e::return +char func_bank1_e::return#0 +char func_bank1_e::return#1 +char func_bank1_e::return#2 +char func_bank1_e::return#3 +char func_bank1_e::return#4 +char func_bank1_f(char a , char b) +char func_bank1_f::$0 +char func_bank1_f::a +char func_bank1_f::a#0 +char func_bank1_f::a#1 +char func_bank1_f::b +char func_bank1_f::b#0 +char func_bank1_f::b#1 +char func_bank1_f::return +char func_bank1_f::return#0 +char func_bank1_f::return#1 +char func_bank1_f::return#2 +char func_bank1_f::return#3 +char func_bank1_f::return#4 +__bank(bank) char func_bank2_a(char a , char b) +char func_bank2_a::$0 +char func_bank2_a::a +char func_bank2_a::a#0 +char func_bank2_a::a#1 +char func_bank2_a::a#2 +char func_bank2_a::a#3 +char func_bank2_a::a#4 +char func_bank2_a::b +char func_bank2_a::b#0 +char func_bank2_a::b#1 +char func_bank2_a::b#2 +char func_bank2_a::b#3 +char func_bank2_a::b#4 +char func_bank2_a::return +char func_bank2_a::return#0 +char func_bank2_a::return#1 +char func_bank2_a::return#10 +char func_bank2_a::return#2 +char func_bank2_a::return#3 +char func_bank2_a::return#4 +char func_bank2_a::return#5 +char func_bank2_a::return#6 +char func_bank2_a::return#7 +char func_bank2_a::return#8 +char func_bank2_a::return#9 +char func_bank2_b(char a , char b) +char func_bank2_b::$0 +char func_bank2_b::a +char func_bank2_b::a#0 +char func_bank2_b::a#1 +char func_bank2_b::a#2 +char func_bank2_b::b +char func_bank2_b::b#0 +char func_bank2_b::b#1 +char func_bank2_b::b#2 +char func_bank2_b::return +char func_bank2_b::return#0 +char func_bank2_b::return#1 +char func_bank2_b::return#2 +char func_bank2_b::return#3 +char func_bank2_b::return#4 +char func_bank2_b::return#5 +char func_bank2_b::return#6 +__bank(bank) char func_bank2_c(char a , char b) +char func_bank2_c::$0 +char func_bank2_c::a +char func_bank2_c::a#0 +char func_bank2_c::a#1 +char func_bank2_c::b +char func_bank2_c::b#0 +char func_bank2_c::b#1 +char func_bank2_c::return +char func_bank2_c::return#0 +char func_bank2_c::return#1 +char func_bank2_c::return#2 +char func_bank2_c::return#3 +char func_bank2_c::return#4 +__bank(bank) char func_bank2_d(char a , char b) +char func_bank2_d::$0 +char func_bank2_d::a +char func_bank2_d::a#0 +char func_bank2_d::a#1 +char func_bank2_d::b +char func_bank2_d::b#0 +char func_bank2_d::b#1 +char func_bank2_d::return +char func_bank2_d::return#0 +char func_bank2_d::return#1 +char func_bank2_d::return#2 +char func_bank2_d::return#3 +char func_bank2_d::return#4 +__bank(bank) char func_bank2_e(char a , char b) +char func_bank2_e::$0 +char func_bank2_e::a +char func_bank2_e::a#0 +char func_bank2_e::a#1 +char func_bank2_e::b +char func_bank2_e::b#0 +char func_bank2_e::b#1 +char func_bank2_e::return +char func_bank2_e::return#0 +char func_bank2_e::return#1 +char func_bank2_e::return#2 +char func_bank2_e::return#3 +char func_bank2_e::return#4 +__bank(bank) char func_bank2_f(char a , char b) +char func_bank2_f::$0 +char func_bank2_f::a +char func_bank2_f::a#0 +char func_bank2_f::a#1 +char func_bank2_f::b +char func_bank2_f::b#0 +char func_bank2_f::b#1 +char func_bank2_f::return +char func_bank2_f::return#0 +char func_bank2_f::return#1 +char func_bank2_f::return#2 +char func_bank2_f::return#3 +char func_bank2_f::return#4 +void main() +char main::$0 +char main::$1 +char main::$10 +char main::$11 +char main::$2 +char main::$3 +char main::$4 +char main::$5 +char main::$6 +char main::$7 +char main::$8 +char main::$9 + +Adding number conversion cast (unumber) 7 in func_bank1_a::b#3 = 7 +Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$0 +Adding number conversion cast (unumber) 7 in func_bank1_b::b#1 = 7 +Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$1 +Adding number conversion cast (unumber) 7 in func_bank1_c::b#0 = 7 +Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$2 +Adding number conversion cast (unumber) 7 in func_bank1_d::b#0 = 7 +Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$3 +Adding number conversion cast (unumber) 7 in func_bank1_e::b#0 = 7 +Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$4 +Adding number conversion cast (unumber) 7 in func_bank1_f::b#0 = 7 +Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$5 +Adding number conversion cast (unumber) 7 in func_bank2_a::b#3 = 7 +Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$6 +Adding number conversion cast (unumber) 7 in func_bank2_b::b#1 = 7 +Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$7 +Adding number conversion cast (unumber) 7 in func_bank2_c::b#0 = 7 +Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$8 +Adding number conversion cast (unumber) 7 in func_bank2_d::b#0 = 7 +Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$9 +Adding number conversion cast (unumber) 7 in func_bank2_e::b#0 = 7 +Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$10 +Adding number conversion cast (unumber) 7 in func_bank2_f::b#0 = 7 +Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$11 +Successful SSA optimization PassNAddNumberTypeConversions +Inlining cast func_bank1_a::b#3 = (unumber)7 +Inlining cast func_bank1_b::b#1 = (unumber)7 +Inlining cast func_bank1_c::b#0 = (unumber)7 +Inlining cast func_bank1_d::b#0 = (unumber)7 +Inlining cast func_bank1_e::b#0 = (unumber)7 +Inlining cast func_bank1_f::b#0 = (unumber)7 +Inlining cast func_bank2_a::b#3 = (unumber)7 +Inlining cast func_bank2_b::b#1 = (unumber)7 +Inlining cast func_bank2_c::b#0 = (unumber)7 +Inlining cast func_bank2_d::b#0 = (unumber)7 +Inlining cast func_bank2_e::b#0 = (unumber)7 +Inlining cast func_bank2_f::b#0 = (unumber)7 +Successful SSA optimization Pass2InlineCast +Simplifying constant pointer cast (char *) 1024 +Simplifying constant integer cast 7 +Simplifying constant integer cast 0 +Simplifying constant integer cast 7 +Simplifying constant integer cast 0 +Simplifying constant integer cast 7 +Simplifying constant integer cast 0 +Simplifying constant integer cast 7 +Simplifying constant integer cast 0 +Simplifying constant integer cast 7 +Simplifying constant integer cast 0 +Simplifying constant integer cast 7 +Simplifying constant integer cast 0 +Simplifying constant integer cast 7 +Simplifying constant integer cast 0 +Simplifying constant integer cast 7 +Simplifying constant integer cast 0 +Simplifying constant integer cast 7 +Simplifying constant integer cast 0 +Simplifying constant integer cast 7 +Simplifying constant integer cast 0 +Simplifying constant integer cast 7 +Simplifying constant integer cast 0 +Simplifying constant integer cast 7 +Simplifying constant integer cast 0 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (char) 7 +Finalized unsigned number type (char) 0 +Finalized unsigned number type (char) 7 +Finalized unsigned number type (char) 0 +Finalized unsigned number type (char) 7 +Finalized unsigned number type (char) 0 +Finalized unsigned number type (char) 7 +Finalized unsigned number type (char) 0 +Finalized unsigned number type (char) 7 +Finalized unsigned number type (char) 0 +Finalized unsigned number type (char) 7 +Finalized unsigned number type (char) 0 +Finalized unsigned number type (char) 7 +Finalized unsigned number type (char) 0 +Finalized unsigned number type (char) 7 +Finalized unsigned number type (char) 0 +Finalized unsigned number type (char) 7 +Finalized unsigned number type (char) 0 +Finalized unsigned number type (char) 7 +Finalized unsigned number type (char) 0 +Finalized unsigned number type (char) 7 +Finalized unsigned number type (char) 0 +Finalized unsigned number type (char) 7 +Finalized unsigned number type (char) 0 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Alias func_bank1_a::return#0 = func_bank1_a::$0 func_bank1_a::return#6 func_bank1_a::return#1 +Alias func_bank1_a::return#2 = func_bank1_a::return#7 +Alias func_bank1_c::return#0 = func_bank1_c::$0 func_bank1_c::return#3 func_bank1_c::return#1 +Alias func_bank2_a::return#0 = func_bank2_a::return#6 +Alias func_bank1_d::return#0 = func_bank1_d::$0 func_bank1_d::return#3 func_bank1_d::return#1 +Alias func_bank2_a::return#1 = func_bank2_a::$0 func_bank2_a::return#7 func_bank2_a::return#2 +Alias func_bank1_a::return#3 = func_bank1_a::return#8 +Alias func_bank2_c::return#0 = func_bank2_c::$0 func_bank2_c::return#3 func_bank2_c::return#1 +Alias func_bank2_a::return#3 = func_bank2_a::return#8 +Alias func_bank2_d::return#0 = func_bank2_d::$0 func_bank2_d::return#3 func_bank2_d::return#1 +Alias func_bank2_b::return#0 = func_bank2_b::return#4 +Alias func_bank2_e::return#0 = func_bank2_e::$0 func_bank2_e::return#3 func_bank2_e::return#1 +Alias func_bank1_b::return#0 = func_bank1_b::return#4 +Alias func_bank2_f::return#0 = func_bank2_f::$0 func_bank2_f::return#3 func_bank2_f::return#1 +Alias func_bank1_b::return#1 = func_bank1_b::$0 func_bank1_b::return#5 func_bank1_b::return#2 +Alias func_bank2_b::return#1 = func_bank2_b::$0 func_bank2_b::return#5 func_bank2_b::return#2 +Alias func_bank1_a::return#4 = func_bank1_a::return#9 +Alias func_bank1_e::return#0 = func_bank1_e::$0 func_bank1_e::return#3 func_bank1_e::return#1 +Alias func_bank2_a::return#4 = func_bank2_a::return#9 +Alias func_bank1_f::return#0 = func_bank1_f::$0 func_bank1_f::return#3 func_bank1_f::return#1 +Alias func_bank1_a::return#10 = func_bank1_a::return#5 +Alias func_bank1_b::return#3 = func_bank1_b::return#6 +Alias func_bank1_c::return#2 = func_bank1_c::return#4 +Alias func_bank1_d::return#2 = func_bank1_d::return#4 +Alias func_bank1_e::return#2 = func_bank1_e::return#4 +Alias func_bank1_f::return#2 = func_bank1_f::return#4 +Alias func_bank2_a::return#10 = func_bank2_a::return#5 +Alias func_bank2_b::return#3 = func_bank2_b::return#6 +Alias func_bank2_c::return#2 = func_bank2_c::return#4 +Alias func_bank2_d::return#2 = func_bank2_d::return#4 +Alias func_bank2_e::return#2 = func_bank2_e::return#4 +Alias func_bank2_f::return#2 = func_bank2_f::return#4 +Successful SSA optimization Pass2AliasElimination +Identical Phi Values func_bank1_c::a#1 func_bank1_c::a#0 +Identical Phi Values func_bank1_c::b#1 func_bank1_c::b#0 +Identical Phi Values func_bank1_d::a#1 func_bank1_d::a#0 +Identical Phi Values func_bank1_d::b#1 func_bank1_d::b#0 +Identical Phi Values func_bank2_c::a#1 func_bank2_c::a#0 +Identical Phi Values func_bank2_c::b#1 func_bank2_c::b#0 +Identical Phi Values func_bank2_d::a#1 func_bank2_d::a#0 +Identical Phi Values func_bank2_d::b#1 func_bank2_d::b#0 +Identical Phi Values func_bank2_e::a#1 func_bank2_e::a#0 +Identical Phi Values func_bank2_e::b#1 func_bank2_e::b#0 +Identical Phi Values func_bank2_f::a#1 func_bank2_f::a#0 +Identical Phi Values func_bank2_f::b#1 func_bank2_f::b#0 +Identical Phi Values func_bank1_e::a#1 func_bank1_e::a#0 +Identical Phi Values func_bank1_e::b#1 func_bank1_e::b#0 +Identical Phi Values func_bank1_f::a#1 func_bank1_f::a#0 +Identical Phi Values func_bank1_f::b#1 func_bank1_f::b#0 +Successful SSA optimization Pass2IdenticalPhiElimination +Constant func_bank1_a::a#3 = '0' +Constant func_bank1_a::b#3 = 7 +Constant func_bank1_b::a#1 = '0' +Constant func_bank1_b::b#1 = 7 +Constant func_bank1_c::a#0 = '0' +Constant func_bank1_c::b#0 = 7 +Constant func_bank1_d::a#0 = '0' +Constant func_bank1_d::b#0 = 7 +Constant func_bank1_e::a#0 = '0' +Constant func_bank1_e::b#0 = 7 +Constant func_bank1_f::a#0 = '0' +Constant func_bank1_f::b#0 = 7 +Constant func_bank2_a::a#3 = '0' +Constant func_bank2_a::b#3 = 7 +Constant func_bank2_b::a#1 = '0' +Constant func_bank2_b::b#1 = 7 +Constant func_bank2_c::a#0 = '0' +Constant func_bank2_c::b#0 = 7 +Constant func_bank2_d::a#0 = '0' +Constant func_bank2_d::b#0 = 7 +Constant func_bank2_e::a#0 = '0' +Constant func_bank2_e::b#0 = 7 +Constant func_bank2_f::a#0 = '0' +Constant func_bank2_f::b#0 = 7 +Successful SSA optimization Pass2ConstantIdentification +Constant func_bank1_a::a#0 = func_bank1_c::a#0 +Constant func_bank1_a::b#0 = func_bank1_c::b#0 +Constant func_bank2_a::a#0 = func_bank1_d::a#0 +Constant func_bank2_a::b#0 = func_bank1_d::b#0 +Constant func_bank1_a::a#1 = func_bank2_c::a#0 +Constant func_bank1_a::b#1 = func_bank2_c::b#0 +Constant func_bank2_a::a#1 = func_bank2_d::a#0 +Constant func_bank2_a::b#1 = func_bank2_d::b#0 +Constant func_bank2_b::a#0 = func_bank2_e::a#0 +Constant func_bank2_b::b#0 = func_bank2_e::b#0 +Constant func_bank1_b::a#0 = func_bank2_f::a#0 +Constant func_bank1_b::b#0 = func_bank2_f::b#0 +Constant func_bank1_a::a#2 = func_bank1_e::a#0 +Constant func_bank1_a::b#2 = func_bank1_e::b#0 +Constant func_bank2_a::a#2 = func_bank1_f::a#0 +Constant func_bank2_a::b#2 = func_bank1_f::b#0 +Successful SSA optimization Pass2ConstantIdentification +Simplifying expression containing zero SCREEN in [73] SCREEN[0] = main::$0 +Simplifying expression containing zero SCREEN in [79] SCREEN[0] = main::$1 +Simplifying expression containing zero SCREEN in [85] SCREEN[0] = main::$2 +Simplifying expression containing zero SCREEN in [91] SCREEN[0] = main::$3 +Simplifying expression containing zero SCREEN in [97] SCREEN[0] = main::$4 +Simplifying expression containing zero SCREEN in [103] SCREEN[0] = main::$5 +Simplifying expression containing zero SCREEN in [109] SCREEN[0] = main::$6 +Simplifying expression containing zero SCREEN in [115] SCREEN[0] = main::$7 +Simplifying expression containing zero SCREEN in [121] SCREEN[0] = main::$8 +Simplifying expression containing zero SCREEN in [127] SCREEN[0] = main::$9 +Simplifying expression containing zero SCREEN in [133] SCREEN[0] = main::$10 +Simplifying expression containing zero SCREEN in [139] SCREEN[0] = main::$11 +Successful SSA optimization PassNSimplifyExpressionWithZero +Removing unused procedure __start +Removing unused procedure block __start +Removing unused procedure block __start::@1 +Removing unused procedure block __start::@return +Successful SSA optimization PassNEliminateEmptyStart +Inlining constant with var siblings func_bank1_a::a#3 +Inlining constant with var siblings func_bank1_a::b#3 +Inlining constant with var siblings func_bank1_a::a#0 +Inlining constant with var siblings func_bank1_a::b#0 +Inlining constant with var siblings func_bank1_a::a#1 +Inlining constant with var siblings func_bank1_a::b#1 +Inlining constant with var siblings func_bank1_a::a#2 +Inlining constant with var siblings func_bank1_a::b#2 +Inlining constant with var siblings func_bank2_a::a#3 +Inlining constant with var siblings func_bank2_a::b#3 +Inlining constant with var siblings func_bank2_a::a#0 +Inlining constant with var siblings func_bank2_a::b#0 +Inlining constant with var siblings func_bank2_a::a#1 +Inlining constant with var siblings func_bank2_a::b#1 +Inlining constant with var siblings func_bank2_a::a#2 +Inlining constant with var siblings func_bank2_a::b#2 +Inlining constant with var siblings func_bank1_b::a#1 +Inlining constant with var siblings func_bank1_b::b#1 +Inlining constant with var siblings func_bank1_b::a#0 +Inlining constant with var siblings func_bank1_b::b#0 +Inlining constant with var siblings func_bank2_b::a#1 +Inlining constant with var siblings func_bank2_b::b#1 +Inlining constant with var siblings func_bank2_b::a#0 +Inlining constant with var siblings func_bank2_b::b#0 +Constant inlined func_bank1_a::b#0 = func_bank1_c::b#0 +Constant inlined func_bank1_a::a#1 = func_bank2_c::a#0 +Constant inlined func_bank2_a::b#2 = func_bank1_f::b#0 +Constant inlined func_bank2_a::a#3 = '0' +Constant inlined func_bank1_a::a#0 = func_bank1_c::a#0 +Constant inlined func_bank2_a::b#3 = 7 +Constant inlined func_bank2_a::a#0 = func_bank1_d::a#0 +Constant inlined func_bank1_a::b#3 = 7 +Constant inlined func_bank1_a::b#2 = func_bank1_e::b#0 +Constant inlined func_bank2_a::b#0 = func_bank1_d::b#0 +Constant inlined func_bank2_a::a#1 = func_bank2_d::a#0 +Constant inlined func_bank1_a::a#3 = '0' +Constant inlined func_bank1_a::b#1 = func_bank2_c::b#0 +Constant inlined func_bank1_a::a#2 = func_bank1_e::a#0 +Constant inlined func_bank2_a::b#1 = func_bank2_d::b#0 +Constant inlined func_bank2_a::a#2 = func_bank1_f::a#0 +Constant inlined func_bank2_b::b#0 = func_bank2_e::b#0 +Constant inlined func_bank2_b::a#1 = '0' +Constant inlined func_bank1_b::a#0 = func_bank2_f::a#0 +Constant inlined func_bank2_b::a#0 = func_bank2_e::a#0 +Constant inlined func_bank1_b::b#0 = func_bank2_f::b#0 +Constant inlined func_bank1_b::a#1 = '0' +Constant inlined func_bank1_b::b#1 = 7 +Constant inlined func_bank2_b::b#1 = 7 +Successful SSA optimization Pass2ConstantInlining +Adding NOP phi() at start of main +Adding NOP phi() at start of func_bank1_c +Adding NOP phi() at start of func_bank1_d +Adding NOP phi() at start of func_bank1_e +Adding NOP phi() at start of func_bank1_f +Adding NOP phi() at start of func_bank2_c +Adding NOP phi() at start of func_bank2_d +Adding NOP phi() at start of func_bank2_e +Adding NOP phi() at start of func_bank2_f +CALL GRAPH +Calls in [main] to func_bank1_a:1 func_bank1_b:5 func_bank1_c:9 func_bank1_d:13 func_bank1_e:17 func_bank1_f:21 func_bank2_a:25 func_bank2_b:29 func_bank2_c:33 func_bank2_d:37 func_bank2_e:41 func_bank2_f:45 +Calls in [func_bank1_c] to func_bank1_a:57 +Calls in [func_bank1_d] to func_bank2_a:62 +Calls in [func_bank1_e] to func_bank1_a:67 +Calls in [func_bank1_f] to func_bank2_a:72 +Calls in [func_bank2_c] to func_bank1_a:83 +Calls in [func_bank2_d] to func_bank2_a:88 +Calls in [func_bank2_e] to func_bank2_b:93 +Calls in [func_bank2_f] to func_bank1_b:98 + +Created 8 initial phi equivalence classes +Coalesced down to 8 phi equivalence classes +Adding NOP phi() at start of main +Adding NOP phi() at start of func_bank1_c +Adding NOP phi() at start of func_bank1_d +Adding NOP phi() at start of func_bank1_e +Adding NOP phi() at start of func_bank1_f +Adding NOP phi() at start of func_bank2_c +Adding NOP phi() at start of func_bank2_d +Adding NOP phi() at start of func_bank2_e +Adding NOP phi() at start of func_bank2_f + +FINAL CONTROL FLOW GRAPH + +void main() +main: scope:[main] from + [0] phi() + [1] call func_bank1_a + [2] func_bank1_a::return#10 = func_bank1_a::return#0 + to:main::@1 +main::@1: scope:[main] from main + [3] main::$0 = func_bank1_a::return#10 + [4] *SCREEN = main::$0 + [5] call func_bank1_b + [6] func_bank1_b::return#3 = func_bank1_b::return#1 + to:main::@2 +main::@2: scope:[main] from main::@1 + [7] main::$1 = func_bank1_b::return#3 + [8] *SCREEN = main::$1 + [9] call func_bank1_c + [10] func_bank1_c::return#2 = func_bank1_c::return#0 + to:main::@3 +main::@3: scope:[main] from main::@2 + [11] main::$2 = func_bank1_c::return#2 + [12] *SCREEN = main::$2 + [13] call func_bank1_d + [14] func_bank1_d::return#2 = func_bank1_d::return#0 + to:main::@4 +main::@4: scope:[main] from main::@3 + [15] main::$3 = func_bank1_d::return#2 + [16] *SCREEN = main::$3 + [17] call func_bank1_e + [18] func_bank1_e::return#2 = func_bank1_e::return#0 + to:main::@5 +main::@5: scope:[main] from main::@4 + [19] main::$4 = func_bank1_e::return#2 + [20] *SCREEN = main::$4 + [21] call func_bank1_f + [22] func_bank1_f::return#2 = func_bank1_f::return#0 + to:main::@6 +main::@6: scope:[main] from main::@5 + [23] main::$5 = func_bank1_f::return#2 + [24] *SCREEN = main::$5 + [25] call func_bank2_a + [26] func_bank2_a::return#10 = func_bank2_a::return#1 + to:main::@7 +main::@7: scope:[main] from main::@6 + [27] main::$6 = func_bank2_a::return#10 + [28] *SCREEN = main::$6 + [29] call func_bank2_b + [30] func_bank2_b::return#3 = func_bank2_b::return#1 + to:main::@8 +main::@8: scope:[main] from main::@7 + [31] main::$7 = func_bank2_b::return#3 + [32] *SCREEN = main::$7 + [33] call func_bank2_c + [34] func_bank2_c::return#2 = func_bank2_c::return#0 + to:main::@9 +main::@9: scope:[main] from main::@8 + [35] main::$8 = func_bank2_c::return#2 + [36] *SCREEN = main::$8 + [37] call func_bank2_d + [38] func_bank2_d::return#2 = func_bank2_d::return#0 + to:main::@10 +main::@10: scope:[main] from main::@9 + [39] main::$9 = func_bank2_d::return#2 + [40] *SCREEN = main::$9 + [41] call func_bank2_e + [42] func_bank2_e::return#2 = func_bank2_e::return#0 + to:main::@11 +main::@11: scope:[main] from main::@10 + [43] main::$10 = func_bank2_e::return#2 + [44] *SCREEN = main::$10 + [45] call func_bank2_f + [46] func_bank2_f::return#2 = func_bank2_f::return#0 + to:main::@12 +main::@12: scope:[main] from main::@11 + [47] main::$11 = func_bank2_f::return#2 + [48] *SCREEN = main::$11 + to:main::@return +main::@return: scope:[main] from main::@12 + [49] return + to:@return + +__bank(bank) char func_bank1_a(char a , char b) +func_bank1_a: scope:[func_bank1_a] from func_bank1_c func_bank1_e func_bank2_c main + [50] func_bank1_a::b#4 = phi( func_bank1_c/func_bank1_c::b#0, func_bank1_e/func_bank1_e::b#0, func_bank2_c/func_bank2_c::b#0, main/7 ) + [50] func_bank1_a::a#4 = phi( func_bank1_c/func_bank1_c::a#0, func_bank1_e/func_bank1_e::a#0, func_bank2_c/func_bank2_c::a#0, main/'0' ) + [51] func_bank1_a::return#0 = func_bank1_a::a#4 + func_bank1_a::b#4 + to:func_bank1_a::@return +func_bank1_a::@return: scope:[func_bank1_a] from func_bank1_a + [52] return + to:@return + +char func_bank1_b(char a , char b) +func_bank1_b: scope:[func_bank1_b] from func_bank2_f main::@1 + [53] func_bank1_b::b#2 = phi( func_bank2_f/func_bank2_f::b#0, main::@1/7 ) + [53] func_bank1_b::a#2 = phi( func_bank2_f/func_bank2_f::a#0, main::@1/'0' ) + [54] func_bank1_b::return#1 = func_bank1_b::a#2 + func_bank1_b::b#2 + to:func_bank1_b::@return +func_bank1_b::@return: scope:[func_bank1_b] from func_bank1_b + [55] return + to:@return + +__bank(bank) char func_bank1_c(char a , char b) +func_bank1_c: scope:[func_bank1_c] from main::@2 + [56] phi() + [57] call func_bank1_a + [58] func_bank1_a::return#2 = func_bank1_a::return#0 + to:func_bank1_c::@1 +func_bank1_c::@1: scope:[func_bank1_c] from func_bank1_c + [59] func_bank1_c::return#0 = func_bank1_a::return#2 + to:func_bank1_c::@return +func_bank1_c::@return: scope:[func_bank1_c] from func_bank1_c::@1 + [60] return + to:@return + +__bank(bank) char func_bank1_d(char a , char b) +func_bank1_d: scope:[func_bank1_d] from main::@3 + [61] phi() + [62] call func_bank2_a + [63] func_bank2_a::return#0 = func_bank2_a::return#1 + to:func_bank1_d::@1 +func_bank1_d::@1: scope:[func_bank1_d] from func_bank1_d + [64] func_bank1_d::return#0 = func_bank2_a::return#0 + to:func_bank1_d::@return +func_bank1_d::@return: scope:[func_bank1_d] from func_bank1_d::@1 + [65] return + to:@return + +char func_bank1_e(char a , char b) +func_bank1_e: scope:[func_bank1_e] from main::@4 + [66] phi() + [67] call func_bank1_a + [68] func_bank1_a::return#4 = func_bank1_a::return#0 + to:func_bank1_e::@1 +func_bank1_e::@1: scope:[func_bank1_e] from func_bank1_e + [69] func_bank1_e::return#0 = func_bank1_a::return#4 + to:func_bank1_e::@return +func_bank1_e::@return: scope:[func_bank1_e] from func_bank1_e::@1 + [70] return + to:@return + +char func_bank1_f(char a , char b) +func_bank1_f: scope:[func_bank1_f] from main::@5 + [71] phi() + [72] call func_bank2_a + [73] func_bank2_a::return#4 = func_bank2_a::return#1 + to:func_bank1_f::@1 +func_bank1_f::@1: scope:[func_bank1_f] from func_bank1_f + [74] func_bank1_f::return#0 = func_bank2_a::return#4 + to:func_bank1_f::@return +func_bank1_f::@return: scope:[func_bank1_f] from func_bank1_f::@1 + [75] return + to:@return + +__bank(bank) char func_bank2_a(char a , char b) +func_bank2_a: scope:[func_bank2_a] from func_bank1_d func_bank1_f func_bank2_d main::@6 + [76] func_bank2_a::b#4 = phi( func_bank1_d/func_bank1_d::b#0, func_bank1_f/func_bank1_f::b#0, func_bank2_d/func_bank2_d::b#0, main::@6/7 ) + [76] func_bank2_a::a#4 = phi( func_bank1_d/func_bank1_d::a#0, func_bank1_f/func_bank1_f::a#0, func_bank2_d/func_bank2_d::a#0, main::@6/'0' ) + [77] func_bank2_a::return#1 = func_bank2_a::a#4 + func_bank2_a::b#4 + to:func_bank2_a::@return +func_bank2_a::@return: scope:[func_bank2_a] from func_bank2_a + [78] return + to:@return + +char func_bank2_b(char a , char b) +func_bank2_b: scope:[func_bank2_b] from func_bank2_e main::@7 + [79] func_bank2_b::b#2 = phi( func_bank2_e/func_bank2_e::b#0, main::@7/7 ) + [79] func_bank2_b::a#2 = phi( func_bank2_e/func_bank2_e::a#0, main::@7/'0' ) + [80] func_bank2_b::return#1 = func_bank2_b::a#2 + func_bank2_b::b#2 + to:func_bank2_b::@return +func_bank2_b::@return: scope:[func_bank2_b] from func_bank2_b + [81] return + to:@return + +__bank(bank) char func_bank2_c(char a , char b) +func_bank2_c: scope:[func_bank2_c] from main::@8 + [82] phi() + [83] call func_bank1_a + [84] func_bank1_a::return#3 = func_bank1_a::return#0 + to:func_bank2_c::@1 +func_bank2_c::@1: scope:[func_bank2_c] from func_bank2_c + [85] func_bank2_c::return#0 = func_bank1_a::return#3 + to:func_bank2_c::@return +func_bank2_c::@return: scope:[func_bank2_c] from func_bank2_c::@1 + [86] return + to:@return + +__bank(bank) char func_bank2_d(char a , char b) +func_bank2_d: scope:[func_bank2_d] from main::@9 + [87] phi() + [88] call func_bank2_a + [89] func_bank2_a::return#3 = func_bank2_a::return#1 + to:func_bank2_d::@1 +func_bank2_d::@1: scope:[func_bank2_d] from func_bank2_d + [90] func_bank2_d::return#0 = func_bank2_a::return#3 + to:func_bank2_d::@return +func_bank2_d::@return: scope:[func_bank2_d] from func_bank2_d::@1 + [91] return + to:@return + +__bank(bank) char func_bank2_e(char a , char b) +func_bank2_e: scope:[func_bank2_e] from main::@10 + [92] phi() + [93] call func_bank2_b + [94] func_bank2_b::return#0 = func_bank2_b::return#1 + to:func_bank2_e::@1 +func_bank2_e::@1: scope:[func_bank2_e] from func_bank2_e + [95] func_bank2_e::return#0 = func_bank2_b::return#0 + to:func_bank2_e::@return +func_bank2_e::@return: scope:[func_bank2_e] from func_bank2_e::@1 + [96] return + to:@return + +__bank(bank) char func_bank2_f(char a , char b) +func_bank2_f: scope:[func_bank2_f] from main::@11 + [97] phi() + [98] call func_bank1_b + [99] func_bank1_b::return#0 = func_bank1_b::return#1 + to:func_bank2_f::@1 +func_bank2_f::@1: scope:[func_bank2_f] from func_bank2_f + [100] func_bank2_f::return#0 = func_bank1_b::return#0 + to:func_bank2_f::@return +func_bank2_f::@return: scope:[func_bank2_f] from func_bank2_f::@1 + [101] return + to:@return + + +VARIABLE REGISTER WEIGHTS +__bank(bank) char func_bank1_a(char a , char b) +char func_bank1_a::a +char func_bank1_a::a#4 // 101.0 +char func_bank1_a::b +char func_bank1_a::b#4 // 101.0 +char func_bank1_a::return +char func_bank1_a::return#0 // 22.66666666666666 +char func_bank1_a::return#10 // 4.0 +char func_bank1_a::return#2 // 22.0 +char func_bank1_a::return#3 // 22.0 +char func_bank1_a::return#4 // 22.0 +char func_bank1_b(char a , char b) +char func_bank1_b::a +char func_bank1_b::a#2 // 101.0 +char func_bank1_b::b +char func_bank1_b::b#2 // 101.0 +char func_bank1_b::return +char func_bank1_b::return#0 // 22.0 +char func_bank1_b::return#1 // 28.5 +char func_bank1_b::return#3 // 4.0 +__bank(bank) char func_bank1_c(char a , char b) +char func_bank1_c::a +char func_bank1_c::b +char func_bank1_c::return +char func_bank1_c::return#0 // 4.333333333333333 +char func_bank1_c::return#2 // 4.0 +__bank(bank) char func_bank1_d(char a , char b) +char func_bank1_d::a +char func_bank1_d::b +char func_bank1_d::return +char func_bank1_d::return#0 // 4.333333333333333 +char func_bank1_d::return#2 // 4.0 +char func_bank1_e(char a , char b) +char func_bank1_e::a +char func_bank1_e::b +char func_bank1_e::return +char func_bank1_e::return#0 // 4.333333333333333 +char func_bank1_e::return#2 // 4.0 +char func_bank1_f(char a , char b) +char func_bank1_f::a +char func_bank1_f::b +char func_bank1_f::return +char func_bank1_f::return#0 // 4.333333333333333 +char func_bank1_f::return#2 // 4.0 +__bank(bank) char func_bank2_a(char a , char b) +char func_bank2_a::a +char func_bank2_a::a#4 // 101.0 +char func_bank2_a::b +char func_bank2_a::b#4 // 101.0 +char func_bank2_a::return +char func_bank2_a::return#0 // 22.0 +char func_bank2_a::return#1 // 22.666666666666664 +char func_bank2_a::return#10 // 4.0 +char func_bank2_a::return#3 // 22.0 +char func_bank2_a::return#4 // 22.0 +char func_bank2_b(char a , char b) +char func_bank2_b::a +char func_bank2_b::a#2 // 101.0 +char func_bank2_b::b +char func_bank2_b::b#2 // 101.0 +char func_bank2_b::return +char func_bank2_b::return#0 // 22.0 +char func_bank2_b::return#1 // 28.5 +char func_bank2_b::return#3 // 4.0 +__bank(bank) char func_bank2_c(char a , char b) +char func_bank2_c::a +char func_bank2_c::b +char func_bank2_c::return +char func_bank2_c::return#0 // 4.333333333333333 +char func_bank2_c::return#2 // 4.0 +__bank(bank) char func_bank2_d(char a , char b) +char func_bank2_d::a +char func_bank2_d::b +char func_bank2_d::return +char func_bank2_d::return#0 // 4.333333333333333 +char func_bank2_d::return#2 // 4.0 +__bank(bank) char func_bank2_e(char a , char b) +char func_bank2_e::a +char func_bank2_e::b +char func_bank2_e::return +char func_bank2_e::return#0 // 4.333333333333333 +char func_bank2_e::return#2 // 4.0 +__bank(bank) char func_bank2_f(char a , char b) +char func_bank2_f::a +char func_bank2_f::b +char func_bank2_f::return +char func_bank2_f::return#0 // 4.333333333333333 +char func_bank2_f::return#2 // 4.0 +void main() +char main::$0 // 4.0 +char main::$1 // 4.0 +char main::$10 // 4.0 +char main::$11 // 4.0 +char main::$2 // 4.0 +char main::$3 // 4.0 +char main::$4 // 4.0 +char main::$5 // 4.0 +char main::$6 // 4.0 +char main::$7 // 4.0 +char main::$8 // 4.0 +char main::$9 // 4.0 + +Initial phi equivalence classes +[ func_bank1_a::a#4 ] +[ func_bank1_a::b#4 ] +[ func_bank1_b::a#2 ] +[ func_bank1_b::b#2 ] +[ func_bank2_a::a#4 ] +[ func_bank2_a::b#4 ] +[ func_bank2_b::a#2 ] +[ func_bank2_b::b#2 ] +Added variable func_bank1_a::return#10 to live range equivalence class [ func_bank1_a::return#10 ] +Added variable main::$0 to live range equivalence class [ main::$0 ] +Added variable func_bank1_b::return#3 to live range equivalence class [ func_bank1_b::return#3 ] +Added variable main::$1 to live range equivalence class [ main::$1 ] +Added variable func_bank1_c::return#2 to live range equivalence class [ func_bank1_c::return#2 ] +Added variable main::$2 to live range equivalence class [ main::$2 ] +Added variable func_bank1_d::return#2 to live range equivalence class [ func_bank1_d::return#2 ] +Added variable main::$3 to live range equivalence class [ main::$3 ] +Added variable func_bank1_e::return#2 to live range equivalence class [ func_bank1_e::return#2 ] +Added variable main::$4 to live range equivalence class [ main::$4 ] +Added variable func_bank1_f::return#2 to live range equivalence class [ func_bank1_f::return#2 ] +Added variable main::$5 to live range equivalence class [ main::$5 ] +Added variable func_bank2_a::return#10 to live range equivalence class [ func_bank2_a::return#10 ] +Added variable main::$6 to live range equivalence class [ main::$6 ] +Added variable func_bank2_b::return#3 to live range equivalence class [ func_bank2_b::return#3 ] +Added variable main::$7 to live range equivalence class [ main::$7 ] +Added variable func_bank2_c::return#2 to live range equivalence class [ func_bank2_c::return#2 ] +Added variable main::$8 to live range equivalence class [ main::$8 ] +Added variable func_bank2_d::return#2 to live range equivalence class [ func_bank2_d::return#2 ] +Added variable main::$9 to live range equivalence class [ main::$9 ] +Added variable func_bank2_e::return#2 to live range equivalence class [ func_bank2_e::return#2 ] +Added variable main::$10 to live range equivalence class [ main::$10 ] +Added variable func_bank2_f::return#2 to live range equivalence class [ func_bank2_f::return#2 ] +Added variable main::$11 to live range equivalence class [ main::$11 ] +Added variable func_bank1_a::return#0 to live range equivalence class [ func_bank1_a::return#0 ] +Added variable func_bank1_b::return#1 to live range equivalence class [ func_bank1_b::return#1 ] +Added variable func_bank1_a::return#2 to live range equivalence class [ func_bank1_a::return#2 ] +Added variable func_bank1_c::return#0 to live range equivalence class [ func_bank1_c::return#0 ] +Added variable func_bank2_a::return#0 to live range equivalence class [ func_bank2_a::return#0 ] +Added variable func_bank1_d::return#0 to live range equivalence class [ func_bank1_d::return#0 ] +Added variable func_bank1_a::return#4 to live range equivalence class [ func_bank1_a::return#4 ] +Added variable func_bank1_e::return#0 to live range equivalence class [ func_bank1_e::return#0 ] +Added variable func_bank2_a::return#4 to live range equivalence class [ func_bank2_a::return#4 ] +Added variable func_bank1_f::return#0 to live range equivalence class [ func_bank1_f::return#0 ] +Added variable func_bank2_a::return#1 to live range equivalence class [ func_bank2_a::return#1 ] +Added variable func_bank2_b::return#1 to live range equivalence class [ func_bank2_b::return#1 ] +Added variable func_bank1_a::return#3 to live range equivalence class [ func_bank1_a::return#3 ] +Added variable func_bank2_c::return#0 to live range equivalence class [ func_bank2_c::return#0 ] +Added variable func_bank2_a::return#3 to live range equivalence class [ func_bank2_a::return#3 ] +Added variable func_bank2_d::return#0 to live range equivalence class [ func_bank2_d::return#0 ] +Added variable func_bank2_b::return#0 to live range equivalence class [ func_bank2_b::return#0 ] +Added variable func_bank2_e::return#0 to live range equivalence class [ func_bank2_e::return#0 ] +Added variable func_bank1_b::return#0 to live range equivalence class [ func_bank1_b::return#0 ] +Added variable func_bank2_f::return#0 to live range equivalence class [ func_bank2_f::return#0 ] +Complete equivalence classes +[ func_bank1_a::a#4 ] +[ func_bank1_a::b#4 ] +[ func_bank1_b::a#2 ] +[ func_bank1_b::b#2 ] +[ func_bank2_a::a#4 ] +[ func_bank2_a::b#4 ] +[ func_bank2_b::a#2 ] +[ func_bank2_b::b#2 ] +[ func_bank1_a::return#10 ] +[ main::$0 ] +[ func_bank1_b::return#3 ] +[ main::$1 ] +[ func_bank1_c::return#2 ] +[ main::$2 ] +[ func_bank1_d::return#2 ] +[ main::$3 ] +[ func_bank1_e::return#2 ] +[ main::$4 ] +[ func_bank1_f::return#2 ] +[ main::$5 ] +[ func_bank2_a::return#10 ] +[ main::$6 ] +[ func_bank2_b::return#3 ] +[ main::$7 ] +[ func_bank2_c::return#2 ] +[ main::$8 ] +[ func_bank2_d::return#2 ] +[ main::$9 ] +[ func_bank2_e::return#2 ] +[ main::$10 ] +[ func_bank2_f::return#2 ] +[ main::$11 ] +[ func_bank1_a::return#0 ] +[ func_bank1_b::return#1 ] +[ func_bank1_a::return#2 ] +[ func_bank1_c::return#0 ] +[ func_bank2_a::return#0 ] +[ func_bank1_d::return#0 ] +[ func_bank1_a::return#4 ] +[ func_bank1_e::return#0 ] +[ func_bank2_a::return#4 ] +[ func_bank1_f::return#0 ] +[ func_bank2_a::return#1 ] +[ func_bank2_b::return#1 ] +[ func_bank1_a::return#3 ] +[ func_bank2_c::return#0 ] +[ func_bank2_a::return#3 ] +[ func_bank2_d::return#0 ] +[ func_bank2_b::return#0 ] +[ func_bank2_e::return#0 ] +[ func_bank1_b::return#0 ] +[ func_bank2_f::return#0 ] +Allocated zp[1]:2 [ func_bank1_a::a#4 ] +Allocated zp[1]:3 [ func_bank1_a::b#4 ] +Allocated zp[1]:4 [ func_bank1_b::a#2 ] +Allocated zp[1]:5 [ func_bank1_b::b#2 ] +Allocated zp[1]:6 [ func_bank2_a::a#4 ] +Allocated zp[1]:7 [ func_bank2_a::b#4 ] +Allocated zp[1]:8 [ func_bank2_b::a#2 ] +Allocated zp[1]:9 [ func_bank2_b::b#2 ] +Allocated zp[1]:10 [ func_bank1_b::return#1 ] +Allocated zp[1]:11 [ func_bank2_b::return#1 ] +Allocated zp[1]:12 [ func_bank2_a::return#1 ] +Allocated zp[1]:13 [ func_bank1_a::return#0 ] +Allocated zp[1]:14 [ func_bank1_a::return#2 ] +Allocated zp[1]:15 [ func_bank2_a::return#0 ] +Allocated zp[1]:16 [ func_bank1_a::return#4 ] +Allocated zp[1]:17 [ func_bank2_a::return#4 ] +Allocated zp[1]:18 [ func_bank1_a::return#3 ] +Allocated zp[1]:19 [ func_bank2_a::return#3 ] +Allocated zp[1]:20 [ func_bank2_b::return#0 ] +Allocated zp[1]:21 [ func_bank1_b::return#0 ] +Allocated zp[1]:22 [ func_bank1_c::return#0 ] +Allocated zp[1]:23 [ func_bank1_d::return#0 ] +Allocated zp[1]:24 [ func_bank1_e::return#0 ] +Allocated zp[1]:25 [ func_bank1_f::return#0 ] +Allocated zp[1]:26 [ func_bank2_c::return#0 ] +Allocated zp[1]:27 [ func_bank2_d::return#0 ] +Allocated zp[1]:28 [ func_bank2_e::return#0 ] +Allocated zp[1]:29 [ func_bank2_f::return#0 ] +Allocated zp[1]:30 [ func_bank1_a::return#10 ] +Allocated zp[1]:31 [ main::$0 ] +Allocated zp[1]:32 [ func_bank1_b::return#3 ] +Allocated zp[1]:33 [ main::$1 ] +Allocated zp[1]:34 [ func_bank1_c::return#2 ] +Allocated zp[1]:35 [ main::$2 ] +Allocated zp[1]:36 [ func_bank1_d::return#2 ] +Allocated zp[1]:37 [ main::$3 ] +Allocated zp[1]:38 [ func_bank1_e::return#2 ] +Allocated zp[1]:39 [ main::$4 ] +Allocated zp[1]:40 [ func_bank1_f::return#2 ] +Allocated zp[1]:41 [ main::$5 ] +Allocated zp[1]:42 [ func_bank2_a::return#10 ] +Allocated zp[1]:43 [ main::$6 ] +Allocated zp[1]:44 [ func_bank2_b::return#3 ] +Allocated zp[1]:45 [ main::$7 ] +Allocated zp[1]:46 [ func_bank2_c::return#2 ] +Allocated zp[1]:47 [ main::$8 ] +Allocated zp[1]:48 [ func_bank2_d::return#2 ] +Allocated zp[1]:49 [ main::$9 ] +Allocated zp[1]:50 [ func_bank2_e::return#2 ] +Allocated zp[1]:51 [ main::$10 ] +Allocated zp[1]:52 [ func_bank2_f::return#2 ] +Allocated zp[1]:53 [ main::$11 ] +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [51] func_bank1_a::return#0 = func_bank1_a::a#4 + func_bank1_a::b#4 [ func_bank1_a::return#0 ] ( func_bank1_a:1 [ func_bank1_a::return#0 ] { { func_bank1_a::return#0 = func_bank1_a::return#10 } } func_bank1_c:9::func_bank1_a:57 [ func_bank1_a::return#0 ] { { func_bank1_c::return#0 = func_bank1_c::return#2 } { func_bank1_a::return#0 = func_bank1_a::return#2 } } func_bank1_e:17::func_bank1_a:67 [ func_bank1_a::return#0 ] { { func_bank1_e::return#0 = func_bank1_e::return#2 } { func_bank1_a::return#0 = func_bank1_a::return#4 } } func_bank2_c:33::func_bank1_a:83 [ func_bank1_a::return#0 ] { { func_bank2_c::return#0 = func_bank2_c::return#2 } { func_bank1_a::return#0 = func_bank1_a::return#3 } } ) always clobbers reg byte a +Statement [54] func_bank1_b::return#1 = func_bank1_b::a#2 + func_bank1_b::b#2 [ func_bank1_b::return#1 ] ( func_bank1_b:5 [ func_bank1_b::return#1 ] { { func_bank1_b::return#1 = func_bank1_b::return#3 } } func_bank2_f:45::func_bank1_b:98 [ func_bank1_b::return#1 ] { { func_bank2_f::return#0 = func_bank2_f::return#2 } { func_bank1_b::return#0 = func_bank1_b::return#1 } } ) always clobbers reg byte a +Statement [77] func_bank2_a::return#1 = func_bank2_a::a#4 + func_bank2_a::b#4 [ func_bank2_a::return#1 ] ( func_bank2_a:25 [ func_bank2_a::return#1 ] { { func_bank2_a::return#1 = func_bank2_a::return#10 } } func_bank1_d:13::func_bank2_a:62 [ func_bank2_a::return#1 ] { { func_bank1_d::return#0 = func_bank1_d::return#2 } { func_bank2_a::return#0 = func_bank2_a::return#1 } } func_bank1_f:21::func_bank2_a:72 [ func_bank2_a::return#1 ] { { func_bank1_f::return#0 = func_bank1_f::return#2 } { func_bank2_a::return#1 = func_bank2_a::return#4 } } func_bank2_d:37::func_bank2_a:88 [ func_bank2_a::return#1 ] { { func_bank2_d::return#0 = func_bank2_d::return#2 } { func_bank2_a::return#1 = func_bank2_a::return#3 } } ) always clobbers reg byte a +Statement [80] func_bank2_b::return#1 = func_bank2_b::a#2 + func_bank2_b::b#2 [ func_bank2_b::return#1 ] ( func_bank2_b:29 [ func_bank2_b::return#1 ] { { func_bank2_b::return#1 = func_bank2_b::return#3 } } func_bank2_e:41::func_bank2_b:93 [ func_bank2_b::return#1 ] { { func_bank2_e::return#0 = func_bank2_e::return#2 } { func_bank2_b::return#0 = func_bank2_b::return#1 } } ) always clobbers reg byte a +Potential registers zp[1]:2 [ func_bank1_a::a#4 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:3 [ func_bank1_a::b#4 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:4 [ func_bank1_b::a#2 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:5 [ func_bank1_b::b#2 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:6 [ func_bank2_a::a#4 ] : zp[1]:6 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:7 [ func_bank2_a::b#4 ] : zp[1]:7 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:8 [ func_bank2_b::a#2 ] : zp[1]:8 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:9 [ func_bank2_b::b#2 ] : zp[1]:9 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:30 [ func_bank1_a::return#10 ] : zp[1]:30 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:31 [ main::$0 ] : zp[1]:31 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:32 [ func_bank1_b::return#3 ] : zp[1]:32 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:33 [ main::$1 ] : zp[1]:33 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:34 [ func_bank1_c::return#2 ] : zp[1]:34 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:35 [ main::$2 ] : zp[1]:35 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:36 [ func_bank1_d::return#2 ] : zp[1]:36 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:37 [ main::$3 ] : zp[1]:37 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:38 [ func_bank1_e::return#2 ] : zp[1]:38 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:39 [ main::$4 ] : zp[1]:39 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:40 [ func_bank1_f::return#2 ] : zp[1]:40 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:41 [ main::$5 ] : zp[1]:41 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:42 [ func_bank2_a::return#10 ] : zp[1]:42 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:43 [ main::$6 ] : zp[1]:43 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:44 [ func_bank2_b::return#3 ] : zp[1]:44 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:45 [ main::$7 ] : zp[1]:45 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:46 [ func_bank2_c::return#2 ] : zp[1]:46 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:47 [ main::$8 ] : zp[1]:47 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:48 [ func_bank2_d::return#2 ] : zp[1]:48 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:49 [ main::$9 ] : zp[1]:49 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:50 [ func_bank2_e::return#2 ] : zp[1]:50 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:51 [ main::$10 ] : zp[1]:51 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:52 [ func_bank2_f::return#2 ] : zp[1]:52 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:53 [ main::$11 ] : zp[1]:53 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:13 [ func_bank1_a::return#0 ] : zp[1]:13 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:10 [ func_bank1_b::return#1 ] : zp[1]:10 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:14 [ func_bank1_a::return#2 ] : zp[1]:14 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:22 [ func_bank1_c::return#0 ] : zp[1]:22 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:15 [ func_bank2_a::return#0 ] : zp[1]:15 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:23 [ func_bank1_d::return#0 ] : zp[1]:23 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:16 [ func_bank1_a::return#4 ] : zp[1]:16 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:24 [ func_bank1_e::return#0 ] : zp[1]:24 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:17 [ func_bank2_a::return#4 ] : zp[1]:17 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:25 [ func_bank1_f::return#0 ] : zp[1]:25 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:12 [ func_bank2_a::return#1 ] : zp[1]:12 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:11 [ func_bank2_b::return#1 ] : zp[1]:11 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:18 [ func_bank1_a::return#3 ] : zp[1]:18 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:26 [ func_bank2_c::return#0 ] : zp[1]:26 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:19 [ func_bank2_a::return#3 ] : zp[1]:19 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:27 [ func_bank2_d::return#0 ] : zp[1]:27 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:20 [ func_bank2_b::return#0 ] : zp[1]:20 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:28 [ func_bank2_e::return#0 ] : zp[1]:28 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:21 [ func_bank1_b::return#0 ] : zp[1]:21 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:29 [ func_bank2_f::return#0 ] : zp[1]:29 , reg byte a , reg byte x , reg byte y , + +REGISTER UPLIFT SCOPES +Uplift Scope [func_bank1_a] 101: zp[1]:2 [ func_bank1_a::a#4 ] 101: zp[1]:3 [ func_bank1_a::b#4 ] 22.67: zp[1]:13 [ func_bank1_a::return#0 ] 22: zp[1]:14 [ func_bank1_a::return#2 ] 22: zp[1]:16 [ func_bank1_a::return#4 ] 22: zp[1]:18 [ func_bank1_a::return#3 ] 4: zp[1]:30 [ func_bank1_a::return#10 ] +Uplift Scope [func_bank2_a] 101: zp[1]:6 [ func_bank2_a::a#4 ] 101: zp[1]:7 [ func_bank2_a::b#4 ] 22.67: zp[1]:12 [ func_bank2_a::return#1 ] 22: zp[1]:15 [ func_bank2_a::return#0 ] 22: zp[1]:17 [ func_bank2_a::return#4 ] 22: zp[1]:19 [ func_bank2_a::return#3 ] 4: zp[1]:42 [ func_bank2_a::return#10 ] +Uplift Scope [func_bank1_b] 101: zp[1]:4 [ func_bank1_b::a#2 ] 101: zp[1]:5 [ func_bank1_b::b#2 ] 28.5: zp[1]:10 [ func_bank1_b::return#1 ] 22: zp[1]:21 [ func_bank1_b::return#0 ] 4: zp[1]:32 [ func_bank1_b::return#3 ] +Uplift Scope [func_bank2_b] 101: zp[1]:8 [ func_bank2_b::a#2 ] 101: zp[1]:9 [ func_bank2_b::b#2 ] 28.5: zp[1]:11 [ func_bank2_b::return#1 ] 22: zp[1]:20 [ func_bank2_b::return#0 ] 4: zp[1]:44 [ func_bank2_b::return#3 ] +Uplift Scope [main] 4: zp[1]:31 [ main::$0 ] 4: zp[1]:33 [ main::$1 ] 4: zp[1]:35 [ main::$2 ] 4: zp[1]:37 [ main::$3 ] 4: zp[1]:39 [ main::$4 ] 4: zp[1]:41 [ main::$5 ] 4: zp[1]:43 [ main::$6 ] 4: zp[1]:45 [ main::$7 ] 4: zp[1]:47 [ main::$8 ] 4: zp[1]:49 [ main::$9 ] 4: zp[1]:51 [ main::$10 ] 4: zp[1]:53 [ main::$11 ] +Uplift Scope [func_bank1_c] 4.33: zp[1]:22 [ func_bank1_c::return#0 ] 4: zp[1]:34 [ func_bank1_c::return#2 ] +Uplift Scope [func_bank1_d] 4.33: zp[1]:23 [ func_bank1_d::return#0 ] 4: zp[1]:36 [ func_bank1_d::return#2 ] +Uplift Scope [func_bank2_c] 4.33: zp[1]:26 [ func_bank2_c::return#0 ] 4: zp[1]:46 [ func_bank2_c::return#2 ] +Uplift Scope [func_bank2_d] 4.33: zp[1]:27 [ func_bank2_d::return#0 ] 4: zp[1]:48 [ func_bank2_d::return#2 ] +Uplift Scope [func_bank2_e] 4.33: zp[1]:28 [ func_bank2_e::return#0 ] 4: zp[1]:50 [ func_bank2_e::return#2 ] +Uplift Scope [func_bank2_f] 4.33: zp[1]:29 [ func_bank2_f::return#0 ] 4: zp[1]:52 [ func_bank2_f::return#2 ] +Uplift Scope [func_bank1_e] 4.33: zp[1]:24 [ func_bank1_e::return#0 ] 4: zp[1]:38 [ func_bank1_e::return#2 ] +Uplift Scope [func_bank1_f] 4.33: zp[1]:25 [ func_bank1_f::return#0 ] 4: zp[1]:40 [ func_bank1_f::return#2 ] +Uplift Scope [] + +Uplifting [func_bank1_a] best 740 combination reg byte x [ func_bank1_a::a#4 ] reg byte a [ func_bank1_a::b#4 ] reg byte a [ func_bank1_a::return#0 ] reg byte a [ func_bank1_a::return#2 ] zp[1]:16 [ func_bank1_a::return#4 ] zp[1]:18 [ func_bank1_a::return#3 ] zp[1]:30 [ func_bank1_a::return#10 ] +Limited combination testing to 100 combinations of 16384 possible. +Uplifting [func_bank2_a] best 695 combination reg byte x [ func_bank2_a::a#4 ] reg byte a [ func_bank2_a::b#4 ] reg byte a [ func_bank2_a::return#1 ] reg byte a [ func_bank2_a::return#0 ] zp[1]:17 [ func_bank2_a::return#4 ] zp[1]:19 [ func_bank2_a::return#3 ] zp[1]:42 [ func_bank2_a::return#10 ] +Limited combination testing to 100 combinations of 16384 possible. +Uplifting [func_bank1_b] best 668 combination reg byte x [ func_bank1_b::a#2 ] reg byte a [ func_bank1_b::b#2 ] reg byte a [ func_bank1_b::return#1 ] reg byte a [ func_bank1_b::return#0 ] zp[1]:32 [ func_bank1_b::return#3 ] +Limited combination testing to 100 combinations of 1024 possible. +Uplifting [func_bank2_b] best 641 combination reg byte x [ func_bank2_b::a#2 ] reg byte a [ func_bank2_b::b#2 ] reg byte a [ func_bank2_b::return#1 ] reg byte a [ func_bank2_b::return#0 ] zp[1]:44 [ func_bank2_b::return#3 ] +Limited combination testing to 100 combinations of 1024 possible. +Uplifting [main] best 617 combination reg byte a [ main::$0 ] reg byte a [ main::$1 ] reg byte a [ main::$2 ] reg byte a [ main::$3 ] zp[1]:39 [ main::$4 ] zp[1]:41 [ main::$5 ] zp[1]:43 [ main::$6 ] zp[1]:45 [ main::$7 ] zp[1]:47 [ main::$8 ] zp[1]:49 [ main::$9 ] zp[1]:51 [ main::$10 ] zp[1]:53 [ main::$11 ] +Limited combination testing to 100 combinations of 16777216 possible. +Uplifting [func_bank1_c] best 605 combination reg byte a [ func_bank1_c::return#0 ] reg byte a [ func_bank1_c::return#2 ] +Uplifting [func_bank1_d] best 593 combination reg byte a [ func_bank1_d::return#0 ] reg byte a [ func_bank1_d::return#2 ] +Uplifting [func_bank2_c] best 581 combination reg byte a [ func_bank2_c::return#0 ] reg byte a [ func_bank2_c::return#2 ] +Uplifting [func_bank2_d] best 569 combination reg byte a [ func_bank2_d::return#0 ] reg byte a [ func_bank2_d::return#2 ] +Uplifting [func_bank2_e] best 557 combination reg byte a [ func_bank2_e::return#0 ] reg byte a [ func_bank2_e::return#2 ] +Uplifting [func_bank2_f] best 545 combination reg byte a [ func_bank2_f::return#0 ] reg byte a [ func_bank2_f::return#2 ] +Uplifting [func_bank1_e] best 533 combination reg byte a [ func_bank1_e::return#0 ] reg byte a [ func_bank1_e::return#2 ] +Uplifting [func_bank1_f] best 521 combination reg byte a [ func_bank1_f::return#0 ] reg byte a [ func_bank1_f::return#2 ] +Uplifting [] best 521 combination +Attempting to uplift remaining variables inzp[1]:16 [ func_bank1_a::return#4 ] +Uplifting [func_bank1_a] best 515 combination reg byte a [ func_bank1_a::return#4 ] +Attempting to uplift remaining variables inzp[1]:17 [ func_bank2_a::return#4 ] +Uplifting [func_bank2_a] best 509 combination reg byte a [ func_bank2_a::return#4 ] +Attempting to uplift remaining variables inzp[1]:18 [ func_bank1_a::return#3 ] +Uplifting [func_bank1_a] best 503 combination reg byte a [ func_bank1_a::return#3 ] +Attempting to uplift remaining variables inzp[1]:19 [ func_bank2_a::return#3 ] +Uplifting [func_bank2_a] best 497 combination reg byte a [ func_bank2_a::return#3 ] +Attempting to uplift remaining variables inzp[1]:30 [ func_bank1_a::return#10 ] +Uplifting [func_bank1_a] best 491 combination reg byte a [ func_bank1_a::return#10 ] +Attempting to uplift remaining variables inzp[1]:32 [ func_bank1_b::return#3 ] +Uplifting [func_bank1_b] best 485 combination reg byte a [ func_bank1_b::return#3 ] +Attempting to uplift remaining variables inzp[1]:39 [ main::$4 ] +Uplifting [main] best 479 combination reg byte a [ main::$4 ] +Attempting to uplift remaining variables inzp[1]:41 [ main::$5 ] +Uplifting [main] best 473 combination reg byte a [ main::$5 ] +Attempting to uplift remaining variables inzp[1]:42 [ func_bank2_a::return#10 ] +Uplifting [func_bank2_a] best 467 combination reg byte a [ func_bank2_a::return#10 ] +Attempting to uplift remaining variables inzp[1]:43 [ main::$6 ] +Uplifting [main] best 461 combination reg byte a [ main::$6 ] +Attempting to uplift remaining variables inzp[1]:44 [ func_bank2_b::return#3 ] +Uplifting [func_bank2_b] best 455 combination reg byte a [ func_bank2_b::return#3 ] +Attempting to uplift remaining variables inzp[1]:45 [ main::$7 ] +Uplifting [main] best 449 combination reg byte a [ main::$7 ] +Attempting to uplift remaining variables inzp[1]:47 [ main::$8 ] +Uplifting [main] best 443 combination reg byte a [ main::$8 ] +Attempting to uplift remaining variables inzp[1]:49 [ main::$9 ] +Uplifting [main] best 437 combination reg byte a [ main::$9 ] +Attempting to uplift remaining variables inzp[1]:51 [ main::$10 ] +Uplifting [main] best 431 combination reg byte a [ main::$10 ] +Attempting to uplift remaining variables inzp[1]:53 [ main::$11 ] +Uplifting [main] best 425 combination reg byte a [ main::$11 ] + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Test a far call procedure with a calling convention phi + // Upstart +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + + // Global Constants & labels + .label SCREEN = $400 +.segment Code + // main +main: { + // [1] call func_bank1_a + // [50] phi from main to func_bank1_a [phi:main->func_bank1_a] + func_bank1_a_from_main: + // [50] phi func_bank1_a::b#4 = 7 [phi:main->func_bank1_a#0] -- vbuaa=vbuc1 + lda #7 + // [50] phi func_bank1_a::a#4 = '0' [phi:main->func_bank1_a#1] -- call_far_cx16_ram_finalize + ldx #'0' + jsr $ff6e + .byte func_bank1_a + .byte 1 + // [2] func_bank1_a::return#10 = func_bank1_a::return#0 + jmp __b1 + // main::@1 + __b1: + // [3] main::$0 = func_bank1_a::return#10 + // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa + // far call + sta SCREEN + // [5] call func_bank1_b + // [53] phi from main::@1 to func_bank1_b [phi:main::@1->func_bank1_b] + func_bank1_b_from___b1: + // [53] phi func_bank1_b::b#2 = 7 [phi:main::@1->func_bank1_b#0] -- vbuaa=vbuc1 + lda #7 + // [53] phi func_bank1_b::a#2 = '0' [phi:main::@1->func_bank1_b#1] -- vbuxx=vbuc1 + ldx #'0' + jsr func_bank1_b + // [6] func_bank1_b::return#3 = func_bank1_b::return#1 + jmp __b2 + // main::@2 + __b2: + // [7] main::$1 = func_bank1_b::return#3 + // [8] *SCREEN = main::$1 -- _deref_pbuc1=vbuaa + // far call + sta SCREEN + // [9] call func_bank1_c + // [56] phi from main::@2 to func_bank1_c [phi:main::@2->func_bank1_c] -- call_far_cx16_ram_finalize + func_bank1_c_from___b2: + jsr $ff6e + .byte func_bank1_c + .byte 1 + // [10] func_bank1_c::return#2 = func_bank1_c::return#0 + jmp __b3 + // main::@3 + __b3: + // [11] main::$2 = func_bank1_c::return#2 + // [12] *SCREEN = main::$2 -- _deref_pbuc1=vbuaa + // far call + sta SCREEN + // [13] call func_bank1_d + // [61] phi from main::@3 to func_bank1_d [phi:main::@3->func_bank1_d] -- call_far_cx16_ram_finalize + func_bank1_d_from___b3: + jsr $ff6e + .byte func_bank1_d + .byte 1 + // [14] func_bank1_d::return#2 = func_bank1_d::return#0 + jmp __b4 + // main::@4 + __b4: + // [15] main::$3 = func_bank1_d::return#2 + // [16] *SCREEN = main::$3 -- _deref_pbuc1=vbuaa + // far call + sta SCREEN + // [17] call func_bank1_e + // [66] phi from main::@4 to func_bank1_e [phi:main::@4->func_bank1_e] + func_bank1_e_from___b4: + jsr func_bank1_e + // [18] func_bank1_e::return#2 = func_bank1_e::return#0 + jmp __b5 + // main::@5 + __b5: + // [19] main::$4 = func_bank1_e::return#2 + // [20] *SCREEN = main::$4 -- _deref_pbuc1=vbuaa + // near call + sta SCREEN + // [21] call func_bank1_f + // [71] phi from main::@5 to func_bank1_f [phi:main::@5->func_bank1_f] + func_bank1_f_from___b5: + jsr func_bank1_f + // [22] func_bank1_f::return#2 = func_bank1_f::return#0 + jmp __b6 + // main::@6 + __b6: + // [23] main::$5 = func_bank1_f::return#2 + // [24] *SCREEN = main::$5 -- _deref_pbuc1=vbuaa + // near call + sta SCREEN + // [25] call func_bank2_a + // [76] phi from main::@6 to func_bank2_a [phi:main::@6->func_bank2_a] + func_bank2_a_from___b6: + // [76] phi func_bank2_a::b#4 = 7 [phi:main::@6->func_bank2_a#0] -- vbuaa=vbuc1 + lda #7 + // [76] phi func_bank2_a::a#4 = '0' [phi:main::@6->func_bank2_a#1] -- call_far_cx16_ram_finalize + ldx #'0' + jsr $ff6e + .byte func_bank2_a + .byte 2 + // [26] func_bank2_a::return#10 = func_bank2_a::return#1 + jmp __b7 + // main::@7 + __b7: + // [27] main::$6 = func_bank2_a::return#10 + // [28] *SCREEN = main::$6 -- _deref_pbuc1=vbuaa + // far call + sta SCREEN + // [29] call func_bank2_b + // [79] phi from main::@7 to func_bank2_b [phi:main::@7->func_bank2_b] + func_bank2_b_from___b7: + // [79] phi func_bank2_b::b#2 = 7 [phi:main::@7->func_bank2_b#0] -- vbuaa=vbuc1 + lda #7 + // [79] phi func_bank2_b::a#2 = '0' [phi:main::@7->func_bank2_b#1] -- vbuxx=vbuc1 + ldx #'0' + jsr func_bank2_b + // [30] func_bank2_b::return#3 = func_bank2_b::return#1 + jmp __b8 + // main::@8 + __b8: + // [31] main::$7 = func_bank2_b::return#3 + // [32] *SCREEN = main::$7 -- _deref_pbuc1=vbuaa + // far call + sta SCREEN + // [33] call func_bank2_c + // [82] phi from main::@8 to func_bank2_c [phi:main::@8->func_bank2_c] -- call_far_cx16_ram_finalize + func_bank2_c_from___b8: + jsr $ff6e + .byte func_bank2_c + .byte 2 + // [34] func_bank2_c::return#2 = func_bank2_c::return#0 + jmp __b9 + // main::@9 + __b9: + // [35] main::$8 = func_bank2_c::return#2 + // [36] *SCREEN = main::$8 -- _deref_pbuc1=vbuaa + // far call + sta SCREEN + // [37] call func_bank2_d + // [87] phi from main::@9 to func_bank2_d [phi:main::@9->func_bank2_d] -- call_far_cx16_ram_finalize + func_bank2_d_from___b9: + jsr $ff6e + .byte func_bank2_d + .byte 2 + // [38] func_bank2_d::return#2 = func_bank2_d::return#0 + jmp __b10 + // main::@10 + __b10: + // [39] main::$9 = func_bank2_d::return#2 + // [40] *SCREEN = main::$9 -- _deref_pbuc1=vbuaa + // far call + sta SCREEN + // [41] call func_bank2_e + // [92] phi from main::@10 to func_bank2_e [phi:main::@10->func_bank2_e] -- call_far_cx16_ram_finalize + func_bank2_e_from___b10: + jsr $ff6e + .byte func_bank2_e + .byte 2 + // [42] func_bank2_e::return#2 = func_bank2_e::return#0 + jmp __b11 + // main::@11 + __b11: + // [43] main::$10 = func_bank2_e::return#2 + // [44] *SCREEN = main::$10 -- _deref_pbuc1=vbuaa + // far call + sta SCREEN + // [45] call func_bank2_f + // [97] phi from main::@11 to func_bank2_f [phi:main::@11->func_bank2_f] -- call_far_cx16_ram_finalize + func_bank2_f_from___b11: + jsr $ff6e + .byte func_bank2_f + .byte 2 + // [46] func_bank2_f::return#2 = func_bank2_f::return#0 + jmp __b12 + // main::@12 + __b12: + // [47] main::$11 = func_bank2_f::return#2 + // [48] *SCREEN = main::$11 -- _deref_pbuc1=vbuaa + // far call + sta SCREEN + jmp __breturn + // main::@return + __breturn: + // [49] return + rts +} +.segment stage + // func_bank1_a +// __register(A) char func_bank1_a(__register(X) char a, __register(A) char b) +func_bank1_a: { + // [51] func_bank1_a::return#0 = func_bank1_a::a#4 + func_bank1_a::b#4 -- vbuaa=vbuxx_plus_vbuaa + stx.z $ff + clc + adc.z $ff + jmp __breturn + // func_bank1_a::@return + __breturn: + // [52] return + rts +} +.segment platform + // func_bank1_b +// __register(A) char func_bank1_b(__register(X) char a, __register(A) char b) +func_bank1_b: { + // [54] func_bank1_b::return#1 = func_bank1_b::a#2 + func_bank1_b::b#2 -- vbuaa=vbuxx_plus_vbuaa + stx.z $ff + clc + adc.z $ff + jmp __breturn + // func_bank1_b::@return + __breturn: + // [55] return + rts +} +.segment stage + // func_bank1_c +// __register(A) char func_bank1_c(char a, char b) +func_bank1_c: { + .const a = '0' + .const b = 7 + // [57] call func_bank1_a + // [50] phi from func_bank1_c to func_bank1_a [phi:func_bank1_c->func_bank1_a] + func_bank1_a_from_func_bank1_c: + // [50] phi func_bank1_a::b#4 = func_bank1_c::b#0 [phi:func_bank1_c->func_bank1_a#0] -- vbuaa=vbuc1 + lda #b + // [50] phi func_bank1_a::a#4 = func_bank1_c::a#0 [phi:func_bank1_c->func_bank1_a#1] -- vbuxx=vbuc1 + ldx #a + jsr func_bank1_a + // [58] func_bank1_a::return#2 = func_bank1_a::return#0 + jmp __b1 + // func_bank1_c::@1 + __b1: + // [59] func_bank1_c::return#0 = func_bank1_a::return#2 + jmp __breturn + // func_bank1_c::@return + __breturn: + // [60] return + rts +} + // func_bank1_d +// __register(A) char func_bank1_d(char a, char b) +func_bank1_d: { + .const a = '0' + .const b = 7 + // [62] call func_bank2_a + // [76] phi from func_bank1_d to func_bank2_a [phi:func_bank1_d->func_bank2_a] + func_bank2_a_from_func_bank1_d: + // [76] phi func_bank2_a::b#4 = func_bank1_d::b#0 [phi:func_bank1_d->func_bank2_a#0] -- vbuaa=vbuc1 + lda #b + // [76] phi func_bank2_a::a#4 = func_bank1_d::a#0 [phi:func_bank1_d->func_bank2_a#1] -- call_far_cx16_ram_finalize + ldx #a + jsr $ff6e + .byte func_bank2_a + .byte 2 + // [63] func_bank2_a::return#0 = func_bank2_a::return#1 + jmp __b1 + // func_bank1_d::@1 + __b1: + // [64] func_bank1_d::return#0 = func_bank2_a::return#0 + jmp __breturn + // func_bank1_d::@return + __breturn: + // [65] return + rts +} +.segment platform + // func_bank1_e +// __register(A) char func_bank1_e(char a, char b) +func_bank1_e: { + .const a = '0' + .const b = 7 + // [67] call func_bank1_a + // [50] phi from func_bank1_e to func_bank1_a [phi:func_bank1_e->func_bank1_a] + func_bank1_a_from_func_bank1_e: + // [50] phi func_bank1_a::b#4 = func_bank1_e::b#0 [phi:func_bank1_e->func_bank1_a#0] -- vbuaa=vbuc1 + lda #b + // [50] phi func_bank1_a::a#4 = func_bank1_e::a#0 [phi:func_bank1_e->func_bank1_a#1] -- call_far_cx16_ram_finalize + ldx #a + jsr $ff6e + .byte func_bank1_a + .byte 1 + // [68] func_bank1_a::return#4 = func_bank1_a::return#0 + jmp __b1 + // func_bank1_e::@1 + __b1: + // [69] func_bank1_e::return#0 = func_bank1_a::return#4 + jmp __breturn + // func_bank1_e::@return + __breturn: + // [70] return + rts +} + // func_bank1_f +// __register(A) char func_bank1_f(char a, char b) +func_bank1_f: { + .const a = '0' + .const b = 7 + // [72] call func_bank2_a + // [76] phi from func_bank1_f to func_bank2_a [phi:func_bank1_f->func_bank2_a] + func_bank2_a_from_func_bank1_f: + // [76] phi func_bank2_a::b#4 = func_bank1_f::b#0 [phi:func_bank1_f->func_bank2_a#0] -- vbuaa=vbuc1 + lda #b + // [76] phi func_bank2_a::a#4 = func_bank1_f::a#0 [phi:func_bank1_f->func_bank2_a#1] -- call_far_cx16_ram_finalize + ldx #a + jsr $ff6e + .byte func_bank2_a + .byte 2 + // [73] func_bank2_a::return#4 = func_bank2_a::return#1 + jmp __b1 + // func_bank1_f::@1 + __b1: + // [74] func_bank1_f::return#0 = func_bank2_a::return#4 + jmp __breturn + // func_bank1_f::@return + __breturn: + // [75] return + rts +} + // func_bank2_a +// __register(A) char func_bank2_a(__register(X) char a, __register(A) char b) +func_bank2_a: { + // [77] func_bank2_a::return#1 = func_bank2_a::a#4 + func_bank2_a::b#4 -- vbuaa=vbuxx_plus_vbuaa + stx.z $ff + clc + adc.z $ff + jmp __breturn + // func_bank2_a::@return + __breturn: + // [78] return + rts +} + // func_bank2_b +// __register(A) char func_bank2_b(__register(X) char a, __register(A) char b) +func_bank2_b: { + // [80] func_bank2_b::return#1 = func_bank2_b::a#2 + func_bank2_b::b#2 -- vbuaa=vbuxx_plus_vbuaa + stx.z $ff + clc + adc.z $ff + jmp __breturn + // func_bank2_b::@return + __breturn: + // [81] return + rts +} + // func_bank2_c +// __register(A) char func_bank2_c(char a, char b) +func_bank2_c: { + .const a = '0' + .const b = 7 + // [83] call func_bank1_a + // [50] phi from func_bank2_c to func_bank1_a [phi:func_bank2_c->func_bank1_a] + func_bank1_a_from_func_bank2_c: + // [50] phi func_bank1_a::b#4 = func_bank2_c::b#0 [phi:func_bank2_c->func_bank1_a#0] -- vbuaa=vbuc1 + lda #b + // [50] phi func_bank1_a::a#4 = func_bank2_c::a#0 [phi:func_bank2_c->func_bank1_a#1] -- call_far_cx16_ram_finalize + ldx #a + jsr $ff6e + .byte func_bank1_a + .byte 1 + // [84] func_bank1_a::return#3 = func_bank1_a::return#0 + jmp __b1 + // func_bank2_c::@1 + __b1: + // [85] func_bank2_c::return#0 = func_bank1_a::return#3 + jmp __breturn + // func_bank2_c::@return + __breturn: + // [86] return + rts +} + // func_bank2_d +// __register(A) char func_bank2_d(char a, char b) +func_bank2_d: { + .const a = '0' + .const b = 7 + // [88] call func_bank2_a + // [76] phi from func_bank2_d to func_bank2_a [phi:func_bank2_d->func_bank2_a] + func_bank2_a_from_func_bank2_d: + // [76] phi func_bank2_a::b#4 = func_bank2_d::b#0 [phi:func_bank2_d->func_bank2_a#0] -- vbuaa=vbuc1 + lda #b + // [76] phi func_bank2_a::a#4 = func_bank2_d::a#0 [phi:func_bank2_d->func_bank2_a#1] -- vbuxx=vbuc1 + ldx #a + jsr func_bank2_a + // [89] func_bank2_a::return#3 = func_bank2_a::return#1 + jmp __b1 + // func_bank2_d::@1 + __b1: + // [90] func_bank2_d::return#0 = func_bank2_a::return#3 + jmp __breturn + // func_bank2_d::@return + __breturn: + // [91] return + rts +} + // func_bank2_e +// __register(A) char func_bank2_e(char a, char b) +func_bank2_e: { + .const a = '0' + .const b = 7 + // [93] call func_bank2_b + // [79] phi from func_bank2_e to func_bank2_b [phi:func_bank2_e->func_bank2_b] + func_bank2_b_from_func_bank2_e: + // [79] phi func_bank2_b::b#2 = func_bank2_e::b#0 [phi:func_bank2_e->func_bank2_b#0] -- vbuaa=vbuc1 + lda #b + // [79] phi func_bank2_b::a#2 = func_bank2_e::a#0 [phi:func_bank2_e->func_bank2_b#1] -- vbuxx=vbuc1 + ldx #a + jsr func_bank2_b + // [94] func_bank2_b::return#0 = func_bank2_b::return#1 + jmp __b1 + // func_bank2_e::@1 + __b1: + // [95] func_bank2_e::return#0 = func_bank2_b::return#0 + jmp __breturn + // func_bank2_e::@return + __breturn: + // [96] return + rts +} + // func_bank2_f +// __register(A) char func_bank2_f(char a, char b) +func_bank2_f: { + .const a = '0' + .const b = 7 + // [98] call func_bank1_b + // [53] phi from func_bank2_f to func_bank1_b [phi:func_bank2_f->func_bank1_b] + func_bank1_b_from_func_bank2_f: + // [53] phi func_bank1_b::b#2 = func_bank2_f::b#0 [phi:func_bank2_f->func_bank1_b#0] -- vbuaa=vbuc1 + lda #b + // [53] phi func_bank1_b::a#2 = func_bank2_f::a#0 [phi:func_bank2_f->func_bank1_b#1] -- vbuxx=vbuc1 + ldx #a + jsr func_bank1_b + // [99] func_bank1_b::return#0 = func_bank1_b::return#1 + jmp __b1 + // func_bank2_f::@1 + __b1: + // [100] func_bank2_f::return#0 = func_bank1_b::return#0 + jmp __breturn + // func_bank2_f::@return + __breturn: + // [101] return + rts +} + // File Data + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __b1 +Removing instruction jmp __b2 +Removing instruction jmp __b3 +Removing instruction jmp __b4 +Removing instruction jmp __b5 +Removing instruction jmp __b6 +Removing instruction jmp __b7 +Removing instruction jmp __b8 +Removing instruction jmp __b9 +Removing instruction jmp __b10 +Removing instruction jmp __b11 +Removing instruction jmp __b12 +Removing instruction jmp __breturn +Removing instruction jmp __breturn +Removing instruction jmp __breturn +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Removing instruction jmp __breturn +Removing instruction jmp __breturn +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction __breturn: +Removing instruction __breturn: +Removing instruction __breturn: +Removing instruction __breturn: +Removing instruction __breturn: +Removing instruction __breturn: +Removing instruction __breturn: +Removing instruction __breturn: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction func_bank1_a_from_main: +Removing instruction __b1: +Removing instruction func_bank1_b_from___b1: +Removing instruction __b2: +Removing instruction func_bank1_c_from___b2: +Removing instruction __b3: +Removing instruction func_bank1_d_from___b3: +Removing instruction __b4: +Removing instruction func_bank1_e_from___b4: +Removing instruction __b5: +Removing instruction func_bank1_f_from___b5: +Removing instruction __b6: +Removing instruction func_bank2_a_from___b6: +Removing instruction __b7: +Removing instruction func_bank2_b_from___b7: +Removing instruction __b8: +Removing instruction func_bank2_c_from___b8: +Removing instruction __b9: +Removing instruction func_bank2_d_from___b9: +Removing instruction __b10: +Removing instruction func_bank2_e_from___b10: +Removing instruction __b11: +Removing instruction func_bank2_f_from___b11: +Removing instruction __b12: +Removing instruction __breturn: +Removing instruction __breturn: +Removing instruction __breturn: +Removing instruction func_bank1_a_from_func_bank1_c: +Removing instruction __b1: +Removing instruction func_bank2_a_from_func_bank1_d: +Removing instruction __b1: +Removing instruction func_bank1_a_from_func_bank1_e: +Removing instruction __b1: +Removing instruction func_bank2_a_from_func_bank1_f: +Removing instruction __b1: +Removing instruction __breturn: +Removing instruction __breturn: +Removing instruction func_bank1_a_from_func_bank2_c: +Removing instruction __b1: +Removing instruction func_bank2_a_from_func_bank2_d: +Removing instruction __b1: +Removing instruction func_bank2_b_from_func_bank2_e: +Removing instruction __b1: +Removing instruction func_bank1_b_from_func_bank2_f: +Removing instruction __b1: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +__constant char * const SCREEN = (char *) 1024 +__bank(bank) char func_bank1_a(char a , char b) +char func_bank1_a::a +char func_bank1_a::a#4 // reg byte x 101.0 +char func_bank1_a::b +char func_bank1_a::b#4 // reg byte a 101.0 +char func_bank1_a::return +char func_bank1_a::return#0 // reg byte a 22.66666666666666 +char func_bank1_a::return#10 // reg byte a 4.0 +char func_bank1_a::return#2 // reg byte a 22.0 +char func_bank1_a::return#3 // reg byte a 22.0 +char func_bank1_a::return#4 // reg byte a 22.0 +char func_bank1_b(char a , char b) +char func_bank1_b::a +char func_bank1_b::a#2 // reg byte x 101.0 +char func_bank1_b::b +char func_bank1_b::b#2 // reg byte a 101.0 +char func_bank1_b::return +char func_bank1_b::return#0 // reg byte a 22.0 +char func_bank1_b::return#1 // reg byte a 28.5 +char func_bank1_b::return#3 // reg byte a 4.0 +__bank(bank) char func_bank1_c(char a , char b) +char func_bank1_c::a +__constant char func_bank1_c::a#0 = '0' // a +char func_bank1_c::b +__constant char func_bank1_c::b#0 = 7 // b +char func_bank1_c::return +char func_bank1_c::return#0 // reg byte a 4.333333333333333 +char func_bank1_c::return#2 // reg byte a 4.0 +__bank(bank) char func_bank1_d(char a , char b) +char func_bank1_d::a +__constant char func_bank1_d::a#0 = '0' // a +char func_bank1_d::b +__constant char func_bank1_d::b#0 = 7 // b +char func_bank1_d::return +char func_bank1_d::return#0 // reg byte a 4.333333333333333 +char func_bank1_d::return#2 // reg byte a 4.0 +char func_bank1_e(char a , char b) +char func_bank1_e::a +__constant char func_bank1_e::a#0 = '0' // a +char func_bank1_e::b +__constant char func_bank1_e::b#0 = 7 // b +char func_bank1_e::return +char func_bank1_e::return#0 // reg byte a 4.333333333333333 +char func_bank1_e::return#2 // reg byte a 4.0 +char func_bank1_f(char a , char b) +char func_bank1_f::a +__constant char func_bank1_f::a#0 = '0' // a +char func_bank1_f::b +__constant char func_bank1_f::b#0 = 7 // b +char func_bank1_f::return +char func_bank1_f::return#0 // reg byte a 4.333333333333333 +char func_bank1_f::return#2 // reg byte a 4.0 +__bank(bank) char func_bank2_a(char a , char b) +char func_bank2_a::a +char func_bank2_a::a#4 // reg byte x 101.0 +char func_bank2_a::b +char func_bank2_a::b#4 // reg byte a 101.0 +char func_bank2_a::return +char func_bank2_a::return#0 // reg byte a 22.0 +char func_bank2_a::return#1 // reg byte a 22.666666666666664 +char func_bank2_a::return#10 // reg byte a 4.0 +char func_bank2_a::return#3 // reg byte a 22.0 +char func_bank2_a::return#4 // reg byte a 22.0 +char func_bank2_b(char a , char b) +char func_bank2_b::a +char func_bank2_b::a#2 // reg byte x 101.0 +char func_bank2_b::b +char func_bank2_b::b#2 // reg byte a 101.0 +char func_bank2_b::return +char func_bank2_b::return#0 // reg byte a 22.0 +char func_bank2_b::return#1 // reg byte a 28.5 +char func_bank2_b::return#3 // reg byte a 4.0 +__bank(bank) char func_bank2_c(char a , char b) +char func_bank2_c::a +__constant char func_bank2_c::a#0 = '0' // a +char func_bank2_c::b +__constant char func_bank2_c::b#0 = 7 // b +char func_bank2_c::return +char func_bank2_c::return#0 // reg byte a 4.333333333333333 +char func_bank2_c::return#2 // reg byte a 4.0 +__bank(bank) char func_bank2_d(char a , char b) +char func_bank2_d::a +__constant char func_bank2_d::a#0 = '0' // a +char func_bank2_d::b +__constant char func_bank2_d::b#0 = 7 // b +char func_bank2_d::return +char func_bank2_d::return#0 // reg byte a 4.333333333333333 +char func_bank2_d::return#2 // reg byte a 4.0 +__bank(bank) char func_bank2_e(char a , char b) +char func_bank2_e::a +__constant char func_bank2_e::a#0 = '0' // a +char func_bank2_e::b +__constant char func_bank2_e::b#0 = 7 // b +char func_bank2_e::return +char func_bank2_e::return#0 // reg byte a 4.333333333333333 +char func_bank2_e::return#2 // reg byte a 4.0 +__bank(bank) char func_bank2_f(char a , char b) +char func_bank2_f::a +__constant char func_bank2_f::a#0 = '0' // a +char func_bank2_f::b +__constant char func_bank2_f::b#0 = 7 // b +char func_bank2_f::return +char func_bank2_f::return#0 // reg byte a 4.333333333333333 +char func_bank2_f::return#2 // reg byte a 4.0 +void main() +char main::$0 // reg byte a 4.0 +char main::$1 // reg byte a 4.0 +char main::$10 // reg byte a 4.0 +char main::$11 // reg byte a 4.0 +char main::$2 // reg byte a 4.0 +char main::$3 // reg byte a 4.0 +char main::$4 // reg byte a 4.0 +char main::$5 // reg byte a 4.0 +char main::$6 // reg byte a 4.0 +char main::$7 // reg byte a 4.0 +char main::$8 // reg byte a 4.0 +char main::$9 // reg byte a 4.0 + +reg byte x [ func_bank1_a::a#4 ] +reg byte a [ func_bank1_a::b#4 ] +reg byte x [ func_bank1_b::a#2 ] +reg byte a [ func_bank1_b::b#2 ] +reg byte x [ func_bank2_a::a#4 ] +reg byte a [ func_bank2_a::b#4 ] +reg byte x [ func_bank2_b::a#2 ] +reg byte a [ func_bank2_b::b#2 ] +reg byte a [ func_bank1_a::return#10 ] +reg byte a [ main::$0 ] +reg byte a [ func_bank1_b::return#3 ] +reg byte a [ main::$1 ] +reg byte a [ func_bank1_c::return#2 ] +reg byte a [ main::$2 ] +reg byte a [ func_bank1_d::return#2 ] +reg byte a [ main::$3 ] +reg byte a [ func_bank1_e::return#2 ] +reg byte a [ main::$4 ] +reg byte a [ func_bank1_f::return#2 ] +reg byte a [ main::$5 ] +reg byte a [ func_bank2_a::return#10 ] +reg byte a [ main::$6 ] +reg byte a [ func_bank2_b::return#3 ] +reg byte a [ main::$7 ] +reg byte a [ func_bank2_c::return#2 ] +reg byte a [ main::$8 ] +reg byte a [ func_bank2_d::return#2 ] +reg byte a [ main::$9 ] +reg byte a [ func_bank2_e::return#2 ] +reg byte a [ main::$10 ] +reg byte a [ func_bank2_f::return#2 ] +reg byte a [ main::$11 ] +reg byte a [ func_bank1_a::return#0 ] +reg byte a [ func_bank1_b::return#1 ] +reg byte a [ func_bank1_a::return#2 ] +reg byte a [ func_bank1_c::return#0 ] +reg byte a [ func_bank2_a::return#0 ] +reg byte a [ func_bank1_d::return#0 ] +reg byte a [ func_bank1_a::return#4 ] +reg byte a [ func_bank1_e::return#0 ] +reg byte a [ func_bank2_a::return#4 ] +reg byte a [ func_bank1_f::return#0 ] +reg byte a [ func_bank2_a::return#1 ] +reg byte a [ func_bank2_b::return#1 ] +reg byte a [ func_bank1_a::return#3 ] +reg byte a [ func_bank2_c::return#0 ] +reg byte a [ func_bank2_a::return#3 ] +reg byte a [ func_bank2_d::return#0 ] +reg byte a [ func_bank2_b::return#0 ] +reg byte a [ func_bank2_e::return#0 ] +reg byte a [ func_bank1_b::return#0 ] +reg byte a [ func_bank2_f::return#0 ] + + +FINAL ASSEMBLER +Score: 326 + + // File Comments +// Test a far call procedure with a calling convention phi + // Upstart +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + + // Global Constants & labels + .label SCREEN = $400 +.segment Code + // main +main: { + // func_bank1_a('0', 7) + // [1] call func_bank1_a + // [50] phi from main to func_bank1_a [phi:main->func_bank1_a] + // [50] phi func_bank1_a::b#4 = 7 [phi:main->func_bank1_a#0] -- vbuaa=vbuc1 + lda #7 + // [50] phi func_bank1_a::a#4 = '0' [phi:main->func_bank1_a#1] -- call_far_cx16_ram_finalize + ldx #'0' + jsr $ff6e + .byte func_bank1_a + .byte 1 + // func_bank1_a('0', 7) + // [2] func_bank1_a::return#10 = func_bank1_a::return#0 + // main::@1 + // [3] main::$0 = func_bank1_a::return#10 + // SCREEN[0] = func_bank1_a('0', 7) + // [4] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa + // far call + sta SCREEN + // func_bank1_b('0', 7) + // [5] call func_bank1_b + // [53] phi from main::@1 to func_bank1_b [phi:main::@1->func_bank1_b] + // [53] phi func_bank1_b::b#2 = 7 [phi:main::@1->func_bank1_b#0] -- vbuaa=vbuc1 + lda #7 + // [53] phi func_bank1_b::a#2 = '0' [phi:main::@1->func_bank1_b#1] -- vbuxx=vbuc1 + ldx #'0' + jsr func_bank1_b + // func_bank1_b('0', 7) + // [6] func_bank1_b::return#3 = func_bank1_b::return#1 + // main::@2 + // [7] main::$1 = func_bank1_b::return#3 + // SCREEN[0] = func_bank1_b('0', 7) + // [8] *SCREEN = main::$1 -- _deref_pbuc1=vbuaa + // far call + sta SCREEN + // func_bank1_c('0', 7) + // [9] call func_bank1_c + // [56] phi from main::@2 to func_bank1_c [phi:main::@2->func_bank1_c] -- call_far_cx16_ram_finalize + jsr $ff6e + .byte func_bank1_c + .byte 1 + // func_bank1_c('0', 7) + // [10] func_bank1_c::return#2 = func_bank1_c::return#0 + // main::@3 + // [11] main::$2 = func_bank1_c::return#2 + // SCREEN[0] = func_bank1_c('0', 7) + // [12] *SCREEN = main::$2 -- _deref_pbuc1=vbuaa + // far call + sta SCREEN + // func_bank1_d('0', 7) + // [13] call func_bank1_d + // [61] phi from main::@3 to func_bank1_d [phi:main::@3->func_bank1_d] -- call_far_cx16_ram_finalize + jsr $ff6e + .byte func_bank1_d + .byte 1 + // func_bank1_d('0', 7) + // [14] func_bank1_d::return#2 = func_bank1_d::return#0 + // main::@4 + // [15] main::$3 = func_bank1_d::return#2 + // SCREEN[0] = func_bank1_d('0', 7) + // [16] *SCREEN = main::$3 -- _deref_pbuc1=vbuaa + // far call + sta SCREEN + // func_bank1_e('0', 7) + // [17] call func_bank1_e + // [66] phi from main::@4 to func_bank1_e [phi:main::@4->func_bank1_e] + jsr func_bank1_e + // func_bank1_e('0', 7) + // [18] func_bank1_e::return#2 = func_bank1_e::return#0 + // main::@5 + // [19] main::$4 = func_bank1_e::return#2 + // SCREEN[0] = func_bank1_e('0', 7) + // [20] *SCREEN = main::$4 -- _deref_pbuc1=vbuaa + // near call + sta SCREEN + // func_bank1_f('0', 7) + // [21] call func_bank1_f + // [71] phi from main::@5 to func_bank1_f [phi:main::@5->func_bank1_f] + jsr func_bank1_f + // func_bank1_f('0', 7) + // [22] func_bank1_f::return#2 = func_bank1_f::return#0 + // main::@6 + // [23] main::$5 = func_bank1_f::return#2 + // SCREEN[0] = func_bank1_f('0', 7) + // [24] *SCREEN = main::$5 -- _deref_pbuc1=vbuaa + // near call + sta SCREEN + // func_bank2_a('0', 7) + // [25] call func_bank2_a + // [76] phi from main::@6 to func_bank2_a [phi:main::@6->func_bank2_a] + // [76] phi func_bank2_a::b#4 = 7 [phi:main::@6->func_bank2_a#0] -- vbuaa=vbuc1 + lda #7 + // [76] phi func_bank2_a::a#4 = '0' [phi:main::@6->func_bank2_a#1] -- call_far_cx16_ram_finalize + ldx #'0' + jsr $ff6e + .byte func_bank2_a + .byte 2 + // func_bank2_a('0', 7) + // [26] func_bank2_a::return#10 = func_bank2_a::return#1 + // main::@7 + // [27] main::$6 = func_bank2_a::return#10 + // SCREEN[0] = func_bank2_a('0', 7) + // [28] *SCREEN = main::$6 -- _deref_pbuc1=vbuaa + // far call + sta SCREEN + // func_bank2_b('0', 7) + // [29] call func_bank2_b + // [79] phi from main::@7 to func_bank2_b [phi:main::@7->func_bank2_b] + // [79] phi func_bank2_b::b#2 = 7 [phi:main::@7->func_bank2_b#0] -- vbuaa=vbuc1 + lda #7 + // [79] phi func_bank2_b::a#2 = '0' [phi:main::@7->func_bank2_b#1] -- vbuxx=vbuc1 + ldx #'0' + jsr func_bank2_b + // func_bank2_b('0', 7) + // [30] func_bank2_b::return#3 = func_bank2_b::return#1 + // main::@8 + // [31] main::$7 = func_bank2_b::return#3 + // SCREEN[0] = func_bank2_b('0', 7) + // [32] *SCREEN = main::$7 -- _deref_pbuc1=vbuaa + // far call + sta SCREEN + // func_bank2_c('0', 7) + // [33] call func_bank2_c + // [82] phi from main::@8 to func_bank2_c [phi:main::@8->func_bank2_c] -- call_far_cx16_ram_finalize + jsr $ff6e + .byte func_bank2_c + .byte 2 + // func_bank2_c('0', 7) + // [34] func_bank2_c::return#2 = func_bank2_c::return#0 + // main::@9 + // [35] main::$8 = func_bank2_c::return#2 + // SCREEN[0] = func_bank2_c('0', 7) + // [36] *SCREEN = main::$8 -- _deref_pbuc1=vbuaa + // far call + sta SCREEN + // func_bank2_d('0', 7) + // [37] call func_bank2_d + // [87] phi from main::@9 to func_bank2_d [phi:main::@9->func_bank2_d] -- call_far_cx16_ram_finalize + jsr $ff6e + .byte func_bank2_d + .byte 2 + // func_bank2_d('0', 7) + // [38] func_bank2_d::return#2 = func_bank2_d::return#0 + // main::@10 + // [39] main::$9 = func_bank2_d::return#2 + // SCREEN[0] = func_bank2_d('0', 7) + // [40] *SCREEN = main::$9 -- _deref_pbuc1=vbuaa + // far call + sta SCREEN + // func_bank2_e('0', 7) + // [41] call func_bank2_e + // [92] phi from main::@10 to func_bank2_e [phi:main::@10->func_bank2_e] -- call_far_cx16_ram_finalize + jsr $ff6e + .byte func_bank2_e + .byte 2 + // func_bank2_e('0', 7) + // [42] func_bank2_e::return#2 = func_bank2_e::return#0 + // main::@11 + // [43] main::$10 = func_bank2_e::return#2 + // SCREEN[0] = func_bank2_e('0', 7) + // [44] *SCREEN = main::$10 -- _deref_pbuc1=vbuaa + // far call + sta SCREEN + // func_bank2_f('0', 7) + // [45] call func_bank2_f + // [97] phi from main::@11 to func_bank2_f [phi:main::@11->func_bank2_f] -- call_far_cx16_ram_finalize + jsr $ff6e + .byte func_bank2_f + .byte 2 + // func_bank2_f('0', 7) + // [46] func_bank2_f::return#2 = func_bank2_f::return#0 + // main::@12 + // [47] main::$11 = func_bank2_f::return#2 + // SCREEN[0] = func_bank2_f('0', 7) + // [48] *SCREEN = main::$11 -- _deref_pbuc1=vbuaa + // far call + sta SCREEN + // main::@return + // } + // [49] return + rts +} +.segment stage + // func_bank1_a +// __register(A) char func_bank1_a(__register(X) char a, __register(A) char b) +func_bank1_a: { + // a+b + // [51] func_bank1_a::return#0 = func_bank1_a::a#4 + func_bank1_a::b#4 -- vbuaa=vbuxx_plus_vbuaa + stx.z $ff + clc + adc.z $ff + // func_bank1_a::@return + // } + // [52] return + rts +} +.segment platform + // func_bank1_b +// __register(A) char func_bank1_b(__register(X) char a, __register(A) char b) +func_bank1_b: { + // a+b + // [54] func_bank1_b::return#1 = func_bank1_b::a#2 + func_bank1_b::b#2 -- vbuaa=vbuxx_plus_vbuaa + stx.z $ff + clc + adc.z $ff + // func_bank1_b::@return + // } + // [55] return + rts +} +.segment stage + // func_bank1_c +// __register(A) char func_bank1_c(char a, char b) +func_bank1_c: { + .const a = '0' + .const b = 7 + // func_bank1_a(a,b) + // [57] call func_bank1_a + // [50] phi from func_bank1_c to func_bank1_a [phi:func_bank1_c->func_bank1_a] + // [50] phi func_bank1_a::b#4 = func_bank1_c::b#0 [phi:func_bank1_c->func_bank1_a#0] -- vbuaa=vbuc1 + lda #b + // [50] phi func_bank1_a::a#4 = func_bank1_c::a#0 [phi:func_bank1_c->func_bank1_a#1] -- vbuxx=vbuc1 + ldx #a + jsr func_bank1_a + // func_bank1_a(a,b) + // [58] func_bank1_a::return#2 = func_bank1_a::return#0 + // func_bank1_c::@1 + // [59] func_bank1_c::return#0 = func_bank1_a::return#2 + // func_bank1_c::@return + // } + // [60] return + rts +} + // func_bank1_d +// __register(A) char func_bank1_d(char a, char b) +func_bank1_d: { + .const a = '0' + .const b = 7 + // func_bank2_a(a,b) + // [62] call func_bank2_a + // [76] phi from func_bank1_d to func_bank2_a [phi:func_bank1_d->func_bank2_a] + // [76] phi func_bank2_a::b#4 = func_bank1_d::b#0 [phi:func_bank1_d->func_bank2_a#0] -- vbuaa=vbuc1 + lda #b + // [76] phi func_bank2_a::a#4 = func_bank1_d::a#0 [phi:func_bank1_d->func_bank2_a#1] -- call_far_cx16_ram_finalize + ldx #a + jsr $ff6e + .byte func_bank2_a + .byte 2 + // func_bank2_a(a,b) + // [63] func_bank2_a::return#0 = func_bank2_a::return#1 + // func_bank1_d::@1 + // [64] func_bank1_d::return#0 = func_bank2_a::return#0 + // func_bank1_d::@return + // } + // [65] return + rts +} +.segment platform + // func_bank1_e +// __register(A) char func_bank1_e(char a, char b) +func_bank1_e: { + .const a = '0' + .const b = 7 + // func_bank1_a(a,b) + // [67] call func_bank1_a + // [50] phi from func_bank1_e to func_bank1_a [phi:func_bank1_e->func_bank1_a] + // [50] phi func_bank1_a::b#4 = func_bank1_e::b#0 [phi:func_bank1_e->func_bank1_a#0] -- vbuaa=vbuc1 + lda #b + // [50] phi func_bank1_a::a#4 = func_bank1_e::a#0 [phi:func_bank1_e->func_bank1_a#1] -- call_far_cx16_ram_finalize + ldx #a + jsr $ff6e + .byte func_bank1_a + .byte 1 + // func_bank1_a(a,b) + // [68] func_bank1_a::return#4 = func_bank1_a::return#0 + // func_bank1_e::@1 + // [69] func_bank1_e::return#0 = func_bank1_a::return#4 + // func_bank1_e::@return + // } + // [70] return + rts +} + // func_bank1_f +// __register(A) char func_bank1_f(char a, char b) +func_bank1_f: { + .const a = '0' + .const b = 7 + // func_bank2_a(a,b) + // [72] call func_bank2_a + // [76] phi from func_bank1_f to func_bank2_a [phi:func_bank1_f->func_bank2_a] + // [76] phi func_bank2_a::b#4 = func_bank1_f::b#0 [phi:func_bank1_f->func_bank2_a#0] -- vbuaa=vbuc1 + lda #b + // [76] phi func_bank2_a::a#4 = func_bank1_f::a#0 [phi:func_bank1_f->func_bank2_a#1] -- call_far_cx16_ram_finalize + ldx #a + jsr $ff6e + .byte func_bank2_a + .byte 2 + // func_bank2_a(a,b) + // [73] func_bank2_a::return#4 = func_bank2_a::return#1 + // func_bank1_f::@1 + // [74] func_bank1_f::return#0 = func_bank2_a::return#4 + // func_bank1_f::@return + // } + // [75] return + rts +} + // func_bank2_a +// __register(A) char func_bank2_a(__register(X) char a, __register(A) char b) +func_bank2_a: { + // a+b + // [77] func_bank2_a::return#1 = func_bank2_a::a#4 + func_bank2_a::b#4 -- vbuaa=vbuxx_plus_vbuaa + stx.z $ff + clc + adc.z $ff + // func_bank2_a::@return + // } + // [78] return + rts +} + // func_bank2_b +// __register(A) char func_bank2_b(__register(X) char a, __register(A) char b) +func_bank2_b: { + // a+b + // [80] func_bank2_b::return#1 = func_bank2_b::a#2 + func_bank2_b::b#2 -- vbuaa=vbuxx_plus_vbuaa + stx.z $ff + clc + adc.z $ff + // func_bank2_b::@return + // } + // [81] return + rts +} + // func_bank2_c +// __register(A) char func_bank2_c(char a, char b) +func_bank2_c: { + .const a = '0' + .const b = 7 + // func_bank1_a(a,b) + // [83] call func_bank1_a + // [50] phi from func_bank2_c to func_bank1_a [phi:func_bank2_c->func_bank1_a] + // [50] phi func_bank1_a::b#4 = func_bank2_c::b#0 [phi:func_bank2_c->func_bank1_a#0] -- vbuaa=vbuc1 + lda #b + // [50] phi func_bank1_a::a#4 = func_bank2_c::a#0 [phi:func_bank2_c->func_bank1_a#1] -- call_far_cx16_ram_finalize + ldx #a + jsr $ff6e + .byte func_bank1_a + .byte 1 + // func_bank1_a(a,b) + // [84] func_bank1_a::return#3 = func_bank1_a::return#0 + // func_bank2_c::@1 + // [85] func_bank2_c::return#0 = func_bank1_a::return#3 + // func_bank2_c::@return + // } + // [86] return + rts +} + // func_bank2_d +// __register(A) char func_bank2_d(char a, char b) +func_bank2_d: { + .const a = '0' + .const b = 7 + // func_bank2_a(a,b) + // [88] call func_bank2_a + // [76] phi from func_bank2_d to func_bank2_a [phi:func_bank2_d->func_bank2_a] + // [76] phi func_bank2_a::b#4 = func_bank2_d::b#0 [phi:func_bank2_d->func_bank2_a#0] -- vbuaa=vbuc1 + lda #b + // [76] phi func_bank2_a::a#4 = func_bank2_d::a#0 [phi:func_bank2_d->func_bank2_a#1] -- vbuxx=vbuc1 + ldx #a + jsr func_bank2_a + // func_bank2_a(a,b) + // [89] func_bank2_a::return#3 = func_bank2_a::return#1 + // func_bank2_d::@1 + // [90] func_bank2_d::return#0 = func_bank2_a::return#3 + // func_bank2_d::@return + // } + // [91] return + rts +} + // func_bank2_e +// __register(A) char func_bank2_e(char a, char b) +func_bank2_e: { + .const a = '0' + .const b = 7 + // func_bank2_b(a,b) + // [93] call func_bank2_b + // [79] phi from func_bank2_e to func_bank2_b [phi:func_bank2_e->func_bank2_b] + // [79] phi func_bank2_b::b#2 = func_bank2_e::b#0 [phi:func_bank2_e->func_bank2_b#0] -- vbuaa=vbuc1 + lda #b + // [79] phi func_bank2_b::a#2 = func_bank2_e::a#0 [phi:func_bank2_e->func_bank2_b#1] -- vbuxx=vbuc1 + ldx #a + jsr func_bank2_b + // func_bank2_b(a,b) + // [94] func_bank2_b::return#0 = func_bank2_b::return#1 + // func_bank2_e::@1 + // [95] func_bank2_e::return#0 = func_bank2_b::return#0 + // func_bank2_e::@return + // } + // [96] return + rts +} + // func_bank2_f +// __register(A) char func_bank2_f(char a, char b) +func_bank2_f: { + .const a = '0' + .const b = 7 + // func_bank1_b(a,b) + // [98] call func_bank1_b + // [53] phi from func_bank2_f to func_bank1_b [phi:func_bank2_f->func_bank1_b] + // [53] phi func_bank1_b::b#2 = func_bank2_f::b#0 [phi:func_bank2_f->func_bank1_b#0] -- vbuaa=vbuc1 + lda #b + // [53] phi func_bank1_b::a#2 = func_bank2_f::a#0 [phi:func_bank2_f->func_bank1_b#1] -- vbuxx=vbuc1 + ldx #a + jsr func_bank1_b + // func_bank1_b(a,b) + // [99] func_bank1_b::return#0 = func_bank1_b::return#1 + // func_bank2_f::@1 + // [100] func_bank2_f::return#0 = func_bank1_b::return#0 + // func_bank2_f::@return + // } + // [101] return + rts +} + // File Data + diff --git a/src/test/ref/procedure-callingconvention-phi-bank-5.sym b/src/test/ref/procedure-callingconvention-phi-bank-5.sym new file mode 100644 index 000000000..c0905901f --- /dev/null +++ b/src/test/ref/procedure-callingconvention-phi-bank-5.sym @@ -0,0 +1,171 @@ +__constant char * const SCREEN = (char *) 1024 +__bank(bank) char func_bank1_a(char a , char b) +char func_bank1_a::a +char func_bank1_a::a#4 // reg byte x 101.0 +char func_bank1_a::b +char func_bank1_a::b#4 // reg byte a 101.0 +char func_bank1_a::return +char func_bank1_a::return#0 // reg byte a 22.66666666666666 +char func_bank1_a::return#10 // reg byte a 4.0 +char func_bank1_a::return#2 // reg byte a 22.0 +char func_bank1_a::return#3 // reg byte a 22.0 +char func_bank1_a::return#4 // reg byte a 22.0 +char func_bank1_b(char a , char b) +char func_bank1_b::a +char func_bank1_b::a#2 // reg byte x 101.0 +char func_bank1_b::b +char func_bank1_b::b#2 // reg byte a 101.0 +char func_bank1_b::return +char func_bank1_b::return#0 // reg byte a 22.0 +char func_bank1_b::return#1 // reg byte a 28.5 +char func_bank1_b::return#3 // reg byte a 4.0 +__bank(bank) char func_bank1_c(char a , char b) +char func_bank1_c::a +__constant char func_bank1_c::a#0 = '0' // a +char func_bank1_c::b +__constant char func_bank1_c::b#0 = 7 // b +char func_bank1_c::return +char func_bank1_c::return#0 // reg byte a 4.333333333333333 +char func_bank1_c::return#2 // reg byte a 4.0 +__bank(bank) char func_bank1_d(char a , char b) +char func_bank1_d::a +__constant char func_bank1_d::a#0 = '0' // a +char func_bank1_d::b +__constant char func_bank1_d::b#0 = 7 // b +char func_bank1_d::return +char func_bank1_d::return#0 // reg byte a 4.333333333333333 +char func_bank1_d::return#2 // reg byte a 4.0 +char func_bank1_e(char a , char b) +char func_bank1_e::a +__constant char func_bank1_e::a#0 = '0' // a +char func_bank1_e::b +__constant char func_bank1_e::b#0 = 7 // b +char func_bank1_e::return +char func_bank1_e::return#0 // reg byte a 4.333333333333333 +char func_bank1_e::return#2 // reg byte a 4.0 +char func_bank1_f(char a , char b) +char func_bank1_f::a +__constant char func_bank1_f::a#0 = '0' // a +char func_bank1_f::b +__constant char func_bank1_f::b#0 = 7 // b +char func_bank1_f::return +char func_bank1_f::return#0 // reg byte a 4.333333333333333 +char func_bank1_f::return#2 // reg byte a 4.0 +__bank(bank) char func_bank2_a(char a , char b) +char func_bank2_a::a +char func_bank2_a::a#4 // reg byte x 101.0 +char func_bank2_a::b +char func_bank2_a::b#4 // reg byte a 101.0 +char func_bank2_a::return +char func_bank2_a::return#0 // reg byte a 22.0 +char func_bank2_a::return#1 // reg byte a 22.666666666666664 +char func_bank2_a::return#10 // reg byte a 4.0 +char func_bank2_a::return#3 // reg byte a 22.0 +char func_bank2_a::return#4 // reg byte a 22.0 +char func_bank2_b(char a , char b) +char func_bank2_b::a +char func_bank2_b::a#2 // reg byte x 101.0 +char func_bank2_b::b +char func_bank2_b::b#2 // reg byte a 101.0 +char func_bank2_b::return +char func_bank2_b::return#0 // reg byte a 22.0 +char func_bank2_b::return#1 // reg byte a 28.5 +char func_bank2_b::return#3 // reg byte a 4.0 +__bank(bank) char func_bank2_c(char a , char b) +char func_bank2_c::a +__constant char func_bank2_c::a#0 = '0' // a +char func_bank2_c::b +__constant char func_bank2_c::b#0 = 7 // b +char func_bank2_c::return +char func_bank2_c::return#0 // reg byte a 4.333333333333333 +char func_bank2_c::return#2 // reg byte a 4.0 +__bank(bank) char func_bank2_d(char a , char b) +char func_bank2_d::a +__constant char func_bank2_d::a#0 = '0' // a +char func_bank2_d::b +__constant char func_bank2_d::b#0 = 7 // b +char func_bank2_d::return +char func_bank2_d::return#0 // reg byte a 4.333333333333333 +char func_bank2_d::return#2 // reg byte a 4.0 +__bank(bank) char func_bank2_e(char a , char b) +char func_bank2_e::a +__constant char func_bank2_e::a#0 = '0' // a +char func_bank2_e::b +__constant char func_bank2_e::b#0 = 7 // b +char func_bank2_e::return +char func_bank2_e::return#0 // reg byte a 4.333333333333333 +char func_bank2_e::return#2 // reg byte a 4.0 +__bank(bank) char func_bank2_f(char a , char b) +char func_bank2_f::a +__constant char func_bank2_f::a#0 = '0' // a +char func_bank2_f::b +__constant char func_bank2_f::b#0 = 7 // b +char func_bank2_f::return +char func_bank2_f::return#0 // reg byte a 4.333333333333333 +char func_bank2_f::return#2 // reg byte a 4.0 +void main() +char main::$0 // reg byte a 4.0 +char main::$1 // reg byte a 4.0 +char main::$10 // reg byte a 4.0 +char main::$11 // reg byte a 4.0 +char main::$2 // reg byte a 4.0 +char main::$3 // reg byte a 4.0 +char main::$4 // reg byte a 4.0 +char main::$5 // reg byte a 4.0 +char main::$6 // reg byte a 4.0 +char main::$7 // reg byte a 4.0 +char main::$8 // reg byte a 4.0 +char main::$9 // reg byte a 4.0 + +reg byte x [ func_bank1_a::a#4 ] +reg byte a [ func_bank1_a::b#4 ] +reg byte x [ func_bank1_b::a#2 ] +reg byte a [ func_bank1_b::b#2 ] +reg byte x [ func_bank2_a::a#4 ] +reg byte a [ func_bank2_a::b#4 ] +reg byte x [ func_bank2_b::a#2 ] +reg byte a [ func_bank2_b::b#2 ] +reg byte a [ func_bank1_a::return#10 ] +reg byte a [ main::$0 ] +reg byte a [ func_bank1_b::return#3 ] +reg byte a [ main::$1 ] +reg byte a [ func_bank1_c::return#2 ] +reg byte a [ main::$2 ] +reg byte a [ func_bank1_d::return#2 ] +reg byte a [ main::$3 ] +reg byte a [ func_bank1_e::return#2 ] +reg byte a [ main::$4 ] +reg byte a [ func_bank1_f::return#2 ] +reg byte a [ main::$5 ] +reg byte a [ func_bank2_a::return#10 ] +reg byte a [ main::$6 ] +reg byte a [ func_bank2_b::return#3 ] +reg byte a [ main::$7 ] +reg byte a [ func_bank2_c::return#2 ] +reg byte a [ main::$8 ] +reg byte a [ func_bank2_d::return#2 ] +reg byte a [ main::$9 ] +reg byte a [ func_bank2_e::return#2 ] +reg byte a [ main::$10 ] +reg byte a [ func_bank2_f::return#2 ] +reg byte a [ main::$11 ] +reg byte a [ func_bank1_a::return#0 ] +reg byte a [ func_bank1_b::return#1 ] +reg byte a [ func_bank1_a::return#2 ] +reg byte a [ func_bank1_c::return#0 ] +reg byte a [ func_bank2_a::return#0 ] +reg byte a [ func_bank1_d::return#0 ] +reg byte a [ func_bank1_a::return#4 ] +reg byte a [ func_bank1_e::return#0 ] +reg byte a [ func_bank2_a::return#4 ] +reg byte a [ func_bank1_f::return#0 ] +reg byte a [ func_bank2_a::return#1 ] +reg byte a [ func_bank2_b::return#1 ] +reg byte a [ func_bank1_a::return#3 ] +reg byte a [ func_bank2_c::return#0 ] +reg byte a [ func_bank2_a::return#3 ] +reg byte a [ func_bank2_d::return#0 ] +reg byte a [ func_bank2_b::return#0 ] +reg byte a [ func_bank2_e::return#0 ] +reg byte a [ func_bank1_b::return#0 ] +reg byte a [ func_bank2_f::return#0 ] diff --git a/src/test/ref/procedure-callingconvention-stack-bank-0.asm b/src/test/ref/procedure-callingconvention-stack-bank-0.asm new file mode 100644 index 000000000..ec687e5fb --- /dev/null +++ b/src/test/ref/procedure-callingconvention-stack-bank-0.asm @@ -0,0 +1,45 @@ +// Test a procedure with calling convention stack +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + .const STACK_BASE = $103 + .label SCREEN = $400 +.segment stage +// __register(A) char plus(__zp(2) char a, __register(A) char b) +plus: { + .const OFFSET_STACK_A = 1 + .const OFFSET_STACK_B = 0 + .const OFFSET_STACK_RETURN_1 = 1 + .label a = 2 + tsx + lda STACK_BASE+OFFSET_STACK_A,x + sta.z a + tsx + lda STACK_BASE+OFFSET_STACK_B,x + // return a+b; + clc + adc.z a + // } + tsx + sta STACK_BASE+OFFSET_STACK_RETURN_1,x + rts +} +main: { + // plus('0', 7) + lda #'0' + pha + lda #7 + pha + jsr plus + pla + pla + // SCREEN[0] = plus('0', 7) + sta SCREEN + // } + rts +} diff --git a/src/test/ref/procedure-callingconvention-stack-bank-0.cfg b/src/test/ref/procedure-callingconvention-stack-bank-0.cfg new file mode 100644 index 000000000..e23f2647e --- /dev/null +++ b/src/test/ref/procedure-callingconvention-stack-bank-0.cfg @@ -0,0 +1,24 @@ + +__stackcall char plus(char a , char b) +plus: scope:[plus] from + [0] plus::a#0 = stackidx(char,plus::OFFSET_STACK_A) + [1] plus::b#0 = stackidx(char,plus::OFFSET_STACK_B) + [2] plus::return#0 = plus::a#0 + plus::b#0 + to:plus::@return +plus::@return: scope:[plus] from plus + [3] stackidx(char,plus::OFFSET_STACK_RETURN_1) = plus::return#0 + [4] return + to:@return + +void main() +main: scope:[main] from + [5] stackpush(char) = '0' + [6] stackpush(char) = 7 + [7] callexecute plus + sideeffect stackpullpadding(1) + [9] main::$0 = stackpull(char) + [10] *SCREEN = main::$0 + to:main::@return +main::@return: scope:[main] from main + [11] return + to:@return diff --git a/src/test/ref/procedure-callingconvention-stack-bank-0.log b/src/test/ref/procedure-callingconvention-stack-bank-0.log new file mode 100644 index 000000000..de9b614ed --- /dev/null +++ b/src/test/ref/procedure-callingconvention-stack-bank-0.log @@ -0,0 +1,350 @@ +Loading link script "procedure-callingconvention-stack-bank.ld" +Adding parameter assignment in __stackcall procedure plus::b = param(plus::b) +Adding parameter assignment in __stackcall procedure plus::a = param(plus::a) +Calling convention __stackcall adding prepare/execute/finalize for main::$0 = call plus('0', 7) +Calling convention STACK_CALL replacing param(plus::a) with stackidx(char,plus::OFFSET_STACK_A) +Calling convention STACK_CALL replacing param(plus::b) with stackidx(char,plus::OFFSET_STACK_B) +Calling convention STACK_CALL adding stack return stackidx(char,plus::OFFSET_STACK_RETURN_1) = plus::return +Calling convention STACK_CALL adding stack pull main::$0 = stackpull(char) +Calling convention STACK_CALL adding stack push stackpush(char) = '0' +Calling convention STACK_CALL adding stack push stackpush(char) = 7 + +CONTROL FLOW GRAPH SSA + +void main() +main: scope:[main] from __start + stackpush(char) = '0' + stackpush(char) = 7 + callexecute plus + sideeffect stackpullpadding(1) + main::$0 = stackpull(char) + SCREEN[0] = main::$0 + to:main::@return +main::@return: scope:[main] from main + return + to:@return + +__stackcall char plus(char a , char b) +plus: scope:[plus] from + plus::a#0 = stackidx(char,plus::OFFSET_STACK_A) + plus::b#0 = stackidx(char,plus::OFFSET_STACK_B) + plus::$0 = plus::a#0 + plus::b#0 + plus::return#0 = plus::$0 + to:plus::@return +plus::@return: scope:[plus] from plus + plus::return#1 = phi( plus/plus::return#0 ) + stackidx(char,plus::OFFSET_STACK_RETURN_1) = plus::return#1 + return + to:@return + +void __start() +__start: scope:[__start] from + call main + to:__start::@1 +__start::@1: scope:[__start] from __start + to:__start::@return +__start::@return: scope:[__start] from __start::@1 + return + to:@return + +SYMBOL TABLE SSA +__constant char * const SCREEN = (char *)$400 +__constant unsigned int STACK_BASE = $103 +void __start() +void main() +char main::$0 +__stackcall char plus(char a , char b) +char plus::$0 +__constant char plus::OFFSET_STACK_A = 1 +__constant char plus::OFFSET_STACK_B = 0 +__constant char plus::OFFSET_STACK_RETURN_1 = 1 +char plus::a +char plus::a#0 +char plus::b +char plus::b#0 +char plus::return +char plus::return#0 +char plus::return#1 + +Adding number conversion cast (unumber) 7 in stackpush(char) = 7 +Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$0 +Successful SSA optimization PassNAddNumberTypeConversions +Inlining cast stackpush(char) = (unumber)7 +Successful SSA optimization Pass2InlineCast +Simplifying constant pointer cast (char *) 1024 +Simplifying constant integer cast 7 +Simplifying constant integer cast 0 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (char) 7 +Finalized unsigned number type (char) 0 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Alias plus::return#0 = plus::$0 plus::return#1 +Successful SSA optimization Pass2AliasElimination +Simplifying expression containing zero SCREEN in [5] SCREEN[0] = main::$0 +Successful SSA optimization PassNSimplifyExpressionWithZero +Removing unused procedure __start +Removing unused procedure block __start +Removing unused procedure block __start::@1 +Removing unused procedure block __start::@return +Successful SSA optimization PassNEliminateEmptyStart +Finalized unsigned number type (char) 1 +Successful SSA optimization PassNFinalizeNumberTypeConversions +CALL GRAPH +Calls in [main] to plus:7 + +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes + +FINAL CONTROL FLOW GRAPH + +__stackcall char plus(char a , char b) +plus: scope:[plus] from + [0] plus::a#0 = stackidx(char,plus::OFFSET_STACK_A) + [1] plus::b#0 = stackidx(char,plus::OFFSET_STACK_B) + [2] plus::return#0 = plus::a#0 + plus::b#0 + to:plus::@return +plus::@return: scope:[plus] from plus + [3] stackidx(char,plus::OFFSET_STACK_RETURN_1) = plus::return#0 + [4] return + to:@return + +void main() +main: scope:[main] from + [5] stackpush(char) = '0' + [6] stackpush(char) = 7 + [7] callexecute plus + sideeffect stackpullpadding(1) + [9] main::$0 = stackpull(char) + [10] *SCREEN = main::$0 + to:main::@return +main::@return: scope:[main] from main + [11] return + to:@return + + +VARIABLE REGISTER WEIGHTS +void main() +char main::$0 // 4.0 +__stackcall char plus(char a , char b) +char plus::a +char plus::a#0 // 11.0 +char plus::b +char plus::b#0 // 22.0 +char plus::return +char plus::return#0 // 22.0 + +Initial phi equivalence classes +Added variable plus::a#0 to live range equivalence class [ plus::a#0 ] +Added variable plus::b#0 to live range equivalence class [ plus::b#0 ] +Added variable plus::return#0 to live range equivalence class [ plus::return#0 ] +Added variable main::$0 to live range equivalence class [ main::$0 ] +Complete equivalence classes +[ plus::a#0 ] +[ plus::b#0 ] +[ plus::return#0 ] +[ main::$0 ] +Allocated zp[1]:2 [ plus::b#0 ] +Allocated zp[1]:3 [ plus::return#0 ] +Allocated zp[1]:4 [ plus::a#0 ] +Allocated zp[1]:5 [ main::$0 ] +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [0] plus::a#0 = stackidx(char,plus::OFFSET_STACK_A) [ plus::a#0 ] ( plus:7 [ plus::a#0 ] { } ) always clobbers reg byte a reg byte x +Statement [1] plus::b#0 = stackidx(char,plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( plus:7 [ plus::a#0 plus::b#0 ] { } ) always clobbers reg byte a reg byte x +Removing always clobbered register reg byte a as potential for zp[1]:4 [ plus::a#0 ] +Removing always clobbered register reg byte x as potential for zp[1]:4 [ plus::a#0 ] +Statement [2] plus::return#0 = plus::a#0 + plus::b#0 [ plus::return#0 ] ( plus:7 [ plus::return#0 ] { } ) always clobbers reg byte a +Statement [3] stackidx(char,plus::OFFSET_STACK_RETURN_1) = plus::return#0 [ ] ( plus:7 [ ] { } ) always clobbers reg byte x +Statement [5] stackpush(char) = '0' [ ] ( [ ] { } ) always clobbers reg byte a +Statement [6] stackpush(char) = 7 [ ] ( [ ] { } ) always clobbers reg byte a +Statement sideeffect stackpullpadding(1) always clobbers reg byte a +Statement [9] main::$0 = stackpull(char) [ main::$0 ] ( [ main::$0 ] { } ) always clobbers reg byte a +Statement [0] plus::a#0 = stackidx(char,plus::OFFSET_STACK_A) [ plus::a#0 ] ( plus:7 [ plus::a#0 ] { } ) always clobbers reg byte a reg byte x +Statement [1] plus::b#0 = stackidx(char,plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( plus:7 [ plus::a#0 plus::b#0 ] { } ) always clobbers reg byte a reg byte x +Statement [2] plus::return#0 = plus::a#0 + plus::b#0 [ plus::return#0 ] ( plus:7 [ plus::return#0 ] { } ) always clobbers reg byte a +Statement [3] stackidx(char,plus::OFFSET_STACK_RETURN_1) = plus::return#0 [ ] ( plus:7 [ ] { } ) always clobbers reg byte x +Statement [5] stackpush(char) = '0' [ ] ( [ ] { } ) always clobbers reg byte a +Statement [6] stackpush(char) = 7 [ ] ( [ ] { } ) always clobbers reg byte a +Statement sideeffect stackpullpadding(1) always clobbers reg byte a +Statement [9] main::$0 = stackpull(char) [ main::$0 ] ( [ main::$0 ] { } ) always clobbers reg byte a +Potential registers zp[1]:4 [ plus::a#0 ] : zp[1]:4 , reg byte y , +Potential registers zp[1]:2 [ plus::b#0 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:3 [ plus::return#0 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:5 [ main::$0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , + +REGISTER UPLIFT SCOPES +Uplift Scope [plus] 22: zp[1]:2 [ plus::b#0 ] 22: zp[1]:3 [ plus::return#0 ] 11: zp[1]:4 [ plus::a#0 ] +Uplift Scope [main] 4: zp[1]:5 [ main::$0 ] +Uplift Scope [] + +Uplifting [plus] best 79 combination reg byte a [ plus::b#0 ] reg byte a [ plus::return#0 ] zp[1]:4 [ plus::a#0 ] +Uplifting [main] best 73 combination reg byte a [ main::$0 ] +Uplifting [] best 73 combination +Attempting to uplift remaining variables inzp[1]:4 [ plus::a#0 ] +Uplifting [plus] best 73 combination zp[1]:4 [ plus::a#0 ] +Allocated (was zp[1]:4) zp[1]:2 [ plus::a#0 ] + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Test a procedure with calling convention stack + // Upstart +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + // Global Constants & labels + .const STACK_BASE = $103 + .label SCREEN = $400 +.segment stage + // plus +// __register(A) char plus(__zp(2) char a, __register(A) char b) +plus: { + .const OFFSET_STACK_A = 1 + .const OFFSET_STACK_B = 0 + .const OFFSET_STACK_RETURN_1 = 1 + .label a = 2 + // [0] plus::a#0 = stackidx(char,plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 + tsx + lda STACK_BASE+OFFSET_STACK_A,x + sta.z a + // [1] plus::b#0 = stackidx(char,plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1 + tsx + lda STACK_BASE+OFFSET_STACK_B,x + // [2] plus::return#0 = plus::a#0 + plus::b#0 -- vbuaa=vbuz1_plus_vbuaa + clc + adc.z a + jmp __breturn + // plus::@return + __breturn: + // [3] stackidx(char,plus::OFFSET_STACK_RETURN_1) = plus::return#0 -- _stackidxbyte_vbuc1=vbuaa + tsx + sta STACK_BASE+OFFSET_STACK_RETURN_1,x + // [4] return + rts +} + // main +main: { + // [5] stackpush(char) = '0' -- _stackpushbyte_=vbuc1 + lda #'0' + pha + // [6] stackpush(char) = 7 -- _stackpushbyte_=vbuc1 + lda #7 + pha + // [7] callexecute plus -- call_vprc1 + jsr plus + // sideeffect stackpullpadding(1) -- _stackpullpadding_1 + pla + // [9] main::$0 = stackpull(char) -- vbuaa=_stackpullbyte_ + pla + // [10] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa + sta SCREEN + jmp __breturn + // main::@return + __breturn: + // [11] return + rts +} + // File Data + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __breturn +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction __breturn: +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +__constant char * const SCREEN = (char *) 1024 +__constant unsigned int STACK_BASE = $103 +void main() +char main::$0 // reg byte a 4.0 +__stackcall char plus(char a , char b) +__constant char plus::OFFSET_STACK_A = 1 +__constant char plus::OFFSET_STACK_B = 0 +__constant char plus::OFFSET_STACK_RETURN_1 = 1 +char plus::a +char plus::a#0 // a zp[1]:2 11.0 +char plus::b +char plus::b#0 // reg byte a 22.0 +char plus::return +char plus::return#0 // reg byte a 22.0 + +zp[1]:2 [ plus::a#0 ] +reg byte a [ plus::b#0 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] + + +FINAL ASSEMBLER +Score: 67 + + // File Comments +// Test a procedure with calling convention stack + // Upstart +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + // Global Constants & labels + .const STACK_BASE = $103 + .label SCREEN = $400 +.segment stage + // plus +// __register(A) char plus(__zp(2) char a, __register(A) char b) +plus: { + .const OFFSET_STACK_A = 1 + .const OFFSET_STACK_B = 0 + .const OFFSET_STACK_RETURN_1 = 1 + .label a = 2 + // [0] plus::a#0 = stackidx(char,plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 + tsx + lda STACK_BASE+OFFSET_STACK_A,x + sta.z a + // [1] plus::b#0 = stackidx(char,plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1 + tsx + lda STACK_BASE+OFFSET_STACK_B,x + // return a+b; + // [2] plus::return#0 = plus::a#0 + plus::b#0 -- vbuaa=vbuz1_plus_vbuaa + clc + adc.z a + // plus::@return + // } + // [3] stackidx(char,plus::OFFSET_STACK_RETURN_1) = plus::return#0 -- _stackidxbyte_vbuc1=vbuaa + tsx + sta STACK_BASE+OFFSET_STACK_RETURN_1,x + // [4] return + rts +} + // main +main: { + // plus('0', 7) + // [5] stackpush(char) = '0' -- _stackpushbyte_=vbuc1 + lda #'0' + pha + // [6] stackpush(char) = 7 -- _stackpushbyte_=vbuc1 + lda #7 + pha + // [7] callexecute plus -- call_vprc1 + jsr plus + // sideeffect stackpullpadding(1) -- _stackpullpadding_1 + pla + // [9] main::$0 = stackpull(char) -- vbuaa=_stackpullbyte_ + pla + // SCREEN[0] = plus('0', 7) + // [10] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa + sta SCREEN + // main::@return + // } + // [11] return + rts +} + // File Data + diff --git a/src/test/ref/procedure-callingconvention-stack-bank-0.sym b/src/test/ref/procedure-callingconvention-stack-bank-0.sym new file mode 100644 index 000000000..30874c0fd --- /dev/null +++ b/src/test/ref/procedure-callingconvention-stack-bank-0.sym @@ -0,0 +1,19 @@ +__constant char * const SCREEN = (char *) 1024 +__constant unsigned int STACK_BASE = $103 +void main() +char main::$0 // reg byte a 4.0 +__stackcall char plus(char a , char b) +__constant char plus::OFFSET_STACK_A = 1 +__constant char plus::OFFSET_STACK_B = 0 +__constant char plus::OFFSET_STACK_RETURN_1 = 1 +char plus::a +char plus::a#0 // a zp[1]:2 11.0 +char plus::b +char plus::b#0 // reg byte a 22.0 +char plus::return +char plus::return#0 // reg byte a 22.0 + +zp[1]:2 [ plus::a#0 ] +reg byte a [ plus::b#0 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] diff --git a/src/test/ref/procedure-callingconvention-stack-bank-1.asm b/src/test/ref/procedure-callingconvention-stack-bank-1.asm new file mode 100644 index 000000000..ec687e5fb --- /dev/null +++ b/src/test/ref/procedure-callingconvention-stack-bank-1.asm @@ -0,0 +1,45 @@ +// Test a procedure with calling convention stack +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + .const STACK_BASE = $103 + .label SCREEN = $400 +.segment stage +// __register(A) char plus(__zp(2) char a, __register(A) char b) +plus: { + .const OFFSET_STACK_A = 1 + .const OFFSET_STACK_B = 0 + .const OFFSET_STACK_RETURN_1 = 1 + .label a = 2 + tsx + lda STACK_BASE+OFFSET_STACK_A,x + sta.z a + tsx + lda STACK_BASE+OFFSET_STACK_B,x + // return a+b; + clc + adc.z a + // } + tsx + sta STACK_BASE+OFFSET_STACK_RETURN_1,x + rts +} +main: { + // plus('0', 7) + lda #'0' + pha + lda #7 + pha + jsr plus + pla + pla + // SCREEN[0] = plus('0', 7) + sta SCREEN + // } + rts +} diff --git a/src/test/ref/procedure-callingconvention-stack-bank-1.cfg b/src/test/ref/procedure-callingconvention-stack-bank-1.cfg new file mode 100644 index 000000000..e23f2647e --- /dev/null +++ b/src/test/ref/procedure-callingconvention-stack-bank-1.cfg @@ -0,0 +1,24 @@ + +__stackcall char plus(char a , char b) +plus: scope:[plus] from + [0] plus::a#0 = stackidx(char,plus::OFFSET_STACK_A) + [1] plus::b#0 = stackidx(char,plus::OFFSET_STACK_B) + [2] plus::return#0 = plus::a#0 + plus::b#0 + to:plus::@return +plus::@return: scope:[plus] from plus + [3] stackidx(char,plus::OFFSET_STACK_RETURN_1) = plus::return#0 + [4] return + to:@return + +void main() +main: scope:[main] from + [5] stackpush(char) = '0' + [6] stackpush(char) = 7 + [7] callexecute plus + sideeffect stackpullpadding(1) + [9] main::$0 = stackpull(char) + [10] *SCREEN = main::$0 + to:main::@return +main::@return: scope:[main] from main + [11] return + to:@return diff --git a/src/test/ref/procedure-callingconvention-stack-bank-1.log b/src/test/ref/procedure-callingconvention-stack-bank-1.log new file mode 100644 index 000000000..de9b614ed --- /dev/null +++ b/src/test/ref/procedure-callingconvention-stack-bank-1.log @@ -0,0 +1,350 @@ +Loading link script "procedure-callingconvention-stack-bank.ld" +Adding parameter assignment in __stackcall procedure plus::b = param(plus::b) +Adding parameter assignment in __stackcall procedure plus::a = param(plus::a) +Calling convention __stackcall adding prepare/execute/finalize for main::$0 = call plus('0', 7) +Calling convention STACK_CALL replacing param(plus::a) with stackidx(char,plus::OFFSET_STACK_A) +Calling convention STACK_CALL replacing param(plus::b) with stackidx(char,plus::OFFSET_STACK_B) +Calling convention STACK_CALL adding stack return stackidx(char,plus::OFFSET_STACK_RETURN_1) = plus::return +Calling convention STACK_CALL adding stack pull main::$0 = stackpull(char) +Calling convention STACK_CALL adding stack push stackpush(char) = '0' +Calling convention STACK_CALL adding stack push stackpush(char) = 7 + +CONTROL FLOW GRAPH SSA + +void main() +main: scope:[main] from __start + stackpush(char) = '0' + stackpush(char) = 7 + callexecute plus + sideeffect stackpullpadding(1) + main::$0 = stackpull(char) + SCREEN[0] = main::$0 + to:main::@return +main::@return: scope:[main] from main + return + to:@return + +__stackcall char plus(char a , char b) +plus: scope:[plus] from + plus::a#0 = stackidx(char,plus::OFFSET_STACK_A) + plus::b#0 = stackidx(char,plus::OFFSET_STACK_B) + plus::$0 = plus::a#0 + plus::b#0 + plus::return#0 = plus::$0 + to:plus::@return +plus::@return: scope:[plus] from plus + plus::return#1 = phi( plus/plus::return#0 ) + stackidx(char,plus::OFFSET_STACK_RETURN_1) = plus::return#1 + return + to:@return + +void __start() +__start: scope:[__start] from + call main + to:__start::@1 +__start::@1: scope:[__start] from __start + to:__start::@return +__start::@return: scope:[__start] from __start::@1 + return + to:@return + +SYMBOL TABLE SSA +__constant char * const SCREEN = (char *)$400 +__constant unsigned int STACK_BASE = $103 +void __start() +void main() +char main::$0 +__stackcall char plus(char a , char b) +char plus::$0 +__constant char plus::OFFSET_STACK_A = 1 +__constant char plus::OFFSET_STACK_B = 0 +__constant char plus::OFFSET_STACK_RETURN_1 = 1 +char plus::a +char plus::a#0 +char plus::b +char plus::b#0 +char plus::return +char plus::return#0 +char plus::return#1 + +Adding number conversion cast (unumber) 7 in stackpush(char) = 7 +Adding number conversion cast (unumber) 0 in SCREEN[0] = main::$0 +Successful SSA optimization PassNAddNumberTypeConversions +Inlining cast stackpush(char) = (unumber)7 +Successful SSA optimization Pass2InlineCast +Simplifying constant pointer cast (char *) 1024 +Simplifying constant integer cast 7 +Simplifying constant integer cast 0 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (char) 7 +Finalized unsigned number type (char) 0 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Alias plus::return#0 = plus::$0 plus::return#1 +Successful SSA optimization Pass2AliasElimination +Simplifying expression containing zero SCREEN in [5] SCREEN[0] = main::$0 +Successful SSA optimization PassNSimplifyExpressionWithZero +Removing unused procedure __start +Removing unused procedure block __start +Removing unused procedure block __start::@1 +Removing unused procedure block __start::@return +Successful SSA optimization PassNEliminateEmptyStart +Finalized unsigned number type (char) 1 +Successful SSA optimization PassNFinalizeNumberTypeConversions +CALL GRAPH +Calls in [main] to plus:7 + +Created 0 initial phi equivalence classes +Coalesced down to 0 phi equivalence classes + +FINAL CONTROL FLOW GRAPH + +__stackcall char plus(char a , char b) +plus: scope:[plus] from + [0] plus::a#0 = stackidx(char,plus::OFFSET_STACK_A) + [1] plus::b#0 = stackidx(char,plus::OFFSET_STACK_B) + [2] plus::return#0 = plus::a#0 + plus::b#0 + to:plus::@return +plus::@return: scope:[plus] from plus + [3] stackidx(char,plus::OFFSET_STACK_RETURN_1) = plus::return#0 + [4] return + to:@return + +void main() +main: scope:[main] from + [5] stackpush(char) = '0' + [6] stackpush(char) = 7 + [7] callexecute plus + sideeffect stackpullpadding(1) + [9] main::$0 = stackpull(char) + [10] *SCREEN = main::$0 + to:main::@return +main::@return: scope:[main] from main + [11] return + to:@return + + +VARIABLE REGISTER WEIGHTS +void main() +char main::$0 // 4.0 +__stackcall char plus(char a , char b) +char plus::a +char plus::a#0 // 11.0 +char plus::b +char plus::b#0 // 22.0 +char plus::return +char plus::return#0 // 22.0 + +Initial phi equivalence classes +Added variable plus::a#0 to live range equivalence class [ plus::a#0 ] +Added variable plus::b#0 to live range equivalence class [ plus::b#0 ] +Added variable plus::return#0 to live range equivalence class [ plus::return#0 ] +Added variable main::$0 to live range equivalence class [ main::$0 ] +Complete equivalence classes +[ plus::a#0 ] +[ plus::b#0 ] +[ plus::return#0 ] +[ main::$0 ] +Allocated zp[1]:2 [ plus::b#0 ] +Allocated zp[1]:3 [ plus::return#0 ] +Allocated zp[1]:4 [ plus::a#0 ] +Allocated zp[1]:5 [ main::$0 ] +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [0] plus::a#0 = stackidx(char,plus::OFFSET_STACK_A) [ plus::a#0 ] ( plus:7 [ plus::a#0 ] { } ) always clobbers reg byte a reg byte x +Statement [1] plus::b#0 = stackidx(char,plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( plus:7 [ plus::a#0 plus::b#0 ] { } ) always clobbers reg byte a reg byte x +Removing always clobbered register reg byte a as potential for zp[1]:4 [ plus::a#0 ] +Removing always clobbered register reg byte x as potential for zp[1]:4 [ plus::a#0 ] +Statement [2] plus::return#0 = plus::a#0 + plus::b#0 [ plus::return#0 ] ( plus:7 [ plus::return#0 ] { } ) always clobbers reg byte a +Statement [3] stackidx(char,plus::OFFSET_STACK_RETURN_1) = plus::return#0 [ ] ( plus:7 [ ] { } ) always clobbers reg byte x +Statement [5] stackpush(char) = '0' [ ] ( [ ] { } ) always clobbers reg byte a +Statement [6] stackpush(char) = 7 [ ] ( [ ] { } ) always clobbers reg byte a +Statement sideeffect stackpullpadding(1) always clobbers reg byte a +Statement [9] main::$0 = stackpull(char) [ main::$0 ] ( [ main::$0 ] { } ) always clobbers reg byte a +Statement [0] plus::a#0 = stackidx(char,plus::OFFSET_STACK_A) [ plus::a#0 ] ( plus:7 [ plus::a#0 ] { } ) always clobbers reg byte a reg byte x +Statement [1] plus::b#0 = stackidx(char,plus::OFFSET_STACK_B) [ plus::a#0 plus::b#0 ] ( plus:7 [ plus::a#0 plus::b#0 ] { } ) always clobbers reg byte a reg byte x +Statement [2] plus::return#0 = plus::a#0 + plus::b#0 [ plus::return#0 ] ( plus:7 [ plus::return#0 ] { } ) always clobbers reg byte a +Statement [3] stackidx(char,plus::OFFSET_STACK_RETURN_1) = plus::return#0 [ ] ( plus:7 [ ] { } ) always clobbers reg byte x +Statement [5] stackpush(char) = '0' [ ] ( [ ] { } ) always clobbers reg byte a +Statement [6] stackpush(char) = 7 [ ] ( [ ] { } ) always clobbers reg byte a +Statement sideeffect stackpullpadding(1) always clobbers reg byte a +Statement [9] main::$0 = stackpull(char) [ main::$0 ] ( [ main::$0 ] { } ) always clobbers reg byte a +Potential registers zp[1]:4 [ plus::a#0 ] : zp[1]:4 , reg byte y , +Potential registers zp[1]:2 [ plus::b#0 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:3 [ plus::return#0 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:5 [ main::$0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , + +REGISTER UPLIFT SCOPES +Uplift Scope [plus] 22: zp[1]:2 [ plus::b#0 ] 22: zp[1]:3 [ plus::return#0 ] 11: zp[1]:4 [ plus::a#0 ] +Uplift Scope [main] 4: zp[1]:5 [ main::$0 ] +Uplift Scope [] + +Uplifting [plus] best 79 combination reg byte a [ plus::b#0 ] reg byte a [ plus::return#0 ] zp[1]:4 [ plus::a#0 ] +Uplifting [main] best 73 combination reg byte a [ main::$0 ] +Uplifting [] best 73 combination +Attempting to uplift remaining variables inzp[1]:4 [ plus::a#0 ] +Uplifting [plus] best 73 combination zp[1]:4 [ plus::a#0 ] +Allocated (was zp[1]:4) zp[1]:2 [ plus::a#0 ] + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Test a procedure with calling convention stack + // Upstart +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + // Global Constants & labels + .const STACK_BASE = $103 + .label SCREEN = $400 +.segment stage + // plus +// __register(A) char plus(__zp(2) char a, __register(A) char b) +plus: { + .const OFFSET_STACK_A = 1 + .const OFFSET_STACK_B = 0 + .const OFFSET_STACK_RETURN_1 = 1 + .label a = 2 + // [0] plus::a#0 = stackidx(char,plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 + tsx + lda STACK_BASE+OFFSET_STACK_A,x + sta.z a + // [1] plus::b#0 = stackidx(char,plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1 + tsx + lda STACK_BASE+OFFSET_STACK_B,x + // [2] plus::return#0 = plus::a#0 + plus::b#0 -- vbuaa=vbuz1_plus_vbuaa + clc + adc.z a + jmp __breturn + // plus::@return + __breturn: + // [3] stackidx(char,plus::OFFSET_STACK_RETURN_1) = plus::return#0 -- _stackidxbyte_vbuc1=vbuaa + tsx + sta STACK_BASE+OFFSET_STACK_RETURN_1,x + // [4] return + rts +} + // main +main: { + // [5] stackpush(char) = '0' -- _stackpushbyte_=vbuc1 + lda #'0' + pha + // [6] stackpush(char) = 7 -- _stackpushbyte_=vbuc1 + lda #7 + pha + // [7] callexecute plus -- call_vprc1 + jsr plus + // sideeffect stackpullpadding(1) -- _stackpullpadding_1 + pla + // [9] main::$0 = stackpull(char) -- vbuaa=_stackpullbyte_ + pla + // [10] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa + sta SCREEN + jmp __breturn + // main::@return + __breturn: + // [11] return + rts +} + // File Data + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __breturn +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction __breturn: +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +__constant char * const SCREEN = (char *) 1024 +__constant unsigned int STACK_BASE = $103 +void main() +char main::$0 // reg byte a 4.0 +__stackcall char plus(char a , char b) +__constant char plus::OFFSET_STACK_A = 1 +__constant char plus::OFFSET_STACK_B = 0 +__constant char plus::OFFSET_STACK_RETURN_1 = 1 +char plus::a +char plus::a#0 // a zp[1]:2 11.0 +char plus::b +char plus::b#0 // reg byte a 22.0 +char plus::return +char plus::return#0 // reg byte a 22.0 + +zp[1]:2 [ plus::a#0 ] +reg byte a [ plus::b#0 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] + + +FINAL ASSEMBLER +Score: 67 + + // File Comments +// Test a procedure with calling convention stack + // Upstart +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + // Global Constants & labels + .const STACK_BASE = $103 + .label SCREEN = $400 +.segment stage + // plus +// __register(A) char plus(__zp(2) char a, __register(A) char b) +plus: { + .const OFFSET_STACK_A = 1 + .const OFFSET_STACK_B = 0 + .const OFFSET_STACK_RETURN_1 = 1 + .label a = 2 + // [0] plus::a#0 = stackidx(char,plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 + tsx + lda STACK_BASE+OFFSET_STACK_A,x + sta.z a + // [1] plus::b#0 = stackidx(char,plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1 + tsx + lda STACK_BASE+OFFSET_STACK_B,x + // return a+b; + // [2] plus::return#0 = plus::a#0 + plus::b#0 -- vbuaa=vbuz1_plus_vbuaa + clc + adc.z a + // plus::@return + // } + // [3] stackidx(char,plus::OFFSET_STACK_RETURN_1) = plus::return#0 -- _stackidxbyte_vbuc1=vbuaa + tsx + sta STACK_BASE+OFFSET_STACK_RETURN_1,x + // [4] return + rts +} + // main +main: { + // plus('0', 7) + // [5] stackpush(char) = '0' -- _stackpushbyte_=vbuc1 + lda #'0' + pha + // [6] stackpush(char) = 7 -- _stackpushbyte_=vbuc1 + lda #7 + pha + // [7] callexecute plus -- call_vprc1 + jsr plus + // sideeffect stackpullpadding(1) -- _stackpullpadding_1 + pla + // [9] main::$0 = stackpull(char) -- vbuaa=_stackpullbyte_ + pla + // SCREEN[0] = plus('0', 7) + // [10] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa + sta SCREEN + // main::@return + // } + // [11] return + rts +} + // File Data + diff --git a/src/test/ref/procedure-callingconvention-stack-bank-1.sym b/src/test/ref/procedure-callingconvention-stack-bank-1.sym new file mode 100644 index 000000000..30874c0fd --- /dev/null +++ b/src/test/ref/procedure-callingconvention-stack-bank-1.sym @@ -0,0 +1,19 @@ +__constant char * const SCREEN = (char *) 1024 +__constant unsigned int STACK_BASE = $103 +void main() +char main::$0 // reg byte a 4.0 +__stackcall char plus(char a , char b) +__constant char plus::OFFSET_STACK_A = 1 +__constant char plus::OFFSET_STACK_B = 0 +__constant char plus::OFFSET_STACK_RETURN_1 = 1 +char plus::a +char plus::a#0 // a zp[1]:2 11.0 +char plus::b +char plus::b#0 // reg byte a 22.0 +char plus::return +char plus::return#0 // reg byte a 22.0 + +zp[1]:2 [ plus::a#0 ] +reg byte a [ plus::b#0 ] +reg byte a [ plus::return#0 ] +reg byte a [ main::$0 ] diff --git a/src/test/ref/procedure-callingconvention-stack-bank-2.asm b/src/test/ref/procedure-callingconvention-stack-bank-2.asm new file mode 100644 index 000000000..10a9f97c1 --- /dev/null +++ b/src/test/ref/procedure-callingconvention-stack-bank-2.asm @@ -0,0 +1,74 @@ +// Test a procedure with calling convention stack +// A slightly more complex call +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + .const STACK_BASE = $103 + .label SCREEN = $400 + .label i = 4 +.segment Code +__start: { + // char i = 0 + lda #0 + sta.z i + jsr main + rts +} +.segment stage +// this should give a pragma error during compile, as test is not declared yet. +// __register(A) char plus(__zp(2) char a, __register(A) char b) +plus: { + .const OFFSET_STACK_A = 1 + .const OFFSET_STACK_B = 0 + .const OFFSET_STACK_RETURN_1 = 1 + .label a = 2 + tsx + lda STACK_BASE+OFFSET_STACK_A,x + sta.z a + tsx + lda STACK_BASE+OFFSET_STACK_B,x + // i++; + inc.z i + // return a+b; + clc + adc.z a + // } + tsx + sta STACK_BASE+OFFSET_STACK_RETURN_1,x + rts +} +main: { + .label a = 3 + lda #0 + sta.z a + __b1: + // char v = a+1 + ldx.z a + inx + // char w = plus('0', v) + lda #'0' + pha + txa + pha + jsr plus + pla + pla + // w+a + clc + adc.z a + // SCREEN[i] = w+a + ldy.z i + sta SCREEN,y + // for(char a:0..1) + inc.z a + lda #2 + cmp.z a + bne __b1 + // } + rts +} diff --git a/src/test/ref/procedure-callingconvention-stack-bank-2.cfg b/src/test/ref/procedure-callingconvention-stack-bank-2.cfg new file mode 100644 index 000000000..ff4b58982 --- /dev/null +++ b/src/test/ref/procedure-callingconvention-stack-bank-2.cfg @@ -0,0 +1,48 @@ + +void __start() +__start: scope:[__start] from + [0] phi() + to:__start::__init1 +__start::__init1: scope:[__start] from __start + [1] i = 0 + to:__start::@1 +__start::@1: scope:[__start] from __start::__init1 + [2] phi() + [3] call main + to:__start::@return +__start::@return: scope:[__start] from __start::@1 + [4] return + to:@return + +__stackcall char plus(char a , char b) +plus: scope:[plus] from + [5] plus::a#0 = stackidx(char,plus::OFFSET_STACK_A) + [6] plus::b#0 = stackidx(char,plus::OFFSET_STACK_B) + [7] i = ++ i + [8] plus::return#0 = plus::a#0 + plus::b#0 + to:plus::@return +plus::@return: scope:[plus] from plus + [9] stackidx(char,plus::OFFSET_STACK_RETURN_1) = plus::return#0 + [10] return + to:@return + +void main() +main: scope:[main] from __start::@1 + [11] phi() + to:main::@1 +main::@1: scope:[main] from main main::@1 + [12] main::a#2 = phi( main/0, main::@1/main::a#1 ) + [13] main::v#0 = main::a#2 + 1 + [14] stackpush(char) = '0' + [15] stackpush(char) = main::v#0 + [16] callexecute plus + sideeffect stackpullpadding(1) + [18] main::w#0 = stackpull(char) + [19] main::$2 = main::w#0 + main::a#2 + [20] SCREEN[i] = main::$2 + [21] main::a#1 = ++ main::a#2 + [22] if(main::a#1!=2) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + [23] return + to:@return diff --git a/src/test/ref/procedure-callingconvention-stack-bank-2.log b/src/test/ref/procedure-callingconvention-stack-bank-2.log new file mode 100644 index 000000000..4a6f3d67b --- /dev/null +++ b/src/test/ref/procedure-callingconvention-stack-bank-2.log @@ -0,0 +1,595 @@ +Loading link script "procedure-callingconvention-stack-bank.ld" +Converting variable modified inside __stackcall procedure plus() to load/store i +Adding parameter assignment in __stackcall procedure plus::b = param(plus::b) +Adding parameter assignment in __stackcall procedure plus::a = param(plus::a) +Inlined call call __init +Eliminating unused variable with no statement main::$0 +Eliminating unused variable with no statement main::$1 +Calling convention __stackcall adding prepare/execute/finalize for main::w = call plus('0', main::v) +Calling convention STACK_CALL replacing param(plus::a) with stackidx(char,plus::OFFSET_STACK_A) +Calling convention STACK_CALL replacing param(plus::b) with stackidx(char,plus::OFFSET_STACK_B) +Calling convention STACK_CALL adding stack return stackidx(char,plus::OFFSET_STACK_RETURN_1) = plus::return +Calling convention STACK_CALL adding stack pull main::w = stackpull(char) +Calling convention STACK_CALL adding stack push stackpush(char) = '0' +Calling convention STACK_CALL adding stack push stackpush(char) = main::v + +CONTROL FLOW GRAPH SSA + +void main() +main: scope:[main] from __start::@1 + main::a#0 = 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + main::a#2 = phi( main/main::a#0, main::@1/main::a#1 ) + main::v#0 = main::a#2 + 1 + stackpush(char) = '0' + stackpush(char) = main::v#0 + callexecute plus + sideeffect stackpullpadding(1) + main::w#0 = stackpull(char) + main::$2 = main::w#0 + main::a#2 + SCREEN[i] = main::$2 + main::a#1 = main::a#2 + rangenext(0,1) + main::$3 = main::a#1 != rangelast(0,1) + if(main::$3) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return + +__stackcall char plus(char a , char b) +plus: scope:[plus] from + plus::a#0 = stackidx(char,plus::OFFSET_STACK_A) + plus::b#0 = stackidx(char,plus::OFFSET_STACK_B) + i = ++ i + plus::$0 = plus::a#0 + plus::b#0 + plus::return#0 = plus::$0 + to:plus::@return +plus::@return: scope:[plus] from plus + plus::return#1 = phi( plus/plus::return#0 ) + stackidx(char,plus::OFFSET_STACK_RETURN_1) = plus::return#1 + return + to:@return + +void __start() +__start: scope:[__start] from + to:__start::__init1 +__start::__init1: scope:[__start] from __start + i = 0 + to:__start::@1 +__start::@1: scope:[__start] from __start::__init1 + call main + to:__start::@2 +__start::@2: scope:[__start] from __start::@1 + to:__start::@return +__start::@return: scope:[__start] from __start::@2 + return + to:@return + +SYMBOL TABLE SSA +__constant char * const SCREEN = (char *)$400 +__constant unsigned int STACK_BASE = $103 +void __start() +__loadstore char i +void main() +char main::$2 +bool main::$3 +char main::a +char main::a#0 +char main::a#1 +char main::a#2 +char main::v +char main::v#0 +char main::w +char main::w#0 +__stackcall char plus(char a , char b) +char plus::$0 +__constant char plus::OFFSET_STACK_A = 1 +__constant char plus::OFFSET_STACK_B = 0 +__constant char plus::OFFSET_STACK_RETURN_1 = 1 +char plus::a +char plus::a#0 +char plus::b +char plus::b#0 +char plus::return +char plus::return#0 +char plus::return#1 + +Adding number conversion cast (unumber) 1 in main::v#0 = main::a#2 + 1 +Successful SSA optimization PassNAddNumberTypeConversions +Simplifying constant pointer cast (char *) 1024 +Simplifying constant integer cast 1 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (char) 1 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Alias plus::return#0 = plus::$0 plus::return#1 +Successful SSA optimization Pass2AliasElimination +Simple Condition main::$3 [12] if(main::a#1!=rangelast(0,1)) goto main::@1 +Successful SSA optimization Pass2ConditionalJumpSimplification +Constant main::a#0 = 0 +Successful SSA optimization Pass2ConstantIdentification +Resolved ranged next value [10] main::a#1 = ++ main::a#2 to ++ +Resolved ranged comparison value [12] if(main::a#1!=rangelast(0,1)) goto main::@1 to 2 +Adding number conversion cast (unumber) 2 in if(main::a#1!=2) goto main::@1 +Successful SSA optimization PassNAddNumberTypeConversions +Simplifying constant integer cast 2 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (char) 2 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Inlining constant with var siblings main::a#0 +Constant inlined main::a#0 = 0 +Successful SSA optimization Pass2ConstantInlining +Finalized unsigned number type (char) 1 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Added new block during phi lifting main::@2(between main::@1 and main::@1) +Adding NOP phi() at start of __start +Adding NOP phi() at start of __start::@1 +Adding NOP phi() at start of __start::@2 +Adding NOP phi() at start of main +CALL GRAPH +Calls in [__start] to main:3 +Calls in [main] to plus:17 + +Created 1 initial phi equivalence classes +Coalesced [25] main::a#3 = main::a#1 +Coalesced down to 1 phi equivalence classes +Culled Empty Block label __start::@2 +Culled Empty Block label main::@2 +Adding NOP phi() at start of __start +Adding NOP phi() at start of __start::@1 +Adding NOP phi() at start of main + +FINAL CONTROL FLOW GRAPH + +void __start() +__start: scope:[__start] from + [0] phi() + to:__start::__init1 +__start::__init1: scope:[__start] from __start + [1] i = 0 + to:__start::@1 +__start::@1: scope:[__start] from __start::__init1 + [2] phi() + [3] call main + to:__start::@return +__start::@return: scope:[__start] from __start::@1 + [4] return + to:@return + +__stackcall char plus(char a , char b) +plus: scope:[plus] from + [5] plus::a#0 = stackidx(char,plus::OFFSET_STACK_A) + [6] plus::b#0 = stackidx(char,plus::OFFSET_STACK_B) + [7] i = ++ i + [8] plus::return#0 = plus::a#0 + plus::b#0 + to:plus::@return +plus::@return: scope:[plus] from plus + [9] stackidx(char,plus::OFFSET_STACK_RETURN_1) = plus::return#0 + [10] return + to:@return + +void main() +main: scope:[main] from __start::@1 + [11] phi() + to:main::@1 +main::@1: scope:[main] from main main::@1 + [12] main::a#2 = phi( main/0, main::@1/main::a#1 ) + [13] main::v#0 = main::a#2 + 1 + [14] stackpush(char) = '0' + [15] stackpush(char) = main::v#0 + [16] callexecute plus + sideeffect stackpullpadding(1) + [18] main::w#0 = stackpull(char) + [19] main::$2 = main::w#0 + main::a#2 + [20] SCREEN[i] = main::$2 + [21] main::a#1 = ++ main::a#2 + [22] if(main::a#1!=2) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + [23] return + to:@return + +null depth in calling loop Loop head: main::@1 tails: main::@1 blocks: main::@1 in scope plus + +VARIABLE REGISTER WEIGHTS +void __start() +__loadstore char i // 105.24999999999999 +void main() +char main::$2 // 202.0 +char main::a +char main::a#1 // 151.5 +char main::a#2 // 44.888888888888886 +char main::v +char main::v#0 // 101.0 +char main::w +char main::w#0 // 202.0 +__stackcall char plus(char a , char b) +char plus::a +char plus::a#0 // 667.3333333333334 +char plus::b +char plus::b#0 // 1001.0 +char plus::return +char plus::return#0 // 2002.0 + +Initial phi equivalence classes +[ main::a#2 main::a#1 ] +Added variable i to live range equivalence class [ i ] +Added variable plus::a#0 to live range equivalence class [ plus::a#0 ] +Added variable plus::b#0 to live range equivalence class [ plus::b#0 ] +Added variable plus::return#0 to live range equivalence class [ plus::return#0 ] +Added variable main::v#0 to live range equivalence class [ main::v#0 ] +Added variable main::w#0 to live range equivalence class [ main::w#0 ] +Added variable main::$2 to live range equivalence class [ main::$2 ] +Complete equivalence classes +[ main::a#2 main::a#1 ] +[ i ] +[ plus::a#0 ] +[ plus::b#0 ] +[ plus::return#0 ] +[ main::v#0 ] +[ main::w#0 ] +[ main::$2 ] +Allocated zp[1]:2 [ plus::return#0 ] +Allocated zp[1]:3 [ plus::b#0 ] +Allocated zp[1]:4 [ plus::a#0 ] +Allocated zp[1]:5 [ main::w#0 ] +Allocated zp[1]:6 [ main::$2 ] +Allocated zp[1]:7 [ main::a#2 main::a#1 ] +Allocated zp[1]:8 [ i ] +Allocated zp[1]:9 [ main::v#0 ] +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [1] i = 0 [ i ] ( [ i ] { } ) always clobbers reg byte a +Statement [5] plus::a#0 = stackidx(char,plus::OFFSET_STACK_A) [ i plus::a#0 ] ( main:3::plus:16 [ main::a#2 i plus::a#0 ] { } ) always clobbers reg byte a reg byte x +Removing always clobbered register reg byte a as potential for zp[1]:7 [ main::a#2 main::a#1 ] +Removing always clobbered register reg byte x as potential for zp[1]:7 [ main::a#2 main::a#1 ] +Statement [6] plus::b#0 = stackidx(char,plus::OFFSET_STACK_B) [ i plus::a#0 plus::b#0 ] ( main:3::plus:16 [ main::a#2 i plus::a#0 plus::b#0 ] { } ) always clobbers reg byte a reg byte x +Removing always clobbered register reg byte a as potential for zp[1]:4 [ plus::a#0 ] +Removing always clobbered register reg byte x as potential for zp[1]:4 [ plus::a#0 ] +Statement [8] plus::return#0 = plus::a#0 + plus::b#0 [ i plus::return#0 ] ( main:3::plus:16 [ main::a#2 i plus::return#0 ] { } ) always clobbers reg byte a +Statement [9] stackidx(char,plus::OFFSET_STACK_RETURN_1) = plus::return#0 [ i ] ( main:3::plus:16 [ main::a#2 i ] { } ) always clobbers reg byte x +Statement [14] stackpush(char) = '0' [ i main::a#2 main::v#0 ] ( main:3 [ i main::a#2 main::v#0 ] { } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:9 [ main::v#0 ] +Statement [15] stackpush(char) = main::v#0 [ i main::a#2 ] ( main:3 [ i main::a#2 ] { } ) always clobbers reg byte a +Statement sideeffect stackpullpadding(1) always clobbers reg byte a +Statement [18] main::w#0 = stackpull(char) [ i main::a#2 main::w#0 ] ( main:3 [ i main::a#2 main::w#0 ] { } ) always clobbers reg byte a +Statement [19] main::$2 = main::w#0 + main::a#2 [ i main::a#2 main::$2 ] ( main:3 [ i main::a#2 main::$2 ] { } ) always clobbers reg byte a +Statement [20] SCREEN[i] = main::$2 [ i main::a#2 ] ( main:3 [ i main::a#2 ] { } ) always clobbers reg byte y +Removing always clobbered register reg byte y as potential for zp[1]:7 [ main::a#2 main::a#1 ] +Statement [22] if(main::a#1!=2) goto main::@1 [ i main::a#1 ] ( main:3 [ i main::a#1 ] { } ) always clobbers reg byte a +Statement [1] i = 0 [ i ] ( [ i ] { } ) always clobbers reg byte a +Statement [5] plus::a#0 = stackidx(char,plus::OFFSET_STACK_A) [ i plus::a#0 ] ( main:3::plus:16 [ main::a#2 i plus::a#0 ] { } ) always clobbers reg byte a reg byte x +Statement [6] plus::b#0 = stackidx(char,plus::OFFSET_STACK_B) [ i plus::a#0 plus::b#0 ] ( main:3::plus:16 [ main::a#2 i plus::a#0 plus::b#0 ] { } ) always clobbers reg byte a reg byte x +Statement [8] plus::return#0 = plus::a#0 + plus::b#0 [ i plus::return#0 ] ( main:3::plus:16 [ main::a#2 i plus::return#0 ] { } ) always clobbers reg byte a +Statement [9] stackidx(char,plus::OFFSET_STACK_RETURN_1) = plus::return#0 [ i ] ( main:3::plus:16 [ main::a#2 i ] { } ) always clobbers reg byte x +Statement [14] stackpush(char) = '0' [ i main::a#2 main::v#0 ] ( main:3 [ i main::a#2 main::v#0 ] { } ) always clobbers reg byte a +Statement [15] stackpush(char) = main::v#0 [ i main::a#2 ] ( main:3 [ i main::a#2 ] { } ) always clobbers reg byte a +Statement sideeffect stackpullpadding(1) always clobbers reg byte a +Statement [18] main::w#0 = stackpull(char) [ i main::a#2 main::w#0 ] ( main:3 [ i main::a#2 main::w#0 ] { } ) always clobbers reg byte a +Statement [19] main::$2 = main::w#0 + main::a#2 [ i main::a#2 main::$2 ] ( main:3 [ i main::a#2 main::$2 ] { } ) always clobbers reg byte a +Statement [20] SCREEN[i] = main::$2 [ i main::a#2 ] ( main:3 [ i main::a#2 ] { } ) always clobbers reg byte y +Statement [22] if(main::a#1!=2) goto main::@1 [ i main::a#1 ] ( main:3 [ i main::a#1 ] { } ) always clobbers reg byte a +Potential registers zp[1]:7 [ main::a#2 main::a#1 ] : zp[1]:7 , +Potential registers zp[1]:8 [ i ] : zp[1]:8 , +Potential registers zp[1]:4 [ plus::a#0 ] : zp[1]:4 , reg byte y , +Potential registers zp[1]:3 [ plus::b#0 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:2 [ plus::return#0 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:9 [ main::v#0 ] : zp[1]:9 , reg byte x , reg byte y , +Potential registers zp[1]:5 [ main::w#0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:6 [ main::$2 ] : zp[1]:6 , reg byte a , reg byte x , reg byte y , + +REGISTER UPLIFT SCOPES +Uplift Scope [plus] 2,002: zp[1]:2 [ plus::return#0 ] 1,001: zp[1]:3 [ plus::b#0 ] 667.33: zp[1]:4 [ plus::a#0 ] +Uplift Scope [main] 202: zp[1]:5 [ main::w#0 ] 202: zp[1]:6 [ main::$2 ] 196.39: zp[1]:7 [ main::a#2 main::a#1 ] 101: zp[1]:9 [ main::v#0 ] +Uplift Scope [] 105.25: zp[1]:8 [ i ] +Uplift Scope [__start] + +Uplifting [plus] best 945 combination reg byte a [ plus::return#0 ] reg byte a [ plus::b#0 ] zp[1]:4 [ plus::a#0 ] +Uplifting [main] best 785 combination reg byte a [ main::w#0 ] reg byte a [ main::$2 ] zp[1]:7 [ main::a#2 main::a#1 ] reg byte x [ main::v#0 ] +Uplifting [] best 785 combination zp[1]:8 [ i ] +Uplifting [__start] best 785 combination +Attempting to uplift remaining variables inzp[1]:4 [ plus::a#0 ] +Uplifting [plus] best 785 combination zp[1]:4 [ plus::a#0 ] +Attempting to uplift remaining variables inzp[1]:7 [ main::a#2 main::a#1 ] +Uplifting [main] best 785 combination zp[1]:7 [ main::a#2 main::a#1 ] +Attempting to uplift remaining variables inzp[1]:8 [ i ] +Uplifting [] best 785 combination zp[1]:8 [ i ] +Allocated (was zp[1]:4) zp[1]:2 [ plus::a#0 ] +Allocated (was zp[1]:7) zp[1]:3 [ main::a#2 main::a#1 ] +Allocated (was zp[1]:8) zp[1]:4 [ i ] + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Test a procedure with calling convention stack +// A slightly more complex call + // Upstart +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + // Global Constants & labels + .const STACK_BASE = $103 + .label SCREEN = $400 + .label i = 4 +.segment Code + // __start +__start: { + jmp __init1 + // __start::__init1 + __init1: + // [1] i = 0 -- vbuz1=vbuc1 + lda #0 + sta.z i + // [2] phi from __start::__init1 to __start::@1 [phi:__start::__init1->__start::@1] + __b1_from___init1: + jmp __b1 + // __start::@1 + __b1: + // [3] call main + // [11] phi from __start::@1 to main [phi:__start::@1->main] + main_from___b1: + jsr main + jmp __breturn + // __start::@return + __breturn: + // [4] return + rts +} +.segment stage + // plus +// this should give a pragma error during compile, as test is not declared yet. +// __register(A) char plus(__zp(2) char a, __register(A) char b) +plus: { + .const OFFSET_STACK_A = 1 + .const OFFSET_STACK_B = 0 + .const OFFSET_STACK_RETURN_1 = 1 + .label a = 2 + // [5] plus::a#0 = stackidx(char,plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 + tsx + lda STACK_BASE+OFFSET_STACK_A,x + sta.z a + // [6] plus::b#0 = stackidx(char,plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1 + tsx + lda STACK_BASE+OFFSET_STACK_B,x + // [7] i = ++ i -- vbuz1=_inc_vbuz1 + inc.z i + // [8] plus::return#0 = plus::a#0 + plus::b#0 -- vbuaa=vbuz1_plus_vbuaa + clc + adc.z a + jmp __breturn + // plus::@return + __breturn: + // [9] stackidx(char,plus::OFFSET_STACK_RETURN_1) = plus::return#0 -- _stackidxbyte_vbuc1=vbuaa + tsx + sta STACK_BASE+OFFSET_STACK_RETURN_1,x + // [10] return + rts +} + // main +main: { + .label a = 3 + // [12] phi from main to main::@1 [phi:main->main::@1] + __b1_from_main: + // [12] phi main::a#2 = 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 + lda #0 + sta.z a + jmp __b1 + // [12] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + __b1_from___b1: + // [12] phi main::a#2 = main::a#1 [phi:main::@1->main::@1#0] -- register_copy + jmp __b1 + // main::@1 + __b1: + // [13] main::v#0 = main::a#2 + 1 -- vbuxx=vbuz1_plus_1 + ldx.z a + inx + // [14] stackpush(char) = '0' -- _stackpushbyte_=vbuc1 + lda #'0' + pha + // [15] stackpush(char) = main::v#0 -- _stackpushbyte_=vbuxx + txa + pha + // [16] callexecute plus -- call_vprc1 + jsr plus + // sideeffect stackpullpadding(1) -- _stackpullpadding_1 + pla + // [18] main::w#0 = stackpull(char) -- vbuaa=_stackpullbyte_ + pla + // [19] main::$2 = main::w#0 + main::a#2 -- vbuaa=vbuaa_plus_vbuz1 + clc + adc.z a + // [20] SCREEN[i] = main::$2 -- pbuc1_derefidx_vbuz1=vbuaa + ldy.z i + sta SCREEN,y + // [21] main::a#1 = ++ main::a#2 -- vbuz1=_inc_vbuz1 + inc.z a + // [22] if(main::a#1!=2) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 + lda #2 + cmp.z a + bne __b1_from___b1 + jmp __breturn + // main::@return + __breturn: + // [23] return + rts +} + // File Data + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __init1 +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Removing instruction jmp __breturn +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Replacing label __b1_from___b1 with __b1 +Removing instruction __b1_from___init1: +Removing instruction main_from___b1: +Removing instruction __b1_from___b1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction __init1: +Removing instruction __b1: +Removing instruction __breturn: +Removing instruction __breturn: +Removing instruction __b1_from_main: +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Removing instruction jmp __b1 +Succesful ASM optimization Pass5NextJumpElimination + +FINAL SYMBOL TABLE +__constant char * const SCREEN = (char *) 1024 +__constant unsigned int STACK_BASE = $103 +void __start() +__loadstore char i // zp[1]:4 105.24999999999999 +void main() +char main::$2 // reg byte a 202.0 +char main::a +char main::a#1 // a zp[1]:3 151.5 +char main::a#2 // a zp[1]:3 44.888888888888886 +char main::v +char main::v#0 // reg byte x 101.0 +char main::w +char main::w#0 // reg byte a 202.0 +__stackcall char plus(char a , char b) +__constant char plus::OFFSET_STACK_A = 1 +__constant char plus::OFFSET_STACK_B = 0 +__constant char plus::OFFSET_STACK_RETURN_1 = 1 +char plus::a +char plus::a#0 // a zp[1]:2 667.3333333333334 +char plus::b +char plus::b#0 // reg byte a 1001.0 +char plus::return +char plus::return#0 // reg byte a 2002.0 + +zp[1]:3 [ main::a#2 main::a#1 ] +zp[1]:4 [ i ] +zp[1]:2 [ plus::a#0 ] +reg byte a [ plus::b#0 ] +reg byte a [ plus::return#0 ] +reg byte x [ main::v#0 ] +reg byte a [ main::w#0 ] +reg byte a [ main::$2 ] + + +FINAL ASSEMBLER +Score: 656 + + // File Comments +// Test a procedure with calling convention stack +// A slightly more complex call + // Upstart +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + // Global Constants & labels + .const STACK_BASE = $103 + .label SCREEN = $400 + .label i = 4 +.segment Code + // __start +__start: { + // __start::__init1 + // char i = 0 + // [1] i = 0 -- vbuz1=vbuc1 + lda #0 + sta.z i + // [2] phi from __start::__init1 to __start::@1 [phi:__start::__init1->__start::@1] + // __start::@1 + // [3] call main + // [11] phi from __start::@1 to main [phi:__start::@1->main] + jsr main + // __start::@return + // [4] return + rts +} +.segment stage + // plus +// this should give a pragma error during compile, as test is not declared yet. +// __register(A) char plus(__zp(2) char a, __register(A) char b) +plus: { + .const OFFSET_STACK_A = 1 + .const OFFSET_STACK_B = 0 + .const OFFSET_STACK_RETURN_1 = 1 + .label a = 2 + // [5] plus::a#0 = stackidx(char,plus::OFFSET_STACK_A) -- vbuz1=_stackidxbyte_vbuc1 + tsx + lda STACK_BASE+OFFSET_STACK_A,x + sta.z a + // [6] plus::b#0 = stackidx(char,plus::OFFSET_STACK_B) -- vbuaa=_stackidxbyte_vbuc1 + tsx + lda STACK_BASE+OFFSET_STACK_B,x + // i++; + // [7] i = ++ i -- vbuz1=_inc_vbuz1 + inc.z i + // return a+b; + // [8] plus::return#0 = plus::a#0 + plus::b#0 -- vbuaa=vbuz1_plus_vbuaa + clc + adc.z a + // plus::@return + // } + // [9] stackidx(char,plus::OFFSET_STACK_RETURN_1) = plus::return#0 -- _stackidxbyte_vbuc1=vbuaa + tsx + sta STACK_BASE+OFFSET_STACK_RETURN_1,x + // [10] return + rts +} + // main +main: { + .label a = 3 + // [12] phi from main to main::@1 [phi:main->main::@1] + // [12] phi main::a#2 = 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 + lda #0 + sta.z a + // [12] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + // [12] phi main::a#2 = main::a#1 [phi:main::@1->main::@1#0] -- register_copy + // main::@1 + __b1: + // char v = a+1 + // [13] main::v#0 = main::a#2 + 1 -- vbuxx=vbuz1_plus_1 + ldx.z a + inx + // char w = plus('0', v) + // [14] stackpush(char) = '0' -- _stackpushbyte_=vbuc1 + lda #'0' + pha + // [15] stackpush(char) = main::v#0 -- _stackpushbyte_=vbuxx + txa + pha + // [16] callexecute plus -- call_vprc1 + jsr plus + // sideeffect stackpullpadding(1) -- _stackpullpadding_1 + pla + // [18] main::w#0 = stackpull(char) -- vbuaa=_stackpullbyte_ + pla + // w+a + // [19] main::$2 = main::w#0 + main::a#2 -- vbuaa=vbuaa_plus_vbuz1 + clc + adc.z a + // SCREEN[i] = w+a + // [20] SCREEN[i] = main::$2 -- pbuc1_derefidx_vbuz1=vbuaa + ldy.z i + sta SCREEN,y + // for(char a:0..1) + // [21] main::a#1 = ++ main::a#2 -- vbuz1=_inc_vbuz1 + inc.z a + // [22] if(main::a#1!=2) goto main::@1 -- vbuz1_neq_vbuc1_then_la1 + lda #2 + cmp.z a + bne __b1 + // main::@return + // } + // [23] return + rts +} + // File Data + diff --git a/src/test/ref/procedure-callingconvention-stack-bank-2.sym b/src/test/ref/procedure-callingconvention-stack-bank-2.sym new file mode 100644 index 000000000..0e71cf52f --- /dev/null +++ b/src/test/ref/procedure-callingconvention-stack-bank-2.sym @@ -0,0 +1,32 @@ +__constant char * const SCREEN = (char *) 1024 +__constant unsigned int STACK_BASE = $103 +void __start() +__loadstore char i // zp[1]:4 105.24999999999999 +void main() +char main::$2 // reg byte a 202.0 +char main::a +char main::a#1 // a zp[1]:3 151.5 +char main::a#2 // a zp[1]:3 44.888888888888886 +char main::v +char main::v#0 // reg byte x 101.0 +char main::w +char main::w#0 // reg byte a 202.0 +__stackcall char plus(char a , char b) +__constant char plus::OFFSET_STACK_A = 1 +__constant char plus::OFFSET_STACK_B = 0 +__constant char plus::OFFSET_STACK_RETURN_1 = 1 +char plus::a +char plus::a#0 // a zp[1]:2 667.3333333333334 +char plus::b +char plus::b#0 // reg byte a 1001.0 +char plus::return +char plus::return#0 // reg byte a 2002.0 + +zp[1]:3 [ main::a#2 main::a#1 ] +zp[1]:4 [ i ] +zp[1]:2 [ plus::a#0 ] +reg byte a [ plus::b#0 ] +reg byte a [ plus::return#0 ] +reg byte x [ main::v#0 ] +reg byte a [ main::w#0 ] +reg byte a [ main::$2 ] diff --git a/src/test/ref/procedure-callingconvention-stack-bank-3.asm b/src/test/ref/procedure-callingconvention-stack-bank-3.asm new file mode 100644 index 000000000..57944cb6c --- /dev/null +++ b/src/test/ref/procedure-callingconvention-stack-bank-3.asm @@ -0,0 +1,74 @@ +// Test a procedure with calling convention stack +// Illustrates live range problem with function variable printother::i and global variable val +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + .label SCREEN = $400 + .label val = 2 +.segment Code +__start: { + // char val = 0 + lda #0 + sta.z val + jsr main + rts +} +printother: { + ldx #0 + __b1: + // (SCREEN+40)[i]++; + inc SCREEN+$28,x + // for(char i:0..5) + inx + cpx #6 + bne __b1 + // } + rts +} +incval: { + // val++; + inc.z val + // } + rts +} +printval: { + // SCREEN[0] = val + lda.z val + sta SCREEN + // } + rts +} +ival: { + // incval() + jsr incval + // } + rts +} +pval: { + // printval() + jsr printval + // } + rts +} +.segment stage +main: { + ldy #0 + __b1: + // pval() + jsr pval + // printother() + jsr printother + // ival() + jsr ival + // for(char i:0..5) + iny + cpy #6 + bne __b1 + // } + rts +} diff --git a/src/test/ref/procedure-callingconvention-stack-bank-3.cfg b/src/test/ref/procedure-callingconvention-stack-bank-3.cfg new file mode 100644 index 000000000..01f3d9e0f --- /dev/null +++ b/src/test/ref/procedure-callingconvention-stack-bank-3.cfg @@ -0,0 +1,79 @@ + +void __start() +__start: scope:[__start] from + [0] phi() + to:__start::__init1 +__start::__init1: scope:[__start] from __start + [1] val = 0 + to:__start::@1 +__start::@1: scope:[__start] from __start::__init1 + [2] phi() + [3] callexecute main + to:__start::@return +__start::@return: scope:[__start] from __start::@1 + [4] return + to:@return + +__stackcall void printother() +printother: scope:[printother] from + [5] phi() + to:printother::@1 +printother::@1: scope:[printother] from printother printother::@1 + [6] printother::i#2 = phi( printother/0, printother::@1/printother::i#1 ) + [7] (SCREEN+$28)[printother::i#2] = ++ (SCREEN+$28)[printother::i#2] + [8] printother::i#1 = ++ printother::i#2 + [9] if(printother::i#1!=6) goto printother::@1 + to:printother::@return +printother::@return: scope:[printother] from printother::@1 + [10] return + to:@return + +__stackcall void incval() +incval: scope:[incval] from + [11] val = ++ val + to:incval::@return +incval::@return: scope:[incval] from incval + [12] return + to:@return + +__stackcall void printval() +printval: scope:[printval] from + [13] *SCREEN = val + to:printval::@return +printval::@return: scope:[printval] from printval + [14] return + to:@return + +__stackcall void ival() +ival: scope:[ival] from + [15] phi() + [16] callexecute incval + to:ival::@return +ival::@return: scope:[ival] from ival + [17] return + to:@return + +__stackcall void pval() +pval: scope:[pval] from + [18] phi() + [19] callexecute printval + to:pval::@return +pval::@return: scope:[pval] from pval + [20] return + to:@return + +__stackcall void main() +main: scope:[main] from + [21] phi() + to:main::@1 +main::@1: scope:[main] from main main::@1 + [22] main::i#2 = phi( main/0, main::@1/main::i#1 ) + [23] callexecute pval + [24] callexecute printother + [25] callexecute ival + [26] main::i#1 = ++ main::i#2 + [27] if(main::i#1!=6) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + [28] return + to:@return diff --git a/src/test/ref/procedure-callingconvention-stack-bank-3.log b/src/test/ref/procedure-callingconvention-stack-bank-3.log new file mode 100644 index 000000000..6c840b6f9 --- /dev/null +++ b/src/test/ref/procedure-callingconvention-stack-bank-3.log @@ -0,0 +1,644 @@ +Loading link script "procedure-callingconvention-stack-bank.ld" +Converting variable modified inside __stackcall procedure main() to load/store val +Inlined call call __init +Calling convention __stackcall adding prepare/execute/finalize for call pval +Calling convention __stackcall adding prepare/execute/finalize for call printother +Calling convention __stackcall adding prepare/execute/finalize for call ival +Calling convention __stackcall adding prepare/execute/finalize for call printval +Calling convention __stackcall adding prepare/execute/finalize for call incval +Calling convention __stackcall adding prepare/execute/finalize for call main + +CONTROL FLOW GRAPH SSA + +__stackcall void main() +main: scope:[main] from + main::i#0 = 0 + to:main::@1 +main::@1: scope:[main] from main main::@1 + main::i#2 = phi( main/main::i#0, main::@1/main::i#1 ) + callexecute pval + callexecute printother + callexecute ival + main::i#1 = main::i#2 + rangenext(0,5) + main::$3 = main::i#1 != rangelast(0,5) + if(main::$3) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + return + to:@return + +__stackcall void pval() +pval: scope:[pval] from + callexecute printval + to:pval::@return +pval::@return: scope:[pval] from pval + return + to:@return + +__stackcall void ival() +ival: scope:[ival] from + callexecute incval + to:ival::@return +ival::@return: scope:[ival] from ival + return + to:@return + +__stackcall void printval() +printval: scope:[printval] from + SCREEN[0] = val + to:printval::@return +printval::@return: scope:[printval] from printval + return + to:@return + +__stackcall void incval() +incval: scope:[incval] from + val = ++ val + to:incval::@return +incval::@return: scope:[incval] from incval + return + to:@return + +__stackcall void printother() +printother: scope:[printother] from + printother::i#0 = 0 + to:printother::@1 +printother::@1: scope:[printother] from printother printother::@1 + printother::i#2 = phi( printother/printother::i#0, printother::@1/printother::i#1 ) + (SCREEN+$28)[printother::i#2] = ++ (SCREEN+$28)[printother::i#2] + printother::i#1 = printother::i#2 + rangenext(0,5) + printother::$1 = printother::i#1 != rangelast(0,5) + if(printother::$1) goto printother::@1 + to:printother::@return +printother::@return: scope:[printother] from printother::@1 + return + to:@return + +void __start() +__start: scope:[__start] from + to:__start::__init1 +__start::__init1: scope:[__start] from __start + val = 0 + to:__start::@1 +__start::@1: scope:[__start] from __start::__init1 + callexecute main + to:__start::@return +__start::@return: scope:[__start] from __start::@1 + return + to:@return + +SYMBOL TABLE SSA +__constant char * const SCREEN = (char *)$400 +void __start() +__stackcall void incval() +__stackcall void ival() +__stackcall void main() +bool main::$3 +char main::i +char main::i#0 +char main::i#1 +char main::i#2 +__stackcall void printother() +bool printother::$1 +char printother::i +char printother::i#0 +char printother::i#1 +char printother::i#2 +__stackcall void printval() +__stackcall void pval() +__loadstore char val + +Adding number conversion cast (unumber) 0 in SCREEN[0] = val +Adding number conversion cast (unumber) $28 in (SCREEN+$28)[printother::i#2] = ++ (SCREEN+$28)[printother::i#2] +Successful SSA optimization PassNAddNumberTypeConversions +Simplifying constant pointer cast (char *) 1024 +Simplifying constant integer cast 0 +Simplifying constant integer cast $28 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (char) 0 +Finalized unsigned number type (char) $28 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Simple Condition main::$3 [7] if(main::i#1!=rangelast(0,5)) goto main::@1 +Simple Condition printother::$1 [22] if(printother::i#1!=rangelast(0,5)) goto printother::@1 +Successful SSA optimization Pass2ConditionalJumpSimplification +Constant main::i#0 = 0 +Constant printother::i#0 = 0 +Successful SSA optimization Pass2ConstantIdentification +Resolved ranged next value [5] main::i#1 = ++ main::i#2 to ++ +Resolved ranged comparison value [7] if(main::i#1!=rangelast(0,5)) goto main::@1 to 6 +Resolved ranged next value [20] printother::i#1 = ++ printother::i#2 to ++ +Resolved ranged comparison value [22] if(printother::i#1!=rangelast(0,5)) goto printother::@1 to 6 +Simplifying expression containing zero SCREEN in [13] SCREEN[0] = val +Successful SSA optimization PassNSimplifyExpressionWithZero +Adding number conversion cast (unumber) 6 in if(main::i#1!=6) goto main::@1 +Adding number conversion cast (unumber) 6 in if(printother::i#1!=6) goto printother::@1 +Successful SSA optimization PassNAddNumberTypeConversions +Simplifying constant integer cast 6 +Simplifying constant integer cast 6 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (char) 6 +Finalized unsigned number type (char) 6 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Inlining constant with var siblings main::i#0 +Inlining constant with var siblings printother::i#0 +Constant inlined main::i#0 = 0 +Constant inlined printother::i#0 = 0 +Successful SSA optimization Pass2ConstantInlining +Added new block during phi lifting main::@2(between main::@1 and main::@1) +Added new block during phi lifting printother::@2(between printother::@1 and printother::@1) +Adding NOP phi() at start of __start +Adding NOP phi() at start of __start::@1 +Adding NOP phi() at start of printother +Adding NOP phi() at start of ival +Adding NOP phi() at start of pval +Adding NOP phi() at start of main +CALL GRAPH +Calls in [__start] to main:3 +Calls in [ival] to incval:17 +Calls in [pval] to printval:20 +Calls in [main] to pval:24 printother:25 ival:26 + +Created 2 initial phi equivalence classes +Coalesced [11] printother::i#3 = printother::i#1 +Coalesced [30] main::i#3 = main::i#1 +Coalesced down to 2 phi equivalence classes +Culled Empty Block label printother::@2 +Culled Empty Block label main::@2 +Adding NOP phi() at start of __start +Adding NOP phi() at start of __start::@1 +Adding NOP phi() at start of printother +Adding NOP phi() at start of ival +Adding NOP phi() at start of pval +Adding NOP phi() at start of main + +FINAL CONTROL FLOW GRAPH + +void __start() +__start: scope:[__start] from + [0] phi() + to:__start::__init1 +__start::__init1: scope:[__start] from __start + [1] val = 0 + to:__start::@1 +__start::@1: scope:[__start] from __start::__init1 + [2] phi() + [3] callexecute main + to:__start::@return +__start::@return: scope:[__start] from __start::@1 + [4] return + to:@return + +__stackcall void printother() +printother: scope:[printother] from + [5] phi() + to:printother::@1 +printother::@1: scope:[printother] from printother printother::@1 + [6] printother::i#2 = phi( printother/0, printother::@1/printother::i#1 ) + [7] (SCREEN+$28)[printother::i#2] = ++ (SCREEN+$28)[printother::i#2] + [8] printother::i#1 = ++ printother::i#2 + [9] if(printother::i#1!=6) goto printother::@1 + to:printother::@return +printother::@return: scope:[printother] from printother::@1 + [10] return + to:@return + +__stackcall void incval() +incval: scope:[incval] from + [11] val = ++ val + to:incval::@return +incval::@return: scope:[incval] from incval + [12] return + to:@return + +__stackcall void printval() +printval: scope:[printval] from + [13] *SCREEN = val + to:printval::@return +printval::@return: scope:[printval] from printval + [14] return + to:@return + +__stackcall void ival() +ival: scope:[ival] from + [15] phi() + [16] callexecute incval + to:ival::@return +ival::@return: scope:[ival] from ival + [17] return + to:@return + +__stackcall void pval() +pval: scope:[pval] from + [18] phi() + [19] callexecute printval + to:pval::@return +pval::@return: scope:[pval] from pval + [20] return + to:@return + +__stackcall void main() +main: scope:[main] from + [21] phi() + to:main::@1 +main::@1: scope:[main] from main main::@1 + [22] main::i#2 = phi( main/0, main::@1/main::i#1 ) + [23] callexecute pval + [24] callexecute printother + [25] callexecute ival + [26] main::i#1 = ++ main::i#2 + [27] if(main::i#1!=6) goto main::@1 + to:main::@return +main::@return: scope:[main] from main::@1 + [28] return + to:@return + +null depth in calling loop Loop head: main::@1 tails: main::@1 blocks: main::@1 in scope printother +null depth in calling loop Loop head: main::@1 tails: main::@1 blocks: main::@1 in scope ival +null depth in calling loop Loop head: main::@1 tails: main::@1 blocks: main::@1 in scope pval +null depth in calling loop Loop head: main::@1 tails: main::@1 blocks: main::@1 in scope ival +null depth in calling loop Loop head: main::@1 tails: main::@1 blocks: main::@1 in scope pval + +VARIABLE REGISTER WEIGHTS +void __start() +__stackcall void incval() +__stackcall void ival() +__stackcall void main() +char main::i +char main::i#1 // 151.5 +char main::i#2 // 50.5 +__stackcall void printother() +char printother::i +char printother::i#1 // 15001.5 +char printother::i#2 // 20002.0 +__stackcall void printval() +__stackcall void pval() +__loadstore char val // 1579.2105263157896 + +Initial phi equivalence classes +[ printother::i#2 printother::i#1 ] +[ main::i#2 main::i#1 ] +Added variable val to live range equivalence class [ val ] +Complete equivalence classes +[ printother::i#2 printother::i#1 ] +[ main::i#2 main::i#1 ] +[ val ] +Allocated zp[1]:2 [ printother::i#2 printother::i#1 ] +Allocated zp[1]:3 [ val ] +Allocated zp[1]:4 [ main::i#2 main::i#1 ] +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [1] val = 0 [ val ] ( [ val ] { } ) always clobbers reg byte a +Statement [13] *SCREEN = val [ val ] ( main:3::pval:23::printval:19 [ main::i#2 val ] { } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:4 [ main::i#2 main::i#1 ] +Statement [1] val = 0 [ val ] ( [ val ] { } ) always clobbers reg byte a +Statement [13] *SCREEN = val [ val ] ( main:3::pval:23::printval:19 [ main::i#2 val ] { } ) always clobbers reg byte a +Potential registers zp[1]:2 [ printother::i#2 printother::i#1 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:4 [ main::i#2 main::i#1 ] : zp[1]:4 , reg byte x , reg byte y , +Potential registers zp[1]:3 [ val ] : zp[1]:3 , + +REGISTER UPLIFT SCOPES +Uplift Scope [printother] 35,003.5: zp[1]:2 [ printother::i#2 printother::i#1 ] +Uplift Scope [] 1,579.21: zp[1]:3 [ val ] +Uplift Scope [main] 202: zp[1]:4 [ main::i#2 main::i#1 ] +Uplift Scope [pval] +Uplift Scope [ival] +Uplift Scope [printval] +Uplift Scope [incval] +Uplift Scope [__start] + +Uplifting [printother] best 815 combination reg byte x [ printother::i#2 printother::i#1 ] +Uplifting [] best 815 combination zp[1]:3 [ val ] +Uplifting [main] best 725 combination reg byte y [ main::i#2 main::i#1 ] +Uplifting [pval] best 725 combination +Uplifting [ival] best 725 combination +Uplifting [printval] best 725 combination +Uplifting [incval] best 725 combination +Uplifting [__start] best 725 combination +Attempting to uplift remaining variables inzp[1]:3 [ val ] +Uplifting [] best 725 combination zp[1]:3 [ val ] +Allocated (was zp[1]:3) zp[1]:2 [ val ] + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Test a procedure with calling convention stack +// Illustrates live range problem with function variable printother::i and global variable val + // Upstart +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + // Global Constants & labels + .label SCREEN = $400 + .label val = 2 +.segment Code + // __start +__start: { + jmp __init1 + // __start::__init1 + __init1: + // [1] val = 0 -- vbuz1=vbuc1 + lda #0 + sta.z val + // [2] phi from __start::__init1 to __start::@1 [phi:__start::__init1->__start::@1] + __b1_from___init1: + jmp __b1 + // __start::@1 + __b1: + // [3] callexecute main -- call_vprc1 + jsr main + jmp __breturn + // __start::@return + __breturn: + // [4] return + rts +} + // printother +printother: { + // [6] phi from printother to printother::@1 [phi:printother->printother::@1] + __b1_from_printother: + // [6] phi printother::i#2 = 0 [phi:printother->printother::@1#0] -- vbuxx=vbuc1 + ldx #0 + jmp __b1 + // [6] phi from printother::@1 to printother::@1 [phi:printother::@1->printother::@1] + __b1_from___b1: + // [6] phi printother::i#2 = printother::i#1 [phi:printother::@1->printother::@1#0] -- register_copy + jmp __b1 + // printother::@1 + __b1: + // [7] (SCREEN+$28)[printother::i#2] = ++ (SCREEN+$28)[printother::i#2] -- pbuc1_derefidx_vbuxx=_inc_pbuc1_derefidx_vbuxx + inc SCREEN+$28,x + // [8] printother::i#1 = ++ printother::i#2 -- vbuxx=_inc_vbuxx + inx + // [9] if(printother::i#1!=6) goto printother::@1 -- vbuxx_neq_vbuc1_then_la1 + cpx #6 + bne __b1_from___b1 + jmp __breturn + // printother::@return + __breturn: + // [10] return + rts +} + // incval +incval: { + // [11] val = ++ val -- vbuz1=_inc_vbuz1 + inc.z val + jmp __breturn + // incval::@return + __breturn: + // [12] return + rts +} + // printval +printval: { + // [13] *SCREEN = val -- _deref_pbuc1=vbuz1 + lda.z val + sta SCREEN + jmp __breturn + // printval::@return + __breturn: + // [14] return + rts +} + // ival +ival: { + // [16] callexecute incval -- call_vprc1 + jsr incval + jmp __breturn + // ival::@return + __breturn: + // [17] return + rts +} + // pval +pval: { + // [19] callexecute printval -- call_vprc1 + jsr printval + jmp __breturn + // pval::@return + __breturn: + // [20] return + rts +} +.segment stage + // main +main: { + // [22] phi from main to main::@1 [phi:main->main::@1] + __b1_from_main: + // [22] phi main::i#2 = 0 [phi:main->main::@1#0] -- vbuyy=vbuc1 + ldy #0 + jmp __b1 + // [22] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + __b1_from___b1: + // [22] phi main::i#2 = main::i#1 [phi:main::@1->main::@1#0] -- register_copy + jmp __b1 + // main::@1 + __b1: + // [23] callexecute pval -- call_vprc1 + jsr pval + // [24] callexecute printother -- call_vprc1 + jsr printother + // [25] callexecute ival -- call_vprc1 + jsr ival + // [26] main::i#1 = ++ main::i#2 -- vbuyy=_inc_vbuyy + iny + // [27] if(main::i#1!=6) goto main::@1 -- vbuyy_neq_vbuc1_then_la1 + cpy #6 + bne __b1_from___b1 + jmp __breturn + // main::@return + __breturn: + // [28] return + rts +} + // File Data + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __init1 +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Removing instruction jmp __breturn +Removing instruction jmp __breturn +Removing instruction jmp __breturn +Removing instruction jmp __breturn +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Replacing label __b1_from___b1 with __b1 +Replacing label __b1_from___b1 with __b1 +Removing instruction __b1_from___init1: +Removing instruction __b1_from___b1: +Removing instruction __b1_from___b1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction __init1: +Removing instruction __b1: +Removing instruction __breturn: +Removing instruction __b1_from_printother: +Removing instruction __breturn: +Removing instruction __breturn: +Removing instruction __breturn: +Removing instruction __breturn: +Removing instruction __breturn: +Removing instruction __b1_from_main: +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Removing instruction jmp __b1 +Removing instruction jmp __b1 +Succesful ASM optimization Pass5NextJumpElimination + +FINAL SYMBOL TABLE +__constant char * const SCREEN = (char *) 1024 +void __start() +__stackcall void incval() +__stackcall void ival() +__stackcall void main() +char main::i +char main::i#1 // reg byte y 151.5 +char main::i#2 // reg byte y 50.5 +__stackcall void printother() +char printother::i +char printother::i#1 // reg byte x 15001.5 +char printother::i#2 // reg byte x 20002.0 +__stackcall void printval() +__stackcall void pval() +__loadstore char val // zp[1]:2 1579.2105263157896 + +reg byte x [ printother::i#2 printother::i#1 ] +reg byte y [ main::i#2 main::i#1 ] +zp[1]:2 [ val ] + + +FINAL ASSEMBLER +Score: 497 + + // File Comments +// Test a procedure with calling convention stack +// Illustrates live range problem with function variable printother::i and global variable val + // Upstart +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + // Global Constants & labels + .label SCREEN = $400 + .label val = 2 +.segment Code + // __start +__start: { + // __start::__init1 + // char val = 0 + // [1] val = 0 -- vbuz1=vbuc1 + lda #0 + sta.z val + // [2] phi from __start::__init1 to __start::@1 [phi:__start::__init1->__start::@1] + // __start::@1 + // [3] callexecute main -- call_vprc1 + jsr main + // __start::@return + // [4] return + rts +} + // printother +printother: { + // [6] phi from printother to printother::@1 [phi:printother->printother::@1] + // [6] phi printother::i#2 = 0 [phi:printother->printother::@1#0] -- vbuxx=vbuc1 + ldx #0 + // [6] phi from printother::@1 to printother::@1 [phi:printother::@1->printother::@1] + // [6] phi printother::i#2 = printother::i#1 [phi:printother::@1->printother::@1#0] -- register_copy + // printother::@1 + __b1: + // (SCREEN+40)[i]++; + // [7] (SCREEN+$28)[printother::i#2] = ++ (SCREEN+$28)[printother::i#2] -- pbuc1_derefidx_vbuxx=_inc_pbuc1_derefidx_vbuxx + inc SCREEN+$28,x + // for(char i:0..5) + // [8] printother::i#1 = ++ printother::i#2 -- vbuxx=_inc_vbuxx + inx + // [9] if(printother::i#1!=6) goto printother::@1 -- vbuxx_neq_vbuc1_then_la1 + cpx #6 + bne __b1 + // printother::@return + // } + // [10] return + rts +} + // incval +incval: { + // val++; + // [11] val = ++ val -- vbuz1=_inc_vbuz1 + inc.z val + // incval::@return + // } + // [12] return + rts +} + // printval +printval: { + // SCREEN[0] = val + // [13] *SCREEN = val -- _deref_pbuc1=vbuz1 + lda.z val + sta SCREEN + // printval::@return + // } + // [14] return + rts +} + // ival +ival: { + // incval() + // [16] callexecute incval -- call_vprc1 + jsr incval + // ival::@return + // } + // [17] return + rts +} + // pval +pval: { + // printval() + // [19] callexecute printval -- call_vprc1 + jsr printval + // pval::@return + // } + // [20] return + rts +} +.segment stage + // main +main: { + // [22] phi from main to main::@1 [phi:main->main::@1] + // [22] phi main::i#2 = 0 [phi:main->main::@1#0] -- vbuyy=vbuc1 + ldy #0 + // [22] phi from main::@1 to main::@1 [phi:main::@1->main::@1] + // [22] phi main::i#2 = main::i#1 [phi:main::@1->main::@1#0] -- register_copy + // main::@1 + __b1: + // pval() + // [23] callexecute pval -- call_vprc1 + jsr pval + // printother() + // [24] callexecute printother -- call_vprc1 + jsr printother + // ival() + // [25] callexecute ival -- call_vprc1 + jsr ival + // for(char i:0..5) + // [26] main::i#1 = ++ main::i#2 -- vbuyy=_inc_vbuyy + iny + // [27] if(main::i#1!=6) goto main::@1 -- vbuyy_neq_vbuc1_then_la1 + cpy #6 + bne __b1 + // main::@return + // } + // [28] return + rts +} + // File Data + diff --git a/src/test/ref/procedure-callingconvention-stack-bank-3.sym b/src/test/ref/procedure-callingconvention-stack-bank-3.sym new file mode 100644 index 000000000..4eeb8472d --- /dev/null +++ b/src/test/ref/procedure-callingconvention-stack-bank-3.sym @@ -0,0 +1,19 @@ +__constant char * const SCREEN = (char *) 1024 +void __start() +__stackcall void incval() +__stackcall void ival() +__stackcall void main() +char main::i +char main::i#1 // reg byte y 151.5 +char main::i#2 // reg byte y 50.5 +__stackcall void printother() +char printother::i +char printother::i#1 // reg byte x 15001.5 +char printother::i#2 // reg byte x 20002.0 +__stackcall void printval() +__stackcall void pval() +__loadstore char val // zp[1]:2 1579.2105263157896 + +reg byte x [ printother::i#2 printother::i#1 ] +reg byte y [ main::i#2 main::i#1 ] +zp[1]:2 [ val ] diff --git a/src/test/ref/procedure-callingconvention-stack-bank-4.asm b/src/test/ref/procedure-callingconvention-stack-bank-4.asm new file mode 100644 index 000000000..f5f8d94ab --- /dev/null +++ b/src/test/ref/procedure-callingconvention-stack-bank-4.asm @@ -0,0 +1,111 @@ +// Test a procedure with calling convention stack +// Returning and passing struct values +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + .const OFFSET_STRUCT_POINT_Y = 1 + .const SIZEOF_STRUCT_POINT = 2 + .const STACK_BASE = $103 + .label SCREEN = $400 + .label idx = 4 +.segment Code +__start: { + // char idx = 0 + lda #0 + sta.z idx + jsr main + rts +} +.segment stage +// void print(__zp(2) struct Point p) +print: { + .const OFFSET_STACK_P = 0 + .label p = 2 + tsx + lda STACK_BASE+OFFSET_STACK_P,x + sta.z p + lda STACK_BASE+OFFSET_STACK_P+1,x + sta.z p+1 + // SCREEN[idx++] = p.x + lda.z p + ldy.z idx + sta SCREEN,y + // SCREEN[idx++] = p.x; + inc.z idx + // SCREEN[idx++] = p.y + lda.z p+OFFSET_STRUCT_POINT_Y + ldy.z idx + sta SCREEN,y + // SCREEN[idx++] = p.y; + inc.z idx + // } + rts +} +// __zp(6) struct Point get(__register(X) char i) +get: { + .const OFFSET_STACK_I = 0 + .const OFFSET_STACK_RETURN_0 = 0 + .label return = 6 + .label p = 8 + tsx + lda STACK_BASE+OFFSET_STACK_I,x + tax + // i/2 + txa + lsr + // struct Point p = { i, i/2 } + stx.z p + sta.z p+OFFSET_STRUCT_POINT_Y + // return p; + ldy #SIZEOF_STRUCT_POINT + !: + lda p-1,y + sta return-1,y + dey + bne !- + // } + tsx + lda.z return + sta STACK_BASE+OFFSET_STACK_RETURN_0,x + lda.z return+1 + sta STACK_BASE+OFFSET_STACK_RETURN_0+1,x + rts +} +main: { + .label p = 2 + .label i = 5 + lda #0 + sta.z i + __b1: + // for(char i=0;i<5;i++) + lda.z i + cmp #5 + bcc __b2 + // } + rts + __b2: + // struct Point p = get(i) + lda.z i + pha + pha + jsr get + pla + sta.z p + pla + sta.z p+1 + // print(p) + pha + lda.z p + pha + jsr print + pla + pla + // for(char i=0;i<5;i++) + inc.z i + jmp __b1 +} diff --git a/src/test/ref/procedure-callingconvention-stack-bank-4.cfg b/src/test/ref/procedure-callingconvention-stack-bank-4.cfg new file mode 100644 index 000000000..df3d4fa35 --- /dev/null +++ b/src/test/ref/procedure-callingconvention-stack-bank-4.cfg @@ -0,0 +1,62 @@ + +void __start() +__start: scope:[__start] from + [0] phi() + to:__start::__init1 +__start::__init1: scope:[__start] from __start + [1] idx = 0 + to:__start::@1 +__start::@1: scope:[__start] from __start::__init1 + [2] phi() + [3] callexecute main + to:__start::@return +__start::@return: scope:[__start] from __start::@1 + [4] return + to:@return + +__stackcall void print(struct Point p) +print: scope:[print] from + [5] print::p = stackidx(struct Point,print::OFFSET_STACK_P) + [6] SCREEN[idx] = *((char *)&print::p) + [7] idx = ++ idx + [8] SCREEN[idx] = *((char *)&print::p+OFFSET_STRUCT_POINT_Y) + [9] idx = ++ idx + to:print::@return +print::@return: scope:[print] from print + [10] return + to:@return + +__stackcall struct Point get(char i) +get: scope:[get] from + [11] get::i#0 = stackidx(char,get::OFFSET_STACK_I) + [12] get::$0 = get::i#0 >> 1 + [13] *((char *)&get::p) = get::i#0 + [14] *((char *)&get::p+OFFSET_STRUCT_POINT_Y) = get::$0 + [15] *(&get::return) = memcpy(*(&get::p), struct Point, SIZEOF_STRUCT_POINT) + to:get::@return +get::@return: scope:[get] from get + [16] stackidx(struct Point,get::OFFSET_STACK_RETURN_0) = get::return + [17] return + to:@return + +__stackcall void main() +main: scope:[main] from + [18] phi() + to:main::@1 +main::@1: scope:[main] from main main::@2 + [19] main::i#2 = phi( main/0, main::@2/main::i#1 ) + [20] if(main::i#2<5) goto main::@2 + to:main::@return +main::@return: scope:[main] from main::@1 + [21] return + to:@return +main::@2: scope:[main] from main::@1 + [22] stackpush(char) = main::i#2 + sideeffect stackpushpadding(1) + [24] callexecute get + [25] main::p = stackpull(struct Point) + [26] stackpush(struct Point) = main::p + [27] callexecute print + sideeffect stackpullpadding(2) + [29] main::i#1 = ++ main::i#2 + to:main::@1 diff --git a/src/test/ref/procedure-callingconvention-stack-bank-4.log b/src/test/ref/procedure-callingconvention-stack-bank-4.log new file mode 100644 index 000000000..4d3cfc93f --- /dev/null +++ b/src/test/ref/procedure-callingconvention-stack-bank-4.log @@ -0,0 +1,710 @@ +Loading link script "procedure-callingconvention-stack-bank.ld" +Converting variable modified inside __stackcall procedure main() to load/store idx +Adding parameter assignment in __stackcall procedure get::i = param(get::i) +Adding parameter assignment in __stackcall procedure print::p = param(print::p) +Inlined call call __init +Eliminating unused variable with no statement main::$1 +Calling convention __stackcall adding prepare/execute/finalize for main::p = call get(main::i) +Calling convention __stackcall adding prepare/execute/finalize for call print(main::p) +Calling convention __stackcall adding prepare/execute/finalize for call main +Calling convention STACK_CALL replacing param(get::i) with stackidx(char,get::OFFSET_STACK_I) +Calling convention STACK_CALL replacing param(print::p) with stackidx(struct Point,print::OFFSET_STACK_P) +Calling convention STACK_CALL adding stack return stackidx(struct Point,get::OFFSET_STACK_RETURN_0) = get::return +Calling convention STACK_CALL adding stack pull main::p = stackpull(struct Point) +Calling convention STACK_CALL adding stack push stackpush(char) = main::i +Calling convention STACK_CALL adding stack push stackpush(struct Point) = main::p +Removing C-classic struct-unwound assignment get::p = struct-unwound {*((char *)&get::p+OFFSET_STRUCT_POINT_X), *((char *)&get::p+OFFSET_STRUCT_POINT_Y)} +Removing C-classic struct-unwound assignment get::return = struct-unwound {*(&get::return)} + +CONTROL FLOW GRAPH SSA + +__stackcall void main() +main: scope:[main] from + main::i#0 = 0 + to:main::@1 +main::@1: scope:[main] from main main::@2 + main::i#2 = phi( main/main::i#0, main::@2/main::i#1 ) + main::$0 = main::i#2 < 5 + if(main::$0) goto main::@2 + to:main::@return +main::@2: scope:[main] from main::@1 + main::i#3 = phi( main::@1/main::i#2 ) + stackpush(char) = main::i#3 + sideeffect stackpushpadding(1) + callexecute get + main::p = stackpull(struct Point) + stackpush(struct Point) = main::p + callexecute print + sideeffect stackpullpadding(2) + main::i#1 = ++ main::i#3 + to:main::@1 +main::@return: scope:[main] from main::@1 + return + to:@return + +__stackcall struct Point get(char i) +get: scope:[get] from + get::i#0 = stackidx(char,get::OFFSET_STACK_I) + get::$0 = get::i#0 / 2 + *((char *)&get::p+OFFSET_STRUCT_POINT_X) = get::i#0 + *((char *)&get::p+OFFSET_STRUCT_POINT_Y) = get::$0 + *(&get::return) = memcpy(*(&get::p), struct Point, SIZEOF_STRUCT_POINT) + to:get::@return +get::@return: scope:[get] from get + stackidx(struct Point,get::OFFSET_STACK_RETURN_0) = get::return + return + to:@return + +__stackcall void print(struct Point p) +print: scope:[print] from + print::p = stackidx(struct Point,print::OFFSET_STACK_P) + SCREEN[idx] = *((char *)&print::p+OFFSET_STRUCT_POINT_X) + idx = ++ idx + SCREEN[idx] = *((char *)&print::p+OFFSET_STRUCT_POINT_Y) + idx = ++ idx + to:print::@return +print::@return: scope:[print] from print + return + to:@return + +void __start() +__start: scope:[__start] from + to:__start::__init1 +__start::__init1: scope:[__start] from __start + idx = 0 + to:__start::@1 +__start::@1: scope:[__start] from __start::__init1 + callexecute main + to:__start::@return +__start::@return: scope:[__start] from __start::@1 + return + to:@return + +SYMBOL TABLE SSA +__constant char OFFSET_STRUCT_POINT_X = 0 +__constant char OFFSET_STRUCT_POINT_Y = 1 +__constant char * const SCREEN = (char *)$400 +__constant char SIZEOF_STRUCT_POINT = 2 +__constant unsigned int STACK_BASE = $103 +void __start() +__stackcall struct Point get(char i) +number get::$0 +__constant char get::OFFSET_STACK_I = 0 +__constant char get::OFFSET_STACK_RETURN_0 = 0 +char get::i +char get::i#0 +__loadstore struct Point get::p +__loadstore struct Point get::return +__loadstore char idx +__stackcall void main() +bool main::$0 +char main::i +char main::i#0 +char main::i#1 +char main::i#2 +char main::i#3 +__loadstore struct Point main::p +__stackcall void print(struct Point p) +__constant char print::OFFSET_STACK_P = 0 +__loadstore struct Point print::p + +Adding number conversion cast (unumber) 5 in main::$0 = main::i#2 < 5 +Adding number conversion cast (unumber) 2 in get::$0 = get::i#0 / 2 +Adding number conversion cast (unumber) get::$0 in get::$0 = get::i#0 / (unumber)2 +Successful SSA optimization PassNAddNumberTypeConversions +Simplifying constant pointer cast (char *) 1024 +Simplifying constant integer cast 5 +Simplifying constant integer cast 2 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (char) 5 +Finalized unsigned number type (char) 2 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Inferred type updated to char in get::$0 = get::i#0 / 2 +Alias main::i#2 = main::i#3 +Successful SSA optimization Pass2AliasElimination +Simple Condition main::$0 [3] if(main::i#2<5) goto main::@2 +Successful SSA optimization Pass2ConditionalJumpSimplification +Constant main::i#0 = 0 +Successful SSA optimization Pass2ConstantIdentification +Simplifying expression containing zero (char *)&get::p in [15] *((char *)&get::p+OFFSET_STRUCT_POINT_X) = get::i#0 +Simplifying expression containing zero (char *)&print::p in [21] SCREEN[idx] = *((char *)&print::p+OFFSET_STRUCT_POINT_X) +Successful SSA optimization PassNSimplifyExpressionWithZero +Eliminating unused constant OFFSET_STRUCT_POINT_X +Successful SSA optimization PassNEliminateUnusedVars +Rewriting division to use shift [12] get::$0 = get::i#0 / 2 +Successful SSA optimization Pass2MultiplyToShiftRewriting +Inlining constant with var siblings main::i#0 +Constant inlined main::i#0 = 0 +Successful SSA optimization Pass2ConstantInlining +Finalized unsigned number type (char) 1 +Finalized unsigned number type (char) 2 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Adding NOP phi() at start of __start +Adding NOP phi() at start of __start::@1 +Adding NOP phi() at start of main +CALL GRAPH +Calls in [__start] to main:3 +Calls in [main] to get:24 print:27 + +Created 1 initial phi equivalence classes +Coalesced [30] main::i#4 = main::i#1 +Coalesced down to 1 phi equivalence classes +Adding NOP phi() at start of __start +Adding NOP phi() at start of __start::@1 +Adding NOP phi() at start of main + +FINAL CONTROL FLOW GRAPH + +void __start() +__start: scope:[__start] from + [0] phi() + to:__start::__init1 +__start::__init1: scope:[__start] from __start + [1] idx = 0 + to:__start::@1 +__start::@1: scope:[__start] from __start::__init1 + [2] phi() + [3] callexecute main + to:__start::@return +__start::@return: scope:[__start] from __start::@1 + [4] return + to:@return + +__stackcall void print(struct Point p) +print: scope:[print] from + [5] print::p = stackidx(struct Point,print::OFFSET_STACK_P) + [6] SCREEN[idx] = *((char *)&print::p) + [7] idx = ++ idx + [8] SCREEN[idx] = *((char *)&print::p+OFFSET_STRUCT_POINT_Y) + [9] idx = ++ idx + to:print::@return +print::@return: scope:[print] from print + [10] return + to:@return + +__stackcall struct Point get(char i) +get: scope:[get] from + [11] get::i#0 = stackidx(char,get::OFFSET_STACK_I) + [12] get::$0 = get::i#0 >> 1 + [13] *((char *)&get::p) = get::i#0 + [14] *((char *)&get::p+OFFSET_STRUCT_POINT_Y) = get::$0 + [15] *(&get::return) = memcpy(*(&get::p), struct Point, SIZEOF_STRUCT_POINT) + to:get::@return +get::@return: scope:[get] from get + [16] stackidx(struct Point,get::OFFSET_STACK_RETURN_0) = get::return + [17] return + to:@return + +__stackcall void main() +main: scope:[main] from + [18] phi() + to:main::@1 +main::@1: scope:[main] from main main::@2 + [19] main::i#2 = phi( main/0, main::@2/main::i#1 ) + [20] if(main::i#2<5) goto main::@2 + to:main::@return +main::@return: scope:[main] from main::@1 + [21] return + to:@return +main::@2: scope:[main] from main::@1 + [22] stackpush(char) = main::i#2 + sideeffect stackpushpadding(1) + [24] callexecute get + [25] main::p = stackpull(struct Point) + [26] stackpush(struct Point) = main::p + [27] callexecute print + sideeffect stackpullpadding(2) + [29] main::i#1 = ++ main::i#2 + to:main::@1 + +null depth in calling loop Loop head: main::@1 tails: main::@2 blocks: main::@2 main::@1 in scope print +null depth in calling loop Loop head: main::@1 tails: main::@2 blocks: main::@2 main::@1 in scope get + +VARIABLE REGISTER WEIGHTS +void __start() +__stackcall struct Point get(char i) +char get::$0 // 1001.0 +char get::i +char get::i#0 // 1501.5 +__loadstore struct Point get::p +__loadstore struct Point get::return // 47.666666666666664 +__loadstore char idx // 316.2105263157895 +__stackcall void main() +char main::i +char main::i#1 // 202.0 +char main::i#2 // 44.888888888888886 +__loadstore struct Point main::p // 202.0 +__stackcall void print(struct Point p) +__loadstore struct Point print::p // 333.6666666666667 + +Initial phi equivalence classes +[ main::i#2 main::i#1 ] +Added variable idx to live range equivalence class [ idx ] +Added variable print::p to live range equivalence class [ print::p ] +Added variable get::i#0 to live range equivalence class [ get::i#0 ] +Added variable get::$0 to live range equivalence class [ get::$0 ] +Added variable main::p to live range equivalence class [ main::p ] +Added variable get::return to live range equivalence class [ get::return ] +Added variable get::p to live range equivalence class [ get::p ] +Complete equivalence classes +[ main::i#2 main::i#1 ] +[ idx ] +[ print::p ] +[ get::i#0 ] +[ get::$0 ] +[ main::p ] +[ get::return ] +[ get::p ] +Allocated zp[1]:2 [ get::i#0 ] +Allocated zp[1]:3 [ get::$0 ] +Allocated zp[2]:4 [ print::p ] +Allocated zp[1]:6 [ idx ] +Allocated zp[1]:7 [ main::i#2 main::i#1 ] +Allocated zp[2]:8 [ main::p ] +Allocated zp[2]:10 [ get::return ] +Allocated zp[2]:12 [ get::p ] +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [1] idx = 0 [ idx get::p get::return ] ( [ idx get::p get::return ] { } ) always clobbers reg byte a +Statement [5] print::p = stackidx(struct Point,print::OFFSET_STACK_P) [ idx print::p ] ( main:3::print:27 [ get::p get::return main::i#2 idx print::p ] { } ) always clobbers reg byte a reg byte x +Removing always clobbered register reg byte a as potential for zp[1]:7 [ main::i#2 main::i#1 ] +Removing always clobbered register reg byte x as potential for zp[1]:7 [ main::i#2 main::i#1 ] +Statement [6] SCREEN[idx] = *((char *)&print::p) [ idx print::p ] ( main:3::print:27 [ get::p get::return main::i#2 idx print::p ] { } ) always clobbers reg byte a reg byte y +Removing always clobbered register reg byte y as potential for zp[1]:7 [ main::i#2 main::i#1 ] +Statement [8] SCREEN[idx] = *((char *)&print::p+OFFSET_STRUCT_POINT_Y) [ idx ] ( main:3::print:27 [ get::p get::return main::i#2 idx ] { } ) always clobbers reg byte a reg byte y +Statement [11] get::i#0 = stackidx(char,get::OFFSET_STACK_I) [ get::i#0 get::p get::return ] ( main:3::get:24 [ idx main::i#2 get::i#0 get::p get::return ] { } ) always clobbers reg byte a reg byte x +Statement [12] get::$0 = get::i#0 >> 1 [ get::i#0 get::$0 get::p get::return ] ( main:3::get:24 [ idx main::i#2 get::i#0 get::$0 get::p get::return ] { } ) always clobbers reg byte a +Removing always clobbered register reg byte a as potential for zp[1]:2 [ get::i#0 ] +Statement [15] *(&get::return) = memcpy(*(&get::p), struct Point, SIZEOF_STRUCT_POINT) [ get::p get::return ] ( main:3::get:24 [ idx main::i#2 get::p get::return ] { } ) always clobbers reg byte a reg byte y +Statement [16] stackidx(struct Point,get::OFFSET_STACK_RETURN_0) = get::return [ get::p get::return ] ( main:3::get:24 [ idx main::i#2 get::p get::return ] { } ) always clobbers reg byte a reg byte x +Statement [20] if(main::i#2<5) goto main::@2 [ idx get::p get::return main::i#2 ] ( main:3 [ idx get::p get::return main::i#2 ] { } ) always clobbers reg byte a +Statement [22] stackpush(char) = main::i#2 [ idx get::p get::return main::i#2 ] ( main:3 [ idx get::p get::return main::i#2 ] { } ) always clobbers reg byte a +Statement [25] main::p = stackpull(struct Point) [ idx get::p get::return main::i#2 main::p ] ( main:3 [ idx get::p get::return main::i#2 main::p ] { } ) always clobbers reg byte a +Statement [26] stackpush(struct Point) = main::p [ idx get::p get::return main::i#2 ] ( main:3 [ idx get::p get::return main::i#2 ] { } ) always clobbers reg byte a +Statement sideeffect stackpullpadding(2) always clobbers reg byte a +Statement [1] idx = 0 [ idx get::p get::return ] ( [ idx get::p get::return ] { } ) always clobbers reg byte a +Statement [5] print::p = stackidx(struct Point,print::OFFSET_STACK_P) [ idx print::p ] ( main:3::print:27 [ get::p get::return main::i#2 idx print::p ] { } ) always clobbers reg byte a reg byte x +Statement [6] SCREEN[idx] = *((char *)&print::p) [ idx print::p ] ( main:3::print:27 [ get::p get::return main::i#2 idx print::p ] { } ) always clobbers reg byte a reg byte y +Statement [8] SCREEN[idx] = *((char *)&print::p+OFFSET_STRUCT_POINT_Y) [ idx ] ( main:3::print:27 [ get::p get::return main::i#2 idx ] { } ) always clobbers reg byte a reg byte y +Statement [11] get::i#0 = stackidx(char,get::OFFSET_STACK_I) [ get::i#0 get::p get::return ] ( main:3::get:24 [ idx main::i#2 get::i#0 get::p get::return ] { } ) always clobbers reg byte a reg byte x +Statement [12] get::$0 = get::i#0 >> 1 [ get::i#0 get::$0 get::p get::return ] ( main:3::get:24 [ idx main::i#2 get::i#0 get::$0 get::p get::return ] { } ) always clobbers reg byte a +Statement [15] *(&get::return) = memcpy(*(&get::p), struct Point, SIZEOF_STRUCT_POINT) [ get::p get::return ] ( main:3::get:24 [ idx main::i#2 get::p get::return ] { } ) always clobbers reg byte a reg byte y +Statement [16] stackidx(struct Point,get::OFFSET_STACK_RETURN_0) = get::return [ get::p get::return ] ( main:3::get:24 [ idx main::i#2 get::p get::return ] { } ) always clobbers reg byte a reg byte x +Statement [20] if(main::i#2<5) goto main::@2 [ idx get::p get::return main::i#2 ] ( main:3 [ idx get::p get::return main::i#2 ] { } ) always clobbers reg byte a +Statement [22] stackpush(char) = main::i#2 [ idx get::p get::return main::i#2 ] ( main:3 [ idx get::p get::return main::i#2 ] { } ) always clobbers reg byte a +Statement [25] main::p = stackpull(struct Point) [ idx get::p get::return main::i#2 main::p ] ( main:3 [ idx get::p get::return main::i#2 main::p ] { } ) always clobbers reg byte a +Statement [26] stackpush(struct Point) = main::p [ idx get::p get::return main::i#2 ] ( main:3 [ idx get::p get::return main::i#2 ] { } ) always clobbers reg byte a +Statement sideeffect stackpullpadding(2) always clobbers reg byte a +Potential registers zp[1]:7 [ main::i#2 main::i#1 ] : zp[1]:7 , +Potential registers zp[1]:6 [ idx ] : zp[1]:6 , +Potential registers zp[2]:4 [ print::p ] : zp[2]:4 , +Potential registers zp[1]:2 [ get::i#0 ] : zp[1]:2 , reg byte x , reg byte y , +Potential registers zp[1]:3 [ get::$0 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y , +Potential registers zp[2]:8 [ main::p ] : zp[2]:8 , +Potential registers zp[2]:10 [ get::return ] : zp[2]:10 , +Potential registers zp[2]:12 [ get::p ] : zp[2]:12 , + +REGISTER UPLIFT SCOPES +Uplift Scope [get] 1,501.5: zp[1]:2 [ get::i#0 ] 1,001: zp[1]:3 [ get::$0 ] 47.67: zp[2]:10 [ get::return ] 0: zp[2]:12 [ get::p ] +Uplift Scope [main] 246.89: zp[1]:7 [ main::i#2 main::i#1 ] 202: zp[2]:8 [ main::p ] +Uplift Scope [print] 333.67: zp[2]:4 [ print::p ] +Uplift Scope [] 316.21: zp[1]:6 [ idx ] +Uplift Scope [Point] +Uplift Scope [__start] + +Uplifting [get] best 993 combination reg byte x [ get::i#0 ] reg byte a [ get::$0 ] zp[2]:10 [ get::return ] zp[2]:12 [ get::p ] +Uplifting [main] best 993 combination zp[1]:7 [ main::i#2 main::i#1 ] zp[2]:8 [ main::p ] +Uplifting [print] best 993 combination zp[2]:4 [ print::p ] +Uplifting [] best 993 combination zp[1]:6 [ idx ] +Uplifting [Point] best 993 combination +Uplifting [__start] best 993 combination +Attempting to uplift remaining variables inzp[1]:6 [ idx ] +Uplifting [] best 993 combination zp[1]:6 [ idx ] +Attempting to uplift remaining variables inzp[1]:7 [ main::i#2 main::i#1 ] +Uplifting [main] best 993 combination zp[1]:7 [ main::i#2 main::i#1 ] +Coalescing zero page register [ zp[2]:8 [ main::p ] ] with [ zp[2]:4 [ print::p ] ] +Allocated (was zp[2]:8) zp[2]:2 [ main::p print::p ] +Allocated (was zp[1]:6) zp[1]:4 [ idx ] +Allocated (was zp[1]:7) zp[1]:5 [ main::i#2 main::i#1 ] +Allocated (was zp[2]:10) zp[2]:6 [ get::return ] +Allocated (was zp[2]:12) zp[2]:8 [ get::p ] + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Test a procedure with calling convention stack +// Returning and passing struct values + // Upstart +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + // Global Constants & labels + .const OFFSET_STRUCT_POINT_Y = 1 + .const SIZEOF_STRUCT_POINT = 2 + .const STACK_BASE = $103 + .label SCREEN = $400 + .label idx = 4 +.segment Code + // __start +__start: { + jmp __init1 + // __start::__init1 + __init1: + // [1] idx = 0 -- vbuz1=vbuc1 + lda #0 + sta.z idx + // [2] phi from __start::__init1 to __start::@1 [phi:__start::__init1->__start::@1] + __b1_from___init1: + jmp __b1 + // __start::@1 + __b1: + // [3] callexecute main -- call_vprc1 + jsr main + jmp __breturn + // __start::@return + __breturn: + // [4] return + rts +} +.segment stage + // print +// void print(__zp(2) struct Point p) +print: { + .const OFFSET_STACK_P = 0 + .label p = 2 + // [5] print::p = stackidx(struct Point,print::OFFSET_STACK_P) -- vssz1=_stackidxstruct_2_vbuc1 + tsx + lda STACK_BASE+OFFSET_STACK_P,x + sta.z p + lda STACK_BASE+OFFSET_STACK_P+1,x + sta.z p+1 + // [6] SCREEN[idx] = *((char *)&print::p) -- pbuc1_derefidx_vbuz1=_deref_pbuc2 + lda.z p + ldy.z idx + sta SCREEN,y + // [7] idx = ++ idx -- vbuz1=_inc_vbuz1 + inc.z idx + // [8] SCREEN[idx] = *((char *)&print::p+OFFSET_STRUCT_POINT_Y) -- pbuc1_derefidx_vbuz1=_deref_pbuc2 + lda.z p+OFFSET_STRUCT_POINT_Y + ldy.z idx + sta SCREEN,y + // [9] idx = ++ idx -- vbuz1=_inc_vbuz1 + inc.z idx + jmp __breturn + // print::@return + __breturn: + // [10] return + rts +} + // get +// __zp(6) struct Point get(__register(X) char i) +get: { + .const OFFSET_STACK_I = 0 + .const OFFSET_STACK_RETURN_0 = 0 + .label return = 6 + .label p = 8 + // [11] get::i#0 = stackidx(char,get::OFFSET_STACK_I) -- vbuxx=_stackidxbyte_vbuc1 + tsx + lda STACK_BASE+OFFSET_STACK_I,x + tax + // [12] get::$0 = get::i#0 >> 1 -- vbuaa=vbuxx_ror_1 + txa + lsr + // [13] *((char *)&get::p) = get::i#0 -- _deref_pbuc1=vbuxx + stx.z p + // [14] *((char *)&get::p+OFFSET_STRUCT_POINT_Y) = get::$0 -- _deref_pbuc1=vbuaa + sta.z p+OFFSET_STRUCT_POINT_Y + // [15] *(&get::return) = memcpy(*(&get::p), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3 + ldy #SIZEOF_STRUCT_POINT + !: + lda p-1,y + sta return-1,y + dey + bne !- + jmp __breturn + // get::@return + __breturn: + // [16] stackidx(struct Point,get::OFFSET_STACK_RETURN_0) = get::return -- _stackidxstruct_2_vbuc1=vssz1 + tsx + lda.z return + sta STACK_BASE+OFFSET_STACK_RETURN_0,x + lda.z return+1 + sta STACK_BASE+OFFSET_STACK_RETURN_0+1,x + // [17] return + rts +} + // main +main: { + .label p = 2 + .label i = 5 + // [19] phi from main to main::@1 [phi:main->main::@1] + __b1_from_main: + // [19] phi main::i#2 = 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 + lda #0 + sta.z i + jmp __b1 + // main::@1 + __b1: + // [20] if(main::i#2<5) goto main::@2 -- vbuz1_lt_vbuc1_then_la1 + lda.z i + cmp #5 + bcc __b2 + jmp __breturn + // main::@return + __breturn: + // [21] return + rts + // main::@2 + __b2: + // [22] stackpush(char) = main::i#2 -- _stackpushbyte_=vbuz1 + lda.z i + pha + // sideeffect stackpushpadding(1) -- _stackpushpadding_1 + pha + // [24] callexecute get -- call_vprc1 + jsr get + // [25] main::p = stackpull(struct Point) -- vssz1=_stackpullstruct_2_ + pla + sta.z p + pla + sta.z p+1 + // [26] stackpush(struct Point) = main::p -- _stackpushstruct_2_=vssz1 + lda.z p+1 + pha + lda.z p + pha + // [27] callexecute print -- call_vprc1 + jsr print + // sideeffect stackpullpadding(2) -- _stackpullpadding_2 + pla + pla + // [29] main::i#1 = ++ main::i#2 -- vbuz1=_inc_vbuz1 + inc.z i + // [19] phi from main::@2 to main::@1 [phi:main::@2->main::@1] + __b1_from___b2: + // [19] phi main::i#2 = main::i#1 [phi:main::@2->main::@1#0] -- register_copy + jmp __b1 +} + // File Data + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __init1 +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Removing instruction jmp __breturn +Removing instruction jmp __breturn +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction lda.z p+1 +Succesful ASM optimization Pass5UnnecesaryLoadElimination +Removing instruction __b1_from___init1: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction __init1: +Removing instruction __b1: +Removing instruction __breturn: +Removing instruction __breturn: +Removing instruction __breturn: +Removing instruction __b1_from_main: +Removing instruction __breturn: +Removing instruction __b1_from___b2: +Succesful ASM optimization Pass5UnusedLabelElimination + +FINAL SYMBOL TABLE +__constant char OFFSET_STRUCT_POINT_Y = 1 +__constant char * const SCREEN = (char *) 1024 +__constant char SIZEOF_STRUCT_POINT = 2 +__constant unsigned int STACK_BASE = $103 +void __start() +__stackcall struct Point get(char i) +char get::$0 // reg byte a 1001.0 +__constant char get::OFFSET_STACK_I = 0 +__constant char get::OFFSET_STACK_RETURN_0 = 0 +char get::i +char get::i#0 // reg byte x 1501.5 +__loadstore struct Point get::p // zp[2]:8 +__loadstore struct Point get::return // zp[2]:6 47.666666666666664 +__loadstore char idx // zp[1]:4 316.2105263157895 +__stackcall void main() +char main::i +char main::i#1 // i zp[1]:5 202.0 +char main::i#2 // i zp[1]:5 44.888888888888886 +__loadstore struct Point main::p // zp[2]:2 202.0 +__stackcall void print(struct Point p) +__constant char print::OFFSET_STACK_P = 0 +__loadstore struct Point print::p // zp[2]:2 333.6666666666667 + +zp[1]:5 [ main::i#2 main::i#1 ] +zp[1]:4 [ idx ] +reg byte x [ get::i#0 ] +reg byte a [ get::$0 ] +zp[2]:2 [ main::p print::p ] +zp[2]:6 [ get::return ] +zp[2]:8 [ get::p ] + + +FINAL ASSEMBLER +Score: 861 + + // File Comments +// Test a procedure with calling convention stack +// Returning and passing struct values + // Upstart +.cpu _65c02 + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + // Global Constants & labels + .const OFFSET_STRUCT_POINT_Y = 1 + .const SIZEOF_STRUCT_POINT = 2 + .const STACK_BASE = $103 + .label SCREEN = $400 + .label idx = 4 +.segment Code + // __start +__start: { + // __start::__init1 + // char idx = 0 + // [1] idx = 0 -- vbuz1=vbuc1 + lda #0 + sta.z idx + // [2] phi from __start::__init1 to __start::@1 [phi:__start::__init1->__start::@1] + // __start::@1 + // [3] callexecute main -- call_vprc1 + jsr main + // __start::@return + // [4] return + rts +} +.segment stage + // print +// void print(__zp(2) struct Point p) +print: { + .const OFFSET_STACK_P = 0 + .label p = 2 + // [5] print::p = stackidx(struct Point,print::OFFSET_STACK_P) -- vssz1=_stackidxstruct_2_vbuc1 + tsx + lda STACK_BASE+OFFSET_STACK_P,x + sta.z p + lda STACK_BASE+OFFSET_STACK_P+1,x + sta.z p+1 + // SCREEN[idx++] = p.x + // [6] SCREEN[idx] = *((char *)&print::p) -- pbuc1_derefidx_vbuz1=_deref_pbuc2 + lda.z p + ldy.z idx + sta SCREEN,y + // SCREEN[idx++] = p.x; + // [7] idx = ++ idx -- vbuz1=_inc_vbuz1 + inc.z idx + // SCREEN[idx++] = p.y + // [8] SCREEN[idx] = *((char *)&print::p+OFFSET_STRUCT_POINT_Y) -- pbuc1_derefidx_vbuz1=_deref_pbuc2 + lda.z p+OFFSET_STRUCT_POINT_Y + ldy.z idx + sta SCREEN,y + // SCREEN[idx++] = p.y; + // [9] idx = ++ idx -- vbuz1=_inc_vbuz1 + inc.z idx + // print::@return + // } + // [10] return + rts +} + // get +// __zp(6) struct Point get(__register(X) char i) +get: { + .const OFFSET_STACK_I = 0 + .const OFFSET_STACK_RETURN_0 = 0 + .label return = 6 + .label p = 8 + // [11] get::i#0 = stackidx(char,get::OFFSET_STACK_I) -- vbuxx=_stackidxbyte_vbuc1 + tsx + lda STACK_BASE+OFFSET_STACK_I,x + tax + // i/2 + // [12] get::$0 = get::i#0 >> 1 -- vbuaa=vbuxx_ror_1 + txa + lsr + // struct Point p = { i, i/2 } + // [13] *((char *)&get::p) = get::i#0 -- _deref_pbuc1=vbuxx + stx.z p + // [14] *((char *)&get::p+OFFSET_STRUCT_POINT_Y) = get::$0 -- _deref_pbuc1=vbuaa + sta.z p+OFFSET_STRUCT_POINT_Y + // return p; + // [15] *(&get::return) = memcpy(*(&get::p), struct Point, SIZEOF_STRUCT_POINT) -- _deref_pssc1=_deref_pssc2_memcpy_vbuc3 + ldy #SIZEOF_STRUCT_POINT + !: + lda p-1,y + sta return-1,y + dey + bne !- + // get::@return + // } + // [16] stackidx(struct Point,get::OFFSET_STACK_RETURN_0) = get::return -- _stackidxstruct_2_vbuc1=vssz1 + tsx + lda.z return + sta STACK_BASE+OFFSET_STACK_RETURN_0,x + lda.z return+1 + sta STACK_BASE+OFFSET_STACK_RETURN_0+1,x + // [17] return + rts +} + // main +main: { + .label p = 2 + .label i = 5 + // [19] phi from main to main::@1 [phi:main->main::@1] + // [19] phi main::i#2 = 0 [phi:main->main::@1#0] -- vbuz1=vbuc1 + lda #0 + sta.z i + // main::@1 + __b1: + // for(char i=0;i<5;i++) + // [20] if(main::i#2<5) goto main::@2 -- vbuz1_lt_vbuc1_then_la1 + lda.z i + cmp #5 + bcc __b2 + // main::@return + // } + // [21] return + rts + // main::@2 + __b2: + // struct Point p = get(i) + // [22] stackpush(char) = main::i#2 -- _stackpushbyte_=vbuz1 + lda.z i + pha + // sideeffect stackpushpadding(1) -- _stackpushpadding_1 + pha + // [24] callexecute get -- call_vprc1 + jsr get + // [25] main::p = stackpull(struct Point) -- vssz1=_stackpullstruct_2_ + pla + sta.z p + pla + sta.z p+1 + // print(p) + // [26] stackpush(struct Point) = main::p -- _stackpushstruct_2_=vssz1 + pha + lda.z p + pha + // [27] callexecute print -- call_vprc1 + jsr print + // sideeffect stackpullpadding(2) -- _stackpullpadding_2 + pla + pla + // for(char i=0;i<5;i++) + // [29] main::i#1 = ++ main::i#2 -- vbuz1=_inc_vbuz1 + inc.z i + // [19] phi from main::@2 to main::@1 [phi:main::@2->main::@1] + // [19] phi main::i#2 = main::i#1 [phi:main::@2->main::@1#0] -- register_copy + jmp __b1 +} + // File Data + diff --git a/src/test/ref/procedure-callingconvention-stack-bank-4.sym b/src/test/ref/procedure-callingconvention-stack-bank-4.sym new file mode 100644 index 000000000..0c4dcbeba --- /dev/null +++ b/src/test/ref/procedure-callingconvention-stack-bank-4.sym @@ -0,0 +1,30 @@ +__constant char OFFSET_STRUCT_POINT_Y = 1 +__constant char * const SCREEN = (char *) 1024 +__constant char SIZEOF_STRUCT_POINT = 2 +__constant unsigned int STACK_BASE = $103 +void __start() +__stackcall struct Point get(char i) +char get::$0 // reg byte a 1001.0 +__constant char get::OFFSET_STACK_I = 0 +__constant char get::OFFSET_STACK_RETURN_0 = 0 +char get::i +char get::i#0 // reg byte x 1501.5 +__loadstore struct Point get::p // zp[2]:8 +__loadstore struct Point get::return // zp[2]:6 47.666666666666664 +__loadstore char idx // zp[1]:4 316.2105263157895 +__stackcall void main() +char main::i +char main::i#1 // i zp[1]:5 202.0 +char main::i#2 // i zp[1]:5 44.888888888888886 +__loadstore struct Point main::p // zp[2]:2 202.0 +__stackcall void print(struct Point p) +__constant char print::OFFSET_STACK_P = 0 +__loadstore struct Point print::p // zp[2]:2 333.6666666666667 + +zp[1]:5 [ main::i#2 main::i#1 ] +zp[1]:4 [ idx ] +reg byte x [ get::i#0 ] +reg byte a [ get::$0 ] +zp[2]:2 [ main::p print::p ] +zp[2]:6 [ get::return ] +zp[2]:8 [ get::p ] diff --git a/src/test/ref/procedure-callingconvention-stack-bank-5.asm b/src/test/ref/procedure-callingconvention-stack-bank-5.asm new file mode 100644 index 000000000..7a7f95bc0 --- /dev/null +++ b/src/test/ref/procedure-callingconvention-stack-bank-5.asm @@ -0,0 +1,50 @@ +// Test a procedure with calling convention stack +// Recursion that works (no local variables) + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + .const STACK_BASE = $103 + .label SCREEN = $400 +.segment stage +// __register(A) char pow2(__register(A) char n) +pow2: { + .const OFFSET_STACK_N = 0 + .const OFFSET_STACK_RETURN_0 = 0 + tsx + lda STACK_BASE+OFFSET_STACK_N,x + // if (n == 0) + cmp #0 + beq __b1 + // n-1 + sec + sbc #1 + // char c = pow2(n-1) + pha + jsr pow2 + pla + // return c+c; + asl + jmp __breturn + __b1: + lda #1 + __breturn: + // } + tsx + sta STACK_BASE+OFFSET_STACK_RETURN_0,x + rts +} +main: { + // pow2(6) + lda #6 + pha + jsr pow2 + pla + // *SCREEN = pow2(6) + sta SCREEN + // } + rts +} diff --git a/src/test/ref/procedure-callingconvention-stack-bank-5.cfg b/src/test/ref/procedure-callingconvention-stack-bank-5.cfg new file mode 100644 index 000000000..17c2baaed --- /dev/null +++ b/src/test/ref/procedure-callingconvention-stack-bank-5.cfg @@ -0,0 +1,29 @@ + +__stackcall char pow2(char n) +pow2: scope:[pow2] from + [0] pow2::n#0 = stackidx(char,pow2::OFFSET_STACK_N) + [1] if(pow2::n#0==0) goto pow2::@return + to:pow2::@1 +pow2::@1: scope:[pow2] from pow2 + [2] pow2::$1 = pow2::n#0 - 1 + [3] stackpush(char) = pow2::$1 + [4] callexecute pow2 + [5] pow2::c#0 = stackpull(char) + [6] pow2::return#1 = pow2::c#0 + pow2::c#0 + to:pow2::@return +pow2::@return: scope:[pow2] from pow2 pow2::@1 + [7] pow2::return#2 = phi( pow2/1, pow2::@1/pow2::return#1 ) + [8] stackidx(char,pow2::OFFSET_STACK_RETURN_0) = pow2::return#2 + [9] return + to:@return + +void main() +main: scope:[main] from + [10] stackpush(char) = 6 + [11] callexecute pow2 + [12] main::$0 = stackpull(char) + [13] *SCREEN = main::$0 + to:main::@return +main::@return: scope:[main] from main + [14] return + to:@return diff --git a/src/test/ref/procedure-callingconvention-stack-bank-5.log b/src/test/ref/procedure-callingconvention-stack-bank-5.log new file mode 100644 index 000000000..e3d77a25a --- /dev/null +++ b/src/test/ref/procedure-callingconvention-stack-bank-5.log @@ -0,0 +1,408 @@ +Loading link script "procedure-callingconvention-stack-bank.ld" +Warning! Unknown #pragma platform +Adding parameter assignment in __stackcall procedure pow2::n = param(pow2::n) +Eliminating unused variable with no statement pow2::$2 +Calling convention __stackcall adding prepare/execute/finalize for main::$0 = call pow2(6) +Calling convention __stackcall adding prepare/execute/finalize for pow2::c = call pow2(pow2::$1) +Calling convention STACK_CALL replacing param(pow2::n) with stackidx(char,pow2::OFFSET_STACK_N) +Calling convention STACK_CALL adding stack return stackidx(char,pow2::OFFSET_STACK_RETURN_0) = pow2::return +Calling convention STACK_CALL adding stack pull main::$0 = stackpull(char) +Calling convention STACK_CALL adding stack pull pow2::c = stackpull(char) +Calling convention STACK_CALL adding stack push stackpush(char) = 6 +Calling convention STACK_CALL adding stack push stackpush(char) = pow2::$1 + +CONTROL FLOW GRAPH SSA + +void main() +main: scope:[main] from __start + stackpush(char) = 6 + callexecute pow2 + main::$0 = stackpull(char) + *SCREEN = main::$0 + to:main::@return +main::@return: scope:[main] from main + return + to:@return + +__stackcall char pow2(char n) +pow2: scope:[pow2] from + pow2::n#0 = stackidx(char,pow2::OFFSET_STACK_N) + pow2::$0 = pow2::n#0 == 0 + if(pow2::$0) goto pow2::@1 + to:pow2::@2 +pow2::@1: scope:[pow2] from pow2 + pow2::return#0 = 1 + to:pow2::@return +pow2::@2: scope:[pow2] from pow2 + pow2::n#1 = phi( pow2/pow2::n#0 ) + pow2::$1 = pow2::n#1 - 1 + stackpush(char) = pow2::$1 + callexecute pow2 + pow2::c#0 = stackpull(char) + pow2::$3 = pow2::c#0 + pow2::c#0 + pow2::return#1 = pow2::$3 + to:pow2::@return +pow2::@return: scope:[pow2] from pow2::@1 pow2::@2 + pow2::return#2 = phi( pow2::@1/pow2::return#0, pow2::@2/pow2::return#1 ) + stackidx(char,pow2::OFFSET_STACK_RETURN_0) = pow2::return#2 + return + to:@return + +void __start() +__start: scope:[__start] from + call main + to:__start::@1 +__start::@1: scope:[__start] from __start + to:__start::@return +__start::@return: scope:[__start] from __start::@1 + return + to:@return + +SYMBOL TABLE SSA +__constant char * const SCREEN = (char *)$400 +__constant unsigned int STACK_BASE = $103 +void __start() +void main() +char main::$0 +__stackcall char pow2(char n) +bool pow2::$0 +number pow2::$1 +char pow2::$3 +__constant char pow2::OFFSET_STACK_N = 0 +__constant char pow2::OFFSET_STACK_RETURN_0 = 0 +char pow2::c +char pow2::c#0 +char pow2::n +char pow2::n#0 +char pow2::n#1 +char pow2::return +char pow2::return#0 +char pow2::return#1 +char pow2::return#2 + +Adding number conversion cast (unumber) 6 in stackpush(char) = 6 +Adding number conversion cast (unumber) 0 in pow2::$0 = pow2::n#0 == 0 +Adding number conversion cast (unumber) 1 in pow2::return#0 = 1 +Adding number conversion cast (unumber) 1 in pow2::$1 = pow2::n#1 - 1 +Adding number conversion cast (unumber) pow2::$1 in pow2::$1 = pow2::n#1 - (unumber)1 +Successful SSA optimization PassNAddNumberTypeConversions +Inlining cast stackpush(char) = (unumber)6 +Inlining cast pow2::return#0 = (unumber)1 +Successful SSA optimization Pass2InlineCast +Simplifying constant pointer cast (char *) 1024 +Simplifying constant integer cast 6 +Simplifying constant integer cast 0 +Simplifying constant integer cast 1 +Simplifying constant integer cast 1 +Successful SSA optimization PassNCastSimplification +Finalized unsigned number type (char) 6 +Finalized unsigned number type (char) 0 +Finalized unsigned number type (char) 1 +Finalized unsigned number type (char) 1 +Successful SSA optimization PassNFinalizeNumberTypeConversions +Inferred type updated to char in pow2::$1 = pow2::n#1 - 1 +Alias pow2::n#0 = pow2::n#1 +Alias pow2::return#1 = pow2::$3 +Successful SSA optimization Pass2AliasElimination +Simple Condition pow2::$0 [7] if(pow2::n#0==0) goto pow2::@1 +Successful SSA optimization Pass2ConditionalJumpSimplification +Constant pow2::return#0 = 1 +Successful SSA optimization Pass2ConstantIdentification +Removing unused procedure __start +Removing unused procedure block __start +Removing unused procedure block __start::@1 +Removing unused procedure block __start::@return +Successful SSA optimization PassNEliminateEmptyStart +Inlining constant with var siblings pow2::return#0 +Constant inlined pow2::return#0 = 1 +Successful SSA optimization Pass2ConstantInlining +Adding NOP phi() at start of pow2::@1 +CALL GRAPH +Calls in [pow2] to pow2:4 +Calls in [main] to pow2:13 + +Created 1 initial phi equivalence classes +Coalesced [7] pow2::return#3 = pow2::return#1 +Coalesced down to 1 phi equivalence classes +Culled Empty Block label pow2::@1 +Renumbering block pow2::@2 to pow2::@1 + +FINAL CONTROL FLOW GRAPH + +__stackcall char pow2(char n) +pow2: scope:[pow2] from + [0] pow2::n#0 = stackidx(char,pow2::OFFSET_STACK_N) + [1] if(pow2::n#0==0) goto pow2::@return + to:pow2::@1 +pow2::@1: scope:[pow2] from pow2 + [2] pow2::$1 = pow2::n#0 - 1 + [3] stackpush(char) = pow2::$1 + [4] callexecute pow2 + [5] pow2::c#0 = stackpull(char) + [6] pow2::return#1 = pow2::c#0 + pow2::c#0 + to:pow2::@return +pow2::@return: scope:[pow2] from pow2 pow2::@1 + [7] pow2::return#2 = phi( pow2/1, pow2::@1/pow2::return#1 ) + [8] stackidx(char,pow2::OFFSET_STACK_RETURN_0) = pow2::return#2 + [9] return + to:@return + +void main() +main: scope:[main] from + [10] stackpush(char) = 6 + [11] callexecute pow2 + [12] main::$0 = stackpull(char) + [13] *SCREEN = main::$0 + to:main::@return +main::@return: scope:[main] from main + [14] return + to:@return + + +VARIABLE REGISTER WEIGHTS +void main() +char main::$0 // 4.0 +__stackcall char pow2(char n) +char pow2::$1 // 22.0 +char pow2::c +char pow2::c#0 // 33.0 +char pow2::n +char pow2::n#0 // 16.5 +char pow2::return +char pow2::return#1 // 22.0 +char pow2::return#2 // 22.0 + +Initial phi equivalence classes +[ pow2::return#2 pow2::return#1 ] +Added variable pow2::n#0 to live range equivalence class [ pow2::n#0 ] +Added variable pow2::$1 to live range equivalence class [ pow2::$1 ] +Added variable pow2::c#0 to live range equivalence class [ pow2::c#0 ] +Added variable main::$0 to live range equivalence class [ main::$0 ] +Complete equivalence classes +[ pow2::return#2 pow2::return#1 ] +[ pow2::n#0 ] +[ pow2::$1 ] +[ pow2::c#0 ] +[ main::$0 ] +Allocated zp[1]:2 [ pow2::return#2 pow2::return#1 ] +Allocated zp[1]:3 [ pow2::c#0 ] +Allocated zp[1]:4 [ pow2::$1 ] +Allocated zp[1]:5 [ pow2::n#0 ] +Allocated zp[1]:6 [ main::$0 ] +REGISTER UPLIFT POTENTIAL REGISTERS +Statement [0] pow2::n#0 = stackidx(char,pow2::OFFSET_STACK_N) [ pow2::n#0 ] ( pow2:11 [ pow2::n#0 ] { } ) always clobbers reg byte a reg byte x +Statement [5] pow2::c#0 = stackpull(char) [ pow2::c#0 ] ( pow2:11 [ pow2::c#0 ] { } ) always clobbers reg byte a +Statement [6] pow2::return#1 = pow2::c#0 + pow2::c#0 [ pow2::return#1 ] ( pow2:11 [ pow2::return#1 ] { } ) always clobbers reg byte a +Statement [8] stackidx(char,pow2::OFFSET_STACK_RETURN_0) = pow2::return#2 [ ] ( pow2:11 [ ] { } ) always clobbers reg byte x +Statement [10] stackpush(char) = 6 [ ] ( [ ] { } ) always clobbers reg byte a +Statement [12] main::$0 = stackpull(char) [ main::$0 ] ( [ main::$0 ] { } ) always clobbers reg byte a +Potential registers zp[1]:2 [ pow2::return#2 pow2::return#1 ] : zp[1]:2 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:5 [ pow2::n#0 ] : zp[1]:5 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:4 [ pow2::$1 ] : zp[1]:4 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:3 [ pow2::c#0 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:6 [ main::$0 ] : zp[1]:6 , reg byte a , reg byte x , reg byte y , + +REGISTER UPLIFT SCOPES +Uplift Scope [pow2] 44: zp[1]:2 [ pow2::return#2 pow2::return#1 ] 33: zp[1]:3 [ pow2::c#0 ] 22: zp[1]:4 [ pow2::$1 ] 16.5: zp[1]:5 [ pow2::n#0 ] +Uplift Scope [main] 4: zp[1]:6 [ main::$0 ] +Uplift Scope [] + +Uplifting [pow2] best 87 combination reg byte a [ pow2::return#2 pow2::return#1 ] reg byte a [ pow2::c#0 ] reg byte a [ pow2::$1 ] reg byte a [ pow2::n#0 ] +Limited combination testing to 100 combinations of 256 possible. +Uplifting [main] best 81 combination reg byte a [ main::$0 ] +Uplifting [] best 81 combination + +ASSEMBLER BEFORE OPTIMIZATION + // File Comments +// Test a procedure with calling convention stack +// Recursion that works (no local variables) + // Upstart + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + // Global Constants & labels + .const STACK_BASE = $103 + .label SCREEN = $400 +.segment stage + // pow2 +// __register(A) char pow2(__register(A) char n) +pow2: { + .const OFFSET_STACK_N = 0 + .const OFFSET_STACK_RETURN_0 = 0 + // [0] pow2::n#0 = stackidx(char,pow2::OFFSET_STACK_N) -- vbuaa=_stackidxbyte_vbuc1 + tsx + lda STACK_BASE+OFFSET_STACK_N,x + // [1] if(pow2::n#0==0) goto pow2::@return -- vbuaa_eq_0_then_la1 + cmp #0 + beq __breturn_from_pow2 + jmp __b1 + // pow2::@1 + __b1: + // [2] pow2::$1 = pow2::n#0 - 1 -- vbuaa=vbuaa_minus_1 + sec + sbc #1 + // [3] stackpush(char) = pow2::$1 -- _stackpushbyte_=vbuaa + pha + // [4] callexecute pow2 -- call_vprc1 + jsr pow2 + // [5] pow2::c#0 = stackpull(char) -- vbuaa=_stackpullbyte_ + pla + // [6] pow2::return#1 = pow2::c#0 + pow2::c#0 -- vbuaa=vbuaa_plus_vbuaa + asl + // [7] phi from pow2::@1 to pow2::@return [phi:pow2::@1->pow2::@return] + __breturn_from___b1: + // [7] phi pow2::return#2 = pow2::return#1 [phi:pow2::@1->pow2::@return#0] -- register_copy + jmp __breturn + // [7] phi from pow2 to pow2::@return [phi:pow2->pow2::@return] + __breturn_from_pow2: + // [7] phi pow2::return#2 = 1 [phi:pow2->pow2::@return#0] -- vbuaa=vbuc1 + lda #1 + jmp __breturn + // pow2::@return + __breturn: + // [8] stackidx(char,pow2::OFFSET_STACK_RETURN_0) = pow2::return#2 -- _stackidxbyte_vbuc1=vbuaa + tsx + sta STACK_BASE+OFFSET_STACK_RETURN_0,x + // [9] return + rts +} + // main +main: { + // [10] stackpush(char) = 6 -- _stackpushbyte_=vbuc1 + lda #6 + pha + // [11] callexecute pow2 -- call_vprc1 + jsr pow2 + // [12] main::$0 = stackpull(char) -- vbuaa=_stackpullbyte_ + pla + // [13] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa + sta SCREEN + jmp __breturn + // main::@return + __breturn: + // [14] return + rts +} + // File Data + +ASSEMBLER OPTIMIZATIONS +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Removing instruction jmp __breturn +Succesful ASM optimization Pass5NextJumpElimination +Removing instruction __b1: +Removing instruction __breturn_from___b1: +Removing instruction __breturn: +Succesful ASM optimization Pass5UnusedLabelElimination +Relabelling long label __breturn_from_pow2 to __b1 +Succesful ASM optimization Pass5RelabelLongLabels + +FINAL SYMBOL TABLE +__constant char * const SCREEN = (char *) 1024 +__constant unsigned int STACK_BASE = $103 +void main() +char main::$0 // reg byte a 4.0 +__stackcall char pow2(char n) +char pow2::$1 // reg byte a 22.0 +__constant char pow2::OFFSET_STACK_N = 0 +__constant char pow2::OFFSET_STACK_RETURN_0 = 0 +char pow2::c +char pow2::c#0 // reg byte a 33.0 +char pow2::n +char pow2::n#0 // reg byte a 16.5 +char pow2::return +char pow2::return#1 // reg byte a 22.0 +char pow2::return#2 // reg byte a 22.0 + +reg byte a [ pow2::return#2 pow2::return#1 ] +reg byte a [ pow2::n#0 ] +reg byte a [ pow2::$1 ] +reg byte a [ pow2::c#0 ] +reg byte a [ main::$0 ] + + +FINAL ASSEMBLER +Score: 72 + + // File Comments +// Test a procedure with calling convention stack +// Recursion that works (no local variables) + // Upstart + .segmentdef Program [segments="Basic, Code, Data, stage, platform"] +.segmentdef Basic [start=$0801] +.segmentdef Code [start=$80d] +.segmentdef Data [startAfter="Code"] +.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100] +.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100] + + // Global Constants & labels + .const STACK_BASE = $103 + .label SCREEN = $400 +.segment stage + // pow2 +// __register(A) char pow2(__register(A) char n) +pow2: { + .const OFFSET_STACK_N = 0 + .const OFFSET_STACK_RETURN_0 = 0 + // [0] pow2::n#0 = stackidx(char,pow2::OFFSET_STACK_N) -- vbuaa=_stackidxbyte_vbuc1 + tsx + lda STACK_BASE+OFFSET_STACK_N,x + // if (n == 0) + // [1] if(pow2::n#0==0) goto pow2::@return -- vbuaa_eq_0_then_la1 + cmp #0 + beq __b1 + // pow2::@1 + // n-1 + // [2] pow2::$1 = pow2::n#0 - 1 -- vbuaa=vbuaa_minus_1 + sec + sbc #1 + // char c = pow2(n-1) + // [3] stackpush(char) = pow2::$1 -- _stackpushbyte_=vbuaa + pha + // [4] callexecute pow2 -- call_vprc1 + jsr pow2 + // [5] pow2::c#0 = stackpull(char) -- vbuaa=_stackpullbyte_ + pla + // return c+c; + // [6] pow2::return#1 = pow2::c#0 + pow2::c#0 -- vbuaa=vbuaa_plus_vbuaa + asl + // [7] phi from pow2::@1 to pow2::@return [phi:pow2::@1->pow2::@return] + // [7] phi pow2::return#2 = pow2::return#1 [phi:pow2::@1->pow2::@return#0] -- register_copy + jmp __breturn + // [7] phi from pow2 to pow2::@return [phi:pow2->pow2::@return] + __b1: + // [7] phi pow2::return#2 = 1 [phi:pow2->pow2::@return#0] -- vbuaa=vbuc1 + lda #1 + // pow2::@return + __breturn: + // } + // [8] stackidx(char,pow2::OFFSET_STACK_RETURN_0) = pow2::return#2 -- _stackidxbyte_vbuc1=vbuaa + tsx + sta STACK_BASE+OFFSET_STACK_RETURN_0,x + // [9] return + rts +} + // main +main: { + // pow2(6) + // [10] stackpush(char) = 6 -- _stackpushbyte_=vbuc1 + lda #6 + pha + // [11] callexecute pow2 -- call_vprc1 + jsr pow2 + // [12] main::$0 = stackpull(char) -- vbuaa=_stackpullbyte_ + pla + // *SCREEN = pow2(6) + // [13] *SCREEN = main::$0 -- _deref_pbuc1=vbuaa + sta SCREEN + // main::@return + // } + // [14] return + rts +} + // File Data + diff --git a/src/test/ref/procedure-callingconvention-stack-bank-5.sym b/src/test/ref/procedure-callingconvention-stack-bank-5.sym new file mode 100644 index 000000000..b914904e4 --- /dev/null +++ b/src/test/ref/procedure-callingconvention-stack-bank-5.sym @@ -0,0 +1,21 @@ +__constant char * const SCREEN = (char *) 1024 +__constant unsigned int STACK_BASE = $103 +void main() +char main::$0 // reg byte a 4.0 +__stackcall char pow2(char n) +char pow2::$1 // reg byte a 22.0 +__constant char pow2::OFFSET_STACK_N = 0 +__constant char pow2::OFFSET_STACK_RETURN_0 = 0 +char pow2::c +char pow2::c#0 // reg byte a 33.0 +char pow2::n +char pow2::n#0 // reg byte a 16.5 +char pow2::return +char pow2::return#1 // reg byte a 22.0 +char pow2::return#2 // reg byte a 22.0 + +reg byte a [ pow2::return#2 pow2::return#1 ] +reg byte a [ pow2::n#0 ] +reg byte a [ pow2::$1 ] +reg byte a [ pow2::c#0 ] +reg byte a [ main::$0 ]