rumpk/hal/stubs.zig

196 lines
4.7 KiB
Zig

// VOXIS FORGE // RUMPK L0
// libc_stubs.zig
// We are the standard library now.
//
// These C ABI functions are exported so Nim's generated C code
// can link against them. No glibc. No musl. Pure sovereignty.
// =========================================================
// Memory Operations (Nim needs these)
// =========================================================
export fn memcpy(dest: [*]u8, src: [*]const u8, len: usize) [*]u8 {
var i: usize = 0;
while (i < len) : (i += 1) {
dest[i] = src[i];
}
return dest;
}
export fn memset(dest: [*]u8, val: c_int, len: usize) [*]u8 {
const v: u8 = @intCast(val & 0xFF);
var i: usize = 0;
while (i < len) : (i += 1) {
dest[i] = v;
}
return dest;
}
export fn memmove(dest: [*]u8, src: [*]const u8, len: usize) [*]u8 {
if (@intFromPtr(dest) < @intFromPtr(src)) {
return memcpy(dest, src, len);
}
// Copy backwards for overlapping regions
var i: usize = len;
while (i > 0) {
i -= 1;
dest[i] = src[i];
}
return dest;
}
export fn memcmp(s1: [*]const u8, s2: [*]const u8, len: usize) c_int {
var i: usize = 0;
while (i < len) : (i += 1) {
if (s1[i] != s2[i]) {
return if (s1[i] < s2[i]) @as(c_int, -1) else @as(c_int, 1);
}
}
return 0;
}
// =========================================================
// String Operations
// =========================================================
export fn strlen(s: [*]const u8) usize {
var len: usize = 0;
while (s[len] != 0) : (len += 1) {}
return len;
}
export fn strcpy(dest: [*]u8, src: [*]const u8) [*]u8 {
var i: usize = 0;
while (src[i] != 0) : (i += 1) {
dest[i] = src[i];
}
dest[i] = 0;
return dest;
}
export fn strcmp(s1: [*]const u8, s2: [*]const u8) c_int {
var i: usize = 0;
while (s1[i] != 0 and s1[i] == s2[i]) : (i += 1) {}
if (s1[i] == s2[i]) return 0;
return if (s1[i] < s2[i]) @as(c_int, -1) else @as(c_int, 1);
}
// =========================================================
// Heap Stubs (Bump Allocator)
// =========================================================
var heap_base: [64 * 1024]u8 = undefined;
var heap_offset: usize = 0;
export fn malloc(size: usize) ?*anyopaque {
if (heap_offset + size > heap_base.len) {
return null;
}
const ptr = &heap_base[heap_offset];
heap_offset += size;
// Align to 8 bytes
heap_offset = (heap_offset + 7) & ~@as(usize, 7);
return ptr;
}
export fn free(ptr: ?*anyopaque) void {
// Bump allocator - no deallocation
_ = ptr;
}
export fn realloc(ptr: ?*anyopaque, size: usize) ?*anyopaque {
// Simple realloc - just allocate new (wasteful but works for bootstrap)
_ = ptr;
return malloc(size);
}
export fn calloc(nmemb: usize, size: usize) ?*anyopaque {
const total = nmemb * size;
const ptr = malloc(total);
if (ptr) |p| {
_ = memset(@ptrCast(p), 0, total);
}
return ptr;
}
// =========================================================
// Stdio Stubs (Route to UART)
// =========================================================
const uart = @import("uart.zig");
export fn puts(s: [*]const u8) c_int {
const len = strlen(s);
uart.write_bytes(s[0..len]);
uart.putc('\n');
return 0;
}
export fn putchar(c: c_int) c_int {
uart.putc(@intCast(c & 0xFF));
return c;
}
export fn printf(fmt: [*]const u8, ...) c_int {
// Minimal printf - just output format string
const len = strlen(fmt);
uart.write_bytes(fmt[0..len]);
return @intCast(len);
}
export fn fprintf(stream: ?*anyopaque, fmt: [*]const u8, ...) c_int {
_ = stream;
return printf(fmt);
}
export fn fflush(stream: ?*anyopaque) c_int {
_ = stream;
return 0;
}
export fn fwrite(ptr: [*]const u8, size: usize, nmemb: usize, stream: ?*anyopaque) usize {
_ = stream;
uart.write_bytes(ptr[0 .. size * nmemb]);
return nmemb;
}
// =========================================================
// Signal Stubs (No signals in freestanding)
// =========================================================
export fn signal(signum: c_int, handler: ?*anyopaque) ?*anyopaque {
_ = signum;
_ = handler;
return null;
}
export fn raise(sig: c_int) c_int {
_ = sig;
return 0;
}
// =========================================================
// Exit Stubs
// =========================================================
fn halt() noreturn {
while (true) {
asm volatile ("wfi");
}
}
export fn exit(status: c_int) noreturn {
_ = status;
uart.puts("[RUMPK] exit() called - halt\n");
halt();
}
export fn abort() noreturn {
uart.puts("[RUMPK] abort() called - halt\n");
halt();
}
export fn _Exit(status: c_int) noreturn {
exit(status);
}