Setting inferred volatile on symbol affected by address-of: setnam::filename_len in asm { ldafilename_len ldxfilename ldyfilename+1 jsr$ffbd  }
Setting inferred volatile on symbol affected by address-of: setnam::filename in asm { ldafilename_len ldxfilename ldyfilename+1 jsr$ffbd  }
Setting inferred volatile on symbol affected by address-of: setlfs::device in asm { ldxdevice lda#1 ldy#0 jsr$ffba  }
Setting inferred volatile on symbol affected by address-of: load::address in asm { ldxaddress ldyaddress+1 ldaverify jsr$ffd5 bcserror lda#$ff error: stastatus  }
Setting inferred volatile on symbol affected by address-of: load::verify in asm { ldxaddress ldyaddress+1 ldaverify jsr$ffd5 bcserror lda#$ff error: stastatus  }
Setting inferred volatile on symbol affected by address-of: load::status in asm { ldxaddress ldyaddress+1 ldaverify jsr$ffd5 bcserror lda#$ff error: stastatus  }
Setting inferred volatile on symbol affected by address-of: getin::ch in asm { jsr$ffe4 stach  }
Eliminating unused variable with no statement memcpy_to_vram::$3

CONTROL FLOW GRAPH SSA

void vpoke(char vbank , char *vaddr , char data)
vpoke: scope:[vpoke]  from main::@2 main::@4
  vpoke::data#2 = phi( main::@2/vpoke::data#0, main::@4/vpoke::data#1 )
  vpoke::vbank#2 = phi( main::@2/vpoke::vbank#0, main::@4/vpoke::vbank#1 )
  vpoke::vaddr#2 = phi( main::@2/vpoke::vaddr#0, main::@4/vpoke::vaddr#1 )
  *VERA_CTRL = *VERA_CTRL & ~VERA_ADDRSEL
  vpoke::$0 = byte0  vpoke::vaddr#2
  *VERA_ADDRX_L = vpoke::$0
  vpoke::$1 = byte1  vpoke::vaddr#2
  *VERA_ADDRX_M = vpoke::$1
  vpoke::$2 = VERA_INC_0 | vpoke::vbank#2
  *VERA_ADDRX_H = vpoke::$2
  *VERA_DATA0 = vpoke::data#2
  to:vpoke::@return
vpoke::@return: scope:[vpoke]  from vpoke
  return 
  to:@return

void memcpy_to_vram(char vbank , void *vdest , void *src , unsigned int num)
memcpy_to_vram: scope:[memcpy_to_vram]  from main::@3
  memcpy_to_vram::num#1 = phi( main::@3/memcpy_to_vram::num#0 )
  memcpy_to_vram::src#1 = phi( main::@3/memcpy_to_vram::src#0 )
  memcpy_to_vram::vbank#1 = phi( main::@3/memcpy_to_vram::vbank#0 )
  memcpy_to_vram::vdest#1 = phi( main::@3/memcpy_to_vram::vdest#0 )
  *VERA_CTRL = *VERA_CTRL & ~VERA_ADDRSEL
  memcpy_to_vram::$0 = byte0  memcpy_to_vram::vdest#1
  *VERA_ADDRX_L = memcpy_to_vram::$0
  memcpy_to_vram::$1 = byte1  memcpy_to_vram::vdest#1
  *VERA_ADDRX_M = memcpy_to_vram::$1
  memcpy_to_vram::$2 = VERA_INC_1 | memcpy_to_vram::vbank#1
  *VERA_ADDRX_H = memcpy_to_vram::$2
  memcpy_to_vram::$5 = (char *)memcpy_to_vram::src#1
  memcpy_to_vram::end#0 = memcpy_to_vram::$5 + memcpy_to_vram::num#1
  memcpy_to_vram::s#0 = ((char *)) memcpy_to_vram::src#1
  to:memcpy_to_vram::@1
memcpy_to_vram::@1: scope:[memcpy_to_vram]  from memcpy_to_vram memcpy_to_vram::@2
  memcpy_to_vram::end#1 = phi( memcpy_to_vram/memcpy_to_vram::end#0, memcpy_to_vram::@2/memcpy_to_vram::end#2 )
  memcpy_to_vram::s#2 = phi( memcpy_to_vram/memcpy_to_vram::s#0, memcpy_to_vram::@2/memcpy_to_vram::s#1 )
  memcpy_to_vram::$4 = memcpy_to_vram::s#2 != memcpy_to_vram::end#1
  if(memcpy_to_vram::$4) goto memcpy_to_vram::@2
  to:memcpy_to_vram::@return
memcpy_to_vram::@2: scope:[memcpy_to_vram]  from memcpy_to_vram::@1
  memcpy_to_vram::end#2 = phi( memcpy_to_vram::@1/memcpy_to_vram::end#1 )
  memcpy_to_vram::s#3 = phi( memcpy_to_vram::@1/memcpy_to_vram::s#2 )
  *VERA_DATA0 = *memcpy_to_vram::s#3
  memcpy_to_vram::s#1 = ++ memcpy_to_vram::s#3
  to:memcpy_to_vram::@1
memcpy_to_vram::@return: scope:[memcpy_to_vram]  from memcpy_to_vram::@1
  return 
  to:@return

void main()
main: scope:[main]  from __start
  main::vaddr#0 = DEFAULT_SCREEN
  main::i#0 = 0
  to:main::@1
main::@1: scope:[main]  from main main::@5
  main::vaddr#6 = phi( main/main::vaddr#0, main::@5/main::vaddr#2 )
  main::i#2 = phi( main/main::i#0, main::@5/main::i#1 )
  main::$4 = 0 != main::MSG[main::i#2]
  if(main::$4) goto main::@2
  to:main::@3
main::@2: scope:[main]  from main::@1
  main::i#3 = phi( main::@1/main::i#2 )
  main::vaddr#3 = phi( main::@1/main::vaddr#6 )
  vpoke::vbank#0 = 0
  vpoke::vaddr#0 = main::vaddr#3
  vpoke::data#0 = main::MSG[main::i#3]
  call vpoke
  to:main::@4
main::@4: scope:[main]  from main::@2
  main::i#5 = phi( main::@2/main::i#3 )
  main::vaddr#4 = phi( main::@2/main::vaddr#3 )
  main::vaddr#1 = ++ main::vaddr#4
  vpoke::vbank#1 = 0
  vpoke::vaddr#1 = main::vaddr#1
  vpoke::data#1 = $21
  call vpoke
  to:main::@5
main::@5: scope:[main]  from main::@4
  main::i#4 = phi( main::@4/main::i#5 )
  main::vaddr#5 = phi( main::@4/main::vaddr#1 )
  main::vaddr#2 = ++ main::vaddr#5
  main::i#1 = ++ main::i#4
  to:main::@1
main::@3: scope:[main]  from main::@1
  main::$0 = sizeof  main::MSG2
  memcpy_to_vram::vbank#0 = 0
  memcpy_to_vram::vdest#0 = (void *)DEFAULT_SCREEN+$100
  memcpy_to_vram::src#0 = (void *)main::MSG2
  memcpy_to_vram::num#0 = main::$0
  call memcpy_to_vram
  to:main::@6
main::@6: scope:[main]  from main::@3
  to:main::@return
main::@return: scope:[main]  from main::@6
  return 
  to:@return

void __start()
__start: scope:[__start]  from
  call main
  to:__start::@1
__start::@1: scope:[__start]  from __start
  to:__start::@return
__start::@return: scope:[__start]  from __start::@1
  return 
  to:@return

SYMBOL TABLE SSA
__constant char * const DEFAULT_SCREEN = (char *)0
__constant const char VERA_ADDRSEL = 1
__constant char * const VERA_ADDRX_H = (char *)$9f22
__constant char * const VERA_ADDRX_L = (char *)$9f20
__constant char * const VERA_ADDRX_M = (char *)$9f21
__constant char * const VERA_CTRL = (char *)$9f25
__constant char * const VERA_DATA0 = (char *)$9f23
__constant const char VERA_INC_0 = 0
__constant const char VERA_INC_1 = $10
void __start()
void main()
unsigned int main::$0
bool main::$4
__constant char main::MSG[] = "hello world!"
__constant char main::MSG2[] = "h e l l o   w o r l d ! "
char main::i
char main::i#0
char main::i#1
char main::i#2
char main::i#3
char main::i#4
char main::i#5
char *main::vaddr
char *main::vaddr#0
char *main::vaddr#1
char *main::vaddr#2
char *main::vaddr#3
char *main::vaddr#4
char *main::vaddr#5
char *main::vaddr#6
void memcpy_to_vram(char vbank , void *vdest , void *src , unsigned int num)
char memcpy_to_vram::$0
char memcpy_to_vram::$1
char memcpy_to_vram::$2
bool memcpy_to_vram::$4
char *memcpy_to_vram::$5
char *memcpy_to_vram::end
char *memcpy_to_vram::end#0
char *memcpy_to_vram::end#1
char *memcpy_to_vram::end#2
unsigned int memcpy_to_vram::num
unsigned int memcpy_to_vram::num#0
unsigned int memcpy_to_vram::num#1
char *memcpy_to_vram::s
char *memcpy_to_vram::s#0
char *memcpy_to_vram::s#1
char *memcpy_to_vram::s#2
char *memcpy_to_vram::s#3
void *memcpy_to_vram::src
void *memcpy_to_vram::src#0
void *memcpy_to_vram::src#1
char memcpy_to_vram::vbank
char memcpy_to_vram::vbank#0
char memcpy_to_vram::vbank#1
void *memcpy_to_vram::vdest
void *memcpy_to_vram::vdest#0
void *memcpy_to_vram::vdest#1
void vpoke(char vbank , char *vaddr , char data)
char vpoke::$0
char vpoke::$1
char vpoke::$2
char vpoke::data
char vpoke::data#0
char vpoke::data#1
char vpoke::data#2
char *vpoke::vaddr
char *vpoke::vaddr#0
char *vpoke::vaddr#1
char *vpoke::vaddr#2
char vpoke::vbank
char vpoke::vbank#0
char vpoke::vbank#1
char vpoke::vbank#2

Adding number conversion cast (unumber) 0 in main::$4 = 0 != main::MSG[main::i#2]
Adding number conversion cast (unumber) 0 in vpoke::vbank#0 = 0
Adding number conversion cast (unumber) 0 in vpoke::vbank#1 = 0
Adding number conversion cast (unumber) $21 in vpoke::data#1 = $21
Adding number conversion cast (unumber) 0 in memcpy_to_vram::vbank#0 = 0
Adding number conversion cast (unumber) $100 in memcpy_to_vram::vdest#0 = (void *)DEFAULT_SCREEN+$100
Successful SSA optimization PassNAddNumberTypeConversions
Inlining cast memcpy_to_vram::s#0 = (char *)memcpy_to_vram::src#1
Inlining cast vpoke::vbank#0 = (unumber)0
Inlining cast vpoke::vbank#1 = (unumber)0
Inlining cast vpoke::data#1 = (unumber)$21
Inlining cast memcpy_to_vram::vbank#0 = (unumber)0
Successful SSA optimization Pass2InlineCast
Simplifying constant pointer cast (char *) 40736
Simplifying constant pointer cast (char *) 40737
Simplifying constant pointer cast (char *) 40738
Simplifying constant pointer cast (char *) 40739
Simplifying constant pointer cast (char *) 40741
Simplifying constant pointer cast (char *) 0
Simplifying constant integer cast 0
Simplifying constant integer cast 0
Simplifying constant integer cast 0
Simplifying constant integer cast $21
Simplifying constant integer cast 0
Simplifying constant integer cast $100
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (char) 0
Finalized unsigned number type (char) 0
Finalized unsigned number type (char) 0
Finalized unsigned number type (char) $21
Finalized unsigned number type (char) 0
Finalized unsigned number type (unsigned int) $100
Successful SSA optimization PassNFinalizeNumberTypeConversions
Alias memcpy_to_vram::s#2 = memcpy_to_vram::s#3 
Alias memcpy_to_vram::end#1 = memcpy_to_vram::end#2 
Alias main::vaddr#3 = main::vaddr#6 main::vaddr#4 
Alias main::i#2 = main::i#3 main::i#5 main::i#4 
Alias main::vaddr#1 = main::vaddr#5 
Alias memcpy_to_vram::num#0 = main::$0 
Successful SSA optimization Pass2AliasElimination
Identical Phi Values memcpy_to_vram::vdest#1 memcpy_to_vram::vdest#0
Identical Phi Values memcpy_to_vram::vbank#1 memcpy_to_vram::vbank#0
Identical Phi Values memcpy_to_vram::src#1 memcpy_to_vram::src#0
Identical Phi Values memcpy_to_vram::num#1 memcpy_to_vram::num#0
Identical Phi Values memcpy_to_vram::end#1 memcpy_to_vram::end#0
Successful SSA optimization Pass2IdenticalPhiElimination
Simple Condition memcpy_to_vram::$4 [23] if(memcpy_to_vram::s#2!=memcpy_to_vram::end#0) goto memcpy_to_vram::@2
Simple Condition main::$4 [31] if(0!=main::MSG[main::i#2]) goto main::@2
Successful SSA optimization Pass2ConditionalJumpSimplification
Constant right-side identified [43] memcpy_to_vram::num#0 = sizeof  main::MSG2
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant main::vaddr#0 = DEFAULT_SCREEN
Constant main::i#0 = 0
Constant vpoke::vbank#0 = 0
Constant vpoke::vbank#1 = 0
Constant vpoke::data#1 = $21
Constant memcpy_to_vram::num#0 = sizeof main::MSG2
Constant memcpy_to_vram::vbank#0 = 0
Constant memcpy_to_vram::vdest#0 = (void *)DEFAULT_SCREEN+$100
Constant memcpy_to_vram::src#0 = (void *)main::MSG2
Successful SSA optimization Pass2ConstantIdentification
Constant memcpy_to_vram::$5 = (char *)memcpy_to_vram::src#0
Constant memcpy_to_vram::s#0 = (char *)memcpy_to_vram::src#0
Successful SSA optimization Pass2ConstantIdentification
Simplifying expression containing zero vpoke::vbank#2 in [6] vpoke::$2 = VERA_INC_0 | vpoke::vbank#2
Simplifying expression containing zero VERA_INC_1 in [16] memcpy_to_vram::$2 = VERA_INC_1 | memcpy_to_vram::vbank#0
Successful SSA optimization PassNSimplifyExpressionWithZero
Eliminating unused constant VERA_INC_0
Eliminating unused constant memcpy_to_vram::vbank#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
Resolving string sizeof() sizeof main::MSG2
Successful SSA optimization PassNSizeOfSimplification
Alias vpoke::vbank#2 = vpoke::$2 
Successful SSA optimization Pass2AliasElimination
Constant right-side identified [10] memcpy_to_vram::$0 = byte0  memcpy_to_vram::vdest#0
Constant right-side identified [12] memcpy_to_vram::$1 = byte1  memcpy_to_vram::vdest#0
Constant right-side identified [16] memcpy_to_vram::end#0 = memcpy_to_vram::$5 + memcpy_to_vram::num#0
Successful SSA optimization Pass2ConstantRValueConsolidation
Constant memcpy_to_vram::$0 = byte0 memcpy_to_vram::vdest#0
Constant memcpy_to_vram::$1 = byte1 memcpy_to_vram::vdest#0
Constant memcpy_to_vram::$2 = VERA_INC_1
Constant memcpy_to_vram::end#0 = memcpy_to_vram::$5+memcpy_to_vram::num#0
Successful SSA optimization Pass2ConstantIdentification
Simplifying constant evaluating to zero byte0 memcpy_to_vram::vdest#0 in 
Successful SSA optimization PassNSimplifyConstantZero
Adding number conversion cast (unumber) $19 in 
Successful SSA optimization PassNAddNumberTypeConversions
Simplifying constant integer cast $19
Successful SSA optimization PassNCastSimplification
Finalized unsigned number type (char) $19
Successful SSA optimization PassNFinalizeNumberTypeConversions
Inlining constant with var siblings vpoke::vbank#0
Inlining constant with var siblings vpoke::vbank#1
Inlining constant with var siblings vpoke::data#1
Inlining constant with var siblings memcpy_to_vram::s#0
Inlining constant with var siblings main::vaddr#0
Inlining constant with var siblings main::i#0
Constant inlined memcpy_to_vram::s#0 = (char *)memcpy_to_vram::src#0
Constant inlined memcpy_to_vram::$2 = VERA_INC_1
Constant inlined main::i#0 = 0
Constant inlined memcpy_to_vram::$0 = 0
Constant inlined main::vaddr#0 = DEFAULT_SCREEN
Constant inlined memcpy_to_vram::$1 = byte1 memcpy_to_vram::vdest#0
Constant inlined vpoke::vbank#0 = 0
Constant inlined memcpy_to_vram::$5 = (char *)memcpy_to_vram::src#0
Constant inlined vpoke::vbank#1 = 0
Constant inlined vpoke::data#1 = $21
Successful SSA optimization Pass2ConstantInlining
Identical Phi Values vpoke::vbank#2 0
Successful SSA optimization Pass2IdenticalPhiElimination
Adding NOP phi() at start of main
Adding NOP phi() at start of main::@3
Adding NOP phi() at start of main::@6
CALL GRAPH
Calls in [main] to memcpy_to_vram:4 vpoke:11 vpoke:15 

Created 5 initial phi equivalence classes
Coalesced [9] vpoke::vaddr#3 = vpoke::vaddr#0
Coalesced [10] vpoke::data#3 = vpoke::data#0
Coalesced [14] vpoke::vaddr#4 = vpoke::vaddr#1
Coalesced [18] main::i#6 = main::i#1
Coalesced [19] main::vaddr#7 = main::vaddr#2
Coalesced [29] memcpy_to_vram::s#4 = memcpy_to_vram::s#1
Coalesced down to 5 phi equivalence classes
Culled Empty Block label main::@6
Adding NOP phi() at start of main
Adding NOP phi() at start of main::@3

FINAL CONTROL FLOW GRAPH

void main()
main: scope:[main]  from
  [0] phi()
  to:main::@1
main::@1: scope:[main]  from main main::@5
  [1] main::vaddr#3 = phi( main/DEFAULT_SCREEN, main::@5/main::vaddr#2 )
  [1] main::i#2 = phi( main/0, main::@5/main::i#1 )
  [2] if(0!=main::MSG[main::i#2]) goto main::@2
  to:main::@3
main::@3: scope:[main]  from main::@1
  [3] phi()
  [4] call memcpy_to_vram
  to:main::@return
main::@return: scope:[main]  from main::@3
  [5] return 
  to:@return
main::@2: scope:[main]  from main::@1
  [6] vpoke::vaddr#0 = main::vaddr#3
  [7] vpoke::data#0 = main::MSG[main::i#2]
  [8] call vpoke
  to:main::@4
main::@4: scope:[main]  from main::@2
  [9] main::vaddr#1 = ++ main::vaddr#3
  [10] vpoke::vaddr#1 = main::vaddr#1
  [11] call vpoke
  to:main::@5
main::@5: scope:[main]  from main::@4
  [12] main::vaddr#2 = ++ main::vaddr#1
  [13] main::i#1 = ++ main::i#2
  to:main::@1

void memcpy_to_vram(char vbank , void *vdest , void *src , unsigned int num)
memcpy_to_vram: scope:[memcpy_to_vram]  from main::@3
  [14] *VERA_CTRL = *VERA_CTRL & ~VERA_ADDRSEL
  [15] *VERA_ADDRX_L = 0
  [16] *VERA_ADDRX_M = byte1 memcpy_to_vram::vdest#0
  [17] *VERA_ADDRX_H = VERA_INC_1
  to:memcpy_to_vram::@1
memcpy_to_vram::@1: scope:[memcpy_to_vram]  from memcpy_to_vram memcpy_to_vram::@2
  [18] memcpy_to_vram::s#2 = phi( memcpy_to_vram/(char *)memcpy_to_vram::src#0, memcpy_to_vram::@2/memcpy_to_vram::s#1 )
  [19] if(memcpy_to_vram::s#2!=memcpy_to_vram::end#0) goto memcpy_to_vram::@2
  to:memcpy_to_vram::@return
memcpy_to_vram::@return: scope:[memcpy_to_vram]  from memcpy_to_vram::@1
  [20] return 
  to:@return
memcpy_to_vram::@2: scope:[memcpy_to_vram]  from memcpy_to_vram::@1
  [21] *VERA_DATA0 = *memcpy_to_vram::s#2
  [22] memcpy_to_vram::s#1 = ++ memcpy_to_vram::s#2
  to:memcpy_to_vram::@1

void vpoke(char vbank , char *vaddr , char data)
vpoke: scope:[vpoke]  from main::@2 main::@4
  [23] vpoke::data#2 = phi( main::@2/vpoke::data#0, main::@4/$21 )
  [23] vpoke::vaddr#2 = phi( main::@2/vpoke::vaddr#0, main::@4/vpoke::vaddr#1 )
  [24] *VERA_CTRL = *VERA_CTRL & ~VERA_ADDRSEL
  [25] vpoke::$0 = byte0  vpoke::vaddr#2
  [26] *VERA_ADDRX_L = vpoke::$0
  [27] vpoke::$1 = byte1  vpoke::vaddr#2
  [28] *VERA_ADDRX_M = vpoke::$1
  [29] *VERA_ADDRX_H = 0
  [30] *VERA_DATA0 = vpoke::data#2
  to:vpoke::@return
vpoke::@return: scope:[vpoke]  from vpoke
  [31] return 
  to:@return


VARIABLE REGISTER WEIGHTS
void main()
char main::i
char main::i#1 // 22.0
char main::i#2 // 4.888888888888889
char *main::vaddr
char *main::vaddr#1 // 11.0
char *main::vaddr#2 // 11.0
char *main::vaddr#3 // 6.6000000000000005
void memcpy_to_vram(char vbank , void *vdest , void *src , unsigned int num)
char *memcpy_to_vram::end
unsigned int memcpy_to_vram::num
char *memcpy_to_vram::s
char *memcpy_to_vram::s#1 // 202.0
char *memcpy_to_vram::s#2 // 134.66666666666666
void *memcpy_to_vram::src
char memcpy_to_vram::vbank
void *memcpy_to_vram::vdest
void vpoke(char vbank , char *vaddr , char data)
char vpoke::$0 // 202.0
char vpoke::$1 // 202.0
char vpoke::data
char vpoke::data#0 // 22.0
char vpoke::data#2 // 16.0
char *vpoke::vaddr
char *vpoke::vaddr#0 // 11.0
char *vpoke::vaddr#1 // 22.0
char *vpoke::vaddr#2 // 56.0
char vpoke::vbank

Initial phi equivalence classes
[ main::i#2 main::i#1 ]
[ main::vaddr#3 main::vaddr#2 ]
[ memcpy_to_vram::s#2 memcpy_to_vram::s#1 ]
[ vpoke::vaddr#2 vpoke::vaddr#0 vpoke::vaddr#1 ]
[ vpoke::data#2 vpoke::data#0 ]
Added variable main::vaddr#1 to live range equivalence class [ main::vaddr#1 ]
Added variable vpoke::$0 to live range equivalence class [ vpoke::$0 ]
Added variable vpoke::$1 to live range equivalence class [ vpoke::$1 ]
Complete equivalence classes
[ main::i#2 main::i#1 ]
[ main::vaddr#3 main::vaddr#2 ]
[ memcpy_to_vram::s#2 memcpy_to_vram::s#1 ]
[ vpoke::vaddr#2 vpoke::vaddr#0 vpoke::vaddr#1 ]
[ vpoke::data#2 vpoke::data#0 ]
[ main::vaddr#1 ]
[ vpoke::$0 ]
[ vpoke::$1 ]
Allocated zp[1]:2 [ main::i#2 main::i#1 ]
Allocated zp[2]:3 [ main::vaddr#3 main::vaddr#2 ]
Allocated zp[2]:5 [ memcpy_to_vram::s#2 memcpy_to_vram::s#1 ]
Allocated zp[2]:7 [ vpoke::vaddr#2 vpoke::vaddr#0 vpoke::vaddr#1 ]
Allocated zp[1]:9 [ vpoke::data#2 vpoke::data#0 ]
Allocated zp[2]:10 [ main::vaddr#1 ]
Allocated zp[1]:12 [ vpoke::$0 ]
Allocated zp[1]:13 [ vpoke::$1 ]
REGISTER UPLIFT POTENTIAL REGISTERS
Statement [2] if(0!=main::MSG[main::i#2]) goto main::@2 [ main::i#2 main::vaddr#3 ] (  [ main::i#2 main::vaddr#3 ] { }  ) always clobbers reg byte a 
Removing always clobbered register reg byte a as potential for zp[1]:2 [ main::i#2 main::i#1 ]
Statement [6] vpoke::vaddr#0 = main::vaddr#3 [ main::i#2 main::vaddr#3 vpoke::vaddr#0 ] (  [ main::i#2 main::vaddr#3 vpoke::vaddr#0 ] { { vpoke::vaddr#0 = vpoke::vaddr#2 main::vaddr#3 } { vpoke::data#0 = vpoke::data#2 } }  ) always clobbers reg byte a 
Statement [9] main::vaddr#1 = ++ main::vaddr#3 [ main::i#2 main::vaddr#1 ] (  [ main::i#2 main::vaddr#1 ] { { vpoke::vaddr#1 = vpoke::vaddr#2 main::vaddr#1 } }  ) always clobbers reg byte a 
Statement [10] vpoke::vaddr#1 = main::vaddr#1 [ main::i#2 main::vaddr#1 vpoke::vaddr#1 ] (  [ main::i#2 main::vaddr#1 vpoke::vaddr#1 ] { { vpoke::vaddr#1 = vpoke::vaddr#2 main::vaddr#1 } }  ) always clobbers reg byte a 
Statement [12] main::vaddr#2 = ++ main::vaddr#1 [ main::i#2 main::vaddr#2 ] (  [ main::i#2 main::vaddr#2 ] { }  ) always clobbers reg byte a 
Statement [14] *VERA_CTRL = *VERA_CTRL & ~VERA_ADDRSEL [ ] ( memcpy_to_vram:4 [ ] { }  ) always clobbers reg byte a 
Statement [15] *VERA_ADDRX_L = 0 [ ] ( memcpy_to_vram:4 [ ] { }  ) always clobbers reg byte a 
Statement [16] *VERA_ADDRX_M = byte1 memcpy_to_vram::vdest#0 [ ] ( memcpy_to_vram:4 [ ] { }  ) always clobbers reg byte a 
Statement [17] *VERA_ADDRX_H = VERA_INC_1 [ ] ( memcpy_to_vram:4 [ ] { }  ) always clobbers reg byte a 
Statement [19] if(memcpy_to_vram::s#2!=memcpy_to_vram::end#0) goto memcpy_to_vram::@2 [ memcpy_to_vram::s#2 ] ( memcpy_to_vram:4 [ memcpy_to_vram::s#2 ] { }  ) always clobbers reg byte a 
Statement [21] *VERA_DATA0 = *memcpy_to_vram::s#2 [ memcpy_to_vram::s#2 ] ( memcpy_to_vram:4 [ memcpy_to_vram::s#2 ] { }  ) always clobbers reg byte a reg byte y 
Statement [24] *VERA_CTRL = *VERA_CTRL & ~VERA_ADDRSEL [ vpoke::vaddr#2 vpoke::data#2 ] ( vpoke:8 [ main::i#2 main::vaddr#3 vpoke::vaddr#2 vpoke::data#2 ] { { vpoke::vaddr#0 = vpoke::vaddr#2 main::vaddr#3 } { vpoke::data#0 = vpoke::data#2 } }  vpoke:11 [ main::i#2 main::vaddr#1 vpoke::vaddr#2 vpoke::data#2 ] { { vpoke::vaddr#1 = vpoke::vaddr#2 main::vaddr#1 } }  ) always clobbers reg byte a 
Removing always clobbered register reg byte a as potential for zp[1]:9 [ vpoke::data#2 vpoke::data#0 ]
Statement [29] *VERA_ADDRX_H = 0 [ vpoke::data#2 ] ( vpoke:8 [ main::i#2 main::vaddr#3 vpoke::data#2 ] { { vpoke::vaddr#0 = vpoke::vaddr#2 main::vaddr#3 } { vpoke::data#0 = vpoke::data#2 } }  vpoke:11 [ main::i#2 main::vaddr#1 vpoke::data#2 ] { { vpoke::vaddr#1 = vpoke::vaddr#2 main::vaddr#1 } }  ) always clobbers reg byte a 
Statement [2] if(0!=main::MSG[main::i#2]) goto main::@2 [ main::i#2 main::vaddr#3 ] (  [ main::i#2 main::vaddr#3 ] { }  ) always clobbers reg byte a 
Statement [6] vpoke::vaddr#0 = main::vaddr#3 [ main::i#2 main::vaddr#3 vpoke::vaddr#0 ] (  [ main::i#2 main::vaddr#3 vpoke::vaddr#0 ] { { vpoke::vaddr#0 = vpoke::vaddr#2 main::vaddr#3 } { vpoke::data#0 = vpoke::data#2 } }  ) always clobbers reg byte a 
Statement [9] main::vaddr#1 = ++ main::vaddr#3 [ main::i#2 main::vaddr#1 ] (  [ main::i#2 main::vaddr#1 ] { { vpoke::vaddr#1 = vpoke::vaddr#2 main::vaddr#1 } }  ) always clobbers reg byte a 
Statement [10] vpoke::vaddr#1 = main::vaddr#1 [ main::i#2 main::vaddr#1 vpoke::vaddr#1 ] (  [ main::i#2 main::vaddr#1 vpoke::vaddr#1 ] { { vpoke::vaddr#1 = vpoke::vaddr#2 main::vaddr#1 } }  ) always clobbers reg byte a 
Statement [12] main::vaddr#2 = ++ main::vaddr#1 [ main::i#2 main::vaddr#2 ] (  [ main::i#2 main::vaddr#2 ] { }  ) always clobbers reg byte a 
Statement [14] *VERA_CTRL = *VERA_CTRL & ~VERA_ADDRSEL [ ] ( memcpy_to_vram:4 [ ] { }  ) always clobbers reg byte a 
Statement [15] *VERA_ADDRX_L = 0 [ ] ( memcpy_to_vram:4 [ ] { }  ) always clobbers reg byte a 
Statement [16] *VERA_ADDRX_M = byte1 memcpy_to_vram::vdest#0 [ ] ( memcpy_to_vram:4 [ ] { }  ) always clobbers reg byte a 
Statement [17] *VERA_ADDRX_H = VERA_INC_1 [ ] ( memcpy_to_vram:4 [ ] { }  ) always clobbers reg byte a 
Statement [19] if(memcpy_to_vram::s#2!=memcpy_to_vram::end#0) goto memcpy_to_vram::@2 [ memcpy_to_vram::s#2 ] ( memcpy_to_vram:4 [ memcpy_to_vram::s#2 ] { }  ) always clobbers reg byte a 
Statement [21] *VERA_DATA0 = *memcpy_to_vram::s#2 [ memcpy_to_vram::s#2 ] ( memcpy_to_vram:4 [ memcpy_to_vram::s#2 ] { }  ) always clobbers reg byte a reg byte y 
Statement [24] *VERA_CTRL = *VERA_CTRL & ~VERA_ADDRSEL [ vpoke::vaddr#2 vpoke::data#2 ] ( vpoke:8 [ main::i#2 main::vaddr#3 vpoke::vaddr#2 vpoke::data#2 ] { { vpoke::vaddr#0 = vpoke::vaddr#2 main::vaddr#3 } { vpoke::data#0 = vpoke::data#2 } }  vpoke:11 [ main::i#2 main::vaddr#1 vpoke::vaddr#2 vpoke::data#2 ] { { vpoke::vaddr#1 = vpoke::vaddr#2 main::vaddr#1 } }  ) always clobbers reg byte a 
Statement [29] *VERA_ADDRX_H = 0 [ vpoke::data#2 ] ( vpoke:8 [ main::i#2 main::vaddr#3 vpoke::data#2 ] { { vpoke::vaddr#0 = vpoke::vaddr#2 main::vaddr#3 } { vpoke::data#0 = vpoke::data#2 } }  vpoke:11 [ main::i#2 main::vaddr#1 vpoke::data#2 ] { { vpoke::vaddr#1 = vpoke::vaddr#2 main::vaddr#1 } }  ) always clobbers reg byte a 
Potential registers zp[1]:2 [ main::i#2 main::i#1 ] : zp[1]:2 , reg byte x , reg byte y , 
Potential registers zp[2]:3 [ main::vaddr#3 main::vaddr#2 ] : zp[2]:3 , 
Potential registers zp[2]:5 [ memcpy_to_vram::s#2 memcpy_to_vram::s#1 ] : zp[2]:5 , 
Potential registers zp[2]:7 [ vpoke::vaddr#2 vpoke::vaddr#0 vpoke::vaddr#1 ] : zp[2]:7 , 
Potential registers zp[1]:9 [ vpoke::data#2 vpoke::data#0 ] : zp[1]:9 , reg byte x , reg byte y , 
Potential registers zp[2]:10 [ main::vaddr#1 ] : zp[2]:10 , 
Potential registers zp[1]:12 [ vpoke::$0 ] : zp[1]:12 , reg byte a , reg byte x , reg byte y , 
Potential registers zp[1]:13 [ vpoke::$1 ] : zp[1]:13 , reg byte a , reg byte x , reg byte y , 

REGISTER UPLIFT SCOPES
Uplift Scope [vpoke] 202: zp[1]:12 [ vpoke::$0 ] 202: zp[1]:13 [ vpoke::$1 ] 89: zp[2]:7 [ vpoke::vaddr#2 vpoke::vaddr#0 vpoke::vaddr#1 ] 38: zp[1]:9 [ vpoke::data#2 vpoke::data#0 ] 
Uplift Scope [memcpy_to_vram] 336.67: zp[2]:5 [ memcpy_to_vram::s#2 memcpy_to_vram::s#1 ] 
Uplift Scope [main] 26.89: zp[1]:2 [ main::i#2 main::i#1 ] 17.6: zp[2]:3 [ main::vaddr#3 main::vaddr#2 ] 11: zp[2]:10 [ main::vaddr#1 ] 
Uplift Scope [VERA_SPRITE] 
Uplift Scope [MOS6522_VIA] 
Uplift Scope [] 

Uplifting [vpoke] best 1750 combination reg byte a [ vpoke::$0 ] reg byte a [ vpoke::$1 ] zp[2]:7 [ vpoke::vaddr#2 vpoke::vaddr#0 vpoke::vaddr#1 ] reg byte x [ vpoke::data#2 vpoke::data#0 ] 
Uplifting [memcpy_to_vram] best 1750 combination zp[2]:5 [ memcpy_to_vram::s#2 memcpy_to_vram::s#1 ] 
Uplifting [main] best 1630 combination reg byte y [ main::i#2 main::i#1 ] zp[2]:3 [ main::vaddr#3 main::vaddr#2 ] zp[2]:10 [ main::vaddr#1 ] 
Uplifting [VERA_SPRITE] best 1630 combination 
Uplifting [MOS6522_VIA] best 1630 combination 
Uplifting [] best 1630 combination 
Coalescing zero page register [ zp[2]:3 [ main::vaddr#3 main::vaddr#2 ] ] with [ zp[2]:10 [ main::vaddr#1 ] ] - score: 2
Coalescing zero page register [ zp[2]:3 [ main::vaddr#3 main::vaddr#2 main::vaddr#1 ] ] with [ zp[2]:7 [ vpoke::vaddr#2 vpoke::vaddr#0 vpoke::vaddr#1 ] ] - score: 1
Allocated (was zp[2]:3) zp[2]:2 [ main::vaddr#3 main::vaddr#2 main::vaddr#1 vpoke::vaddr#2 vpoke::vaddr#0 vpoke::vaddr#1 ]
Allocated (was zp[2]:5) zp[2]:4 [ memcpy_to_vram::s#2 memcpy_to_vram::s#1 ]

ASSEMBLER BEFORE OPTIMIZATION
  // File Comments
// Example program for the Commander X16
// Displays text on the screen by transfering data to VERA
  // Upstart
.cpu _65c02
  // Commodore 64 PRG executable file
.file [name="cx16-text.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
  // Global Constants & labels
  .const VERA_INC_1 = $10
  .const VERA_ADDRSEL = 1
  .const SIZEOF_CHAR = 1
  /// $9F20 VRAM Address (7:0)
  .label VERA_ADDRX_L = $9f20
  /// $9F21 VRAM Address (15:8)
  .label VERA_ADDRX_M = $9f21
  /// $9F22 VRAM Address (7:0)
  /// Bit 4-7: Address Increment  The following is the amount incremented per value value:increment
  ///                             0:0, 1:1, 2:2, 3:4, 4:8, 5:16, 6:32, 7:64, 8:128, 9:256, 10:512, 11:40, 12:80, 13:160, 14:320, 15:640
  /// Bit 3: DECR Setting the DECR bit, will decrement instead of increment by the value set by the 'Address Increment' field.
  /// Bit 0: VRAM Address (16)
  .label VERA_ADDRX_H = $9f22
  /// $9F23	DATA0	VRAM Data port 0
  .label VERA_DATA0 = $9f23
  /// $9F25	CTRL Control
  /// Bit 7: Reset
  /// Bit 1: DCSEL
  /// Bit 2: ADDRSEL
  .label VERA_CTRL = $9f25
  /// VRAM Address of the default screen
  .label DEFAULT_SCREEN = 0
.segment Code
  // main
main: {
    .label vaddr = 2
    // [1] phi from main to main::@1 [phi:main->main::@1]
  __b1_from_main:
    // [1] phi main::vaddr#3 = DEFAULT_SCREEN [phi:main->main::@1#0] -- pbuz1=pbuc1 
    lda #<DEFAULT_SCREEN
    sta.z vaddr
    lda #>DEFAULT_SCREEN
    sta.z vaddr+1
    // [1] phi main::i#2 = 0 [phi:main->main::@1#1] -- vbuyy=vbuc1 
    ldy #0
    jmp __b1
    // main::@1
  __b1:
    // [2] if(0!=main::MSG[main::i#2]) goto main::@2 -- 0_neq_pbuc1_derefidx_vbuyy_then_la1 
    lda MSG,y
    cmp #0
    bne __b2
    // [3] phi from main::@1 to main::@3 [phi:main::@1->main::@3]
  __b3_from___b1:
    jmp __b3
    // main::@3
  __b3:
    // [4] call memcpy_to_vram
    // Space is 0x20, red background black foreground
    jsr memcpy_to_vram
    jmp __breturn
    // main::@return
  __breturn:
    // [5] return 
    rts
    // main::@2
  __b2:
    // [6] vpoke::vaddr#0 = main::vaddr#3
    // [7] vpoke::data#0 = main::MSG[main::i#2] -- vbuxx=pbuc1_derefidx_vbuyy 
    ldx MSG,y
    // [8] call vpoke
    // [23] phi from main::@2 to vpoke [phi:main::@2->vpoke]
  vpoke_from___b2:
    // [23] phi vpoke::data#2 = vpoke::data#0 [phi:main::@2->vpoke#0] -- register_copy 
    // [23] phi vpoke::vaddr#2 = vpoke::vaddr#0 [phi:main::@2->vpoke#1] -- register_copy 
    jsr vpoke
    jmp __b4
    // main::@4
  __b4:
    // [9] main::vaddr#1 = ++ main::vaddr#3 -- pbuz1=_inc_pbuz1 
    inc.z vaddr
    bne !+
    inc.z vaddr+1
  !:
    // [10] vpoke::vaddr#1 = main::vaddr#1
    // [11] call vpoke
  // Message
    // [23] phi from main::@4 to vpoke [phi:main::@4->vpoke]
  vpoke_from___b4:
    // [23] phi vpoke::data#2 = $21 [phi:main::@4->vpoke#0] -- vbuxx=vbuc1 
    ldx #$21
    // [23] phi vpoke::vaddr#2 = vpoke::vaddr#1 [phi:main::@4->vpoke#1] -- register_copy 
    jsr vpoke
    jmp __b5
    // main::@5
  __b5:
    // [12] main::vaddr#2 = ++ main::vaddr#1 -- pbuz1=_inc_pbuz1 
    inc.z vaddr
    bne !+
    inc.z vaddr+1
  !:
    // [13] main::i#1 = ++ main::i#2 -- vbuyy=_inc_vbuyy 
    iny
    // [1] phi from main::@5 to main::@1 [phi:main::@5->main::@1]
  __b1_from___b5:
    // [1] phi main::vaddr#3 = main::vaddr#2 [phi:main::@5->main::@1#0] -- register_copy 
    // [1] phi main::i#2 = main::i#1 [phi:main::@5->main::@1#1] -- register_copy 
    jmp __b1
  .segment Data
    // Copy message to screen one char at a time
    MSG: .text "hello world!"
    .byte 0
    // Copy message (and colors) to screen using memcpy_to_vram
    MSG2: .text "h e l l o   w o r l d ! "
    .byte 0
}
.segment Code
  // memcpy_to_vram
// Copy block of memory (from RAM to VRAM)
// Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination in VRAM.
// - vbank: Which 64K VRAM bank to put data into (0/1)
// - vdest: The destination address in VRAM
// - src: The source address in RAM
// - num: The number of bytes to copy
// void memcpy_to_vram(char vbank, void *vdest, void *src, unsigned int num)
memcpy_to_vram: {
    .const num = $19*SIZEOF_CHAR
    .label vdest = DEFAULT_SCREEN+$100
    .label src = main.MSG2
    // Transfer the data
    .label end = src+num
    .label s = 4
    // [14] *VERA_CTRL = *VERA_CTRL & ~VERA_ADDRSEL -- _deref_pbuc1=_deref_pbuc1_band_vbuc2 
    // Select DATA0
    lda #VERA_ADDRSEL^$ff
    and VERA_CTRL
    sta VERA_CTRL
    // [15] *VERA_ADDRX_L = 0 -- _deref_pbuc1=vbuc2 
    // Set address
    lda #0
    sta VERA_ADDRX_L
    // [16] *VERA_ADDRX_M = byte1 memcpy_to_vram::vdest#0 -- _deref_pbuc1=vbuc2 
    lda #>vdest
    sta VERA_ADDRX_M
    // [17] *VERA_ADDRX_H = VERA_INC_1 -- _deref_pbuc1=vbuc2 
    lda #VERA_INC_1
    sta VERA_ADDRX_H
    // [18] phi from memcpy_to_vram to memcpy_to_vram::@1 [phi:memcpy_to_vram->memcpy_to_vram::@1]
  __b1_from_memcpy_to_vram:
    // [18] phi memcpy_to_vram::s#2 = (char *)memcpy_to_vram::src#0 [phi:memcpy_to_vram->memcpy_to_vram::@1#0] -- pbuz1=pbuc1 
    lda #<src
    sta.z s
    lda #>src
    sta.z s+1
    jmp __b1
    // memcpy_to_vram::@1
  __b1:
    // [19] if(memcpy_to_vram::s#2!=memcpy_to_vram::end#0) goto memcpy_to_vram::@2 -- pbuz1_neq_pbuc1_then_la1 
    lda.z s+1
    cmp #>end
    bne __b2
    lda.z s
    cmp #<end
    bne __b2
    jmp __breturn
    // memcpy_to_vram::@return
  __breturn:
    // [20] return 
    rts
    // memcpy_to_vram::@2
  __b2:
    // [21] *VERA_DATA0 = *memcpy_to_vram::s#2 -- _deref_pbuc1=_deref_pbuz1 
    ldy #0
    lda (s),y
    sta VERA_DATA0
    // [22] memcpy_to_vram::s#1 = ++ memcpy_to_vram::s#2 -- pbuz1=_inc_pbuz1 
    inc.z s
    bne !+
    inc.z s+1
  !:
    // [18] phi from memcpy_to_vram::@2 to memcpy_to_vram::@1 [phi:memcpy_to_vram::@2->memcpy_to_vram::@1]
  __b1_from___b2:
    // [18] phi memcpy_to_vram::s#2 = memcpy_to_vram::s#1 [phi:memcpy_to_vram::@2->memcpy_to_vram::@1#0] -- register_copy 
    jmp __b1
}
  // vpoke
// Put a single byte into VRAM.
// Uses VERA DATA0
// - bank: Which 64K VRAM bank to put data into (0/1)
// - addr: The address in VRAM
// - data: The data to put into VRAM
// void vpoke(char vbank, __zp(2) char *vaddr, __register(X) char data)
vpoke: {
    .label vaddr = 2
    // [24] *VERA_CTRL = *VERA_CTRL & ~VERA_ADDRSEL -- _deref_pbuc1=_deref_pbuc1_band_vbuc2 
    // Select DATA0
    lda #VERA_ADDRSEL^$ff
    and VERA_CTRL
    sta VERA_CTRL
    // [25] vpoke::$0 = byte0  vpoke::vaddr#2 -- vbuaa=_byte0_pbuz1 
    lda.z vaddr
    // [26] *VERA_ADDRX_L = vpoke::$0 -- _deref_pbuc1=vbuaa 
    // Set address
    sta VERA_ADDRX_L
    // [27] vpoke::$1 = byte1  vpoke::vaddr#2 -- vbuaa=_byte1_pbuz1 
    lda.z vaddr+1
    // [28] *VERA_ADDRX_M = vpoke::$1 -- _deref_pbuc1=vbuaa 
    sta VERA_ADDRX_M
    // [29] *VERA_ADDRX_H = 0 -- _deref_pbuc1=vbuc2 
    lda #0
    sta VERA_ADDRX_H
    // [30] *VERA_DATA0 = vpoke::data#2 -- _deref_pbuc1=vbuxx 
    // Set data
    stx VERA_DATA0
    jmp __breturn
    // vpoke::@return
  __breturn:
    // [31] return 
    rts
}
  // File Data

ASSEMBLER OPTIMIZATIONS
Removing instruction jmp __b1
Removing instruction jmp __b3
Removing instruction jmp __breturn
Removing instruction jmp __b4
Removing instruction jmp __b5
Removing instruction jmp __b1
Removing instruction jmp __breturn
Removing instruction jmp __breturn
Succesful ASM optimization Pass5NextJumpElimination
Removing instruction __b3_from___b1:
Succesful ASM optimization Pass5RedundantLabelElimination
Removing instruction __b1_from_main:
Removing instruction __b3:
Removing instruction __breturn:
Removing instruction vpoke_from___b2:
Removing instruction __b4:
Removing instruction vpoke_from___b4:
Removing instruction __b5:
Removing instruction __b1_from___b5:
Removing instruction __b1_from_memcpy_to_vram:
Removing instruction __breturn:
Removing instruction __b1_from___b2:
Removing instruction __breturn:
Succesful ASM optimization Pass5UnusedLabelElimination

FINAL SYMBOL TABLE
__constant char * const DEFAULT_SCREEN = (char *) 0
__constant char SIZEOF_CHAR = 1
__constant const char VERA_ADDRSEL = 1
__constant char * const VERA_ADDRX_H = (char *) 40738
__constant char * const VERA_ADDRX_L = (char *) 40736
__constant char * const VERA_ADDRX_M = (char *) 40737
__constant char * const VERA_CTRL = (char *) 40741
__constant char * const VERA_DATA0 = (char *) 40739
__constant const char VERA_INC_1 = $10
void main()
__constant char main::MSG[] = "hello world!"
__constant char main::MSG2[] = "h e l l o   w o r l d ! "
char main::i
char main::i#1 // reg byte y 22.0
char main::i#2 // reg byte y 4.888888888888889
char *main::vaddr
char *main::vaddr#1 // vaddr zp[2]:2 11.0
char *main::vaddr#2 // vaddr zp[2]:2 11.0
char *main::vaddr#3 // vaddr zp[2]:2 6.6000000000000005
void memcpy_to_vram(char vbank , void *vdest , void *src , unsigned int num)
char *memcpy_to_vram::end
__constant char *memcpy_to_vram::end#0 = (char *)memcpy_to_vram::src#0+memcpy_to_vram::num#0 // end
unsigned int memcpy_to_vram::num
__constant unsigned int memcpy_to_vram::num#0 = $19*SIZEOF_CHAR // num
char *memcpy_to_vram::s
char *memcpy_to_vram::s#1 // s zp[2]:4 202.0
char *memcpy_to_vram::s#2 // s zp[2]:4 134.66666666666666
void *memcpy_to_vram::src
__constant void *memcpy_to_vram::src#0 = (void *)main::MSG2 // src
char memcpy_to_vram::vbank
void *memcpy_to_vram::vdest
__constant void *memcpy_to_vram::vdest#0 = (void *)DEFAULT_SCREEN+$100 // vdest
void vpoke(char vbank , char *vaddr , char data)
char vpoke::$0 // reg byte a 202.0
char vpoke::$1 // reg byte a 202.0
char vpoke::data
char vpoke::data#0 // reg byte x 22.0
char vpoke::data#2 // reg byte x 16.0
char *vpoke::vaddr
char *vpoke::vaddr#0 // vaddr zp[2]:2 11.0
char *vpoke::vaddr#1 // vaddr zp[2]:2 22.0
char *vpoke::vaddr#2 // vaddr zp[2]:2 56.0
char vpoke::vbank

reg byte y [ main::i#2 main::i#1 ]
zp[2]:2 [ main::vaddr#3 main::vaddr#2 main::vaddr#1 vpoke::vaddr#2 vpoke::vaddr#0 vpoke::vaddr#1 ]
zp[2]:4 [ memcpy_to_vram::s#2 memcpy_to_vram::s#1 ]
reg byte x [ vpoke::data#2 vpoke::data#0 ]
reg byte a [ vpoke::$0 ]
reg byte a [ vpoke::$1 ]


FINAL ASSEMBLER
Score: 1175

  // File Comments
// Example program for the Commander X16
// Displays text on the screen by transfering data to VERA
  // Upstart
.cpu _65c02
  // Commodore 64 PRG executable file
.file [name="cx16-text.prg", type="prg", segments="Program"]
.segmentdef Program [segments="Basic, Code, Data"]
.segmentdef Basic [start=$0801]
.segmentdef Code [start=$80d]
.segmentdef Data [startAfter="Code"]
.segment Basic
:BasicUpstart(main)
  // Global Constants & labels
  .const VERA_INC_1 = $10
  .const VERA_ADDRSEL = 1
  .const SIZEOF_CHAR = 1
  /// $9F20 VRAM Address (7:0)
  .label VERA_ADDRX_L = $9f20
  /// $9F21 VRAM Address (15:8)
  .label VERA_ADDRX_M = $9f21
  /// $9F22 VRAM Address (7:0)
  /// Bit 4-7: Address Increment  The following is the amount incremented per value value:increment
  ///                             0:0, 1:1, 2:2, 3:4, 4:8, 5:16, 6:32, 7:64, 8:128, 9:256, 10:512, 11:40, 12:80, 13:160, 14:320, 15:640
  /// Bit 3: DECR Setting the DECR bit, will decrement instead of increment by the value set by the 'Address Increment' field.
  /// Bit 0: VRAM Address (16)
  .label VERA_ADDRX_H = $9f22
  /// $9F23	DATA0	VRAM Data port 0
  .label VERA_DATA0 = $9f23
  /// $9F25	CTRL Control
  /// Bit 7: Reset
  /// Bit 1: DCSEL
  /// Bit 2: ADDRSEL
  .label VERA_CTRL = $9f25
  /// VRAM Address of the default screen
  .label DEFAULT_SCREEN = 0
.segment Code
  // main
main: {
    .label vaddr = 2
    // [1] phi from main to main::@1 [phi:main->main::@1]
    // [1] phi main::vaddr#3 = DEFAULT_SCREEN [phi:main->main::@1#0] -- pbuz1=pbuc1 
    lda #<DEFAULT_SCREEN
    sta.z vaddr
    lda #>DEFAULT_SCREEN
    sta.z vaddr+1
    // [1] phi main::i#2 = 0 [phi:main->main::@1#1] -- vbuyy=vbuc1 
    ldy #0
    // main::@1
  __b1:
    // for(char i=0;MSG[i];i++)
    // [2] if(0!=main::MSG[main::i#2]) goto main::@2 -- 0_neq_pbuc1_derefidx_vbuyy_then_la1 
    lda MSG,y
    cmp #0
    bne __b2
    // [3] phi from main::@1 to main::@3 [phi:main::@1->main::@3]
    // main::@3
    // memcpy_to_vram(0, DEFAULT_SCREEN+0x100, MSG2, sizeof(MSG2))
    // [4] call memcpy_to_vram
    // Space is 0x20, red background black foreground
    jsr memcpy_to_vram
    // main::@return
    // }
    // [5] return 
    rts
    // main::@2
  __b2:
    // vpoke(0, vaddr++, MSG[i])
    // [6] vpoke::vaddr#0 = main::vaddr#3
    // [7] vpoke::data#0 = main::MSG[main::i#2] -- vbuxx=pbuc1_derefidx_vbuyy 
    ldx MSG,y
    // [8] call vpoke
    // [23] phi from main::@2 to vpoke [phi:main::@2->vpoke]
    // [23] phi vpoke::data#2 = vpoke::data#0 [phi:main::@2->vpoke#0] -- register_copy 
    // [23] phi vpoke::vaddr#2 = vpoke::vaddr#0 [phi:main::@2->vpoke#1] -- register_copy 
    jsr vpoke
    // main::@4
    // vpoke(0, vaddr++, MSG[i]);
    // [9] main::vaddr#1 = ++ main::vaddr#3 -- pbuz1=_inc_pbuz1 
    inc.z vaddr
    bne !+
    inc.z vaddr+1
  !:
    // vpoke(0, vaddr++, 0x21)
    // [10] vpoke::vaddr#1 = main::vaddr#1
    // [11] call vpoke
  // Message
    // [23] phi from main::@4 to vpoke [phi:main::@4->vpoke]
    // [23] phi vpoke::data#2 = $21 [phi:main::@4->vpoke#0] -- vbuxx=vbuc1 
    ldx #$21
    // [23] phi vpoke::vaddr#2 = vpoke::vaddr#1 [phi:main::@4->vpoke#1] -- register_copy 
    jsr vpoke
    // main::@5
    // vpoke(0, vaddr++, 0x21);
    // [12] main::vaddr#2 = ++ main::vaddr#1 -- pbuz1=_inc_pbuz1 
    inc.z vaddr
    bne !+
    inc.z vaddr+1
  !:
    // for(char i=0;MSG[i];i++)
    // [13] main::i#1 = ++ main::i#2 -- vbuyy=_inc_vbuyy 
    iny
    // [1] phi from main::@5 to main::@1 [phi:main::@5->main::@1]
    // [1] phi main::vaddr#3 = main::vaddr#2 [phi:main::@5->main::@1#0] -- register_copy 
    // [1] phi main::i#2 = main::i#1 [phi:main::@5->main::@1#1] -- register_copy 
    jmp __b1
  .segment Data
    // Copy message to screen one char at a time
    MSG: .text "hello world!"
    .byte 0
    // Copy message (and colors) to screen using memcpy_to_vram
    MSG2: .text "h e l l o   w o r l d ! "
    .byte 0
}
.segment Code
  // memcpy_to_vram
// Copy block of memory (from RAM to VRAM)
// Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination in VRAM.
// - vbank: Which 64K VRAM bank to put data into (0/1)
// - vdest: The destination address in VRAM
// - src: The source address in RAM
// - num: The number of bytes to copy
// void memcpy_to_vram(char vbank, void *vdest, void *src, unsigned int num)
memcpy_to_vram: {
    .const num = $19*SIZEOF_CHAR
    .label vdest = DEFAULT_SCREEN+$100
    .label src = main.MSG2
    // Transfer the data
    .label end = src+num
    .label s = 4
    // *VERA_CTRL &= ~VERA_ADDRSEL
    // [14] *VERA_CTRL = *VERA_CTRL & ~VERA_ADDRSEL -- _deref_pbuc1=_deref_pbuc1_band_vbuc2 
    // Select DATA0
    lda #VERA_ADDRSEL^$ff
    and VERA_CTRL
    sta VERA_CTRL
    // *VERA_ADDRX_L = BYTE0(vdest)
    // [15] *VERA_ADDRX_L = 0 -- _deref_pbuc1=vbuc2 
    // Set address
    lda #0
    sta VERA_ADDRX_L
    // *VERA_ADDRX_M = BYTE1(vdest)
    // [16] *VERA_ADDRX_M = byte1 memcpy_to_vram::vdest#0 -- _deref_pbuc1=vbuc2 
    lda #>vdest
    sta VERA_ADDRX_M
    // *VERA_ADDRX_H = VERA_INC_1 | vbank
    // [17] *VERA_ADDRX_H = VERA_INC_1 -- _deref_pbuc1=vbuc2 
    lda #VERA_INC_1
    sta VERA_ADDRX_H
    // [18] phi from memcpy_to_vram to memcpy_to_vram::@1 [phi:memcpy_to_vram->memcpy_to_vram::@1]
    // [18] phi memcpy_to_vram::s#2 = (char *)memcpy_to_vram::src#0 [phi:memcpy_to_vram->memcpy_to_vram::@1#0] -- pbuz1=pbuc1 
    lda #<src
    sta.z s
    lda #>src
    sta.z s+1
    // memcpy_to_vram::@1
  __b1:
    // for(char *s = src; s!=end; s++)
    // [19] if(memcpy_to_vram::s#2!=memcpy_to_vram::end#0) goto memcpy_to_vram::@2 -- pbuz1_neq_pbuc1_then_la1 
    lda.z s+1
    cmp #>end
    bne __b2
    lda.z s
    cmp #<end
    bne __b2
    // memcpy_to_vram::@return
    // }
    // [20] return 
    rts
    // memcpy_to_vram::@2
  __b2:
    // *VERA_DATA0 = *s
    // [21] *VERA_DATA0 = *memcpy_to_vram::s#2 -- _deref_pbuc1=_deref_pbuz1 
    ldy #0
    lda (s),y
    sta VERA_DATA0
    // for(char *s = src; s!=end; s++)
    // [22] memcpy_to_vram::s#1 = ++ memcpy_to_vram::s#2 -- pbuz1=_inc_pbuz1 
    inc.z s
    bne !+
    inc.z s+1
  !:
    // [18] phi from memcpy_to_vram::@2 to memcpy_to_vram::@1 [phi:memcpy_to_vram::@2->memcpy_to_vram::@1]
    // [18] phi memcpy_to_vram::s#2 = memcpy_to_vram::s#1 [phi:memcpy_to_vram::@2->memcpy_to_vram::@1#0] -- register_copy 
    jmp __b1
}
  // vpoke
// Put a single byte into VRAM.
// Uses VERA DATA0
// - bank: Which 64K VRAM bank to put data into (0/1)
// - addr: The address in VRAM
// - data: The data to put into VRAM
// void vpoke(char vbank, __zp(2) char *vaddr, __register(X) char data)
vpoke: {
    .label vaddr = 2
    // *VERA_CTRL &= ~VERA_ADDRSEL
    // [24] *VERA_CTRL = *VERA_CTRL & ~VERA_ADDRSEL -- _deref_pbuc1=_deref_pbuc1_band_vbuc2 
    // Select DATA0
    lda #VERA_ADDRSEL^$ff
    and VERA_CTRL
    sta VERA_CTRL
    // BYTE0(vaddr)
    // [25] vpoke::$0 = byte0  vpoke::vaddr#2 -- vbuaa=_byte0_pbuz1 
    lda.z vaddr
    // *VERA_ADDRX_L = BYTE0(vaddr)
    // [26] *VERA_ADDRX_L = vpoke::$0 -- _deref_pbuc1=vbuaa 
    // Set address
    sta VERA_ADDRX_L
    // BYTE1(vaddr)
    // [27] vpoke::$1 = byte1  vpoke::vaddr#2 -- vbuaa=_byte1_pbuz1 
    lda.z vaddr+1
    // *VERA_ADDRX_M = BYTE1(vaddr)
    // [28] *VERA_ADDRX_M = vpoke::$1 -- _deref_pbuc1=vbuaa 
    sta VERA_ADDRX_M
    // *VERA_ADDRX_H = VERA_INC_0 | vbank
    // [29] *VERA_ADDRX_H = 0 -- _deref_pbuc1=vbuc2 
    lda #0
    sta VERA_ADDRX_H
    // *VERA_DATA0 = data
    // [30] *VERA_DATA0 = vpoke::data#2 -- _deref_pbuc1=vbuxx 
    // Set data
    stx VERA_DATA0
    // vpoke::@return
    // }
    // [31] return 
    rts
}
  // File Data

