Compare commits
4 Commits
77dba68a0b
...
ae37b1218b
Author | SHA1 | Date |
---|---|---|
Rekai Nyangadzayi Musuka | ae37b1218b | |
Rekai Nyangadzayi Musuka | 070322064d | |
Rekai Nyangadzayi Musuka | 37bd6758fb | |
Rekai Nyangadzayi Musuka | 7f6ab626d9 |
20
src/cpu.zig
20
src/cpu.zig
|
@ -1,19 +1,19 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const util = @import("util.zig");
|
const util = @import("util.zig");
|
||||||
|
|
||||||
const BarrelShifter = @import("cpu/barrel_shifter.zig");
|
const BarrelShifter = @import("cpu/arm/barrel_shifter.zig");
|
||||||
const Bus = @import("Bus.zig");
|
const Bus = @import("Bus.zig");
|
||||||
const Bit = @import("bitfield").Bit;
|
const Bit = @import("bitfield").Bit;
|
||||||
const Bitfield = @import("bitfield").Bitfield;
|
const Bitfield = @import("bitfield").Bitfield;
|
||||||
const Scheduler = @import("scheduler.zig").Scheduler;
|
const Scheduler = @import("scheduler.zig").Scheduler;
|
||||||
|
|
||||||
const dataProcessing = @import("cpu/data_processing.zig").dataProcessing;
|
const dataProcessing = @import("cpu/arm/data_processing.zig").dataProcessing;
|
||||||
const psrTransfer = @import("cpu/psr_transfer.zig").psrTransfer;
|
const psrTransfer = @import("cpu/arm/psr_transfer.zig").psrTransfer;
|
||||||
const singleDataTransfer = @import("cpu/single_data_transfer.zig").singleDataTransfer;
|
const singleDataTransfer = @import("cpu/arm/single_data_transfer.zig").singleDataTransfer;
|
||||||
const halfAndSignedDataTransfer = @import("cpu/half_signed_data_transfer.zig").halfAndSignedDataTransfer;
|
const halfAndSignedDataTransfer = @import("cpu/arm/half_signed_data_transfer.zig").halfAndSignedDataTransfer;
|
||||||
const blockDataTransfer = @import("cpu/block_data_transfer.zig").blockDataTransfer;
|
const blockDataTransfer = @import("cpu/arm/block_data_transfer.zig").blockDataTransfer;
|
||||||
const branch = @import("cpu/branch.zig").branch;
|
const branch = @import("cpu/arm/branch.zig").branch;
|
||||||
const branchAndExchange = @import("cpu/branch.zig").branchAndExchange;
|
const branchAndExchange = @import("cpu/arm/branch.zig").branchAndExchange;
|
||||||
|
|
||||||
pub const InstrFn = fn (*Arm7tdmi, *Bus, u32) void;
|
pub const InstrFn = fn (*Arm7tdmi, *Bus, u32) void;
|
||||||
const arm_lut: [0x1000]InstrFn = populate();
|
const arm_lut: [0x1000]InstrFn = populate();
|
||||||
|
@ -102,7 +102,7 @@ fn checkCond(cpsr: *const PSR, opcode: u32) bool {
|
||||||
// TODO: Should I implement an enum?
|
// TODO: Should I implement an enum?
|
||||||
return switch (@truncate(u4, opcode >> 28)) {
|
return switch (@truncate(u4, opcode >> 28)) {
|
||||||
0x0 => cpsr.z.read(), // EQ - Equal
|
0x0 => cpsr.z.read(), // EQ - Equal
|
||||||
0x1 => !cpsr.z.read(), // NEQ - Not equal
|
0x1 => !cpsr.z.read(), // NE - Not equal
|
||||||
0x2 => cpsr.c.read(), // CS - Unsigned higher or same
|
0x2 => cpsr.c.read(), // CS - Unsigned higher or same
|
||||||
0x3 => !cpsr.c.read(), // CC - Unsigned lower
|
0x3 => !cpsr.c.read(), // CC - Unsigned lower
|
||||||
0x4 => cpsr.n.read(), // MI - Negative
|
0x4 => cpsr.n.read(), // MI - Negative
|
||||||
|
@ -113,7 +113,7 @@ fn checkCond(cpsr: *const PSR, opcode: u32) bool {
|
||||||
0x9 => !cpsr.c.read() and cpsr.z.read(), // LS - unsigned lower or same
|
0x9 => !cpsr.c.read() and cpsr.z.read(), // LS - unsigned lower or same
|
||||||
0xA => cpsr.n.read() == cpsr.v.read(), // GE - Greater or equal
|
0xA => cpsr.n.read() == cpsr.v.read(), // GE - Greater or equal
|
||||||
0xB => cpsr.n.read() != cpsr.v.read(), // LT - Less than
|
0xB => cpsr.n.read() != cpsr.v.read(), // LT - Less than
|
||||||
0xC => !cpsr.z.read() and (cpsr.n.read() == cpsr.z.read()), // GT - Greater than
|
0xC => !cpsr.z.read() and (cpsr.n.read() == cpsr.v.read()), // GT - Greater than
|
||||||
0xD => cpsr.z.read() or (cpsr.n.read() != cpsr.v.read()), // LE - Less than or equal
|
0xD => cpsr.z.read() or (cpsr.n.read() != cpsr.v.read()), // LE - Less than or equal
|
||||||
0xE => true, // AL - Always
|
0xE => true, // AL - Always
|
||||||
0xF => std.debug.panic("[CPU] 0xF is a reserved condition field", .{}),
|
0xF => std.debug.panic("[CPU] 0xF is a reserved condition field", .{}),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const Arm7tdmi = @import("../cpu.zig").Arm7tdmi;
|
const Arm7tdmi = @import("../../cpu.zig").Arm7tdmi;
|
||||||
const CPSR = @import("../cpu.zig").PSR;
|
const CPSR = @import("../../cpu.zig").PSR;
|
||||||
|
|
||||||
pub fn exec(comptime S: bool, cpu: *Arm7tdmi, opcode: u32) u32 {
|
pub fn exec(comptime S: bool, cpu: *Arm7tdmi, opcode: u32) u32 {
|
||||||
var shift_amt: u8 = undefined;
|
var shift_amt: u8 = undefined;
|
|
@ -1,8 +1,8 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const Bus = @import("../Bus.zig");
|
const Bus = @import("../../Bus.zig");
|
||||||
const Arm7tdmi = @import("../cpu.zig").Arm7tdmi;
|
const Arm7tdmi = @import("../../cpu.zig").Arm7tdmi;
|
||||||
const InstrFn = @import("../cpu.zig").InstrFn;
|
const InstrFn = @import("../../cpu.zig").InstrFn;
|
||||||
|
|
||||||
pub fn blockDataTransfer(comptime P: bool, comptime U: bool, comptime S: bool, comptime W: bool, comptime L: bool) InstrFn {
|
pub fn blockDataTransfer(comptime P: bool, comptime U: bool, comptime S: bool, comptime W: bool, comptime L: bool) InstrFn {
|
||||||
return struct {
|
return struct {
|
||||||
|
@ -12,9 +12,10 @@ pub fn blockDataTransfer(comptime P: bool, comptime U: bool, comptime S: bool, c
|
||||||
|
|
||||||
if (S and opcode >> 15 & 1 == 0) std.debug.panic("[CPU] TODO: STM/LDM with S set but R15 not in transfer list", .{});
|
if (S and opcode >> 15 & 1 == 0) std.debug.panic("[CPU] TODO: STM/LDM with S set but R15 not in transfer list", .{});
|
||||||
|
|
||||||
|
var address: u32 = undefined;
|
||||||
if (U) {
|
if (U) {
|
||||||
// Increment
|
// Increment
|
||||||
var address = if (P) base + 4 else base;
|
address = if (P) base + 4 else base;
|
||||||
|
|
||||||
var i: u5 = 0;
|
var i: u5 = 0;
|
||||||
while (i < 0x10) : (i += 1) {
|
while (i < 0x10) : (i += 1) {
|
||||||
|
@ -23,24 +24,22 @@ pub fn blockDataTransfer(comptime P: bool, comptime U: bool, comptime S: bool, c
|
||||||
address += 4;
|
address += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (W and P or !P) cpu.r[rn] = address - 4;
|
|
||||||
} else {
|
} else {
|
||||||
// Decrement
|
// Decrement
|
||||||
var address = if (P) base - 4 else base;
|
address = if (P) base - 4 else base;
|
||||||
|
|
||||||
var i: u5 = 0x10;
|
var i: u5 = 0x10;
|
||||||
while (i > 0) : (i -= 1) {
|
while (i > 0) : (i -= 1) {
|
||||||
const reg_idx = i - 1;
|
const j = i - 1;
|
||||||
|
|
||||||
if (opcode >> reg_idx & 1 == 1) {
|
if (opcode >> j & 1 == 1) {
|
||||||
transfer(cpu, bus, reg_idx, address);
|
transfer(cpu, bus, j, address);
|
||||||
address -= 4;
|
address -= 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (W and P or !P) cpu.r[rn] = address + 4;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (W and P or !P) cpu.r[rn] = if (U) address else address + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn transfer(cpu: *Arm7tdmi, bus: *Bus, i: u5, address: u32) void {
|
fn transfer(cpu: *Arm7tdmi, bus: *Bus, i: u5, address: u32) void {
|
|
@ -1,9 +1,9 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const util = @import("../util.zig");
|
const util = @import("../../util.zig");
|
||||||
|
|
||||||
const Bus = @import("../Bus.zig");
|
const Bus = @import("../../Bus.zig");
|
||||||
const Arm7tdmi = @import("../cpu.zig").Arm7tdmi;
|
const Arm7tdmi = @import("../../cpu.zig").Arm7tdmi;
|
||||||
const InstrFn = @import("../cpu.zig").InstrFn;
|
const InstrFn = @import("../../cpu.zig").InstrFn;
|
||||||
|
|
||||||
pub fn branch(comptime L: bool) InstrFn {
|
pub fn branch(comptime L: bool) InstrFn {
|
||||||
return struct {
|
return struct {
|
|
@ -1,9 +1,9 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const BarrelShifter = @import("barrel_shifter.zig");
|
const BarrelShifter = @import("barrel_shifter.zig");
|
||||||
const Bus = @import("../Bus.zig");
|
const Bus = @import("../../Bus.zig");
|
||||||
const Arm7tdmi = @import("../cpu.zig").Arm7tdmi;
|
const Arm7tdmi = @import("../../cpu.zig").Arm7tdmi;
|
||||||
const InstrFn = @import("../cpu.zig").InstrFn;
|
const InstrFn = @import("../../cpu.zig").InstrFn;
|
||||||
|
|
||||||
pub fn dataProcessing(comptime I: bool, comptime S: bool, comptime instrKind: u4) InstrFn {
|
pub fn dataProcessing(comptime I: bool, comptime S: bool, comptime instrKind: u4) InstrFn {
|
||||||
return struct {
|
return struct {
|
|
@ -1,9 +1,9 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const util = @import("../util.zig");
|
const util = @import("../../util.zig");
|
||||||
|
|
||||||
const Bus = @import("../Bus.zig");
|
const Bus = @import("../../Bus.zig");
|
||||||
const Arm7tdmi = @import("../cpu.zig").Arm7tdmi;
|
const Arm7tdmi = @import("../../cpu.zig").Arm7tdmi;
|
||||||
const InstrFn = @import("../cpu.zig").InstrFn;
|
const InstrFn = @import("../../cpu.zig").InstrFn;
|
||||||
|
|
||||||
pub fn halfAndSignedDataTransfer(comptime P: bool, comptime U: bool, comptime I: bool, comptime W: bool, comptime L: bool) InstrFn {
|
pub fn halfAndSignedDataTransfer(comptime P: bool, comptime U: bool, comptime I: bool, comptime W: bool, comptime L: bool) InstrFn {
|
||||||
return struct {
|
return struct {
|
|
@ -1,8 +1,8 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const Bus = @import("../Bus.zig");
|
const Bus = @import("../../Bus.zig");
|
||||||
const Arm7tdmi = @import("../cpu.zig").Arm7tdmi;
|
const Arm7tdmi = @import("../../cpu.zig").Arm7tdmi;
|
||||||
const InstrFn = @import("../cpu.zig").InstrFn;
|
const InstrFn = @import("../../cpu.zig").InstrFn;
|
||||||
|
|
||||||
pub fn psrTransfer(comptime I: bool, comptime isSpsr: bool) InstrFn {
|
pub fn psrTransfer(comptime I: bool, comptime isSpsr: bool) InstrFn {
|
||||||
return struct {
|
return struct {
|
||||||
|
@ -24,15 +24,13 @@ pub fn psrTransfer(comptime I: bool, comptime isSpsr: bool) InstrFn {
|
||||||
|
|
||||||
switch (@truncate(u3, opcode >> 16)) {
|
switch (@truncate(u3, opcode >> 16)) {
|
||||||
0b000 => {
|
0b000 => {
|
||||||
const right = if (I) std.math.rotr(u32, opcode & 0xFF, opcode >> 8 & 0xF) else cpu.r[rm];
|
const right = if (I) std.math.rotr(u32, opcode & 0xFF, opcode >> 7 & 0xF) else cpu.r[rm];
|
||||||
|
|
||||||
if (isSpsr) {
|
if (isSpsr) {
|
||||||
std.debug.panic("[CPU] TODO: MSR (flags only) on SPSR_<current_mode> is unimplemented", .{});
|
std.debug.panic("[CPU] TODO: MSR (flags only) on SPSR_<current_mode> is unimplemented", .{});
|
||||||
} else {
|
} else {
|
||||||
cpu.cpsr.n.write(right >> 31 & 1 == 1);
|
const mask: u32 = 0xF000_0000;
|
||||||
cpu.cpsr.z.write(right >> 30 & 1 == 1);
|
cpu.cpsr.raw = (cpu.cpsr.raw & ~mask) | (right & mask);
|
||||||
cpu.cpsr.c.write(right >> 29 & 1 == 1);
|
|
||||||
cpu.cpsr.v.write(right >> 28 & 1 == 1);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
0b001 => {
|
0b001 => {
|
|
@ -1,11 +1,11 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const util = @import("../util.zig");
|
const util = @import("../../util.zig");
|
||||||
|
|
||||||
const BarrelShifter = @import("barrel_shifter.zig");
|
const BarrelShifter = @import("barrel_shifter.zig");
|
||||||
const Bus = @import("../Bus.zig");
|
const Bus = @import("../../Bus.zig");
|
||||||
const Arm7tdmi = @import("../cpu.zig").Arm7tdmi;
|
const Arm7tdmi = @import("../../cpu.zig").Arm7tdmi;
|
||||||
const CPSR = @import("../cpu.zig").PSR;
|
const CPSR = @import("../../cpu.zig").PSR;
|
||||||
const InstrFn = @import("../cpu.zig").InstrFn;
|
const InstrFn = @import("../../cpu.zig").InstrFn;
|
||||||
|
|
||||||
pub fn singleDataTransfer(comptime I: bool, comptime P: bool, comptime U: bool, comptime B: bool, comptime W: bool, comptime L: bool) InstrFn {
|
pub fn singleDataTransfer(comptime I: bool, comptime P: bool, comptime U: bool, comptime B: bool, comptime W: bool, comptime L: bool) InstrFn {
|
||||||
return struct {
|
return struct {
|
Loading…
Reference in New Issue