Commit c0629c3539

David Rubin <daviru007@icloud.com>
2024-03-29 16:19:52
riscv: implement `airNot`
1 parent 4ce85f9
Changed files (3)
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 });
 }
 
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,
     }
 }
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,