authorgravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-03-17 15:55:46-07:00
committergravatar for david@vortan.devDavid Rubin <david@vortan.dev> 2024-05-11 02:17:11-07:00
logf67fa73fe8bc5cc38af826c396d912b7f72b3261
treea98bed3c14dc031b734cc5898ce92f580b6dd9af
parentb2150094badd3c14411a811ee0e508183b2142a2

riscv: 16 bit `@byteSwap`


3 files changed, 46 insertions(+), 3 deletions(-)

src/arch/riscv64/CodeGen.zig+41-3
......@@ -1537,9 +1537,47 @@ fn airAbs(self: *Self, inst: Air.Inst.Index) !void {
15371537fn airByteSwap(self: *Self, inst: Air.Inst.Index) !void {
15381538 const ty_op = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
15391539 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
1540 if (true)
1541 return self.fail("TODO: airByteSwap", .{});
1542 break :result undefined;
1540 const mod = self.bin_file.comp.module.?;
1541 const ty = self.typeOf(ty_op.operand);
1542 const operand = try self.resolveInst(ty_op.operand);
1543
1544 const int_bits = ty.intInfo(mod).bits;
1545
1546 // bytes are no-op
1547 if (int_bits == 8 and self.reuseOperand(inst, ty_op.operand, 0, operand)) {
1548 return self.finishAir(inst, operand, .{ ty_op.operand, .none, .none });
1549 }
1550
1551 const dest_reg = try self.register_manager.allocReg(null, gp);
1552 try self.genSetReg(ty, dest_reg, operand);
1553
1554 const dest_mcv: MCValue = .{ .register = dest_reg };
1555
1556 switch (int_bits) {
1557 16 => {
1558 const temp = try self.binOp(.shr, null, dest_mcv, .{ .immediate = 8 }, ty, Type.u8);
1559 assert(temp == .register);
1560 _ = try self.addInst(.{
1561 .tag = .slli,
1562 .data = .{ .i_type = .{
1563 .imm12 = 8,
1564 .rd = dest_reg,
1565 .rs1 = dest_reg,
1566 } },
1567 });
1568 _ = try self.addInst(.{
1569 .tag = .@"or",
1570 .data = .{ .r_type = .{
1571 .rd = dest_reg,
1572 .rs1 = dest_reg,
1573 .rs2 = temp.register,
1574 } },
1575 });
1576 },
1577 else => return self.fail("TODO: {d} bits for airByteSwap", .{int_bits}),
1578 }
1579
1580 break :result dest_mcv;
15431581 };
15441582 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
15451583}
src/arch/riscv64/Emit.zig+2
......@@ -55,6 +55,7 @@ pub fn emitMir(
5555 switch (tag) {
5656 .add => try emit.mirRType(inst),
5757 .sub => try emit.mirRType(inst),
58 .@"or" => try emit.mirRType(inst),
5859
5960 .cmp_eq => try emit.mirRType(inst),
6061 .cmp_gt => try emit.mirRType(inst),
......@@ -191,6 +192,7 @@ fn mirRType(emit: *Emit, inst: Mir.Inst.Index) !void {
191192 },
192193 .sllw => try emit.writeInstruction(Instruction.sllw(rd, rs1, rs2)),
193194 .srlw => try emit.writeInstruction(Instruction.srlw(rd, rs1, rs2)),
195 .@"or" => try emit.writeInstruction(Instruction.@"or"(rd, rs1, rs2)),
194196 else => unreachable,
195197 }
196198}
src/arch/riscv64/Mir.zig+3
......@@ -33,6 +33,9 @@ pub const Inst = struct {
3333 ebreak,
3434 ecall,
3535
36 /// OR instruction. Uses r_type payload.
37 @"or",
38
3639 /// Addition
3740 add,
3841 /// Subtraction