mirror of
https://gitlab.com/camelot/kickc.git
synced 2024-09-30 09:57:11 +00:00
Added support for indirect calls to advanced expressions through a new fragment type. Closes #708
This commit is contained in:
parent
77db0e8701
commit
66a1222fdb
@ -1,4 +1,4 @@
|
||||
//KICKC FRAGMENT CACHE 8d6655dbd 8d6657e44
|
||||
//KICKC FRAGMENT CACHE 84ae04234 84ae062c1
|
||||
//FRAGMENT vbuzz=vbuc1
|
||||
ldz #{c1}
|
||||
//FRAGMENT vbuzz_lt_vbuc1_then_la1
|
||||
|
1677
src/main/fragment/cache/fragment-cache-mega45gs02.asm
vendored
1677
src/main/fragment/cache/fragment-cache-mega45gs02.asm
vendored
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
//KICKC FRAGMENT CACHE 8d6655dbd 8d6657e44
|
||||
//KICKC FRAGMENT CACHE 84ae04234 84ae062c1
|
||||
//FRAGMENT vbuz1=vbuc1
|
||||
lda #{c1}
|
||||
sta {z1}
|
||||
|
1057
src/main/fragment/cache/fragment-cache-mos6502x.asm
vendored
1057
src/main/fragment/cache/fragment-cache-mos6502x.asm
vendored
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
//KICKC FRAGMENT CACHE 8d6655dbd 8d6657e44
|
||||
//KICKC FRAGMENT CACHE 84ae04234 84ae062c1
|
||||
//FRAGMENT _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc {c1}
|
||||
//FRAGMENT isr_hardware_all_entry
|
||||
|
@ -1,4 +1,4 @@
|
||||
//KICKC FRAGMENT CACHE 8d6655dbd 8d6657e44
|
||||
//KICKC FRAGMENT CACHE 84ae04234 84ae062c1
|
||||
//FRAGMENT vbuz1=_deref_pbuc1
|
||||
lda {c1}
|
||||
sta {z1}
|
||||
@ -244,81 +244,3 @@ inc
|
||||
//FRAGMENT vbuyy_neq_vbuc1_then_la1
|
||||
cpy #{c1}
|
||||
bne {la1}
|
||||
//FRAGMENT 0_neq_pbuc1_derefidx_vbuz1_then_la1
|
||||
ldy {z1}
|
||||
lda {c1},y
|
||||
cmp #0
|
||||
bne {la1}
|
||||
//FRAGMENT pbuz1=pbuz2
|
||||
lda {z2}
|
||||
sta {z1}
|
||||
lda {z2}+1
|
||||
sta {z1}+1
|
||||
//FRAGMENT vbuz1=pbuc1_derefidx_vbuz2
|
||||
ldy {z2}
|
||||
lda {c1},y
|
||||
sta {z1}
|
||||
//FRAGMENT pbuz1=_inc_pbuz2
|
||||
clc
|
||||
lda {z2}
|
||||
adc #1
|
||||
sta {z1}
|
||||
lda {z2}+1
|
||||
adc #0
|
||||
sta {z1}+1
|
||||
//FRAGMENT _deref_pbuc1=_deref_pbuz1
|
||||
ldy #0
|
||||
lda ({z1}),y
|
||||
sta {c1}
|
||||
//FRAGMENT vbuz1=_byte0_pbuz2
|
||||
lda {z2}
|
||||
sta {z1}
|
||||
//FRAGMENT vbuz1=_byte1_pbuz2
|
||||
lda {z2}+1
|
||||
sta {z1}
|
||||
//FRAGMENT 0_neq_pbuc1_derefidx_vbuaa_then_la1
|
||||
tay
|
||||
lda {c1},y
|
||||
cmp #0
|
||||
bne {la1}
|
||||
//FRAGMENT 0_neq_pbuc1_derefidx_vbuxx_then_la1
|
||||
lda {c1},x
|
||||
cmp #0
|
||||
bne {la1}
|
||||
//FRAGMENT 0_neq_pbuc1_derefidx_vbuyy_then_la1
|
||||
lda {c1},y
|
||||
cmp #0
|
||||
bne {la1}
|
||||
//FRAGMENT vbuz1=pbuc1_derefidx_vbuxx
|
||||
lda {c1},x
|
||||
sta {z1}
|
||||
//FRAGMENT vbuz1=pbuc1_derefidx_vbuyy
|
||||
lda {c1},y
|
||||
sta {z1}
|
||||
//FRAGMENT vbuaa=pbuc1_derefidx_vbuz1
|
||||
ldy {z1}
|
||||
lda {c1},y
|
||||
//FRAGMENT vbuaa=pbuc1_derefidx_vbuxx
|
||||
lda {c1},x
|
||||
//FRAGMENT vbuaa=pbuc1_derefidx_vbuyy
|
||||
lda {c1},y
|
||||
//FRAGMENT vbuxx=pbuc1_derefidx_vbuz1
|
||||
ldy {z1}
|
||||
ldx {c1},y
|
||||
//FRAGMENT vbuaa=_byte0_pbuz1
|
||||
lda {z1}
|
||||
//FRAGMENT vbuxx=_byte0_pbuz1
|
||||
ldx {z1}
|
||||
//FRAGMENT vbuaa=_byte1_pbuz1
|
||||
lda {z1}+1
|
||||
//FRAGMENT vbuxx=_byte1_pbuz1
|
||||
ldx {z1}+1
|
||||
//FRAGMENT vbuyy=_byte0_pbuz1
|
||||
ldy {z1}
|
||||
//FRAGMENT vbuyy=_byte1_pbuz1
|
||||
ldy {z1}+1
|
||||
//FRAGMENT vbuyy=pbuc1_derefidx_vbuz1
|
||||
ldx {z1}
|
||||
ldy {c1},x
|
||||
//FRAGMENT vbuxx=pbuc1_derefidx_vbuyy
|
||||
ldx {c1},y
|
||||
|
1
src/main/fragment/mos6502-common/call__deref_pprc1.asm
Normal file
1
src/main/fragment/mos6502-common/call__deref_pprc1.asm
Normal file
@ -0,0 +1 @@
|
||||
jsr {c1}
|
@ -0,0 +1,7 @@
|
||||
lda ({z1}),y
|
||||
sta !+ +1
|
||||
iny
|
||||
lda ({z1}),y
|
||||
sta !+ +2
|
||||
!:
|
||||
jsr $0000
|
@ -58,6 +58,24 @@ public class AsmFragmentInstanceSpecBuilder {
|
||||
return new AsmFragmentInstanceSpecBuilder(program, bindings, fragmentInstanceSpec);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a fragment instance spec factory for an indirect call
|
||||
* @return the fragment instance spec factory
|
||||
*/
|
||||
public static AsmFragmentInstanceSpecBuilder call(StatementCallExecute call, Program program) {
|
||||
return new AsmFragmentInstanceSpecBuilder(call, program);
|
||||
}
|
||||
|
||||
private AsmFragmentInstanceSpecBuilder(StatementCallExecute call, Program program) {
|
||||
this.program = program;
|
||||
this.bindings = new LinkedHashMap<>();
|
||||
ScopeRef codeScope = program.getStatementInfos().getBlock(call).getScope();
|
||||
StringBuilder signature = new StringBuilder();
|
||||
signature.append("call_");
|
||||
signature.append(bind(call.getProcedureRVal()));
|
||||
this.asmFragmentInstanceSpec = new AsmFragmentInstanceSpec(program, signature.toString(), bindings, codeScope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a fragment instance spec factory for an interrupt routine entry
|
||||
*
|
||||
|
@ -17,7 +17,6 @@ import dk.camelot64.kickc.model.values.*;
|
||||
import dk.camelot64.kickc.passes.calcs.PassNCalcVariableReferenceInfos;
|
||||
import dk.camelot64.kickc.passes.utils.SizeOfConstants;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
@ -658,17 +657,17 @@ public class Pass4CodeGeneration {
|
||||
ConstantValue memberValue = structValue.getValue(memberRef);
|
||||
Variable memberVariable = getScope().getVar(memberRef);
|
||||
addChunkData(dataChunk, memberValue, memberVariable.getType(), memberVariable.getArraySpec(), scopeRef);
|
||||
size += SymbolTypeStruct.getMemberSizeBytes(memberVariable.getType(), memberVariable.getArraySize(), getScope());
|
||||
size += SymbolTypeStruct.getMemberSizeBytes(memberVariable.getType(), memberVariable.getArraySize(), getScope());
|
||||
}
|
||||
// Add padding if this is a union and the first member does not use all bytes
|
||||
final int declaredSize = structValue.getStructType().getSizeBytes();
|
||||
if(size<declaredSize) {
|
||||
if(size < declaredSize) {
|
||||
long paddingSize = declaredSize - size;
|
||||
// TODO: Use SIZEOF constant
|
||||
ConstantValue paddingSizeVal = new ConstantInteger(paddingSize);
|
||||
String paddingBytesAsm = AsmFormat.getAsmConstant(program, paddingSizeVal, 99, scopeRef);
|
||||
String paddingBytesAsm = AsmFormat.getAsmConstant(program, paddingSizeVal, 99, scopeRef);
|
||||
ConstantValue zeroValue = new ConstantInteger(0l, SymbolType.BYTE);
|
||||
dataChunk.addDataZeroFilled(AsmDataNumeric.Type.BYTE, paddingBytesAsm, (int)paddingSize, getEncoding(zeroValue));
|
||||
dataChunk.addDataZeroFilled(AsmDataNumeric.Type.BYTE, paddingBytesAsm, (int) paddingSize, getEncoding(zeroValue));
|
||||
}
|
||||
} else if(value instanceof StructZero) {
|
||||
final SymbolTypeStruct typeStruct = ((StructZero) value).getTypeStruct();
|
||||
@ -814,7 +813,7 @@ public class Pass4CodeGeneration {
|
||||
StatementSource statementSource = statement.getSource();
|
||||
if(warnFragmentMissing) {
|
||||
String stmtFormat = "";
|
||||
if(statementSource!=null)
|
||||
if(statementSource != null)
|
||||
stmtFormat = statementSource.format();
|
||||
program.getLog().append("Warning! Unknown fragment for statement " + statement.toString(program, false) + "\nMissing ASM fragment " + e.getFragmentSignature() + "\n" + stmtFormat);
|
||||
asm.addLine(new AsmInlineKickAsm(".assert \"Missing ASM fragment " + e.getFragmentSignature() + "\", 0, 1", 0L, 0L));
|
||||
@ -892,8 +891,8 @@ public class Pass4CodeGeneration {
|
||||
AsmFragmentInstanceSpecBuilder asmFragmentInstanceSpecBuilder = AsmFragmentInstanceSpecBuilder.makelong4(call, program);
|
||||
ensureEncoding(asm, asmFragmentInstanceSpecBuilder);
|
||||
generateAsm(asm, asmFragmentInstanceSpecBuilder.getAsmFragmentInstanceSpec());
|
||||
} else {
|
||||
throw new CompileError("Intrinsic procedure not supported "+procedure.toString(program));
|
||||
} else {
|
||||
throw new CompileError("Intrinsic procedure not supported " + procedure.toString(program));
|
||||
}
|
||||
} else if(Procedure.CallingConvention.PHI_CALL.equals(procedure.getCallingConvention())) {
|
||||
// Generate PHI transition
|
||||
@ -921,19 +920,18 @@ public class Pass4CodeGeneration {
|
||||
supported = true;
|
||||
} else if(procedureRVal instanceof PointerDereferenceSimple) {
|
||||
RValue pointer = ((PointerDereferenceSimple) procedureRVal).getPointer();
|
||||
if(pointer instanceof ConstantValue) {
|
||||
ensureEncoding(asm, pointer);
|
||||
asm.addInstruction("jsr", CpuAddressingMode.ABS, AsmFormat.getAsmConstant(program, (ConstantValue) pointer, 99, block.getScope()), false);
|
||||
asm.getCurrentChunk().setClobberOverwrite(CpuClobber.CLOBBER_ALL);
|
||||
supported = true;
|
||||
} else if(pointer instanceof VariableRef) {
|
||||
while(pointer instanceof CastValue)
|
||||
pointer = ((CastValue) pointer).getValue();
|
||||
if(pointer instanceof VariableRef) {
|
||||
Variable variable = getScope().getVariable((VariableRef) pointer);
|
||||
generateIndirectCall(asm, variable, block.getScope());
|
||||
asm.getCurrentChunk().setClobberOverwrite(CpuClobber.CLOBBER_ALL);
|
||||
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());
|
||||
} else {
|
||||
// Generate ASM for an indirect call
|
||||
AsmFragmentInstanceSpecBuilder asmFragmentInstanceSpecBuilder = AsmFragmentInstanceSpecBuilder.call(call, program);
|
||||
ensureEncoding(asm, asmFragmentInstanceSpecBuilder);
|
||||
generateAsm(asm, asmFragmentInstanceSpecBuilder.getAsmFragmentInstanceSpec());
|
||||
asm.getCurrentChunk().setClobberOverwrite(CpuClobber.CLOBBER_ALL);
|
||||
supported = true;
|
||||
}
|
||||
@ -1059,7 +1057,7 @@ public class Pass4CodeGeneration {
|
||||
entryName = entryFragment.getAsmFragmentInstanceSpec().getSignature();
|
||||
}
|
||||
try {
|
||||
asm.startChunk(procedure.getRef(), null, "interrupt(" + entryName+ ")");
|
||||
asm.startChunk(procedure.getRef(), null, "interrupt(" + entryName + ")");
|
||||
generateAsm(asm, entryFragment.getAsmFragmentInstanceSpec());
|
||||
} catch(AsmFragmentTemplateSynthesizer.UnknownFragmentException e) {
|
||||
throw new CompileError("Interrupt type not supported " + procedure.getInterruptType() + " int " + procedure.toString() + "\n" + e.getMessage());
|
||||
|
@ -3393,6 +3393,11 @@ public class TestProgramsFast extends TestPrograms {
|
||||
compileAndCompare("function-pointer-noarg-call.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionPointerReturn3() throws IOException {
|
||||
compileAndCompare("function-pointer-return-3.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFunctionPointerReturn2() throws IOException {
|
||||
compileAndCompare("function-pointer-return-2.c");
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Calling a function pointer with parameters
|
||||
// Reference the function without &
|
||||
// Calling a function pointer with return value
|
||||
// Reference the function without &, Call it without *
|
||||
|
||||
char * const RASTER = (char*)0xd012;
|
||||
char * const BORDER = (char*)0xd020;
|
||||
|
40
src/test/kc/function-pointer-return-3.c
Normal file
40
src/test/kc/function-pointer-return-3.c
Normal file
@ -0,0 +1,40 @@
|
||||
// Calling a function pointer with return value
|
||||
// Calling a function pointer inside a struct without *
|
||||
|
||||
|
||||
struct Task {
|
||||
char param;
|
||||
void (*handler)(char);
|
||||
};
|
||||
|
||||
char * const RASTER = (char*)0xd012;
|
||||
char * const BORDER = (char*)0xd020;
|
||||
char * const BACKGROUND = (char*)0xd021;
|
||||
|
||||
void set_border(char col) {
|
||||
*BORDER = col;
|
||||
}
|
||||
|
||||
void set_bg(char col) {
|
||||
*BACKGROUND = col;
|
||||
}
|
||||
|
||||
void run(struct Task* task) {
|
||||
task->handler(task->param);
|
||||
}
|
||||
|
||||
struct Task tasks[] = {
|
||||
{ 0, &set_border },
|
||||
{ 0, &set_bg },
|
||||
{ 1, &set_border },
|
||||
{ 2, &set_bg }
|
||||
};
|
||||
|
||||
|
||||
void main() {
|
||||
for(;;) {
|
||||
for(char i=0; i < sizeof(tasks)/sizeof(struct Task); i++) {
|
||||
run(tasks+i);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
Inlined call vicSelectGfxBank::$0 = call toDd00(vicSelectGfxBank::gfx)
|
||||
Inlined call call __init
|
||||
Inlined call call __init
|
||||
Calling convention STACK_CALL adding prepare/execute/finalize for call *musicInit
|
||||
Calling convention STACK_CALL adding prepare/execute/finalize for call *musicPlay
|
||||
|
||||
@ -31,7 +31,7 @@ __start: scope:[__start] from
|
||||
__start::__init1: scope:[__start] from __start
|
||||
to:__start::@1
|
||||
__start::@1: scope:[__start] from __start::__init1
|
||||
call main
|
||||
call main
|
||||
to:__start::@2
|
||||
__start::@2: scope:[__start] from __start::@1
|
||||
to:__start::@return
|
||||
@ -158,7 +158,7 @@ ASSEMBLER BEFORE OPTIMIZATION
|
||||
// main
|
||||
// Play the music
|
||||
main: {
|
||||
// [1] callexecute *musicInit
|
||||
// [1] callexecute *musicInit -- call__deref_pprc1
|
||||
// Initialize the music
|
||||
jsr musicInit
|
||||
jmp __b1
|
||||
@ -174,7 +174,7 @@ main: {
|
||||
__b2:
|
||||
// [3] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR) = ++ *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR
|
||||
// [4] callexecute *musicPlay
|
||||
// [4] callexecute *musicPlay -- call__deref_pprc1
|
||||
// Play the music
|
||||
jsr musicPlay
|
||||
jmp __b3
|
||||
@ -249,7 +249,7 @@ Score: 1066
|
||||
// Play the music
|
||||
main: {
|
||||
// (*musicInit)()
|
||||
// [1] callexecute *musicInit
|
||||
// [1] callexecute *musicInit -- call__deref_pprc1
|
||||
// Initialize the music
|
||||
jsr musicInit
|
||||
// Wait for the RASTER
|
||||
@ -265,7 +265,7 @@ main: {
|
||||
// [3] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR) = ++ *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR
|
||||
// (*musicPlay)()
|
||||
// [4] callexecute *musicPlay
|
||||
// [4] callexecute *musicPlay -- call__deref_pprc1
|
||||
// Play the music
|
||||
jsr musicPlay
|
||||
// main::@3
|
||||
|
@ -1,6 +1,6 @@
|
||||
Resolved forward reference irq_play to __interrupt(rom_sys_c64) void irq_play()
|
||||
Inlined call vicSelectGfxBank::$0 = call toDd00(vicSelectGfxBank::gfx)
|
||||
Inlined call call __init
|
||||
Inlined call call __init
|
||||
Calling convention STACK_CALL adding prepare/execute/finalize for call *musicInit
|
||||
Calling convention STACK_CALL adding prepare/execute/finalize for call *musicPlay
|
||||
|
||||
@ -42,7 +42,7 @@ __start: scope:[__start] from
|
||||
__start::__init1: scope:[__start] from __start
|
||||
to:__start::@1
|
||||
__start::@1: scope:[__start] from __start::__init1
|
||||
call main
|
||||
call main
|
||||
to:__start::@2
|
||||
__start::@2: scope:[__start] from __start::@1
|
||||
to:__start::@return
|
||||
@ -220,7 +220,7 @@ irq_play: {
|
||||
// interrupt(isr_rom_sys_c64_entry) -- isr_rom_sys_c64_entry
|
||||
// [0] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR) = ++ *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR
|
||||
// [1] callexecute *musicPlay
|
||||
// [1] callexecute *musicPlay -- call__deref_pprc1
|
||||
// Play SID
|
||||
jsr musicPlay
|
||||
jmp __b1
|
||||
@ -244,7 +244,7 @@ irq_play: {
|
||||
main: {
|
||||
// asm { sei }
|
||||
sei
|
||||
// [6] callexecute *musicInit
|
||||
// [6] callexecute *musicInit -- call__deref_pprc1
|
||||
jsr musicInit
|
||||
jmp __b1
|
||||
// main::@1
|
||||
@ -378,7 +378,7 @@ irq_play: {
|
||||
// [0] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR) = ++ *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR
|
||||
// (*musicPlay)()
|
||||
// [1] callexecute *musicPlay
|
||||
// [1] callexecute *musicPlay -- call__deref_pprc1
|
||||
// Play SID
|
||||
jsr musicPlay
|
||||
// irq_play::@1
|
||||
@ -403,7 +403,7 @@ main: {
|
||||
// asm { sei }
|
||||
sei
|
||||
// (*musicInit)()
|
||||
// [6] callexecute *musicInit
|
||||
// [6] callexecute *musicInit -- call__deref_pprc1
|
||||
jsr musicInit
|
||||
// main::@1
|
||||
// CIA1->INTERRUPT = CIA_INTERRUPT_CLEAR
|
||||
|
@ -52,7 +52,7 @@ Setting inferred volatile on symbol affected by address-of: memoryRemap256M::xVa
|
||||
Setting inferred volatile on symbol affected by address-of: memoryRemap256M::yVal in asm { ldalMb ldx#$0f ldyuMb ldz#$0f map ldaaVal ldxxVal ldyyVal ldzzVal map eom }
|
||||
Setting inferred volatile on symbol affected by address-of: memoryRemap256M::zVal in asm { ldalMb ldx#$0f ldyuMb ldz#$0f map ldaaVal ldxxVal ldyyVal ldzzVal map eom }
|
||||
Inlined call vicSelectGfxBank::$0 = call toDd00(vicSelectGfxBank::gfx)
|
||||
Inlined call call __init
|
||||
Inlined call call __init
|
||||
Eliminating unused variable with no statement memoryRemap::$0
|
||||
Eliminating unused variable with no statement memoryRemap::$4
|
||||
Eliminating unused variable with no statement memoryRemap::$5
|
||||
@ -98,7 +98,7 @@ memoryRemapBlock: scope:[memoryRemapBlock] from irq main::@6
|
||||
memoryRemap::remapBlocks#0 = memoryRemapBlock::blockBits#0
|
||||
memoryRemap::lowerPageOffset#0 = memoryRemapBlock::pageOffset#0
|
||||
memoryRemap::upperPageOffset#0 = memoryRemapBlock::pageOffset#0
|
||||
call memoryRemap
|
||||
call memoryRemap
|
||||
to:memoryRemapBlock::@1
|
||||
memoryRemapBlock::@1: scope:[memoryRemapBlock] from memoryRemapBlock
|
||||
to:memoryRemapBlock::@return
|
||||
@ -136,7 +136,7 @@ main: scope:[main] from __start::@1
|
||||
memoryRemap::remapBlocks#1 = 0
|
||||
memoryRemap::lowerPageOffset#1 = 0
|
||||
memoryRemap::upperPageOffset#1 = 0
|
||||
call memoryRemap
|
||||
call memoryRemap
|
||||
to:main::@5
|
||||
main::@5: scope:[main] from main
|
||||
*((byte*)VICIII+OFFSET_STRUCT_MOS4569_VICIII_KEY) = $47
|
||||
@ -152,12 +152,12 @@ main::@5: scope:[main] from main
|
||||
memcpy_dma4::src_bank#0 = 0
|
||||
memcpy_dma4::src#0 = (void*)upperCodeData
|
||||
memcpy_dma4::num#0 = main::$1
|
||||
call memcpy_dma4
|
||||
call memcpy_dma4
|
||||
to:main::@6
|
||||
main::@6: scope:[main] from main::@5
|
||||
memoryRemapBlock::blockPage#0 = $40
|
||||
memoryRemapBlock::memoryPage#0 = $100
|
||||
call memoryRemapBlock
|
||||
call memoryRemapBlock
|
||||
to:main::@7
|
||||
main::@7: scope:[main] from main::@6
|
||||
asm { lda#0 }
|
||||
@ -167,7 +167,7 @@ main::@1: scope:[main] from main::@7
|
||||
memoryRemap::remapBlocks#2 = 0
|
||||
memoryRemap::lowerPageOffset#2 = 0
|
||||
memoryRemap::upperPageOffset#2 = 0
|
||||
call memoryRemap
|
||||
call memoryRemap
|
||||
to:main::@8
|
||||
main::@8: scope:[main] from main::@1
|
||||
*((byte*)CIA1+OFFSET_STRUCT_MOS6526_CIA_INTERRUPT) = CIA_INTERRUPT_CLEAR
|
||||
@ -206,7 +206,7 @@ irq: scope:[irq] from
|
||||
*((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR) = ++ *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR)
|
||||
memoryRemapBlock::blockPage#1 = $40
|
||||
memoryRemapBlock::memoryPage#1 = $100
|
||||
call memoryRemapBlock
|
||||
call memoryRemapBlock
|
||||
to:irq::@4
|
||||
irq::@4: scope:[irq] from irq
|
||||
callexecute *musicPlay
|
||||
@ -215,7 +215,7 @@ irq::@1: scope:[irq] from irq::@4
|
||||
memoryRemap::remapBlocks#3 = 0
|
||||
memoryRemap::lowerPageOffset#3 = 0
|
||||
memoryRemap::upperPageOffset#3 = 0
|
||||
call memoryRemap
|
||||
call memoryRemap
|
||||
to:irq::@5
|
||||
irq::@5: scope:[irq] from irq::@1
|
||||
irq::raster#0 = *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_RASTER)
|
||||
@ -238,7 +238,7 @@ __start: scope:[__start] from
|
||||
__start::__init1: scope:[__start] from __start
|
||||
to:__start::@1
|
||||
__start::@1: scope:[__start] from __start::__init1
|
||||
call main
|
||||
call main
|
||||
to:__start::@2
|
||||
__start::@2: scope:[__start] from __start::@1
|
||||
to:__start::@return
|
||||
@ -666,7 +666,7 @@ __interrupt(hardware_clobber) void irq()
|
||||
irq: scope:[irq] from
|
||||
[0] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_IRQ_STATUS) = IRQ_RASTER
|
||||
[1] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR) = ++ *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR)
|
||||
[2] call memoryRemapBlock
|
||||
[2] call memoryRemapBlock
|
||||
to:irq::@4
|
||||
irq::@4: scope:[irq] from irq
|
||||
[3] phi()
|
||||
@ -674,7 +674,7 @@ irq::@4: scope:[irq] from irq
|
||||
to:irq::@1
|
||||
irq::@1: scope:[irq] from irq::@4
|
||||
[5] phi()
|
||||
[6] call memoryRemap
|
||||
[6] call memoryRemap
|
||||
to:irq::@5
|
||||
irq::@5: scope:[irq] from irq::@1
|
||||
[7] irq::raster#0 = *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_RASTER)
|
||||
@ -692,7 +692,7 @@ irq::@return: scope:[irq] from irq::@3
|
||||
void main()
|
||||
main: scope:[main] from
|
||||
asm { sei }
|
||||
[12] call memoryRemap
|
||||
[12] call memoryRemap
|
||||
to:main::@5
|
||||
main::@5: scope:[main] from main
|
||||
[13] *((byte*)VICIII+OFFSET_STRUCT_MOS4569_VICIII_KEY) = $47
|
||||
@ -702,11 +702,11 @@ main::@5: scope:[main] from main
|
||||
[17] *PROCPORT_DDR = PROCPORT_DDR_MEMORY_MASK
|
||||
[18] *PROCPORT = PROCPORT_RAM_IO
|
||||
[19] *((byte*)VICIV+OFFSET_STRUCT_MEGA65_VICIV_SIDBDRWD_LO) = 1
|
||||
[20] call memcpy_dma4
|
||||
[20] call memcpy_dma4
|
||||
to:main::@6
|
||||
main::@6: scope:[main] from main::@5
|
||||
[21] phi()
|
||||
[22] call memoryRemapBlock
|
||||
[22] call memoryRemapBlock
|
||||
to:main::@7
|
||||
main::@7: scope:[main] from main::@6
|
||||
asm { lda#0 }
|
||||
@ -714,7 +714,7 @@ main::@7: scope:[main] from main::@6
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main::@7
|
||||
[25] phi()
|
||||
[26] call memoryRemap
|
||||
[26] call memoryRemap
|
||||
to:main::@8
|
||||
main::@8: scope:[main] from main::@1
|
||||
[27] *((byte*)CIA1+OFFSET_STRUCT_MOS6526_CIA_INTERRUPT) = CIA_INTERRUPT_CLEAR
|
||||
@ -741,7 +741,7 @@ main::@4: scope:[main] from main::@3
|
||||
void memoryRemapBlock(byte memoryRemapBlock::blockPage , word memoryRemapBlock::memoryPage)
|
||||
memoryRemapBlock: scope:[memoryRemapBlock] from irq main::@6
|
||||
[40] phi()
|
||||
[41] call memoryRemap
|
||||
[41] call memoryRemap
|
||||
to:memoryRemapBlock::@return
|
||||
memoryRemapBlock::@return: scope:[memoryRemapBlock] from memoryRemapBlock
|
||||
[42] return
|
||||
@ -1137,7 +1137,7 @@ irq: {
|
||||
sta VICII+OFFSET_STRUCT_MOS6569_VICII_IRQ_STATUS
|
||||
// [1] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR) = ++ *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR
|
||||
// [2] call memoryRemapBlock
|
||||
// [2] call memoryRemapBlock
|
||||
// Remap memory to put music at $4000
|
||||
// [40] phi from irq to memoryRemapBlock [phi:irq->memoryRemapBlock]
|
||||
memoryRemapBlock_from_irq:
|
||||
@ -1147,7 +1147,7 @@ irq: {
|
||||
jmp __b4
|
||||
// irq::@4
|
||||
__b4:
|
||||
// [4] callexecute *musicPlay
|
||||
// [4] callexecute *musicPlay -- call__deref_pprc1
|
||||
// Play remapped SID
|
||||
jsr musicPlay
|
||||
// [5] phi from irq::@4 to irq::@1 [phi:irq::@4->irq::@1]
|
||||
@ -1155,7 +1155,7 @@ irq: {
|
||||
jmp __b1
|
||||
// irq::@1
|
||||
__b1:
|
||||
// [6] call memoryRemap
|
||||
// [6] call memoryRemap
|
||||
// Reset memory mapping
|
||||
// [43] phi from irq::@1 to memoryRemap [phi:irq::@1->memoryRemap]
|
||||
memoryRemap_from___b1:
|
||||
@ -1205,7 +1205,7 @@ main: {
|
||||
// asm { sei }
|
||||
// Stop IRQ's
|
||||
sei
|
||||
// [12] call memoryRemap
|
||||
// [12] call memoryRemap
|
||||
// Map memory to BANK 0 : 0x00XXXX - giving access to I/O
|
||||
// [43] phi from main to memoryRemap [phi:main->memoryRemap]
|
||||
memoryRemap_from_main:
|
||||
@ -1252,7 +1252,7 @@ main: {
|
||||
// open sideborder
|
||||
lda #1
|
||||
sta VICIV+OFFSET_STRUCT_MEGA65_VICIV_SIDBDRWD_LO
|
||||
// [20] call memcpy_dma4
|
||||
// [20] call memcpy_dma4
|
||||
// Transfer banked code/data to upper memory ($10000)
|
||||
jsr memcpy_dma4
|
||||
// [21] phi from main::@5 to main::@6 [phi:main::@5->main::@6]
|
||||
@ -1260,7 +1260,7 @@ main: {
|
||||
jmp __b6
|
||||
// main::@6
|
||||
__b6:
|
||||
// [22] call memoryRemapBlock
|
||||
// [22] call memoryRemapBlock
|
||||
// Remap [$4000-$5fff] to point to [$10000-$11fff]
|
||||
// [40] phi from main::@6 to memoryRemapBlock [phi:main::@6->memoryRemapBlock]
|
||||
memoryRemapBlock_from___b6:
|
||||
@ -1271,14 +1271,14 @@ main: {
|
||||
// asm { lda#0 }
|
||||
// Initialize SID
|
||||
lda #0
|
||||
// [24] callexecute *musicInit
|
||||
// [24] callexecute *musicInit -- call__deref_pprc1
|
||||
jsr musicInit
|
||||
// [25] phi from main::@7 to main::@1 [phi:main::@7->main::@1]
|
||||
__b1_from___b7:
|
||||
jmp __b1
|
||||
// main::@1
|
||||
__b1:
|
||||
// [26] call memoryRemap
|
||||
// [26] call memoryRemap
|
||||
// Reset memory mapping
|
||||
// [43] phi from main::@1 to memoryRemap [phi:main::@1->memoryRemap]
|
||||
memoryRemap_from___b1:
|
||||
@ -1374,7 +1374,7 @@ memoryRemapBlock: {
|
||||
// Which block is being remapped? (0-7)
|
||||
.const block = $40>>5
|
||||
.const blockBits = 1<<block
|
||||
// [41] call memoryRemap
|
||||
// [41] call memoryRemap
|
||||
// [43] phi from memoryRemapBlock to memoryRemap [phi:memoryRemapBlock->memoryRemap]
|
||||
memoryRemap_from_memoryRemapBlock:
|
||||
// [43] phi memoryRemap::upperPageOffset#4 = memoryRemapBlock::pageOffset#0 [phi:memoryRemapBlock->memoryRemap#0] -- vwuz1=vwuc1
|
||||
@ -1839,20 +1839,20 @@ irq: {
|
||||
// [1] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR) = ++ *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR) -- _deref_pbuc1=_inc__deref_pbuc1
|
||||
inc VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR
|
||||
// memoryRemapBlock(0x40, 0x100)
|
||||
// [2] call memoryRemapBlock
|
||||
// [2] call memoryRemapBlock
|
||||
// Remap memory to put music at $4000
|
||||
// [40] phi from irq to memoryRemapBlock [phi:irq->memoryRemapBlock]
|
||||
jsr memoryRemapBlock
|
||||
// [3] phi from irq to irq::@4 [phi:irq->irq::@4]
|
||||
// irq::@4
|
||||
// (*musicPlay)()
|
||||
// [4] callexecute *musicPlay
|
||||
// [4] callexecute *musicPlay -- call__deref_pprc1
|
||||
// Play remapped SID
|
||||
jsr musicPlay
|
||||
// [5] phi from irq::@4 to irq::@1 [phi:irq::@4->irq::@1]
|
||||
// irq::@1
|
||||
// memoryRemap(0,0,0)
|
||||
// [6] call memoryRemap
|
||||
// [6] call memoryRemap
|
||||
// Reset memory mapping
|
||||
// [43] phi from irq::@1 to memoryRemap [phi:irq::@1->memoryRemap]
|
||||
// [43] phi memoryRemap::upperPageOffset#4 = 0 [phi:irq::@1->memoryRemap#0] -- vwuz1=vbuc1
|
||||
@ -1897,7 +1897,7 @@ main: {
|
||||
// Stop IRQ's
|
||||
sei
|
||||
// memoryRemap(0,0,0)
|
||||
// [12] call memoryRemap
|
||||
// [12] call memoryRemap
|
||||
// Map memory to BANK 0 : 0x00XXXX - giving access to I/O
|
||||
// [43] phi from main to memoryRemap [phi:main->memoryRemap]
|
||||
// [43] phi memoryRemap::upperPageOffset#4 = 0 [phi:main->memoryRemap#0] -- vwuz1=vbuc1
|
||||
@ -1946,13 +1946,13 @@ main: {
|
||||
lda #1
|
||||
sta VICIV+OFFSET_STRUCT_MEGA65_VICIV_SIDBDRWD_LO
|
||||
// memcpy_dma4(1, (void*)0x0000, 0, upperCodeData, MUSIC_END-MUSIC)
|
||||
// [20] call memcpy_dma4
|
||||
// [20] call memcpy_dma4
|
||||
// Transfer banked code/data to upper memory ($10000)
|
||||
jsr memcpy_dma4
|
||||
// [21] phi from main::@5 to main::@6 [phi:main::@5->main::@6]
|
||||
// main::@6
|
||||
// memoryRemapBlock(0x40, 0x100)
|
||||
// [22] call memoryRemapBlock
|
||||
// [22] call memoryRemapBlock
|
||||
// Remap [$4000-$5fff] to point to [$10000-$11fff]
|
||||
// [40] phi from main::@6 to memoryRemapBlock [phi:main::@6->memoryRemapBlock]
|
||||
jsr memoryRemapBlock
|
||||
@ -1962,12 +1962,12 @@ main: {
|
||||
// Initialize SID
|
||||
lda #0
|
||||
// (*musicInit)()
|
||||
// [24] callexecute *musicInit
|
||||
// [24] callexecute *musicInit -- call__deref_pprc1
|
||||
jsr musicInit
|
||||
// [25] phi from main::@7 to main::@1 [phi:main::@7->main::@1]
|
||||
// main::@1
|
||||
// memoryRemap(0,0,0)
|
||||
// [26] call memoryRemap
|
||||
// [26] call memoryRemap
|
||||
// Reset memory mapping
|
||||
// [43] phi from main::@1 to memoryRemap [phi:main::@1->memoryRemap]
|
||||
// [43] phi memoryRemap::upperPageOffset#4 = 0 [phi:main::@1->memoryRemap#0] -- vwuz1=vbuc1
|
||||
@ -2062,7 +2062,7 @@ memoryRemapBlock: {
|
||||
.const block = $40>>5
|
||||
.const blockBits = 1<<block
|
||||
// memoryRemap(blockBits, pageOffset, pageOffset)
|
||||
// [41] call memoryRemap
|
||||
// [41] call memoryRemap
|
||||
// [43] phi from memoryRemapBlock to memoryRemap [phi:memoryRemapBlock->memoryRemap]
|
||||
// [43] phi memoryRemap::upperPageOffset#4 = memoryRemapBlock::pageOffset#0 [phi:memoryRemapBlock->memoryRemap#0] -- vwuz1=vwuc1
|
||||
lda #<pageOffset
|
||||
|
@ -23,7 +23,7 @@ Setting inferred volatile on symbol affected by address-of: memoryRemap256M::xVa
|
||||
Setting inferred volatile on symbol affected by address-of: memoryRemap256M::yVal in asm { ldalMb ldx#$0f ldyuMb ldz#$0f map ldaaVal ldxxVal ldyyVal ldzzVal map eom }
|
||||
Setting inferred volatile on symbol affected by address-of: memoryRemap256M::zVal in asm { ldalMb ldx#$0f ldyuMb ldz#$0f map ldaaVal ldxxVal ldyyVal ldzzVal map eom }
|
||||
Inlined call vicSelectGfxBank::$0 = call toDd00(vicSelectGfxBank::gfx)
|
||||
Inlined call call __init
|
||||
Inlined call call __init
|
||||
Eliminating unused variable with no statement memset::$2
|
||||
Eliminating unused variable with no statement irq::$1
|
||||
Eliminating unused variable with no statement irq::$17
|
||||
@ -89,7 +89,7 @@ main::@1: scope:[main] from main
|
||||
memset::str#0 = (void*)SCREEN
|
||||
memset::c#0 = ' '
|
||||
memset::num#0 = $28*$19
|
||||
call memset
|
||||
call memset
|
||||
memset::return#2 = memset::return#1
|
||||
to:main::@11
|
||||
main::@11: scope:[main] from main::@1
|
||||
@ -450,7 +450,7 @@ __start::__init1: scope:[__start] from __start
|
||||
greet_idx = 0
|
||||
to:__start::@1
|
||||
__start::@1: scope:[__start] from __start::__init1
|
||||
call main
|
||||
call main
|
||||
to:__start::@2
|
||||
__start::@2: scope:[__start] from __start::@1
|
||||
to:__start::@return
|
||||
@ -1326,7 +1326,7 @@ __start::__init1: scope:[__start] from __start
|
||||
to:__start::@1
|
||||
__start::@1: scope:[__start] from __start::__init1
|
||||
[6] phi()
|
||||
[7] call main
|
||||
[7] call main
|
||||
to:__start::@return
|
||||
__start::@return: scope:[__start] from __start::@1
|
||||
[8] return
|
||||
@ -1539,7 +1539,7 @@ main: scope:[main] from __start::@1
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[117] phi()
|
||||
[118] call memset
|
||||
[118] call memset
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1 main::@3
|
||||
[119] main::i1#2 = phi( main::@1/0, main::@3/main::i1#1 )
|
||||
@ -2203,7 +2203,7 @@ __start: {
|
||||
jmp __b1
|
||||
// __start::@1
|
||||
__b1:
|
||||
// [7] call main
|
||||
// [7] call main
|
||||
jsr main
|
||||
jmp __breturn
|
||||
// __start::@return
|
||||
@ -2255,7 +2255,7 @@ irq: {
|
||||
jmp __b4
|
||||
// irq::@4
|
||||
__b4:
|
||||
// [17] callexecute *songPlay
|
||||
// [17] callexecute *songPlay -- call__deref_pprc1
|
||||
// play music
|
||||
jsr songPlay
|
||||
jmp __b1
|
||||
@ -2734,14 +2734,14 @@ main: {
|
||||
// asm { lda#0 }
|
||||
// Initialize music
|
||||
lda #0
|
||||
// [116] callexecute *songInit
|
||||
// [116] callexecute *songInit -- call__deref_pprc1
|
||||
jsr songInit
|
||||
// [117] phi from main to main::@1 [phi:main->main::@1]
|
||||
__b1_from_main:
|
||||
jmp __b1
|
||||
// main::@1
|
||||
__b1:
|
||||
// [118] call memset
|
||||
// [118] call memset
|
||||
// Clear screen
|
||||
// [144] phi from main::@1 to memset [phi:main::@1->memset]
|
||||
memset_from___b1:
|
||||
@ -3396,7 +3396,7 @@ __start: {
|
||||
sta.z greet_idx
|
||||
// [6] phi from __start::__init1 to __start::@1 [phi:__start::__init1->__start::@1]
|
||||
// __start::@1
|
||||
// [7] call main
|
||||
// [7] call main
|
||||
jsr main
|
||||
// __start::@return
|
||||
// [8] return
|
||||
@ -3449,7 +3449,7 @@ irq: {
|
||||
// [16] phi from irq::@2 to irq::@4 [phi:irq::@2->irq::@4]
|
||||
// irq::@4
|
||||
// (*songPlay)()
|
||||
// [17] callexecute *songPlay
|
||||
// [17] callexecute *songPlay -- call__deref_pprc1
|
||||
// play music
|
||||
jsr songPlay
|
||||
// irq::@1
|
||||
@ -3946,12 +3946,12 @@ main: {
|
||||
// Initialize music
|
||||
lda #0
|
||||
// (*songInit)()
|
||||
// [116] callexecute *songInit
|
||||
// [116] callexecute *songInit -- call__deref_pprc1
|
||||
jsr songInit
|
||||
// [117] phi from main to main::@1 [phi:main->main::@1]
|
||||
// main::@1
|
||||
// memset(SCREEN, ' ', 40*25)
|
||||
// [118] call memset
|
||||
// [118] call memset
|
||||
// Clear screen
|
||||
// [144] phi from main::@1 to memset [phi:main::@1->memset]
|
||||
jsr memset
|
||||
|
@ -1,5 +1,5 @@
|
||||
// Calling a function pointer with parameters
|
||||
// Reference the function without &
|
||||
// Calling a function pointer with return value
|
||||
// Reference the function without &, Call it without *
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="function-pointer-return-2.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
|
@ -238,8 +238,8 @@ Uplifting [] best 194 combination
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Calling a function pointer with parameters
|
||||
// Reference the function without &
|
||||
// Calling a function pointer with return value
|
||||
// Reference the function without &, Call it without *
|
||||
// Upstart
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="function-pointer-return-2.prg", type="prg", segments="Program"]
|
||||
@ -391,8 +391,8 @@ FINAL ASSEMBLER
|
||||
Score: 95
|
||||
|
||||
// File Comments
|
||||
// Calling a function pointer with parameters
|
||||
// Reference the function without &
|
||||
// Calling a function pointer with return value
|
||||
// Reference the function without &, Call it without *
|
||||
// Upstart
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="function-pointer-return-2.prg", type="prg", segments="Program"]
|
||||
|
94
src/test/ref/function-pointer-return-3.asm
Normal file
94
src/test/ref/function-pointer-return-3.asm
Normal file
@ -0,0 +1,94 @@
|
||||
// Calling a function pointer with return value
|
||||
// Calling a function pointer inside a struct without *
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="function-pointer-return-3.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$0801]
|
||||
.segmentdef Code [start=$80d]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segment Basic
|
||||
:BasicUpstart(main)
|
||||
.const SIZEOF_STRUCT_TASK = 3
|
||||
.const OFFSET_STRUCT_TASK_HANDLER = 1
|
||||
.const STACK_BASE = $103
|
||||
.label BORDER = $d020
|
||||
.label BACKGROUND = $d021
|
||||
.segment Code
|
||||
main: {
|
||||
.label i = 2
|
||||
__b3:
|
||||
lda #0
|
||||
sta.z i
|
||||
__b1:
|
||||
// for(char i=0; i < sizeof(tasks)/sizeof(struct Task); i++)
|
||||
lda.z i
|
||||
cmp #4*SIZEOF_STRUCT_TASK/SIZEOF_STRUCT_TASK
|
||||
bcc __b2
|
||||
jmp __b3
|
||||
__b2:
|
||||
// tasks+i
|
||||
lda.z i
|
||||
asl
|
||||
clc
|
||||
adc.z i
|
||||
tax
|
||||
// run(tasks+i)
|
||||
txa
|
||||
clc
|
||||
adc #<tasks
|
||||
sta.z run.task
|
||||
lda #>tasks
|
||||
adc #0
|
||||
sta.z run.task+1
|
||||
jsr run
|
||||
// for(char i=0; i < sizeof(tasks)/sizeof(struct Task); i++)
|
||||
inc.z i
|
||||
jmp __b1
|
||||
}
|
||||
// set_bg(byte register(A) col)
|
||||
set_bg: {
|
||||
.const OFFSET_STACK_COL = 0
|
||||
tsx
|
||||
lda STACK_BASE+OFFSET_STACK_COL,x
|
||||
// *BACKGROUND = col
|
||||
sta BACKGROUND
|
||||
// }
|
||||
rts
|
||||
}
|
||||
// set_border(byte register(A) col)
|
||||
set_border: {
|
||||
.const OFFSET_STACK_COL = 0
|
||||
tsx
|
||||
lda STACK_BASE+OFFSET_STACK_COL,x
|
||||
// *BORDER = col
|
||||
sta BORDER
|
||||
// }
|
||||
rts
|
||||
}
|
||||
// run(struct Task* zp(3) task)
|
||||
run: {
|
||||
.label task = 3
|
||||
// task->handler(task->param)
|
||||
lda tasks,x
|
||||
pha
|
||||
ldy #OFFSET_STRUCT_TASK_HANDLER
|
||||
lda (task),y
|
||||
sta !+ +1
|
||||
iny
|
||||
lda (task),y
|
||||
sta !+ +2
|
||||
!:
|
||||
jsr 0
|
||||
pla
|
||||
// }
|
||||
rts
|
||||
}
|
||||
.segment Data
|
||||
tasks: .byte 0
|
||||
.word set_border
|
||||
.byte 0
|
||||
.word set_bg
|
||||
.byte 1
|
||||
.word set_border
|
||||
.byte 2
|
||||
.word set_bg
|
46
src/test/ref/function-pointer-return-3.cfg
Normal file
46
src/test/ref/function-pointer-return-3.cfg
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
void main()
|
||||
main: scope:[main] from
|
||||
[0] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1 main::@3
|
||||
[1] main::i#2 = phi( main/0, main::@3/main::i#1, main::@1/0 )
|
||||
[2] if(main::i#2<4*SIZEOF_STRUCT_TASK/SIZEOF_STRUCT_TASK) goto main::@2
|
||||
to:main::@1
|
||||
main::@2: scope:[main] from main::@1
|
||||
[3] main::$6 = main::i#2 << 1
|
||||
[4] main::$5 = main::$6 + main::i#2
|
||||
[5] run::task#0 = tasks + main::$5
|
||||
[6] call run
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2
|
||||
[7] main::i#1 = ++ main::i#2
|
||||
to:main::@1
|
||||
|
||||
__stackcall void set_bg(byte set_bg::col)
|
||||
set_bg: scope:[set_bg] from
|
||||
[8] set_bg::col#0 = stackidx(byte,set_bg::OFFSET_STACK_COL)
|
||||
[9] *BACKGROUND = set_bg::col#0
|
||||
to:set_bg::@return
|
||||
set_bg::@return: scope:[set_bg] from set_bg
|
||||
[10] return
|
||||
to:@return
|
||||
|
||||
__stackcall void set_border(byte set_border::col)
|
||||
set_border: scope:[set_border] from
|
||||
[11] set_border::col#0 = stackidx(byte,set_border::OFFSET_STACK_COL)
|
||||
[12] *BORDER = set_border::col#0
|
||||
to:set_border::@return
|
||||
set_border::@return: scope:[set_border] from set_border
|
||||
[13] return
|
||||
to:@return
|
||||
|
||||
void run(struct Task* run::task)
|
||||
run: scope:[run] from main::@2
|
||||
[14] stackpush(byte) = ((byte*)tasks)[main::$5]
|
||||
[15] callexecute *(((void(byte)**)run::task#0)[OFFSET_STRUCT_TASK_HANDLER])
|
||||
sideeffect stackpullbytes(1)
|
||||
to:run::@return
|
||||
run::@return: scope:[run] from run
|
||||
[17] return
|
||||
to:@return
|
646
src/test/ref/function-pointer-return-3.log
Normal file
646
src/test/ref/function-pointer-return-3.log
Normal file
@ -0,0 +1,646 @@
|
||||
Setting inferred __stackcall on procedure affected by address-of __stackcall void set_border(byte set_border::col) caused by statement void set_border(byte set_border::col)
|
||||
Setting inferred __stackcall on procedure affected by address-of __stackcall void set_bg(byte set_bg::col) caused by statement void set_bg(byte set_bg::col)
|
||||
Setting inferred __stackcall on procedure affected by address-of __stackcall void set_border(byte set_border::col) caused by statement __stackcall void set_border(byte set_border::col)
|
||||
Setting inferred __stackcall on procedure affected by address-of __stackcall void set_bg(byte set_bg::col) caused by statement __stackcall void set_bg(byte set_bg::col)
|
||||
Adding parameter assignment in __stackcall procedure set_border::col = param(set_border::col)
|
||||
Adding parameter assignment in __stackcall procedure set_bg::col = param(set_bg::col)
|
||||
Calling convention STACK_CALL adding prepare/execute/finalize for call *(*run::$1) *run::$2
|
||||
Calling convention STACK_CALL replacing param(set_border::col) with stackidx(byte,set_border::OFFSET_STACK_COL)
|
||||
Calling convention STACK_CALL replacing param(set_bg::col) with stackidx(byte,set_bg::OFFSET_STACK_COL)
|
||||
Calling convention STACK_CALL adding stack push stackpush(byte) = *run::$2
|
||||
|
||||
CONTROL FLOW GRAPH SSA
|
||||
|
||||
__stackcall void set_border(byte set_border::col)
|
||||
set_border: scope:[set_border] from
|
||||
set_border::col#0 = stackidx(byte,set_border::OFFSET_STACK_COL)
|
||||
*BORDER = set_border::col#0
|
||||
to:set_border::@return
|
||||
set_border::@return: scope:[set_border] from set_border
|
||||
return
|
||||
to:@return
|
||||
|
||||
__stackcall void set_bg(byte set_bg::col)
|
||||
set_bg: scope:[set_bg] from
|
||||
set_bg::col#0 = stackidx(byte,set_bg::OFFSET_STACK_COL)
|
||||
*BACKGROUND = set_bg::col#0
|
||||
to:set_bg::@return
|
||||
set_bg::@return: scope:[set_bg] from set_bg
|
||||
return
|
||||
to:@return
|
||||
|
||||
void run(struct Task* run::task)
|
||||
run: scope:[run] from main::@3
|
||||
run::task#1 = phi( main::@3/run::task#0 )
|
||||
run::$3 = (void(byte)**)run::task#1
|
||||
run::$1 = run::$3 + OFFSET_STRUCT_TASK_HANDLER
|
||||
run::$4 = (byte*)run::task#1
|
||||
run::$2 = run::$4 + OFFSET_STRUCT_TASK_PARAM
|
||||
stackpush(byte) = *run::$2
|
||||
callexecute *(*run::$1)
|
||||
sideeffect stackpullbytes(1)
|
||||
to:run::@return
|
||||
run::@return: scope:[run] from run
|
||||
return
|
||||
to:@return
|
||||
|
||||
void main()
|
||||
main: scope:[main] from __start
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@2
|
||||
main::i#0 = 0
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1 main::@4
|
||||
main::i#2 = phi( main::@1/main::i#0, main::@4/main::i#1 )
|
||||
main::$0 = sizeof tasks
|
||||
main::$1 = main::$0 / SIZEOF_STRUCT_TASK
|
||||
main::$2 = main::i#2 < main::$1
|
||||
if(main::$2) goto main::@3
|
||||
to:main::@1
|
||||
main::@3: scope:[main] from main::@2
|
||||
main::i#3 = phi( main::@2/main::i#2 )
|
||||
main::$5 = main::i#3 * SIZEOF_STRUCT_TASK
|
||||
main::$3 = tasks + main::$5
|
||||
run::task#0 = main::$3
|
||||
call run
|
||||
to:main::@4
|
||||
main::@4: scope:[main] from main::@3
|
||||
main::i#4 = phi( main::@3/main::i#3 )
|
||||
main::i#1 = ++ main::i#4
|
||||
to:main::@2
|
||||
main::@return: scope:[main] from
|
||||
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 byte* const BACKGROUND = (byte*)$d021
|
||||
constant byte* const BORDER = (byte*)$d020
|
||||
constant byte OFFSET_STRUCT_TASK_HANDLER = 1
|
||||
constant byte OFFSET_STRUCT_TASK_PARAM = 0
|
||||
constant byte SIZEOF_STRUCT_TASK = 3
|
||||
constant word STACK_BASE = $103
|
||||
void __start()
|
||||
void main()
|
||||
word~ main::$0
|
||||
word~ main::$1
|
||||
bool~ main::$2
|
||||
struct Task*~ main::$3
|
||||
byte~ main::$5
|
||||
byte main::i
|
||||
byte main::i#0
|
||||
byte main::i#1
|
||||
byte main::i#2
|
||||
byte main::i#3
|
||||
byte main::i#4
|
||||
void run(struct Task* run::task)
|
||||
void(byte)**~ run::$1
|
||||
byte*~ run::$2
|
||||
void(byte)**~ run::$3
|
||||
byte*~ run::$4
|
||||
struct Task* run::task
|
||||
struct Task* run::task#0
|
||||
struct Task* run::task#1
|
||||
__stackcall void set_bg(byte set_bg::col)
|
||||
constant byte set_bg::OFFSET_STACK_COL = 0
|
||||
byte set_bg::col
|
||||
byte set_bg::col#0
|
||||
__stackcall void set_border(byte set_border::col)
|
||||
constant byte set_border::OFFSET_STACK_COL = 0
|
||||
byte set_border::col
|
||||
byte set_border::col#0
|
||||
constant struct Task* tasks[] = { { param: 0, handler: &set_border }, { param: 0, handler: &set_bg }, { param: 1, handler: &set_border }, { param: 2, handler: &set_bg } }
|
||||
|
||||
Simplifying constant pointer cast (byte*) 53280
|
||||
Simplifying constant pointer cast (byte*) 53281
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Alias main::i#2 = main::i#3 main::i#4
|
||||
Alias run::task#0 = main::$3
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Identical Phi Values run::task#1 run::task#0
|
||||
Successful SSA optimization Pass2IdenticalPhiElimination
|
||||
Simple Condition main::$2 [20] if(main::i#2<main::$1) goto main::@3
|
||||
Successful SSA optimization Pass2ConditionalJumpSimplification
|
||||
Constant right-side identified [17] main::$0 = sizeof tasks
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant main::i#0 = 0
|
||||
Constant main::$0 = sizeof tasks
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Converting *(pointer+n) to pointer[n] [11] stackpush(byte) = *run::$2 -- run::$4[OFFSET_STRUCT_TASK_PARAM]
|
||||
Converting *(pointer+n) to pointer[n] [12] callexecute *(*run::$1) -- run::$3[OFFSET_STRUCT_TASK_HANDLER]
|
||||
Successful SSA optimization Pass2InlineDerefIdx
|
||||
Simplifying expression containing zero run::$4 in [10] run::$2 = run::$4 + OFFSET_STRUCT_TASK_PARAM
|
||||
Simplifying expression containing zero run::$4 in [11] stackpush(byte) = run::$4[OFFSET_STRUCT_TASK_PARAM]
|
||||
Successful SSA optimization PassNSimplifyExpressionWithZero
|
||||
Removing unused block main::@return
|
||||
Successful SSA optimization Pass2EliminateUnusedBlocks
|
||||
Eliminating unused variable run::$1 and assignment [7] run::$1 = run::$3 + OFFSET_STRUCT_TASK_HANDLER
|
||||
Eliminating unused variable run::$2 and assignment [9] run::$2 = run::$4
|
||||
Eliminating unused constant OFFSET_STRUCT_TASK_PARAM
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
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
|
||||
Resolving array sizeof() sizeof tasks
|
||||
Successful SSA optimization PassNSizeOfSimplification
|
||||
Constant right-side identified [13] main::$1 = main::$0 / SIZEOF_STRUCT_TASK
|
||||
Successful SSA optimization Pass2ConstantRValueConsolidation
|
||||
Constant main::$1 = main::$0/SIZEOF_STRUCT_TASK
|
||||
Successful SSA optimization Pass2ConstantIdentification
|
||||
Converting *(pointer+n) to pointer[n] [8] stackpush(byte) = *run::$4 -- ((byte*)tasks)[main::$5]
|
||||
Successful SSA optimization Pass2InlineDerefIdx
|
||||
Eliminating unused variable run::$4 and assignment [7] run::$4 = (byte*)run::task#0
|
||||
Successful SSA optimization PassNEliminateUnusedVars
|
||||
Adding number conversion cast (unumber) 4 in
|
||||
Successful SSA optimization PassNAddNumberTypeConversions
|
||||
Simplifying constant integer cast 4
|
||||
Successful SSA optimization PassNCastSimplification
|
||||
Finalized unsigned number type (byte) 4
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Constant value identified (byte*)tasks in [7] stackpush(byte) = ((byte*)tasks)[main::$5]
|
||||
Successful SSA optimization Pass2ConstantValues
|
||||
Inlining Noop Cast [6] run::$3 = (void(byte)**)run::task#0 keeping run::task#0
|
||||
Successful SSA optimization Pass2NopCastInlining
|
||||
Rewriting multiplication to use shift and addition[13] main::$5 = main::i#2 * SIZEOF_STRUCT_TASK
|
||||
Inlining constant with var siblings main::i#0
|
||||
Constant inlined main::$1 = 4*SIZEOF_STRUCT_TASK/SIZEOF_STRUCT_TASK
|
||||
Constant inlined main::i#0 = 0
|
||||
Constant inlined main::$0 = 4*SIZEOF_STRUCT_TASK
|
||||
Successful SSA optimization Pass2ConstantInlining
|
||||
Alias main::$5 = main::$7
|
||||
Successful SSA optimization Pass2AliasElimination
|
||||
Finalized unsigned number type (byte) 1
|
||||
Successful SSA optimization PassNFinalizeNumberTypeConversions
|
||||
Adding NOP phi() at start of main
|
||||
Adding NOP phi() at start of main::@1
|
||||
CALL GRAPH
|
||||
Calls in [main] to run:7
|
||||
Calls in [run] to null:17
|
||||
|
||||
Created 1 initial phi equivalence classes
|
||||
Coalesced [9] main::i#5 = main::i#1
|
||||
Coalesced down to 1 phi equivalence classes
|
||||
Culled Empty Block label main::@1
|
||||
Renumbering block main::@2 to main::@1
|
||||
Renumbering block main::@3 to main::@2
|
||||
Renumbering block main::@4 to main::@3
|
||||
Adding NOP phi() at start of main
|
||||
|
||||
FINAL CONTROL FLOW GRAPH
|
||||
|
||||
void main()
|
||||
main: scope:[main] from
|
||||
[0] phi()
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main main::@1 main::@3
|
||||
[1] main::i#2 = phi( main/0, main::@3/main::i#1, main::@1/0 )
|
||||
[2] if(main::i#2<4*SIZEOF_STRUCT_TASK/SIZEOF_STRUCT_TASK) goto main::@2
|
||||
to:main::@1
|
||||
main::@2: scope:[main] from main::@1
|
||||
[3] main::$6 = main::i#2 << 1
|
||||
[4] main::$5 = main::$6 + main::i#2
|
||||
[5] run::task#0 = tasks + main::$5
|
||||
[6] call run
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2
|
||||
[7] main::i#1 = ++ main::i#2
|
||||
to:main::@1
|
||||
|
||||
__stackcall void set_bg(byte set_bg::col)
|
||||
set_bg: scope:[set_bg] from
|
||||
[8] set_bg::col#0 = stackidx(byte,set_bg::OFFSET_STACK_COL)
|
||||
[9] *BACKGROUND = set_bg::col#0
|
||||
to:set_bg::@return
|
||||
set_bg::@return: scope:[set_bg] from set_bg
|
||||
[10] return
|
||||
to:@return
|
||||
|
||||
__stackcall void set_border(byte set_border::col)
|
||||
set_border: scope:[set_border] from
|
||||
[11] set_border::col#0 = stackidx(byte,set_border::OFFSET_STACK_COL)
|
||||
[12] *BORDER = set_border::col#0
|
||||
to:set_border::@return
|
||||
set_border::@return: scope:[set_border] from set_border
|
||||
[13] return
|
||||
to:@return
|
||||
|
||||
void run(struct Task* run::task)
|
||||
run: scope:[run] from main::@2
|
||||
[14] stackpush(byte) = ((byte*)tasks)[main::$5]
|
||||
[15] callexecute *(((void(byte)**)run::task#0)[OFFSET_STRUCT_TASK_HANDLER])
|
||||
sideeffect stackpullbytes(1)
|
||||
to:run::@return
|
||||
run::@return: scope:[run] from run
|
||||
[17] return
|
||||
to:@return
|
||||
|
||||
|
||||
VARIABLE REGISTER WEIGHTS
|
||||
void main()
|
||||
byte~ main::$5 61.5
|
||||
byte~ main::$6 22.0
|
||||
byte main::i
|
||||
byte main::i#1 22.0
|
||||
byte main::i#2 24.16666666666666
|
||||
void run(struct Task* run::task)
|
||||
struct Task* run::task
|
||||
struct Task* run::task#0 110.0
|
||||
__stackcall void set_bg(byte set_bg::col)
|
||||
byte set_bg::col
|
||||
byte set_bg::col#0 4.0
|
||||
__stackcall void set_border(byte set_border::col)
|
||||
byte set_border::col
|
||||
byte set_border::col#0 4.0
|
||||
|
||||
Initial phi equivalence classes
|
||||
[ main::i#2 main::i#1 ]
|
||||
Added variable main::$6 to live range equivalence class [ main::$6 ]
|
||||
Added variable main::$5 to live range equivalence class [ main::$5 ]
|
||||
Added variable run::task#0 to live range equivalence class [ run::task#0 ]
|
||||
Added variable set_bg::col#0 to live range equivalence class [ set_bg::col#0 ]
|
||||
Added variable set_border::col#0 to live range equivalence class [ set_border::col#0 ]
|
||||
Complete equivalence classes
|
||||
[ main::i#2 main::i#1 ]
|
||||
[ main::$6 ]
|
||||
[ main::$5 ]
|
||||
[ run::task#0 ]
|
||||
[ set_bg::col#0 ]
|
||||
[ set_border::col#0 ]
|
||||
Allocated zp[1]:2 [ main::i#2 main::i#1 ]
|
||||
Allocated zp[1]:3 [ main::$6 ]
|
||||
Allocated zp[1]:4 [ main::$5 ]
|
||||
Allocated zp[2]:5 [ run::task#0 ]
|
||||
Allocated zp[1]:7 [ set_bg::col#0 ]
|
||||
Allocated zp[1]:8 [ set_border::col#0 ]
|
||||
REGISTER UPLIFT POTENTIAL REGISTERS
|
||||
Statement [3] main::$6 = main::i#2 << 1 [ main::i#2 main::$6 ] ( [ main::i#2 main::$6 ] { } ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::i#2 main::i#1 ]
|
||||
Statement [4] main::$5 = main::$6 + main::i#2 [ main::i#2 main::$5 ] ( [ main::i#2 main::$5 ] { } ) always clobbers reg byte a
|
||||
Statement [5] run::task#0 = tasks + main::$5 [ main::i#2 main::$5 ] ( [ main::i#2 main::$5 ] { } ) always clobbers reg byte a
|
||||
Removing always clobbered register reg byte a as potential for zp[1]:4 [ main::$5 ]
|
||||
Statement [8] set_bg::col#0 = stackidx(byte,set_bg::OFFSET_STACK_COL) [ set_bg::col#0 ] ( [ set_bg::col#0 ] { } ) always clobbers reg byte a reg byte x
|
||||
Statement [11] set_border::col#0 = stackidx(byte,set_border::OFFSET_STACK_COL) [ set_border::col#0 ] ( [ set_border::col#0 ] { } ) always clobbers reg byte a reg byte x
|
||||
Statement [14] stackpush(byte) = ((byte*)tasks)[main::$5] [ ] ( run:6 [ main::i#2 ] { } ) always clobbers reg byte a
|
||||
Statement [15] callexecute *(((void(byte)**)run::task#0)[OFFSET_STRUCT_TASK_HANDLER]) [ ] ( run:6 [ main::i#2 ] { } ) always clobbers reg byte a reg byte x reg byte y
|
||||
Removing always clobbered register reg byte x as potential for zp[1]:2 [ main::i#2 main::i#1 ]
|
||||
Removing always clobbered register reg byte y as potential for zp[1]:2 [ main::i#2 main::i#1 ]
|
||||
Statement sideeffect stackpullbytes(1) always clobbers reg byte a
|
||||
Statement [2] if(main::i#2<4*SIZEOF_STRUCT_TASK/SIZEOF_STRUCT_TASK) goto main::@2 [ main::i#2 ] ( [ main::i#2 ] { } ) always clobbers reg byte a
|
||||
Statement [3] main::$6 = main::i#2 << 1 [ main::i#2 main::$6 ] ( [ main::i#2 main::$6 ] { } ) always clobbers reg byte a
|
||||
Statement [4] main::$5 = main::$6 + main::i#2 [ main::i#2 main::$5 ] ( [ main::i#2 main::$5 ] { } ) always clobbers reg byte a
|
||||
Statement [5] run::task#0 = tasks + main::$5 [ main::i#2 main::$5 ] ( [ main::i#2 main::$5 ] { } ) always clobbers reg byte a
|
||||
Statement [8] set_bg::col#0 = stackidx(byte,set_bg::OFFSET_STACK_COL) [ set_bg::col#0 ] ( [ set_bg::col#0 ] { } ) always clobbers reg byte a reg byte x
|
||||
Statement [11] set_border::col#0 = stackidx(byte,set_border::OFFSET_STACK_COL) [ set_border::col#0 ] ( [ set_border::col#0 ] { } ) always clobbers reg byte a reg byte x
|
||||
Statement [14] stackpush(byte) = ((byte*)tasks)[main::$5] [ ] ( run:6 [ main::i#2 ] { } ) always clobbers reg byte a
|
||||
Statement [15] callexecute *(((void(byte)**)run::task#0)[OFFSET_STRUCT_TASK_HANDLER]) [ ] ( run:6 [ main::i#2 ] { } ) always clobbers reg byte a reg byte x reg byte y
|
||||
Statement sideeffect stackpullbytes(1) always clobbers reg byte a
|
||||
Potential registers zp[1]:2 [ main::i#2 main::i#1 ] : zp[1]:2 ,
|
||||
Potential registers zp[1]:3 [ main::$6 ] : zp[1]:3 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp[1]:4 [ main::$5 ] : zp[1]:4 , reg byte x , reg byte y ,
|
||||
Potential registers zp[2]:5 [ run::task#0 ] : zp[2]:5 ,
|
||||
Potential registers zp[1]:7 [ set_bg::col#0 ] : zp[1]:7 , reg byte a , reg byte x , reg byte y ,
|
||||
Potential registers zp[1]:8 [ set_border::col#0 ] : zp[1]:8 , reg byte a , reg byte x , reg byte y ,
|
||||
|
||||
REGISTER UPLIFT SCOPES
|
||||
Uplift Scope [main] 61.5: zp[1]:4 [ main::$5 ] 46.17: zp[1]:2 [ main::i#2 main::i#1 ] 22: zp[1]:3 [ main::$6 ]
|
||||
Uplift Scope [run] 110: zp[2]:5 [ run::task#0 ]
|
||||
Uplift Scope [set_border] 4: zp[1]:8 [ set_border::col#0 ]
|
||||
Uplift Scope [set_bg] 4: zp[1]:7 [ set_bg::col#0 ]
|
||||
Uplift Scope [Task]
|
||||
Uplift Scope []
|
||||
|
||||
Uplifting [main] best 2669 combination reg byte x [ main::$5 ] zp[1]:2 [ main::i#2 main::i#1 ] reg byte a [ main::$6 ]
|
||||
Uplifting [run] best 2669 combination zp[2]:5 [ run::task#0 ]
|
||||
Uplifting [set_border] best 2663 combination reg byte a [ set_border::col#0 ]
|
||||
Uplifting [set_bg] best 2657 combination reg byte a [ set_bg::col#0 ]
|
||||
Uplifting [Task] best 2657 combination
|
||||
Uplifting [] best 2657 combination
|
||||
Attempting to uplift remaining variables inzp[1]:2 [ main::i#2 main::i#1 ]
|
||||
Uplifting [main] best 2657 combination zp[1]:2 [ main::i#2 main::i#1 ]
|
||||
Allocated (was zp[2]:5) zp[2]:3 [ run::task#0 ]
|
||||
|
||||
ASSEMBLER BEFORE OPTIMIZATION
|
||||
// File Comments
|
||||
// Calling a function pointer with return value
|
||||
// Calling a function pointer inside a struct without *
|
||||
// Upstart
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="function-pointer-return-3.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$0801]
|
||||
.segmentdef Code [start=$80d]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segment Basic
|
||||
:BasicUpstart(main)
|
||||
// Global Constants & labels
|
||||
.const SIZEOF_STRUCT_TASK = 3
|
||||
.const OFFSET_STRUCT_TASK_HANDLER = 1
|
||||
.const STACK_BASE = $103
|
||||
.label BORDER = $d020
|
||||
.label BACKGROUND = $d021
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
.label i = 2
|
||||
// [1] phi from main main::@1 to main::@1 [phi:main/main::@1->main::@1]
|
||||
__b1_from_main:
|
||||
__b1_from___b1:
|
||||
// [1] phi main::i#2 = 0 [phi:main/main::@1->main::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z i
|
||||
jmp __b1
|
||||
// main::@1
|
||||
__b1:
|
||||
// [2] if(main::i#2<4*SIZEOF_STRUCT_TASK/SIZEOF_STRUCT_TASK) goto main::@2 -- vbuz1_lt_vbuc1_then_la1
|
||||
lda.z i
|
||||
cmp #4*SIZEOF_STRUCT_TASK/SIZEOF_STRUCT_TASK
|
||||
bcc __b2
|
||||
jmp __b1_from___b1
|
||||
// main::@2
|
||||
__b2:
|
||||
// [3] main::$6 = main::i#2 << 1 -- vbuaa=vbuz1_rol_1
|
||||
lda.z i
|
||||
asl
|
||||
// [4] main::$5 = main::$6 + main::i#2 -- vbuxx=vbuaa_plus_vbuz1
|
||||
clc
|
||||
adc.z i
|
||||
tax
|
||||
// [5] run::task#0 = tasks + main::$5 -- pssz1=pssc1_plus_vbuxx
|
||||
txa
|
||||
clc
|
||||
adc #<tasks
|
||||
sta.z run.task
|
||||
lda #>tasks
|
||||
adc #0
|
||||
sta.z run.task+1
|
||||
// [6] call run
|
||||
jsr run
|
||||
jmp __b3
|
||||
// main::@3
|
||||
__b3:
|
||||
// [7] main::i#1 = ++ main::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc.z i
|
||||
// [1] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
|
||||
__b1_from___b3:
|
||||
// [1] phi main::i#2 = main::i#1 [phi:main::@3->main::@1#0] -- register_copy
|
||||
jmp __b1
|
||||
}
|
||||
// set_bg
|
||||
// set_bg(byte register(A) col)
|
||||
set_bg: {
|
||||
.const OFFSET_STACK_COL = 0
|
||||
// [8] set_bg::col#0 = stackidx(byte,set_bg::OFFSET_STACK_COL) -- vbuaa=_stackidxbyte_vbuc1
|
||||
tsx
|
||||
lda STACK_BASE+OFFSET_STACK_COL,x
|
||||
// [9] *BACKGROUND = set_bg::col#0 -- _deref_pbuc1=vbuaa
|
||||
sta BACKGROUND
|
||||
jmp __breturn
|
||||
// set_bg::@return
|
||||
__breturn:
|
||||
// [10] return
|
||||
rts
|
||||
}
|
||||
// set_border
|
||||
// set_border(byte register(A) col)
|
||||
set_border: {
|
||||
.const OFFSET_STACK_COL = 0
|
||||
// [11] set_border::col#0 = stackidx(byte,set_border::OFFSET_STACK_COL) -- vbuaa=_stackidxbyte_vbuc1
|
||||
tsx
|
||||
lda STACK_BASE+OFFSET_STACK_COL,x
|
||||
// [12] *BORDER = set_border::col#0 -- _deref_pbuc1=vbuaa
|
||||
sta BORDER
|
||||
jmp __breturn
|
||||
// set_border::@return
|
||||
__breturn:
|
||||
// [13] return
|
||||
rts
|
||||
}
|
||||
// run
|
||||
// run(struct Task* zp(3) task)
|
||||
run: {
|
||||
.label task = 3
|
||||
// [14] stackpush(byte) = ((byte*)tasks)[main::$5] -- _stackpushbyte_=pbuc1_derefidx_vbuxx
|
||||
lda tasks,x
|
||||
pha
|
||||
// [15] callexecute *(((void(byte)**)run::task#0)[OFFSET_STRUCT_TASK_HANDLER]) -- call__deref_(qprz1_derefidx_vbuc1)
|
||||
ldy #OFFSET_STRUCT_TASK_HANDLER
|
||||
lda (task),y
|
||||
sta !+ +1
|
||||
iny
|
||||
lda (task),y
|
||||
sta !+ +2
|
||||
!:
|
||||
jsr 0
|
||||
// sideeffect stackpullbytes(1) -- _stackpullbyte_1
|
||||
pla
|
||||
jmp __breturn
|
||||
// run::@return
|
||||
__breturn:
|
||||
// [17] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
.segment Data
|
||||
tasks: .byte 0
|
||||
.word set_border
|
||||
.byte 0
|
||||
.word set_bg
|
||||
.byte 1
|
||||
.word set_border
|
||||
.byte 2
|
||||
.word set_bg
|
||||
|
||||
ASSEMBLER OPTIMIZATIONS
|
||||
Removing instruction jmp __b1
|
||||
Removing instruction jmp __b3
|
||||
Removing instruction jmp __breturn
|
||||
Removing instruction jmp __breturn
|
||||
Removing instruction jmp __breturn
|
||||
Succesful ASM optimization Pass5NextJumpElimination
|
||||
Removing instruction __b1_from_main:
|
||||
Succesful ASM optimization Pass5RedundantLabelElimination
|
||||
Removing instruction __b3:
|
||||
Removing instruction __b1_from___b3:
|
||||
Removing instruction __breturn:
|
||||
Removing instruction __breturn:
|
||||
Removing instruction __breturn:
|
||||
Succesful ASM optimization Pass5UnusedLabelElimination
|
||||
Relabelling long label __b1_from___b1 to __b3
|
||||
Succesful ASM optimization Pass5RelabelLongLabels
|
||||
|
||||
FINAL SYMBOL TABLE
|
||||
constant byte* const BACKGROUND = (byte*) 53281
|
||||
constant byte* const BORDER = (byte*) 53280
|
||||
constant byte OFFSET_STRUCT_TASK_HANDLER = 1
|
||||
constant byte SIZEOF_STRUCT_TASK = 3
|
||||
constant word STACK_BASE = $103
|
||||
void main()
|
||||
byte~ main::$5 reg byte x 61.5
|
||||
byte~ main::$6 reg byte a 22.0
|
||||
byte main::i
|
||||
byte main::i#1 i zp[1]:2 22.0
|
||||
byte main::i#2 i zp[1]:2 24.16666666666666
|
||||
void run(struct Task* run::task)
|
||||
struct Task* run::task
|
||||
struct Task* run::task#0 task zp[2]:3 110.0
|
||||
__stackcall void set_bg(byte set_bg::col)
|
||||
constant byte set_bg::OFFSET_STACK_COL = 0
|
||||
byte set_bg::col
|
||||
byte set_bg::col#0 reg byte a 4.0
|
||||
__stackcall void set_border(byte set_border::col)
|
||||
constant byte set_border::OFFSET_STACK_COL = 0
|
||||
byte set_border::col
|
||||
byte set_border::col#0 reg byte a 4.0
|
||||
constant struct Task* tasks[] = { { param: 0, handler: &set_border }, { param: 0, handler: &set_bg }, { param: 1, handler: &set_border }, { param: 2, handler: &set_bg } }
|
||||
|
||||
zp[1]:2 [ main::i#2 main::i#1 ]
|
||||
reg byte a [ main::$6 ]
|
||||
reg byte x [ main::$5 ]
|
||||
zp[2]:3 [ run::task#0 ]
|
||||
reg byte a [ set_bg::col#0 ]
|
||||
reg byte a [ set_border::col#0 ]
|
||||
|
||||
|
||||
FINAL ASSEMBLER
|
||||
Score: 2318
|
||||
|
||||
// File Comments
|
||||
// Calling a function pointer with return value
|
||||
// Calling a function pointer inside a struct without *
|
||||
// Upstart
|
||||
// Commodore 64 PRG executable file
|
||||
.file [name="function-pointer-return-3.prg", type="prg", segments="Program"]
|
||||
.segmentdef Program [segments="Basic, Code, Data"]
|
||||
.segmentdef Basic [start=$0801]
|
||||
.segmentdef Code [start=$80d]
|
||||
.segmentdef Data [startAfter="Code"]
|
||||
.segment Basic
|
||||
:BasicUpstart(main)
|
||||
// Global Constants & labels
|
||||
.const SIZEOF_STRUCT_TASK = 3
|
||||
.const OFFSET_STRUCT_TASK_HANDLER = 1
|
||||
.const STACK_BASE = $103
|
||||
.label BORDER = $d020
|
||||
.label BACKGROUND = $d021
|
||||
.segment Code
|
||||
// main
|
||||
main: {
|
||||
.label i = 2
|
||||
// [1] phi from main main::@1 to main::@1 [phi:main/main::@1->main::@1]
|
||||
__b3:
|
||||
// [1] phi main::i#2 = 0 [phi:main/main::@1->main::@1#0] -- vbuz1=vbuc1
|
||||
lda #0
|
||||
sta.z i
|
||||
// main::@1
|
||||
__b1:
|
||||
// for(char i=0; i < sizeof(tasks)/sizeof(struct Task); i++)
|
||||
// [2] if(main::i#2<4*SIZEOF_STRUCT_TASK/SIZEOF_STRUCT_TASK) goto main::@2 -- vbuz1_lt_vbuc1_then_la1
|
||||
lda.z i
|
||||
cmp #4*SIZEOF_STRUCT_TASK/SIZEOF_STRUCT_TASK
|
||||
bcc __b2
|
||||
jmp __b3
|
||||
// main::@2
|
||||
__b2:
|
||||
// tasks+i
|
||||
// [3] main::$6 = main::i#2 << 1 -- vbuaa=vbuz1_rol_1
|
||||
lda.z i
|
||||
asl
|
||||
// [4] main::$5 = main::$6 + main::i#2 -- vbuxx=vbuaa_plus_vbuz1
|
||||
clc
|
||||
adc.z i
|
||||
tax
|
||||
// run(tasks+i)
|
||||
// [5] run::task#0 = tasks + main::$5 -- pssz1=pssc1_plus_vbuxx
|
||||
txa
|
||||
clc
|
||||
adc #<tasks
|
||||
sta.z run.task
|
||||
lda #>tasks
|
||||
adc #0
|
||||
sta.z run.task+1
|
||||
// [6] call run
|
||||
jsr run
|
||||
// main::@3
|
||||
// for(char i=0; i < sizeof(tasks)/sizeof(struct Task); i++)
|
||||
// [7] main::i#1 = ++ main::i#2 -- vbuz1=_inc_vbuz1
|
||||
inc.z i
|
||||
// [1] phi from main::@3 to main::@1 [phi:main::@3->main::@1]
|
||||
// [1] phi main::i#2 = main::i#1 [phi:main::@3->main::@1#0] -- register_copy
|
||||
jmp __b1
|
||||
}
|
||||
// set_bg
|
||||
// set_bg(byte register(A) col)
|
||||
set_bg: {
|
||||
.const OFFSET_STACK_COL = 0
|
||||
// [8] set_bg::col#0 = stackidx(byte,set_bg::OFFSET_STACK_COL) -- vbuaa=_stackidxbyte_vbuc1
|
||||
tsx
|
||||
lda STACK_BASE+OFFSET_STACK_COL,x
|
||||
// *BACKGROUND = col
|
||||
// [9] *BACKGROUND = set_bg::col#0 -- _deref_pbuc1=vbuaa
|
||||
sta BACKGROUND
|
||||
// set_bg::@return
|
||||
// }
|
||||
// [10] return
|
||||
rts
|
||||
}
|
||||
// set_border
|
||||
// set_border(byte register(A) col)
|
||||
set_border: {
|
||||
.const OFFSET_STACK_COL = 0
|
||||
// [11] set_border::col#0 = stackidx(byte,set_border::OFFSET_STACK_COL) -- vbuaa=_stackidxbyte_vbuc1
|
||||
tsx
|
||||
lda STACK_BASE+OFFSET_STACK_COL,x
|
||||
// *BORDER = col
|
||||
// [12] *BORDER = set_border::col#0 -- _deref_pbuc1=vbuaa
|
||||
sta BORDER
|
||||
// set_border::@return
|
||||
// }
|
||||
// [13] return
|
||||
rts
|
||||
}
|
||||
// run
|
||||
// run(struct Task* zp(3) task)
|
||||
run: {
|
||||
.label task = 3
|
||||
// task->handler(task->param)
|
||||
// [14] stackpush(byte) = ((byte*)tasks)[main::$5] -- _stackpushbyte_=pbuc1_derefidx_vbuxx
|
||||
lda tasks,x
|
||||
pha
|
||||
// [15] callexecute *(((void(byte)**)run::task#0)[OFFSET_STRUCT_TASK_HANDLER]) -- call__deref_(qprz1_derefidx_vbuc1)
|
||||
ldy #OFFSET_STRUCT_TASK_HANDLER
|
||||
lda (task),y
|
||||
sta !+ +1
|
||||
iny
|
||||
lda (task),y
|
||||
sta !+ +2
|
||||
!:
|
||||
jsr 0
|
||||
// sideeffect stackpullbytes(1) -- _stackpullbyte_1
|
||||
pla
|
||||
// run::@return
|
||||
// }
|
||||
// [17] return
|
||||
rts
|
||||
}
|
||||
// File Data
|
||||
.segment Data
|
||||
tasks: .byte 0
|
||||
.word set_border
|
||||
.byte 0
|
||||
.word set_bg
|
||||
.byte 1
|
||||
.word set_border
|
||||
.byte 2
|
||||
.word set_bg
|
||||
|
30
src/test/ref/function-pointer-return-3.sym
Normal file
30
src/test/ref/function-pointer-return-3.sym
Normal file
@ -0,0 +1,30 @@
|
||||
constant byte* const BACKGROUND = (byte*) 53281
|
||||
constant byte* const BORDER = (byte*) 53280
|
||||
constant byte OFFSET_STRUCT_TASK_HANDLER = 1
|
||||
constant byte SIZEOF_STRUCT_TASK = 3
|
||||
constant word STACK_BASE = $103
|
||||
void main()
|
||||
byte~ main::$5 reg byte x 61.5
|
||||
byte~ main::$6 reg byte a 22.0
|
||||
byte main::i
|
||||
byte main::i#1 i zp[1]:2 22.0
|
||||
byte main::i#2 i zp[1]:2 24.16666666666666
|
||||
void run(struct Task* run::task)
|
||||
struct Task* run::task
|
||||
struct Task* run::task#0 task zp[2]:3 110.0
|
||||
__stackcall void set_bg(byte set_bg::col)
|
||||
constant byte set_bg::OFFSET_STACK_COL = 0
|
||||
byte set_bg::col
|
||||
byte set_bg::col#0 reg byte a 4.0
|
||||
__stackcall void set_border(byte set_border::col)
|
||||
constant byte set_border::OFFSET_STACK_COL = 0
|
||||
byte set_border::col
|
||||
byte set_border::col#0 reg byte a 4.0
|
||||
constant struct Task* tasks[] = { { param: 0, handler: &set_border }, { param: 0, handler: &set_bg }, { param: 1, handler: &set_border }, { param: 2, handler: &set_bg } }
|
||||
|
||||
zp[1]:2 [ main::i#2 main::i#1 ]
|
||||
reg byte a [ main::$6 ]
|
||||
reg byte x [ main::$5 ]
|
||||
zp[2]:3 [ run::task#0 ]
|
||||
reg byte a [ set_bg::col#0 ]
|
||||
reg byte a [ set_border::col#0 ]
|
Loading…
Reference in New Issue
Block a user