Commit 611c38e6da

mlugg <mlugg@mlugg.co.uk>
2025-09-27 12:18:33
x86_64: fix unencodable `rem` lowerings
The memory operand might use one of the extended GPRs R8 through R15 and hence require a REX prefix, but having a REX prefix makes the high-byte register AH unencodeable as the src operand. This latent bug was exposed by this branch, presumably because `select` now happens to be putting something in an extended GPR instead of a legacy GPR. In theory this could be fixed with minimal cost by introducing a way to communicate to `select` that neither the destination memory nor the other temporary can be in an extended GPR. However, I just went for the simple solution which comes at a cost of one trivial instruction: copy the remainder from AH to AL, and *then* copy AL to the destination.
1 parent 77fca16
Changed files (1)
src
codegen
src/codegen/x86_64/CodeGen.zig
@@ -37912,7 +37912,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
                         .{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_unaligned_size), ._, ._ },
                         .{ .@"0:", ._, .movsx, .tmp1d, .memia(.src0b, .tmp0, .add_unaligned_size), ._, ._ },
                         .{ ._, .i_, .div, .memia(.src1b, .tmp0, .add_unaligned_size), ._, ._, ._ },
-                        .{ ._, ._, .mov, .memia(.dst0b, .tmp0, .add_unaligned_size), .tmp1h, ._, ._ },
+                        .{ ._, ._, .movsx, .tmp1d, .tmp1h, ._, ._ },
+                        .{ ._, ._, .mov, .memia(.dst0b, .tmp0, .add_unaligned_size), .tmp1l, ._, ._ },
                         .{ ._, ._, .add, .tmp0p, .si(1), ._, ._ },
                         .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
                     } },
@@ -37944,7 +37945,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
                         .{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_unaligned_size), ._, ._ },
                         .{ .@"0:", ._, .movsx, .tmp1d, .memia(.src0b, .tmp0, .add_unaligned_size), ._, ._ },
                         .{ ._, .i_, .div, .memia(.src1b, .tmp0, .add_unaligned_size), ._, ._, ._ },
-                        .{ ._, ._, .mov, .memia(.dst0b, .tmp0, .add_unaligned_size), .tmp1h, ._, ._ },
+                        .{ ._, ._, .movsx, .tmp1d, .tmp1h, ._, ._ },
+                        .{ ._, ._, .mov, .memia(.dst0b, .tmp0, .add_unaligned_size), .tmp1l, ._, ._ },
                         .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
                         .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
                     } },
@@ -37977,7 +37979,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
                         .{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_unaligned_size), ._, ._ },
                         .{ .@"0:", ._, .movzx, .tmp1d, .memia(.src0b, .tmp0, .add_unaligned_size), ._, ._ },
                         .{ ._, ._, .div, .memia(.src1b, .tmp0, .add_unaligned_size), ._, ._, ._ },
-                        .{ ._, ._, .mov, .memia(.dst0b, .tmp0, .add_unaligned_size), .tmp1h, ._, ._ },
+                        .{ ._, ._, .movzx, .tmp1d, .tmp1h, ._, ._ },
+                        .{ ._, ._, .mov, .memia(.dst0b, .tmp0, .add_unaligned_size), .tmp1l, ._, ._ },
                         .{ ._, ._, .add, .tmp0p, .si(1), ._, ._ },
                         .{ ._, ._nc, .j, .@"0b", ._, ._, ._ },
                     } },
@@ -38009,7 +38012,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void {
                         .{ ._, ._, .mov, .tmp0p, .sa(.src0, .sub_unaligned_size), ._, ._ },
                         .{ .@"0:", ._, .movzx, .tmp1d, .memia(.src0b, .tmp0, .add_unaligned_size), ._, ._ },
                         .{ ._, ._, .div, .memia(.src1b, .tmp0, .add_unaligned_size), ._, ._, ._ },
-                        .{ ._, ._, .mov, .memia(.dst0b, .tmp0, .add_unaligned_size), .tmp1h, ._, ._ },
+                        .{ ._, ._, .movzx, .tmp1d, .tmp1h, ._, ._ },
+                        .{ ._, ._, .mov, .memia(.dst0b, .tmp0, .add_unaligned_size), .tmp1l, ._, ._ },
                         .{ ._, ._c, .in, .tmp0p, ._, ._, ._ },
                         .{ ._, ._nz, .j, .@"0b", ._, ._, ._ },
                     } },