Compare commits
No commits in common. "30bad76e446465576847c19a4150d864e95e080c" and "48017b45f5782b462a5310dc35a66af8fd956bc5" have entirely different histories.
30bad76e44
...
48017b45f5
100
src/cpu.zig
100
src/cpu.zig
|
@ -19,7 +19,6 @@ const branchAndExchange = @import("cpu/arm/branch.zig").branchAndExchange;
|
||||||
const softwareInterrupt = @import("cpu/arm/software_interrupt.zig").softwareInterrupt;
|
const softwareInterrupt = @import("cpu/arm/software_interrupt.zig").softwareInterrupt;
|
||||||
const multiply = @import("cpu/arm/multiply.zig").multiply;
|
const multiply = @import("cpu/arm/multiply.zig").multiply;
|
||||||
const multiplyLong = @import("cpu/arm/multiply_long.zig").multiplyLong;
|
const multiplyLong = @import("cpu/arm/multiply_long.zig").multiplyLong;
|
||||||
const singleDataSwap = @import("cpu/arm/single_data_swap.zig").singleDataSwap;
|
|
||||||
|
|
||||||
// THUMB Instruction Groups
|
// THUMB Instruction Groups
|
||||||
const format1 = @import("cpu/thumb/format1.zig").format1;
|
const format1 = @import("cpu/thumb/format1.zig").format1;
|
||||||
|
@ -492,35 +491,33 @@ fn thumbPopulate() [0x400]ThumbInstrFn {
|
||||||
|
|
||||||
fn armPopulate() [0x1000]ArmInstrFn {
|
fn armPopulate() [0x1000]ArmInstrFn {
|
||||||
return comptime {
|
return comptime {
|
||||||
@setEvalBranchQuota(0xE000);
|
@setEvalBranchQuota(0x5000); // TODO: Figure out exact size
|
||||||
var lut = [_]ArmInstrFn{armUndefined} ** 0x1000;
|
var lut = [_]ArmInstrFn{armUndefined} ** 0x1000;
|
||||||
|
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < lut.len) : (i += 1) {
|
while (i < lut.len) : (i += 1) {
|
||||||
// Instructions with Opcode[27] == 0
|
if (i >> 10 & 0x3 == 0b00) {
|
||||||
|
const I = i >> 9 & 1 == 1;
|
||||||
|
const S = i >> 4 & 1 == 1;
|
||||||
|
const instrKind = i >> 5 & 0xF;
|
||||||
|
|
||||||
|
lut[i] = dataProcessing(I, S, instrKind);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i >> 10 & 0x3 == 0b00 and i >> 7 & 0x3 == 0b10 and i >> 4 & 1 == 0) {
|
||||||
|
// PSR Transfer
|
||||||
|
const I = i >> 9 & 1 == 1;
|
||||||
|
const R = i >> 6 & 1 == 1;
|
||||||
|
const kind = i >> 4 & 0x3;
|
||||||
|
|
||||||
|
lut[i] = psrTransfer(I, R, kind);
|
||||||
|
}
|
||||||
|
|
||||||
if (i == 0x121) {
|
if (i == 0x121) {
|
||||||
// Bits 27:20 and 7:4
|
|
||||||
lut[i] = branchAndExchange;
|
lut[i] = branchAndExchange;
|
||||||
} else if (i >> 6 & 0x3F == 0b000000 and i & 0xF == 0b1001) {
|
}
|
||||||
// Bits 27:22 and 7:4
|
|
||||||
const A = i >> 5 & 1 == 1;
|
|
||||||
const S = i >> 4 & 1 == 1;
|
|
||||||
|
|
||||||
lut[i] = multiply(A, S);
|
if (i >> 9 & 0x7 == 0b000 and i >> 3 & 1 == 1 and i & 1 == 1) {
|
||||||
} else if (i >> 7 & 0x1F == 0b00010 and i >> 4 & 0x3 == 0b00 and i & 0xF == 0b1001) {
|
|
||||||
// Bits 27:23, 21:20 and 7:4
|
|
||||||
const B = i >> 6 & 1 == 1;
|
|
||||||
|
|
||||||
lut[i] = singleDataSwap(B);
|
|
||||||
} else if (i >> 7 & 0x1F == 0b00001 and i & 0xF == 0b1001) {
|
|
||||||
// Bits 27:23 and bits 7:4
|
|
||||||
const U = i >> 6 & 1 == 1;
|
|
||||||
const A = i >> 5 & 1 == 1;
|
|
||||||
const S = i >> 4 & 1 == 1;
|
|
||||||
|
|
||||||
lut[i] = multiplyLong(U, A, S);
|
|
||||||
} else if (i >> 9 & 0x7 == 0b000 and i >> 3 & 1 == 1 and i & 1 == 1) {
|
|
||||||
// Bits 27:25, 7 and 4
|
|
||||||
const P = i >> 8 & 1 == 1;
|
const P = i >> 8 & 1 == 1;
|
||||||
const U = i >> 7 & 1 == 1;
|
const U = i >> 7 & 1 == 1;
|
||||||
const I = i >> 6 & 1 == 1;
|
const I = i >> 6 & 1 == 1;
|
||||||
|
@ -528,18 +525,24 @@ fn armPopulate() [0x1000]ArmInstrFn {
|
||||||
const L = i >> 4 & 1 == 1;
|
const L = i >> 4 & 1 == 1;
|
||||||
|
|
||||||
lut[i] = halfAndSignedDataTransfer(P, U, I, W, L);
|
lut[i] = halfAndSignedDataTransfer(P, U, I, W, L);
|
||||||
} else if (i >> 9 & 0x7 == 0b011 and i & 1 == 1) {
|
}
|
||||||
// Bits 27:25 and 4
|
|
||||||
lut[i] = armUndefined;
|
|
||||||
} else if (i >> 10 & 0x3 == 0b00 and i >> 7 & 0x3 == 0b10 and i >> 4 & 1 == 0) {
|
|
||||||
// Bits 27:26, 24:23 and 20
|
|
||||||
const I = i >> 9 & 1 == 1;
|
|
||||||
const R = i >> 6 & 1 == 1;
|
|
||||||
const kind = i >> 4 & 0x3;
|
|
||||||
|
|
||||||
lut[i] = psrTransfer(I, R, kind);
|
if (i >> 6 & 0x3F == 0b000000 and i & 0xF == 0b1001) {
|
||||||
} else if (i >> 10 & 0x3 == 0b01) {
|
const A = i >> 5 & 1 == 1;
|
||||||
// Bits 27:26
|
const S = i >> 4 & 1 == 1;
|
||||||
|
|
||||||
|
lut[i] = multiply(A, S);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i >> 7 & 0x1F == 0b00001 and i & 0xF == 0b1001) {
|
||||||
|
const U = i >> 6 & 1 == 1;
|
||||||
|
const A = i >> 5 & 1 == 1;
|
||||||
|
const S = i >> 4 & 1 == 1;
|
||||||
|
|
||||||
|
lut[i] = multiplyLong(U, A, S);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i >> 10 & 0x3 == 0b01) {
|
||||||
const I = i >> 9 & 1 == 1;
|
const I = i >> 9 & 1 == 1;
|
||||||
const P = i >> 8 & 1 == 1;
|
const P = i >> 8 & 1 == 1;
|
||||||
const U = i >> 7 & 1 == 1;
|
const U = i >> 7 & 1 == 1;
|
||||||
|
@ -548,22 +551,9 @@ fn armPopulate() [0x1000]ArmInstrFn {
|
||||||
const L = i >> 4 & 1 == 1;
|
const L = i >> 4 & 1 == 1;
|
||||||
|
|
||||||
lut[i] = singleDataTransfer(I, P, U, B, W, L);
|
lut[i] = singleDataTransfer(I, P, U, B, W, L);
|
||||||
} else if (i >> 10 & 0x3 == 0b00) {
|
|
||||||
// Bits 27:26
|
|
||||||
const I = i >> 9 & 1 == 1;
|
|
||||||
const S = i >> 4 & 1 == 1;
|
|
||||||
const instrKind = i >> 5 & 0xF;
|
|
||||||
|
|
||||||
lut[i] = dataProcessing(I, S, instrKind);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instructions with Opcode[27] == 1
|
if (i >> 9 & 0x7 == 0b100) {
|
||||||
if (i >> 8 & 0xF == 0b1110) {
|
|
||||||
// bits 27:24
|
|
||||||
// Coprocessor Data Opertation + Register Transfer
|
|
||||||
lut[i] = armUndefined;
|
|
||||||
} else if (i >> 9 & 0x7 == 0b100) {
|
|
||||||
// Bits 27:25
|
|
||||||
const P = i >> 8 & 1 == 1;
|
const P = i >> 8 & 1 == 1;
|
||||||
const U = i >> 7 & 1 == 1;
|
const U = i >> 7 & 1 == 1;
|
||||||
const S = i >> 6 & 1 == 1;
|
const S = i >> 6 & 1 == 1;
|
||||||
|
@ -571,18 +561,14 @@ fn armPopulate() [0x1000]ArmInstrFn {
|
||||||
const L = i >> 4 & 1 == 1;
|
const L = i >> 4 & 1 == 1;
|
||||||
|
|
||||||
lut[i] = blockDataTransfer(P, U, S, W, L);
|
lut[i] = blockDataTransfer(P, U, S, W, L);
|
||||||
} else if (i >> 9 & 0x7 == 0b101) {
|
}
|
||||||
// Bits 27:25
|
|
||||||
|
if (i >> 9 & 0x7 == 0b101) {
|
||||||
const L = i >> 8 & 1 == 1;
|
const L = i >> 8 & 1 == 1;
|
||||||
lut[i] = branch(L);
|
lut[i] = branch(L);
|
||||||
} else if (i >> 9 & 0x7 == 0b110) {
|
|
||||||
// Bits 27:25
|
|
||||||
// Coprocessor Data Transfer
|
|
||||||
lut[i] = armUndefined;
|
|
||||||
} else if (i >> 8 & 0xF == 0b1111) {
|
|
||||||
// Bits 27:24
|
|
||||||
lut[i] = softwareInterrupt();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (i >> 8 & 0xF == 0b1111) lut[i] = softwareInterrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
return lut;
|
return lut;
|
||||||
|
|
|
@ -33,6 +33,12 @@ pub fn halfAndSignedDataTransfer(comptime P: bool, comptime U: bool, comptime I:
|
||||||
|
|
||||||
if (L) {
|
if (L) {
|
||||||
switch (@truncate(u2, opcode >> 5)) {
|
switch (@truncate(u2, opcode >> 5)) {
|
||||||
|
0b00 => {
|
||||||
|
// SWP
|
||||||
|
const value = bus.read32(cpu.r[rn]);
|
||||||
|
const tmp = std.math.rotr(u32, value, 8 * (cpu.r[rn] & 0x3));
|
||||||
|
bus.write32(cpu.r[rm], tmp);
|
||||||
|
},
|
||||||
0b01 => {
|
0b01 => {
|
||||||
// LDRH
|
// LDRH
|
||||||
const value = bus.read16(address & 0xFFFF_FFFE);
|
const value = bus.read16(address & 0xFFFF_FFFE);
|
||||||
|
@ -48,13 +54,14 @@ pub fn halfAndSignedDataTransfer(comptime P: bool, comptime U: bool, comptime I:
|
||||||
cpu.r[rd] = util.u32SignExtend(16, @as(u32, bus.read16(address)));
|
cpu.r[rd] = util.u32SignExtend(16, @as(u32, bus.read16(address)));
|
||||||
cpu.panic("[CPU|ARM|LDRSH] TODO: Affect the CPSR", .{});
|
cpu.panic("[CPU|ARM|LDRSH] TODO: Affect the CPSR", .{});
|
||||||
},
|
},
|
||||||
0b00 => unreachable, // SWP
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (opcode >> 5 & 0x01 == 0x01) {
|
if (opcode >> 5 & 0x01 == 0x01) {
|
||||||
// STRH
|
// STRH
|
||||||
bus.write16(address, @truncate(u16, cpu.r[rd]));
|
bus.write16(address, @truncate(u16, cpu.r[rd]));
|
||||||
} else unreachable; // SWP
|
} else {
|
||||||
|
std.debug.print("[CPU|ARM|SignedDataTransfer] {X:0>8} was improperly decoded", .{opcode});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
address = modified_base;
|
address = modified_base;
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
const std = @import("std");
|
|
||||||
|
|
||||||
const Bus = @import("../../Bus.zig");
|
|
||||||
const Arm7tdmi = @import("../../cpu.zig").Arm7tdmi;
|
|
||||||
const InstrFn = @import("../../cpu.zig").ArmInstrFn;
|
|
||||||
|
|
||||||
pub fn singleDataSwap(comptime B: bool) InstrFn {
|
|
||||||
return struct {
|
|
||||||
fn inner(cpu: *Arm7tdmi, bus: *Bus, opcode: u32) void {
|
|
||||||
const rn = opcode >> 16 & 0xF;
|
|
||||||
const rd = opcode >> 12 & 0xF;
|
|
||||||
const rm = opcode & 0xF;
|
|
||||||
|
|
||||||
const address = cpu.r[rn];
|
|
||||||
|
|
||||||
if (B) {
|
|
||||||
// SWPB
|
|
||||||
const value = bus.read8(address);
|
|
||||||
bus.write8(address, @truncate(u8, cpu.r[rm]));
|
|
||||||
cpu.r[rd] = value;
|
|
||||||
} else {
|
|
||||||
// SWP
|
|
||||||
const value = std.math.rotr(u32, bus.read32(address), 8 * (address & 0x3));
|
|
||||||
bus.write32(address, cpu.r[rm]);
|
|
||||||
cpu.r[rd] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.inner;
|
|
||||||
}
|
|
19
src/ppu.zig
19
src/ppu.zig
|
@ -50,20 +50,19 @@ pub const Ppu = struct {
|
||||||
std.mem.copy(u8, self.frame_buf[start..end], self.vram.buf[start..end]);
|
std.mem.copy(u8, self.frame_buf[start..end], self.vram.buf[start..end]);
|
||||||
},
|
},
|
||||||
0x4 => {
|
0x4 => {
|
||||||
const select = io.dispcnt.frame_select.read();
|
const frame_select = io.dispcnt.frame_select.read();
|
||||||
const vram_start = width * @as(usize, scanline);
|
|
||||||
const buf_start = vram_start * @sizeOf(u16);
|
|
||||||
|
|
||||||
const start = vram_start + if (select) 0xA000 else @as(usize, 0);
|
const fb_start = buf_pitch * @as(usize, scanline);
|
||||||
const end = start + width; // Each Entry is only a byte long
|
const vram_start = fb_start >> 1;
|
||||||
|
|
||||||
|
const start = if (frame_select) 0xA000 + vram_start else vram_start;
|
||||||
|
const end = start + width;
|
||||||
|
|
||||||
// Render Current Scanline
|
|
||||||
for (self.vram.buf[start..end]) |byte, i| {
|
for (self.vram.buf[start..end]) |byte, i| {
|
||||||
const id = byte * 2;
|
const fb_i = i * @sizeOf(u16);
|
||||||
const j = i * @sizeOf(u16);
|
|
||||||
|
|
||||||
self.frame_buf[buf_start + j + 1] = self.palette.buf[id + 1];
|
self.frame_buf[fb_start + fb_i + 1] = self.palette.buf[byte + 1];
|
||||||
self.frame_buf[buf_start + j] = self.palette.buf[id];
|
self.frame_buf[fb_start + fb_i] = self.palette.buf[byte];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => {}, // std.debug.panic("[PPU] TODO: Implement BG Mode {}", .{bg_mode}),
|
else => {}, // std.debug.panic("[PPU] TODO: Implement BG Mode {}", .{bg_mode}),
|
||||||
|
|
Loading…
Reference in New Issue