aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Rubin <daviru007@icloud.com>2024-03-17 15:55:46 -0700
committerDavid Rubin <daviru007@icloud.com>2024-05-11 02:17:11 -0700
commitf67fa73fe8bc5cc38af826c396d912b7f72b3261 (patch)
treea98bed3c14dc031b734cc5898ce92f580b6dd9af /src
parentb2150094badd3c14411a811ee0e508183b2142a2 (diff)
downloadzig-f67fa73fe8bc5cc38af826c396d912b7f72b3261.tar.gz
zig-f67fa73fe8bc5cc38af826c396d912b7f72b3261.zip
riscv: 16 bit `@byteSwap`
Diffstat (limited to 'src')
-rw-r--r--src/arch/riscv64/CodeGen.zig44
-rw-r--r--src/arch/riscv64/Emit.zig2
-rw-r--r--src/arch/riscv64/Mir.zig3
3 files changed, 46 insertions, 3 deletions
diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig
index edd3c9bf57..22418d7833 100644
--- a/src/arch/riscv64/CodeGen.zig
+++ b/src/arch/riscv64/CodeGen.zig
@@ -1537,9 +1537,47 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {
const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
- if (true)
- return self.fail("TODO: airByteSwap", .{});
- break :result undefined;
+ const mod = self.bin_file.comp.module.?;
+ const ty = self.typeOf(ty_op.operand);
+ const operand = try self.resolveInst(ty_op.operand);
+
+ const int_bits = ty.intInfo(mod).bits;
+
+ // bytes are no-op
+ if (int_bits == 8 and self.reuseOperand(inst, ty_op.operand, 0, operand)) {
+ return self.finishAir(inst, operand, .{ ty_op.operand, .none, .none });
+ }
+
+ const dest_reg = try self.register_manager.allocReg(null, gp);
+ try self.genSetReg(ty, dest_reg, operand);
+
+ const dest_mcv: MCValue = .{ .register = dest_reg };
+
+ switch (int_bits) {
+ 16 => {
+ const temp = try self.binOp(.shr, null, dest_mcv, .{ .immediate = 8 }, ty, Type.u8);
+ assert(temp == .register);
+ _ = try self.addInst(.{
+ .tag = .slli,
+ .data = .{ .i_type = .{
+ .imm12 = 8,
+ .rd = dest_reg,
+ .rs1 = dest_reg,
+ } },
+ });
+ _ = try self.addInst(.{
+ .tag = .@"or",
+ .data = .{ .r_type = .{
+ .rd = dest_reg,
+ .rs1 = dest_reg,
+ .rs2 = temp.register,
+ } },
+ });
+ },
+ else => return self.fail("TODO: {d} bits for airByteSwap", .{int_bits}),
+ }
+
+ break :result dest_mcv;
};
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
}
diff --git a/src/arch/riscv64/Emit.zig b/src/arch/riscv64/Emit.zig
index e120e5ce23..55e1ff07e2 100644
--- a/src/arch/riscv64/Emit.zig
+++ b/src/arch/riscv64/Emit.zig
@@ -55,6 +55,7 @@ pub fn emitMir(
switch (tag) {
.add => try emit.mirRType(inst),
.sub => try emit.mirRType(inst),
+ .@"or" => try emit.mirRType(inst),
.cmp_eq => try emit.mirRType(inst),
.cmp_gt => try emit.mirRType(inst),
@@ -191,6 +192,7 @@ fn mirRType(emit: *Emit, inst: Mir.Inst.Index) !void {
},
.sllw => try emit.writeInstruction(Instruction.sllw(rd, rs1, rs2)),
.srlw => try emit.writeInstruction(Instruction.srlw(rd, rs1, rs2)),
+ .@"or" => try emit.writeInstruction(Instruction.@"or"(rd, rs1, rs2)),
else => unreachable,
}
}
diff --git a/src/arch/riscv64/Mir.zig b/src/arch/riscv64/Mir.zig
index 7527f0b216..8a0ad039df 100644
--- a/src/arch/riscv64/Mir.zig
+++ b/src/arch/riscv64/Mir.zig
@@ -33,6 +33,9 @@ pub const Inst = struct {
ebreak,
ecall,
+ /// OR instruction. Uses r_type payload.
+ @"or",
+
/// Addition
add,
/// Subtraction