PAGE_SIZE := 4096 MAX_ALLOC := 0xFF alloc := fn($Expr: type, bytes: int): ^Expr { pages := 1 + bytes / PAGE_SIZE if pages <= MAX_ALLOC { return @bitcast(@inline(request_page, pages)) } ptr := @inline(request_page, 0xFF) remaining := pages - MAX_ALLOC loop if remaining <= 0 break else { if remaining < MAX_ALLOC { request_page(remaining) } else { request_page(MAX_ALLOC) } remaining -= MAX_ALLOC } return @bitcast(ptr) } request_page := fn(page_count: u8): ^u8 { msg := "\{00}\{01}xxxxxxxx\0" msg_page_count := msg + 1; *msg_page_count = page_count return @eca(3, 2, msg, 12) } release_page := fn(ptr: ^u8, page_count: u8): void { msg := "\{01}\{00}xxxxxxxx\0" msg_page_count := msg + 1; *msg_page_count = page_count msg_ptr := @as(^^u8, @bitcast(msg + 2)); *msg_ptr = ptr return @eca(3, 2, msg, 12) } OutbMsg := packed struct {a: u8, b: u8, addr: u16, value: u8} InbMsg := packed struct {a: u8, b: u8, addr: u16} OutlMsg := packed struct {a: u8, b: u8, addr: u16, value: u32} InlMsg := packed struct {a: u8, b: u8, addr: u16} outb := fn(addr: u16, value: u8): void { return @eca(3, 3, &OutbMsg.(1, 0, addr, value), @sizeof(OutbMsg)) } inb := fn(addr: u16): u8 { return @eca(3, 3, &InbMsg.(0, 0, addr), @sizeof(InbMsg)) } outl := fn(addr: u16, value: u32): void { return @eca(3, 3, &OutlMsg.(1, 2, addr, value), @sizeof(OutlMsg)) } inl := fn(addr: u16): u32 { return @eca(3, 3, &InlMsg.(0, 2, addr), @sizeof(InlMsg)) } CopyMsg := packed struct {a: u8, count: uint, src: uint, dest: ^u8} copy := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void { return @eca(3, 2, &CopyMsg.(4, count * @sizeof(Expr), @bitcast(src), @bitcast(dest)), @sizeof(CopyMsg)) } SetMsg := packed struct {a: u8, count: uint, size: uint, src: ^u8, dest: ^u8} set := fn($Expr: type, src: ^Expr, dest: ^Expr, count: uint): void { return @eca(3, 2, &SetMsg.(5, count, @sizeof(Expr), @bitcast(src), @bitcast(dest)), @sizeof(SetMsg)) }