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 {...@@ -417,7 +417,6 @@ fn asmRegister(self: *Self, tag: Mir.Inst.Tag, reg: Register) !void {
417}417}
418418
419fn asmImmediate(self: *Self, tag: Mir.Inst.Tag, imm: Immediate) !void {419fn asmImmediate(self: *Self, tag: Mir.Inst.Tag, imm: Immediate) !void {
420 // TODO imm64
421 const ops: Mir.Inst.Ops = if (imm == .signed) .imm_s else .imm_u;420 const ops: Mir.Inst.Ops = if (imm == .signed) .imm_s else .imm_u;
422 const data: Mir.Inst.Data = switch (ops) {421 const data: Mir.Inst.Data = switch (ops) {
423 .imm_s => .{ .imm_s = imm.signed },422 .imm_s => .{ .imm_s = imm.signed },
...@@ -443,7 +442,10 @@ fn asmRegisterRegister(self: *Self, tag: Mir.Inst.Tag, reg1: Register, reg2: Reg...@@ -443,7 +442,10 @@ fn asmRegisterRegister(self: *Self, tag: Mir.Inst.Tag, reg1: Register, reg2: Reg
443}442}
444443
445fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.Tag, reg: Register, imm: Immediate) !void {444fn 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 };
447 const data: Mir.Inst.Data = switch (ops) {449 const data: Mir.Inst.Data = switch (ops) {
448 .ri_s => .{ .ri_s = .{450 .ri_s => .{ .ri_s = .{
449 .r1 = reg,451 .r1 = reg,
...@@ -453,6 +455,10 @@ fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.Tag, reg: Register, imm: Imme...@@ -453,6 +455,10 @@ fn asmRegisterImmediate(self: *Self, tag: Mir.Inst.Tag, reg: Register, imm: Imme
453 .r1 = reg,455 .r1 = reg,
454 .imm = @intCast(u32, imm.unsigned),456 .imm = @intCast(u32, imm.unsigned),
455 } },457 } },
458 .ri64 => .{ .rx = .{
459 .r1 = reg,
460 .payload = try self.addExtra(Mir.Imm64.encode(imm.unsigned)),
461 } },
456 else => unreachable,462 else => unreachable,
457 };463 };
458 _ = try self.addInst(.{464 _ = try self.addInst(.{
...@@ -6118,32 +6124,23 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -6118,32 +6124,23 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
6118 // });6124 // });
6119 },6125 },
6120 .immediate => |x| {6126 .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.
6123 if (x == 0) {6127 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.
6124 return self.asmRegisterRegister(.xor, reg.to32(), reg.to32());6130 return self.asmRegisterRegister(.xor, reg.to32(), reg.to32());
6125 }6131 }
6126 if (x <= math.maxInt(i32)) {6132 if (ty.isSignedInt() and x <= math.maxInt(i32)) {
6127 // Next best case: if we set the lower four bytes, the upper four will be zeroed.
6128 return self.asmRegisterImmediate(6133 return self.asmRegisterImmediate(
6129 .mov,6134 .mov,
6130 registerAlias(reg, abi_size),6135 registerAlias(reg, abi_size),
6131 Immediate.u(@intCast(u32, x)),6136 Immediate.s(@intCast(i32, @bitCast(i64, x))),
6132 );6137 );
6133 }6138 }
6134 // Worst case: we need to load the 64-bit register with the IMM. GNU's assemblers calls6139 return self.asmRegisterImmediate(
6135 // this `movabs`, though this is officially just a different variant of the plain `mov`6140 .mov,
6136 // instruction.6141 registerAlias(reg, abi_size),
6137 //6142 Immediate.u(x),
6138 // This encoding is, in fact, the *same* as the one used for 32-bit loads. The only6143 );
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 // });
6147 },6144 },
6148 .register => |src_reg| {6145 .register => |src_reg| {
6149 // If the registers are the same, nothing to do.6146 // 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...@@ -178,9 +178,10 @@ fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE
178 if (mem.eql(u8, field.name, @tagName(tag))) break @field(Instruction.Mnemonic, field.name);178 if (mem.eql(u8, field.name, @tagName(tag))) break @field(Instruction.Mnemonic, field.name);
179 } else unreachable;179 } else unreachable;
180180
181 var operands = [4]Instruction.Operand{ .none, .none, .none, .none };
182 const ops = emit.mir.instructions.items(.ops)[inst];181 const ops = emit.mir.instructions.items(.ops)[inst];
183 const data = emit.mir.instructions.items(.data)[inst];182 const data = emit.mir.instructions.items(.data)[inst];
183
184 var operands = [4]Instruction.Operand{ .none, .none, .none, .none };
184 switch (ops) {185 switch (ops) {
185 .none => {},186 .none => {},
186 .imm_s => operands[0] = .{ .imm = Immediate.s(data.imm_s) },187 .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...@@ -198,6 +199,11 @@ fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE
198 .{ .reg = data.ri_u.r1 },199 .{ .reg = data.ri_u.r1 },
199 .{ .imm = Immediate.u(data.ri_u.imm) },200 .{ .imm = Immediate.u(data.ri_u.imm) },
200 },201 },
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 },
201 else => unreachable,207 else => unreachable,
202 }208 }
203209