// Markus Maiwald (Architect) | Voxis Forge (AI) // RUMPK L0 // libc_stubs.zig // We are the standard library now. const uart = @import("uart.zig"); // ========================================================= // Heap Stubs (Bump Allocator with Block Headers) // ========================================================= // Simple Bump Allocator for L0 var heap: [32 * 1024 * 1024]u8 align(4096) = undefined; // 32MB Heap var heap_idx: usize = 0; // Header structure (64 bytes aligned to match LwIP MEM_ALIGNMENT) const BlockHeader = struct { size: usize, _pad: [64 - @sizeOf(usize)]u8, }; export fn malloc(size: usize) ?*anyopaque { if (size == 0) return null; const total_needed = size + @sizeOf(BlockHeader); const align_mask: usize = 63; // 64-byte alignment const aligned_idx = (heap_idx + align_mask) & ~align_mask; if (aligned_idx + total_needed > heap.len) { return null; } const base_ptr = &heap[aligned_idx]; const header = @as(*BlockHeader, @ptrCast(@alignCast(base_ptr))); header.size = size; heap_idx = aligned_idx + total_needed; return @as(*anyopaque, @ptrFromInt(@intFromPtr(base_ptr) + @sizeOf(BlockHeader))); } export fn free(ptr: ?*anyopaque) void { // Bump allocator: no-op free. _ = ptr; } export fn realloc(ptr: ?*anyopaque, size: usize) ?*anyopaque { if (ptr == null) return malloc(size); if (size == 0) { free(ptr); return null; } // Retrieve old size from header const base_addr = @intFromPtr(ptr.?) - @sizeOf(BlockHeader); const header = @as(*BlockHeader, @ptrFromInt(base_addr)); const old_size = header.size; // Optimization: If new size is smaller and it's the last block, we could shrink? // But for a bump allocator, just allocate new. const new_ptr = malloc(size); if (new_ptr) |np| { const copy_size = if (size < old_size) size else old_size; const src = @as([*]const u8, @ptrCast(ptr.?)); const dst = @as([*]u8, @ptrCast(np)); var i: usize = 0; while (i < copy_size) : (i += 1) { dst[i] = src[i]; } free(ptr); return np; } return null; } export fn calloc(nmemb: usize, size: usize) ?*anyopaque { const total = nmemb * size; const ptr = malloc(total); if (ptr) |p| { const dst = @as([*]u8, @ptrCast(p)); var i: usize = 0; while (i < total) : (i += 1) { dst[i] = 0; } } return ptr; } // ========================================================= // Rumpk Runtime Support // ========================================================= export fn get_ticks() u32 { return 0; // TODO: Implement real timer }