1
0
mirror of https://gitlab.com/camelot/kickc.git synced 2025-01-07 07:29:49 +00:00

Added support for printf() parameter index format string (eg. %2$d). Closes #420

This commit is contained in:
jespergravgaard 2020-04-25 14:48:20 +02:00
parent ae28cb9c67
commit 986ad3b77f
9 changed files with 10183 additions and 15 deletions

View File

@ -25,23 +25,23 @@ public class Pass1PrintfIntrinsicRewrite extends Pass2SsaOptimization {
/** The printf procedure name. */
public static final String INTRINSIC_PRINTF_NAME = "printf";
/** The printf routine used to print a raw char */
public static final String PRINTF_CHAR = "printf_char";
private static final String PRINTF_CHAR = "printf_char";
/** The printf routine used to print a raw string */
public static final String PRINTF_STR = "printf_str";
private static final String PRINTF_STR = "printf_str";
/** The printf routine used to print formatted strings. */
public static final String PRINTF_STRING = "printf_string";
private static final String PRINTF_STRING = "printf_string";
/** The printf routine used to print signed chars. */
public static final String PRINTF_SCHAR = "printf_schar";
private static final String PRINTF_SCHAR = "printf_schar";
/** The printf routine used to print unsigned chars. */
public static final String PRINTF_UCHAR = "printf_uchar";
private static final String PRINTF_UCHAR = "printf_uchar";
/** The printf routine used to print signed integers. */
public static final String PRINTF_SINT = "printf_sint";
private static final String PRINTF_SINT = "printf_sint";
/** The printf routine used to print unsigned integers. */
public static final String PRINTF_UINT = "printf_uint";
private static final String PRINTF_UINT = "printf_uint";
/** The printf routine used to print signed long integers. */
public static final String PRINTF_SLONG = "printf_slong";
private static final String PRINTF_SLONG = "printf_slong";
/** The printf routine used to print unsigned long integers. */
public static final String PRINTF_ULONG = "printf_ulong";
private static final String PRINTF_ULONG = "printf_ulong";
/** Hexadecimal Radix name. */
public static final String HEXADECIMAL = "HEXADECIMAL";
/** Decimal Radix name. */
@ -83,8 +83,12 @@ public class Pass1PrintfIntrinsicRewrite extends Pass2SsaOptimization {
// [%diuxXoscp] type (specifies the type of the parameter/output "d"/"i" decimal signed, "u": decimal unsigned, "x": hexadecimal unsigned (lowercase), "X": hexadecimal unsigned (uppercase), "o": octal unsigned, "s": string, "c": character, "p": pointer, "%": output "%" )
Pattern pattern = Pattern.compile("%([1-9][0-9]*[$])?([-+0#]*)([1-9][0-9]*)?(hh|l)?([%diuxXoscp])");
final Matcher matcher = pattern.matcher(formatString);
// The index for the format field within the string
int formatIdx = 0;
// The index of the parameter being used as value for formatting. Incremented automatically unless field parameter index syntax (eg. %2$d) is used.
int paramIdx = 1;
// True if field parameter index syntax (eg. %2$d) is used.
boolean fieldParamIdx = false;
while(true) {
// Find the next pattern match!
boolean found = matcher.find();
@ -95,9 +99,17 @@ public class Pass1PrintfIntrinsicRewrite extends Pass2SsaOptimization {
final int start = matcher.start();
final int end = matcher.end();
final String typeField = matcher.group(5);
final String paramField = matcher.group(1);
if(paramField != null)
throw new CompileError("printf parameter field not supported", printfCall);
// Ensure that all fields use parameter index syntax!
if(paramField == null && fieldParamIdx && !typeField.equals("%"))
throw new CompileError("Error! If any single printf() placeholder specifies a parameter, all the rest of the placeholders must also specify a parameter!", statement);
if(paramField != null) {
if(!fieldParamIdx && paramIdx > 1)
throw new CompileError("Error! If any single printf() placeholder specifies a parameter, all the rest of the placeholders must also specify a parameter!", statement);
fieldParamIdx = true;
paramIdx = Integer.parseInt(paramField.substring(0, paramField.length()-1));
}
final String flagsField = matcher.group(2);
long leftJustify = (flagsField != null && flagsField.contains("-")) ? 1 : 0;
long signAlways = (flagsField != null && flagsField.contains("+")) ? 1 : 0;
@ -105,8 +117,7 @@ public class Pass1PrintfIntrinsicRewrite extends Pass2SsaOptimization {
final String widthField = matcher.group(3);
long width = (widthField == null) ? 0 : Integer.parseInt(widthField);
final String lengthField = matcher.group(4);
final String typeField = matcher.group(5);
long upperCase = 0l;
long upperCase = 0L;
// First output the non-matching part before the pattern
String prefix = formatString.substring(formatIdx, start);
@ -234,6 +245,7 @@ public class Pass1PrintfIntrinsicRewrite extends Pass2SsaOptimization {
/**
* Adds a call to a PRINTF sub-function.
*
* @param printfProcedureName The name of ths sub-function to call
* @param printfProcedureParameters The parameters to pass
* @param stmtIt The statement iterator to add to
@ -242,8 +254,8 @@ public class Pass1PrintfIntrinsicRewrite extends Pass2SsaOptimization {
private void addPrintfCall(String printfProcedureName, List<RValue> printfProcedureParameters, ListIterator<Statement> stmtIt, StatementCall printfCall) {
final StatementCall call_printf_str_prefix = new StatementCall(null, printfProcedureName, printfProcedureParameters, printfCall.getSource(), Comment.NO_COMMENTS);
final Procedure printfProcedure = getScope().getLocalProcedure(call_printf_str_prefix.getProcedureName());
if(printfProcedure==null) {
throw new CompileError("Needed printf sub-procedure not found " + printfProcedureName+"().", printfCall.getSource());
if(printfProcedure == null) {
throw new CompileError("Needed printf sub-procedure not found " + printfProcedureName + "().", printfCall.getSource());
}
call_printf_str_prefix.setProcedure(printfProcedure.getRef());
stmtIt.add(call_printf_str_prefix);

View File

@ -40,11 +40,26 @@ public class TestPrograms {
public TestPrograms() {
}
@Test
public void testPrintfError3() throws IOException, URISyntaxException {
assertError("printf-error-3.c", "Error! If any single printf() placeholder specifies a parameter, all the rest of the placeholders must also specify a parameter!");
}
@Test
public void testPrintfError2() throws IOException, URISyntaxException {
assertError("printf-error-2.c", "Error! If any single printf() placeholder specifies a parameter, all the rest of the placeholders must also specify a parameter!");
}
@Test
public void testPrintfError1() throws IOException, URISyntaxException {
assertError("printf-error-1.c", "Needed printf sub-procedure not found");
}
@Test
public void testPrintf16() throws IOException, URISyntaxException {
compileAndCompare("printf-16.c");
}
@Test
public void testPrintf15() throws IOException, URISyntaxException {
compileAndCompare("printf-15.c");

14
src/test/kc/printf-16.c Normal file
View File

@ -0,0 +1,14 @@
// Tests printf function call rewriting
// Test parameter field syntax %2$d
#include <printf.h>
void main() {
printf_cls();
printf("%%d %%d: %d %d\n",1, 2);
printf("%%1$d %%2$d: %1$d %2$d\n",1, 2);
printf("%%1$d %%1$d: %1$d %1$d\n",1, 2);
printf("%%2$d %%2$d: %2$d %2$d\n",1, 2);
printf("%%2$d %%1$d: %2$d %1$d\n",1, 2);
}

View File

@ -0,0 +1,9 @@
// Tests printf function call rewriting
// USe parameter field syntax for a subset of fields
#include <printf.h>
void main() {
printf("%d %1$d",1,1);
}

View File

@ -0,0 +1,9 @@
// Tests printf function call rewriting
// USe parameter field syntax for a subset of fields
#include <printf.h>
void main() {
printf("%1$d %d",1,1);
}

697
src/test/ref/printf-16.asm Normal file
View File

@ -0,0 +1,697 @@
// Tests printf function call rewriting
// Test parameter field syntax %2$d
.pc = $801 "Basic"
:BasicUpstart(__bbegin)
.pc = $80d "Program"
.const OFFSET_STRUCT_PRINTF_BUFFER_NUMBER_DIGITS = 1
.const SIZEOF_STRUCT_PRINTF_BUFFER_NUMBER = $c
.label printf_cursor_x = 7
.label printf_cursor_y = 8
.label printf_cursor_ptr = 9
__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: {
// printf_cls()
jsr printf_cls
// printf("%%d %%d: %d %d\n",1, 2)
lda #<str
sta.z printf_str.str
lda #>str
sta.z printf_str.str+1
jsr printf_str
// printf("%%d %%d: %d %d\n",1, 2)
lda #'%'
jsr printf_char
// printf("%%d %%d: %d %d\n",1, 2)
lda #<str1
sta.z printf_str.str
lda #>str1
sta.z printf_str.str+1
jsr printf_str
// printf("%%d %%d: %d %d\n",1, 2)
lda #'%'
jsr printf_char
// printf("%%d %%d: %d %d\n",1, 2)
lda #<str2
sta.z printf_str.str
lda #>str2
sta.z printf_str.str+1
jsr printf_str
// printf("%%d %%d: %d %d\n",1, 2)
lda #<1
sta.z printf_sint.value
lda #>1
sta.z printf_sint.value+1
jsr printf_sint
// printf("%%d %%d: %d %d\n",1, 2)
lda #<str3
sta.z printf_str.str
lda #>str3
sta.z printf_str.str+1
jsr printf_str
// printf("%%d %%d: %d %d\n",1, 2)
lda #<2
sta.z printf_sint.value
lda #>2
sta.z printf_sint.value+1
jsr printf_sint
// printf("%%d %%d: %d %d\n",1, 2)
lda #<str4
sta.z printf_str.str
lda #>str4
sta.z printf_str.str+1
jsr printf_str
// printf("%%1$d %%2$d: %1$d %2$d\n",1, 2)
lda #<str
sta.z printf_str.str
lda #>str
sta.z printf_str.str+1
jsr printf_str
// printf("%%1$d %%2$d: %1$d %2$d\n",1, 2)
lda #'%'
jsr printf_char
// printf("%%1$d %%2$d: %1$d %2$d\n",1, 2)
lda #<str6
sta.z printf_str.str
lda #>str6
sta.z printf_str.str+1
jsr printf_str
// printf("%%1$d %%2$d: %1$d %2$d\n",1, 2)
lda #'%'
jsr printf_char
// printf("%%1$d %%2$d: %1$d %2$d\n",1, 2)
lda #<str7
sta.z printf_str.str
lda #>str7
sta.z printf_str.str+1
jsr printf_str
// printf("%%1$d %%2$d: %1$d %2$d\n",1, 2)
lda #<1
sta.z printf_sint.value
lda #>1
sta.z printf_sint.value+1
jsr printf_sint
// printf("%%1$d %%2$d: %1$d %2$d\n",1, 2)
lda #<str3
sta.z printf_str.str
lda #>str3
sta.z printf_str.str+1
jsr printf_str
// printf("%%1$d %%2$d: %1$d %2$d\n",1, 2)
lda #<2
sta.z printf_sint.value
lda #>2
sta.z printf_sint.value+1
jsr printf_sint
// printf("%%1$d %%2$d: %1$d %2$d\n",1, 2)
lda #<str4
sta.z printf_str.str
lda #>str4
sta.z printf_str.str+1
jsr printf_str
// printf("%%1$d %%1$d: %1$d %1$d\n",1, 2)
lda #<str
sta.z printf_str.str
lda #>str
sta.z printf_str.str+1
jsr printf_str
// printf("%%1$d %%1$d: %1$d %1$d\n",1, 2)
lda #'%'
jsr printf_char
// printf("%%1$d %%1$d: %1$d %1$d\n",1, 2)
lda #<str6
sta.z printf_str.str
lda #>str6
sta.z printf_str.str+1
jsr printf_str
// printf("%%1$d %%1$d: %1$d %1$d\n",1, 2)
lda #'%'
jsr printf_char
// printf("%%1$d %%1$d: %1$d %1$d\n",1, 2)
lda #<str12
sta.z printf_str.str
lda #>str12
sta.z printf_str.str+1
jsr printf_str
// printf("%%1$d %%1$d: %1$d %1$d\n",1, 2)
lda #<1
sta.z printf_sint.value
lda #>1
sta.z printf_sint.value+1
jsr printf_sint
// printf("%%1$d %%1$d: %1$d %1$d\n",1, 2)
lda #<str3
sta.z printf_str.str
lda #>str3
sta.z printf_str.str+1
jsr printf_str
// printf("%%1$d %%1$d: %1$d %1$d\n",1, 2)
lda #<1
sta.z printf_sint.value
lda #>1
sta.z printf_sint.value+1
jsr printf_sint
// printf("%%1$d %%1$d: %1$d %1$d\n",1, 2)
lda #<str4
sta.z printf_str.str
lda #>str4
sta.z printf_str.str+1
jsr printf_str
// printf("%%2$d %%2$d: %2$d %2$d\n",1, 2)
lda #<str
sta.z printf_str.str
lda #>str
sta.z printf_str.str+1
jsr printf_str
// printf("%%2$d %%2$d: %2$d %2$d\n",1, 2)
lda #'%'
jsr printf_char
// printf("%%2$d %%2$d: %2$d %2$d\n",1, 2)
lda #<str16
sta.z printf_str.str
lda #>str16
sta.z printf_str.str+1
jsr printf_str
// printf("%%2$d %%2$d: %2$d %2$d\n",1, 2)
lda #'%'
jsr printf_char
// printf("%%2$d %%2$d: %2$d %2$d\n",1, 2)
lda #<str7
sta.z printf_str.str
lda #>str7
sta.z printf_str.str+1
jsr printf_str
// printf("%%2$d %%2$d: %2$d %2$d\n",1, 2)
lda #<2
sta.z printf_sint.value
lda #>2
sta.z printf_sint.value+1
jsr printf_sint
// printf("%%2$d %%2$d: %2$d %2$d\n",1, 2)
lda #<str3
sta.z printf_str.str
lda #>str3
sta.z printf_str.str+1
jsr printf_str
// printf("%%2$d %%2$d: %2$d %2$d\n",1, 2)
lda #<2
sta.z printf_sint.value
lda #>2
sta.z printf_sint.value+1
jsr printf_sint
// printf("%%2$d %%2$d: %2$d %2$d\n",1, 2)
lda #<str4
sta.z printf_str.str
lda #>str4
sta.z printf_str.str+1
jsr printf_str
// printf("%%2$d %%1$d: %2$d %1$d\n",1, 2)
lda #<str
sta.z printf_str.str
lda #>str
sta.z printf_str.str+1
jsr printf_str
// printf("%%2$d %%1$d: %2$d %1$d\n",1, 2)
lda #'%'
jsr printf_char
// printf("%%2$d %%1$d: %2$d %1$d\n",1, 2)
lda #<str16
sta.z printf_str.str
lda #>str16
sta.z printf_str.str+1
jsr printf_str
// printf("%%2$d %%1$d: %2$d %1$d\n",1, 2)
lda #'%'
jsr printf_char
// printf("%%2$d %%1$d: %2$d %1$d\n",1, 2)
lda #<str12
sta.z printf_str.str
lda #>str12
sta.z printf_str.str+1
jsr printf_str
// printf("%%2$d %%1$d: %2$d %1$d\n",1, 2)
lda #<2
sta.z printf_sint.value
lda #>2
sta.z printf_sint.value+1
jsr printf_sint
// printf("%%2$d %%1$d: %2$d %1$d\n",1, 2)
lda #<str3
sta.z printf_str.str
lda #>str3
sta.z printf_str.str+1
jsr printf_str
// printf("%%2$d %%1$d: %2$d %1$d\n",1, 2)
lda #<1
sta.z printf_sint.value
lda #>1
sta.z printf_sint.value+1
jsr printf_sint
// printf("%%2$d %%1$d: %2$d %1$d\n",1, 2)
lda #<str4
sta.z printf_str.str
lda #>str4
sta.z printf_str.str+1
jsr printf_str
// }
rts
str: .text ""
.byte 0
str1: .text "d "
.byte 0
str2: .text "d: "
.byte 0
str3: .text " "
.byte 0
str4: .text @"\n"
.byte 0
str6: .text "1$d "
.byte 0
str7: .text "2$d: "
.byte 0
str12: .text "1$d: "
.byte 0
str16: .text "2$d "
.byte 0
}
// Print a zero-terminated string
// Handles escape codes such as newline
// printf_str(byte* zp(2) str)
printf_str: {
.label str = 2
__b2:
// ch = *str++
ldy #0
lda (str),y
inc.z str
bne !+
inc.z str+1
!:
// 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 newline
printf_ln: {
.label __0 = 9
.label __1 = 9
// 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
// }
rts
}
// 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: {
.label __6 = 9
// *(printf_cursor_ptr++) = ch
ldy #0
sta (printf_cursor_ptr),y
// *(printf_cursor_ptr++) = ch;
inc.z printf_cursor_ptr
bne !+
inc.z printf_cursor_ptr+1
!:
// if(++printf_cursor_x==PRINTF_SCREEN_WIDTH)
inc.z printf_cursor_x
lda #$28
cmp.z printf_cursor_x
bne __breturn
// printf_cursor_x = 0
lda #0
sta.z printf_cursor_x
// ++printf_cursor_y;
inc.z printf_cursor_y
// 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)
ldx #' '
lda #<$400+$28*$19-$28
sta.z memset.str
lda #>$400+$28*$19-$28
sta.z memset.str+1
lda #<$28
sta.z memset.num
lda #>$28
sta.z memset.num+1
jsr memset
// printf_cursor_ptr-PRINTF_SCREEN_WIDTH
lda.z __6
sec
sbc #<$28
sta.z __6
lda.z __6+1
sbc #>$28
sta.z __6+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(void* zp($b) str, byte register(X) c, word zp(5) num)
memset: {
.label end = 5
.label dst = $b
.label num = 5
.label str = $b
// if(num>0)
lda.z num
bne !+
lda.z num+1
beq __breturn
!:
// end = (char*)str + num
lda.z end
clc
adc.z str
sta.z end
lda.z end+1
adc.z str+1
sta.z end+1
__b2:
// for(char* dst = str; dst!=end; dst++)
lda.z dst+1
cmp.z end+1
bne __b3
lda.z dst
cmp.z end
bne __b3
__breturn:
// }
rts
__b3:
// *dst = c
txa
ldy #0
sta (dst),y
// for(char* dst = str; dst!=end; dst++)
inc.z dst
bne !+
inc.z dst+1
!:
jmp __b2
}
// 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: {
.label destination = $400
.label source = $400+$28
.const num = $28*$19-$28
.label src_end = source+num
.label dst = $b
.label src = 5
lda #<destination
sta.z dst
lda #>destination
sta.z dst+1
lda #<source
sta.z src
lda #>source
sta.z src+1
__b1:
// while(src!=src_end)
lda.z src+1
cmp #>src_end
bne __b2
lda.z src
cmp #<src_end
bne __b2
// }
rts
__b2:
// *dst++ = *src++
ldy #0
lda (src),y
sta (dst),y
// *dst++ = *src++;
inc.z dst
bne !+
inc.z dst+1
!:
inc.z src
bne !+
inc.z src+1
!:
jmp __b1
}
// Print a signed integer using a specific format
// printf_sint(signed word zp(2) value)
printf_sint: {
.label value = 2
// printf_buffer.sign = 0
// Handle any sign
lda #0
sta printf_buffer
// if(value<0)
lda.z value+1
bmi __b1
jmp __b2
__b1:
// value = -value
sec
lda #0
sbc.z value
sta.z value
lda #0
sbc.z value+1
sta.z value+1
// printf_buffer.sign = '-'
lda #'-'
sta printf_buffer
__b2:
// utoa(uvalue, printf_buffer.digits, format.radix)
jsr utoa
// printf_number_buffer(printf_buffer, format)
lda printf_buffer
// Print using format
jsr printf_number_buffer
// }
rts
}
// Print the contents of the number buffer using a specific format.
// This handles minimum length, zero-filling, and left/right justification from the format
// printf_number_buffer(byte register(A) buffer_sign)
printf_number_buffer: {
.label buffer_digits = printf_buffer+OFFSET_STRUCT_PRINTF_BUFFER_NUMBER_DIGITS
// if(buffer.sign)
cmp #0
beq __b2
// printf_char(buffer.sign)
jsr printf_char
__b2:
// printf_str(buffer.digits)
lda #<buffer_digits
sta.z printf_str.str
lda #>buffer_digits
sta.z printf_str.str+1
jsr printf_str
// }
rts
}
// Converts unsigned number value to a string representing it in RADIX format.
// If the leading digits are zero they are not included in the string.
// - value : The number to be converted to RADIX
// - buffer : receives the string representing the number and zero-termination.
// - radix : The radix to convert the number to (from the enum RADIX)
// utoa(word zp(2) value, byte* zp(5) buffer)
utoa: {
.label digit_value = $b
.label buffer = 5
.label digit = 4
.label value = 2
lda #<printf_buffer+OFFSET_STRUCT_PRINTF_BUFFER_NUMBER_DIGITS
sta.z buffer
lda #>printf_buffer+OFFSET_STRUCT_PRINTF_BUFFER_NUMBER_DIGITS
sta.z buffer+1
ldx #0
txa
sta.z digit
__b1:
// for( char digit=0; digit<max_digits-1; digit++ )
lda.z digit
cmp #5-1
bcc __b2
// *buffer++ = DIGITS[(char)value]
lda.z value
tay
lda DIGITS,y
ldy #0
sta (buffer),y
// *buffer++ = DIGITS[(char)value];
inc.z buffer
bne !+
inc.z buffer+1
!:
// *buffer = 0
lda #0
tay
sta (buffer),y
// }
rts
__b2:
// digit_value = digit_values[digit]
lda.z digit
asl
tay
lda RADIX_DECIMAL_VALUES,y
sta.z digit_value
lda RADIX_DECIMAL_VALUES+1,y
sta.z digit_value+1
// if (started || value >= digit_value)
cpx #0
bne __b5
cmp.z value+1
bne !+
lda.z digit_value
cmp.z value
beq __b5
!:
bcc __b5
__b4:
// for( char digit=0; digit<max_digits-1; digit++ )
inc.z digit
jmp __b1
__b5:
// utoa_append(buffer++, value, digit_value)
jsr utoa_append
// utoa_append(buffer++, value, digit_value)
// value = utoa_append(buffer++, value, digit_value)
// value = utoa_append(buffer++, value, digit_value);
inc.z buffer
bne !+
inc.z buffer+1
!:
ldx #1
jmp __b4
}
// Used to convert a single digit of an unsigned number value to a string representation
// Counts a single digit up from '0' as long as the value is larger than sub.
// Each time the digit is increased sub is subtracted from value.
// - buffer : pointer to the char that receives the digit
// - value : The value where the digit will be derived from
// - sub : the value of a '1' in the digit. Subtracted continually while the digit is increased.
// (For decimal the subs used are 10000, 1000, 100, 10, 1)
// returns : the value reduced by sub * digit so that it is less than sub.
// utoa_append(byte* zp(5) buffer, word zp(2) value, word zp($b) sub)
utoa_append: {
.label buffer = 5
.label value = 2
.label sub = $b
.label return = 2
ldx #0
__b1:
// while (value >= sub)
lda.z sub+1
cmp.z value+1
bne !+
lda.z sub
cmp.z value
beq __b2
!:
bcc __b2
// *buffer = DIGITS[digit]
lda DIGITS,x
ldy #0
sta (buffer),y
// }
rts
__b2:
// digit++;
inx
// value -= sub
lda.z value
sec
sbc.z sub
sta.z value
lda.z value+1
sbc.z sub+1
sta.z value+1
jmp __b1
}
// Clear the screen. Also resets current line/char cursor.
printf_cls: {
// memset(PRINTF_SCREEN_ADDRESS, ' ', PRINTF_SCREEN_BYTES)
ldx #' '
lda #<$400
sta.z memset.str
lda #>$400
sta.z memset.str+1
lda #<$28*$19
sta.z memset.num
lda #>$28*$19
sta.z memset.num+1
jsr memset
// printf_cursor_ptr = PRINTF_SCREEN_ADDRESS
lda #<$400
sta.z printf_cursor_ptr
lda #>$400
sta.z printf_cursor_ptr+1
// printf_cursor_x = 0
lda #0
sta.z printf_cursor_x
// printf_cursor_y = 0
sta.z printf_cursor_y
// }
rts
}
// The digits used for numbers
DIGITS: .text "0123456789abcdef"
// Values of decimal digits
RADIX_DECIMAL_VALUES: .word $2710, $3e8, $64, $a
// Buffer used for stringified number being printed
printf_buffer: .fill SIZEOF_STRUCT_PRINTF_BUFFER_NUMBER, 0

436
src/test/ref/printf-16.cfg Normal file
View File

@ -0,0 +1,436 @@
@begin: scope:[] from
[0] phi()
to:@1
@1: scope:[] from @begin
[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 @2
[6] phi()
(void()) main()
main: scope:[main] from @2
[7] phi()
[8] call printf_cls
to:main::@1
main::@1: scope:[main] from main
[9] phi()
[10] call printf_str
to:main::@2
main::@2: scope:[main] from main::@1
[11] phi()
[12] call printf_char
to:main::@3
main::@3: scope:[main] from main::@2
[13] phi()
[14] call printf_str
to:main::@4
main::@4: scope:[main] from main::@3
[15] phi()
[16] call printf_char
to:main::@5
main::@5: scope:[main] from main::@4
[17] phi()
[18] call printf_str
to:main::@6
main::@6: scope:[main] from main::@5
[19] phi()
[20] call printf_sint
to:main::@7
main::@7: scope:[main] from main::@6
[21] phi()
[22] call printf_str
to:main::@8
main::@8: scope:[main] from main::@7
[23] phi()
[24] call printf_sint
to:main::@9
main::@9: scope:[main] from main::@8
[25] phi()
[26] call printf_str
to:main::@10
main::@10: scope:[main] from main::@9
[27] phi()
[28] call printf_str
to:main::@11
main::@11: scope:[main] from main::@10
[29] phi()
[30] call printf_char
to:main::@12
main::@12: scope:[main] from main::@11
[31] phi()
[32] call printf_str
to:main::@13
main::@13: scope:[main] from main::@12
[33] phi()
[34] call printf_char
to:main::@14
main::@14: scope:[main] from main::@13
[35] phi()
[36] call printf_str
to:main::@15
main::@15: scope:[main] from main::@14
[37] phi()
[38] call printf_sint
to:main::@16
main::@16: scope:[main] from main::@15
[39] phi()
[40] call printf_str
to:main::@17
main::@17: scope:[main] from main::@16
[41] phi()
[42] call printf_sint
to:main::@18
main::@18: scope:[main] from main::@17
[43] phi()
[44] call printf_str
to:main::@19
main::@19: scope:[main] from main::@18
[45] phi()
[46] call printf_str
to:main::@20
main::@20: scope:[main] from main::@19
[47] phi()
[48] call printf_char
to:main::@21
main::@21: scope:[main] from main::@20
[49] phi()
[50] call printf_str
to:main::@22
main::@22: scope:[main] from main::@21
[51] phi()
[52] call printf_char
to:main::@23
main::@23: scope:[main] from main::@22
[53] phi()
[54] call printf_str
to:main::@24
main::@24: scope:[main] from main::@23
[55] phi()
[56] call printf_sint
to:main::@25
main::@25: scope:[main] from main::@24
[57] phi()
[58] call printf_str
to:main::@26
main::@26: scope:[main] from main::@25
[59] phi()
[60] call printf_sint
to:main::@27
main::@27: scope:[main] from main::@26
[61] phi()
[62] call printf_str
to:main::@28
main::@28: scope:[main] from main::@27
[63] phi()
[64] call printf_str
to:main::@29
main::@29: scope:[main] from main::@28
[65] phi()
[66] call printf_char
to:main::@30
main::@30: scope:[main] from main::@29
[67] phi()
[68] call printf_str
to:main::@31
main::@31: scope:[main] from main::@30
[69] phi()
[70] call printf_char
to:main::@32
main::@32: scope:[main] from main::@31
[71] phi()
[72] call printf_str
to:main::@33
main::@33: scope:[main] from main::@32
[73] phi()
[74] call printf_sint
to:main::@34
main::@34: scope:[main] from main::@33
[75] phi()
[76] call printf_str
to:main::@35
main::@35: scope:[main] from main::@34
[77] phi()
[78] call printf_sint
to:main::@36
main::@36: scope:[main] from main::@35
[79] phi()
[80] call printf_str
to:main::@37
main::@37: scope:[main] from main::@36
[81] phi()
[82] call printf_str
to:main::@38
main::@38: scope:[main] from main::@37
[83] phi()
[84] call printf_char
to:main::@39
main::@39: scope:[main] from main::@38
[85] phi()
[86] call printf_str
to:main::@40
main::@40: scope:[main] from main::@39
[87] phi()
[88] call printf_char
to:main::@41
main::@41: scope:[main] from main::@40
[89] phi()
[90] call printf_str
to:main::@42
main::@42: scope:[main] from main::@41
[91] phi()
[92] call printf_sint
to:main::@43
main::@43: scope:[main] from main::@42
[93] phi()
[94] call printf_str
to:main::@44
main::@44: scope:[main] from main::@43
[95] phi()
[96] call printf_sint
to:main::@45
main::@45: scope:[main] from main::@44
[97] phi()
[98] call printf_str
to:main::@return
main::@return: scope:[main] from main::@45
[99] return
to:@return
(void()) printf_str((byte*) printf_str::str)
printf_str: scope:[printf_str] from main::@1 main::@10 main::@12 main::@14 main::@16 main::@18 main::@19 main::@21 main::@23 main::@25 main::@27 main::@28 main::@3 main::@30 main::@32 main::@34 main::@36 main::@37 main::@39 main::@41 main::@43 main::@45 main::@5 main::@7 main::@9 printf_number_buffer::@2
[100] (byte*) printf_str::str#29 ← phi( main::@1/(const byte*) main::str main::@10/(const byte*) main::str main::@12/(const byte*) main::str6 main::@14/(const byte*) main::str7 main::@16/(const byte*) main::str3 main::@18/(const byte*) main::str4 main::@19/(const byte*) main::str main::@21/(const byte*) main::str6 main::@23/(const byte*) main::str12 main::@25/(const byte*) main::str3 main::@27/(const byte*) main::str4 main::@28/(const byte*) main::str main::@3/(const byte*) main::str1 main::@30/(const byte*) main::str16 main::@32/(const byte*) main::str7 main::@34/(const byte*) main::str3 main::@36/(const byte*) main::str4 main::@37/(const byte*) main::str main::@39/(const byte*) main::str16 main::@41/(const byte*) main::str12 main::@43/(const byte*) main::str3 main::@45/(const byte*) main::str4 main::@5/(const byte*) main::str2 main::@7/(const byte*) main::str3 main::@9/(const byte*) main::str4 printf_number_buffer::@2/(const byte*) printf_number_buffer::buffer_digits#0 )
to:printf_str::@1
printf_str::@1: scope:[printf_str] from printf_str printf_str::@4 printf_str::@5
[101] (byte*) printf_str::str#27 ← phi( printf_str/(byte*) printf_str::str#29 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
[102] (byte) printf_str::ch#0 ← *((byte*) printf_str::str#27)
[103] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#27
[104] 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
[105] return
to:@return
printf_str::@3: scope:[printf_str] from printf_str::@2
[106] 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
[107] (byte) printf_char::ch#1 ← (byte) printf_str::ch#0
[108] call printf_char
to:printf_str::@1
printf_str::@4: scope:[printf_str] from printf_str::@3
[109] phi()
[110] call printf_ln
to:printf_str::@1
(void()) printf_ln()
printf_ln: scope:[printf_ln] from printf_str::@4
[111] (byte*~) printf_ln::$0 ← (byte*) printf_cursor_ptr - (byte) printf_cursor_x
[112] (byte*~) printf_ln::$1 ← (byte*~) printf_ln::$0 + (byte) $28
[113] (byte*) printf_cursor_ptr ← (byte*~) printf_ln::$1
[114] (byte) printf_cursor_x ← (byte) 0
[115] (byte) printf_cursor_y ← ++ (byte) printf_cursor_y
to:printf_ln::@return
printf_ln::@return: scope:[printf_ln] from printf_ln
[116] return
to:@return
(void()) printf_char((byte) printf_char::ch)
printf_char: scope:[printf_char] from main::@11 main::@13 main::@2 main::@20 main::@22 main::@29 main::@31 main::@38 main::@4 main::@40 printf_number_buffer::@3 printf_str::@5
[117] (byte) printf_char::ch#13 ← phi( main::@11/(byte) '%' main::@13/(byte) '%' main::@2/(byte) '%' main::@20/(byte) '%' main::@22/(byte) '%' main::@29/(byte) '%' main::@31/(byte) '%' main::@38/(byte) '%' main::@4/(byte) '%' main::@40/(byte) '%' printf_number_buffer::@3/(byte) printf_char::ch#2 printf_str::@5/(byte) printf_char::ch#1 )
[118] *((byte*) printf_cursor_ptr) ← (byte) printf_char::ch#13
[119] (byte*) printf_cursor_ptr ← ++ (byte*) printf_cursor_ptr
[120] (byte) printf_cursor_x ← ++ (byte) printf_cursor_x
[121] if((byte) printf_cursor_x!=(byte) $28) goto printf_char::@return
to:printf_char::@1
printf_char::@1: scope:[printf_char] from printf_char
[122] (byte) printf_cursor_x ← (byte) 0
[123] (byte) printf_cursor_y ← ++ (byte) printf_cursor_y
[124] if((byte) printf_cursor_y!=(byte) $19) goto printf_char::@return
to:printf_char::@2
printf_char::@2: scope:[printf_char] from printf_char::@1
[125] phi()
[126] call memcpy
to:printf_char::@3
printf_char::@3: scope:[printf_char] from printf_char::@2
[127] phi()
[128] call memset
to:printf_char::@4
printf_char::@4: scope:[printf_char] from printf_char::@3
[129] (byte*~) printf_char::$6 ← (byte*) printf_cursor_ptr - (byte) $28
[130] (byte*) printf_cursor_ptr ← (byte*~) printf_char::$6
[131] (byte) printf_cursor_y ← -- (byte) printf_cursor_y
to:printf_char::@return
printf_char::@return: scope:[printf_char] from printf_char printf_char::@1 printf_char::@4
[132] return
to:@return
(void*()) memset((void*) memset::str , (byte) memset::c , (word) memset::num)
memset: scope:[memset] from printf_char::@3 printf_cls
[133] (byte) memset::c#4 ← phi( printf_char::@3/(byte) ' ' printf_cls/(byte) ' ' )
[133] (void*) memset::str#3 ← phi( printf_char::@3/(void*)(number) $400+(number) $28*(number) $19-(number) $28 printf_cls/(void*) 1024 )
[133] (word) memset::num#2 ← phi( printf_char::@3/(byte) $28 printf_cls/(word)(number) $28*(number) $19 )
[134] if((word) memset::num#2<=(byte) 0) goto memset::@return
to:memset::@1
memset::@1: scope:[memset] from memset
[135] (byte*) memset::end#0 ← (byte*)(void*) memset::str#3 + (word) memset::num#2
[136] (byte*) memset::dst#4 ← (byte*)(void*) memset::str#3
to:memset::@2
memset::@2: scope:[memset] from memset::@1 memset::@3
[137] (byte*) memset::dst#2 ← phi( memset::@1/(byte*) memset::dst#4 memset::@3/(byte*) memset::dst#1 )
[138] if((byte*) memset::dst#2!=(byte*) memset::end#0) goto memset::@3
to:memset::@return
memset::@return: scope:[memset] from memset memset::@2
[139] return
to:@return
memset::@3: scope:[memset] from memset::@2
[140] *((byte*) memset::dst#2) ← (byte) memset::c#4
[141] (byte*) memset::dst#1 ← ++ (byte*) memset::dst#2
to:memset::@2
(void*()) memcpy((void*) memcpy::destination , (void*) memcpy::source , (word) memcpy::num)
memcpy: scope:[memcpy] from printf_char::@2
[142] phi()
to:memcpy::@1
memcpy::@1: scope:[memcpy] from memcpy memcpy::@2
[143] (byte*) memcpy::dst#2 ← phi( memcpy/(byte*)(const void*) memcpy::destination#0 memcpy::@2/(byte*) memcpy::dst#1 )
[143] (byte*) memcpy::src#2 ← phi( memcpy/(byte*)(const void*) memcpy::source#0 memcpy::@2/(byte*) memcpy::src#1 )
[144] if((byte*) memcpy::src#2!=(const byte*) memcpy::src_end#0) goto memcpy::@2
to:memcpy::@return
memcpy::@return: scope:[memcpy] from memcpy::@1
[145] return
to:@return
memcpy::@2: scope:[memcpy] from memcpy::@1
[146] *((byte*) memcpy::dst#2) ← *((byte*) memcpy::src#2)
[147] (byte*) memcpy::dst#1 ← ++ (byte*) memcpy::dst#2
[148] (byte*) memcpy::src#1 ← ++ (byte*) memcpy::src#2
to:memcpy::@1
(void()) printf_sint((signed word) printf_sint::value , (byte) printf_sint::format_min_length , (byte) printf_sint::format_justify_left , (byte) printf_sint::format_sign_always , (byte) printf_sint::format_zero_padding , (byte) printf_sint::format_upper_case , (byte) printf_sint::format_radix)
printf_sint: scope:[printf_sint] from main::@15 main::@17 main::@24 main::@26 main::@33 main::@35 main::@42 main::@44 main::@6 main::@8
[149] (signed word) printf_sint::value#11 ← phi( main::@15/(signed byte) 1 main::@17/(signed byte) 2 main::@24/(signed byte) 1 main::@26/(signed byte) 1 main::@33/(signed byte) 2 main::@35/(signed byte) 2 main::@42/(signed byte) 2 main::@44/(signed byte) 1 main::@6/(signed byte) 1 main::@8/(signed byte) 2 )
[150] *((byte*)&(struct printf_buffer_number) printf_buffer) ← (byte) 0
[151] if((signed word) printf_sint::value#11<(signed byte) 0) goto printf_sint::@1
to:printf_sint::@2
printf_sint::@1: scope:[printf_sint] from printf_sint
[152] (signed word) printf_sint::value#0 ← - (signed word) printf_sint::value#11
[153] *((byte*)&(struct printf_buffer_number) printf_buffer) ← (byte) '-'
to:printf_sint::@2
printf_sint::@2: scope:[printf_sint] from printf_sint printf_sint::@1
[154] (signed word) printf_sint::value#13 ← phi( printf_sint::@1/(signed word) printf_sint::value#0 printf_sint/(signed word) printf_sint::value#11 )
[155] (word) utoa::value#1 ← (word)(signed word) printf_sint::value#13
[156] call utoa
to:printf_sint::@3
printf_sint::@3: scope:[printf_sint] from printf_sint::@2
[157] (byte) printf_number_buffer::buffer_sign#0 ← *((byte*)&(struct printf_buffer_number) printf_buffer)
[158] call printf_number_buffer
to:printf_sint::@return
printf_sint::@return: scope:[printf_sint] from printf_sint::@3
[159] return
to:@return
(void()) printf_number_buffer((byte) printf_number_buffer::buffer_sign , (byte*) printf_number_buffer::buffer_digits , (byte) printf_number_buffer::format_min_length , (byte) printf_number_buffer::format_justify_left , (byte) printf_number_buffer::format_sign_always , (byte) printf_number_buffer::format_zero_padding , (byte) printf_number_buffer::format_upper_case , (byte) printf_number_buffer::format_radix)
printf_number_buffer: scope:[printf_number_buffer] from printf_sint::@3
[160] phi()
to:printf_number_buffer::@1
printf_number_buffer::@1: scope:[printf_number_buffer] from printf_number_buffer
[161] if((byte) 0==(byte) printf_number_buffer::buffer_sign#0) goto printf_number_buffer::@2
to:printf_number_buffer::@3
printf_number_buffer::@3: scope:[printf_number_buffer] from printf_number_buffer::@1
[162] (byte) printf_char::ch#2 ← (byte) printf_number_buffer::buffer_sign#0
[163] call printf_char
to:printf_number_buffer::@2
printf_number_buffer::@2: scope:[printf_number_buffer] from printf_number_buffer::@1 printf_number_buffer::@3
[164] phi()
[165] call printf_str
to:printf_number_buffer::@return
printf_number_buffer::@return: scope:[printf_number_buffer] from printf_number_buffer::@2
[166] return
to:@return
(void()) utoa((word) utoa::value , (byte*) utoa::buffer , (byte) utoa::radix)
utoa: scope:[utoa] from printf_sint::@2
[167] phi()
to:utoa::@1
utoa::@1: scope:[utoa] from utoa utoa::@4
[168] (byte*) utoa::buffer#11 ← phi( utoa::@4/(byte*) utoa::buffer#14 utoa/(byte*)&(struct printf_buffer_number) printf_buffer+(const byte) OFFSET_STRUCT_PRINTF_BUFFER_NUMBER_DIGITS )
[168] (byte) utoa::started#2 ← phi( utoa::@4/(byte) utoa::started#4 utoa/(byte) 0 )
[168] (word) utoa::value#2 ← phi( utoa::@4/(word) utoa::value#6 utoa/(word) utoa::value#1 )
[168] (byte) utoa::digit#2 ← phi( utoa::@4/(byte) utoa::digit#1 utoa/(byte) 0 )
[169] if((byte) utoa::digit#2<(byte) 5-(byte) 1) goto utoa::@2
to:utoa::@3
utoa::@3: scope:[utoa] from utoa::@1
[170] (byte~) utoa::$11 ← (byte)(word) utoa::value#2
[171] *((byte*) utoa::buffer#11) ← *((const byte*) DIGITS + (byte~) utoa::$11)
[172] (byte*) utoa::buffer#3 ← ++ (byte*) utoa::buffer#11
[173] *((byte*) utoa::buffer#3) ← (byte) 0
to:utoa::@return
utoa::@return: scope:[utoa] from utoa::@3
[174] return
to:@return
utoa::@2: scope:[utoa] from utoa::@1
[175] (byte~) utoa::$10 ← (byte) utoa::digit#2 << (byte) 1
[176] (word) utoa::digit_value#0 ← *((const word*) RADIX_DECIMAL_VALUES + (byte~) utoa::$10)
[177] if((byte) 0!=(byte) utoa::started#2) goto utoa::@5
to:utoa::@7
utoa::@7: scope:[utoa] from utoa::@2
[178] if((word) utoa::value#2>=(word) utoa::digit_value#0) goto utoa::@5
to:utoa::@4
utoa::@4: scope:[utoa] from utoa::@6 utoa::@7
[179] (byte*) utoa::buffer#14 ← phi( utoa::@7/(byte*) utoa::buffer#11 utoa::@6/(byte*) utoa::buffer#4 )
[179] (byte) utoa::started#4 ← phi( utoa::@7/(byte) utoa::started#2 utoa::@6/(byte) 1 )
[179] (word) utoa::value#6 ← phi( utoa::@7/(word) utoa::value#2 utoa::@6/(word) utoa::value#0 )
[180] (byte) utoa::digit#1 ← ++ (byte) utoa::digit#2
to:utoa::@1
utoa::@5: scope:[utoa] from utoa::@2 utoa::@7
[181] (byte*) utoa_append::buffer#0 ← (byte*) utoa::buffer#11
[182] (word) utoa_append::value#0 ← (word) utoa::value#2
[183] (word) utoa_append::sub#0 ← (word) utoa::digit_value#0
[184] call utoa_append
[185] (word) utoa_append::return#0 ← (word) utoa_append::value#2
to:utoa::@6
utoa::@6: scope:[utoa] from utoa::@5
[186] (word) utoa::value#0 ← (word) utoa_append::return#0
[187] (byte*) utoa::buffer#4 ← ++ (byte*) utoa::buffer#11
to:utoa::@4
(word()) utoa_append((byte*) utoa_append::buffer , (word) utoa_append::value , (word) utoa_append::sub)
utoa_append: scope:[utoa_append] from utoa::@5
[188] phi()
to:utoa_append::@1
utoa_append::@1: scope:[utoa_append] from utoa_append utoa_append::@2
[189] (byte) utoa_append::digit#2 ← phi( utoa_append/(byte) 0 utoa_append::@2/(byte) utoa_append::digit#1 )
[189] (word) utoa_append::value#2 ← phi( utoa_append/(word) utoa_append::value#0 utoa_append::@2/(word) utoa_append::value#1 )
[190] if((word) utoa_append::value#2>=(word) utoa_append::sub#0) goto utoa_append::@2
to:utoa_append::@3
utoa_append::@3: scope:[utoa_append] from utoa_append::@1
[191] *((byte*) utoa_append::buffer#0) ← *((const byte*) DIGITS + (byte) utoa_append::digit#2)
to:utoa_append::@return
utoa_append::@return: scope:[utoa_append] from utoa_append::@3
[192] return
to:@return
utoa_append::@2: scope:[utoa_append] from utoa_append::@1
[193] (byte) utoa_append::digit#1 ← ++ (byte) utoa_append::digit#2
[194] (word) utoa_append::value#1 ← (word) utoa_append::value#2 - (word) utoa_append::sub#0
to:utoa_append::@1
(void()) printf_cls()
printf_cls: scope:[printf_cls] from main
[195] phi()
[196] call memset
to:printf_cls::@1
printf_cls::@1: scope:[printf_cls] from printf_cls
[197] (byte*) printf_cursor_ptr ← (byte*) 1024
[198] (byte) printf_cursor_x ← (byte) 0
[199] (byte) printf_cursor_y ← (byte) 0
to:printf_cls::@return
printf_cls::@return: scope:[printf_cls] from printf_cls::@1
[200] return
to:@return

8722
src/test/ref/printf-16.log Normal file

File diff suppressed because one or more lines are too long

254
src/test/ref/printf-16.sym Normal file
View File

@ -0,0 +1,254 @@
(label) @1
(label) @2
(label) @begin
(label) @end
(const byte*) DIGITS[] = (byte*) "0123456789abcdef"z
(const byte) OFFSET_STRUCT_PRINTF_BUFFER_NUMBER_DIGITS = (byte) 1
(const byte) RADIX::BINARY = (number) 2
(const byte) RADIX::DECIMAL = (number) $a
(const byte) RADIX::HEXADECIMAL = (number) $10
(const byte) RADIX::OCTAL = (number) 8
(const word*) RADIX_DECIMAL_VALUES[] = { (word) $2710, (word) $3e8, (word) $64, (word) $a }
(const byte) SIZEOF_STRUCT_PRINTF_BUFFER_NUMBER = (byte) $c
(void()) main()
(label) main::@1
(label) main::@10
(label) main::@11
(label) main::@12
(label) main::@13
(label) main::@14
(label) main::@15
(label) main::@16
(label) main::@17
(label) main::@18
(label) main::@19
(label) main::@2
(label) main::@20
(label) main::@21
(label) main::@22
(label) main::@23
(label) main::@24
(label) main::@25
(label) main::@26
(label) main::@27
(label) main::@28
(label) main::@29
(label) main::@3
(label) main::@30
(label) main::@31
(label) main::@32
(label) main::@33
(label) main::@34
(label) main::@35
(label) main::@36
(label) main::@37
(label) main::@38
(label) main::@39
(label) main::@4
(label) main::@40
(label) main::@41
(label) main::@42
(label) main::@43
(label) main::@44
(label) main::@45
(label) main::@5
(label) main::@6
(label) main::@7
(label) main::@8
(label) main::@9
(label) main::@return
(const byte*) main::str[(byte) 1] = (byte*) ""
(const byte*) main::str1[(byte) 3] = (byte*) "d "
(const byte*) main::str12[(byte) 6] = (byte*) "1$d: "
(const byte*) main::str16[(byte) 5] = (byte*) "2$d "
(const byte*) main::str2[(byte) 8] = (byte*) "d: "
(const byte*) main::str3[(byte) 2] = (byte*) " "
(const byte*) main::str4[(byte) 2] = (byte*) "
"
(const byte*) main::str6[(byte) 5] = (byte*) "1$d "
(const byte*) main::str7[(byte) 6] = (byte*) "2$d: "
(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]:11 1.000000001E9
(byte*) memcpy::dst#2 dst zp[2]:11 1.000000001E9
(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]:5 2.000000002E9
(byte*) memcpy::src#2 src zp[2]:5 1.000000001E9
(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::@3
(label) memset::@return
(byte) memset::c
(byte) memset::c#4 reg byte x 1.25000000125E8
(byte*) memset::dst
(byte*) memset::dst#1 dst zp[2]:11 2.000000002E9
(byte*) memset::dst#2 dst zp[2]:11 1.3366666683333335E9
(byte*) memset::dst#4 dst zp[2]:11 2.0000002E7
(byte*) memset::end
(byte*) memset::end#0 end zp[2]:5 1.683333336666667E8
(word) memset::num
(word) memset::num#2 num zp[2]:5 1.0000001E7
(void*) memset::return
(void*) memset::str
(void*) memset::str#3 str zp[2]:11
(struct printf_buffer_number) printf_buffer loadstore mem[12] = {}
(const byte*) printf_buffer_number::digits[(number) $b] = { fill( $b, 0) }
(byte) printf_buffer_number::sign
(void()) printf_char((byte) printf_char::ch)
(byte*~) printf_char::$6 zp[2]:9 2000002.0
(label) printf_char::@1
(label) printf_char::@2
(label) printf_char::@3
(label) printf_char::@4
(label) printf_char::@return
(byte) printf_char::ch
(byte) printf_char::ch#1 reg byte a 200002.0
(byte) printf_char::ch#13 reg byte a 1101003.0
(byte) printf_char::ch#2 reg byte a 2002.0
(void()) printf_cls()
(label) printf_cls::@1
(label) printf_cls::@return
(byte*) printf_cursor_ptr loadstore zp[2]:9 49296.54929577465
(byte) printf_cursor_x loadstore zp[1]:7 42553.96453900709
(byte) printf_cursor_y loadstore zp[1]:8 48951.818181818184
(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]:9 2000002.0
(byte*~) printf_ln::$1 zp[2]:9 2000002.0
(label) printf_ln::@return
(void()) printf_number_buffer((byte) printf_number_buffer::buffer_sign , (byte*) printf_number_buffer::buffer_digits , (byte) printf_number_buffer::format_min_length , (byte) printf_number_buffer::format_justify_left , (byte) printf_number_buffer::format_sign_always , (byte) printf_number_buffer::format_zero_padding , (byte) printf_number_buffer::format_upper_case , (byte) printf_number_buffer::format_radix)
(label) printf_number_buffer::@1
(label) printf_number_buffer::@2
(label) printf_number_buffer::@3
(label) printf_number_buffer::@return
(struct printf_buffer_number) printf_number_buffer::buffer
(byte*) printf_number_buffer::buffer_digits
(const byte*) printf_number_buffer::buffer_digits#0 buffer_digits = (byte*)&(struct printf_buffer_number) printf_buffer+(const byte) OFFSET_STRUCT_PRINTF_BUFFER_NUMBER_DIGITS
(byte) printf_number_buffer::buffer_sign
(byte) printf_number_buffer::buffer_sign#0 reg byte a 701.0
(struct printf_format_number) printf_number_buffer::format
(byte) printf_number_buffer::format_justify_left
(byte) printf_number_buffer::format_min_length
(byte) printf_number_buffer::format_radix
(byte) printf_number_buffer::format_sign_always
(byte) printf_number_buffer::format_upper_case
(byte) printf_number_buffer::format_zero_padding
(signed byte) printf_number_buffer::len
(signed byte) printf_number_buffer::padding
(void()) printf_sint((signed word) printf_sint::value , (byte) printf_sint::format_min_length , (byte) printf_sint::format_justify_left , (byte) printf_sint::format_sign_always , (byte) printf_sint::format_zero_padding , (byte) printf_sint::format_upper_case , (byte) printf_sint::format_radix)
(label) printf_sint::@1
(label) printf_sint::@2
(label) printf_sint::@3
(label) printf_sint::@return
(struct printf_format_number) printf_sint::format
(byte) printf_sint::format_justify_left
(byte) printf_sint::format_min_length
(byte) printf_sint::format_radix
(byte) printf_sint::format_sign_always
(byte) printf_sint::format_upper_case
(byte) printf_sint::format_zero_padding
(word) printf_sint::uvalue
(signed word) printf_sint::value
(signed word) printf_sint::value#0 value zp[2]:2 101.0
(signed word) printf_sint::value#11 value zp[2]:2 101.0
(signed word) printf_sint::value#13 value zp[2]:2 202.0
(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 100001.0
(byte*) printf_str::str
(byte*) printf_str::str#0 str zp[2]:2 42857.57142857143
(byte*) printf_str::str#27 str zp[2]:2 205002.5
(byte*) printf_str::str#29 str zp[2]:2 10001.0
(void()) utoa((word) utoa::value , (byte*) utoa::buffer , (byte) utoa::radix)
(byte~) utoa::$10 reg byte a 20002.0
(byte~) utoa::$11 reg byte a 2002.0
(label) utoa::@1
(label) utoa::@2
(label) utoa::@3
(label) utoa::@4
(label) utoa::@5
(label) utoa::@6
(label) utoa::@7
(label) utoa::@return
(byte*) utoa::buffer
(byte*) utoa::buffer#11 buffer zp[2]:5 3000.4285714285716
(byte*) utoa::buffer#14 buffer zp[2]:5 15001.5
(byte*) utoa::buffer#3 buffer zp[2]:5 2002.0
(byte*) utoa::buffer#4 buffer zp[2]:5 20002.0
(byte) utoa::digit
(byte) utoa::digit#1 digit zp[1]:4 20002.0
(byte) utoa::digit#2 digit zp[1]:4 2857.4285714285716
(word) utoa::digit_value
(word) utoa::digit_value#0 digit_value zp[2]:11 6000.6
(word*) utoa::digit_values
(byte) utoa::max_digits
(byte) utoa::radix
(byte) utoa::started
(byte) utoa::started#2 reg byte x 5000.5
(byte) utoa::started#4 reg byte x 10001.0
(word) utoa::value
(word) utoa::value#0 value zp[2]:2 10001.0
(word) utoa::value#1 value zp[2]:2 551.0
(word) utoa::value#2 value zp[2]:2 5857.857142857143
(word) utoa::value#6 value zp[2]:2 15001.5
(word()) utoa_append((byte*) utoa_append::buffer , (word) utoa_append::value , (word) utoa_append::sub)
(label) utoa_append::@1
(label) utoa_append::@2
(label) utoa_append::@3
(label) utoa_append::@return
(byte*) utoa_append::buffer
(byte*) utoa_append::buffer#0 buffer zp[2]:5 13750.25
(byte) utoa_append::digit
(byte) utoa_append::digit#1 reg byte x 1.0000001E7
(byte) utoa_append::digit#2 reg byte x 1.00500015E7
(word) utoa_append::return
(word) utoa_append::return#0 return zp[2]:2 20002.0
(word) utoa_append::sub
(word) utoa_append::sub#0 sub zp[2]:11 3335000.5
(word) utoa_append::value
(word) utoa_append::value#0 value zp[2]:2 36667.33333333333
(word) utoa_append::value#1 value zp[2]:2 2.0000002E7
(word) utoa_append::value#2 value zp[2]:2 5018334.166666666
reg byte a [ printf_char::ch#13 printf_char::ch#2 printf_char::ch#1 ]
reg byte x [ memset::c#4 ]
zp[2]:2 [ printf_sint::value#13 printf_sint::value#0 printf_sint::value#11 utoa::value#2 utoa::value#6 utoa::value#1 utoa::value#0 utoa_append::value#2 utoa_append::value#0 utoa_append::value#1 utoa_append::return#0 printf_str::str#27 printf_str::str#29 printf_str::str#0 ]
zp[1]:4 [ utoa::digit#2 utoa::digit#1 ]
reg byte x [ utoa::started#2 utoa::started#4 ]
zp[2]:5 [ utoa::buffer#11 utoa::buffer#14 utoa::buffer#4 utoa::buffer#3 utoa_append::buffer#0 memcpy::src#2 memcpy::src#1 memset::num#2 memset::end#0 ]
reg byte x [ utoa_append::digit#2 utoa_append::digit#1 ]
zp[1]:7 [ printf_cursor_x ]
zp[1]:8 [ printf_cursor_y ]
zp[2]:9 [ printf_cursor_ptr printf_char::$6 printf_ln::$0 printf_ln::$1 ]
reg byte a [ printf_str::ch#0 ]
reg byte a [ printf_number_buffer::buffer_sign#0 ]
reg byte a [ utoa::$11 ]
reg byte a [ utoa::$10 ]
zp[2]:11 [ utoa::digit_value#0 utoa_append::sub#0 memcpy::dst#2 memcpy::dst#1 memset::str#3 memset::dst#2 memset::dst#4 memset::dst#1 ]
mem[12] [ printf_buffer ]