Skip to content

Commit f884d75

Browse files
committed
feat(syscall): implement printf (syscall: write)
1 parent c68fdc7 commit f884d75

File tree

12 files changed

+382
-17
lines changed

12 files changed

+382
-17
lines changed

sim/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ TEST_RUNNER = $(BUILD)/TestRunner
1919
CC = gcc
2020
CXX = g++
2121
LD = $(CC)
22-
CFLAGS = -I./include -Wall
22+
CFLAGS = -g -I./include -Wall
2323
CXXFLAGS = $(CFLAGS)
2424

2525
## 3. Rules

sim/include/trap.h

Lines changed: 0 additions & 11 deletions
This file was deleted.

sim/src/decode.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include <cpu.h>
55
#include <memory.h>
66
#include <decode.h>
7-
#include <trap.h>
7+
#include "syscall.h"
88

99
extern CPU_state cpu;
1010

sim/src/syscall.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
#include <cpu.h>
2-
#include <include/syscall.h>
2+
#include "syscall.h"
33
#include <decode.h>
44
#include <stdio.h>
5+
#include <memory.h>
56

67
extern CPU_state cpu;
78

@@ -20,7 +21,9 @@ void handle_syscall(Decode *s) {
2021
uint64_t count = cpu.reg[12]; // a2
2122
if (fd == 1) { // stdout
2223
for (uint64_t i = 0; i < count; i++) {
23-
putchar(*(uint8_t *)(buf + i));
24+
// printf("Syscall: write byte %02x from addr %016lx\n", mem_read(buf + i, 1), buf + i);
25+
uint8_t byte_to_write = mem_read(buf + i, 1);
26+
putchar(byte_to_write);
2427
}
2528
cpu.reg[10] = count; // return value in a0
2629
} else {

test/Makefile

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ BUILD = build
33
TARGET = $(BUILD)/$(T).bin
44
$(shell mkdir -p $(BUILD)/objs)
55

6+
LIB_SRCS = $(wildcard lib/*.c)
7+
LIB_OBJS = $(patsubst lib/%.c, $(BUILD)/objs/%.o, $(LIB_SRCS))
8+
69
## 2. General Compilation Flags
710
### Cross compiler
811
CROSS_COMPILE = riscv64-unknown-elf-
@@ -36,11 +39,16 @@ $(BUILD)/objs/trm.o: trm/trm.c
3639
@echo + CC "->" $<
3740
@$(CC) -std=gnu11 $(CFLAGS) -c -o $@ $<
3841

42+
$(BUILD)/objs/%.o: lib/%.c
43+
@echo + CC "->" $<
44+
@$(CC) -std=gnu11 $(CFLAGS) -c -o $@ $<
45+
3946
$(BUILD)/objs/%.o: src/%.c
4047
@echo + CC "->" $<
4148
@$(CC) -std=gnu11 $(CFLAGS) -c -o $@ $<
4249

43-
$(BUILD)/%.elf: $(addprefix $(BUILD)/objs/, %.o trm.o start.o)
50+
# $(BUILD)/%.elf: $(addprefix $(BUILD)/objs/, %.o trm.o start.o)
51+
$(BUILD)/%.elf: $(addprefix $(BUILD)/objs/, %.o) $(LIB_OBJS) $(BUILD)/objs/trm.o $(BUILD)/objs/start.o
4452
@echo + LD "->" $^
4553
@$(LD) $(LDFLAGS) $^ -o $@
4654

test/include/stdarg.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#ifndef STDARG_H
2+
#define STDARG_H
3+
4+
typedef __builtin_va_list va_list;
5+
6+
#define va_start(ap, last) __builtin_va_start(ap, last)
7+
8+
#define va_arg(ap, type) __builtin_va_arg(ap, type)
9+
10+
#define va_end(ap) __builtin_va_end(ap)
11+
12+
#endif

test/include/stdio.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#ifndef STDIO_H
2+
#define STDIO_H
3+
4+
#include "stdarg.h"
5+
#include <stdint.h>
6+
7+
#ifndef NULL
8+
#define NULL ((void*)0)
9+
#endif
10+
11+
#define STDIN_FILENO 0
12+
#define STDOUT_FILENO 1
13+
#define STDERR_FILENO 2
14+
15+
void putchar(int c);
16+
int getchar(void);
17+
18+
void printfmt(void (*putch)(int, void*), void *putdat, const char *fmt, ...);
19+
void vprintfmt(void (*putch)(int, void*), void *putdat, const char *fmt, va_list ap);
20+
21+
int printf(const char *fmt, ...);
22+
int vprintf(const char *fmt, va_list ap);
23+
24+
#endif

test/lib/console.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#include "syscall.h"
2+
#include <stdint.h>
3+
#include "stdio.h"
4+
5+
void putchar(int c) {
6+
// Implement putchar to output a character to the console
7+
// This is a stub implementation; replace with actual output code
8+
// For example, you might write to a memory-mapped I/O register
9+
// or use a system call to write to stdout.
10+
write(STDOUT_FILENO, &c, 1);
11+
}
12+
13+
// int getchar(void) {
14+
// // Implement getchar to read a character from the console
15+
// // This is a stub implementation; replace with actual input code
16+
// // For example, you might read from a memory-mapped I/O register
17+
// // or use a system call to read from stdin.
18+
// }

test/lib/printf.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include "stdio.h"
2+
#include "stdarg.h"
3+
4+
static void putch(int ch, int *cnt) {
5+
putchar(ch);
6+
*cnt += 1;
7+
}
8+
9+
int vprintf(const char *fmt, va_list ap) {
10+
int cnt = 0;
11+
vprintfmt((void *)putch, &cnt, fmt, ap);
12+
return cnt;
13+
}
14+
15+
int printf(const char *fmt, ...) {
16+
va_list ap;
17+
int cnt;
18+
19+
va_start(ap, fmt);
20+
cnt = vprintf(fmt, ap);
21+
va_end(ap);
22+
23+
return cnt;
24+
}

test/lib/printfmt.c

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
#include "stdio.h"
2+
#include "stdarg.h"
3+
4+
typedef unsigned long size_t;
5+
static size_t strnlen(const char *s, size_t maxlen) {
6+
size_t len = 0;
7+
while (len < maxlen && s[len] != '\0') {
8+
len++;
9+
}
10+
return len;
11+
}
12+
13+
/*
14+
* Print a number (base <= 16) in reverse order,
15+
* using specified putch function and associated pointer putdat.
16+
*/
17+
static void
18+
printnum(void (*putch)(int, void*), void *putdat,
19+
unsigned long long num, unsigned base, int width, int padc)
20+
{
21+
// first recursively print all preceding (more significant) digits
22+
if (num >= base) {
23+
printnum(putch, putdat, num / base, base, width - 1, padc);
24+
} else {
25+
// print any needed pad characters before first digit
26+
while (--width > 0)
27+
putch(padc, putdat);
28+
}
29+
30+
// then print this (the least significant) digit
31+
putch("0123456789abcdef"[num % base], putdat);
32+
}
33+
34+
// Get an unsigned int of various possible sizes from a varargs list,
35+
// depending on the lflag parameter.
36+
static unsigned long long
37+
getuint(va_list *ap, int lflag)
38+
{
39+
if (lflag >= 2)
40+
return va_arg(*ap, unsigned long long);
41+
else if (lflag)
42+
return va_arg(*ap, unsigned long);
43+
else
44+
return va_arg(*ap, unsigned int);
45+
}
46+
47+
// Same as getuint but signed - can't use getuint
48+
// because of sign extension
49+
static long long
50+
getint(va_list *ap, int lflag)
51+
{
52+
if (lflag >= 2)
53+
return va_arg(*ap, long long);
54+
else if (lflag)
55+
return va_arg(*ap, long);
56+
else
57+
return va_arg(*ap, int);
58+
}
59+
60+
// Main function to format and print a string.
61+
void printfmt(void (*putch)(int, void*), void *putdat, const char *fmt, ...);
62+
63+
void
64+
vprintfmt(void (*putch)(int, void*), void *putdat, const char *fmt, va_list ap)
65+
{
66+
register const char *p;
67+
register int ch;
68+
unsigned long long num;
69+
int base, lflag, width, precision, altflag;
70+
char padc;
71+
72+
while (1) {
73+
while ((ch = *(unsigned char *) fmt++) != '%') {
74+
if (ch == '\0')
75+
return;
76+
77+
putch(ch, putdat);
78+
}
79+
80+
// Process a %-escape sequence
81+
padc = ' ';
82+
width = -1;
83+
precision = -1;
84+
lflag = 0;
85+
altflag = 0;
86+
reswitch:
87+
switch (ch = *(unsigned char *) fmt++) {
88+
89+
// flag to pad on the right
90+
case '-':
91+
padc = '-';
92+
goto reswitch;
93+
94+
// flag to pad with 0's instead of spaces
95+
case '0':
96+
padc = '0';
97+
goto reswitch;
98+
99+
// width field
100+
case '1':
101+
case '2':
102+
case '3':
103+
case '4':
104+
case '5':
105+
case '6':
106+
case '7':
107+
case '8':
108+
case '9':
109+
for (precision = 0; ; ++fmt) {
110+
precision = precision * 10 + ch - '0';
111+
ch = *fmt;
112+
if (ch < '0' || ch > '9')
113+
break;
114+
}
115+
goto process_precision;
116+
117+
case '*':
118+
precision = va_arg(ap, int);
119+
goto process_precision;
120+
121+
case '.':
122+
if (width < 0)
123+
width = 0;
124+
goto reswitch;
125+
126+
case '#':
127+
altflag = 1;
128+
goto reswitch;
129+
130+
process_precision:
131+
if (width < 0)
132+
width = precision, precision = -1;
133+
goto reswitch;
134+
135+
// long flag (doubled for long long)
136+
case 'l':
137+
lflag++;
138+
goto reswitch;
139+
140+
// character
141+
case 'c':
142+
putch(va_arg(ap, int), putdat);
143+
break;
144+
145+
// string
146+
case 's':
147+
if ((p = va_arg(ap, char *)) == NULL)
148+
p = "(null)";
149+
if (width > 0 && padc != '-')
150+
for (width -= strnlen(p, precision); width > 0; width--)
151+
putch(padc, putdat);
152+
for (; (ch = *p++) != '\0' && (precision < 0 || --precision >= 0); width--)
153+
if (altflag && (ch < ' ' || ch > '~'))
154+
putch('?', putdat);
155+
else
156+
putch(ch, putdat);
157+
for (; width > 0; width--)
158+
putch(' ', putdat);
159+
break;
160+
161+
// (signed) decimal
162+
case 'd':
163+
num = getint(&ap, lflag);
164+
if ((long long) num < 0) {
165+
putch('-', putdat);
166+
num = -(long long) num;
167+
}
168+
base = 10;
169+
goto number;
170+
171+
// unsigned decimal
172+
case 'u':
173+
num = getuint(&ap, lflag);
174+
base = 10;
175+
goto number;
176+
177+
// (unsigned) octal
178+
case 'o':
179+
num = getuint(&ap, lflag);
180+
base = 8;
181+
goto number;
182+
183+
// pointer
184+
case 'p':
185+
putch('0', putdat);
186+
putch('x', putdat);
187+
num = (unsigned long long)
188+
(uintptr_t) va_arg(ap, void *);
189+
base = 16;
190+
goto number;
191+
192+
// (unsigned) hexadecimal
193+
case 'x':
194+
num = getuint(&ap, lflag);
195+
base = 16;
196+
number:
197+
printnum(putch, putdat, num, base, width, padc);
198+
break;
199+
200+
// escaped '%' character
201+
case '%':
202+
putch(ch, putdat);
203+
break;
204+
205+
// unrecognized escape sequence - just print it literally
206+
default:
207+
putch('%', putdat);
208+
for (fmt--; fmt[-1] != '%'; fmt--)
209+
/* do nothing */;
210+
break;
211+
}
212+
}
213+
}
214+
215+
void
216+
printfmt(void (*putch)(int, void*), void *putdat, const char *fmt, ...)
217+
{
218+
va_list ap;
219+
220+
va_start(ap, fmt);
221+
vprintfmt(putch, putdat, fmt, ap);
222+
va_end(ap);
223+
}

0 commit comments

Comments
 (0)