| ... | ... | @@ -1821,11 +1821,11 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: |
| 1821 | 1821 | const dst_ty = self.air.typeOfIndex(inst); |
| 1822 | 1822 | const air_tags = self.air.instructions.items(.tag); |
| 1823 | 1823 | switch (air_tags[inst]) { |
| 1824 | | .add, .addwrap => try self.genBinMathOpMir(.add, dst_ty, dst_mcv, src_mcv), |
| 1825 | | .bool_or, .bit_or => try self.genBinMathOpMir(.@"or", dst_ty, dst_mcv, src_mcv), |
| 1826 | | .bool_and, .bit_and => try self.genBinMathOpMir(.@"and", dst_ty, dst_mcv, src_mcv), |
| 1827 | | .sub, .subwrap => try self.genBinMathOpMir(.sub, dst_ty, dst_mcv, src_mcv), |
| 1828 | | .xor, .not => try self.genBinMathOpMir(.xor, dst_ty, dst_mcv, src_mcv), |
| 1824 | .add, .addwrap => try self.genBinMathOpMir(.add, dst_ty, .unsigned, dst_mcv, src_mcv), |
| 1825 | .bool_or, .bit_or => try self.genBinMathOpMir(.@"or", dst_ty, .unsigned, dst_mcv, src_mcv), |
| 1826 | .bool_and, .bit_and => try self.genBinMathOpMir(.@"and", dst_ty, .unsigned, dst_mcv, src_mcv), |
| 1827 | .sub, .subwrap => try self.genBinMathOpMir(.sub, dst_ty, .unsigned, dst_mcv, src_mcv), |
| 1828 | .xor, .not => try self.genBinMathOpMir(.xor, dst_ty, .unsigned, dst_mcv, src_mcv), |
| 1829 | 1829 | .mul, .mulwrap => try self.genIMulOpMir(dst_ty, dst_mcv, src_mcv), |
| 1830 | 1830 | else => unreachable, |
| 1831 | 1831 | } |
| ... | ... | @@ -1837,6 +1837,7 @@ fn genBinMathOpMir( |
| 1837 | 1837 | self: *Self, |
| 1838 | 1838 | mir_tag: Mir.Inst.Tag, |
| 1839 | 1839 | dst_ty: Type, |
| 1840 | signedness: std.builtin.Signedness, |
| 1840 | 1841 | dst_mcv: MCValue, |
| 1841 | 1842 | src_mcv: MCValue, |
| 1842 | 1843 | ) !void { |
| ... | ... | @@ -1856,11 +1857,16 @@ fn genBinMathOpMir( |
| 1856 | 1857 | .ptr_stack_offset => unreachable, |
| 1857 | 1858 | .ptr_embedded_in_code => unreachable, |
| 1858 | 1859 | .register => |src_reg| { |
| 1860 | // TODO think more carefully about this: is this actually correct? |
| 1861 | const reg_size = if (mir_tag == .cmp and signedness == .signed) |
| 1862 | @divExact(dst_reg.size(), 8) |
| 1863 | else |
| 1864 | @divExact(src_reg.size(), 8); |
| 1859 | 1865 | _ = try self.addInst(.{ |
| 1860 | 1866 | .tag = mir_tag, |
| 1861 | 1867 | .ops = (Mir.Ops{ |
| 1862 | | .reg1 = registerAlias(dst_reg, @divExact(src_reg.size(), 8)), |
| 1863 | | .reg2 = src_reg, |
| 1868 | .reg1 = registerAlias(dst_reg, reg_size), |
| 1869 | .reg2 = registerAlias(src_reg, reg_size), |
| 1864 | 1870 | }).encode(), |
| 1865 | 1871 | .data = undefined, |
| 1866 | 1872 | }); |
| ... | ... | @@ -2446,7 +2452,7 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 2446 | 2452 | // This instruction supports only signed 32-bit immediates at most. |
| 2447 | 2453 | const src_mcv = try self.limitImmediateType(bin_op.rhs, i32); |
| 2448 | 2454 | |
| 2449 | | try self.genBinMathOpMir(.cmp, ty, dst_mcv, src_mcv); |
| 2455 | try self.genBinMathOpMir(.cmp, ty, signedness, dst_mcv, src_mcv); |
| 2450 | 2456 | break :result switch (signedness) { |
| 2451 | 2457 | .signed => MCValue{ .compare_flags_signed = op }, |
| 2452 | 2458 | .unsigned => MCValue{ .compare_flags_unsigned = op }, |
| ... | ... | @@ -2669,7 +2675,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 2669 | 2675 | } |
| 2670 | 2676 | |
| 2671 | 2677 | fn isNull(self: *Self, ty: Type, operand: MCValue) !MCValue { |
| 2672 | | try self.genBinMathOpMir(.cmp, ty, operand, MCValue{ .immediate = 0 }); |
| 2678 | try self.genBinMathOpMir(.cmp, ty, .unsigned, operand, MCValue{ .immediate = 0 }); |
| 2673 | 2679 | return MCValue{ .compare_flags_unsigned = .eq }; |
| 2674 | 2680 | } |
| 2675 | 2681 | |
| ... | ... | @@ -2686,7 +2692,7 @@ fn isErr(self: *Self, ty: Type, operand: MCValue) !MCValue { |
| 2686 | 2692 | return MCValue{ .immediate = 0 }; // always false |
| 2687 | 2693 | } else if (!payload_type.hasCodeGenBits()) { |
| 2688 | 2694 | if (err_type.abiSize(self.target.*) <= 8) { |
| 2689 | | try self.genBinMathOpMir(.cmp, err_type, operand, MCValue{ .immediate = 0 }); |
| 2695 | try self.genBinMathOpMir(.cmp, err_type, .unsigned, operand, MCValue{ .immediate = 0 }); |
| 2690 | 2696 | return MCValue{ .compare_flags_unsigned = .gt }; |
| 2691 | 2697 | } else { |
| 2692 | 2698 | return self.fail("TODO isErr for errors with size larger than register size", .{}); |
| ... | ... | @@ -3378,7 +3384,9 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 3378 | 3384 | else => unreachable, |
| 3379 | 3385 | } |
| 3380 | 3386 | }, |
| 3381 | | .compare_flags_unsigned => |op| { |
| 3387 | .compare_flags_unsigned, |
| 3388 | .compare_flags_signed, |
| 3389 | => |op| { |
| 3382 | 3390 | const tag: Mir.Inst.Tag = switch (op) { |
| 3383 | 3391 | .gte, .gt, .lt, .lte => .cond_set_byte_above_below, |
| 3384 | 3392 | .eq, .neq => .cond_set_byte_eq_ne, |
| ... | ... | @@ -3400,10 +3408,6 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 3400 | 3408 | .data = undefined, |
| 3401 | 3409 | }); |
| 3402 | 3410 | }, |
| 3403 | | .compare_flags_signed => |op| { |
| 3404 | | _ = op; |
| 3405 | | return self.fail("TODO set register with compare flags value (signed)", .{}); |
| 3406 | | }, |
| 3407 | 3411 | .immediate => |x| { |
| 3408 | 3412 | // 32-bit moves zero-extend to 64-bit, so xoring the 32-bit |
| 3409 | 3413 | // register is the fastest way to zero a register. |
| ... | ... | @@ -3441,7 +3445,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 3441 | 3445 | _ = try self.addInst(.{ |
| 3442 | 3446 | .tag = .movabs, |
| 3443 | 3447 | .ops = (Mir.Ops{ |
| 3444 | | .reg1 = reg, |
| 3448 | .reg1 = reg.to64(), |
| 3445 | 3449 | }).encode(), |
| 3446 | 3450 | .data = .{ .payload = payload }, |
| 3447 | 3451 | }); |