authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-09 09:38:59+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-11 20:05:49+01:00
logf61a70e812b0301f4e54e38ff4ce2b041f395e8d
tree6da2945145d580f4df1c868e4e6c1bffc72e2a20
parentaa8fda799e64c02d44fe80d1297b5ec8ae6b7677

x86_64: handle encoding and decoding Imm64 unsigned


2 files changed, 24 insertions(+), 21 deletions(-)

src/arch/x86_64/CodeGen.zig+17-20
......@@ -417,7 +417,6 @@ fn asmRegister(self: *Self, tag: Mir.Inst.Tag, reg: Register) !void {
417417}
418418
419419fn asmImmediate(self: *Self, tag: Mir.Inst.Tag, imm: Immediate) !void {
420 // TODO imm64
421420 const ops: Mir.Inst.Ops = if (imm == .signed) .imm_s else .imm_u;
422421 const data: Mir.Inst.Data = switch (ops) {
423422 .imm_s => .{ .imm_s = imm.signed },
......@@ -443,7 +442,10 @@ fn asmRegisterRegister(self: *Self, tag: Mir.Inst.Tag, reg1: Register, reg2: Reg
443442}
444443
445444fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.Tag, reg: Register, imm: Immediate) !void {
446 const ops: Mir.Inst.Ops = if (imm == .signed) .ri_s else .ri_u;
445 const ops: Mir.Inst.Ops = switch (imm) {
446 .signed => .ri_s,
447 .unsigned => |x| if (x <= math.maxInt(u32)) .ri_u else .ri64,
448 };
447449 const data: Mir.Inst.Data = switch (ops) {
448450 .ri_s => .{ .ri_s = .{
449451 .r1 = reg,
......@@ -453,6 +455,10 @@ fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.Tag, reg: Register, imm: Imme
453455 .r1 = reg,
454456 .imm = @intCast(u32, imm.unsigned),
455457 } },
458 .ri64 => .{ .rx = .{
459 .r1 = reg,
460 .payload = try self.addExtra(Mir.Imm64.encode(imm.unsigned)),
461 } },
456462 else => unreachable,
457463 };
458464 _ = try self.addInst(.{
......@@ -6118,32 +6124,23 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
61186124 // });
61196125 },
61206126 .immediate => |x| {
6121 // 32-bit moves zero-extend to 64-bit, so xoring the 32-bit
6122 // register is the fastest way to zero a register.
61236127 if (x == 0) {
6128 // 32-bit moves zero-extend to 64-bit, so xoring the 32-bit
6129 // register is the fastest way to zero a register.
61246130 return self.asmRegisterRegister(.xor, reg.to32(), reg.to32());
61256131 }
6126 if (x <= math.maxInt(i32)) {
6127 // Next best case: if we set the lower four bytes, the upper four will be zeroed.
6132 if (ty.isSignedInt() and x <= math.maxInt(i32)) {
61286133 return self.asmRegisterImmediate(
61296134 .mov,
61306135 registerAlias(reg, abi_size),
6131 Immediate.u(@intCast(u32, x)),
6136 Immediate.s(@intCast(i32, @bitCast(i64, x))),
61326137 );
61336138 }
6134 // Worst case: we need to load the 64-bit register with the IMM. GNU's assemblers calls
6135 // this `movabs`, though this is officially just a different variant of the plain `mov`
6136 // instruction.
6137 //
6138 // This encoding is, in fact, the *same* as the one used for 32-bit loads. The only
6139 // difference is that we set REX.W before the instruction, which extends the load to
6140 // 64-bit and uses the full bit-width of the register.
6141 // const payload = try self.addExtra(Mir.Imm64.encode(x));
6142 // _ = try self.addInst(.{
6143 // .tag = .movabs,
6144 // .ops = Mir.Inst.Ops.encode(.{ .reg1 = reg.to64() }),
6145 // .data = .{ .payload = payload },
6146 // });
6139 return self.asmRegisterImmediate(
6140 .mov,
6141 registerAlias(reg, abi_size),
6142 Immediate.u(x),
6143 );
61476144 },
61486145 .register => |src_reg| {
61496146 // If the registers are the same, nothing to do.
src/arch/x86_64/Emit.zig+7-1
......@@ -178,9 +178,10 @@ fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE
178178 if (mem.eql(u8, field.name, @tagName(tag))) break @field(Instruction.Mnemonic, field.name);
179179 } else unreachable;
180180
181 var operands = [4]Instruction.Operand{ .none, .none, .none, .none };
182181 const ops = emit.mir.instructions.items(.ops)[inst];
183182 const data = emit.mir.instructions.items(.data)[inst];
183
184 var operands = [4]Instruction.Operand{ .none, .none, .none, .none };
184185 switch (ops) {
185186 .none => {},
186187 .imm_s => operands[0] = .{ .imm = Immediate.s(data.imm_s) },
......@@ -198,6 +199,11 @@ fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE
198199 .{ .reg = data.ri_u.r1 },
199200 .{ .imm = Immediate.u(data.ri_u.imm) },
200201 },
202 .ri64 => {
203 operands[0] = .{ .reg = data.rx.r1 };
204 const imm64 = emit.mir.extraData(Mir.Imm64, data.rx.payload).data;
205 operands[1] = .{ .imm = Immediate.u(Mir.Imm64.decode(imm64)) };
206 },
201207 else => unreachable,
202208 }
203209