diff options
| author | David Rubin <daviru007@icloud.com> | 2024-03-17 15:55:46 -0700 |
|---|---|---|
| committer | David Rubin <daviru007@icloud.com> | 2024-05-11 02:17:11 -0700 |
| commit | f67fa73fe8bc5cc38af826c396d912b7f72b3261 (patch) | |
| tree | a98bed3c14dc031b734cc5898ce92f580b6dd9af /src | |
| parent | b2150094badd3c14411a811ee0e508183b2142a2 (diff) | |
| download | zig-f67fa73fe8bc5cc38af826c396d912b7f72b3261.tar.gz zig-f67fa73fe8bc5cc38af826c396d912b7f72b3261.zip | |
riscv: 16 bit `@byteSwap`
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/riscv64/CodeGen.zig | 44 | ||||
| -rw-r--r-- | src/arch/riscv64/Emit.zig | 2 | ||||
| -rw-r--r-- | src/arch/riscv64/Mir.zig | 3 |
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 |
