From ff3f79801c599de01a3281a6bce361497039ca7c Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Mon, 23 May 2022 12:58:31 -0300 Subject: [PATCH] chore: modify type signature of util.sext --- src/cpu/arm/branch.zig | 2 +- src/cpu/arm/half_signed_data_transfer.zig | 6 +++--- src/cpu/thumb/branch.zig | 6 +++--- src/cpu/thumb/data_transfer.zig | 6 +++--- src/util.zig | 13 +++++++++---- 5 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/cpu/arm/branch.zig b/src/cpu/arm/branch.zig index 03b4fd5..5f9dfe5 100644 --- a/src/cpu/arm/branch.zig +++ b/src/cpu/arm/branch.zig @@ -10,7 +10,7 @@ pub fn branch(comptime L: bool) InstrFn { return struct { fn inner(cpu: *Arm7tdmi, _: *Bus, opcode: u32) void { if (L) cpu.r[14] = cpu.r[15]; - cpu.r[15] = cpu.fakePC() +% (sext(24, opcode) << 2); + cpu.r[15] = cpu.fakePC() +% (sext(u32, u24, opcode) << 2); } }.inner; } diff --git a/src/cpu/arm/half_signed_data_transfer.zig b/src/cpu/arm/half_signed_data_transfer.zig index 9c20e0b..5ffae2c 100644 --- a/src/cpu/arm/half_signed_data_transfer.zig +++ b/src/cpu/arm/half_signed_data_transfer.zig @@ -43,14 +43,14 @@ pub fn halfAndSignedDataTransfer(comptime P: bool, comptime U: bool, comptime I: }, 0b10 => { // LDRSB - result = sext(8, bus.read(u8, address)); + result = sext(u32, u8, bus.read(u8, address)); }, 0b11 => { // LDRSH result = if (address & 1 == 1) blk: { - break :blk sext(8, bus.read(u8, address)); + break :blk sext(u32, u8, bus.read(u8, address)); } else blk: { - break :blk sext(16, bus.read(u16, address)); + break :blk sext(u32, u16, bus.read(u16, address)); }; }, 0b00 => unreachable, // SWP diff --git a/src/cpu/thumb/branch.zig b/src/cpu/thumb/branch.zig index 3bc8277..2515910 100644 --- a/src/cpu/thumb/branch.zig +++ b/src/cpu/thumb/branch.zig @@ -9,7 +9,7 @@ pub fn format16(comptime cond: u4) InstrFn { return struct { fn inner(cpu: *Arm7tdmi, _: *Bus, opcode: u16) void { // B - const offset = sext(8, opcode & 0xFF) << 1; + const offset = sext(u32, u8, opcode & 0xFF) << 1; const should_execute = switch (cond) { 0xE, 0xF => cpu.panic("[CPU/THUMB.16] Undefined conditional branch with condition {}", .{cond}), @@ -27,7 +27,7 @@ pub fn format18() InstrFn { return struct { // B but conditional fn inner(cpu: *Arm7tdmi, _: *Bus, opcode: u16) void { - const offset = sext(11, opcode & 0x7FF) << 1; + const offset = sext(u32, u11, opcode & 0x7FF) << 1; cpu.r[15] = (cpu.r[15] + 2) +% offset; } }.inner; @@ -47,7 +47,7 @@ pub fn format19(comptime is_low: bool) InstrFn { cpu.r[14] = old_pc | 1; } else { // Instruction 1 - cpu.r[14] = (cpu.r[15] + 2) +% (sext(11, offset) << 12); + cpu.r[14] = (cpu.r[15] + 2) +% (sext(u32, u11, offset) << 12); } } }.inner; diff --git a/src/cpu/thumb/data_transfer.zig b/src/cpu/thumb/data_transfer.zig index d299908..ced9813 100644 --- a/src/cpu/thumb/data_transfer.zig +++ b/src/cpu/thumb/data_transfer.zig @@ -36,7 +36,7 @@ pub fn format78(comptime op: u2, comptime T: bool) InstrFn { }, 0b01 => { // LDSB - cpu.r[rd] = sext(8, bus.read(u8, address)); + cpu.r[rd] = sext(u32, u8, bus.read(u8, address)); }, 0b10 => { // LDRH @@ -46,9 +46,9 @@ pub fn format78(comptime op: u2, comptime T: bool) InstrFn { 0b11 => { // LDRSH cpu.r[rd] = if (address & 1 == 1) blk: { - break :blk sext(8, bus.read(u8, address)); + break :blk sext(u32, u8, bus.read(u8, address)); } else blk: { - break :blk sext(16, bus.read(u16, address)); + break :blk sext(u32, u16, bus.read(u16, address)); }; }, } diff --git a/src/util.zig b/src/util.zig index 82019ff..f2faa39 100644 --- a/src/util.zig +++ b/src/util.zig @@ -1,11 +1,16 @@ const std = @import("std"); const Log2Int = std.math.Log2Int; -pub inline fn sext(comptime bits: comptime_int, value: u32) u32 { - comptime std.debug.assert(bits <= 32); - const amount = 32 - bits; +// Sign-Extend value of type `T` to type `U` +pub fn sext(comptime T: type, comptime U: type, value: T) T { + // U must have less bits than T + comptime std.debug.assert(@typeInfo(U).Int.bits <= @typeInfo(T).Int.bits); - return @bitCast(u32, @bitCast(i32, value << amount) >> amount); + const iT = std.meta.Int(.signed, @typeInfo(T).Int.bits); + const ExtU = if (@typeInfo(U).Int.signedness == .unsigned) T else iT; + const shift = @intCast(Log2Int(T), @typeInfo(T).Int.bits - @typeInfo(U).Int.bits); + + return @bitCast(T, @bitCast(iT, @as(ExtU, @truncate(U, value)) << shift) >> shift); } /// See https://godbolt.org/z/W3en9Eche