chore(cpu): iron out some false assumptions
This commit is contained in:
113
src/cpu.zig
113
src/cpu.zig
@@ -1,4 +1,5 @@
|
||||
const std = @import("std");
|
||||
const util = @import("util.zig");
|
||||
const Bus = @import("bus.zig").Bus;
|
||||
const Scheduler = @import("scheduler.zig").Scheduler;
|
||||
|
||||
@@ -16,12 +17,11 @@ pub const ARM7TDMI = struct {
|
||||
cpsr: CPSR,
|
||||
|
||||
pub fn new(scheduler: *Scheduler, bus: *Bus) @This() {
|
||||
const cpsr: u32 = 0x0000_00DF;
|
||||
return .{
|
||||
.r = [_]u32{0x00} ** 16,
|
||||
.sch = scheduler,
|
||||
.bus = bus,
|
||||
.cpsr = @bitCast(CPSR, cpsr),
|
||||
.cpsr = .{ .inner = 0x0000_00DF },
|
||||
};
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ pub const ARM7TDMI = struct {
|
||||
};
|
||||
|
||||
fn armIdx(opcode: u32) u12 {
|
||||
return @truncate(u12, opcode >> 20 & 0xFF) << 4 | @truncate(u12, opcode >> 8 & 0xF);
|
||||
return @truncate(u12, opcode >> 20 & 0xFF) << 4 | @truncate(u12, opcode >> 4 & 0xF);
|
||||
}
|
||||
|
||||
fn populate() [0x1000]InstrFn {
|
||||
@@ -65,29 +65,18 @@ fn populate() [0x1000]InstrFn {
|
||||
lut[i] = comptimeDataProcessing(I, S, instrKind);
|
||||
}
|
||||
|
||||
if (i >> 9 & 0x7 == 0b000 and i >> 6 & 0x01 == 0x00 and i & 0xF == 0x0) {
|
||||
if (i >> 9 & 0x7 == 0b000 and i >> 3 & 0x01 == 0x01 and i & 0x01 == 0x01) {
|
||||
// Halfword and Signed Data Transfer with register offset
|
||||
const P = i >> 8 & 0x01 == 0x01;
|
||||
const U = i >> 7 & 0x01 == 0x01;
|
||||
const I = true;
|
||||
const I = i >> 6 & 0x01 == 0x01;
|
||||
const W = i >> 5 & 0x01 == 0x01;
|
||||
const L = i >> 4 & 0x01 == 0x01;
|
||||
|
||||
lut[i] = comptimeHalfSignedDataTransfer(P, U, I, W, L);
|
||||
}
|
||||
|
||||
if (i >> 9 & 0x7 == 0b000 and i >> 6 & 0x01 == 0x01) {
|
||||
// Halfword and Signed Data Tranfer with immediate offset
|
||||
const P = i >> 8 & 0x01 == 0x01;
|
||||
const U = i >> 7 & 0x01 == 0x01;
|
||||
const I = false;
|
||||
const W = i >> 5 & 0x01 == 0x01;
|
||||
const L = i >> 4 & 0x01 == 0x01;
|
||||
|
||||
lut[i] = comptimeHalfSignedDataTransfer(P, U, I, W, L);
|
||||
}
|
||||
|
||||
if (i >> 10 & 0x3 == 0b01 and i & 0x01 == 0x00) {
|
||||
if (i >> 10 & 0x3 == 0b01) {
|
||||
const I = i >> 9 & 0x01 == 0x01;
|
||||
const P = i >> 8 & 0x01 == 0x01;
|
||||
const U = i >> 7 & 0x01 == 0x01;
|
||||
@@ -108,22 +97,85 @@ fn populate() [0x1000]InstrFn {
|
||||
};
|
||||
}
|
||||
|
||||
const CPSR = packed struct {
|
||||
n: bool, // Negative / Less Than
|
||||
z: bool, // Zero
|
||||
c: bool, // Carry / Borrow / Extend
|
||||
v: bool, // Overflow
|
||||
_: u20,
|
||||
i: bool, // IRQ Disable
|
||||
f: bool, // FIQ Diable
|
||||
t: bool, // State
|
||||
m: Mode, // Mode
|
||||
const CPSR = struct {
|
||||
inner: u32,
|
||||
|
||||
pub fn n(self: *const @This()) bool {
|
||||
return self.inner >> 31 & 0x01 == 0x01;
|
||||
}
|
||||
|
||||
pub fn set_n(self: *@This(), set: bool) void {
|
||||
self.set_bit(31, set);
|
||||
}
|
||||
|
||||
pub fn z(self: *const @This()) bool {
|
||||
return self.inner >> 30 & 0x01 == 0x01;
|
||||
}
|
||||
|
||||
pub fn set_z(self: *@This(), set: bool) void {
|
||||
self.set_bit(30, set);
|
||||
}
|
||||
|
||||
pub fn c(self: *const @This()) bool {
|
||||
return self.inner >> 29 & 0x01 == 0x01;
|
||||
}
|
||||
|
||||
pub fn set_c(self: *@This(), set: bool) void {
|
||||
self.set_bit(29, set);
|
||||
}
|
||||
|
||||
pub fn v(self: *const @This()) bool {
|
||||
return self.inner >> 28 & 0x01 == 0x01;
|
||||
}
|
||||
|
||||
pub fn set_v(self: *@This(), set: bool) void {
|
||||
self.set_bit(28, set);
|
||||
}
|
||||
|
||||
pub fn i(self: *const @This()) bool {
|
||||
return self.inner >> 7 & 0x01 == 0x01;
|
||||
}
|
||||
|
||||
pub fn set_i(self: *@This(), set: bool) void {
|
||||
self.set_bit(7, set);
|
||||
}
|
||||
|
||||
pub fn f(self: *const @This()) bool {
|
||||
return self.inner >> 6 & 0x01 == 0x01;
|
||||
}
|
||||
|
||||
pub fn set_f(self: *@This(), set: bool) void {
|
||||
self.set_bit(6, set);
|
||||
}
|
||||
|
||||
pub fn t(self: *const @This()) bool {
|
||||
return self.inner >> 5 & 0x01 == 0x01;
|
||||
}
|
||||
|
||||
pub fn set_t(self: *@This(), set: bool) void {
|
||||
self.set_bit(5, set);
|
||||
}
|
||||
|
||||
pub fn mode(self: *const @This()) Mode {
|
||||
return self.inner & 0x1F;
|
||||
}
|
||||
|
||||
pub fn set_mode(_: *@This(), _: Mode) void {
|
||||
std.debug.panic("TODO: Implement set_mode for CPSR", .{});
|
||||
}
|
||||
|
||||
fn set_bit(self: *@This(), comptime bit: usize, set: bool) void {
|
||||
const set_val = @as(u32, @boolToInt(set)) << bit;
|
||||
const mask = ~(@as(u32, 1) << bit);
|
||||
|
||||
self.inner = (self.inner & mask) | set_val;
|
||||
}
|
||||
};
|
||||
|
||||
const Mode = enum(u5) {
|
||||
User = 0b10000,
|
||||
Fiq = 0b10001,
|
||||
Irq = 0b10010,
|
||||
FIQ = 0b10001,
|
||||
IRQ = 0b10010,
|
||||
Supervisor = 0b10011,
|
||||
Abort = 0b10111,
|
||||
Undefined = 0b11011,
|
||||
@@ -142,8 +194,7 @@ fn comptimeBranch(comptime L: bool) InstrFn {
|
||||
cpu.r[14] = cpu.r[15] - 4;
|
||||
}
|
||||
|
||||
const offset = @bitCast(i32, (opcode << 2) << 8) >> 8;
|
||||
cpu.r[15] = cpu.fakePC() + @bitCast(u32, offset);
|
||||
cpu.r[15] = cpu.fakePC() + util.u32SignExtend(24, opcode << 2);
|
||||
}
|
||||
}.branch;
|
||||
}
|
||||
|
Reference in New Issue
Block a user