authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-01-15 18:28:39+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-01-15 18:28:39+01:00
log4d4bbd76240e155151d0bf964debe09ea05fc7ef
tree38b7fe11d8f3547e3f92e63cec2ed9910b523ae2
parenta5c7742ba6fc793608b8bb7ba058e33eccd9cfec

stage2: refactor handling of immediates in x86_64 backend

Fixes issues with incorrect operand sizes in a handful of cases and allows for usage of differently sized integers in Zig sources.

4 files changed, 142 insertions(+), 107 deletions(-)

src/arch/x86_64/CodeGen.zig+28-28
...@@ -497,14 +497,14 @@ fn gen(self: *Self) InnerError!void {...@@ -497,14 +497,14 @@ fn gen(self: *Self) InnerError!void {
497 .ops = (Mir.Ops{497 .ops = (Mir.Ops{
498 .reg1 = .rsp,498 .reg1 = .rsp,
499 }).encode(),499 }).encode(),
500 .data = .{ .imm = @intCast(i32, aligned_stack_end) + stack_adjustment },500 .data = .{ .imm = @bitCast(u32, @intCast(i32, aligned_stack_end) + stack_adjustment) },
501 });501 });
502 self.mir_instructions.set(backpatch_stack_add, .{502 self.mir_instructions.set(backpatch_stack_add, .{
503 .tag = .add,503 .tag = .add,
504 .ops = (Mir.Ops{504 .ops = (Mir.Ops{
505 .reg1 = .rsp,505 .reg1 = .rsp,
506 }).encode(),506 }).encode(),
507 .data = .{ .imm = @intCast(i32, aligned_stack_end) + stack_adjustment },507 .data = .{ .imm = @bitCast(u32, @intCast(i32, aligned_stack_end) + stack_adjustment) },
508 });508 });
509 }509 }
510 } else {510 } else {
...@@ -1347,7 +1347,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -1347,7 +1347,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
1347 .reg2 = .rbp,1347 .reg2 = .rbp,
1348 .flags = 0b01,1348 .flags = 0b01,
1349 }).encode(),1349 }).encode(),
1350 .data = .{ .imm = -@intCast(i32, off + 16) },1350 .data = .{ .imm = @bitCast(u32, -@intCast(i32, off + 16)) },
1351 });1351 });
1352 // add addr, offset1352 // add addr, offset
1353 _ = try self.addInst(.{1353 _ = try self.addInst(.{
...@@ -1555,7 +1555,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -1555,7 +1555,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
1555 try self.genSetReg(Type.initTag(.u32), count_reg, .{ .immediate = @intCast(u32, abi_size) });1555 try self.genSetReg(Type.initTag(.u32), count_reg, .{ .immediate = @intCast(u32, abi_size) });
15561556
1557 return self.genInlineMemcpy(1557 return self.genInlineMemcpy(
1558 -@intCast(i32, off + abi_size),1558 @bitCast(u32, -@intCast(i32, off + abi_size)),
1559 registerAlias(addr_reg, @divExact(reg.size(), 8)),1559 registerAlias(addr_reg, @divExact(reg.size(), 8)),
1560 count_reg.to64(),1560 count_reg.to64(),
1561 tmp_reg.to8(),1561 tmp_reg.to8(),
...@@ -1637,7 +1637,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -1637,7 +1637,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
1637 // introduce new MIR tag specifically for mov [reg + 0], imm1637 // introduce new MIR tag specifically for mov [reg + 0], imm
1638 const payload = try self.addExtra(Mir.ImmPair{1638 const payload = try self.addExtra(Mir.ImmPair{
1639 .dest_off = 0,1639 .dest_off = 0,
1640 .operand = @bitCast(i32, @intCast(u32, imm)),1640 .operand = @truncate(u32, imm),
1641 });1641 });
1642 _ = try self.addInst(.{1642 _ = try self.addInst(.{
1643 .tag = .mov_mem_imm,1643 .tag = .mov_mem_imm,
...@@ -1872,7 +1872,7 @@ fn genBinMathOpMir(...@@ -1872,7 +1872,7 @@ fn genBinMathOpMir(
1872 .ops = (Mir.Ops{1872 .ops = (Mir.Ops{
1873 .reg1 = registerAlias(dst_reg, @intCast(u32, abi_size)),1873 .reg1 = registerAlias(dst_reg, @intCast(u32, abi_size)),
1874 }).encode(),1874 }).encode(),
1875 .data = .{ .imm = @intCast(i32, imm) },1875 .data = .{ .imm = @truncate(u32, imm) },
1876 });1876 });
1877 },1877 },
1878 .embedded_in_code, .memory => {1878 .embedded_in_code, .memory => {
...@@ -1891,7 +1891,7 @@ fn genBinMathOpMir(...@@ -1891,7 +1891,7 @@ fn genBinMathOpMir(
1891 .reg2 = .rbp,1891 .reg2 = .rbp,
1892 .flags = 0b01,1892 .flags = 0b01,
1893 }).encode(),1893 }).encode(),
1894 .data = .{ .imm = -@intCast(i32, adj_off) },1894 .data = .{ .imm = @bitCast(u32, -@intCast(i32, adj_off)) },
1895 });1895 });
1896 },1896 },
1897 .compare_flags_unsigned => {1897 .compare_flags_unsigned => {
...@@ -1926,7 +1926,7 @@ fn genBinMathOpMir(...@@ -1926,7 +1926,7 @@ fn genBinMathOpMir(
1926 .reg2 = registerAlias(src_reg, @intCast(u32, abi_size)),1926 .reg2 = registerAlias(src_reg, @intCast(u32, abi_size)),
1927 .flags = 0b10,1927 .flags = 0b10,
1928 }).encode(),1928 }).encode(),
1929 .data = .{ .imm = -@intCast(i32, adj_off) },1929 .data = .{ .imm = @bitCast(u32, -@intCast(i32, adj_off)) },
1930 });1930 });
1931 },1931 },
1932 .immediate => |imm| {1932 .immediate => |imm| {
...@@ -1947,8 +1947,8 @@ fn genBinMathOpMir(...@@ -1947,8 +1947,8 @@ fn genBinMathOpMir(
1947 else => unreachable,1947 else => unreachable,
1948 };1948 };
1949 const payload = try self.addExtra(Mir.ImmPair{1949 const payload = try self.addExtra(Mir.ImmPair{
1950 .dest_off = -@intCast(i32, adj_off),1950 .dest_off = @bitCast(u32, -@intCast(i32, adj_off)),
1951 .operand = @bitCast(i32, @intCast(u32, imm)),1951 .operand = @truncate(u32, imm),
1952 });1952 });
1953 _ = try self.addInst(.{1953 _ = try self.addInst(.{
1954 .tag = tag,1954 .tag = tag,
...@@ -2015,7 +2015,7 @@ fn genIMulOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !...@@ -2015,7 +2015,7 @@ fn genIMulOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) !
2015 .reg2 = dst_reg.to32(),2015 .reg2 = dst_reg.to32(),
2016 .flags = 0b10,2016 .flags = 0b10,
2017 }).encode(),2017 }).encode(),
2018 .data = .{ .imm = @intCast(i32, imm) },2018 .data = .{ .imm = @truncate(u32, imm) },
2019 });2019 });
2020 } else {2020 } else {
2021 // TODO verify we don't spill and assign to the same register as dst_mcv2021 // TODO verify we don't spill and assign to the same register as dst_mcv
...@@ -2088,7 +2088,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -2088,7 +2088,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
2088 const mcv = self.args[arg_index];2088 const mcv = self.args[arg_index];
2089 const payload = try self.addExtra(Mir.ArgDbgInfo{2089 const payload = try self.addExtra(Mir.ArgDbgInfo{
2090 .air_inst = inst,2090 .air_inst = inst,
2091 .arg_index = @intCast(u32, arg_index), // TODO can arg_index: u32?2091 .arg_index = @truncate(u32, arg_index), // TODO can arg_index: u32?
2092 });2092 });
2093 _ = try self.addInst(.{2093 _ = try self.addInst(.{
2094 .tag = .arg_dbg_info,2094 .tag = .arg_dbg_info,
...@@ -2196,7 +2196,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {...@@ -2196,7 +2196,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
2196 .ops = (Mir.Ops{2196 .ops = (Mir.Ops{
2197 .flags = 0b01,2197 .flags = 0b01,
2198 }).encode(),2198 }).encode(),
2199 .data = .{ .imm = @bitCast(i32, got_addr) },2199 .data = .{ .imm = @truncate(u32, got_addr) },
2200 });2200 });
2201 } else if (func_value.castTag(.extern_fn)) |_| {2201 } else if (func_value.castTag(.extern_fn)) |_| {
2202 return self.fail("TODO implement calling extern functions", .{});2202 return self.fail("TODO implement calling extern functions", .{});
...@@ -3121,8 +3121,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3121,8 +3121,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3121 // offset from rbp, which is at the top of the stack frame.3121 // offset from rbp, which is at the top of the stack frame.
3122 // mov [rbp+offset], immediate3122 // mov [rbp+offset], immediate
3123 const payload = try self.addExtra(Mir.ImmPair{3123 const payload = try self.addExtra(Mir.ImmPair{
3124 .dest_off = -@intCast(i32, adj_off),3124 .dest_off = @bitCast(u32, -@intCast(i32, adj_off)),
3125 .operand = @bitCast(i32, @intCast(u32, x_big)),3125 .operand = @truncate(u32, x_big),
3126 });3126 });
3127 _ = try self.addInst(.{3127 _ = try self.addInst(.{
3128 .tag = .mov_mem_imm,3128 .tag = .mov_mem_imm,
...@@ -3147,8 +3147,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3147,8 +3147,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3147 // insted just use two 32 bit writes to avoid register allocation3147 // insted just use two 32 bit writes to avoid register allocation
3148 {3148 {
3149 const payload = try self.addExtra(Mir.ImmPair{3149 const payload = try self.addExtra(Mir.ImmPair{
3150 .dest_off = negative_offset + 4,3150 .dest_off = @bitCast(u32, negative_offset + 4),
3151 .operand = @bitCast(i32, @truncate(u32, x_big >> 32)),3151 .operand = @truncate(u32, x_big >> 32),
3152 });3152 });
3153 _ = try self.addInst(.{3153 _ = try self.addInst(.{
3154 .tag = .mov_mem_imm,3154 .tag = .mov_mem_imm,
...@@ -3161,8 +3161,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3161,8 +3161,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3161 }3161 }
3162 {3162 {
3163 const payload = try self.addExtra(Mir.ImmPair{3163 const payload = try self.addExtra(Mir.ImmPair{
3164 .dest_off = negative_offset,3164 .dest_off = @bitCast(u32, negative_offset),
3165 .operand = @bitCast(i32, @truncate(u32, x_big)),3165 .operand = @truncate(u32, x_big),
3166 });3166 });
3167 _ = try self.addInst(.{3167 _ = try self.addInst(.{
3168 .tag = .mov_mem_imm,3168 .tag = .mov_mem_imm,
...@@ -3192,7 +3192,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3192,7 +3192,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3192 .reg2 = registerAlias(reg, @intCast(u32, abi_size)),3192 .reg2 = registerAlias(reg, @intCast(u32, abi_size)),
3193 .flags = 0b10,3193 .flags = 0b10,
3194 }).encode(),3194 }).encode(),
3195 .data = .{ .imm = -@intCast(i32, adj_off) },3195 .data = .{ .imm = @bitCast(u32, -@intCast(i32, adj_off)) },
3196 });3196 });
3197 },3197 },
3198 .memory, .embedded_in_code => {3198 .memory, .embedded_in_code => {
...@@ -3228,14 +3228,14 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3228,14 +3228,14 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3228 .reg1 = addr_reg.to64(),3228 .reg1 = addr_reg.to64(),
3229 .reg2 = .rbp,3229 .reg2 = .rbp,
3230 }).encode(),3230 }).encode(),
3231 .data = .{ .imm = -@intCast(i32, off + abi_size) },3231 .data = .{ .imm = @bitCast(u32, -@intCast(i32, off + abi_size)) },
3232 });3232 });
32333233
3234 // TODO allow for abi_size to be u643234 // TODO allow for abi_size to be u64
3235 try self.genSetReg(Type.initTag(.u32), count_reg, .{ .immediate = @intCast(u32, abi_size) });3235 try self.genSetReg(Type.initTag(.u32), count_reg, .{ .immediate = @intCast(u32, abi_size) });
32363236
3237 return self.genInlineMemcpy(3237 return self.genInlineMemcpy(
3238 -@intCast(i32, stack_offset + abi_size),3238 @bitCast(u32, -@intCast(i32, stack_offset + abi_size)),
3239 addr_reg.to64(),3239 addr_reg.to64(),
3240 count_reg.to64(),3240 count_reg.to64(),
3241 tmp_reg.to8(),3241 tmp_reg.to8(),
...@@ -3246,7 +3246,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3246,7 +3246,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
32463246
3247fn genInlineMemcpy(3247fn genInlineMemcpy(
3248 self: *Self,3248 self: *Self,
3249 stack_offset: i32,3249 stack_offset: u32,
3250 addr_reg: Register,3250 addr_reg: Register,
3251 count_reg: Register,3251 count_reg: Register,
3252 tmp_reg: Register,3252 tmp_reg: Register,
...@@ -3361,7 +3361,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -3361,7 +3361,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
3361 .reg1 = registerAlias(reg, @intCast(u32, ptr_abi_size)),3361 .reg1 = registerAlias(reg, @intCast(u32, ptr_abi_size)),
3362 .reg2 = .rbp,3362 .reg2 = .rbp,
3363 }).encode(),3363 }).encode(),
3364 .data = .{ .imm = -@intCast(i32, off) },3364 .data = .{ .imm = @bitCast(u32, -@intCast(i32, off)) },
3365 });3365 });
3366 },3366 },
3367 .ptr_embedded_in_code => unreachable,3367 .ptr_embedded_in_code => unreachable,
...@@ -3426,7 +3426,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -3426,7 +3426,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
3426 .ops = (Mir.Ops{3426 .ops = (Mir.Ops{
3427 .reg1 = registerAlias(reg, @intCast(u32, abi_size)),3427 .reg1 = registerAlias(reg, @intCast(u32, abi_size)),
3428 }).encode(),3428 }).encode(),
3429 .data = .{ .imm = @intCast(i32, x) },3429 .data = .{ .imm = @truncate(u32, x) },
3430 });3430 });
3431 return;3431 return;
3432 }3432 }
...@@ -3482,7 +3482,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -3482,7 +3482,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
3482 .reg1 = reg,3482 .reg1 = reg,
3483 .flags = 0b10,3483 .flags = 0b10,
3484 }).encode(),3484 }).encode(),
3485 .data = .{ .got_entry = @intCast(u32, x) },3485 .data = .{ .got_entry = @truncate(u32, x) },
3486 });3486 });
3487 // MOV reg, [reg]3487 // MOV reg, [reg]
3488 _ = try self.addInst(.{3488 _ = try self.addInst(.{
...@@ -3502,7 +3502,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -3502,7 +3502,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
3502 .reg1 = reg,3502 .reg1 = reg,
3503 .flags = 0b01,3503 .flags = 0b01,
3504 }).encode(),3504 }).encode(),
3505 .data = .{ .imm = @intCast(i32, x) },3505 .data = .{ .imm = @truncate(u32, x) },
3506 });3506 });
3507 } else {3507 } else {
3508 // If this is RAX, we can use a direct load.3508 // If this is RAX, we can use a direct load.
...@@ -3561,7 +3561,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -3561,7 +3561,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
3561 .reg2 = .rbp,3561 .reg2 = .rbp,
3562 .flags = 0b01,3562 .flags = 0b01,
3563 }).encode(),3563 }).encode(),
3564 .data = .{ .imm = -@intCast(i32, off) },3564 .data = .{ .imm = @bitCast(u32, -@intCast(i32, off)) },
3565 });3565 });
3566 },3566 },
3567 }3567 }
src/arch/x86_64/Isel.zig+81-76
...@@ -483,17 +483,26 @@ inline fn setRexWRegister(reg: Register) bool {...@@ -483,17 +483,26 @@ inline fn setRexWRegister(reg: Register) bool {
483 };483 };
484}484}
485485
486inline fn immOpSize(imm: i64) u8 {486inline fn immOpSize(u_imm: u32) u8 {
487 blk: {487 const imm = @bitCast(i32, u_imm);
488 _ = math.cast(i8, imm) catch break :blk;488 if (math.minInt(i8) <= imm and imm <= math.maxInt(i8)) {
489 return 8;489 return 8;
490 }490 }
491 blk: {491 if (math.minInt(i16) <= imm and imm <= math.maxInt(i16)) {
492 _ = math.cast(i16, imm) catch break :blk;
493 return 16;492 return 16;
494 }493 }
495 blk: {494 return 32;
496 _ = math.cast(i32, imm) catch break :blk;495}
496
497inline fn imm64OpSize(u_imm: u64) u8 {
498 const imm = @bitCast(i64, u_imm);
499 if (math.minInt(i8) <= imm and imm <= math.maxInt(i8)) {
500 return 8;
501 }
502 if (math.minInt(i16) <= imm and imm <= math.maxInt(i16)) {
503 return 16;
504 }
505 if (math.minInt(i32) <= imm and imm <= math.maxInt(i32)) {
497 return 32;506 return 32;
498 }507 }
499 return 64;508 return 64;
...@@ -560,10 +569,10 @@ fn mirMovabs(isel: *Isel, inst: Mir.Inst.Index) InnerError!void {...@@ -560,10 +569,10 @@ fn mirMovabs(isel: *Isel, inst: Mir.Inst.Index) InnerError!void {
560 const tag = isel.mir.instructions.items(.tag)[inst];569 const tag = isel.mir.instructions.items(.tag)[inst];
561 assert(tag == .movabs);570 assert(tag == .movabs);
562 const ops = Mir.Ops.decode(isel.mir.instructions.items(.ops)[inst]);571 const ops = Mir.Ops.decode(isel.mir.instructions.items(.ops)[inst]);
563 const imm: i64 = if (ops.reg1.size() == 64) blk: {572 const imm: u64 = if (ops.reg1.size() == 64) blk: {
564 const payload = isel.mir.instructions.items(.data)[inst].payload;573 const payload = isel.mir.instructions.items(.data)[inst].payload;
565 const imm = isel.mir.extraData(Mir.Imm64, payload).data;574 const imm = isel.mir.extraData(Mir.Imm64, payload).data;
566 break :blk @bitCast(i64, imm.decode());575 break :blk imm.decode();
567 } else isel.mir.instructions.items(.data)[inst].imm;576 } else isel.mir.instructions.items(.data)[inst].imm;
568 if (ops.flags == 0b00) {577 if (ops.flags == 0b00) {
569 // movabs reg, imm64578 // movabs reg, imm64
...@@ -1233,7 +1242,7 @@ const ScaleIndex = struct {...@@ -1233,7 +1242,7 @@ const ScaleIndex = struct {
1233const Memory = struct {1242const Memory = struct {
1234 base: ?Register,1243 base: ?Register,
1235 rip: bool = false,1244 rip: bool = false,
1236 disp: i32,1245 disp: u32,
1237 ptr_size: PtrSize,1246 ptr_size: PtrSize,
1238 scale_index: ?ScaleIndex = null,1247 scale_index: ?ScaleIndex = null,
12391248
...@@ -1283,7 +1292,7 @@ const Memory = struct {...@@ -1283,7 +1292,7 @@ const Memory = struct {
1283 } else {1292 } else {
1284 encoder.sib_baseDisp8(dst);1293 encoder.sib_baseDisp8(dst);
1285 }1294 }
1286 encoder.disp8(@intCast(i8, mem_op.disp));1295 encoder.disp8(@bitCast(i8, @truncate(u8, mem_op.disp)));
1287 } else {1296 } else {
1288 encoder.modRm_SIBDisp32(src);1297 encoder.modRm_SIBDisp32(src);
1289 if (mem_op.scale_index) |si| {1298 if (mem_op.scale_index) |si| {
...@@ -1291,17 +1300,17 @@ const Memory = struct {...@@ -1291,17 +1300,17 @@ const Memory = struct {
1291 } else {1300 } else {
1292 encoder.sib_baseDisp32(dst);1301 encoder.sib_baseDisp32(dst);
1293 }1302 }
1294 encoder.disp32(mem_op.disp);1303 encoder.disp32(@bitCast(i32, mem_op.disp));
1295 }1304 }
1296 } else {1305 } else {
1297 if (mem_op.disp == 0) {1306 if (mem_op.disp == 0) {
1298 encoder.modRm_indirectDisp0(src, dst);1307 encoder.modRm_indirectDisp0(src, dst);
1299 } else if (immOpSize(mem_op.disp) == 8) {1308 } else if (immOpSize(mem_op.disp) == 8) {
1300 encoder.modRm_indirectDisp8(src, dst);1309 encoder.modRm_indirectDisp8(src, dst);
1301 encoder.disp8(@intCast(i8, mem_op.disp));1310 encoder.disp8(@bitCast(i8, @truncate(u8, mem_op.disp)));
1302 } else {1311 } else {
1303 encoder.modRm_indirectDisp32(src, dst);1312 encoder.modRm_indirectDisp32(src, dst);
1304 encoder.disp32(mem_op.disp);1313 encoder.disp32(@bitCast(i32, mem_op.disp));
1305 }1314 }
1306 }1315 }
1307 } else {1316 } else {
...@@ -1315,16 +1324,16 @@ const Memory = struct {...@@ -1315,16 +1324,16 @@ const Memory = struct {
1315 encoder.sib_disp32();1324 encoder.sib_disp32();
1316 }1325 }
1317 }1326 }
1318 encoder.disp32(mem_op.disp);1327 encoder.disp32(@bitCast(i32, mem_op.disp));
1319 }1328 }
1320 }1329 }
1321};1330};
13221331
1323fn encodeImm(encoder: Encoder, imm: i32, size: u64) void {1332fn encodeImm(encoder: Encoder, imm: u32, size: u64) void {
1324 switch (size) {1333 switch (size) {
1325 8 => encoder.imm8(@intCast(i8, imm)),1334 8 => encoder.imm8(@bitCast(i8, @truncate(u8, imm))),
1326 16 => encoder.imm16(@intCast(i16, imm)),1335 16 => encoder.imm16(@bitCast(i16, @truncate(u16, imm))),
1327 32, 64 => encoder.imm32(imm),1336 32, 64 => encoder.imm32(@bitCast(i32, imm)),
1328 else => unreachable,1337 else => unreachable,
1329 }1338 }
1330}1339}
...@@ -1338,7 +1347,7 @@ const RegisterOrMemory = union(enum) {...@@ -1338,7 +1347,7 @@ const RegisterOrMemory = union(enum) {
1338 }1347 }
13391348
1340 fn mem(ptr_size: Memory.PtrSize, args: struct {1349 fn mem(ptr_size: Memory.PtrSize, args: struct {
1341 disp: i32,1350 disp: u32,
1342 base: ?Register = null,1351 base: ?Register = null,
1343 scale_index: ?ScaleIndex = null,1352 scale_index: ?ScaleIndex = null,
1344 }) RegisterOrMemory {1353 }) RegisterOrMemory {
...@@ -1352,7 +1361,7 @@ const RegisterOrMemory = union(enum) {...@@ -1352,7 +1361,7 @@ const RegisterOrMemory = union(enum) {
1352 };1361 };
1353 }1362 }
13541363
1355 fn rip(ptr_size: Memory.PtrSize, disp: i32) RegisterOrMemory {1364 fn rip(ptr_size: Memory.PtrSize, disp: u32) RegisterOrMemory {
1356 return .{1365 return .{
1357 .memory = .{1366 .memory = .{
1358 .base = null,1367 .base = null,
...@@ -1377,12 +1386,12 @@ fn lowerToZoEnc(tag: Tag, code: *std.ArrayList(u8)) LoweringError!void {...@@ -1377,12 +1386,12 @@ fn lowerToZoEnc(tag: Tag, code: *std.ArrayList(u8)) LoweringError!void {
1377 opc.encode(encoder);1386 opc.encode(encoder);
1378}1387}
13791388
1380fn lowerToIEnc(tag: Tag, imm: i32, code: *std.ArrayList(u8)) LoweringError!void {1389fn lowerToIEnc(tag: Tag, imm: u32, code: *std.ArrayList(u8)) LoweringError!void {
1381 if (tag == .ret_far or tag == .ret_near) {1390 if (tag == .ret_far or tag == .ret_near) {
1382 const encoder = try Encoder.init(code, 3);1391 const encoder = try Encoder.init(code, 3);
1383 const opc = getOpCode(tag, .i, false).?;1392 const opc = getOpCode(tag, .i, false).?;
1384 opc.encode(encoder);1393 opc.encode(encoder);
1385 encoder.imm16(@intCast(i16, imm));1394 encoder.imm16(@bitCast(i16, @truncate(u16, imm)));
1386 return;1395 return;
1387 }1396 }
1388 const opc = getOpCode(tag, .i, immOpSize(imm) == 8).?;1397 const opc = getOpCode(tag, .i, immOpSize(imm) == 8).?;
...@@ -1410,11 +1419,11 @@ fn lowerToOEnc(tag: Tag, reg: Register, code: *std.ArrayList(u8)) LoweringError!...@@ -1410,11 +1419,11 @@ fn lowerToOEnc(tag: Tag, reg: Register, code: *std.ArrayList(u8)) LoweringError!
1410 opc.encodeWithReg(encoder, reg);1419 opc.encodeWithReg(encoder, reg);
1411}1420}
14121421
1413fn lowerToDEnc(tag: Tag, imm: i32, code: *std.ArrayList(u8)) LoweringError!void {1422fn lowerToDEnc(tag: Tag, imm: u32, code: *std.ArrayList(u8)) LoweringError!void {
1414 const opc = getOpCode(tag, .d, false).?;1423 const opc = getOpCode(tag, .d, false).?;
1415 const encoder = try Encoder.init(code, 6);1424 const encoder = try Encoder.init(code, 6);
1416 opc.encode(encoder);1425 opc.encode(encoder);
1417 encoder.imm32(imm);1426 encoder.imm32(@bitCast(i32, imm));
1418}1427}
14191428
1420fn lowerToMEnc(tag: Tag, reg_or_mem: RegisterOrMemory, code: *std.ArrayList(u8)) LoweringError!void {1429fn lowerToMEnc(tag: Tag, reg_or_mem: RegisterOrMemory, code: *std.ArrayList(u8)) LoweringError!void {
...@@ -1467,19 +1476,19 @@ fn lowerToMEnc(tag: Tag, reg_or_mem: RegisterOrMemory, code: *std.ArrayList(u8))...@@ -1467,19 +1476,19 @@ fn lowerToMEnc(tag: Tag, reg_or_mem: RegisterOrMemory, code: *std.ArrayList(u8))
1467 }1476 }
1468}1477}
14691478
1470fn lowerToTdEnc(tag: Tag, moffs: i64, reg: Register, code: *std.ArrayList(u8)) LoweringError!void {1479fn lowerToTdEnc(tag: Tag, moffs: u64, reg: Register, code: *std.ArrayList(u8)) LoweringError!void {
1471 return lowerToTdFdEnc(tag, reg, moffs, code, true);1480 return lowerToTdFdEnc(tag, reg, moffs, code, true);
1472}1481}
14731482
1474fn lowerToFdEnc(tag: Tag, reg: Register, moffs: i64, code: *std.ArrayList(u8)) LoweringError!void {1483fn lowerToFdEnc(tag: Tag, reg: Register, moffs: u64, code: *std.ArrayList(u8)) LoweringError!void {
1475 return lowerToTdFdEnc(tag, reg, moffs, code, false);1484 return lowerToTdFdEnc(tag, reg, moffs, code, false);
1476}1485}
14771486
1478fn lowerToTdFdEnc(tag: Tag, reg: Register, moffs: i64, code: *std.ArrayList(u8), td: bool) LoweringError!void {1487fn lowerToTdFdEnc(tag: Tag, reg: Register, moffs: u64, code: *std.ArrayList(u8), td: bool) LoweringError!void {
1479 if (reg.lowId() != Register.rax.lowId()) {1488 if (reg.lowId() != Register.rax.lowId()) {
1480 return error.RaxOperandExpected;1489 return error.RaxOperandExpected;
1481 }1490 }
1482 if (reg.size() != immOpSize(moffs)) {1491 if (reg.size() != imm64OpSize(moffs)) {
1483 return error.OperandSizeMismatch;1492 return error.OperandSizeMismatch;
1484 }1493 }
1485 const opc = if (td)1494 const opc = if (td)
...@@ -1495,27 +1504,16 @@ fn lowerToTdFdEnc(tag: Tag, reg: Register, moffs: i64, code: *std.ArrayList(u8),...@@ -1495,27 +1504,16 @@ fn lowerToTdFdEnc(tag: Tag, reg: Register, moffs: i64, code: *std.ArrayList(u8),
1495 });1504 });
1496 opc.encode(encoder);1505 opc.encode(encoder);
1497 switch (reg.size()) {1506 switch (reg.size()) {
1498 8 => {1507 8 => encoder.imm8(@bitCast(i8, @truncate(u8, moffs))),
1499 const moffs8 = try math.cast(i8, moffs);1508 16 => encoder.imm16(@bitCast(i16, @truncate(u16, moffs))),
1500 encoder.imm8(moffs8);1509 32 => encoder.imm32(@bitCast(i32, @truncate(u32, moffs))),
1501 },1510 64 => encoder.imm64(moffs),
1502 16 => {
1503 const moffs16 = try math.cast(i16, moffs);
1504 encoder.imm16(moffs16);
1505 },
1506 32 => {
1507 const moffs32 = try math.cast(i32, moffs);
1508 encoder.imm32(moffs32);
1509 },
1510 64 => {
1511 encoder.imm64(@bitCast(u64, moffs));
1512 },
1513 else => unreachable,1511 else => unreachable,
1514 }1512 }
1515}1513}
15161514
1517fn lowerToOiEnc(tag: Tag, reg: Register, imm: i64, code: *std.ArrayList(u8)) LoweringError!void {1515fn lowerToOiEnc(tag: Tag, reg: Register, imm: u64, code: *std.ArrayList(u8)) LoweringError!void {
1518 if (reg.size() != immOpSize(imm)) {1516 if (reg.size() != imm64OpSize(imm)) {
1519 return error.OperandSizeMismatch;1517 return error.OperandSizeMismatch;
1520 }1518 }
1521 const opc = getOpCode(tag, .oi, reg.size() == 8).?;1519 const opc = getOpCode(tag, .oi, reg.size() == 8).?;
...@@ -1529,26 +1527,15 @@ fn lowerToOiEnc(tag: Tag, reg: Register, imm: i64, code: *std.ArrayList(u8)) Low...@@ -1529,26 +1527,15 @@ fn lowerToOiEnc(tag: Tag, reg: Register, imm: i64, code: *std.ArrayList(u8)) Low
1529 });1527 });
1530 opc.encodeWithReg(encoder, reg);1528 opc.encodeWithReg(encoder, reg);
1531 switch (reg.size()) {1529 switch (reg.size()) {
1532 8 => {1530 8 => encoder.imm8(@bitCast(i8, @truncate(u8, imm))),
1533 const imm8 = try math.cast(i8, imm);1531 16 => encoder.imm16(@bitCast(i16, @truncate(u16, imm))),
1534 encoder.imm8(imm8);1532 32 => encoder.imm32(@bitCast(i32, @truncate(u32, imm))),
1535 },1533 64 => encoder.imm64(imm),
1536 16 => {
1537 const imm16 = try math.cast(i16, imm);
1538 encoder.imm16(imm16);
1539 },
1540 32 => {
1541 const imm32 = try math.cast(i32, imm);
1542 encoder.imm32(imm32);
1543 },
1544 64 => {
1545 encoder.imm64(@bitCast(u64, imm));
1546 },
1547 else => unreachable,1534 else => unreachable,
1548 }1535 }
1549}1536}
15501537
1551fn lowerToMiEnc(tag: Tag, reg_or_mem: RegisterOrMemory, imm: i32, code: *std.ArrayList(u8)) LoweringError!void {1538fn lowerToMiEnc(tag: Tag, reg_or_mem: RegisterOrMemory, imm: u32, code: *std.ArrayList(u8)) LoweringError!void {
1552 const modrm_ext = getModRmExt(tag).?;1539 const modrm_ext = getModRmExt(tag).?;
1553 switch (reg_or_mem) {1540 switch (reg_or_mem) {
1554 .register => |dst_reg| {1541 .register => |dst_reg| {
...@@ -1700,7 +1687,7 @@ fn lowerToRmiEnc(...@@ -1700,7 +1687,7 @@ fn lowerToRmiEnc(
1700 tag: Tag,1687 tag: Tag,
1701 reg: Register,1688 reg: Register,
1702 reg_or_mem: RegisterOrMemory,1689 reg_or_mem: RegisterOrMemory,
1703 imm: i32,1690 imm: u32,
1704 code: *std.ArrayList(u8),1691 code: *std.ArrayList(u8),
1705) LoweringError!void {1692) LoweringError!void {
1706 if (reg.size() == 8) {1693 if (reg.size() == 8) {
...@@ -1804,7 +1791,10 @@ test "lower MI encoding" {...@@ -1804,7 +1791,10 @@ test "lower MI encoding" {
1804 try expectEqualHexStrings("\x48\xc7\xc0\x10\x00\x00\x00", isel.lowered(), "mov rax, 0x10");1791 try expectEqualHexStrings("\x48\xc7\xc0\x10\x00\x00\x00", isel.lowered(), "mov rax, 0x10");
1805 try lowerToMiEnc(.mov, RegisterOrMemory.mem(.dword_ptr, .{ .disp = 0, .base = .r11 }), 0x10, isel.code());1792 try lowerToMiEnc(.mov, RegisterOrMemory.mem(.dword_ptr, .{ .disp = 0, .base = .r11 }), 0x10, isel.code());
1806 try expectEqualHexStrings("\x41\xc7\x03\x10\x00\x00\x00", isel.lowered(), "mov dword ptr [r11 + 0], 0x10");1793 try expectEqualHexStrings("\x41\xc7\x03\x10\x00\x00\x00", isel.lowered(), "mov dword ptr [r11 + 0], 0x10");
1807 try lowerToMiEnc(.add, RegisterOrMemory.mem(.dword_ptr, .{ .disp = -8, .base = .rdx }), 0x10, isel.code());1794 try lowerToMiEnc(.add, RegisterOrMemory.mem(.dword_ptr, .{
1795 .disp = @bitCast(u32, @as(i32, -8)),
1796 .base = .rdx,
1797 }), 0x10, isel.code());
1808 try expectEqualHexStrings("\x81\x42\xF8\x10\x00\x00\x00", isel.lowered(), "add dword ptr [rdx - 8], 0x10");1798 try expectEqualHexStrings("\x81\x42\xF8\x10\x00\x00\x00", isel.lowered(), "add dword ptr [rdx - 8], 0x10");
1809 try lowerToMiEnc(.sub, RegisterOrMemory.mem(.dword_ptr, .{1799 try lowerToMiEnc(.sub, RegisterOrMemory.mem(.dword_ptr, .{
1810 .disp = 0x10000000,1800 .disp = 0x10000000,
...@@ -1836,15 +1826,24 @@ test "lower MI encoding" {...@@ -1836,15 +1826,24 @@ test "lower MI encoding" {
1836 isel.lowered(),1826 isel.lowered(),
1837 "mov qword ptr [rip + 0x10], 0x10",1827 "mov qword ptr [rip + 0x10], 0x10",
1838 );1828 );
1839 try lowerToMiEnc(.mov, RegisterOrMemory.mem(.qword_ptr, .{ .disp = -8, .base = .rbp }), 0x10, isel.code());1829 try lowerToMiEnc(.mov, RegisterOrMemory.mem(.qword_ptr, .{
1830 .disp = @bitCast(u32, @as(i32, -8)),
1831 .base = .rbp,
1832 }), 0x10, isel.code());
1840 try expectEqualHexStrings(1833 try expectEqualHexStrings(
1841 "\x48\xc7\x45\xf8\x10\x00\x00\x00",1834 "\x48\xc7\x45\xf8\x10\x00\x00\x00",
1842 isel.lowered(),1835 isel.lowered(),
1843 "mov qword ptr [rbp - 8], 0x10",1836 "mov qword ptr [rbp - 8], 0x10",
1844 );1837 );
1845 try lowerToMiEnc(.mov, RegisterOrMemory.mem(.word_ptr, .{ .disp = -2, .base = .rbp }), 0x10, isel.code());1838 try lowerToMiEnc(.mov, RegisterOrMemory.mem(.word_ptr, .{
1839 .disp = @bitCast(u32, @as(i32, -2)),
1840 .base = .rbp,
1841 }), 0x10, isel.code());
1846 try expectEqualHexStrings("\x66\xC7\x45\xFE\x10\x00", isel.lowered(), "mov word ptr [rbp - 2], 0x10");1842 try expectEqualHexStrings("\x66\xC7\x45\xFE\x10\x00", isel.lowered(), "mov word ptr [rbp - 2], 0x10");
1847 try lowerToMiEnc(.mov, RegisterOrMemory.mem(.byte_ptr, .{ .disp = -1, .base = .rbp }), 0x10, isel.code());1843 try lowerToMiEnc(.mov, RegisterOrMemory.mem(.byte_ptr, .{
1844 .disp = @bitCast(u32, @as(i32, -1)),
1845 .base = .rbp,
1846 }), 0x10, isel.code());
1848 try expectEqualHexStrings("\xC6\x45\xFF\x10", isel.lowered(), "mov byte ptr [rbp - 1], 0x10");1847 try expectEqualHexStrings("\xC6\x45\xFF\x10", isel.lowered(), "mov byte ptr [rbp - 1], 0x10");
1849 try lowerToMiEnc(.mov, RegisterOrMemory.mem(.qword_ptr, .{1848 try lowerToMiEnc(.mov, RegisterOrMemory.mem(.qword_ptr, .{
1850 .disp = 0x10000000,1849 .disp = 0x10000000,
...@@ -1897,12 +1896,15 @@ test "lower RM encoding" {...@@ -1897,12 +1896,15 @@ test "lower RM encoding" {
1897 isel.lowered(),1896 isel.lowered(),
1898 "sub r11, qword ptr [r12 + 0x10000000]",1897 "sub r11, qword ptr [r12 + 0x10000000]",
1899 );1898 );
1900 try lowerToRmEnc(.mov, .rax, RegisterOrMemory.mem(.qword_ptr, .{ .disp = -4, .base = .rbp }), isel.code());1899 try lowerToRmEnc(.mov, .rax, RegisterOrMemory.mem(.qword_ptr, .{
1900 .disp = @bitCast(u32, @as(i32, -4)),
1901 .base = .rbp,
1902 }), isel.code());
1901 try expectEqualHexStrings("\x48\x8B\x45\xFC", isel.lowered(), "mov rax, qword ptr [rbp - 4]");1903 try expectEqualHexStrings("\x48\x8B\x45\xFC", isel.lowered(), "mov rax, qword ptr [rbp - 4]");
1902 try lowerToRmEnc(.lea, .rax, RegisterOrMemory.rip(.qword_ptr, 0x10), isel.code());1904 try lowerToRmEnc(.lea, .rax, RegisterOrMemory.rip(.qword_ptr, 0x10), isel.code());
1903 try expectEqualHexStrings("\x48\x8D\x05\x10\x00\x00\x00", isel.lowered(), "lea rax, [rip + 0x10]");1905 try expectEqualHexStrings("\x48\x8D\x05\x10\x00\x00\x00", isel.lowered(), "lea rax, [rip + 0x10]");
1904 try lowerToRmEnc(.mov, .rax, RegisterOrMemory.mem(.qword_ptr, .{1906 try lowerToRmEnc(.mov, .rax, RegisterOrMemory.mem(.qword_ptr, .{
1905 .disp = -8,1907 .disp = @bitCast(u32, @as(i32, -8)),
1906 .base = .rbp,1908 .base = .rbp,
1907 .scale_index = .{1909 .scale_index = .{
1908 .scale = 0,1910 .scale = 0,
...@@ -1911,7 +1913,7 @@ test "lower RM encoding" {...@@ -1911,7 +1913,7 @@ test "lower RM encoding" {
1911 }), isel.code());1913 }), isel.code());
1912 try expectEqualHexStrings("\x48\x8B\x44\x0D\xF8", isel.lowered(), "mov rax, qword ptr [rbp + rcx*1 - 8]");1914 try expectEqualHexStrings("\x48\x8B\x44\x0D\xF8", isel.lowered(), "mov rax, qword ptr [rbp + rcx*1 - 8]");
1913 try lowerToRmEnc(.mov, .eax, RegisterOrMemory.mem(.dword_ptr, .{1915 try lowerToRmEnc(.mov, .eax, RegisterOrMemory.mem(.dword_ptr, .{
1914 .disp = -4,1916 .disp = @bitCast(u32, @as(i32, -4)),
1915 .base = .rbp,1917 .base = .rbp,
1916 .scale_index = .{1918 .scale_index = .{
1917 .scale = 2,1919 .scale = 2,
...@@ -1920,7 +1922,7 @@ test "lower RM encoding" {...@@ -1920,7 +1922,7 @@ test "lower RM encoding" {
1920 }), isel.code());1922 }), isel.code());
1921 try expectEqualHexStrings("\x8B\x44\x95\xFC", isel.lowered(), "mov eax, dword ptr [rbp + rdx*4 - 4]");1923 try expectEqualHexStrings("\x8B\x44\x95\xFC", isel.lowered(), "mov eax, dword ptr [rbp + rdx*4 - 4]");
1922 try lowerToRmEnc(.mov, .rax, RegisterOrMemory.mem(.qword_ptr, .{1924 try lowerToRmEnc(.mov, .rax, RegisterOrMemory.mem(.qword_ptr, .{
1923 .disp = -8,1925 .disp = @bitCast(u32, @as(i32, -8)),
1924 .base = .rbp,1926 .base = .rbp,
1925 .scale_index = .{1927 .scale_index = .{
1926 .scale = 3,1928 .scale = 3,
...@@ -1929,7 +1931,7 @@ test "lower RM encoding" {...@@ -1929,7 +1931,7 @@ test "lower RM encoding" {
1929 }), isel.code());1931 }), isel.code());
1930 try expectEqualHexStrings("\x48\x8B\x44\xCD\xF8", isel.lowered(), "mov rax, qword ptr [rbp + rcx*8 - 8]");1932 try expectEqualHexStrings("\x48\x8B\x44\xCD\xF8", isel.lowered(), "mov rax, qword ptr [rbp + rcx*8 - 8]");
1931 try lowerToRmEnc(.mov, .r8b, RegisterOrMemory.mem(.byte_ptr, .{1933 try lowerToRmEnc(.mov, .r8b, RegisterOrMemory.mem(.byte_ptr, .{
1932 .disp = -24,1934 .disp = @bitCast(u32, @as(i32, -24)),
1933 .base = .rsi,1935 .base = .rsi,
1934 .scale_index = .{1936 .scale_index = .{
1935 .scale = 0,1937 .scale = 0,
...@@ -1953,7 +1955,10 @@ test "lower MR encoding" {...@@ -1953,7 +1955,10 @@ test "lower MR encoding" {
1953 defer isel.deinit();1955 defer isel.deinit();
1954 try lowerToMrEnc(.mov, RegisterOrMemory.reg(.rax), .rbx, isel.code());1956 try lowerToMrEnc(.mov, RegisterOrMemory.reg(.rax), .rbx, isel.code());
1955 try expectEqualHexStrings("\x48\x89\xd8", isel.lowered(), "mov rax, rbx");1957 try expectEqualHexStrings("\x48\x89\xd8", isel.lowered(), "mov rax, rbx");
1956 try lowerToMrEnc(.mov, RegisterOrMemory.mem(.qword_ptr, .{ .disp = -4, .base = .rbp }), .r11, isel.code());1958 try lowerToMrEnc(.mov, RegisterOrMemory.mem(.qword_ptr, .{
1959 .disp = @bitCast(u32, @as(i32, -4)),
1960 .base = .rbp,
1961 }), .r11, isel.code());
1957 try expectEqualHexStrings("\x4c\x89\x5d\xfc", isel.lowered(), "mov qword ptr [rbp - 4], r11");1962 try expectEqualHexStrings("\x4c\x89\x5d\xfc", isel.lowered(), "mov qword ptr [rbp - 4], r11");
1958 try lowerToMrEnc(.add, RegisterOrMemory.mem(.byte_ptr, .{ .disp = 0x10000000 }), .r12b, isel.code());1963 try lowerToMrEnc(.add, RegisterOrMemory.mem(.byte_ptr, .{ .disp = 0x10000000 }), .r12b, isel.code());
1959 try expectEqualHexStrings(1964 try expectEqualHexStrings(
...@@ -2063,7 +2068,7 @@ test "lower RMI encoding" {...@@ -2063,7 +2068,7 @@ test "lower RMI encoding" {
2063 var isel = TestIsel.init();2068 var isel = TestIsel.init();
2064 defer isel.deinit();2069 defer isel.deinit();
2065 try lowerToRmiEnc(.imul, .rax, RegisterOrMemory.mem(.qword_ptr, .{2070 try lowerToRmiEnc(.imul, .rax, RegisterOrMemory.mem(.qword_ptr, .{
2066 .disp = -8,2071 .disp = @bitCast(u32, @as(i32, -8)),
2067 .base = .rbp,2072 .base = .rbp,
2068 }), 0x10, isel.code());2073 }), 0x10, isel.code());
2069 try expectEqualHexStrings(2074 try expectEqualHexStrings(
...@@ -2072,12 +2077,12 @@ test "lower RMI encoding" {...@@ -2072,12 +2077,12 @@ test "lower RMI encoding" {
2072 "imul rax, qword ptr [rbp - 8], 0x10",2077 "imul rax, qword ptr [rbp - 8], 0x10",
2073 );2078 );
2074 try lowerToRmiEnc(.imul, .eax, RegisterOrMemory.mem(.dword_ptr, .{2079 try lowerToRmiEnc(.imul, .eax, RegisterOrMemory.mem(.dword_ptr, .{
2075 .disp = -4,2080 .disp = @bitCast(u32, @as(i32, -4)),
2076 .base = .rbp,2081 .base = .rbp,
2077 }), 0x10, isel.code());2082 }), 0x10, isel.code());
2078 try expectEqualHexStrings("\x69\x45\xFC\x10\x00\x00\x00", isel.lowered(), "imul eax, dword ptr [rbp - 4], 0x10");2083 try expectEqualHexStrings("\x69\x45\xFC\x10\x00\x00\x00", isel.lowered(), "imul eax, dword ptr [rbp - 4], 0x10");
2079 try lowerToRmiEnc(.imul, .ax, RegisterOrMemory.mem(.word_ptr, .{2084 try lowerToRmiEnc(.imul, .ax, RegisterOrMemory.mem(.word_ptr, .{
2080 .disp = -2,2085 .disp = @bitCast(u32, @as(i32, -2)),
2081 .base = .rbp,2086 .base = .rbp,
2082 }), 0x10, isel.code());2087 }), 0x10, isel.code());
2083 try expectEqualHexStrings("\x66\x69\x45\xFE\x10\x00", isel.lowered(), "imul ax, word ptr [rbp - 2], 0x10");2088 try expectEqualHexStrings("\x66\x69\x45\xFE\x10\x00", isel.lowered(), "imul ax, word ptr [rbp - 2], 0x10");
src/arch/x86_64/Mir.zig+3-3
...@@ -302,7 +302,7 @@ pub const Inst = struct {...@@ -302,7 +302,7 @@ pub const Inst = struct {
302 /// Another instruction.302 /// Another instruction.
303 inst: Index,303 inst: Index,
304 /// A 32-bit immediate value.304 /// A 32-bit immediate value.
305 imm: i32,305 imm: u32,
306 /// An extern function.306 /// An extern function.
307 /// Index into the linker's string table.307 /// Index into the linker's string table.
308 extern_fn: u32,308 extern_fn: u32,
...@@ -324,8 +324,8 @@ pub const Inst = struct {...@@ -324,8 +324,8 @@ pub const Inst = struct {
324};324};
325325
326pub const ImmPair = struct {326pub const ImmPair = struct {
327 dest_off: i32,327 dest_off: u32,
328 operand: i32,328 operand: u32,
329};329};
330330
331pub const Imm64 = struct {331pub const Imm64 = struct {
test/stage2/x86_64.zig+30
...@@ -1700,6 +1700,36 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -1700,6 +1700,36 @@ pub fn addCases(ctx: *TestContext) !void {
1700 \\ if (!ok) unreachable;1700 \\ if (!ok) unreachable;
1701 \\}1701 \\}
1702 , "");1702 , "");
1703 case.addCompareOutput(
1704 \\pub fn main() void {
1705 \\ var x: u16 = undefined;
1706 \\ set(&x);
1707 \\ assert(x == 123);
1708 \\}
1709 \\
1710 \\fn set(x: *u16) void {
1711 \\ x.* = 123;
1712 \\}
1713 \\
1714 \\fn assert(ok: bool) void {
1715 \\ if (!ok) unreachable;
1716 \\}
1717 , "");
1718 case.addCompareOutput(
1719 \\pub fn main() void {
1720 \\ var x: u8 = undefined;
1721 \\ set(&x);
1722 \\ assert(x == 123);
1723 \\}
1724 \\
1725 \\fn set(x: *u8) void {
1726 \\ x.* = 123;
1727 \\}
1728 \\
1729 \\fn assert(ok: bool) void {
1730 \\ if (!ok) unreachable;
1731 \\}
1732 , "");
1703 }1733 }
17041734
1705 {1735 {