chore: tmp
This commit is contained in:
parent
cbd535f6c9
commit
1d4b5d4024
|
@ -3,6 +3,8 @@ pub fn blockDataTransfer(comptime InstrFn: type, comptime P: bool, comptime U: b
|
|||
|
||||
return struct {
|
||||
fn inner(cpu: *Arm32, opcode: u32) void {
|
||||
if (opcode == @byteSwap(0x030020E9)) @breakpoint();
|
||||
|
||||
const rn: u4 = @truncate(opcode >> 16 & 0xF);
|
||||
const rlist: u16 = @intCast(opcode & 0xFFFF);
|
||||
|
||||
|
@ -20,8 +22,6 @@ pub fn blockDataTransfer(comptime InstrFn: type, comptime P: bool, comptime U: b
|
|||
break :blk base_addr - (4 * reg_count) + if (!P) 4 else 0;
|
||||
};
|
||||
|
||||
// FIXME : why 4 * reg_count?
|
||||
|
||||
const new_base_addr: u32 = if (U) blk: {
|
||||
break :blk base_addr + 4 * reg_count;
|
||||
} else blk: {
|
||||
|
@ -77,23 +77,47 @@ pub fn blockDataTransfer(comptime InstrFn: type, comptime P: bool, comptime U: b
|
|||
}
|
||||
}
|
||||
|
||||
{
|
||||
const cond = @as(u2, @intFromBool(P)) << 1 | @intFromBool(U);
|
||||
|
||||
const end_address: u32 = switch (cond) {
|
||||
0b00 => base_addr, // Decrement After
|
||||
0b10 => base_addr - 4, // Increment Before
|
||||
0b01 => base_addr + (4 * reg_count) - 4, // Increment After
|
||||
0b11 => base_addr + (4 * reg_count), // Increment Before
|
||||
};
|
||||
|
||||
const actual_addr = address - 4;
|
||||
|
||||
if (actual_addr != end_address) {
|
||||
cpu.panic(
|
||||
\\P = {}, U = {}, S = {}, W = {}, L = {}
|
||||
\\base_addr = 0x{X:0>8}
|
||||
\\start_addr = 0x{X:0>8}
|
||||
\\expected_end_address = 0x{X:0>8} actual_end_address = 0x{X:0>8}
|
||||
\\rlist = 0b{b:0>16}, first_in_list = r{}
|
||||
, .{ P, U, S, W, L, base_addr, start_addr, end_address, actual_addr, rlist, first_in_list });
|
||||
}
|
||||
}
|
||||
|
||||
// What happens when W is set and Rn is in the rlist? (STM)
|
||||
//
|
||||
// Armv4: Store OLD Base if Rb is FIRST entry in Rlist, otherwise store NEW base
|
||||
// Armv5: Always store OLD Base
|
||||
|
||||
if (W and !L) {
|
||||
const rn_in_rlist = rlist >> rn & 1 == 1;
|
||||
if (rlist >> rn & 1 == 0) { // rn is not in rlist
|
||||
cpu.r[rn] = new_base_addr;
|
||||
return;
|
||||
}
|
||||
|
||||
if (rn_in_rlist) {
|
||||
const mask = @as(u16, 1) << rn;
|
||||
const is_first = @popCount(rlist & (mask - 1)) == 0;
|
||||
const mask = @as(u16, 1) << rn;
|
||||
const is_first = @popCount(rlist & (mask - 1)) == 0;
|
||||
|
||||
cpu.r[rn] = switch (Arm32.arch) {
|
||||
.v4t => if (is_first) base_addr else new_base_addr,
|
||||
.v5te => base_addr,
|
||||
};
|
||||
} else cpu.r[rn] = new_base_addr;
|
||||
cpu.r[rn] = switch (Arm32.arch) {
|
||||
.v4t => if (is_first) base_addr else new_base_addr,
|
||||
.v5te => base_addr,
|
||||
};
|
||||
}
|
||||
|
||||
// What happens when W is set and Rn is in the rlist? (LDM)
|
||||
|
@ -102,7 +126,7 @@ pub fn blockDataTransfer(comptime InstrFn: type, comptime P: bool, comptime U: b
|
|||
// ARMv5: writeback if Rn is "the ONLY register" or NOT the LAST register
|
||||
|
||||
if (W and L) {
|
||||
if (rlist >> rn & 1 == 0) {
|
||||
if (rlist >> rn & 1 == 0) { // rn is not in rlist
|
||||
cpu.r[rn] = new_base_addr;
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue