diff --git a/src/uxn.zig b/src/uxn.zig index f324685..1a032e2 100644 --- a/src/uxn.zig +++ b/src/uxn.zig @@ -40,11 +40,42 @@ const Memory = struct { } }; +test "memory peek/poke" { + var mem = Memory{ .m = undefined }; + mem.poke(u16, 0, 0xABCD); + mem.poke(u8, 2, 0x69); + try std.testing.expectEqual(0xABCD, mem.peek(u16, 0)); + try std.testing.expectEqual(0x69, mem.peek(u8, 2)); +} + const Stack = struct { s: [0x100]u8, sp: u8 = 0, pub fn peek(self: *Stack, comptime T: type) T { + std.debug.print("\x1b[1;32mstack peek:\x1b[0m sp {d}, type {s}\n", .{ self.sp, @typeName(T) }); + return switch (T) { + u8 => self.s[self.sp -% 1], + u16 => @as(u16, @intCast(self.s[self.sp -% 2])) << 8 | self.s[self.sp -% 1], + else => @compileError("expected u8 or u16, got " + @typeName(T)), + }; + } + + pub fn poke(self: *Stack, comptime T: type, v: T) void { + std.debug.print("\x1b[1;32mstack poke:\x1b[0m sp {d}, type {s}\n", .{ self.sp, @typeName(T) }); + switch (T) { + u8 => self.s[self.sp -% 1] = v, + u16 => { + self.s[self.sp -% 2] = @truncate(v >> 8); + self.s[self.sp -% 1] = @truncate(v & 0xFF); + }, + else => @compileError("expected u8 or u16, got " + @typeName(T)), + } + } + + pub fn pop(self: *Stack, comptime T: type) T { + self.sp -%= @intCast(@divExact(@typeInfo(T).int.bits, 8)); + std.debug.print("\x1b[1;32mstack pop:\x1b[0m sp {d}, type {s}\n", .{ self.sp, @typeName(T) }); return switch (T) { u8 => self.s[self.sp], u16 => @as(u16, @intCast(self.s[self.sp])) << 8 | self.s[self.sp +% 1], @@ -52,7 +83,8 @@ const Stack = struct { }; } - pub fn poke(self: *Stack, comptime T: type, v: T) void { + pub fn push(self: *Stack, comptime T: type, v: T) void { + std.debug.print("\x1b[1;32mstack push:\x1b[0m sp {d}, type {s}\n", .{ self.sp, @typeName(T) }); switch (T) { u8 => self.s[self.sp] = v, u16 => { @@ -61,19 +93,24 @@ const Stack = struct { }, else => @compileError("expected u8 or u16, got " + @typeName(T)), } - } - - pub fn pop(self: *Stack, comptime T: type) T { - self.sp -%= @intCast(@divExact(@typeInfo(T).int.bits, 8)); - return self.peek(T); - } - - pub fn push(self: *Stack, comptime T: type, v: T) void { - self.poke(T, v); self.sp +%= @intCast(@divExact(@typeInfo(T).int.bits, 8)); } }; +test "stack poke/peek/push/pop" { + var stack = Stack{ .s = undefined }; + stack.push(u16, 0xABCD); + stack.push(u8, 0x69); + try std.testing.expectEqual(0x69, stack.peek(u8)); + try std.testing.expectEqual(0x69, stack.pop(u8)); + try std.testing.expectEqual(0xABCD, stack.peek(u16)); + try std.testing.expectEqual(0xABCD, stack.pop(u16)); + stack.poke(u8, 0xBF); + try std.testing.expectEqual(0xBF, stack.peek(u8)); + stack.poke(u16, 0xBEEF); + try std.testing.expectEqual(0xBEEF, stack.peek(u16)); +} + pub fn eval(self: *Uxn) bool { switch (self.mem.m[self.pc]) { 0x00 => return true, // BRK @@ -603,24 +640,6 @@ fn sft(stack: *Stack, comptime T: type, comptime keep: bool) void { } } -// TODO move the mem/stack to just below their respective definitions - -test "memory peek/poke" { - var mem = Memory{ .m = undefined }; - mem.poke(u16, 0, 0xABCD); - mem.poke(u8, 2, 0xAA); - try std.testing.expectEqual(0xABCD, mem.peek(u16, 0)); - try std.testing.expectEqual(0xAA, mem.peek(u8, 2)); -} - -test "stack push/pop" { - var stack = Stack{ .s = undefined }; - stack.push(u16, 0xABCD); - stack.push(u8, 0xAA); - try std.testing.expectEqual(0xAA, stack.pop(u8)); - try std.testing.expectEqual(0xABCD, stack.pop(u16)); -} - // test "arithmetic instructions" { // var uxn = Uxn{ // .mem = .{ .m = undefined },