mirror of
https://gitlab.com/camelot/kickc.git
synced 2025-02-10 10:31:27 +00:00
Added printf() support for %d, %i, %x, %o and length specifiers %hhd %ld.
This commit is contained in:
parent
28c9b2ada7
commit
d7143771ba
@ -24,10 +24,21 @@ public class Pass1PrintfIntrinsicRewrite extends Pass2SsaOptimization {
|
||||
public static final String INTRINSIC_PRINTF_NAME = "printf";
|
||||
/** The printf routine used to print formatted strings. */
|
||||
public static final String PRINTF_STRING = "printf_string";
|
||||
/** The printf routine used to print signed chars. */
|
||||
public static final String PRINTF_SCHAR = "printf_schar";
|
||||
/** The printf routine used to print unsigned chars. */
|
||||
public static final String PRINTF_UCHAR = "printf_uchar";
|
||||
/** The printf routine used to print signed integers. */
|
||||
public static final String PRINTF_SINT = "printf_sint";
|
||||
/** The printf routine used to print unsigned integers. */
|
||||
public static final String PRINTF_UINT = "printf_uint";
|
||||
/** The printf routine used to print signed long integers. */
|
||||
public static final String PRINTF_SLONG = "printf_slong";
|
||||
/** The printf routine used to print unsigned long integers. */
|
||||
public static final String PRINTF_ULONG = "printf_ulong";
|
||||
public static final String DECIMAL = "DECIMAL";
|
||||
public static final String HEXADECIMAL = "HEXADECIMAL";
|
||||
public static final String OCTAL = "OCTAL";
|
||||
|
||||
public Pass1PrintfIntrinsicRewrite(Program program) {
|
||||
super(program);
|
||||
@ -78,17 +89,13 @@ public class Pass1PrintfIntrinsicRewrite extends Pass2SsaOptimization {
|
||||
final String paramField = matcher.group(1);
|
||||
if(paramField != null)
|
||||
throw new CompileError("printf parameter field not supported", printfCall);
|
||||
|
||||
final String flagsField = matcher.group(2);
|
||||
long leftJustify = (flagsField != null && flagsField.contains("-")) ? 1 : 0;
|
||||
long signAlways = (flagsField != null && flagsField.contains("+")) ? 1 : 0;
|
||||
long zeroPadding = (flagsField != null && flagsField.contains("0")) ? 1 : 0;
|
||||
|
||||
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);
|
||||
|
||||
// First output the non-matching part before the pattern
|
||||
@ -96,7 +103,6 @@ public class Pass1PrintfIntrinsicRewrite extends Pass2SsaOptimization {
|
||||
printfConstantString(prefix, printfCall, stmtIt, formatEncoding);
|
||||
formatIdx = end;
|
||||
|
||||
|
||||
if(typeField.equals("s")) {
|
||||
// A formatted string
|
||||
//struct printf_format_string {
|
||||
@ -116,14 +122,43 @@ public class Pass1PrintfIntrinsicRewrite extends Pass2SsaOptimization {
|
||||
// A formatted integer
|
||||
SymbolVariableRef radix;
|
||||
String printf_number_procedure;
|
||||
if(typeField.equals("d")) {
|
||||
radix = getScope().getLocalConstant("DECIMAL").getRef();
|
||||
printf_number_procedure = PRINTF_SINT;
|
||||
} else if(typeField.equals("x")) {
|
||||
radix = getScope().getLocalConstant("HEXADECIMAL").getRef();
|
||||
printf_number_procedure = PRINTF_UINT;
|
||||
boolean signed;
|
||||
switch(typeField) {
|
||||
case "d":
|
||||
case "i":
|
||||
radix = getScope().getLocalConstant(DECIMAL).getRef();
|
||||
signed = true;
|
||||
break;
|
||||
case "u":
|
||||
radix = getScope().getLocalConstant(DECIMAL).getRef();
|
||||
signed = false;
|
||||
break;
|
||||
case "x":
|
||||
radix = getScope().getLocalConstant(HEXADECIMAL).getRef();
|
||||
signed = false;
|
||||
break;
|
||||
case "X":
|
||||
throw new CompileError("printf hexadecimal upper case not supported", printfCall);
|
||||
case "o":
|
||||
radix = getScope().getLocalConstant(OCTAL).getRef();
|
||||
signed = false;
|
||||
break;
|
||||
default:
|
||||
throw new CompileError("printf type field not supported", printfCall);
|
||||
}
|
||||
|
||||
if(lengthField == null) {
|
||||
// Integer (16bit)
|
||||
printf_number_procedure = signed ? PRINTF_SINT : PRINTF_UINT;
|
||||
} else if(lengthField.equals("hh")) {
|
||||
// TODO: Handle 8-bits in a better way - since KickC does not do integer promotion!
|
||||
// Integer (8bit)
|
||||
printf_number_procedure = signed ? PRINTF_SCHAR : PRINTF_UCHAR;
|
||||
} else if(lengthField.equals("l")) {
|
||||
// Integer (32bit)
|
||||
printf_number_procedure = signed ? PRINTF_SLONG : PRINTF_ULONG;
|
||||
} else {
|
||||
throw new CompileError("printf type field not supported", printfCall);
|
||||
throw new CompileError("printf length field not supported", printfCall);
|
||||
}
|
||||
|
||||
// Format specifying how to format a printed number
|
||||
|
@ -41,7 +41,12 @@ public class TestPrograms {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPintf10() throws IOException, URISyntaxException {
|
||||
public void testPrintf11() throws IOException, URISyntaxException {
|
||||
compileAndCompare("printf-11.c");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrintf10() throws IOException, URISyntaxException {
|
||||
compileAndCompare("printf-10.c");
|
||||
}
|
||||
|
||||
|
@ -26,37 +26,9 @@ void printf_string(char* str, struct printf_format_string format) {
|
||||
printf_str(str);
|
||||
}
|
||||
|
||||
// The different supported radix
|
||||
enum RADIX { BINARY=2, OCTAL=8, DECIMAL=10, HEXADECIMAL=16 };
|
||||
|
||||
// Format specifying how to format a printed number
|
||||
struct printf_format_number {
|
||||
// The minimal number of chars to output (used for padding with spaces or 0)
|
||||
char min_length;
|
||||
// Justify left instead of right, which is the default.
|
||||
char justify_left;
|
||||
// Always show a sign for a number, even if is is positive. (Default is to only show sign for negative numbers)
|
||||
char sign_always;
|
||||
// Pad the number with zeros to get the min width
|
||||
char zero_padding;
|
||||
// The number radix to use for formatting
|
||||
enum RADIX radix;
|
||||
};
|
||||
|
||||
const char printf_hextab[] = "0123456789abcdef"z;
|
||||
|
||||
// Print an unsigned int using a specific format
|
||||
// Always prints hexadecimals - ignores min_length and flags
|
||||
void printf_uint(unsigned int uvalue, struct printf_format_number format) {
|
||||
*screen++ = printf_hextab[(>uvalue)>>4];
|
||||
*screen++ = printf_hextab[(>uvalue)&0xf];
|
||||
*screen++ = printf_hextab[(<uvalue)>>4];
|
||||
*screen++ = printf_hextab[(<uvalue)&0xf];
|
||||
}
|
||||
|
||||
void main() {
|
||||
unsigned int age = 46;
|
||||
printf("Hello, I am %s. who are you?", "Jesper");
|
||||
printf("I am %x years old", age);
|
||||
char* name = "Jesper";
|
||||
printf("Hello, I am %s. who are you?", name);
|
||||
}
|
||||
|
||||
|
47
src/test/kc/printf-11.c
Normal file
47
src/test/kc/printf-11.c
Normal file
@ -0,0 +1,47 @@
|
||||
// Tests printf function call rewriting
|
||||
// A simple number - with the printf-sub funtions in the same file.
|
||||
|
||||
__intrinsic void printf(char* format, ...);
|
||||
|
||||
char * screen = 0x0400;
|
||||
char idx = 0;
|
||||
|
||||
void printf_str(char* str) {
|
||||
while(*str) {
|
||||
*screen++ = *str++;
|
||||
}
|
||||
}
|
||||
|
||||
// The different supported radix
|
||||
enum RADIX { BINARY=2, OCTAL=8, DECIMAL=10, HEXADECIMAL=16 };
|
||||
|
||||
// Format specifying how to format a printed number
|
||||
struct printf_format_number {
|
||||
// The minimal number of chars to output (used for padding with spaces or 0)
|
||||
char min_length;
|
||||
// Justify left instead of right, which is the default.
|
||||
char justify_left;
|
||||
// Always show a sign for a number, even if is is positive. (Default is to only show sign for negative numbers)
|
||||
char sign_always;
|
||||
// Pad the number with zeros to get the min width
|
||||
char zero_padding;
|
||||
// The number radix to use for formatting
|
||||
enum RADIX radix;
|
||||
};
|
||||
|
||||
const char printf_hextab[] = "0123456789abcdef"z;
|
||||
|
||||
// Print an unsigned int using a specific format
|
||||
// Always prints hexadecimals - ignores min_length and flags
|
||||
void printf_uint(unsigned int uvalue, struct printf_format_number format) {
|
||||
*screen++ = printf_hextab[(>uvalue)>>4];
|
||||
*screen++ = printf_hextab[(>uvalue)&0xf];
|
||||
*screen++ = printf_hextab[(<uvalue)>>4];
|
||||
*screen++ = printf_hextab[(<uvalue)&0xf];
|
||||
}
|
||||
|
||||
void main() {
|
||||
unsigned int pct = 342;
|
||||
printf("Commodore is %x cool", pct);
|
||||
}
|
||||
|
@ -5,8 +5,7 @@
|
||||
.pc = $80d "Program"
|
||||
.label screen = 2
|
||||
main: {
|
||||
.label age = $2e
|
||||
// printf("Hello, I am %s. who are you?", "Jesper")
|
||||
// printf("Hello, I am %s. who are you?", name)
|
||||
lda #<$400
|
||||
sta.z screen
|
||||
lda #>$400
|
||||
@ -16,39 +15,21 @@ main: {
|
||||
lda #>str
|
||||
sta.z printf_str.str+1
|
||||
jsr printf_str
|
||||
// printf("Hello, I am %s. who are you?", "Jesper")
|
||||
// printf("Hello, I am %s. who are you?", name)
|
||||
jsr printf_string
|
||||
// printf("Hello, I am %s. who are you?", "Jesper")
|
||||
lda #<str2
|
||||
// printf("Hello, I am %s. who are you?", name)
|
||||
lda #<str1
|
||||
sta.z printf_str.str
|
||||
lda #>str2
|
||||
sta.z printf_str.str+1
|
||||
jsr printf_str
|
||||
// printf("I am %x years old", age)
|
||||
lda #<str3
|
||||
sta.z printf_str.str
|
||||
lda #>str3
|
||||
sta.z printf_str.str+1
|
||||
jsr printf_str
|
||||
// printf("I am %x years old", age)
|
||||
jsr printf_uint
|
||||
// printf("I am %x years old", age)
|
||||
lda #<str4
|
||||
sta.z printf_str.str
|
||||
lda #>str4
|
||||
lda #>str1
|
||||
sta.z printf_str.str+1
|
||||
jsr printf_str
|
||||
// }
|
||||
rts
|
||||
name: .text "Jesper"
|
||||
.byte 0
|
||||
str: .text "Hello, I am "
|
||||
.byte 0
|
||||
str1: .text "Jesper"
|
||||
.byte 0
|
||||
str2: .text ". who are you?"
|
||||
.byte 0
|
||||
str3: .text "I am "
|
||||
.byte 0
|
||||
str4: .text " years old"
|
||||
str1: .text ". who are you?"
|
||||
.byte 0
|
||||
}
|
||||
// printf_str(byte* zp(4) str)
|
||||
@ -78,58 +59,15 @@ printf_str: {
|
||||
!:
|
||||
jmp __b1
|
||||
}
|
||||
// Print an unsigned int using a specific format
|
||||
// Always prints hexadecimals - ignores min_length and flags
|
||||
printf_uint: {
|
||||
// *screen++ = printf_hextab[(>uvalue)>>4]
|
||||
lda printf_hextab
|
||||
ldy #0
|
||||
sta (screen),y
|
||||
// *screen++ = printf_hextab[(>uvalue)>>4];
|
||||
inc.z screen
|
||||
bne !+
|
||||
inc.z screen+1
|
||||
!:
|
||||
// *screen++ = printf_hextab[(>uvalue)&0xf]
|
||||
lda printf_hextab
|
||||
ldy #0
|
||||
sta (screen),y
|
||||
// *screen++ = printf_hextab[(>uvalue)&0xf];
|
||||
inc.z screen
|
||||
bne !+
|
||||
inc.z screen+1
|
||||
!:
|
||||
// *screen++ = printf_hextab[(<uvalue)>>4]
|
||||
lda printf_hextab+((<main.age)>>4)
|
||||
ldy #0
|
||||
sta (screen),y
|
||||
// *screen++ = printf_hextab[(<uvalue)>>4];
|
||||
inc.z screen
|
||||
bne !+
|
||||
inc.z screen+1
|
||||
!:
|
||||
// *screen++ = printf_hextab[(<uvalue)&0xf]
|
||||
lda printf_hextab+((<main.age)&$f)
|
||||
ldy #0
|
||||
sta (screen),y
|
||||
// *screen++ = printf_hextab[(<uvalue)&0xf];
|
||||
inc.z screen
|
||||
bne !+
|
||||
inc.z screen+1
|
||||
!:
|
||||
// }
|
||||
rts
|
||||
}
|
||||
// Print a string value using a specific format
|
||||
// Handles justification and min length
|
||||
printf_string: {
|
||||
// printf_str(str)
|
||||
lda #<main.str1
|
||||
lda #<main.name
|
||||
sta.z printf_str.str
|
||||
lda #>main.str1
|
||||
lda #>main.name
|
||||
sta.z printf_str.str+1
|
||||
jsr printf_str
|
||||
// }
|
||||
rts
|
||||
}
|
||||
printf_hextab: .text "0123456789abcdef"
|
||||
|
@ -20,62 +20,35 @@ main::@1: scope:[main] from main
|
||||
main::@2: scope:[main] from main::@1
|
||||
[8] phi()
|
||||
[9] call printf_str
|
||||
to:main::@3
|
||||
main::@3: scope:[main] from main::@2
|
||||
[10] phi()
|
||||
[11] call printf_str
|
||||
to:main::@4
|
||||
main::@4: scope:[main] from main::@3
|
||||
[12] phi()
|
||||
[13] call printf_uint
|
||||
to:main::@5
|
||||
main::@5: scope:[main] from main::@4
|
||||
[14] phi()
|
||||
[15] call printf_str
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@5
|
||||
[16] return
|
||||
main::@return: scope:[main] from main::@2
|
||||
[10] return
|
||||
to:@return
|
||||
|
||||
(void()) printf_str((byte*) printf_str::str)
|
||||
printf_str: scope:[printf_str] from main main::@2 main::@3 main::@5 printf_string
|
||||
[17] (byte*) screen#36 ← phi( main/(byte*) 1024 main::@2/(byte*) screen#18 main::@3/(byte*) screen#18 main::@5/(byte*) screen#23 printf_string/(byte*) screen#18 )
|
||||
[17] (byte*) printf_str::str#8 ← phi( main/(const byte*) main::str main::@2/(const byte*) main::str2 main::@3/(const byte*) main::str3 main::@5/(const byte*) main::str4 printf_string/(const byte*) main::str1 )
|
||||
printf_str: scope:[printf_str] from main main::@2 printf_string
|
||||
[11] (byte*) screen#23 ← phi( main/(byte*) 1024 main::@2/(byte*) screen#10 printf_string/(byte*) screen#10 )
|
||||
[11] (byte*) printf_str::str#6 ← phi( main/(const byte*) main::str main::@2/(const byte*) main::str1 printf_string/(const byte*) main::name )
|
||||
to:printf_str::@1
|
||||
printf_str::@1: scope:[printf_str] from printf_str printf_str::@2
|
||||
[18] (byte*) screen#18 ← phi( printf_str/(byte*) screen#36 printf_str::@2/(byte*) screen#1 )
|
||||
[18] (byte*) printf_str::str#6 ← phi( printf_str/(byte*) printf_str::str#8 printf_str::@2/(byte*) printf_str::str#0 )
|
||||
[19] if((byte) 0!=*((byte*) printf_str::str#6)) goto printf_str::@2
|
||||
[12] (byte*) screen#10 ← phi( printf_str/(byte*) screen#23 printf_str::@2/(byte*) screen#1 )
|
||||
[12] (byte*) printf_str::str#4 ← phi( printf_str/(byte*) printf_str::str#6 printf_str::@2/(byte*) printf_str::str#0 )
|
||||
[13] if((byte) 0!=*((byte*) printf_str::str#4)) goto printf_str::@2
|
||||
to:printf_str::@return
|
||||
printf_str::@return: scope:[printf_str] from printf_str::@1
|
||||
[20] return
|
||||
[14] return
|
||||
to:@return
|
||||
printf_str::@2: scope:[printf_str] from printf_str::@1
|
||||
[21] *((byte*) screen#18) ← *((byte*) printf_str::str#6)
|
||||
[22] (byte*) screen#1 ← ++ (byte*) screen#18
|
||||
[23] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#6
|
||||
[15] *((byte*) screen#10) ← *((byte*) printf_str::str#4)
|
||||
[16] (byte*) screen#1 ← ++ (byte*) screen#10
|
||||
[17] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#4
|
||||
to:printf_str::@1
|
||||
|
||||
(void()) printf_uint((word) printf_uint::uvalue , (byte) printf_uint::format_min_length , (byte) printf_uint::format_justify_left , (byte) printf_uint::format_sign_always , (byte) printf_uint::format_zero_padding , (byte) printf_uint::format_radix)
|
||||
printf_uint: scope:[printf_uint] from main::@4
|
||||
[24] *((byte*) screen#18) ← *((const to_nomodify byte*) printf_hextab)
|
||||
[25] (byte*) screen#5 ← ++ (byte*) screen#18
|
||||
[26] *((byte*) screen#5) ← *((const to_nomodify byte*) printf_hextab)
|
||||
[27] (byte*) screen#6 ← ++ (byte*) screen#5
|
||||
[28] *((byte*) screen#6) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::age>>(byte) 4)
|
||||
[29] (byte*) screen#7 ← ++ (byte*) screen#6
|
||||
[30] *((byte*) screen#7) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::age&(byte) $f)
|
||||
[31] (byte*) screen#23 ← ++ (byte*) screen#7
|
||||
to:printf_uint::@return
|
||||
printf_uint::@return: scope:[printf_uint] from printf_uint
|
||||
[32] return
|
||||
to:@return
|
||||
|
||||
(void()) printf_string((byte*) printf_string::str , (byte) printf_string::format_min_length , (byte) printf_string::format_justify_left)
|
||||
printf_string: scope:[printf_string] from main::@1
|
||||
[33] phi()
|
||||
[34] call printf_str
|
||||
[18] phi()
|
||||
[19] call printf_str
|
||||
to:printf_string::@return
|
||||
printf_string::@return: scope:[printf_string] from printf_string
|
||||
[35] return
|
||||
[20] return
|
||||
to:@return
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,62 +1,33 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) RADIX::BINARY = (number) 2
|
||||
(const byte) RADIX::DECIMAL = (number) $a
|
||||
(const byte) RADIX::HEXADECIMAL = (number) $10
|
||||
(const byte) RADIX::OCTAL = (number) 8
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@3
|
||||
(label) main::@4
|
||||
(label) main::@5
|
||||
(label) main::@return
|
||||
(const word) main::age = (word) $2e
|
||||
(const byte*) main::name = (byte*) "Jesper"
|
||||
(const byte*) main::str[(byte) $d] = (byte*) "Hello, I am "
|
||||
(const byte*) main::str1[(byte) 7] = (byte*) "Jesper"
|
||||
(const byte*) main::str2[(byte) $f] = (byte*) ". who are you?"
|
||||
(const byte*) main::str3[(byte) 6] = (byte*) "I am "
|
||||
(const byte*) main::str4[(byte) $b] = (byte*) " years old"
|
||||
(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::zero_padding
|
||||
(const byte*) main::str1[(byte) $f] = (byte*) ". who are you?"
|
||||
(byte) printf_format_string::justify_left
|
||||
(byte) printf_format_string::min_length
|
||||
(const to_nomodify byte*) printf_hextab[] = (byte*) "0123456789abcdef"z
|
||||
(void()) printf_str((byte*) printf_str::str)
|
||||
(label) printf_str::@1
|
||||
(label) printf_str::@2
|
||||
(label) printf_str::@return
|
||||
(byte*) printf_str::str
|
||||
(byte*) printf_str::str#0 str zp[2]:4 20002.0
|
||||
(byte*) printf_str::str#6 str zp[2]:4 10251.25
|
||||
(byte*) printf_str::str#8 str zp[2]:4 1001.0
|
||||
(byte*) printf_str::str#4 str zp[2]:4 10251.25
|
||||
(byte*) printf_str::str#6 str zp[2]:4 1001.0
|
||||
(void()) printf_string((byte*) printf_string::str , (byte) printf_string::format_min_length , (byte) printf_string::format_justify_left)
|
||||
(label) printf_string::@return
|
||||
(struct printf_format_string) printf_string::format
|
||||
(byte) printf_string::format_justify_left
|
||||
(byte) printf_string::format_min_length
|
||||
(byte*) printf_string::str
|
||||
(void()) printf_uint((word) printf_uint::uvalue , (byte) printf_uint::format_min_length , (byte) printf_uint::format_justify_left , (byte) printf_uint::format_sign_always , (byte) printf_uint::format_zero_padding , (byte) printf_uint::format_radix)
|
||||
(label) printf_uint::@return
|
||||
(struct printf_format_number) printf_uint::format
|
||||
(byte) printf_uint::format_justify_left
|
||||
(byte) printf_uint::format_min_length
|
||||
(byte) printf_uint::format_radix
|
||||
(byte) printf_uint::format_sign_always
|
||||
(byte) printf_uint::format_zero_padding
|
||||
(word) printf_uint::uvalue
|
||||
(byte*) screen
|
||||
(byte*) screen#1 screen zp[2]:2 10001.0
|
||||
(byte*) screen#18 screen zp[2]:2 1958.0625
|
||||
(byte*) screen#23 screen zp[2]:2 28.0
|
||||
(byte*) screen#36 screen zp[2]:2 1135.0
|
||||
(byte*) screen#5 screen zp[2]:2 151.5
|
||||
(byte*) screen#6 screen zp[2]:2 151.5
|
||||
(byte*) screen#7 screen zp[2]:2 151.5
|
||||
(byte*) screen#10 screen zp[2]:2 2828.7272727272725
|
||||
(byte*) screen#23 screen zp[2]:2 1113.0
|
||||
|
||||
zp[2]:2 [ screen#36 screen#18 screen#23 screen#1 screen#5 screen#7 screen#6 ]
|
||||
zp[2]:4 [ printf_str::str#6 printf_str::str#8 printf_str::str#0 ]
|
||||
zp[2]:2 [ screen#23 screen#10 screen#1 ]
|
||||
zp[2]:4 [ printf_str::str#4 printf_str::str#6 printf_str::str#0 ]
|
||||
|
103
src/test/ref/printf-11.asm
Normal file
103
src/test/ref/printf-11.asm
Normal file
@ -0,0 +1,103 @@
|
||||
// Tests printf function call rewriting
|
||||
// A simple number - with the printf-sub funtions in the same file.
|
||||
.pc = $801 "Basic"
|
||||
:BasicUpstart(main)
|
||||
.pc = $80d "Program"
|
||||
.label screen = 4
|
||||
main: {
|
||||
.label pct = $156
|
||||
// printf("Commodore is %x cool", pct)
|
||||
lda #<$400
|
||||
sta.z screen
|
||||
lda #>$400
|
||||
sta.z screen+1
|
||||
lda #<str
|
||||
sta.z printf_str.str
|
||||
lda #>str
|
||||
sta.z printf_str.str+1
|
||||
jsr printf_str
|
||||
// printf("Commodore is %x cool", pct)
|
||||
jsr printf_uint
|
||||
// printf("Commodore is %x cool", pct)
|
||||
lda #<str1
|
||||
sta.z printf_str.str
|
||||
lda #>str1
|
||||
sta.z printf_str.str+1
|
||||
jsr printf_str
|
||||
// }
|
||||
rts
|
||||
str: .text "Commodore is "
|
||||
.byte 0
|
||||
str1: .text " cool"
|
||||
.byte 0
|
||||
}
|
||||
// printf_str(byte* zp(2) str)
|
||||
printf_str: {
|
||||
.label str = 2
|
||||
__b1:
|
||||
// while(*str)
|
||||
ldy #0
|
||||
lda (str),y
|
||||
cmp #0
|
||||
bne __b2
|
||||
// }
|
||||
rts
|
||||
__b2:
|
||||
// *screen++ = *str++
|
||||
ldy #0
|
||||
lda (str),y
|
||||
sta (screen),y
|
||||
// *screen++ = *str++;
|
||||
inc.z screen
|
||||
bne !+
|
||||
inc.z screen+1
|
||||
!:
|
||||
inc.z str
|
||||
bne !+
|
||||
inc.z str+1
|
||||
!:
|
||||
jmp __b1
|
||||
}
|
||||
// Print an unsigned int using a specific format
|
||||
// Always prints hexadecimals - ignores min_length and flags
|
||||
printf_uint: {
|
||||
// *screen++ = printf_hextab[(>uvalue)>>4]
|
||||
lda printf_hextab
|
||||
ldy #0
|
||||
sta (screen),y
|
||||
// *screen++ = printf_hextab[(>uvalue)>>4];
|
||||
inc.z screen
|
||||
bne !+
|
||||
inc.z screen+1
|
||||
!:
|
||||
// *screen++ = printf_hextab[(>uvalue)&0xf]
|
||||
lda printf_hextab+((>main.pct)&$f)
|
||||
ldy #0
|
||||
sta (screen),y
|
||||
// *screen++ = printf_hextab[(>uvalue)&0xf];
|
||||
inc.z screen
|
||||
bne !+
|
||||
inc.z screen+1
|
||||
!:
|
||||
// *screen++ = printf_hextab[(<uvalue)>>4]
|
||||
lda printf_hextab+((<main.pct)>>4)
|
||||
ldy #0
|
||||
sta (screen),y
|
||||
// *screen++ = printf_hextab[(<uvalue)>>4];
|
||||
inc.z screen
|
||||
bne !+
|
||||
inc.z screen+1
|
||||
!:
|
||||
// *screen++ = printf_hextab[(<uvalue)&0xf]
|
||||
lda printf_hextab+((<main.pct)&$f)
|
||||
ldy #0
|
||||
sta (screen),y
|
||||
// *screen++ = printf_hextab[(<uvalue)&0xf];
|
||||
inc.z screen
|
||||
bne !+
|
||||
inc.z screen+1
|
||||
!:
|
||||
// }
|
||||
rts
|
||||
}
|
||||
printf_hextab: .text "0123456789abcdef"
|
60
src/test/ref/printf-11.cfg
Normal file
60
src/test/ref/printf-11.cfg
Normal file
@ -0,0 +1,60 @@
|
||||
@begin: scope:[] from
|
||||
[0] phi()
|
||||
to:@1
|
||||
@1: scope:[] from @begin
|
||||
[1] phi()
|
||||
[2] call main
|
||||
to:@end
|
||||
@end: scope:[] from @1
|
||||
[3] phi()
|
||||
|
||||
(void()) main()
|
||||
main: scope:[main] from @1
|
||||
[4] phi()
|
||||
[5] call printf_str
|
||||
to:main::@1
|
||||
main::@1: scope:[main] from main
|
||||
[6] phi()
|
||||
[7] call printf_uint
|
||||
to:main::@2
|
||||
main::@2: scope:[main] from main::@1
|
||||
[8] phi()
|
||||
[9] call printf_str
|
||||
to:main::@return
|
||||
main::@return: scope:[main] from main::@2
|
||||
[10] return
|
||||
to:@return
|
||||
|
||||
(void()) printf_str((byte*) printf_str::str)
|
||||
printf_str: scope:[printf_str] from main main::@2
|
||||
[11] (byte*) screen#25 ← phi( main/(byte*) 1024 main::@2/(byte*) screen#16 )
|
||||
[11] (byte*) printf_str::str#5 ← phi( main/(const byte*) main::str main::@2/(const byte*) main::str1 )
|
||||
to:printf_str::@1
|
||||
printf_str::@1: scope:[printf_str] from printf_str printf_str::@2
|
||||
[12] (byte*) screen#13 ← phi( printf_str/(byte*) screen#25 printf_str::@2/(byte*) screen#1 )
|
||||
[12] (byte*) printf_str::str#3 ← phi( printf_str/(byte*) printf_str::str#5 printf_str::@2/(byte*) printf_str::str#0 )
|
||||
[13] if((byte) 0!=*((byte*) printf_str::str#3)) goto printf_str::@2
|
||||
to:printf_str::@return
|
||||
printf_str::@return: scope:[printf_str] from printf_str::@1
|
||||
[14] return
|
||||
to:@return
|
||||
printf_str::@2: scope:[printf_str] from printf_str::@1
|
||||
[15] *((byte*) screen#13) ← *((byte*) printf_str::str#3)
|
||||
[16] (byte*) screen#1 ← ++ (byte*) screen#13
|
||||
[17] (byte*) printf_str::str#0 ← ++ (byte*) printf_str::str#3
|
||||
to:printf_str::@1
|
||||
|
||||
(void()) printf_uint((word) printf_uint::uvalue , (byte) printf_uint::format_min_length , (byte) printf_uint::format_justify_left , (byte) printf_uint::format_sign_always , (byte) printf_uint::format_zero_padding , (byte) printf_uint::format_radix)
|
||||
printf_uint: scope:[printf_uint] from main::@1
|
||||
[18] *((byte*) screen#13) ← *((const to_nomodify byte*) printf_hextab)
|
||||
[19] (byte*) screen#3 ← ++ (byte*) screen#13
|
||||
[20] *((byte*) screen#3) ← *((const to_nomodify byte*) printf_hextab+>(const word) main::pct&(byte) $f)
|
||||
[21] (byte*) screen#4 ← ++ (byte*) screen#3
|
||||
[22] *((byte*) screen#4) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::pct>>(byte) 4)
|
||||
[23] (byte*) screen#5 ← ++ (byte*) screen#4
|
||||
[24] *((byte*) screen#5) ← *((const to_nomodify byte*) printf_hextab+<(const word) main::pct&(byte) $f)
|
||||
[25] (byte*) screen#16 ← ++ (byte*) screen#5
|
||||
to:printf_uint::@return
|
||||
printf_uint::@return: scope:[printf_uint] from printf_uint
|
||||
[26] return
|
||||
to:@return
|
1075
src/test/ref/printf-11.log
Normal file
1075
src/test/ref/printf-11.log
Normal file
File diff suppressed because it is too large
Load Diff
48
src/test/ref/printf-11.sym
Normal file
48
src/test/ref/printf-11.sym
Normal file
@ -0,0 +1,48 @@
|
||||
(label) @1
|
||||
(label) @begin
|
||||
(label) @end
|
||||
(const byte) RADIX::BINARY = (number) 2
|
||||
(const byte) RADIX::DECIMAL = (number) $a
|
||||
(const byte) RADIX::HEXADECIMAL = (number) $10
|
||||
(const byte) RADIX::OCTAL = (number) 8
|
||||
(void()) main()
|
||||
(label) main::@1
|
||||
(label) main::@2
|
||||
(label) main::@return
|
||||
(const word) main::pct = (word) $156
|
||||
(const byte*) main::str[(byte) $e] = (byte*) "Commodore is "
|
||||
(const byte*) main::str1[(byte) 6] = (byte*) " cool"
|
||||
(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::zero_padding
|
||||
(const to_nomodify byte*) printf_hextab[] = (byte*) "0123456789abcdef"z
|
||||
(void()) printf_str((byte*) printf_str::str)
|
||||
(label) printf_str::@1
|
||||
(label) printf_str::@2
|
||||
(label) printf_str::@return
|
||||
(byte*) printf_str::str
|
||||
(byte*) printf_str::str#0 str zp[2]:2 2002.0
|
||||
(byte*) printf_str::str#3 str zp[2]:2 1026.25
|
||||
(byte*) printf_str::str#5 str zp[2]:2 101.0
|
||||
(void()) printf_uint((word) printf_uint::uvalue , (byte) printf_uint::format_min_length , (byte) printf_uint::format_justify_left , (byte) printf_uint::format_sign_always , (byte) printf_uint::format_zero_padding , (byte) printf_uint::format_radix)
|
||||
(label) printf_uint::@return
|
||||
(struct printf_format_number) printf_uint::format
|
||||
(byte) printf_uint::format_justify_left
|
||||
(byte) printf_uint::format_min_length
|
||||
(byte) printf_uint::format_radix
|
||||
(byte) printf_uint::format_sign_always
|
||||
(byte) printf_uint::format_zero_padding
|
||||
(word) printf_uint::uvalue
|
||||
(byte*) screen
|
||||
(byte*) screen#1 screen zp[2]:4 1001.0
|
||||
(byte*) screen#13 screen zp[2]:4 472.28571428571433
|
||||
(byte*) screen#16 screen zp[2]:4 28.0
|
||||
(byte*) screen#25 screen zp[2]:4 112.0
|
||||
(byte*) screen#3 screen zp[2]:4 151.5
|
||||
(byte*) screen#4 screen zp[2]:4 151.5
|
||||
(byte*) screen#5 screen zp[2]:4 151.5
|
||||
|
||||
zp[2]:2 [ printf_str::str#3 printf_str::str#5 printf_str::str#0 ]
|
||||
zp[2]:4 [ screen#13 screen#25 screen#16 screen#1 screen#3 screen#5 screen#4 ]
|
Loading…
x
Reference in New Issue
Block a user