23451c8e85
Co-authored-by: aider (openrouter/moonshotai/kimi-k2.6) <aider@aider.chat>
143 lines
3.3 KiB
C
143 lines
3.3 KiB
C
#include "forth.h"
|
|
#include <stdint.h>
|
|
#include <stdarg.h>
|
|
|
|
// VGA text-mode buffer
|
|
static uint16_t* vga_buffer = (uint16_t*)0xB8000;
|
|
static int vga_row = 0;
|
|
static int vga_col = 0;
|
|
|
|
static void vga_putchar(char c) {
|
|
if (c == '\n') {
|
|
vga_col = 0;
|
|
vga_row++;
|
|
} else {
|
|
int idx = vga_row * 80 + vga_col;
|
|
vga_buffer[idx] = (uint16_t)((0x0F << 8) | (unsigned char)c);
|
|
vga_col++;
|
|
if (vga_col >= 80) {
|
|
vga_col = 0;
|
|
vga_row++;
|
|
}
|
|
}
|
|
if (vga_row >= 25) {
|
|
vga_row = 0;
|
|
vga_col = 0;
|
|
}
|
|
}
|
|
|
|
static inline void outb(uint16_t port, uint8_t val) {
|
|
__asm__ volatile ("outb %0, %1" : : "a"(val), "Nd"(port));
|
|
}
|
|
|
|
static inline uint8_t inb(uint16_t port) {
|
|
uint8_t ret;
|
|
__asm__ volatile ("inb %1, %0" : "=a"(ret) : "Nd"(port));
|
|
return ret;
|
|
}
|
|
|
|
static void serial_init(void) {
|
|
outb(0x3F8 + 1, 0x00);
|
|
outb(0x3F8 + 3, 0x80);
|
|
outb(0x3F8 + 0, 0x01);
|
|
outb(0x3F8 + 1, 0x00);
|
|
outb(0x3F8 + 3, 0x03);
|
|
outb(0x3F8 + 2, 0xC7);
|
|
outb(0x3F8 + 4, 0x0B);
|
|
}
|
|
|
|
void forth_putchar(char c) {
|
|
vga_putchar(c);
|
|
while ((inb(0x3F8 + 5) & 0x20) == 0) { }
|
|
outb(0x3F8, (uint8_t)c);
|
|
}
|
|
|
|
int forth_getchar(void) {
|
|
if ((inb(0x3F8 + 5) & 1) == 0) {
|
|
return FORTH_EOF;
|
|
}
|
|
return inb(0x3F8);
|
|
}
|
|
|
|
void forth_fflush(void) {
|
|
}
|
|
|
|
void forth_panic(void) {
|
|
__asm__ volatile ("cli; hlt");
|
|
__builtin_unreachable();
|
|
}
|
|
|
|
int64_t forth_strtoll(const char* str, char** endptr, int base) {
|
|
const char* s = str;
|
|
int neg = 0;
|
|
int64_t val = 0;
|
|
while (forth_isspace(*s)) s++;
|
|
if (*s == '-') { neg = 1; s++; }
|
|
else if (*s == '+') { s++; }
|
|
while (*s >= '0' && *s <= '9') {
|
|
val = val * base + (*s - '0');
|
|
s++;
|
|
}
|
|
if (endptr) *endptr = (char*)s;
|
|
return neg ? -val : val;
|
|
}
|
|
|
|
static void print_str(const char* s) {
|
|
while (*s) forth_putchar(*s++);
|
|
}
|
|
|
|
static void print_int(long long v) {
|
|
char buf[32];
|
|
int i = 30;
|
|
int neg = 0;
|
|
if (v < 0) { neg = 1; v = -v; }
|
|
buf[31] = '\0';
|
|
if (v == 0) {
|
|
buf[i--] = '0';
|
|
} else {
|
|
while (v > 0 && i >= 0) {
|
|
buf[i--] = '0' + (v % 10);
|
|
v /= 10;
|
|
}
|
|
}
|
|
if (neg) buf[i--] = '-';
|
|
print_str(&buf[i + 1]);
|
|
}
|
|
|
|
void forth_printf(const char* fmt, ...) {
|
|
va_list ap;
|
|
va_start(ap, fmt);
|
|
while (*fmt) {
|
|
if (*fmt == '%' && *(fmt + 1)) {
|
|
fmt++;
|
|
if (*fmt == 's') {
|
|
print_str(va_arg(ap, const char*));
|
|
} else if (*fmt == 'c') {
|
|
forth_putchar((char)va_arg(ap, int));
|
|
} else if (*fmt == '%') {
|
|
forth_putchar('%');
|
|
} else if (*fmt == 'l') {
|
|
if (*(fmt + 1) == 'l' && (*(fmt + 2) == 'd' || *(fmt + 2) == 'i' || *(fmt + 2) == 'u')) {
|
|
fmt += 2;
|
|
print_int(va_arg(ap, long long));
|
|
}
|
|
} else if (*fmt == 'd' || *fmt == 'i' || *fmt == 'u') {
|
|
print_int(va_arg(ap, int));
|
|
} else {
|
|
forth_putchar('%');
|
|
forth_putchar(*fmt);
|
|
}
|
|
} else {
|
|
forth_putchar(*fmt);
|
|
}
|
|
fmt++;
|
|
}
|
|
va_end(ap);
|
|
}
|
|
|
|
void kernel_main(void) {
|
|
serial_init();
|
|
forth_run();
|
|
forth_panic();
|
|
}
|