fix(arm): group multiply instructions together
- implement clz in ARMv5TE
This commit is contained in:
17
src/arm/cpu/arm/misc_instructions.zig
Normal file
17
src/arm/cpu/arm/misc_instructions.zig
Normal file
@@ -0,0 +1,17 @@
|
||||
const sext = @import("zba-util").sext;
|
||||
|
||||
pub fn clz(comptime InstrFn: type) InstrFn {
|
||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
||||
|
||||
return struct {
|
||||
pub fn inner(cpu: *Arm32, opcode: u32) void {
|
||||
const rd = opcode >> 12 & 0xF;
|
||||
const rm = opcode & 0xF;
|
||||
|
||||
if (rd == 0xF) cpu.panic("CLZ: UNPREDICTABLE behaviour when rd == 15", .{});
|
||||
if (rm == 0xF) cpu.panic("CLZ: UNPREDICTABLE behaviour when rm == 15", .{});
|
||||
|
||||
cpu.r[rd] = @clz(cpu.r[rm]);
|
||||
}
|
||||
}.inner;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
pub fn multiply(comptime InstrFn: type, comptime A: bool, comptime S: bool) InstrFn {
|
||||
pub fn multiply(comptime InstrFn: type, comptime L: bool, comptime U: bool, comptime A: bool, comptime S: bool) InstrFn {
|
||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
||||
|
||||
return struct {
|
||||
@@ -8,49 +8,41 @@ pub fn multiply(comptime InstrFn: type, comptime A: bool, comptime S: bool) Inst
|
||||
const rs = opcode >> 8 & 0xF;
|
||||
const rm = opcode & 0xF;
|
||||
|
||||
const temp: u64 = @as(u64, cpu.r[rm]) * @as(u64, cpu.r[rs]) + if (A) cpu.r[rn] else 0;
|
||||
const result: u32 = @truncate(temp);
|
||||
cpu.r[rd] = result;
|
||||
if (L) {
|
||||
const rd_hi = rd;
|
||||
const rd_lo = rn;
|
||||
|
||||
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;
|
||||
}
|
||||
if (U) {
|
||||
// Signed (WHY IS IT U THEN?)
|
||||
var result: i64 = @as(i64, @as(i32, @bitCast(cpu.r[rm]))) * @as(i64, @as(i32, @bitCast(cpu.r[rs])));
|
||||
if (A) result +%= @bitCast(@as(u64, cpu.r[rd_hi]) << 32 | @as(u64, cpu.r[rd_lo]));
|
||||
|
||||
pub fn multiplyLong(comptime InstrFn: type, comptime U: bool, comptime A: bool, comptime S: bool) InstrFn {
|
||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
||||
cpu.r[rd_hi] = @bitCast(@as(i32, @truncate(result >> 32)));
|
||||
cpu.r[rd_lo] = @bitCast(@as(i32, @truncate(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]);
|
||||
|
||||
return struct {
|
||||
fn inner(cpu: *Arm32, opcode: u32) void {
|
||||
const rd_hi = opcode >> 16 & 0xF;
|
||||
const rd_lo = opcode >> 12 & 0xF;
|
||||
const rs = opcode >> 8 & 0xF;
|
||||
const rm = opcode & 0xF;
|
||||
cpu.r[rd_hi] = @truncate(result >> 32);
|
||||
cpu.r[rd_lo] = @truncate(result);
|
||||
}
|
||||
|
||||
if (U) {
|
||||
// Signed (WHY IS IT U THEN?)
|
||||
var result: i64 = @as(i64, @as(i32, @bitCast(cpu.r[rm]))) * @as(i64, @as(i32, @bitCast(cpu.r[rs])));
|
||||
if (A) result +%= @bitCast(@as(u64, cpu.r[rd_hi]) << 32 | @as(u64, cpu.r[rd_lo]));
|
||||
|
||||
cpu.r[rd_hi] = @bitCast(@as(i32, @truncate(result >> 32)));
|
||||
cpu.r[rd_lo] = @bitCast(@as(i32, @truncate(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
|
||||
}
|
||||
} 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]);
|
||||
const temp: u64 = @as(u64, cpu.r[rm]) * @as(u64, cpu.r[rs]) + if (A) cpu.r[rn] else 0;
|
||||
const result: u32 = @truncate(temp);
|
||||
cpu.r[rd] = result;
|
||||
|
||||
cpu.r[rd_hi] = @truncate(result >> 32);
|
||||
cpu.r[rd_lo] = @truncate(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
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user