diff --git a/src/cpu.zig b/src/cpu.zig index 519e1bf..574e6f8 100644 --- a/src/cpu.zig +++ b/src/cpu.zig @@ -17,6 +17,7 @@ const blockDataTransfer = @import("cpu/arm/block_data_transfer.zig").blockDataTr const branch = @import("cpu/arm/branch.zig").branch; const branchAndExchange = @import("cpu/arm/branch.zig").branchAndExchange; const softwareInterrupt = @import("cpu/arm/software_interrupt.zig").softwareInterrupt; +const multiply = @import("cpu/arm/multiply.zig").multiply; // THUMB Instruction Groups const format1 = @import("cpu/thumb/format1.zig").format1; @@ -448,6 +449,13 @@ fn armPopulate() [0x1000]ArmInstrFn { lut[i] = psrTransfer(I, R, kind); } + if (i >> 6 & 0x3F == 0b000000 and i & 0xF == 0b1001) { + const A = i >> 5 & 1 == 1; + const S = i >> 4 & 1 == 1; + + lut[i] = multiply(A, S); + } + if (i == 0x121) { lut[i] = branchAndExchange; } diff --git a/src/cpu/arm/multiply.zig b/src/cpu/arm/multiply.zig new file mode 100644 index 0000000..f3f3721 --- /dev/null +++ b/src/cpu/arm/multiply.zig @@ -0,0 +1,25 @@ +const std = @import("std"); + +const Bus = @import("../../Bus.zig"); +const Arm7tdmi = @import("../../cpu.zig").Arm7tdmi; +const InstrFn = @import("../../cpu.zig").ArmInstrFn; + +pub fn multiply(comptime A: bool, comptime S: bool) InstrFn { + return struct { + fn inner(cpu: *Arm7tdmi, _: *Bus, opcode: u32) void { + const rd = opcode >> 16 & 0xF; + const rn = opcode >> 12 & 0xF; + const rs = opcode >> 8 & 0xF; + const rm = opcode & 0xF; + + const result = cpu.r[rm] * cpu.r[rs] + if (A) cpu.r[rn] else 0; + cpu.r[rd] = result; + + if (S) { + cpu.cpsr.n.write(result >> 31 & 1 == 1); + cpu.cpsr.z.write(result == 0); + // V is unaffected, C is *actually* undefined in ARMv4 + } + } + }.inner; +} diff --git a/src/cpu/thumb/format4.zig b/src/cpu/thumb/format4.zig index 23433b7..80af863 100644 --- a/src/cpu/thumb/format4.zig +++ b/src/cpu/thumb/format4.zig @@ -92,7 +92,10 @@ pub fn format4(comptime op: u4) InstrFn { // MUL const result = cpu.r[rs] * cpu.r[rd]; cpu.r[rd] = result; - std.debug.panic("[CPU|THUMB|MUL] TODO: Set flags on ALU MUL", .{}); + + cpu.cpsr.n.write(result >> 31 & 1 == 1); + cpu.cpsr.z.write(result == 0); + // V is unaffected, assuming similar behaviour to ARMv4 MUL C is undefined }, 0xE => { // BIC