commit 9bea854dc2af293cba1d000b31f6e82d9c431285 (tree)
parent b18b4db7095f58b1e8b3f5ac4993bda38231c2af
Author: Jacob Young <jacobly0@users.noreply.github.com>
Date: Thu, 4 May 2023 03:36:28 -0400
x86_64: implement `@floor`, `@ceil`, and `@trunc`
Diffstat:
1 file changed, 41 insertions(+), 3 deletions(-)
diff --git a/src/arch/x86_64/CodeGen.zig b/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);