mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-06-09 18:29:36 +00:00
466 lines
12 KiB
Plaintext
466 lines
12 KiB
Plaintext
Loading link script "call-banked-phi.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(cx16_ram, 1) 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 )
|
|
min::a#0 = plus::a#1
|
|
min::b#0 = plus::b#1
|
|
call min
|
|
min::return#0 = min::return#2
|
|
to:plus::@1
|
|
plus::@1: scope:[plus] from plus
|
|
min::return#3 = phi( plus/min::return#0 )
|
|
plus::$0 = min::return#3
|
|
plus::return#1 = plus::$0
|
|
to:plus::@return
|
|
plus::@return: scope:[plus] from plus::@1
|
|
plus::return#4 = phi( plus::@1/plus::return#1 )
|
|
plus::return#2 = plus::return#4
|
|
return
|
|
to:@return
|
|
|
|
__bank(cx16_ram, 2) char min(char a , char b)
|
|
min: scope:[min] from plus
|
|
min::b#1 = phi( plus/min::b#0 )
|
|
min::a#1 = phi( plus/min::a#0 )
|
|
min::$0 = min::a#1 + min::b#1
|
|
min::return#1 = min::$0
|
|
to:min::@return
|
|
min::@return: scope:[min] from min
|
|
min::return#4 = phi( min/min::return#1 )
|
|
min::return#2 = min::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(cx16_ram, 2) char min(char a , char b)
|
|
char min::$0
|
|
char min::a
|
|
char min::a#0
|
|
char min::a#1
|
|
char min::b
|
|
char min::b#0
|
|
char min::b#1
|
|
char min::return
|
|
char min::return#0
|
|
char min::return#1
|
|
char min::return#2
|
|
char min::return#3
|
|
char min::return#4
|
|
__bank(cx16_ram, 1) 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 min::return#0 = min::return#3
|
|
Alias plus::return#1 = plus::$0 plus::return#4 plus::return#2
|
|
Alias min::return#1 = min::$0 min::return#4 min::return#2
|
|
Successful SSA optimization Pass2AliasElimination
|
|
Identical Phi Values plus::a#1 plus::a#0
|
|
Identical Phi Values plus::b#1 plus::b#0
|
|
Identical Phi Values min::a#1 min::a#0
|
|
Identical Phi Values min::b#1 min::b#0
|
|
Successful SSA optimization Pass2IdenticalPhiElimination
|
|
Constant plus::a#0 = '0'
|
|
Constant plus::b#0 = 7
|
|
Successful SSA optimization Pass2ConstantIdentification
|
|
Constant min::a#0 = plus::a#0
|
|
Constant min::b#0 = plus::b#0
|
|
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 [9] min::return#1 = min::a#0 + min::b#0
|
|
Successful SSA optimization Pass2ConstantRValueConsolidation
|
|
Constant min::return#1 = min::a#0+min::b#0
|
|
Successful SSA optimization Pass2ConstantIdentification
|
|
Constant min::return#0 = min::return#1
|
|
Successful SSA optimization Pass2ConstantIdentification
|
|
Constant plus::return#1 = min::return#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 min::return#0
|
|
Constant inlined plus::return#0 = min::return#1
|
|
Constant inlined main::$0 = min::return#1
|
|
Constant inlined plus::return#1 = min::return#1
|
|
Constant inlined min::a#0 = plus::a#0
|
|
Constant inlined min::return#0 = min::return#1
|
|
Constant inlined min::b#0 = plus::b#0
|
|
Successful SSA optimization Pass2ConstantInlining
|
|
Adding NOP phi() at start of main
|
|
Adding NOP phi() at start of plus
|
|
Adding NOP phi() at start of plus::@1
|
|
Adding NOP phi() at start of min
|
|
CALL GRAPH
|
|
Calls in [main] to plus:1
|
|
Calls in [plus] to min:5
|
|
|
|
Created 0 initial phi equivalence classes
|
|
Coalesced down to 0 phi equivalence classes
|
|
Culled Empty Block label plus::@1
|
|
Adding NOP phi() at start of main
|
|
Adding NOP phi() at start of plus
|
|
Adding NOP phi() at start of min
|
|
|
|
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 = min::return#1
|
|
to:main::@return
|
|
main::@return: scope:[main] from main::@1
|
|
[3] return
|
|
to:@return
|
|
|
|
__bank(cx16_ram, 1) char plus(char a , char b)
|
|
plus: scope:[plus] from main
|
|
[4] phi()
|
|
[5] call min
|
|
to:plus::@return
|
|
plus::@return: scope:[plus] from plus
|
|
[6] return
|
|
to:@return
|
|
|
|
__bank(cx16_ram, 2) char min(char a , char b)
|
|
min: scope:[min] from plus
|
|
[7] phi()
|
|
to:min::@return
|
|
min::@return: scope:[min] from min
|
|
[8] return
|
|
to:@return
|
|
|
|
|
|
VARIABLE REGISTER WEIGHTS
|
|
void main()
|
|
__bank(cx16_ram, 2) char min(char a , char b)
|
|
char min::a
|
|
char min::b
|
|
char min::return
|
|
__bank(cx16_ram, 1) 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 [1] call plus [ ] ( [ ] { } ) always clobbers reg byte a
|
|
Statement [2] *SCREEN = min::return#1 [ ] ( [ ] { } ) always clobbers reg byte a
|
|
|
|
REGISTER UPLIFT SCOPES
|
|
Uplift Scope [main]
|
|
Uplift Scope [plus]
|
|
Uplift Scope [min]
|
|
Uplift Scope []
|
|
|
|
Uplifting [main] best 93 combination
|
|
Uplifting [plus] best 93 combination
|
|
Uplifting [min] best 93 combination
|
|
Uplifting [] best 93 combination
|
|
|
|
ASSEMBLER BEFORE OPTIMIZATION
|
|
// File Comments
|
|
/**
|
|
* @file call-banked-phi-case-5-far-1.c
|
|
* @author Sven Van de Velde (sven.van.de.velde@telenet.be),
|
|
* @author Jesper Gravgaard
|
|
* @brief Test a procedure with calling convention PHI - case #5.
|
|
* Implementation using the #pragma bank and nobank directives.
|
|
* @version 0.1
|
|
* @date 2023-04-11
|
|
*
|
|
* @copyright Copyright (c) 2023
|
|
*
|
|
* The following cases exist in banked calling implementations:
|
|
*
|
|
* - case #1 - unbanked to unbanked and no banking areas
|
|
* - case #2 - unbanked to banked to any bank area
|
|
* - case #3 - banked to unbanked from any bank area
|
|
* - case #4 - banked to same bank in same bank area
|
|
* - case #5 - banked to different bank in same bank area
|
|
* - case #6 - banked to any bank between different bank areas
|
|
*
|
|
* This brings us to the call types:
|
|
*
|
|
* - near = case #1, #3, #4
|
|
* - close = case #2, #6
|
|
* - far = case #5
|
|
*
|
|
*/
|
|
// Upstart
|
|
.file [name="call-banked-phi-case-5-far-1.prg", type="prg", segments="Program"]
|
|
.segmentdef Program [segments="Basic, Code, Data"]
|
|
.segmentdef Basic [start=$0801]
|
|
.segmentdef Code [start=$80d]
|
|
.segmentdef Data [startAfter="Code"]
|
|
.segmentdef RAM_Bank1 [start=$A000, min=$A000, max=$BFFF, align=$100]
|
|
.segmentdef RAM_Bank2 [start=$A000, min=$A000, max=$BFFF, align=$100]
|
|
.segmentdef ROM_Bank1 [start=$C000, min=$C000, max=$FFFF, align=$100]
|
|
.segment Basic
|
|
:BasicUpstart(main)
|
|
.segment Code
|
|
.segment Data
|
|
|
|
|
|
// Global Constants & labels
|
|
.label SCREEN = $400
|
|
.segment Code
|
|
// main
|
|
main: {
|
|
// [1] call plus
|
|
// [4] phi from main to plus [phi:main->plus] -- call_phi_close_cx16_ram
|
|
plus_from_main:
|
|
lda.z 0
|
|
pha
|
|
lda #1
|
|
sta.z 0
|
|
jsr plus
|
|
pla
|
|
sta.z 0
|
|
jmp __b1
|
|
// main::@1
|
|
__b1:
|
|
// [2] *SCREEN = min::return#1 -- _deref_pbuc1=vbuc2
|
|
lda #min.return
|
|
sta SCREEN
|
|
jmp __breturn
|
|
// main::@return
|
|
__breturn:
|
|
// [3] return
|
|
rts
|
|
}
|
|
.segment RAM_Bank1
|
|
// plus
|
|
// char plus(char a, char b)
|
|
// __bank(cx16_ram, 1)
|
|
plus: {
|
|
.label a = '0'
|
|
.label b = 7
|
|
// [5] call min
|
|
// [7] phi from plus to min [phi:plus->min] -- call_phi_far_cx16_ram
|
|
min_from_plus:
|
|
jsr $ff6e
|
|
.byte <min
|
|
.byte >min
|
|
.byte 2
|
|
jmp __breturn
|
|
// plus::@return
|
|
__breturn:
|
|
// [6] return
|
|
rts
|
|
}
|
|
.segment RAM_Bank2
|
|
// min
|
|
// char min(char a, char b)
|
|
// __bank(cx16_ram, 2)
|
|
min: {
|
|
.label return = plus.a+plus.b
|
|
jmp __breturn
|
|
// min::@return
|
|
__breturn:
|
|
// [8] return
|
|
rts
|
|
}
|
|
// File Data
|
|
|
|
ASSEMBLER OPTIMIZATIONS
|
|
Removing instruction jmp __b1
|
|
Removing instruction jmp __breturn
|
|
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 min_from_plus:
|
|
Removing instruction __breturn:
|
|
Removing instruction __breturn:
|
|
Succesful ASM optimization Pass5UnusedLabelElimination
|
|
|
|
FINAL SYMBOL TABLE
|
|
__constant char * const SCREEN = (char *) 1024
|
|
void main()
|
|
__bank(cx16_ram, 2) char min(char a , char b)
|
|
char min::a
|
|
char min::b
|
|
char min::return
|
|
__constant char min::return#1 = plus::a#0+plus::b#0 // return
|
|
__bank(cx16_ram, 1) 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
|
|
|
|
|
|
|
|
FINAL ASSEMBLER
|
|
Score: 54
|
|
|
|
// File Comments
|
|
/**
|
|
* @file call-banked-phi-case-5-far-1.c
|
|
* @author Sven Van de Velde (sven.van.de.velde@telenet.be),
|
|
* @author Jesper Gravgaard
|
|
* @brief Test a procedure with calling convention PHI - case #5.
|
|
* Implementation using the #pragma bank and nobank directives.
|
|
* @version 0.1
|
|
* @date 2023-04-11
|
|
*
|
|
* @copyright Copyright (c) 2023
|
|
*
|
|
* The following cases exist in banked calling implementations:
|
|
*
|
|
* - case #1 - unbanked to unbanked and no banking areas
|
|
* - case #2 - unbanked to banked to any bank area
|
|
* - case #3 - banked to unbanked from any bank area
|
|
* - case #4 - banked to same bank in same bank area
|
|
* - case #5 - banked to different bank in same bank area
|
|
* - case #6 - banked to any bank between different bank areas
|
|
*
|
|
* This brings us to the call types:
|
|
*
|
|
* - near = case #1, #3, #4
|
|
* - close = case #2, #6
|
|
* - far = case #5
|
|
*
|
|
*/
|
|
// Upstart
|
|
.file [name="call-banked-phi-case-5-far-1.prg", type="prg", segments="Program"]
|
|
.segmentdef Program [segments="Basic, Code, Data"]
|
|
.segmentdef Basic [start=$0801]
|
|
.segmentdef Code [start=$80d]
|
|
.segmentdef Data [startAfter="Code"]
|
|
.segmentdef RAM_Bank1 [start=$A000, min=$A000, max=$BFFF, align=$100]
|
|
.segmentdef RAM_Bank2 [start=$A000, min=$A000, max=$BFFF, align=$100]
|
|
.segmentdef ROM_Bank1 [start=$C000, min=$C000, max=$FFFF, align=$100]
|
|
.segment Basic
|
|
:BasicUpstart(main)
|
|
.segment Code
|
|
.segment Data
|
|
|
|
|
|
// Global Constants & labels
|
|
.label SCREEN = $400
|
|
.segment Code
|
|
// main
|
|
main: {
|
|
// plus('0', 7)
|
|
// [1] call plus
|
|
// [4] phi from main to plus [phi:main->plus] -- call_phi_close_cx16_ram
|
|
lda.z 0
|
|
pha
|
|
lda #1
|
|
sta.z 0
|
|
jsr plus
|
|
pla
|
|
sta.z 0
|
|
// main::@1
|
|
// SCREEN[0] = plus('0', 7)
|
|
// [2] *SCREEN = min::return#1 -- _deref_pbuc1=vbuc2
|
|
lda #min.return
|
|
sta SCREEN
|
|
// main::@return
|
|
// }
|
|
// [3] return
|
|
rts
|
|
}
|
|
.segment RAM_Bank1
|
|
// plus
|
|
// char plus(char a, char b)
|
|
// __bank(cx16_ram, 1)
|
|
plus: {
|
|
.label a = '0'
|
|
.label b = 7
|
|
// min(a, b)
|
|
// [5] call min
|
|
// [7] phi from plus to min [phi:plus->min] -- call_phi_far_cx16_ram
|
|
jsr $ff6e
|
|
.byte <min
|
|
.byte >min
|
|
.byte 2
|
|
// plus::@return
|
|
// }
|
|
// [6] return
|
|
rts
|
|
}
|
|
.segment RAM_Bank2
|
|
// min
|
|
// char min(char a, char b)
|
|
// __bank(cx16_ram, 2)
|
|
min: {
|
|
.label return = plus.a+plus.b
|
|
// min::@return
|
|
// [8] return
|
|
rts
|
|
}
|
|
// File Data
|
|
|