tmp: progress towards reworking arm ldm/stm
This commit is contained in:
parent
2c5d474c56
commit
cbd535f6c9
|
@ -12,18 +12,20 @@ pub fn blockDataTransfer(comptime InstrFn: type, comptime P: bool, comptime U: b
|
|||
// U determines whether the LDM/STM transfer is made upwards (U == 1)
|
||||
// or downwards (U == 0).
|
||||
|
||||
const base_addr = cpu.r[rn];
|
||||
|
||||
const start_addr: u32 = if (U) blk: {
|
||||
break :blk cpu.r[rn] + if (P) 4 else 0;
|
||||
break :blk base_addr + if (P) 4 else 0;
|
||||
} else blk: {
|
||||
break :blk cpu.r[rn] - (4 * reg_count) + if (!P) 4 else 0;
|
||||
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 cpu.r[rn] + 4 * reg_count;
|
||||
break :blk base_addr + 4 * reg_count;
|
||||
} else blk: {
|
||||
break :blk cpu.r[rn] - 4 * reg_count;
|
||||
break :blk base_addr - 4 * reg_count;
|
||||
};
|
||||
|
||||
var address = start_addr;
|
||||
|
@ -36,9 +38,9 @@ pub fn blockDataTransfer(comptime InstrFn: type, comptime P: bool, comptime U: b
|
|||
if (rlist == 0) {
|
||||
if (Arm32.arch == .v4t) {
|
||||
const undefined_addr: u32 = if (U) blk: {
|
||||
break :blk cpu.r[rn] + if (P) 4 else 0;
|
||||
break :blk base_addr + if (P) 4 else 0;
|
||||
} else blk: {
|
||||
break :blk cpu.r[rn] - (0x40 - if (!P) 4 else 0);
|
||||
break :blk base_addr - (0x40 - if (!P) 4 else 0);
|
||||
};
|
||||
|
||||
if (L) {
|
||||
|
@ -49,20 +51,14 @@ pub fn blockDataTransfer(comptime InstrFn: type, comptime P: bool, comptime U: b
|
|||
}
|
||||
}
|
||||
|
||||
cpu.r[rn] = if (U) cpu.r[rn] + 0x40 else cpu.r[rn] - 0x40;
|
||||
cpu.r[rn] = if (U) base_addr + 0x40 else base_addr - 0x40;
|
||||
return;
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
// FIXME: This absolutely needs revisiting :skull:
|
||||
|
||||
const r15_present = rlist >> 15 & 1 == 1;
|
||||
var write_to_base = true;
|
||||
|
||||
// var first = true;
|
||||
for (first_in_list..16) |idx| {
|
||||
const i: u4 = @intCast(idx);
|
||||
|
||||
|
@ -70,13 +66,36 @@ pub fn blockDataTransfer(comptime InstrFn: type, comptime P: bool, comptime U: b
|
|||
transfer(cpu, r15_present, i, address);
|
||||
address += 4;
|
||||
|
||||
if (W and !L and write_to_base) {
|
||||
cpu.r[rn] = new_base_addr;
|
||||
write_to_base = false;
|
||||
}
|
||||
// if (W and !L and first) {
|
||||
// cpu.r[rn] = switch (Arm32.arch) {
|
||||
// .v4t => new_base_addr,
|
||||
// .v5te => start_addr,
|
||||
// };
|
||||
|
||||
// first = false;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
// 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 (rn_in_rlist) {
|
||||
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;
|
||||
}
|
||||
|
||||
// What happens when W is set and Rn is in the rlist? (LDM)
|
||||
//
|
||||
// ARMv4: No writeback
|
||||
|
|
Loading…
Reference in New Issue