| ... | ... | @@ -1275,7 +1275,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void { |
| 1275 | 1275 | .round, |
| 1276 | 1276 | .trunc_float, |
| 1277 | 1277 | .neg, |
| 1278 | | => try func.airUnaryMath(inst), |
| 1278 | => try func.airUnaryMath(inst, tag), |
| 1279 | 1279 | |
| 1280 | 1280 | .add_with_overflow => try func.airAddWithOverflow(inst), |
| 1281 | 1281 | .sub_with_overflow => try func.airSubWithOverflow(inst), |
| ... | ... | @@ -3741,13 +3741,65 @@ fn airBitReverse(func: *Func, inst: Air.Inst.Index) !void { |
| 3741 | 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 { |
| 3745 | | const tag = func.air.instructions.items(.tag)[@intFromEnum(inst)]; |
| 3744 | fn airUnaryMath(func: *Func, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { |
| 3745 | const zcu = func.bin_file.comp.module.?; |
| 3746 | 3746 | const un_op = func.air.instructions.items(.data)[@intFromEnum(inst)].un_op; |
| 3747 | | const result: MCValue = if (func.liveness.isUnused(inst)) |
| 3748 | | .unreach |
| 3749 | | else |
| 3750 | | return func.fail("TODO implementairUnaryMath {s} for {}", .{ @tagName(tag), func.target.cpu.arch }); |
| 3747 | const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: { |
| 3748 | const ty = func.typeOf(un_op); |
| 3749 | |
| 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 | 3803 | return func.finishAir(inst, result, .{ un_op, .none, .none }); |
| 3752 | 3804 | } |
| 3753 | 3805 | |