chore: don't write to CPSR + swap with SPSR at the same time

This commit is contained in:
Rekai Nyangadzayi Musuka 2022-09-28 10:01:52 -03:00
parent 014180cbd0
commit a948c6f900
1 changed files with 39 additions and 52 deletions

View File

@ -75,73 +75,60 @@ pub fn dataProcessing(comptime I: bool, comptime S: bool, comptime kind: u4) Ins
0x8, 0x9, 0xA, 0xB => {}, // Test Operations 0x8, 0x9, 0xA, 0xB => {}, // Test Operations
else => { else => {
cpu.r[rd] = result; cpu.r[rd] = result;
if (rd == 0xF) cpu.pipe.reload(u32, cpu); if (rd == 0xF) {
if (S) cpu.setCpsr(cpu.spsr.raw);
cpu.pipe.reload(u32, cpu);
}
}, },
} }
// Write Flags // Write Flags
switch (kind) { switch (kind) {
0x0, 0x1, 0xC, 0xD, 0xE, 0xF => { 0x0, 0x1, 0xC, 0xD, 0xE, 0xF => if (S and rd != 0xF) {
// Logic Operation Flags // Logic Operation Flags
if (S) { cpu.cpsr.n.write(result >> 31 & 1 == 1);
if (rd == 0xF) { cpu.cpsr.z.write(result == 0);
cpu.setCpsr(cpu.spsr.raw); // C set by Barrel Shifter, V is unaffected
} else {
cpu.cpsr.n.write(result >> 31 & 1 == 1);
cpu.cpsr.z.write(result == 0);
// C set by Barrel Shifter, V is unaffected
}
}
}, },
0x2, 0x3 => { 0x2, 0x3 => if (S and rd != 0xF) {
// SUB, RSB Flags // SUB, RSB Flags
if (S) { cpu.cpsr.n.write(result >> 31 & 1 == 1);
cpu.cpsr.n.write(result >> 31 & 1 == 1); cpu.cpsr.z.write(result == 0);
cpu.cpsr.z.write(result == 0);
if (kind == 0x2) { if (kind == 0x2) {
// SUB specific // SUB specific
cpu.cpsr.c.write(op2 <= op1); cpu.cpsr.c.write(op2 <= op1);
cpu.cpsr.v.write(((op1 ^ result) & (~op2 ^ result)) >> 31 & 1 == 1); cpu.cpsr.v.write(((op1 ^ result) & (~op2 ^ result)) >> 31 & 1 == 1);
} else { } else {
// RSB Specific // RSB Specific
cpu.cpsr.c.write(op1 <= op2); cpu.cpsr.c.write(op1 <= op2);
cpu.cpsr.v.write(((op2 ^ result) & (~op1 ^ result)) >> 31 & 1 == 1); cpu.cpsr.v.write(((op2 ^ result) & (~op1 ^ result)) >> 31 & 1 == 1);
}
if (rd == 0xF) cpu.setCpsr(cpu.spsr.raw);
} }
}, },
0x4, 0x5 => { 0x4, 0x5 => if (S and rd != 0xF) {
// ADD, ADC Flags // ADD, ADC Flags
if (S) { cpu.cpsr.n.write(result >> 31 & 1 == 1);
cpu.cpsr.n.write(result >> 31 & 1 == 1); cpu.cpsr.z.write(result == 0);
cpu.cpsr.z.write(result == 0); cpu.cpsr.c.write(didOverflow);
cpu.cpsr.c.write(didOverflow); cpu.cpsr.v.write(((op1 ^ result) & (op2 ^ result)) >> 31 & 1 == 1);
cpu.cpsr.v.write(((op1 ^ result) & (op2 ^ result)) >> 31 & 1 == 1);
if (rd == 0xF) cpu.setCpsr(cpu.spsr.raw);
}
}, },
0x6, 0x7 => { 0x6, 0x7 => if (S and rd != 0xF) {
// SBC, RSC Flags // SBC, RSC Flags
if (S) { cpu.cpsr.n.write(result >> 31 & 1 == 1);
cpu.cpsr.n.write(result >> 31 & 1 == 1); cpu.cpsr.z.write(result == 0);
cpu.cpsr.z.write(result == 0);
if (kind == 0x6) { if (kind == 0x6) {
// SBC specific // SBC specific
const subtrahend = @as(u64, op2) -% old_carry +% 1; const subtrahend = @as(u64, op2) -% old_carry +% 1;
cpu.cpsr.c.write(subtrahend <= op1); cpu.cpsr.c.write(subtrahend <= op1);
cpu.cpsr.v.write(((op1 ^ result) & (~op2 ^ result)) >> 31 & 1 == 1); cpu.cpsr.v.write(((op1 ^ result) & (~op2 ^ result)) >> 31 & 1 == 1);
} else { } else {
// RSC Specific // RSC Specific
const subtrahend = @as(u64, op1) -% old_carry +% 1; const subtrahend = @as(u64, op1) -% old_carry +% 1;
cpu.cpsr.c.write(subtrahend <= op2); cpu.cpsr.c.write(subtrahend <= op2);
cpu.cpsr.v.write(((op2 ^ result) & (~op1 ^ result)) >> 31 & 1 == 1); cpu.cpsr.v.write(((op2 ^ result) & (~op1 ^ result)) >> 31 & 1 == 1);
}
if (rd == 0xF) cpu.setCpsr(cpu.spsr.raw);
} }
}, },
0x8, 0x9, 0xA, 0xB => { 0x8, 0x9, 0xA, 0xB => {