| ... | ... | @@ -887,6 +887,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { |
| 887 | 887 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 888 | 888 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 889 | 889 | const operand = try self.resolveInst(ty_op.operand); |
| 890 | const operand_ty = self.air.typeOf(ty_op.operand); |
| 890 | 891 | switch (operand) { |
| 891 | 892 | .dead => unreachable, |
| 892 | 893 | .unreach => unreachable, |
| ... | ... | @@ -917,7 +918,68 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { |
| 917 | 918 | break :result r; |
| 918 | 919 | }, |
| 919 | 920 | else => { |
| 920 | | break :result try self.genBinOp(inst, ty_op.operand, .bool_true, .not); |
| 921 | switch (operand_ty.zigTypeTag()) { |
| 922 | .Bool => { |
| 923 | const op_reg = switch (operand) { |
| 924 | .register => |r| r, |
| 925 | else => try self.copyToTmpRegister(operand_ty, operand), |
| 926 | }; |
| 927 | self.register_manager.freezeRegs(&.{op_reg}); |
| 928 | defer self.register_manager.unfreezeRegs(&.{op_reg}); |
| 929 | |
| 930 | const dest_reg = blk: { |
| 931 | if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) { |
| 932 | break :blk op_reg; |
| 933 | } |
| 934 | |
| 935 | break :blk try self.register_manager.allocReg(null); |
| 936 | }; |
| 937 | |
| 938 | _ = try self.addInst(.{ |
| 939 | .tag = .eor, |
| 940 | .data = .{ .rr_op = .{ |
| 941 | .rd = dest_reg, |
| 942 | .rn = op_reg, |
| 943 | .op = Instruction.Operand.fromU32(1).?, |
| 944 | } }, |
| 945 | }); |
| 946 | |
| 947 | break :result MCValue{ .register = dest_reg }; |
| 948 | }, |
| 949 | .Int => { |
| 950 | const int_info = operand_ty.intInfo(self.target.*); |
| 951 | if (int_info.bits <= 32) { |
| 952 | const op_reg = switch (operand) { |
| 953 | .register => |r| r, |
| 954 | else => try self.copyToTmpRegister(operand_ty, operand), |
| 955 | }; |
| 956 | self.register_manager.freezeRegs(&.{op_reg}); |
| 957 | defer self.register_manager.unfreezeRegs(&.{op_reg}); |
| 958 | |
| 959 | const dest_reg = blk: { |
| 960 | if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) { |
| 961 | break :blk op_reg; |
| 962 | } |
| 963 | |
| 964 | break :blk try self.register_manager.allocReg(null); |
| 965 | }; |
| 966 | |
| 967 | _ = try self.addInst(.{ |
| 968 | .tag = .mvn, |
| 969 | .data = .{ .rr_op = .{ |
| 970 | .rd = dest_reg, |
| 971 | .rn = undefined, |
| 972 | .op = Instruction.Operand.reg(op_reg, Instruction.Operand.Shift.none), |
| 973 | } }, |
| 974 | }); |
| 975 | |
| 976 | break :result MCValue{ .register = dest_reg }; |
| 977 | } else { |
| 978 | return self.fail("TODO ARM not on integers > u32/i32", .{}); |
| 979 | } |
| 980 | }, |
| 981 | else => unreachable, |
| 982 | } |
| 921 | 983 | }, |
| 922 | 984 | } |
| 923 | 985 | }; |
| ... | ... | @@ -2073,9 +2135,6 @@ fn genBinOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air |
| 2073 | 2135 | const ty = self.air.typeOf(op_lhs); |
| 2074 | 2136 | |
| 2075 | 2137 | switch (ty.zigTypeTag()) { |
| 2076 | | .Bool => { |
| 2077 | | return self.genBinIntOp(inst, op_lhs, op_rhs, op, 1, .unsigned); |
| 2078 | | }, |
| 2079 | 2138 | .Int => { |
| 2080 | 2139 | const int_info = ty.intInfo(self.target.*); |
| 2081 | 2140 | return self.genBinIntOp(inst, op_lhs, op_rhs, op, int_info.bits, int_info.signedness); |
| ... | ... | @@ -2237,21 +2296,6 @@ fn genBinOpCode( |
| 2237 | 2296 | }; |
| 2238 | 2297 | |
| 2239 | 2298 | switch (op) { |
| 2240 | | .not => { |
| 2241 | | const tag: Mir.Inst.Tag = switch (op) { |
| 2242 | | .not => .eor, |
| 2243 | | else => unreachable, |
| 2244 | | }; |
| 2245 | | |
| 2246 | | _ = try self.addInst(.{ |
| 2247 | | .tag = tag, |
| 2248 | | .data = .{ .rr_op = .{ |
| 2249 | | .rd = dst_reg, |
| 2250 | | .rn = op1, |
| 2251 | | .op = operand, |
| 2252 | | } }, |
| 2253 | | }); |
| 2254 | | }, |
| 2255 | 2299 | .cmp_eq => { |
| 2256 | 2300 | _ = try self.addInst(.{ |
| 2257 | 2301 | .tag = .cmp, |