| ... | @@ -1275,7 +1275,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -1275,7 +1275,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void { |
| 1275 | .round, | 1275 | .round, |
| 1276 | .trunc_float, | 1276 | .trunc_float, |
| 1277 | .neg, | 1277 | .neg, |
| 1278 | => try func.airUnaryMath(inst), | 1278 | => try func.airUnaryMath(inst, tag), |
| 1279 | | 1279 | |
| 1280 | .add_with_overflow => try func.airAddWithOverflow(inst), | 1280 | .add_with_overflow => try func.airAddWithOverflow(inst), |
| 1281 | .sub_with_overflow => try func.airSubWithOverflow(inst), | 1281 | .sub_with_overflow => try func.airSubWithOverflow(inst), |
| ... | @@ -3741,13 +3741,65 @@ fn airBitReverse(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -3741,13 +3741,65 @@ fn airBitReverse(func: *Func, inst: Air.Inst.Index) !void { |
| 3741 | return func.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 3741 | return func.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 3742 | } | 3742 | } |
| 3743 | | 3743 | |
| 3744 | fn airUnaryMath(func: *Func, inst: Air.Inst.Index) !void { | 3744 | fn airUnaryMath(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { |
| 3745 | const tag = func.air.instructions.items(.tag)[@intFromEnum(inst)]; | 3745 | const zcu = func.bin_file.comp.module.?; |
| 3746 | const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op; | 3746 | const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 3747 | const result: MCValue = if (func.liveness.isUnused(inst)) | 3747 | const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: { |
| 3748 | .unreach | 3748 | const ty = func.typeOf(un_op); |
| 3749 | else | 3749 | |
| 3750 | return func.fail("TODO implementairUnaryMath {s} for {}", .{ @tagName(tag), func.target.cpu.arch }); | 3750 | const operand = try func.resolveInst(un_op); |
| | 3751 | const operand_bit_size = ty.bitSize(zcu); |
| | 3752 | |
| | 3753 | if (!math.isPowerOfTwo(operand_bit_size)) |
| | 3754 | return func.fail("TODO: airUnaryMath non-pow 2", .{}); |
| | 3755 | |
| | 3756 | const operand_reg, const operand_lock = try func.promoteReg(ty, operand); |
| | 3757 | defer if (operand_lock) |lock| func.register_manager.unlockReg(lock); |
| | 3758 | |
| | 3759 | const dst_class = func.typeRegClass(ty); |
| | 3760 | const dst_reg, const dst_lock = try func.allocReg(dst_class); |
| | 3761 | defer func.register_manager.unlockReg(dst_lock); |
| | 3762 | |
| | 3763 | switch (ty.zigTypeTag(zcu)) { |
| | 3764 | .Float => { |
| | 3765 | assert(dst_class == .float); |
| | 3766 | |
| | 3767 | switch (operand_bit_size) { |
| | 3768 | 16, 80, 128 => return func.fail("TODO: airUnaryMath Float bit-size {}", .{operand_bit_size}), |
| | 3769 | 32, 64 => {}, |
| | 3770 | else => unreachable, |
| | 3771 | } |
| | 3772 | |
| | 3773 | switch (tag) { |
| | 3774 | .sqrt => { |
| | 3775 | _ = try func.addInst(.{ |
| | 3776 | .tag = if (operand_bit_size == 64) .fsqrtd else .fsqrts, |
| | 3777 | .ops = .rrr, |
| | 3778 | .data = .{ |
| | 3779 | .r_type = .{ |
| | 3780 | .rd = dst_reg, |
| | 3781 | .rs1 = operand_reg, |
| | 3782 | .rs2 = .f0, // unused, spec says it's 0 |
| | 3783 | }, |
| | 3784 | }, |
| | 3785 | }); |
| | 3786 | }, |
| | 3787 | else => return func.fail("TODO: airUnaryMath Float {s}", .{@tagName(tag)}), |
| | 3788 | } |
| | 3789 | }, |
| | 3790 | .Int => { |
| | 3791 | assert(dst_class == .int); |
| | 3792 | |
| | 3793 | switch (tag) { |
| | 3794 | else => return func.fail("TODO: airUnaryMath Float {s}", .{@tagName(tag)}), |
| | 3795 | } |
| | 3796 | }, |
| | 3797 | else => return func.fail("TODO: airUnaryMath ty: {}", .{ty.fmt(zcu)}), |
| | 3798 | } |
| | 3799 | |
| | 3800 | break :result MCValue{ .register = dst_reg }; |
| | 3801 | }; |
| | 3802 | |
| 3751 | return func.finishAir(inst, result, .{ un_op, .none, .none }); | 3803 | return func.finishAir(inst, result, .{ un_op, .none, .none }); |
| 3752 | } | 3804 | } |
| 3753 | | 3805 | |