authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-09 15:03:41+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-11 20:05:49+01:00
log1bde522c2c6cae52c581458774ad1dfa479d8426
tree766c326bb139c2c05340e4fa7c4b51df51c57480
parent7221cd8ec90b5f206cf0b2979ba165719e5a2f23

x86_64: add helper for Jcc instruction


2 files changed, 126 insertions(+), 206 deletions(-)

src/arch/x86_64/CodeGen.zig+97-150
......@@ -4511,35 +4511,29 @@ fn genCondBrMir(self: *Self, ty: Type, mcv: MCValue) !u32 {
45114511 const abi_size = ty.abiSize(self.target.*);
45124512 switch (mcv) {
45134513 .eflags => |cc| {
4514 _ = cc;
4515 // return self.addInst(.{
4516 // .tag = .cond_jmp,
4517 // .ops = Mir.Inst.Ops.encode(.{}),
4518 // .data = .{
4519 // .inst_cc = .{
4520 // .inst = undefined,
4521 // // Here we map the opposites since the jump is to the false branch.
4522 // .cc = cc.negate(),
4523 // },
4524 // },
4525 // });
4514 return self.addInst(.{
4515 .tag = .jcc,
4516 .ops = .inst_cc,
4517 .data = .{
4518 .inst_cc = .{
4519 .inst = undefined,
4520 // Here we map the opposites since the jump is to the false branch.
4521 .cc = cc.negate(),
4522 },
4523 },
4524 });
45264525 },
45274526 .register => |reg| {
4528 _ = reg;
45294527 try self.spillEflagsIfOccupied();
4530 // _ = try self.addInst(.{
4531 // .tag = .@"test",
4532 // .ops = Mir.Inst.Ops.encode(.{ .reg1 = reg }),
4533 // .data = .{ .imm = 1 },
4534 // });
4535 // return self.addInst(.{
4536 // .tag = .cond_jmp,
4537 // .ops = Mir.Inst.Ops.encode(.{}),
4538 // .data = .{ .inst_cc = .{
4539 // .inst = undefined,
4540 // .cc = .e,
4541 // } },
4542 // });
4528 try self.asmRegisterImmediate(.@"test", reg, Immediate.u(1));
4529 return self.addInst(.{
4530 .tag = .jcc,
4531 .ops = .inst_cc,
4532 .data = .{ .inst_cc = .{
4533 .inst = undefined,
4534 .cc = .e,
4535 } },
4536 });
45434537 },
45444538 .immediate,
45454539 .stack_offset,
......@@ -4961,22 +4955,17 @@ fn genCondSwitchMir(self: *Self, ty: Type, condition: MCValue, case: MCValue) !u
49614955 },
49624956 }
49634957
4964 // _ = try self.addInst(.{
4965 // .tag = .@"test",
4966 // .ops = Mir.Inst.Ops.encode(.{
4967 // .reg1 = registerAlias(cond_reg, abi_size),
4968 // .reg2 = registerAlias(cond_reg, abi_size),
4969 // }),
4970 // .data = undefined,
4971 // });
4972 // return self.addInst(.{
4973 // .tag = .cond_jmp,
4974 // .ops = Mir.Inst.Ops.encode(.{}),
4975 // .data = .{ .inst_cc = .{
4976 // .inst = undefined,
4977 // .cc = .ne,
4978 // } },
4979 // });
4958 const aliased_reg = registerAlias(cond_reg, abi_size);
4959 try self.asmRegisterRegister(.@"test", aliased_reg, aliased_reg);
4960
4961 return self.addInst(.{
4962 .tag = .jcc,
4963 .ops = .inst_cc,
4964 .data = .{ .inst_cc = .{
4965 .inst = undefined,
4966 .cc = .ne,
4967 } },
4968 });
49804969 },
49814970 .stack_offset => {
49824971 try self.spillEflagsIfOccupied();
......@@ -5189,9 +5178,9 @@ fn canonicaliseBranches(self: *Self, parent_branch: *Branch, canon_branch: *Bran
51895178fn performReloc(self: *Self, reloc: Mir.Inst.Index) !void {
51905179 const next_inst = @intCast(u32, self.mir_instructions.len);
51915180 switch (self.mir_instructions.items(.tag)[reloc]) {
5192 // .cond_jmp => {
5193 // self.mir_instructions.items(.data)[reloc].inst_cc.inst = next_inst;
5194 // },
5181 .jcc => {
5182 self.mir_instructions.items(.data)[reloc].inst_cc.inst = next_inst;
5183 },
51955184 .jmp => {
51965185 self.mir_instructions.items(.data)[reloc].inst = next_inst;
51975186 },
......@@ -5806,7 +5795,6 @@ fn genInlineMemcpy(
58065795 const index_reg = regs[2].to64();
58075796 const count_reg = regs[3].to64();
58085797 const tmp_reg = regs[4].to8();
5809 _ = index_reg;
58105798 _ = tmp_reg;
58115799
58125800 switch (dst_ptr) {
......@@ -5825,15 +5813,11 @@ fn genInlineMemcpy(
58255813 // });
58265814 },
58275815 .register => |reg| {
5828 _ = reg;
5829 // _ = try self.addInst(.{
5830 // .tag = .mov,
5831 // .ops = Mir.Inst.Ops.encode(.{
5832 // .reg1 = registerAlias(dst_addr_reg, @intCast(u32, @divExact(reg.bitSize(), 8))),
5833 // .reg2 = reg,
5834 // }),
5835 // .data = undefined,
5836 // });
5816 try self.asmRegisterRegister(
5817 .mov,
5818 registerAlias(dst_addr_reg, @intCast(u32, @divExact(reg.bitSize(), 8))),
5819 reg,
5820 );
58375821 },
58385822 else => {
58395823 return self.fail("TODO implement memcpy for setting stack when dest is {}", .{dst_ptr});
......@@ -5856,15 +5840,11 @@ fn genInlineMemcpy(
58565840 // });
58575841 },
58585842 .register => |reg| {
5859 _ = reg;
5860 // _ = try self.addInst(.{
5861 // .tag = .mov,
5862 // .ops = Mir.Inst.Ops.encode(.{
5863 // .reg1 = registerAlias(src_addr_reg, @intCast(u32, @divExact(reg.bitSize(), 8))),
5864 // .reg2 = reg,
5865 // }),
5866 // .data = undefined,
5867 // });
5843 try self.asmRegisterRegister(
5844 .mov,
5845 registerAlias(src_addr_reg, @intCast(u32, @divExact(reg.bitSize(), 8))),
5846 reg,
5847 );
58685848 },
58695849 else => {
58705850 return self.fail("TODO implement memcpy for setting stack when src is {}", .{src_ptr});
......@@ -5873,30 +5853,24 @@ fn genInlineMemcpy(
58735853
58745854 try self.genSetReg(Type.usize, count_reg, len);
58755855
5876 // mov index_reg, 0
5877 // _ = try self.addInst(.{
5878 // .tag = .mov,
5879 // .ops = Mir.Inst.Ops.encode(.{ .reg1 = index_reg }),
5880 // .data = .{ .imm = 0 },
5881 // });
5882
5883 // loop:
5884 // cmp count, 0
5885 // const loop_start = try self.addInst(.{
5886 // .tag = .cmp,
5887 // .ops = Mir.Inst.Ops.encode(.{ .reg1 = count_reg }),
5888 // .data = .{ .imm = 0 },
5889 // });
5856 try self.asmRegisterImmediate(.mov, index_reg, Immediate.u(0));
58905857
5891 // je end
5892 // const loop_reloc = try self.addInst(.{
5893 // .tag = .cond_jmp,
5894 // .ops = Mir.Inst.Ops.encode(.{}),
5895 // .data = .{ .inst_cc = .{
5896 // .inst = undefined,
5897 // .cc = .e,
5898 // } },
5899 // });
5858 const loop_start = try self.addInst(.{
5859 .tag = .cmp,
5860 .ops = .ri_u,
5861 .data = .{ .ri_u = .{
5862 .r1 = count_reg,
5863 .imm = 0,
5864 } },
5865 });
5866 const loop_reloc = try self.addInst(.{
5867 .tag = .jcc,
5868 .ops = .inst_cc,
5869 .data = .{ .inst_cc = .{
5870 .inst = undefined,
5871 .cc = .e,
5872 } },
5873 });
59005874
59015875 // mov tmp, [addr + index_reg]
59025876 // _ = try self.addInst(.{
......@@ -5918,29 +5892,16 @@ fn genInlineMemcpy(
59185892 // .data = .{ .payload = try self.addExtra(Mir.IndexRegisterDisp.encode(index_reg, 0)) },
59195893 // });
59205894
5921 // add index_reg, 1
5922 // _ = try self.addInst(.{
5923 // .tag = .add,
5924 // .ops = Mir.Inst.Ops.encode(.{ .reg1 = index_reg }),
5925 // .data = .{ .imm = 1 },
5926 // });
5927
5928 // sub count, 1
5929 // _ = try self.addInst(.{
5930 // .tag = .sub,
5931 // .ops = Mir.Inst.Ops.encode(.{ .reg1 = count_reg }),
5932 // .data = .{ .imm = 1 },
5933 // });
5895 try self.asmRegisterImmediate(.add, index_reg, Immediate.u(1));
5896 try self.asmRegisterImmediate(.sub, count_reg, Immediate.u(1));
59345897
5935 // jmp loop
5936 // _ = try self.addInst(.{
5937 // .tag = .jmp,
5938 // .ops = Mir.Inst.Ops.encode(.{}),
5939 // .data = .{ .inst = loop_start },
5940 // });
5898 _ = try self.addInst(.{
5899 .tag = .jmp,
5900 .ops = .inst,
5901 .data = .{ .inst = loop_start },
5902 });
59415903
5942 // end:
5943 // try self.performReloc(loop_reloc);
5904 try self.performReloc(loop_reloc);
59445905}
59455906
59465907fn genInlineMemset(
......@@ -5982,15 +5943,11 @@ fn genInlineMemset(
59825943 // });
59835944 },
59845945 .register => |reg| {
5985 _ = reg;
5986 // _ = try self.addInst(.{
5987 // .tag = .mov,
5988 // .ops = Mir.Inst.Ops.encode(.{
5989 // .reg1 = registerAlias(addr_reg, @intCast(u32, @divExact(reg.bitSize(), 8))),
5990 // .reg2 = reg,
5991 // }),
5992 // .data = undefined,
5993 // });
5946 try self.asmRegisterRegister(
5947 .mov,
5948 registerAlias(addr_reg, @intCast(u32, @divExact(reg.bitSize(), 8))),
5949 reg,
5950 );
59945951 },
59955952 else => {
59965953 return self.fail("TODO implement memcpy for setting stack when dest is {}", .{dst_ptr});
......@@ -6000,26 +5957,23 @@ fn genInlineMemset(
60005957 try self.genSetReg(Type.usize, index_reg, len);
60015958 try self.genBinOpMir(.sub, Type.usize, .{ .register = index_reg }, .{ .immediate = 1 });
60025959
6003 // loop:
6004 // cmp index_reg, -1
6005 // const loop_start = try self.addInst(.{
6006 // .tag = .cmp,
6007 // .ops = Mir.Inst.Ops.encode(.{
6008 // .reg1 = index_reg,
6009 // .flags = 0b11,
6010 // }),
6011 // .data = .{ .imm_s = -1 },
6012 // });
5960 const loop_start = try self.addInst(.{
5961 .tag = .cmp,
5962 .ops = .ri_s,
5963 .data = .{ .ri_s = .{
5964 .r1 = index_reg,
5965 .imm = -1,
5966 } },
5967 });
60135968
6014 // je end
6015 // const loop_reloc = try self.addInst(.{
6016 // .tag = .cond_jmp,
6017 // .ops = Mir.Inst.Ops.encode(.{}),
6018 // .data = .{ .inst_cc = .{
6019 // .inst = undefined,
6020 // .cc = .e,
6021 // } },
6022 // });
5969 const loop_reloc = try self.addInst(.{
5970 .tag = .jcc,
5971 .ops = .inst_cc,
5972 .data = .{ .inst_cc = .{
5973 .inst = undefined,
5974 .cc = .e,
5975 } },
5976 });
60235977
60245978 switch (value) {
60255979 .immediate => |x| {
......@@ -6042,22 +5996,15 @@ fn genInlineMemset(
60425996 else => return self.fail("TODO inline memset for value of type {}", .{value}),
60435997 }
60445998
6045 // sub index_reg, 1
6046 // _ = try self.addInst(.{
6047 // .tag = .sub,
6048 // .ops = Mir.Inst.Ops.encode(.{ .reg1 = index_reg }),
6049 // .data = .{ .imm = 1 },
6050 // });
5999 try self.asmRegisterImmediate(.sub, index_reg, Immediate.u(1));
60516000
6052 // jmp loop
6053 // _ = try self.addInst(.{
6054 // .tag = .jmp,
6055 // .ops = Mir.Inst.Ops.encode(.{}),
6056 // .data = .{ .inst = loop_start },
6057 // });
6001 _ = try self.addInst(.{
6002 .tag = .jmp,
6003 .ops = .inst,
6004 .data = .{ .inst = loop_start },
6005 });
60586006
6059 // end:
6060 // try self.performReloc(loop_reloc);
6007 try self.performReloc(loop_reloc);
60616008}
60626009
60636010fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void {
src/arch/x86_64/Emit.zig+29-56
......@@ -1,4 +1,3 @@
1//!
21//! This file contains the functionality for lowering x86_64 MIR into
32//! machine code
43
......@@ -118,8 +117,9 @@ pub fn lowerMir(emit: *Emit) InnerError!void {
118117 => try emit.mirEncodeGeneric(tag, inst),
119118
120119 // Pseudo-instructions
121 .cmovcc => try emit.mirCmovCC(inst),
122 .setcc => try emit.mirSetCC(inst),
120 .cmovcc => try emit.mirCmovcc(inst),
121 .setcc => try emit.mirSetcc(inst),
122 .jcc => try emit.mirJcc(inst),
123123
124124 .dbg_line => try emit.mirDbgLine(inst),
125125 .dbg_prologue_end => try emit.mirDbgPrologueEnd(inst),
......@@ -220,19 +220,19 @@ fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerE
220220 });
221221}
222222
223fn mnemonicFromCC(comptime basename: []const u8, cc: bits.Condition) Instruction.Mnemonic {
223fn mnemonicFromConditionCode(comptime basename: []const u8, cc: bits.Condition) Instruction.Mnemonic {
224224 inline for (@typeInfo(bits.Condition).Enum.fields) |field| {
225225 if (mem.eql(u8, field.name, @tagName(cc)))
226226 return @field(Instruction.Mnemonic, basename ++ field.name);
227227 } else unreachable;
228228}
229229
230fn mirCmovCC(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
230fn mirCmovcc(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
231231 const ops = emit.mir.instructions.items(.ops)[inst];
232232 switch (ops) {
233233 .rr_c => {
234234 const data = emit.mir.instructions.items(.data)[inst].rr_c;
235 const mnemonic = mnemonicFromCC("cmov", data.cc);
235 const mnemonic = mnemonicFromConditionCode("cmov", data.cc);
236236 return emit.encode(mnemonic, .{
237237 .op1 = .{ .reg = data.r1 },
238238 .op2 = .{ .reg = data.r2 },
......@@ -242,12 +242,12 @@ fn mirCmovCC(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
242242 }
243243}
244244
245fn mirSetCC(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
245fn mirSetcc(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
246246 const ops = emit.mir.instructions.items(.ops)[inst];
247247 switch (ops) {
248248 .r_c => {
249249 const data = emit.mir.instructions.items(.data)[inst].r_c;
250 const mnemonic = mnemonicFromCC("set", data.cc);
250 const mnemonic = mnemonicFromConditionCode("set", data.cc);
251251 return emit.encode(mnemonic, .{
252252 .op1 = .{ .reg = data.r1 },
253253 });
......@@ -256,6 +256,27 @@ fn mirSetCC(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
256256 }
257257}
258258
259fn mirJcc(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
260 const ops = emit.mir.instructions.items(.ops)[inst];
261 switch (ops) {
262 .inst_cc => {
263 const data = emit.mir.instructions.items(.data)[inst].inst_cc;
264 const mnemonic = mnemonicFromConditionCode("j", data.cc);
265 const source = emit.code.items.len;
266 try emit.encode(mnemonic, .{
267 .op1 = .{ .imm = Immediate.s(0) },
268 });
269 try emit.relocs.append(emit.bin_file.allocator, .{
270 .source = source,
271 .target = data.inst,
272 .offset = emit.code.items.len - 4,
273 .length = 6,
274 });
275 },
276 else => unreachable, // TODO
277 }
278}
279
259280fn mirPushPopRegisterList(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void {
260281 const payload = emit.mir.instructions.items(.data)[inst].payload;
261282 const save_reg_list = emit.mir.extraData(Mir.SaveRegisterList, payload).data;
......@@ -326,54 +347,6 @@ fn mirPushPopRegisterList(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index)
326347// }
327348// }
328349
329// fn mirCondJmp(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
330// const tag = emit.mir.instructions.items(.tag)[inst];
331// assert(tag == .cond_jmp);
332// const inst_cc = emit.mir.instructions.items(.data)[inst].inst_cc;
333// const mnemonic: Instruction.Mnemonic = switch (inst_cc.cc) {
334// .a => .ja,
335// .ae => .jae,
336// .b => .jb,
337// .be => .jbe,
338// .c => .jc,
339// .e => .je,
340// .g => .jg,
341// .ge => .jge,
342// .l => .jl,
343// .le => .jle,
344// .na => .jna,
345// .nae => .jnae,
346// .nb => .jnb,
347// .nbe => .jnbe,
348// .nc => .jnc,
349// .ne => .jne,
350// .ng => .jng,
351// .nge => .jnge,
352// .nl => .jnl,
353// .nle => .jnle,
354// .no => .jno,
355// .np => .jnp,
356// .ns => .jns,
357// .nz => .jnz,
358// .o => .jo,
359// .p => .jp,
360// .pe => .jpe,
361// .po => .jpo,
362// .s => .js,
363// .z => .jz,
364// };
365// const source = emit.code.items.len;
366// try emit.encode(mnemonic, .{
367// .op1 = .{ .imm = Immediate.s(0) },
368// });
369// try emit.relocs.append(emit.bin_file.allocator, .{
370// .source = source,
371// .target = inst_cc.inst,
372// .offset = emit.code.items.len - 4,
373// .length = 6,
374// });
375// }
376
377350// fn mirLea(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
378351// const tag = emit.mir.instructions.items(.tag)[inst];
379352// assert(tag == .lea);