feat(cpu): Implement Multiply Long ARM instructions
This commit is contained in:
parent
28c81f79ae
commit
48017b45f5
|
@ -18,6 +18,7 @@ const branch = @import("cpu/arm/branch.zig").branch;
|
||||||
const branchAndExchange = @import("cpu/arm/branch.zig").branchAndExchange;
|
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;
|
||||||
|
|
||||||
// THUMB Instruction Groups
|
// THUMB Instruction Groups
|
||||||
const format1 = @import("cpu/thumb/format1.zig").format1;
|
const format1 = @import("cpu/thumb/format1.zig").format1;
|
||||||
|
@ -533,6 +534,14 @@ fn armPopulate() [0x1000]ArmInstrFn {
|
||||||
lut[i] = multiply(A, S);
|
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) {
|
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;
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
const Bus = @import("../../Bus.zig");
|
||||||
|
const Arm7tdmi = @import("../../cpu.zig").Arm7tdmi;
|
||||||
|
const InstrFn = @import("../../cpu.zig").ArmInstrFn;
|
||||||
|
|
||||||
|
pub fn multiplyLong(comptime U: bool, comptime A: bool, comptime S: bool) InstrFn {
|
||||||
|
return struct {
|
||||||
|
fn inner(cpu: *Arm7tdmi, _: *Bus, opcode: u32) void {
|
||||||
|
const rd_hi = opcode >> 16 & 0xF;
|
||||||
|
const rd_lo = opcode >> 12 & 0xF;
|
||||||
|
const rs = opcode >> 8 & 0xF;
|
||||||
|
const rm = opcode & 0xF;
|
||||||
|
|
||||||
|
if (U) {
|
||||||
|
// Signed (WHY IS IT U THEN?)
|
||||||
|
var result: i64 = @as(i64, @bitCast(i32, cpu.r[rm])) * @as(i64, @bitCast(i32, cpu.r[rs]));
|
||||||
|
if (A) result += @bitCast(i64, @as(u64, cpu.r[rd_hi]) << 32 | @as(u64, cpu.r[rd_lo]));
|
||||||
|
|
||||||
|
cpu.r[rd_hi] = @bitCast(u32, @truncate(i32, result >> 32));
|
||||||
|
cpu.r[rd_lo] = @bitCast(u32, @truncate(i32, result));
|
||||||
|
} else {
|
||||||
|
// Unsigned
|
||||||
|
var result: u64 = @as(u64, cpu.r[rm]) * @as(u64, cpu.r[rs]);
|
||||||
|
if (A) result += @as(u64, cpu.r[rd_hi]) << 32 | @as(u64, cpu.r[rd_lo]);
|
||||||
|
|
||||||
|
cpu.r[rd_hi] = @truncate(u32, result >> 32);
|
||||||
|
cpu.r[rd_lo] = @truncate(u32, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (S) {
|
||||||
|
cpu.cpsr.z.write(cpu.r[rd_hi] == 0 and cpu.r[rd_lo] == 0);
|
||||||
|
cpu.cpsr.n.write(cpu.r[rd_hi] >> 31 & 1 == 1);
|
||||||
|
// C and V are set to meaningless values
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.inner;
|
||||||
|
}
|
Loading…
Reference in New Issue