From 3948ffd3df50e361efdf37bee8ff1f55b82ba6b4 Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Sat, 2 May 2020 15:38:02 +0200 Subject: [PATCH] Updated helloworld.c to use and printf() --- src/test/kc/examples/helloworld/helloworld.c | 5 +- .../ref/examples/helloworld/helloworld.asm | 265 +- .../ref/examples/helloworld/helloworld.cfg | 169 +- .../ref/examples/helloworld/helloworld.log | 2510 ++++++++++++----- .../ref/examples/helloworld/helloworld.sym | 114 +- 5 files changed, 2217 insertions(+), 846 deletions(-) diff --git a/src/test/kc/examples/helloworld/helloworld.c b/src/test/kc/examples/helloworld/helloworld.c index d9b46d0cd..b5e37cec7 100644 --- a/src/test/kc/examples/helloworld/helloworld.c +++ b/src/test/kc/examples/helloworld/helloworld.c @@ -1,6 +1,5 @@ -#include +#include void main() { - print_str("hello world!"); - print_ln(); + printf("hello world!\n"); } diff --git a/src/test/ref/examples/helloworld/helloworld.asm b/src/test/ref/examples/helloworld/helloworld.asm index d0a61da00..bbc4dad5e 100644 --- a/src/test/ref/examples/helloworld/helloworld.asm +++ b/src/test/ref/examples/helloworld/helloworld.asm @@ -1,88 +1,225 @@ .pc = $801 "Basic" -:BasicUpstart(main) +:BasicUpstart(__bbegin) .pc = $80d "Program" - .label print_line_cursor = 2 - .label print_char_cursor = 6 + .label printf_cursor_x = 8 + .label printf_cursor_y = 9 + .label printf_cursor_ptr = $a +__bbegin: + // printf_cursor_x = 0 + // X-position of cursor + lda #0 + sta.z printf_cursor_x + // printf_cursor_y = 0 + // Y-position of cursor + sta.z printf_cursor_y + // printf_cursor_ptr = PRINTF_SCREEN_ADDRESS + // Pointer to cursor address + lda #<$400 + sta.z printf_cursor_ptr + lda #>$400 + sta.z printf_cursor_ptr+1 + jsr main + rts main: { - // print_str("hello world!") - jsr print_str - // print_ln() - jsr print_ln + // printf("hello world!\n") + jsr printf_str // } rts - str: .text "hello world!" + str: .text @"hello world!\n" .byte 0 } -// Print a newline -print_ln: { - lda #<$400 - sta.z print_line_cursor - lda #>$400 - sta.z print_line_cursor+1 - __b1: - // print_line_cursor + $28 - lda #$28 - clc - adc.z print_line_cursor - sta.z print_line_cursor - bcc !+ - inc.z print_line_cursor+1 - !: - // while (print_line_cursor$400 - sta.z print_char_cursor+1 +// Handles escape codes such as newline +// printf_str(byte* zp(2) str) +printf_str: { + .label str = 2 lda #main.str sta.z str+1 - __b1: - // while(*str) - ldy #0 - lda (str),y - cmp #0 - bne __b2 - // } - rts __b2: - // print_char(*(str++)) + // ch = *str++ ldy #0 lda (str),y - jsr print_char - // print_char(*(str++)); inc.z str bne !+ inc.z str+1 !: - jmp __b1 + // if(ch==0) + cmp #0 + bne __b3 + // } + rts + __b3: + // if(ch=='\n') + cmp #'\n' + beq __b4 + // printf_char(ch) + jsr printf_char + jmp __b2 + __b4: + // printf_ln() + jsr printf_ln + jmp __b2 } -// Print a single char -// print_char(byte register(A) ch) -print_char: { - // *(print_char_cursor++) = ch - ldy #0 - sta (print_char_cursor),y - // *(print_char_cursor++) = ch; - inc.z print_char_cursor - bne !+ - inc.z print_char_cursor+1 +// Print a newline +printf_ln: { + .label __0 = $a + .label __1 = $a + // printf_cursor_ptr - printf_cursor_x + sec + lda.z __0 + sbc.z printf_cursor_x + sta.z __0 + bcs !+ + dec.z __0+1 !: + // printf_cursor_ptr - printf_cursor_x + PRINTF_SCREEN_WIDTH + lda #$28 + clc + adc.z __1 + sta.z __1 + bcc !+ + inc.z __1+1 + !: + // printf_cursor_ptr = printf_cursor_ptr - printf_cursor_x + PRINTF_SCREEN_WIDTH + // printf_cursor_x = 0 + lda #0 + sta.z printf_cursor_x + // printf_cursor_y++; + inc.z printf_cursor_y + // printf_scroll() + jsr printf_scroll + // } + rts +} +// Scroll the entire screen if the cursor is on the last line +printf_scroll: { + .label __4 = $a + // if(printf_cursor_y==PRINTF_SCREEN_HEIGHT) + lda #$19 + cmp.z printf_cursor_y + bne __breturn + // memcpy(PRINTF_SCREEN_ADDRESS, PRINTF_SCREEN_ADDRESS+PRINTF_SCREEN_WIDTH, PRINTF_SCREEN_BYTES-PRINTF_SCREEN_WIDTH) + jsr memcpy + // memset(PRINTF_SCREEN_ADDRESS+PRINTF_SCREEN_BYTES-PRINTF_SCREEN_WIDTH, ' ', PRINTF_SCREEN_WIDTH) + jsr memset + // printf_cursor_ptr-PRINTF_SCREEN_WIDTH + lda.z __4 + sec + sbc #<$28 + sta.z __4 + lda.z __4+1 + sbc #>$28 + sta.z __4+1 + // printf_cursor_ptr = printf_cursor_ptr-PRINTF_SCREEN_WIDTH + // printf_cursor_y--; + dec.z printf_cursor_y + __breturn: + // } + rts +} +// Copies the character c (an unsigned char) to the first num characters of the object pointed to by the argument str. +memset: { + .const c = ' ' + .const num = $28 + .label str = $400+$28*$19-$28 + .label end = str+num + .label dst = 4 + lda #str + sta.z dst+1 + __b1: + // for(char* dst = str; dst!=end; dst++) + lda.z dst+1 + cmp #>end + bne __b2 + lda.z dst + cmp #destination + sta.z dst+1 + lda #source + sta.z src+1 + __b1: + // while(src!=src_end) + lda.z src+1 + cmp #>src_end + bne __b2 + lda.z src + cmp # (number) 0 + (bool~) memset::$1 ← ! (bool~) memset::$0 + if((bool~) memset::$1) goto memset::@1 + to:memset::@2 +memset::@1: scope:[memset] from memset memset::@3 + (void*) memset::str#1 ← phi( memset/(void*) memset::str#3 memset::@3/(void*) memset::str#4 ) + (void*) memset::return#0 ← (void*) memset::str#1 + to:memset::@return +memset::@2: scope:[memset] from memset + (byte) memset::c#3 ← phi( memset/(byte) memset::c#4 ) + (word) memset::num#2 ← phi( memset/(word) memset::num#1 ) + (void*) memset::str#2 ← phi( memset/(void*) memset::str#3 ) + (byte*~) memset::$4 ← (byte*)(void*) memset::str#2 + (byte*~) memset::$2 ← (byte*~) memset::$4 + (word) memset::num#2 + (byte*) memset::end#0 ← (byte*~) memset::$2 + (byte*) memset::dst#0 ← ((byte*)) (void*) memset::str#2 + to:memset::@3 +memset::@3: scope:[memset] from memset::@2 memset::@4 + (byte) memset::c#2 ← phi( memset::@2/(byte) memset::c#3 memset::@4/(byte) memset::c#1 ) + (void*) memset::str#4 ← phi( memset::@2/(void*) memset::str#2 memset::@4/(void*) memset::str#5 ) + (byte*) memset::end#1 ← phi( memset::@2/(byte*) memset::end#0 memset::@4/(byte*) memset::end#2 ) + (byte*) memset::dst#2 ← phi( memset::@2/(byte*) memset::dst#0 memset::@4/(byte*) memset::dst#1 ) + (bool~) memset::$3 ← (byte*) memset::dst#2 != (byte*) memset::end#1 + if((bool~) memset::$3) goto memset::@4 + to:memset::@1 +memset::@4: scope:[memset] from memset::@3 + (void*) memset::str#5 ← phi( memset::@3/(void*) memset::str#4 ) + (byte*) memset::end#2 ← phi( memset::@3/(byte*) memset::end#1 ) + (byte*) memset::dst#3 ← phi( memset::@3/(byte*) memset::dst#2 ) + (byte) memset::c#1 ← phi( memset::@3/(byte) memset::c#2 ) + *((byte*) memset::dst#3) ← (byte) memset::c#1 + (byte*) memset::dst#1 ← ++ (byte*) memset::dst#3 + to:memset::@3 +memset::@return: scope:[memset] from memset::@1 + (void*) memset::return#3 ← phi( memset::@1/(void*) memset::return#0 ) + (void*) memset::return#1 ← (void*) memset::return#3 + return + to:@return @1: scope:[] from @begin - (byte*) print_screen#0 ← (byte*)(number) $400 - (byte*) print_line_cursor#0 ← (byte*) print_screen#0 - (byte*) print_char_cursor#0 ← (byte*) print_line_cursor#0 + (byte) printf_cursor_x ← (byte) 0 + (byte) printf_cursor_y ← (byte) 0 + (byte*) printf_cursor_ptr ← (byte*)(number) $400 to:@2 -(void()) print_str((byte*) print_str::str) -print_str: scope:[print_str] from main - (byte*) print_char_cursor#26 ← phi( main/(byte*) print_char_cursor#24 ) - (byte*) print_str::str#5 ← phi( main/(byte*) print_str::str#1 ) - to:print_str::@1 -print_str::@1: scope:[print_str] from print_str print_str::@3 - (byte*) print_char_cursor#22 ← phi( print_str/(byte*) print_char_cursor#26 print_str::@3/(byte*) print_char_cursor#1 ) - (byte*) print_str::str#2 ← phi( print_str/(byte*) print_str::str#5 print_str::@3/(byte*) print_str::str#0 ) - (bool~) print_str::$1 ← (number) 0 != *((byte*) print_str::str#2) - if((bool~) print_str::$1) goto print_str::@2 - to:print_str::@return -print_str::@2: scope:[print_str] from print_str::@1 - (byte*) print_char_cursor#21 ← phi( print_str::@1/(byte*) print_char_cursor#22 ) - (byte*) print_str::str#3 ← phi( print_str::@1/(byte*) print_str::str#2 ) - (byte) print_char::ch#0 ← *((byte*) print_str::str#3) - call print_char - to:print_str::@3 -print_str::@3: scope:[print_str] from print_str::@2 - (byte*) print_str::str#4 ← phi( print_str::@2/(byte*) print_str::str#3 ) - (byte*) print_char_cursor#11 ← phi( print_str::@2/(byte*) print_char_cursor#6 ) - (byte*) print_char_cursor#1 ← (byte*) print_char_cursor#11 - (byte*) print_str::str#0 ← ++ (byte*) print_str::str#4 - to:print_str::@1 -print_str::@return: scope:[print_str] from print_str::@1 - (byte*) print_char_cursor#12 ← phi( print_str::@1/(byte*) print_char_cursor#22 ) - (byte*) print_char_cursor#2 ← (byte*) print_char_cursor#12 +(void()) printf_char((byte) printf_char::ch) +printf_char: scope:[printf_char] from printf_str::@5 + (byte) printf_char::ch#1 ← phi( printf_str::@5/(byte) printf_char::ch#0 ) + *((byte*) printf_cursor_ptr) ← (byte) printf_char::ch#1 + (byte*) printf_cursor_ptr ← ++ (byte*) printf_cursor_ptr + (byte) printf_cursor_x ← ++ (byte) printf_cursor_x + (bool~) printf_char::$0 ← (byte) printf_cursor_x == (number) $28 + (bool~) printf_char::$1 ← ! (bool~) printf_char::$0 + if((bool~) printf_char::$1) goto printf_char::@return + to:printf_char::@1 +printf_char::@1: scope:[printf_char] from printf_char + (byte) printf_cursor_x ← (number) 0 + (byte) printf_cursor_y ← ++ (byte) printf_cursor_y + call printf_scroll + to:printf_char::@2 +printf_char::@2: scope:[printf_char] from printf_char::@1 + to:printf_char::@return +printf_char::@return: scope:[printf_char] from printf_char printf_char::@2 return to:@return -(void()) print_ln() -print_ln: scope:[print_ln] from main::@1 - (byte*) print_char_cursor#23 ← phi( main::@1/(byte*) print_char_cursor#7 ) - (byte*) print_line_cursor#12 ← phi( main::@1/(byte*) print_line_cursor#13 ) - to:print_ln::@1 -print_ln::@1: scope:[print_ln] from print_ln print_ln::@1 - (byte*) print_char_cursor#13 ← phi( print_ln/(byte*) print_char_cursor#23 print_ln::@1/(byte*) print_char_cursor#13 ) - (byte*) print_line_cursor#6 ← phi( print_ln/(byte*) print_line_cursor#12 print_ln::@1/(byte*) print_line_cursor#1 ) - (byte*~) print_ln::$0 ← (byte*) print_line_cursor#6 + (number) $28 - (byte*) print_line_cursor#1 ← (byte*~) print_ln::$0 - (bool~) print_ln::$1 ← (byte*) print_line_cursor#1 < (byte*) print_char_cursor#13 - if((bool~) print_ln::$1) goto print_ln::@1 - to:print_ln::@2 -print_ln::@2: scope:[print_ln] from print_ln::@1 - (byte*) print_line_cursor#7 ← phi( print_ln::@1/(byte*) print_line_cursor#1 ) - (byte*) print_char_cursor#3 ← (byte*) print_line_cursor#7 - to:print_ln::@return -print_ln::@return: scope:[print_ln] from print_ln::@2 - (byte*) print_char_cursor#14 ← phi( print_ln::@2/(byte*) print_char_cursor#3 ) - (byte*) print_line_cursor#8 ← phi( print_ln::@2/(byte*) print_line_cursor#7 ) - (byte*) print_line_cursor#2 ← (byte*) print_line_cursor#8 - (byte*) print_char_cursor#4 ← (byte*) print_char_cursor#14 +(void()) printf_ln() +printf_ln: scope:[printf_ln] from printf_str::@4 + (byte*~) printf_ln::$0 ← (byte*) printf_cursor_ptr - (byte) printf_cursor_x + (byte*~) printf_ln::$1 ← (byte*~) printf_ln::$0 + (number) $28 + (byte*) printf_cursor_ptr ← (byte*~) printf_ln::$1 + (byte) printf_cursor_x ← (number) 0 + (byte) printf_cursor_y ← ++ (byte) printf_cursor_y + call printf_scroll + to:printf_ln::@1 +printf_ln::@1: scope:[printf_ln] from printf_ln + to:printf_ln::@return +printf_ln::@return: scope:[printf_ln] from printf_ln::@1 return to:@return -(void()) print_char((byte) print_char::ch) -print_char: scope:[print_char] from print_str::@2 - (byte*) print_char_cursor#15 ← phi( print_str::@2/(byte*) print_char_cursor#21 ) - (byte) print_char::ch#1 ← phi( print_str::@2/(byte) print_char::ch#0 ) - *((byte*) print_char_cursor#15) ← (byte) print_char::ch#1 - (byte*) print_char_cursor#5 ← ++ (byte*) print_char_cursor#15 - to:print_char::@return -print_char::@return: scope:[print_char] from print_char - (byte*) print_char_cursor#16 ← phi( print_char/(byte*) print_char_cursor#5 ) - (byte*) print_char_cursor#6 ← (byte*) print_char_cursor#16 +(void()) printf_scroll() +printf_scroll: scope:[printf_scroll] from printf_char::@1 printf_ln + (bool~) printf_scroll::$0 ← (byte) printf_cursor_y == (number) $19 + (bool~) printf_scroll::$1 ← ! (bool~) printf_scroll::$0 + if((bool~) printf_scroll::$1) goto printf_scroll::@return + to:printf_scroll::@1 +printf_scroll::@1: scope:[printf_scroll] from printf_scroll + (void*) memcpy::destination#0 ← (void*)(number) $400 + (void*) memcpy::source#0 ← (void*)(number) $400+(number) $28 + (word) memcpy::num#0 ← (number) $28*(number) $19-(number) $28 + call memcpy + (void*) memcpy::return#2 ← (void*) memcpy::return#1 + to:printf_scroll::@2 +printf_scroll::@2: scope:[printf_scroll] from printf_scroll::@1 + (void*) memset::str#0 ← (void*)(number) $400+(number) $28*(number) $19-(number) $28 + (byte) memset::c#0 ← (byte) ' ' + (word) memset::num#0 ← (number) $28 + call memset + (void*) memset::return#2 ← (void*) memset::return#1 + to:printf_scroll::@3 +printf_scroll::@3: scope:[printf_scroll] from printf_scroll::@2 + (byte*~) printf_scroll::$4 ← (byte*) printf_cursor_ptr - (number) $28 + (byte*) printf_cursor_ptr ← (byte*~) printf_scroll::$4 + (byte) printf_cursor_y ← -- (byte) printf_cursor_y + to:printf_scroll::@return +printf_scroll::@return: scope:[printf_scroll] from printf_scroll printf_scroll::@3 + return + to:@return + +(void()) printf_str((byte*) printf_str::str) +printf_str: scope:[printf_str] from main + (byte*) printf_str::str#4 ← phi( main/(byte*) printf_str::str#1 ) + to:printf_str::@1 +printf_str::@1: scope:[printf_str] from printf_str printf_str::@6 printf_str::@7 + (byte*) printf_str::str#3 ← phi( printf_str/(byte*) printf_str::str#4 printf_str::@6/(byte*) printf_str::str#5 printf_str::@7/(byte*) printf_str::str#6 ) + if(true) goto printf_str::@2 + to:printf_str::@return +printf_str::@2: scope:[printf_str] from printf_str::@1 + (byte*) printf_str::str#2 ← phi( printf_str::@1/(byte*) printf_str::str#3 ) + (byte) printf_str::ch#0 ← *((byte*) printf_str::str#2) + (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#2 + (bool~) printf_str::$0 ← (byte) printf_str::ch#0 == (number) 0 + (bool~) printf_str::$1 ← ! (bool~) printf_str::$0 + if((bool~) printf_str::$1) goto printf_str::@3 + to:printf_str::@return +printf_str::@3: scope:[printf_str] from printf_str::@2 + (byte*) printf_str::str#9 ← phi( printf_str::@2/(byte*) printf_str::str#0 ) + (byte) printf_str::ch#1 ← phi( printf_str::@2/(byte) printf_str::ch#0 ) + (bool~) printf_str::$2 ← (byte) printf_str::ch#1 == (byte) ' +' + if((bool~) printf_str::$2) goto printf_str::@4 + to:printf_str::@5 +printf_str::@4: scope:[printf_str] from printf_str::@3 + (byte*) printf_str::str#7 ← phi( printf_str::@3/(byte*) printf_str::str#9 ) + call printf_ln + to:printf_str::@6 +printf_str::@6: scope:[printf_str] from printf_str::@4 + (byte*) printf_str::str#5 ← phi( printf_str::@4/(byte*) printf_str::str#7 ) + to:printf_str::@1 +printf_str::@5: scope:[printf_str] from printf_str::@3 + (byte*) printf_str::str#8 ← phi( printf_str::@3/(byte*) printf_str::str#9 ) + (byte) printf_str::ch#2 ← phi( printf_str::@3/(byte) printf_str::ch#1 ) + (byte) printf_char::ch#0 ← (byte) printf_str::ch#2 + call printf_char + to:printf_str::@7 +printf_str::@7: scope:[printf_str] from printf_str::@5 + (byte*) printf_str::str#6 ← phi( printf_str::@5/(byte*) printf_str::str#8 ) + to:printf_str::@1 +printf_str::@return: scope:[printf_str] from printf_str::@1 printf_str::@2 return to:@return (void()) main() main: scope:[main] from @2 - (byte*) print_line_cursor#15 ← phi( @2/(byte*) print_line_cursor#14 ) - (byte*) print_char_cursor#24 ← phi( @2/(byte*) print_char_cursor#25 ) - (byte*) print_str::str#1 ← (const byte*) main::str - call print_str + (byte*) printf_str::str#1 ← (const byte*) main::str + call printf_str to:main::@1 main::@1: scope:[main] from main - (byte*) print_line_cursor#13 ← phi( main/(byte*) print_line_cursor#15 ) - (byte*) print_char_cursor#17 ← phi( main/(byte*) print_char_cursor#2 ) - (byte*) print_char_cursor#7 ← (byte*) print_char_cursor#17 - call print_ln - to:main::@2 -main::@2: scope:[main] from main::@1 - (byte*) print_char_cursor#18 ← phi( main::@1/(byte*) print_char_cursor#4 ) - (byte*) print_line_cursor#9 ← phi( main::@1/(byte*) print_line_cursor#2 ) - (byte*) print_line_cursor#3 ← (byte*) print_line_cursor#9 - (byte*) print_char_cursor#8 ← (byte*) print_char_cursor#18 to:main::@return -main::@return: scope:[main] from main::@2 - (byte*) print_line_cursor#10 ← phi( main::@2/(byte*) print_line_cursor#3 ) - (byte*) print_char_cursor#19 ← phi( main::@2/(byte*) print_char_cursor#8 ) - (byte*) print_char_cursor#9 ← (byte*) print_char_cursor#19 - (byte*) print_line_cursor#4 ← (byte*) print_line_cursor#10 +main::@return: scope:[main] from main::@1 return to:@return @2: scope:[] from @1 - (byte*) print_line_cursor#14 ← phi( @1/(byte*) print_line_cursor#0 ) - (byte*) print_char_cursor#25 ← phi( @1/(byte*) print_char_cursor#0 ) call main to:@3 @3: scope:[] from @2 - (byte*) print_line_cursor#11 ← phi( @2/(byte*) print_line_cursor#4 ) - (byte*) print_char_cursor#20 ← phi( @2/(byte*) print_char_cursor#9 ) - (byte*) print_char_cursor#10 ← (byte*) print_char_cursor#20 - (byte*) print_line_cursor#5 ← (byte*) print_line_cursor#11 to:@end @end: scope:[] from @3 @@ -126,266 +233,569 @@ SYMBOL TABLE SSA (const byte) RADIX::OCTAL = (number) 8 (void()) main() (label) main::@1 -(label) main::@2 (label) main::@return -(const byte*) main::str[(byte) $d] = (byte*) "hello world!" -(void()) print_char((byte) print_char::ch) -(label) print_char::@return -(byte) print_char::ch -(byte) print_char::ch#0 -(byte) print_char::ch#1 -(byte*) print_char_cursor -(byte*) print_char_cursor#0 -(byte*) print_char_cursor#1 -(byte*) print_char_cursor#10 -(byte*) print_char_cursor#11 -(byte*) print_char_cursor#12 -(byte*) print_char_cursor#13 -(byte*) print_char_cursor#14 -(byte*) print_char_cursor#15 -(byte*) print_char_cursor#16 -(byte*) print_char_cursor#17 -(byte*) print_char_cursor#18 -(byte*) print_char_cursor#19 -(byte*) print_char_cursor#2 -(byte*) print_char_cursor#20 -(byte*) print_char_cursor#21 -(byte*) print_char_cursor#22 -(byte*) print_char_cursor#23 -(byte*) print_char_cursor#24 -(byte*) print_char_cursor#25 -(byte*) print_char_cursor#26 -(byte*) print_char_cursor#3 -(byte*) print_char_cursor#4 -(byte*) print_char_cursor#5 -(byte*) print_char_cursor#6 -(byte*) print_char_cursor#7 -(byte*) print_char_cursor#8 -(byte*) print_char_cursor#9 -(byte*) print_line_cursor -(byte*) print_line_cursor#0 -(byte*) print_line_cursor#1 -(byte*) print_line_cursor#10 -(byte*) print_line_cursor#11 -(byte*) print_line_cursor#12 -(byte*) print_line_cursor#13 -(byte*) print_line_cursor#14 -(byte*) print_line_cursor#15 -(byte*) print_line_cursor#2 -(byte*) print_line_cursor#3 -(byte*) print_line_cursor#4 -(byte*) print_line_cursor#5 -(byte*) print_line_cursor#6 -(byte*) print_line_cursor#7 -(byte*) print_line_cursor#8 -(byte*) print_line_cursor#9 -(void()) print_ln() -(byte*~) print_ln::$0 -(bool~) print_ln::$1 -(label) print_ln::@1 -(label) print_ln::@2 -(label) print_ln::@return -(byte*) print_screen -(byte*) print_screen#0 -(void()) print_str((byte*) print_str::str) -(bool~) print_str::$1 -(label) print_str::@1 -(label) print_str::@2 -(label) print_str::@3 -(label) print_str::@return -(byte*) print_str::str -(byte*) print_str::str#0 -(byte*) print_str::str#1 -(byte*) print_str::str#2 -(byte*) print_str::str#3 -(byte*) print_str::str#4 -(byte*) print_str::str#5 +(const byte*) main::str[(byte) $e] = (byte*) "hello world! +" +(void*()) memcpy((void*) memcpy::destination , (void*) memcpy::source , (word) memcpy::num) +(byte*~) memcpy::$0 +(bool~) memcpy::$1 +(byte*~) 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 +(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 +(void*) memcpy::return +(void*) memcpy::return#0 +(void*) memcpy::return#1 +(void*) memcpy::return#2 +(void*) memcpy::return#3 +(void*) memcpy::source +(void*) memcpy::source#0 +(void*) memcpy::source#1 +(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 +(void*()) memset((void*) memset::str , (byte) memset::c , (word) memset::num) +(bool~) memset::$0 +(bool~) memset::$1 +(byte*~) memset::$2 +(bool~) memset::$3 +(byte*~) memset::$4 +(label) memset::@1 +(label) memset::@2 +(label) memset::@3 +(label) memset::@4 +(label) memset::@return +(byte) memset::c +(byte) memset::c#0 +(byte) memset::c#1 +(byte) memset::c#2 +(byte) memset::c#3 +(byte) memset::c#4 +(byte*) memset::dst +(byte*) memset::dst#0 +(byte*) memset::dst#1 +(byte*) memset::dst#2 +(byte*) memset::dst#3 +(byte*) memset::end +(byte*) memset::end#0 +(byte*) memset::end#1 +(byte*) memset::end#2 +(word) memset::num +(word) memset::num#0 +(word) memset::num#1 +(word) memset::num#2 +(void*) memset::return +(void*) memset::return#0 +(void*) memset::return#1 +(void*) memset::return#2 +(void*) memset::return#3 +(void*) memset::str +(void*) memset::str#0 +(void*) memset::str#1 +(void*) memset::str#2 +(void*) memset::str#3 +(void*) memset::str#4 +(void*) memset::str#5 +(const byte*) printf_buffer_number::digits[(number) $b] = { fill( $b, 0) } +(byte) printf_buffer_number::sign +(void()) printf_char((byte) printf_char::ch) +(bool~) printf_char::$0 +(bool~) printf_char::$1 +(label) printf_char::@1 +(label) printf_char::@2 +(label) printf_char::@return +(byte) printf_char::ch +(byte) printf_char::ch#0 +(byte) printf_char::ch#1 +(byte*) printf_cursor_ptr loadstore +(byte) printf_cursor_x loadstore +(byte) printf_cursor_y loadstore +(byte) printf_format_number::justify_left +(byte) printf_format_number::min_length +(byte) printf_format_number::radix +(byte) printf_format_number::sign_always +(byte) printf_format_number::upper_case +(byte) printf_format_number::zero_padding +(byte) printf_format_string::justify_left +(byte) printf_format_string::min_length +(void()) printf_ln() +(byte*~) printf_ln::$0 +(byte*~) printf_ln::$1 +(label) printf_ln::@1 +(label) printf_ln::@return +(void()) printf_scroll() +(bool~) printf_scroll::$0 +(bool~) printf_scroll::$1 +(byte*~) printf_scroll::$4 +(label) printf_scroll::@1 +(label) printf_scroll::@2 +(label) printf_scroll::@3 +(label) printf_scroll::@return +(void()) printf_str((byte*) printf_str::str) +(bool~) printf_str::$0 +(bool~) printf_str::$1 +(bool~) printf_str::$2 +(label) printf_str::@1 +(label) printf_str::@2 +(label) printf_str::@3 +(label) printf_str::@4 +(label) printf_str::@5 +(label) printf_str::@6 +(label) printf_str::@7 +(label) printf_str::@return +(byte) printf_str::ch +(byte) printf_str::ch#0 +(byte) printf_str::ch#1 +(byte) printf_str::ch#2 +(byte*) printf_str::str +(byte*) printf_str::str#0 +(byte*) printf_str::str#1 +(byte*) printf_str::str#2 +(byte*) printf_str::str#3 +(byte*) printf_str::str#4 +(byte*) printf_str::str#5 +(byte*) printf_str::str#6 +(byte*) printf_str::str#7 +(byte*) printf_str::str#8 +(byte*) printf_str::str#9 -Adding number conversion cast (unumber) 0 in (bool~) print_str::$1 ← (number) 0 != *((byte*) print_str::str#2) -Adding number conversion cast (unumber) $28 in (byte*~) print_ln::$0 ← (byte*) print_line_cursor#6 + (number) $28 +Adding number conversion cast (unumber) 0 in (bool~) memset::$0 ← (word) memset::num#1 > (number) 0 +Adding number conversion cast (unumber) $28 in (bool~) printf_char::$0 ← (byte) printf_cursor_x == (number) $28 +Adding number conversion cast (unumber) 0 in (byte) printf_cursor_x ← (number) 0 +Adding number conversion cast (unumber) $28 in (byte*~) printf_ln::$1 ← (byte*~) printf_ln::$0 + (number) $28 +Adding number conversion cast (unumber) 0 in (byte) printf_cursor_x ← (number) 0 +Adding number conversion cast (unumber) $19 in (bool~) printf_scroll::$0 ← (byte) printf_cursor_y == (number) $19 +Adding number conversion cast (unumber) $28*$19-$28 in (word) memcpy::num#0 ← (number) $28*(number) $19-(number) $28 +Adding number conversion cast (unumber) $28 in (word) memset::num#0 ← (number) $28 +Adding number conversion cast (unumber) $28 in (byte*~) printf_scroll::$4 ← (byte*) printf_cursor_ptr - (number) $28 +Adding number conversion cast (unumber) 0 in (bool~) printf_str::$0 ← (byte) printf_str::ch#0 == (number) 0 Successful SSA optimization PassNAddNumberTypeConversions +Inlining cast (byte*) memcpy::src#0 ← (byte*)(void*) memcpy::source#1 +Inlining cast (byte*) memcpy::dst#0 ← (byte*)(void*) memcpy::destination#1 +Inlining cast (byte*) memset::dst#0 ← (byte*)(void*) memset::str#2 +Inlining cast (byte) printf_cursor_x ← (unumber)(number) 0 +Inlining cast (byte) printf_cursor_x ← (unumber)(number) 0 +Inlining cast (word) memcpy::num#0 ← (unumber)(number) $28*(number) $19-(number) $28 +Inlining cast (word) memset::num#0 ← (unumber)(number) $28 +Successful SSA optimization Pass2InlineCast +Simplifying constant integer cast 0 Simplifying constant pointer cast (byte*) 1024 +Simplifying constant integer cast $28 Simplifying constant integer cast 0 Simplifying constant integer cast $28 +Simplifying constant integer cast 0 +Simplifying constant integer cast $19 +Simplifying constant pointer cast (void*) 1024 +Simplifying constant integer cast $28 +Simplifying constant integer cast $28 +Simplifying constant integer cast 0 Successful SSA optimization PassNCastSimplification Finalized unsigned number type (byte) 0 Finalized unsigned number type (byte) $28 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (byte) $28 +Finalized unsigned number type (byte) 0 +Finalized unsigned number type (byte) $19 +Finalized unsigned number type (byte) $28 +Finalized unsigned number type (byte) $28 +Finalized unsigned number type (byte) 0 Successful SSA optimization PassNFinalizeNumberTypeConversions -Alias print_char_cursor#0 = print_line_cursor#0 print_screen#0 print_char_cursor#25 print_line_cursor#14 -Alias print_str::str#2 = print_str::str#3 print_str::str#4 -Alias print_char_cursor#12 = print_char_cursor#21 print_char_cursor#22 print_char_cursor#2 -Alias print_char_cursor#1 = print_char_cursor#11 -Alias print_line_cursor#1 = print_ln::$0 print_line_cursor#7 print_char_cursor#3 print_line_cursor#8 print_char_cursor#14 print_line_cursor#2 print_char_cursor#4 -Alias print_char_cursor#16 = print_char_cursor#5 print_char_cursor#6 -Alias print_line_cursor#13 = print_line_cursor#15 -Alias print_char_cursor#17 = print_char_cursor#7 -Alias print_line_cursor#10 = print_line_cursor#3 print_line_cursor#9 print_line_cursor#4 -Alias print_char_cursor#18 = print_char_cursor#8 print_char_cursor#19 print_char_cursor#9 -Alias print_char_cursor#10 = print_char_cursor#20 -Alias print_line_cursor#11 = print_line_cursor#5 +Inversing boolean not [20] (bool~) memset::$1 ← (word) memset::num#1 <= (byte) 0 from [19] (bool~) memset::$0 ← (word) memset::num#1 > (byte) 0 +Inversing boolean not [46] (bool~) printf_char::$1 ← (byte) printf_cursor_x != (byte) $28 from [45] (bool~) printf_char::$0 ← (byte) printf_cursor_x == (byte) $28 +Inversing boolean not [60] (bool~) printf_scroll::$1 ← (byte) printf_cursor_y != (byte) $19 from [59] (bool~) printf_scroll::$0 ← (byte) printf_cursor_y == (byte) $19 +Inversing boolean not [83] (bool~) printf_str::$1 ← (byte) printf_str::ch#0 != (byte) 0 from [82] (bool~) printf_str::$0 ← (byte) printf_str::ch#0 == (byte) 0 +Successful SSA optimization Pass2UnaryNotSimplification +Alias candidate removed (volatile)printf_cursor_ptr = printf_ln::$1 printf_scroll::$4 +Alias memcpy::src_end#0 = memcpy::$0 +Alias memcpy::src#2 = memcpy::src#3 +Alias memcpy::dst#2 = memcpy::dst#3 +Alias memcpy::src_end#1 = memcpy::src_end#2 +Alias memcpy::destination#2 = memcpy::destination#4 memcpy::destination#3 memcpy::return#0 memcpy::return#3 memcpy::return#1 +Alias memset::return#0 = memset::str#1 memset::return#3 memset::return#1 +Alias memset::str#2 = memset::str#3 +Alias memset::num#1 = memset::num#2 +Alias memset::c#3 = memset::c#4 +Alias memset::end#0 = memset::$2 +Alias memset::c#1 = memset::c#2 +Alias memset::dst#2 = memset::dst#3 +Alias memset::end#1 = memset::end#2 +Alias memset::str#4 = memset::str#5 +Alias printf_str::str#2 = printf_str::str#3 +Alias printf_str::ch#0 = printf_str::ch#1 printf_str::ch#2 +Alias printf_str::str#0 = printf_str::str#9 printf_str::str#7 printf_str::str#5 printf_str::str#8 printf_str::str#6 Successful SSA optimization Pass2AliasElimination -Identical Phi Values (byte*) print_str::str#5 (byte*) print_str::str#1 -Identical Phi Values (byte*) print_char_cursor#26 (byte*) print_char_cursor#24 -Identical Phi Values (byte*) print_char_cursor#1 (byte*) print_char_cursor#16 -Identical Phi Values (byte*) print_line_cursor#12 (byte*) print_line_cursor#13 -Identical Phi Values (byte*) print_char_cursor#23 (byte*) print_char_cursor#17 -Identical Phi Values (byte*) print_char_cursor#13 (byte*) print_char_cursor#23 -Identical Phi Values (byte) print_char::ch#1 (byte) print_char::ch#0 -Identical Phi Values (byte*) print_char_cursor#15 (byte*) print_char_cursor#12 -Identical Phi Values (byte*) print_char_cursor#24 (byte*) print_char_cursor#0 -Identical Phi Values (byte*) print_line_cursor#13 (byte*) print_char_cursor#0 -Identical Phi Values (byte*) print_char_cursor#17 (byte*) print_char_cursor#12 -Identical Phi Values (byte*) print_line_cursor#10 (byte*) print_line_cursor#1 -Identical Phi Values (byte*) print_char_cursor#18 (byte*) print_line_cursor#1 -Identical Phi Values (byte*) print_char_cursor#10 (byte*) print_char_cursor#18 -Identical Phi Values (byte*) print_line_cursor#11 (byte*) print_line_cursor#10 +Alias candidate removed (volatile)printf_cursor_ptr = printf_ln::$1 printf_scroll::$4 +Identical Phi Values (void*) memcpy::source#1 (void*) memcpy::source#0 +Identical Phi Values (void*) memcpy::destination#1 (void*) memcpy::destination#0 +Identical Phi Values (word) memcpy::num#1 (word) memcpy::num#0 +Identical Phi Values (byte*) memcpy::src_end#1 (byte*) memcpy::src_end#0 +Identical Phi Values (void*) memcpy::destination#2 (void*) memcpy::destination#1 +Identical Phi Values (word) memset::num#1 (word) memset::num#0 +Identical Phi Values (void*) memset::str#2 (void*) memset::str#0 +Identical Phi Values (byte) memset::c#3 (byte) memset::c#0 +Identical Phi Values (byte*) memset::end#1 (byte*) memset::end#0 +Identical Phi Values (void*) memset::str#4 (void*) memset::str#2 +Identical Phi Values (byte) memset::c#1 (byte) memset::c#3 +Identical Phi Values (byte) printf_char::ch#1 (byte) printf_char::ch#0 +Identical Phi Values (byte*) printf_str::str#4 (byte*) printf_str::str#1 Successful SSA optimization Pass2IdenticalPhiElimination -Simple Condition (bool~) print_str::$1 [4] if((byte) 0!=*((byte*) print_str::str#2)) goto print_str::@2 -Simple Condition (bool~) print_ln::$1 [14] if((byte*) print_line_cursor#1<(byte*) print_char_cursor#12) goto print_ln::@1 +Identical Phi Values (void*) memset::return#0 (void*) memset::str#0 +Successful SSA optimization Pass2IdenticalPhiElimination +Simple Condition (bool~) memcpy::$1 [7] if((byte*) memcpy::src#2!=(byte*) memcpy::src_end#0) goto memcpy::@2 +Simple Condition (bool~) memset::$1 [14] if((word) memset::num#0<=(byte) 0) goto memset::@1 +Simple Condition (bool~) memset::$3 [21] if((byte*) memset::dst#2!=(byte*) memset::end#0) goto memset::@4 +Simple Condition (bool~) printf_char::$1 [33] if((byte) printf_cursor_x!=(byte) $28) goto printf_char::@return +Simple Condition (bool~) printf_scroll::$1 [46] if((byte) printf_cursor_y!=(byte) $19) goto printf_scroll::@return +Simple Condition (bool~) printf_str::$1 [67] if((byte) printf_str::ch#0!=(byte) 0) goto printf_str::@3 +Simple Condition (bool~) printf_str::$2 [69] if((byte) printf_str::ch#0==(byte) ' +') goto printf_str::@4 Successful SSA optimization Pass2ConditionalJumpSimplification -Constant (const byte*) print_char_cursor#0 = (byte*) 1024 -Constant (const byte*) print_str::str#1 = main::str +Constant right-side identified [49] (word) memcpy::num#0 ← (unumber)(number) $28*(number) $19-(number) $28 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const void*) memcpy::destination#0 = (void*) 1024 +Constant (const void*) memcpy::source#0 = (void*)$400+$28 +Constant (const word) memcpy::num#0 = (unumber)$28*$19-$28 +Constant (const void*) memset::str#0 = (void*)$400+$28*$19-$28 +Constant (const byte) memset::c#0 = ' ' +Constant (const word) memset::num#0 = $28 +Constant (const byte*) printf_str::str#1 = main::str Successful SSA optimization Pass2ConstantIdentification -Inlining constant with var siblings (const byte*) print_str::str#1 -Inlining constant with var siblings (const byte*) print_char_cursor#0 -Constant inlined print_char_cursor#0 = (byte*) 1024 -Constant inlined print_str::str#1 = (const byte*) main::str +Constant (const byte*) memcpy::src#0 = (byte*)memcpy::source#0 +Constant (const byte*) memcpy::dst#0 = (byte*)memcpy::destination#0 +Constant (const byte*) memcpy::$2 = (byte*)memcpy::source#0 +Constant (const byte*) memset::$4 = (byte*)memset::str#0 +Constant (const byte*) memset::dst#0 = (byte*)memset::str#0 +Constant (const void*) memcpy::return#2 = memcpy::destination#0 +Constant (const void*) memset::return#2 = memset::str#0 +Successful SSA optimization Pass2ConstantIdentification +if() condition always false - eliminating [14] if((const word) memset::num#0<=(byte) 0) goto memset::@1 +if() condition always true - replacing block destination [63] if(true) goto printf_str::@2 +Successful SSA optimization Pass2ConstantIfs +Eliminating unused constant (const void*) memcpy::return#2 +Eliminating unused constant (const void*) memset::return#2 +Successful SSA optimization PassNEliminateUnusedVars +Alias candidate removed (volatile)printf_cursor_ptr = printf_ln::$1 printf_scroll::$4 +Constant right-side identified [0] (byte*) memcpy::src_end#0 ← (const byte*) memcpy::$2 + (const word) memcpy::num#0 +Constant right-side identified [7] (byte*) memset::end#0 ← (const byte*) memset::$4 + (const word) memset::num#0 +Successful SSA optimization Pass2ConstantRValueConsolidation +Constant (const byte*) memcpy::src_end#0 = memcpy::$2+memcpy::num#0 +Constant (const byte*) memset::end#0 = memset::$4+memset::num#0 +Successful SSA optimization Pass2ConstantIdentification +Alias candidate removed (volatile)printf_cursor_ptr = printf_ln::$1 printf_scroll::$4 +Inlining constant with var siblings (const byte*) memcpy::src#0 +Inlining constant with var siblings (const byte*) memcpy::dst#0 +Inlining constant with var siblings (const byte*) memset::dst#0 +Inlining constant with var siblings (const byte*) printf_str::str#1 +Constant inlined memset::dst#0 = (byte*)(const void*) memset::str#0 +Constant inlined memcpy::src#0 = (byte*)(const void*) memcpy::source#0 +Constant inlined memcpy::$2 = (byte*)(const void*) memcpy::source#0 +Constant inlined memset::$4 = (byte*)(const void*) memset::str#0 +Constant inlined memcpy::dst#0 = (byte*)(const void*) memcpy::destination#0 +Constant inlined printf_str::str#1 = (const byte*) main::str Successful SSA optimization Pass2ConstantInlining -Added new block during phi lifting print_ln::@3(between print_ln::@1 and print_ln::@1) +Alias candidate removed (volatile)printf_cursor_ptr = printf_ln::$1 printf_scroll::$4 +Alias candidate removed (volatile)printf_cursor_ptr = printf_ln::$1 printf_scroll::$4 Adding NOP phi() at start of @begin -Adding NOP phi() at start of @1 Adding NOP phi() at start of @2 Adding NOP phi() at start of @3 Adding NOP phi() at start of @end Adding NOP phi() at start of main Adding NOP phi() at start of main::@1 -Adding NOP phi() at start of main::@2 -Adding NOP phi() at start of print_ln -Adding NOP phi() at start of print_ln::@2 -Adding NOP phi() at start of print_str +Adding NOP phi() at start of printf_str +Adding NOP phi() at start of printf_str::@4 +Adding NOP phi() at start of printf_ln::@1 +Adding NOP phi() at start of printf_scroll::@1 +Adding NOP phi() at start of printf_scroll::@2 +Adding NOP phi() at start of memset +Adding NOP phi() at start of memset::@2 +Adding NOP phi() at start of memset::@1 +Adding NOP phi() at start of memcpy +Adding NOP phi() at start of memcpy::@3 +Adding NOP phi() at start of printf_char::@2 CALL GRAPH -Calls in [] to main:3 -Calls in [main] to print_str:7 print_ln:9 -Calls in [print_str] to print_char:24 +Calls in [] to main:5 +Calls in [main] to printf_str:9 +Calls in [printf_str] to printf_char:20 printf_ln:23 +Calls in [printf_ln] to printf_scroll:30 +Calls in [printf_scroll] to memcpy:35 memset:37 +Calls in [printf_char] to printf_scroll:67 -Created 3 initial phi equivalence classes -Coalesced [18] print_line_cursor#16 ← print_line_cursor#1 -Coalesced [26] print_str::str#6 ← print_str::str#0 -Coalesced [27] print_char_cursor#27 ← print_char_cursor#16 -Coalesced down to 3 phi equivalence classes -Culled Empty Block (label) @1 +Created 4 initial phi equivalence classes +Coalesced [21] printf_str::str#11 ← printf_str::str#0 +Coalesced (already) [24] printf_str::str#10 ← printf_str::str#0 +Coalesced [50] memset::dst#4 ← memset::dst#1 +Coalesced [59] memcpy::src#4 ← memcpy::src#1 +Coalesced [60] memcpy::dst#4 ← memcpy::dst#1 +Coalesced down to 4 phi equivalence classes Culled Empty Block (label) @3 -Culled Empty Block (label) main::@2 -Culled Empty Block (label) print_ln::@2 -Culled Empty Block (label) print_ln::@3 -Renumbering block @2 to @1 +Culled Empty Block (label) main::@1 +Culled Empty Block (label) printf_str::@7 +Culled Empty Block (label) printf_str::@6 +Culled Empty Block (label) printf_ln::@1 +Culled Empty Block (label) memset::@2 +Culled Empty Block (label) memset::@1 +Culled Empty Block (label) memcpy::@3 +Culled Empty Block (label) printf_char::@2 +Renumbering block memset::@3 to memset::@1 +Renumbering block memset::@4 to memset::@2 Adding NOP phi() at start of @begin -Adding NOP phi() at start of @1 +Adding NOP phi() at start of @2 Adding NOP phi() at start of @end Adding NOP phi() at start of main -Adding NOP phi() at start of main::@1 -Adding NOP phi() at start of print_ln -Adding NOP phi() at start of print_str +Adding NOP phi() at start of printf_str +Adding NOP phi() at start of printf_str::@4 +Adding NOP phi() at start of printf_scroll::@1 +Adding NOP phi() at start of printf_scroll::@2 +Adding NOP phi() at start of memset +Adding NOP phi() at start of memcpy FINAL CONTROL FLOW GRAPH @begin: scope:[] from [0] phi() to:@1 @1: scope:[] from @begin - [1] phi() - [2] call main + [1] (byte) printf_cursor_x ← (byte) 0 + [2] (byte) printf_cursor_y ← (byte) 0 + [3] (byte*) printf_cursor_ptr ← (byte*) 1024 + to:@2 +@2: scope:[] from @1 + [4] phi() + [5] call main to:@end -@end: scope:[] from @1 - [3] phi() +@end: scope:[] from @2 + [6] phi() (void()) main() -main: scope:[main] from @1 - [4] phi() - [5] call print_str - to:main::@1 -main::@1: scope:[main] from main - [6] phi() - [7] call print_ln +main: scope:[main] from @2 + [7] phi() + [8] call printf_str to:main::@return -main::@return: scope:[main] from main::@1 - [8] return +main::@return: scope:[main] from main + [9] return to:@return -(void()) print_ln() -print_ln: scope:[print_ln] from main::@1 - [9] phi() - to:print_ln::@1 -print_ln::@1: scope:[print_ln] from print_ln print_ln::@1 - [10] (byte*) print_line_cursor#6 ← phi( print_ln/(byte*) 1024 print_ln::@1/(byte*) print_line_cursor#1 ) - [11] (byte*) print_line_cursor#1 ← (byte*) print_line_cursor#6 + (byte) $28 - [12] if((byte*) print_line_cursor#1<(byte*) print_char_cursor#12) goto print_ln::@1 - to:print_ln::@return -print_ln::@return: scope:[print_ln] from print_ln::@1 - [13] return +(void()) printf_str((byte*) printf_str::str) +printf_str: scope:[printf_str] from main + [10] phi() + to:printf_str::@1 +printf_str::@1: scope:[printf_str] from printf_str printf_str::@4 printf_str::@5 + [11] (byte*) printf_str::str#2 ← phi( printf_str/(const byte*) main::str printf_str::@4/(byte*) printf_str::str#0 printf_str::@5/(byte*) printf_str::str#0 ) + to:printf_str::@2 +printf_str::@2: scope:[printf_str] from printf_str::@1 + [12] (byte) printf_str::ch#0 ← *((byte*) printf_str::str#2) + [13] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#2 + [14] if((byte) printf_str::ch#0!=(byte) 0) goto printf_str::@3 + to:printf_str::@return +printf_str::@return: scope:[printf_str] from printf_str::@2 + [15] return + to:@return +printf_str::@3: scope:[printf_str] from printf_str::@2 + [16] if((byte) printf_str::ch#0==(byte) ' +') goto printf_str::@4 + to:printf_str::@5 +printf_str::@5: scope:[printf_str] from printf_str::@3 + [17] (byte) printf_char::ch#0 ← (byte) printf_str::ch#0 + [18] call printf_char + to:printf_str::@1 +printf_str::@4: scope:[printf_str] from printf_str::@3 + [19] phi() + [20] call printf_ln + to:printf_str::@1 + +(void()) printf_ln() +printf_ln: scope:[printf_ln] from printf_str::@4 + [21] (byte*~) printf_ln::$0 ← (byte*) printf_cursor_ptr - (byte) printf_cursor_x + [22] (byte*~) printf_ln::$1 ← (byte*~) printf_ln::$0 + (byte) $28 + [23] (byte*) printf_cursor_ptr ← (byte*~) printf_ln::$1 + [24] (byte) printf_cursor_x ← (byte) 0 + [25] (byte) printf_cursor_y ← ++ (byte) printf_cursor_y + [26] call printf_scroll + to:printf_ln::@return +printf_ln::@return: scope:[printf_ln] from printf_ln + [27] return to:@return -(void()) print_str((byte*) print_str::str) -print_str: scope:[print_str] from main - [14] phi() - to:print_str::@1 -print_str::@1: scope:[print_str] from print_str print_str::@3 - [15] (byte*) print_char_cursor#12 ← phi( print_str/(byte*) 1024 print_str::@3/(byte*) print_char_cursor#16 ) - [15] (byte*) print_str::str#2 ← phi( print_str/(const byte*) main::str print_str::@3/(byte*) print_str::str#0 ) - [16] if((byte) 0!=*((byte*) print_str::str#2)) goto print_str::@2 - to:print_str::@return -print_str::@return: scope:[print_str] from print_str::@1 - [17] return +(void()) printf_scroll() +printf_scroll: scope:[printf_scroll] from printf_char::@1 printf_ln + [28] if((byte) printf_cursor_y!=(byte) $19) goto printf_scroll::@return + to:printf_scroll::@1 +printf_scroll::@1: scope:[printf_scroll] from printf_scroll + [29] phi() + [30] call memcpy + to:printf_scroll::@2 +printf_scroll::@2: scope:[printf_scroll] from printf_scroll::@1 + [31] phi() + [32] call memset + to:printf_scroll::@3 +printf_scroll::@3: scope:[printf_scroll] from printf_scroll::@2 + [33] (byte*~) printf_scroll::$4 ← (byte*) printf_cursor_ptr - (byte) $28 + [34] (byte*) printf_cursor_ptr ← (byte*~) printf_scroll::$4 + [35] (byte) printf_cursor_y ← -- (byte) printf_cursor_y + to:printf_scroll::@return +printf_scroll::@return: scope:[printf_scroll] from printf_scroll printf_scroll::@3 + [36] return to:@return -print_str::@2: scope:[print_str] from print_str::@1 - [18] (byte) print_char::ch#0 ← *((byte*) print_str::str#2) - [19] call print_char - to:print_str::@3 -print_str::@3: scope:[print_str] from print_str::@2 - [20] (byte*) print_str::str#0 ← ++ (byte*) print_str::str#2 - to:print_str::@1 -(void()) print_char((byte) print_char::ch) -print_char: scope:[print_char] from print_str::@2 - [21] *((byte*) print_char_cursor#12) ← (byte) print_char::ch#0 - [22] (byte*) print_char_cursor#16 ← ++ (byte*) print_char_cursor#12 - to:print_char::@return -print_char::@return: scope:[print_char] from print_char - [23] return +(void*()) memset((void*) memset::str , (byte) memset::c , (word) memset::num) +memset: scope:[memset] from printf_scroll::@2 + [37] phi() + to:memset::@1 +memset::@1: scope:[memset] from memset memset::@2 + [38] (byte*) memset::dst#2 ← phi( memset/(byte*)(const void*) memset::str#0 memset::@2/(byte*) memset::dst#1 ) + [39] if((byte*) memset::dst#2!=(const byte*) memset::end#0) goto memset::@2 + to:memset::@return +memset::@return: scope:[memset] from memset::@1 + [40] return + to:@return +memset::@2: scope:[memset] from memset::@1 + [41] *((byte*) memset::dst#2) ← (const byte) memset::c#0 + [42] (byte*) memset::dst#1 ← ++ (byte*) memset::dst#2 + to:memset::@1 + +(void*()) memcpy((void*) memcpy::destination , (void*) memcpy::source , (word) memcpy::num) +memcpy: scope:[memcpy] from printf_scroll::@1 + [43] phi() + to:memcpy::@1 +memcpy::@1: scope:[memcpy] from memcpy memcpy::@2 + [44] (byte*) memcpy::dst#2 ← phi( memcpy/(byte*)(const void*) memcpy::destination#0 memcpy::@2/(byte*) memcpy::dst#1 ) + [44] (byte*) memcpy::src#2 ← phi( memcpy/(byte*)(const void*) memcpy::source#0 memcpy::@2/(byte*) memcpy::src#1 ) + [45] if((byte*) memcpy::src#2!=(const byte*) memcpy::src_end#0) goto memcpy::@2 + to:memcpy::@return +memcpy::@return: scope:[memcpy] from memcpy::@1 + [46] return + to:@return +memcpy::@2: scope:[memcpy] from memcpy::@1 + [47] *((byte*) memcpy::dst#2) ← *((byte*) memcpy::src#2) + [48] (byte*) memcpy::dst#1 ← ++ (byte*) memcpy::dst#2 + [49] (byte*) memcpy::src#1 ← ++ (byte*) memcpy::src#2 + to:memcpy::@1 + +(void()) printf_char((byte) printf_char::ch) +printf_char: scope:[printf_char] from printf_str::@5 + [50] *((byte*) printf_cursor_ptr) ← (byte) printf_char::ch#0 + [51] (byte*) printf_cursor_ptr ← ++ (byte*) printf_cursor_ptr + [52] (byte) printf_cursor_x ← ++ (byte) printf_cursor_x + [53] if((byte) printf_cursor_x!=(byte) $28) goto printf_char::@return + to:printf_char::@1 +printf_char::@1: scope:[printf_char] from printf_char + [54] (byte) printf_cursor_x ← (byte) 0 + [55] (byte) printf_cursor_y ← ++ (byte) printf_cursor_y + [56] call printf_scroll + to:printf_char::@return +printf_char::@return: scope:[printf_char] from printf_char printf_char::@1 + [57] return to:@return VARIABLE REGISTER WEIGHTS (void()) main() -(void()) print_char((byte) print_char::ch) -(byte) print_char::ch -(byte) print_char::ch#0 11002.0 -(byte*) print_char_cursor -(byte*) print_char_cursor#12 2000.363636363636 -(byte*) print_char_cursor#16 2750.5 -(byte*) print_line_cursor -(byte*) print_line_cursor#1 1501.5 -(byte*) print_line_cursor#6 2002.0 -(void()) print_ln() -(byte*) print_screen -(void()) print_str((byte*) print_str::str) -(byte*) print_str::str -(byte*) print_str::str#0 2002.0 -(byte*) print_str::str#2 1001.0 +(void*()) memcpy((void*) memcpy::destination , (void*) memcpy::source , (word) memcpy::num) +(void*) memcpy::destination +(byte*) memcpy::dst +(byte*) memcpy::dst#1 1.00000001E8 +(byte*) memcpy::dst#2 1.00000001E8 +(word) memcpy::num +(void*) memcpy::return +(void*) memcpy::source +(byte*) memcpy::src +(byte*) memcpy::src#1 2.00000002E8 +(byte*) memcpy::src#2 1.00000001E8 +(byte*) memcpy::src_end +(void*()) memset((void*) memset::str , (byte) memset::c , (word) memset::num) +(byte) memset::c +(byte*) memset::dst +(byte*) memset::dst#1 2.00000002E8 +(byte*) memset::dst#2 1.3333333466666667E8 +(byte*) memset::end +(word) memset::num +(void*) memset::return +(void*) memset::str +(byte) printf_buffer_number::sign +(void()) printf_char((byte) printf_char::ch) +(byte) printf_char::ch +(byte) printf_char::ch#0 11002.0 +(byte*) printf_cursor_ptr loadstore 7353.205882352942 +(byte) printf_cursor_x loadstore 2222.5185185185182 +(byte) printf_cursor_y loadstore 8947.605263157893 +(byte) printf_format_number::justify_left +(byte) printf_format_number::min_length +(byte) printf_format_number::radix +(byte) printf_format_number::sign_always +(byte) printf_format_number::upper_case +(byte) printf_format_number::zero_padding +(byte) printf_format_string::justify_left +(byte) printf_format_string::min_length +(void()) printf_ln() +(byte*~) printf_ln::$0 20002.0 +(byte*~) printf_ln::$1 20002.0 +(void()) printf_scroll() +(byte*~) printf_scroll::$4 200002.0 +(void()) printf_str((byte*) printf_str::str) +(byte) printf_str::ch +(byte) printf_str::ch#0 1001.0 +(byte*) printf_str::str +(byte*) printf_str::str#0 429.0 +(byte*) printf_str::str#2 2002.0 Initial phi equivalence classes -[ print_line_cursor#6 print_line_cursor#1 ] -[ print_str::str#2 print_str::str#0 ] -[ print_char_cursor#12 print_char_cursor#16 ] -Added variable print_char::ch#0 to live range equivalence class [ print_char::ch#0 ] +[ printf_str::str#2 printf_str::str#0 ] +[ memset::dst#2 memset::dst#1 ] +[ memcpy::src#2 memcpy::src#1 ] +[ memcpy::dst#2 memcpy::dst#1 ] +Added variable printf_cursor_x to live range equivalence class [ printf_cursor_x ] +Added variable printf_cursor_y to live range equivalence class [ printf_cursor_y ] +Added variable printf_cursor_ptr to live range equivalence class [ printf_cursor_ptr ] +Added variable printf_str::ch#0 to live range equivalence class [ printf_str::ch#0 ] +Added variable printf_char::ch#0 to live range equivalence class [ printf_char::ch#0 ] +Added variable printf_ln::$0 to live range equivalence class [ printf_ln::$0 ] +Added variable printf_ln::$1 to live range equivalence class [ printf_ln::$1 ] +Added variable printf_scroll::$4 to live range equivalence class [ printf_scroll::$4 ] Complete equivalence classes -[ print_line_cursor#6 print_line_cursor#1 ] -[ print_str::str#2 print_str::str#0 ] -[ print_char_cursor#12 print_char_cursor#16 ] -[ print_char::ch#0 ] -Allocated zp[2]:2 [ print_line_cursor#6 print_line_cursor#1 ] -Allocated zp[2]:4 [ print_str::str#2 print_str::str#0 ] -Allocated zp[2]:6 [ print_char_cursor#12 print_char_cursor#16 ] -Allocated zp[1]:8 [ print_char::ch#0 ] +[ printf_str::str#2 printf_str::str#0 ] +[ memset::dst#2 memset::dst#1 ] +[ memcpy::src#2 memcpy::src#1 ] +[ memcpy::dst#2 memcpy::dst#1 ] +[ printf_cursor_x ] +[ printf_cursor_y ] +[ printf_cursor_ptr ] +[ printf_str::ch#0 ] +[ printf_char::ch#0 ] +[ printf_ln::$0 ] +[ printf_ln::$1 ] +[ printf_scroll::$4 ] +Allocated zp[2]:2 [ printf_str::str#2 printf_str::str#0 ] +Allocated zp[2]:4 [ memset::dst#2 memset::dst#1 ] +Allocated zp[2]:6 [ memcpy::src#2 memcpy::src#1 ] +Allocated zp[2]:8 [ memcpy::dst#2 memcpy::dst#1 ] +Allocated zp[1]:10 [ printf_cursor_x ] +Allocated zp[1]:11 [ printf_cursor_y ] +Allocated zp[2]:12 [ printf_cursor_ptr ] +Allocated zp[1]:14 [ printf_str::ch#0 ] +Allocated zp[1]:15 [ printf_char::ch#0 ] +Allocated zp[2]:16 [ printf_ln::$0 ] +Allocated zp[2]:18 [ printf_ln::$1 ] +Allocated zp[2]:20 [ printf_scroll::$4 ] INITIAL ASM Target platform is c64basic / MOS6502X @@ -395,186 +805,427 @@ Target platform is c64basic / MOS6502X :BasicUpstart(__bbegin) .pc = $80d "Program" // Global Constants & labels - .label print_line_cursor = 2 - .label print_char_cursor = 6 + .label printf_cursor_x = $a + .label printf_cursor_y = $b + .label printf_cursor_ptr = $c // @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: + // [1] (byte) printf_cursor_x ← (byte) 0 -- vbuz1=vbuc1 + // X-position of cursor + lda #0 + sta.z printf_cursor_x + // [2] (byte) printf_cursor_y ← (byte) 0 -- vbuz1=vbuc1 + // Y-position of cursor + lda #0 + sta.z printf_cursor_y + // [3] (byte*) printf_cursor_ptr ← (byte*) 1024 -- pbuz1=pbuc1 + // Pointer to cursor address + lda #<$400 + sta.z printf_cursor_ptr + lda #>$400 + sta.z printf_cursor_ptr+1 + // [4] phi from @1 to @2 [phi:@1->@2] +__b2_from___b1: + jmp __b2 + // @2 +__b2: + // [5] call main + // [7] phi from @2 to main [phi:@2->main] +main_from___b2: jsr main - // [3] phi from @1 to @end [phi:@1->@end] -__bend_from___b1: + // [6] phi from @2 to @end [phi:@2->@end] +__bend_from___b2: jmp __bend // @end __bend: // main main: { - // [5] call print_str - // [14] phi from main to print_str [phi:main->print_str] - print_str_from_main: - jsr print_str - // [6] phi from main to main::@1 [phi:main->main::@1] - __b1_from_main: - jmp __b1 - // main::@1 - __b1: - // [7] call print_ln - // [9] phi from main::@1 to print_ln [phi:main::@1->print_ln] - print_ln_from___b1: - jsr print_ln + // [8] call printf_str + // [10] phi from main to printf_str [phi:main->printf_str] + printf_str_from_main: + jsr printf_str jmp __breturn // main::@return __breturn: - // [8] return + // [9] return rts - str: .text "hello world!" + str: .text @"hello world!\n" .byte 0 } - // print_ln -// Print a newline -print_ln: { - // [10] phi from print_ln to print_ln::@1 [phi:print_ln->print_ln::@1] - __b1_from_print_ln: - // [10] phi (byte*) print_line_cursor#6 = (byte*) 1024 [phi:print_ln->print_ln::@1#0] -- pbuz1=pbuc1 - lda #<$400 - sta.z print_line_cursor - lda #>$400 - sta.z print_line_cursor+1 - jmp __b1 - // [10] phi from print_ln::@1 to print_ln::@1 [phi:print_ln::@1->print_ln::@1] - __b1_from___b1: - // [10] phi (byte*) print_line_cursor#6 = (byte*) print_line_cursor#1 [phi:print_ln::@1->print_ln::@1#0] -- register_copy - jmp __b1 - // print_ln::@1 - __b1: - // [11] (byte*) print_line_cursor#1 ← (byte*) print_line_cursor#6 + (byte) $28 -- pbuz1=pbuz1_plus_vbuc1 - lda #$28 - clc - adc.z print_line_cursor - sta.z print_line_cursor - bcc !+ - inc.z print_line_cursor+1 - !: - // [12] if((byte*) print_line_cursor#1<(byte*) print_char_cursor#12) goto print_ln::@1 -- pbuz1_lt_pbuz2_then_la1 - lda.z print_line_cursor+1 - cmp.z print_char_cursor+1 - bcc __b1_from___b1 - bne !+ - lda.z print_line_cursor - cmp.z print_char_cursor - bcc __b1_from___b1 - !: - jmp __breturn - // print_ln::@return - __breturn: - // [13] return - rts -} - // print_str + // printf_str // Print a zero-terminated string -// print_str(byte* zp(4) str) -print_str: { - .label str = 4 - // [15] phi from print_str to print_str::@1 [phi:print_str->print_str::@1] - __b1_from_print_str: - // [15] phi (byte*) print_char_cursor#12 = (byte*) 1024 [phi:print_str->print_str::@1#0] -- pbuz1=pbuc1 - lda #<$400 - sta.z print_char_cursor - lda #>$400 - sta.z print_char_cursor+1 - // [15] phi (byte*) print_str::str#2 = (const byte*) main::str [phi:print_str->print_str::@1#1] -- pbuz1=pbuc1 +// Handles escape codes such as newline +// printf_str(byte* zp(2) str) +printf_str: { + .label ch = $e + .label str = 2 + // [11] phi from printf_str to printf_str::@1 [phi:printf_str->printf_str::@1] + __b1_from_printf_str: + // [11] phi (byte*) printf_str::str#2 = (const byte*) main::str [phi:printf_str->printf_str::@1#0] -- pbuz1=pbuc1 lda #main.str sta.z str+1 jmp __b1 - // print_str::@1 + // printf_str::@1 __b1: - // [16] if((byte) 0!=*((byte*) print_str::str#2)) goto print_str::@2 -- vbuc1_neq__deref_pbuz1_then_la1 - ldy #0 - lda (str),y - cmp #0 - bne __b2 - jmp __breturn - // print_str::@return - __breturn: - // [17] return - rts - // print_str::@2 + jmp __b2 + // printf_str::@2 __b2: - // [18] (byte) print_char::ch#0 ← *((byte*) print_str::str#2) -- vbuz1=_deref_pbuz2 + // [12] (byte) printf_str::ch#0 ← *((byte*) printf_str::str#2) -- vbuz1=_deref_pbuz2 ldy #0 lda (str),y - sta.z print_char.ch - // [19] call print_char - jsr print_char - jmp __b3 - // print_str::@3 - __b3: - // [20] (byte*) print_str::str#0 ← ++ (byte*) print_str::str#2 -- pbuz1=_inc_pbuz1 + sta.z ch + // [13] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#2 -- pbuz1=_inc_pbuz1 inc.z str bne !+ inc.z str+1 !: - // [15] phi from print_str::@3 to print_str::@1 [phi:print_str::@3->print_str::@1] - __b1_from___b3: - // [15] phi (byte*) print_char_cursor#12 = (byte*) print_char_cursor#16 [phi:print_str::@3->print_str::@1#0] -- register_copy - // [15] phi (byte*) print_str::str#2 = (byte*) print_str::str#0 [phi:print_str::@3->print_str::@1#1] -- register_copy + // [14] if((byte) printf_str::ch#0!=(byte) 0) goto printf_str::@3 -- vbuz1_neq_0_then_la1 + lda.z ch + cmp #0 + bne __b3 + jmp __breturn + // printf_str::@return + __breturn: + // [15] return + rts + // printf_str::@3 + __b3: + // [16] if((byte) printf_str::ch#0==(byte) ' ') goto printf_str::@4 -- vbuz1_eq_vbuc1_then_la1 + lda #'\n' + cmp.z ch + beq __b4_from___b3 + jmp __b5 + // printf_str::@5 + __b5: + // [17] (byte) printf_char::ch#0 ← (byte) printf_str::ch#0 -- vbuz1=vbuz2 + lda.z ch + sta.z printf_char.ch + // [18] call printf_char + jsr printf_char + // [11] phi from printf_str::@4 printf_str::@5 to printf_str::@1 [phi:printf_str::@4/printf_str::@5->printf_str::@1] + __b1_from___b4: + __b1_from___b5: + // [11] phi (byte*) printf_str::str#2 = (byte*) printf_str::str#0 [phi:printf_str::@4/printf_str::@5->printf_str::@1#0] -- register_copy + jmp __b1 + // [19] phi from printf_str::@3 to printf_str::@4 [phi:printf_str::@3->printf_str::@4] + __b4_from___b3: + jmp __b4 + // printf_str::@4 + __b4: + // [20] call printf_ln + jsr printf_ln + jmp __b1_from___b4 +} + // printf_ln +// Print a newline +printf_ln: { + .label __0 = $10 + .label __1 = $12 + // [21] (byte*~) printf_ln::$0 ← (byte*) printf_cursor_ptr - (byte) printf_cursor_x -- pbuz1=pbuz2_minus_vbuz3 + sec + lda.z printf_cursor_ptr + sbc.z printf_cursor_x + sta.z __0 + lda.z printf_cursor_ptr+1 + sbc #0 + sta.z __0+1 + // [22] (byte*~) printf_ln::$1 ← (byte*~) printf_ln::$0 + (byte) $28 -- pbuz1=pbuz2_plus_vbuc1 + lda #$28 + clc + adc.z __0 + sta.z __1 + lda #0 + adc.z __0+1 + sta.z __1+1 + // [23] (byte*) printf_cursor_ptr ← (byte*~) printf_ln::$1 -- pbuz1=pbuz2 + lda.z __1 + sta.z printf_cursor_ptr + lda.z __1+1 + sta.z printf_cursor_ptr+1 + // [24] (byte) printf_cursor_x ← (byte) 0 -- vbuz1=vbuc1 + lda #0 + sta.z printf_cursor_x + // [25] (byte) printf_cursor_y ← ++ (byte) printf_cursor_y -- vbuz1=_inc_vbuz1 + inc.z printf_cursor_y + // [26] call printf_scroll + jsr printf_scroll + jmp __breturn + // printf_ln::@return + __breturn: + // [27] return + rts +} + // printf_scroll +// Scroll the entire screen if the cursor is on the last line +printf_scroll: { + .label __4 = $14 + // [28] if((byte) printf_cursor_y!=(byte) $19) goto printf_scroll::@return -- vbuz1_neq_vbuc1_then_la1 + lda #$19 + cmp.z printf_cursor_y + bne __breturn + // [29] phi from printf_scroll to printf_scroll::@1 [phi:printf_scroll->printf_scroll::@1] + __b1_from_printf_scroll: + jmp __b1 + // printf_scroll::@1 + __b1: + // [30] call memcpy + // [43] phi from printf_scroll::@1 to memcpy [phi:printf_scroll::@1->memcpy] + memcpy_from___b1: + jsr memcpy + // [31] phi from printf_scroll::@1 to printf_scroll::@2 [phi:printf_scroll::@1->printf_scroll::@2] + __b2_from___b1: + jmp __b2 + // printf_scroll::@2 + __b2: + // [32] call memset + // [37] phi from printf_scroll::@2 to memset [phi:printf_scroll::@2->memset] + memset_from___b2: + jsr memset + jmp __b3 + // printf_scroll::@3 + __b3: + // [33] (byte*~) printf_scroll::$4 ← (byte*) printf_cursor_ptr - (byte) $28 -- pbuz1=pbuz2_minus_vwuc1 + lda.z printf_cursor_ptr + sec + sbc #<$28 + sta.z __4 + lda.z printf_cursor_ptr+1 + sbc #>$28 + sta.z __4+1 + // [34] (byte*) printf_cursor_ptr ← (byte*~) printf_scroll::$4 -- pbuz1=pbuz2 + lda.z __4 + sta.z printf_cursor_ptr + lda.z __4+1 + sta.z printf_cursor_ptr+1 + // [35] (byte) printf_cursor_y ← -- (byte) printf_cursor_y -- vbuz1=_dec_vbuz1 + dec.z printf_cursor_y + jmp __breturn + // printf_scroll::@return + __breturn: + // [36] return + rts +} + // memset +// Copies the character c (an unsigned char) to the first num characters of the object pointed to by the argument str. +memset: { + .const c = ' ' + .const num = $28 + .label str = $400+$28*$19-$28 + .label end = str+num + .label dst = 4 + // [38] phi from memset to memset::@1 [phi:memset->memset::@1] + __b1_from_memset: + // [38] phi (byte*) memset::dst#2 = (byte*)(const void*) memset::str#0 [phi:memset->memset::@1#0] -- pbuz1=pbuc1 + lda #str + sta.z dst+1 + jmp __b1 + // memset::@1 + __b1: + // [39] if((byte*) memset::dst#2!=(const byte*) memset::end#0) goto memset::@2 -- pbuz1_neq_pbuc1_then_la1 + lda.z dst+1 + cmp #>end + bne __b2 + lda.z dst + cmp #memset::@1] + __b1_from___b2: + // [38] phi (byte*) memset::dst#2 = (byte*) memset::dst#1 [phi:memset::@2->memset::@1#0] -- register_copy jmp __b1 } - // print_char + // 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: { + .const num = $28*$19-$28 + .label destination = $400 + .label source = $400+$28 + .label src_end = source+num + .label dst = 8 + .label src = 6 + // [44] phi from memcpy to memcpy::@1 [phi:memcpy->memcpy::@1] + __b1_from_memcpy: + // [44] phi (byte*) memcpy::dst#2 = (byte*)(const void*) memcpy::destination#0 [phi:memcpy->memcpy::@1#0] -- pbuz1=pbuc1 + lda #destination + sta.z dst+1 + // [44] phi (byte*) memcpy::src#2 = (byte*)(const void*) memcpy::source#0 [phi:memcpy->memcpy::@1#1] -- pbuz1=pbuc1 + lda #source + sta.z src+1 + jmp __b1 + // memcpy::@1 + __b1: + // [45] if((byte*) memcpy::src#2!=(const byte*) memcpy::src_end#0) goto memcpy::@2 -- pbuz1_neq_pbuc1_then_la1 + lda.z src+1 + cmp #>src_end + bne __b2 + lda.z src + cmp #memcpy::@1] + __b1_from___b2: + // [44] phi (byte*) memcpy::dst#2 = (byte*) memcpy::dst#1 [phi:memcpy::@2->memcpy::@1#0] -- register_copy + // [44] phi (byte*) memcpy::src#2 = (byte*) memcpy::src#1 [phi:memcpy::@2->memcpy::@1#1] -- register_copy + jmp __b1 +} + // printf_char // Print a single char -// print_char(byte zp(8) ch) -print_char: { - .label ch = 8 - // [21] *((byte*) print_char_cursor#12) ← (byte) print_char::ch#0 -- _deref_pbuz1=vbuz2 +// If the end of the screen is reached scroll it up one char and place the cursor at the +// printf_char(byte zp($f) ch) +printf_char: { + .label ch = $f + // [50] *((byte*) printf_cursor_ptr) ← (byte) printf_char::ch#0 -- _deref_pbuz1=vbuz2 lda.z ch ldy #0 - sta (print_char_cursor),y - // [22] (byte*) print_char_cursor#16 ← ++ (byte*) print_char_cursor#12 -- pbuz1=_inc_pbuz1 - inc.z print_char_cursor + sta (printf_cursor_ptr),y + // [51] (byte*) printf_cursor_ptr ← ++ (byte*) printf_cursor_ptr -- pbuz1=_inc_pbuz1 + inc.z printf_cursor_ptr bne !+ - inc.z print_char_cursor+1 + inc.z printf_cursor_ptr+1 !: + // [52] (byte) printf_cursor_x ← ++ (byte) printf_cursor_x -- vbuz1=_inc_vbuz1 + inc.z printf_cursor_x + // [53] if((byte) printf_cursor_x!=(byte) $28) goto printf_char::@return -- vbuz1_neq_vbuc1_then_la1 + lda #$28 + cmp.z printf_cursor_x + bne __breturn + jmp __b1 + // printf_char::@1 + __b1: + // [54] (byte) printf_cursor_x ← (byte) 0 -- vbuz1=vbuc1 + lda #0 + sta.z printf_cursor_x + // [55] (byte) printf_cursor_y ← ++ (byte) printf_cursor_y -- vbuz1=_inc_vbuz1 + inc.z printf_cursor_y + // [56] call printf_scroll + jsr printf_scroll jmp __breturn - // print_char::@return + // printf_char::@return __breturn: - // [23] return + // [57] return rts } // File Data REGISTER UPLIFT POTENTIAL REGISTERS -Statement [11] (byte*) print_line_cursor#1 ← (byte*) print_line_cursor#6 + (byte) $28 [ print_line_cursor#1 print_char_cursor#12 ] ( main:2::print_ln:7 [ print_line_cursor#1 print_char_cursor#12 ] { } ) always clobbers reg byte a -Statement [12] if((byte*) print_line_cursor#1<(byte*) print_char_cursor#12) goto print_ln::@1 [ print_line_cursor#1 print_char_cursor#12 ] ( main:2::print_ln:7 [ print_line_cursor#1 print_char_cursor#12 ] { } ) always clobbers reg byte a -Statement [16] if((byte) 0!=*((byte*) print_str::str#2)) goto print_str::@2 [ print_char_cursor#12 print_str::str#2 ] ( main:2::print_str:5 [ print_char_cursor#12 print_str::str#2 ] { } ) always clobbers reg byte a reg byte y -Statement [18] (byte) print_char::ch#0 ← *((byte*) print_str::str#2) [ print_char_cursor#12 print_str::str#2 print_char::ch#0 ] ( main:2::print_str:5 [ print_char_cursor#12 print_str::str#2 print_char::ch#0 ] { } ) always clobbers reg byte a reg byte y -Statement [21] *((byte*) print_char_cursor#12) ← (byte) print_char::ch#0 [ print_char_cursor#12 ] ( main:2::print_str:5::print_char:19 [ print_str::str#2 print_char_cursor#12 ] { } ) always clobbers reg byte y -Potential registers zp[2]:2 [ print_line_cursor#6 print_line_cursor#1 ] : zp[2]:2 , -Potential registers zp[2]:4 [ print_str::str#2 print_str::str#0 ] : zp[2]:4 , -Potential registers zp[2]:6 [ print_char_cursor#12 print_char_cursor#16 ] : zp[2]:6 , -Potential registers zp[1]:8 [ print_char::ch#0 ] : zp[1]:8 , reg byte a , reg byte x , reg byte y , +Statement [1] (byte) printf_cursor_x ← (byte) 0 [ printf_cursor_x ] ( [ printf_cursor_x ] { } ) always clobbers reg byte a +Statement [2] (byte) printf_cursor_y ← (byte) 0 [ printf_cursor_x printf_cursor_y ] ( [ printf_cursor_x printf_cursor_y ] { } ) always clobbers reg byte a +Statement [3] (byte*) printf_cursor_ptr ← (byte*) 1024 [ printf_cursor_x printf_cursor_y printf_cursor_ptr ] ( [ printf_cursor_x printf_cursor_y printf_cursor_ptr ] { } ) always clobbers reg byte a +Statement [12] (byte) printf_str::ch#0 ← *((byte*) printf_str::str#2) [ printf_cursor_x printf_cursor_y printf_cursor_ptr printf_str::str#2 printf_str::ch#0 ] ( main:5::printf_str:8 [ printf_cursor_x printf_cursor_y printf_cursor_ptr printf_str::str#2 printf_str::ch#0 ] { } ) always clobbers reg byte a reg byte y +Statement [21] (byte*~) printf_ln::$0 ← (byte*) printf_cursor_ptr - (byte) printf_cursor_x [ printf_cursor_y printf_ln::$0 ] ( main:5::printf_str:8::printf_ln:20 [ printf_str::str#0 printf_cursor_y printf_ln::$0 ] { } ) always clobbers reg byte a +Statement [22] (byte*~) printf_ln::$1 ← (byte*~) printf_ln::$0 + (byte) $28 [ printf_cursor_y printf_ln::$1 ] ( main:5::printf_str:8::printf_ln:20 [ printf_str::str#0 printf_cursor_y printf_ln::$1 ] { } ) always clobbers reg byte a +Statement [23] (byte*) printf_cursor_ptr ← (byte*~) printf_ln::$1 [ printf_cursor_y printf_cursor_ptr ] ( main:5::printf_str:8::printf_ln:20 [ printf_str::str#0 printf_cursor_y printf_cursor_ptr ] { } ) always clobbers reg byte a +Statement [24] (byte) printf_cursor_x ← (byte) 0 [ printf_cursor_x printf_cursor_y printf_cursor_ptr ] ( main:5::printf_str:8::printf_ln:20 [ printf_str::str#0 printf_cursor_x printf_cursor_y printf_cursor_ptr ] { } ) always clobbers reg byte a +Statement [28] if((byte) printf_cursor_y!=(byte) $19) goto printf_scroll::@return [ printf_cursor_y printf_cursor_ptr ] ( main:5::printf_str:8::printf_ln:20::printf_scroll:26 [ printf_str::str#0 printf_cursor_x printf_cursor_y printf_cursor_ptr ] { } main:5::printf_str:8::printf_char:18::printf_scroll:56 [ printf_str::str#0 printf_cursor_x printf_cursor_y printf_cursor_ptr ] { { printf_char::ch#0 = printf_str::ch#0 } } ) always clobbers reg byte a +Statement [33] (byte*~) printf_scroll::$4 ← (byte*) printf_cursor_ptr - (byte) $28 [ printf_cursor_y printf_scroll::$4 ] ( main:5::printf_str:8::printf_ln:20::printf_scroll:26 [ printf_str::str#0 printf_cursor_x printf_cursor_y printf_scroll::$4 ] { } main:5::printf_str:8::printf_char:18::printf_scroll:56 [ printf_str::str#0 printf_cursor_x printf_cursor_y printf_scroll::$4 ] { { printf_char::ch#0 = printf_str::ch#0 } } ) always clobbers reg byte a +Statement [34] (byte*) printf_cursor_ptr ← (byte*~) printf_scroll::$4 [ printf_cursor_y printf_cursor_ptr ] ( main:5::printf_str:8::printf_ln:20::printf_scroll:26 [ printf_str::str#0 printf_cursor_x printf_cursor_y printf_cursor_ptr ] { } main:5::printf_str:8::printf_char:18::printf_scroll:56 [ printf_str::str#0 printf_cursor_x printf_cursor_y printf_cursor_ptr ] { { printf_char::ch#0 = printf_str::ch#0 } } ) always clobbers reg byte a +Statement [39] if((byte*) memset::dst#2!=(const byte*) memset::end#0) goto memset::@2 [ memset::dst#2 ] ( main:5::printf_str:8::printf_ln:20::printf_scroll:26::memset:32 [ printf_str::str#0 printf_cursor_x printf_cursor_y printf_cursor_ptr memset::dst#2 ] { } main:5::printf_str:8::printf_char:18::printf_scroll:56::memset:32 [ printf_str::str#0 printf_cursor_x printf_cursor_y printf_cursor_ptr memset::dst#2 ] { { printf_char::ch#0 = printf_str::ch#0 } } ) always clobbers reg byte a +Statement [41] *((byte*) memset::dst#2) ← (const byte) memset::c#0 [ memset::dst#2 ] ( main:5::printf_str:8::printf_ln:20::printf_scroll:26::memset:32 [ printf_str::str#0 printf_cursor_x printf_cursor_y printf_cursor_ptr memset::dst#2 ] { } main:5::printf_str:8::printf_char:18::printf_scroll:56::memset:32 [ printf_str::str#0 printf_cursor_x printf_cursor_y printf_cursor_ptr memset::dst#2 ] { { printf_char::ch#0 = printf_str::ch#0 } } ) always clobbers reg byte a reg byte y +Statement [45] if((byte*) memcpy::src#2!=(const byte*) memcpy::src_end#0) goto memcpy::@2 [ memcpy::src#2 memcpy::dst#2 ] ( main:5::printf_str:8::printf_ln:20::printf_scroll:26::memcpy:30 [ printf_str::str#0 printf_cursor_x printf_cursor_y printf_cursor_ptr memcpy::src#2 memcpy::dst#2 ] { } main:5::printf_str:8::printf_char:18::printf_scroll:56::memcpy:30 [ printf_str::str#0 printf_cursor_x printf_cursor_y printf_cursor_ptr memcpy::src#2 memcpy::dst#2 ] { { printf_char::ch#0 = printf_str::ch#0 } } ) always clobbers reg byte a +Statement [47] *((byte*) memcpy::dst#2) ← *((byte*) memcpy::src#2) [ memcpy::src#2 memcpy::dst#2 ] ( main:5::printf_str:8::printf_ln:20::printf_scroll:26::memcpy:30 [ printf_str::str#0 printf_cursor_x printf_cursor_y printf_cursor_ptr memcpy::src#2 memcpy::dst#2 ] { } main:5::printf_str:8::printf_char:18::printf_scroll:56::memcpy:30 [ printf_str::str#0 printf_cursor_x printf_cursor_y printf_cursor_ptr memcpy::src#2 memcpy::dst#2 ] { { printf_char::ch#0 = printf_str::ch#0 } } ) always clobbers reg byte a reg byte y +Statement [50] *((byte*) printf_cursor_ptr) ← (byte) printf_char::ch#0 [ printf_cursor_x printf_cursor_y printf_cursor_ptr ] ( main:5::printf_str:8::printf_char:18 [ printf_str::str#0 printf_cursor_x printf_cursor_y printf_cursor_ptr ] { { printf_char::ch#0 = printf_str::ch#0 } } ) always clobbers reg byte y +Statement [53] if((byte) printf_cursor_x!=(byte) $28) goto printf_char::@return [ printf_cursor_x printf_cursor_y printf_cursor_ptr ] ( main:5::printf_str:8::printf_char:18 [ printf_str::str#0 printf_cursor_x printf_cursor_y printf_cursor_ptr ] { { printf_char::ch#0 = printf_str::ch#0 } } ) always clobbers reg byte a +Statement [54] (byte) printf_cursor_x ← (byte) 0 [ printf_cursor_x printf_cursor_y printf_cursor_ptr ] ( main:5::printf_str:8::printf_char:18 [ printf_str::str#0 printf_cursor_x printf_cursor_y printf_cursor_ptr ] { { printf_char::ch#0 = printf_str::ch#0 } } ) always clobbers reg byte a +Potential registers zp[2]:2 [ printf_str::str#2 printf_str::str#0 ] : zp[2]:2 , +Potential registers zp[2]:4 [ memset::dst#2 memset::dst#1 ] : zp[2]:4 , +Potential registers zp[2]:6 [ memcpy::src#2 memcpy::src#1 ] : zp[2]:6 , +Potential registers zp[2]:8 [ memcpy::dst#2 memcpy::dst#1 ] : zp[2]:8 , +Potential registers zp[1]:10 [ printf_cursor_x ] : zp[1]:10 , +Potential registers zp[1]:11 [ printf_cursor_y ] : zp[1]:11 , +Potential registers zp[2]:12 [ printf_cursor_ptr ] : zp[2]:12 , +Potential registers zp[1]:14 [ printf_str::ch#0 ] : zp[1]:14 , reg byte a , reg byte x , reg byte y , +Potential registers zp[1]:15 [ printf_char::ch#0 ] : zp[1]:15 , reg byte a , reg byte x , reg byte y , +Potential registers zp[2]:16 [ printf_ln::$0 ] : zp[2]:16 , +Potential registers zp[2]:18 [ printf_ln::$1 ] : zp[2]:18 , +Potential registers zp[2]:20 [ printf_scroll::$4 ] : zp[2]:20 , REGISTER UPLIFT SCOPES -Uplift Scope [print_char] 11,002: zp[1]:8 [ print_char::ch#0 ] -Uplift Scope [] 4,750.86: zp[2]:6 [ print_char_cursor#12 print_char_cursor#16 ] 3,503.5: zp[2]:2 [ print_line_cursor#6 print_line_cursor#1 ] -Uplift Scope [print_str] 3,003: zp[2]:4 [ print_str::str#2 print_str::str#0 ] +Uplift Scope [memcpy] 300,000,003: zp[2]:6 [ memcpy::src#2 memcpy::src#1 ] 200,000,002: zp[2]:8 [ memcpy::dst#2 memcpy::dst#1 ] +Uplift Scope [memset] 333,333,336.67: zp[2]:4 [ memset::dst#2 memset::dst#1 ] +Uplift Scope [printf_scroll] 200,002: zp[2]:20 [ printf_scroll::$4 ] +Uplift Scope [printf_ln] 20,002: zp[2]:16 [ printf_ln::$0 ] 20,002: zp[2]:18 [ printf_ln::$1 ] +Uplift Scope [] 8,947.61: zp[1]:11 [ printf_cursor_y ] 7,353.21: zp[2]:12 [ printf_cursor_ptr ] 2,222.52: zp[1]:10 [ printf_cursor_x ] +Uplift Scope [printf_char] 11,002: zp[1]:15 [ printf_char::ch#0 ] +Uplift Scope [printf_str] 2,431: zp[2]:2 [ printf_str::str#2 printf_str::str#0 ] 1,001: zp[1]:14 [ printf_str::ch#0 ] Uplift Scope [RADIX] -Uplift Scope [print_ln] +Uplift Scope [printf_format_number] +Uplift Scope [printf_buffer_number] +Uplift Scope [printf_format_string] Uplift Scope [main] -Uplifting [print_char] best 1337 combination reg byte a [ print_char::ch#0 ] -Uplifting [] best 1337 combination zp[2]:6 [ print_char_cursor#12 print_char_cursor#16 ] zp[2]:2 [ print_line_cursor#6 print_line_cursor#1 ] -Uplifting [print_str] best 1337 combination zp[2]:4 [ print_str::str#2 print_str::str#0 ] -Uplifting [RADIX] best 1337 combination -Uplifting [print_ln] best 1337 combination -Uplifting [main] best 1337 combination +Uplifting [memcpy] best 15274 combination zp[2]:6 [ memcpy::src#2 memcpy::src#1 ] zp[2]:8 [ memcpy::dst#2 memcpy::dst#1 ] +Uplifting [memset] best 15274 combination zp[2]:4 [ memset::dst#2 memset::dst#1 ] +Uplifting [printf_scroll] best 15274 combination zp[2]:20 [ printf_scroll::$4 ] +Uplifting [printf_ln] best 15274 combination zp[2]:16 [ printf_ln::$0 ] zp[2]:18 [ printf_ln::$1 ] +Uplifting [] best 15274 combination zp[1]:11 [ printf_cursor_y ] zp[2]:12 [ printf_cursor_ptr ] zp[1]:10 [ printf_cursor_x ] +Uplifting [printf_char] best 15241 combination reg byte a [ printf_char::ch#0 ] +Uplifting [printf_str] best 15121 combination zp[2]:2 [ printf_str::str#2 printf_str::str#0 ] reg byte a [ printf_str::ch#0 ] +Uplifting [RADIX] best 15121 combination +Uplifting [printf_format_number] best 15121 combination +Uplifting [printf_buffer_number] best 15121 combination +Uplifting [printf_format_string] best 15121 combination +Uplifting [main] best 15121 combination +Attempting to uplift remaining variables inzp[1]:11 [ printf_cursor_y ] +Uplifting [] best 15121 combination zp[1]:11 [ printf_cursor_y ] +Attempting to uplift remaining variables inzp[1]:10 [ printf_cursor_x ] +Uplifting [] best 15121 combination zp[1]:10 [ printf_cursor_x ] +Coalescing zero page register [ zp[2]:12 [ printf_cursor_ptr ] ] with [ zp[2]:20 [ printf_scroll::$4 ] ] - score: 2 +Coalescing zero page register [ zp[2]:12 [ printf_cursor_ptr printf_scroll::$4 ] ] with [ zp[2]:16 [ printf_ln::$0 ] ] - score: 1 +Coalescing zero page register [ zp[2]:12 [ printf_cursor_ptr printf_scroll::$4 printf_ln::$0 ] ] with [ zp[2]:18 [ printf_ln::$1 ] ] - score: 1 +Coalescing zero page register [ zp[2]:6 [ memcpy::src#2 memcpy::src#1 ] ] with [ zp[2]:4 [ memset::dst#2 memset::dst#1 ] ] +Allocated (was zp[2]:6) zp[2]:4 [ memcpy::src#2 memcpy::src#1 memset::dst#2 memset::dst#1 ] +Allocated (was zp[2]:8) zp[2]:6 [ memcpy::dst#2 memcpy::dst#1 ] +Allocated (was zp[1]:10) zp[1]:8 [ printf_cursor_x ] +Allocated (was zp[1]:11) zp[1]:9 [ printf_cursor_y ] +Allocated (was zp[2]:12) zp[2]:10 [ printf_cursor_ptr printf_scroll::$4 printf_ln::$0 printf_ln::$1 ] ASSEMBLER BEFORE OPTIMIZATION // File Comments @@ -583,202 +1234,411 @@ ASSEMBLER BEFORE OPTIMIZATION :BasicUpstart(__bbegin) .pc = $80d "Program" // Global Constants & labels - .label print_line_cursor = 2 - .label print_char_cursor = 6 + .label printf_cursor_x = 8 + .label printf_cursor_y = 9 + .label printf_cursor_ptr = $a // @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: + // [1] (byte) printf_cursor_x ← (byte) 0 -- vbuz1=vbuc1 + // X-position of cursor + lda #0 + sta.z printf_cursor_x + // [2] (byte) printf_cursor_y ← (byte) 0 -- vbuz1=vbuc1 + // Y-position of cursor + lda #0 + sta.z printf_cursor_y + // [3] (byte*) printf_cursor_ptr ← (byte*) 1024 -- pbuz1=pbuc1 + // Pointer to cursor address + lda #<$400 + sta.z printf_cursor_ptr + lda #>$400 + sta.z printf_cursor_ptr+1 + // [4] phi from @1 to @2 [phi:@1->@2] +__b2_from___b1: + jmp __b2 + // @2 +__b2: + // [5] call main + // [7] phi from @2 to main [phi:@2->main] +main_from___b2: jsr main - // [3] phi from @1 to @end [phi:@1->@end] -__bend_from___b1: + // [6] phi from @2 to @end [phi:@2->@end] +__bend_from___b2: jmp __bend // @end __bend: // main main: { - // [5] call print_str - // [14] phi from main to print_str [phi:main->print_str] - print_str_from_main: - jsr print_str - // [6] phi from main to main::@1 [phi:main->main::@1] - __b1_from_main: - jmp __b1 - // main::@1 - __b1: - // [7] call print_ln - // [9] phi from main::@1 to print_ln [phi:main::@1->print_ln] - print_ln_from___b1: - jsr print_ln + // [8] call printf_str + // [10] phi from main to printf_str [phi:main->printf_str] + printf_str_from_main: + jsr printf_str jmp __breturn // main::@return __breturn: - // [8] return + // [9] return rts - str: .text "hello world!" + str: .text @"hello world!\n" .byte 0 } - // print_ln -// Print a newline -print_ln: { - // [10] phi from print_ln to print_ln::@1 [phi:print_ln->print_ln::@1] - __b1_from_print_ln: - // [10] phi (byte*) print_line_cursor#6 = (byte*) 1024 [phi:print_ln->print_ln::@1#0] -- pbuz1=pbuc1 - lda #<$400 - sta.z print_line_cursor - lda #>$400 - sta.z print_line_cursor+1 - jmp __b1 - // [10] phi from print_ln::@1 to print_ln::@1 [phi:print_ln::@1->print_ln::@1] - __b1_from___b1: - // [10] phi (byte*) print_line_cursor#6 = (byte*) print_line_cursor#1 [phi:print_ln::@1->print_ln::@1#0] -- register_copy - jmp __b1 - // print_ln::@1 - __b1: - // [11] (byte*) print_line_cursor#1 ← (byte*) print_line_cursor#6 + (byte) $28 -- pbuz1=pbuz1_plus_vbuc1 - lda #$28 - clc - adc.z print_line_cursor - sta.z print_line_cursor - bcc !+ - inc.z print_line_cursor+1 - !: - // [12] if((byte*) print_line_cursor#1<(byte*) print_char_cursor#12) goto print_ln::@1 -- pbuz1_lt_pbuz2_then_la1 - lda.z print_line_cursor+1 - cmp.z print_char_cursor+1 - bcc __b1_from___b1 - bne !+ - lda.z print_line_cursor - cmp.z print_char_cursor - bcc __b1_from___b1 - !: - jmp __breturn - // print_ln::@return - __breturn: - // [13] return - rts -} - // print_str + // printf_str // Print a zero-terminated string -// print_str(byte* zp(4) str) -print_str: { - .label str = 4 - // [15] phi from print_str to print_str::@1 [phi:print_str->print_str::@1] - __b1_from_print_str: - // [15] phi (byte*) print_char_cursor#12 = (byte*) 1024 [phi:print_str->print_str::@1#0] -- pbuz1=pbuc1 - lda #<$400 - sta.z print_char_cursor - lda #>$400 - sta.z print_char_cursor+1 - // [15] phi (byte*) print_str::str#2 = (const byte*) main::str [phi:print_str->print_str::@1#1] -- pbuz1=pbuc1 +// Handles escape codes such as newline +// printf_str(byte* zp(2) str) +printf_str: { + .label str = 2 + // [11] phi from printf_str to printf_str::@1 [phi:printf_str->printf_str::@1] + __b1_from_printf_str: + // [11] phi (byte*) printf_str::str#2 = (const byte*) main::str [phi:printf_str->printf_str::@1#0] -- pbuz1=pbuc1 lda #main.str sta.z str+1 jmp __b1 - // print_str::@1 + // printf_str::@1 __b1: - // [16] if((byte) 0!=*((byte*) print_str::str#2)) goto print_str::@2 -- vbuc1_neq__deref_pbuz1_then_la1 - ldy #0 - lda (str),y - cmp #0 - bne __b2 - jmp __breturn - // print_str::@return - __breturn: - // [17] return - rts - // print_str::@2 + jmp __b2 + // printf_str::@2 __b2: - // [18] (byte) print_char::ch#0 ← *((byte*) print_str::str#2) -- vbuaa=_deref_pbuz1 + // [12] (byte) printf_str::ch#0 ← *((byte*) printf_str::str#2) -- vbuaa=_deref_pbuz1 ldy #0 lda (str),y - // [19] call print_char - jsr print_char - jmp __b3 - // print_str::@3 - __b3: - // [20] (byte*) print_str::str#0 ← ++ (byte*) print_str::str#2 -- pbuz1=_inc_pbuz1 + // [13] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#2 -- pbuz1=_inc_pbuz1 inc.z str bne !+ inc.z str+1 !: - // [15] phi from print_str::@3 to print_str::@1 [phi:print_str::@3->print_str::@1] - __b1_from___b3: - // [15] phi (byte*) print_char_cursor#12 = (byte*) print_char_cursor#16 [phi:print_str::@3->print_str::@1#0] -- register_copy - // [15] phi (byte*) print_str::str#2 = (byte*) print_str::str#0 [phi:print_str::@3->print_str::@1#1] -- register_copy + // [14] if((byte) printf_str::ch#0!=(byte) 0) goto printf_str::@3 -- vbuaa_neq_0_then_la1 + cmp #0 + bne __b3 + jmp __breturn + // printf_str::@return + __breturn: + // [15] return + rts + // printf_str::@3 + __b3: + // [16] if((byte) printf_str::ch#0==(byte) ' ') goto printf_str::@4 -- vbuaa_eq_vbuc1_then_la1 + cmp #'\n' + beq __b4_from___b3 + jmp __b5 + // printf_str::@5 + __b5: + // [17] (byte) printf_char::ch#0 ← (byte) printf_str::ch#0 + // [18] call printf_char + jsr printf_char + // [11] phi from printf_str::@4 printf_str::@5 to printf_str::@1 [phi:printf_str::@4/printf_str::@5->printf_str::@1] + __b1_from___b4: + __b1_from___b5: + // [11] phi (byte*) printf_str::str#2 = (byte*) printf_str::str#0 [phi:printf_str::@4/printf_str::@5->printf_str::@1#0] -- register_copy + jmp __b1 + // [19] phi from printf_str::@3 to printf_str::@4 [phi:printf_str::@3->printf_str::@4] + __b4_from___b3: + jmp __b4 + // printf_str::@4 + __b4: + // [20] call printf_ln + jsr printf_ln + jmp __b1_from___b4 +} + // printf_ln +// Print a newline +printf_ln: { + .label __0 = $a + .label __1 = $a + // [21] (byte*~) printf_ln::$0 ← (byte*) printf_cursor_ptr - (byte) printf_cursor_x -- pbuz1=pbuz1_minus_vbuz2 + sec + lda.z __0 + sbc.z printf_cursor_x + sta.z __0 + bcs !+ + dec.z __0+1 + !: + // [22] (byte*~) printf_ln::$1 ← (byte*~) printf_ln::$0 + (byte) $28 -- pbuz1=pbuz1_plus_vbuc1 + lda #$28 + clc + adc.z __1 + sta.z __1 + bcc !+ + inc.z __1+1 + !: + // [23] (byte*) printf_cursor_ptr ← (byte*~) printf_ln::$1 + // [24] (byte) printf_cursor_x ← (byte) 0 -- vbuz1=vbuc1 + lda #0 + sta.z printf_cursor_x + // [25] (byte) printf_cursor_y ← ++ (byte) printf_cursor_y -- vbuz1=_inc_vbuz1 + inc.z printf_cursor_y + // [26] call printf_scroll + jsr printf_scroll + jmp __breturn + // printf_ln::@return + __breturn: + // [27] return + rts +} + // printf_scroll +// Scroll the entire screen if the cursor is on the last line +printf_scroll: { + .label __4 = $a + // [28] if((byte) printf_cursor_y!=(byte) $19) goto printf_scroll::@return -- vbuz1_neq_vbuc1_then_la1 + lda #$19 + cmp.z printf_cursor_y + bne __breturn + // [29] phi from printf_scroll to printf_scroll::@1 [phi:printf_scroll->printf_scroll::@1] + __b1_from_printf_scroll: + jmp __b1 + // printf_scroll::@1 + __b1: + // [30] call memcpy + // [43] phi from printf_scroll::@1 to memcpy [phi:printf_scroll::@1->memcpy] + memcpy_from___b1: + jsr memcpy + // [31] phi from printf_scroll::@1 to printf_scroll::@2 [phi:printf_scroll::@1->printf_scroll::@2] + __b2_from___b1: + jmp __b2 + // printf_scroll::@2 + __b2: + // [32] call memset + // [37] phi from printf_scroll::@2 to memset [phi:printf_scroll::@2->memset] + memset_from___b2: + jsr memset + jmp __b3 + // printf_scroll::@3 + __b3: + // [33] (byte*~) printf_scroll::$4 ← (byte*) printf_cursor_ptr - (byte) $28 -- pbuz1=pbuz1_minus_vwuc1 + lda.z __4 + sec + sbc #<$28 + sta.z __4 + lda.z __4+1 + sbc #>$28 + sta.z __4+1 + // [34] (byte*) printf_cursor_ptr ← (byte*~) printf_scroll::$4 + // [35] (byte) printf_cursor_y ← -- (byte) printf_cursor_y -- vbuz1=_dec_vbuz1 + dec.z printf_cursor_y + jmp __breturn + // printf_scroll::@return + __breturn: + // [36] return + rts +} + // memset +// Copies the character c (an unsigned char) to the first num characters of the object pointed to by the argument str. +memset: { + .const c = ' ' + .const num = $28 + .label str = $400+$28*$19-$28 + .label end = str+num + .label dst = 4 + // [38] phi from memset to memset::@1 [phi:memset->memset::@1] + __b1_from_memset: + // [38] phi (byte*) memset::dst#2 = (byte*)(const void*) memset::str#0 [phi:memset->memset::@1#0] -- pbuz1=pbuc1 + lda #str + sta.z dst+1 + jmp __b1 + // memset::@1 + __b1: + // [39] if((byte*) memset::dst#2!=(const byte*) memset::end#0) goto memset::@2 -- pbuz1_neq_pbuc1_then_la1 + lda.z dst+1 + cmp #>end + bne __b2 + lda.z dst + cmp #memset::@1] + __b1_from___b2: + // [38] phi (byte*) memset::dst#2 = (byte*) memset::dst#1 [phi:memset::@2->memset::@1#0] -- register_copy jmp __b1 } - // print_char -// Print a single char -// print_char(byte register(A) ch) -print_char: { - // [21] *((byte*) print_char_cursor#12) ← (byte) print_char::ch#0 -- _deref_pbuz1=vbuaa - ldy #0 - sta (print_char_cursor),y - // [22] (byte*) print_char_cursor#16 ← ++ (byte*) print_char_cursor#12 -- pbuz1=_inc_pbuz1 - inc.z print_char_cursor - bne !+ - inc.z print_char_cursor+1 - !: + // 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: { + .const num = $28*$19-$28 + .label destination = $400 + .label source = $400+$28 + .label src_end = source+num + .label dst = 6 + .label src = 4 + // [44] phi from memcpy to memcpy::@1 [phi:memcpy->memcpy::@1] + __b1_from_memcpy: + // [44] phi (byte*) memcpy::dst#2 = (byte*)(const void*) memcpy::destination#0 [phi:memcpy->memcpy::@1#0] -- pbuz1=pbuc1 + lda #destination + sta.z dst+1 + // [44] phi (byte*) memcpy::src#2 = (byte*)(const void*) memcpy::source#0 [phi:memcpy->memcpy::@1#1] -- pbuz1=pbuc1 + lda #source + sta.z src+1 + jmp __b1 + // memcpy::@1 + __b1: + // [45] if((byte*) memcpy::src#2!=(const byte*) memcpy::src_end#0) goto memcpy::@2 -- pbuz1_neq_pbuc1_then_la1 + lda.z src+1 + cmp #>src_end + bne __b2 + lda.z src + cmp #memcpy::@1] + __b1_from___b2: + // [44] phi (byte*) memcpy::dst#2 = (byte*) memcpy::dst#1 [phi:memcpy::@2->memcpy::@1#0] -- register_copy + // [44] phi (byte*) memcpy::src#2 = (byte*) memcpy::src#1 [phi:memcpy::@2->memcpy::@1#1] -- register_copy + jmp __b1 +} + // printf_char +// Print a single char +// If the end of the screen is reached scroll it up one char and place the cursor at the +// printf_char(byte register(A) ch) +printf_char: { + // [50] *((byte*) printf_cursor_ptr) ← (byte) printf_char::ch#0 -- _deref_pbuz1=vbuaa + ldy #0 + sta (printf_cursor_ptr),y + // [51] (byte*) printf_cursor_ptr ← ++ (byte*) printf_cursor_ptr -- pbuz1=_inc_pbuz1 + inc.z printf_cursor_ptr + bne !+ + inc.z printf_cursor_ptr+1 + !: + // [52] (byte) printf_cursor_x ← ++ (byte) printf_cursor_x -- vbuz1=_inc_vbuz1 + inc.z printf_cursor_x + // [53] if((byte) printf_cursor_x!=(byte) $28) goto printf_char::@return -- vbuz1_neq_vbuc1_then_la1 + lda #$28 + cmp.z printf_cursor_x + bne __breturn + jmp __b1 + // printf_char::@1 + __b1: + // [54] (byte) printf_cursor_x ← (byte) 0 -- vbuz1=vbuc1 + lda #0 + sta.z printf_cursor_x + // [55] (byte) printf_cursor_y ← ++ (byte) printf_cursor_y -- vbuz1=_inc_vbuz1 + inc.z printf_cursor_y + // [56] call printf_scroll + jsr printf_scroll + jmp __breturn + // printf_char::@return + __breturn: + // [57] return rts } // File Data ASSEMBLER OPTIMIZATIONS Removing instruction jmp __b1 +Removing instruction jmp __b2 Removing instruction jmp __bend -Removing instruction jmp __b1 Removing instruction jmp __breturn Removing instruction jmp __b1 +Removing instruction jmp __b2 +Removing instruction jmp __breturn +Removing instruction jmp __b5 +Removing instruction jmp __b4 Removing instruction jmp __breturn Removing instruction jmp __b1 -Removing instruction jmp __breturn +Removing instruction jmp __b2 Removing instruction jmp __b3 Removing instruction jmp __breturn -Succesful ASM optimization Pass5NextJumpElimination -Replacing label __b1_from___b1 with __b1 -Replacing label __b1_from___b1 with __b1 -Removing instruction __b1_from___bbegin: -Removing instruction __b1: -Removing instruction main_from___b1: -Removing instruction __bend_from___b1: -Removing instruction __b1_from_main: -Removing instruction print_ln_from___b1: -Removing instruction __b1_from___b1: -Succesful ASM optimization Pass5RedundantLabelElimination -Removing instruction __bend: -Removing instruction print_str_from_main: -Removing instruction __b1: -Removing instruction __breturn: -Removing instruction __b1_from_print_ln: -Removing instruction __breturn: -Removing instruction __b1_from_print_str: -Removing instruction __breturn: -Removing instruction __b3: -Removing instruction __b1_from___b3: -Removing instruction __breturn: -Succesful ASM optimization Pass5UnusedLabelElimination -Updating BasicUpstart to call main directly -Removing instruction jsr main -Succesful ASM optimization Pass5SkipBegin Removing instruction jmp __b1 +Removing instruction jmp __breturn +Removing instruction jmp __b1 +Removing instruction jmp __breturn +Removing instruction jmp __b1 +Removing instruction jmp __breturn Succesful ASM optimization Pass5NextJumpElimination -Removing instruction __bbegin: +Removing instruction lda #0 +Removing instruction ldy #0 +Succesful ASM optimization Pass5UnnecesaryLoadElimination +Replacing label __b4_from___b3 with __b4 +Replacing label __b1 with __b2 +Replacing label __b1_from___b4 with __b1_from___b5 +Removing instruction __b1: +Removing instruction __b2_from___b1: +Removing instruction main_from___b2: +Removing instruction __bend_from___b2: +Removing instruction __b1: +Removing instruction __b1_from___b4: +Removing instruction __b4_from___b3: +Removing instruction __b1_from_printf_scroll: +Removing instruction memcpy_from___b1: +Removing instruction __b2_from___b1: +Removing instruction memset_from___b2: +Succesful ASM optimization Pass5RedundantLabelElimination +Removing instruction __b2: +Removing instruction __bend: +Removing instruction printf_str_from_main: +Removing instruction __breturn: +Removing instruction __b1_from_printf_str: +Removing instruction __breturn: +Removing instruction __b5: +Removing instruction __breturn: +Removing instruction __b1: +Removing instruction __b2: +Removing instruction __b3: +Removing instruction __b1_from_memset: +Removing instruction __breturn: +Removing instruction __b1_from___b2: +Removing instruction __b1_from_memcpy: +Removing instruction __breturn: +Removing instruction __b1_from___b2: +Removing instruction __b1: +Succesful ASM optimization Pass5UnusedLabelElimination +Skipping double jump to __b2 in jmp __b1_from___b5 +Succesful ASM optimization Pass5DoubleJumpElimination +Relabelling long label __b1_from___b5 to __b1 +Succesful ASM optimization Pass5RelabelLongLabels +Adding RTS to root block +Succesful ASM optimization Pass5AddMainRts +Removing instruction __b1: Succesful ASM optimization Pass5UnusedLabelElimination FINAL SYMBOL TABLE (label) @1 +(label) @2 (label) @begin (label) @end (const byte) RADIX::BINARY = (number) 2 @@ -786,177 +1646,423 @@ FINAL SYMBOL TABLE (const byte) RADIX::HEXADECIMAL = (number) $10 (const byte) RADIX::OCTAL = (number) 8 (void()) main() -(label) main::@1 (label) main::@return -(const byte*) main::str[(byte) $d] = (byte*) "hello world!" -(void()) print_char((byte) print_char::ch) -(label) print_char::@return -(byte) print_char::ch -(byte) print_char::ch#0 reg byte a 11002.0 -(byte*) print_char_cursor -(byte*) print_char_cursor#12 print_char_cursor zp[2]:6 2000.363636363636 -(byte*) print_char_cursor#16 print_char_cursor zp[2]:6 2750.5 -(byte*) print_line_cursor -(byte*) print_line_cursor#1 print_line_cursor zp[2]:2 1501.5 -(byte*) print_line_cursor#6 print_line_cursor zp[2]:2 2002.0 -(void()) print_ln() -(label) print_ln::@1 -(label) print_ln::@return -(byte*) print_screen -(void()) print_str((byte*) print_str::str) -(label) print_str::@1 -(label) print_str::@2 -(label) print_str::@3 -(label) print_str::@return -(byte*) print_str::str -(byte*) print_str::str#0 str zp[2]:4 2002.0 -(byte*) print_str::str#2 str zp[2]:4 1001.0 +(const byte*) main::str[(byte) $e] = (byte*) "hello world! +" +(void*()) memcpy((void*) memcpy::destination , (void*) memcpy::source , (word) memcpy::num) +(label) memcpy::@1 +(label) memcpy::@2 +(label) memcpy::@return +(void*) memcpy::destination +(const void*) memcpy::destination#0 destination = (void*) 1024 +(byte*) memcpy::dst +(byte*) memcpy::dst#1 dst zp[2]:6 1.00000001E8 +(byte*) memcpy::dst#2 dst zp[2]:6 1.00000001E8 +(word) memcpy::num +(const word) memcpy::num#0 num = (word)(number) $28*(number) $19-(number) $28 +(void*) memcpy::return +(void*) memcpy::source +(const void*) memcpy::source#0 source = (void*)(number) $400+(number) $28 +(byte*) memcpy::src +(byte*) memcpy::src#1 src zp[2]:4 2.00000002E8 +(byte*) memcpy::src#2 src zp[2]:4 1.00000001E8 +(byte*) memcpy::src_end +(const byte*) memcpy::src_end#0 src_end = (byte*)(const void*) memcpy::source#0+(const word) memcpy::num#0 +(void*()) memset((void*) memset::str , (byte) memset::c , (word) memset::num) +(label) memset::@1 +(label) memset::@2 +(label) memset::@return +(byte) memset::c +(const byte) memset::c#0 c = (byte) ' ' +(byte*) memset::dst +(byte*) memset::dst#1 dst zp[2]:4 2.00000002E8 +(byte*) memset::dst#2 dst zp[2]:4 1.3333333466666667E8 +(byte*) memset::end +(const byte*) memset::end#0 end = (byte*)(const void*) memset::str#0+(const word) memset::num#0 +(word) memset::num +(const word) memset::num#0 num = (byte) $28 +(void*) memset::return +(void*) memset::str +(const void*) memset::str#0 str = (void*)(number) $400+(number) $28*(number) $19-(number) $28 +(const byte*) printf_buffer_number::digits[(number) $b] = { fill( $b, 0) } +(byte) printf_buffer_number::sign +(void()) printf_char((byte) printf_char::ch) +(label) printf_char::@1 +(label) printf_char::@return +(byte) printf_char::ch +(byte) printf_char::ch#0 reg byte a 11002.0 +(byte*) printf_cursor_ptr loadstore zp[2]:10 7353.205882352942 +(byte) printf_cursor_x loadstore zp[1]:8 2222.5185185185182 +(byte) printf_cursor_y loadstore zp[1]:9 8947.605263157893 +(byte) printf_format_number::justify_left +(byte) printf_format_number::min_length +(byte) printf_format_number::radix +(byte) printf_format_number::sign_always +(byte) printf_format_number::upper_case +(byte) printf_format_number::zero_padding +(byte) printf_format_string::justify_left +(byte) printf_format_string::min_length +(void()) printf_ln() +(byte*~) printf_ln::$0 zp[2]:10 20002.0 +(byte*~) printf_ln::$1 zp[2]:10 20002.0 +(label) printf_ln::@return +(void()) printf_scroll() +(byte*~) printf_scroll::$4 zp[2]:10 200002.0 +(label) printf_scroll::@1 +(label) printf_scroll::@2 +(label) printf_scroll::@3 +(label) printf_scroll::@return +(void()) printf_str((byte*) printf_str::str) +(label) printf_str::@1 +(label) printf_str::@2 +(label) printf_str::@3 +(label) printf_str::@4 +(label) printf_str::@5 +(label) printf_str::@return +(byte) printf_str::ch +(byte) printf_str::ch#0 reg byte a 1001.0 +(byte*) printf_str::str +(byte*) printf_str::str#0 str zp[2]:2 429.0 +(byte*) printf_str::str#2 str zp[2]:2 2002.0 -zp[2]:2 [ print_line_cursor#6 print_line_cursor#1 ] -zp[2]:4 [ print_str::str#2 print_str::str#0 ] -zp[2]:6 [ print_char_cursor#12 print_char_cursor#16 ] -reg byte a [ print_char::ch#0 ] +zp[2]:2 [ printf_str::str#2 printf_str::str#0 ] +zp[2]:4 [ memcpy::src#2 memcpy::src#1 memset::dst#2 memset::dst#1 ] +zp[2]:6 [ memcpy::dst#2 memcpy::dst#1 ] +zp[1]:8 [ printf_cursor_x ] +zp[1]:9 [ printf_cursor_y ] +zp[2]:10 [ printf_cursor_ptr printf_scroll::$4 printf_ln::$0 printf_ln::$1 ] +reg byte a [ printf_str::ch#0 ] +reg byte a [ printf_char::ch#0 ] FINAL ASSEMBLER -Score: 1136 +Score: 13489 // File Comments // Upstart .pc = $801 "Basic" -:BasicUpstart(main) +:BasicUpstart(__bbegin) .pc = $80d "Program" // Global Constants & labels - .label print_line_cursor = 2 - .label print_char_cursor = 6 + .label printf_cursor_x = 8 + .label printf_cursor_y = 9 + .label printf_cursor_ptr = $a // @begin - // [1] phi from @begin to @1 [phi:@begin->@1] +__bbegin: // @1 - // [2] call main - // [4] phi from @1 to main [phi:@1->main] - // [3] phi from @1 to @end [phi:@1->@end] + // printf_cursor_x = 0 + // [1] (byte) printf_cursor_x ← (byte) 0 -- vbuz1=vbuc1 + // X-position of cursor + lda #0 + sta.z printf_cursor_x + // printf_cursor_y = 0 + // [2] (byte) printf_cursor_y ← (byte) 0 -- vbuz1=vbuc1 + // Y-position of cursor + sta.z printf_cursor_y + // printf_cursor_ptr = PRINTF_SCREEN_ADDRESS + // [3] (byte*) printf_cursor_ptr ← (byte*) 1024 -- pbuz1=pbuc1 + // Pointer to cursor address + lda #<$400 + sta.z printf_cursor_ptr + lda #>$400 + sta.z printf_cursor_ptr+1 + // [4] phi from @1 to @2 [phi:@1->@2] + // @2 + // [5] call main + // [7] phi from @2 to main [phi:@2->main] + jsr main + rts + // [6] phi from @2 to @end [phi:@2->@end] // @end // main main: { - // print_str("hello world!") - // [5] call print_str - // [14] phi from main to print_str [phi:main->print_str] - jsr print_str - // [6] phi from main to main::@1 [phi:main->main::@1] - // main::@1 - // print_ln() - // [7] call print_ln - // [9] phi from main::@1 to print_ln [phi:main::@1->print_ln] - jsr print_ln + // printf("hello world!\n") + // [8] call printf_str + // [10] phi from main to printf_str [phi:main->printf_str] + jsr printf_str // main::@return // } - // [8] return + // [9] return rts - str: .text "hello world!" + str: .text @"hello world!\n" .byte 0 } - // print_ln -// Print a newline -print_ln: { - // [10] phi from print_ln to print_ln::@1 [phi:print_ln->print_ln::@1] - // [10] phi (byte*) print_line_cursor#6 = (byte*) 1024 [phi:print_ln->print_ln::@1#0] -- pbuz1=pbuc1 - lda #<$400 - sta.z print_line_cursor - lda #>$400 - sta.z print_line_cursor+1 - // [10] phi from print_ln::@1 to print_ln::@1 [phi:print_ln::@1->print_ln::@1] - // [10] phi (byte*) print_line_cursor#6 = (byte*) print_line_cursor#1 [phi:print_ln::@1->print_ln::@1#0] -- register_copy - // print_ln::@1 - __b1: - // print_line_cursor + $28 - // [11] (byte*) print_line_cursor#1 ← (byte*) print_line_cursor#6 + (byte) $28 -- pbuz1=pbuz1_plus_vbuc1 - lda #$28 - clc - adc.z print_line_cursor - sta.z print_line_cursor - bcc !+ - inc.z print_line_cursor+1 - !: - // while (print_line_cursorprint_str::@1] - // [15] phi (byte*) print_char_cursor#12 = (byte*) 1024 [phi:print_str->print_str::@1#0] -- pbuz1=pbuc1 - lda #<$400 - sta.z print_char_cursor - lda #>$400 - sta.z print_char_cursor+1 - // [15] phi (byte*) print_str::str#2 = (const byte*) main::str [phi:print_str->print_str::@1#1] -- pbuz1=pbuc1 +// Handles escape codes such as newline +// printf_str(byte* zp(2) str) +printf_str: { + .label str = 2 + // [11] phi from printf_str to printf_str::@1 [phi:printf_str->printf_str::@1] + // [11] phi (byte*) printf_str::str#2 = (const byte*) main::str [phi:printf_str->printf_str::@1#0] -- pbuz1=pbuc1 lda #main.str sta.z str+1 - // print_str::@1 - __b1: - // while(*str) - // [16] if((byte) 0!=*((byte*) print_str::str#2)) goto print_str::@2 -- vbuc1_neq__deref_pbuz1_then_la1 - ldy #0 - lda (str),y - cmp #0 - bne __b2 - // print_str::@return - // } - // [17] return - rts - // print_str::@2 + // printf_str::@1 + // printf_str::@2 __b2: - // print_char(*(str++)) - // [18] (byte) print_char::ch#0 ← *((byte*) print_str::str#2) -- vbuaa=_deref_pbuz1 + // ch = *str++ + // [12] (byte) printf_str::ch#0 ← *((byte*) printf_str::str#2) -- vbuaa=_deref_pbuz1 ldy #0 lda (str),y - // [19] call print_char - jsr print_char - // print_str::@3 - // print_char(*(str++)); - // [20] (byte*) print_str::str#0 ← ++ (byte*) print_str::str#2 -- pbuz1=_inc_pbuz1 + // [13] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#2 -- pbuz1=_inc_pbuz1 inc.z str bne !+ inc.z str+1 !: - // [15] phi from print_str::@3 to print_str::@1 [phi:print_str::@3->print_str::@1] - // [15] phi (byte*) print_char_cursor#12 = (byte*) print_char_cursor#16 [phi:print_str::@3->print_str::@1#0] -- register_copy - // [15] phi (byte*) print_str::str#2 = (byte*) print_str::str#0 [phi:print_str::@3->print_str::@1#1] -- register_copy + // if(ch==0) + // [14] if((byte) printf_str::ch#0!=(byte) 0) goto printf_str::@3 -- vbuaa_neq_0_then_la1 + cmp #0 + bne __b3 + // printf_str::@return + // } + // [15] return + rts + // printf_str::@3 + __b3: + // if(ch=='\n') + // [16] if((byte) printf_str::ch#0==(byte) ' ') goto printf_str::@4 -- vbuaa_eq_vbuc1_then_la1 + cmp #'\n' + beq __b4 + // printf_str::@5 + // printf_char(ch) + // [17] (byte) printf_char::ch#0 ← (byte) printf_str::ch#0 + // [18] call printf_char + jsr printf_char + // [11] phi from printf_str::@4 printf_str::@5 to printf_str::@1 [phi:printf_str::@4/printf_str::@5->printf_str::@1] + // [11] phi (byte*) printf_str::str#2 = (byte*) printf_str::str#0 [phi:printf_str::@4/printf_str::@5->printf_str::@1#0] -- register_copy + jmp __b2 + // [19] phi from printf_str::@3 to printf_str::@4 [phi:printf_str::@3->printf_str::@4] + // printf_str::@4 + __b4: + // printf_ln() + // [20] call printf_ln + jsr printf_ln + jmp __b2 +} + // printf_ln +// Print a newline +printf_ln: { + .label __0 = $a + .label __1 = $a + // printf_cursor_ptr - printf_cursor_x + // [21] (byte*~) printf_ln::$0 ← (byte*) printf_cursor_ptr - (byte) printf_cursor_x -- pbuz1=pbuz1_minus_vbuz2 + sec + lda.z __0 + sbc.z printf_cursor_x + sta.z __0 + bcs !+ + dec.z __0+1 + !: + // printf_cursor_ptr - printf_cursor_x + PRINTF_SCREEN_WIDTH + // [22] (byte*~) printf_ln::$1 ← (byte*~) printf_ln::$0 + (byte) $28 -- pbuz1=pbuz1_plus_vbuc1 + lda #$28 + clc + adc.z __1 + sta.z __1 + bcc !+ + inc.z __1+1 + !: + // printf_cursor_ptr = printf_cursor_ptr - printf_cursor_x + PRINTF_SCREEN_WIDTH + // [23] (byte*) printf_cursor_ptr ← (byte*~) printf_ln::$1 + // printf_cursor_x = 0 + // [24] (byte) printf_cursor_x ← (byte) 0 -- vbuz1=vbuc1 + lda #0 + sta.z printf_cursor_x + // printf_cursor_y++; + // [25] (byte) printf_cursor_y ← ++ (byte) printf_cursor_y -- vbuz1=_inc_vbuz1 + inc.z printf_cursor_y + // printf_scroll() + // [26] call printf_scroll + jsr printf_scroll + // printf_ln::@return + // } + // [27] return + rts +} + // printf_scroll +// Scroll the entire screen if the cursor is on the last line +printf_scroll: { + .label __4 = $a + // if(printf_cursor_y==PRINTF_SCREEN_HEIGHT) + // [28] if((byte) printf_cursor_y!=(byte) $19) goto printf_scroll::@return -- vbuz1_neq_vbuc1_then_la1 + lda #$19 + cmp.z printf_cursor_y + bne __breturn + // [29] phi from printf_scroll to printf_scroll::@1 [phi:printf_scroll->printf_scroll::@1] + // printf_scroll::@1 + // memcpy(PRINTF_SCREEN_ADDRESS, PRINTF_SCREEN_ADDRESS+PRINTF_SCREEN_WIDTH, PRINTF_SCREEN_BYTES-PRINTF_SCREEN_WIDTH) + // [30] call memcpy + // [43] phi from printf_scroll::@1 to memcpy [phi:printf_scroll::@1->memcpy] + jsr memcpy + // [31] phi from printf_scroll::@1 to printf_scroll::@2 [phi:printf_scroll::@1->printf_scroll::@2] + // printf_scroll::@2 + // memset(PRINTF_SCREEN_ADDRESS+PRINTF_SCREEN_BYTES-PRINTF_SCREEN_WIDTH, ' ', PRINTF_SCREEN_WIDTH) + // [32] call memset + // [37] phi from printf_scroll::@2 to memset [phi:printf_scroll::@2->memset] + jsr memset + // printf_scroll::@3 + // printf_cursor_ptr-PRINTF_SCREEN_WIDTH + // [33] (byte*~) printf_scroll::$4 ← (byte*) printf_cursor_ptr - (byte) $28 -- pbuz1=pbuz1_minus_vwuc1 + lda.z __4 + sec + sbc #<$28 + sta.z __4 + lda.z __4+1 + sbc #>$28 + sta.z __4+1 + // printf_cursor_ptr = printf_cursor_ptr-PRINTF_SCREEN_WIDTH + // [34] (byte*) printf_cursor_ptr ← (byte*~) printf_scroll::$4 + // printf_cursor_y--; + // [35] (byte) printf_cursor_y ← -- (byte) printf_cursor_y -- vbuz1=_dec_vbuz1 + dec.z printf_cursor_y + // printf_scroll::@return + __breturn: + // } + // [36] return + rts +} + // memset +// Copies the character c (an unsigned char) to the first num characters of the object pointed to by the argument str. +memset: { + .const c = ' ' + .const num = $28 + .label str = $400+$28*$19-$28 + .label end = str+num + .label dst = 4 + // [38] phi from memset to memset::@1 [phi:memset->memset::@1] + // [38] phi (byte*) memset::dst#2 = (byte*)(const void*) memset::str#0 [phi:memset->memset::@1#0] -- pbuz1=pbuc1 + lda #str + sta.z dst+1 + // memset::@1 + __b1: + // for(char* dst = str; dst!=end; dst++) + // [39] if((byte*) memset::dst#2!=(const byte*) memset::end#0) goto memset::@2 -- pbuz1_neq_pbuc1_then_la1 + lda.z dst+1 + cmp #>end + bne __b2 + lda.z dst + cmp #memset::@1] + // [38] phi (byte*) memset::dst#2 = (byte*) memset::dst#1 [phi:memset::@2->memset::@1#0] -- register_copy jmp __b1 } - // print_char -// Print a single char -// print_char(byte register(A) ch) -print_char: { - // *(print_char_cursor++) = ch - // [21] *((byte*) print_char_cursor#12) ← (byte) print_char::ch#0 -- _deref_pbuz1=vbuaa - ldy #0 - sta (print_char_cursor),y - // *(print_char_cursor++) = ch; - // [22] (byte*) print_char_cursor#16 ← ++ (byte*) print_char_cursor#12 -- pbuz1=_inc_pbuz1 - inc.z print_char_cursor - bne !+ - inc.z print_char_cursor+1 - !: - // print_char::@return + // 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: { + .const num = $28*$19-$28 + .label destination = $400 + .label source = $400+$28 + .label src_end = source+num + .label dst = 6 + .label src = 4 + // [44] phi from memcpy to memcpy::@1 [phi:memcpy->memcpy::@1] + // [44] phi (byte*) memcpy::dst#2 = (byte*)(const void*) memcpy::destination#0 [phi:memcpy->memcpy::@1#0] -- pbuz1=pbuc1 + lda #destination + sta.z dst+1 + // [44] phi (byte*) memcpy::src#2 = (byte*)(const void*) memcpy::source#0 [phi:memcpy->memcpy::@1#1] -- pbuz1=pbuc1 + lda #source + sta.z src+1 + // memcpy::@1 + __b1: + // while(src!=src_end) + // [45] if((byte*) memcpy::src#2!=(const byte*) memcpy::src_end#0) goto memcpy::@2 -- pbuz1_neq_pbuc1_then_la1 + lda.z src+1 + cmp #>src_end + bne __b2 + lda.z src + cmp #memcpy::@1] + // [44] phi (byte*) memcpy::dst#2 = (byte*) memcpy::dst#1 [phi:memcpy::@2->memcpy::@1#0] -- register_copy + // [44] phi (byte*) memcpy::src#2 = (byte*) memcpy::src#1 [phi:memcpy::@2->memcpy::@1#1] -- register_copy + jmp __b1 +} + // printf_char +// Print a single char +// If the end of the screen is reached scroll it up one char and place the cursor at the +// printf_char(byte register(A) ch) +printf_char: { + // *(printf_cursor_ptr++) = ch + // [50] *((byte*) printf_cursor_ptr) ← (byte) printf_char::ch#0 -- _deref_pbuz1=vbuaa + ldy #0 + sta (printf_cursor_ptr),y + // *(printf_cursor_ptr++) = ch; + // [51] (byte*) printf_cursor_ptr ← ++ (byte*) printf_cursor_ptr -- pbuz1=_inc_pbuz1 + inc.z printf_cursor_ptr + bne !+ + inc.z printf_cursor_ptr+1 + !: + // if(++printf_cursor_x==PRINTF_SCREEN_WIDTH) + // [52] (byte) printf_cursor_x ← ++ (byte) printf_cursor_x -- vbuz1=_inc_vbuz1 + inc.z printf_cursor_x + // [53] if((byte) printf_cursor_x!=(byte) $28) goto printf_char::@return -- vbuz1_neq_vbuc1_then_la1 + lda #$28 + cmp.z printf_cursor_x + bne __breturn + // printf_char::@1 + // printf_cursor_x = 0 + // [54] (byte) printf_cursor_x ← (byte) 0 -- vbuz1=vbuc1 + lda #0 + sta.z printf_cursor_x + // ++printf_cursor_y; + // [55] (byte) printf_cursor_y ← ++ (byte) printf_cursor_y -- vbuz1=_inc_vbuz1 + inc.z printf_cursor_y + // printf_scroll() + // [56] call printf_scroll + jsr printf_scroll + // printf_char::@return + __breturn: + // } + // [57] return rts } // File Data diff --git a/src/test/ref/examples/helloworld/helloworld.sym b/src/test/ref/examples/helloworld/helloworld.sym index 57f649248..fb8e41b9f 100644 --- a/src/test/ref/examples/helloworld/helloworld.sym +++ b/src/test/ref/examples/helloworld/helloworld.sym @@ -1,4 +1,5 @@ (label) @1 +(label) @2 (label) @begin (label) @end (const byte) RADIX::BINARY = (number) 2 @@ -6,33 +7,90 @@ (const byte) RADIX::HEXADECIMAL = (number) $10 (const byte) RADIX::OCTAL = (number) 8 (void()) main() -(label) main::@1 (label) main::@return -(const byte*) main::str[(byte) $d] = (byte*) "hello world!" -(void()) print_char((byte) print_char::ch) -(label) print_char::@return -(byte) print_char::ch -(byte) print_char::ch#0 reg byte a 11002.0 -(byte*) print_char_cursor -(byte*) print_char_cursor#12 print_char_cursor zp[2]:6 2000.363636363636 -(byte*) print_char_cursor#16 print_char_cursor zp[2]:6 2750.5 -(byte*) print_line_cursor -(byte*) print_line_cursor#1 print_line_cursor zp[2]:2 1501.5 -(byte*) print_line_cursor#6 print_line_cursor zp[2]:2 2002.0 -(void()) print_ln() -(label) print_ln::@1 -(label) print_ln::@return -(byte*) print_screen -(void()) print_str((byte*) print_str::str) -(label) print_str::@1 -(label) print_str::@2 -(label) print_str::@3 -(label) print_str::@return -(byte*) print_str::str -(byte*) print_str::str#0 str zp[2]:4 2002.0 -(byte*) print_str::str#2 str zp[2]:4 1001.0 +(const byte*) main::str[(byte) $e] = (byte*) "hello world! +" +(void*()) memcpy((void*) memcpy::destination , (void*) memcpy::source , (word) memcpy::num) +(label) memcpy::@1 +(label) memcpy::@2 +(label) memcpy::@return +(void*) memcpy::destination +(const void*) memcpy::destination#0 destination = (void*) 1024 +(byte*) memcpy::dst +(byte*) memcpy::dst#1 dst zp[2]:6 1.00000001E8 +(byte*) memcpy::dst#2 dst zp[2]:6 1.00000001E8 +(word) memcpy::num +(const word) memcpy::num#0 num = (word)(number) $28*(number) $19-(number) $28 +(void*) memcpy::return +(void*) memcpy::source +(const void*) memcpy::source#0 source = (void*)(number) $400+(number) $28 +(byte*) memcpy::src +(byte*) memcpy::src#1 src zp[2]:4 2.00000002E8 +(byte*) memcpy::src#2 src zp[2]:4 1.00000001E8 +(byte*) memcpy::src_end +(const byte*) memcpy::src_end#0 src_end = (byte*)(const void*) memcpy::source#0+(const word) memcpy::num#0 +(void*()) memset((void*) memset::str , (byte) memset::c , (word) memset::num) +(label) memset::@1 +(label) memset::@2 +(label) memset::@return +(byte) memset::c +(const byte) memset::c#0 c = (byte) ' ' +(byte*) memset::dst +(byte*) memset::dst#1 dst zp[2]:4 2.00000002E8 +(byte*) memset::dst#2 dst zp[2]:4 1.3333333466666667E8 +(byte*) memset::end +(const byte*) memset::end#0 end = (byte*)(const void*) memset::str#0+(const word) memset::num#0 +(word) memset::num +(const word) memset::num#0 num = (byte) $28 +(void*) memset::return +(void*) memset::str +(const void*) memset::str#0 str = (void*)(number) $400+(number) $28*(number) $19-(number) $28 +(const byte*) printf_buffer_number::digits[(number) $b] = { fill( $b, 0) } +(byte) printf_buffer_number::sign +(void()) printf_char((byte) printf_char::ch) +(label) printf_char::@1 +(label) printf_char::@return +(byte) printf_char::ch +(byte) printf_char::ch#0 reg byte a 11002.0 +(byte*) printf_cursor_ptr loadstore zp[2]:10 7353.205882352942 +(byte) printf_cursor_x loadstore zp[1]:8 2222.5185185185182 +(byte) printf_cursor_y loadstore zp[1]:9 8947.605263157893 +(byte) printf_format_number::justify_left +(byte) printf_format_number::min_length +(byte) printf_format_number::radix +(byte) printf_format_number::sign_always +(byte) printf_format_number::upper_case +(byte) printf_format_number::zero_padding +(byte) printf_format_string::justify_left +(byte) printf_format_string::min_length +(void()) printf_ln() +(byte*~) printf_ln::$0 zp[2]:10 20002.0 +(byte*~) printf_ln::$1 zp[2]:10 20002.0 +(label) printf_ln::@return +(void()) printf_scroll() +(byte*~) printf_scroll::$4 zp[2]:10 200002.0 +(label) printf_scroll::@1 +(label) printf_scroll::@2 +(label) printf_scroll::@3 +(label) printf_scroll::@return +(void()) printf_str((byte*) printf_str::str) +(label) printf_str::@1 +(label) printf_str::@2 +(label) printf_str::@3 +(label) printf_str::@4 +(label) printf_str::@5 +(label) printf_str::@return +(byte) printf_str::ch +(byte) printf_str::ch#0 reg byte a 1001.0 +(byte*) printf_str::str +(byte*) printf_str::str#0 str zp[2]:2 429.0 +(byte*) printf_str::str#2 str zp[2]:2 2002.0 -zp[2]:2 [ print_line_cursor#6 print_line_cursor#1 ] -zp[2]:4 [ print_str::str#2 print_str::str#0 ] -zp[2]:6 [ print_char_cursor#12 print_char_cursor#16 ] -reg byte a [ print_char::ch#0 ] +zp[2]:2 [ printf_str::str#2 printf_str::str#0 ] +zp[2]:4 [ memcpy::src#2 memcpy::src#1 memset::dst#2 memset::dst#1 ] +zp[2]:6 [ memcpy::dst#2 memcpy::dst#1 ] +zp[1]:8 [ printf_cursor_x ] +zp[1]:9 [ printf_cursor_y ] +zp[2]:10 [ printf_cursor_ptr printf_scroll::$4 printf_ln::$0 printf_ln::$1 ] +reg byte a [ printf_str::ch#0 ] +reg byte a [ printf_char::ch#0 ]