From 82bad92fcf92415f5ee1a1c3c0432c48073a7139 Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Thu, 26 Jan 2023 23:54:33 -0600 Subject: [PATCH] fix: refactor how `c` and `s` track breakpoints We move state from Server.zig to Emulator.zig (the interface) --- src/Packet.zig | 31 ++++++++++++++++--------------- src/Server.zig | 4 +--- src/lib.zig | 32 +++++++++++++++++++++++++++++++- 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/src/Packet.zig b/src/Packet.zig index f77a728..2ea85ee 100644 --- a/src/Packet.zig +++ b/src/Packet.zig @@ -46,7 +46,7 @@ const String = union(enum) { } }; -pub fn parse(self: *Self, allocator: Allocator, state: *State, emu: Emulator) !String { +pub fn parse(self: *Self, allocator: Allocator, emu: *Emulator) !String { switch (self.contents[0]) { // Required '?' => { @@ -97,24 +97,25 @@ pub fn parse(self: *Self, allocator: Allocator, state: *State, emu: Emulator) !S }, 'M' => @panic("TODO: Memory Write"), 'c' => { - while (true) { - emu.step(); - - const r = emu.registers(); - const is_thumb = emu.cpsr() >> 5 & 1 == 1; - const r15 = r[15] -| if (is_thumb) @as(u32, 4) else 8; - - if (state.hw_bkpt.isHit(r15)) { - return .{ .static = "T05 hwbreak;" }; - } + switch (emu.contd()) { + .SingleStep => unreachable, + .Trap => |r| switch (r) { + .HwBkpt => return .{ .static = "T05 hwbreak:;" }, + .SwBkpt => return .{ .static = "T05 swbreak:;" }, + }, } }, 's' => { // var tokens = std.mem.tokenize(u8, self.contents[1..], " "); // const addr = if (tokens.next()) |s| try std.fmt.parseInt(u32, s, 16) else null; - emu.step(); - return .{ .static = "S05" }; // Signal.Trap + switch (emu.step()) { + .SingleStep => return .{ .static = "T05" }, + .Trap => |r| switch (r) { + .HwBkpt => return .{ .static = "T05 hwbreak:;" }, + .SwBkpt => return .{ .static = "T05 swbreak:;" }, + }, + } }, // Breakpoints @@ -126,7 +127,7 @@ pub fn parse(self: *Self, allocator: Allocator, state: *State, emu: Emulator) !S const addr_str = tokens.next() orelse return error.InvalidPacket; const addr = try std.fmt.parseInt(u32, addr_str, 16); - state.hw_bkpt.remove(addr); + emu.state.hw_bkpt.remove(addr); return .{ .static = "OK" }; }, '2' => return .{ .static = "" }, // TODO: Remove Write Watchpoint @@ -144,7 +145,7 @@ pub fn parse(self: *Self, allocator: Allocator, state: *State, emu: Emulator) !S const addr = try std.fmt.parseInt(u32, addr_str, 16); const kind = try std.fmt.parseInt(u32, kind_str, 16); - state.hw_bkpt.add(addr, kind) catch |e| { + emu.state.hw_bkpt.add(addr, kind) catch |e| { switch (e) { error.OutOfSpace => return .{ .static = "E22" }, // FIXME: Which errno? else => return e, diff --git a/src/Server.zig b/src/Server.zig index 1be0f65..ac39a23 100644 --- a/src/Server.zig +++ b/src/Server.zig @@ -1,7 +1,6 @@ const std = @import("std"); const network = @import("network"); const Packet = @import("Packet.zig"); -const State = @import("State.zig"); const Socket = network.Socket; const Allocator = std.mem.Allocator; @@ -60,7 +59,6 @@ pkt_cache: ?[]const u8 = null, client: Socket, _socket: Socket, -state: State = .{}, emu: Emulator, pub fn init(emulator: Emulator) !Self { @@ -131,7 +129,7 @@ fn handlePacket(self: *Self, allocator: Allocator, input: []const u8) !Action { var packet = Packet.from(allocator, input) catch return .nack; defer packet.deinit(allocator); - var string = packet.parse(allocator, &self.state, self.emu) catch return .nack; + var string = packet.parse(allocator, &self.emu) catch return .nack; defer string.deinit(allocator); const reply = string.inner(); diff --git a/src/lib.zig b/src/lib.zig index cb534c0..f19a982 100644 --- a/src/lib.zig +++ b/src/lib.zig @@ -1,10 +1,20 @@ /// Re-export of the server interface pub const Server = @import("Server.zig"); +const State = @import("State.zig"); /// Interface for interacting between GDB and a GBA emu pub const Emulator = struct { const Self = @This(); + const Signal = union(enum) { + const Kind = enum { HwBkpt, SwBkpt }; + + Trap: Kind, + SingleStep: void, + }; + + state: State = .{}, + ptr: *anyopaque, readFn: *const fn (*anyopaque, u32) u8, @@ -75,7 +85,27 @@ pub const Emulator = struct { return self.cpsrFn(self.ptr); } - pub inline fn step(self: Self) void { + pub inline fn contd(self: *Self) Signal { + while (true) { + const signal = self.step(); + + switch (signal) { + .SingleStep => {}, + .Trap => return signal, + } + } + } + + pub inline fn step(self: *Self) Signal { self.stepFn(self.ptr); + + const r = self.registersFn(self.ptr); + const is_thumb = self.cpsrFn(self.ptr) >> 5 & 1 == 1; + + const r15 = r[15] -| if (is_thumb) @as(u32, 4) else 8; + + if (self.state.hw_bkpt.isHit(r15)) return .{ .Trap = .HwBkpt }; + + return .SingleStep; } };