Commit 6893f90887

Jacob Young <jacobly0@users.noreply.github.com>
2023-05-03 08:37:48
x86_64: implement sqrt
1 parent a5e5089
src/arch/x86_64/CodeGen.zig
@@ -229,6 +229,7 @@ pub const MCValue = union(enum) {
     fn isRegister(mcv: MCValue) bool {
         return switch (mcv) {
             .register => true,
+            .register_offset => |reg_off| return reg_off.off == 0,
             else => false,
         };
     }
@@ -1449,7 +1450,6 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
             .shl_sat         => try self.airShlSat(inst),
             .slice           => try self.airSlice(inst),
 
-            .sqrt,
             .sin,
             .cos,
             .tan,
@@ -1464,6 +1464,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
             .trunc_float,
             => try self.airUnaryMath(inst),
 
+            .sqrt => try self.airSqrt(inst),
             .neg, .fabs => try self.airFloatSign(inst),
 
             .add_with_overflow => try self.airAddSubWithOverflow(inst),
@@ -4242,6 +4243,31 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {
     return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none });
 }
 
+fn airSqrt(self: *Self, inst: Air.Inst.Index) !void {
+    const un_op = self.air.instructions.items(.data)[inst].un_op;
+    const ty = self.air.typeOf(un_op);
+
+    const src_mcv = try self.resolveInst(un_op);
+    const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, un_op, 0, src_mcv))
+        src_mcv
+    else
+        try self.copyToRegisterWithInstTracking(inst, ty, src_mcv);
+
+    try self.genBinOpMir(switch (ty.zigTypeTag()) {
+        .Float => switch (ty.floatBits(self.target.*)) {
+            32 => .sqrtss,
+            64 => .sqrtsd,
+            else => return self.fail("TODO implement airSqrt for {}", .{
+                ty.fmt(self.bin_file.options.module.?),
+            }),
+        },
+        else => return self.fail("TODO implement airSqrt for {}", .{
+            ty.fmt(self.bin_file.options.module.?),
+        }),
+    }, ty, dst_mcv, src_mcv);
+    return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none });
+}
+
 fn airUnaryMath(self: *Self, inst: Air.Inst.Index) !void {
     const un_op = self.air.instructions.items(.data)[inst].un_op;
     _ = un_op;
src/arch/x86_64/Encoding.zig
@@ -277,6 +277,8 @@ pub const Mnemonic = enum {
     movss,
     mulss,
     orps,
+    sqrtps,
+    sqrtss,
     subss,
     ucomiss,
     xorps,
@@ -291,6 +293,8 @@ pub const Mnemonic = enum {
     movq, //movd, movsd,
     mulsd,
     orpd,
+    sqrtpd,
+    sqrtsd,
     subsd,
     ucomisd,
     xorpd,
src/arch/x86_64/encodings.zig
@@ -856,6 +856,9 @@ pub const table = [_]Entry{
 
     .{ .subss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5c }, 0, .sse },
 
+    .{ .sqrtps, .rm, &.{ .xmm, .xmm_m128 }, &.{       0x0f, 0x51 }, 0, .sse },
+    .{ .sqrtss, .rm, &.{ .xmm, .xmm_m32  }, &.{ 0xf3, 0x0f, 0x51 }, 0, .sse },
+
     .{ .ucomiss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0x0f, 0x2e }, 0, .sse },
 
     .{ .xorps, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x0f, 0x57 }, 0, .sse },
@@ -895,6 +898,9 @@ pub const table = [_]Entry{
 
     .{ .orpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x56 }, 0, .sse2 },
 
+    .{ .sqrtpd, .rm, &.{ .xmm, .xmm_m128 }, &.{ 0x66, 0x0f, 0x51 }, 0, .sse2 },
+    .{ .sqrtsd, .rm, &.{ .xmm, .xmm_m64  }, &.{ 0xf2, 0x0f, 0x51 }, 0, .sse2 },
+
     .{ .subsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5c }, 0, .sse2 },
 
     .{ .movsd, .rm, &.{ .xmm,     .xmm_m64 }, &.{ 0xf2, 0x0f, 0x10 }, 0, .sse2 },
src/arch/x86_64/Lower.zig
@@ -105,6 +105,8 @@ pub fn lowerMir(lower: *Lower, inst: Mir.Inst) Error![]const Instruction {
         .mulss,
         .orps,
         .roundss,
+        .sqrtps,
+        .sqrtss,
         .subss,
         .ucomiss,
         .xorps,
@@ -122,6 +124,8 @@ pub fn lowerMir(lower: *Lower, inst: Mir.Inst) Error![]const Instruction {
         .mulsd,
         .orpd,
         .roundsd,
+        .sqrtpd,
+        .sqrtsd,
         .subsd,
         .ucomisd,
         .xorpd,
src/arch/x86_64/Mir.zig
@@ -190,7 +190,11 @@ pub const Inst = struct {
         orps,
         /// Round scalar single-precision floating-point values
         roundss,
+        /// Square root of scalar single precision floating-point value
+        sqrtps,
         /// Subtract scalar single-precision floating-point values
+        sqrtss,
+        /// Square root of single precision floating-point values
         subss,
         /// Unordered compare scalar single-precision floating-point values
         ucomiss,
@@ -224,6 +228,10 @@ pub const Inst = struct {
         orpd,
         /// Round scalar double-precision floating-point values
         roundsd,
+        /// Square root of double precision floating-point values
+        sqrtpd,
+        /// Square root of scalar double precision floating-point value
+        sqrtsd,
         /// Subtract scalar double-precision floating-point values
         subsd,
         /// Unordered compare scalar double-precision floating-point values