mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-08-08 13:25:12 +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:
@@ -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="%O", type="prg", segments="Program"]
|
||||||
.file [name="BANK1.BIN", type="bin", segments="Bank1"]
|
|
||||||
.segmentdef Program [segments="Basic, Code, Data"]
|
.segmentdef Program [segments="Basic, Code, Data"]
|
||||||
.segmentdef Basic [start=$0801]
|
.segmentdef Basic [start=$0801]
|
||||||
.segmentdef Code [start=%P]
|
.segmentdef Code [start=%P]
|
||||||
.segmentdef Data [startAfter="Code"]
|
.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
|
.segment Basic
|
||||||
:BasicUpstart(%E)
|
:BasicUpstart(%E)
|
||||||
.segment Code
|
.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 <cx16.h>
|
||||||
#include <conio.h>
|
#include <conio.h>
|
||||||
#include <printf.h>
|
#include <printf.h>
|
||||||
#include <kernal.h>
|
#include <cx16-kernal.h>
|
||||||
|
|
||||||
#include "cx16-banking-1.h"
|
|
||||||
|
|
||||||
|
|
||||||
// The target computer platform is the Commander X16,
|
// The target computer platform is the Commander X16,
|
||||||
// which implements banking in ram between 0xA0000 and 0xBFFF,
|
// 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
|
CONTROL FLOW GRAPH SSA
|
||||||
|
|
||||||
@@ -157,24 +157,29 @@ Uplifting [] best 60 combination
|
|||||||
|
|
||||||
ASSEMBLER BEFORE OPTIMIZATION
|
ASSEMBLER BEFORE OPTIMIZATION
|
||||||
// File Comments
|
// File Comments
|
||||||
// Test a procedure with calling convention PHI
|
// Test a procedure with calling convention PHI - case #1
|
||||||
// Upstart
|
// Upstart
|
||||||
.cpu _65c02
|
.file [name="call-banked-phi-case-1-near-0.prg", type="prg", segments="Program"]
|
||||||
.segmentdef Program [segments="Basic, Code, Data, stage, platform"]
|
.segmentdef Program [segments="Basic, Code, Data"]
|
||||||
.segmentdef Basic [start=$0801]
|
.segmentdef Basic [start=$0801]
|
||||||
.segmentdef Code [start=$80d]
|
.segmentdef Code [start=$80d]
|
||||||
.segmentdef Data [startAfter="Code"]
|
.segmentdef Data [startAfter="Code"]
|
||||||
.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100]
|
.segmentdef RAM_Bank1 [start=$A000, min=$A000, max=$BFFF, align=$100]
|
||||||
.segmentdef platform [start=$C000, min=$C000, max=$C7FF, 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
|
// Global Constants & labels
|
||||||
.label SCREEN = $400
|
.label SCREEN = $400
|
||||||
.segment stage
|
.segment Code
|
||||||
// main
|
// main
|
||||||
main: {
|
main: {
|
||||||
// [1] call plus
|
// [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:
|
plus_from_main:
|
||||||
jsr plus
|
jsr plus
|
||||||
jmp __b1
|
jmp __b1
|
||||||
@@ -231,25 +236,30 @@ FINAL ASSEMBLER
|
|||||||
Score: 24
|
Score: 24
|
||||||
|
|
||||||
// File Comments
|
// File Comments
|
||||||
// Test a procedure with calling convention PHI
|
// Test a procedure with calling convention PHI - case #1
|
||||||
// Upstart
|
// Upstart
|
||||||
.cpu _65c02
|
.file [name="call-banked-phi-case-1-near-0.prg", type="prg", segments="Program"]
|
||||||
.segmentdef Program [segments="Basic, Code, Data, stage, platform"]
|
.segmentdef Program [segments="Basic, Code, Data"]
|
||||||
.segmentdef Basic [start=$0801]
|
.segmentdef Basic [start=$0801]
|
||||||
.segmentdef Code [start=$80d]
|
.segmentdef Code [start=$80d]
|
||||||
.segmentdef Data [startAfter="Code"]
|
.segmentdef Data [startAfter="Code"]
|
||||||
.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100]
|
.segmentdef RAM_Bank1 [start=$A000, min=$A000, max=$BFFF, align=$100]
|
||||||
.segmentdef platform [start=$C000, min=$C000, max=$C7FF, 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
|
// Global Constants & labels
|
||||||
.label SCREEN = $400
|
.label SCREEN = $400
|
||||||
.segment stage
|
.segment Code
|
||||||
// main
|
// main
|
||||||
main: {
|
main: {
|
||||||
// plus('0', 7)
|
// plus('0', 7)
|
||||||
// [1] call plus
|
// [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
|
jsr plus
|
||||||
// main::@1
|
// main::@1
|
||||||
// SCREEN[0] = plus('0', 7)
|
// 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
|
CONTROL FLOW GRAPH SSA
|
||||||
|
|
||||||
@@ -144,6 +144,7 @@ char plus::return
|
|||||||
Initial phi equivalence classes
|
Initial phi equivalence classes
|
||||||
Complete equivalence classes
|
Complete equivalence classes
|
||||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||||
|
Statement [1] call plus [ ] ( [ ] { } ) always clobbers reg byte a
|
||||||
Statement [2] *SCREEN = plus::return#1 [ ] ( [ ] { } ) always clobbers reg byte a
|
Statement [2] *SCREEN = plus::return#1 [ ] ( [ ] { } ) always clobbers reg byte a
|
||||||
|
|
||||||
REGISTER UPLIFT SCOPES
|
REGISTER UPLIFT SCOPES
|
||||||
@@ -151,35 +152,42 @@ Uplift Scope [main]
|
|||||||
Uplift Scope [plus]
|
Uplift Scope [plus]
|
||||||
Uplift Scope []
|
Uplift Scope []
|
||||||
|
|
||||||
Uplifting [main] best 60 combination
|
Uplifting [main] best 75 combination
|
||||||
Uplifting [plus] best 60 combination
|
Uplifting [plus] best 75 combination
|
||||||
Uplifting [] best 60 combination
|
Uplifting [] best 75 combination
|
||||||
|
|
||||||
ASSEMBLER BEFORE OPTIMIZATION
|
ASSEMBLER BEFORE OPTIMIZATION
|
||||||
// File Comments
|
// File Comments
|
||||||
// Test a far call procedure with a calling convention PHI into ROM
|
// Test a procedure with calling convention PHI - case #2
|
||||||
// Upstart
|
// Upstart
|
||||||
.cpu _65c02
|
.file [name="call-banked-phi-case-2-close-0.prg", type="prg", segments="Program"]
|
||||||
.segmentdef Program [segments="Basic, Code, Data, stage, platform"]
|
.segmentdef Program [segments="Basic, Code, Data"]
|
||||||
.segmentdef Basic [start=$0801]
|
.segmentdef Basic [start=$0801]
|
||||||
.segmentdef Code [start=$80d]
|
.segmentdef Code [start=$80d]
|
||||||
.segmentdef Data [startAfter="Code"]
|
.segmentdef Data [startAfter="Code"]
|
||||||
.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100]
|
.segmentdef RAM_Bank1 [start=$A000, min=$A000, max=$BFFF, align=$100]
|
||||||
.segmentdef platform [start=$C000, min=$C000, max=$C7FF, 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
|
// Global Constants & labels
|
||||||
.label SCREEN = $400
|
.label SCREEN = $400
|
||||||
.segment stage
|
.segment Code
|
||||||
// main
|
// main
|
||||||
main: {
|
main: {
|
||||||
// [1] call plus
|
// [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:
|
plus_from_main:
|
||||||
jsr $ff6e
|
lda #1
|
||||||
.byte <plus
|
sta.z 0
|
||||||
.byte >plus
|
pha
|
||||||
.byte 1
|
jsr plus
|
||||||
|
pla
|
||||||
|
sta.z 0
|
||||||
jmp __b1
|
jmp __b1
|
||||||
// main::@1
|
// main::@1
|
||||||
__b1:
|
__b1:
|
||||||
@@ -192,8 +200,8 @@ main: {
|
|||||||
// [3] return
|
// [3] return
|
||||||
rts
|
rts
|
||||||
}
|
}
|
||||||
|
.segment RAM_Bank1
|
||||||
// plus
|
// plus
|
||||||
// test rom bank
|
|
||||||
// char plus(char a, char b)
|
// char plus(char a, char b)
|
||||||
plus: {
|
plus: {
|
||||||
.const a = '0'
|
.const a = '0'
|
||||||
@@ -232,32 +240,39 @@ __constant char plus::return#1 = plus::a#0+plus::b#0 // return
|
|||||||
|
|
||||||
|
|
||||||
FINAL ASSEMBLER
|
FINAL ASSEMBLER
|
||||||
Score: 24
|
Score: 39
|
||||||
|
|
||||||
// File Comments
|
// File Comments
|
||||||
// Test a far call procedure with a calling convention PHI into ROM
|
// Test a procedure with calling convention PHI - case #2
|
||||||
// Upstart
|
// Upstart
|
||||||
.cpu _65c02
|
.file [name="call-banked-phi-case-2-close-0.prg", type="prg", segments="Program"]
|
||||||
.segmentdef Program [segments="Basic, Code, Data, stage, platform"]
|
.segmentdef Program [segments="Basic, Code, Data"]
|
||||||
.segmentdef Basic [start=$0801]
|
.segmentdef Basic [start=$0801]
|
||||||
.segmentdef Code [start=$80d]
|
.segmentdef Code [start=$80d]
|
||||||
.segmentdef Data [startAfter="Code"]
|
.segmentdef Data [startAfter="Code"]
|
||||||
.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100]
|
.segmentdef RAM_Bank1 [start=$A000, min=$A000, max=$BFFF, align=$100]
|
||||||
.segmentdef platform [start=$C000, min=$C000, max=$C7FF, 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
|
// Global Constants & labels
|
||||||
.label SCREEN = $400
|
.label SCREEN = $400
|
||||||
.segment stage
|
.segment Code
|
||||||
// main
|
// main
|
||||||
main: {
|
main: {
|
||||||
// plus('0', 7)
|
// plus('0', 7)
|
||||||
// [1] call plus
|
// [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
|
||||||
jsr $ff6e
|
lda #1
|
||||||
.byte <plus
|
sta.z 0
|
||||||
.byte >plus
|
pha
|
||||||
.byte 1
|
jsr plus
|
||||||
|
pla
|
||||||
|
sta.z 0
|
||||||
// main::@1
|
// main::@1
|
||||||
// SCREEN[0] = plus('0', 7)
|
// SCREEN[0] = plus('0', 7)
|
||||||
// [2] *SCREEN = plus::return#1 -- _deref_pbuc1=vbuc2
|
// [2] *SCREEN = plus::return#1 -- _deref_pbuc1=vbuc2
|
||||||
@@ -268,8 +283,8 @@ main: {
|
|||||||
// [3] return
|
// [3] return
|
||||||
rts
|
rts
|
||||||
}
|
}
|
||||||
|
.segment RAM_Bank1
|
||||||
// plus
|
// plus
|
||||||
// test rom bank
|
|
||||||
// char plus(char a, char b)
|
// char plus(char a, char b)
|
||||||
plus: {
|
plus: {
|
||||||
.const a = '0'
|
.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
|
CONTROL FLOW GRAPH SSA
|
||||||
|
|
||||||
@@ -144,6 +144,7 @@ char plus::return
|
|||||||
Initial phi equivalence classes
|
Initial phi equivalence classes
|
||||||
Complete equivalence classes
|
Complete equivalence classes
|
||||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||||
|
Statement [1] call plus [ ] ( [ ] { } ) always clobbers reg byte a
|
||||||
Statement [2] *SCREEN = plus::return#1 [ ] ( [ ] { } ) always clobbers reg byte a
|
Statement [2] *SCREEN = plus::return#1 [ ] ( [ ] { } ) always clobbers reg byte a
|
||||||
|
|
||||||
REGISTER UPLIFT SCOPES
|
REGISTER UPLIFT SCOPES
|
||||||
@@ -151,35 +152,42 @@ Uplift Scope [main]
|
|||||||
Uplift Scope [plus]
|
Uplift Scope [plus]
|
||||||
Uplift Scope []
|
Uplift Scope []
|
||||||
|
|
||||||
Uplifting [main] best 60 combination
|
Uplifting [main] best 75 combination
|
||||||
Uplifting [plus] best 60 combination
|
Uplifting [plus] best 75 combination
|
||||||
Uplifting [] best 60 combination
|
Uplifting [] best 75 combination
|
||||||
|
|
||||||
ASSEMBLER BEFORE OPTIMIZATION
|
ASSEMBLER BEFORE OPTIMIZATION
|
||||||
// File Comments
|
// File Comments
|
||||||
// Test a far call procedure with a calling convention PHI
|
// Test a procedure with calling convention PHI - case #2
|
||||||
// Upstart
|
// Upstart
|
||||||
.cpu _65c02
|
.file [name="call-banked-phi-case-2-close-1.prg", type="prg", segments="Program"]
|
||||||
.segmentdef Program [segments="Basic, Code, Data, stage, platform"]
|
.segmentdef Program [segments="Basic, Code, Data"]
|
||||||
.segmentdef Basic [start=$0801]
|
.segmentdef Basic [start=$0801]
|
||||||
.segmentdef Code [start=$80d]
|
.segmentdef Code [start=$80d]
|
||||||
.segmentdef Data [startAfter="Code"]
|
.segmentdef Data [startAfter="Code"]
|
||||||
.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100]
|
.segmentdef RAM_Bank1 [start=$A000, min=$A000, max=$BFFF, align=$100]
|
||||||
.segmentdef platform [start=$C000, min=$C000, max=$C7FF, 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
|
// Global Constants & labels
|
||||||
.label SCREEN = $400
|
.label SCREEN = $400
|
||||||
.segment stage
|
.segment Code
|
||||||
// main
|
// main
|
||||||
main: {
|
main: {
|
||||||
// [1] call plus
|
// [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:
|
plus_from_main:
|
||||||
jsr $ff6e
|
lda #1
|
||||||
.byte <plus
|
sta.z 0
|
||||||
.byte >plus
|
pha
|
||||||
.byte 2
|
jsr plus
|
||||||
|
pla
|
||||||
|
sta.z 0
|
||||||
jmp __b1
|
jmp __b1
|
||||||
// main::@1
|
// main::@1
|
||||||
__b1:
|
__b1:
|
||||||
@@ -192,8 +200,8 @@ main: {
|
|||||||
// [3] return
|
// [3] return
|
||||||
rts
|
rts
|
||||||
}
|
}
|
||||||
|
.segment RAM_Bank1
|
||||||
// plus
|
// plus
|
||||||
// Test rom fragment
|
|
||||||
// char plus(char a, char b)
|
// char plus(char a, char b)
|
||||||
plus: {
|
plus: {
|
||||||
.const a = '0'
|
.const a = '0'
|
||||||
@@ -232,32 +240,39 @@ __constant char plus::return#1 = plus::a#0+plus::b#0 // return
|
|||||||
|
|
||||||
|
|
||||||
FINAL ASSEMBLER
|
FINAL ASSEMBLER
|
||||||
Score: 24
|
Score: 39
|
||||||
|
|
||||||
// File Comments
|
// File Comments
|
||||||
// Test a far call procedure with a calling convention PHI
|
// Test a procedure with calling convention PHI - case #2
|
||||||
// Upstart
|
// Upstart
|
||||||
.cpu _65c02
|
.file [name="call-banked-phi-case-2-close-1.prg", type="prg", segments="Program"]
|
||||||
.segmentdef Program [segments="Basic, Code, Data, stage, platform"]
|
.segmentdef Program [segments="Basic, Code, Data"]
|
||||||
.segmentdef Basic [start=$0801]
|
.segmentdef Basic [start=$0801]
|
||||||
.segmentdef Code [start=$80d]
|
.segmentdef Code [start=$80d]
|
||||||
.segmentdef Data [startAfter="Code"]
|
.segmentdef Data [startAfter="Code"]
|
||||||
.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100]
|
.segmentdef RAM_Bank1 [start=$A000, min=$A000, max=$BFFF, align=$100]
|
||||||
.segmentdef platform [start=$C000, min=$C000, max=$C7FF, 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
|
// Global Constants & labels
|
||||||
.label SCREEN = $400
|
.label SCREEN = $400
|
||||||
.segment stage
|
.segment Code
|
||||||
// main
|
// main
|
||||||
main: {
|
main: {
|
||||||
// plus('0', 7)
|
// plus('0', 7)
|
||||||
// [1] call plus
|
// [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
|
||||||
jsr $ff6e
|
lda #1
|
||||||
.byte <plus
|
sta.z 0
|
||||||
.byte >plus
|
pha
|
||||||
.byte 2
|
jsr plus
|
||||||
|
pla
|
||||||
|
sta.z 0
|
||||||
// main::@1
|
// main::@1
|
||||||
// SCREEN[0] = plus('0', 7)
|
// SCREEN[0] = plus('0', 7)
|
||||||
// [2] *SCREEN = plus::return#1 -- _deref_pbuc1=vbuc2
|
// [2] *SCREEN = plus::return#1 -- _deref_pbuc1=vbuc2
|
||||||
@@ -268,8 +283,8 @@ main: {
|
|||||||
// [3] return
|
// [3] return
|
||||||
rts
|
rts
|
||||||
}
|
}
|
||||||
|
.segment RAM_Bank1
|
||||||
// plus
|
// plus
|
||||||
// Test rom fragment
|
|
||||||
// char plus(char a, char b)
|
// char plus(char a, char b)
|
||||||
plus: {
|
plus: {
|
||||||
.const a = '0'
|
.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
|
[1] call plus
|
||||||
to:main::@1
|
to:main::@1
|
||||||
main::@1: scope:[main] from main
|
main::@1: scope:[main] from main
|
||||||
[2] *SCREEN = plus::return#1
|
[2] *SCREEN = min::return#1
|
||||||
to:main::@return
|
to:main::@return
|
||||||
main::@return: scope:[main] from main::@1
|
main::@return: scope:[main] from main::@1
|
||||||
[3] return
|
[3] return
|
||||||
@@ -14,7 +14,16 @@ main::@return: scope:[main] from main::@1
|
|||||||
__bank(bank) char plus(char a , char b)
|
__bank(bank) char plus(char a , char b)
|
||||||
plus: scope:[plus] from main
|
plus: scope:[plus] from main
|
||||||
[4] phi()
|
[4] phi()
|
||||||
|
[5] call min
|
||||||
to:plus::@return
|
to:plus::@return
|
||||||
plus::@return: scope:[plus] from plus
|
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
|
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
|
CONTROL FLOW GRAPH SSA
|
||||||
|
|
||||||
@@ -22,15 +22,35 @@ __bank(bank) char plus(char a , char b)
|
|||||||
plus: scope:[plus] from main
|
plus: scope:[plus] from main
|
||||||
plus::b#1 = phi( main/plus::b#0 )
|
plus::b#1 = phi( main/plus::b#0 )
|
||||||
plus::a#1 = phi( main/plus::a#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
|
plus::return#1 = plus::$0
|
||||||
to:plus::@return
|
to:plus::@return
|
||||||
plus::@return: scope:[plus] from plus
|
plus::@return: scope:[plus] from plus::@1
|
||||||
plus::return#4 = phi( plus/plus::return#1 )
|
plus::return#4 = phi( plus::@1/plus::return#1 )
|
||||||
plus::return#2 = plus::return#4
|
plus::return#2 = plus::return#4
|
||||||
return
|
return
|
||||||
to:@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()
|
void __start()
|
||||||
__start: scope:[__start] from
|
__start: scope:[__start] from
|
||||||
call main
|
call main
|
||||||
@@ -46,6 +66,20 @@ __constant char * const SCREEN = (char *)$400
|
|||||||
void __start()
|
void __start()
|
||||||
void main()
|
void main()
|
||||||
char main::$0
|
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)
|
__bank(bank) char plus(char a , char b)
|
||||||
char plus::$0
|
char plus::$0
|
||||||
char plus::a
|
char plus::a
|
||||||
@@ -74,14 +108,21 @@ Finalized unsigned number type (char) 7
|
|||||||
Finalized unsigned number type (char) 0
|
Finalized unsigned number type (char) 0
|
||||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||||
Alias plus::return#0 = plus::return#3
|
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 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
|
Successful SSA optimization Pass2AliasElimination
|
||||||
Identical Phi Values plus::a#1 plus::a#0
|
Identical Phi Values plus::a#1 plus::a#0
|
||||||
Identical Phi Values plus::b#1 plus::b#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
|
Successful SSA optimization Pass2IdenticalPhiElimination
|
||||||
Constant plus::a#0 = '0'
|
Constant plus::a#0 = '0'
|
||||||
Constant plus::b#0 = 7
|
Constant plus::b#0 = 7
|
||||||
Successful SSA optimization Pass2ConstantIdentification
|
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
|
Simplifying expression containing zero SCREEN in [5] SCREEN[0] = main::$0
|
||||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||||
Removing unused procedure __start
|
Removing unused procedure __start
|
||||||
@@ -89,27 +130,40 @@ Removing unused procedure block __start
|
|||||||
Removing unused procedure block __start::@1
|
Removing unused procedure block __start::@1
|
||||||
Removing unused procedure block __start::@return
|
Removing unused procedure block __start::@return
|
||||||
Successful SSA optimization PassNEliminateEmptyStart
|
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
|
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
|
Successful SSA optimization Pass2ConstantIdentification
|
||||||
Constant plus::return#0 = plus::return#1
|
Constant plus::return#0 = plus::return#1
|
||||||
Successful SSA optimization Pass2ConstantIdentification
|
Successful SSA optimization Pass2ConstantIdentification
|
||||||
Constant main::$0 = plus::return#0
|
Constant main::$0 = plus::return#0
|
||||||
Successful SSA optimization Pass2ConstantIdentification
|
Successful SSA optimization Pass2ConstantIdentification
|
||||||
Inlining constant with different constant siblings plus::return#0
|
Inlining constant with different constant siblings min::return#0
|
||||||
Constant inlined plus::return#0 = plus::return#1
|
Constant inlined plus::return#0 = min::return#1
|
||||||
Constant inlined main::$0 = plus::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
|
Successful SSA optimization Pass2ConstantInlining
|
||||||
Adding NOP phi() at start of main
|
Adding NOP phi() at start of main
|
||||||
Adding NOP phi() at start of plus
|
Adding NOP phi() at start of plus
|
||||||
|
Adding NOP phi() at start of plus::@1
|
||||||
|
Adding NOP phi() at start of min
|
||||||
CALL GRAPH
|
CALL GRAPH
|
||||||
Calls in [main] to plus:1
|
Calls in [main] to plus:1
|
||||||
|
Calls in [plus] to min:5
|
||||||
|
|
||||||
Created 0 initial phi equivalence classes
|
Created 0 initial phi equivalence classes
|
||||||
Coalesced down to 0 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 main
|
||||||
Adding NOP phi() at start of plus
|
Adding NOP phi() at start of plus
|
||||||
|
Adding NOP phi() at start of min
|
||||||
|
|
||||||
FINAL CONTROL FLOW GRAPH
|
FINAL CONTROL FLOW GRAPH
|
||||||
|
|
||||||
@@ -119,7 +173,7 @@ main: scope:[main] from
|
|||||||
[1] call plus
|
[1] call plus
|
||||||
to:main::@1
|
to:main::@1
|
||||||
main::@1: scope:[main] from main
|
main::@1: scope:[main] from main
|
||||||
[2] *SCREEN = plus::return#1
|
[2] *SCREEN = min::return#1
|
||||||
to:main::@return
|
to:main::@return
|
||||||
main::@return: scope:[main] from main::@1
|
main::@return: scope:[main] from main::@1
|
||||||
[3] return
|
[3] return
|
||||||
@@ -128,14 +182,27 @@ main::@return: scope:[main] from main::@1
|
|||||||
__bank(bank) char plus(char a , char b)
|
__bank(bank) char plus(char a , char b)
|
||||||
plus: scope:[plus] from main
|
plus: scope:[plus] from main
|
||||||
[4] phi()
|
[4] phi()
|
||||||
|
[5] call min
|
||||||
to:plus::@return
|
to:plus::@return
|
||||||
plus::@return: scope:[plus] from plus
|
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
|
to:@return
|
||||||
|
|
||||||
|
|
||||||
VARIABLE REGISTER WEIGHTS
|
VARIABLE REGISTER WEIGHTS
|
||||||
void main()
|
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)
|
__bank(bank) char plus(char a , char b)
|
||||||
char plus::a
|
char plus::a
|
||||||
char plus::b
|
char plus::b
|
||||||
@@ -144,47 +211,57 @@ char plus::return
|
|||||||
Initial phi equivalence classes
|
Initial phi equivalence classes
|
||||||
Complete equivalence classes
|
Complete equivalence classes
|
||||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
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
|
REGISTER UPLIFT SCOPES
|
||||||
Uplift Scope [main]
|
Uplift Scope [main]
|
||||||
Uplift Scope [plus]
|
Uplift Scope [plus]
|
||||||
|
Uplift Scope [min]
|
||||||
Uplift Scope []
|
Uplift Scope []
|
||||||
|
|
||||||
Uplifting [main] best 60 combination
|
Uplifting [main] best 90 combination
|
||||||
Uplifting [plus] best 60 combination
|
Uplifting [plus] best 90 combination
|
||||||
Uplifting [] best 60 combination
|
Uplifting [min] best 90 combination
|
||||||
|
Uplifting [] best 90 combination
|
||||||
|
|
||||||
ASSEMBLER BEFORE OPTIMIZATION
|
ASSEMBLER BEFORE OPTIMIZATION
|
||||||
// File Comments
|
// File Comments
|
||||||
// Test a far call procedure with a calling convention PHI
|
// Test a procedure with calling convention PHI - case #3
|
||||||
// Upstart
|
// Upstart
|
||||||
.cpu _65c02
|
.file [name="call-banked-phi-case-3-near-0.prg", type="prg", segments="Program"]
|
||||||
.segmentdef Program [segments="Basic, Code, Data, stage, platform"]
|
.segmentdef Program [segments="Basic, Code, Data"]
|
||||||
.segmentdef Basic [start=$0801]
|
.segmentdef Basic [start=$0801]
|
||||||
.segmentdef Code [start=$80d]
|
.segmentdef Code [start=$80d]
|
||||||
.segmentdef Data [startAfter="Code"]
|
.segmentdef Data [startAfter="Code"]
|
||||||
.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100]
|
.segmentdef RAM_Bank1 [start=$A000, min=$A000, max=$BFFF, align=$100]
|
||||||
.segmentdef platform [start=$C000, min=$C000, max=$C7FF, 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
|
// Global Constants & labels
|
||||||
.label SCREEN = $400
|
.label SCREEN = $400
|
||||||
.segment stage
|
.segment Code
|
||||||
// main
|
// main
|
||||||
main: {
|
main: {
|
||||||
// [1] call plus
|
// [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:
|
plus_from_main:
|
||||||
jsr $ff6e
|
lda #1
|
||||||
.byte <plus
|
sta.z 0
|
||||||
.byte >plus
|
pha
|
||||||
.byte 1
|
jsr plus
|
||||||
|
pla
|
||||||
|
sta.z 0
|
||||||
jmp __b1
|
jmp __b1
|
||||||
// main::@1
|
// main::@1
|
||||||
__b1:
|
__b1:
|
||||||
// [2] *SCREEN = plus::return#1 -- _deref_pbuc1=vbuc2
|
// [2] *SCREEN = min::return#1 -- _deref_pbuc1=vbuc2
|
||||||
lda #plus.return
|
lda #min.return
|
||||||
sta SCREEN
|
sta SCREEN
|
||||||
jmp __breturn
|
jmp __breturn
|
||||||
// main::@return
|
// main::@return
|
||||||
@@ -192,16 +269,31 @@ main: {
|
|||||||
// [3] return
|
// [3] return
|
||||||
rts
|
rts
|
||||||
}
|
}
|
||||||
|
.segment RAM_Bank1
|
||||||
// plus
|
// plus
|
||||||
// char plus(char a, char b)
|
// char plus(char a, char b)
|
||||||
plus: {
|
plus: {
|
||||||
.const a = '0'
|
.label a = '0'
|
||||||
.const b = 7
|
.label b = 7
|
||||||
.label return = a+b
|
// [5] call min
|
||||||
|
// [7] phi from plus to min [phi:plus->min] -- call__phi_near_finalize
|
||||||
|
min_from_plus:
|
||||||
|
jsr min
|
||||||
jmp __breturn
|
jmp __breturn
|
||||||
// plus::@return
|
// plus::@return
|
||||||
__breturn:
|
__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
|
rts
|
||||||
}
|
}
|
||||||
// File Data
|
// File Data
|
||||||
@@ -210,71 +302,99 @@ ASSEMBLER OPTIMIZATIONS
|
|||||||
Removing instruction jmp __b1
|
Removing instruction jmp __b1
|
||||||
Removing instruction jmp __breturn
|
Removing instruction jmp __breturn
|
||||||
Removing instruction jmp __breturn
|
Removing instruction jmp __breturn
|
||||||
|
Removing instruction jmp __breturn
|
||||||
Succesful ASM optimization Pass5NextJumpElimination
|
Succesful ASM optimization Pass5NextJumpElimination
|
||||||
Removing instruction plus_from_main:
|
Removing instruction plus_from_main:
|
||||||
Removing instruction __b1:
|
Removing instruction __b1:
|
||||||
Removing instruction __breturn:
|
Removing instruction __breturn:
|
||||||
|
Removing instruction min_from_plus:
|
||||||
|
Removing instruction __breturn:
|
||||||
Removing instruction __breturn:
|
Removing instruction __breturn:
|
||||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||||
|
|
||||||
FINAL SYMBOL TABLE
|
FINAL SYMBOL TABLE
|
||||||
__constant char * const SCREEN = (char *) 1024
|
__constant char * const SCREEN = (char *) 1024
|
||||||
void main()
|
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)
|
__bank(bank) char plus(char a , char b)
|
||||||
char plus::a
|
char plus::a
|
||||||
__constant char plus::a#0 = '0' // a
|
__constant char plus::a#0 = '0' // a
|
||||||
char plus::b
|
char plus::b
|
||||||
__constant char plus::b#0 = 7 // b
|
__constant char plus::b#0 = 7 // b
|
||||||
char plus::return
|
char plus::return
|
||||||
__constant char plus::return#1 = plus::a#0+plus::b#0 // return
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FINAL ASSEMBLER
|
FINAL ASSEMBLER
|
||||||
Score: 24
|
Score: 51
|
||||||
|
|
||||||
// File Comments
|
// File Comments
|
||||||
// Test a far call procedure with a calling convention PHI
|
// Test a procedure with calling convention PHI - case #3
|
||||||
// Upstart
|
// Upstart
|
||||||
.cpu _65c02
|
.file [name="call-banked-phi-case-3-near-0.prg", type="prg", segments="Program"]
|
||||||
.segmentdef Program [segments="Basic, Code, Data, stage, platform"]
|
.segmentdef Program [segments="Basic, Code, Data"]
|
||||||
.segmentdef Basic [start=$0801]
|
.segmentdef Basic [start=$0801]
|
||||||
.segmentdef Code [start=$80d]
|
.segmentdef Code [start=$80d]
|
||||||
.segmentdef Data [startAfter="Code"]
|
.segmentdef Data [startAfter="Code"]
|
||||||
.segmentdef stage [start=$0400, min=$0400, max=$07FF, align=$100]
|
.segmentdef RAM_Bank1 [start=$A000, min=$A000, max=$BFFF, align=$100]
|
||||||
.segmentdef platform [start=$C000, min=$C000, max=$C7FF, 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
|
// Global Constants & labels
|
||||||
.label SCREEN = $400
|
.label SCREEN = $400
|
||||||
.segment stage
|
.segment Code
|
||||||
// main
|
// main
|
||||||
main: {
|
main: {
|
||||||
// plus('0', 7)
|
// plus('0', 7)
|
||||||
// [1] call plus
|
// [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
|
||||||
jsr $ff6e
|
lda #1
|
||||||
.byte <plus
|
sta.z 0
|
||||||
.byte >plus
|
pha
|
||||||
.byte 1
|
jsr plus
|
||||||
|
pla
|
||||||
|
sta.z 0
|
||||||
// main::@1
|
// main::@1
|
||||||
// SCREEN[0] = plus('0', 7)
|
// SCREEN[0] = plus('0', 7)
|
||||||
// [2] *SCREEN = plus::return#1 -- _deref_pbuc1=vbuc2
|
// [2] *SCREEN = min::return#1 -- _deref_pbuc1=vbuc2
|
||||||
lda #plus.return
|
lda #min.return
|
||||||
sta SCREEN
|
sta SCREEN
|
||||||
// main::@return
|
// main::@return
|
||||||
// }
|
// }
|
||||||
// [3] return
|
// [3] return
|
||||||
rts
|
rts
|
||||||
}
|
}
|
||||||
|
.segment RAM_Bank1
|
||||||
// plus
|
// plus
|
||||||
// char plus(char a, char b)
|
// char plus(char a, char b)
|
||||||
plus: {
|
plus: {
|
||||||
.const a = '0'
|
.label a = '0'
|
||||||
.const b = 7
|
.label b = 7
|
||||||
.label return = a+b
|
// min(a, b)
|
||||||
|
// [5] call min
|
||||||
|
// [7] phi from plus to min [phi:plus->min] -- call__phi_near_finalize
|
||||||
|
jsr min
|
||||||
// plus::@return
|
// 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
|
rts
|
||||||
}
|
}
|
||||||
// File Data
|
// File Data
|
@@ -1,10 +1,14 @@
|
|||||||
__constant char * const SCREEN = (char *) 1024
|
__constant char * const SCREEN = (char *) 1024
|
||||||
void main()
|
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)
|
__bank(bank) char plus(char a , char b)
|
||||||
char plus::a
|
char plus::a
|
||||||
__constant char plus::a#0 = '0' // a
|
__constant char plus::a#0 = '0' // a
|
||||||
char plus::b
|
char plus::b
|
||||||
__constant char plus::b#0 = 7 // b
|
__constant char plus::b#0 = 7 // b
|
||||||
char plus::return
|
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
|
[1] call plus
|
||||||
to:main::@1
|
to:main::@1
|
||||||
main::@1: scope:[main] from main
|
main::@1: scope:[main] from main
|
||||||
[2] *SCREEN = plus::return#0
|
[2] *SCREEN = min::return#1
|
||||||
to:main::@return
|
to:main::@return
|
||||||
main::@return: scope:[main] from main::@1
|
main::@return: scope:[main] from main::@1
|
||||||
[3] return
|
[3] return
|
||||||
@@ -14,7 +14,16 @@ main::@return: scope:[main] from main::@1
|
|||||||
__bank(bank) char plus(char a , char b)
|
__bank(bank) char plus(char a , char b)
|
||||||
plus: scope:[plus] from main
|
plus: scope:[plus] from main
|
||||||
[4] phi()
|
[4] phi()
|
||||||
|
[5] call min
|
||||||
to:plus::@return
|
to:plus::@return
|
||||||
plus::@return: scope:[plus] from plus
|
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
|
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
|
__constant char * const SCREEN = (char *) 1024
|
||||||
void main()
|
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)
|
__bank(bank) char plus(char a , char b)
|
||||||
char plus::a
|
char plus::a
|
||||||
__constant char plus::a#0 = '0' // a
|
__constant char plus::a#0 = '0' // a
|
||||||
char plus::b
|
char plus::b
|
||||||
__constant char plus::b#0 = 7 // b
|
__constant char plus::b#0 = 7 // b
|
||||||
char plus::return
|
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
Reference in New Issue
Block a user