Commit 9bea854dc2

Jacob Young <jacobly0@users.noreply.github.com>
2023-05-04 09:36:28
x86_64: implement `@floor`, `@ceil`, and `@trunc`
1 parent b18b4db
Changed files (1)
src
arch
src/arch/x86_64/CodeGen.zig
@@ -1480,12 +1480,12 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
             .log,
             .log2,
             .log10,
-            .floor,
-            .ceil,
             .round,
-            .trunc_float,
             => try self.airUnaryMath(inst),
 
+            .floor => try self.airRound(inst, Immediate.u(0b1_0_01)),
+            .ceil => try self.airRound(inst, Immediate.u(0b1_0_10)),
+            .trunc_float => try self.airRound(inst, Immediate.u(0b1_0_11)),
             .sqrt => try self.airSqrt(inst),
             .neg, .fabs => try self.airFloatSign(inst),
 
@@ -4258,6 +4258,44 @@ fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void {
     return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none });
 }
 
+fn airRound(self: *Self, inst: Air.Inst.Index, mode: Immediate) !void {
+    const un_op = self.air.instructions.items(.data)[inst].un_op;
+    const ty = self.air.typeOf(un_op);
+
+    if (!Target.x86.featureSetHas(self.target.cpu.features, .sse4_1))
+        return self.fail("TODO implement airRound without sse4_1 feature", .{});
+
+    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);
+
+    const mir_tag: Mir.Inst.Tag = switch (ty.zigTypeTag()) {
+        .Float => switch (ty.floatBits(self.target.*)) {
+            32 => .roundss,
+            64 => .roundsd,
+            else => return self.fail("TODO implement airRound for {}", .{
+                ty.fmt(self.bin_file.options.module.?),
+            }),
+        },
+        else => return self.fail("TODO implement airRound for {}", .{
+            ty.fmt(self.bin_file.options.module.?),
+        }),
+    };
+    assert(dst_mcv.isRegister());
+    if (src_mcv.isRegister())
+        try self.asmRegisterRegisterImmediate(mir_tag, dst_mcv.getReg().?, src_mcv.getReg().?, mode)
+    else
+        try self.asmRegisterMemoryImmediate(
+            mir_tag,
+            dst_mcv.getReg().?,
+            src_mcv.mem(Memory.PtrSize.fromSize(@intCast(u32, ty.abiSize(self.target.*)))),
+            mode,
+        );
+    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);