From 9bea854dc2af293cba1d000b31f6e82d9c431285 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Thu, 4 May 2023 03:36:28 -0400 Subject: [PATCH] x86_64: implement `@floor`, `@ceil`, and `@trunc` --- src/arch/x86_64/CodeGen.zig | 44 ++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 97e672b71f..fbed0bcf96 100644 --- 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);