| ... | ... | @@ -548,11 +548,11 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 548 | 548 | .cmp_gt => try self.airCmp(inst, .gt), |
| 549 | 549 | .cmp_neq => try self.airCmp(inst, .neq), |
| 550 | 550 | |
| 551 | | .bool_and => try self.airBoolOp(inst), |
| 552 | | .bool_or => try self.airBoolOp(inst), |
| 553 | | .bit_and => try self.airBitAnd(inst), |
| 554 | | .bit_or => try self.airBitOr(inst), |
| 555 | | .xor => try self.airXor(inst), |
| 551 | .bool_and => try self.airBinOp(inst), |
| 552 | .bool_or => try self.airBinOp(inst), |
| 553 | .bit_and => try self.airBinOp(inst), |
| 554 | .bit_or => try self.airBinOp(inst), |
| 555 | .xor => try self.airBinOp(inst), |
| 556 | 556 | .shr, .shr_exact => try self.airShr(inst), |
| 557 | 557 | |
| 558 | 558 | .alloc => try self.airAlloc(inst), |
| ... | ... | @@ -1029,24 +1029,6 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void { |
| 1029 | 1029 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1030 | 1030 | } |
| 1031 | 1031 | |
| 1032 | | fn airBitAnd(self: *Self, inst: Air.Inst.Index) !void { |
| 1033 | | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1034 | | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .bit_and); |
| 1035 | | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1036 | | } |
| 1037 | | |
| 1038 | | fn airBitOr(self: *Self, inst: Air.Inst.Index) !void { |
| 1039 | | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1040 | | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .bit_or); |
| 1041 | | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1042 | | } |
| 1043 | | |
| 1044 | | fn airXor(self: *Self, inst: Air.Inst.Index) !void { |
| 1045 | | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1046 | | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .xor); |
| 1047 | | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1048 | | } |
| 1049 | | |
| 1050 | 1032 | fn airShl(self: *Self, inst: Air.Inst.Index) !void { |
| 1051 | 1033 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1052 | 1034 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .shl); |
| ... | ... | @@ -1770,11 +1752,23 @@ fn binOpRegister( |
| 1770 | 1752 | .add, .ptr_add => .add, |
| 1771 | 1753 | .sub, .ptr_sub => .sub, |
| 1772 | 1754 | .mul => .mul, |
| 1755 | .bit_and, |
| 1756 | .bool_and, |
| 1757 | => .@"and", |
| 1758 | .bit_or, |
| 1759 | .bool_or, |
| 1760 | => .orr, |
| 1761 | .xor => .eor, |
| 1773 | 1762 | else => unreachable, |
| 1774 | 1763 | }; |
| 1775 | 1764 | const mir_data: Mir.Inst.Data = switch (tag) { |
| 1776 | 1765 | .add, |
| 1777 | 1766 | .sub, |
| 1767 | .bit_and, |
| 1768 | .bool_and, |
| 1769 | .bit_or, |
| 1770 | .bool_or, |
| 1771 | .xor, |
| 1778 | 1772 | .ptr_add, |
| 1779 | 1773 | .ptr_sub, |
| 1780 | 1774 | => .{ .rr_op = .{ |
| ... | ... | @@ -1862,11 +1856,23 @@ fn binOpImmediate( |
| 1862 | 1856 | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| 1863 | 1857 | .add => .add, |
| 1864 | 1858 | .sub => .sub, |
| 1859 | .bit_and, |
| 1860 | .bool_and, |
| 1861 | => .@"and", |
| 1862 | .bit_or, |
| 1863 | .bool_or, |
| 1864 | => .orr, |
| 1865 | .xor => .eor, |
| 1865 | 1866 | else => unreachable, |
| 1866 | 1867 | }; |
| 1867 | 1868 | const mir_data: Mir.Inst.Data = switch (tag) { |
| 1868 | 1869 | .add, |
| 1869 | 1870 | .sub, |
| 1871 | .bit_and, |
| 1872 | .bool_and, |
| 1873 | .bit_or, |
| 1874 | .bool_or, |
| 1875 | .xor, |
| 1870 | 1876 | => .{ .rr_op = .{ |
| 1871 | 1877 | .rd = dest_reg, |
| 1872 | 1878 | .rn = lhs_reg, |
| ... | ... | @@ -1964,6 +1970,54 @@ fn binOp( |
| 1964 | 1970 | else => unreachable, |
| 1965 | 1971 | } |
| 1966 | 1972 | }, |
| 1973 | .bit_and, |
| 1974 | .bit_or, |
| 1975 | .xor, |
| 1976 | => { |
| 1977 | switch (lhs_ty.zigTypeTag()) { |
| 1978 | .Vector => return self.fail("TODO ARM binary operations on vectors", .{}), |
| 1979 | .Int => { |
| 1980 | assert(lhs_ty.eql(rhs_ty)); |
| 1981 | const int_info = lhs_ty.intInfo(self.target.*); |
| 1982 | if (int_info.bits <= 32) { |
| 1983 | const lhs_immediate_ok = lhs == .immediate and Instruction.Operand.fromU32(lhs.immediate) != null; |
| 1984 | const rhs_immediate_ok = rhs == .immediate and Instruction.Operand.fromU32(rhs.immediate) != null; |
| 1985 | |
| 1986 | if (rhs_immediate_ok) { |
| 1987 | return try self.binOpImmediate(tag, maybe_inst, lhs, rhs, lhs_ty, false); |
| 1988 | } else if (lhs_immediate_ok) { |
| 1989 | // swap lhs and rhs |
| 1990 | return try self.binOpImmediate(tag, maybe_inst, rhs, lhs, rhs_ty, true); |
| 1991 | } else { |
| 1992 | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 1993 | } |
| 1994 | } else { |
| 1995 | return self.fail("TODO ARM binary operations on integers > u32/i32", .{}); |
| 1996 | } |
| 1997 | }, |
| 1998 | else => unreachable, |
| 1999 | } |
| 2000 | }, |
| 2001 | .bool_and, |
| 2002 | .bool_or, |
| 2003 | => { |
| 2004 | switch (lhs_ty.zigTypeTag()) { |
| 2005 | .Bool => { |
| 2006 | const lhs_immediate_ok = lhs == .immediate; |
| 2007 | const rhs_immediate_ok = rhs == .immediate; |
| 2008 | |
| 2009 | if (rhs_immediate_ok) { |
| 2010 | return try self.binOpImmediate(tag, maybe_inst, lhs, rhs, lhs_ty, false); |
| 2011 | } else if (lhs_immediate_ok) { |
| 2012 | // swap lhs and rhs |
| 2013 | return try self.binOpImmediate(tag, maybe_inst, rhs, lhs, rhs_ty, true); |
| 2014 | } else { |
| 2015 | return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); |
| 2016 | } |
| 2017 | }, |
| 2018 | else => unreachable, |
| 2019 | } |
| 2020 | }, |
| 1967 | 2021 | .ptr_add, |
| 1968 | 2022 | .ptr_sub, |
| 1969 | 2023 | => { |
| ... | ... | @@ -2183,17 +2237,9 @@ fn genBinOpCode( |
| 2183 | 2237 | }; |
| 2184 | 2238 | |
| 2185 | 2239 | switch (op) { |
| 2186 | | .bool_and, |
| 2187 | | .bit_and, |
| 2188 | | .bool_or, |
| 2189 | | .bit_or, |
| 2190 | | .not, |
| 2191 | | .xor, |
| 2192 | | => { |
| 2240 | .not => { |
| 2193 | 2241 | const tag: Mir.Inst.Tag = switch (op) { |
| 2194 | | .bool_and, .bit_and => .@"and", |
| 2195 | | .bool_or, .bit_or => .orr, |
| 2196 | | .not, .xor => .eor, |
| 2242 | .not => .eor, |
| 2197 | 2243 | else => unreachable, |
| 2198 | 2244 | }; |
| 2199 | 2245 | |
| ... | ... | @@ -3154,17 +3200,6 @@ fn airBr(self: *Self, inst: Air.Inst.Index) !void { |
| 3154 | 3200 | return self.finishAir(inst, .dead, .{ branch.operand, .none, .none }); |
| 3155 | 3201 | } |
| 3156 | 3202 | |
| 3157 | | fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void { |
| 3158 | | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 3159 | | const air_tags = self.air.instructions.items(.tag); |
| 3160 | | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else switch (air_tags[inst]) { |
| 3161 | | .bool_and => try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .bool_and), |
| 3162 | | .bool_or => try self.genBinOp(inst, bin_op.lhs, bin_op.rhs, .bool_or), |
| 3163 | | else => unreachable, // Not a boolean operation |
| 3164 | | }; |
| 3165 | | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 3166 | | } |
| 3167 | | |
| 3168 | 3203 | fn br(self: *Self, block: Air.Inst.Index, operand: Air.Inst.Ref) !void { |
| 3169 | 3204 | const block_data = self.blocks.getPtr(block).?; |
| 3170 | 3205 | |