Compare commits
2 Commits
apu-things
...
27a6ced4a7
Author | SHA1 | Date | |
---|---|---|---|
27a6ced4a7 | |||
b200dd9fa1 |
56
src/cpu.zig
56
src/cpu.zig
@@ -60,6 +60,7 @@ pub const Arm7tdmi = struct {
|
||||
const Self = @This();
|
||||
|
||||
r: [16]u32,
|
||||
pipe: Pipline,
|
||||
sched: *Scheduler,
|
||||
bus: Bus,
|
||||
cpsr: PSR,
|
||||
@@ -82,6 +83,7 @@ pub const Arm7tdmi = struct {
|
||||
pub fn init(alloc: Allocator, sched: *Scheduler, paths: FilePaths) !Self {
|
||||
return Self{
|
||||
.r = [_]u32{0x00} ** 16,
|
||||
.pipe = Pipline.init(),
|
||||
.sched = sched,
|
||||
.bus = try Bus.init(alloc, sched, paths),
|
||||
.cpsr = .{ .raw = 0x0000_001F },
|
||||
@@ -256,19 +258,21 @@ pub const Arm7tdmi = struct {
|
||||
}
|
||||
|
||||
pub fn step(self: *Self) void {
|
||||
if (self.cpsr.t.read()) {
|
||||
const opcode = self.fetch(u16);
|
||||
if (self.cpsr.t.read()) blk: {
|
||||
const opcode = @truncate(u16, self.pipe.step(self, u16) orelse break :blk);
|
||||
if (enable_logging) if (self.log_file) |file| self.debug_log(file, opcode);
|
||||
|
||||
thumb_lut[thumbIdx(opcode)](self, &self.bus, opcode);
|
||||
} else {
|
||||
const opcode = self.fetch(u32);
|
||||
} else blk: {
|
||||
const opcode = self.pipe.step(self, u32) orelse break :blk;
|
||||
if (enable_logging) if (self.log_file) |file| self.debug_log(file, opcode);
|
||||
|
||||
if (checkCond(self.cpsr, @truncate(u4, opcode >> 28))) {
|
||||
if (checkCond(self.cpsr, @truncate(u4, opcode >> 28)))
|
||||
arm_lut[armIdx(opcode)](self, &self.bus, opcode);
|
||||
}
|
||||
}
|
||||
|
||||
if (!self.pipe.flushed) self.r[15] += if (self.cpsr.t.read()) 2 else @as(u32, 4);
|
||||
self.pipe.flushed = false;
|
||||
}
|
||||
|
||||
pub fn stepDmaTransfer(self: *Self) bool {
|
||||
@@ -445,7 +449,7 @@ pub const Arm7tdmi = struct {
|
||||
const r12 = self.r[12];
|
||||
const r13 = self.r[13];
|
||||
const r14 = self.r[14];
|
||||
const r15 = self.r[15];
|
||||
const r15 = self.r[15] -| if (self.cpsr.t.read()) 4 else @as(u32, 8);
|
||||
|
||||
const c_psr = self.cpsr.raw;
|
||||
|
||||
@@ -669,6 +673,44 @@ fn armPopulate() [0x1000]ArmInstrFn {
|
||||
};
|
||||
}
|
||||
|
||||
const Pipline = struct {
|
||||
const Self = @This();
|
||||
stage: [2]?u32,
|
||||
flushed: bool,
|
||||
|
||||
fn init() Self {
|
||||
return .{
|
||||
.stage = [_]?u32{null} ** 2,
|
||||
.flushed = false,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn flush(self: *Self) void {
|
||||
for (self.stage) |*opcode| opcode.* = null;
|
||||
self.flushed = true;
|
||||
}
|
||||
|
||||
pub fn step(self: *Self, cpu: *Arm7tdmi, comptime T: type) ?u32 {
|
||||
comptime std.debug.assert(T == u32 or T == u16);
|
||||
|
||||
const opcode = self.stage[0];
|
||||
|
||||
self.stage[0] = self.stage[1];
|
||||
self.stage[1] = cpu.bus.read(T, cpu.r[15]);
|
||||
|
||||
return opcode;
|
||||
}
|
||||
|
||||
fn reload(self: *Self, cpu: *Arm7tdmi, comptime T: type) void {
|
||||
comptime std.debug.assert(T == u32 or T == u16);
|
||||
const inc = if (T == u32) 4 else 2;
|
||||
|
||||
self.stage[0] = cpu.bus.read(T, cpu.r[15]);
|
||||
self.stage[1] = cpu.bus.read(T, cpu.r[15] + inc);
|
||||
cpu.r[15] += inc * 2;
|
||||
}
|
||||
};
|
||||
|
||||
pub const PSR = extern union {
|
||||
mode: Bitfield(u32, 0, 5),
|
||||
t: Bit(u32, 5),
|
||||
|
@@ -9,14 +9,25 @@ const sext = @import("../../util.zig").sext;
|
||||
pub fn branch(comptime L: bool) InstrFn {
|
||||
return struct {
|
||||
fn inner(cpu: *Arm7tdmi, _: *Bus, opcode: u32) void {
|
||||
if (L) cpu.r[14] = cpu.r[15];
|
||||
cpu.r[15] = cpu.fakePC() +% (sext(u32, u24, opcode) << 2);
|
||||
if (L) cpu.r[14] = cpu.r[15] - 4;
|
||||
|
||||
const offset = sext(u32, u24, opcode) << 2;
|
||||
cpu.r[15] = cpu.r[15] +% offset;
|
||||
cpu.pipe.flush();
|
||||
}
|
||||
}.inner;
|
||||
}
|
||||
|
||||
pub fn branchAndExchange(cpu: *Arm7tdmi, _: *Bus, opcode: u32) void {
|
||||
const rn = opcode & 0xF;
|
||||
cpu.cpsr.t.write(cpu.r[rn] & 1 == 1);
|
||||
cpu.r[15] = cpu.r[rn] & 0xFFFF_FFFE;
|
||||
|
||||
if (cpu.r[rn] & 1 == 1) {
|
||||
cpu.r[15] = cpu.r[rn] & ~@as(u32, 1);
|
||||
cpu.cpsr.t.set();
|
||||
} else {
|
||||
cpu.r[15] = cpu.r[rn] & ~@as(u32, 3);
|
||||
cpu.cpsr.t.unset();
|
||||
}
|
||||
|
||||
cpu.pipe.flush();
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@ const expected_rate = @import("emu.zig").frame_rate;
|
||||
|
||||
const sample_rate = @import("apu.zig").host_sample_rate;
|
||||
|
||||
pub const enable_logging: bool = false;
|
||||
pub const enable_logging: bool = true;
|
||||
const is_binary: bool = false;
|
||||
const log = std.log.scoped(.GUI);
|
||||
pub const log_level = if (builtin.mode != .Debug) .info else std.log.default_level;
|
||||
@@ -72,7 +72,7 @@ pub fn main() anyerror!void {
|
||||
var cpu = try Arm7tdmi.init(alloc, &scheduler, paths);
|
||||
defer cpu.deinit();
|
||||
cpu.bus.attach(&cpu);
|
||||
// cpu.fastBoot(); // Uncomment to skip BIOS
|
||||
cpu.fastBoot(); // Uncomment to skip BIOS
|
||||
|
||||
// Copy ROM title while Emulator still belongs to this thread
|
||||
const title = cpu.bus.pak.title;
|
||||
|
Reference in New Issue
Block a user