Loading link script "kernalload.ld" Inlined call vicSelectGfxBank::$0 = call toDd00 vicSelectGfxBank::gfx Inlined call main::$3 = call toSpritePtr LOAD_SPRITE CONTROL FLOW GRAPH SSA word strlen(byte* strlen::str) strlen: scope:[strlen] from setnam strlen::str#4 = phi( setnam/strlen::str#1 ) strlen::len#0 = 0 to:strlen::@1 strlen::@1: scope:[strlen] from strlen strlen::@2 strlen::len#4 = phi( strlen/strlen::len#0, strlen::@2/strlen::len#1 ) strlen::str#2 = phi( strlen/strlen::str#4, strlen::@2/strlen::str#0 ) strlen::$0 = 0 != *strlen::str#2 if(strlen::$0) goto strlen::@2 to:strlen::@3 strlen::@2: scope:[strlen] from strlen::@1 strlen::str#3 = phi( strlen::@1/strlen::str#2 ) strlen::len#2 = phi( strlen::@1/strlen::len#4 ) strlen::len#1 = ++ strlen::len#2 strlen::str#0 = ++ strlen::str#3 to:strlen::@1 strlen::@3: scope:[strlen] from strlen::@1 strlen::len#3 = phi( strlen::@1/strlen::len#4 ) strlen::return#0 = strlen::len#3 to:strlen::@return strlen::@return: scope:[strlen] from strlen::@3 strlen::return#3 = phi( strlen::@3/strlen::return#0 ) strlen::return#1 = strlen::return#3 return to:@return void main() main: scope:[main] from __start loadFileToMemory::device#0 = 8 loadFileToMemory::filename#0 = main::filename loadFileToMemory::address#0 = LOAD_SPRITE call loadFileToMemory loadFileToMemory::return#0 = loadFileToMemory::return#2 to:main::@4 main::@4: scope:[main] from main loadFileToMemory::return#3 = phi( main/loadFileToMemory::return#0 ) main::$0 = loadFileToMemory::return#3 main::status#0 = main::$0 main::$1 = main::status#0 != $ff main::$2 = ! main::$1 if(main::$2) goto main::@1 to:main::@2 main::@1: scope:[main] from main::@4 main::@5 *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE) = 1 main::toSpritePtr1_sprite#0 = LOAD_SPRITE to:main::toSpritePtr1 main::toSpritePtr1: scope:[main] from main::@1 main::toSpritePtr1_sprite#1 = phi( main::@1/main::toSpritePtr1_sprite#0 ) main::toSpritePtr1_$1 = (word)main::toSpritePtr1_sprite#1 main::toSpritePtr1_$0 = main::toSpritePtr1_$1 / $40 main::toSpritePtr1_return#0 = (byte)main::toSpritePtr1_$0 to:main::toSpritePtr1_@return main::toSpritePtr1_@return: scope:[main] from main::toSpritePtr1 main::toSpritePtr1_return#2 = phi( main::toSpritePtr1/main::toSpritePtr1_return#0 ) main::toSpritePtr1_return#1 = main::toSpritePtr1_return#2 to:main::@3 main::@3: scope:[main] from main::toSpritePtr1_@return main::toSpritePtr1_return#3 = phi( main::toSpritePtr1_@return/main::toSpritePtr1_return#1 ) main::$3 = main::toSpritePtr1_return#3 SPRITES_PTR[0] = main::$3 SPRITES_COLOR[0] = GREEN SPRITES_XPOS[0] = $15 SPRITES_YPOS[0] = $33 to:main::@return main::@2: scope:[main] from main::@4 main::status#1 = phi( main::@4/main::status#0 ) *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR) = 2 error::err#0 = main::status#1 call error to:main::@5 main::@5: scope:[main] from main::@2 to:main::@1 main::@return: scope:[main] from main::@3 return to:@return byte loadFileToMemory(byte loadFileToMemory::device , byte* loadFileToMemory::filename , byte* loadFileToMemory::address) loadFileToMemory: scope:[loadFileToMemory] from main loadFileToMemory::address#3 = phi( main/loadFileToMemory::address#0 ) loadFileToMemory::device#2 = phi( main/loadFileToMemory::device#0 ) loadFileToMemory::filename#1 = phi( main/loadFileToMemory::filename#0 ) setnam::filename#0 = loadFileToMemory::filename#1 call setnam to:loadFileToMemory::@1 loadFileToMemory::@1: scope:[loadFileToMemory] from loadFileToMemory loadFileToMemory::address#2 = phi( loadFileToMemory/loadFileToMemory::address#3 ) loadFileToMemory::device#1 = phi( loadFileToMemory/loadFileToMemory::device#2 ) setlfs::device#0 = loadFileToMemory::device#1 call setlfs to:loadFileToMemory::@2 loadFileToMemory::@2: scope:[loadFileToMemory] from loadFileToMemory::@1 loadFileToMemory::address#1 = phi( loadFileToMemory::@1/loadFileToMemory::address#2 ) load::address#0 = loadFileToMemory::address#1 load::verify#0 = false call load load::return#0 = load::return#2 to:loadFileToMemory::@3 loadFileToMemory::@3: scope:[loadFileToMemory] from loadFileToMemory::@2 load::return#3 = phi( loadFileToMemory::@2/load::return#0 ) loadFileToMemory::$2 = load::return#3 loadFileToMemory::return#1 = loadFileToMemory::$2 to:loadFileToMemory::@return loadFileToMemory::@return: scope:[loadFileToMemory] from loadFileToMemory::@3 loadFileToMemory::return#4 = phi( loadFileToMemory::@3/loadFileToMemory::return#1 ) loadFileToMemory::return#2 = loadFileToMemory::return#4 return to:@return void error(byte error::err) error: scope:[error] from main::@2 error::err#1 = phi( main::@2/error::err#0 ) *error::errCode = error::err#1 asm { ldxerrCode jsr$a437 } to:error::@return error::@return: scope:[error] from error return to:@return void setnam(byte* setnam::filename) setnam: scope:[setnam] from loadFileToMemory setnam::filename#1 = phi( loadFileToMemory/setnam::filename#0 ) strlen::str#1 = setnam::filename#1 call strlen strlen::return#2 = strlen::return#1 to:setnam::@1 setnam::@1: scope:[setnam] from setnam setnam::filename#2 = phi( setnam/setnam::filename#1 ) strlen::return#4 = phi( setnam/strlen::return#2 ) setnam::$0 = strlen::return#4 *setnam::filename_len = (byte)setnam::$0 *setnam::filename_ptr = setnam::filename#2 asm { ldafilename_len ldxfilename_ptr ldyfilename_ptr+1 jsr$ffbd } to:setnam::@return setnam::@return: scope:[setnam] from setnam::@1 return to:@return void setlfs(byte setlfs::device) setlfs: scope:[setlfs] from loadFileToMemory::@1 setlfs::device#1 = phi( loadFileToMemory::@1/setlfs::device#0 ) *setlfs::deviceNum = setlfs::device#1 asm { ldxdeviceNum lda#1 ldy#0 jsr$ffba } to:setlfs::@return setlfs::@return: scope:[setlfs] from setlfs return to:@return byte load(byte* load::address , bool load::verify) load: scope:[load] from loadFileToMemory::@2 load::address#1 = phi( loadFileToMemory::@2/load::address#0 ) load::verify#1 = phi( loadFileToMemory::@2/load::verify#0 ) *load::loadOrVerify = (byte)load::verify#1 *load::loadAddress = load::address#1 asm { ldxloadAddress ldyloadAddress+1 ldaloadOrVerify jsr$ffd5 bcserror lda#$ff error: stastatus } load::return#1 = *load::status to:load::@return load::@return: scope:[load] from load load::return#4 = phi( load/load::return#1 ) load::return#2 = load::return#4 return to:@return void __start() __start: scope:[__start] from call main to:__start::@1 __start::@1: scope:[__start] from __start to:__start::@return __start::@return: scope:[__start] from __start::@1 return to:@return SYMBOL TABLE SSA const nomodify byte GREEN = 5 const nomodify byte* LOAD_SPRITE = (byte*)$3000 const nomodify word OFFSET_SPRITE_PTRS = $3f8 const byte OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR = $20 const byte OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE = $15 const nomodify byte* SCREEN = (byte*)$400 const byte* SPRITE[] = kickasm {{ .var pic = LoadPicture("sprite.png", List().add($000000, $ffffff)) .for (var y=0; y<21; y++) .for (var x=0;x<3; x++) .byte pic.getSinglecolorByte(x,y) }} const nomodify byte* SPRITES_COLOR = (byte*)$d027 const nomodify byte* SPRITES_PTR = SCREEN+OFFSET_SPRITE_PTRS const nomodify byte* SPRITES_XPOS = (byte*)$d000 const nomodify byte* SPRITES_YPOS = (byte*)$d001 const nomodify struct MOS6569_VICII* VICII = (struct MOS6569_VICII*)$d000 void __start() void error(byte error::err) byte error::err byte error::err#0 byte error::err#1 const nomodify byte* error::errCode = (byte*)$ff byte load(byte* load::address , bool load::verify) byte* load::address byte* load::address#0 byte* load::address#1 const byte** load::loadAddress = (byte**)$fe const byte* load::loadOrVerify = (byte*)$fd byte load::return byte load::return#0 byte load::return#1 byte load::return#2 byte load::return#3 byte load::return#4 const byte* load::status = (byte*)$fd bool load::verify bool load::verify#0 bool load::verify#1 byte loadFileToMemory(byte loadFileToMemory::device , byte* loadFileToMemory::filename , byte* loadFileToMemory::address) byte~ loadFileToMemory::$2 byte* loadFileToMemory::address byte* loadFileToMemory::address#0 byte* loadFileToMemory::address#1 byte* loadFileToMemory::address#2 byte* loadFileToMemory::address#3 byte loadFileToMemory::device byte loadFileToMemory::device#0 byte loadFileToMemory::device#1 byte loadFileToMemory::device#2 byte* loadFileToMemory::filename byte* loadFileToMemory::filename#0 byte* loadFileToMemory::filename#1 byte loadFileToMemory::return byte loadFileToMemory::return#0 byte loadFileToMemory::return#1 byte loadFileToMemory::return#2 byte loadFileToMemory::return#3 byte loadFileToMemory::return#4 void main() byte~ main::$0 bool~ main::$1 bool~ main::$2 byte~ main::$3 const byte* main::filename[7] = "SPRITE" byte main::status byte main::status#0 byte main::status#1 number~ main::toSpritePtr1_$0 word~ main::toSpritePtr1_$1 byte main::toSpritePtr1_return byte main::toSpritePtr1_return#0 byte main::toSpritePtr1_return#1 byte main::toSpritePtr1_return#2 byte main::toSpritePtr1_return#3 byte* main::toSpritePtr1_sprite byte* main::toSpritePtr1_sprite#0 byte* main::toSpritePtr1_sprite#1 void setlfs(byte setlfs::device) byte setlfs::device byte setlfs::device#0 byte setlfs::device#1 const nomodify byte* setlfs::deviceNum = (byte*)$ff void setnam(byte* setnam::filename) word~ setnam::$0 byte* setnam::filename byte* setnam::filename#0 byte* setnam::filename#1 byte* setnam::filename#2 const nomodify byte* setnam::filename_len = (byte*)$fd const nomodify byte** setnam::filename_ptr = (byte**)$fe word strlen(byte* strlen::str) bool~ strlen::$0 word strlen::len word strlen::len#0 word strlen::len#1 word strlen::len#2 word strlen::len#3 word strlen::len#4 word strlen::return word strlen::return#0 word strlen::return#1 word strlen::return#2 word strlen::return#3 word strlen::return#4 byte* strlen::str byte* strlen::str#0 byte* strlen::str#1 byte* strlen::str#2 byte* strlen::str#3 byte* strlen::str#4 Adding number conversion cast (unumber) 0 in strlen::$0 = 0 != *strlen::str#2 Adding number conversion cast (unumber) 8 in loadFileToMemory::device#0 = 8 Adding number conversion cast (unumber) $ff in main::$1 = main::status#0 != $ff Adding number conversion cast (unumber) 1 in *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE) = 1 Adding number conversion cast (unumber) $40 in main::toSpritePtr1_$0 = main::toSpritePtr1_$1 / $40 Adding number conversion cast (unumber) main::toSpritePtr1_$0 in main::toSpritePtr1_$0 = main::toSpritePtr1_$1 / (unumber)$40 Adding number conversion cast (unumber) 0 in SPRITES_PTR[0] = main::$3 Adding number conversion cast (unumber) 0 in SPRITES_COLOR[0] = GREEN Adding number conversion cast (unumber) $15 in SPRITES_XPOS[0] = $15 Adding number conversion cast (unumber) 0 in SPRITES_XPOS[0] = ((unumber)) $15 Adding number conversion cast (unumber) $33 in SPRITES_YPOS[0] = $33 Adding number conversion cast (unumber) 0 in SPRITES_YPOS[0] = ((unumber)) $33 Adding number conversion cast (unumber) 2 in *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR) = 2 Successful SSA optimization PassNAddNumberTypeConversions Inlining cast loadFileToMemory::device#0 = (unumber)8 Inlining cast *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE) = (unumber)1 Inlining cast SPRITES_XPOS[(unumber)0] = (unumber)$15 Inlining cast SPRITES_YPOS[(unumber)0] = (unumber)$33 Inlining cast *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR) = (unumber)2 Successful SSA optimization Pass2InlineCast Simplifying constant pointer cast (byte*) 53248 Simplifying constant pointer cast (byte*) 53249 Simplifying constant pointer cast (byte*) 53287 Simplifying constant pointer cast (struct MOS6569_VICII*) 53248 Simplifying constant pointer cast (byte*) 12288 Simplifying constant pointer cast (byte*) 1024 Simplifying constant pointer cast (byte*) 255 Simplifying constant pointer cast (byte*) 253 Simplifying constant pointer cast (byte**) 254 Simplifying constant pointer cast (byte*) 255 Simplifying constant pointer cast (byte*) 253 Simplifying constant pointer cast (byte**) 254 Simplifying constant pointer cast (byte*) 253 Simplifying constant integer cast 0 Simplifying constant integer cast 8 Simplifying constant integer cast $ff Simplifying constant integer cast 1 Simplifying constant integer cast $40 Simplifying constant integer cast 0 Simplifying constant integer cast 0 Simplifying constant integer cast $15 Simplifying constant integer cast 0 Simplifying constant integer cast $33 Simplifying constant integer cast 0 Simplifying constant integer cast 2 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (byte) 0 Finalized unsigned number type (byte) 8 Finalized unsigned number type (byte) $ff Finalized unsigned number type (byte) 1 Finalized unsigned number type (byte) $40 Finalized unsigned number type (byte) 0 Finalized unsigned number type (byte) 0 Finalized unsigned number type (byte) $15 Finalized unsigned number type (byte) 0 Finalized unsigned number type (byte) $33 Finalized unsigned number type (byte) 0 Finalized unsigned number type (byte) 2 Successful SSA optimization PassNFinalizeNumberTypeConversions Inferred type updated to word in main::toSpritePtr1_$0 = main::toSpritePtr1_$1 / $40 Inversing boolean not [22] main::$2 = main::status#0 == $ff from [21] main::$1 = main::status#0 != $ff Successful SSA optimization Pass2UnaryNotSimplification Alias strlen::len#2 = strlen::len#4 strlen::len#3 strlen::return#0 strlen::return#3 strlen::return#1 Alias strlen::str#2 = strlen::str#3 Alias loadFileToMemory::return#0 = loadFileToMemory::return#3 Alias main::status#0 = main::$0 main::status#1 Alias main::toSpritePtr1_sprite#0 = main::toSpritePtr1_sprite#1 Alias main::toSpritePtr1_return#0 = main::toSpritePtr1_return#2 main::toSpritePtr1_return#1 main::toSpritePtr1_return#3 main::$3 Alias loadFileToMemory::device#1 = loadFileToMemory::device#2 Alias loadFileToMemory::address#1 = loadFileToMemory::address#2 loadFileToMemory::address#3 Alias load::return#0 = load::return#3 Alias loadFileToMemory::return#1 = loadFileToMemory::$2 loadFileToMemory::return#4 loadFileToMemory::return#2 Alias strlen::return#2 = strlen::return#4 Alias setnam::filename#1 = setnam::filename#2 Alias load::return#1 = load::return#4 load::return#2 Successful SSA optimization Pass2AliasElimination Identical Phi Values strlen::str#4 strlen::str#1 Identical Phi Values loadFileToMemory::filename#1 loadFileToMemory::filename#0 Identical Phi Values loadFileToMemory::device#1 loadFileToMemory::device#0 Identical Phi Values loadFileToMemory::address#1 loadFileToMemory::address#0 Identical Phi Values error::err#1 error::err#0 Identical Phi Values setnam::filename#1 setnam::filename#0 Identical Phi Values setlfs::device#1 setlfs::device#0 Identical Phi Values load::verify#1 load::verify#0 Identical Phi Values load::address#1 load::address#0 Successful SSA optimization Pass2IdenticalPhiElimination Simple Condition strlen::$0 [4] if(0!=*strlen::str#2) goto strlen::@2 Simple Condition main::$2 [15] if(main::status#0==$ff) goto main::@1 Successful SSA optimization Pass2ConditionalJumpSimplification Constant strlen::len#0 = 0 Constant loadFileToMemory::device#0 = 8 Constant loadFileToMemory::filename#0 = main::filename Constant loadFileToMemory::address#0 = LOAD_SPRITE Constant main::toSpritePtr1_sprite#0 = LOAD_SPRITE Constant load::verify#0 = false Successful SSA optimization Pass2ConstantIdentification Constant main::toSpritePtr1_$1 = (word)main::toSpritePtr1_sprite#0 Constant setnam::filename#0 = loadFileToMemory::filename#0 Constant setlfs::device#0 = loadFileToMemory::device#0 Constant load::address#0 = loadFileToMemory::address#0 Successful SSA optimization Pass2ConstantIdentification Constant strlen::str#1 = setnam::filename#0 Successful SSA optimization Pass2ConstantIdentification Constant value identified (byte)load::verify#0 in [58] *load::loadOrVerify = (byte)load::verify#0 Successful SSA optimization Pass2ConstantValues Simplifying constant evaluating to zero (byte)load::verify#0 in [58] *load::loadOrVerify = (byte)load::verify#0 Successful SSA optimization PassNSimplifyConstantZero Simplifying expression containing zero SPRITES_PTR in [21] SPRITES_PTR[0] = main::toSpritePtr1_return#0 Simplifying expression containing zero SPRITES_COLOR in [22] SPRITES_COLOR[0] = GREEN Simplifying expression containing zero SPRITES_XPOS in [23] SPRITES_XPOS[0] = $15 Simplifying expression containing zero SPRITES_YPOS in [24] SPRITES_YPOS[0] = $33 Successful SSA optimization PassNSimplifyExpressionWithZero Eliminating unused constant load::verify#0 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 Constant right-side identified [10] main::toSpritePtr1_$0 = main::toSpritePtr1_$1 / $40 Successful SSA optimization Pass2ConstantRValueConsolidation Constant main::toSpritePtr1_$0 = main::toSpritePtr1_$1/$40 Successful SSA optimization Pass2ConstantIdentification Constant main::toSpritePtr1_return#0 = (byte)main::toSpritePtr1_$0 Successful SSA optimization Pass2ConstantIdentification Inlining constant with var siblings strlen::len#0 Inlining constant with var siblings strlen::str#1 Constant inlined main::toSpritePtr1_sprite#0 = LOAD_SPRITE Constant inlined load::address#0 = LOAD_SPRITE Constant inlined setnam::filename#0 = main::filename Constant inlined main::toSpritePtr1_$0 = (word)LOAD_SPRITE/$40 Constant inlined strlen::str#1 = main::filename Constant inlined loadFileToMemory::address#0 = LOAD_SPRITE Constant inlined setlfs::device#0 = loadFileToMemory::device#0 Constant inlined main::toSpritePtr1_$1 = (word)LOAD_SPRITE Constant inlined strlen::len#0 = 0 Constant inlined loadFileToMemory::filename#0 = main::filename Successful SSA optimization Pass2ConstantInlining Adding NOP phi() at start of main Adding NOP phi() at start of main::@5 Adding NOP phi() at start of main::toSpritePtr1 Adding NOP phi() at start of main::toSpritePtr1_@return Adding NOP phi() at start of loadFileToMemory Adding NOP phi() at start of loadFileToMemory::@1 Adding NOP phi() at start of loadFileToMemory::@2 Adding NOP phi() at start of setnam Adding NOP phi() at start of strlen Adding NOP phi() at start of strlen::@3 CALL GRAPH Calls in [main] to loadFileToMemory:1 error:7 Calls in [loadFileToMemory] to setnam:18 setlfs:20 load:22 Calls in [setnam] to strlen:30 Created 2 initial phi equivalence classes Coalesced [52] strlen::str#5 = strlen::str#0 Coalesced [53] strlen::len#5 = strlen::len#1 Coalesced down to 2 phi equivalence classes Culled Empty Block label main::@5 Culled Empty Block label main::toSpritePtr1_@return Culled Empty Block label strlen::@3 Adding NOP phi() at start of main Adding NOP phi() at start of main::toSpritePtr1 Adding NOP phi() at start of loadFileToMemory Adding NOP phi() at start of loadFileToMemory::@1 Adding NOP phi() at start of loadFileToMemory::@2 Adding NOP phi() at start of setnam Adding NOP phi() at start of strlen FINAL CONTROL FLOW GRAPH void main() main: scope:[main] from [0] phi() [1] call loadFileToMemory [2] loadFileToMemory::return#0 = loadFileToMemory::return#1 to:main::@4 main::@4: scope:[main] from main [3] main::status#0 = loadFileToMemory::return#0 [4] if(main::status#0==$ff) goto main::@1 to:main::@2 main::@2: scope:[main] from main::@4 [5] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR) = 2 [6] error::err#0 = main::status#0 [7] call error to:main::@1 main::@1: scope:[main] from main::@2 main::@4 [8] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE) = 1 to:main::toSpritePtr1 main::toSpritePtr1: scope:[main] from main::@1 [9] phi() to:main::@3 main::@3: scope:[main] from main::toSpritePtr1 [10] *SPRITES_PTR = main::toSpritePtr1_return#0 [11] *SPRITES_COLOR = GREEN [12] *SPRITES_XPOS = $15 [13] *SPRITES_YPOS = $33 to:main::@return main::@return: scope:[main] from main::@3 [14] return to:@return byte loadFileToMemory(byte loadFileToMemory::device , byte* loadFileToMemory::filename , byte* loadFileToMemory::address) loadFileToMemory: scope:[loadFileToMemory] from main [15] phi() [16] call setnam to:loadFileToMemory::@1 loadFileToMemory::@1: scope:[loadFileToMemory] from loadFileToMemory [17] phi() [18] call setlfs to:loadFileToMemory::@2 loadFileToMemory::@2: scope:[loadFileToMemory] from loadFileToMemory::@1 [19] phi() [20] call load [21] load::return#0 = load::return#1 to:loadFileToMemory::@3 loadFileToMemory::@3: scope:[loadFileToMemory] from loadFileToMemory::@2 [22] loadFileToMemory::return#1 = load::return#0 to:loadFileToMemory::@return loadFileToMemory::@return: scope:[loadFileToMemory] from loadFileToMemory::@3 [23] return to:@return void error(byte error::err) error: scope:[error] from main::@2 [24] *error::errCode = error::err#0 asm { ldxerrCode jsr$a437 } to:error::@return error::@return: scope:[error] from error [26] return to:@return void setnam(byte* setnam::filename) setnam: scope:[setnam] from loadFileToMemory [27] phi() [28] call strlen [29] strlen::return#2 = strlen::len#2 to:setnam::@1 setnam::@1: scope:[setnam] from setnam [30] setnam::$0 = strlen::return#2 [31] *setnam::filename_len = (byte)setnam::$0 [32] *setnam::filename_ptr = main::filename asm { ldafilename_len ldxfilename_ptr ldyfilename_ptr+1 jsr$ffbd } to:setnam::@return setnam::@return: scope:[setnam] from setnam::@1 [34] return to:@return void setlfs(byte setlfs::device) setlfs: scope:[setlfs] from loadFileToMemory::@1 [35] *setlfs::deviceNum = loadFileToMemory::device#0 asm { ldxdeviceNum lda#1 ldy#0 jsr$ffba } to:setlfs::@return setlfs::@return: scope:[setlfs] from setlfs [37] return to:@return byte load(byte* load::address , bool load::verify) load: scope:[load] from loadFileToMemory::@2 [38] *load::loadOrVerify = 0 [39] *load::loadAddress = LOAD_SPRITE asm { ldxloadAddress ldyloadAddress+1 ldaloadOrVerify jsr$ffd5 bcserror lda#$ff error: stastatus } [41] load::return#1 = *load::status to:load::@return load::@return: scope:[load] from load [42] return to:@return word strlen(byte* strlen::str) strlen: scope:[strlen] from setnam [43] phi() to:strlen::@1 strlen::@1: scope:[strlen] from strlen strlen::@2 [44] strlen::len#2 = phi( strlen/0, strlen::@2/strlen::len#1 ) [44] strlen::str#2 = phi( strlen/main::filename, strlen::@2/strlen::str#0 ) [45] if(0!=*strlen::str#2) goto strlen::@2 to:strlen::@return strlen::@return: scope:[strlen] from strlen::@1 [46] return to:@return strlen::@2: scope:[strlen] from strlen::@1 [47] strlen::len#1 = ++ strlen::len#2 [48] strlen::str#0 = ++ strlen::str#2 to:strlen::@1 VARIABLE REGISTER WEIGHTS void error(byte error::err) byte error::err byte error::err#0 13.0 byte load(byte* load::address , bool load::verify) byte* load::address byte load::return byte load::return#0 22.0 byte load::return#1 37.33333333333333 bool load::verify byte loadFileToMemory(byte loadFileToMemory::device , byte* loadFileToMemory::filename , byte* loadFileToMemory::address) byte* loadFileToMemory::address byte loadFileToMemory::device byte* loadFileToMemory::filename byte loadFileToMemory::return byte loadFileToMemory::return#0 4.0 byte loadFileToMemory::return#1 4.333333333333333 void main() byte main::status byte main::status#0 2.0 byte main::toSpritePtr1_return byte* main::toSpritePtr1_sprite void setlfs(byte setlfs::device) byte setlfs::device void setnam(byte* setnam::filename) word~ setnam::$0 101.0 byte* setnam::filename word strlen(byte* strlen::str) word strlen::len word strlen::len#1 10001.0 word strlen::len#2 5025.75 word strlen::return word strlen::return#2 202.0 byte* strlen::str byte* strlen::str#0 20002.0 byte* strlen::str#2 10001.0 Initial phi equivalence classes [ strlen::str#2 strlen::str#0 ] [ strlen::len#2 strlen::len#1 ] Added variable loadFileToMemory::return#0 to live range equivalence class [ loadFileToMemory::return#0 ] Added variable main::status#0 to live range equivalence class [ main::status#0 ] Added variable error::err#0 to live range equivalence class [ error::err#0 ] Added variable load::return#0 to live range equivalence class [ load::return#0 ] Added variable loadFileToMemory::return#1 to live range equivalence class [ loadFileToMemory::return#1 ] Added variable strlen::return#2 to live range equivalence class [ strlen::return#2 ] Added variable setnam::$0 to live range equivalence class [ setnam::$0 ] Added variable load::return#1 to live range equivalence class [ load::return#1 ] Complete equivalence classes [ strlen::str#2 strlen::str#0 ] [ strlen::len#2 strlen::len#1 ] [ loadFileToMemory::return#0 ] [ main::status#0 ] [ error::err#0 ] [ load::return#0 ] [ loadFileToMemory::return#1 ] [ strlen::return#2 ] [ setnam::$0 ] [ load::return#1 ] Allocated zp[2]:2 [ strlen::str#2 strlen::str#0 ] Allocated zp[2]:4 [ strlen::len#2 strlen::len#1 ] Allocated zp[1]:6 [ loadFileToMemory::return#0 ] Allocated zp[1]:7 [ main::status#0 ] Allocated zp[1]:8 [ error::err#0 ] Allocated zp[1]:9 [ load::return#0 ] Allocated zp[1]:10 [ loadFileToMemory::return#1 ] Allocated zp[2]:11 [ strlen::return#2 ] Allocated zp[2]:13 [ setnam::$0 ] Allocated zp[1]:15 [ load::return#1 ] REGISTER UPLIFT POTENTIAL REGISTERS Statement [5] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR) = 2 [ main::status#0 ] ( [ main::status#0 ] { { error::err#0 = main::status#0 } } ) always clobbers reg byte a Removing always clobbered register reg byte a as potential for zp[1]:7 [ main::status#0 ] Statement [8] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE) = 1 [ ] ( [ ] { } ) always clobbers reg byte a Statement [10] *SPRITES_PTR = main::toSpritePtr1_return#0 [ ] ( [ ] { } ) always clobbers reg byte a Statement [11] *SPRITES_COLOR = GREEN [ ] ( [ ] { } ) always clobbers reg byte a Statement [12] *SPRITES_XPOS = $15 [ ] ( [ ] { } ) always clobbers reg byte a Statement [13] *SPRITES_YPOS = $33 [ ] ( [ ] { } ) always clobbers reg byte a Statement asm { ldxerrCode jsr$a437 } always clobbers reg byte a reg byte x reg byte y Statement [29] strlen::return#2 = strlen::len#2 [ strlen::return#2 ] ( loadFileToMemory:1::setnam:16 [ strlen::return#2 ] { { loadFileToMemory::return#0 = loadFileToMemory::return#1 } { strlen::return#2 = strlen::len#2 } } ) always clobbers reg byte a Statement [30] setnam::$0 = strlen::return#2 [ setnam::$0 ] ( loadFileToMemory:1::setnam:16 [ setnam::$0 ] { { loadFileToMemory::return#0 = loadFileToMemory::return#1 } } ) always clobbers reg byte a Statement [31] *setnam::filename_len = (byte)setnam::$0 [ ] ( loadFileToMemory:1::setnam:16 [ ] { { loadFileToMemory::return#0 = loadFileToMemory::return#1 } } ) always clobbers reg byte a Statement [32] *setnam::filename_ptr = main::filename [ ] ( loadFileToMemory:1::setnam:16 [ ] { { loadFileToMemory::return#0 = loadFileToMemory::return#1 } } ) always clobbers reg byte a Statement asm { ldafilename_len ldxfilename_ptr ldyfilename_ptr+1 jsr$ffbd } always clobbers reg byte a reg byte x reg byte y Statement [35] *setlfs::deviceNum = loadFileToMemory::device#0 [ ] ( loadFileToMemory:1::setlfs:18 [ ] { { loadFileToMemory::return#0 = loadFileToMemory::return#1 } } ) always clobbers reg byte a Statement asm { ldxdeviceNum lda#1 ldy#0 jsr$ffba } always clobbers reg byte a reg byte x reg byte y Statement [38] *load::loadOrVerify = 0 [ ] ( loadFileToMemory:1::load:20 [ ] { { loadFileToMemory::return#0 = loadFileToMemory::return#1 } { load::return#0 = load::return#1 } } ) always clobbers reg byte a Statement [39] *load::loadAddress = LOAD_SPRITE [ ] ( loadFileToMemory:1::load:20 [ ] { { loadFileToMemory::return#0 = loadFileToMemory::return#1 } { load::return#0 = load::return#1 } } ) always clobbers reg byte a Statement asm { ldxloadAddress ldyloadAddress+1 ldaloadOrVerify jsr$ffd5 bcserror lda#$ff error: stastatus } always clobbers reg byte a reg byte x reg byte y Statement [45] if(0!=*strlen::str#2) goto strlen::@2 [ strlen::len#2 strlen::str#2 ] ( loadFileToMemory:1::setnam:16::strlen:28 [ strlen::len#2 strlen::str#2 ] { { loadFileToMemory::return#0 = loadFileToMemory::return#1 } { strlen::return#2 = strlen::len#2 } } ) always clobbers reg byte a reg byte y Statement [5] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR) = 2 [ main::status#0 ] ( [ main::status#0 ] { { error::err#0 = main::status#0 } } ) always clobbers reg byte a Statement [8] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE) = 1 [ ] ( [ ] { } ) always clobbers reg byte a Statement [10] *SPRITES_PTR = main::toSpritePtr1_return#0 [ ] ( [ ] { } ) always clobbers reg byte a Statement [11] *SPRITES_COLOR = GREEN [ ] ( [ ] { } ) always clobbers reg byte a Statement [12] *SPRITES_XPOS = $15 [ ] ( [ ] { } ) always clobbers reg byte a Statement [13] *SPRITES_YPOS = $33 [ ] ( [ ] { } ) always clobbers reg byte a Statement asm { ldxerrCode jsr$a437 } always clobbers reg byte a reg byte x reg byte y Statement [29] strlen::return#2 = strlen::len#2 [ strlen::return#2 ] ( loadFileToMemory:1::setnam:16 [ strlen::return#2 ] { { loadFileToMemory::return#0 = loadFileToMemory::return#1 } { strlen::return#2 = strlen::len#2 } } ) always clobbers reg byte a Statement [30] setnam::$0 = strlen::return#2 [ setnam::$0 ] ( loadFileToMemory:1::setnam:16 [ setnam::$0 ] { { loadFileToMemory::return#0 = loadFileToMemory::return#1 } } ) always clobbers reg byte a Statement [31] *setnam::filename_len = (byte)setnam::$0 [ ] ( loadFileToMemory:1::setnam:16 [ ] { { loadFileToMemory::return#0 = loadFileToMemory::return#1 } } ) always clobbers reg byte a Statement [32] *setnam::filename_ptr = main::filename [ ] ( loadFileToMemory:1::setnam:16 [ ] { { loadFileToMemory::return#0 = loadFileToMemory::return#1 } } ) always clobbers reg byte a Statement asm { ldafilename_len ldxfilename_ptr ldyfilename_ptr+1 jsr$ffbd } always clobbers reg byte a reg byte x reg byte y Statement [35] *setlfs::deviceNum = loadFileToMemory::device#0 [ ] ( loadFileToMemory:1::setlfs:18 [ ] { { loadFileToMemory::return#0 = loadFileToMemory::return#1 } } ) always clobbers reg byte a Statement asm { ldxdeviceNum lda#1 ldy#0 jsr$ffba } always clobbers reg byte a reg byte x reg byte y Statement [38] *load::loadOrVerify = 0 [ ] ( loadFileToMemory:1::load:20 [ ] { { loadFileToMemory::return#0 = loadFileToMemory::return#1 } { load::return#0 = load::return#1 } } ) always clobbers reg byte a Statement [39] *load::loadAddress = LOAD_SPRITE [ ] ( loadFileToMemory:1::load:20 [ ] { { loadFileToMemory::return#0 = loadFileToMemory::return#1 } { load::return#0 = load::return#1 } } ) always clobbers reg byte a Statement asm { ldxloadAddress ldyloadAddress+1 ldaloadOrVerify jsr$ffd5 bcserror lda#$ff error: stastatus } always clobbers reg byte a reg byte x reg byte y Statement [45] if(0!=*strlen::str#2) goto strlen::@2 [ strlen::len#2 strlen::str#2 ] ( loadFileToMemory:1::setnam:16::strlen:28 [ strlen::len#2 strlen::str#2 ] { { loadFileToMemory::return#0 = loadFileToMemory::return#1 } { strlen::return#2 = strlen::len#2 } } ) always clobbers reg byte a reg byte y Potential registers zp[2]:2 [ strlen::str#2 strlen::str#0 ] : zp[2]:2 , Potential registers zp[2]:4 [ strlen::len#2 strlen::len#1 ] : zp[2]:4 , Potential registers zp[1]:6 [ loadFileToMemory::return#0 ] : zp[1]:6 , reg byte a , reg byte x , reg byte y , Potential registers zp[1]:7 [ main::status#0 ] : zp[1]:7 , reg byte x , reg byte y , Potential registers zp[1]:8 [ error::err#0 ] : zp[1]:8 , reg byte a , reg byte x , reg byte y , Potential registers zp[1]:9 [ load::return#0 ] : zp[1]:9 , reg byte a , reg byte x , reg byte y , Potential registers zp[1]:10 [ loadFileToMemory::return#1 ] : zp[1]:10 , reg byte a , reg byte x , reg byte y , Potential registers zp[2]:11 [ strlen::return#2 ] : zp[2]:11 , Potential registers zp[2]:13 [ setnam::$0 ] : zp[2]:13 , Potential registers zp[1]:15 [ load::return#1 ] : zp[1]:15 , reg byte a , reg byte x , reg byte y , REGISTER UPLIFT SCOPES Uplift Scope [strlen] 30,003: zp[2]:2 [ strlen::str#2 strlen::str#0 ] 15,026.75: zp[2]:4 [ strlen::len#2 strlen::len#1 ] 202: zp[2]:11 [ strlen::return#2 ] Uplift Scope [setnam] 101: zp[2]:13 [ setnam::$0 ] Uplift Scope [load] 37.33: zp[1]:15 [ load::return#1 ] 22: zp[1]:9 [ load::return#0 ] Uplift Scope [error] 13: zp[1]:8 [ error::err#0 ] Uplift Scope [loadFileToMemory] 4.33: zp[1]:10 [ loadFileToMemory::return#1 ] 4: zp[1]:6 [ loadFileToMemory::return#0 ] Uplift Scope [main] 2: zp[1]:7 [ main::status#0 ] Uplift Scope [MOS6526_CIA] Uplift Scope [MOS6569_VICII] Uplift Scope [MOS6581_SID] Uplift Scope [setlfs] Uplift Scope [] Uplifting [strlen] best 1032 combination zp[2]:2 [ strlen::str#2 strlen::str#0 ] zp[2]:4 [ strlen::len#2 strlen::len#1 ] zp[2]:11 [ strlen::return#2 ] Uplifting [setnam] best 1032 combination zp[2]:13 [ setnam::$0 ] Uplifting [load] best 1020 combination reg byte a [ load::return#1 ] reg byte a [ load::return#0 ] Uplifting [error] best 1014 combination reg byte a [ error::err#0 ] Uplifting [loadFileToMemory] best 1002 combination reg byte a [ loadFileToMemory::return#1 ] reg byte a [ loadFileToMemory::return#0 ] Uplifting [main] best 997 combination reg byte x [ main::status#0 ] Uplifting [MOS6526_CIA] best 997 combination Uplifting [MOS6569_VICII] best 997 combination Uplifting [MOS6581_SID] best 997 combination Uplifting [setlfs] best 997 combination Uplifting [] best 997 combination Coalescing zero page register [ zp[2]:4 [ strlen::len#2 strlen::len#1 ] ] with [ zp[2]:11 [ strlen::return#2 ] ] - score: 1 Coalescing zero page register [ zp[2]:4 [ strlen::len#2 strlen::len#1 strlen::return#2 ] ] with [ zp[2]:13 [ setnam::$0 ] ] - score: 1 ASSEMBLER BEFORE OPTIMIZATION // File Comments // Load a file to memory using the C64 KERNAL LOAD functions // The kernalload.ld link file creates a D64 disk image containing the executable and the sprite. // To execute the program succesfully you must mount the D64 disk image and execute the kernalload.PRG program // Upstart // Create a D64 disk containing the program and a sprite file .disk [filename="kernalload.d64", name="DISK", id=1] { [name="KERNALLOAD", type="prg", segments="Program"], [name="SPRITE", type="prg", segments="Sprite"] } .segmentdef Program [segments="Basic, Code, Data"] .segmentdef Basic [start=$0801] .segmentdef Code [start=$0810] .segmentdef Data [startAfter="Code"] .segmentdef Sprite .segment Basic :BasicUpstart(main) .segment Code // Global Constants & labels // The offset of the sprite pointers from the screen start address .const OFFSET_SPRITE_PTRS = $3f8 .const GREEN = 5 .const OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE = $15 .const OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR = $20 .label SPRITES_XPOS = $d000 .label SPRITES_YPOS = $d001 .label SPRITES_COLOR = $d027 // The VIC-II MOS 6567/6569 .label VICII = $d000 // Address to load to .label LOAD_SPRITE = $3000 .label SCREEN = $400 .label SPRITES_PTR = SCREEN+OFFSET_SPRITE_PTRS .segment Code // main main: { .const toSpritePtr1_return = LOAD_SPRITE/$40 // [1] call loadFileToMemory // [15] phi from main to loadFileToMemory [phi:main->loadFileToMemory] loadFileToMemory_from_main: jsr loadFileToMemory // [2] loadFileToMemory::return#0 = loadFileToMemory::return#1 jmp __b4 // main::@4 __b4: // [3] main::status#0 = loadFileToMemory::return#0 -- vbuxx=vbuaa tax // [4] if(main::status#0==$ff) goto main::@1 -- vbuxx_eq_vbuc1_then_la1 cpx #$ff beq __b1 jmp __b2 // main::@2 __b2: // [5] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR) = 2 -- _deref_pbuc1=vbuc2 lda #2 sta VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR // [6] error::err#0 = main::status#0 -- vbuaa=vbuxx txa // [7] call error jsr error jmp __b1 // main::@1 __b1: // [8] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE) = 1 -- _deref_pbuc1=vbuc2 // Show the loaded sprite on screen lda #1 sta VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE // [9] phi from main::@1 to main::toSpritePtr1 [phi:main::@1->main::toSpritePtr1] toSpritePtr1_from___b1: jmp toSpritePtr1 // main::toSpritePtr1 toSpritePtr1: jmp __b3 // main::@3 __b3: // [10] *SPRITES_PTR = main::toSpritePtr1_return#0 -- _deref_pbuc1=vbuc2 lda #toSpritePtr1_return sta SPRITES_PTR // [11] *SPRITES_COLOR = GREEN -- _deref_pbuc1=vbuc2 lda #GREEN sta SPRITES_COLOR // [12] *SPRITES_XPOS = $15 -- _deref_pbuc1=vbuc2 lda #$15 sta SPRITES_XPOS // [13] *SPRITES_YPOS = $33 -- _deref_pbuc1=vbuc2 lda #$33 sta SPRITES_YPOS jmp __breturn // main::@return __breturn: // [14] return rts .segment Data filename: .text "SPRITE" .byte 0 } .segment Code // loadFileToMemory // Load a file to memory // Returns a status: // - 0xff: Success // - other: Kernal Error Code (https://commodore.ca/manuals/pdfs/commodore_error_messages.pdf) loadFileToMemory: { .label device = 8 // [16] call setnam // [27] phi from loadFileToMemory to setnam [phi:loadFileToMemory->setnam] setnam_from_loadFileToMemory: jsr setnam // [17] phi from loadFileToMemory to loadFileToMemory::@1 [phi:loadFileToMemory->loadFileToMemory::@1] __b1_from_loadFileToMemory: jmp __b1 // loadFileToMemory::@1 __b1: // [18] call setlfs jsr setlfs // [19] phi from loadFileToMemory::@1 to loadFileToMemory::@2 [phi:loadFileToMemory::@1->loadFileToMemory::@2] __b2_from___b1: jmp __b2 // loadFileToMemory::@2 __b2: // [20] call load jsr load // [21] load::return#0 = load::return#1 jmp __b3 // loadFileToMemory::@3 __b3: // [22] loadFileToMemory::return#1 = load::return#0 jmp __breturn // loadFileToMemory::@return __breturn: // [23] return rts } // error // Basic ERROR function // ERROR. Show error. // error(byte register(A) err) error: { .label errCode = $ff // [24] *error::errCode = error::err#0 -- _deref_pbuc1=vbuaa sta errCode // asm { ldxerrCode jsr$a437 } ldx errCode jsr $a437 jmp __breturn // error::@return __breturn: // [26] return rts } // setnam // Kernal SETNAM function // SETNAM. Set file name parameters. setnam: { .label filename_len = $fd .label filename_ptr = $fe .label __0 = 4 // [28] call strlen // [43] phi from setnam to strlen [phi:setnam->strlen] strlen_from_setnam: jsr strlen // [29] strlen::return#2 = strlen::len#2 jmp __b1 // setnam::@1 __b1: // [30] setnam::$0 = strlen::return#2 // [31] *setnam::filename_len = (byte)setnam::$0 -- _deref_pbuc1=_byte_vwuz1 lda.z __0 sta filename_len // [32] *setnam::filename_ptr = main::filename -- _deref_qbuc1=pbuc2 lda #main.filename sta filename_ptr+1 // asm { ldafilename_len ldxfilename_ptr ldyfilename_ptr+1 jsr$ffbd } lda filename_len ldx filename_ptr ldy filename_ptr+1 jsr $ffbd jmp __breturn // setnam::@return __breturn: // [34] return rts } // setlfs // SETLFS. Set file parameters. setlfs: { .label deviceNum = $ff // [35] *setlfs::deviceNum = loadFileToMemory::device#0 -- _deref_pbuc1=vbuc2 lda #loadFileToMemory.device sta deviceNum // asm { ldxdeviceNum lda#1 ldy#0 jsr$ffba } ldx deviceNum lda #1 ldy #0 jsr $ffba jmp __breturn // setlfs::@return __breturn: // [37] return rts } // load //LOAD. Load or verify file. (Must call SETLFS and SETNAM beforehands.) // Returns a status, 0xff: Success other: Kernal Error Code load: { .label loadOrVerify = $fd .label loadAddress = $fe .label status = $fd // [38] *load::loadOrVerify = 0 -- _deref_pbuc1=vbuc2 lda #0 sta loadOrVerify // [39] *load::loadAddress = LOAD_SPRITE -- _deref_qbuc1=pbuc2 lda #LOAD_SPRITE sta loadAddress+1 // asm { ldxloadAddress ldyloadAddress+1 ldaloadOrVerify jsr$ffd5 bcserror lda#$ff error: stastatus } ldx loadAddress ldy loadAddress+1 lda loadOrVerify jsr $ffd5 bcs error lda #$ff error: sta status // [41] load::return#1 = *load::status -- vbuaa=_deref_pbuc1 lda status jmp __breturn // load::@return __breturn: // [42] return rts } // strlen // Computes the length of the string str up to but not including the terminating null character. // strlen(byte* zp(2) str) strlen: { .label len = 4 .label str = 2 .label return = 4 // [44] phi from strlen to strlen::@1 [phi:strlen->strlen::@1] __b1_from_strlen: // [44] phi strlen::len#2 = 0 [phi:strlen->strlen::@1#0] -- vwuz1=vwuc1 lda #<0 sta.z len lda #>0 sta.z len+1 // [44] phi strlen::str#2 = main::filename [phi:strlen->strlen::@1#1] -- pbuz1=pbuc1 lda #main.filename sta.z str+1 jmp __b1 // strlen::@1 __b1: // [45] if(0!=*strlen::str#2) goto strlen::@2 -- 0_neq__deref_pbuz1_then_la1 ldy #0 lda (str),y cmp #0 bne __b2 jmp __breturn // strlen::@return __breturn: // [46] return rts // strlen::@2 __b2: // [47] strlen::len#1 = ++ strlen::len#2 -- vwuz1=_inc_vwuz1 inc.z len bne !+ inc.z len+1 !: // [48] strlen::str#0 = ++ strlen::str#2 -- pbuz1=_inc_pbuz1 inc.z str bne !+ inc.z str+1 !: // [44] phi from strlen::@2 to strlen::@1 [phi:strlen::@2->strlen::@1] __b1_from___b2: // [44] phi strlen::len#2 = strlen::len#1 [phi:strlen::@2->strlen::@1#0] -- register_copy // [44] phi strlen::str#2 = strlen::str#0 [phi:strlen::@2->strlen::@1#1] -- register_copy jmp __b1 } // File Data .segment Sprite SPRITE: .var pic = LoadPicture("sprite.png", List().add($000000, $ffffff)) .for (var y=0; y<21; y++) .for (var x=0;x<3; x++) .byte pic.getSinglecolorByte(x,y) ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b4 Removing instruction jmp __b2 Removing instruction jmp __b1 Removing instruction jmp toSpritePtr1 Removing instruction jmp __b3 Removing instruction jmp __breturn Removing instruction jmp __b1 Removing instruction jmp __b2 Removing instruction jmp __b3 Removing instruction jmp __breturn Removing instruction jmp __breturn Removing instruction jmp __b1 Removing instruction jmp __breturn Removing instruction jmp __breturn Removing instruction jmp __breturn Removing instruction jmp __b1 Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination Replacing instruction ldx errCode with TAX Replacing instruction ldx deviceNum with TAX Replacing instruction ldy loadAddress+1 with TAY Removing instruction lda status Removing instruction lda #>0 Succesful ASM optimization Pass5UnnecesaryLoadElimination Removing instruction toSpritePtr1_from___b1: Removing instruction toSpritePtr1: Removing instruction __b1_from_loadFileToMemory: Removing instruction __b2_from___b1: Removing instruction __breturn: Succesful ASM optimization Pass5RedundantLabelElimination Removing instruction loadFileToMemory_from_main: Removing instruction __b4: Removing instruction __b2: Removing instruction __b3: Removing instruction __breturn: Removing instruction setnam_from_loadFileToMemory: Removing instruction __b1: Removing instruction __b2: Removing instruction __b3: Removing instruction __breturn: Removing instruction strlen_from_setnam: Removing instruction __b1: Removing instruction __breturn: Removing instruction __breturn: Removing instruction __breturn: Removing instruction __b1_from_strlen: Removing instruction __breturn: Removing instruction __b1_from___b2: Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE const nomodify byte GREEN = 5 const nomodify byte* LOAD_SPRITE = (byte*) 12288 const nomodify word OFFSET_SPRITE_PTRS = $3f8 const byte OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR = $20 const byte OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE = $15 const nomodify byte* SCREEN = (byte*) 1024 const byte* SPRITE[] = kickasm {{ .var pic = LoadPicture("sprite.png", List().add($000000, $ffffff)) .for (var y=0; y<21; y++) .for (var x=0;x<3; x++) .byte pic.getSinglecolorByte(x,y) }} const nomodify byte* SPRITES_COLOR = (byte*) 53287 const nomodify byte* SPRITES_PTR = SCREEN+OFFSET_SPRITE_PTRS const nomodify byte* SPRITES_XPOS = (byte*) 53248 const nomodify byte* SPRITES_YPOS = (byte*) 53249 const nomodify struct MOS6569_VICII* VICII = (struct MOS6569_VICII*) 53248 void error(byte error::err) byte error::err byte error::err#0 reg byte a 13.0 const nomodify byte* error::errCode = (byte*) 255 byte load(byte* load::address , bool load::verify) byte* load::address const byte** load::loadAddress = (byte**) 254 const byte* load::loadOrVerify = (byte*) 253 byte load::return byte load::return#0 reg byte a 22.0 byte load::return#1 reg byte a 37.33333333333333 const byte* load::status = (byte*) 253 bool load::verify byte loadFileToMemory(byte loadFileToMemory::device , byte* loadFileToMemory::filename , byte* loadFileToMemory::address) byte* loadFileToMemory::address byte loadFileToMemory::device const byte loadFileToMemory::device#0 device = 8 byte* loadFileToMemory::filename byte loadFileToMemory::return byte loadFileToMemory::return#0 reg byte a 4.0 byte loadFileToMemory::return#1 reg byte a 4.333333333333333 void main() const byte* main::filename[7] = "SPRITE" byte main::status byte main::status#0 reg byte x 2.0 byte main::toSpritePtr1_return const byte main::toSpritePtr1_return#0 toSpritePtr1_return = (byte)(word)LOAD_SPRITE/$40 byte* main::toSpritePtr1_sprite void setlfs(byte setlfs::device) byte setlfs::device const nomodify byte* setlfs::deviceNum = (byte*) 255 void setnam(byte* setnam::filename) word~ setnam::$0 zp[2]:4 101.0 byte* setnam::filename const nomodify byte* setnam::filename_len = (byte*) 253 const nomodify byte** setnam::filename_ptr = (byte**) 254 word strlen(byte* strlen::str) word strlen::len word strlen::len#1 len zp[2]:4 10001.0 word strlen::len#2 len zp[2]:4 5025.75 word strlen::return word strlen::return#2 return zp[2]:4 202.0 byte* strlen::str byte* strlen::str#0 str zp[2]:2 20002.0 byte* strlen::str#2 str zp[2]:2 10001.0 zp[2]:2 [ strlen::str#2 strlen::str#0 ] zp[2]:4 [ strlen::len#2 strlen::len#1 strlen::return#2 setnam::$0 ] reg byte a [ loadFileToMemory::return#0 ] reg byte x [ main::status#0 ] reg byte a [ error::err#0 ] reg byte a [ load::return#0 ] reg byte a [ loadFileToMemory::return#1 ] reg byte a [ load::return#1 ] FINAL ASSEMBLER Score: 811 // File Comments // Load a file to memory using the C64 KERNAL LOAD functions // The kernalload.ld link file creates a D64 disk image containing the executable and the sprite. // To execute the program succesfully you must mount the D64 disk image and execute the kernalload.PRG program // Upstart // Create a D64 disk containing the program and a sprite file .disk [filename="kernalload.d64", name="DISK", id=1] { [name="KERNALLOAD", type="prg", segments="Program"], [name="SPRITE", type="prg", segments="Sprite"] } .segmentdef Program [segments="Basic, Code, Data"] .segmentdef Basic [start=$0801] .segmentdef Code [start=$0810] .segmentdef Data [startAfter="Code"] .segmentdef Sprite .segment Basic :BasicUpstart(main) .segment Code // Global Constants & labels // The offset of the sprite pointers from the screen start address .const OFFSET_SPRITE_PTRS = $3f8 .const GREEN = 5 .const OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE = $15 .const OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR = $20 .label SPRITES_XPOS = $d000 .label SPRITES_YPOS = $d001 .label SPRITES_COLOR = $d027 // The VIC-II MOS 6567/6569 .label VICII = $d000 // Address to load to .label LOAD_SPRITE = $3000 .label SCREEN = $400 .label SPRITES_PTR = SCREEN+OFFSET_SPRITE_PTRS .segment Code // main main: { .const toSpritePtr1_return = LOAD_SPRITE/$40 // loadFileToMemory(8, "SPRITE", LOAD_SPRITE) // [1] call loadFileToMemory // [15] phi from main to loadFileToMemory [phi:main->loadFileToMemory] jsr loadFileToMemory // loadFileToMemory(8, "SPRITE", LOAD_SPRITE) // [2] loadFileToMemory::return#0 = loadFileToMemory::return#1 // main::@4 // status = loadFileToMemory(8, "SPRITE", LOAD_SPRITE) // [3] main::status#0 = loadFileToMemory::return#0 -- vbuxx=vbuaa tax // if(status!=0xff) // [4] if(main::status#0==$ff) goto main::@1 -- vbuxx_eq_vbuc1_then_la1 cpx #$ff beq __b1 // main::@2 // VICII->BORDER_COLOR = 0x02 // [5] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR) = 2 -- _deref_pbuc1=vbuc2 lda #2 sta VICII+OFFSET_STRUCT_MOS6569_VICII_BORDER_COLOR // error(status) // [6] error::err#0 = main::status#0 -- vbuaa=vbuxx txa // [7] call error jsr error // main::@1 __b1: // VICII->SPRITES_ENABLE = %00000001 // [8] *((byte*)VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE) = 1 -- _deref_pbuc1=vbuc2 // Show the loaded sprite on screen lda #1 sta VICII+OFFSET_STRUCT_MOS6569_VICII_SPRITES_ENABLE // [9] phi from main::@1 to main::toSpritePtr1 [phi:main::@1->main::toSpritePtr1] // main::toSpritePtr1 // main::@3 // SPRITES_PTR[0] = toSpritePtr(LOAD_SPRITE) // [10] *SPRITES_PTR = main::toSpritePtr1_return#0 -- _deref_pbuc1=vbuc2 lda #toSpritePtr1_return sta SPRITES_PTR // SPRITES_COLOR[0] = GREEN // [11] *SPRITES_COLOR = GREEN -- _deref_pbuc1=vbuc2 lda #GREEN sta SPRITES_COLOR // SPRITES_XPOS[0] = 0x15 // [12] *SPRITES_XPOS = $15 -- _deref_pbuc1=vbuc2 lda #$15 sta SPRITES_XPOS // SPRITES_YPOS[0] = 0x33 // [13] *SPRITES_YPOS = $33 -- _deref_pbuc1=vbuc2 lda #$33 sta SPRITES_YPOS // main::@return // } // [14] return rts .segment Data filename: .text "SPRITE" .byte 0 } .segment Code // loadFileToMemory // Load a file to memory // Returns a status: // - 0xff: Success // - other: Kernal Error Code (https://commodore.ca/manuals/pdfs/commodore_error_messages.pdf) loadFileToMemory: { .label device = 8 // setnam(filename) // [16] call setnam // [27] phi from loadFileToMemory to setnam [phi:loadFileToMemory->setnam] jsr setnam // [17] phi from loadFileToMemory to loadFileToMemory::@1 [phi:loadFileToMemory->loadFileToMemory::@1] // loadFileToMemory::@1 // setlfs(device) // [18] call setlfs jsr setlfs // [19] phi from loadFileToMemory::@1 to loadFileToMemory::@2 [phi:loadFileToMemory::@1->loadFileToMemory::@2] // loadFileToMemory::@2 // load(address, false) // [20] call load jsr load // [21] load::return#0 = load::return#1 // loadFileToMemory::@3 // [22] loadFileToMemory::return#1 = load::return#0 // loadFileToMemory::@return // } // [23] return rts } // error // Basic ERROR function // ERROR. Show error. // error(byte register(A) err) error: { .label errCode = $ff // *errCode = err // [24] *error::errCode = error::err#0 -- _deref_pbuc1=vbuaa sta errCode // asm // asm { ldxerrCode jsr$a437 } tax jsr $a437 // error::@return // } // [26] return rts } // setnam // Kernal SETNAM function // SETNAM. Set file name parameters. setnam: { .label filename_len = $fd .label filename_ptr = $fe .label __0 = 4 // strlen(filename) // [28] call strlen // [43] phi from setnam to strlen [phi:setnam->strlen] jsr strlen // strlen(filename) // [29] strlen::return#2 = strlen::len#2 // setnam::@1 // [30] setnam::$0 = strlen::return#2 // *filename_len = (char)strlen(filename) // [31] *setnam::filename_len = (byte)setnam::$0 -- _deref_pbuc1=_byte_vwuz1 lda.z __0 sta filename_len // *filename_ptr = filename // [32] *setnam::filename_ptr = main::filename -- _deref_qbuc1=pbuc2 lda #main.filename sta filename_ptr+1 // asm // asm { ldafilename_len ldxfilename_ptr ldyfilename_ptr+1 jsr$ffbd } lda filename_len ldx filename_ptr ldy filename_ptr+1 jsr $ffbd // setnam::@return // } // [34] return rts } // setlfs // SETLFS. Set file parameters. setlfs: { .label deviceNum = $ff // *deviceNum = device // [35] *setlfs::deviceNum = loadFileToMemory::device#0 -- _deref_pbuc1=vbuc2 lda #loadFileToMemory.device sta deviceNum // asm // asm { ldxdeviceNum lda#1 ldy#0 jsr$ffba } tax lda #1 ldy #0 jsr $ffba // setlfs::@return // } // [37] return rts } // load //LOAD. Load or verify file. (Must call SETLFS and SETNAM beforehands.) // Returns a status, 0xff: Success other: Kernal Error Code load: { .label loadOrVerify = $fd .label loadAddress = $fe .label status = $fd // *loadOrVerify = (char)verify // [38] *load::loadOrVerify = 0 -- _deref_pbuc1=vbuc2 lda #0 sta loadOrVerify // *loadAddress = address // [39] *load::loadAddress = LOAD_SPRITE -- _deref_qbuc1=pbuc2 lda #LOAD_SPRITE sta loadAddress+1 // asm // asm { ldxloadAddress ldyloadAddress+1 ldaloadOrVerify jsr$ffd5 bcserror lda#$ff error: stastatus } ldx loadAddress tay lda loadOrVerify jsr $ffd5 bcs error lda #$ff error: sta status // return *status; // [41] load::return#1 = *load::status -- vbuaa=_deref_pbuc1 // load::@return // } // [42] return rts } // strlen // Computes the length of the string str up to but not including the terminating null character. // strlen(byte* zp(2) str) strlen: { .label len = 4 .label str = 2 .label return = 4 // [44] phi from strlen to strlen::@1 [phi:strlen->strlen::@1] // [44] phi strlen::len#2 = 0 [phi:strlen->strlen::@1#0] -- vwuz1=vwuc1 lda #<0 sta.z len sta.z len+1 // [44] phi strlen::str#2 = main::filename [phi:strlen->strlen::@1#1] -- pbuz1=pbuc1 lda #main.filename sta.z str+1 // strlen::@1 __b1: // while(*str) // [45] if(0!=*strlen::str#2) goto strlen::@2 -- 0_neq__deref_pbuz1_then_la1 ldy #0 lda (str),y cmp #0 bne __b2 // strlen::@return // } // [46] return rts // strlen::@2 __b2: // len++; // [47] strlen::len#1 = ++ strlen::len#2 -- vwuz1=_inc_vwuz1 inc.z len bne !+ inc.z len+1 !: // str++; // [48] strlen::str#0 = ++ strlen::str#2 -- pbuz1=_inc_pbuz1 inc.z str bne !+ inc.z str+1 !: // [44] phi from strlen::@2 to strlen::@1 [phi:strlen::@2->strlen::@1] // [44] phi strlen::len#2 = strlen::len#1 [phi:strlen::@2->strlen::@1#0] -- register_copy // [44] phi strlen::str#2 = strlen::str#0 [phi:strlen::@2->strlen::@1#1] -- register_copy jmp __b1 } // File Data .segment Sprite SPRITE: .var pic = LoadPicture("sprite.png", List().add($000000, $ffffff)) .for (var y=0; y<21; y++) .for (var x=0;x<3; x++) .byte pic.getSinglecolorByte(x,y)