mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-04-21 11:42:30 +00:00
- near, close, far implementation using fragments for phi calls
- fragment consolidation - removal of platform - stackcall banked throws error - testing
This commit is contained in:
parent
a52b5dc4a9
commit
b62430bfc3
@ -0,0 +1,6 @@
|
||||
lda #{c1}
|
||||
sta $0
|
||||
pha
|
||||
jsr {la1}
|
||||
pla
|
||||
sta $0
|
@ -0,0 +1,7 @@
|
||||
lda #{c1}
|
||||
sta $1
|
||||
pha
|
||||
jsr {la1}
|
||||
pla
|
||||
sta $1
|
||||
|
1
src/main/fragment/mos6502-common/call_phi_near.asm
Normal file
1
src/main/fragment/mos6502-common/call_phi_near.asm
Normal file
@ -0,0 +1 @@
|
||||
jsr {la1}
|
14
src/test/kc/call-banked-phi-case-1-near-0.c
Normal file
14
src/test/kc/call-banked-phi-case-1-near-0.c
Normal file
@ -0,0 +1,14 @@
|
||||
// Test a procedure with calling convention PHI - case #1
|
||||
|
||||
#pragma code_seg(Code)
|
||||
#pragma link("call-banked-phi.ld")
|
||||
|
||||
char* const SCREEN = (char*)0x0400;
|
||||
|
||||
void main(void) {
|
||||
SCREEN[0] = plus('0', 7);
|
||||
}
|
||||
|
||||
char plus(char a, char b) {
|
||||
return a+b;
|
||||
}
|
14
src/test/kc/call-banked-phi-case-1-near-1.c
Normal file
14
src/test/kc/call-banked-phi-case-1-near-1.c
Normal file
@ -0,0 +1,14 @@
|
||||
// Test a procedure with calling convention PHI - case #1
|
||||
|
||||
#pragma code_seg(Code)
|
||||
#pragma link("call-banked-phi.ld")
|
||||
|
||||
char* const SCREEN = (char*)0x0400;
|
||||
|
||||
void main(void) {
|
||||
SCREEN[0] = plus('0', 7);
|
||||
}
|
||||
|
||||
char plus(char a, char b) {
|
||||
return a+b;
|
||||
}
|
17
src/test/kc/call-banked-phi-case-2-close-0.c
Normal file
17
src/test/kc/call-banked-phi-case-2-close-0.c
Normal file
@ -0,0 +1,17 @@
|
||||
// Test a procedure with calling convention PHI - case #2
|
||||
|
||||
#pragma link("call-banked-phi.ld")
|
||||
|
||||
|
||||
char* const SCREEN = (char*)0x0400;
|
||||
|
||||
#pragma code_seg(RAM_Bank1)
|
||||
__bank(cx16_ram,1) char plus(char a, char b) {
|
||||
return a+b;
|
||||
}
|
||||
|
||||
#pragma code_seg(Code)
|
||||
void main(void) {
|
||||
SCREEN[0] = plus('0', 7);
|
||||
}
|
||||
|
17
src/test/kc/call-banked-phi-case-2-close-1.c
Normal file
17
src/test/kc/call-banked-phi-case-2-close-1.c
Normal file
@ -0,0 +1,17 @@
|
||||
// Test a procedure with calling convention PHI - case #2
|
||||
|
||||
#pragma link("call-banked-phi.ld")
|
||||
|
||||
|
||||
char* const SCREEN = (char*)0x0400;
|
||||
|
||||
#pragma code_seg(RAM_Bank1)
|
||||
__bank(cx16_ram,1) char plus(char a, char b) {
|
||||
return a+b;
|
||||
}
|
||||
|
||||
#pragma code_seg(Code)
|
||||
void main(void) {
|
||||
SCREEN[0] = plus('0', 7);
|
||||
}
|
||||
|
22
src/test/kc/call-banked-phi-case-3-near-0.c
Normal file
22
src/test/kc/call-banked-phi-case-3-near-0.c
Normal file
@ -0,0 +1,22 @@
|
||||
// Test a procedure with calling convention PHI - case #3
|
||||
|
||||
#pragma link("call-banked-phi.ld")
|
||||
|
||||
|
||||
char* const SCREEN = (char*)0x0400;
|
||||
|
||||
#pragma code_seg(Code)
|
||||
char min(char a, char b) {
|
||||
return a+b;
|
||||
}
|
||||
|
||||
#pragma code_seg(RAM_Bank1)
|
||||
__bank(cx16_ram,1) char plus(char a, char b) {
|
||||
return min(a, b);
|
||||
}
|
||||
|
||||
#pragma code_seg(Code)
|
||||
void main(void) {
|
||||
SCREEN[0] = plus('0', 7);
|
||||
}
|
||||
|
22
src/test/kc/call-banked-phi-case-3-near-1.c
Normal file
22
src/test/kc/call-banked-phi-case-3-near-1.c
Normal file
@ -0,0 +1,22 @@
|
||||
// Test a procedure with calling convention PHI - case #3
|
||||
|
||||
#pragma link("call-banked-phi.ld")
|
||||
|
||||
|
||||
char* const SCREEN = (char*)0x0400;
|
||||
|
||||
#pragma code_seg(Code)
|
||||
char min(char a, char b) {
|
||||
return a+b;
|
||||
}
|
||||
|
||||
#pragma code_seg(RAM_Bank1)
|
||||
__bank(cx16_ram,1) char plus(char a, char b) {
|
||||
return min(a, b);
|
||||
}
|
||||
|
||||
#pragma code_seg(Code)
|
||||
void main(void) {
|
||||
SCREEN[0] = plus('0', 7);
|
||||
}
|
||||
|
21
src/test/kc/call-banked-phi-case-4-near-0.c
Normal file
21
src/test/kc/call-banked-phi-case-4-near-0.c
Normal file
@ -0,0 +1,21 @@
|
||||
// Test a procedure with calling convention PHI - case #4
|
||||
|
||||
#pragma link("call-banked-phi.ld")
|
||||
|
||||
|
||||
char* const SCREEN = (char*)0x0400;
|
||||
|
||||
#pragma code_seg(Code)
|
||||
void main(void) {
|
||||
SCREEN[0] = plus('0', 7);
|
||||
}
|
||||
|
||||
#pragma code_seg(RAM_Bank1)
|
||||
char __bank(cx16_ram, 1) plus(char a, char b) {
|
||||
return min(a, b);
|
||||
}
|
||||
|
||||
#pragma code_seg(RAM_Bank1)
|
||||
char __bank(cx16_ram, 1) min(char a, char b) {
|
||||
return a+b;
|
||||
}
|
21
src/test/kc/call-banked-phi-case-4-near-1.c
Normal file
21
src/test/kc/call-banked-phi-case-4-near-1.c
Normal file
@ -0,0 +1,21 @@
|
||||
// Test a procedure with calling convention PHI - case #4
|
||||
|
||||
#pragma link("call-banked-phi.ld")
|
||||
|
||||
|
||||
char* const SCREEN = (char*)0x0400;
|
||||
|
||||
#pragma code_seg(Code)
|
||||
void main(void) {
|
||||
SCREEN[0] = plus('0', 7);
|
||||
}
|
||||
|
||||
#pragma code_seg(RAM_Bank1)
|
||||
char __bank(cx16_ram, 1) plus(char a, char b) {
|
||||
return min(a, b);
|
||||
}
|
||||
|
||||
#pragma code_seg(RAM_Bank1)
|
||||
char __bank(cx16_ram, 1) min(char a, char b) {
|
||||
return a+b;
|
||||
}
|
21
src/test/kc/call-banked-phi-case-5-far-0.c
Normal file
21
src/test/kc/call-banked-phi-case-5-far-0.c
Normal file
@ -0,0 +1,21 @@
|
||||
// Test a procedure with calling convention PHI - case #4
|
||||
|
||||
#pragma link("call-banked-phi.ld")
|
||||
|
||||
|
||||
char* const SCREEN = (char*)0x0400;
|
||||
|
||||
#pragma code_seg(Code)
|
||||
void main(void) {
|
||||
SCREEN[0] = plus('0', 7);
|
||||
}
|
||||
|
||||
#pragma code_seg(RAM_Bank1)
|
||||
char __bank(cx16_ram, 1) plus(char a, char b) {
|
||||
return min(a, b);
|
||||
}
|
||||
|
||||
#pragma code_seg(RAM_Bank2)
|
||||
char __bank(cx16_ram, 2) min(char a, char b) {
|
||||
return a+b;
|
||||
}
|
21
src/test/kc/call-banked-phi-case-5-far-1.c
Normal file
21
src/test/kc/call-banked-phi-case-5-far-1.c
Normal file
@ -0,0 +1,21 @@
|
||||
// Test a procedure with calling convention PHI - case #4
|
||||
|
||||
#pragma link("call-banked-phi.ld")
|
||||
|
||||
|
||||
char* const SCREEN = (char*)0x0400;
|
||||
|
||||
#pragma code_seg(Code)
|
||||
void main(void) {
|
||||
SCREEN[0] = plus('0', 7);
|
||||
}
|
||||
|
||||
#pragma code_seg(RAM_Bank1)
|
||||
char __bank(cx16_ram, 1) plus(char a, char b) {
|
||||
return min(a, b);
|
||||
}
|
||||
|
||||
#pragma code_seg(RAM_Bank2)
|
||||
char __bank(cx16_ram, 2) min(char a, char b) {
|
||||
return a+b;
|
||||
}
|
20
src/test/kc/call-banked-phi-case-6-close-0.c
Normal file
20
src/test/kc/call-banked-phi-case-6-close-0.c
Normal file
@ -0,0 +1,20 @@
|
||||
// Test a procedure with calling convention PHI - case #6
|
||||
|
||||
#pragma link("call-banked-phi.ld")
|
||||
|
||||
char* const SCREEN = (char*)0x0400;
|
||||
|
||||
#pragma code_seg(Code)
|
||||
void main(void) {
|
||||
SCREEN[0] = plus('0', 7); // close call
|
||||
}
|
||||
|
||||
#pragma code_seg(RAM_Bank1)
|
||||
__bank(cx16_ram, 1) plus(char a, char b) {
|
||||
return min(a, b); // near call
|
||||
}
|
||||
|
||||
#pragma code_seg(ROM_Bank1)
|
||||
__bank(cx16_rom, 1) min(char a, char b) {
|
||||
return a+b;
|
||||
}
|
25
src/test/kc/call-banked-phi-case-6-close-1.c
Normal file
25
src/test/kc/call-banked-phi-case-6-close-1.c
Normal file
@ -0,0 +1,25 @@
|
||||
// Test a procedure with calling convention PHI - case #6
|
||||
|
||||
#pragma link("call-banked-phi.ld")
|
||||
|
||||
char* const SCREEN = (char*)0x0400;
|
||||
|
||||
#pragma code_seg(Code)
|
||||
void main(void) {
|
||||
SCREEN[0] = plus('0', 7); // close call
|
||||
}
|
||||
|
||||
#pragma code_seg(RAM_Bank1)
|
||||
#pragma bank(cx16_ram, 1)
|
||||
char plus(char a, char b) {
|
||||
return min(a, b); // near call
|
||||
}
|
||||
|
||||
#pragma code_seg(ROM_Bank1)
|
||||
#pragma bank(cx16_rom, 1)
|
||||
char min(char a, char b) {
|
||||
return a+b;
|
||||
}
|
||||
|
||||
#pragma code_seg(Code)
|
||||
#pragma nobank(dummy)
|
15
src/test/kc/call-banked-stack-case-2-close-0.c
Normal file
15
src/test/kc/call-banked-stack-case-2-close-0.c
Normal file
@ -0,0 +1,15 @@
|
||||
// Test a procedure with calling convention PHI - case #1
|
||||
|
||||
#pragma link("call-banked-stack.ld")
|
||||
|
||||
char* const SCREEN = (char*)0x0400;
|
||||
|
||||
#pragma code_seg(Code)
|
||||
void main(void) {
|
||||
SCREEN[0] = plus('0', 7); // near stack call
|
||||
}
|
||||
|
||||
#pragma code_seg(Code)
|
||||
__stackcall char plus(char a, char b) {
|
||||
return a+b;
|
||||
}
|
20
src/test/kc/call-banked-stack-case-5-far-0.c
Normal file
20
src/test/kc/call-banked-stack-case-5-far-0.c
Normal file
@ -0,0 +1,20 @@
|
||||
// Test a procedure with calling convention PHI - case #4
|
||||
|
||||
#pragma link("call-banked-phi.ld")
|
||||
|
||||
char* const SCREEN = (char*)0x0400;
|
||||
|
||||
#pragma code_seg(Code)
|
||||
void main(void) {
|
||||
SCREEN[0] = plus('0', 7); // close call
|
||||
}
|
||||
|
||||
#pragma code_seg(RAM_Bank1)
|
||||
char __bank(cx16_ram, 1) plus(char a, char b) {
|
||||
return min(a, b); // far call
|
||||
}
|
||||
|
||||
#pragma code_seg(RAM_Bank2)
|
||||
char __bank(cx16_ram, 2) min(char a, char b) {
|
||||
return a+b;
|
||||
}
|
@ -1,10 +1,11 @@
|
||||
.file [name="%O", type="prg", segments="Program"]
|
||||
.file [name="BANK1.BIN", type="bin", segments="Bank1"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$0801]
|
||||
.segmentdef Code [start=%P]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segmentdef Bank1 [start=$A000, min=$A000, max=$BFFF, align=$100]
|
||||
.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(%E)
|
||||
.segment Code
|
@ -1,55 +0,0 @@
|
||||
/**
|
||||
* @file cx16-banking-1.c
|
||||
* @author your name (you@domain.com)
|
||||
* @brief This program demonstrates a simple example of a banked call.
|
||||
* @version 0.1
|
||||
* @date 2023-04-05
|
||||
*
|
||||
* @copyright Copyright (c) 2023
|
||||
*
|
||||
*/
|
||||
|
||||
// The linker specification of the different segments.
|
||||
#pragma link("cx16-banking-1.ld")
|
||||
#pragma var_model(mem)
|
||||
|
||||
#include <cx16.h>
|
||||
#include <conio.h>
|
||||
#include <printf.h>
|
||||
#include <kernal.h>
|
||||
|
||||
#include "cx16-banking-0.h"
|
||||
|
||||
|
||||
// The target computer platform is the Commander X16,
|
||||
// which implements banking in ram between 0xA0000 and 0xBFFF,
|
||||
// and in ram between 0xC000 and 0xFFFF.
|
||||
#pragma target(cx16)
|
||||
|
||||
char* const SCREEN = (char*)0x0400;
|
||||
|
||||
#pragma code_seg(Bank1) // The sequent functions will be addressed specified by segment bank1 in the linker.
|
||||
#pragma bank(ram, 1) // The sequent functions will be banked using call method ram in bank number 1.
|
||||
|
||||
char __stackcall plus(char a, char b) {
|
||||
return a+b;
|
||||
}
|
||||
|
||||
#pragma code_seg(Code) // The sequent functions will be addressed in the default main memory location (segment Code).
|
||||
#pragma nobank(dummy) // The sequent functions will consider no banking calculations anymore.
|
||||
|
||||
void load_bank(char bank, char *file) {
|
||||
bank_set_bram(bank);
|
||||
cbm_k_setnam(file);
|
||||
cbm_k_setlfs(1,8,2);
|
||||
cbm_k_load((char*)0xA000, 0);
|
||||
cbm_k_close(1);
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
|
||||
load_bank(1, "BANK1.BIN");
|
||||
|
||||
SCREEN[0] = plus('0', 7);
|
||||
}
|
||||
|
@ -16,10 +16,7 @@
|
||||
#include <cx16.h>
|
||||
#include <conio.h>
|
||||
#include <printf.h>
|
||||
#include <kernal.h>
|
||||
|
||||
#include "cx16-banking-1.h"
|
||||
|
||||
#include <cx16-kernal.h>
|
||||
|
||||
// The target computer platform is the Commander X16,
|
||||
// which implements banking in ram between 0xA0000 and 0xBFFF,
|
@ -1,15 +0,0 @@
|
||||
// Test a procedure with calling convention PHI
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
char __bank(ram,2) plus(char a, char b) {
|
||||
return a+b;
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
// 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;
|
||||
|
||||
void main(void) {
|
||||
SCREEN[0] = plus('0', 7);
|
||||
}
|
||||
|
||||
#pragma code_seg(stage)
|
||||
#pragma bank(ram, 1)
|
||||
|
||||
char plus(char a, char b) {
|
||||
return a+b;
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
// Test a far call procedure with a calling convention PHI into ROM
|
||||
|
||||
#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)
|
||||
#pragma bank(rom, 1) // test rom bank
|
||||
|
||||
char plus(char a, char b) {
|
||||
return a+b;
|
||||
}
|
||||
|
@ -1,21 +0,0 @@
|
||||
// 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;
|
||||
|
||||
void main(void) {
|
||||
SCREEN[0] = plus('0', 7);
|
||||
}
|
||||
|
||||
#pragma code_seg(stage)
|
||||
#pragma bank(rom, 2) // Test rom fragment
|
||||
|
||||
char plus(char a, char b) {
|
||||
return a+b;
|
||||
}
|
||||
|
||||
#pragma nobank(dummy)
|
||||
|
@ -1,20 +0,0 @@
|
||||
// Test a far call procedure with a calling convention phi
|
||||
|
||||
#pragma link("procedure-callingconvention-phi-bank.ld")
|
||||
#pragma target(cx16)
|
||||
|
||||
char* const SCREEN = (char*)0x0400;
|
||||
|
||||
#pragma code_seg(stage)
|
||||
#pragma bank(ram, 20)
|
||||
|
||||
char plus(char a, char b) {
|
||||
return a+b;
|
||||
}
|
||||
|
||||
#pragma nobank(dummy)
|
||||
|
||||
void main(void) {
|
||||
SCREEN[0] = plus('0', 7);
|
||||
}
|
||||
|
@ -1,119 +0,0 @@
|
||||
|
||||
// The linker specification of the different segments.
|
||||
#pragma link("procedure-callingconvention-phi-bank-5.ld")
|
||||
|
||||
// The target computer platform is the Commander X16,
|
||||
// which implements banking in ram between 0xA0000 and 0xBFFF,
|
||||
// and in rom between 0xC000 and 0xFFFF.
|
||||
#pragma target(cx16)
|
||||
|
||||
char *const SCREEN = (char *)0x0400; // Just for test purposes.
|
||||
|
||||
#pragma code_seg(Bank1) // The sequent functions will be addressed specified by segment bank1 in the linker.
|
||||
#pragma bank(ram, 1) // The sequent functions will be banked using call method ram in bank number 1.
|
||||
|
||||
// Function declarations
|
||||
char func_ram_bank1_a(char a, char b);
|
||||
char __bank(ram, 1) func_ram_bank1_b(char a, char b);
|
||||
char func_ram_bank1_c(char a, char b);
|
||||
char func_ram_bank1_d(char a, char b);
|
||||
char func_ram_bank1_e(char a, char b);
|
||||
char func_ram_bank1_f(char a, char b);
|
||||
char func_rom_bank2_a(char a, char b);
|
||||
char __bank(rom, 2) func_rom_bank2_b(char a, char b);
|
||||
char func_rom_bank2_c(char a, char b);
|
||||
char func_rom_bank2_d(char a, char b);
|
||||
char func_rom_bank2_e(char a, char b);
|
||||
char func_rom_bank2_f(char a, char b);
|
||||
char func_main_a(char a, char b);
|
||||
char func_main_b(char a, char b);
|
||||
|
||||
// Functional code
|
||||
|
||||
char func_ram_bank1_a(char a, char b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
char func_ram_bank1_c(char a, char b) {
|
||||
return func_ram_bank1_a(a, b); // Non banked call in ram bank 1.
|
||||
}
|
||||
|
||||
char func_ram_bank1_d(char a, char b) {
|
||||
return func_rom_bank2_a(a, b); // Banked call from ram bank 1 to rom bank 2.
|
||||
}
|
||||
|
||||
char func_ram_bank1_e(char a, char b) {
|
||||
return func_rom_bank2_b(a, b); // Banked call from ram bank 1 to rom bank 2.
|
||||
}
|
||||
|
||||
char func_ram_bank1_f(char a, char b) {
|
||||
return func_main_a(a, b); // Non banked call from ram bank 1 to main memory.
|
||||
}
|
||||
|
||||
|
||||
#pragma code_seg(Bank2) // The sequent functions will be addressed specified by segment bank2 in the linker.
|
||||
#pragma bank(rom, 2) // The sequent functions will be banked using call method rom in bank number 2.
|
||||
|
||||
char func_rom_bank2_a(char a, char b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
char func_rom_bank2_c(char a, char b) {
|
||||
return func_ram_bank1_a(a, b); // Banked call from rom bank 2 to ram bank 1.
|
||||
}
|
||||
|
||||
char func_rom_bank2_d(char a, char b) {
|
||||
return func_rom_bank2_a(a, b); // Non banked call in rom bank 2.
|
||||
}
|
||||
|
||||
char func_rom_bank2_e(char a, char b) {
|
||||
return func_rom_bank2_b(a, b); // Non Banked call in rom bank 2.
|
||||
}
|
||||
|
||||
char func_rom_bank2_f(char a, char b) {
|
||||
return func_main_a(a, b); // Non banked call from rom bank 2 to main memory.
|
||||
}
|
||||
|
||||
|
||||
#pragma nobank(dummy) // The sequent functions will consider no banking calculations anymore.
|
||||
|
||||
// The __bank directive declares this function to be banked using call method ram in bank number 1 of banked ram.
|
||||
char __bank(ram, 1) func_ram_bank1_b(char a, char b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
// The __bank directive declares this function to be banked using call method rom in bank number 2 of banked rom.
|
||||
char __bank(rom, 2) func_rom_bank2_b(char a, char b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
#pragma code_seg(Code) // The sequent functions will be addressed in the default main memory location (segment Code).
|
||||
|
||||
// Allocated in main memory.
|
||||
char func_main_a(char a, char b) {
|
||||
return func_ram_bank1_e(a, b); // Banked call to ram in bank 1 from main memory.
|
||||
}
|
||||
|
||||
// Allocated in main memory.
|
||||
char func_main_b(char a, char b) {
|
||||
return func_rom_bank2_e(a, b); // Banked call to rom in bank 2 from main memory.
|
||||
}
|
||||
|
||||
// Practically this means that the main() function is placed in main memory ...
|
||||
|
||||
void main(void) {
|
||||
SCREEN[0] = func_ram_bank1_a('0', 7); // Banked call to ram in bank 1 from main memory.
|
||||
SCREEN[0] = func_ram_bank1_b('0', 7); // Banked call to ram in bank 1 from main memory.
|
||||
SCREEN[0] = func_ram_bank1_c('0', 7); // Banked call to ram in bank 1 from main memory.
|
||||
SCREEN[0] = func_ram_bank1_d('0', 7); // Banked call to ram in bank 1 from main memory.
|
||||
SCREEN[0] = func_ram_bank1_e('0', 7); // Banked call to ram in bank 1 from main memory.
|
||||
SCREEN[0] = func_ram_bank1_f('0', 7); // Banked call to ram in bank 1 from main memory.
|
||||
SCREEN[0] = func_rom_bank2_a('0', 7); // Banked call to rom in bank 2 from main memory.
|
||||
SCREEN[0] = func_rom_bank2_b('0', 7); // Banked call to rom in bank 2 from main memory.
|
||||
SCREEN[0] = func_rom_bank2_c('0', 7); // Banked call to rom in bank 2 from main memory.
|
||||
SCREEN[0] = func_rom_bank2_d('0', 7); // Banked call to rom in bank 2 from main memory.
|
||||
SCREEN[0] = func_rom_bank2_e('0', 7); // banked call to rom in bank 2 from main memory.
|
||||
SCREEN[0] = func_rom_bank2_f('0', 7); // banked call to rom in bank 2 from main memory.
|
||||
SCREEN[0] = func_main_a('0', 7); // Near call in main memory from main memory.
|
||||
SCREEN[0] = func_main_b('0', 7); // Near call in main memory from main memory.
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
.segmentdef Program [segments="Basic, Code, Data, Bank1, Bank2"]
|
||||
.segmentdef Basic [start=$0801]a
|
||||
.segmentdef Code [start=%P]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segmentdef Bank1 [start=$A000, min=$A000, max=$BFFF, align=$100]
|
||||
.segmentdef Bank2 [start=$C000, min=$C000, max=$FFFF, align=$100]
|
||||
|
33
src/test/ref/call-banked-phi-case-1-near-0.asm
Normal file
33
src/test/ref/call-banked-phi-case-1-near-0.asm
Normal file
@ -0,0 +1,33 @@
|
||||
// Test a procedure with calling convention PHI - case #1
|
||||
.file [name="call-banked-phi-case-1-near-0.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
|
||||
|
||||
|
||||
.label SCREEN = $400
|
||||
.segment Code
|
||||
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
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
Loading link script "procedure-callingconvention-phi-bank.ld"
|
||||
Loading link script "call-banked-phi.ld"
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
|
||||
@ -157,24 +157,29 @@ Uplifting [] best 60 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Test a procedure with calling convention PHI
|
||||
// Test a procedure with calling convention PHI - case #1
|
||||
// Upstart
|
||||
.cpu _65c02
|
||||
.segmentdef Program [segments="Basic, Code, Data, stage, platform"]
|
||||
.file [name="call-banked-phi-case-1-near-0.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.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]
|
||||
.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 stage
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
// [1] call plus
|
||||
// [4] phi from main to plus [phi:main->plus]
|
||||
// [4] phi from main to plus [phi:main->plus] -- call__phi_near_finalize
|
||||
plus_from_main:
|
||||
jsr plus
|
||||
jmp __b1
|
||||
@ -231,25 +236,30 @@ FINAL ASSEMBLER
|
||||
Score: 24
|
||||
|
||||
// File Comments
|
||||
// Test a procedure with calling convention PHI
|
||||
// Test a procedure with calling convention PHI - case #1
|
||||
// Upstart
|
||||
.cpu _65c02
|
||||
.segmentdef Program [segments="Basic, Code, Data, stage, platform"]
|
||||
.file [name="call-banked-phi-case-1-near-0.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.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]
|
||||
.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 stage
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
// plus('0', 7)
|
||||
// [1] call plus
|
||||
// [4] phi from main to plus [phi:main->plus]
|
||||
// [4] phi from main to plus [phi:main->plus] -- call__phi_near_finalize
|
||||
jsr plus
|
||||
// main::@1
|
||||
// SCREEN[0] = plus('0', 7)
|
40
src/test/ref/call-banked-phi-case-1-near-1.asm
Normal file
40
src/test/ref/call-banked-phi-case-1-near-1.asm
Normal file
@ -0,0 +1,40 @@
|
||||
// Test a procedure with calling convention PHI - case #1
|
||||
.file [name="call-banked-phi-case-1-near-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
|
||||
|
||||
|
||||
.label SCREEN = $400
|
||||
.segment Code
|
||||
main: {
|
||||
// plus('0', 7)
|
||||
jsr plus
|
||||
// SCREEN[0] = plus('0', 7)
|
||||
lda #min.return
|
||||
sta SCREEN
|
||||
// }
|
||||
rts
|
||||
}
|
||||
// char plus(char a, char b)
|
||||
plus: {
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// min(a, b)
|
||||
jsr min
|
||||
// }
|
||||
rts
|
||||
}
|
||||
// char min(char a, char b)
|
||||
min: {
|
||||
.label return = plus.a+plus.b
|
||||
rts
|
||||
}
|
29
src/test/ref/call-banked-phi-case-1-near-1.cfg
Normal file
29
src/test/ref/call-banked-phi-case-1-near-1.cfg
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
386
src/test/ref/call-banked-phi-case-1-near-1.log
Normal file
386
src/test/ref/call-banked-phi-case-1-near-1.log
Normal file
@ -0,0 +1,386 @@
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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()
|
||||
char min(char a , char b)
|
||||
char min::a
|
||||
char min::b
|
||||
char min::return
|
||||
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 = 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 75 combination
|
||||
Uplifting [plus] best 75 combination
|
||||
Uplifting [min] best 75 combination
|
||||
Uplifting [] best 75 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Test a procedure with calling convention PHI - case #1
|
||||
// Upstart
|
||||
.file [name="call-banked-phi-case-1-near-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_near_finalize
|
||||
plus_from_main:
|
||||
jsr plus
|
||||
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
|
||||
}
|
||||
// plus
|
||||
// char plus(char a, char b)
|
||||
plus: {
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// [5] call min
|
||||
// [7] phi from plus to min [phi:plus->min] -- call__phi_near_finalize
|
||||
min_from_plus:
|
||||
jsr min
|
||||
jmp __breturn
|
||||
// plus::@return
|
||||
__breturn:
|
||||
// [6] return
|
||||
rts
|
||||
}
|
||||
// min
|
||||
// char min(char a, char b)
|
||||
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()
|
||||
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
|
||||
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: 36
|
||||
|
||||
// File Comments
|
||||
// Test a procedure with calling convention PHI - case #1
|
||||
// Upstart
|
||||
.file [name="call-banked-phi-case-1-near-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_near_finalize
|
||||
jsr plus
|
||||
// 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
|
||||
}
|
||||
// plus
|
||||
// char plus(char a, char b)
|
||||
plus: {
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// min(a, b)
|
||||
// [5] call min
|
||||
// [7] phi from plus to min [phi:plus->min] -- call__phi_near_finalize
|
||||
jsr min
|
||||
// plus::@return
|
||||
// }
|
||||
// [6] return
|
||||
rts
|
||||
}
|
||||
// min
|
||||
// char min(char a, char b)
|
||||
min: {
|
||||
.label return = plus.a+plus.b
|
||||
// min::@return
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
14
src/test/ref/call-banked-phi-case-1-near-1.sym
Normal file
14
src/test/ref/call-banked-phi-case-1-near-1.sym
Normal file
@ -0,0 +1,14 @@
|
||||
__constant char * const SCREEN = (char *) 1024
|
||||
void main()
|
||||
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
|
||||
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
|
||||
|
39
src/test/ref/call-banked-phi-case-2-close-0.asm
Normal file
39
src/test/ref/call-banked-phi-case-2-close-0.asm
Normal file
@ -0,0 +1,39 @@
|
||||
// Test a procedure with calling convention PHI - case #2
|
||||
.file [name="call-banked-phi-case-2-close-0.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
|
||||
|
||||
|
||||
.label SCREEN = $400
|
||||
.segment Code
|
||||
main: {
|
||||
// plus('0', 7)
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
jsr plus
|
||||
pla
|
||||
sta.z 0
|
||||
// SCREEN[0] = plus('0', 7)
|
||||
lda #plus.return
|
||||
sta SCREEN
|
||||
// }
|
||||
rts
|
||||
}
|
||||
.segment RAM_Bank1
|
||||
// char plus(char a, char b)
|
||||
plus: {
|
||||
.const a = '0'
|
||||
.const b = 7
|
||||
.label return = a+b
|
||||
rts
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
Loading link script "procedure-callingconvention-phi-bank.ld"
|
||||
Loading link script "call-banked-phi.ld"
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
|
||||
@ -144,6 +144,7 @@ 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 = plus::return#1 [ ] ( [ ] { } ) always clobbers reg byte a
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
@ -151,35 +152,42 @@ Uplift Scope [main]
|
||||
Uplift Scope [plus]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 60 combination
|
||||
Uplifting [plus] best 60 combination
|
||||
Uplifting [] best 60 combination
|
||||
Uplifting [main] best 75 combination
|
||||
Uplifting [plus] best 75 combination
|
||||
Uplifting [] best 75 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Test a far call procedure with a calling convention PHI into ROM
|
||||
// Test a procedure with calling convention PHI - case #2
|
||||
// Upstart
|
||||
.cpu _65c02
|
||||
.segmentdef Program [segments="Basic, Code, Data, stage, platform"]
|
||||
.file [name="call-banked-phi-case-2-close-0.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.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]
|
||||
.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 stage
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
// [1] call plus
|
||||
// [4] phi from main to plus [phi:main->plus] -- call_far_cx16_rom_finalize
|
||||
// [4] phi from main to plus [phi:main->plus] -- call_cx16_ram_phi_close_finalize
|
||||
plus_from_main:
|
||||
jsr $ff6e
|
||||
.byte <plus
|
||||
.byte >plus
|
||||
.byte 1
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
jsr plus
|
||||
pla
|
||||
sta.z 0
|
||||
jmp __b1
|
||||
// main::@1
|
||||
__b1:
|
||||
@ -192,8 +200,8 @@ main: {
|
||||
// [3] return
|
||||
rts
|
||||
}
|
||||
.segment RAM_Bank1
|
||||
// plus
|
||||
// test rom bank
|
||||
// char plus(char a, char b)
|
||||
plus: {
|
||||
.const a = '0'
|
||||
@ -232,32 +240,39 @@ __constant char plus::return#1 = plus::a#0+plus::b#0 // return
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 24
|
||||
Score: 39
|
||||
|
||||
// File Comments
|
||||
// Test a far call procedure with a calling convention PHI into ROM
|
||||
// Test a procedure with calling convention PHI - case #2
|
||||
// Upstart
|
||||
.cpu _65c02
|
||||
.segmentdef Program [segments="Basic, Code, Data, stage, platform"]
|
||||
.file [name="call-banked-phi-case-2-close-0.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.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]
|
||||
.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 stage
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
// plus('0', 7)
|
||||
// [1] call plus
|
||||
// [4] phi from main to plus [phi:main->plus] -- call_far_cx16_rom_finalize
|
||||
jsr $ff6e
|
||||
.byte <plus
|
||||
.byte >plus
|
||||
.byte 1
|
||||
// [4] phi from main to plus [phi:main->plus] -- call_cx16_ram_phi_close_finalize
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
jsr plus
|
||||
pla
|
||||
sta.z 0
|
||||
// main::@1
|
||||
// SCREEN[0] = plus('0', 7)
|
||||
// [2] *SCREEN = plus::return#1 -- _deref_pbuc1=vbuc2
|
||||
@ -268,8 +283,8 @@ main: {
|
||||
// [3] return
|
||||
rts
|
||||
}
|
||||
.segment RAM_Bank1
|
||||
// plus
|
||||
// test rom bank
|
||||
// char plus(char a, char b)
|
||||
plus: {
|
||||
.const a = '0'
|
39
src/test/ref/call-banked-phi-case-2-close-1.asm
Normal file
39
src/test/ref/call-banked-phi-case-2-close-1.asm
Normal file
@ -0,0 +1,39 @@
|
||||
// Test a procedure with calling convention PHI - case #2
|
||||
.file [name="call-banked-phi-case-2-close-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
|
||||
|
||||
|
||||
.label SCREEN = $400
|
||||
.segment Code
|
||||
main: {
|
||||
// plus('0', 7)
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
jsr plus
|
||||
pla
|
||||
sta.z 0
|
||||
// SCREEN[0] = plus('0', 7)
|
||||
lda #plus.return
|
||||
sta SCREEN
|
||||
// }
|
||||
rts
|
||||
}
|
||||
.segment RAM_Bank1
|
||||
// char plus(char a, char b)
|
||||
plus: {
|
||||
.const a = '0'
|
||||
.const b = 7
|
||||
.label return = a+b
|
||||
rts
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
Loading link script "procedure-callingconvention-phi-bank.ld"
|
||||
Loading link script "call-banked-phi.ld"
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
|
||||
@ -144,6 +144,7 @@ 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 = plus::return#1 [ ] ( [ ] { } ) always clobbers reg byte a
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
@ -151,35 +152,42 @@ Uplift Scope [main]
|
||||
Uplift Scope [plus]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 60 combination
|
||||
Uplifting [plus] best 60 combination
|
||||
Uplifting [] best 60 combination
|
||||
Uplifting [main] best 75 combination
|
||||
Uplifting [plus] best 75 combination
|
||||
Uplifting [] best 75 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Test a far call procedure with a calling convention PHI
|
||||
// Test a procedure with calling convention PHI - case #2
|
||||
// Upstart
|
||||
.cpu _65c02
|
||||
.segmentdef Program [segments="Basic, Code, Data, stage, platform"]
|
||||
.file [name="call-banked-phi-case-2-close-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 stage [start=$0400, min=$0400, max=$07FF, align=$100]
|
||||
.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100]
|
||||
.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 stage
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
// [1] call plus
|
||||
// [4] phi from main to plus [phi:main->plus] -- call_far_cx16_rom_finalize
|
||||
// [4] phi from main to plus [phi:main->plus] -- call_cx16_ram_phi_close_finalize
|
||||
plus_from_main:
|
||||
jsr $ff6e
|
||||
.byte <plus
|
||||
.byte >plus
|
||||
.byte 2
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
jsr plus
|
||||
pla
|
||||
sta.z 0
|
||||
jmp __b1
|
||||
// main::@1
|
||||
__b1:
|
||||
@ -192,8 +200,8 @@ main: {
|
||||
// [3] return
|
||||
rts
|
||||
}
|
||||
.segment RAM_Bank1
|
||||
// plus
|
||||
// Test rom fragment
|
||||
// char plus(char a, char b)
|
||||
plus: {
|
||||
.const a = '0'
|
||||
@ -232,32 +240,39 @@ __constant char plus::return#1 = plus::a#0+plus::b#0 // return
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 24
|
||||
Score: 39
|
||||
|
||||
// File Comments
|
||||
// Test a far call procedure with a calling convention PHI
|
||||
// Test a procedure with calling convention PHI - case #2
|
||||
// Upstart
|
||||
.cpu _65c02
|
||||
.segmentdef Program [segments="Basic, Code, Data, stage, platform"]
|
||||
.file [name="call-banked-phi-case-2-close-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 stage [start=$0400, min=$0400, max=$07FF, align=$100]
|
||||
.segmentdef platform [start=$C000, min=$C000, max=$C7FF, align=$100]
|
||||
.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 stage
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
// plus('0', 7)
|
||||
// [1] call plus
|
||||
// [4] phi from main to plus [phi:main->plus] -- call_far_cx16_rom_finalize
|
||||
jsr $ff6e
|
||||
.byte <plus
|
||||
.byte >plus
|
||||
.byte 2
|
||||
// [4] phi from main to plus [phi:main->plus] -- call_cx16_ram_phi_close_finalize
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
jsr plus
|
||||
pla
|
||||
sta.z 0
|
||||
// main::@1
|
||||
// SCREEN[0] = plus('0', 7)
|
||||
// [2] *SCREEN = plus::return#1 -- _deref_pbuc1=vbuc2
|
||||
@ -268,8 +283,8 @@ main: {
|
||||
// [3] return
|
||||
rts
|
||||
}
|
||||
.segment RAM_Bank1
|
||||
// plus
|
||||
// Test rom fragment
|
||||
// char plus(char a, char b)
|
||||
plus: {
|
||||
.const a = '0'
|
47
src/test/ref/call-banked-phi-case-3-near-0.asm
Normal file
47
src/test/ref/call-banked-phi-case-3-near-0.asm
Normal file
@ -0,0 +1,47 @@
|
||||
// Test a procedure with calling convention PHI - case #3
|
||||
.file [name="call-banked-phi-case-3-near-0.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
|
||||
|
||||
|
||||
.label SCREEN = $400
|
||||
.segment Code
|
||||
main: {
|
||||
// plus('0', 7)
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
jsr plus
|
||||
pla
|
||||
sta.z 0
|
||||
// SCREEN[0] = plus('0', 7)
|
||||
lda #min.return
|
||||
sta SCREEN
|
||||
// }
|
||||
rts
|
||||
}
|
||||
.segment RAM_Bank1
|
||||
// char plus(char a, char b)
|
||||
plus: {
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// min(a, b)
|
||||
jsr min
|
||||
// }
|
||||
rts
|
||||
}
|
||||
.segment Code
|
||||
// char min(char a, char b)
|
||||
min: {
|
||||
.label return = plus.a+plus.b
|
||||
rts
|
||||
}
|
@ -5,7 +5,7 @@ main: scope:[main] from
|
||||
[1] call plus
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[2] *SCREEN = plus::return#1
|
||||
[2] *SCREEN = min::return#1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[3] return
|
||||
@ -14,7 +14,16 @@ main::@return: scope:[main] from main::@1
|
||||
__bank(bank) 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
|
||||
[5] return
|
||||
[6] return
|
||||
to:@return
|
||||
|
||||
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
|
@ -1,4 +1,4 @@
|
||||
Loading link script "procedure-callingconvention-phi-bank.ld"
|
||||
Loading link script "call-banked-phi.ld"
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
|
||||
@ -22,15 +22,35 @@ __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
|
||||
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
|
||||
plus::return#4 = phi( plus/plus::return#1 )
|
||||
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
|
||||
|
||||
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
|
||||
@ -46,6 +66,20 @@ __constant char * const SCREEN = (char *)$400
|
||||
void __start()
|
||||
void main()
|
||||
char main::$0
|
||||
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(bank) char plus(char a , char b)
|
||||
char plus::$0
|
||||
char plus::a
|
||||
@ -74,14 +108,21 @@ 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
|
||||
@ -89,27 +130,40 @@ 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
|
||||
Constant right-side identified [9] min::return#1 = min::a#0 + min::b#0
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant plus::return#1 = plus::a#0+plus::b#0
|
||||
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 plus::return#0
|
||||
Constant inlined plus::return#0 = plus::return#1
|
||||
Constant inlined main::$0 = plus::return#1
|
||||
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
|
||||
|
||||
@ -119,7 +173,7 @@ main: scope:[main] from
|
||||
[1] call plus
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[2] *SCREEN = plus::return#1
|
||||
[2] *SCREEN = min::return#1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[3] return
|
||||
@ -128,14 +182,27 @@ main::@return: scope:[main] from main::@1
|
||||
__bank(bank) 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
|
||||
[5] return
|
||||
[6] return
|
||||
to:@return
|
||||
|
||||
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()
|
||||
char min(char a , char b)
|
||||
char min::a
|
||||
char min::b
|
||||
char min::return
|
||||
__bank(bank) char plus(char a , char b)
|
||||
char plus::a
|
||||
char plus::b
|
||||
@ -144,47 +211,57 @@ 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
|
||||
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 60 combination
|
||||
Uplifting [plus] best 60 combination
|
||||
Uplifting [] best 60 combination
|
||||
Uplifting [main] best 90 combination
|
||||
Uplifting [plus] best 90 combination
|
||||
Uplifting [min] best 90 combination
|
||||
Uplifting [] best 90 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Test a far call procedure with a calling convention PHI
|
||||
// Test a procedure with calling convention PHI - case #3
|
||||
// Upstart
|
||||
.cpu _65c02
|
||||
.segmentdef Program [segments="Basic, Code, Data, stage, platform"]
|
||||
.file [name="call-banked-phi-case-3-near-0.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.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]
|
||||
.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 stage
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
// [1] call plus
|
||||
// [4] phi from main to plus [phi:main->plus] -- call_far_cx16_ram_finalize
|
||||
// [4] phi from main to plus [phi:main->plus] -- call_cx16_ram_phi_close_finalize
|
||||
plus_from_main:
|
||||
jsr $ff6e
|
||||
.byte <plus
|
||||
.byte >plus
|
||||
.byte 1
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
jsr plus
|
||||
pla
|
||||
sta.z 0
|
||||
jmp __b1
|
||||
// main::@1
|
||||
__b1:
|
||||
// [2] *SCREEN = plus::return#1 -- _deref_pbuc1=vbuc2
|
||||
lda #plus.return
|
||||
// [2] *SCREEN = min::return#1 -- _deref_pbuc1=vbuc2
|
||||
lda #min.return
|
||||
sta SCREEN
|
||||
jmp __breturn
|
||||
// main::@return
|
||||
@ -192,16 +269,31 @@ main: {
|
||||
// [3] return
|
||||
rts
|
||||
}
|
||||
.segment RAM_Bank1
|
||||
// plus
|
||||
// char plus(char a, char b)
|
||||
plus: {
|
||||
.const a = '0'
|
||||
.const b = 7
|
||||
.label return = a+b
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// [5] call min
|
||||
// [7] phi from plus to min [phi:plus->min] -- call__phi_near_finalize
|
||||
min_from_plus:
|
||||
jsr min
|
||||
jmp __breturn
|
||||
// plus::@return
|
||||
__breturn:
|
||||
// [5] return
|
||||
// [6] return
|
||||
rts
|
||||
}
|
||||
.segment Code
|
||||
// min
|
||||
// char min(char a, char b)
|
||||
min: {
|
||||
.label return = plus.a+plus.b
|
||||
jmp __breturn
|
||||
// min::@return
|
||||
__breturn:
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
@ -210,71 +302,99 @@ 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()
|
||||
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(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
|
||||
Score: 51
|
||||
|
||||
// File Comments
|
||||
// Test a far call procedure with a calling convention PHI
|
||||
// Test a procedure with calling convention PHI - case #3
|
||||
// Upstart
|
||||
.cpu _65c02
|
||||
.segmentdef Program [segments="Basic, Code, Data, stage, platform"]
|
||||
.file [name="call-banked-phi-case-3-near-0.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.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]
|
||||
.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 stage
|
||||
.segment Code
|
||||
// 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 >plus
|
||||
.byte 1
|
||||
// [4] phi from main to plus [phi:main->plus] -- call_cx16_ram_phi_close_finalize
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
jsr plus
|
||||
pla
|
||||
sta.z 0
|
||||
// main::@1
|
||||
// SCREEN[0] = plus('0', 7)
|
||||
// [2] *SCREEN = plus::return#1 -- _deref_pbuc1=vbuc2
|
||||
lda #plus.return
|
||||
// [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)
|
||||
plus: {
|
||||
.const a = '0'
|
||||
.const b = 7
|
||||
.label return = a+b
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// min(a, b)
|
||||
// [5] call min
|
||||
// [7] phi from plus to min [phi:plus->min] -- call__phi_near_finalize
|
||||
jsr min
|
||||
// plus::@return
|
||||
// [5] return
|
||||
// }
|
||||
// [6] return
|
||||
rts
|
||||
}
|
||||
.segment Code
|
||||
// min
|
||||
// char min(char a, char b)
|
||||
min: {
|
||||
.label return = plus.a+plus.b
|
||||
// min::@return
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
@ -1,10 +1,14 @@
|
||||
__constant char * const SCREEN = (char *) 1024
|
||||
void main()
|
||||
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(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
|
||||
|
47
src/test/ref/call-banked-phi-case-3-near-1.asm
Normal file
47
src/test/ref/call-banked-phi-case-3-near-1.asm
Normal file
@ -0,0 +1,47 @@
|
||||
// Test a procedure with calling convention PHI - case #3
|
||||
.file [name="call-banked-phi-case-3-near-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
|
||||
|
||||
|
||||
.label SCREEN = $400
|
||||
.segment Code
|
||||
main: {
|
||||
// plus('0', 7)
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
jsr plus
|
||||
pla
|
||||
sta.z 0
|
||||
// SCREEN[0] = plus('0', 7)
|
||||
lda #min.return
|
||||
sta SCREEN
|
||||
// }
|
||||
rts
|
||||
}
|
||||
.segment RAM_Bank1
|
||||
// char plus(char a, char b)
|
||||
plus: {
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// min(a, b)
|
||||
jsr min
|
||||
// }
|
||||
rts
|
||||
}
|
||||
.segment Code
|
||||
// char min(char a, char b)
|
||||
min: {
|
||||
.label return = plus.a+plus.b
|
||||
rts
|
||||
}
|
@ -5,7 +5,7 @@ main: scope:[main] from
|
||||
[1] call plus
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[2] *SCREEN = plus::return#0
|
||||
[2] *SCREEN = min::return#1
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@1
|
||||
[3] return
|
||||
@ -14,7 +14,16 @@ main::@return: scope:[main] from main::@1
|
||||
__bank(bank) 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
|
||||
[5] return
|
||||
[6] return
|
||||
to:@return
|
||||
|
||||
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
|
401
src/test/ref/call-banked-phi-case-3-near-1.log
Normal file
401
src/test/ref/call-banked-phi-case-3-near-1.log
Normal file
@ -0,0 +1,401 @@
|
||||
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(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 )
|
||||
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
|
||||
|
||||
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
|
||||
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(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 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(bank) 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
|
||||
|
||||
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()
|
||||
char min(char a , char b)
|
||||
char min::a
|
||||
char min::b
|
||||
char min::return
|
||||
__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 [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 90 combination
|
||||
Uplifting [plus] best 90 combination
|
||||
Uplifting [min] best 90 combination
|
||||
Uplifting [] best 90 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Test a procedure with calling convention PHI - case #3
|
||||
// Upstart
|
||||
.file [name="call-banked-phi-case-3-near-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_cx16_ram_phi_close_finalize
|
||||
plus_from_main:
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
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)
|
||||
plus: {
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// [5] call min
|
||||
// [7] phi from plus to min [phi:plus->min] -- call__phi_near_finalize
|
||||
min_from_plus:
|
||||
jsr min
|
||||
jmp __breturn
|
||||
// plus::@return
|
||||
__breturn:
|
||||
// [6] return
|
||||
rts
|
||||
}
|
||||
.segment Code
|
||||
// min
|
||||
// char min(char a, char b)
|
||||
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()
|
||||
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(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
|
||||
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 51
|
||||
|
||||
// File Comments
|
||||
// Test a procedure with calling convention PHI - case #3
|
||||
// Upstart
|
||||
.file [name="call-banked-phi-case-3-near-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_cx16_ram_phi_close_finalize
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
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)
|
||||
plus: {
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// min(a, b)
|
||||
// [5] call min
|
||||
// [7] phi from plus to min [phi:plus->min] -- call__phi_near_finalize
|
||||
jsr min
|
||||
// plus::@return
|
||||
// }
|
||||
// [6] return
|
||||
rts
|
||||
}
|
||||
.segment Code
|
||||
// min
|
||||
// char min(char a, char b)
|
||||
min: {
|
||||
.label return = plus.a+plus.b
|
||||
// min::@return
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
@ -1,10 +1,14 @@
|
||||
__constant char * const SCREEN = (char *) 1024
|
||||
void main()
|
||||
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(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
|
||||
|
46
src/test/ref/call-banked-phi-case-4-near-0.asm
Normal file
46
src/test/ref/call-banked-phi-case-4-near-0.asm
Normal file
@ -0,0 +1,46 @@
|
||||
// Test a procedure with calling convention PHI - case #4
|
||||
.file [name="call-banked-phi-case-4-near-0.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
|
||||
|
||||
|
||||
.label SCREEN = $400
|
||||
.segment Code
|
||||
main: {
|
||||
// plus('0', 7)
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
jsr plus
|
||||
pla
|
||||
sta.z 0
|
||||
// SCREEN[0] = plus('0', 7)
|
||||
lda #min.return
|
||||
sta SCREEN
|
||||
// }
|
||||
rts
|
||||
}
|
||||
.segment RAM_Bank1
|
||||
// char plus(char a, char b)
|
||||
plus: {
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// min(a, b)
|
||||
jsr min
|
||||
// }
|
||||
rts
|
||||
}
|
||||
// char min(char a, char b)
|
||||
min: {
|
||||
.label return = plus.a+plus.b
|
||||
rts
|
||||
}
|
29
src/test/ref/call-banked-phi-case-4-near-0.cfg
Normal file
29
src/test/ref/call-banked-phi-case-4-near-0.cfg
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
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(bank) 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(bank) 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
|
399
src/test/ref/call-banked-phi-case-4-near-0.log
Normal file
399
src/test/ref/call-banked-phi-case-4-near-0.log
Normal file
@ -0,0 +1,399 @@
|
||||
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(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 )
|
||||
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(bank) 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(bank) 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(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 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(bank) 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(bank) 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(bank) char min(char a , char b)
|
||||
char min::a
|
||||
char min::b
|
||||
char min::return
|
||||
__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 [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 90 combination
|
||||
Uplifting [plus] best 90 combination
|
||||
Uplifting [min] best 90 combination
|
||||
Uplifting [] best 90 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Test a procedure with calling convention PHI - case #4
|
||||
// Upstart
|
||||
.file [name="call-banked-phi-case-4-near-0.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_cx16_ram_phi_close_finalize
|
||||
plus_from_main:
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
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)
|
||||
plus: {
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// [5] call min
|
||||
// [7] phi from plus to min [phi:plus->min] -- call__phi_near_finalize
|
||||
min_from_plus:
|
||||
jsr min
|
||||
jmp __breturn
|
||||
// plus::@return
|
||||
__breturn:
|
||||
// [6] return
|
||||
rts
|
||||
}
|
||||
// min
|
||||
// char min(char a, char b)
|
||||
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(bank) 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(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
|
||||
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 51
|
||||
|
||||
// File Comments
|
||||
// Test a procedure with calling convention PHI - case #4
|
||||
// Upstart
|
||||
.file [name="call-banked-phi-case-4-near-0.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_cx16_ram_phi_close_finalize
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
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)
|
||||
plus: {
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// min(a, b)
|
||||
// [5] call min
|
||||
// [7] phi from plus to min [phi:plus->min] -- call__phi_near_finalize
|
||||
jsr min
|
||||
// plus::@return
|
||||
// }
|
||||
// [6] return
|
||||
rts
|
||||
}
|
||||
// min
|
||||
// char min(char a, char b)
|
||||
min: {
|
||||
.label return = plus.a+plus.b
|
||||
// min::@return
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
14
src/test/ref/call-banked-phi-case-4-near-0.sym
Normal file
14
src/test/ref/call-banked-phi-case-4-near-0.sym
Normal file
@ -0,0 +1,14 @@
|
||||
__constant char * const SCREEN = (char *) 1024
|
||||
void main()
|
||||
__bank(bank) 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(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
|
||||
|
46
src/test/ref/call-banked-phi-case-4-near-1.asm
Normal file
46
src/test/ref/call-banked-phi-case-4-near-1.asm
Normal file
@ -0,0 +1,46 @@
|
||||
// Test a procedure with calling convention PHI - case #4
|
||||
.file [name="call-banked-phi-case-4-near-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
|
||||
|
||||
|
||||
.label SCREEN = $400
|
||||
.segment Code
|
||||
main: {
|
||||
// plus('0', 7)
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
jsr plus
|
||||
pla
|
||||
sta.z 0
|
||||
// SCREEN[0] = plus('0', 7)
|
||||
lda #min.return
|
||||
sta SCREEN
|
||||
// }
|
||||
rts
|
||||
}
|
||||
.segment RAM_Bank1
|
||||
// char plus(char a, char b)
|
||||
plus: {
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// min(a, b)
|
||||
jsr min
|
||||
// }
|
||||
rts
|
||||
}
|
||||
// char min(char a, char b)
|
||||
min: {
|
||||
.label return = plus.a+plus.b
|
||||
rts
|
||||
}
|
29
src/test/ref/call-banked-phi-case-4-near-1.cfg
Normal file
29
src/test/ref/call-banked-phi-case-4-near-1.cfg
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
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(bank) 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(bank) 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
|
399
src/test/ref/call-banked-phi-case-4-near-1.log
Normal file
399
src/test/ref/call-banked-phi-case-4-near-1.log
Normal file
@ -0,0 +1,399 @@
|
||||
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(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 )
|
||||
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(bank) 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(bank) 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(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 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(bank) 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(bank) 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(bank) char min(char a , char b)
|
||||
char min::a
|
||||
char min::b
|
||||
char min::return
|
||||
__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 [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 90 combination
|
||||
Uplifting [plus] best 90 combination
|
||||
Uplifting [min] best 90 combination
|
||||
Uplifting [] best 90 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Test a procedure with calling convention PHI - case #4
|
||||
// Upstart
|
||||
.file [name="call-banked-phi-case-4-near-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_cx16_ram_phi_close_finalize
|
||||
plus_from_main:
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
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)
|
||||
plus: {
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// [5] call min
|
||||
// [7] phi from plus to min [phi:plus->min] -- call__phi_near_finalize
|
||||
min_from_plus:
|
||||
jsr min
|
||||
jmp __breturn
|
||||
// plus::@return
|
||||
__breturn:
|
||||
// [6] return
|
||||
rts
|
||||
}
|
||||
// min
|
||||
// char min(char a, char b)
|
||||
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(bank) 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(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
|
||||
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 51
|
||||
|
||||
// File Comments
|
||||
// Test a procedure with calling convention PHI - case #4
|
||||
// Upstart
|
||||
.file [name="call-banked-phi-case-4-near-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_cx16_ram_phi_close_finalize
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
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)
|
||||
plus: {
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// min(a, b)
|
||||
// [5] call min
|
||||
// [7] phi from plus to min [phi:plus->min] -- call__phi_near_finalize
|
||||
jsr min
|
||||
// plus::@return
|
||||
// }
|
||||
// [6] return
|
||||
rts
|
||||
}
|
||||
// min
|
||||
// char min(char a, char b)
|
||||
min: {
|
||||
.label return = plus.a+plus.b
|
||||
// min::@return
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
14
src/test/ref/call-banked-phi-case-4-near-1.sym
Normal file
14
src/test/ref/call-banked-phi-case-4-near-1.sym
Normal file
@ -0,0 +1,14 @@
|
||||
__constant char * const SCREEN = (char *) 1024
|
||||
void main()
|
||||
__bank(bank) 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(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
|
||||
|
50
src/test/ref/call-banked-phi-case-5-far-0.asm
Normal file
50
src/test/ref/call-banked-phi-case-5-far-0.asm
Normal file
@ -0,0 +1,50 @@
|
||||
// Test a procedure with calling convention PHI - case #4
|
||||
.file [name="call-banked-phi-case-5-far-0.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
|
||||
|
||||
|
||||
.label SCREEN = $400
|
||||
.segment Code
|
||||
main: {
|
||||
// plus('0', 7)
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
jsr plus
|
||||
pla
|
||||
sta.z 0
|
||||
// SCREEN[0] = plus('0', 7)
|
||||
lda #min.return
|
||||
sta SCREEN
|
||||
// }
|
||||
rts
|
||||
}
|
||||
.segment RAM_Bank1
|
||||
// char plus(char a, char b)
|
||||
plus: {
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// min(a, b)
|
||||
jsr $ff6e
|
||||
.byte <min
|
||||
.byte >min
|
||||
.byte 2
|
||||
// }
|
||||
rts
|
||||
}
|
||||
.segment RAM_Bank2
|
||||
// char min(char a, char b)
|
||||
min: {
|
||||
.label return = plus.a+plus.b
|
||||
rts
|
||||
}
|
29
src/test/ref/call-banked-phi-case-5-far-0.cfg
Normal file
29
src/test/ref/call-banked-phi-case-5-far-0.cfg
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
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(bank) 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(bank) 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
|
407
src/test/ref/call-banked-phi-case-5-far-0.log
Normal file
407
src/test/ref/call-banked-phi-case-5-far-0.log
Normal file
@ -0,0 +1,407 @@
|
||||
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(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 )
|
||||
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(bank) 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(bank) 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(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 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(bank) 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(bank) 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(bank) char min(char a , char b)
|
||||
char min::a
|
||||
char min::b
|
||||
char min::return
|
||||
__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 [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 90 combination
|
||||
Uplifting [plus] best 90 combination
|
||||
Uplifting [min] best 90 combination
|
||||
Uplifting [] best 90 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Test a procedure with calling convention PHI - case #4
|
||||
// Upstart
|
||||
.file [name="call-banked-phi-case-5-far-0.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_cx16_ram_phi_close_finalize
|
||||
plus_from_main:
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
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)
|
||||
plus: {
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// [5] call min
|
||||
// [7] phi from plus to min [phi:plus->min] -- call_cx16_ram_phi_far_finalize
|
||||
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)
|
||||
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(bank) 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(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
|
||||
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 51
|
||||
|
||||
// File Comments
|
||||
// Test a procedure with calling convention PHI - case #4
|
||||
// Upstart
|
||||
.file [name="call-banked-phi-case-5-far-0.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_cx16_ram_phi_close_finalize
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
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)
|
||||
plus: {
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// min(a, b)
|
||||
// [5] call min
|
||||
// [7] phi from plus to min [phi:plus->min] -- call_cx16_ram_phi_far_finalize
|
||||
jsr $ff6e
|
||||
.byte <min
|
||||
.byte >min
|
||||
.byte 2
|
||||
// plus::@return
|
||||
// }
|
||||
// [6] return
|
||||
rts
|
||||
}
|
||||
.segment RAM_Bank2
|
||||
// min
|
||||
// char min(char a, char b)
|
||||
min: {
|
||||
.label return = plus.a+plus.b
|
||||
// min::@return
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
14
src/test/ref/call-banked-phi-case-5-far-0.sym
Normal file
14
src/test/ref/call-banked-phi-case-5-far-0.sym
Normal file
@ -0,0 +1,14 @@
|
||||
__constant char * const SCREEN = (char *) 1024
|
||||
void main()
|
||||
__bank(bank) 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(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
|
||||
|
50
src/test/ref/call-banked-phi-case-5-far-1.asm
Normal file
50
src/test/ref/call-banked-phi-case-5-far-1.asm
Normal file
@ -0,0 +1,50 @@
|
||||
// Test a procedure with calling convention PHI - case #4
|
||||
.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
|
||||
|
||||
|
||||
.label SCREEN = $400
|
||||
.segment Code
|
||||
main: {
|
||||
// plus('0', 7)
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
jsr plus
|
||||
pla
|
||||
sta.z 0
|
||||
// SCREEN[0] = plus('0', 7)
|
||||
lda #min.return
|
||||
sta SCREEN
|
||||
// }
|
||||
rts
|
||||
}
|
||||
.segment RAM_Bank1
|
||||
// char plus(char a, char b)
|
||||
plus: {
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// min(a, b)
|
||||
jsr $ff6e
|
||||
.byte <min
|
||||
.byte >min
|
||||
.byte 2
|
||||
// }
|
||||
rts
|
||||
}
|
||||
.segment RAM_Bank2
|
||||
// char min(char a, char b)
|
||||
min: {
|
||||
.label return = plus.a+plus.b
|
||||
rts
|
||||
}
|
29
src/test/ref/call-banked-phi-case-5-far-1.cfg
Normal file
29
src/test/ref/call-banked-phi-case-5-far-1.cfg
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
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(bank) 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(bank) 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
|
407
src/test/ref/call-banked-phi-case-5-far-1.log
Normal file
407
src/test/ref/call-banked-phi-case-5-far-1.log
Normal file
@ -0,0 +1,407 @@
|
||||
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(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 )
|
||||
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(bank) 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(bank) 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(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 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(bank) 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(bank) 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(bank) char min(char a , char b)
|
||||
char min::a
|
||||
char min::b
|
||||
char min::return
|
||||
__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 [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 90 combination
|
||||
Uplifting [plus] best 90 combination
|
||||
Uplifting [min] best 90 combination
|
||||
Uplifting [] best 90 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Test a procedure with calling convention PHI - case #4
|
||||
// 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_cx16_ram_phi_close_finalize
|
||||
plus_from_main:
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
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)
|
||||
plus: {
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// [5] call min
|
||||
// [7] phi from plus to min [phi:plus->min] -- call_cx16_ram_phi_far_finalize
|
||||
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)
|
||||
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(bank) 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(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
|
||||
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 51
|
||||
|
||||
// File Comments
|
||||
// Test a procedure with calling convention PHI - case #4
|
||||
// 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_cx16_ram_phi_close_finalize
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
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)
|
||||
plus: {
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// min(a, b)
|
||||
// [5] call min
|
||||
// [7] phi from plus to min [phi:plus->min] -- call_cx16_ram_phi_far_finalize
|
||||
jsr $ff6e
|
||||
.byte <min
|
||||
.byte >min
|
||||
.byte 2
|
||||
// plus::@return
|
||||
// }
|
||||
// [6] return
|
||||
rts
|
||||
}
|
||||
.segment RAM_Bank2
|
||||
// min
|
||||
// char min(char a, char b)
|
||||
min: {
|
||||
.label return = plus.a+plus.b
|
||||
// min::@return
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
14
src/test/ref/call-banked-phi-case-5-far-1.sym
Normal file
14
src/test/ref/call-banked-phi-case-5-far-1.sym
Normal file
@ -0,0 +1,14 @@
|
||||
__constant char * const SCREEN = (char *) 1024
|
||||
void main()
|
||||
__bank(bank) 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(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
|
||||
|
52
src/test/ref/call-banked-phi-case-6-close-0.asm
Normal file
52
src/test/ref/call-banked-phi-case-6-close-0.asm
Normal file
@ -0,0 +1,52 @@
|
||||
// Test a procedure with calling convention PHI - case #6
|
||||
.file [name="call-banked-phi-case-6-close-0.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
|
||||
|
||||
|
||||
.label SCREEN = $400
|
||||
.segment Code
|
||||
main: {
|
||||
// plus('0', 7)
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
jsr plus
|
||||
pla
|
||||
sta.z 0
|
||||
// SCREEN[0] = plus('0', 7)
|
||||
lda #min.return
|
||||
sta SCREEN
|
||||
// }
|
||||
rts
|
||||
}
|
||||
.segment RAM_Bank1
|
||||
// char plus(char a, char b)
|
||||
plus: {
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// min(a, b)
|
||||
lda #1
|
||||
sta.z 1
|
||||
pha
|
||||
jsr min
|
||||
pla
|
||||
sta.z 1
|
||||
// }
|
||||
rts
|
||||
}
|
||||
.segment ROM_Bank1
|
||||
// char min(char a, char b)
|
||||
min: {
|
||||
.label return = plus.a+plus.b
|
||||
rts
|
||||
}
|
29
src/test/ref/call-banked-phi-case-6-close-0.cfg
Normal file
29
src/test/ref/call-banked-phi-case-6-close-0.cfg
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
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(bank) 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(bank) 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
|
412
src/test/ref/call-banked-phi-case-6-close-0.log
Normal file
412
src/test/ref/call-banked-phi-case-6-close-0.log
Normal file
@ -0,0 +1,412 @@
|
||||
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(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 )
|
||||
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(bank) 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(bank) 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(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 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(bank) 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(bank) 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(bank) char min(char a , char b)
|
||||
char min::a
|
||||
char min::b
|
||||
char min::return
|
||||
__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 [1] call plus [ ] ( [ ] { } ) always clobbers reg byte a
|
||||
Statement [2] *SCREEN = min::return#1 [ ] ( [ ] { } ) always clobbers reg byte a
|
||||
Statement [5] call min [ ] ( plus:1 [ ] { } ) always clobbers reg byte a
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main]
|
||||
Uplift Scope [plus]
|
||||
Uplift Scope [min]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 105 combination
|
||||
Uplifting [plus] best 105 combination
|
||||
Uplifting [min] best 105 combination
|
||||
Uplifting [] best 105 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Test a procedure with calling convention PHI - case #6
|
||||
// Upstart
|
||||
.file [name="call-banked-phi-case-6-close-0.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_cx16_ram_phi_close_finalize
|
||||
plus_from_main:
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
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)
|
||||
plus: {
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// [5] call min
|
||||
// [7] phi from plus to min [phi:plus->min] -- call_cx16_rom_phi_close_finalize
|
||||
min_from_plus:
|
||||
lda #1
|
||||
sta.z 1
|
||||
pha
|
||||
jsr min
|
||||
pla
|
||||
sta.z 1
|
||||
jmp __breturn
|
||||
// plus::@return
|
||||
__breturn:
|
||||
// [6] return
|
||||
rts
|
||||
}
|
||||
.segment ROM_Bank1
|
||||
// min
|
||||
// char min(char a, char b)
|
||||
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(bank) 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(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
|
||||
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 66
|
||||
|
||||
// File Comments
|
||||
// Test a procedure with calling convention PHI - case #6
|
||||
// Upstart
|
||||
.file [name="call-banked-phi-case-6-close-0.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_cx16_ram_phi_close_finalize
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
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)
|
||||
plus: {
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// min(a, b)
|
||||
// [5] call min
|
||||
// [7] phi from plus to min [phi:plus->min] -- call_cx16_rom_phi_close_finalize
|
||||
lda #1
|
||||
sta.z 1
|
||||
pha
|
||||
jsr min
|
||||
pla
|
||||
sta.z 1
|
||||
// plus::@return
|
||||
// }
|
||||
// [6] return
|
||||
rts
|
||||
}
|
||||
.segment ROM_Bank1
|
||||
// min
|
||||
// char min(char a, char b)
|
||||
min: {
|
||||
.label return = plus.a+plus.b
|
||||
// min::@return
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
14
src/test/ref/call-banked-phi-case-6-close-0.sym
Normal file
14
src/test/ref/call-banked-phi-case-6-close-0.sym
Normal file
@ -0,0 +1,14 @@
|
||||
__constant char * const SCREEN = (char *) 1024
|
||||
void main()
|
||||
__bank(bank) 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(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
|
||||
|
52
src/test/ref/call-banked-phi-case-6-close-1.asm
Normal file
52
src/test/ref/call-banked-phi-case-6-close-1.asm
Normal file
@ -0,0 +1,52 @@
|
||||
// Test a procedure with calling convention PHI - case #6
|
||||
.file [name="call-banked-phi-case-6-close-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
|
||||
|
||||
|
||||
.label SCREEN = $400
|
||||
.segment Code
|
||||
main: {
|
||||
// plus('0', 7)
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
jsr plus
|
||||
pla
|
||||
sta.z 0
|
||||
// SCREEN[0] = plus('0', 7)
|
||||
lda #min.return
|
||||
sta SCREEN
|
||||
// }
|
||||
rts
|
||||
}
|
||||
.segment RAM_Bank1
|
||||
// char plus(char a, char b)
|
||||
plus: {
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// min(a, b)
|
||||
lda #1
|
||||
sta.z 1
|
||||
pha
|
||||
jsr min
|
||||
pla
|
||||
sta.z 1
|
||||
// }
|
||||
rts
|
||||
}
|
||||
.segment ROM_Bank1
|
||||
// char min(char a, char b)
|
||||
min: {
|
||||
.label return = plus.a+plus.b
|
||||
rts
|
||||
}
|
29
src/test/ref/call-banked-phi-case-6-close-1.cfg
Normal file
29
src/test/ref/call-banked-phi-case-6-close-1.cfg
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
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(bank) 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(bank) 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
|
412
src/test/ref/call-banked-phi-case-6-close-1.log
Normal file
412
src/test/ref/call-banked-phi-case-6-close-1.log
Normal file
@ -0,0 +1,412 @@
|
||||
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(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 )
|
||||
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(bank) 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(bank) 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(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 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(bank) 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(bank) 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(bank) char min(char a , char b)
|
||||
char min::a
|
||||
char min::b
|
||||
char min::return
|
||||
__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 [1] call plus [ ] ( [ ] { } ) always clobbers reg byte a
|
||||
Statement [2] *SCREEN = min::return#1 [ ] ( [ ] { } ) always clobbers reg byte a
|
||||
Statement [5] call min [ ] ( plus:1 [ ] { } ) always clobbers reg byte a
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main]
|
||||
Uplift Scope [plus]
|
||||
Uplift Scope [min]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 105 combination
|
||||
Uplifting [plus] best 105 combination
|
||||
Uplifting [min] best 105 combination
|
||||
Uplifting [] best 105 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Test a procedure with calling convention PHI - case #6
|
||||
// Upstart
|
||||
.file [name="call-banked-phi-case-6-close-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_cx16_ram_phi_close_finalize
|
||||
plus_from_main:
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
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)
|
||||
plus: {
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// [5] call min
|
||||
// [7] phi from plus to min [phi:plus->min] -- call_cx16_rom_phi_close_finalize
|
||||
min_from_plus:
|
||||
lda #1
|
||||
sta.z 1
|
||||
pha
|
||||
jsr min
|
||||
pla
|
||||
sta.z 1
|
||||
jmp __breturn
|
||||
// plus::@return
|
||||
__breturn:
|
||||
// [6] return
|
||||
rts
|
||||
}
|
||||
.segment ROM_Bank1
|
||||
// min
|
||||
// char min(char a, char b)
|
||||
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(bank) 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(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
|
||||
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 66
|
||||
|
||||
// File Comments
|
||||
// Test a procedure with calling convention PHI - case #6
|
||||
// Upstart
|
||||
.file [name="call-banked-phi-case-6-close-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_cx16_ram_phi_close_finalize
|
||||
lda #1
|
||||
sta.z 0
|
||||
pha
|
||||
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)
|
||||
plus: {
|
||||
.label a = '0'
|
||||
.label b = 7
|
||||
// min(a, b)
|
||||
// [5] call min
|
||||
// [7] phi from plus to min [phi:plus->min] -- call_cx16_rom_phi_close_finalize
|
||||
lda #1
|
||||
sta.z 1
|
||||
pha
|
||||
jsr min
|
||||
pla
|
||||
sta.z 1
|
||||
// plus::@return
|
||||
// }
|
||||
// [6] return
|
||||
rts
|
||||
}
|
||||
.segment ROM_Bank1
|
||||
// min
|
||||
// char min(char a, char b)
|
||||
min: {
|
||||
.label return = plus.a+plus.b
|
||||
// min::@return
|
||||
// [8] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
|
14
src/test/ref/call-banked-phi-case-6-close-1.sym
Normal file
14
src/test/ref/call-banked-phi-case-6-close-1.sym
Normal file
@ -0,0 +1,14 @@
|
||||
__constant char * const SCREEN = (char *) 1024
|
||||
void main()
|
||||
__bank(bank) 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(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
|
||||
|
@ -1,28 +0,0 @@
|
||||
// Test a procedure with 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
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
// 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 $ff6e
|
||||
.byte <plus
|
||||
.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
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
// Test a far call procedure with a calling convention PHI into ROM
|
||||
.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 >plus
|
||||
.byte 1
|
||||
// SCREEN[0] = plus('0', 7)
|
||||
lda #plus.return
|
||||
sta SCREEN
|
||||
// }
|
||||
rts
|
||||
}
|
||||
// test rom bank
|
||||
// char plus(char a, char b)
|
||||
plus: {
|
||||
.const a = '0'
|
||||
.const b = 7
|
||||
.label return = a+b
|
||||
rts
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
// 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 $ff6e
|
||||
.byte <plus
|
||||
.byte >plus
|
||||
.byte 2
|
||||
// SCREEN[0] = plus('0', 7)
|
||||
lda #plus.return
|
||||
sta SCREEN
|
||||
// }
|
||||
rts
|
||||
}
|
||||
// Test rom fragment
|
||||
// char plus(char a, char b)
|
||||
plus: {
|
||||
.const a = '0'
|
||||
.const b = 7
|
||||
.label return = a+b
|
||||
rts
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
// 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 $ff6e
|
||||
.byte <plus
|
||||
.byte >plus
|
||||
.byte $14
|
||||
// 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
|
||||
}
|
@ -1,281 +0,0 @@
|
||||
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
|
||||
|
||||
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()
|
||||
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
|
||||
|
||||
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
|
||||
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] -- call_far_cx16_ram_finalize
|
||||
plus_from_main:
|
||||
jsr $ff6e
|
||||
.byte <plus
|
||||
.byte >plus
|
||||
.byte $14
|
||||
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
|
||||
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] -- call_far_cx16_ram_finalize
|
||||
jsr $ff6e
|
||||
.byte <plus
|
||||
.byte >plus
|
||||
.byte $14
|
||||
// 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
|
||||
|
@ -1,312 +0,0 @@
|
||||
// The linker specification of the different segments.
|
||||
.cpu _65c02
|
||||
.segmentdef Program [segments="Basic, Code, Data, Bank1, Bank2"]
|
||||
.segmentdef Basic [start=$0801]a
|
||||
.segmentdef Code [start=$80d]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segmentdef Bank1 [start=$A000, min=$A000, max=$BFFF, align=$100]
|
||||
.segmentdef Bank2 [start=$C000, min=$C000, max=$FFFF, align=$100]
|
||||
|
||||
|
||||
// The target computer platform is the Commander X16,
|
||||
// which implements banking in ram between 0xA0000 and 0xBFFF,
|
||||
// and in rom between 0xC000 and 0xFFFF.
|
||||
.label SCREEN = $400
|
||||
.segment Code
|
||||
// Practically this means that the main() function is placed in main memory ...
|
||||
main: {
|
||||
// func_ram_bank1_a('0', 7)
|
||||
lda #7
|
||||
ldx #'0'
|
||||
jsr $ff6e
|
||||
.byte <func_ram_bank1_a
|
||||
.byte >func_ram_bank1_a
|
||||
.byte 1
|
||||
// func_ram_bank1_a('0', 7)
|
||||
// SCREEN[0] = func_ram_bank1_a('0', 7)
|
||||
sta SCREEN
|
||||
// func_ram_bank1_b('0', 7)
|
||||
jsr func_ram_bank1_b
|
||||
// SCREEN[0] = func_ram_bank1_b('0', 7)
|
||||
// Banked call to ram in bank 1 from main memory.
|
||||
lda #func_ram_bank1_b.return
|
||||
sta SCREEN
|
||||
// func_ram_bank1_c('0', 7)
|
||||
jsr $ff6e
|
||||
.byte <func_ram_bank1_c
|
||||
.byte >func_ram_bank1_c
|
||||
.byte 1
|
||||
// func_ram_bank1_c('0', 7)
|
||||
// SCREEN[0] = func_ram_bank1_c('0', 7)
|
||||
// Banked call to ram in bank 1 from main memory.
|
||||
sta SCREEN
|
||||
// func_ram_bank1_d('0', 7)
|
||||
jsr $ff6e
|
||||
.byte <func_ram_bank1_d
|
||||
.byte >func_ram_bank1_d
|
||||
.byte 1
|
||||
// func_ram_bank1_d('0', 7)
|
||||
// SCREEN[0] = func_ram_bank1_d('0', 7)
|
||||
// Banked call to ram in bank 1 from main memory.
|
||||
sta SCREEN
|
||||
// func_ram_bank1_e('0', 7)
|
||||
ldx #7
|
||||
lda #'0'
|
||||
jsr $ff6e
|
||||
.byte <func_ram_bank1_e
|
||||
.byte >func_ram_bank1_e
|
||||
.byte 1
|
||||
// func_ram_bank1_e('0', 7)
|
||||
// SCREEN[0] = func_ram_bank1_e('0', 7)
|
||||
// Banked call to ram in bank 1 from main memory.
|
||||
sta SCREEN
|
||||
// func_ram_bank1_f('0', 7)
|
||||
jsr $ff6e
|
||||
.byte <func_ram_bank1_f
|
||||
.byte >func_ram_bank1_f
|
||||
.byte 1
|
||||
// func_ram_bank1_f('0', 7)
|
||||
// SCREEN[0] = func_ram_bank1_f('0', 7)
|
||||
// Banked call to ram in bank 1 from main memory.
|
||||
sta SCREEN
|
||||
// func_rom_bank2_a('0', 7)
|
||||
lda #7
|
||||
ldx #'0'
|
||||
jsr $ff6e
|
||||
.byte <func_rom_bank2_a
|
||||
.byte >func_rom_bank2_a
|
||||
.byte 2
|
||||
// func_rom_bank2_a('0', 7)
|
||||
// SCREEN[0] = func_rom_bank2_a('0', 7)
|
||||
// Banked call to ram in bank 1 from main memory.
|
||||
sta SCREEN
|
||||
// func_rom_bank2_b('0', 7)
|
||||
ldx #7
|
||||
lda #'0'
|
||||
jsr func_rom_bank2_b
|
||||
// func_rom_bank2_b('0', 7)
|
||||
// SCREEN[0] = func_rom_bank2_b('0', 7)
|
||||
// Banked call to rom in bank 2 from main memory.
|
||||
sta SCREEN
|
||||
// func_rom_bank2_c('0', 7)
|
||||
jsr $ff6e
|
||||
.byte <func_rom_bank2_c
|
||||
.byte >func_rom_bank2_c
|
||||
.byte 2
|
||||
// func_rom_bank2_c('0', 7)
|
||||
// SCREEN[0] = func_rom_bank2_c('0', 7)
|
||||
// Banked call to rom in bank 2 from main memory.
|
||||
sta SCREEN
|
||||
// func_rom_bank2_d('0', 7)
|
||||
jsr $ff6e
|
||||
.byte <func_rom_bank2_d
|
||||
.byte >func_rom_bank2_d
|
||||
.byte 2
|
||||
// func_rom_bank2_d('0', 7)
|
||||
// SCREEN[0] = func_rom_bank2_d('0', 7)
|
||||
// Banked call to rom in bank 2 from main memory.
|
||||
sta SCREEN
|
||||
// func_rom_bank2_e('0', 7)
|
||||
ldx #7
|
||||
lda #'0'
|
||||
jsr $ff6e
|
||||
.byte <func_rom_bank2_e
|
||||
.byte >func_rom_bank2_e
|
||||
.byte 2
|
||||
// func_rom_bank2_e('0', 7)
|
||||
// SCREEN[0] = func_rom_bank2_e('0', 7)
|
||||
// Banked call to rom in bank 2 from main memory.
|
||||
sta SCREEN
|
||||
// func_rom_bank2_f('0', 7)
|
||||
jsr $ff6e
|
||||
.byte <func_rom_bank2_f
|
||||
.byte >func_rom_bank2_f
|
||||
.byte 2
|
||||
// func_rom_bank2_f('0', 7)
|
||||
// SCREEN[0] = func_rom_bank2_f('0', 7)
|
||||
// banked call to rom in bank 2 from main memory.
|
||||
sta SCREEN
|
||||
// func_main_a('0', 7)
|
||||
ldx #7
|
||||
lda #'0'
|
||||
jsr func_main_a
|
||||
// func_main_a('0', 7)
|
||||
// SCREEN[0] = func_main_a('0', 7)
|
||||
// banked call to rom in bank 2 from main memory.
|
||||
sta SCREEN
|
||||
// func_main_b('0', 7)
|
||||
jsr func_main_b
|
||||
// func_main_b('0', 7)
|
||||
// SCREEN[0] = func_main_b('0', 7)
|
||||
// Near call in main memory from main memory.
|
||||
sta SCREEN
|
||||
// }
|
||||
rts
|
||||
}
|
||||
.segment Bank1
|
||||
// Functional code
|
||||
// __register(A) char func_ram_bank1_a(__register(X) char a, __register(A) char b)
|
||||
func_ram_bank1_a: {
|
||||
// a + b
|
||||
stx.z $ff
|
||||
clc
|
||||
adc.z $ff
|
||||
// }
|
||||
rts
|
||||
}
|
||||
.segment Bank2
|
||||
// The sequent functions will consider no banking calculations anymore.
|
||||
// The __bank directive declares this function to be banked using call method ram in bank number 1 of banked ram.
|
||||
// char func_ram_bank1_b(char a, char b)
|
||||
func_ram_bank1_b: {
|
||||
.const a = '0'
|
||||
.const b = 7
|
||||
.label return = a+b
|
||||
rts
|
||||
}
|
||||
.segment Bank1
|
||||
// __register(A) char func_ram_bank1_c(char a, char b)
|
||||
func_ram_bank1_c: {
|
||||
.const a = '0'
|
||||
.const b = 7
|
||||
// func_ram_bank1_a(a, b)
|
||||
lda #b
|
||||
ldx #a
|
||||
jsr func_ram_bank1_a
|
||||
// func_ram_bank1_a(a, b)
|
||||
// }
|
||||
rts
|
||||
}
|
||||
// __register(A) char func_ram_bank1_d(char a, char b)
|
||||
func_ram_bank1_d: {
|
||||
.const a = '0'
|
||||
.const b = 7
|
||||
// func_rom_bank2_a(a, b)
|
||||
lda #b
|
||||
ldx #a
|
||||
jsr $ff6e
|
||||
.byte <func_rom_bank2_a
|
||||
.byte >func_rom_bank2_a
|
||||
.byte 2
|
||||
// func_rom_bank2_a(a, b)
|
||||
// }
|
||||
rts
|
||||
}
|
||||
// __register(A) char func_ram_bank1_e(__register(A) char a, __register(X) char b)
|
||||
func_ram_bank1_e: {
|
||||
// func_rom_bank2_b(a, b)
|
||||
jsr func_rom_bank2_b
|
||||
// func_rom_bank2_b(a, b)
|
||||
// }
|
||||
rts
|
||||
}
|
||||
// __register(A) char func_ram_bank1_f(char a, char b)
|
||||
func_ram_bank1_f: {
|
||||
.const a = '0'
|
||||
.const b = 7
|
||||
// func_main_a(a, b)
|
||||
ldx #b
|
||||
lda #a
|
||||
jsr func_main_a
|
||||
// func_main_a(a, b)
|
||||
// }
|
||||
rts
|
||||
}
|
||||
.segment Bank2
|
||||
// The sequent functions will be banked using call method rom in bank number 2.
|
||||
// __register(A) char func_rom_bank2_a(__register(X) char a, __register(A) char b)
|
||||
func_rom_bank2_a: {
|
||||
// a + b
|
||||
stx.z $ff
|
||||
clc
|
||||
adc.z $ff
|
||||
// }
|
||||
rts
|
||||
}
|
||||
// The __bank directive declares this function to be banked using call method rom in bank number 2 of banked rom.
|
||||
// __register(A) char func_rom_bank2_b(__register(A) char a, __register(X) char b)
|
||||
func_rom_bank2_b: {
|
||||
// a + b
|
||||
stx.z $ff
|
||||
clc
|
||||
adc.z $ff
|
||||
// }
|
||||
rts
|
||||
}
|
||||
// __register(A) char func_rom_bank2_c(char a, char b)
|
||||
func_rom_bank2_c: {
|
||||
.const a = '0'
|
||||
.const b = 7
|
||||
// func_ram_bank1_a(a, b)
|
||||
lda #b
|
||||
ldx #a
|
||||
jsr $ff6e
|
||||
.byte <func_ram_bank1_a
|
||||
.byte >func_ram_bank1_a
|
||||
.byte 1
|
||||
// func_ram_bank1_a(a, b)
|
||||
// }
|
||||
rts
|
||||
}
|
||||
// __register(A) char func_rom_bank2_d(char a, char b)
|
||||
func_rom_bank2_d: {
|
||||
.const a = '0'
|
||||
.const b = 7
|
||||
// func_rom_bank2_a(a, b)
|
||||
lda #b
|
||||
ldx #a
|
||||
jsr func_rom_bank2_a
|
||||
// func_rom_bank2_a(a, b)
|
||||
// }
|
||||
rts
|
||||
}
|
||||
// __register(A) char func_rom_bank2_e(__register(A) char a, __register(X) char b)
|
||||
func_rom_bank2_e: {
|
||||
// func_rom_bank2_b(a, b)
|
||||
jsr func_rom_bank2_b
|
||||
// func_rom_bank2_b(a, b)
|
||||
// }
|
||||
rts
|
||||
}
|
||||
// __register(A) char func_rom_bank2_f(char a, char b)
|
||||
func_rom_bank2_f: {
|
||||
.const a = '0'
|
||||
.const b = 7
|
||||
// func_main_a(a, b)
|
||||
ldx #b
|
||||
lda #a
|
||||
jsr func_main_a
|
||||
// func_main_a(a, b)
|
||||
// }
|
||||
rts
|
||||
}
|
||||
.segment Code
|
||||
// The sequent functions will be addressed in the default main memory location (segment Code).
|
||||
// Allocated in main memory.
|
||||
// __register(A) char func_main_a(__register(A) char a, __register(X) char b)
|
||||
func_main_a: {
|
||||
// func_ram_bank1_e(a, b)
|
||||
jsr $ff6e
|
||||
.byte <func_ram_bank1_e
|
||||
.byte >func_ram_bank1_e
|
||||
.byte 1
|
||||
// func_ram_bank1_e(a, b)
|
||||
// }
|
||||
rts
|
||||
}
|
||||
// Allocated in main memory.
|
||||
// __register(A) char func_main_b(char a, char b)
|
||||
func_main_b: {
|
||||
.const a = '0'
|
||||
.const b = 7
|
||||
// func_rom_bank2_e(a, b)
|
||||
ldx #b
|
||||
lda #a
|
||||
jsr $ff6e
|
||||
.byte <func_rom_bank2_e
|
||||
.byte >func_rom_bank2_e
|
||||
.byte 2
|
||||
// func_rom_bank2_e(a, b)
|
||||
// }
|
||||
rts
|
||||
}
|
@ -1,267 +0,0 @@
|
||||
|
||||
void main()
|
||||
main: scope:[main] from
|
||||
[0] phi()
|
||||
[1] call func_ram_bank1_a
|
||||
[2] func_ram_bank1_a::return#4 = func_ram_bank1_a::return#0
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[3] main::$0 = func_ram_bank1_a::return#4
|
||||
[4] *SCREEN = main::$0
|
||||
[5] call func_ram_bank1_b
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1
|
||||
[6] *SCREEN = func_ram_bank1_b::return#0
|
||||
[7] call func_ram_bank1_c
|
||||
[8] func_ram_bank1_c::return#2 = func_ram_bank1_c::return#0
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2
|
||||
[9] main::$2 = func_ram_bank1_c::return#2
|
||||
[10] *SCREEN = main::$2
|
||||
[11] call func_ram_bank1_d
|
||||
[12] func_ram_bank1_d::return#2 = func_ram_bank1_d::return#0
|
||||
to:main::@4
|
||||
main::@4: scope:[main] from main::@3
|
||||
[13] main::$3 = func_ram_bank1_d::return#2
|
||||
[14] *SCREEN = main::$3
|
||||
[15] call func_ram_bank1_e
|
||||
[16] func_ram_bank1_e::return#3 = func_ram_bank1_e::return#0
|
||||
to:main::@5
|
||||
main::@5: scope:[main] from main::@4
|
||||
[17] main::$4 = func_ram_bank1_e::return#3
|
||||
[18] *SCREEN = main::$4
|
||||
[19] call func_ram_bank1_f
|
||||
[20] func_ram_bank1_f::return#2 = func_ram_bank1_f::return#0
|
||||
to:main::@6
|
||||
main::@6: scope:[main] from main::@5
|
||||
[21] main::$5 = func_ram_bank1_f::return#2
|
||||
[22] *SCREEN = main::$5
|
||||
[23] call func_rom_bank2_a
|
||||
[24] func_rom_bank2_a::return#4 = func_rom_bank2_a::return#1
|
||||
to:main::@7
|
||||
main::@7: scope:[main] from main::@6
|
||||
[25] main::$6 = func_rom_bank2_a::return#4
|
||||
[26] *SCREEN = main::$6
|
||||
[27] call func_rom_bank2_b
|
||||
[28] func_rom_bank2_b::return#4 = func_rom_bank2_b::return#1
|
||||
to:main::@8
|
||||
main::@8: scope:[main] from main::@7
|
||||
[29] main::$7 = func_rom_bank2_b::return#4
|
||||
[30] *SCREEN = main::$7
|
||||
[31] call func_rom_bank2_c
|
||||
[32] func_rom_bank2_c::return#2 = func_rom_bank2_c::return#0
|
||||
to:main::@9
|
||||
main::@9: scope:[main] from main::@8
|
||||
[33] main::$8 = func_rom_bank2_c::return#2
|
||||
[34] *SCREEN = main::$8
|
||||
[35] call func_rom_bank2_d
|
||||
[36] func_rom_bank2_d::return#2 = func_rom_bank2_d::return#0
|
||||
to:main::@10
|
||||
main::@10: scope:[main] from main::@9
|
||||
[37] main::$9 = func_rom_bank2_d::return#2
|
||||
[38] *SCREEN = main::$9
|
||||
[39] call func_rom_bank2_e
|
||||
[40] func_rom_bank2_e::return#3 = func_rom_bank2_e::return#0
|
||||
to:main::@11
|
||||
main::@11: scope:[main] from main::@10
|
||||
[41] main::$10 = func_rom_bank2_e::return#3
|
||||
[42] *SCREEN = main::$10
|
||||
[43] call func_rom_bank2_f
|
||||
[44] func_rom_bank2_f::return#2 = func_rom_bank2_f::return#0
|
||||
to:main::@12
|
||||
main::@12: scope:[main] from main::@11
|
||||
[45] main::$11 = func_rom_bank2_f::return#2
|
||||
[46] *SCREEN = main::$11
|
||||
[47] call func_main_a
|
||||
[48] func_main_a::return#4 = func_main_a::return#2
|
||||
to:main::@13
|
||||
main::@13: scope:[main] from main::@12
|
||||
[49] main::$12 = func_main_a::return#4
|
||||
[50] *SCREEN = main::$12
|
||||
[51] call func_main_b
|
||||
[52] func_main_b::return#2 = func_main_b::return#0
|
||||
to:main::@14
|
||||
main::@14: scope:[main] from main::@13
|
||||
[53] main::$13 = func_main_b::return#2
|
||||
[54] *SCREEN = main::$13
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@14
|
||||
[55] return
|
||||
to:@return
|
||||
|
||||
__bank(bank) char func_ram_bank1_a(char a , char b)
|
||||
func_ram_bank1_a: scope:[func_ram_bank1_a] from func_ram_bank1_c func_rom_bank2_c main
|
||||
[56] func_ram_bank1_a::b#3 = phi( func_ram_bank1_c/func_ram_bank1_c::b#0, func_rom_bank2_c/func_rom_bank2_c::b#0, main/7 )
|
||||
[56] func_ram_bank1_a::a#3 = phi( func_ram_bank1_c/func_ram_bank1_c::a#0, func_rom_bank2_c/func_rom_bank2_c::a#0, main/'0' )
|
||||
[57] func_ram_bank1_a::return#0 = func_ram_bank1_a::a#3 + func_ram_bank1_a::b#3
|
||||
to:func_ram_bank1_a::@return
|
||||
func_ram_bank1_a::@return: scope:[func_ram_bank1_a] from func_ram_bank1_a
|
||||
[58] return
|
||||
to:@return
|
||||
|
||||
char func_ram_bank1_b(char a , char b)
|
||||
func_ram_bank1_b: scope:[func_ram_bank1_b] from main::@1
|
||||
[59] phi()
|
||||
to:func_ram_bank1_b::@return
|
||||
func_ram_bank1_b::@return: scope:[func_ram_bank1_b] from func_ram_bank1_b
|
||||
[60] return
|
||||
to:@return
|
||||
|
||||
__bank(bank) char func_ram_bank1_c(char a , char b)
|
||||
func_ram_bank1_c: scope:[func_ram_bank1_c] from main::@2
|
||||
[61] phi()
|
||||
[62] call func_ram_bank1_a
|
||||
[63] func_ram_bank1_a::return#2 = func_ram_bank1_a::return#0
|
||||
to:func_ram_bank1_c::@1
|
||||
func_ram_bank1_c::@1: scope:[func_ram_bank1_c] from func_ram_bank1_c
|
||||
[64] func_ram_bank1_c::return#0 = func_ram_bank1_a::return#2
|
||||
to:func_ram_bank1_c::@return
|
||||
func_ram_bank1_c::@return: scope:[func_ram_bank1_c] from func_ram_bank1_c::@1
|
||||
[65] return
|
||||
to:@return
|
||||
|
||||
__bank(bank) char func_ram_bank1_d(char a , char b)
|
||||
func_ram_bank1_d: scope:[func_ram_bank1_d] from main::@3
|
||||
[66] phi()
|
||||
[67] call func_rom_bank2_a
|
||||
[68] func_rom_bank2_a::return#0 = func_rom_bank2_a::return#1
|
||||
to:func_ram_bank1_d::@1
|
||||
func_ram_bank1_d::@1: scope:[func_ram_bank1_d] from func_ram_bank1_d
|
||||
[69] func_ram_bank1_d::return#0 = func_rom_bank2_a::return#0
|
||||
to:func_ram_bank1_d::@return
|
||||
func_ram_bank1_d::@return: scope:[func_ram_bank1_d] from func_ram_bank1_d::@1
|
||||
[70] return
|
||||
to:@return
|
||||
|
||||
__bank(bank) char func_ram_bank1_e(char a , char b)
|
||||
func_ram_bank1_e: scope:[func_ram_bank1_e] from func_main_a main::@4
|
||||
[71] func_ram_bank1_e::b#2 = phi( func_main_a/func_ram_bank1_e::b#0, main::@4/7 )
|
||||
[71] func_ram_bank1_e::a#2 = phi( func_main_a/func_ram_bank1_e::a#0, main::@4/'0' )
|
||||
[72] func_rom_bank2_b::a#0 = func_ram_bank1_e::a#2
|
||||
[73] func_rom_bank2_b::b#0 = func_ram_bank1_e::b#2
|
||||
[74] call func_rom_bank2_b
|
||||
[75] func_rom_bank2_b::return#0 = func_rom_bank2_b::return#1
|
||||
to:func_ram_bank1_e::@1
|
||||
func_ram_bank1_e::@1: scope:[func_ram_bank1_e] from func_ram_bank1_e
|
||||
[76] func_ram_bank1_e::return#0 = func_rom_bank2_b::return#0
|
||||
to:func_ram_bank1_e::@return
|
||||
func_ram_bank1_e::@return: scope:[func_ram_bank1_e] from func_ram_bank1_e::@1
|
||||
[77] return
|
||||
to:@return
|
||||
|
||||
__bank(bank) char func_ram_bank1_f(char a , char b)
|
||||
func_ram_bank1_f: scope:[func_ram_bank1_f] from main::@5
|
||||
[78] phi()
|
||||
[79] call func_main_a
|
||||
[80] func_main_a::return#0 = func_main_a::return#2
|
||||
to:func_ram_bank1_f::@1
|
||||
func_ram_bank1_f::@1: scope:[func_ram_bank1_f] from func_ram_bank1_f
|
||||
[81] func_ram_bank1_f::return#0 = func_main_a::return#0
|
||||
to:func_ram_bank1_f::@return
|
||||
func_ram_bank1_f::@return: scope:[func_ram_bank1_f] from func_ram_bank1_f::@1
|
||||
[82] return
|
||||
to:@return
|
||||
|
||||
__bank(bank) char func_rom_bank2_a(char a , char b)
|
||||
func_rom_bank2_a: scope:[func_rom_bank2_a] from func_ram_bank1_d func_rom_bank2_d main::@6
|
||||
[83] func_rom_bank2_a::b#3 = phi( func_ram_bank1_d/func_ram_bank1_d::b#0, func_rom_bank2_d/func_rom_bank2_d::b#0, main::@6/7 )
|
||||
[83] func_rom_bank2_a::a#3 = phi( func_ram_bank1_d/func_ram_bank1_d::a#0, func_rom_bank2_d/func_rom_bank2_d::a#0, main::@6/'0' )
|
||||
[84] func_rom_bank2_a::return#1 = func_rom_bank2_a::a#3 + func_rom_bank2_a::b#3
|
||||
to:func_rom_bank2_a::@return
|
||||
func_rom_bank2_a::@return: scope:[func_rom_bank2_a] from func_rom_bank2_a
|
||||
[85] return
|
||||
to:@return
|
||||
|
||||
char func_rom_bank2_b(char a , char b)
|
||||
func_rom_bank2_b: scope:[func_rom_bank2_b] from func_ram_bank1_e func_rom_bank2_e main::@7
|
||||
[86] func_rom_bank2_b::b#3 = phi( func_ram_bank1_e/func_rom_bank2_b::b#0, func_rom_bank2_e/func_rom_bank2_b::b#1, main::@7/7 )
|
||||
[86] func_rom_bank2_b::a#3 = phi( func_ram_bank1_e/func_rom_bank2_b::a#0, func_rom_bank2_e/func_rom_bank2_b::a#1, main::@7/'0' )
|
||||
[87] func_rom_bank2_b::return#1 = func_rom_bank2_b::a#3 + func_rom_bank2_b::b#3
|
||||
to:func_rom_bank2_b::@return
|
||||
func_rom_bank2_b::@return: scope:[func_rom_bank2_b] from func_rom_bank2_b
|
||||
[88] return
|
||||
to:@return
|
||||
|
||||
__bank(bank) char func_rom_bank2_c(char a , char b)
|
||||
func_rom_bank2_c: scope:[func_rom_bank2_c] from main::@8
|
||||
[89] phi()
|
||||
[90] call func_ram_bank1_a
|
||||
[91] func_ram_bank1_a::return#3 = func_ram_bank1_a::return#0
|
||||
to:func_rom_bank2_c::@1
|
||||
func_rom_bank2_c::@1: scope:[func_rom_bank2_c] from func_rom_bank2_c
|
||||
[92] func_rom_bank2_c::return#0 = func_ram_bank1_a::return#3
|
||||
to:func_rom_bank2_c::@return
|
||||
func_rom_bank2_c::@return: scope:[func_rom_bank2_c] from func_rom_bank2_c::@1
|
||||
[93] return
|
||||
to:@return
|
||||
|
||||
__bank(bank) char func_rom_bank2_d(char a , char b)
|
||||
func_rom_bank2_d: scope:[func_rom_bank2_d] from main::@9
|
||||
[94] phi()
|
||||
[95] call func_rom_bank2_a
|
||||
[96] func_rom_bank2_a::return#3 = func_rom_bank2_a::return#1
|
||||
to:func_rom_bank2_d::@1
|
||||
func_rom_bank2_d::@1: scope:[func_rom_bank2_d] from func_rom_bank2_d
|
||||
[97] func_rom_bank2_d::return#0 = func_rom_bank2_a::return#3
|
||||
to:func_rom_bank2_d::@return
|
||||
func_rom_bank2_d::@return: scope:[func_rom_bank2_d] from func_rom_bank2_d::@1
|
||||
[98] return
|
||||
to:@return
|
||||
|
||||
__bank(bank) char func_rom_bank2_e(char a , char b)
|
||||
func_rom_bank2_e: scope:[func_rom_bank2_e] from func_main_b main::@10
|
||||
[99] func_rom_bank2_e::b#2 = phi( func_main_b/func_main_b::b#0, main::@10/7 )
|
||||
[99] func_rom_bank2_e::a#2 = phi( func_main_b/func_main_b::a#0, main::@10/'0' )
|
||||
[100] func_rom_bank2_b::a#1 = func_rom_bank2_e::a#2
|
||||
[101] func_rom_bank2_b::b#1 = func_rom_bank2_e::b#2
|
||||
[102] call func_rom_bank2_b
|
||||
[103] func_rom_bank2_b::return#3 = func_rom_bank2_b::return#1
|
||||
to:func_rom_bank2_e::@1
|
||||
func_rom_bank2_e::@1: scope:[func_rom_bank2_e] from func_rom_bank2_e
|
||||
[104] func_rom_bank2_e::return#0 = func_rom_bank2_b::return#3
|
||||
to:func_rom_bank2_e::@return
|
||||
func_rom_bank2_e::@return: scope:[func_rom_bank2_e] from func_rom_bank2_e::@1
|
||||
[105] return
|
||||
to:@return
|
||||
|
||||
__bank(bank) char func_rom_bank2_f(char a , char b)
|
||||
func_rom_bank2_f: scope:[func_rom_bank2_f] from main::@11
|
||||
[106] phi()
|
||||
[107] call func_main_a
|
||||
[108] func_main_a::return#1 = func_main_a::return#2
|
||||
to:func_rom_bank2_f::@1
|
||||
func_rom_bank2_f::@1: scope:[func_rom_bank2_f] from func_rom_bank2_f
|
||||
[109] func_rom_bank2_f::return#0 = func_main_a::return#1
|
||||
to:func_rom_bank2_f::@return
|
||||
func_rom_bank2_f::@return: scope:[func_rom_bank2_f] from func_rom_bank2_f::@1
|
||||
[110] return
|
||||
to:@return
|
||||
|
||||
char func_main_a(char a , char b)
|
||||
func_main_a: scope:[func_main_a] from func_ram_bank1_f func_rom_bank2_f main::@12
|
||||
[111] func_main_a::b#3 = phi( func_ram_bank1_f/func_ram_bank1_f::b#0, func_rom_bank2_f/func_rom_bank2_f::b#0, main::@12/7 )
|
||||
[111] func_main_a::a#3 = phi( func_ram_bank1_f/func_ram_bank1_f::a#0, func_rom_bank2_f/func_rom_bank2_f::a#0, main::@12/'0' )
|
||||
[112] func_ram_bank1_e::a#0 = func_main_a::a#3
|
||||
[113] func_ram_bank1_e::b#0 = func_main_a::b#3
|
||||
[114] call func_ram_bank1_e
|
||||
[115] func_ram_bank1_e::return#2 = func_ram_bank1_e::return#0
|
||||
to:func_main_a::@1
|
||||
func_main_a::@1: scope:[func_main_a] from func_main_a
|
||||
[116] func_main_a::return#2 = func_ram_bank1_e::return#2
|
||||
to:func_main_a::@return
|
||||
func_main_a::@return: scope:[func_main_a] from func_main_a::@1
|
||||
[117] return
|
||||
to:@return
|
||||
|
||||
char func_main_b(char a , char b)
|
||||
func_main_b: scope:[func_main_b] from main::@13
|
||||
[118] phi()
|
||||
[119] call func_rom_bank2_e
|
||||
[120] func_rom_bank2_e::return#2 = func_rom_bank2_e::return#0
|
||||
to:func_main_b::@1
|
||||
func_main_b::@1: scope:[func_main_b] from func_main_b
|
||||
[121] func_main_b::return#0 = func_rom_bank2_e::return#2
|
||||
to:func_main_b::@return
|
||||
func_main_b::@return: scope:[func_main_b] from func_main_b::@1
|
||||
[122] return
|
||||
to:@return
|
File diff suppressed because it is too large
Load Diff
@ -1,204 +0,0 @@
|
||||
__constant char * const SCREEN = (char *) 1024
|
||||
char func_main_a(char a , char b)
|
||||
char func_main_a::a
|
||||
char func_main_a::a#3 // reg byte a 101.0
|
||||
char func_main_a::b
|
||||
char func_main_a::b#3 // reg byte x 50.5
|
||||
char func_main_a::return
|
||||
char func_main_a::return#0 // reg byte a 22.0
|
||||
char func_main_a::return#1 // reg byte a 22.0
|
||||
char func_main_a::return#2 // reg byte a 25.0
|
||||
char func_main_a::return#4 // reg byte a 4.0
|
||||
char func_main_b(char a , char b)
|
||||
char func_main_b::a
|
||||
__constant char func_main_b::a#0 = '0' // a
|
||||
char func_main_b::b
|
||||
__constant char func_main_b::b#0 = 7 // b
|
||||
char func_main_b::return
|
||||
char func_main_b::return#0 // reg byte a 4.333333333333333
|
||||
char func_main_b::return#2 // reg byte a 4.0
|
||||
__bank(bank) char func_ram_bank1_a(char a , char b)
|
||||
char func_ram_bank1_a::a
|
||||
char func_ram_bank1_a::a#3 // reg byte x 101.0
|
||||
char func_ram_bank1_a::b
|
||||
char func_ram_bank1_a::b#3 // reg byte a 101.0
|
||||
char func_ram_bank1_a::return
|
||||
char func_ram_bank1_a::return#0 // reg byte a 24.999999999999996
|
||||
char func_ram_bank1_a::return#2 // reg byte a 22.0
|
||||
char func_ram_bank1_a::return#3 // reg byte a 22.0
|
||||
char func_ram_bank1_a::return#4 // reg byte a 4.0
|
||||
char func_ram_bank1_b(char a , char b)
|
||||
char func_ram_bank1_b::a
|
||||
__constant char func_ram_bank1_b::a#0 = '0' // a
|
||||
char func_ram_bank1_b::b
|
||||
__constant char func_ram_bank1_b::b#0 = 7 // b
|
||||
char func_ram_bank1_b::return
|
||||
__constant char func_ram_bank1_b::return#0 = func_ram_bank1_b::a#0+func_ram_bank1_b::b#0 // return
|
||||
__bank(bank) char func_ram_bank1_c(char a , char b)
|
||||
char func_ram_bank1_c::a
|
||||
__constant char func_ram_bank1_c::a#0 = '0' // a
|
||||
char func_ram_bank1_c::b
|
||||
__constant char func_ram_bank1_c::b#0 = 7 // b
|
||||
char func_ram_bank1_c::return
|
||||
char func_ram_bank1_c::return#0 // reg byte a 4.333333333333333
|
||||
char func_ram_bank1_c::return#2 // reg byte a 4.0
|
||||
__bank(bank) char func_ram_bank1_d(char a , char b)
|
||||
char func_ram_bank1_d::a
|
||||
__constant char func_ram_bank1_d::a#0 = '0' // a
|
||||
char func_ram_bank1_d::b
|
||||
__constant char func_ram_bank1_d::b#0 = 7 // b
|
||||
char func_ram_bank1_d::return
|
||||
char func_ram_bank1_d::return#0 // reg byte a 4.333333333333333
|
||||
char func_ram_bank1_d::return#2 // reg byte a 4.0
|
||||
__bank(bank) char func_ram_bank1_e(char a , char b)
|
||||
char func_ram_bank1_e::a
|
||||
char func_ram_bank1_e::a#0 // reg byte a 101.0
|
||||
char func_ram_bank1_e::a#2 // reg byte a 1102.0
|
||||
char func_ram_bank1_e::b
|
||||
char func_ram_bank1_e::b#0 // reg byte x 202.0
|
||||
char func_ram_bank1_e::b#2 // reg byte x 551.0
|
||||
char func_ram_bank1_e::return
|
||||
char func_ram_bank1_e::return#0 // reg byte a 276.0
|
||||
char func_ram_bank1_e::return#2 // reg byte a 202.0
|
||||
char func_ram_bank1_e::return#3 // reg byte a 4.0
|
||||
__bank(bank) char func_ram_bank1_f(char a , char b)
|
||||
char func_ram_bank1_f::a
|
||||
__constant char func_ram_bank1_f::a#0 = '0' // a
|
||||
char func_ram_bank1_f::b
|
||||
__constant char func_ram_bank1_f::b#0 = 7 // b
|
||||
char func_ram_bank1_f::return
|
||||
char func_ram_bank1_f::return#0 // reg byte a 4.333333333333333
|
||||
char func_ram_bank1_f::return#2 // reg byte a 4.0
|
||||
__bank(bank) char func_rom_bank2_a(char a , char b)
|
||||
char func_rom_bank2_a::a
|
||||
char func_rom_bank2_a::a#3 // reg byte x 101.0
|
||||
char func_rom_bank2_a::b
|
||||
char func_rom_bank2_a::b#3 // reg byte a 101.0
|
||||
char func_rom_bank2_a::return
|
||||
char func_rom_bank2_a::return#0 // reg byte a 22.0
|
||||
char func_rom_bank2_a::return#1 // reg byte a 25.0
|
||||
char func_rom_bank2_a::return#3 // reg byte a 22.0
|
||||
char func_rom_bank2_a::return#4 // reg byte a 4.0
|
||||
char func_rom_bank2_b(char a , char b)
|
||||
char func_rom_bank2_b::a
|
||||
char func_rom_bank2_b::a#0 // reg byte a 1001.0
|
||||
char func_rom_bank2_b::a#1 // reg byte a 101.0
|
||||
char func_rom_bank2_b::a#3 // reg byte a 11103.0
|
||||
char func_rom_bank2_b::b
|
||||
char func_rom_bank2_b::b#0 // reg byte x 2002.0
|
||||
char func_rom_bank2_b::b#1 // reg byte x 202.0
|
||||
char func_rom_bank2_b::b#3 // reg byte x 11103.0
|
||||
char func_rom_bank2_b::return
|
||||
char func_rom_bank2_b::return#0 // reg byte a 2002.0
|
||||
char func_rom_bank2_b::return#1 // reg byte a 2221.0
|
||||
char func_rom_bank2_b::return#3 // reg byte a 202.0
|
||||
char func_rom_bank2_b::return#4 // reg byte a 4.0
|
||||
__bank(bank) char func_rom_bank2_c(char a , char b)
|
||||
char func_rom_bank2_c::a
|
||||
__constant char func_rom_bank2_c::a#0 = '0' // a
|
||||
char func_rom_bank2_c::b
|
||||
__constant char func_rom_bank2_c::b#0 = 7 // b
|
||||
char func_rom_bank2_c::return
|
||||
char func_rom_bank2_c::return#0 // reg byte a 4.333333333333333
|
||||
char func_rom_bank2_c::return#2 // reg byte a 4.0
|
||||
__bank(bank) char func_rom_bank2_d(char a , char b)
|
||||
char func_rom_bank2_d::a
|
||||
__constant char func_rom_bank2_d::a#0 = '0' // a
|
||||
char func_rom_bank2_d::b
|
||||
__constant char func_rom_bank2_d::b#0 = 7 // b
|
||||
char func_rom_bank2_d::return
|
||||
char func_rom_bank2_d::return#0 // reg byte a 4.333333333333333
|
||||
char func_rom_bank2_d::return#2 // reg byte a 4.0
|
||||
__bank(bank) char func_rom_bank2_e(char a , char b)
|
||||
char func_rom_bank2_e::a
|
||||
char func_rom_bank2_e::a#2 // reg byte a 101.0
|
||||
char func_rom_bank2_e::b
|
||||
char func_rom_bank2_e::b#2 // reg byte x 50.5
|
||||
char func_rom_bank2_e::return
|
||||
char func_rom_bank2_e::return#0 // reg byte a 28.5
|
||||
char func_rom_bank2_e::return#2 // reg byte a 22.0
|
||||
char func_rom_bank2_e::return#3 // reg byte a 4.0
|
||||
__bank(bank) char func_rom_bank2_f(char a , char b)
|
||||
char func_rom_bank2_f::a
|
||||
__constant char func_rom_bank2_f::a#0 = '0' // a
|
||||
char func_rom_bank2_f::b
|
||||
__constant char func_rom_bank2_f::b#0 = 7 // b
|
||||
char func_rom_bank2_f::return
|
||||
char func_rom_bank2_f::return#0 // reg byte a 4.333333333333333
|
||||
char func_rom_bank2_f::return#2 // reg byte a 4.0
|
||||
void main()
|
||||
char main::$0 // reg byte a 4.0
|
||||
char main::$10 // reg byte a 4.0
|
||||
char main::$11 // reg byte a 4.0
|
||||
char main::$12 // reg byte a 4.0
|
||||
char main::$13 // 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_ram_bank1_a::a#3 ]
|
||||
reg byte a [ func_ram_bank1_a::b#3 ]
|
||||
reg byte a [ func_ram_bank1_e::a#2 func_ram_bank1_e::a#0 ]
|
||||
reg byte x [ func_ram_bank1_e::b#2 func_ram_bank1_e::b#0 ]
|
||||
reg byte x [ func_rom_bank2_a::a#3 ]
|
||||
reg byte a [ func_rom_bank2_a::b#3 ]
|
||||
reg byte a [ func_rom_bank2_b::a#3 func_rom_bank2_b::a#0 func_rom_bank2_b::a#1 ]
|
||||
reg byte x [ func_rom_bank2_b::b#3 func_rom_bank2_b::b#0 func_rom_bank2_b::b#1 ]
|
||||
reg byte a [ func_rom_bank2_e::a#2 ]
|
||||
reg byte x [ func_rom_bank2_e::b#2 ]
|
||||
reg byte a [ func_main_a::a#3 ]
|
||||
reg byte x [ func_main_a::b#3 ]
|
||||
reg byte a [ func_ram_bank1_a::return#4 ]
|
||||
reg byte a [ main::$0 ]
|
||||
reg byte a [ func_ram_bank1_c::return#2 ]
|
||||
reg byte a [ main::$2 ]
|
||||
reg byte a [ func_ram_bank1_d::return#2 ]
|
||||
reg byte a [ main::$3 ]
|
||||
reg byte a [ func_ram_bank1_e::return#3 ]
|
||||
reg byte a [ main::$4 ]
|
||||
reg byte a [ func_ram_bank1_f::return#2 ]
|
||||
reg byte a [ main::$5 ]
|
||||
reg byte a [ func_rom_bank2_a::return#4 ]
|
||||
reg byte a [ main::$6 ]
|
||||
reg byte a [ func_rom_bank2_b::return#4 ]
|
||||
reg byte a [ main::$7 ]
|
||||
reg byte a [ func_rom_bank2_c::return#2 ]
|
||||
reg byte a [ main::$8 ]
|
||||
reg byte a [ func_rom_bank2_d::return#2 ]
|
||||
reg byte a [ main::$9 ]
|
||||
reg byte a [ func_rom_bank2_e::return#3 ]
|
||||
reg byte a [ main::$10 ]
|
||||
reg byte a [ func_rom_bank2_f::return#2 ]
|
||||
reg byte a [ main::$11 ]
|
||||
reg byte a [ func_main_a::return#4 ]
|
||||
reg byte a [ main::$12 ]
|
||||
reg byte a [ func_main_b::return#2 ]
|
||||
reg byte a [ main::$13 ]
|
||||
reg byte a [ func_ram_bank1_a::return#0 ]
|
||||
reg byte a [ func_ram_bank1_a::return#2 ]
|
||||
reg byte a [ func_ram_bank1_c::return#0 ]
|
||||
reg byte a [ func_rom_bank2_a::return#0 ]
|
||||
reg byte a [ func_ram_bank1_d::return#0 ]
|
||||
reg byte a [ func_rom_bank2_b::return#0 ]
|
||||
reg byte a [ func_ram_bank1_e::return#0 ]
|
||||
reg byte a [ func_main_a::return#0 ]
|
||||
reg byte a [ func_ram_bank1_f::return#0 ]
|
||||
reg byte a [ func_rom_bank2_a::return#1 ]
|
||||
reg byte a [ func_rom_bank2_b::return#1 ]
|
||||
reg byte a [ func_ram_bank1_a::return#3 ]
|
||||
reg byte a [ func_rom_bank2_c::return#0 ]
|
||||
reg byte a [ func_rom_bank2_a::return#3 ]
|
||||
reg byte a [ func_rom_bank2_d::return#0 ]
|
||||
reg byte a [ func_rom_bank2_b::return#3 ]
|
||||
reg byte a [ func_rom_bank2_e::return#0 ]
|
||||
reg byte a [ func_main_a::return#1 ]
|
||||
reg byte a [ func_rom_bank2_f::return#0 ]
|
||||
reg byte a [ func_ram_bank1_e::return#2 ]
|
||||
reg byte a [ func_main_a::return#2 ]
|
||||
reg byte a [ func_rom_bank2_e::return#2 ]
|
||||
reg byte a [ func_main_b::return#0 ]
|
@ -1,45 +0,0 @@
|
||||
// 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
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
|
||||
__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
|
@ -1,350 +0,0 @@
|
||||
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
|
||||
|
@ -1,19 +0,0 @@
|
||||
__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 ]
|
@ -1,45 +0,0 @@
|
||||
// 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
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
|
||||
__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
|
@ -1,350 +0,0 @@
|
||||
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
|
||||
|
@ -1,19 +0,0 @@
|
||||
__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 ]
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user