From c0629c3539f1c944636b6cc9cb531113759b089a Mon Sep 17 00:00:00 2001 From: David Rubin Date: Fri, 29 Mar 2024 08:19:52 -0700 Subject: [PATCH] riscv: implement `airNot` --- src/arch/riscv64/CodeGen.zig | 36 +++++++++++++++++++++++++++++++++++- src/arch/riscv64/Emit.zig | 2 ++ src/arch/riscv64/Mir.zig | 5 ++++- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index 256d2efbfd..6625b6da7b 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -1036,7 +1036,41 @@ fn airIntFromBool(self: *Self, inst: Air.Inst.Index) !void { fn airNot(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 return self.fail("TODO implement NOT for {}", .{self.target.cpu.arch}); + const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { + const mod = self.bin_file.comp.module.?; + + const operand = try self.resolveInst(ty_op.operand); + const ty = self.typeOf(ty_op.operand); + + switch (ty.zigTypeTag(mod)) { + .Bool => { + const operand_reg = blk: { + if (operand == .register) break :blk operand.register; + break :blk try self.copyToTmpRegister(ty, operand); + }; + + const dst_reg: Register = + if (self.reuseOperand(inst, ty_op.operand, 0, operand) and operand == .register) + operand.register + else + try self.register_manager.allocReg(inst, gp); + + _ = try self.addInst(.{ + .tag = .not, + .data = .{ + .rr = .{ + .rs = operand_reg, + .rd = dst_reg, + }, + }, + }); + + break :result .{ .register = dst_reg }; + }, + .Int => return self.fail("TODO: airNot ints", .{}), + else => unreachable, + } + }; 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 8579f33b38..8161e4a99b 100644 --- a/src/arch/riscv64/Emit.zig +++ b/src/arch/riscv64/Emit.zig @@ -83,6 +83,7 @@ pub fn emitMir( .j => try emit.mirPsuedo(inst), .mv => try emit.mirRR(inst), + .not => try emit.mirRR(inst), .nop => try emit.mirNop(inst), .ret => try emit.mirNop(inst), @@ -414,6 +415,7 @@ fn mirRR(emit: *Emit, inst: Mir.Inst.Index) !void { switch (tag) { .mv => try emit.writeInstruction(Instruction.addi(rd, rs, 0)), + .not => try emit.writeInstruction(Instruction.xori(rd, rs, 1)), else => unreachable, } } diff --git a/src/arch/riscv64/Mir.zig b/src/arch/riscv64/Mir.zig index 1b8c8bb3d3..d8c8775a6d 100644 --- a/src/arch/riscv64/Mir.zig +++ b/src/arch/riscv64/Mir.zig @@ -76,7 +76,7 @@ pub const Inst = struct { /// Immediate `==`, uses i_type cmp_imm_eq, - /// Immediate `<=`, uses i_typei + /// Immediate `<=`, uses i_type cmp_imm_lte, /// Branch if equal, Uses b_type @@ -84,6 +84,9 @@ pub const Inst = struct { /// Branch if not equal, Uses b_type bne, + /// Boolean NOT, Uses rr payload + not, + nop, ret,