Warning! Adding boolean cast to non-boolean condition *((byte*) strcpy::src)
Warning! Adding boolean cast to non-boolean condition *((byte*) strlen::str)
Inlined call (byte~) vicSelectGfxBank::$0 ← call toDd00 (byte*) vicSelectGfxBank::gfx 
Inlined call (byte~) main::$0 ← call toD018 (const byte*) SCREEN_COPY (const byte*) CHARSET 
Culled Empty Block (label) @1
Culled Empty Block (label) @2
Culled Empty Block (label) @3
Culled Empty Block (label) @4
Culled Empty Block (label) memcpy::@4
Culled Empty Block (label) memcpy::@5
Culled Empty Block (label) memcpy::@6
Culled Empty Block (label) memcpy::@7
Culled Empty Block (label) @5
Culled Empty Block (label) @6
Culled Empty Block (label) @7
Culled Empty Block (label) @8
Culled Empty Block (label) @9
Culled Empty Block (label) main::toD0181_@1

CONTROL FLOW GRAPH SSA
@begin: scope:[]  from
  to:@10

(void*()) memcpy((void*) memcpy::destination , (void*) memcpy::source , (word) memcpy::num)
memcpy: scope:[memcpy]  from main::@1 main::@2
  (word) memcpy::num#2 ← phi( main::@1/(word) memcpy::num#0 main::@2/(word) memcpy::num#1 )
  (void*) memcpy::destination#2 ← phi( main::@1/(void*) memcpy::destination#0 main::@2/(void*) memcpy::destination#1 )
  (void*) memcpy::source#2 ← phi( main::@1/(void*) memcpy::source#0 main::@2/(void*) memcpy::source#1 )
  (byte*) memcpy::src#0 ← ((byte*)) (void*) memcpy::source#2
  (byte*) memcpy::dst#0 ← ((byte*)) (void*) memcpy::destination#2
  (byte*~) memcpy::$0 ← ((byte*)) (void*) memcpy::source#2
  (byte*~) memcpy::$1 ← (byte*~) memcpy::$0 + (word) memcpy::num#2
  (byte*) memcpy::src_end#0 ← (byte*~) memcpy::$1
  to:memcpy::@1
memcpy::@1: scope:[memcpy]  from memcpy memcpy::@2
  (void*) memcpy::destination#4 ← phi( memcpy/(void*) memcpy::destination#2 memcpy::@2/(void*) memcpy::destination#5 )
  (byte*) memcpy::dst#3 ← phi( memcpy/(byte*) memcpy::dst#0 memcpy::@2/(byte*) memcpy::dst#1 )
  (byte*) memcpy::src_end#1 ← phi( memcpy/(byte*) memcpy::src_end#0 memcpy::@2/(byte*) memcpy::src_end#2 )
  (byte*) memcpy::src#2 ← phi( memcpy/(byte*) memcpy::src#0 memcpy::@2/(byte*) memcpy::src#1 )
  (bool~) memcpy::$2 ← (byte*) memcpy::src#2 != (byte*) memcpy::src_end#1
  if((bool~) memcpy::$2) goto memcpy::@2
  to:memcpy::@3
memcpy::@2: scope:[memcpy]  from memcpy::@1
  (void*) memcpy::destination#5 ← phi( memcpy::@1/(void*) memcpy::destination#4 )
  (byte*) memcpy::src_end#2 ← phi( memcpy::@1/(byte*) memcpy::src_end#1 )
  (byte*) memcpy::dst#2 ← phi( memcpy::@1/(byte*) memcpy::dst#3 )
  (byte*) memcpy::src#3 ← phi( memcpy::@1/(byte*) memcpy::src#2 )
  *((byte*) memcpy::dst#2) ← *((byte*) memcpy::src#3)
  (byte*) memcpy::dst#1 ← ++ (byte*) memcpy::dst#2
  (byte*) memcpy::src#1 ← ++ (byte*) memcpy::src#3
  to:memcpy::@1
memcpy::@3: scope:[memcpy]  from memcpy::@1
  (void*) memcpy::destination#3 ← phi( memcpy::@1/(void*) memcpy::destination#4 )
  (void*) memcpy::return#0 ← (void*) memcpy::destination#3
  to:memcpy::@return
memcpy::@return: scope:[memcpy]  from memcpy::@3
  (void*) memcpy::return#4 ← phi( memcpy::@3/(void*) memcpy::return#0 )
  (void*) memcpy::return#1 ← (void*) memcpy::return#4
  return 
  to:@return

(void()) main()
main: scope:[main]  from @10
  (byte*) main::toD0181_screen#0 ← (const byte*) SCREEN_COPY
  (byte*) main::toD0181_gfx#0 ← (const byte*) CHARSET
  to:main::toD0181
main::toD0181: scope:[main]  from main
  (byte*) main::toD0181_gfx#1 ← phi( main/(byte*) main::toD0181_gfx#0 )
  (byte*) main::toD0181_screen#1 ← phi( main/(byte*) main::toD0181_screen#0 )
  (word~) main::toD0181_$0 ← ((word)) (byte*) main::toD0181_screen#1
  (number~) main::toD0181_$1 ← (word~) main::toD0181_$0 & (number) $3fff
  (number~) main::toD0181_$2 ← (number~) main::toD0181_$1 * (number) 4
  (number~) main::toD0181_$3 ← > (number~) main::toD0181_$2
  (word~) main::toD0181_$4 ← ((word)) (byte*) main::toD0181_gfx#1
  (byte~) main::toD0181_$5 ← > (word~) main::toD0181_$4
  (number~) main::toD0181_$6 ← (byte~) main::toD0181_$5 / (number) 4
  (number~) main::toD0181_$7 ← (number~) main::toD0181_$6 & (number) $f
  (number~) main::toD0181_$8 ← (number~) main::toD0181_$3 | (number~) main::toD0181_$7
  (byte) main::toD0181_return#0 ← (number~) main::toD0181_$8
  to:main::toD0181_@return
main::toD0181_@return: scope:[main]  from main::toD0181
  (byte) main::toD0181_return#2 ← phi( main::toD0181/(byte) main::toD0181_return#0 )
  (byte) main::toD0181_return#1 ← (byte) main::toD0181_return#2
  to:main::@1
main::@1: scope:[main]  from main::toD0181_@return
  (byte) main::toD0181_return#3 ← phi( main::toD0181_@return/(byte) main::toD0181_return#1 )
  (byte~) main::$0 ← (byte) main::toD0181_return#3
  *((const byte*) D018) ← (byte~) main::$0
  (void*) memcpy::destination#0 ← (void*)(const byte*) SCREEN_COPY
  (void*) memcpy::source#0 ← (void*)(const byte*) SCREEN
  (word) memcpy::num#0 ← (number) $400
  call memcpy 
  (void*) memcpy::return#2 ← (void*) memcpy::return#1
  to:main::@2
main::@2: scope:[main]  from main::@1
  asm { sei  }
  *((const byte*) PROCPORT) ← (const byte) PROCPORT_RAM_CHARROM
  (void*) memcpy::destination#1 ← (void*)(const byte*) CHARSET
  (void*) memcpy::source#1 ← (void*)(const byte*) CHARGEN
  (word) memcpy::num#1 ← (number) $800
  call memcpy 
  (void*) memcpy::return#3 ← (void*) memcpy::return#1
  to:main::@3
main::@3: scope:[main]  from main::@2
  *((const byte*) PROCPORT) ← (const byte) PROCPORT_BASIC_KERNEL_IO
  asm { cli  }
  to:main::@return
main::@return: scope:[main]  from main::@3
  return 
  to:@return
@10: scope:[]  from @begin
  call main 
  to:@11
@11: scope:[]  from @10
  to:@end
@end: scope:[]  from @11

SYMBOL TABLE SSA
(label) @10
(label) @11
(label) @begin
(label) @end
(const byte*) CHARGEN = (byte*)(number) $d000
(const byte*) CHARSET = (byte*)(number) $2000
(const byte*) D018 = (byte*)(number) $d018
(const byte*) PROCPORT = (byte*)(number) 1
(const byte) PROCPORT_BASIC_KERNEL_IO = (byte) 7
(const byte) PROCPORT_RAM_CHARROM = (byte) 1
(const byte*) SCREEN = (byte*)(number) $400
(const byte*) SCREEN_COPY = (byte*)(number) $2400
(void()) main()
(byte~) main::$0
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@return
(label) main::toD0181
(word~) main::toD0181_$0
(number~) main::toD0181_$1
(number~) main::toD0181_$2
(number~) main::toD0181_$3
(word~) main::toD0181_$4
(byte~) main::toD0181_$5
(number~) main::toD0181_$6
(number~) main::toD0181_$7
(number~) main::toD0181_$8
(label) main::toD0181_@return
(byte*) main::toD0181_gfx
(byte*) main::toD0181_gfx#0
(byte*) main::toD0181_gfx#1
(byte) main::toD0181_return
(byte) main::toD0181_return#0
(byte) main::toD0181_return#1
(byte) main::toD0181_return#2
(byte) main::toD0181_return#3
(byte*) main::toD0181_screen
(byte*) main::toD0181_screen#0
(byte*) main::toD0181_screen#1
(void*()) memcpy((void*) memcpy::destination , (void*) memcpy::source , (word) memcpy::num)
(byte*~) memcpy::$0
(byte*~) memcpy::$1
(bool~) memcpy::$2
(label) memcpy::@1
(label) memcpy::@2
(label) memcpy::@3
(label) memcpy::@return
(void*) memcpy::destination
(void*) memcpy::destination#0
(void*) memcpy::destination#1
(void*) memcpy::destination#2
(void*) memcpy::destination#3
(void*) memcpy::destination#4
(void*) memcpy::destination#5
(byte*) memcpy::dst
(byte*) memcpy::dst#0
(byte*) memcpy::dst#1
(byte*) memcpy::dst#2
(byte*) memcpy::dst#3
(word) memcpy::num
(word) memcpy::num#0
(word) memcpy::num#1
(word) memcpy::num#2
(void*) memcpy::return
(void*) memcpy::return#0
(void*) memcpy::return#1
(void*) memcpy::return#2
(void*) memcpy::return#3
(void*) memcpy::return#4
(void*) memcpy::source
(void*) memcpy::source#0
(void*) memcpy::source#1
(void*) memcpy::source#2
(byte*) memcpy::src
(byte*) memcpy::src#0
(byte*) memcpy::src#1
(byte*) memcpy::src#2
(byte*) memcpy::src#3
(byte*) memcpy::src_end
(byte*) memcpy::src_end#0
(byte*) memcpy::src_end#1
(byte*) memcpy::src_end#2

Adding number conversion cast (unumber) $3fff in (number~) main::toD0181_$1 ← (word~) main::toD0181_$0 & (number) $3fff
Adding number conversion cast (unumber) main::toD0181_$1 in (number~) main::toD0181_$1 ← (word~) main::toD0181_$0 & (unumber)(number) $3fff
Adding number conversion cast (unumber) 4 in (number~) main::toD0181_$2 ← (unumber~) main::toD0181_$1 * (number) 4
Adding number conversion cast (unumber) main::toD0181_$2 in (number~) main::toD0181_$2 ← (unumber~) main::toD0181_$1 * (unumber)(number) 4
Adding number conversion cast (unumber) main::toD0181_$3 in (number~) main::toD0181_$3 ← > (unumber~) main::toD0181_$2
Adding number conversion cast (unumber) 4 in (number~) main::toD0181_$6 ← (byte~) main::toD0181_$5 / (number) 4
Adding number conversion cast (unumber) main::toD0181_$6 in (number~) main::toD0181_$6 ← (byte~) main::toD0181_$5 / (unumber)(number) 4
Adding number conversion cast (unumber) $f in (number~) main::toD0181_$7 ← (unumber~) main::toD0181_$6 & (number) $f
Adding number conversion cast (unumber) main::toD0181_$7 in (number~) main::toD0181_$7 ← (unumber~) main::toD0181_$6 & (unumber)(number) $f
Adding number conversion cast (unumber) main::toD0181_$8 in (number~) main::toD0181_$8 ← (unumber~) main::toD0181_$3 | (unumber~) main::toD0181_$7
Adding number conversion cast (unumber) $400 in (word) memcpy::num#0 ← (number) $400
Adding number conversion cast (unumber) $800 in (word) memcpy::num#1 ← (number) $800
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast (byte*) memcpy::src#0 ← (byte*)(void*) memcpy::source#2
Inlining cast (byte*) memcpy::dst#0 ← (byte*)(void*) memcpy::destination#2
Inlining cast (byte*~) memcpy::$0 ← (byte*)(void*) memcpy::source#2
Inlining cast (word~) main::toD0181_$0 ← (word)(byte*) main::toD0181_screen#1
Inlining cast (word~) main::toD0181_$4 ← (word)(byte*) main::toD0181_gfx#1
Inlining cast (word) memcpy::num#0 ← (unumber)(number) $400
Inlining cast (word) memcpy::num#1 ← (unumber)(number) $800
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (byte*) 1
Simplifying constant pointer cast (byte*) 53248
Simplifying constant pointer cast (byte*) 53272
Simplifying constant pointer cast (byte*) 8192
Simplifying constant pointer cast (byte*) 1024
Simplifying constant pointer cast (byte*) 9216
Simplifying constant integer cast $3fff
Simplifying constant integer cast 4
Simplifying constant integer cast 4
Simplifying constant integer cast $f
Simplifying constant integer cast $400
Simplifying constant integer cast $800
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (word) $3fff
Finalized unsigned number type (byte) 4
Finalized unsigned number type (byte) 4
Finalized unsigned number type (byte) $f
Finalized unsigned number type (word) $400
Finalized unsigned number type (word) $800
Successful SSA optimization PassNFinalizeNumberTypeConversions
Inferred type updated to word in (unumber~) main::toD0181_$1 ← (word~) main::toD0181_$0 & (word) $3fff
Inferred type updated to word in (unumber~) main::toD0181_$2 ← (word~) main::toD0181_$1 * (byte) 4
Inferred type updated to byte in (unumber~) main::toD0181_$3 ← > (word~) main::toD0181_$2
Inferred type updated to byte in (unumber~) main::toD0181_$6 ← (byte~) main::toD0181_$5 / (byte) 4
Inferred type updated to byte in (unumber~) main::toD0181_$7 ← (byte~) main::toD0181_$6 & (byte) $f
Inferred type updated to byte in (unumber~) main::toD0181_$8 ← (byte~) main::toD0181_$3 | (byte~) main::toD0181_$7
Alias (byte*) memcpy::src_end#0 = (byte*~) memcpy::$1 
Alias (byte*) memcpy::src#2 = (byte*) memcpy::src#3 
Alias (byte*) memcpy::dst#2 = (byte*) memcpy::dst#3 
Alias (byte*) memcpy::src_end#1 = (byte*) memcpy::src_end#2 
Alias (void*) memcpy::destination#3 = (void*) memcpy::destination#5 (void*) memcpy::destination#4 (void*) memcpy::return#0 (void*) memcpy::return#4 (void*) memcpy::return#1 
Alias (byte*) main::toD0181_screen#0 = (byte*) main::toD0181_screen#1 
Alias (byte*) main::toD0181_gfx#0 = (byte*) main::toD0181_gfx#1 
Alias (byte) main::toD0181_return#0 = (byte~) main::toD0181_$8 (byte) main::toD0181_return#2 (byte) main::toD0181_return#1 (byte) main::toD0181_return#3 (byte~) main::$0 
Successful SSA optimization Pass2AliasElimination
Identical Phi Values (byte*) memcpy::src_end#1 (byte*) memcpy::src_end#0
Identical Phi Values (void*) memcpy::destination#3 (void*) memcpy::destination#2
Successful SSA optimization Pass2IdenticalPhiElimination
Simple Condition (bool~) memcpy::$2 [7] if((byte*) memcpy::src#2!=(byte*) memcpy::src_end#0) goto memcpy::@2
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant (const byte*) main::toD0181_screen#0 = SCREEN_COPY
Constant (const byte*) main::toD0181_gfx#0 = CHARSET
Constant (const void*) memcpy::destination#0 = (void*)SCREEN_COPY
Constant (const void*) memcpy::source#0 = (void*)SCREEN
Constant (const word) memcpy::num#0 = $400
Constant (const void*) memcpy::destination#1 = (void*)CHARSET
Constant (const void*) memcpy::source#1 = (void*)CHARGEN
Constant (const word) memcpy::num#1 = $800
Successful SSA optimization Pass2ConstantIdentification
Constant (const word) main::toD0181_$0 = (word)main::toD0181_screen#0
Constant (const word) main::toD0181_$4 = (word)main::toD0181_gfx#0
Successful SSA optimization Pass2ConstantIdentification
Eliminating unused variable (void*) memcpy::return#2 and assignment [20] (void*) memcpy::return#2 ← (void*) memcpy::destination#2
Eliminating unused variable (void*) memcpy::return#3 and assignment [24] (void*) memcpy::return#3 ← (void*) memcpy::destination#2
Successful SSA optimization PassNEliminateUnusedVars
Constant right-side identified [11] (word~) main::toD0181_$1 ← (const word) main::toD0181_$0 & (word) $3fff
Constant right-side identified [14] (byte~) main::toD0181_$5 ← > (const word) main::toD0181_$4
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const word) main::toD0181_$1 = main::toD0181_$0&$3fff
Constant (const byte) main::toD0181_$5 = >main::toD0181_$4
Successful SSA optimization Pass2ConstantIdentification
Constant right-side identified [11] (word~) main::toD0181_$2 ← (const word) main::toD0181_$1 * (byte) 4
Constant right-side identified [13] (byte~) main::toD0181_$6 ← (const byte) main::toD0181_$5 / (byte) 4
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const word) main::toD0181_$2 = main::toD0181_$1*4
Constant (const byte) main::toD0181_$6 = main::toD0181_$5/4
Successful SSA optimization Pass2ConstantIdentification
Constant right-side identified [11] (byte~) main::toD0181_$3 ← > (const word) main::toD0181_$2
Constant right-side identified [12] (byte~) main::toD0181_$7 ← (const byte) main::toD0181_$6 & (byte) $f
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte) main::toD0181_$3 = >main::toD0181_$2
Constant (const byte) main::toD0181_$7 = main::toD0181_$6&$f
Successful SSA optimization Pass2ConstantIdentification
Constant right-side identified [11] (byte) main::toD0181_return#0 ← (const byte) main::toD0181_$3 | (const byte) main::toD0181_$7
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant (const byte) main::toD0181_return#0 = main::toD0181_$3|main::toD0181_$7
Successful SSA optimization Pass2ConstantIdentification
Inlining Noop Cast [1] (byte*) memcpy::src#0 ← (byte*)(void*) memcpy::source#2 keeping memcpy::source#2
Inlining Noop Cast [2] (byte*) memcpy::dst#0 ← (byte*)(void*) memcpy::destination#2 keeping memcpy::destination#2
Inlining Noop Cast [3] (byte*~) memcpy::$0 ← (byte*)(void*) memcpy::source#2 keeping memcpy::source#2
Successful SSA optimization Pass2NopCastInlining
Inlining constant with var siblings (const void*) memcpy::destination#0
Inlining constant with var siblings (const void*) memcpy::source#0
Inlining constant with var siblings (const word) memcpy::num#0
Inlining constant with var siblings (const void*) memcpy::destination#1
Inlining constant with var siblings (const void*) memcpy::source#1
Inlining constant with var siblings (const word) memcpy::num#1
Constant inlined main::toD0181_screen#0 = (const byte*) SCREEN_COPY
Constant inlined main::toD0181_gfx#0 = (const byte*) CHARSET
Constant inlined main::toD0181_$7 = >(word)(const byte*) CHARSET/(byte) 4&(byte) $f
Constant inlined main::toD0181_$2 = (word)(const byte*) SCREEN_COPY&(word) $3fff*(byte) 4
Constant inlined main::toD0181_$1 = (word)(const byte*) SCREEN_COPY&(word) $3fff
Constant inlined main::toD0181_$0 = (word)(const byte*) SCREEN_COPY
Constant inlined memcpy::destination#0 = (void*)(const byte*) SCREEN_COPY
Constant inlined memcpy::destination#1 = (void*)(const byte*) CHARSET
Constant inlined main::toD0181_$6 = >(word)(const byte*) CHARSET/(byte) 4
Constant inlined memcpy::source#0 = (void*)(const byte*) SCREEN
Constant inlined main::toD0181_$5 = >(word)(const byte*) CHARSET
Constant inlined main::toD0181_$4 = (word)(const byte*) CHARSET
Constant inlined main::toD0181_$3 = >(word)(const byte*) SCREEN_COPY&(word) $3fff*(byte) 4
Constant inlined memcpy::num#1 = (word) $800
Constant inlined memcpy::num#0 = (word) $400
Constant inlined memcpy::source#1 = (void*)(const byte*) CHARGEN
Successful SSA optimization Pass2ConstantInlining
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @10
Adding NOP phi() at start of @11
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
Adding NOP phi() at start of main::toD0181
Adding NOP phi() at start of main::toD0181_@return
Adding NOP phi() at start of memcpy::@3
CALL GRAPH
Calls in [] to main:2 
Calls in [main] to memcpy:9 memcpy:12 

Created 5 initial phi equivalence classes
Coalesced [27] memcpy::src#5 ← memcpy::src#1
Coalesced [28] memcpy::dst#5 ← memcpy::dst#1
Coalesced down to 5 phi equivalence classes
Culled Empty Block (label) @11
Culled Empty Block (label) main::toD0181_@return
Culled Empty Block (label) memcpy::@3
Renumbering block @10 to @1
Adding NOP phi() at start of @begin
Adding NOP phi() at start of @1
Adding NOP phi() at start of @end
Adding NOP phi() at start of main
Adding NOP phi() at start of main::toD0181

FINAL CONTROL FLOW GRAPH
@begin: scope:[]  from
  [0] phi()
  to:@1
@1: scope:[]  from @begin
  [1] phi()
  [2] call main 
  to:@end
@end: scope:[]  from @1
  [3] phi()

(void()) main()
main: scope:[main]  from @1
  [4] phi()
  to:main::toD0181
main::toD0181: scope:[main]  from main
  [5] phi()
  to:main::@1
main::@1: scope:[main]  from main::toD0181
  [6] *((const byte*) D018) ← (const byte) main::toD0181_return#0
  [7] call memcpy 
  to:main::@2
main::@2: scope:[main]  from main::@1
  asm { sei  }
  [9] *((const byte*) PROCPORT) ← (const byte) PROCPORT_RAM_CHARROM
  [10] call memcpy 
  to:main::@3
main::@3: scope:[main]  from main::@2
  [11] *((const byte*) PROCPORT) ← (const byte) PROCPORT_BASIC_KERNEL_IO
  asm { cli  }
  to:main::@return
main::@return: scope:[main]  from main::@3
  [13] return 
  to:@return

(void*()) memcpy((void*) memcpy::destination , (void*) memcpy::source , (word) memcpy::num)
memcpy: scope:[memcpy]  from main::@1 main::@2
  [14] (word) memcpy::num#2 ← phi( main::@1/(word) $400 main::@2/(word) $800 )
  [14] (void*) memcpy::destination#2 ← phi( main::@1/(void*)(const byte*) SCREEN_COPY main::@2/(void*)(const byte*) CHARSET )
  [14] (void*) memcpy::source#2 ← phi( main::@1/(void*)(const byte*) SCREEN main::@2/(void*)(const byte*) CHARGEN )
  [15] (byte*) memcpy::src_end#0 ← (byte*)(void*) memcpy::source#2 + (word) memcpy::num#2
  [16] (byte*) memcpy::src#4 ← (byte*)(void*) memcpy::source#2
  [17] (byte*) memcpy::dst#4 ← (byte*)(void*) memcpy::destination#2
  to:memcpy::@1
memcpy::@1: scope:[memcpy]  from memcpy memcpy::@2
  [18] (byte*) memcpy::dst#2 ← phi( memcpy/(byte*) memcpy::dst#4 memcpy::@2/(byte*) memcpy::dst#1 )
  [18] (byte*) memcpy::src#2 ← phi( memcpy/(byte*) memcpy::src#4 memcpy::@2/(byte*) memcpy::src#1 )
  [19] if((byte*) memcpy::src#2!=(byte*) memcpy::src_end#0) goto memcpy::@2
  to:memcpy::@return
memcpy::@return: scope:[memcpy]  from memcpy::@1
  [20] return 
  to:@return
memcpy::@2: scope:[memcpy]  from memcpy::@1
  [21] *((byte*) memcpy::dst#2) ← *((byte*) memcpy::src#2)
  [22] (byte*) memcpy::dst#1 ← ++ (byte*) memcpy::dst#2
  [23] (byte*) memcpy::src#1 ← ++ (byte*) memcpy::src#2
  to:memcpy::@1


VARIABLE REGISTER WEIGHTS
(void()) main()
(byte*) main::toD0181_gfx
(byte) main::toD0181_return
(byte*) main::toD0181_screen
(void*()) memcpy((void*) memcpy::destination , (void*) memcpy::source , (word) memcpy::num)
(void*) memcpy::destination
(void*) memcpy::destination#2
(byte*) memcpy::dst
(byte*) memcpy::dst#1 11.0
(byte*) memcpy::dst#2 11.666666666666666
(byte*) memcpy::dst#4 4.0
(word) memcpy::num
(word) memcpy::num#2 2.0
(void*) memcpy::return
(void*) memcpy::source
(void*) memcpy::source#2
(byte*) memcpy::src
(byte*) memcpy::src#1 22.0
(byte*) memcpy::src#2 11.5
(byte*) memcpy::src#4 2.0
(byte*) memcpy::src_end
(byte*) memcpy::src_end#0 1.625

Initial phi equivalence classes
[ memcpy::source#2 ]
[ memcpy::destination#2 ]
[ memcpy::num#2 ]
[ memcpy::src#2 memcpy::src#4 memcpy::src#1 ]
[ memcpy::dst#2 memcpy::dst#4 memcpy::dst#1 ]
Added variable memcpy::src_end#0 to live range equivalence class [ memcpy::src_end#0 ]
Complete equivalence classes
[ memcpy::source#2 ]
[ memcpy::destination#2 ]
[ memcpy::num#2 ]
[ memcpy::src#2 memcpy::src#4 memcpy::src#1 ]
[ memcpy::dst#2 memcpy::dst#4 memcpy::dst#1 ]
[ memcpy::src_end#0 ]
Allocated zp[2]:2 [ memcpy::source#2 ]
Allocated zp[2]:4 [ memcpy::destination#2 ]
Allocated zp[2]:6 [ memcpy::num#2 ]
Allocated zp[2]:8 [ memcpy::src#2 memcpy::src#4 memcpy::src#1 ]
Allocated zp[2]:10 [ memcpy::dst#2 memcpy::dst#4 memcpy::dst#1 ]
Allocated zp[2]:12 [ memcpy::src_end#0 ]

INITIAL ASM
Target platform is c64basic / MOS6502X
  // File Comments
// Test memcpy - copy charset and screen using memcpy() from stdlib string
  // Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
  // Global Constants & labels
  // Processor Port Register controlling RAM/ROM configuration and the datasette
  .label PROCPORT = 1
  // RAM in $A000, $E000 CHAR ROM in $D000
  .const PROCPORT_RAM_CHARROM = 1
  // BASIC in $A000, I/O in $D000, KERNEL in $E000
  .const PROCPORT_BASIC_KERNEL_IO = 7
  // The address of the CHARGEN character set
  .label CHARGEN = $d000
  .label D018 = $d018
  .label CHARSET = $2000
  .label SCREEN = $400
  .label SCREEN_COPY = $2400
  // @begin
__bbegin:
  // [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
  jmp __b1
  // @1
__b1:
  // [2] call main 
  // [4] phi from @1 to main [phi:@1->main]
main_from___b1:
  jsr main
  // [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
  jmp __bend
  // @end
__bend:
  // main
main: {
    .const toD0181_return = (>(SCREEN_COPY&$3fff)*4)|(>CHARSET)/4&$f
    // [5] phi from main to main::toD0181 [phi:main->main::toD0181]
  toD0181_from_main:
    jmp toD0181
    // main::toD0181
  toD0181:
    jmp __b1
    // main::@1
  __b1:
    // [6] *((const byte*) D018) ← (const byte) main::toD0181_return#0 -- _deref_pbuc1=vbuc2 
    lda #toD0181_return
    sta D018
    // [7] call memcpy 
    // [14] phi from main::@1 to memcpy [phi:main::@1->memcpy]
  memcpy_from___b1:
    // [14] phi (word) memcpy::num#2 = (word) $400 [phi:main::@1->memcpy#0] -- vwuz1=vwuc1 
    lda #<$400
    sta.z memcpy.num
    lda #>$400
    sta.z memcpy.num+1
    // [14] phi (void*) memcpy::destination#2 = (void*)(const byte*) SCREEN_COPY [phi:main::@1->memcpy#1] -- pvoz1=pvoc1 
    lda #<SCREEN_COPY
    sta.z memcpy.destination
    lda #>SCREEN_COPY
    sta.z memcpy.destination+1
    // [14] phi (void*) memcpy::source#2 = (void*)(const byte*) SCREEN [phi:main::@1->memcpy#2] -- pvoz1=pvoc1 
    lda #<SCREEN
    sta.z memcpy.source
    lda #>SCREEN
    sta.z memcpy.source+1
    jsr memcpy
    jmp __b2
    // main::@2
  __b2:
    // asm { sei  }
    sei
    // [9] *((const byte*) PROCPORT) ← (const byte) PROCPORT_RAM_CHARROM -- _deref_pbuc1=vbuc2 
    lda #PROCPORT_RAM_CHARROM
    sta PROCPORT
    // [10] call memcpy 
    // [14] phi from main::@2 to memcpy [phi:main::@2->memcpy]
  memcpy_from___b2:
    // [14] phi (word) memcpy::num#2 = (word) $800 [phi:main::@2->memcpy#0] -- vwuz1=vwuc1 
    lda #<$800
    sta.z memcpy.num
    lda #>$800
    sta.z memcpy.num+1
    // [14] phi (void*) memcpy::destination#2 = (void*)(const byte*) CHARSET [phi:main::@2->memcpy#1] -- pvoz1=pvoc1 
    lda #<CHARSET
    sta.z memcpy.destination
    lda #>CHARSET
    sta.z memcpy.destination+1
    // [14] phi (void*) memcpy::source#2 = (void*)(const byte*) CHARGEN [phi:main::@2->memcpy#2] -- pvoz1=pvoc1 
    lda #<CHARGEN
    sta.z memcpy.source
    lda #>CHARGEN
    sta.z memcpy.source+1
    jsr memcpy
    jmp __b3
    // main::@3
  __b3:
    // [11] *((const byte*) PROCPORT) ← (const byte) PROCPORT_BASIC_KERNEL_IO -- _deref_pbuc1=vbuc2 
    lda #PROCPORT_BASIC_KERNEL_IO
    sta PROCPORT
    // asm { cli  }
    cli
    jmp __breturn
    // main::@return
  __breturn:
    // [13] return 
    rts
}
  // memcpy
// Copy block of memory (forwards)
// Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination.
// memcpy(void* zp(4) destination, void* zp(2) source, word zp(6) num)
memcpy: {
    .label src_end = $c
    .label dst = $a
    .label src = 8
    .label source = 2
    .label destination = 4
    .label num = 6
    // [15] (byte*) memcpy::src_end#0 ← (byte*)(void*) memcpy::source#2 + (word) memcpy::num#2 -- pbuz1=pbuz2_plus_vwuz3 
    lda.z source
    clc
    adc.z num
    sta.z src_end
    lda.z source+1
    adc.z num+1
    sta.z src_end+1
    // [16] (byte*) memcpy::src#4 ← (byte*)(void*) memcpy::source#2 -- pbuz1=pbuz2 
    lda.z source
    sta.z src
    lda.z source+1
    sta.z src+1
    // [17] (byte*) memcpy::dst#4 ← (byte*)(void*) memcpy::destination#2 -- pbuz1=pbuz2 
    lda.z destination
    sta.z dst
    lda.z destination+1
    sta.z dst+1
    // [18] phi from memcpy memcpy::@2 to memcpy::@1 [phi:memcpy/memcpy::@2->memcpy::@1]
  __b1_from_memcpy:
  __b1_from___b2:
    // [18] phi (byte*) memcpy::dst#2 = (byte*) memcpy::dst#4 [phi:memcpy/memcpy::@2->memcpy::@1#0] -- register_copy 
    // [18] phi (byte*) memcpy::src#2 = (byte*) memcpy::src#4 [phi:memcpy/memcpy::@2->memcpy::@1#1] -- register_copy 
    jmp __b1
    // memcpy::@1
  __b1:
    // [19] if((byte*) memcpy::src#2!=(byte*) memcpy::src_end#0) goto memcpy::@2 -- pbuz1_neq_pbuz2_then_la1 
    lda.z src+1
    cmp.z src_end+1
    bne __b2
    lda.z src
    cmp.z src_end
    bne __b2
    jmp __breturn
    // memcpy::@return
  __breturn:
    // [20] return 
    rts
    // memcpy::@2
  __b2:
    // [21] *((byte*) memcpy::dst#2) ← *((byte*) memcpy::src#2) -- _deref_pbuz1=_deref_pbuz2 
    ldy #0
    lda (src),y
    ldy #0
    sta (dst),y
    // [22] (byte*) memcpy::dst#1 ← ++ (byte*) memcpy::dst#2 -- pbuz1=_inc_pbuz1 
    inc.z dst
    bne !+
    inc.z dst+1
  !:
    // [23] (byte*) memcpy::src#1 ← ++ (byte*) memcpy::src#2 -- pbuz1=_inc_pbuz1 
    inc.z src
    bne !+
    inc.z src+1
  !:
    jmp __b1_from___b2
}
  // File Data

REGISTER UPLIFT POTENTIAL REGISTERS
Statement [6] *((const byte*) D018) ← (const byte) main::toD0181_return#0 [ ] ( main:2 [ ] ) always clobbers reg byte a 
Statement [9] *((const byte*) PROCPORT) ← (const byte) PROCPORT_RAM_CHARROM [ ] ( main:2 [ ] ) always clobbers reg byte a 
Statement [11] *((const byte*) PROCPORT) ← (const byte) PROCPORT_BASIC_KERNEL_IO [ ] ( main:2 [ ] ) always clobbers reg byte a 
Statement [15] (byte*) memcpy::src_end#0 ← (byte*)(void*) memcpy::source#2 + (word) memcpy::num#2 [ memcpy::source#2 memcpy::destination#2 memcpy::src_end#0 ] ( main:2::memcpy:7 [ memcpy::source#2 memcpy::destination#2 memcpy::src_end#0 ] main:2::memcpy:10 [ memcpy::source#2 memcpy::destination#2 memcpy::src_end#0 ] ) always clobbers reg byte a 
Statement [16] (byte*) memcpy::src#4 ← (byte*)(void*) memcpy::source#2 [ memcpy::destination#2 memcpy::src_end#0 memcpy::src#4 ] ( main:2::memcpy:7 [ memcpy::destination#2 memcpy::src_end#0 memcpy::src#4 ] main:2::memcpy:10 [ memcpy::destination#2 memcpy::src_end#0 memcpy::src#4 ] ) always clobbers reg byte a 
Statement [17] (byte*) memcpy::dst#4 ← (byte*)(void*) memcpy::destination#2 [ memcpy::src_end#0 memcpy::src#4 memcpy::dst#4 ] ( main:2::memcpy:7 [ memcpy::src_end#0 memcpy::src#4 memcpy::dst#4 ] main:2::memcpy:10 [ memcpy::src_end#0 memcpy::src#4 memcpy::dst#4 ] ) always clobbers reg byte a 
Statement [19] if((byte*) memcpy::src#2!=(byte*) memcpy::src_end#0) goto memcpy::@2 [ memcpy::src_end#0 memcpy::src#2 memcpy::dst#2 ] ( main:2::memcpy:7 [ memcpy::src_end#0 memcpy::src#2 memcpy::dst#2 ] main:2::memcpy:10 [ memcpy::src_end#0 memcpy::src#2 memcpy::dst#2 ] ) always clobbers reg byte a 
Statement [21] *((byte*) memcpy::dst#2) ← *((byte*) memcpy::src#2) [ memcpy::src_end#0 memcpy::src#2 memcpy::dst#2 ] ( main:2::memcpy:7 [ memcpy::src_end#0 memcpy::src#2 memcpy::dst#2 ] main:2::memcpy:10 [ memcpy::src_end#0 memcpy::src#2 memcpy::dst#2 ] ) always clobbers reg byte a reg byte y 
Potential registers zp[2]:2 [ memcpy::source#2 ] : zp[2]:2 , 
Potential registers zp[2]:4 [ memcpy::destination#2 ] : zp[2]:4 , 
Potential registers zp[2]:6 [ memcpy::num#2 ] : zp[2]:6 , 
Potential registers zp[2]:8 [ memcpy::src#2 memcpy::src#4 memcpy::src#1 ] : zp[2]:8 , 
Potential registers zp[2]:10 [ memcpy::dst#2 memcpy::dst#4 memcpy::dst#1 ] : zp[2]:10 , 
Potential registers zp[2]:12 [ memcpy::src_end#0 ] : zp[2]:12 , 

REGISTER UPLIFT SCOPES
Uplift Scope [memcpy] 35.5: zp[2]:8 [ memcpy::src#2 memcpy::src#4 memcpy::src#1 ] 26.67: zp[2]:10 [ memcpy::dst#2 memcpy::dst#4 memcpy::dst#1 ] 2: zp[2]:6 [ memcpy::num#2 ] 1.62: zp[2]:12 [ memcpy::src_end#0 ] 0: zp[2]:2 [ memcpy::source#2 ] 0: zp[2]:4 [ memcpy::destination#2 ] 
Uplift Scope [main] 
Uplift Scope [] 

Uplifting [memcpy] best 869 combination zp[2]:8 [ memcpy::src#2 memcpy::src#4 memcpy::src#1 ] zp[2]:10 [ memcpy::dst#2 memcpy::dst#4 memcpy::dst#1 ] zp[2]:6 [ memcpy::num#2 ] zp[2]:12 [ memcpy::src_end#0 ] zp[2]:2 [ memcpy::source#2 ] zp[2]:4 [ memcpy::destination#2 ] 
Uplifting [main] best 869 combination 
Uplifting [] best 869 combination 
Coalescing zero page register [ zp[2]:2 [ memcpy::source#2 ] ] with [ zp[2]:8 [ memcpy::src#2 memcpy::src#4 memcpy::src#1 ] ] - score: 1
Coalescing zero page register [ zp[2]:4 [ memcpy::destination#2 ] ] with [ zp[2]:10 [ memcpy::dst#2 memcpy::dst#4 memcpy::dst#1 ] ] - score: 1
Coalescing zero page register [ zp[2]:6 [ memcpy::num#2 ] ] with [ zp[2]:12 [ memcpy::src_end#0 ] ] - score: 1

ASSEMBLER BEFORE OPTIMIZATION
  // File Comments
// Test memcpy - copy charset and screen using memcpy() from stdlib string
  // Upstart
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
  // Global Constants & labels
  // Processor Port Register controlling RAM/ROM configuration and the datasette
  .label PROCPORT = 1
  // RAM in $A000, $E000 CHAR ROM in $D000
  .const PROCPORT_RAM_CHARROM = 1
  // BASIC in $A000, I/O in $D000, KERNEL in $E000
  .const PROCPORT_BASIC_KERNEL_IO = 7
  // The address of the CHARGEN character set
  .label CHARGEN = $d000
  .label D018 = $d018
  .label CHARSET = $2000
  .label SCREEN = $400
  .label SCREEN_COPY = $2400
  // @begin
__bbegin:
  // [1] phi from @begin to @1 [phi:@begin->@1]
__b1_from___bbegin:
  jmp __b1
  // @1
__b1:
  // [2] call main 
  // [4] phi from @1 to main [phi:@1->main]
main_from___b1:
  jsr main
  // [3] phi from @1 to @end [phi:@1->@end]
__bend_from___b1:
  jmp __bend
  // @end
__bend:
  // main
main: {
    .const toD0181_return = (>(SCREEN_COPY&$3fff)*4)|(>CHARSET)/4&$f
    // [5] phi from main to main::toD0181 [phi:main->main::toD0181]
  toD0181_from_main:
    jmp toD0181
    // main::toD0181
  toD0181:
    jmp __b1
    // main::@1
  __b1:
    // [6] *((const byte*) D018) ← (const byte) main::toD0181_return#0 -- _deref_pbuc1=vbuc2 
    lda #toD0181_return
    sta D018
    // [7] call memcpy 
    // [14] phi from main::@1 to memcpy [phi:main::@1->memcpy]
  memcpy_from___b1:
    // [14] phi (word) memcpy::num#2 = (word) $400 [phi:main::@1->memcpy#0] -- vwuz1=vwuc1 
    lda #<$400
    sta.z memcpy.num
    lda #>$400
    sta.z memcpy.num+1
    // [14] phi (void*) memcpy::destination#2 = (void*)(const byte*) SCREEN_COPY [phi:main::@1->memcpy#1] -- pvoz1=pvoc1 
    lda #<SCREEN_COPY
    sta.z memcpy.destination
    lda #>SCREEN_COPY
    sta.z memcpy.destination+1
    // [14] phi (void*) memcpy::source#2 = (void*)(const byte*) SCREEN [phi:main::@1->memcpy#2] -- pvoz1=pvoc1 
    lda #<SCREEN
    sta.z memcpy.source
    lda #>SCREEN
    sta.z memcpy.source+1
    jsr memcpy
    jmp __b2
    // main::@2
  __b2:
    // asm { sei  }
    sei
    // [9] *((const byte*) PROCPORT) ← (const byte) PROCPORT_RAM_CHARROM -- _deref_pbuc1=vbuc2 
    lda #PROCPORT_RAM_CHARROM
    sta PROCPORT
    // [10] call memcpy 
    // [14] phi from main::@2 to memcpy [phi:main::@2->memcpy]
  memcpy_from___b2:
    // [14] phi (word) memcpy::num#2 = (word) $800 [phi:main::@2->memcpy#0] -- vwuz1=vwuc1 
    lda #<$800
    sta.z memcpy.num
    lda #>$800
    sta.z memcpy.num+1
    // [14] phi (void*) memcpy::destination#2 = (void*)(const byte*) CHARSET [phi:main::@2->memcpy#1] -- pvoz1=pvoc1 
    lda #<CHARSET
    sta.z memcpy.destination
    lda #>CHARSET
    sta.z memcpy.destination+1
    // [14] phi (void*) memcpy::source#2 = (void*)(const byte*) CHARGEN [phi:main::@2->memcpy#2] -- pvoz1=pvoc1 
    lda #<CHARGEN
    sta.z memcpy.source
    lda #>CHARGEN
    sta.z memcpy.source+1
    jsr memcpy
    jmp __b3
    // main::@3
  __b3:
    // [11] *((const byte*) PROCPORT) ← (const byte) PROCPORT_BASIC_KERNEL_IO -- _deref_pbuc1=vbuc2 
    lda #PROCPORT_BASIC_KERNEL_IO
    sta PROCPORT
    // asm { cli  }
    cli
    jmp __breturn
    // main::@return
  __breturn:
    // [13] return 
    rts
}
  // memcpy
// Copy block of memory (forwards)
// Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination.
// memcpy(void* zp(4) destination, void* zp(2) source, word zp(6) num)
memcpy: {
    .label src_end = 6
    .label dst = 4
    .label src = 2
    .label source = 2
    .label destination = 4
    .label num = 6
    // [15] (byte*) memcpy::src_end#0 ← (byte*)(void*) memcpy::source#2 + (word) memcpy::num#2 -- pbuz1=pbuz2_plus_vwuz1 
    lda.z src_end
    clc
    adc.z source
    sta.z src_end
    lda.z src_end+1
    adc.z source+1
    sta.z src_end+1
    // [16] (byte*) memcpy::src#4 ← (byte*)(void*) memcpy::source#2
    // [17] (byte*) memcpy::dst#4 ← (byte*)(void*) memcpy::destination#2
    // [18] phi from memcpy memcpy::@2 to memcpy::@1 [phi:memcpy/memcpy::@2->memcpy::@1]
  __b1_from_memcpy:
  __b1_from___b2:
    // [18] phi (byte*) memcpy::dst#2 = (byte*) memcpy::dst#4 [phi:memcpy/memcpy::@2->memcpy::@1#0] -- register_copy 
    // [18] phi (byte*) memcpy::src#2 = (byte*) memcpy::src#4 [phi:memcpy/memcpy::@2->memcpy::@1#1] -- register_copy 
    jmp __b1
    // memcpy::@1
  __b1:
    // [19] if((byte*) memcpy::src#2!=(byte*) memcpy::src_end#0) goto memcpy::@2 -- pbuz1_neq_pbuz2_then_la1 
    lda.z src+1
    cmp.z src_end+1
    bne __b2
    lda.z src
    cmp.z src_end
    bne __b2
    jmp __breturn
    // memcpy::@return
  __breturn:
    // [20] return 
    rts
    // memcpy::@2
  __b2:
    // [21] *((byte*) memcpy::dst#2) ← *((byte*) memcpy::src#2) -- _deref_pbuz1=_deref_pbuz2 
    ldy #0
    lda (src),y
    ldy #0
    sta (dst),y
    // [22] (byte*) memcpy::dst#1 ← ++ (byte*) memcpy::dst#2 -- pbuz1=_inc_pbuz1 
    inc.z dst
    bne !+
    inc.z dst+1
  !:
    // [23] (byte*) memcpy::src#1 ← ++ (byte*) memcpy::src#2 -- pbuz1=_inc_pbuz1 
    inc.z src
    bne !+
    inc.z src+1
  !:
    jmp __b1_from___b2
}
  // File Data

ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __bend
Removing instruction jmp toD0181
Removing instruction jmp __b1
Removing instruction jmp __b2
Removing instruction jmp __b3
Removing instruction jmp __breturn
Removing instruction jmp __b1
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction ldy #0
Succesful ASM optimization Pass5UnnecesaryLoadElimination
Replacing label __bbegin with __b1
Replacing label __b1_from___b2 with __b1
Removing instruction __bbegin:
Removing instruction __b1_from___bbegin:
Removing instruction main_from___b1:
Removing instruction __bend_from___b1:
Removing instruction toD0181_from_main:
Removing instruction toD0181:
Removing instruction __b1_from_memcpy:
Removing instruction __b1_from___b2:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __bend:
Removing instruction __b1:
Removing instruction memcpy_from___b1:
Removing instruction __b2:
Removing instruction memcpy_from___b2:
Removing instruction __b3:
Removing instruction __breturn:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination
Updating BasicUpstart to call main directly
Removing instruction jsr main
Succesful ASM optimization Pass5SkipBegin
Removing instruction __b1:
Succesful ASM optimization Pass5UnusedLabelElimination

FINAL SYMBOL TABLE
(label) @1
(label) @begin
(label) @end
(const byte*) CHARGEN = (byte*) 53248
(const byte*) CHARSET = (byte*) 8192
(const byte*) D018 = (byte*) 53272
(const byte*) PROCPORT = (byte*) 1
(const byte) PROCPORT_BASIC_KERNEL_IO = (byte) 7
(const byte) PROCPORT_RAM_CHARROM = (byte) 1
(const byte*) SCREEN = (byte*) 1024
(const byte*) SCREEN_COPY = (byte*) 9216
(void()) main()
(label) main::@1
(label) main::@2
(label) main::@3
(label) main::@return
(label) main::toD0181
(byte*) main::toD0181_gfx
(byte) main::toD0181_return
(const byte) main::toD0181_return#0 toD0181_return = >(word)(const byte*) SCREEN_COPY&(word) $3fff*(byte) 4|>(word)(const byte*) CHARSET/(byte) 4&(byte) $f
(byte*) main::toD0181_screen
(void*()) memcpy((void*) memcpy::destination , (void*) memcpy::source , (word) memcpy::num)
(label) memcpy::@1
(label) memcpy::@2
(label) memcpy::@return
(void*) memcpy::destination
(void*) memcpy::destination#2 destination zp[2]:4
(byte*) memcpy::dst
(byte*) memcpy::dst#1 dst zp[2]:4 11.0
(byte*) memcpy::dst#2 dst zp[2]:4 11.666666666666666
(byte*) memcpy::dst#4 dst zp[2]:4 4.0
(word) memcpy::num
(word) memcpy::num#2 num zp[2]:6 2.0
(void*) memcpy::return
(void*) memcpy::source
(void*) memcpy::source#2 source zp[2]:2
(byte*) memcpy::src
(byte*) memcpy::src#1 src zp[2]:2 22.0
(byte*) memcpy::src#2 src zp[2]:2 11.5
(byte*) memcpy::src#4 src zp[2]:2 2.0
(byte*) memcpy::src_end
(byte*) memcpy::src_end#0 src_end zp[2]:6 1.625

zp[2]:2 [ memcpy::source#2 memcpy::src#2 memcpy::src#4 memcpy::src#1 ]
zp[2]:4 [ memcpy::destination#2 memcpy::dst#2 memcpy::dst#4 memcpy::dst#1 ]
zp[2]:6 [ memcpy::num#2 memcpy::src_end#0 ]


FINAL ASSEMBLER
Score: 711

  // File Comments
// Test memcpy - copy charset and screen using memcpy() from stdlib string
  // Upstart
.pc = $801 "Basic"
:BasicUpstart(main)
.pc = $80d "Program"
  // Global Constants & labels
  // Processor Port Register controlling RAM/ROM configuration and the datasette
  .label PROCPORT = 1
  // RAM in $A000, $E000 CHAR ROM in $D000
  .const PROCPORT_RAM_CHARROM = 1
  // BASIC in $A000, I/O in $D000, KERNEL in $E000
  .const PROCPORT_BASIC_KERNEL_IO = 7
  // The address of the CHARGEN character set
  .label CHARGEN = $d000
  .label D018 = $d018
  .label CHARSET = $2000
  .label SCREEN = $400
  .label SCREEN_COPY = $2400
  // @begin
  // [1] phi from @begin to @1 [phi:@begin->@1]
  // @1
  // [2] call main 
  // [4] phi from @1 to main [phi:@1->main]
  // [3] phi from @1 to @end [phi:@1->@end]
  // @end
  // main
main: {
    .const toD0181_return = (>(SCREEN_COPY&$3fff)*4)|(>CHARSET)/4&$f
    // [5] phi from main to main::toD0181 [phi:main->main::toD0181]
    // main::toD0181
    // main::@1
    // *D018 = toD018(SCREEN_COPY, CHARSET)
    // [6] *((const byte*) D018) ← (const byte) main::toD0181_return#0 -- _deref_pbuc1=vbuc2 
    lda #toD0181_return
    sta D018
    // memcpy(SCREEN_COPY, SCREEN, 0x0400)
    // [7] call memcpy 
    // [14] phi from main::@1 to memcpy [phi:main::@1->memcpy]
    // [14] phi (word) memcpy::num#2 = (word) $400 [phi:main::@1->memcpy#0] -- vwuz1=vwuc1 
    lda #<$400
    sta.z memcpy.num
    lda #>$400
    sta.z memcpy.num+1
    // [14] phi (void*) memcpy::destination#2 = (void*)(const byte*) SCREEN_COPY [phi:main::@1->memcpy#1] -- pvoz1=pvoc1 
    lda #<SCREEN_COPY
    sta.z memcpy.destination
    lda #>SCREEN_COPY
    sta.z memcpy.destination+1
    // [14] phi (void*) memcpy::source#2 = (void*)(const byte*) SCREEN [phi:main::@1->memcpy#2] -- pvoz1=pvoc1 
    lda #<SCREEN
    sta.z memcpy.source
    lda #>SCREEN
    sta.z memcpy.source+1
    jsr memcpy
    // main::@2
    // asm
    // asm { sei  }
    sei
    // *PROCPORT = PROCPORT_RAM_CHARROM
    // [9] *((const byte*) PROCPORT) ← (const byte) PROCPORT_RAM_CHARROM -- _deref_pbuc1=vbuc2 
    lda #PROCPORT_RAM_CHARROM
    sta PROCPORT
    // memcpy(CHARSET, CHARGEN, 0x0800)
    // [10] call memcpy 
    // [14] phi from main::@2 to memcpy [phi:main::@2->memcpy]
    // [14] phi (word) memcpy::num#2 = (word) $800 [phi:main::@2->memcpy#0] -- vwuz1=vwuc1 
    lda #<$800
    sta.z memcpy.num
    lda #>$800
    sta.z memcpy.num+1
    // [14] phi (void*) memcpy::destination#2 = (void*)(const byte*) CHARSET [phi:main::@2->memcpy#1] -- pvoz1=pvoc1 
    lda #<CHARSET
    sta.z memcpy.destination
    lda #>CHARSET
    sta.z memcpy.destination+1
    // [14] phi (void*) memcpy::source#2 = (void*)(const byte*) CHARGEN [phi:main::@2->memcpy#2] -- pvoz1=pvoc1 
    lda #<CHARGEN
    sta.z memcpy.source
    lda #>CHARGEN
    sta.z memcpy.source+1
    jsr memcpy
    // main::@3
    // *PROCPORT = PROCPORT_BASIC_KERNEL_IO
    // [11] *((const byte*) PROCPORT) ← (const byte) PROCPORT_BASIC_KERNEL_IO -- _deref_pbuc1=vbuc2 
    lda #PROCPORT_BASIC_KERNEL_IO
    sta PROCPORT
    // asm
    // asm { cli  }
    cli
    // main::@return
    // }
    // [13] return 
    rts
}
  // memcpy
// Copy block of memory (forwards)
// Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination.
// memcpy(void* zp(4) destination, void* zp(2) source, word zp(6) num)
memcpy: {
    .label src_end = 6
    .label dst = 4
    .label src = 2
    .label source = 2
    .label destination = 4
    .label num = 6
    // src_end = (char*)source+num
    // [15] (byte*) memcpy::src_end#0 ← (byte*)(void*) memcpy::source#2 + (word) memcpy::num#2 -- pbuz1=pbuz2_plus_vwuz1 
    lda.z src_end
    clc
    adc.z source
    sta.z src_end
    lda.z src_end+1
    adc.z source+1
    sta.z src_end+1
    // [16] (byte*) memcpy::src#4 ← (byte*)(void*) memcpy::source#2
    // [17] (byte*) memcpy::dst#4 ← (byte*)(void*) memcpy::destination#2
    // [18] phi from memcpy memcpy::@2 to memcpy::@1 [phi:memcpy/memcpy::@2->memcpy::@1]
    // [18] phi (byte*) memcpy::dst#2 = (byte*) memcpy::dst#4 [phi:memcpy/memcpy::@2->memcpy::@1#0] -- register_copy 
    // [18] phi (byte*) memcpy::src#2 = (byte*) memcpy::src#4 [phi:memcpy/memcpy::@2->memcpy::@1#1] -- register_copy 
    // memcpy::@1
  __b1:
    // while(src!=src_end)
    // [19] if((byte*) memcpy::src#2!=(byte*) memcpy::src_end#0) goto memcpy::@2 -- pbuz1_neq_pbuz2_then_la1 
    lda.z src+1
    cmp.z src_end+1
    bne __b2
    lda.z src
    cmp.z src_end
    bne __b2
    // memcpy::@return
    // }
    // [20] return 
    rts
    // memcpy::@2
  __b2:
    // *dst++ = *src++
    // [21] *((byte*) memcpy::dst#2) ← *((byte*) memcpy::src#2) -- _deref_pbuz1=_deref_pbuz2 
    ldy #0
    lda (src),y
    sta (dst),y
    // *dst++ = *src++;
    // [22] (byte*) memcpy::dst#1 ← ++ (byte*) memcpy::dst#2 -- pbuz1=_inc_pbuz1 
    inc.z dst
    bne !+
    inc.z dst+1
  !:
    // [23] (byte*) memcpy::src#1 ← ++ (byte*) memcpy::src#2 -- pbuz1=_inc_pbuz1 
    inc.z src
    bne !+
    inc.z src+1
  !:
    jmp __b1
}
  // File Data

