mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-02-21 22:29:07 +00:00
Implemented Xmega65 SYSCALLS.
This commit is contained in:
parent
dbb6ce5933
commit
d70fbe4c34
@ -123,17 +123,19 @@ public class LiveRangeVariablesEffective {
|
||||
CallPaths calledRefs = procedureCallPaths.get(calledRef);
|
||||
for(CallPath calledPath : calledRefs.getCallPaths()) {
|
||||
List<CallGraph.CallBlock.Call> path = calledPath.getPath();
|
||||
CallGraph.CallBlock.Call lastCall = path.get(path.size() - 1);
|
||||
Integer lastCallStatementIdx = lastCall.getCallStatementIdx();
|
||||
LabelRef lastCallBlockRef = program.getStatementInfos().getBlockRef(lastCallStatementIdx);
|
||||
if(lastCallBlockRef.equals(block.getLabel())) {
|
||||
if(callAliases == null) {
|
||||
// Found a matching call!
|
||||
callAliases = calledPath.getInnerAliases();
|
||||
} else {
|
||||
// Found another matching call!
|
||||
callAliases = new Pass2AliasElimination.Aliases(callAliases);
|
||||
callAliases.addAll(calledPath.getInnerAliases());
|
||||
if(path.size() > 0) {
|
||||
CallGraph.CallBlock.Call lastCall = path.get(path.size() - 1);
|
||||
Integer lastCallStatementIdx = lastCall.getCallStatementIdx();
|
||||
LabelRef lastCallBlockRef = program.getStatementInfos().getBlockRef(lastCallStatementIdx);
|
||||
if(lastCallBlockRef.equals(block.getLabel())) {
|
||||
if(callAliases == null) {
|
||||
// Found a matching call!
|
||||
callAliases = calledPath.getInnerAliases();
|
||||
} else {
|
||||
// Found another matching call!
|
||||
callAliases = new Pass2AliasElimination.Aliases(callAliases);
|
||||
callAliases.addAll(calledPath.getInnerAliases());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,8 +8,7 @@ public class SymbolTypePointer implements SymbolType {
|
||||
|
||||
private SymbolType elementType;
|
||||
|
||||
public SymbolTypePointer(
|
||||
SymbolType elementType) {
|
||||
public SymbolTypePointer(SymbolType elementType) {
|
||||
this.elementType = elementType;
|
||||
}
|
||||
|
||||
|
@ -772,6 +772,10 @@ public class Pass4CodeGeneration {
|
||||
Variable variable = getScope().getVariable((VariableRef) pointer);
|
||||
generateIndirectCall(asm, variable, block.getScope());
|
||||
supported = true;
|
||||
} else if(pointer instanceof CastValue && ((CastValue) pointer).getValue() instanceof VariableRef) {
|
||||
Variable variable = getScope().getVariable((VariableRef) ((CastValue) pointer).getValue());
|
||||
generateIndirectCall(asm, variable, block.getScope());
|
||||
supported = true;
|
||||
}
|
||||
} else if(procedure instanceof VariableRef) {
|
||||
Variable procedureVariable = getScope().getVariable((VariableRef) procedure);
|
||||
|
@ -6,18 +6,39 @@
|
||||
|
||||
#pragma link("xmega65.ld")
|
||||
|
||||
void main() {
|
||||
char i=0;
|
||||
while(true) {
|
||||
unsigned int fn = CALLS[i*2];
|
||||
void()* f = (void()*)fn;
|
||||
(*f)();
|
||||
if(++i==2) i=0;
|
||||
}
|
||||
}
|
||||
|
||||
char* BORDERCOL = 0xd020;
|
||||
|
||||
void fn1() {
|
||||
const byte* BORDERCOL = $d020;
|
||||
(*BORDERCOL)++;
|
||||
}
|
||||
|
||||
char* BGCOL = 0xd021;
|
||||
|
||||
void main() {
|
||||
while(true) {
|
||||
*BGCOL = SYSCALLS[0];
|
||||
(*BGCOL)++;
|
||||
}
|
||||
void fn2() {
|
||||
const byte* BGCOL = $d021;
|
||||
(*BGCOL)++;
|
||||
}
|
||||
|
||||
#pragma data_seg(Syscall)
|
||||
|
||||
byte[] SYSCALLS = kickasm {{
|
||||
jmp main
|
||||
nop
|
||||
}};
|
||||
const char JMP = 0x4c;
|
||||
const char NOP = 0xea;
|
||||
|
||||
char[] SYSCALLS = {
|
||||
JMP, <&fn1, >&fn1, NOP,
|
||||
JMP, <&fn2, >&fn2, NOP,
|
||||
JMP, <&main, >&main, NOP
|
||||
};
|
||||
|
||||
const unsigned int* CALLS = (word*)(SYSCALLS+1);
|
||||
|
@ -10,17 +10,43 @@
|
||||
.segmentdef Data [startAfter="Code", min=$8200, max=$bdff]
|
||||
.segmentdef Stack [min=$be00, max=$beff, fill]
|
||||
.segmentdef Zeropage [min=$bf00, max=$bfff, fill]
|
||||
.label BGCOL = $d021
|
||||
.const JMP = $4c
|
||||
.const NOP = $ea
|
||||
.label CALLS = SYSCALLS+1
|
||||
.segment Code
|
||||
main: {
|
||||
.label fn = 3
|
||||
.label i = 2
|
||||
b1:
|
||||
lda SYSCALLS
|
||||
sta BGCOL
|
||||
inc BGCOL
|
||||
lda #0
|
||||
sta.z i
|
||||
b2:
|
||||
lda.z i
|
||||
asl
|
||||
asl
|
||||
tay
|
||||
lda CALLS,y
|
||||
sta.z fn
|
||||
lda CALLS+1,y
|
||||
sta.z fn+1
|
||||
jsr bi_fn
|
||||
inc.z i
|
||||
lda #2
|
||||
cmp.z i
|
||||
bne b2
|
||||
jmp b1
|
||||
bi_fn:
|
||||
jmp (fn)
|
||||
}
|
||||
fn2: {
|
||||
.label BGCOL = $d021
|
||||
inc BGCOL
|
||||
rts
|
||||
}
|
||||
fn1: {
|
||||
.label BORDERCOL = $d020
|
||||
inc BORDERCOL
|
||||
rts
|
||||
}
|
||||
.segment Syscall
|
||||
SYSCALLS:
|
||||
jmp main
|
||||
nop
|
||||
|
||||
SYSCALLS: .byte JMP, <fn1, >fn1, NOP, JMP, <fn2, >fn2, NOP, JMP, <main, >main, NOP
|
||||
|
@ -10,7 +10,29 @@
|
||||
main: scope:[main] from @1
|
||||
[4] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
[5] *((const byte*) BGCOL#0) ← *((const byte[]) SYSCALLS#0)
|
||||
[6] *((const byte*) BGCOL#0) ← ++ *((const byte*) BGCOL#0)
|
||||
main::@1: scope:[main] from main main::@2 main::@3
|
||||
[5] (byte) main::i#3 ← phi( main/(byte) 0 main::@3/(byte) main::i#1 main::@2/(byte) 0 )
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1
|
||||
[6] (byte~) main::$0 ← (byte) main::i#3 << (byte) 1
|
||||
[7] (byte~) main::$5 ← (byte~) main::$0 << (byte) 1
|
||||
[8] (word) main::fn#0 ← *((const word*) CALLS#0 + (byte~) main::$5)
|
||||
[9] call *((void()*)(word) main::fn#0)
|
||||
[10] (byte) main::i#1 ← ++ (byte) main::i#3
|
||||
[11] if((byte) main::i#1!=(byte) 2) goto main::@3
|
||||
to:main::@1
|
||||
main::@3: scope:[main] from main::@2
|
||||
[12] phi()
|
||||
to:main::@1
|
||||
fn2: scope:[fn2] from
|
||||
[13] *((const byte*) fn2::BGCOL#0) ← ++ *((const byte*) fn2::BGCOL#0)
|
||||
to:fn2::@return
|
||||
fn2::@return: scope:[fn2] from fn2
|
||||
[14] return
|
||||
to:@return
|
||||
fn1: scope:[fn1] from
|
||||
[15] *((const byte*) fn1::BORDERCOL#0) ← ++ *((const byte*) fn1::BORDERCOL#0)
|
||||
to:fn1::@return
|
||||
fn1::@return: scope:[fn1] from fn1
|
||||
[16] return
|
||||
to:@return
|
||||
|
@ -1,89 +1,287 @@
|
||||
Loading link script "xmega65.ld"
|
||||
Resolved forward reference SYSCALLS to (byte[]) SYSCALLS
|
||||
Resolved forward reference CALLS to (word*) CALLS
|
||||
Fixing pointer array-indexing *((word*) CALLS + (number~) main::$0)
|
||||
Identified constant variable (byte*) BORDERCOL
|
||||
Identified constant variable (byte*) BGCOL
|
||||
Culled Empty Block (label) main::@4
|
||||
Culled Empty Block (label) main::@3
|
||||
Culled Empty Block (label) main::@5
|
||||
Culled Empty Block (label) main::@3
|
||||
Culled Empty Block (label) main::@6
|
||||
Culled Empty Block (label) main::@4
|
||||
Culled Empty Block (label) main::@8
|
||||
Culled Empty Block (label) @1
|
||||
Culled Empty Block (label) @2
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
@begin: scope:[] from
|
||||
(byte*) BGCOL#0 ← ((byte*)) (number) $d021
|
||||
to:@1
|
||||
main: scope:[main] from @1
|
||||
to:@3
|
||||
main: scope:[main] from @3
|
||||
(byte) main::i#0 ← (number) 0
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@2
|
||||
main::@1: scope:[main] from main main::@2 main::@7
|
||||
(byte) main::i#4 ← phi( main/(byte) main::i#0 main::@2/(byte) main::i#1 main::@7/(byte) main::i#2 )
|
||||
if(true) goto main::@2
|
||||
to:main::@return
|
||||
main::@2: scope:[main] from main::@1
|
||||
*((byte*) BGCOL#0) ← *((byte[]) SYSCALLS#0 + (number) 0)
|
||||
*((byte*) BGCOL#0) ← ++ *((byte*) BGCOL#0)
|
||||
(byte) main::i#3 ← phi( main::@1/(byte) main::i#4 )
|
||||
(number~) main::$0 ← (byte) main::i#3 * (number) 2
|
||||
(number~) main::$5 ← (number~) main::$0 * (const byte) SIZEOF_WORD
|
||||
(word) main::fn#0 ← *((word*) CALLS#0 + (number~) main::$5)
|
||||
(void()*~) main::$1 ← ((void()*)) (word) main::fn#0
|
||||
(void()*) main::f#0 ← (void()*~) main::$1
|
||||
call *((void()*) main::f#0)
|
||||
(byte) main::i#1 ← ++ (byte) main::i#3
|
||||
(bool~) main::$3 ← (byte) main::i#1 == (number) 2
|
||||
(bool~) main::$4 ← ! (bool~) main::$3
|
||||
if((bool~) main::$4) goto main::@1
|
||||
to:main::@7
|
||||
main::@7: scope:[main] from main::@2
|
||||
(byte) main::i#2 ← (number) 0
|
||||
to:main::@1
|
||||
main::@return: scope:[main] from main::@1
|
||||
return
|
||||
to:@return
|
||||
@1: scope:[] from @begin
|
||||
(byte[]) SYSCALLS#0 ← kickasm {{ jmp main
|
||||
nop
|
||||
}}
|
||||
fn1: scope:[fn1] from
|
||||
(byte*) fn1::BORDERCOL#0 ← ((byte*)) (number) $d020
|
||||
*((byte*) fn1::BORDERCOL#0) ← ++ *((byte*) fn1::BORDERCOL#0)
|
||||
to:fn1::@return
|
||||
fn1::@return: scope:[fn1] from fn1
|
||||
return
|
||||
to:@return
|
||||
fn2: scope:[fn2] from
|
||||
(byte*) fn2::BGCOL#0 ← ((byte*)) (number) $d021
|
||||
*((byte*) fn2::BGCOL#0) ← ++ *((byte*) fn2::BGCOL#0)
|
||||
to:fn2::@return
|
||||
fn2::@return: scope:[fn2] from fn2
|
||||
return
|
||||
to:@return
|
||||
@3: scope:[] from @begin
|
||||
(byte) JMP#0 ← (number) $4c
|
||||
(byte) NOP#0 ← (number) $ea
|
||||
(void()*~) $0 ← & (void()) fn1()
|
||||
(byte~) $1 ← < (void()*~) $0
|
||||
(void()*~) $2 ← & (void()) fn1()
|
||||
(byte~) $3 ← > (void()*~) $2
|
||||
(void()*~) $4 ← & (void()) fn2()
|
||||
(byte~) $5 ← < (void()*~) $4
|
||||
(void()*~) $6 ← & (void()) fn2()
|
||||
(byte~) $7 ← > (void()*~) $6
|
||||
(void()*~) $8 ← & (void()) main()
|
||||
(byte~) $9 ← < (void()*~) $8
|
||||
(void()*~) $10 ← & (void()) main()
|
||||
(byte~) $11 ← > (void()*~) $10
|
||||
(byte[]) SYSCALLS#0 ← { (byte) JMP#0, (byte~) $1, (byte~) $3, (byte) NOP#0, (byte) JMP#0, (byte~) $5, (byte~) $7, (byte) NOP#0, (byte) JMP#0, (byte~) $9, (byte~) $11, (byte) NOP#0 }
|
||||
(byte*~) $12 ← (byte[]) SYSCALLS#0 + (number) 1
|
||||
(word*~) $13 ← ((word*)) (byte*~) $12
|
||||
(word*) CALLS#0 ← (word*~) $13
|
||||
call main
|
||||
to:@2
|
||||
@2: scope:[] from @1
|
||||
to:@4
|
||||
@4: scope:[] from @3
|
||||
to:@end
|
||||
@end: scope:[] from @2
|
||||
@end: scope:[] from @4
|
||||
|
||||
SYMBOL TABLE SSA
|
||||
(label) @1
|
||||
(label) @2
|
||||
(void()*~) $0
|
||||
(byte~) $1
|
||||
(void()*~) $10
|
||||
(byte~) $11
|
||||
(byte*~) $12
|
||||
(word*~) $13
|
||||
(void()*~) $2
|
||||
(byte~) $3
|
||||
(void()*~) $4
|
||||
(byte~) $5
|
||||
(void()*~) $6
|
||||
(byte~) $7
|
||||
(void()*~) $8
|
||||
(byte~) $9
|
||||
(label) @3
|
||||
(label) @4
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte*) BGCOL
|
||||
(byte*) BGCOL#0
|
||||
(word*) CALLS
|
||||
(word*) CALLS#0
|
||||
(byte) JMP
|
||||
(byte) JMP#0
|
||||
(byte) NOP
|
||||
(byte) NOP#0
|
||||
(const byte) SIZEOF_WORD = (byte) 2
|
||||
(byte[]) SYSCALLS
|
||||
(byte[]) SYSCALLS#0
|
||||
(void()) fn1()
|
||||
(label) fn1::@return
|
||||
(byte*) fn1::BORDERCOL
|
||||
(byte*) fn1::BORDERCOL#0
|
||||
(void()) fn2()
|
||||
(label) fn2::@return
|
||||
(byte*) fn2::BGCOL
|
||||
(byte*) fn2::BGCOL#0
|
||||
(void()) main()
|
||||
(number~) main::$0
|
||||
(void()*~) main::$1
|
||||
(bool~) main::$3
|
||||
(bool~) main::$4
|
||||
(number~) main::$5
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@7
|
||||
(label) main::@return
|
||||
(void()*) main::f
|
||||
(void()*) main::f#0
|
||||
(word) main::fn
|
||||
(word) main::fn#0
|
||||
(byte) main::i
|
||||
(byte) main::i#0
|
||||
(byte) main::i#1
|
||||
(byte) main::i#2
|
||||
(byte) main::i#3
|
||||
(byte) main::i#4
|
||||
|
||||
Adding number conversion cast (unumber) 0 in *((byte*) BGCOL#0) ← *((byte[]) SYSCALLS#0 + (number) 0)
|
||||
Adding number conversion cast (unumber) 0 in (byte) main::i#0 ← (number) 0
|
||||
Adding number conversion cast (unumber) 2 in (number~) main::$0 ← (byte) main::i#3 * (number) 2
|
||||
Adding number conversion cast (unumber) main::$0 in (number~) main::$0 ← (byte) main::i#3 * (unumber)(number) 2
|
||||
Adding number conversion cast (unumber) main::$5 in (number~) main::$5 ← (unumber~) main::$0 * (const byte) SIZEOF_WORD
|
||||
Adding number conversion cast (unumber) 2 in (bool~) main::$3 ← (byte) main::i#1 == (number) 2
|
||||
Adding number conversion cast (unumber) 0 in (byte) main::i#2 ← (number) 0
|
||||
Adding number conversion cast (unumber) $4c in (byte) JMP#0 ← (number) $4c
|
||||
Adding number conversion cast (unumber) $ea in (byte) NOP#0 ← (number) $ea
|
||||
Adding number conversion cast (unumber) 1 in (byte*~) $12 ← (byte[]) SYSCALLS#0 + (number) 1
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Inlining cast (byte*) BGCOL#0 ← (byte*)(number) $d021
|
||||
Inlining cast (byte) main::i#0 ← (unumber)(number) 0
|
||||
Inlining cast (void()*~) main::$1 ← (void()*)(word) main::fn#0
|
||||
Inlining cast (byte) main::i#2 ← (unumber)(number) 0
|
||||
Inlining cast (byte*) fn1::BORDERCOL#0 ← (byte*)(number) $d020
|
||||
Inlining cast (byte*) fn2::BGCOL#0 ← (byte*)(number) $d021
|
||||
Inlining cast (byte) JMP#0 ← (unumber)(number) $4c
|
||||
Inlining cast (byte) NOP#0 ← (unumber)(number) $ea
|
||||
Inlining cast (word*~) $13 ← (word*)(byte*~) $12
|
||||
Successful SSA optimization Pass2InlineCast
|
||||
Simplifying constant pointer cast (byte*) 53281
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant integer cast 2
|
||||
Simplifying constant integer cast 2
|
||||
Simplifying constant integer cast 0
|
||||
Simplifying constant pointer cast (byte*) 53280
|
||||
Simplifying constant pointer cast (byte*) 53281
|
||||
Simplifying constant integer cast $4c
|
||||
Simplifying constant integer cast $ea
|
||||
Simplifying constant integer cast 1
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) 2
|
||||
Finalized unsigned number type (byte) 2
|
||||
Finalized unsigned number type (byte) 0
|
||||
Finalized unsigned number type (byte) $4c
|
||||
Finalized unsigned number type (byte) $ea
|
||||
Finalized unsigned number type (byte) 1
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Constant (const byte*) BGCOL#0 = (byte*) 53281
|
||||
Constant (const byte[]) SYSCALLS#0 = kickasm {{ jmp main
|
||||
nop
|
||||
}}
|
||||
Inferred type updated to byte in (unumber~) main::$0 ← (byte) main::i#3 * (byte) 2
|
||||
Inferred type updated to byte in (unumber~) main::$5 ← (byte~) main::$0 * (const byte) SIZEOF_WORD
|
||||
Inversing boolean not [12] (bool~) main::$4 ← (byte) main::i#1 != (byte) 2 from [11] (bool~) main::$3 ← (byte) main::i#1 == (byte) 2
|
||||
Successful SSA optimization Pass2UnaryNotSimplification
|
||||
Alias (byte) main::i#3 = (byte) main::i#4
|
||||
Alias (void()*) main::f#0 = (void()*~) main::$1
|
||||
Alias (word*) CALLS#0 = (word*~) $13
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Identified duplicate assignment right side [26] (void()*~) $2 ← & (void()) fn1()
|
||||
Identified duplicate assignment right side [30] (void()*~) $6 ← & (void()) fn2()
|
||||
Identified duplicate assignment right side [34] (void()*~) $10 ← & (void()) main()
|
||||
Successful SSA optimization Pass2DuplicateRValueIdentification
|
||||
Simple Condition (bool~) main::$4 [13] if((byte) main::i#1!=(byte) 2) goto main::@1
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Constant right-side identified [24] (void()*~) $0 ← & (void()) fn1()
|
||||
Constant right-side identified [28] (void()*~) $4 ← & (void()) fn2()
|
||||
Constant right-side identified [32] (void()*~) $8 ← & (void()) main()
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte) main::i#0 = 0
|
||||
Constant (const byte) main::i#2 = 0
|
||||
Constant (const byte*) fn1::BORDERCOL#0 = (byte*) 53280
|
||||
Constant (const byte*) fn2::BGCOL#0 = (byte*) 53281
|
||||
Constant (const byte) JMP#0 = $4c
|
||||
Constant (const byte) NOP#0 = $ea
|
||||
Constant (const void()*) $0 = &fn1
|
||||
Constant (const void()*) $4 = &fn2
|
||||
Constant (const void()*) $8 = &main
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
if() condition always true - replacing block destination [1] if(true) goto main::@2
|
||||
Constant (const void()*) $2 = $0
|
||||
Constant (const void()*) $6 = $4
|
||||
Constant (const void()*) $10 = $8
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
if() condition always true - replacing block destination [2] if(true) goto main::@2
|
||||
Successful SSA optimization Pass2ConstantIfs
|
||||
Simplifying expression containing zero SYSCALLS#0 in [2] *((const byte*) BGCOL#0) ← *((const byte[]) SYSCALLS#0 + (byte) 0)
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Removing unused block main::@return
|
||||
Successful SSA optimization Pass2EliminateUnusedBlocks
|
||||
Constant right-side identified [12] (byte~) $1 ← < (const void()*) $0
|
||||
Constant right-side identified [13] (byte~) $3 ← > (const void()*) $2
|
||||
Constant right-side identified [14] (byte~) $5 ← < (const void()*) $4
|
||||
Constant right-side identified [15] (byte~) $7 ← > (const void()*) $6
|
||||
Constant right-side identified [16] (byte~) $9 ← < (const void()*) $8
|
||||
Constant right-side identified [17] (byte~) $11 ← > (const void()*) $10
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte) $1 = <$0
|
||||
Constant (const byte) $3 = >$2
|
||||
Constant (const byte) $5 = <$4
|
||||
Constant (const byte) $7 = >$6
|
||||
Constant (const byte) $9 = <$8
|
||||
Constant (const byte) $11 = >$10
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Identified constant from value list (byte[]) { (const byte) JMP#0, (const byte) $1, (const byte) $3, (const byte) NOP#0, (const byte) JMP#0, (const byte) $5, (const byte) $7, (const byte) NOP#0, (const byte) JMP#0, (const byte) $9, (const byte) $11, (const byte) NOP#0 }
|
||||
Successful SSA optimization Pass2ConstantInitializerValueLists
|
||||
Constant (const byte[]) SYSCALLS#0 = { JMP#0, $1, $3, NOP#0, JMP#0, $5, $7, NOP#0, JMP#0, $9, $11, NOP#0 }
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant right-side identified [12] (byte*~) $12 ← (const byte[]) SYSCALLS#0 + (byte) 1
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant (const byte*) $12 = SYSCALLS#0+1
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Constant value identified (word*)$12 in [13] (word*) CALLS#0 ← (word*)(const byte*) $12
|
||||
Successful SSA optimization Pass2ConstantValues
|
||||
Constant (const word*) CALLS#0 = (word*)$12
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Inlining Noop Cast [4] (void()*) main::f#0 ← (void()*)(word) main::fn#0 keeping main::fn#0
|
||||
Successful SSA optimization Pass2NopCastInlining
|
||||
Rewriting multiplication to use shift [1] (byte~) main::$0 ← (byte) main::i#3 * (byte) 2
|
||||
Rewriting multiplication to use shift [2] (byte~) main::$5 ← (byte~) main::$0 * (const byte) SIZEOF_WORD
|
||||
Successful SSA optimization Pass2MultiplyToShiftRewriting
|
||||
Inlining constant with var siblings (const byte) main::i#0
|
||||
Inlining constant with var siblings (const byte) main::i#2
|
||||
Constant inlined $10 = &(void()) main()
|
||||
Constant inlined $11 = >&(void()) main()
|
||||
Constant inlined $12 = (const byte[]) SYSCALLS#0+(byte) 1
|
||||
Constant inlined $0 = &(void()) fn1()
|
||||
Constant inlined $1 = <&(void()) fn1()
|
||||
Constant inlined $2 = &(void()) fn1()
|
||||
Constant inlined $3 = >&(void()) fn1()
|
||||
Constant inlined $4 = &(void()) fn2()
|
||||
Constant inlined $5 = <&(void()) fn2()
|
||||
Constant inlined $6 = &(void()) fn2()
|
||||
Constant inlined $7 = >&(void()) fn2()
|
||||
Constant inlined $8 = &(void()) main()
|
||||
Constant inlined $9 = <&(void()) main()
|
||||
Constant inlined main::i#0 = (byte) 0
|
||||
Constant inlined main::i#2 = (byte) 0
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Eliminating unused constant (const byte) SIZEOF_WORD
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Added new block during phi lifting main::@9(between main::@2 and main::@1)
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @2
|
||||
Adding NOP phi() at start of @3
|
||||
Adding NOP phi() at start of @4
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main
|
||||
Adding NOP phi() at start of main::@1
|
||||
Adding NOP phi() at start of main::@7
|
||||
CALL GRAPH
|
||||
Calls in [] to main:2
|
||||
|
||||
Created 0 initial phi equivalence classes
|
||||
Coalesced down to 0 phi equivalence classes
|
||||
Culled Empty Block (label) @2
|
||||
Culled Empty Block (label) main::@1
|
||||
Renumbering block main::@2 to main::@1
|
||||
Created 1 initial phi equivalence classes
|
||||
Coalesced [14] main::i#5 ← main::i#1
|
||||
Coalesced down to 1 phi equivalence classes
|
||||
Culled Empty Block (label) @4
|
||||
Culled Empty Block (label) main::@7
|
||||
Renumbering block @3 to @1
|
||||
Renumbering block main::@9 to main::@3
|
||||
Adding NOP phi() at start of @begin
|
||||
Adding NOP phi() at start of @1
|
||||
Adding NOP phi() at start of @end
|
||||
Adding NOP phi() at start of main
|
||||
Adding NOP phi() at start of main::@3
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
@begin: scope:[] from
|
||||
@ -98,19 +296,67 @@ FINAL CONTROL FLOW GRAPH
|
||||
main: scope:[main] from @1
|
||||
[4] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1
|
||||
[5] *((const byte*) BGCOL#0) ← *((const byte[]) SYSCALLS#0)
|
||||
[6] *((const byte*) BGCOL#0) ← ++ *((const byte*) BGCOL#0)
|
||||
main::@1: scope:[main] from main main::@2 main::@3
|
||||
[5] (byte) main::i#3 ← phi( main/(byte) 0 main::@3/(byte) main::i#1 main::@2/(byte) 0 )
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1
|
||||
[6] (byte~) main::$0 ← (byte) main::i#3 << (byte) 1
|
||||
[7] (byte~) main::$5 ← (byte~) main::$0 << (byte) 1
|
||||
[8] (word) main::fn#0 ← *((const word*) CALLS#0 + (byte~) main::$5)
|
||||
[9] call *((void()*)(word) main::fn#0)
|
||||
[10] (byte) main::i#1 ← ++ (byte) main::i#3
|
||||
[11] if((byte) main::i#1!=(byte) 2) goto main::@3
|
||||
to:main::@1
|
||||
main::@3: scope:[main] from main::@2
|
||||
[12] phi()
|
||||
to:main::@1
|
||||
fn2: scope:[fn2] from
|
||||
[13] *((const byte*) fn2::BGCOL#0) ← ++ *((const byte*) fn2::BGCOL#0)
|
||||
to:fn2::@return
|
||||
fn2::@return: scope:[fn2] from fn2
|
||||
[14] return
|
||||
to:@return
|
||||
fn1: scope:[fn1] from
|
||||
[15] *((const byte*) fn1::BORDERCOL#0) ← ++ *((const byte*) fn1::BORDERCOL#0)
|
||||
to:fn1::@return
|
||||
fn1::@return: scope:[fn1] from fn1
|
||||
[16] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
(byte*) BGCOL
|
||||
(word*) CALLS
|
||||
(byte) JMP
|
||||
(byte) NOP
|
||||
(byte[]) SYSCALLS
|
||||
(void()) fn1()
|
||||
(byte*) fn1::BORDERCOL
|
||||
(void()) fn2()
|
||||
(byte*) fn2::BGCOL
|
||||
(void()) main()
|
||||
(byte~) main::$0 202.0
|
||||
(byte~) main::$5 202.0
|
||||
(void()*) main::f
|
||||
(word) main::fn
|
||||
(word) main::fn#0 101.0
|
||||
(byte) main::i
|
||||
(byte) main::i#1 71.0
|
||||
(byte) main::i#3 42.599999999999994
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ main::i#3 main::i#1 ]
|
||||
Added variable main::$0 to zero page equivalence class [ main::$0 ]
|
||||
Added variable main::$5 to zero page equivalence class [ main::$5 ]
|
||||
Added variable main::fn#0 to zero page equivalence class [ main::fn#0 ]
|
||||
Complete equivalence classes
|
||||
[ main::i#3 main::i#1 ]
|
||||
[ main::$0 ]
|
||||
[ main::$5 ]
|
||||
[ main::fn#0 ]
|
||||
Allocated zp ZP_BYTE:2 [ main::i#3 main::i#1 ]
|
||||
Allocated zp ZP_BYTE:3 [ main::$0 ]
|
||||
Allocated zp ZP_BYTE:4 [ main::$5 ]
|
||||
Allocated zp ZP_WORD:5 [ main::fn#0 ]
|
||||
|
||||
INITIAL ASM
|
||||
Target platform is custom
|
||||
@ -129,7 +375,9 @@ Target platform is custom
|
||||
.segmentdef Stack [min=$be00, max=$beff, fill]
|
||||
.segmentdef Zeropage [min=$bf00, max=$bfff, fill]
|
||||
// Global Constants & labels
|
||||
.label BGCOL = $d021
|
||||
.const JMP = $4c
|
||||
.const NOP = $ea
|
||||
.label CALLS = SYSCALLS+1
|
||||
// @begin
|
||||
bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
@ -149,32 +397,115 @@ bend:
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
.label _0 = 3
|
||||
.label _5 = 4
|
||||
.label fn = 5
|
||||
.label i = 2
|
||||
// [5] phi from main main::@2 to main::@1 [phi:main/main::@2->main::@1]
|
||||
b1_from_main:
|
||||
b1_from_b2:
|
||||
// [5] phi (byte) main::i#3 = (byte) 0 [phi:main/main::@2->main::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z i
|
||||
jmp b1
|
||||
// main::@1
|
||||
b1:
|
||||
// [5] *((const byte*) BGCOL#0) ← *((const byte[]) SYSCALLS#0) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda SYSCALLS
|
||||
sta BGCOL
|
||||
// [6] *((const byte*) BGCOL#0) ← ++ *((const byte*) BGCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc BGCOL
|
||||
jmp b2
|
||||
// main::@2
|
||||
b2:
|
||||
// [6] (byte~) main::$0 ← (byte) main::i#3 << (byte) 1 -- vbuz1=vbuz2_rol_1
|
||||
lda.z i
|
||||
asl
|
||||
sta.z _0
|
||||
// [7] (byte~) main::$5 ← (byte~) main::$0 << (byte) 1 -- vbuz1=vbuz2_rol_1
|
||||
lda.z _0
|
||||
asl
|
||||
sta.z _5
|
||||
// [8] (word) main::fn#0 ← *((const word*) CALLS#0 + (byte~) main::$5) -- vwuz1=pwuc1_derefidx_vbuz2
|
||||
ldy.z _5
|
||||
lda CALLS,y
|
||||
sta.z fn
|
||||
lda CALLS+1,y
|
||||
sta.z fn+1
|
||||
// [9] call *((void()*)(word) main::fn#0)
|
||||
jsr bi_fn
|
||||
// [10] (byte) main::i#1 ← ++ (byte) main::i#3 -- vbuz1=_inc_vbuz1
|
||||
inc.z i
|
||||
// [11] if((byte) main::i#1!=(byte) 2) goto main::@3 -- vbuz1_neq_vbuc1_then_la1
|
||||
lda #2
|
||||
cmp.z i
|
||||
bne b3_from_b2
|
||||
jmp b1_from_b2
|
||||
// [12] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
|
||||
b3_from_b2:
|
||||
jmp b3
|
||||
// main::@3
|
||||
b3:
|
||||
// [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
|
||||
b1_from_b3:
|
||||
// [5] phi (byte) main::i#3 = (byte) main::i#1 [phi:main::@3->main::@1#0] -- register_copy
|
||||
jmp b1
|
||||
bi_fn:
|
||||
jmp (fn)
|
||||
}
|
||||
// fn2
|
||||
fn2: {
|
||||
.label BGCOL = $d021
|
||||
// [13] *((const byte*) fn2::BGCOL#0) ← ++ *((const byte*) fn2::BGCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc BGCOL
|
||||
jmp breturn
|
||||
// fn2::@return
|
||||
breturn:
|
||||
// [14] return
|
||||
rts
|
||||
}
|
||||
// fn1
|
||||
fn1: {
|
||||
.label BORDERCOL = $d020
|
||||
// [15] *((const byte*) fn1::BORDERCOL#0) ← ++ *((const byte*) fn1::BORDERCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc BORDERCOL
|
||||
jmp breturn
|
||||
// fn1::@return
|
||||
breturn:
|
||||
// [16] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
.segment Syscall
|
||||
SYSCALLS:
|
||||
jmp main
|
||||
nop
|
||||
|
||||
SYSCALLS: .byte JMP, <fn1, >fn1, NOP, JMP, <fn2, >fn2, NOP, JMP, <main, >main, NOP
|
||||
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [5] *((const byte*) BGCOL#0) ← *((const byte[]) SYSCALLS#0) [ ] ( main:2 [ ] ) always clobbers reg byte a
|
||||
Statement [6] (byte~) main::$0 ← (byte) main::i#3 << (byte) 1 [ main::i#3 main::$0 ] ( [ main::i#3 main::$0 ] main:2 [ main::i#3 main::$0 ] ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp ZP_BYTE:2 [ main::i#3 main::i#1 ]
|
||||
Statement [7] (byte~) main::$5 ← (byte~) main::$0 << (byte) 1 [ main::i#3 main::$5 ] ( [ main::i#3 main::$5 ] main:2 [ main::i#3 main::$5 ] ) always clobbers reg byte a
|
||||
Statement [8] (word) main::fn#0 ← *((const word*) CALLS#0 + (byte~) main::$5) [ main::i#3 main::fn#0 ] ( [ main::i#3 main::fn#0 ] main:2 [ main::i#3 main::fn#0 ] ) always clobbers reg byte a
|
||||
Statement [9] call *((void()*)(word) main::fn#0) [ main::i#3 ] ( [ main::i#3 ] main:2 [ main::i#3 ] ) always clobbers reg byte a reg byte x reg byte y
|
||||
Removing always clobbered register reg byte x as potential for zp ZP_BYTE:2 [ main::i#3 main::i#1 ]
|
||||
Removing always clobbered register reg byte y as potential for zp ZP_BYTE:2 [ main::i#3 main::i#1 ]
|
||||
Statement [11] if((byte) main::i#1!=(byte) 2) goto main::@3 [ main::i#1 ] ( [ main::i#1 ] main:2 [ main::i#1 ] ) always clobbers reg byte a
|
||||
Statement [6] (byte~) main::$0 ← (byte) main::i#3 << (byte) 1 [ main::i#3 main::$0 ] ( [ main::i#3 main::$0 ] main:2 [ main::i#3 main::$0 ] ) always clobbers reg byte a
|
||||
Statement [7] (byte~) main::$5 ← (byte~) main::$0 << (byte) 1 [ main::i#3 main::$5 ] ( [ main::i#3 main::$5 ] main:2 [ main::i#3 main::$5 ] ) always clobbers reg byte a
|
||||
Statement [8] (word) main::fn#0 ← *((const word*) CALLS#0 + (byte~) main::$5) [ main::i#3 main::fn#0 ] ( [ main::i#3 main::fn#0 ] main:2 [ main::i#3 main::fn#0 ] ) always clobbers reg byte a
|
||||
Statement [9] call *((void()*)(word) main::fn#0) [ main::i#3 ] ( [ main::i#3 ] main:2 [ main::i#3 ] ) always clobbers reg byte a reg byte x reg byte y
|
||||
Statement [11] if((byte) main::i#1!=(byte) 2) goto main::@3 [ main::i#1 ] ( [ main::i#1 ] main:2 [ main::i#1 ] ) always clobbers reg byte a
|
||||
Potential registers zp ZP_BYTE:2 [ main::i#3 main::i#1 ] : zp ZP_BYTE:2 ,
|
||||
Potential registers zp ZP_BYTE:3 [ main::$0 ] : zp ZP_BYTE:3 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_BYTE:4 [ main::$5 ] : zp ZP_BYTE:4 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp ZP_WORD:5 [ main::fn#0 ] : zp ZP_WORD:5 ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main]
|
||||
Uplift Scope [main] 202: zp ZP_BYTE:3 [ main::$0 ] 202: zp ZP_BYTE:4 [ main::$5 ] 113.6: zp ZP_BYTE:2 [ main::i#3 main::i#1 ] 101: zp ZP_WORD:5 [ main::fn#0 ]
|
||||
Uplift Scope [fn1]
|
||||
Uplift Scope [fn2]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 212 combination
|
||||
Uplifting [] best 212 combination
|
||||
Uplifting [main] best 6252 combination reg byte a [ main::$0 ] reg byte a [ main::$5 ] zp ZP_BYTE:2 [ main::i#3 main::i#1 ] zp ZP_WORD:5 [ main::fn#0 ]
|
||||
Uplifting [fn1] best 6252 combination
|
||||
Uplifting [fn2] best 6252 combination
|
||||
Uplifting [] best 6252 combination
|
||||
Attempting to uplift remaining variables inzp ZP_BYTE:2 [ main::i#3 main::i#1 ]
|
||||
Uplifting [main] best 6252 combination zp ZP_BYTE:2 [ main::i#3 main::i#1 ]
|
||||
Allocated (was zp ZP_WORD:5) zp ZP_WORD:3 [ main::fn#0 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
@ -192,7 +523,9 @@ ASSEMBLER BEFORE OPTIMIZATION
|
||||
.segmentdef Stack [min=$be00, max=$beff, fill]
|
||||
.segmentdef Zeropage [min=$bf00, max=$bfff, fill]
|
||||
// Global Constants & labels
|
||||
.label BGCOL = $d021
|
||||
.const JMP = $4c
|
||||
.const NOP = $ea
|
||||
.label CALLS = SYSCALLS+1
|
||||
// @begin
|
||||
bbegin:
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
@ -212,56 +545,155 @@ bend:
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
.label fn = 3
|
||||
.label i = 2
|
||||
// [5] phi from main main::@2 to main::@1 [phi:main/main::@2->main::@1]
|
||||
b1_from_main:
|
||||
b1_from_b2:
|
||||
// [5] phi (byte) main::i#3 = (byte) 0 [phi:main/main::@2->main::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z i
|
||||
jmp b1
|
||||
// main::@1
|
||||
b1:
|
||||
// [5] *((const byte*) BGCOL#0) ← *((const byte[]) SYSCALLS#0) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda SYSCALLS
|
||||
sta BGCOL
|
||||
// [6] *((const byte*) BGCOL#0) ← ++ *((const byte*) BGCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc BGCOL
|
||||
jmp b2
|
||||
// main::@2
|
||||
b2:
|
||||
// [6] (byte~) main::$0 ← (byte) main::i#3 << (byte) 1 -- vbuaa=vbuz1_rol_1
|
||||
lda.z i
|
||||
asl
|
||||
// [7] (byte~) main::$5 ← (byte~) main::$0 << (byte) 1 -- vbuaa=vbuaa_rol_1
|
||||
asl
|
||||
// [8] (word) main::fn#0 ← *((const word*) CALLS#0 + (byte~) main::$5) -- vwuz1=pwuc1_derefidx_vbuaa
|
||||
tay
|
||||
lda CALLS,y
|
||||
sta.z fn
|
||||
lda CALLS+1,y
|
||||
sta.z fn+1
|
||||
// [9] call *((void()*)(word) main::fn#0)
|
||||
jsr bi_fn
|
||||
// [10] (byte) main::i#1 ← ++ (byte) main::i#3 -- vbuz1=_inc_vbuz1
|
||||
inc.z i
|
||||
// [11] if((byte) main::i#1!=(byte) 2) goto main::@3 -- vbuz1_neq_vbuc1_then_la1
|
||||
lda #2
|
||||
cmp.z i
|
||||
bne b3_from_b2
|
||||
jmp b1_from_b2
|
||||
// [12] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
|
||||
b3_from_b2:
|
||||
jmp b3
|
||||
// main::@3
|
||||
b3:
|
||||
// [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
|
||||
b1_from_b3:
|
||||
// [5] phi (byte) main::i#3 = (byte) main::i#1 [phi:main::@3->main::@1#0] -- register_copy
|
||||
jmp b1
|
||||
bi_fn:
|
||||
jmp (fn)
|
||||
}
|
||||
// fn2
|
||||
fn2: {
|
||||
.label BGCOL = $d021
|
||||
// [13] *((const byte*) fn2::BGCOL#0) ← ++ *((const byte*) fn2::BGCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc BGCOL
|
||||
jmp breturn
|
||||
// fn2::@return
|
||||
breturn:
|
||||
// [14] return
|
||||
rts
|
||||
}
|
||||
// fn1
|
||||
fn1: {
|
||||
.label BORDERCOL = $d020
|
||||
// [15] *((const byte*) fn1::BORDERCOL#0) ← ++ *((const byte*) fn1::BORDERCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc BORDERCOL
|
||||
jmp breturn
|
||||
// fn1::@return
|
||||
breturn:
|
||||
// [16] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
.segment Syscall
|
||||
SYSCALLS:
|
||||
jmp main
|
||||
nop
|
||||
|
||||
SYSCALLS: .byte JMP, <fn1, >fn1, NOP, JMP, <fn2, >fn2, NOP, JMP, <main, >main, NOP
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp bend
|
||||
Removing instruction jmp b1
|
||||
Removing instruction jmp b2
|
||||
Removing instruction jmp b3
|
||||
Removing instruction jmp breturn
|
||||
Removing instruction jmp breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Replacing label b3_from_b2 with b3
|
||||
Replacing label b1 with b2
|
||||
Removing instruction b1_from_bbegin:
|
||||
Removing instruction b1:
|
||||
Removing instruction main_from_b1:
|
||||
Removing instruction bend_from_b1:
|
||||
Removing instruction b1_from_main:
|
||||
Removing instruction b1:
|
||||
Removing instruction b3_from_b2:
|
||||
Removing instruction b1_from_b3:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction bbegin:
|
||||
Removing instruction bend:
|
||||
Removing instruction breturn:
|
||||
Removing instruction breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Removing instruction jsr main
|
||||
Succesful ASM optimization Pass5SkipBegin
|
||||
Skipping double jump to b2 in bne b3
|
||||
Succesful ASM optimization Pass5DoubleJumpElimination
|
||||
Relabelling long label b1_from_b2 to b1
|
||||
Succesful ASM optimization Pass5RelabelLongLabels
|
||||
Removing instruction b3:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Removing unreachable instruction jmp b2
|
||||
Succesful ASM optimization Pass5UnreachableCodeElimination
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte*) BGCOL
|
||||
(const byte*) BGCOL#0 BGCOL = (byte*) 53281
|
||||
(word*) CALLS
|
||||
(const word*) CALLS#0 CALLS = (word*)(const byte[]) SYSCALLS#0+(byte) 1
|
||||
(byte) JMP
|
||||
(const byte) JMP#0 JMP = (byte) $4c
|
||||
(byte) NOP
|
||||
(const byte) NOP#0 NOP = (byte) $ea
|
||||
(byte[]) SYSCALLS
|
||||
(const byte[]) SYSCALLS#0 SYSCALLS = kickasm {{ jmp main
|
||||
nop
|
||||
}}
|
||||
(const byte[]) SYSCALLS#0 SYSCALLS = { (const byte) JMP#0, <&(void()) fn1(), >&(void()) fn1(), (const byte) NOP#0, (const byte) JMP#0, <&(void()) fn2(), >&(void()) fn2(), (const byte) NOP#0, (const byte) JMP#0, <&(void()) main(), >&(void()) main(), (const byte) NOP#0 }
|
||||
(void()) fn1()
|
||||
(label) fn1::@return
|
||||
(byte*) fn1::BORDERCOL
|
||||
(const byte*) fn1::BORDERCOL#0 BORDERCOL = (byte*) 53280
|
||||
(void()) fn2()
|
||||
(label) fn2::@return
|
||||
(byte*) fn2::BGCOL
|
||||
(const byte*) fn2::BGCOL#0 BGCOL = (byte*) 53281
|
||||
(void()) main()
|
||||
(byte~) main::$0 reg byte a 202.0
|
||||
(byte~) main::$5 reg byte a 202.0
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@3
|
||||
(void()*) main::f
|
||||
(word) main::fn
|
||||
(word) main::fn#0 fn zp ZP_WORD:3 101.0
|
||||
(byte) main::i
|
||||
(byte) main::i#1 i zp ZP_BYTE:2 71.0
|
||||
(byte) main::i#3 i zp ZP_BYTE:2 42.599999999999994
|
||||
|
||||
zp ZP_BYTE:2 [ main::i#3 main::i#1 ]
|
||||
reg byte a [ main::$0 ]
|
||||
reg byte a [ main::$5 ]
|
||||
zp ZP_WORD:3 [ main::fn#0 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 170
|
||||
Score: 5574
|
||||
|
||||
// File Comments
|
||||
// Example showing how to perform linking using a linker-file
|
||||
@ -278,7 +710,9 @@ Score: 170
|
||||
.segmentdef Stack [min=$be00, max=$beff, fill]
|
||||
.segmentdef Zeropage [min=$bf00, max=$bfff, fill]
|
||||
// Global Constants & labels
|
||||
.label BGCOL = $d021
|
||||
.const JMP = $4c
|
||||
.const NOP = $ea
|
||||
.label CALLS = SYSCALLS+1
|
||||
// @begin
|
||||
// [1] phi from @begin to @1 [phi:@begin->@1]
|
||||
// @1
|
||||
@ -289,21 +723,70 @@ Score: 170
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
// main::@1
|
||||
.label fn = 3
|
||||
.label i = 2
|
||||
// [5] phi from main main::@2 to main::@1 [phi:main/main::@2->main::@1]
|
||||
b1:
|
||||
// *BGCOL = SYSCALLS[0]
|
||||
// [5] *((const byte*) BGCOL#0) ← *((const byte[]) SYSCALLS#0) -- _deref_pbuc1=_deref_pbuc2
|
||||
lda SYSCALLS
|
||||
sta BGCOL
|
||||
// (*BGCOL)++;
|
||||
// [6] *((const byte*) BGCOL#0) ← ++ *((const byte*) BGCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc BGCOL
|
||||
// [5] phi (byte) main::i#3 = (byte) 0 [phi:main/main::@2->main::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z i
|
||||
// main::@1
|
||||
// main::@2
|
||||
b2:
|
||||
// i*2
|
||||
// [6] (byte~) main::$0 ← (byte) main::i#3 << (byte) 1 -- vbuaa=vbuz1_rol_1
|
||||
lda.z i
|
||||
asl
|
||||
// fn = CALLS[i*2]
|
||||
// [7] (byte~) main::$5 ← (byte~) main::$0 << (byte) 1 -- vbuaa=vbuaa_rol_1
|
||||
asl
|
||||
// [8] (word) main::fn#0 ← *((const word*) CALLS#0 + (byte~) main::$5) -- vwuz1=pwuc1_derefidx_vbuaa
|
||||
tay
|
||||
lda CALLS,y
|
||||
sta.z fn
|
||||
lda CALLS+1,y
|
||||
sta.z fn+1
|
||||
// (*f)()
|
||||
// [9] call *((void()*)(word) main::fn#0)
|
||||
jsr bi_fn
|
||||
// if(++i==2)
|
||||
// [10] (byte) main::i#1 ← ++ (byte) main::i#3 -- vbuz1=_inc_vbuz1
|
||||
inc.z i
|
||||
// [11] if((byte) main::i#1!=(byte) 2) goto main::@3 -- vbuz1_neq_vbuc1_then_la1
|
||||
lda #2
|
||||
cmp.z i
|
||||
bne b2
|
||||
jmp b1
|
||||
// [12] phi from main::@2 to main::@3 [phi:main::@2->main::@3]
|
||||
// main::@3
|
||||
// [5] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
|
||||
// [5] phi (byte) main::i#3 = (byte) main::i#1 [phi:main::@3->main::@1#0] -- register_copy
|
||||
bi_fn:
|
||||
jmp (fn)
|
||||
}
|
||||
// fn2
|
||||
fn2: {
|
||||
.label BGCOL = $d021
|
||||
// (*BGCOL)++;
|
||||
// [13] *((const byte*) fn2::BGCOL#0) ← ++ *((const byte*) fn2::BGCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc BGCOL
|
||||
// fn2::@return
|
||||
// }
|
||||
// [14] return
|
||||
rts
|
||||
}
|
||||
// fn1
|
||||
fn1: {
|
||||
.label BORDERCOL = $d020
|
||||
// (*BORDERCOL)++;
|
||||
// [15] *((const byte*) fn1::BORDERCOL#0) ← ++ *((const byte*) fn1::BORDERCOL#0) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc BORDERCOL
|
||||
// fn1::@return
|
||||
// }
|
||||
// [16] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
.segment Syscall
|
||||
SYSCALLS:
|
||||
jmp main
|
||||
nop
|
||||
|
||||
SYSCALLS: .byte JMP, <fn1, >fn1, NOP, JMP, <fn2, >fn2, NOP, JMP, <main, >main, NOP
|
||||
|
||||
|
@ -1,12 +1,36 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(byte*) BGCOL
|
||||
(const byte*) BGCOL#0 BGCOL = (byte*) 53281
|
||||
(word*) CALLS
|
||||
(const word*) CALLS#0 CALLS = (word*)(const byte[]) SYSCALLS#0+(byte) 1
|
||||
(byte) JMP
|
||||
(const byte) JMP#0 JMP = (byte) $4c
|
||||
(byte) NOP
|
||||
(const byte) NOP#0 NOP = (byte) $ea
|
||||
(byte[]) SYSCALLS
|
||||
(const byte[]) SYSCALLS#0 SYSCALLS = kickasm {{ jmp main
|
||||
nop
|
||||
}}
|
||||
(const byte[]) SYSCALLS#0 SYSCALLS = { (const byte) JMP#0, <&(void()) fn1(), >&(void()) fn1(), (const byte) NOP#0, (const byte) JMP#0, <&(void()) fn2(), >&(void()) fn2(), (const byte) NOP#0, (const byte) JMP#0, <&(void()) main(), >&(void()) main(), (const byte) NOP#0 }
|
||||
(void()) fn1()
|
||||
(label) fn1::@return
|
||||
(byte*) fn1::BORDERCOL
|
||||
(const byte*) fn1::BORDERCOL#0 BORDERCOL = (byte*) 53280
|
||||
(void()) fn2()
|
||||
(label) fn2::@return
|
||||
(byte*) fn2::BGCOL
|
||||
(const byte*) fn2::BGCOL#0 BGCOL = (byte*) 53281
|
||||
(void()) main()
|
||||
(byte~) main::$0 reg byte a 202.0
|
||||
(byte~) main::$5 reg byte a 202.0
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@3
|
||||
(void()*) main::f
|
||||
(word) main::fn
|
||||
(word) main::fn#0 fn zp ZP_WORD:3 101.0
|
||||
(byte) main::i
|
||||
(byte) main::i#1 i zp ZP_BYTE:2 71.0
|
||||
(byte) main::i#3 i zp ZP_BYTE:2 42.599999999999994
|
||||
|
||||
zp ZP_BYTE:2 [ main::i#3 main::i#1 ]
|
||||
reg byte a [ main::$0 ]
|
||||
reg byte a [ main::$5 ]
|
||||
zp ZP_WORD:3 [ main::fn#0 ]
|
||||
|
Loading…
x
Reference in New Issue
Block a user