authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-03-26 21:33:56-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-03-27 05:58:00-04:00
logabb37a7cb8d4bfae2da6d2cb9e9e6305ef6e52c4
treefb30cd3257f76d7026d1fd930c8157b959b50e38
parent0e5e001278465e508130eb159327e6aa11895f1c

x86_64: factor out lowering from emitting


8 files changed, 2167 insertions(+), 2127 deletions(-)

src/arch/x86_64/CodeGen.zig+9-12
......@@ -341,19 +341,22 @@ pub fn generate(
341341 defer mir.deinit(bin_file.allocator);
342342
343343 var emit = Emit{
344 .mir = mir,
344 .lower = .{
345 .allocator = bin_file.allocator,
346 .mir = mir,
347 .target = &bin_file.options.target,
348 .src_loc = src_loc,
349 },
345350 .bin_file = bin_file,
346351 .debug_output = debug_output,
347 .target = &bin_file.options.target,
348 .src_loc = src_loc,
349352 .code = code,
350353 .prev_di_pc = 0,
351354 .prev_di_line = module_fn.lbrace_line,
352355 .prev_di_column = module_fn.lbrace_column,
353356 };
354357 defer emit.deinit();
355 emit.lowerMir() catch |err| switch (err) {
356 error.EmitFail => return Result{ .fail = emit.err_msg.? },
358 emit.emitMir() catch |err| switch (err) {
359 error.LowerFail, error.EmitFail => return Result{ .fail = emit.lower.err_msg.? },
357360 error.InvalidInstruction, error.CannotEncode => |e| {
358361 const msg = switch (e) {
359362 error.InvalidInstruction => "CodeGen failed to find a viable instruction.",
......@@ -7070,16 +7073,10 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
70707073 if (reg.to64() == .rax) {
70717074 // If this is RAX, we can use a direct load.
70727075 // Otherwise, we need to load the address, then indirectly load the value.
7073 var moffs: Mir.MemoryMoffs = .{
7074 .seg = @enumToInt(Register.ds),
7075 .msb = undefined,
7076 .lsb = undefined,
7077 };
7078 moffs.encodeOffset(x);
70797076 _ = try self.addInst(.{
70807077 .tag = .mov_moffs,
70817078 .ops = .rax_moffs,
7082 .data = .{ .payload = try self.addExtra(moffs) },
7079 .data = .{ .payload = try self.addExtra(Mir.MemoryMoffs.encode(.ds, x)) },
70837080 });
70847081 } else {
70857082 // Rather than duplicate the logic used for the move, we just use a self-call with a new MCValue.
src/arch/x86_64/Emit.zig+168-737
......@@ -1,40 +1,8 @@
1//! This file contains the functionality for lowering x86_64 MIR into
2//! machine code
1//! This file contains the functionality for emitting x86_64 MIR as machine code
32
4const Emit = @This();
5
6const std = @import("std");
7const assert = std.debug.assert;
8const bits = @import("bits.zig");
9const abi = @import("abi.zig");
10const encoder = @import("encoder.zig");
11const link = @import("../../link.zig");
12const log = std.log.scoped(.codegen);
13const math = std.math;
14const mem = std.mem;
15const testing = std.testing;
16
17const Air = @import("../../Air.zig");
18const Allocator = mem.Allocator;
19const CodeGen = @import("CodeGen.zig");
20const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput;
21const Encoder = bits.Encoder;
22const ErrorMsg = Module.ErrorMsg;
23const Immediate = bits.Immediate;
24const Instruction = encoder.Instruction;
25const MCValue = @import("CodeGen.zig").MCValue;
26const Memory = bits.Memory;
27const Mir = @import("Mir.zig");
28const Module = @import("../../Module.zig");
29const Register = bits.Register;
30const Type = @import("../../type.zig").Type;
31
32mir: Mir,
3lower: Lower,
334bin_file: *link.File,
345debug_output: DebugInfoOutput,
35target: *const std.Target,
36err_msg: ?*ErrorMsg = null,
37src_loc: Module.SrcLoc,
386code: *std.ArrayList(u8),
397
408prev_di_line: u32,
......@@ -45,166 +13,176 @@ prev_di_pc: usize,
4513code_offset_mapping: std.AutoHashMapUnmanaged(Mir.Inst.Index, usize) = .{},
4614relocs: std.ArrayListUnmanaged(Reloc) = .{},
4715
48const InnerError = error{
49 OutOfMemory,
50 EmitFail,
51 InvalidInstruction,
52 CannotEncode,
53};
54
55const Reloc = struct {
56 /// Offset of the instruction.
57 source: usize,
58 /// Target of the relocation.
59 target: Mir.Inst.Index,
60 /// Offset of the relocation within the instruction.
61 offset: usize,
62 /// Length of the instruction.
63 length: u5,
64};
65
66pub fn lowerMir(emit: *Emit) InnerError!void {
67 const mir_tags = emit.mir.instructions.items(.tag);
68
69 for (mir_tags, 0..) |tag, index| {
70 const inst = @intCast(u32, index);
71 try emit.code_offset_mapping.putNoClobber(emit.bin_file.allocator, inst, emit.code.items.len);
72 switch (tag) {
73 .adc,
74 .add,
75 .@"and",
76 .bsf,
77 .bsr,
78 .bswap,
79 .bt,
80 .btc,
81 .btr,
82 .bts,
83 .call,
84 .cbw,
85 .cwde,
86 .cdqe,
87 .cwd,
88 .cdq,
89 .cqo,
90 .cmp,
91 .cmpxchg,
92 .div,
93 .fisttp,
94 .fld,
95 .idiv,
96 .imul,
97 .int3,
98 .jmp,
99 .lea,
100 .lfence,
101 .lzcnt,
102 .mfence,
103 .mov,
104 .movbe,
105 .movzx,
106 .mul,
107 .neg,
108 .nop,
109 .not,
110 .@"or",
111 .pop,
112 .popcnt,
113 .push,
114 .rcl,
115 .rcr,
116 .ret,
117 .rol,
118 .ror,
119 .sal,
120 .sar,
121 .sbb,
122 .sfence,
123 .shl,
124 .shld,
125 .shr,
126 .shrd,
127 .sub,
128 .syscall,
129 .@"test",
130 .tzcnt,
131 .ud2,
132 .xadd,
133 .xchg,
134 .xor,
135
136 .addss,
137 .cmpss,
138 .divss,
139 .maxss,
140 .minss,
141 .movss,
142 .mulss,
143 .roundss,
144 .subss,
145 .ucomiss,
146 .addsd,
147 .cmpsd,
148 .divsd,
149 .maxsd,
150 .minsd,
151 .movsd,
152 .mulsd,
153 .roundsd,
154 .subsd,
155 .ucomisd,
156 => try emit.mirEncodeGeneric(tag, inst),
157
158 .cmps,
159 .lods,
160 .movs,
161 .scas,
162 .stos,
163 => try emit.mirString(tag, inst),
164
165 .cmpxchgb => try emit.mirCmpxchgBytes(inst),
166
167 .jmp_reloc => try emit.mirJmpReloc(inst),
168
169 .call_extern => try emit.mirCallExtern(inst),
170
171 .lea_linker => try emit.mirLeaLinker(inst),
172
173 .mov_moffs => try emit.mirMovMoffs(inst),
174
175 .movsx => try emit.mirMovsx(inst),
176 .cmovcc => try emit.mirCmovcc(inst),
177 .setcc => try emit.mirSetcc(inst),
178 .jcc => try emit.mirJcc(inst),
16pub const Error = Lower.Error || error{EmitFail};
17
18pub fn emitMir(emit: *Emit) Error!void {
19 for (0..emit.lower.mir.instructions.len) |i| {
20 const index = @intCast(Mir.Inst.Index, i);
21 const inst = emit.lower.mir.instructions.get(index);
22
23 const start_offset = @intCast(u32, emit.code.items.len);
24 try emit.code_offset_mapping.putNoClobber(emit.lower.allocator, index, start_offset);
25 for (try emit.lower.lowerMir(inst)) |lower_inst| try lower_inst.encode(emit.code.writer());
26 const end_offset = @intCast(u32, emit.code.items.len);
27
28 switch (inst.tag) {
29 else => {},
30
31 .jmp_reloc => try emit.relocs.append(emit.lower.allocator, .{
32 .source = start_offset,
33 .target = inst.data.inst,
34 .offset = end_offset - 4,
35 .length = 5,
36 }),
37
38 .call_extern => if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
39 // Add relocation to the decl.
40 const atom_index = macho_file.getAtomIndexForSymbol(
41 .{ .sym_index = inst.data.relocation.atom_index, .file = null },
42 ).?;
43 const target = macho_file.getGlobalByIndex(inst.data.relocation.sym_index);
44 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
45 .type = @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),
46 .target = target,
47 .offset = end_offset - 4,
48 .addend = 0,
49 .pcrel = true,
50 .length = 2,
51 });
52 } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
53 // Add relocation to the decl.
54 const atom_index = coff_file.getAtomIndexForSymbol(
55 .{ .sym_index = inst.data.relocation.atom_index, .file = null },
56 ).?;
57 const target = coff_file.getGlobalByIndex(inst.data.relocation.sym_index);
58 try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
59 .type = .direct,
60 .target = target,
61 .offset = end_offset - 4,
62 .addend = 0,
63 .pcrel = true,
64 .length = 2,
65 });
66 } else return emit.fail("TODO implement {} for {}", .{ inst.tag, emit.bin_file.tag }),
67
68 .lea_linker => if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
69 const metadata =
70 emit.lower.mir.extraData(Mir.LeaRegisterReloc, inst.data.payload).data;
71 const reloc_type = switch (inst.ops) {
72 .got_reloc => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_GOT),
73 .direct_reloc => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_SIGNED),
74 else => unreachable,
75 };
76 const atom_index = macho_file.getAtomIndexForSymbol(.{
77 .sym_index = metadata.atom_index,
78 .file = null,
79 }).?;
80 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
81 .type = reloc_type,
82 .target = .{ .sym_index = metadata.sym_index, .file = null },
83 .offset = @intCast(u32, end_offset - 4),
84 .addend = 0,
85 .pcrel = true,
86 .length = 2,
87 });
88 } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
89 const metadata =
90 emit.lower.mir.extraData(Mir.LeaRegisterReloc, inst.data.payload).data;
91 const atom_index = coff_file.getAtomIndexForSymbol(.{
92 .sym_index = metadata.atom_index,
93 .file = null,
94 }).?;
95 try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
96 .type = switch (inst.ops) {
97 .got_reloc => .got,
98 .direct_reloc => .direct,
99 .import_reloc => .import,
100 else => unreachable,
101 },
102 .target = switch (inst.ops) {
103 .got_reloc,
104 .direct_reloc,
105 => .{ .sym_index = metadata.sym_index, .file = null },
106 .import_reloc => coff_file.getGlobalByIndex(metadata.sym_index),
107 else => unreachable,
108 },
109 .offset = @intCast(u32, end_offset - 4),
110 .addend = 0,
111 .pcrel = true,
112 .length = 2,
113 });
114 } else return emit.fail("TODO implement {} for {}", .{ inst.tag, emit.bin_file.tag }),
115
116 .jcc => try emit.relocs.append(emit.lower.allocator, .{
117 .source = start_offset,
118 .target = inst.data.inst_cc.inst,
119 .offset = end_offset - 4,
120 .length = 6,
121 }),
179122
180 .dbg_line => try emit.mirDbgLine(inst),
181 .dbg_prologue_end => try emit.mirDbgPrologueEnd(inst),
182 .dbg_epilogue_begin => try emit.mirDbgEpilogueBegin(inst),
123 .dbg_line => {
124 const dbg_line_column =
125 emit.lower.mir.extraData(Mir.DbgLineColumn, inst.data.payload).data;
126 try emit.dbgAdvancePCAndLine(dbg_line_column.line, dbg_line_column.column);
127 },
183128
184 .push_regs => try emit.mirPushPopRegisterList(.push, inst),
185 .pop_regs => try emit.mirPushPopRegisterList(.pop, inst),
129 .dbg_prologue_end => {
130 switch (emit.debug_output) {
131 .dwarf => |dw| {
132 try dw.setPrologueEnd();
133 log.debug("mirDbgPrologueEnd (line={d}, col={d})", .{
134 emit.prev_di_line, emit.prev_di_column,
135 });
136 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
137 },
138 .plan9 => {},
139 .none => {},
140 }
141 },
186142
187 .dead => {},
143 .dbg_epilogue_begin => {
144 switch (emit.debug_output) {
145 .dwarf => |dw| {
146 try dw.setEpilogueBegin();
147 log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{
148 emit.prev_di_line, emit.prev_di_column,
149 });
150 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
151 },
152 .plan9 => {},
153 .none => {},
154 }
155 },
188156 }
189157 }
190
191158 try emit.fixupRelocs();
192159}
193160
194161pub fn deinit(emit: *Emit) void {
195 emit.relocs.deinit(emit.bin_file.allocator);
196 emit.code_offset_mapping.deinit(emit.bin_file.allocator);
162 emit.relocs.deinit(emit.lower.allocator);
163 emit.code_offset_mapping.deinit(emit.lower.allocator);
197164 emit.* = undefined;
198165}
199166
200fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError {
201 @setCold(true);
202 assert(emit.err_msg == null);
203 emit.err_msg = try ErrorMsg.create(emit.bin_file.allocator, emit.src_loc, format, args);
204 return error.EmitFail;
167fn fail(emit: *Emit, comptime format: []const u8, args: anytype) Error {
168 return switch (emit.lower.fail(format, args)) {
169 error.LowerFail => error.EmitFail,
170 else => |e| e,
171 };
205172}
206173
207fn fixupRelocs(emit: *Emit) InnerError!void {
174const Reloc = struct {
175 /// Offset of the instruction.
176 source: usize,
177 /// Target of the relocation.
178 target: Mir.Inst.Index,
179 /// Offset of the relocation within the instruction.
180 offset: usize,
181 /// Length of the instruction.
182 length: u5,
183};
184
185fn fixupRelocs(emit: *Emit) Error!void {
208186 // TODO this function currently assumes all relocs via JMP/CALL instructions are 32bit in size.
209187 // This should be reversed like it is done in aarch64 MIR emit code: start with the smallest
210188 // possible resolution, i.e., 8bit, and iteratively converge on the minimum required resolution
......@@ -217,532 +195,7 @@ fn fixupRelocs(emit: *Emit) InnerError!void {
217195 }
218196}
219197
220fn encode(emit: *Emit, mnemonic: Instruction.Mnemonic, ops: Instruction.Init) InnerError!void {
221 const inst = try Instruction.new(mnemonic, ops);
222 return inst.encode(emit.code.writer());
223}
224
225fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void {
226 const mnemonic = inline for (@typeInfo(Instruction.Mnemonic).Enum.fields) |field| {
227 if (mem.eql(u8, field.name, @tagName(tag))) break @field(Instruction.Mnemonic, field.name);
228 } else unreachable;
229
230 const ops = emit.mir.instructions.items(.ops)[inst];
231 const data = emit.mir.instructions.items(.data)[inst];
232
233 const prefix: Instruction.Prefix = switch (ops) {
234 .lock_m_sib,
235 .lock_m_rip,
236 .lock_mi_sib_u,
237 .lock_mi_rip_u,
238 .lock_mi_sib_s,
239 .lock_mi_rip_s,
240 .lock_mr_sib,
241 .lock_mr_rip,
242 .lock_moffs_rax,
243 => .lock,
244 else => .none,
245 };
246
247 var op1: Instruction.Operand = .none;
248 var op2: Instruction.Operand = .none;
249 var op3: Instruction.Operand = .none;
250 var op4: Instruction.Operand = .none;
251
252 switch (ops) {
253 .none => {},
254 .i_s => op1 = .{ .imm = Immediate.s(@bitCast(i32, data.i)) },
255 .i_u => op1 = .{ .imm = Immediate.u(data.i) },
256 .r => op1 = .{ .reg = data.r },
257 .rr => {
258 op1 = .{ .reg = data.rr.r1 };
259 op2 = .{ .reg = data.rr.r2 };
260 },
261 .rrr => {
262 op1 = .{ .reg = data.rrr.r1 };
263 op2 = .{ .reg = data.rrr.r2 };
264 op3 = .{ .reg = data.rrr.r3 };
265 },
266 .ri_s, .ri_u => {
267 const imm = switch (ops) {
268 .ri_s => Immediate.s(@bitCast(i32, data.ri.i)),
269 .ri_u => Immediate.u(data.ri.i),
270 else => unreachable,
271 };
272 op1 = .{ .reg = data.ri.r };
273 op2 = .{ .imm = imm };
274 },
275 .ri64 => {
276 const imm64 = emit.mir.extraData(Mir.Imm64, data.rx.payload).data;
277 op1 = .{ .reg = data.rx.r };
278 op2 = .{ .imm = Immediate.u(Mir.Imm64.decode(imm64)) };
279 },
280 .rri_s, .rri_u => {
281 const imm = switch (ops) {
282 .rri_s => Immediate.s(@bitCast(i32, data.rri.i)),
283 .rri_u => Immediate.u(data.rri.i),
284 else => unreachable,
285 };
286 op1 = .{ .reg = data.rri.r1 };
287 op2 = .{ .reg = data.rri.r2 };
288 op3 = .{ .imm = imm };
289 },
290 .m_sib, .lock_m_sib => {
291 const msib = emit.mir.extraData(Mir.MemorySib, data.payload).data;
292 op1 = .{ .mem = Mir.MemorySib.decode(msib) };
293 },
294 .m_rip, .lock_m_rip => {
295 const mrip = emit.mir.extraData(Mir.MemoryRip, data.payload).data;
296 op1 = .{ .mem = Mir.MemoryRip.decode(mrip) };
297 },
298 .mi_sib_s, .mi_sib_u, .lock_mi_sib_s, .lock_mi_sib_u => {
299 const msib = emit.mir.extraData(Mir.MemorySib, data.ix.payload).data;
300 const imm = switch (ops) {
301 .mi_sib_s, .lock_mi_sib_s => Immediate.s(@bitCast(i32, data.ix.i)),
302 .mi_sib_u, .lock_mi_sib_u => Immediate.u(data.ix.i),
303 else => unreachable,
304 };
305 op1 = .{ .mem = Mir.MemorySib.decode(msib) };
306 op2 = .{ .imm = imm };
307 },
308 .mi_rip_u, .mi_rip_s, .lock_mi_rip_u, .lock_mi_rip_s => {
309 const mrip = emit.mir.extraData(Mir.MemoryRip, data.ix.payload).data;
310 const imm = switch (ops) {
311 .mi_rip_s, .lock_mi_rip_s => Immediate.s(@bitCast(i32, data.ix.i)),
312 .mi_rip_u, .lock_mi_rip_u => Immediate.u(data.ix.i),
313 else => unreachable,
314 };
315 op1 = .{ .mem = Mir.MemoryRip.decode(mrip) };
316 op2 = .{ .imm = imm };
317 },
318 .rm_sib, .mr_sib, .lock_mr_sib => {
319 const msib = emit.mir.extraData(Mir.MemorySib, data.rx.payload).data;
320 const op_r = .{ .reg = data.rx.r };
321 const op_m = .{ .mem = Mir.MemorySib.decode(msib) };
322 switch (ops) {
323 .rm_sib => {
324 op1 = op_r;
325 op2 = op_m;
326 },
327 .mr_sib, .lock_mr_sib => {
328 op1 = op_m;
329 op2 = op_r;
330 },
331 else => unreachable,
332 }
333 },
334 .rm_rip, .mr_rip, .lock_mr_rip => {
335 const mrip = emit.mir.extraData(Mir.MemoryRip, data.rx.payload).data;
336 const op_r = .{ .reg = data.rx.r };
337 const op_m = .{ .mem = Mir.MemoryRip.decode(mrip) };
338 switch (ops) {
339 .rm_rip => {
340 op1 = op_r;
341 op2 = op_m;
342 },
343 .mr_rip, .lock_mr_rip => {
344 op1 = op_m;
345 op2 = op_r;
346 },
347 else => unreachable,
348 }
349 },
350 .mrr_sib => {
351 const msib = emit.mir.extraData(Mir.MemorySib, data.rrx.payload).data;
352 op1 = .{ .mem = Mir.MemorySib.decode(msib) };
353 op2 = .{ .reg = data.rrx.r1 };
354 op2 = .{ .reg = data.rrx.r2 };
355 },
356 .mrr_rip => {
357 const mrip = emit.mir.extraData(Mir.MemoryRip, data.rrx.payload).data;
358 op1 = .{ .mem = Mir.MemoryRip.decode(mrip) };
359 op2 = .{ .reg = data.rrx.r1 };
360 op2 = .{ .reg = data.rrx.r2 };
361 },
362 .mri_sib => {
363 const msib = emit.mir.extraData(Mir.MemorySib, data.rix.payload).data;
364 op1 = .{ .mem = Mir.MemorySib.decode(msib) };
365 op2 = .{ .reg = data.rix.r };
366 op3 = .{ .imm = Immediate.u(data.rix.i) };
367 },
368 .mri_rip => {
369 const mrip = emit.mir.extraData(Mir.MemoryRip, data.rix.payload).data;
370 op1 = .{ .mem = Mir.MemoryRip.decode(mrip) };
371 op2 = .{ .reg = data.rix.r };
372 op3 = .{ .imm = Immediate.u(data.rix.i) };
373 },
374 else => return emit.fail("TODO handle generic encoding: {s}, {s}", .{
375 @tagName(mnemonic),
376 @tagName(ops),
377 }),
378 }
379
380 return emit.encode(mnemonic, .{
381 .prefix = prefix,
382 .op1 = op1,
383 .op2 = op2,
384 .op3 = op3,
385 .op4 = op4,
386 });
387}
388
389fn mirString(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void {
390 const ops = emit.mir.instructions.items(.ops)[inst];
391 switch (ops) {
392 .string => {
393 const data = emit.mir.instructions.items(.data)[inst].string;
394 const mnemonic = switch (tag) {
395 inline .cmps, .lods, .movs, .scas, .stos => |comptime_tag| switch (data.width) {
396 inline else => |comptime_width| @field(
397 Instruction.Mnemonic,
398 @tagName(comptime_tag) ++ @tagName(comptime_width),
399 ),
400 },
401 else => unreachable,
402 };
403 return emit.encode(mnemonic, .{ .prefix = switch (data.repeat) {
404 inline else => |comptime_repeat| @field(Instruction.Prefix, @tagName(comptime_repeat)),
405 } });
406 },
407 else => unreachable,
408 }
409}
410
411fn mirCmpxchgBytes(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
412 const ops = emit.mir.instructions.items(.ops)[inst];
413 const data = emit.mir.instructions.items(.data)[inst];
414
415 var op1: Instruction.Operand = .none;
416 switch (ops) {
417 .m_sib, .lock_m_sib => {
418 const sib = emit.mir.extraData(Mir.MemorySib, data.payload).data;
419 op1 = .{ .mem = Mir.MemorySib.decode(sib) };
420 },
421 .m_rip, .lock_m_rip => {
422 const rip = emit.mir.extraData(Mir.MemoryRip, data.payload).data;
423 op1 = .{ .mem = Mir.MemoryRip.decode(rip) };
424 },
425 else => unreachable,
426 }
427
428 const mnemonic: Instruction.Mnemonic = switch (op1.mem.bitSize()) {
429 64 => .cmpxchg8b,
430 128 => .cmpxchg16b,
431 else => unreachable,
432 };
433
434 return emit.encode(mnemonic, .{
435 .prefix = switch (ops) {
436 .m_sib, .m_rip => .none,
437 .lock_m_sib, .lock_m_rip => .lock,
438 else => unreachable,
439 },
440 .op1 = op1,
441 });
442}
443
444fn mirMovMoffs(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
445 const ops = emit.mir.instructions.items(.ops)[inst];
446 const payload = emit.mir.instructions.items(.data)[inst].payload;
447 const moffs = emit.mir.extraData(Mir.MemoryMoffs, payload).data;
448 const seg = @intToEnum(Register, moffs.seg);
449 const offset = moffs.decodeOffset();
450 switch (ops) {
451 .rax_moffs => {
452 try emit.encode(.mov, .{
453 .op1 = .{ .reg = .rax },
454 .op2 = .{ .mem = Memory.moffs(seg, offset) },
455 });
456 },
457 .moffs_rax, .lock_moffs_rax => {
458 try emit.encode(.mov, .{
459 .prefix = switch (ops) {
460 .moffs_rax => .none,
461 .lock_moffs_rax => .lock,
462 else => unreachable,
463 },
464 .op1 = .{ .mem = Memory.moffs(seg, offset) },
465 .op2 = .{ .reg = .rax },
466 });
467 },
468 else => unreachable,
469 }
470}
471
472fn mirMovsx(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
473 const ops = emit.mir.instructions.items(.ops)[inst];
474 const data = emit.mir.instructions.items(.data)[inst];
475
476 var op1: Instruction.Operand = .none;
477 var op2: Instruction.Operand = .none;
478 switch (ops) {
479 .rr => {
480 op1 = .{ .reg = data.rr.r1 };
481 op2 = .{ .reg = data.rr.r2 };
482 },
483 .rm_sib => {
484 const msib = emit.mir.extraData(Mir.MemorySib, data.rx.payload).data;
485 op1 = .{ .reg = data.rx.r };
486 op2 = .{ .mem = Mir.MemorySib.decode(msib) };
487 },
488 .rm_rip => {
489 const mrip = emit.mir.extraData(Mir.MemoryRip, data.rx.payload).data;
490 op1 = .{ .reg = data.rx.r };
491 op2 = .{ .mem = Mir.MemoryRip.decode(mrip) };
492 },
493 else => unreachable, // TODO
494 }
495
496 const mnemonic: Instruction.Mnemonic = switch (op1.bitSize()) {
497 32, 64 => if (op2.bitSize() == 32) .movsxd else .movsx,
498 else => .movsx,
499 };
500
501 return emit.encode(mnemonic, .{
502 .op1 = op1,
503 .op2 = op2,
504 });
505}
506
507fn mnemonicFromConditionCode(comptime basename: []const u8, cc: bits.Condition) Instruction.Mnemonic {
508 return switch (cc) {
509 inline else => |comptime_cc| @field(Instruction.Mnemonic, basename ++ @tagName(comptime_cc)),
510 };
511}
512
513fn mirCmovcc(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
514 const ops = emit.mir.instructions.items(.ops)[inst];
515 switch (ops) {
516 .rr_cc => {
517 const data = emit.mir.instructions.items(.data)[inst].rr_cc;
518 const mnemonic = mnemonicFromConditionCode("cmov", data.cc);
519 return emit.encode(mnemonic, .{
520 .op1 = .{ .reg = data.r1 },
521 .op2 = .{ .reg = data.r2 },
522 });
523 },
524 .rm_sib_cc => {
525 const data = emit.mir.instructions.items(.data)[inst].rx_cc;
526 const extra = emit.mir.extraData(Mir.MemorySib, data.payload).data;
527 const mnemonic = mnemonicFromConditionCode("cmov", data.cc);
528 return emit.encode(mnemonic, .{
529 .op1 = .{ .reg = data.r },
530 .op2 = .{ .mem = Mir.MemorySib.decode(extra) },
531 });
532 },
533 .rm_rip_cc => {
534 const data = emit.mir.instructions.items(.data)[inst].rx_cc;
535 const extra = emit.mir.extraData(Mir.MemoryRip, data.payload).data;
536 const mnemonic = mnemonicFromConditionCode("cmov", data.cc);
537 return emit.encode(mnemonic, .{
538 .op1 = .{ .reg = data.r },
539 .op2 = .{ .mem = Mir.MemoryRip.decode(extra) },
540 });
541 },
542 else => unreachable,
543 }
544}
545
546fn mirSetcc(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
547 const ops = emit.mir.instructions.items(.ops)[inst];
548 switch (ops) {
549 .r_cc => {
550 const data = emit.mir.instructions.items(.data)[inst].r_cc;
551 const mnemonic = mnemonicFromConditionCode("set", data.cc);
552 return emit.encode(mnemonic, .{
553 .op1 = .{ .reg = data.r },
554 });
555 },
556 .m_sib_cc => {
557 const data = emit.mir.instructions.items(.data)[inst].x_cc;
558 const extra = emit.mir.extraData(Mir.MemorySib, data.payload).data;
559 const mnemonic = mnemonicFromConditionCode("set", data.cc);
560 return emit.encode(mnemonic, .{
561 .op1 = .{ .mem = Mir.MemorySib.decode(extra) },
562 });
563 },
564 .m_rip_cc => {
565 const data = emit.mir.instructions.items(.data)[inst].x_cc;
566 const extra = emit.mir.extraData(Mir.MemoryRip, data.payload).data;
567 const mnemonic = mnemonicFromConditionCode("set", data.cc);
568 return emit.encode(mnemonic, .{
569 .op1 = .{ .mem = Mir.MemoryRip.decode(extra) },
570 });
571 },
572 else => unreachable, // TODO
573 }
574}
575
576fn mirJcc(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
577 const ops = emit.mir.instructions.items(.ops)[inst];
578 switch (ops) {
579 .inst_cc => {
580 const data = emit.mir.instructions.items(.data)[inst].inst_cc;
581 const mnemonic = mnemonicFromConditionCode("j", data.cc);
582 const source = emit.code.items.len;
583 try emit.encode(mnemonic, .{
584 .op1 = .{ .imm = Immediate.s(0) },
585 });
586 try emit.relocs.append(emit.bin_file.allocator, .{
587 .source = source,
588 .target = data.inst,
589 .offset = emit.code.items.len - 4,
590 .length = 6,
591 });
592 },
593 else => unreachable, // TODO
594 }
595}
596
597fn mirJmpReloc(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
598 const target = emit.mir.instructions.items(.data)[inst].inst;
599 const source = emit.code.items.len;
600 try emit.encode(.jmp, .{
601 .op1 = .{ .imm = Immediate.s(0) },
602 });
603 try emit.relocs.append(emit.bin_file.allocator, .{
604 .source = source,
605 .target = target,
606 .offset = emit.code.items.len - 4,
607 .length = 5,
608 });
609}
610
611fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
612 const relocation = emit.mir.instructions.items(.data)[inst].relocation;
613
614 const offset = blk: {
615 try emit.encode(.call, .{
616 .op1 = .{ .imm = Immediate.s(0) },
617 });
618 break :blk @intCast(u32, emit.code.items.len) - 4;
619 };
620
621 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
622 // Add relocation to the decl.
623 const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
624 const target = macho_file.getGlobalByIndex(relocation.sym_index);
625 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
626 .type = @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),
627 .target = target,
628 .offset = offset,
629 .addend = 0,
630 .pcrel = true,
631 .length = 2,
632 });
633 } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
634 // Add relocation to the decl.
635 const atom_index = coff_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
636 const target = coff_file.getGlobalByIndex(relocation.sym_index);
637 try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
638 .type = .direct,
639 .target = target,
640 .offset = offset,
641 .addend = 0,
642 .pcrel = true,
643 .length = 2,
644 });
645 } else {
646 return emit.fail("TODO implement call_extern for linking backends different than MachO and COFF", .{});
647 }
648}
649
650fn mirPushPopRegisterList(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void {
651 const payload = emit.mir.instructions.items(.data)[inst].payload;
652 const save_reg_list = emit.mir.extraData(Mir.SaveRegisterList, payload).data;
653 const base = @intToEnum(Register, save_reg_list.base_reg);
654 var disp: i32 = -@intCast(i32, save_reg_list.stack_end);
655 const reg_list = Mir.RegisterList.fromInt(save_reg_list.register_list);
656 const callee_preserved_regs = abi.getCalleePreservedRegs(emit.target.*);
657 for (callee_preserved_regs) |reg| {
658 if (reg_list.isSet(callee_preserved_regs, reg)) {
659 const op1: Instruction.Operand = .{ .mem = Memory.sib(.qword, .{
660 .base = base,
661 .disp = disp,
662 }) };
663 const op2: Instruction.Operand = .{ .reg = reg };
664 switch (tag) {
665 .push => try emit.encode(.mov, .{
666 .op1 = op1,
667 .op2 = op2,
668 }),
669 .pop => try emit.encode(.mov, .{
670 .op1 = op2,
671 .op2 = op1,
672 }),
673 else => unreachable,
674 }
675 disp += 8;
676 }
677 }
678}
679
680fn mirLeaLinker(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
681 const ops = emit.mir.instructions.items(.ops)[inst];
682 const payload = emit.mir.instructions.items(.data)[inst].payload;
683 const metadata = emit.mir.extraData(Mir.LeaRegisterReloc, payload).data;
684 const reg = @intToEnum(Register, metadata.reg);
685
686 try emit.encode(.lea, .{
687 .op1 = .{ .reg = reg },
688 .op2 = .{ .mem = Memory.rip(Memory.PtrSize.fromBitSize(reg.bitSize()), 0) },
689 });
690
691 const end_offset = emit.code.items.len;
692
693 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
694 const reloc_type = switch (ops) {
695 .got_reloc => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_GOT),
696 .direct_reloc => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_SIGNED),
697 else => unreachable,
698 };
699 const atom_index = macho_file.getAtomIndexForSymbol(.{
700 .sym_index = metadata.atom_index,
701 .file = null,
702 }).?;
703 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
704 .type = reloc_type,
705 .target = .{ .sym_index = metadata.sym_index, .file = null },
706 .offset = @intCast(u32, end_offset - 4),
707 .addend = 0,
708 .pcrel = true,
709 .length = 2,
710 });
711 } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
712 const atom_index = coff_file.getAtomIndexForSymbol(.{
713 .sym_index = metadata.atom_index,
714 .file = null,
715 }).?;
716 try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
717 .type = switch (ops) {
718 .got_reloc => .got,
719 .direct_reloc => .direct,
720 .import_reloc => .import,
721 else => unreachable,
722 },
723 .target = switch (ops) {
724 .got_reloc, .direct_reloc => .{ .sym_index = metadata.sym_index, .file = null },
725 .import_reloc => coff_file.getGlobalByIndex(metadata.sym_index),
726 else => unreachable,
727 },
728 .offset = @intCast(u32, end_offset - 4),
729 .addend = 0,
730 .pcrel = true,
731 .length = 2,
732 });
733 } else {
734 return emit.fail("TODO implement lea reg, [rip + reloc] for linking backends different than MachO", .{});
735 }
736}
737
738fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
739 const payload = emit.mir.instructions.items(.data)[inst].payload;
740 const dbg_line_column = emit.mir.extraData(Mir.DbgLineColumn, payload).data;
741 log.debug("mirDbgLine", .{});
742 try emit.dbgAdvancePCAndLine(dbg_line_column.line, dbg_line_column.column);
743}
744
745fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) InnerError!void {
198fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void {
746199 const delta_line = @intCast(i32, line) - @intCast(i32, emit.prev_di_line);
747200 const delta_pc: usize = emit.code.items.len - emit.prev_di_pc;
748201 log.debug(" (advance pc={d} and line={d})", .{ delta_line, delta_pc });
......@@ -756,7 +209,7 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) InnerError!void {
756209 .plan9 => |dbg_out| {
757210 if (delta_pc <= 0) return; // only do this when the pc changes
758211 // we have already checked the target in the linker to make sure it is compatable
759 const quant = @import("../../link/Plan9/aout.zig").getPCQuant(emit.target.cpu.arch) catch unreachable;
212 const quant = @import("../../link/Plan9/aout.zig").getPCQuant(emit.lower.target.cpu.arch) catch unreachable;
760213
761214 // increasing the line number
762215 try @import("../../link/Plan9.zig").changeLine(dbg_out.dbg_line, delta_line);
......@@ -792,34 +245,12 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) InnerError!void {
792245 }
793246}
794247
795fn mirDbgPrologueEnd(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
796 _ = inst;
797 switch (emit.debug_output) {
798 .dwarf => |dw| {
799 try dw.setPrologueEnd();
800 log.debug("mirDbgPrologueEnd (line={d}, col={d})", .{
801 emit.prev_di_line,
802 emit.prev_di_column,
803 });
804 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
805 },
806 .plan9 => {},
807 .none => {},
808 }
809}
248const link = @import("../../link.zig");
249const log = std.log.scoped(.emit);
250const mem = std.mem;
251const std = @import("std");
810252
811fn mirDbgEpilogueBegin(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
812 _ = inst;
813 switch (emit.debug_output) {
814 .dwarf => |dw| {
815 try dw.setEpilogueBegin();
816 log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{
817 emit.prev_di_line,
818 emit.prev_di_column,
819 });
820 try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
821 },
822 .plan9 => {},
823 .none => {},
824 }
825}
253const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput;
254const Emit = @This();
255const Lower = @import("Lower.zig");
256const Mir = @import("Mir.zig");
src/arch/x86_64/Encoding.zig+137-157
......@@ -7,30 +7,32 @@ const math = std.math;
77const bits = @import("bits.zig");
88const encoder = @import("encoder.zig");
99const Instruction = encoder.Instruction;
10const Operand = Instruction.Operand;
11const Prefix = Instruction.Prefix;
1012const Register = bits.Register;
1113const Rex = encoder.Rex;
1214const LegacyPrefixes = encoder.LegacyPrefixes;
1315
14const table = @import("encodings.zig").table;
15
1616mnemonic: Mnemonic,
17op_en: OpEn,
18op1: Op,
19op2: Op,
20op3: Op,
21op4: Op,
22opc_len: u3,
23opc: [7]u8,
24modrm_ext: u3,
25mode: Mode,
26
27pub fn findByMnemonic(mnemonic: Mnemonic, args: Instruction.Init) !?Encoding {
28 const input_op1 = Op.fromOperand(args.op1);
29 const input_op2 = Op.fromOperand(args.op2);
30 const input_op3 = Op.fromOperand(args.op3);
31 const input_op4 = Op.fromOperand(args.op4);
32
33 const ops = &[_]Instruction.Operand{ args.op1, args.op2, args.op3, args.op4 };
17data: Data,
18
19const Data = struct {
20 op_en: OpEn,
21 ops: [4]Op,
22 opc_len: u3,
23 opc: [7]u8,
24 modrm_ext: u3,
25 mode: Mode,
26};
27
28pub fn findByMnemonic(
29 prefix: Instruction.Prefix,
30 mnemonic: Mnemonic,
31 ops: []const Instruction.Operand,
32) !?Encoding {
33 var input_ops = [1]Op{.none} ** 4;
34 for (input_ops[0..ops.len], ops) |*input_op, op| input_op.* = Op.fromOperand(op);
35
3436 const rex_required = for (ops) |op| switch (op) {
3537 .reg => |r| switch (r) {
3638 .spl, .bpl, .sil, .dil => break true,
......@@ -60,88 +62,29 @@ pub fn findByMnemonic(mnemonic: Mnemonic, args: Instruction.Init) !?Encoding {
6062
6163 if ((rex_required or rex_extended) and rex_invalid) return error.CannotEncode;
6264
63 // TODO work out what is the maximum number of variants we can actually find in one swoop.
64 var candidates: [10]Encoding = undefined;
65 var count: usize = 0;
66 for (table) |entry| {
67 var enc = Encoding{
68 .mnemonic = entry[0],
69 .op_en = entry[1],
70 .op1 = entry[2],
71 .op2 = entry[3],
72 .op3 = entry[4],
73 .op4 = entry[5],
74 .opc_len = @intCast(u3, entry[6].len),
75 .opc = undefined,
76 .modrm_ext = entry[7],
77 .mode = entry[8],
78 };
79 std.mem.copy(u8, &enc.opc, entry[6]);
80 if (enc.mnemonic == mnemonic and
81 input_op1.isSubset(enc.op1, enc.mode) and
82 input_op2.isSubset(enc.op2, enc.mode) and
83 input_op3.isSubset(enc.op3, enc.mode) and
84 input_op4.isSubset(enc.op4, enc.mode))
85 {
86 if (rex_required) {
87 switch (enc.mode) {
88 .rex, .long => {
89 candidates[count] = enc;
90 count += 1;
91 },
92 else => {},
93 }
94 } else {
95 if (enc.mode != .rex) {
96 candidates[count] = enc;
97 count += 1;
98 }
99 }
65 var shortest_enc: ?Encoding = null;
66 var shortest_len: ?usize = null;
67 next: for (mnemonic_to_encodings_map[@enumToInt(mnemonic)]) |data| {
68 switch (data.mode) {
69 .rex => if (!rex_required) continue,
70 .long => {},
71 else => if (rex_required) continue,
10072 }
73 for (input_ops, data.ops) |input_op, data_op|
74 if (!input_op.isSubset(data_op, data.mode)) continue :next;
75
76 const enc = Encoding{ .mnemonic = mnemonic, .data = data };
77 if (shortest_enc) |previous_shortest_enc| {
78 const len = estimateInstructionLength(prefix, enc, ops);
79 const previous_shortest_len = shortest_len orelse
80 estimateInstructionLength(prefix, previous_shortest_enc, ops);
81 if (len < previous_shortest_len) {
82 shortest_enc = enc;
83 shortest_len = len;
84 } else shortest_len = previous_shortest_len;
85 } else shortest_enc = enc;
10186 }
102
103 if (count == 0) return null;
104 if (count == 1) return candidates[0];
105
106 const EncodingLength = struct {
107 fn estimate(encoding: Encoding, params: Instruction.Init) usize {
108 var inst = Instruction{
109 .op1 = params.op1,
110 .op2 = params.op2,
111 .op3 = params.op3,
112 .op4 = params.op4,
113 .prefix = params.prefix,
114 .encoding = encoding,
115 };
116 var cwriter = std.io.countingWriter(std.io.null_writer);
117 inst.encode(cwriter.writer()) catch unreachable; // Not allowed to fail here unless OOM.
118 return @intCast(usize, cwriter.bytes_written);
119 }
120 };
121
122 var shortest_encoding: ?struct {
123 index: usize,
124 len: usize,
125 } = null;
126 var i: usize = 0;
127 while (i < count) : (i += 1) {
128 const candidate = candidates[i];
129 switch (candidate.mode) {
130 .long, .rex => if (rex_invalid) return error.CannotEncode,
131 else => {},
132 }
133
134 const len = EncodingLength.estimate(candidate, args);
135 const current = shortest_encoding orelse {
136 shortest_encoding = .{ .index = i, .len = len };
137 continue;
138 };
139 if (len < current.len) {
140 shortest_encoding = .{ .index = i, .len = len };
141 }
142 }
143
144 return candidates[shortest_encoding.?.index];
87 return shortest_enc;
14588}
14689
14790/// Returns first matching encoding by opcode.
......@@ -149,57 +92,45 @@ pub fn findByOpcode(opc: []const u8, prefixes: struct {
14992 legacy: LegacyPrefixes,
15093 rex: Rex,
15194}, modrm_ext: ?u3) ?Encoding {
152 for (table) |entry| {
153 const enc = Encoding{
154 .mnemonic = entry[0],
155 .op_en = entry[1],
156 .op1 = entry[2],
157 .op2 = entry[3],
158 .op3 = entry[4],
159 .op4 = entry[5],
160 .opc_len = entry[6],
161 .opc = .{ entry[7], entry[8], entry[9] },
162 .modrm_ext = entry[10],
163 .mode = entry[11],
164 };
165 const match = match: {
166 if (modrm_ext) |ext| {
167 break :match ext == enc.modrm_ext and std.mem.eql(u8, enc.opcode(), opc);
95 for (mnemonic_to_encodings_map, 0..) |encs, mnemonic_int| for (encs) |data| {
96 const enc = Encoding{ .mnemonic = @intToEnum(Mnemonic, mnemonic_int), .data = data };
97 if (modrm_ext) |ext| if (ext != data.modrm_ext) continue;
98 if (!std.mem.eql(u8, opc, enc.opcode())) continue;
99 if (prefixes.rex.w) {
100 switch (data.mode) {
101 .short, .fpu, .sse, .sse2, .sse4_1, .none => continue,
102 .long, .rex => {},
168103 }
169 break :match std.mem.eql(u8, enc.opcode(), opc);
170 };
171 if (match) {
172 if (prefixes.rex.w) {
173 switch (enc.mode) {
174 .fpu, .sse, .sse2, .sse4_1, .none => {},
175 .long, .rex => return enc,
176 }
177 } else if (prefixes.rex.present and !prefixes.rex.isSet()) {
178 if (enc.mode == .rex) return enc;
179 } else if (prefixes.legacy.prefix_66) {
180 switch (enc.operandBitSize()) {
181 16 => return enc,
104 } else if (prefixes.rex.present and !prefixes.rex.isSet()) {
105 switch (data.mode) {
106 .rex => {},
107 else => continue,
108 }
109 } else if (prefixes.legacy.prefix_66) {
110 switch (enc.operandBitSize()) {
111 16 => {},
112 else => continue,
113 }
114 } else {
115 switch (data.mode) {
116 .none => switch (enc.operandBitSize()) {
117 16 => continue,
182118 else => {},
183 }
184 } else {
185 if (enc.mode == .none) {
186 switch (enc.operandBitSize()) {
187 16 => {},
188 else => return enc,
189 }
190 }
119 },
120 else => continue,
191121 }
192122 }
193 }
123 return enc;
124 };
194125 return null;
195126}
196127
197128pub fn opcode(encoding: *const Encoding) []const u8 {
198 return encoding.opc[0..encoding.opc_len];
129 return encoding.data.opc[0..encoding.data.opc_len];
199130}
200131
201132pub fn mandatoryPrefix(encoding: *const Encoding) ?u8 {
202 const prefix = encoding.opc[0];
133 const prefix = encoding.data.opc[0];
203134 return switch (prefix) {
204135 0x66, 0xf2, 0xf3 => prefix,
205136 else => null,
......@@ -207,27 +138,27 @@ pub fn mandatoryPrefix(encoding: *const Encoding) ?u8 {
207138}
208139
209140pub fn modRmExt(encoding: Encoding) u3 {
210 return switch (encoding.op_en) {
211 .m, .mi, .m1, .mc => encoding.modrm_ext,
141 return switch (encoding.data.op_en) {
142 .m, .mi, .m1, .mc => encoding.data.modrm_ext,
212143 else => unreachable,
213144 };
214145}
215146
216147pub fn operandBitSize(encoding: Encoding) u64 {
217 switch (encoding.mode) {
148 switch (encoding.data.mode) {
218149 .short => return 16,
219150 .long => return 64,
220151 else => {},
221152 }
222 const bit_size: u64 = switch (encoding.op_en) {
223 .np => switch (encoding.op1) {
153 const bit_size: u64 = switch (encoding.data.op_en) {
154 .np => switch (encoding.data.ops[0]) {
224155 .o16 => 16,
225156 .o32 => 32,
226157 .o64 => 64,
227158 else => 32,
228159 },
229 .td => encoding.op2.bitSize(),
230 else => encoding.op1.bitSize(),
160 .td => encoding.data.ops[1].bitSize(),
161 else => encoding.data.ops[0].bitSize(),
231162 };
232163 return bit_size;
233164}
......@@ -240,7 +171,7 @@ pub fn format(
240171) !void {
241172 _ = options;
242173 _ = fmt;
243 switch (encoding.mode) {
174 switch (encoding.data.mode) {
244175 .long => try writer.writeAll("REX.W + "),
245176 else => {},
246177 }
......@@ -249,10 +180,10 @@ pub fn format(
249180 try writer.print("{x:0>2} ", .{byte});
250181 }
251182
252 switch (encoding.op_en) {
183 switch (encoding.data.op_en) {
253184 .np, .fd, .td, .i, .zi, .d => {},
254185 .o, .oi => {
255 const tag = switch (encoding.op1) {
186 const tag = switch (encoding.data.ops[0]) {
256187 .r8 => "rb",
257188 .r16 => "rw",
258189 .r32 => "rd",
......@@ -265,12 +196,12 @@ pub fn format(
265196 .mr, .rm, .rmi, .mri, .mrc => try writer.writeAll("/r "),
266197 }
267198
268 switch (encoding.op_en) {
199 switch (encoding.data.op_en) {
269200 .i, .d, .zi, .oi, .mi, .rmi, .mri => {
270 const op = switch (encoding.op_en) {
271 .i, .d => encoding.op1,
272 .zi, .oi, .mi => encoding.op2,
273 .rmi, .mri => encoding.op3,
201 const op = switch (encoding.data.op_en) {
202 .i, .d => encoding.data.ops[0],
203 .zi, .oi, .mi => encoding.data.ops[1],
204 .rmi, .mri => encoding.data.ops[2],
274205 else => unreachable,
275206 };
276207 const tag = switch (op) {
......@@ -290,13 +221,12 @@ pub fn format(
290221
291222 try writer.print("{s} ", .{@tagName(encoding.mnemonic)});
292223
293 const ops = &[_]Op{ encoding.op1, encoding.op2, encoding.op3, encoding.op4 };
294 for (ops) |op| switch (op) {
224 for (encoding.data.ops) |op| switch (op) {
295225 .none, .o16, .o32, .o64 => break,
296226 else => try writer.print("{s} ", .{@tagName(op)}),
297227 };
298228
299 const op_en = switch (encoding.op_en) {
229 const op_en = switch (encoding.data.op_en) {
300230 .zi => .i,
301231 else => |op_en| op_en,
302232 };
......@@ -604,3 +534,53 @@ pub const Mode = enum {
604534 sse2,
605535 sse4_1,
606536};
537
538fn estimateInstructionLength(prefix: Prefix, encoding: Encoding, ops: []const Operand) usize {
539 var inst = Instruction{
540 .prefix = prefix,
541 .encoding = encoding,
542 .ops = [1]Operand{.none} ** 4,
543 };
544 std.mem.copy(Operand, &inst.ops, ops);
545
546 var cwriter = std.io.countingWriter(std.io.null_writer);
547 inst.encode(cwriter.writer()) catch unreachable; // Not allowed to fail here unless OOM.
548 return @intCast(usize, cwriter.bytes_written);
549}
550
551const mnemonic_to_encodings_map = init: {
552 @setEvalBranchQuota(100_000);
553 const encodings = @import("encodings.zig");
554 var entries = encodings.table;
555 std.sort.sort(encodings.Entry, &entries, {}, struct {
556 fn lessThan(_: void, lhs: encodings.Entry, rhs: encodings.Entry) bool {
557 return @enumToInt(lhs[0]) < @enumToInt(rhs[0]);
558 }
559 }.lessThan);
560 var data_storage: [entries.len]Data = undefined;
561 var mnemonic_map: [@typeInfo(Mnemonic).Enum.fields.len][]const Data = undefined;
562 var mnemonic_int = 0;
563 var mnemonic_start = 0;
564 for (&data_storage, entries, 0..) |*data, entry, data_index| {
565 data.* = .{
566 .op_en = entry[1],
567 .ops = undefined,
568 .opc_len = entry[3].len,
569 .opc = undefined,
570 .modrm_ext = entry[4],
571 .mode = entry[5],
572 };
573 std.mem.copy(Op, &data.ops, entry[2]);
574 std.mem.copy(u8, &data.opc, entry[3]);
575
576 while (mnemonic_int < @enumToInt(entry[0])) : (mnemonic_int += 1) {
577 mnemonic_map[mnemonic_int] = data_storage[mnemonic_start..data_index];
578 mnemonic_start = data_index;
579 }
580 }
581 while (mnemonic_int < mnemonic_map.len) : (mnemonic_int += 1) {
582 mnemonic_map[mnemonic_int] = data_storage[mnemonic_start..];
583 mnemonic_start = data_storage.len;
584 }
585 break :init mnemonic_map;
586};
src/arch/x86_64/Lower.zig created+465
......@@ -0,0 +1,465 @@
1//! This file contains the functionality for lowering x86_64 MIR to Instructions
2
3allocator: Allocator,
4mir: Mir,
5target: *const std.Target,
6err_msg: ?*ErrorMsg = null,
7src_loc: Module.SrcLoc,
8result: [
9 std.mem.max(usize, &.{
10 abi.Win64.callee_preserved_regs.len,
11 abi.SysV.callee_preserved_regs.len,
12 })
13]Instruction = undefined,
14result_len: usize = undefined,
15
16pub const Error = error{
17 OutOfMemory,
18 LowerFail,
19 InvalidInstruction,
20 CannotEncode,
21};
22
23/// The returned slice is overwritten by the next call to lowerMir.
24pub fn lowerMir(lower: *Lower, inst: Mir.Inst) Error![]const Instruction {
25 lower.result = undefined;
26 errdefer lower.result = undefined;
27 lower.result_len = 0;
28 defer lower.result_len = undefined;
29
30 switch (inst.tag) {
31 .adc,
32 .add,
33 .@"and",
34 .bsf,
35 .bsr,
36 .bswap,
37 .bt,
38 .btc,
39 .btr,
40 .bts,
41 .call,
42 .cbw,
43 .cwde,
44 .cdqe,
45 .cwd,
46 .cdq,
47 .cqo,
48 .cmp,
49 .cmpxchg,
50 .div,
51 .fisttp,
52 .fld,
53 .idiv,
54 .imul,
55 .int3,
56 .jmp,
57 .lea,
58 .lfence,
59 .lzcnt,
60 .mfence,
61 .mov,
62 .movbe,
63 .movzx,
64 .mul,
65 .neg,
66 .nop,
67 .not,
68 .@"or",
69 .pop,
70 .popcnt,
71 .push,
72 .rcl,
73 .rcr,
74 .ret,
75 .rol,
76 .ror,
77 .sal,
78 .sar,
79 .sbb,
80 .sfence,
81 .shl,
82 .shld,
83 .shr,
84 .shrd,
85 .sub,
86 .syscall,
87 .@"test",
88 .tzcnt,
89 .ud2,
90 .xadd,
91 .xchg,
92 .xor,
93
94 .addss,
95 .cmpss,
96 .divss,
97 .maxss,
98 .minss,
99 .movss,
100 .mulss,
101 .roundss,
102 .subss,
103 .ucomiss,
104 .addsd,
105 .cmpsd,
106 .divsd,
107 .maxsd,
108 .minsd,
109 .movsd,
110 .mulsd,
111 .roundsd,
112 .subsd,
113 .ucomisd,
114 => try lower.mirGeneric(inst),
115
116 .cmps,
117 .lods,
118 .movs,
119 .scas,
120 .stos,
121 => try lower.mirString(inst),
122
123 .cmpxchgb => try lower.mirCmpxchgBytes(inst),
124
125 .jmp_reloc => try lower.emit(.none, .jmp, &.{.{ .imm = Immediate.s(0) }}),
126
127 .call_extern => try lower.emit(.none, .call, &.{.{ .imm = Immediate.s(0) }}),
128
129 .lea_linker => try lower.mirLeaLinker(inst),
130
131 .mov_moffs => try lower.mirMovMoffs(inst),
132
133 .movsx => try lower.mirMovsx(inst),
134 .cmovcc => try lower.mirCmovcc(inst),
135 .setcc => try lower.mirSetcc(inst),
136 .jcc => try lower.emit(.none, mnem_cc(.j, inst.data.inst_cc.cc), &.{.{ .imm = Immediate.s(0) }}),
137
138 .push_regs, .pop_regs => try lower.mirPushPopRegisterList(inst),
139
140 .dbg_line,
141 .dbg_prologue_end,
142 .dbg_epilogue_begin,
143 .dead,
144 => {},
145 }
146
147 return lower.result[0..lower.result_len];
148}
149
150pub fn fail(lower: *Lower, comptime format: []const u8, args: anytype) Error {
151 @setCold(true);
152 assert(lower.err_msg == null);
153 lower.err_msg = try ErrorMsg.create(lower.allocator, lower.src_loc, format, args);
154 return error.LowerFail;
155}
156
157fn mnem_cc(comptime base: @Type(.EnumLiteral), cc: bits.Condition) Mnemonic {
158 return switch (cc) {
159 inline else => |c| @field(Mnemonic, @tagName(base) ++ @tagName(c)),
160 };
161}
162
163fn imm(lower: Lower, ops: Mir.Inst.Ops, i: u32) Immediate {
164 return switch (ops) {
165 .rri_s,
166 .ri_s,
167 .i_s,
168 .mi_sib_s,
169 .mi_rip_s,
170 .lock_mi_sib_s,
171 .lock_mi_rip_s,
172 => Immediate.s(@bitCast(i32, i)),
173
174 .rri_u,
175 .ri_u,
176 .i_u,
177 .mi_sib_u,
178 .mi_rip_u,
179 .lock_mi_sib_u,
180 .lock_mi_rip_u,
181 .mri_sib,
182 .mri_rip,
183 => Immediate.u(i),
184
185 .ri64 => Immediate.u(lower.mir.extraData(Mir.Imm64, i).data.decode()),
186
187 else => unreachable,
188 };
189}
190
191fn mem(lower: Lower, ops: Mir.Inst.Ops, payload: u32) Memory {
192 return switch (ops) {
193 .rm_sib,
194 .rm_sib_cc,
195 .m_sib,
196 .m_sib_cc,
197 .mi_sib_u,
198 .mi_sib_s,
199 .mr_sib,
200 .mrr_sib,
201 .mri_sib,
202 .lock_m_sib,
203 .lock_mi_sib_u,
204 .lock_mi_sib_s,
205 .lock_mr_sib,
206 => lower.mir.extraData(Mir.MemorySib, payload).data.decode(),
207
208 .rm_rip,
209 .rm_rip_cc,
210 .m_rip,
211 .m_rip_cc,
212 .mi_rip_u,
213 .mi_rip_s,
214 .mr_rip,
215 .mrr_rip,
216 .mri_rip,
217 .lock_m_rip,
218 .lock_mi_rip_u,
219 .lock_mi_rip_s,
220 .lock_mr_rip,
221 => lower.mir.extraData(Mir.MemoryRip, payload).data.decode(),
222
223 .rax_moffs,
224 .moffs_rax,
225 .lock_moffs_rax,
226 => lower.mir.extraData(Mir.MemoryMoffs, payload).data.decode(),
227
228 else => unreachable,
229 };
230}
231
232fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void {
233 lower.result[lower.result_len] = try Instruction.new(prefix, mnemonic, ops);
234 lower.result_len += 1;
235}
236
237fn mirGeneric(lower: *Lower, inst: Mir.Inst) Error!void {
238 try lower.emit(switch (inst.ops) {
239 else => .none,
240 .lock_m_sib,
241 .lock_m_rip,
242 .lock_mi_sib_u,
243 .lock_mi_rip_u,
244 .lock_mi_sib_s,
245 .lock_mi_rip_s,
246 .lock_mr_sib,
247 .lock_mr_rip,
248 .lock_moffs_rax,
249 => .lock,
250 }, switch (inst.tag) {
251 inline else => |tag| if (@hasField(Mnemonic, @tagName(tag)))
252 @field(Mnemonic, @tagName(tag))
253 else
254 unreachable,
255 }, switch (inst.ops) {
256 .none => &.{},
257 .i_s, .i_u => &.{
258 .{ .imm = lower.imm(inst.ops, inst.data.i) },
259 },
260 .r => &.{
261 .{ .reg = inst.data.r },
262 },
263 .rr => &.{
264 .{ .reg = inst.data.rr.r1 },
265 .{ .reg = inst.data.rr.r2 },
266 },
267 .rrr => &.{
268 .{ .reg = inst.data.rrr.r1 },
269 .{ .reg = inst.data.rrr.r2 },
270 .{ .reg = inst.data.rrr.r3 },
271 },
272 .ri_s, .ri_u => &.{
273 .{ .reg = inst.data.ri.r },
274 .{ .imm = lower.imm(inst.ops, inst.data.ri.i) },
275 },
276 .ri64 => &.{
277 .{ .reg = inst.data.rx.r },
278 .{ .imm = lower.imm(inst.ops, inst.data.rx.payload) },
279 },
280 .rri_s, .rri_u => &.{
281 .{ .reg = inst.data.rri.r1 },
282 .{ .reg = inst.data.rri.r2 },
283 .{ .imm = lower.imm(inst.ops, inst.data.rri.i) },
284 },
285 .m_sib, .lock_m_sib, .m_rip, .lock_m_rip => &.{
286 .{ .mem = lower.mem(inst.ops, inst.data.payload) },
287 },
288 .mi_sib_s,
289 .lock_mi_sib_s,
290 .mi_sib_u,
291 .lock_mi_sib_u,
292 .mi_rip_u,
293 .lock_mi_rip_u,
294 .mi_rip_s,
295 .lock_mi_rip_s,
296 => &.{
297 .{ .mem = lower.mem(inst.ops, inst.data.ix.payload) },
298 .{ .imm = lower.imm(inst.ops, inst.data.ix.i) },
299 },
300 .rm_sib, .rm_rip => &.{
301 .{ .reg = inst.data.rx.r },
302 .{ .mem = lower.mem(inst.ops, inst.data.rx.payload) },
303 },
304 .mr_sib, .lock_mr_sib, .mr_rip, .lock_mr_rip => &.{
305 .{ .mem = lower.mem(inst.ops, inst.data.rx.payload) },
306 .{ .reg = inst.data.rx.r },
307 },
308 .mrr_sib, .mrr_rip => &.{
309 .{ .mem = lower.mem(inst.ops, inst.data.rrx.payload) },
310 .{ .reg = inst.data.rrx.r1 },
311 .{ .reg = inst.data.rrx.r2 },
312 },
313 .mri_sib, .mri_rip => &.{
314 .{ .mem = lower.mem(inst.ops, inst.data.rix.payload) },
315 .{ .reg = inst.data.rix.r },
316 .{ .imm = lower.imm(inst.ops, inst.data.rix.i) },
317 },
318 else => return lower.fail("TODO lower {s} {s}", .{ @tagName(inst.tag), @tagName(inst.ops) }),
319 });
320}
321
322fn mirString(lower: *Lower, inst: Mir.Inst) Error!void {
323 switch (inst.ops) {
324 .string => try lower.emit(switch (inst.data.string.repeat) {
325 inline else => |repeat| @field(Prefix, @tagName(repeat)),
326 }, switch (inst.tag) {
327 inline .cmps, .lods, .movs, .scas, .stos => |tag| switch (inst.data.string.width) {
328 inline else => |width| @field(Mnemonic, @tagName(tag) ++ @tagName(width)),
329 },
330 else => unreachable,
331 }, &.{}),
332 else => return lower.fail("TODO lower {s} {s}", .{ @tagName(inst.tag), @tagName(inst.ops) }),
333 }
334}
335
336fn mirCmpxchgBytes(lower: *Lower, inst: Mir.Inst) Error!void {
337 const ops: [1]Operand = switch (inst.ops) {
338 .m_sib, .lock_m_sib, .m_rip, .lock_m_rip => .{
339 .{ .mem = lower.mem(inst.ops, inst.data.payload) },
340 },
341 else => return lower.fail("TODO lower {s} {s}", .{ @tagName(inst.tag), @tagName(inst.ops) }),
342 };
343 try lower.emit(switch (inst.ops) {
344 .m_sib, .m_rip => .none,
345 .lock_m_sib, .lock_m_rip => .lock,
346 else => unreachable,
347 }, switch (@divExact(ops[0].bitSize(), 8)) {
348 8 => .cmpxchg8b,
349 16 => .cmpxchg16b,
350 else => return lower.fail("invalid operand for {s}", .{@tagName(inst.tag)}),
351 }, &ops);
352}
353
354fn mirMovMoffs(lower: *Lower, inst: Mir.Inst) Error!void {
355 try lower.emit(switch (inst.ops) {
356 .rax_moffs, .moffs_rax => .none,
357 .lock_moffs_rax => .lock,
358 else => return lower.fail("TODO lower {s} {s}", .{ @tagName(inst.tag), @tagName(inst.ops) }),
359 }, .mov, switch (inst.ops) {
360 .rax_moffs => &.{
361 .{ .reg = .rax },
362 .{ .mem = lower.mem(inst.ops, inst.data.payload) },
363 },
364 .moffs_rax, .lock_moffs_rax => &.{
365 .{ .mem = lower.mem(inst.ops, inst.data.payload) },
366 .{ .reg = .rax },
367 },
368 else => unreachable,
369 });
370}
371
372fn mirMovsx(lower: *Lower, inst: Mir.Inst) Error!void {
373 const ops: [2]Operand = switch (inst.ops) {
374 .rr => .{
375 .{ .reg = inst.data.rr.r1 },
376 .{ .reg = inst.data.rr.r2 },
377 },
378 .rm_sib, .rm_rip => .{
379 .{ .reg = inst.data.rx.r },
380 .{ .mem = lower.mem(inst.ops, inst.data.rx.payload) },
381 },
382 else => return lower.fail("TODO lower {s} {s}", .{ @tagName(inst.tag), @tagName(inst.ops) }),
383 };
384 try lower.emit(.none, switch (ops[0].bitSize()) {
385 32, 64 => switch (ops[1].bitSize()) {
386 32 => .movsxd,
387 else => .movsx,
388 },
389 else => .movsx,
390 }, &ops);
391}
392
393fn mirCmovcc(lower: *Lower, inst: Mir.Inst) Error!void {
394 switch (inst.ops) {
395 .rr_cc => try lower.emit(.none, mnem_cc(.cmov, inst.data.rr_cc.cc), &.{
396 .{ .reg = inst.data.rr_cc.r1 },
397 .{ .reg = inst.data.rr_cc.r2 },
398 }),
399 .rm_sib_cc, .rm_rip_cc => try lower.emit(.none, mnem_cc(.cmov, inst.data.rx_cc.cc), &.{
400 .{ .reg = inst.data.rx_cc.r },
401 .{ .mem = lower.mem(inst.ops, inst.data.rx_cc.payload) },
402 }),
403 else => return lower.fail("TODO lower {s} {s}", .{ @tagName(inst.tag), @tagName(inst.ops) }),
404 }
405}
406
407fn mirSetcc(lower: *Lower, inst: Mir.Inst) Error!void {
408 switch (inst.ops) {
409 .r_cc => try lower.emit(.none, mnem_cc(.set, inst.data.r_cc.cc), &.{
410 .{ .reg = inst.data.r_cc.r },
411 }),
412 .m_sib_cc, .m_rip_cc => try lower.emit(.none, mnem_cc(.set, inst.data.x_cc.cc), &.{
413 .{ .mem = lower.mem(inst.ops, inst.data.x_cc.payload) },
414 }),
415 else => return lower.fail("TODO lower {s} {s}", .{ @tagName(inst.tag), @tagName(inst.ops) }),
416 }
417}
418
419fn mirPushPopRegisterList(lower: *Lower, inst: Mir.Inst) Error!void {
420 const save_reg_list = lower.mir.extraData(Mir.SaveRegisterList, inst.data.payload).data;
421 const base = @intToEnum(Register, save_reg_list.base_reg);
422 var disp: i32 = -@intCast(i32, save_reg_list.stack_end);
423 const reg_list = Mir.RegisterList.fromInt(save_reg_list.register_list);
424 const callee_preserved_regs = abi.getCalleePreservedRegs(lower.target.*);
425 for (callee_preserved_regs) |callee_preserved_reg| {
426 if (!reg_list.isSet(callee_preserved_regs, callee_preserved_reg)) continue;
427 const reg_op = Operand{ .reg = callee_preserved_reg };
428 const mem_op = Operand{ .mem = Memory.sib(.qword, .{ .base = base, .disp = disp }) };
429 try lower.emit(.none, .mov, switch (inst.tag) {
430 .push_regs => &.{ mem_op, reg_op },
431 .pop_regs => &.{ reg_op, mem_op },
432 else => unreachable,
433 });
434 disp += 8;
435 }
436}
437
438fn mirLeaLinker(lower: *Lower, inst: Mir.Inst) Error!void {
439 const metadata = lower.mir.extraData(Mir.LeaRegisterReloc, inst.data.payload).data;
440 const reg = @intToEnum(Register, metadata.reg);
441 try lower.emit(.none, .lea, &.{
442 .{ .reg = reg },
443 .{ .mem = Memory.rip(Memory.PtrSize.fromBitSize(reg.bitSize()), 0) },
444 });
445}
446
447const abi = @import("abi.zig");
448const assert = std.debug.assert;
449const bits = @import("bits.zig");
450const encoder = @import("encoder.zig");
451const std = @import("std");
452
453const Air = @import("../../Air.zig");
454const Allocator = std.mem.Allocator;
455const ErrorMsg = Module.ErrorMsg;
456const Immediate = bits.Immediate;
457const Instruction = encoder.Instruction;
458const Lower = @This();
459const Memory = bits.Memory;
460const Mir = @import("Mir.zig");
461const Mnemonic = Instruction.Mnemonic;
462const Module = @import("../../Module.zig");
463const Operand = Instruction.Operand;
464const Prefix = Instruction.Prefix;
465const Register = bits.Register;
src/arch/x86_64/Mir.zig+11-8
......@@ -655,16 +655,19 @@ pub const MemoryMoffs = struct {
655655 msb: u32,
656656 lsb: u32,
657657
658 pub fn encodeOffset(moffs: *MemoryMoffs, v: u64) void {
659 moffs.msb = @truncate(u32, v >> 32);
660 moffs.lsb = @truncate(u32, v);
658 pub fn encode(seg: Register, offset: u64) MemoryMoffs {
659 return .{
660 .seg = @enumToInt(seg),
661 .msb = @truncate(u32, offset >> 32),
662 .lsb = @truncate(u32, offset >> 0),
663 };
661664 }
662665
663 pub fn decodeOffset(moffs: *const MemoryMoffs) u64 {
664 var res: u64 = 0;
665 res |= (@intCast(u64, moffs.msb) << 32);
666 res |= @intCast(u64, moffs.lsb);
667 return res;
666 pub fn decode(moffs: MemoryMoffs) Memory {
667 return .{ .moffs = .{
668 .seg = @intToEnum(Register, moffs.seg),
669 .offset = @as(u64, moffs.msb) << 32 | @as(u64, moffs.lsb) << 0,
670 } };
668671 }
669672};
670673
src/arch/x86_64/bits.zig+1-1
......@@ -515,7 +515,7 @@ pub const Memory = union(enum) {
515515 return switch (mem) {
516516 .rip => |r| r.ptr_size.bitSize(),
517517 .sib => |s| s.ptr_size.bitSize(),
518 .moffs => unreachable,
518 .moffs => 64,
519519 };
520520 }
521521};
src/arch/x86_64/encoder.zig+539-380
......@@ -11,12 +11,9 @@ const Memory = bits.Memory;
1111const Register = bits.Register;
1212
1313pub const Instruction = struct {
14 op1: Operand = .none,
15 op2: Operand = .none,
16 op3: Operand = .none,
17 op4: Operand = .none,
1814 prefix: Prefix = .none,
1915 encoding: Encoding,
16 ops: [4]Operand = .{.none} ** 4,
2017
2118 pub const Mnemonic = Encoding.Mnemonic;
2219
......@@ -107,102 +104,87 @@ pub const Instruction = struct {
107104 }
108105 };
109106
110 pub const Init = struct {
111 prefix: Prefix = .none,
112 op1: Operand = .none,
113 op2: Operand = .none,
114 op3: Operand = .none,
115 op4: Operand = .none,
116 };
117
118 pub fn new(mnemonic: Mnemonic, args: Init) !Instruction {
119 const encoding = (try Encoding.findByMnemonic(mnemonic, args)) orelse {
107 pub fn new(prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) !Instruction {
108 const encoding = (try Encoding.findByMnemonic(prefix, mnemonic, ops)) orelse {
120109 log.err("no encoding found for: {s} {s} {s} {s} {s} {s}", .{
121 @tagName(args.prefix),
110 @tagName(prefix),
122111 @tagName(mnemonic),
123 @tagName(Encoding.Op.fromOperand(args.op1)),
124 @tagName(Encoding.Op.fromOperand(args.op2)),
125 @tagName(Encoding.Op.fromOperand(args.op3)),
126 @tagName(Encoding.Op.fromOperand(args.op4)),
112 @tagName(if (ops.len > 0) Encoding.Op.fromOperand(ops[0]) else .none),
113 @tagName(if (ops.len > 1) Encoding.Op.fromOperand(ops[1]) else .none),
114 @tagName(if (ops.len > 2) Encoding.Op.fromOperand(ops[2]) else .none),
115 @tagName(if (ops.len > 3) Encoding.Op.fromOperand(ops[3]) else .none),
127116 });
128117 return error.InvalidInstruction;
129118 };
130119 log.debug("selected encoding: {}", .{encoding});
131 return .{
132 .prefix = args.prefix,
133 .op1 = args.op1,
134 .op2 = args.op2,
135 .op3 = args.op3,
136 .op4 = args.op4,
120
121 var inst = Instruction{
122 .prefix = prefix,
137123 .encoding = encoding,
124 .ops = [1]Operand{.none} ** 4,
138125 };
126 std.mem.copy(Operand, &inst.ops, ops);
127 return inst;
139128 }
140129
141130 pub fn fmtPrint(inst: Instruction, writer: anytype) !void {
142131 if (inst.prefix != .none) try writer.print("{s} ", .{@tagName(inst.prefix)});
143132 try writer.print("{s}", .{@tagName(inst.encoding.mnemonic)});
144 const ops = [_]struct { Operand, Encoding.Op }{
145 .{ inst.op1, inst.encoding.op1 },
146 .{ inst.op2, inst.encoding.op2 },
147 .{ inst.op3, inst.encoding.op3 },
148 .{ inst.op4, inst.encoding.op4 },
149 };
150 for (&ops, 0..) |op, i| {
151 if (op[0] == .none) break;
152 if (i > 0) {
153 try writer.writeByte(',');
154 }
133 for (inst.ops, inst.encodings.ops, 0..) |op, enc, i| {
134 if (op == .none) break;
135 if (i > 0) try writer.writeByte(',');
155136 try writer.writeByte(' ');
156 try op[0].fmtPrint(op[1], writer);
137 try op.fmtPrint(enc, writer);
157138 }
158139 }
159140
160141 pub fn encode(inst: Instruction, writer: anytype) !void {
161142 const encoder = Encoder(@TypeOf(writer)){ .writer = writer };
162 const encoding = inst.encoding;
143 const enc = inst.encoding;
144 const data = enc.data;
163145
164146 try inst.encodeLegacyPrefixes(encoder);
165147 try inst.encodeMandatoryPrefix(encoder);
166148 try inst.encodeRexPrefix(encoder);
167149 try inst.encodeOpcode(encoder);
168150
169 switch (encoding.op_en) {
151 switch (data.op_en) {
170152 .np, .o => {},
171 .i, .d => try encodeImm(inst.op1.imm, encoding.op1, encoder),
172 .zi, .oi => try encodeImm(inst.op2.imm, encoding.op2, encoder),
173 .fd => try encoder.imm64(inst.op2.mem.moffs.offset),
174 .td => try encoder.imm64(inst.op1.mem.moffs.offset),
153 .i, .d => try encodeImm(inst.ops[0].imm, data.ops[0], encoder),
154 .zi, .oi => try encodeImm(inst.ops[1].imm, data.ops[1], encoder),
155 .fd => try encoder.imm64(inst.ops[1].mem.moffs.offset),
156 .td => try encoder.imm64(inst.ops[0].mem.moffs.offset),
175157 else => {
176 const mem_op = switch (encoding.op_en) {
177 .m, .mi, .m1, .mc, .mr, .mri, .mrc => inst.op1,
178 .rm, .rmi => inst.op2,
158 const mem_op = switch (data.op_en) {
159 .m, .mi, .m1, .mc, .mr, .mri, .mrc => inst.ops[0],
160 .rm, .rmi => inst.ops[1],
179161 else => unreachable,
180162 };
181163 switch (mem_op) {
182164 .reg => |reg| {
183 const rm = switch (encoding.op_en) {
184 .m, .mi, .m1, .mc => encoding.modRmExt(),
185 .mr, .mri, .mrc => inst.op2.reg.lowEnc(),
186 .rm, .rmi => inst.op1.reg.lowEnc(),
165 const rm = switch (data.op_en) {
166 .m, .mi, .m1, .mc => enc.modRmExt(),
167 .mr, .mri, .mrc => inst.ops[1].reg.lowEnc(),
168 .rm, .rmi => inst.ops[0].reg.lowEnc(),
187169 else => unreachable,
188170 };
189171 try encoder.modRm_direct(rm, reg.lowEnc());
190172 },
191173 .mem => |mem| {
192 const op = switch (encoding.op_en) {
174 const op = switch (data.op_en) {
193175 .m, .mi, .m1, .mc => .none,
194 .mr, .mri, .mrc => inst.op2,
195 .rm, .rmi => inst.op1,
176 .mr, .mri, .mrc => inst.ops[1],
177 .rm, .rmi => inst.ops[0],
196178 else => unreachable,
197179 };
198 try encodeMemory(encoding, mem, op, encoder);
180 try encodeMemory(enc, mem, op, encoder);
199181 },
200182 else => unreachable,
201183 }
202184
203 switch (encoding.op_en) {
204 .mi => try encodeImm(inst.op2.imm, encoding.op2, encoder),
205 .rmi, .mri => try encodeImm(inst.op3.imm, encoding.op3, encoder),
185 switch (data.op_en) {
186 .mi => try encodeImm(inst.ops[1].imm, data.ops[1], encoder),
187 .rmi, .mri => try encodeImm(inst.ops[2].imm, data.ops[2], encoder),
206188 else => {},
207189 }
208190 },
......@@ -214,15 +196,16 @@ pub const Instruction = struct {
214196 const first = @boolToInt(inst.encoding.mandatoryPrefix() != null);
215197 const final = opcode.len - 1;
216198 for (opcode[first..final]) |byte| try encoder.opcode_1byte(byte);
217 switch (inst.encoding.op_en) {
218 .o, .oi => try encoder.opcode_withReg(opcode[final], inst.op1.reg.lowEnc()),
199 switch (inst.encoding.data.op_en) {
200 .o, .oi => try encoder.opcode_withReg(opcode[final], inst.ops[0].reg.lowEnc()),
219201 else => try encoder.opcode_1byte(opcode[final]),
220202 }
221203 }
222204
223205 fn encodeLegacyPrefixes(inst: Instruction, encoder: anytype) !void {
224206 const enc = inst.encoding;
225 const op_en = enc.op_en;
207 const data = enc.data;
208 const op_en = data.op_en;
226209
227210 var legacy = LegacyPrefixes{};
228211
......@@ -233,7 +216,7 @@ pub const Instruction = struct {
233216 .rep, .repe, .repz => legacy.prefix_f3 = true,
234217 }
235218
236 if (enc.mode == .none) {
219 if (data.mode == .none) {
237220 const bit_size = enc.operandBitSize();
238221 if (bit_size == 16) {
239222 legacy.set16BitOverride();
......@@ -242,17 +225,17 @@ pub const Instruction = struct {
242225
243226 const segment_override: ?Register = switch (op_en) {
244227 .i, .zi, .o, .oi, .d, .np => null,
245 .fd => inst.op2.mem.base().?,
246 .td => inst.op1.mem.base().?,
247 .rm, .rmi => if (inst.op2.isSegmentRegister()) blk: {
248 break :blk switch (inst.op2) {
228 .fd => inst.ops[1].mem.base().?,
229 .td => inst.ops[0].mem.base().?,
230 .rm, .rmi => if (inst.ops[1].isSegmentRegister()) blk: {
231 break :blk switch (inst.ops[1]) {
249232 .reg => |r| r,
250233 .mem => |m| m.base().?,
251234 else => unreachable,
252235 };
253236 } else null,
254 .m, .mi, .m1, .mc, .mr, .mri, .mrc => if (inst.op1.isSegmentRegister()) blk: {
255 break :blk switch (inst.op1) {
237 .m, .mi, .m1, .mc, .mr, .mri, .mrc => if (inst.ops[0].isSegmentRegister()) blk: {
238 break :blk switch (inst.ops[0]) {
256239 .reg => |r| r,
257240 .mem => |m| m.base().?,
258241 else => unreachable,
......@@ -267,19 +250,19 @@ pub const Instruction = struct {
267250 }
268251
269252 fn encodeRexPrefix(inst: Instruction, encoder: anytype) !void {
270 const op_en = inst.encoding.op_en;
253 const op_en = inst.encoding.data.op_en;
271254
272255 var rex = Rex{};
273 rex.present = inst.encoding.mode == .rex;
274 rex.w = inst.encoding.mode == .long;
256 rex.present = inst.encoding.data.mode == .rex;
257 rex.w = inst.encoding.data.mode == .long;
275258
276259 switch (op_en) {
277260 .np, .i, .zi, .fd, .td, .d => {},
278 .o, .oi => rex.b = inst.op1.reg.isExtended(),
261 .o, .oi => rex.b = inst.ops[0].reg.isExtended(),
279262 .m, .mi, .m1, .mc, .mr, .rm, .rmi, .mri, .mrc => {
280263 const r_op = switch (op_en) {
281 .rm, .rmi => inst.op1,
282 .mr, .mri, .mrc => inst.op2,
264 .rm, .rmi => inst.ops[0],
265 .mr, .mri, .mrc => inst.ops[1],
283266 else => null,
284267 };
285268 if (r_op) |op| {
......@@ -287,8 +270,8 @@ pub const Instruction = struct {
287270 }
288271
289272 const b_x_op = switch (op_en) {
290 .rm, .rmi => inst.op2,
291 .m, .mi, .m1, .mc, .mr, .mri, .mrc => inst.op1,
273 .rm, .rmi => inst.ops[1],
274 .m, .mi, .m1, .mc, .mr, .mri, .mrc => inst.ops[0],
292275 else => unreachable,
293276 };
294277 switch (b_x_op) {
......@@ -827,16 +810,14 @@ const TestEncode = struct {
827810 buffer: [32]u8 = undefined,
828811 index: usize = 0,
829812
830 fn encode(enc: *TestEncode, mnemonic: Instruction.Mnemonic, args: Instruction.Init) !void {
813 fn encode(
814 enc: *TestEncode,
815 mnemonic: Instruction.Mnemonic,
816 ops: []const Instruction.Operand,
817 ) !void {
831818 var stream = std.io.fixedBufferStream(&enc.buffer);
832819 var count_writer = std.io.countingWriter(stream.writer());
833 const inst = try Instruction.new(mnemonic, .{
834 .prefix = args.prefix,
835 .op1 = args.op1,
836 .op2 = args.op2,
837 .op3 = args.op3,
838 .op4 = args.op4,
839 });
820 const inst = try Instruction.new(.none, mnemonic, ops);
840821 try inst.encode(count_writer.writer());
841822 enc.index = count_writer.bytes_written;
842823 }
......@@ -850,9 +831,9 @@ test "encode" {
850831 var buf = std.ArrayList(u8).init(testing.allocator);
851832 defer buf.deinit();
852833
853 const inst = try Instruction.new(.mov, .{
854 .op1 = .{ .reg = .rbx },
855 .op2 = .{ .imm = Immediate.u(4) },
834 const inst = try Instruction.new(.none, .mov, &.{
835 .{ .reg = .rbx },
836 .{ .imm = Immediate.u(4) },
856837 });
857838 try inst.encode(buf.writer());
858839 try testing.expectEqualSlices(u8, &.{ 0x48, 0xc7, 0xc3, 0x4, 0x0, 0x0, 0x0 }, buf.items);
......@@ -861,61 +842,94 @@ test "encode" {
861842test "lower I encoding" {
862843 var enc = TestEncode{};
863844
864 try enc.encode(.push, .{ .op1 = .{ .imm = Immediate.u(0x10) } });
845 try enc.encode(.push, &.{
846 .{ .imm = Immediate.u(0x10) },
847 });
865848 try expectEqualHexStrings("\x6A\x10", enc.code(), "push 0x10");
866849
867 try enc.encode(.push, .{ .op1 = .{ .imm = Immediate.u(0x1000) } });
850 try enc.encode(.push, &.{
851 .{ .imm = Immediate.u(0x1000) },
852 });
868853 try expectEqualHexStrings("\x66\x68\x00\x10", enc.code(), "push 0x1000");
869854
870 try enc.encode(.push, .{ .op1 = .{ .imm = Immediate.u(0x10000000) } });
855 try enc.encode(.push, &.{
856 .{ .imm = Immediate.u(0x10000000) },
857 });
871858 try expectEqualHexStrings("\x68\x00\x00\x00\x10", enc.code(), "push 0x10000000");
872859
873 try enc.encode(.adc, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .imm = Immediate.u(0x10000000) } });
860 try enc.encode(.adc, &.{
861 .{ .reg = .rax },
862 .{ .imm = Immediate.u(0x10000000) },
863 });
874864 try expectEqualHexStrings("\x48\x15\x00\x00\x00\x10", enc.code(), "adc rax, 0x10000000");
875865
876 try enc.encode(.add, .{ .op1 = .{ .reg = .al }, .op2 = .{ .imm = Immediate.u(0x10) } });
866 try enc.encode(.add, &.{
867 .{ .reg = .al },
868 .{ .imm = Immediate.u(0x10) },
869 });
877870 try expectEqualHexStrings("\x04\x10", enc.code(), "add al, 0x10");
878871
879 try enc.encode(.add, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .imm = Immediate.u(0x10) } });
872 try enc.encode(.add, &.{
873 .{ .reg = .rax },
874 .{ .imm = Immediate.u(0x10) },
875 });
880876 try expectEqualHexStrings("\x48\x83\xC0\x10", enc.code(), "add rax, 0x10");
881877
882 try enc.encode(.sbb, .{ .op1 = .{ .reg = .ax }, .op2 = .{ .imm = Immediate.u(0x10) } });
878 try enc.encode(.sbb, &.{
879 .{ .reg = .ax },
880 .{ .imm = Immediate.u(0x10) },
881 });
883882 try expectEqualHexStrings("\x66\x1D\x10\x00", enc.code(), "sbb ax, 0x10");
884883
885 try enc.encode(.xor, .{ .op1 = .{ .reg = .al }, .op2 = .{ .imm = Immediate.u(0x10) } });
884 try enc.encode(.xor, &.{
885 .{ .reg = .al },
886 .{ .imm = Immediate.u(0x10) },
887 });
886888 try expectEqualHexStrings("\x34\x10", enc.code(), "xor al, 0x10");
887889}
888890
889891test "lower MI encoding" {
890892 var enc = TestEncode{};
891893
892 try enc.encode(.mov, .{ .op1 = .{ .reg = .r12 }, .op2 = .{ .imm = Immediate.u(0x1000) } });
894 try enc.encode(.mov, &.{
895 .{ .reg = .r12 },
896 .{ .imm = Immediate.u(0x1000) },
897 });
893898 try expectEqualHexStrings("\x49\xC7\xC4\x00\x10\x00\x00", enc.code(), "mov r12, 0x1000");
894899
895 try enc.encode(.mov, .{
896 .op1 = .{ .mem = Memory.sib(.byte, .{ .base = .r12 }) },
897 .op2 = .{ .imm = Immediate.u(0x10) },
900 try enc.encode(.mov, &.{
901 .{ .mem = Memory.sib(.byte, .{ .base = .r12 }) },
902 .{ .imm = Immediate.u(0x10) },
898903 });
899904 try expectEqualHexStrings("\x41\xC6\x04\x24\x10", enc.code(), "mov BYTE PTR [r12], 0x10");
900905
901 try enc.encode(.mov, .{ .op1 = .{ .reg = .r12 }, .op2 = .{ .imm = Immediate.u(0x1000) } });
906 try enc.encode(.mov, &.{
907 .{ .reg = .r12 },
908 .{ .imm = Immediate.u(0x1000) },
909 });
902910 try expectEqualHexStrings("\x49\xC7\xC4\x00\x10\x00\x00", enc.code(), "mov r12, 0x1000");
903911
904 try enc.encode(.mov, .{ .op1 = .{ .reg = .r12 }, .op2 = .{ .imm = Immediate.u(0x1000) } });
912 try enc.encode(.mov, &.{
913 .{ .reg = .r12 },
914 .{ .imm = Immediate.u(0x1000) },
915 });
905916 try expectEqualHexStrings("\x49\xC7\xC4\x00\x10\x00\x00", enc.code(), "mov r12, 0x1000");
906917
907 try enc.encode(.mov, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .imm = Immediate.u(0x10) } });
918 try enc.encode(.mov, &.{
919 .{ .reg = .rax },
920 .{ .imm = Immediate.u(0x10) },
921 });
908922 try expectEqualHexStrings("\x48\xc7\xc0\x10\x00\x00\x00", enc.code(), "mov rax, 0x10");
909923
910 try enc.encode(.mov, .{
911 .op1 = .{ .mem = Memory.sib(.dword, .{ .base = .r11 }) },
912 .op2 = .{ .imm = Immediate.u(0x10) },
924 try enc.encode(.mov, &.{
925 .{ .mem = Memory.sib(.dword, .{ .base = .r11 }) },
926 .{ .imm = Immediate.u(0x10) },
913927 });
914928 try expectEqualHexStrings("\x41\xc7\x03\x10\x00\x00\x00", enc.code(), "mov DWORD PTR [r11], 0x10");
915929
916 try enc.encode(.mov, .{
917 .op1 = .{ .mem = Memory.rip(.qword, 0x10) },
918 .op2 = .{ .imm = Immediate.u(0x10) },
930 try enc.encode(.mov, &.{
931 .{ .mem = Memory.rip(.qword, 0x10) },
932 .{ .imm = Immediate.u(0x10) },
919933 });
920934 try expectEqualHexStrings(
921935 "\x48\xC7\x05\x10\x00\x00\x00\x10\x00\x00\x00",
......@@ -923,99 +937,108 @@ test "lower MI encoding" {
923937 "mov QWORD PTR [rip + 0x10], 0x10",
924938 );
925939
926 try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.qword, .{
927 .base = .rbp,
928 .disp = -8,
929 }) }, .op2 = .{ .imm = Immediate.u(0x10) } });
940 try enc.encode(.mov, &.{
941 .{ .mem = Memory.sib(.qword, .{ .base = .rbp, .disp = -8 }) },
942 .{ .imm = Immediate.u(0x10) },
943 });
930944 try expectEqualHexStrings("\x48\xc7\x45\xf8\x10\x00\x00\x00", enc.code(), "mov QWORD PTR [rbp - 8], 0x10");
931945
932 try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.word, .{
933 .base = .rbp,
934 .disp = -2,
935 }) }, .op2 = .{ .imm = Immediate.s(-16) } });
946 try enc.encode(.mov, &.{
947 .{ .mem = Memory.sib(.word, .{ .base = .rbp, .disp = -2 }) },
948 .{ .imm = Immediate.s(-16) },
949 });
936950 try expectEqualHexStrings("\x66\xC7\x45\xFE\xF0\xFF", enc.code(), "mov WORD PTR [rbp - 2], -16");
937951
938 try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.byte, .{
939 .base = .rbp,
940 .disp = -1,
941 }) }, .op2 = .{ .imm = Immediate.u(0x10) } });
952 try enc.encode(.mov, &.{
953 .{ .mem = Memory.sib(.byte, .{ .base = .rbp, .disp = -1 }) },
954 .{ .imm = Immediate.u(0x10) },
955 });
942956 try expectEqualHexStrings("\xC6\x45\xFF\x10", enc.code(), "mov BYTE PTR [rbp - 1], 0x10");
943957
944 try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.qword, .{
945 .base = .ds,
946 .disp = 0x10000000,
947 .scale_index = .{
948 .scale = 2,
949 .index = .rcx,
950 },
951 }) }, .op2 = .{ .imm = Immediate.u(0x10) } });
958 try enc.encode(.mov, &.{
959 .{ .mem = Memory.sib(.qword, .{
960 .base = .ds,
961 .disp = 0x10000000,
962 .scale_index = .{ .scale = 2, .index = .rcx },
963 }) },
964 .{ .imm = Immediate.u(0x10) },
965 });
952966 try expectEqualHexStrings(
953967 "\x48\xC7\x04\x4D\x00\x00\x00\x10\x10\x00\x00\x00",
954968 enc.code(),
955969 "mov QWORD PTR [rcx*2 + 0x10000000], 0x10",
956970 );
957971
958 try enc.encode(.adc, .{ .op1 = .{ .mem = Memory.sib(.byte, .{
959 .base = .rbp,
960 .disp = -0x10,
961 }) }, .op2 = .{ .imm = Immediate.u(0x10) } });
972 try enc.encode(.adc, &.{
973 .{ .mem = Memory.sib(.byte, .{ .base = .rbp, .disp = -0x10 }) },
974 .{ .imm = Immediate.u(0x10) },
975 });
962976 try expectEqualHexStrings("\x80\x55\xF0\x10", enc.code(), "adc BYTE PTR [rbp - 0x10], 0x10");
963977
964 try enc.encode(.adc, .{ .op1 = .{ .mem = Memory.rip(.qword, 0) }, .op2 = .{ .imm = Immediate.u(0x10) } });
978 try enc.encode(.adc, &.{
979 .{ .mem = Memory.rip(.qword, 0) },
980 .{ .imm = Immediate.u(0x10) },
981 });
965982 try expectEqualHexStrings("\x48\x83\x15\x00\x00\x00\x00\x10", enc.code(), "adc QWORD PTR [rip], 0x10");
966983
967 try enc.encode(.adc, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .imm = Immediate.u(0x10) } });
984 try enc.encode(.adc, &.{
985 .{ .reg = .rax },
986 .{ .imm = Immediate.u(0x10) },
987 });
968988 try expectEqualHexStrings("\x48\x83\xD0\x10", enc.code(), "adc rax, 0x10");
969989
970 try enc.encode(.add, .{ .op1 = .{ .mem = Memory.sib(.dword, .{
971 .base = .rdx,
972 .disp = -8,
973 }) }, .op2 = .{ .imm = Immediate.u(0x10) } });
990 try enc.encode(.add, &.{
991 .{ .mem = Memory.sib(.dword, .{ .base = .rdx, .disp = -8 }) },
992 .{ .imm = Immediate.u(0x10) },
993 });
974994 try expectEqualHexStrings("\x83\x42\xF8\x10", enc.code(), "add DWORD PTR [rdx - 8], 0x10");
975995
976 try enc.encode(.add, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .imm = Immediate.u(0x10) } });
996 try enc.encode(.add, &.{
997 .{ .reg = .rax },
998 .{ .imm = Immediate.u(0x10) },
999 });
9771000 try expectEqualHexStrings("\x48\x83\xC0\x10", enc.code(), "add rax, 0x10");
9781001
979 try enc.encode(.add, .{ .op1 = .{ .mem = Memory.sib(.qword, .{
980 .base = .rbp,
981 .disp = -0x10,
982 }) }, .op2 = .{ .imm = Immediate.s(-0x10) } });
1002 try enc.encode(.add, &.{
1003 .{ .mem = Memory.sib(.qword, .{ .base = .rbp, .disp = -0x10 }) },
1004 .{ .imm = Immediate.s(-0x10) },
1005 });
9831006 try expectEqualHexStrings("\x48\x83\x45\xF0\xF0", enc.code(), "add QWORD PTR [rbp - 0x10], -0x10");
9841007
985 try enc.encode(.@"and", .{ .op1 = .{ .mem = Memory.sib(.dword, .{
986 .base = .ds,
987 .disp = 0x10000000,
988 }) }, .op2 = .{ .imm = Immediate.u(0x10) } });
1008 try enc.encode(.@"and", &.{
1009 .{ .mem = Memory.sib(.dword, .{ .base = .ds, .disp = 0x10000000 }) },
1010 .{ .imm = Immediate.u(0x10) },
1011 });
9891012 try expectEqualHexStrings(
9901013 "\x83\x24\x25\x00\x00\x00\x10\x10",
9911014 enc.code(),
9921015 "and DWORD PTR ds:0x10000000, 0x10",
9931016 );
9941017
995 try enc.encode(.@"and", .{ .op1 = .{ .mem = Memory.sib(.dword, .{
996 .base = .es,
997 .disp = 0x10000000,
998 }) }, .op2 = .{ .imm = Immediate.u(0x10) } });
1018 try enc.encode(.@"and", &.{
1019 .{ .mem = Memory.sib(.dword, .{ .base = .es, .disp = 0x10000000 }) },
1020 .{ .imm = Immediate.u(0x10) },
1021 });
9991022 try expectEqualHexStrings(
10001023 "\x26\x83\x24\x25\x00\x00\x00\x10\x10",
10011024 enc.code(),
10021025 "and DWORD PTR es:0x10000000, 0x10",
10031026 );
10041027
1005 try enc.encode(.@"and", .{ .op1 = .{ .mem = Memory.sib(.dword, .{
1006 .base = .r12,
1007 .disp = 0x10000000,
1008 }) }, .op2 = .{ .imm = Immediate.u(0x10) } });
1028 try enc.encode(.@"and", &.{
1029 .{ .mem = Memory.sib(.dword, .{ .base = .r12, .disp = 0x10000000 }) },
1030 .{ .imm = Immediate.u(0x10) },
1031 });
10091032 try expectEqualHexStrings(
10101033 "\x41\x83\xA4\x24\x00\x00\x00\x10\x10",
10111034 enc.code(),
10121035 "and DWORD PTR [r12 + 0x10000000], 0x10",
10131036 );
10141037
1015 try enc.encode(.sub, .{ .op1 = .{ .mem = Memory.sib(.dword, .{
1016 .base = .r11,
1017 .disp = 0x10000000,
1018 }) }, .op2 = .{ .imm = Immediate.u(0x10) } });
1038 try enc.encode(.sub, &.{
1039 .{ .mem = Memory.sib(.dword, .{ .base = .r11, .disp = 0x10000000 }) },
1040 .{ .imm = Immediate.u(0x10) },
1041 });
10191042 try expectEqualHexStrings(
10201043 "\x41\x83\xAB\x00\x00\x00\x10\x10",
10211044 enc.code(),
......@@ -1026,185 +1049,227 @@ test "lower MI encoding" {
10261049test "lower RM encoding" {
10271050 var enc = TestEncode{};
10281051
1029 try enc.encode(.mov, .{
1030 .op1 = .{ .reg = .rax },
1031 .op2 = .{ .mem = Memory.sib(.qword, .{ .base = .r11 }) },
1052 try enc.encode(.mov, &.{
1053 .{ .reg = .rax },
1054 .{ .mem = Memory.sib(.qword, .{ .base = .r11 }) },
10321055 });
10331056 try expectEqualHexStrings("\x49\x8b\x03", enc.code(), "mov rax, QWORD PTR [r11]");
10341057
1035 try enc.encode(.mov, .{ .op1 = .{ .reg = .rbx }, .op2 = .{ .mem = Memory.sib(.qword, .{
1036 .base = .ds,
1037 .disp = 0x10,
1038 }) } });
1058 try enc.encode(.mov, &.{
1059 .{ .reg = .rbx },
1060 .{ .mem = Memory.sib(.qword, .{ .base = .ds, .disp = 0x10 }) },
1061 });
10391062 try expectEqualHexStrings("\x48\x8B\x1C\x25\x10\x00\x00\x00", enc.code(), "mov rbx, QWORD PTR ds:0x10");
10401063
1041 try enc.encode(.mov, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .mem = Memory.sib(.qword, .{
1042 .base = .rbp,
1043 .disp = -4,
1044 }) } });
1064 try enc.encode(.mov, &.{
1065 .{ .reg = .rax },
1066 .{ .mem = Memory.sib(.qword, .{ .base = .rbp, .disp = -4 }) },
1067 });
10451068 try expectEqualHexStrings("\x48\x8B\x45\xFC", enc.code(), "mov rax, QWORD PTR [rbp - 4]");
10461069
1047 try enc.encode(.mov, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .mem = Memory.sib(.qword, .{
1048 .base = .rbp,
1049 .scale_index = .{
1050 .scale = 1,
1051 .index = .rcx,
1052 },
1053 .disp = -8,
1054 }) } });
1070 try enc.encode(.mov, &.{
1071 .{ .reg = .rax },
1072 .{ .mem = Memory.sib(.qword, .{
1073 .base = .rbp,
1074 .scale_index = .{ .scale = 1, .index = .rcx },
1075 .disp = -8,
1076 }) },
1077 });
10551078 try expectEqualHexStrings("\x48\x8B\x44\x0D\xF8", enc.code(), "mov rax, QWORD PTR [rbp + rcx*1 - 8]");
10561079
1057 try enc.encode(.mov, .{ .op1 = .{ .reg = .eax }, .op2 = .{ .mem = Memory.sib(.dword, .{
1058 .base = .rbp,
1059 .scale_index = .{
1060 .scale = 4,
1061 .index = .rdx,
1062 },
1063 .disp = -4,
1064 }) } });
1080 try enc.encode(.mov, &.{
1081 .{ .reg = .eax },
1082 .{ .mem = Memory.sib(.dword, .{
1083 .base = .rbp,
1084 .scale_index = .{ .scale = 4, .index = .rdx },
1085 .disp = -4,
1086 }) },
1087 });
10651088 try expectEqualHexStrings("\x8B\x44\x95\xFC", enc.code(), "mov eax, dword ptr [rbp + rdx*4 - 4]");
10661089
1067 try enc.encode(.mov, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .mem = Memory.sib(.qword, .{
1068 .base = .rbp,
1069 .scale_index = .{
1070 .scale = 8,
1071 .index = .rcx,
1072 },
1073 .disp = -8,
1074 }) } });
1090 try enc.encode(.mov, &.{
1091 .{ .reg = .rax },
1092 .{ .mem = Memory.sib(.qword, .{
1093 .base = .rbp,
1094 .scale_index = .{ .scale = 8, .index = .rcx },
1095 .disp = -8,
1096 }) },
1097 });
10751098 try expectEqualHexStrings("\x48\x8B\x44\xCD\xF8", enc.code(), "mov rax, QWORD PTR [rbp + rcx*8 - 8]");
10761099
1077 try enc.encode(.mov, .{ .op1 = .{ .reg = .r8b }, .op2 = .{ .mem = Memory.sib(.byte, .{
1078 .base = .rsi,
1079 .scale_index = .{
1080 .scale = 1,
1081 .index = .rcx,
1082 },
1083 .disp = -24,
1084 }) } });
1100 try enc.encode(.mov, &.{
1101 .{ .reg = .r8b },
1102 .{ .mem = Memory.sib(.byte, .{
1103 .base = .rsi,
1104 .scale_index = .{ .scale = 1, .index = .rcx },
1105 .disp = -24,
1106 }) },
1107 });
10851108 try expectEqualHexStrings("\x44\x8A\x44\x0E\xE8", enc.code(), "mov r8b, BYTE PTR [rsi + rcx*1 - 24]");
10861109
10871110 // TODO this mnemonic needs cleanup as some prefixes are obsolete.
1088 try enc.encode(.mov, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .reg = .cs } });
1111 try enc.encode(.mov, &.{
1112 .{ .reg = .rax },
1113 .{ .reg = .cs },
1114 });
10891115 try expectEqualHexStrings("\x48\x8C\xC8", enc.code(), "mov rax, cs");
10901116
1091 try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.qword, .{
1092 .base = .rbp,
1093 .disp = -16,
1094 }) }, .op2 = .{ .reg = .fs } });
1117 try enc.encode(.mov, &.{
1118 .{ .mem = Memory.sib(.qword, .{ .base = .rbp, .disp = -16 }) },
1119 .{ .reg = .fs },
1120 });
10951121 try expectEqualHexStrings("\x48\x8C\x65\xF0", enc.code(), "mov QWORD PTR [rbp - 16], fs");
10961122
1097 try enc.encode(.mov, .{ .op1 = .{ .reg = .r12w }, .op2 = .{ .reg = .cs } });
1123 try enc.encode(.mov, &.{
1124 .{ .reg = .r12w },
1125 .{ .reg = .cs },
1126 });
10981127 try expectEqualHexStrings("\x66\x41\x8C\xCC", enc.code(), "mov r12w, cs");
10991128
1100 try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.word, .{
1101 .base = .rbp,
1102 .disp = -16,
1103 }) }, .op2 = .{ .reg = .fs } });
1129 try enc.encode(.mov, &.{
1130 .{ .mem = Memory.sib(.word, .{ .base = .rbp, .disp = -16 }) },
1131 .{ .reg = .fs },
1132 });
11041133 try expectEqualHexStrings("\x66\x8C\x65\xF0", enc.code(), "mov WORD PTR [rbp - 16], fs");
11051134
1106 try enc.encode(.movsx, .{ .op1 = .{ .reg = .eax }, .op2 = .{ .reg = .bx } });
1135 try enc.encode(.movsx, &.{
1136 .{ .reg = .eax },
1137 .{ .reg = .bx },
1138 });
11071139 try expectEqualHexStrings("\x0F\xBF\xC3", enc.code(), "movsx eax, bx");
11081140
1109 try enc.encode(.movsx, .{ .op1 = .{ .reg = .eax }, .op2 = .{ .reg = .bl } });
1141 try enc.encode(.movsx, &.{
1142 .{ .reg = .eax },
1143 .{ .reg = .bl },
1144 });
11101145 try expectEqualHexStrings("\x0F\xBE\xC3", enc.code(), "movsx eax, bl");
11111146
1112 try enc.encode(.movsx, .{ .op1 = .{ .reg = .ax }, .op2 = .{ .reg = .bl } });
1147 try enc.encode(.movsx, &.{
1148 .{ .reg = .ax },
1149 .{ .reg = .bl },
1150 });
11131151 try expectEqualHexStrings("\x66\x0F\xBE\xC3", enc.code(), "movsx ax, bl");
11141152
1115 try enc.encode(.movsx, .{
1116 .op1 = .{ .reg = .eax },
1117 .op2 = .{ .mem = Memory.sib(.word, .{ .base = .rbp }) },
1153 try enc.encode(.movsx, &.{
1154 .{ .reg = .eax },
1155 .{ .mem = Memory.sib(.word, .{ .base = .rbp }) },
11181156 });
11191157 try expectEqualHexStrings("\x0F\xBF\x45\x00", enc.code(), "movsx eax, BYTE PTR [rbp]");
11201158
1121 try enc.encode(.movsx, .{
1122 .op1 = .{ .reg = .eax },
1123 .op2 = .{ .mem = Memory.sib(.byte, .{ .scale_index = .{ .index = .rax, .scale = 2 } }) },
1159 try enc.encode(.movsx, &.{
1160 .{ .reg = .eax },
1161 .{ .mem = Memory.sib(.byte, .{ .scale_index = .{ .index = .rax, .scale = 2 } }) },
11241162 });
11251163 try expectEqualHexStrings("\x0F\xBE\x04\x45\x00\x00\x00\x00", enc.code(), "movsx eax, BYTE PTR [rax * 2]");
11261164
1127 try enc.encode(.movsx, .{ .op1 = .{ .reg = .ax }, .op2 = .{ .mem = Memory.rip(.byte, 0x10) } });
1165 try enc.encode(.movsx, &.{
1166 .{ .reg = .ax },
1167 .{ .mem = Memory.rip(.byte, 0x10) },
1168 });
11281169 try expectEqualHexStrings("\x66\x0F\xBE\x05\x10\x00\x00\x00", enc.code(), "movsx ax, BYTE PTR [rip + 0x10]");
11291170
1130 try enc.encode(.movsx, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .reg = .bx } });
1171 try enc.encode(.movsx, &.{
1172 .{ .reg = .rax },
1173 .{ .reg = .bx },
1174 });
11311175 try expectEqualHexStrings("\x48\x0F\xBF\xC3", enc.code(), "movsx rax, bx");
11321176
1133 try enc.encode(.movsxd, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .reg = .ebx } });
1177 try enc.encode(.movsxd, &.{
1178 .{ .reg = .rax },
1179 .{ .reg = .ebx },
1180 });
11341181 try expectEqualHexStrings("\x48\x63\xC3", enc.code(), "movsxd rax, ebx");
11351182
1136 try enc.encode(.lea, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .mem = Memory.rip(.qword, 0x10) } });
1183 try enc.encode(.lea, &.{
1184 .{ .reg = .rax },
1185 .{ .mem = Memory.rip(.qword, 0x10) },
1186 });
11371187 try expectEqualHexStrings("\x48\x8D\x05\x10\x00\x00\x00", enc.code(), "lea rax, QWORD PTR [rip + 0x10]");
11381188
1139 try enc.encode(.lea, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .mem = Memory.rip(.dword, 0x10) } });
1189 try enc.encode(.lea, &.{
1190 .{ .reg = .rax },
1191 .{ .mem = Memory.rip(.dword, 0x10) },
1192 });
11401193 try expectEqualHexStrings("\x48\x8D\x05\x10\x00\x00\x00", enc.code(), "lea rax, DWORD PTR [rip + 0x10]");
11411194
1142 try enc.encode(.lea, .{ .op1 = .{ .reg = .eax }, .op2 = .{ .mem = Memory.rip(.dword, 0x10) } });
1195 try enc.encode(.lea, &.{
1196 .{ .reg = .eax },
1197 .{ .mem = Memory.rip(.dword, 0x10) },
1198 });
11431199 try expectEqualHexStrings("\x8D\x05\x10\x00\x00\x00", enc.code(), "lea eax, DWORD PTR [rip + 0x10]");
11441200
1145 try enc.encode(.lea, .{ .op1 = .{ .reg = .eax }, .op2 = .{ .mem = Memory.rip(.word, 0x10) } });
1201 try enc.encode(.lea, &.{
1202 .{ .reg = .eax },
1203 .{ .mem = Memory.rip(.word, 0x10) },
1204 });
11461205 try expectEqualHexStrings("\x8D\x05\x10\x00\x00\x00", enc.code(), "lea eax, WORD PTR [rip + 0x10]");
11471206
1148 try enc.encode(.lea, .{ .op1 = .{ .reg = .ax }, .op2 = .{ .mem = Memory.rip(.byte, 0x10) } });
1207 try enc.encode(.lea, &.{
1208 .{ .reg = .ax },
1209 .{ .mem = Memory.rip(.byte, 0x10) },
1210 });
11491211 try expectEqualHexStrings("\x66\x8D\x05\x10\x00\x00\x00", enc.code(), "lea ax, BYTE PTR [rip + 0x10]");
11501212
1151 try enc.encode(.lea, .{
1152 .op1 = .{ .reg = .rsi },
1153 .op2 = .{ .mem = Memory.sib(.qword, .{
1213 try enc.encode(.lea, &.{
1214 .{ .reg = .rsi },
1215 .{ .mem = Memory.sib(.qword, .{
11541216 .base = .rbp,
11551217 .scale_index = .{ .scale = 1, .index = .rcx },
11561218 }) },
11571219 });
11581220 try expectEqualHexStrings("\x48\x8D\x74\x0D\x00", enc.code(), "lea rsi, QWORD PTR [rbp + rcx*1 + 0]");
11591221
1160 try enc.encode(.add, .{ .op1 = .{ .reg = .r11 }, .op2 = .{ .mem = Memory.sib(.qword, .{
1161 .base = .ds,
1162 .disp = 0x10000000,
1163 }) } });
1222 try enc.encode(.add, &.{
1223 .{ .reg = .r11 },
1224 .{ .mem = Memory.sib(.qword, .{ .base = .ds, .disp = 0x10000000 }) },
1225 });
11641226 try expectEqualHexStrings("\x4C\x03\x1C\x25\x00\x00\x00\x10", enc.code(), "add r11, QWORD PTR ds:0x10000000");
11651227
1166 try enc.encode(.add, .{ .op1 = .{ .reg = .r12b }, .op2 = .{ .mem = Memory.sib(.byte, .{
1167 .base = .ds,
1168 .disp = 0x10000000,
1169 }) } });
1228 try enc.encode(.add, &.{
1229 .{ .reg = .r12b },
1230 .{ .mem = Memory.sib(.byte, .{ .base = .ds, .disp = 0x10000000 }) },
1231 });
11701232 try expectEqualHexStrings("\x44\x02\x24\x25\x00\x00\x00\x10", enc.code(), "add r11b, BYTE PTR ds:0x10000000");
11711233
1172 try enc.encode(.add, .{ .op1 = .{ .reg = .r12b }, .op2 = .{ .mem = Memory.sib(.byte, .{
1173 .base = .fs,
1174 .disp = 0x10000000,
1175 }) } });
1234 try enc.encode(.add, &.{
1235 .{ .reg = .r12b },
1236 .{ .mem = Memory.sib(.byte, .{ .base = .fs, .disp = 0x10000000 }) },
1237 });
11761238 try expectEqualHexStrings("\x64\x44\x02\x24\x25\x00\x00\x00\x10", enc.code(), "add r11b, BYTE PTR fs:0x10000000");
11771239
1178 try enc.encode(.sub, .{ .op1 = .{ .reg = .r11 }, .op2 = .{ .mem = Memory.sib(.qword, .{
1179 .base = .r13,
1180 .disp = 0x10000000,
1181 }) } });
1240 try enc.encode(.sub, &.{
1241 .{ .reg = .r11 },
1242 .{ .mem = Memory.sib(.qword, .{ .base = .r13, .disp = 0x10000000 }) },
1243 });
11821244 try expectEqualHexStrings("\x4D\x2B\x9D\x00\x00\x00\x10", enc.code(), "sub r11, QWORD PTR [r13 + 0x10000000]");
11831245
1184 try enc.encode(.sub, .{ .op1 = .{ .reg = .r11 }, .op2 = .{ .mem = Memory.sib(.qword, .{
1185 .base = .r12,
1186 .disp = 0x10000000,
1187 }) } });
1246 try enc.encode(.sub, &.{
1247 .{ .reg = .r11 },
1248 .{ .mem = Memory.sib(.qword, .{ .base = .r12, .disp = 0x10000000 }) },
1249 });
11881250 try expectEqualHexStrings("\x4D\x2B\x9C\x24\x00\x00\x00\x10", enc.code(), "sub r11, QWORD PTR [r12 + 0x10000000]");
11891251
1190 try enc.encode(.imul, .{ .op1 = .{ .reg = .r11 }, .op2 = .{ .reg = .r12 } });
1252 try enc.encode(.imul, &.{
1253 .{ .reg = .r11 },
1254 .{ .reg = .r12 },
1255 });
11911256 try expectEqualHexStrings("\x4D\x0F\xAF\xDC", enc.code(), "mov r11, r12");
11921257}
11931258
11941259test "lower RMI encoding" {
11951260 var enc = TestEncode{};
11961261
1197 try enc.encode(.imul, .{
1198 .op1 = .{ .reg = .r11 },
1199 .op2 = .{ .reg = .r12 },
1200 .op3 = .{ .imm = Immediate.s(-2) },
1262 try enc.encode(.imul, &.{
1263 .{ .reg = .r11 },
1264 .{ .reg = .r12 },
1265 .{ .imm = Immediate.s(-2) },
12011266 });
12021267 try expectEqualHexStrings("\x4D\x6B\xDC\xFE", enc.code(), "imul r11, r12, -2");
12031268
1204 try enc.encode(.imul, .{
1205 .op1 = .{ .reg = .r11 },
1206 .op2 = .{ .mem = Memory.rip(.qword, -16) },
1207 .op3 = .{ .imm = Immediate.s(-1024) },
1269 try enc.encode(.imul, &.{
1270 .{ .reg = .r11 },
1271 .{ .mem = Memory.rip(.qword, -16) },
1272 .{ .imm = Immediate.s(-1024) },
12081273 });
12091274 try expectEqualHexStrings(
12101275 "\x4C\x69\x1D\xF0\xFF\xFF\xFF\x00\xFC\xFF\xFF",
......@@ -1212,13 +1277,10 @@ test "lower RMI encoding" {
12121277 "imul r11, QWORD PTR [rip - 16], -1024",
12131278 );
12141279
1215 try enc.encode(.imul, .{
1216 .op1 = .{ .reg = .bx },
1217 .op2 = .{ .mem = Memory.sib(.word, .{
1218 .base = .rbp,
1219 .disp = -16,
1220 }) },
1221 .op3 = .{ .imm = Immediate.s(-1024) },
1280 try enc.encode(.imul, &.{
1281 .{ .reg = .bx },
1282 .{ .mem = Memory.sib(.word, .{ .base = .rbp, .disp = -16 }) },
1283 .{ .imm = Immediate.s(-1024) },
12221284 });
12231285 try expectEqualHexStrings(
12241286 "\x66\x69\x5D\xF0\x00\xFC",
......@@ -1226,13 +1288,10 @@ test "lower RMI encoding" {
12261288 "imul bx, WORD PTR [rbp - 16], -1024",
12271289 );
12281290
1229 try enc.encode(.imul, .{
1230 .op1 = .{ .reg = .bx },
1231 .op2 = .{ .mem = Memory.sib(.word, .{
1232 .base = .rbp,
1233 .disp = -16,
1234 }) },
1235 .op3 = .{ .imm = Immediate.u(1024) },
1291 try enc.encode(.imul, &.{
1292 .{ .reg = .bx },
1293 .{ .mem = Memory.sib(.word, .{ .base = .rbp, .disp = -16 }) },
1294 .{ .imm = Immediate.u(1024) },
12361295 });
12371296 try expectEqualHexStrings(
12381297 "\x66\x69\x5D\xF0\x00\x04",
......@@ -1244,238 +1303,343 @@ test "lower RMI encoding" {
12441303test "lower MR encoding" {
12451304 var enc = TestEncode{};
12461305
1247 try enc.encode(.mov, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .reg = .rbx } });
1306 try enc.encode(.mov, &.{
1307 .{ .reg = .rax },
1308 .{ .reg = .rbx },
1309 });
12481310 try expectEqualHexStrings("\x48\x89\xD8", enc.code(), "mov rax, rbx");
12491311
1250 try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.qword, .{
1251 .base = .rbp,
1252 .disp = -4,
1253 }) }, .op2 = .{ .reg = .r11 } });
1312 try enc.encode(.mov, &.{
1313 .{ .mem = Memory.sib(.qword, .{ .base = .rbp, .disp = -4 }) },
1314 .{ .reg = .r11 },
1315 });
12541316 try expectEqualHexStrings("\x4c\x89\x5d\xfc", enc.code(), "mov QWORD PTR [rbp - 4], r11");
12551317
1256 try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.rip(.qword, 0x10) }, .op2 = .{ .reg = .r12 } });
1318 try enc.encode(.mov, &.{
1319 .{ .mem = Memory.rip(.qword, 0x10) },
1320 .{ .reg = .r12 },
1321 });
12571322 try expectEqualHexStrings("\x4C\x89\x25\x10\x00\x00\x00", enc.code(), "mov QWORD PTR [rip + 0x10], r12");
12581323
1259 try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.qword, .{
1260 .base = .r11,
1261 .scale_index = .{
1262 .scale = 2,
1263 .index = .r12,
1264 },
1265 .disp = 0x10,
1266 }) }, .op2 = .{ .reg = .r13 } });
1324 try enc.encode(.mov, &.{
1325 .{ .mem = Memory.sib(.qword, .{
1326 .base = .r11,
1327 .scale_index = .{ .scale = 2, .index = .r12 },
1328 .disp = 0x10,
1329 }) },
1330 .{ .reg = .r13 },
1331 });
12671332 try expectEqualHexStrings("\x4F\x89\x6C\x63\x10", enc.code(), "mov QWORD PTR [r11 + 2 * r12 + 0x10], r13");
12681333
1269 try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.rip(.word, -0x10) }, .op2 = .{ .reg = .r12w } });
1334 try enc.encode(.mov, &.{
1335 .{ .mem = Memory.rip(.word, -0x10) },
1336 .{ .reg = .r12w },
1337 });
12701338 try expectEqualHexStrings("\x66\x44\x89\x25\xF0\xFF\xFF\xFF", enc.code(), "mov WORD PTR [rip - 0x10], r12w");
12711339
1272 try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.byte, .{
1273 .base = .r11,
1274 .scale_index = .{
1275 .scale = 2,
1276 .index = .r12,
1277 },
1278 .disp = 0x10,
1279 }) }, .op2 = .{ .reg = .r13b } });
1340 try enc.encode(.mov, &.{
1341 .{ .mem = Memory.sib(.byte, .{
1342 .base = .r11,
1343 .scale_index = .{ .scale = 2, .index = .r12 },
1344 .disp = 0x10,
1345 }) },
1346 .{ .reg = .r13b },
1347 });
12801348 try expectEqualHexStrings("\x47\x88\x6C\x63\x10", enc.code(), "mov BYTE PTR [r11 + 2 * r12 + 0x10], r13b");
12811349
1282 try enc.encode(.add, .{ .op1 = .{ .mem = Memory.sib(.byte, .{
1283 .base = .ds,
1284 .disp = 0x10000000,
1285 }) }, .op2 = .{ .reg = .r12b } });
1350 try enc.encode(.add, &.{
1351 .{ .mem = Memory.sib(.byte, .{ .base = .ds, .disp = 0x10000000 }) },
1352 .{ .reg = .r12b },
1353 });
12861354 try expectEqualHexStrings("\x44\x00\x24\x25\x00\x00\x00\x10", enc.code(), "add BYTE PTR ds:0x10000000, r12b");
12871355
1288 try enc.encode(.add, .{ .op1 = .{ .mem = Memory.sib(.dword, .{
1289 .base = .ds,
1290 .disp = 0x10000000,
1291 }) }, .op2 = .{ .reg = .r12d } });
1356 try enc.encode(.add, &.{
1357 .{ .mem = Memory.sib(.dword, .{ .base = .ds, .disp = 0x10000000 }) },
1358 .{ .reg = .r12d },
1359 });
12921360 try expectEqualHexStrings("\x44\x01\x24\x25\x00\x00\x00\x10", enc.code(), "add DWORD PTR [ds:0x10000000], r12d");
12931361
1294 try enc.encode(.add, .{ .op1 = .{ .mem = Memory.sib(.dword, .{
1295 .base = .gs,
1296 .disp = 0x10000000,
1297 }) }, .op2 = .{ .reg = .r12d } });
1362 try enc.encode(.add, &.{
1363 .{ .mem = Memory.sib(.dword, .{ .base = .gs, .disp = 0x10000000 }) },
1364 .{ .reg = .r12d },
1365 });
12981366 try expectEqualHexStrings("\x65\x44\x01\x24\x25\x00\x00\x00\x10", enc.code(), "add DWORD PTR [gs:0x10000000], r12d");
12991367
1300 try enc.encode(.sub, .{ .op1 = .{ .mem = Memory.sib(.qword, .{
1301 .base = .r11,
1302 .disp = 0x10000000,
1303 }) }, .op2 = .{ .reg = .r12 } });
1368 try enc.encode(.sub, &.{
1369 .{ .mem = Memory.sib(.qword, .{ .base = .r11, .disp = 0x10000000 }) },
1370 .{ .reg = .r12 },
1371 });
13041372 try expectEqualHexStrings("\x4D\x29\xA3\x00\x00\x00\x10", enc.code(), "sub QWORD PTR [r11 + 0x10000000], r12");
13051373}
13061374
13071375test "lower M encoding" {
13081376 var enc = TestEncode{};
13091377
1310 try enc.encode(.call, .{ .op1 = .{ .reg = .r12 } });
1378 try enc.encode(.call, &.{
1379 .{ .reg = .r12 },
1380 });
13111381 try expectEqualHexStrings("\x41\xFF\xD4", enc.code(), "call r12");
13121382
1313 try enc.encode(.call, .{ .op1 = .{ .mem = Memory.sib(.qword, .{ .base = .r12 }) } });
1383 try enc.encode(.call, &.{
1384 .{ .mem = Memory.sib(.qword, .{ .base = .r12 }) },
1385 });
13141386 try expectEqualHexStrings("\x41\xFF\x14\x24", enc.code(), "call QWORD PTR [r12]");
13151387
1316 try enc.encode(.call, .{
1317 .op1 = .{ .mem = Memory.sib(.qword, .{
1388 try enc.encode(.call, &.{
1389 .{ .mem = Memory.sib(.qword, .{
13181390 .base = null,
13191391 .scale_index = .{ .index = .r11, .scale = 2 },
13201392 }) },
13211393 });
13221394 try expectEqualHexStrings("\x42\xFF\x14\x5D\x00\x00\x00\x00", enc.code(), "call QWORD PTR [r11 * 2]");
13231395
1324 try enc.encode(.call, .{
1325 .op1 = .{ .mem = Memory.sib(.qword, .{
1396 try enc.encode(.call, &.{
1397 .{ .mem = Memory.sib(.qword, .{
13261398 .base = null,
13271399 .scale_index = .{ .index = .r12, .scale = 2 },
13281400 }) },
13291401 });
13301402 try expectEqualHexStrings("\x42\xFF\x14\x65\x00\x00\x00\x00", enc.code(), "call QWORD PTR [r12 * 2]");
13311403
1332 try enc.encode(.call, .{ .op1 = .{ .mem = Memory.sib(.qword, .{ .base = .gs }) } });
1404 try enc.encode(.call, &.{
1405 .{ .mem = Memory.sib(.qword, .{ .base = .gs }) },
1406 });
13331407 try expectEqualHexStrings("\x65\xFF\x14\x25\x00\x00\x00\x00", enc.code(), "call gs:0x0");
13341408
1335 try enc.encode(.call, .{ .op1 = .{ .imm = Immediate.s(0) } });
1409 try enc.encode(.call, &.{
1410 .{ .imm = Immediate.s(0) },
1411 });
13361412 try expectEqualHexStrings("\xE8\x00\x00\x00\x00", enc.code(), "call 0x0");
13371413
1338 try enc.encode(.push, .{ .op1 = .{ .mem = Memory.sib(.qword, .{ .base = .rbp }) } });
1414 try enc.encode(.push, &.{
1415 .{ .mem = Memory.sib(.qword, .{ .base = .rbp }) },
1416 });
13391417 try expectEqualHexStrings("\xFF\x75\x00", enc.code(), "push QWORD PTR [rbp]");
13401418
1341 try enc.encode(.push, .{ .op1 = .{ .mem = Memory.sib(.word, .{ .base = .rbp }) } });
1419 try enc.encode(.push, &.{
1420 .{ .mem = Memory.sib(.word, .{ .base = .rbp }) },
1421 });
13421422 try expectEqualHexStrings("\x66\xFF\x75\x00", enc.code(), "push QWORD PTR [rbp]");
13431423
1344 try enc.encode(.pop, .{ .op1 = .{ .mem = Memory.rip(.qword, 0) } });
1424 try enc.encode(.pop, &.{
1425 .{ .mem = Memory.rip(.qword, 0) },
1426 });
13451427 try expectEqualHexStrings("\x8F\x05\x00\x00\x00\x00", enc.code(), "pop QWORD PTR [rip]");
13461428
1347 try enc.encode(.pop, .{ .op1 = .{ .mem = Memory.rip(.word, 0) } });
1429 try enc.encode(.pop, &.{
1430 .{ .mem = Memory.rip(.word, 0) },
1431 });
13481432 try expectEqualHexStrings("\x66\x8F\x05\x00\x00\x00\x00", enc.code(), "pop WORD PTR [rbp]");
13491433
1350 try enc.encode(.imul, .{ .op1 = .{ .reg = .rax } });
1434 try enc.encode(.imul, &.{
1435 .{ .reg = .rax },
1436 });
13511437 try expectEqualHexStrings("\x48\xF7\xE8", enc.code(), "imul rax");
13521438
1353 try enc.encode(.imul, .{ .op1 = .{ .reg = .r12 } });
1439 try enc.encode(.imul, &.{
1440 .{ .reg = .r12 },
1441 });
13541442 try expectEqualHexStrings("\x49\xF7\xEC", enc.code(), "imul r12");
13551443}
13561444
13571445test "lower O encoding" {
13581446 var enc = TestEncode{};
13591447
1360 try enc.encode(.push, .{ .op1 = .{ .reg = .rax } });
1448 try enc.encode(.push, &.{
1449 .{ .reg = .rax },
1450 });
13611451 try expectEqualHexStrings("\x50", enc.code(), "push rax");
13621452
1363 try enc.encode(.push, .{ .op1 = .{ .reg = .r12w } });
1453 try enc.encode(.push, &.{
1454 .{ .reg = .r12w },
1455 });
13641456 try expectEqualHexStrings("\x66\x41\x54", enc.code(), "push r12w");
13651457
1366 try enc.encode(.pop, .{ .op1 = .{ .reg = .r12 } });
1458 try enc.encode(.pop, &.{
1459 .{ .reg = .r12 },
1460 });
13671461 try expectEqualHexStrings("\x41\x5c", enc.code(), "pop r12");
13681462}
13691463
13701464test "lower OI encoding" {
13711465 var enc = TestEncode{};
13721466
1373 try enc.encode(.mov, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .imm = Immediate.u(0x1000000000000000) } });
1467 try enc.encode(.mov, &.{
1468 .{ .reg = .rax },
1469 .{ .imm = Immediate.u(0x1000000000000000) },
1470 });
13741471 try expectEqualHexStrings(
13751472 "\x48\xB8\x00\x00\x00\x00\x00\x00\x00\x10",
13761473 enc.code(),
13771474 "movabs rax, 0x1000000000000000",
13781475 );
13791476
1380 try enc.encode(.mov, .{ .op1 = .{ .reg = .r11 }, .op2 = .{ .imm = Immediate.u(0x1000000000000000) } });
1477 try enc.encode(.mov, &.{
1478 .{ .reg = .r11 },
1479 .{ .imm = Immediate.u(0x1000000000000000) },
1480 });
13811481 try expectEqualHexStrings(
13821482 "\x49\xBB\x00\x00\x00\x00\x00\x00\x00\x10",
13831483 enc.code(),
13841484 "movabs r11, 0x1000000000000000",
13851485 );
13861486
1387 try enc.encode(.mov, .{ .op1 = .{ .reg = .r11d }, .op2 = .{ .imm = Immediate.u(0x10000000) } });
1487 try enc.encode(.mov, &.{
1488 .{ .reg = .r11d },
1489 .{ .imm = Immediate.u(0x10000000) },
1490 });
13881491 try expectEqualHexStrings("\x41\xBB\x00\x00\x00\x10", enc.code(), "mov r11d, 0x10000000");
13891492
1390 try enc.encode(.mov, .{ .op1 = .{ .reg = .r11w }, .op2 = .{ .imm = Immediate.u(0x1000) } });
1493 try enc.encode(.mov, &.{
1494 .{ .reg = .r11w },
1495 .{ .imm = Immediate.u(0x1000) },
1496 });
13911497 try expectEqualHexStrings("\x66\x41\xBB\x00\x10", enc.code(), "mov r11w, 0x1000");
13921498
1393 try enc.encode(.mov, .{ .op1 = .{ .reg = .r11b }, .op2 = .{ .imm = Immediate.u(0x10) } });
1499 try enc.encode(.mov, &.{
1500 .{ .reg = .r11b },
1501 .{ .imm = Immediate.u(0x10) },
1502 });
13941503 try expectEqualHexStrings("\x41\xB3\x10", enc.code(), "mov r11b, 0x10");
13951504}
13961505
13971506test "lower FD/TD encoding" {
13981507 var enc = TestEncode{};
13991508
1400 try enc.encode(.mov, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .mem = Memory.moffs(.cs, 0x10) } });
1509 try enc.encode(.mov, &.{
1510 .{ .reg = .rax },
1511 .{ .mem = Memory.moffs(.cs, 0x10) },
1512 });
14011513 try expectEqualHexStrings("\x2E\x48\xA1\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs rax, cs:0x10");
14021514
1403 try enc.encode(.mov, .{ .op1 = .{ .reg = .eax }, .op2 = .{ .mem = Memory.moffs(.fs, 0x10) } });
1515 try enc.encode(.mov, &.{
1516 .{ .reg = .eax },
1517 .{ .mem = Memory.moffs(.fs, 0x10) },
1518 });
14041519 try expectEqualHexStrings("\x64\xA1\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs eax, fs:0x10");
14051520
1406 try enc.encode(.mov, .{ .op1 = .{ .reg = .ax }, .op2 = .{ .mem = Memory.moffs(.gs, 0x10) } });
1521 try enc.encode(.mov, &.{
1522 .{ .reg = .ax },
1523 .{ .mem = Memory.moffs(.gs, 0x10) },
1524 });
14071525 try expectEqualHexStrings("\x65\x66\xA1\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs ax, gs:0x10");
14081526
1409 try enc.encode(.mov, .{ .op1 = .{ .reg = .al }, .op2 = .{ .mem = Memory.moffs(.ds, 0x10) } });
1527 try enc.encode(.mov, &.{
1528 .{ .reg = .al },
1529 .{ .mem = Memory.moffs(.ds, 0x10) },
1530 });
14101531 try expectEqualHexStrings("\xA0\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs al, ds:0x10");
14111532
1412 try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.moffs(.cs, 0x10) }, .op2 = .{ .reg = .rax } });
1533 try enc.encode(.mov, &.{
1534 .{ .mem = Memory.moffs(.cs, 0x10) },
1535 .{ .reg = .rax },
1536 });
14131537 try expectEqualHexStrings("\x2E\x48\xA3\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs cs:0x10, rax");
14141538
1415 try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.moffs(.fs, 0x10) }, .op2 = .{ .reg = .eax } });
1539 try enc.encode(.mov, &.{
1540 .{ .mem = Memory.moffs(.fs, 0x10) },
1541 .{ .reg = .eax },
1542 });
14161543 try expectEqualHexStrings("\x64\xA3\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs fs:0x10, eax");
14171544
1418 try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.moffs(.gs, 0x10) }, .op2 = .{ .reg = .ax } });
1545 try enc.encode(.mov, &.{
1546 .{ .mem = Memory.moffs(.gs, 0x10) },
1547 .{ .reg = .ax },
1548 });
14191549 try expectEqualHexStrings("\x65\x66\xA3\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs gs:0x10, ax");
14201550
1421 try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.moffs(.ds, 0x10) }, .op2 = .{ .reg = .al } });
1551 try enc.encode(.mov, &.{
1552 .{ .mem = Memory.moffs(.ds, 0x10) },
1553 .{ .reg = .al },
1554 });
14221555 try expectEqualHexStrings("\xA2\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs ds:0x10, al");
14231556}
14241557
14251558test "lower NP encoding" {
14261559 var enc = TestEncode{};
14271560
1428 try enc.encode(.int3, .{});
1561 try enc.encode(.int3, &.{});
14291562 try expectEqualHexStrings("\xCC", enc.code(), "int3");
14301563
1431 try enc.encode(.nop, .{});
1564 try enc.encode(.nop, &.{});
14321565 try expectEqualHexStrings("\x90", enc.code(), "nop");
14331566
1434 try enc.encode(.ret, .{});
1567 try enc.encode(.ret, &.{});
14351568 try expectEqualHexStrings("\xC3", enc.code(), "ret");
14361569
1437 try enc.encode(.syscall, .{});
1570 try enc.encode(.syscall, &.{});
14381571 try expectEqualHexStrings("\x0f\x05", enc.code(), "syscall");
14391572}
14401573
1441fn invalidInstruction(mnemonic: Instruction.Mnemonic, args: Instruction.Init) !void {
1442 const err = Instruction.new(mnemonic, args);
1574fn invalidInstruction(mnemonic: Instruction.Mnemonic, ops: []const Instruction.Operand) !void {
1575 const err = Instruction.new(.none, mnemonic, ops);
14431576 try testing.expectError(error.InvalidInstruction, err);
14441577}
14451578
14461579test "invalid instruction" {
1447 try invalidInstruction(.call, .{ .op1 = .{ .reg = .eax } });
1448 try invalidInstruction(.call, .{ .op1 = .{ .reg = .ax } });
1449 try invalidInstruction(.call, .{ .op1 = .{ .reg = .al } });
1450 try invalidInstruction(.call, .{ .op1 = .{ .mem = Memory.rip(.dword, 0) } });
1451 try invalidInstruction(.call, .{ .op1 = .{ .mem = Memory.rip(.word, 0) } });
1452 try invalidInstruction(.call, .{ .op1 = .{ .mem = Memory.rip(.byte, 0) } });
1453 try invalidInstruction(.mov, .{ .op1 = .{ .mem = Memory.rip(.word, 0x10) }, .op2 = .{ .reg = .r12 } });
1454 try invalidInstruction(.lea, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .reg = .rbx } });
1455 try invalidInstruction(.lea, .{ .op1 = .{ .reg = .al }, .op2 = .{ .mem = Memory.rip(.byte, 0) } });
1456 try invalidInstruction(.pop, .{ .op1 = .{ .reg = .r12b } });
1457 try invalidInstruction(.pop, .{ .op1 = .{ .reg = .r12d } });
1458 try invalidInstruction(.push, .{ .op1 = .{ .reg = .r12b } });
1459 try invalidInstruction(.push, .{ .op1 = .{ .reg = .r12d } });
1460 try invalidInstruction(.push, .{ .op1 = .{ .imm = Immediate.u(0x1000000000000000) } });
1580 try invalidInstruction(.call, &.{
1581 .{ .reg = .eax },
1582 });
1583 try invalidInstruction(.call, &.{
1584 .{ .reg = .ax },
1585 });
1586 try invalidInstruction(.call, &.{
1587 .{ .reg = .al },
1588 });
1589 try invalidInstruction(.call, &.{
1590 .{ .mem = Memory.rip(.dword, 0) },
1591 });
1592 try invalidInstruction(.call, &.{
1593 .{ .mem = Memory.rip(.word, 0) },
1594 });
1595 try invalidInstruction(.call, &.{
1596 .{ .mem = Memory.rip(.byte, 0) },
1597 });
1598 try invalidInstruction(.mov, &.{
1599 .{ .mem = Memory.rip(.word, 0x10) },
1600 .{ .reg = .r12 },
1601 });
1602 try invalidInstruction(.lea, &.{
1603 .{ .reg = .rax },
1604 .{ .reg = .rbx },
1605 });
1606 try invalidInstruction(.lea, &.{
1607 .{ .reg = .al },
1608 .{ .mem = Memory.rip(.byte, 0) },
1609 });
1610 try invalidInstruction(.pop, &.{
1611 .{ .reg = .r12b },
1612 });
1613 try invalidInstruction(.pop, &.{
1614 .{ .reg = .r12d },
1615 });
1616 try invalidInstruction(.push, &.{
1617 .{ .reg = .r12b },
1618 });
1619 try invalidInstruction(.push, &.{
1620 .{ .reg = .r12d },
1621 });
1622 try invalidInstruction(.push, &.{
1623 .{ .imm = Immediate.u(0x1000000000000000) },
1624 });
14611625}
14621626
1463fn cannotEncode(mnemonic: Instruction.Mnemonic, args: Instruction.Init) !void {
1464 try testing.expectError(error.CannotEncode, Instruction.new(mnemonic, args));
1627fn cannotEncode(mnemonic: Instruction.Mnemonic, ops: []const Instruction.Operand) !void {
1628 try testing.expectError(error.CannotEncode, Instruction.new(.none, mnemonic, ops));
14651629}
14661630
14671631test "cannot encode" {
1468 try cannotEncode(.@"test", .{
1469 .op1 = .{ .mem = Memory.sib(.byte, .{ .base = .r12 }) },
1470 .op2 = .{ .reg = .ah },
1632 try cannotEncode(.@"test", &.{
1633 .{ .mem = Memory.sib(.byte, .{ .base = .r12 }) },
1634 .{ .reg = .ah },
14711635 });
1472 try cannotEncode(.@"test", .{
1473 .op1 = .{ .reg = .r11b },
1474 .op2 = .{ .reg = .bh },
1636 try cannotEncode(.@"test", &.{
1637 .{ .reg = .r11b },
1638 .{ .reg = .bh },
14751639 });
1476 try cannotEncode(.mov, .{
1477 .op1 = .{ .reg = .sil },
1478 .op2 = .{ .reg = .ah },
1640 try cannotEncode(.mov, &.{
1641 .{ .reg = .sil },
1642 .{ .reg = .ah },
14791643 });
14801644}
14811645
......@@ -1645,12 +1809,7 @@ const Assembler = struct {
16451809
16461810 pub fn assemble(as: *Assembler, writer: anytype) !void {
16471811 while (try as.next()) |parsed_inst| {
1648 const inst = try Instruction.new(parsed_inst.mnemonic, .{
1649 .op1 = parsed_inst.ops[0],
1650 .op2 = parsed_inst.ops[1],
1651 .op3 = parsed_inst.ops[2],
1652 .op4 = parsed_inst.ops[3],
1653 });
1812 const inst = try Instruction.new(.none, parsed_inst.mnemonic, &parsed_inst.ops);
16541813 try inst.encode(writer);
16551814 }
16561815 }
src/arch/x86_64/encodings.zig+837-832
......@@ -6,869 +6,874 @@ const Mode = Encoding.Mode;
66
77const modrm_ext = u3;
88
9const Entry = struct { Mnemonic, OpEn, Op, Op, Op, Op, []const u8, modrm_ext, Mode };
9pub const Entry = struct { Mnemonic, OpEn, []const Op, []const u8, modrm_ext, Mode };
1010
1111// TODO move this into a .zon file when Zig is capable of importing .zon files
1212// zig fmt: off
13pub const table = &[_]Entry{
13pub const table = [_]Entry{
1414 // General-purpose
15 .{ .adc, .zi, .al, .imm8, .none, .none, &.{ 0x14 }, 0, .none },
16 .{ .adc, .zi, .ax, .imm16, .none, .none, &.{ 0x15 }, 0, .none },
17 .{ .adc, .zi, .eax, .imm32, .none, .none, &.{ 0x15 }, 0, .none },
18 .{ .adc, .zi, .rax, .imm32s, .none, .none, &.{ 0x15 }, 0, .long },
19 .{ .adc, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 2, .none },
20 .{ .adc, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 2, .rex },
21 .{ .adc, .mi, .rm16, .imm16, .none, .none, &.{ 0x81 }, 2, .none },
22 .{ .adc, .mi, .rm32, .imm32, .none, .none, &.{ 0x81 }, 2, .none },
23 .{ .adc, .mi, .rm64, .imm32s, .none, .none, &.{ 0x81 }, 2, .long },
24 .{ .adc, .mi, .rm16, .imm8s, .none, .none, &.{ 0x83 }, 2, .none },
25 .{ .adc, .mi, .rm32, .imm8s, .none, .none, &.{ 0x83 }, 2, .none },
26 .{ .adc, .mi, .rm64, .imm8s, .none, .none, &.{ 0x83 }, 2, .long },
27 .{ .adc, .mr, .rm8, .r8, .none, .none, &.{ 0x10 }, 0, .none },
28 .{ .adc, .mr, .rm8, .r8, .none, .none, &.{ 0x10 }, 0, .rex },
29 .{ .adc, .mr, .rm16, .r16, .none, .none, &.{ 0x11 }, 0, .none },
30 .{ .adc, .mr, .rm32, .r32, .none, .none, &.{ 0x11 }, 0, .none },
31 .{ .adc, .mr, .rm64, .r64, .none, .none, &.{ 0x11 }, 0, .long },
32 .{ .adc, .rm, .r8, .rm8, .none, .none, &.{ 0x12 }, 0, .none },
33 .{ .adc, .rm, .r8, .rm8, .none, .none, &.{ 0x12 }, 0, .rex },
34 .{ .adc, .rm, .r16, .rm16, .none, .none, &.{ 0x13 }, 0, .none },
35 .{ .adc, .rm, .r32, .rm32, .none, .none, &.{ 0x13 }, 0, .none },
36 .{ .adc, .rm, .r64, .rm64, .none, .none, &.{ 0x13 }, 0, .long },
37
38 .{ .add, .zi, .al, .imm8, .none, .none, &.{ 0x04 }, 0, .none },
39 .{ .add, .zi, .ax, .imm16, .none, .none, &.{ 0x05 }, 0, .none },
40 .{ .add, .zi, .eax, .imm32, .none, .none, &.{ 0x05 }, 0, .none },
41 .{ .add, .zi, .rax, .imm32s, .none, .none, &.{ 0x05 }, 0, .long },
42 .{ .add, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 0, .none },
43 .{ .add, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 0, .rex },
44 .{ .add, .mi, .rm16, .imm16, .none, .none, &.{ 0x81 }, 0, .none },
45 .{ .add, .mi, .rm32, .imm32, .none, .none, &.{ 0x81 }, 0, .none },
46 .{ .add, .mi, .rm64, .imm32s, .none, .none, &.{ 0x81 }, 0, .long },
47 .{ .add, .mi, .rm16, .imm8s, .none, .none, &.{ 0x83 }, 0, .none },
48 .{ .add, .mi, .rm32, .imm8s, .none, .none, &.{ 0x83 }, 0, .none },
49 .{ .add, .mi, .rm64, .imm8s, .none, .none, &.{ 0x83 }, 0, .long },
50 .{ .add, .mr, .rm8, .r8, .none, .none, &.{ 0x00 }, 0, .none },
51 .{ .add, .mr, .rm8, .r8, .none, .none, &.{ 0x00 }, 0, .rex },
52 .{ .add, .mr, .rm16, .r16, .none, .none, &.{ 0x01 }, 0, .none },
53 .{ .add, .mr, .rm32, .r32, .none, .none, &.{ 0x01 }, 0, .none },
54 .{ .add, .mr, .rm64, .r64, .none, .none, &.{ 0x01 }, 0, .long },
55 .{ .add, .rm, .r8, .rm8, .none, .none, &.{ 0x02 }, 0, .none },
56 .{ .add, .rm, .r8, .rm8, .none, .none, &.{ 0x02 }, 0, .rex },
57 .{ .add, .rm, .r16, .rm16, .none, .none, &.{ 0x03 }, 0, .none },
58 .{ .add, .rm, .r32, .rm32, .none, .none, &.{ 0x03 }, 0, .none },
59 .{ .add, .rm, .r64, .rm64, .none, .none, &.{ 0x03 }, 0, .long },
60
61 .{ .@"and", .zi, .al, .imm8, .none, .none, &.{ 0x24 }, 0, .none },
62 .{ .@"and", .zi, .ax, .imm16, .none, .none, &.{ 0x25 }, 0, .none },
63 .{ .@"and", .zi, .eax, .imm32, .none, .none, &.{ 0x25 }, 0, .none },
64 .{ .@"and", .zi, .rax, .imm32s, .none, .none, &.{ 0x25 }, 0, .long },
65 .{ .@"and", .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 4, .none },
66 .{ .@"and", .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 4, .rex },
67 .{ .@"and", .mi, .rm16, .imm16, .none, .none, &.{ 0x81 }, 4, .none },
68 .{ .@"and", .mi, .rm32, .imm32, .none, .none, &.{ 0x81 }, 4, .none },
69 .{ .@"and", .mi, .rm64, .imm32s, .none, .none, &.{ 0x81 }, 4, .long },
70 .{ .@"and", .mi, .rm16, .imm8s, .none, .none, &.{ 0x83 }, 4, .none },
71 .{ .@"and", .mi, .rm32, .imm8s, .none, .none, &.{ 0x83 }, 4, .none },
72 .{ .@"and", .mi, .rm64, .imm8s, .none, .none, &.{ 0x83 }, 4, .long },
73 .{ .@"and", .mr, .rm8, .r8, .none, .none, &.{ 0x20 }, 0, .none },
74 .{ .@"and", .mr, .rm8, .r8, .none, .none, &.{ 0x20 }, 0, .rex },
75 .{ .@"and", .mr, .rm16, .r16, .none, .none, &.{ 0x21 }, 0, .none },
76 .{ .@"and", .mr, .rm32, .r32, .none, .none, &.{ 0x21 }, 0, .none },
77 .{ .@"and", .mr, .rm64, .r64, .none, .none, &.{ 0x21 }, 0, .long },
78 .{ .@"and", .rm, .r8, .rm8, .none, .none, &.{ 0x22 }, 0, .none },
79 .{ .@"and", .rm, .r8, .rm8, .none, .none, &.{ 0x22 }, 0, .rex },
80 .{ .@"and", .rm, .r16, .rm16, .none, .none, &.{ 0x23 }, 0, .none },
81 .{ .@"and", .rm, .r32, .rm32, .none, .none, &.{ 0x23 }, 0, .none },
82 .{ .@"and", .rm, .r64, .rm64, .none, .none, &.{ 0x23 }, 0, .long },
83
84 .{ .bsf, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0xbc }, 0, .none },
85 .{ .bsf, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0xbc }, 0, .none },
86 .{ .bsf, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0xbc }, 0, .long },
87
88 .{ .bsr, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0xbd }, 0, .none },
89 .{ .bsr, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0xbd }, 0, .none },
90 .{ .bsr, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0xbd }, 0, .long },
91
92 .{ .bswap, .o, .r32, .none, .none, .none, &.{ 0x0f, 0xc8 }, 0, .none },
93 .{ .bswap, .o, .r64, .none, .none, .none, &.{ 0x0f, 0xc8 }, 0, .long },
94
95 .{ .bt, .mr, .rm16, .r16, .none, .none, &.{ 0x0f, 0xa3 }, 0, .none },
96 .{ .bt, .mr, .rm32, .r32, .none, .none, &.{ 0x0f, 0xa3 }, 0, .none },
97 .{ .bt, .mr, .rm64, .r64, .none, .none, &.{ 0x0f, 0xa3 }, 0, .long },
98 .{ .bt, .mi, .rm16, .imm8, .none, .none, &.{ 0x0f, 0xba }, 4, .none },
99 .{ .bt, .mi, .rm32, .imm8, .none, .none, &.{ 0x0f, 0xba }, 4, .none },
100 .{ .bt, .mi, .rm64, .imm8, .none, .none, &.{ 0x0f, 0xba }, 4, .long },
101
102 .{ .btc, .mr, .rm16, .r16, .none, .none, &.{ 0x0f, 0xbb }, 0, .none },
103 .{ .btc, .mr, .rm32, .r32, .none, .none, &.{ 0x0f, 0xbb }, 0, .none },
104 .{ .btc, .mr, .rm64, .r64, .none, .none, &.{ 0x0f, 0xbb }, 0, .long },
105 .{ .btc, .mi, .rm16, .imm8, .none, .none, &.{ 0x0f, 0xba }, 7, .none },
106 .{ .btc, .mi, .rm32, .imm8, .none, .none, &.{ 0x0f, 0xba }, 7, .none },
107 .{ .btc, .mi, .rm64, .imm8, .none, .none, &.{ 0x0f, 0xba }, 7, .long },
108
109 .{ .btr, .mr, .rm16, .r16, .none, .none, &.{ 0x0f, 0xb3 }, 0, .none },
110 .{ .btr, .mr, .rm32, .r32, .none, .none, &.{ 0x0f, 0xb3 }, 0, .none },
111 .{ .btr, .mr, .rm64, .r64, .none, .none, &.{ 0x0f, 0xb3 }, 0, .long },
112 .{ .btr, .mi, .rm16, .imm8, .none, .none, &.{ 0x0f, 0xba }, 6, .none },
113 .{ .btr, .mi, .rm32, .imm8, .none, .none, &.{ 0x0f, 0xba }, 6, .none },
114 .{ .btr, .mi, .rm64, .imm8, .none, .none, &.{ 0x0f, 0xba }, 6, .long },
115
116 .{ .bts, .mr, .rm16, .r16, .none, .none, &.{ 0x0f, 0xab }, 0, .none },
117 .{ .bts, .mr, .rm32, .r32, .none, .none, &.{ 0x0f, 0xab }, 0, .none },
118 .{ .bts, .mr, .rm64, .r64, .none, .none, &.{ 0x0f, 0xab }, 0, .long },
119 .{ .bts, .mi, .rm16, .imm8, .none, .none, &.{ 0x0f, 0xba }, 5, .none },
120 .{ .bts, .mi, .rm32, .imm8, .none, .none, &.{ 0x0f, 0xba }, 5, .none },
121 .{ .bts, .mi, .rm64, .imm8, .none, .none, &.{ 0x0f, 0xba }, 5, .long },
15 .{ .adc, .zi, &.{ .al, .imm8 }, &.{ 0x14 }, 0, .none },
16 .{ .adc, .zi, &.{ .ax, .imm16 }, &.{ 0x15 }, 0, .none },
17 .{ .adc, .zi, &.{ .eax, .imm32 }, &.{ 0x15 }, 0, .none },
18 .{ .adc, .zi, &.{ .rax, .imm32s }, &.{ 0x15 }, 0, .long },
19 .{ .adc, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 2, .none },
20 .{ .adc, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 2, .rex },
21 .{ .adc, .mi, &.{ .rm16, .imm16 }, &.{ 0x81 }, 2, .none },
22 .{ .adc, .mi, &.{ .rm32, .imm32 }, &.{ 0x81 }, 2, .none },
23 .{ .adc, .mi, &.{ .rm64, .imm32s }, &.{ 0x81 }, 2, .long },
24 .{ .adc, .mi, &.{ .rm16, .imm8s }, &.{ 0x83 }, 2, .none },
25 .{ .adc, .mi, &.{ .rm32, .imm8s }, &.{ 0x83 }, 2, .none },
26 .{ .adc, .mi, &.{ .rm64, .imm8s }, &.{ 0x83 }, 2, .long },
27 .{ .adc, .mr, &.{ .rm8, .r8 }, &.{ 0x10 }, 0, .none },
28 .{ .adc, .mr, &.{ .rm8, .r8 }, &.{ 0x10 }, 0, .rex },
29 .{ .adc, .mr, &.{ .rm16, .r16 }, &.{ 0x11 }, 0, .none },
30 .{ .adc, .mr, &.{ .rm32, .r32 }, &.{ 0x11 }, 0, .none },
31 .{ .adc, .mr, &.{ .rm64, .r64 }, &.{ 0x11 }, 0, .long },
32 .{ .adc, .rm, &.{ .r8, .rm8 }, &.{ 0x12 }, 0, .none },
33 .{ .adc, .rm, &.{ .r8, .rm8 }, &.{ 0x12 }, 0, .rex },
34 .{ .adc, .rm, &.{ .r16, .rm16 }, &.{ 0x13 }, 0, .none },
35 .{ .adc, .rm, &.{ .r32, .rm32 }, &.{ 0x13 }, 0, .none },
36 .{ .adc, .rm, &.{ .r64, .rm64 }, &.{ 0x13 }, 0, .long },
37
38 .{ .add, .zi, &.{ .al, .imm8 }, &.{ 0x04 }, 0, .none },
39 .{ .add, .zi, &.{ .ax, .imm16 }, &.{ 0x05 }, 0, .none },
40 .{ .add, .zi, &.{ .eax, .imm32 }, &.{ 0x05 }, 0, .none },
41 .{ .add, .zi, &.{ .rax, .imm32s }, &.{ 0x05 }, 0, .long },
42 .{ .add, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 0, .none },
43 .{ .add, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 0, .rex },
44 .{ .add, .mi, &.{ .rm16, .imm16 }, &.{ 0x81 }, 0, .none },
45 .{ .add, .mi, &.{ .rm32, .imm32 }, &.{ 0x81 }, 0, .none },
46 .{ .add, .mi, &.{ .rm64, .imm32s }, &.{ 0x81 }, 0, .long },
47 .{ .add, .mi, &.{ .rm16, .imm8s }, &.{ 0x83 }, 0, .none },
48 .{ .add, .mi, &.{ .rm32, .imm8s }, &.{ 0x83 }, 0, .none },
49 .{ .add, .mi, &.{ .rm64, .imm8s }, &.{ 0x83 }, 0, .long },
50 .{ .add, .mr, &.{ .rm8, .r8 }, &.{ 0x00 }, 0, .none },
51 .{ .add, .mr, &.{ .rm8, .r8 }, &.{ 0x00 }, 0, .rex },
52 .{ .add, .mr, &.{ .rm16, .r16 }, &.{ 0x01 }, 0, .none },
53 .{ .add, .mr, &.{ .rm32, .r32 }, &.{ 0x01 }, 0, .none },
54 .{ .add, .mr, &.{ .rm64, .r64 }, &.{ 0x01 }, 0, .long },
55 .{ .add, .rm, &.{ .r8, .rm8 }, &.{ 0x02 }, 0, .none },
56 .{ .add, .rm, &.{ .r8, .rm8 }, &.{ 0x02 }, 0, .rex },
57 .{ .add, .rm, &.{ .r16, .rm16 }, &.{ 0x03 }, 0, .none },
58 .{ .add, .rm, &.{ .r32, .rm32 }, &.{ 0x03 }, 0, .none },
59 .{ .add, .rm, &.{ .r64, .rm64 }, &.{ 0x03 }, 0, .long },
60
61 .{ .@"and", .zi, &.{ .al, .imm8 }, &.{ 0x24 }, 0, .none },
62 .{ .@"and", .zi, &.{ .ax, .imm16 }, &.{ 0x25 }, 0, .none },
63 .{ .@"and", .zi, &.{ .eax, .imm32 }, &.{ 0x25 }, 0, .none },
64 .{ .@"and", .zi, &.{ .rax, .imm32s }, &.{ 0x25 }, 0, .long },
65 .{ .@"and", .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 4, .none },
66 .{ .@"and", .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 4, .rex },
67 .{ .@"and", .mi, &.{ .rm16, .imm16 }, &.{ 0x81 }, 4, .none },
68 .{ .@"and", .mi, &.{ .rm32, .imm32 }, &.{ 0x81 }, 4, .none },
69 .{ .@"and", .mi, &.{ .rm64, .imm32s }, &.{ 0x81 }, 4, .long },
70 .{ .@"and", .mi, &.{ .rm16, .imm8s }, &.{ 0x83 }, 4, .none },
71 .{ .@"and", .mi, &.{ .rm32, .imm8s }, &.{ 0x83 }, 4, .none },
72 .{ .@"and", .mi, &.{ .rm64, .imm8s }, &.{ 0x83 }, 4, .long },
73 .{ .@"and", .mr, &.{ .rm8, .r8 }, &.{ 0x20 }, 0, .none },
74 .{ .@"and", .mr, &.{ .rm8, .r8 }, &.{ 0x20 }, 0, .rex },
75 .{ .@"and", .mr, &.{ .rm16, .r16 }, &.{ 0x21 }, 0, .none },
76 .{ .@"and", .mr, &.{ .rm32, .r32 }, &.{ 0x21 }, 0, .none },
77 .{ .@"and", .mr, &.{ .rm64, .r64 }, &.{ 0x21 }, 0, .long },
78 .{ .@"and", .rm, &.{ .r8, .rm8 }, &.{ 0x22 }, 0, .none },
79 .{ .@"and", .rm, &.{ .r8, .rm8 }, &.{ 0x22 }, 0, .rex },
80 .{ .@"and", .rm, &.{ .r16, .rm16 }, &.{ 0x23 }, 0, .none },
81 .{ .@"and", .rm, &.{ .r32, .rm32 }, &.{ 0x23 }, 0, .none },
82 .{ .@"and", .rm, &.{ .r64, .rm64 }, &.{ 0x23 }, 0, .long },
83
84 .{ .bsf, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0xbc }, 0, .none },
85 .{ .bsf, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0xbc }, 0, .none },
86 .{ .bsf, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0xbc }, 0, .long },
87
88 .{ .bsr, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0xbd }, 0, .none },
89 .{ .bsr, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0xbd }, 0, .none },
90 .{ .bsr, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0xbd }, 0, .long },
91
92 .{ .bswap, .o, &.{ .r32 }, &.{ 0x0f, 0xc8 }, 0, .none },
93 .{ .bswap, .o, &.{ .r64 }, &.{ 0x0f, 0xc8 }, 0, .long },
94
95 .{ .bt, .mr, &.{ .rm16, .r16 }, &.{ 0x0f, 0xa3 }, 0, .none },
96 .{ .bt, .mr, &.{ .rm32, .r32 }, &.{ 0x0f, 0xa3 }, 0, .none },
97 .{ .bt, .mr, &.{ .rm64, .r64 }, &.{ 0x0f, 0xa3 }, 0, .long },
98 .{ .bt, .mi, &.{ .rm16, .imm8 }, &.{ 0x0f, 0xba }, 4, .none },
99 .{ .bt, .mi, &.{ .rm32, .imm8 }, &.{ 0x0f, 0xba }, 4, .none },
100 .{ .bt, .mi, &.{ .rm64, .imm8 }, &.{ 0x0f, 0xba }, 4, .long },
101
102 .{ .btc, .mr, &.{ .rm16, .r16 }, &.{ 0x0f, 0xbb }, 0, .none },
103 .{ .btc, .mr, &.{ .rm32, .r32 }, &.{ 0x0f, 0xbb }, 0, .none },
104 .{ .btc, .mr, &.{ .rm64, .r64 }, &.{ 0x0f, 0xbb }, 0, .long },
105 .{ .btc, .mi, &.{ .rm16, .imm8 }, &.{ 0x0f, 0xba }, 7, .none },
106 .{ .btc, .mi, &.{ .rm32, .imm8 }, &.{ 0x0f, 0xba }, 7, .none },
107 .{ .btc, .mi, &.{ .rm64, .imm8 }, &.{ 0x0f, 0xba }, 7, .long },
108
109 .{ .btr, .mr, &.{ .rm16, .r16 }, &.{ 0x0f, 0xb3 }, 0, .none },
110 .{ .btr, .mr, &.{ .rm32, .r32 }, &.{ 0x0f, 0xb3 }, 0, .none },
111 .{ .btr, .mr, &.{ .rm64, .r64 }, &.{ 0x0f, 0xb3 }, 0, .long },
112 .{ .btr, .mi, &.{ .rm16, .imm8 }, &.{ 0x0f, 0xba }, 6, .none },
113 .{ .btr, .mi, &.{ .rm32, .imm8 }, &.{ 0x0f, 0xba }, 6, .none },
114 .{ .btr, .mi, &.{ .rm64, .imm8 }, &.{ 0x0f, 0xba }, 6, .long },
115
116 .{ .bts, .mr, &.{ .rm16, .r16 }, &.{ 0x0f, 0xab }, 0, .none },
117 .{ .bts, .mr, &.{ .rm32, .r32 }, &.{ 0x0f, 0xab }, 0, .none },
118 .{ .bts, .mr, &.{ .rm64, .r64 }, &.{ 0x0f, 0xab }, 0, .long },
119 .{ .bts, .mi, &.{ .rm16, .imm8 }, &.{ 0x0f, 0xba }, 5, .none },
120 .{ .bts, .mi, &.{ .rm32, .imm8 }, &.{ 0x0f, 0xba }, 5, .none },
121 .{ .bts, .mi, &.{ .rm64, .imm8 }, &.{ 0x0f, 0xba }, 5, .long },
122122
123123 // This is M encoding according to Intel, but D makes more sense here.
124 .{ .call, .d, .rel32, .none, .none, .none, &.{ 0xe8 }, 0, .none },
125 .{ .call, .m, .rm64, .none, .none, .none, &.{ 0xff }, 2, .none },
126
127 .{ .cbw, .np, .o16, .none, .none, .none, &.{ 0x98 }, 0, .none },
128 .{ .cwde, .np, .o32, .none, .none, .none, &.{ 0x98 }, 0, .none },
129 .{ .cdqe, .np, .o64, .none, .none, .none, &.{ 0x98 }, 0, .long },
130
131 .{ .cwd, .np, .o16, .none, .none, .none, &.{ 0x99 }, 0, .none },
132 .{ .cdq, .np, .o32, .none, .none, .none, &.{ 0x99 }, 0, .none },
133 .{ .cqo, .np, .o64, .none, .none, .none, &.{ 0x99 }, 0, .long },
134
135 .{ .cmova, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x47 }, 0, .none },
136 .{ .cmova, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x47 }, 0, .none },
137 .{ .cmova, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x47 }, 0, .long },
138 .{ .cmovae, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x43 }, 0, .none },
139 .{ .cmovae, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x43 }, 0, .none },
140 .{ .cmovae, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x43 }, 0, .long },
141 .{ .cmovb, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x42 }, 0, .none },
142 .{ .cmovb, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x42 }, 0, .none },
143 .{ .cmovb, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x42 }, 0, .long },
144 .{ .cmovbe, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x46 }, 0, .none },
145 .{ .cmovbe, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x46 }, 0, .none },
146 .{ .cmovbe, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x46 }, 0, .long },
147 .{ .cmovc, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x42 }, 0, .none },
148 .{ .cmovc, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x42 }, 0, .none },
149 .{ .cmovc, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x42 }, 0, .long },
150 .{ .cmove, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x44 }, 0, .none },
151 .{ .cmove, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x44 }, 0, .none },
152 .{ .cmove, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x44 }, 0, .long },
153 .{ .cmovg, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4f }, 0, .none },
154 .{ .cmovg, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4f }, 0, .none },
155 .{ .cmovg, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4f }, 0, .long },
156 .{ .cmovge, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4d }, 0, .none },
157 .{ .cmovge, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4d }, 0, .none },
158 .{ .cmovge, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4d }, 0, .long },
159 .{ .cmovl, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4c }, 0, .none },
160 .{ .cmovl, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4c }, 0, .none },
161 .{ .cmovl, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4c }, 0, .long },
162 .{ .cmovle, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4e }, 0, .none },
163 .{ .cmovle, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4e }, 0, .none },
164 .{ .cmovle, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4e }, 0, .long },
165 .{ .cmovna, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x46 }, 0, .none },
166 .{ .cmovna, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x46 }, 0, .none },
167 .{ .cmovna, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x46 }, 0, .long },
168 .{ .cmovnae, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x42 }, 0, .none },
169 .{ .cmovnae, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x42 }, 0, .none },
170 .{ .cmovnae, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x42 }, 0, .long },
171 .{ .cmovnb, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x43 }, 0, .none },
172 .{ .cmovnb, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x43 }, 0, .none },
173 .{ .cmovnb, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x43 }, 0, .long },
174 .{ .cmovnbe, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x47 }, 0, .none },
175 .{ .cmovnbe, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x47 }, 0, .none },
176 .{ .cmovnbe, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x47 }, 0, .long },
177 .{ .cmovnc, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x43 }, 0, .none },
178 .{ .cmovnc, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x43 }, 0, .none },
179 .{ .cmovnc, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x43 }, 0, .long },
180 .{ .cmovne, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x45 }, 0, .none },
181 .{ .cmovne, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x45 }, 0, .none },
182 .{ .cmovne, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x45 }, 0, .long },
183 .{ .cmovng, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4e }, 0, .none },
184 .{ .cmovng, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4e }, 0, .none },
185 .{ .cmovng, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4e }, 0, .long },
186 .{ .cmovnge, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4c }, 0, .none },
187 .{ .cmovnge, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4c }, 0, .none },
188 .{ .cmovnge, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4c }, 0, .long },
189 .{ .cmovnl, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4d }, 0, .none },
190 .{ .cmovnl, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4d }, 0, .none },
191 .{ .cmovnl, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4d }, 0, .long },
192 .{ .cmovnle, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4f }, 0, .none },
193 .{ .cmovnle, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4f }, 0, .none },
194 .{ .cmovnle, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4f }, 0, .long },
195 .{ .cmovno, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x41 }, 0, .none },
196 .{ .cmovno, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x41 }, 0, .none },
197 .{ .cmovno, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x41 }, 0, .long },
198 .{ .cmovnp, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4b }, 0, .none },
199 .{ .cmovnp, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4b }, 0, .none },
200 .{ .cmovnp, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4b }, 0, .long },
201 .{ .cmovns, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x49 }, 0, .none },
202 .{ .cmovns, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x49 }, 0, .none },
203 .{ .cmovns, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x49 }, 0, .long },
204 .{ .cmovnz, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x45 }, 0, .none },
205 .{ .cmovnz, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x45 }, 0, .none },
206 .{ .cmovnz, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x45 }, 0, .long },
207 .{ .cmovo, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x40 }, 0, .none },
208 .{ .cmovo, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x40 }, 0, .none },
209 .{ .cmovo, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x40 }, 0, .long },
210 .{ .cmovp, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4a }, 0, .none },
211 .{ .cmovp, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4a }, 0, .none },
212 .{ .cmovp, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4a }, 0, .long },
213 .{ .cmovpe, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4a }, 0, .none },
214 .{ .cmovpe, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4a }, 0, .none },
215 .{ .cmovpe, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4a }, 0, .long },
216 .{ .cmovpo, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4b }, 0, .none },
217 .{ .cmovpo, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4b }, 0, .none },
218 .{ .cmovpo, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4b }, 0, .long },
219 .{ .cmovs, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x48 }, 0, .none },
220 .{ .cmovs, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x48 }, 0, .none },
221 .{ .cmovs, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x48 }, 0, .long },
222 .{ .cmovz, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x44 }, 0, .none },
223 .{ .cmovz, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x44 }, 0, .none },
224 .{ .cmovz, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x44 }, 0, .long },
225
226 .{ .cmp, .zi, .al, .imm8, .none, .none, &.{ 0x3c }, 0, .none },
227 .{ .cmp, .zi, .ax, .imm16, .none, .none, &.{ 0x3d }, 0, .none },
228 .{ .cmp, .zi, .eax, .imm32, .none, .none, &.{ 0x3d }, 0, .none },
229 .{ .cmp, .zi, .rax, .imm32s, .none, .none, &.{ 0x3d }, 0, .long },
230 .{ .cmp, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 7, .none },
231 .{ .cmp, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 7, .rex },
232 .{ .cmp, .mi, .rm16, .imm16, .none, .none, &.{ 0x81 }, 7, .none },
233 .{ .cmp, .mi, .rm32, .imm32, .none, .none, &.{ 0x81 }, 7, .none },
234 .{ .cmp, .mi, .rm64, .imm32s, .none, .none, &.{ 0x81 }, 7, .long },
235 .{ .cmp, .mi, .rm16, .imm8s, .none, .none, &.{ 0x83 }, 7, .none },
236 .{ .cmp, .mi, .rm32, .imm8s, .none, .none, &.{ 0x83 }, 7, .none },
237 .{ .cmp, .mi, .rm64, .imm8s, .none, .none, &.{ 0x83 }, 7, .long },
238 .{ .cmp, .mr, .rm8, .r8, .none, .none, &.{ 0x38 }, 0, .none },
239 .{ .cmp, .mr, .rm8, .r8, .none, .none, &.{ 0x38 }, 0, .rex },
240 .{ .cmp, .mr, .rm16, .r16, .none, .none, &.{ 0x39 }, 0, .none },
241 .{ .cmp, .mr, .rm32, .r32, .none, .none, &.{ 0x39 }, 0, .none },
242 .{ .cmp, .mr, .rm64, .r64, .none, .none, &.{ 0x39 }, 0, .long },
243 .{ .cmp, .rm, .r8, .rm8, .none, .none, &.{ 0x3a }, 0, .none },
244 .{ .cmp, .rm, .r8, .rm8, .none, .none, &.{ 0x3a }, 0, .rex },
245 .{ .cmp, .rm, .r16, .rm16, .none, .none, &.{ 0x3b }, 0, .none },
246 .{ .cmp, .rm, .r32, .rm32, .none, .none, &.{ 0x3b }, 0, .none },
247 .{ .cmp, .rm, .r64, .rm64, .none, .none, &.{ 0x3b }, 0, .long },
248
249 .{ .cmps, .np, .m8, .m8, .none, .none, &.{ 0xa6 }, 0, .none },
250 .{ .cmps, .np, .m16, .m16, .none, .none, &.{ 0xa7 }, 0, .none },
251 .{ .cmps, .np, .m32, .m32, .none, .none, &.{ 0xa7 }, 0, .none },
252 .{ .cmps, .np, .m64, .m64, .none, .none, &.{ 0xa7 }, 0, .long },
253 .{ .cmpsb, .np, .none, .none, .none, .none, &.{ 0xa6 }, 0, .none },
254 .{ .cmpsw, .np, .none, .none, .none, .none, &.{ 0xa7 }, 0, .short },
255 .{ .cmpsd, .np, .none, .none, .none, .none, &.{ 0xa7 }, 0, .none },
256 .{ .cmpsq, .np, .none, .none, .none, .none, &.{ 0xa7 }, 0, .long },
257
258 .{ .cmpxchg, .mr, .rm8, .r8, .none, .none, &.{ 0x0f, 0xb0 }, 0, .none },
259 .{ .cmpxchg, .mr, .rm8, .r8, .none, .none, &.{ 0x0f, 0xb0 }, 0, .rex },
260 .{ .cmpxchg, .mr, .rm16, .r16, .none, .none, &.{ 0x0f, 0xb1 }, 0, .none },
261 .{ .cmpxchg, .mr, .rm32, .r32, .none, .none, &.{ 0x0f, 0xb1 }, 0, .none },
262 .{ .cmpxchg, .mr, .rm64, .r64, .none, .none, &.{ 0x0f, 0xb1 }, 0, .long },
263
264 .{ .cmpxchg8b , .m, .m64, .none, .none, .none, &.{ 0x0f, 0xc7 }, 1, .none },
265 .{ .cmpxchg16b, .m, .m128, .none, .none, .none, &.{ 0x0f, 0xc7 }, 1, .long },
266
267 .{ .div, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 6, .none },
268 .{ .div, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 6, .rex },
269 .{ .div, .m, .rm16, .none, .none, .none, &.{ 0xf7 }, 6, .none },
270 .{ .div, .m, .rm32, .none, .none, .none, &.{ 0xf7 }, 6, .none },
271 .{ .div, .m, .rm64, .none, .none, .none, &.{ 0xf7 }, 6, .long },
272
273 .{ .fisttp, .m, .m16, .none, .none, .none, &.{ 0xdf }, 1, .fpu },
274 .{ .fisttp, .m, .m32, .none, .none, .none, &.{ 0xdb }, 1, .fpu },
275 .{ .fisttp, .m, .m64, .none, .none, .none, &.{ 0xdd }, 1, .fpu },
276
277 .{ .fld, .m, .m32, .none, .none, .none, &.{ 0xd9 }, 0, .fpu },
278 .{ .fld, .m, .m64, .none, .none, .none, &.{ 0xdd }, 0, .fpu },
279 .{ .fld, .m, .m80, .none, .none, .none, &.{ 0xdb }, 5, .fpu },
280
281 .{ .idiv, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 7, .none },
282 .{ .idiv, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 7, .rex },
283 .{ .idiv, .m, .rm16, .none, .none, .none, &.{ 0xf7 }, 7, .none },
284 .{ .idiv, .m, .rm32, .none, .none, .none, &.{ 0xf7 }, 7, .none },
285 .{ .idiv, .m, .rm64, .none, .none, .none, &.{ 0xf7 }, 7, .long },
286
287 .{ .imul, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 5, .none },
288 .{ .imul, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 5, .rex },
289 .{ .imul, .m, .rm16, .none, .none, .none, &.{ 0xf7 }, 5, .none },
290 .{ .imul, .m, .rm32, .none, .none, .none, &.{ 0xf7 }, 5, .none },
291 .{ .imul, .m, .rm64, .none, .none, .none, &.{ 0xf7 }, 5, .long },
292 .{ .imul, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0xaf }, 0, .none },
293 .{ .imul, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0xaf }, 0, .none },
294 .{ .imul, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0xaf }, 0, .long },
295 .{ .imul, .rmi, .r16, .rm16, .imm8s, .none, &.{ 0x6b }, 0, .none },
296 .{ .imul, .rmi, .r32, .rm32, .imm8s, .none, &.{ 0x6b }, 0, .none },
297 .{ .imul, .rmi, .r64, .rm64, .imm8s, .none, &.{ 0x6b }, 0, .long },
298 .{ .imul, .rmi, .r16, .rm16, .imm16, .none, &.{ 0x69 }, 0, .none },
299 .{ .imul, .rmi, .r32, .rm32, .imm32, .none, &.{ 0x69 }, 0, .none },
300 .{ .imul, .rmi, .r64, .rm64, .imm32, .none, &.{ 0x69 }, 0, .long },
301
302 .{ .int3, .np, .none, .none, .none, .none, &.{ 0xcc }, 0, .none },
303
304 .{ .ja, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x87 }, 0, .none },
305 .{ .jae, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x83 }, 0, .none },
306 .{ .jb, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x82 }, 0, .none },
307 .{ .jbe, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x86 }, 0, .none },
308 .{ .jc, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x82 }, 0, .none },
309 .{ .jrcxz, .d, .rel32, .none, .none, .none, &.{ 0xe3 }, 0, .none },
310 .{ .je, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x84 }, 0, .none },
311 .{ .jg, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8f }, 0, .none },
312 .{ .jge, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8d }, 0, .none },
313 .{ .jl, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8c }, 0, .none },
314 .{ .jle, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8e }, 0, .none },
315 .{ .jna, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x86 }, 0, .none },
316 .{ .jnae, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x82 }, 0, .none },
317 .{ .jnb, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x83 }, 0, .none },
318 .{ .jnbe, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x87 }, 0, .none },
319 .{ .jnc, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x83 }, 0, .none },
320 .{ .jne, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x85 }, 0, .none },
321 .{ .jng, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8e }, 0, .none },
322 .{ .jnge, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8c }, 0, .none },
323 .{ .jnl, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8d }, 0, .none },
324 .{ .jnle, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8f }, 0, .none },
325 .{ .jno, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x81 }, 0, .none },
326 .{ .jnp, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8b }, 0, .none },
327 .{ .jns, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x89 }, 0, .none },
328 .{ .jnz, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x85 }, 0, .none },
329 .{ .jo, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x80 }, 0, .none },
330 .{ .jp, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8a }, 0, .none },
331 .{ .jpe, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8a }, 0, .none },
332 .{ .jpo, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8b }, 0, .none },
333 .{ .js, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x88 }, 0, .none },
334 .{ .jz, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x84 }, 0, .none },
335
336 .{ .jmp, .d, .rel32, .none, .none, .none, &.{ 0xe9 }, 0, .none },
337 .{ .jmp, .m, .rm64, .none, .none, .none, &.{ 0xff }, 4, .none },
338
339 .{ .lea, .rm, .r16, .m, .none, .none, &.{ 0x8d }, 0, .none },
340 .{ .lea, .rm, .r32, .m, .none, .none, &.{ 0x8d }, 0, .none },
341 .{ .lea, .rm, .r64, .m, .none, .none, &.{ 0x8d }, 0, .long },
342
343 .{ .lfence, .np, .none, .none, .none, .none, &.{ 0x0f, 0xae, 0xe8 }, 0, .none },
344
345 .{ .lods, .np, .m8, .none, .none, .none, &.{ 0xac }, 0, .none },
346 .{ .lods, .np, .m16, .none, .none, .none, &.{ 0xad }, 0, .none },
347 .{ .lods, .np, .m32, .none, .none, .none, &.{ 0xad }, 0, .none },
348 .{ .lods, .np, .m64, .none, .none, .none, &.{ 0xad }, 0, .long },
349 .{ .lodsb, .np, .none, .none, .none, .none, &.{ 0xac }, 0, .none },
350 .{ .lodsw, .np, .none, .none, .none, .none, &.{ 0xad }, 0, .short },
351 .{ .lodsd, .np, .none, .none, .none, .none, &.{ 0xad }, 0, .none },
352 .{ .lodsq, .np, .none, .none, .none, .none, &.{ 0xad }, 0, .long },
353
354 .{ .lzcnt, .rm, .r16, .rm16, .none, .none, &.{ 0xf3, 0x0f, 0xbd }, 0, .none },
355 .{ .lzcnt, .rm, .r32, .rm32, .none, .none, &.{ 0xf3, 0x0f, 0xbd }, 0, .none },
356 .{ .lzcnt, .rm, .r64, .rm64, .none, .none, &.{ 0xf3, 0x0f, 0xbd }, 0, .long },
357
358 .{ .mfence, .np, .none, .none, .none, .none, &.{ 0x0f, 0xae, 0xf0 }, 0, .none },
359
360 .{ .mov, .mr, .rm8, .r8, .none, .none, &.{ 0x88 }, 0, .none },
361 .{ .mov, .mr, .rm8, .r8, .none, .none, &.{ 0x88 }, 0, .rex },
362 .{ .mov, .mr, .rm16, .r16, .none, .none, &.{ 0x89 }, 0, .none },
363 .{ .mov, .mr, .rm32, .r32, .none, .none, &.{ 0x89 }, 0, .none },
364 .{ .mov, .mr, .rm64, .r64, .none, .none, &.{ 0x89 }, 0, .long },
365 .{ .mov, .rm, .r8, .rm8, .none, .none, &.{ 0x8a }, 0, .none },
366 .{ .mov, .rm, .r8, .rm8, .none, .none, &.{ 0x8a }, 0, .rex },
367 .{ .mov, .rm, .r16, .rm16, .none, .none, &.{ 0x8b }, 0, .none },
368 .{ .mov, .rm, .r32, .rm32, .none, .none, &.{ 0x8b }, 0, .none },
369 .{ .mov, .rm, .r64, .rm64, .none, .none, &.{ 0x8b }, 0, .long },
370 .{ .mov, .mr, .rm16, .sreg, .none, .none, &.{ 0x8c }, 0, .none },
371 .{ .mov, .mr, .rm64, .sreg, .none, .none, &.{ 0x8c }, 0, .long },
372 .{ .mov, .rm, .sreg, .rm16, .none, .none, &.{ 0x8e }, 0, .none },
373 .{ .mov, .rm, .sreg, .rm64, .none, .none, &.{ 0x8e }, 0, .long },
374 .{ .mov, .fd, .al, .moffs, .none, .none, &.{ 0xa0 }, 0, .none },
375 .{ .mov, .fd, .ax, .moffs, .none, .none, &.{ 0xa1 }, 0, .none },
376 .{ .mov, .fd, .eax, .moffs, .none, .none, &.{ 0xa1 }, 0, .none },
377 .{ .mov, .fd, .rax, .moffs, .none, .none, &.{ 0xa1 }, 0, .long },
378 .{ .mov, .td, .moffs, .al, .none, .none, &.{ 0xa2 }, 0, .none },
379 .{ .mov, .td, .moffs, .ax, .none, .none, &.{ 0xa3 }, 0, .none },
380 .{ .mov, .td, .moffs, .eax, .none, .none, &.{ 0xa3 }, 0, .none },
381 .{ .mov, .td, .moffs, .rax, .none, .none, &.{ 0xa3 }, 0, .long },
382 .{ .mov, .oi, .r8, .imm8, .none, .none, &.{ 0xb0 }, 0, .none },
383 .{ .mov, .oi, .r8, .imm8, .none, .none, &.{ 0xb0 }, 0, .rex },
384 .{ .mov, .oi, .r16, .imm16, .none, .none, &.{ 0xb8 }, 0, .none },
385 .{ .mov, .oi, .r32, .imm32, .none, .none, &.{ 0xb8 }, 0, .none },
386 .{ .mov, .oi, .r64, .imm64, .none, .none, &.{ 0xb8 }, 0, .long },
387 .{ .mov, .mi, .rm8, .imm8, .none, .none, &.{ 0xc6 }, 0, .none },
388 .{ .mov, .mi, .rm8, .imm8, .none, .none, &.{ 0xc6 }, 0, .rex },
389 .{ .mov, .mi, .rm16, .imm16, .none, .none, &.{ 0xc7 }, 0, .none },
390 .{ .mov, .mi, .rm32, .imm32, .none, .none, &.{ 0xc7 }, 0, .none },
391 .{ .mov, .mi, .rm64, .imm32s, .none, .none, &.{ 0xc7 }, 0, .long },
392
393 .{ .movbe, .rm, .r16, .m16, .none, .none, &.{ 0x0f, 0x38, 0xf0 }, 0, .none },
394 .{ .movbe, .rm, .r32, .m32, .none, .none, &.{ 0x0f, 0x38, 0xf0 }, 0, .none },
395 .{ .movbe, .rm, .r64, .m64, .none, .none, &.{ 0x0f, 0x38, 0xf0 }, 0, .long },
396 .{ .movbe, .mr, .m16, .r16, .none, .none, &.{ 0x0f, 0x38, 0xf1 }, 0, .none },
397 .{ .movbe, .mr, .m32, .r32, .none, .none, &.{ 0x0f, 0x38, 0xf1 }, 0, .none },
398 .{ .movbe, .mr, .m64, .r64, .none, .none, &.{ 0x0f, 0x38, 0xf1 }, 0, .long },
399
400 .{ .movs, .np, .m8, .m8, .none, .none, &.{ 0xa4 }, 0, .none },
401 .{ .movs, .np, .m16, .m16, .none, .none, &.{ 0xa5 }, 0, .none },
402 .{ .movs, .np, .m32, .m32, .none, .none, &.{ 0xa5 }, 0, .none },
403 .{ .movs, .np, .m64, .m64, .none, .none, &.{ 0xa5 }, 0, .long },
404 .{ .movsb, .np, .none, .none, .none, .none, &.{ 0xa4 }, 0, .none },
405 .{ .movsw, .np, .none, .none, .none, .none, &.{ 0xa5 }, 0, .short },
406 .{ .movsd, .np, .none, .none, .none, .none, &.{ 0xa5 }, 0, .none },
407 .{ .movsq, .np, .none, .none, .none, .none, &.{ 0xa5 }, 0, .long },
408
409 .{ .movsx, .rm, .r16, .rm8, .none, .none, &.{ 0x0f, 0xbe }, 0, .none },
410 .{ .movsx, .rm, .r16, .rm8, .none, .none, &.{ 0x0f, 0xbe }, 0, .rex },
411 .{ .movsx, .rm, .r32, .rm8, .none, .none, &.{ 0x0f, 0xbe }, 0, .none },
412 .{ .movsx, .rm, .r32, .rm8, .none, .none, &.{ 0x0f, 0xbe }, 0, .rex },
413 .{ .movsx, .rm, .r64, .rm8, .none, .none, &.{ 0x0f, 0xbe }, 0, .long },
414 .{ .movsx, .rm, .r32, .rm16, .none, .none, &.{ 0x0f, 0xbf }, 0, .none },
415 .{ .movsx, .rm, .r64, .rm16, .none, .none, &.{ 0x0f, 0xbf }, 0, .long },
124 .{ .call, .d, &.{ .rel32 }, &.{ 0xe8 }, 0, .none },
125 .{ .call, .m, &.{ .rm64 }, &.{ 0xff }, 2, .none },
126
127 .{ .cbw, .np, &.{ .o16 }, &.{ 0x98 }, 0, .none },
128 .{ .cwde, .np, &.{ .o32 }, &.{ 0x98 }, 0, .none },
129 .{ .cdqe, .np, &.{ .o64 }, &.{ 0x98 }, 0, .long },
130
131 .{ .cwd, .np, &.{ .o16 }, &.{ 0x99 }, 0, .none },
132 .{ .cdq, .np, &.{ .o32 }, &.{ 0x99 }, 0, .none },
133 .{ .cqo, .np, &.{ .o64 }, &.{ 0x99 }, 0, .long },
134
135 .{ .cmova, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x47 }, 0, .none },
136 .{ .cmova, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x47 }, 0, .none },
137 .{ .cmova, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x47 }, 0, .long },
138 .{ .cmovae, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x43 }, 0, .none },
139 .{ .cmovae, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x43 }, 0, .none },
140 .{ .cmovae, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x43 }, 0, .long },
141 .{ .cmovb, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x42 }, 0, .none },
142 .{ .cmovb, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x42 }, 0, .none },
143 .{ .cmovb, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x42 }, 0, .long },
144 .{ .cmovbe, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x46 }, 0, .none },
145 .{ .cmovbe, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x46 }, 0, .none },
146 .{ .cmovbe, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x46 }, 0, .long },
147 .{ .cmovc, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x42 }, 0, .none },
148 .{ .cmovc, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x42 }, 0, .none },
149 .{ .cmovc, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x42 }, 0, .long },
150 .{ .cmove, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x44 }, 0, .none },
151 .{ .cmove, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x44 }, 0, .none },
152 .{ .cmove, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x44 }, 0, .long },
153 .{ .cmovg, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4f }, 0, .none },
154 .{ .cmovg, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4f }, 0, .none },
155 .{ .cmovg, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4f }, 0, .long },
156 .{ .cmovge, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4d }, 0, .none },
157 .{ .cmovge, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4d }, 0, .none },
158 .{ .cmovge, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4d }, 0, .long },
159 .{ .cmovl, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4c }, 0, .none },
160 .{ .cmovl, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4c }, 0, .none },
161 .{ .cmovl, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4c }, 0, .long },
162 .{ .cmovle, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4e }, 0, .none },
163 .{ .cmovle, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4e }, 0, .none },
164 .{ .cmovle, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4e }, 0, .long },
165 .{ .cmovna, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x46 }, 0, .none },
166 .{ .cmovna, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x46 }, 0, .none },
167 .{ .cmovna, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x46 }, 0, .long },
168 .{ .cmovnae, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x42 }, 0, .none },
169 .{ .cmovnae, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x42 }, 0, .none },
170 .{ .cmovnae, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x42 }, 0, .long },
171 .{ .cmovnb, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x43 }, 0, .none },
172 .{ .cmovnb, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x43 }, 0, .none },
173 .{ .cmovnb, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x43 }, 0, .long },
174 .{ .cmovnbe, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x47 }, 0, .none },
175 .{ .cmovnbe, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x47 }, 0, .none },
176 .{ .cmovnbe, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x47 }, 0, .long },
177 .{ .cmovnc, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x43 }, 0, .none },
178 .{ .cmovnc, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x43 }, 0, .none },
179 .{ .cmovnc, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x43 }, 0, .long },
180 .{ .cmovne, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x45 }, 0, .none },
181 .{ .cmovne, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x45 }, 0, .none },
182 .{ .cmovne, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x45 }, 0, .long },
183 .{ .cmovng, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4e }, 0, .none },
184 .{ .cmovng, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4e }, 0, .none },
185 .{ .cmovng, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4e }, 0, .long },
186 .{ .cmovnge, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4c }, 0, .none },
187 .{ .cmovnge, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4c }, 0, .none },
188 .{ .cmovnge, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4c }, 0, .long },
189 .{ .cmovnl, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4d }, 0, .none },
190 .{ .cmovnl, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4d }, 0, .none },
191 .{ .cmovnl, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4d }, 0, .long },
192 .{ .cmovnle, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4f }, 0, .none },
193 .{ .cmovnle, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4f }, 0, .none },
194 .{ .cmovnle, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4f }, 0, .long },
195 .{ .cmovno, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x41 }, 0, .none },
196 .{ .cmovno, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x41 }, 0, .none },
197 .{ .cmovno, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x41 }, 0, .long },
198 .{ .cmovnp, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4b }, 0, .none },
199 .{ .cmovnp, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4b }, 0, .none },
200 .{ .cmovnp, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4b }, 0, .long },
201 .{ .cmovns, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x49 }, 0, .none },
202 .{ .cmovns, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x49 }, 0, .none },
203 .{ .cmovns, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x49 }, 0, .long },
204 .{ .cmovnz, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x45 }, 0, .none },
205 .{ .cmovnz, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x45 }, 0, .none },
206 .{ .cmovnz, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x45 }, 0, .long },
207 .{ .cmovo, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x40 }, 0, .none },
208 .{ .cmovo, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x40 }, 0, .none },
209 .{ .cmovo, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x40 }, 0, .long },
210 .{ .cmovp, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4a }, 0, .none },
211 .{ .cmovp, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4a }, 0, .none },
212 .{ .cmovp, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4a }, 0, .long },
213 .{ .cmovpe, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4a }, 0, .none },
214 .{ .cmovpe, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4a }, 0, .none },
215 .{ .cmovpe, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4a }, 0, .long },
216 .{ .cmovpo, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4b }, 0, .none },
217 .{ .cmovpo, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4b }, 0, .none },
218 .{ .cmovpo, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4b }, 0, .long },
219 .{ .cmovs, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x48 }, 0, .none },
220 .{ .cmovs, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x48 }, 0, .none },
221 .{ .cmovs, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x48 }, 0, .long },
222 .{ .cmovz, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x44 }, 0, .none },
223 .{ .cmovz, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x44 }, 0, .none },
224 .{ .cmovz, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x44 }, 0, .long },
225
226 .{ .cmp, .zi, &.{ .al, .imm8 }, &.{ 0x3c }, 0, .none },
227 .{ .cmp, .zi, &.{ .ax, .imm16 }, &.{ 0x3d }, 0, .none },
228 .{ .cmp, .zi, &.{ .eax, .imm32 }, &.{ 0x3d }, 0, .none },
229 .{ .cmp, .zi, &.{ .rax, .imm32s }, &.{ 0x3d }, 0, .long },
230 .{ .cmp, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 7, .none },
231 .{ .cmp, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 7, .rex },
232 .{ .cmp, .mi, &.{ .rm16, .imm16 }, &.{ 0x81 }, 7, .none },
233 .{ .cmp, .mi, &.{ .rm32, .imm32 }, &.{ 0x81 }, 7, .none },
234 .{ .cmp, .mi, &.{ .rm64, .imm32s }, &.{ 0x81 }, 7, .long },
235 .{ .cmp, .mi, &.{ .rm16, .imm8s }, &.{ 0x83 }, 7, .none },
236 .{ .cmp, .mi, &.{ .rm32, .imm8s }, &.{ 0x83 }, 7, .none },
237 .{ .cmp, .mi, &.{ .rm64, .imm8s }, &.{ 0x83 }, 7, .long },
238 .{ .cmp, .mr, &.{ .rm8, .r8 }, &.{ 0x38 }, 0, .none },
239 .{ .cmp, .mr, &.{ .rm8, .r8 }, &.{ 0x38 }, 0, .rex },
240 .{ .cmp, .mr, &.{ .rm16, .r16 }, &.{ 0x39 }, 0, .none },
241 .{ .cmp, .mr, &.{ .rm32, .r32 }, &.{ 0x39 }, 0, .none },
242 .{ .cmp, .mr, &.{ .rm64, .r64 }, &.{ 0x39 }, 0, .long },
243 .{ .cmp, .rm, &.{ .r8, .rm8 }, &.{ 0x3a }, 0, .none },
244 .{ .cmp, .rm, &.{ .r8, .rm8 }, &.{ 0x3a }, 0, .rex },
245 .{ .cmp, .rm, &.{ .r16, .rm16 }, &.{ 0x3b }, 0, .none },
246 .{ .cmp, .rm, &.{ .r32, .rm32 }, &.{ 0x3b }, 0, .none },
247 .{ .cmp, .rm, &.{ .r64, .rm64 }, &.{ 0x3b }, 0, .long },
248
249 .{ .cmps, .np, &.{ .m8, .m8 }, &.{ 0xa6 }, 0, .none },
250 .{ .cmps, .np, &.{ .m16, .m16 }, &.{ 0xa7 }, 0, .none },
251 .{ .cmps, .np, &.{ .m32, .m32 }, &.{ 0xa7 }, 0, .none },
252 .{ .cmps, .np, &.{ .m64, .m64 }, &.{ 0xa7 }, 0, .long },
253
254 .{ .cmpsb, .np, &.{}, &.{ 0xa6 }, 0, .none },
255 .{ .cmpsw, .np, &.{}, &.{ 0xa7 }, 0, .short },
256 .{ .cmpsd, .np, &.{}, &.{ 0xa7 }, 0, .none },
257 .{ .cmpsq, .np, &.{}, &.{ 0xa7 }, 0, .long },
258
259 .{ .cmpxchg, .mr, &.{ .rm8, .r8 }, &.{ 0x0f, 0xb0 }, 0, .none },
260 .{ .cmpxchg, .mr, &.{ .rm8, .r8 }, &.{ 0x0f, 0xb0 }, 0, .rex },
261 .{ .cmpxchg, .mr, &.{ .rm16, .r16 }, &.{ 0x0f, 0xb1 }, 0, .none },
262 .{ .cmpxchg, .mr, &.{ .rm32, .r32 }, &.{ 0x0f, 0xb1 }, 0, .none },
263 .{ .cmpxchg, .mr, &.{ .rm64, .r64 }, &.{ 0x0f, 0xb1 }, 0, .long },
264
265 .{ .cmpxchg8b , .m, &.{ .m64 }, &.{ 0x0f, 0xc7 }, 1, .none },
266 .{ .cmpxchg16b, .m, &.{ .m128 }, &.{ 0x0f, 0xc7 }, 1, .long },
267
268 .{ .div, .m, &.{ .rm8 }, &.{ 0xf6 }, 6, .none },
269 .{ .div, .m, &.{ .rm8 }, &.{ 0xf6 }, 6, .rex },
270 .{ .div, .m, &.{ .rm16 }, &.{ 0xf7 }, 6, .none },
271 .{ .div, .m, &.{ .rm32 }, &.{ 0xf7 }, 6, .none },
272 .{ .div, .m, &.{ .rm64 }, &.{ 0xf7 }, 6, .long },
273
274 .{ .fisttp, .m, &.{ .m16 }, &.{ 0xdf }, 1, .fpu },
275 .{ .fisttp, .m, &.{ .m32 }, &.{ 0xdb }, 1, .fpu },
276 .{ .fisttp, .m, &.{ .m64 }, &.{ 0xdd }, 1, .fpu },
277
278 .{ .fld, .m, &.{ .m32 }, &.{ 0xd9 }, 0, .fpu },
279 .{ .fld, .m, &.{ .m64 }, &.{ 0xdd }, 0, .fpu },
280 .{ .fld, .m, &.{ .m80 }, &.{ 0xdb }, 5, .fpu },
281
282 .{ .idiv, .m, &.{ .rm8 }, &.{ 0xf6 }, 7, .none },
283 .{ .idiv, .m, &.{ .rm8 }, &.{ 0xf6 }, 7, .rex },
284 .{ .idiv, .m, &.{ .rm16 }, &.{ 0xf7 }, 7, .none },
285 .{ .idiv, .m, &.{ .rm32 }, &.{ 0xf7 }, 7, .none },
286 .{ .idiv, .m, &.{ .rm64 }, &.{ 0xf7 }, 7, .long },
287
288 .{ .imul, .m, &.{ .rm8 }, &.{ 0xf6 }, 5, .none },
289 .{ .imul, .m, &.{ .rm8 }, &.{ 0xf6 }, 5, .rex },
290 .{ .imul, .m, &.{ .rm16, }, &.{ 0xf7 }, 5, .none },
291 .{ .imul, .m, &.{ .rm32, }, &.{ 0xf7 }, 5, .none },
292 .{ .imul, .m, &.{ .rm64, }, &.{ 0xf7 }, 5, .long },
293 .{ .imul, .rm, &.{ .r16, .rm16, }, &.{ 0x0f, 0xaf }, 0, .none },
294 .{ .imul, .rm, &.{ .r32, .rm32, }, &.{ 0x0f, 0xaf }, 0, .none },
295 .{ .imul, .rm, &.{ .r64, .rm64, }, &.{ 0x0f, 0xaf }, 0, .long },
296 .{ .imul, .rmi, &.{ .r16, .rm16, .imm8s }, &.{ 0x6b }, 0, .none },
297 .{ .imul, .rmi, &.{ .r32, .rm32, .imm8s }, &.{ 0x6b }, 0, .none },
298 .{ .imul, .rmi, &.{ .r64, .rm64, .imm8s }, &.{ 0x6b }, 0, .long },
299 .{ .imul, .rmi, &.{ .r16, .rm16, .imm16 }, &.{ 0x69 }, 0, .none },
300 .{ .imul, .rmi, &.{ .r32, .rm32, .imm32 }, &.{ 0x69 }, 0, .none },
301 .{ .imul, .rmi, &.{ .r64, .rm64, .imm32 }, &.{ 0x69 }, 0, .long },
302
303 .{ .int3, .np, &.{}, &.{ 0xcc }, 0, .none },
304
305 .{ .ja, .d, &.{ .rel32 }, &.{ 0x0f, 0x87 }, 0, .none },
306 .{ .jae, .d, &.{ .rel32 }, &.{ 0x0f, 0x83 }, 0, .none },
307 .{ .jb, .d, &.{ .rel32 }, &.{ 0x0f, 0x82 }, 0, .none },
308 .{ .jbe, .d, &.{ .rel32 }, &.{ 0x0f, 0x86 }, 0, .none },
309 .{ .jc, .d, &.{ .rel32 }, &.{ 0x0f, 0x82 }, 0, .none },
310 .{ .jrcxz, .d, &.{ .rel32 }, &.{ 0xe3 }, 0, .none },
311 .{ .je, .d, &.{ .rel32 }, &.{ 0x0f, 0x84 }, 0, .none },
312 .{ .jg, .d, &.{ .rel32 }, &.{ 0x0f, 0x8f }, 0, .none },
313 .{ .jge, .d, &.{ .rel32 }, &.{ 0x0f, 0x8d }, 0, .none },
314 .{ .jl, .d, &.{ .rel32 }, &.{ 0x0f, 0x8c }, 0, .none },
315 .{ .jle, .d, &.{ .rel32 }, &.{ 0x0f, 0x8e }, 0, .none },
316 .{ .jna, .d, &.{ .rel32 }, &.{ 0x0f, 0x86 }, 0, .none },
317 .{ .jnae, .d, &.{ .rel32 }, &.{ 0x0f, 0x82 }, 0, .none },
318 .{ .jnb, .d, &.{ .rel32 }, &.{ 0x0f, 0x83 }, 0, .none },
319 .{ .jnbe, .d, &.{ .rel32 }, &.{ 0x0f, 0x87 }, 0, .none },
320 .{ .jnc, .d, &.{ .rel32 }, &.{ 0x0f, 0x83 }, 0, .none },
321 .{ .jne, .d, &.{ .rel32 }, &.{ 0x0f, 0x85 }, 0, .none },
322 .{ .jng, .d, &.{ .rel32 }, &.{ 0x0f, 0x8e }, 0, .none },
323 .{ .jnge, .d, &.{ .rel32 }, &.{ 0x0f, 0x8c }, 0, .none },
324 .{ .jnl, .d, &.{ .rel32 }, &.{ 0x0f, 0x8d }, 0, .none },
325 .{ .jnle, .d, &.{ .rel32 }, &.{ 0x0f, 0x8f }, 0, .none },
326 .{ .jno, .d, &.{ .rel32 }, &.{ 0x0f, 0x81 }, 0, .none },
327 .{ .jnp, .d, &.{ .rel32 }, &.{ 0x0f, 0x8b }, 0, .none },
328 .{ .jns, .d, &.{ .rel32 }, &.{ 0x0f, 0x89 }, 0, .none },
329 .{ .jnz, .d, &.{ .rel32 }, &.{ 0x0f, 0x85 }, 0, .none },
330 .{ .jo, .d, &.{ .rel32 }, &.{ 0x0f, 0x80 }, 0, .none },
331 .{ .jp, .d, &.{ .rel32 }, &.{ 0x0f, 0x8a }, 0, .none },
332 .{ .jpe, .d, &.{ .rel32 }, &.{ 0x0f, 0x8a }, 0, .none },
333 .{ .jpo, .d, &.{ .rel32 }, &.{ 0x0f, 0x8b }, 0, .none },
334 .{ .js, .d, &.{ .rel32 }, &.{ 0x0f, 0x88 }, 0, .none },
335 .{ .jz, .d, &.{ .rel32 }, &.{ 0x0f, 0x84 }, 0, .none },
336
337 .{ .jmp, .d, &.{ .rel32 }, &.{ 0xe9 }, 0, .none },
338 .{ .jmp, .m, &.{ .rm64 }, &.{ 0xff }, 4, .none },
339
340 .{ .lea, .rm, &.{ .r16, .m }, &.{ 0x8d }, 0, .none },
341 .{ .lea, .rm, &.{ .r32, .m }, &.{ 0x8d }, 0, .none },
342 .{ .lea, .rm, &.{ .r64, .m }, &.{ 0x8d }, 0, .long },
343
344 .{ .lfence, .np, &.{}, &.{ 0x0f, 0xae, 0xe8 }, 0, .none },
345
346 .{ .lods, .np, &.{ .m8 }, &.{ 0xac }, 0, .none },
347 .{ .lods, .np, &.{ .m16 }, &.{ 0xad }, 0, .none },
348 .{ .lods, .np, &.{ .m32 }, &.{ 0xad }, 0, .none },
349 .{ .lods, .np, &.{ .m64 }, &.{ 0xad }, 0, .long },
350
351 .{ .lodsb, .np, &.{}, &.{ 0xac }, 0, .none },
352 .{ .lodsw, .np, &.{}, &.{ 0xad }, 0, .short },
353 .{ .lodsd, .np, &.{}, &.{ 0xad }, 0, .none },
354 .{ .lodsq, .np, &.{}, &.{ 0xad }, 0, .long },
355
356 .{ .lzcnt, .rm, &.{ .r16, .rm16 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .none },
357 .{ .lzcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .none },
358 .{ .lzcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .long },
359
360 .{ .mfence, .np, &.{}, &.{ 0x0f, 0xae, 0xf0 }, 0, .none },
361
362 .{ .mov, .mr, &.{ .rm8, .r8 }, &.{ 0x88 }, 0, .none },
363 .{ .mov, .mr, &.{ .rm8, .r8 }, &.{ 0x88 }, 0, .rex },
364 .{ .mov, .mr, &.{ .rm16, .r16 }, &.{ 0x89 }, 0, .none },
365 .{ .mov, .mr, &.{ .rm32, .r32 }, &.{ 0x89 }, 0, .none },
366 .{ .mov, .mr, &.{ .rm64, .r64 }, &.{ 0x89 }, 0, .long },
367 .{ .mov, .rm, &.{ .r8, .rm8 }, &.{ 0x8a }, 0, .none },
368 .{ .mov, .rm, &.{ .r8, .rm8 }, &.{ 0x8a }, 0, .rex },
369 .{ .mov, .rm, &.{ .r16, .rm16 }, &.{ 0x8b }, 0, .none },
370 .{ .mov, .rm, &.{ .r32, .rm32 }, &.{ 0x8b }, 0, .none },
371 .{ .mov, .rm, &.{ .r64, .rm64 }, &.{ 0x8b }, 0, .long },
372 .{ .mov, .mr, &.{ .rm16, .sreg }, &.{ 0x8c }, 0, .none },
373 .{ .mov, .mr, &.{ .rm64, .sreg }, &.{ 0x8c }, 0, .long },
374 .{ .mov, .rm, &.{ .sreg, .rm16 }, &.{ 0x8e }, 0, .none },
375 .{ .mov, .rm, &.{ .sreg, .rm64 }, &.{ 0x8e }, 0, .long },
376 .{ .mov, .fd, &.{ .al, .moffs }, &.{ 0xa0 }, 0, .none },
377 .{ .mov, .fd, &.{ .ax, .moffs }, &.{ 0xa1 }, 0, .none },
378 .{ .mov, .fd, &.{ .eax, .moffs }, &.{ 0xa1 }, 0, .none },
379 .{ .mov, .fd, &.{ .rax, .moffs }, &.{ 0xa1 }, 0, .long },
380 .{ .mov, .td, &.{ .moffs, .al }, &.{ 0xa2 }, 0, .none },
381 .{ .mov, .td, &.{ .moffs, .ax }, &.{ 0xa3 }, 0, .none },
382 .{ .mov, .td, &.{ .moffs, .eax }, &.{ 0xa3 }, 0, .none },
383 .{ .mov, .td, &.{ .moffs, .rax }, &.{ 0xa3 }, 0, .long },
384 .{ .mov, .oi, &.{ .r8, .imm8 }, &.{ 0xb0 }, 0, .none },
385 .{ .mov, .oi, &.{ .r8, .imm8 }, &.{ 0xb0 }, 0, .rex },
386 .{ .mov, .oi, &.{ .r16, .imm16 }, &.{ 0xb8 }, 0, .none },
387 .{ .mov, .oi, &.{ .r32, .imm32 }, &.{ 0xb8 }, 0, .none },
388 .{ .mov, .oi, &.{ .r64, .imm64 }, &.{ 0xb8 }, 0, .long },
389 .{ .mov, .mi, &.{ .rm8, .imm8 }, &.{ 0xc6 }, 0, .none },
390 .{ .mov, .mi, &.{ .rm8, .imm8 }, &.{ 0xc6 }, 0, .rex },
391 .{ .mov, .mi, &.{ .rm16, .imm16 }, &.{ 0xc7 }, 0, .none },
392 .{ .mov, .mi, &.{ .rm32, .imm32 }, &.{ 0xc7 }, 0, .none },
393 .{ .mov, .mi, &.{ .rm64, .imm32s }, &.{ 0xc7 }, 0, .long },
394
395 .{ .movbe, .rm, &.{ .r16, .m16 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .none },
396 .{ .movbe, .rm, &.{ .r32, .m32 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .none },
397 .{ .movbe, .rm, &.{ .r64, .m64 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .long },
398 .{ .movbe, .mr, &.{ .m16, .r16 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .none },
399 .{ .movbe, .mr, &.{ .m32, .r32 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .none },
400 .{ .movbe, .mr, &.{ .m64, .r64 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .long },
401
402 .{ .movs, .np, &.{ .m8, .m8 }, &.{ 0xa4 }, 0, .none },
403 .{ .movs, .np, &.{ .m16, .m16 }, &.{ 0xa5 }, 0, .none },
404 .{ .movs, .np, &.{ .m32, .m32 }, &.{ 0xa5 }, 0, .none },
405 .{ .movs, .np, &.{ .m64, .m64 }, &.{ 0xa5 }, 0, .long },
406
407 .{ .movsb, .np, &.{}, &.{ 0xa4 }, 0, .none },
408 .{ .movsw, .np, &.{}, &.{ 0xa5 }, 0, .short },
409 .{ .movsd, .np, &.{}, &.{ 0xa5 }, 0, .none },
410 .{ .movsq, .np, &.{}, &.{ 0xa5 }, 0, .long },
411
412 .{ .movsx, .rm, &.{ .r16, .rm8 }, &.{ 0x0f, 0xbe }, 0, .none },
413 .{ .movsx, .rm, &.{ .r16, .rm8 }, &.{ 0x0f, 0xbe }, 0, .rex },
414 .{ .movsx, .rm, &.{ .r32, .rm8 }, &.{ 0x0f, 0xbe }, 0, .none },
415 .{ .movsx, .rm, &.{ .r32, .rm8 }, &.{ 0x0f, 0xbe }, 0, .rex },
416 .{ .movsx, .rm, &.{ .r64, .rm8 }, &.{ 0x0f, 0xbe }, 0, .long },
417 .{ .movsx, .rm, &.{ .r32, .rm16 }, &.{ 0x0f, 0xbf }, 0, .none },
418 .{ .movsx, .rm, &.{ .r64, .rm16 }, &.{ 0x0f, 0xbf }, 0, .long },
416419
417420 // This instruction is discouraged.
418 .{ .movsxd, .rm, .r32, .rm32, .none, .none, &.{ 0x63 }, 0, .none },
419 .{ .movsxd, .rm, .r64, .rm32, .none, .none, &.{ 0x63 }, 0, .long },
420
421 .{ .movzx, .rm, .r16, .rm8, .none, .none, &.{ 0x0f, 0xb6 }, 0, .none },
422 .{ .movzx, .rm, .r32, .rm8, .none, .none, &.{ 0x0f, 0xb6 }, 0, .none },
423 .{ .movzx, .rm, .r64, .rm8, .none, .none, &.{ 0x0f, 0xb6 }, 0, .long },
424 .{ .movzx, .rm, .r32, .rm16, .none, .none, &.{ 0x0f, 0xb7 }, 0, .none },
425 .{ .movzx, .rm, .r64, .rm16, .none, .none, &.{ 0x0f, 0xb7 }, 0, .long },
426
427 .{ .mul, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 4, .none },
428 .{ .mul, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 4, .rex },
429 .{ .mul, .m, .rm16, .none, .none, .none, &.{ 0xf7 }, 4, .none },
430 .{ .mul, .m, .rm32, .none, .none, .none, &.{ 0xf7 }, 4, .none },
431 .{ .mul, .m, .rm64, .none, .none, .none, &.{ 0xf7 }, 4, .long },
432
433 .{ .neg, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 3, .none },
434 .{ .neg, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 3, .rex },
435 .{ .neg, .m, .rm16, .none, .none, .none, &.{ 0xf7 }, 3, .none },
436 .{ .neg, .m, .rm32, .none, .none, .none, &.{ 0xf7 }, 3, .none },
437 .{ .neg, .m, .rm64, .none, .none, .none, &.{ 0xf7 }, 3, .long },
438
439 .{ .nop, .np, .none, .none, .none, .none, &.{ 0x90 }, 0, .none },
440
441 .{ .not, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 2, .none },
442 .{ .not, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 2, .rex },
443 .{ .not, .m, .rm16, .none, .none, .none, &.{ 0xf7 }, 2, .none },
444 .{ .not, .m, .rm32, .none, .none, .none, &.{ 0xf7 }, 2, .none },
445 .{ .not, .m, .rm64, .none, .none, .none, &.{ 0xf7 }, 2, .long },
446
447 .{ .@"or", .zi, .al, .imm8, .none, .none, &.{ 0x0c }, 0, .none },
448 .{ .@"or", .zi, .ax, .imm16, .none, .none, &.{ 0x0d }, 0, .none },
449 .{ .@"or", .zi, .eax, .imm32, .none, .none, &.{ 0x0d }, 0, .none },
450 .{ .@"or", .zi, .rax, .imm32s, .none, .none, &.{ 0x0d }, 0, .long },
451 .{ .@"or", .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 1, .none },
452 .{ .@"or", .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 1, .rex },
453 .{ .@"or", .mi, .rm16, .imm16, .none, .none, &.{ 0x81 }, 1, .none },
454 .{ .@"or", .mi, .rm32, .imm32, .none, .none, &.{ 0x81 }, 1, .none },
455 .{ .@"or", .mi, .rm64, .imm32s, .none, .none, &.{ 0x81 }, 1, .long },
456 .{ .@"or", .mi, .rm16, .imm8s, .none, .none, &.{ 0x83 }, 1, .none },
457 .{ .@"or", .mi, .rm32, .imm8s, .none, .none, &.{ 0x83 }, 1, .none },
458 .{ .@"or", .mi, .rm64, .imm8s, .none, .none, &.{ 0x83 }, 1, .long },
459 .{ .@"or", .mr, .rm8, .r8, .none, .none, &.{ 0x08 }, 0, .none },
460 .{ .@"or", .mr, .rm8, .r8, .none, .none, &.{ 0x08 }, 0, .rex },
461 .{ .@"or", .mr, .rm16, .r16, .none, .none, &.{ 0x09 }, 0, .none },
462 .{ .@"or", .mr, .rm32, .r32, .none, .none, &.{ 0x09 }, 0, .none },
463 .{ .@"or", .mr, .rm64, .r64, .none, .none, &.{ 0x09 }, 0, .long },
464 .{ .@"or", .rm, .r8, .rm8, .none, .none, &.{ 0x0a }, 0, .none },
465 .{ .@"or", .rm, .r8, .rm8, .none, .none, &.{ 0x0a }, 0, .rex },
466 .{ .@"or", .rm, .r16, .rm16, .none, .none, &.{ 0x0b }, 0, .none },
467 .{ .@"or", .rm, .r32, .rm32, .none, .none, &.{ 0x0b }, 0, .none },
468 .{ .@"or", .rm, .r64, .rm64, .none, .none, &.{ 0x0b }, 0, .long },
469
470 .{ .pop, .o, .r16, .none, .none, .none, &.{ 0x58 }, 0, .none },
471 .{ .pop, .o, .r64, .none, .none, .none, &.{ 0x58 }, 0, .none },
472 .{ .pop, .m, .rm16, .none, .none, .none, &.{ 0x8f }, 0, .none },
473 .{ .pop, .m, .rm64, .none, .none, .none, &.{ 0x8f }, 0, .none },
474
475 .{ .popcnt, .rm, .r16, .rm16, .none, .none, &.{ 0xf3, 0x0f, 0xb8 }, 0, .none },
476 .{ .popcnt, .rm, .r32, .rm32, .none, .none, &.{ 0xf3, 0x0f, 0xb8 }, 0, .none },
477 .{ .popcnt, .rm, .r64, .rm64, .none, .none, &.{ 0xf3, 0x0f, 0xb8 }, 0, .long },
478
479 .{ .push, .o, .r16, .none, .none, .none, &.{ 0x50 }, 0, .none },
480 .{ .push, .o, .r64, .none, .none, .none, &.{ 0x50 }, 0, .none },
481 .{ .push, .m, .rm16, .none, .none, .none, &.{ 0xff }, 6, .none },
482 .{ .push, .m, .rm64, .none, .none, .none, &.{ 0xff }, 6, .none },
483 .{ .push, .i, .imm8, .none, .none, .none, &.{ 0x6a }, 0, .none },
484 .{ .push, .i, .imm16, .none, .none, .none, &.{ 0x68 }, 0, .none },
485 .{ .push, .i, .imm32, .none, .none, .none, &.{ 0x68 }, 0, .none },
486
487 .{ .ret, .np, .none, .none, .none, .none, &.{ 0xc3 }, 0, .none },
488
489 .{ .rcl, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 2, .none },
490 .{ .rcl, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 2, .rex },
491 .{ .rcl, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 2, .none },
492 .{ .rcl, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 2, .rex },
493 .{ .rcl, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 2, .none },
494 .{ .rcl, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 2, .rex },
495 .{ .rcl, .m1, .rm16, .unity, .none, .none, &.{ 0xd1 }, 2, .none },
496 .{ .rcl, .mc, .rm16, .cl, .none, .none, &.{ 0xd3 }, 2, .none },
497 .{ .rcl, .mi, .rm16, .imm8, .none, .none, &.{ 0xc1 }, 2, .none },
498 .{ .rcl, .m1, .rm32, .unity, .none, .none, &.{ 0xd1 }, 2, .none },
499 .{ .rcl, .m1, .rm64, .unity, .none, .none, &.{ 0xd1 }, 2, .long },
500 .{ .rcl, .mc, .rm32, .cl, .none, .none, &.{ 0xd3 }, 2, .none },
501 .{ .rcl, .mc, .rm64, .cl, .none, .none, &.{ 0xd3 }, 2, .long },
502 .{ .rcl, .mi, .rm32, .imm8, .none, .none, &.{ 0xc1 }, 2, .none },
503 .{ .rcl, .mi, .rm64, .imm8, .none, .none, &.{ 0xc1 }, 2, .long },
504
505 .{ .rcr, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 3, .none },
506 .{ .rcr, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 3, .rex },
507 .{ .rcr, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 3, .none },
508 .{ .rcr, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 3, .rex },
509 .{ .rcr, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 3, .none },
510 .{ .rcr, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 3, .rex },
511 .{ .rcr, .m1, .rm16, .unity, .none, .none, &.{ 0xd1 }, 3, .none },
512 .{ .rcr, .mc, .rm16, .cl, .none, .none, &.{ 0xd3 }, 3, .none },
513 .{ .rcr, .mi, .rm16, .imm8, .none, .none, &.{ 0xc1 }, 3, .none },
514 .{ .rcr, .m1, .rm32, .unity, .none, .none, &.{ 0xd1 }, 3, .none },
515 .{ .rcr, .m1, .rm64, .unity, .none, .none, &.{ 0xd1 }, 3, .long },
516 .{ .rcr, .mc, .rm32, .cl, .none, .none, &.{ 0xd3 }, 3, .none },
517 .{ .rcr, .mc, .rm64, .cl, .none, .none, &.{ 0xd3 }, 3, .long },
518 .{ .rcr, .mi, .rm32, .imm8, .none, .none, &.{ 0xc1 }, 3, .none },
519 .{ .rcr, .mi, .rm64, .imm8, .none, .none, &.{ 0xc1 }, 3, .long },
520
521 .{ .rol, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 0, .none },
522 .{ .rol, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 0, .rex },
523 .{ .rol, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 0, .none },
524 .{ .rol, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 0, .rex },
525 .{ .rol, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 0, .none },
526 .{ .rol, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 0, .rex },
527 .{ .rol, .m1, .rm16, .unity, .none, .none, &.{ 0xd1 }, 0, .none },
528 .{ .rol, .mc, .rm16, .cl, .none, .none, &.{ 0xd3 }, 0, .none },
529 .{ .rol, .mi, .rm16, .imm8, .none, .none, &.{ 0xc1 }, 0, .none },
530 .{ .rol, .m1, .rm32, .unity, .none, .none, &.{ 0xd1 }, 0, .none },
531 .{ .rol, .m1, .rm64, .unity, .none, .none, &.{ 0xd1 }, 0, .long },
532 .{ .rol, .mc, .rm32, .cl, .none, .none, &.{ 0xd3 }, 0, .none },
533 .{ .rol, .mc, .rm64, .cl, .none, .none, &.{ 0xd3 }, 0, .long },
534 .{ .rol, .mi, .rm32, .imm8, .none, .none, &.{ 0xc1 }, 0, .none },
535 .{ .rol, .mi, .rm64, .imm8, .none, .none, &.{ 0xc1 }, 0, .long },
536
537 .{ .ror, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 1, .none },
538 .{ .ror, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 1, .rex },
539 .{ .ror, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 1, .none },
540 .{ .ror, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 1, .rex },
541 .{ .ror, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 1, .none },
542 .{ .ror, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 1, .rex },
543 .{ .ror, .m1, .rm16, .unity, .none, .none, &.{ 0xd1 }, 1, .none },
544 .{ .ror, .mc, .rm16, .cl, .none, .none, &.{ 0xd3 }, 1, .none },
545 .{ .ror, .mi, .rm16, .imm8, .none, .none, &.{ 0xc1 }, 1, .none },
546 .{ .ror, .m1, .rm32, .unity, .none, .none, &.{ 0xd1 }, 1, .none },
547 .{ .ror, .m1, .rm64, .unity, .none, .none, &.{ 0xd1 }, 1, .long },
548 .{ .ror, .mc, .rm32, .cl, .none, .none, &.{ 0xd3 }, 1, .none },
549 .{ .ror, .mc, .rm64, .cl, .none, .none, &.{ 0xd3 }, 1, .long },
550 .{ .ror, .mi, .rm32, .imm8, .none, .none, &.{ 0xc1 }, 1, .none },
551 .{ .ror, .mi, .rm64, .imm8, .none, .none, &.{ 0xc1 }, 1, .long },
552
553 .{ .sal, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 4, .none },
554 .{ .sal, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 4, .rex },
555 .{ .sal, .m1, .rm16, .unity, .none, .none, &.{ 0xd1 }, 4, .none },
556 .{ .sal, .m1, .rm32, .unity, .none, .none, &.{ 0xd1 }, 4, .none },
557 .{ .sal, .m1, .rm64, .unity, .none, .none, &.{ 0xd1 }, 4, .long },
558 .{ .sal, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 4, .none },
559 .{ .sal, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 4, .rex },
560 .{ .sal, .mc, .rm16, .cl, .none, .none, &.{ 0xd3 }, 4, .none },
561 .{ .sal, .mc, .rm32, .cl, .none, .none, &.{ 0xd3 }, 4, .none },
562 .{ .sal, .mc, .rm64, .cl, .none, .none, &.{ 0xd3 }, 4, .long },
563 .{ .sal, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 4, .none },
564 .{ .sal, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 4, .rex },
565 .{ .sal, .mi, .rm16, .imm8, .none, .none, &.{ 0xc1 }, 4, .none },
566 .{ .sal, .mi, .rm32, .imm8, .none, .none, &.{ 0xc1 }, 4, .none },
567 .{ .sal, .mi, .rm64, .imm8, .none, .none, &.{ 0xc1 }, 4, .long },
568
569 .{ .sar, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 7, .none },
570 .{ .sar, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 7, .rex },
571 .{ .sar, .m1, .rm16, .unity, .none, .none, &.{ 0xd1 }, 7, .none },
572 .{ .sar, .m1, .rm32, .unity, .none, .none, &.{ 0xd1 }, 7, .none },
573 .{ .sar, .m1, .rm64, .unity, .none, .none, &.{ 0xd1 }, 7, .long },
574 .{ .sar, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 7, .none },
575 .{ .sar, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 7, .rex },
576 .{ .sar, .mc, .rm16, .cl, .none, .none, &.{ 0xd3 }, 7, .none },
577 .{ .sar, .mc, .rm32, .cl, .none, .none, &.{ 0xd3 }, 7, .none },
578 .{ .sar, .mc, .rm64, .cl, .none, .none, &.{ 0xd3 }, 7, .long },
579 .{ .sar, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 7, .none },
580 .{ .sar, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 7, .rex },
581 .{ .sar, .mi, .rm16, .imm8, .none, .none, &.{ 0xc1 }, 7, .none },
582 .{ .sar, .mi, .rm32, .imm8, .none, .none, &.{ 0xc1 }, 7, .none },
583 .{ .sar, .mi, .rm64, .imm8, .none, .none, &.{ 0xc1 }, 7, .long },
584
585 .{ .sbb, .zi, .al, .imm8, .none, .none, &.{ 0x1c }, 0, .none },
586 .{ .sbb, .zi, .ax, .imm16, .none, .none, &.{ 0x1d }, 0, .none },
587 .{ .sbb, .zi, .eax, .imm32, .none, .none, &.{ 0x1d }, 0, .none },
588 .{ .sbb, .zi, .rax, .imm32s, .none, .none, &.{ 0x1d }, 0, .long },
589 .{ .sbb, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 3, .none },
590 .{ .sbb, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 3, .rex },
591 .{ .sbb, .mi, .rm16, .imm16, .none, .none, &.{ 0x81 }, 3, .none },
592 .{ .sbb, .mi, .rm32, .imm32, .none, .none, &.{ 0x81 }, 3, .none },
593 .{ .sbb, .mi, .rm64, .imm32s, .none, .none, &.{ 0x81 }, 3, .long },
594 .{ .sbb, .mi, .rm16, .imm8s, .none, .none, &.{ 0x83 }, 3, .none },
595 .{ .sbb, .mi, .rm32, .imm8s, .none, .none, &.{ 0x83 }, 3, .none },
596 .{ .sbb, .mi, .rm64, .imm8s, .none, .none, &.{ 0x83 }, 3, .long },
597 .{ .sbb, .mr, .rm8, .r8, .none, .none, &.{ 0x18 }, 0, .none },
598 .{ .sbb, .mr, .rm8, .r8, .none, .none, &.{ 0x18 }, 0, .rex },
599 .{ .sbb, .mr, .rm16, .r16, .none, .none, &.{ 0x19 }, 0, .none },
600 .{ .sbb, .mr, .rm32, .r32, .none, .none, &.{ 0x19 }, 0, .none },
601 .{ .sbb, .mr, .rm64, .r64, .none, .none, &.{ 0x19 }, 0, .long },
602 .{ .sbb, .rm, .r8, .rm8, .none, .none, &.{ 0x1a }, 0, .none },
603 .{ .sbb, .rm, .r8, .rm8, .none, .none, &.{ 0x1a }, 0, .rex },
604 .{ .sbb, .rm, .r16, .rm16, .none, .none, &.{ 0x1b }, 0, .none },
605 .{ .sbb, .rm, .r32, .rm32, .none, .none, &.{ 0x1b }, 0, .none },
606 .{ .sbb, .rm, .r64, .rm64, .none, .none, &.{ 0x1b }, 0, .long },
607
608 .{ .scas, .np, .m8, .none, .none, .none, &.{ 0xae }, 0, .none },
609 .{ .scas, .np, .m16, .none, .none, .none, &.{ 0xaf }, 0, .none },
610 .{ .scas, .np, .m32, .none, .none, .none, &.{ 0xaf }, 0, .none },
611 .{ .scas, .np, .m64, .none, .none, .none, &.{ 0xaf }, 0, .long },
612 .{ .scasb, .np, .none, .none, .none, .none, &.{ 0xae }, 0, .none },
613 .{ .scasw, .np, .none, .none, .none, .none, &.{ 0xaf }, 0, .short },
614 .{ .scasd, .np, .none, .none, .none, .none, &.{ 0xaf }, 0, .none },
615 .{ .scasq, .np, .none, .none, .none, .none, &.{ 0xaf }, 0, .long },
616
617 .{ .seta, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x97 }, 0, .none },
618 .{ .seta, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x97 }, 0, .rex },
619 .{ .setae, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x93 }, 0, .none },
620 .{ .setae, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x93 }, 0, .rex },
621 .{ .setb, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x92 }, 0, .none },
622 .{ .setb, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x92 }, 0, .rex },
623 .{ .setbe, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x96 }, 0, .none },
624 .{ .setbe, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x96 }, 0, .rex },
625 .{ .setc, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x92 }, 0, .none },
626 .{ .setc, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x92 }, 0, .rex },
627 .{ .sete, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x94 }, 0, .none },
628 .{ .sete, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x94 }, 0, .rex },
629 .{ .setg, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9f }, 0, .none },
630 .{ .setg, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9f }, 0, .rex },
631 .{ .setge, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9d }, 0, .none },
632 .{ .setge, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9d }, 0, .rex },
633 .{ .setl, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9c }, 0, .none },
634 .{ .setl, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9c }, 0, .rex },
635 .{ .setle, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9e }, 0, .none },
636 .{ .setle, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9e }, 0, .rex },
637 .{ .setna, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x96 }, 0, .none },
638 .{ .setna, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x96 }, 0, .rex },
639 .{ .setnae, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x92 }, 0, .none },
640 .{ .setnae, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x92 }, 0, .rex },
641 .{ .setnb, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x93 }, 0, .none },
642 .{ .setnb, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x93 }, 0, .rex },
643 .{ .setnbe, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x97 }, 0, .none },
644 .{ .setnbe, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x97 }, 0, .rex },
645 .{ .setnc, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x93 }, 0, .none },
646 .{ .setnc, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x93 }, 0, .rex },
647 .{ .setne, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x95 }, 0, .none },
648 .{ .setne, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x95 }, 0, .rex },
649 .{ .setng, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9e }, 0, .none },
650 .{ .setng, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9e }, 0, .rex },
651 .{ .setnge, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9c }, 0, .none },
652 .{ .setnge, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9c }, 0, .rex },
653 .{ .setnl, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9d }, 0, .none },
654 .{ .setnl, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9d }, 0, .rex },
655 .{ .setnle, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9f }, 0, .none },
656 .{ .setnle, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9f }, 0, .rex },
657 .{ .setno, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x91 }, 0, .none },
658 .{ .setno, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x91 }, 0, .rex },
659 .{ .setnp, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9b }, 0, .none },
660 .{ .setnp, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9b }, 0, .rex },
661 .{ .setns, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x99 }, 0, .none },
662 .{ .setns, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x99 }, 0, .rex },
663 .{ .setnz, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x95 }, 0, .none },
664 .{ .setnz, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x95 }, 0, .rex },
665 .{ .seto, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x90 }, 0, .none },
666 .{ .seto, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x90 }, 0, .rex },
667 .{ .setp, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9a }, 0, .none },
668 .{ .setp, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9a }, 0, .rex },
669 .{ .setpe, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9a }, 0, .none },
670 .{ .setpe, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9a }, 0, .rex },
671 .{ .setpo, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9b }, 0, .none },
672 .{ .setpo, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9b }, 0, .rex },
673 .{ .sets, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x98 }, 0, .none },
674 .{ .sets, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x98 }, 0, .rex },
675 .{ .setz, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x94 }, 0, .none },
676 .{ .setz, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x94 }, 0, .rex },
677
678 .{ .sfence, .np, .none, .none, .none, .none, &.{ 0x0f, 0xae, 0xf8 }, 0, .none },
679
680 .{ .shl, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 4, .none },
681 .{ .shl, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 4, .rex },
682 .{ .shl, .m1, .rm16, .unity, .none, .none, &.{ 0xd1 }, 4, .none },
683 .{ .shl, .m1, .rm32, .unity, .none, .none, &.{ 0xd1 }, 4, .none },
684 .{ .shl, .m1, .rm64, .unity, .none, .none, &.{ 0xd1 }, 4, .long },
685 .{ .shl, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 4, .none },
686 .{ .shl, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 4, .rex },
687 .{ .shl, .mc, .rm16, .cl, .none, .none, &.{ 0xd3 }, 4, .none },
688 .{ .shl, .mc, .rm32, .cl, .none, .none, &.{ 0xd3 }, 4, .none },
689 .{ .shl, .mc, .rm64, .cl, .none, .none, &.{ 0xd3 }, 4, .long },
690 .{ .shl, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 4, .none },
691 .{ .shl, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 4, .rex },
692 .{ .shl, .mi, .rm16, .imm8, .none, .none, &.{ 0xc1 }, 4, .none },
693 .{ .shl, .mi, .rm32, .imm8, .none, .none, &.{ 0xc1 }, 4, .none },
694 .{ .shl, .mi, .rm64, .imm8, .none, .none, &.{ 0xc1 }, 4, .long },
695
696 .{ .shld, .mri, .rm16, .r16, .imm8, .none, &.{ 0x0f, 0xa4 }, 0, .none },
697 .{ .shld, .mrc, .rm16, .r16, .cl, .none, &.{ 0x0f, 0xa5 }, 0, .none },
698 .{ .shld, .mri, .rm32, .r32, .imm8, .none, &.{ 0x0f, 0xa4 }, 0, .none },
699 .{ .shld, .mri, .rm64, .r64, .imm8, .none, &.{ 0x0f, 0xa4 }, 0, .long },
700 .{ .shld, .mrc, .rm32, .r32, .cl, .none, &.{ 0x0f, 0xa5 }, 0, .none },
701 .{ .shld, .mrc, .rm64, .r64, .cl, .none, &.{ 0x0f, 0xa5 }, 0, .long },
702
703 .{ .shr, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 5, .none },
704 .{ .shr, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 5, .rex },
705 .{ .shr, .m1, .rm16, .unity, .none, .none, &.{ 0xd1 }, 5, .none },
706 .{ .shr, .m1, .rm32, .unity, .none, .none, &.{ 0xd1 }, 5, .none },
707 .{ .shr, .m1, .rm64, .unity, .none, .none, &.{ 0xd1 }, 5, .long },
708 .{ .shr, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 5, .none },
709 .{ .shr, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 5, .rex },
710 .{ .shr, .mc, .rm16, .cl, .none, .none, &.{ 0xd3 }, 5, .none },
711 .{ .shr, .mc, .rm32, .cl, .none, .none, &.{ 0xd3 }, 5, .none },
712 .{ .shr, .mc, .rm64, .cl, .none, .none, &.{ 0xd3 }, 5, .long },
713 .{ .shr, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 5, .none },
714 .{ .shr, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 5, .rex },
715 .{ .shr, .mi, .rm16, .imm8, .none, .none, &.{ 0xc1 }, 5, .none },
716 .{ .shr, .mi, .rm32, .imm8, .none, .none, &.{ 0xc1 }, 5, .none },
717 .{ .shr, .mi, .rm64, .imm8, .none, .none, &.{ 0xc1 }, 5, .long },
718
719 .{ .shrd, .mri, .rm16, .r16, .imm8, .none, &.{ 0x0f, 0xac }, 0, .none },
720 .{ .shrd, .mrc, .rm16, .r16, .cl, .none, &.{ 0x0f, 0xad }, 0, .none },
721 .{ .shrd, .mri, .rm32, .r32, .imm8, .none, &.{ 0x0f, 0xac }, 0, .none },
722 .{ .shrd, .mri, .rm64, .r64, .imm8, .none, &.{ 0x0f, 0xac }, 0, .long },
723 .{ .shrd, .mrc, .rm32, .r32, .cl, .none, &.{ 0x0f, 0xad }, 0, .none },
724 .{ .shrd, .mrc, .rm64, .r64, .cl, .none, &.{ 0x0f, 0xad }, 0, .long },
725
726 .{ .stos, .np, .m8, .none, .none, .none, &.{ 0xaa }, 0, .none },
727 .{ .stos, .np, .m16, .none, .none, .none, &.{ 0xab }, 0, .none },
728 .{ .stos, .np, .m32, .none, .none, .none, &.{ 0xab }, 0, .none },
729 .{ .stos, .np, .m64, .none, .none, .none, &.{ 0xab }, 0, .long },
730 .{ .stosb, .np, .none, .none, .none, .none, &.{ 0xaa }, 0, .none },
731 .{ .stosw, .np, .none, .none, .none, .none, &.{ 0xab }, 0, .short },
732 .{ .stosd, .np, .none, .none, .none, .none, &.{ 0xab }, 0, .none },
733 .{ .stosq, .np, .none, .none, .none, .none, &.{ 0xab }, 0, .long },
734
735 .{ .sub, .zi, .al, .imm8, .none, .none, &.{ 0x2c }, 0, .none },
736 .{ .sub, .zi, .ax, .imm16, .none, .none, &.{ 0x2d }, 0, .none },
737 .{ .sub, .zi, .eax, .imm32, .none, .none, &.{ 0x2d }, 0, .none },
738 .{ .sub, .zi, .rax, .imm32s, .none, .none, &.{ 0x2d }, 0, .long },
739 .{ .sub, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 5, .none },
740 .{ .sub, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 5, .rex },
741 .{ .sub, .mi, .rm16, .imm16, .none, .none, &.{ 0x81 }, 5, .none },
742 .{ .sub, .mi, .rm32, .imm32, .none, .none, &.{ 0x81 }, 5, .none },
743 .{ .sub, .mi, .rm64, .imm32s, .none, .none, &.{ 0x81 }, 5, .long },
744 .{ .sub, .mi, .rm16, .imm8s, .none, .none, &.{ 0x83 }, 5, .none },
745 .{ .sub, .mi, .rm32, .imm8s, .none, .none, &.{ 0x83 }, 5, .none },
746 .{ .sub, .mi, .rm64, .imm8s, .none, .none, &.{ 0x83 }, 5, .long },
747 .{ .sub, .mr, .rm8, .r8, .none, .none, &.{ 0x28 }, 0, .none },
748 .{ .sub, .mr, .rm8, .r8, .none, .none, &.{ 0x28 }, 0, .rex },
749 .{ .sub, .mr, .rm16, .r16, .none, .none, &.{ 0x29 }, 0, .none },
750 .{ .sub, .mr, .rm32, .r32, .none, .none, &.{ 0x29 }, 0, .none },
751 .{ .sub, .mr, .rm64, .r64, .none, .none, &.{ 0x29 }, 0, .long },
752 .{ .sub, .rm, .r8, .rm8, .none, .none, &.{ 0x2a }, 0, .none },
753 .{ .sub, .rm, .r8, .rm8, .none, .none, &.{ 0x2a }, 0, .rex },
754 .{ .sub, .rm, .r16, .rm16, .none, .none, &.{ 0x2b }, 0, .none },
755 .{ .sub, .rm, .r32, .rm32, .none, .none, &.{ 0x2b }, 0, .none },
756 .{ .sub, .rm, .r64, .rm64, .none, .none, &.{ 0x2b }, 0, .long },
757
758 .{ .syscall, .np, .none, .none, .none, .none, &.{ 0x0f, 0x05 }, 0, .none }
421 .{ .movsxd, .rm, &.{ .r32, .rm32 }, &.{ 0x63 }, 0, .none },
422 .{ .movsxd, .rm, &.{ .r64, .rm32 }, &.{ 0x63 }, 0, .long },
423
424 .{ .movzx, .rm, &.{ .r16, .rm8 }, &.{ 0x0f, 0xb6 }, 0, .none },
425 .{ .movzx, .rm, &.{ .r32, .rm8 }, &.{ 0x0f, 0xb6 }, 0, .none },
426 .{ .movzx, .rm, &.{ .r64, .rm8 }, &.{ 0x0f, 0xb6 }, 0, .long },
427 .{ .movzx, .rm, &.{ .r32, .rm16 }, &.{ 0x0f, 0xb7 }, 0, .none },
428 .{ .movzx, .rm, &.{ .r64, .rm16 }, &.{ 0x0f, 0xb7 }, 0, .long },
429
430 .{ .mul, .m, &.{ .rm8 }, &.{ 0xf6 }, 4, .none },
431 .{ .mul, .m, &.{ .rm8 }, &.{ 0xf6 }, 4, .rex },
432 .{ .mul, .m, &.{ .rm16 }, &.{ 0xf7 }, 4, .none },
433 .{ .mul, .m, &.{ .rm32 }, &.{ 0xf7 }, 4, .none },
434 .{ .mul, .m, &.{ .rm64 }, &.{ 0xf7 }, 4, .long },
435
436 .{ .neg, .m, &.{ .rm8 }, &.{ 0xf6 }, 3, .none },
437 .{ .neg, .m, &.{ .rm8 }, &.{ 0xf6 }, 3, .rex },
438 .{ .neg, .m, &.{ .rm16 }, &.{ 0xf7 }, 3, .none },
439 .{ .neg, .m, &.{ .rm32 }, &.{ 0xf7 }, 3, .none },
440 .{ .neg, .m, &.{ .rm64 }, &.{ 0xf7 }, 3, .long },
441
442 .{ .nop, .np, &.{}, &.{ 0x90 }, 0, .none },
443
444 .{ .not, .m, &.{ .rm8 }, &.{ 0xf6 }, 2, .none },
445 .{ .not, .m, &.{ .rm8 }, &.{ 0xf6 }, 2, .rex },
446 .{ .not, .m, &.{ .rm16 }, &.{ 0xf7 }, 2, .none },
447 .{ .not, .m, &.{ .rm32 }, &.{ 0xf7 }, 2, .none },
448 .{ .not, .m, &.{ .rm64 }, &.{ 0xf7 }, 2, .long },
449
450 .{ .@"or", .zi, &.{ .al, .imm8 }, &.{ 0x0c }, 0, .none },
451 .{ .@"or", .zi, &.{ .ax, .imm16 }, &.{ 0x0d }, 0, .none },
452 .{ .@"or", .zi, &.{ .eax, .imm32 }, &.{ 0x0d }, 0, .none },
453 .{ .@"or", .zi, &.{ .rax, .imm32s }, &.{ 0x0d }, 0, .long },
454 .{ .@"or", .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 1, .none },
455 .{ .@"or", .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 1, .rex },
456 .{ .@"or", .mi, &.{ .rm16, .imm16 }, &.{ 0x81 }, 1, .none },
457 .{ .@"or", .mi, &.{ .rm32, .imm32 }, &.{ 0x81 }, 1, .none },
458 .{ .@"or", .mi, &.{ .rm64, .imm32s }, &.{ 0x81 }, 1, .long },
459 .{ .@"or", .mi, &.{ .rm16, .imm8s }, &.{ 0x83 }, 1, .none },
460 .{ .@"or", .mi, &.{ .rm32, .imm8s }, &.{ 0x83 }, 1, .none },
461 .{ .@"or", .mi, &.{ .rm64, .imm8s }, &.{ 0x83 }, 1, .long },
462 .{ .@"or", .mr, &.{ .rm8, .r8 }, &.{ 0x08 }, 0, .none },
463 .{ .@"or", .mr, &.{ .rm8, .r8 }, &.{ 0x08 }, 0, .rex },
464 .{ .@"or", .mr, &.{ .rm16, .r16 }, &.{ 0x09 }, 0, .none },
465 .{ .@"or", .mr, &.{ .rm32, .r32 }, &.{ 0x09 }, 0, .none },
466 .{ .@"or", .mr, &.{ .rm64, .r64 }, &.{ 0x09 }, 0, .long },
467 .{ .@"or", .rm, &.{ .r8, .rm8 }, &.{ 0x0a }, 0, .none },
468 .{ .@"or", .rm, &.{ .r8, .rm8 }, &.{ 0x0a }, 0, .rex },
469 .{ .@"or", .rm, &.{ .r16, .rm16 }, &.{ 0x0b }, 0, .none },
470 .{ .@"or", .rm, &.{ .r32, .rm32 }, &.{ 0x0b }, 0, .none },
471 .{ .@"or", .rm, &.{ .r64, .rm64 }, &.{ 0x0b }, 0, .long },
472
473 .{ .pop, .o, &.{ .r16 }, &.{ 0x58 }, 0, .none },
474 .{ .pop, .o, &.{ .r64 }, &.{ 0x58 }, 0, .none },
475 .{ .pop, .m, &.{ .rm16 }, &.{ 0x8f }, 0, .none },
476 .{ .pop, .m, &.{ .rm64 }, &.{ 0x8f }, 0, .none },
477
478 .{ .popcnt, .rm, &.{ .r16, .rm16 }, &.{ 0xf3, 0x0f, 0xb8 }, 0, .none },
479 .{ .popcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xb8 }, 0, .none },
480 .{ .popcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xb8 }, 0, .long },
481
482 .{ .push, .o, &.{ .r16 }, &.{ 0x50 }, 0, .none },
483 .{ .push, .o, &.{ .r64 }, &.{ 0x50 }, 0, .none },
484 .{ .push, .m, &.{ .rm16 }, &.{ 0xff }, 6, .none },
485 .{ .push, .m, &.{ .rm64 }, &.{ 0xff }, 6, .none },
486 .{ .push, .i, &.{ .imm8 }, &.{ 0x6a }, 0, .none },
487 .{ .push, .i, &.{ .imm16 }, &.{ 0x68 }, 0, .none },
488 .{ .push, .i, &.{ .imm32 }, &.{ 0x68 }, 0, .none },
489
490 .{ .ret, .np, &.{}, &.{ 0xc3 }, 0, .none },
491
492 .{ .rcl, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 2, .none },
493 .{ .rcl, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 2, .rex },
494 .{ .rcl, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 2, .none },
495 .{ .rcl, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 2, .rex },
496 .{ .rcl, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 2, .none },
497 .{ .rcl, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 2, .rex },
498 .{ .rcl, .m1, &.{ .rm16, .unity }, &.{ 0xd1 }, 2, .none },
499 .{ .rcl, .mc, &.{ .rm16, .cl }, &.{ 0xd3 }, 2, .none },
500 .{ .rcl, .mi, &.{ .rm16, .imm8 }, &.{ 0xc1 }, 2, .none },
501 .{ .rcl, .m1, &.{ .rm32, .unity }, &.{ 0xd1 }, 2, .none },
502 .{ .rcl, .m1, &.{ .rm64, .unity }, &.{ 0xd1 }, 2, .long },
503 .{ .rcl, .mc, &.{ .rm32, .cl }, &.{ 0xd3 }, 2, .none },
504 .{ .rcl, .mc, &.{ .rm64, .cl }, &.{ 0xd3 }, 2, .long },
505 .{ .rcl, .mi, &.{ .rm32, .imm8 }, &.{ 0xc1 }, 2, .none },
506 .{ .rcl, .mi, &.{ .rm64, .imm8 }, &.{ 0xc1 }, 2, .long },
507
508 .{ .rcr, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 3, .none },
509 .{ .rcr, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 3, .rex },
510 .{ .rcr, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 3, .none },
511 .{ .rcr, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 3, .rex },
512 .{ .rcr, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 3, .none },
513 .{ .rcr, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 3, .rex },
514 .{ .rcr, .m1, &.{ .rm16, .unity }, &.{ 0xd1 }, 3, .none },
515 .{ .rcr, .mc, &.{ .rm16, .cl }, &.{ 0xd3 }, 3, .none },
516 .{ .rcr, .mi, &.{ .rm16, .imm8 }, &.{ 0xc1 }, 3, .none },
517 .{ .rcr, .m1, &.{ .rm32, .unity }, &.{ 0xd1 }, 3, .none },
518 .{ .rcr, .m1, &.{ .rm64, .unity }, &.{ 0xd1 }, 3, .long },
519 .{ .rcr, .mc, &.{ .rm32, .cl }, &.{ 0xd3 }, 3, .none },
520 .{ .rcr, .mc, &.{ .rm64, .cl }, &.{ 0xd3 }, 3, .long },
521 .{ .rcr, .mi, &.{ .rm32, .imm8 }, &.{ 0xc1 }, 3, .none },
522 .{ .rcr, .mi, &.{ .rm64, .imm8 }, &.{ 0xc1 }, 3, .long },
523
524 .{ .rol, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 0, .none },
525 .{ .rol, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 0, .rex },
526 .{ .rol, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 0, .none },
527 .{ .rol, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 0, .rex },
528 .{ .rol, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 0, .none },
529 .{ .rol, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 0, .rex },
530 .{ .rol, .m1, &.{ .rm16, .unity }, &.{ 0xd1 }, 0, .none },
531 .{ .rol, .mc, &.{ .rm16, .cl }, &.{ 0xd3 }, 0, .none },
532 .{ .rol, .mi, &.{ .rm16, .imm8 }, &.{ 0xc1 }, 0, .none },
533 .{ .rol, .m1, &.{ .rm32, .unity }, &.{ 0xd1 }, 0, .none },
534 .{ .rol, .m1, &.{ .rm64, .unity }, &.{ 0xd1 }, 0, .long },
535 .{ .rol, .mc, &.{ .rm32, .cl }, &.{ 0xd3 }, 0, .none },
536 .{ .rol, .mc, &.{ .rm64, .cl }, &.{ 0xd3 }, 0, .long },
537 .{ .rol, .mi, &.{ .rm32, .imm8 }, &.{ 0xc1 }, 0, .none },
538 .{ .rol, .mi, &.{ .rm64, .imm8 }, &.{ 0xc1 }, 0, .long },
539
540 .{ .ror, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 1, .none },
541 .{ .ror, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 1, .rex },
542 .{ .ror, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 1, .none },
543 .{ .ror, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 1, .rex },
544 .{ .ror, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 1, .none },
545 .{ .ror, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 1, .rex },
546 .{ .ror, .m1, &.{ .rm16, .unity }, &.{ 0xd1 }, 1, .none },
547 .{ .ror, .mc, &.{ .rm16, .cl }, &.{ 0xd3 }, 1, .none },
548 .{ .ror, .mi, &.{ .rm16, .imm8 }, &.{ 0xc1 }, 1, .none },
549 .{ .ror, .m1, &.{ .rm32, .unity }, &.{ 0xd1 }, 1, .none },
550 .{ .ror, .m1, &.{ .rm64, .unity }, &.{ 0xd1 }, 1, .long },
551 .{ .ror, .mc, &.{ .rm32, .cl }, &.{ 0xd3 }, 1, .none },
552 .{ .ror, .mc, &.{ .rm64, .cl }, &.{ 0xd3 }, 1, .long },
553 .{ .ror, .mi, &.{ .rm32, .imm8 }, &.{ 0xc1 }, 1, .none },
554 .{ .ror, .mi, &.{ .rm64, .imm8 }, &.{ 0xc1 }, 1, .long },
555
556 .{ .sal, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 4, .none },
557 .{ .sal, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 4, .rex },
558 .{ .sal, .m1, &.{ .rm16, .unity }, &.{ 0xd1 }, 4, .none },
559 .{ .sal, .m1, &.{ .rm32, .unity }, &.{ 0xd1 }, 4, .none },
560 .{ .sal, .m1, &.{ .rm64, .unity }, &.{ 0xd1 }, 4, .long },
561 .{ .sal, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 4, .none },
562 .{ .sal, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 4, .rex },
563 .{ .sal, .mc, &.{ .rm16, .cl }, &.{ 0xd3 }, 4, .none },
564 .{ .sal, .mc, &.{ .rm32, .cl }, &.{ 0xd3 }, 4, .none },
565 .{ .sal, .mc, &.{ .rm64, .cl }, &.{ 0xd3 }, 4, .long },
566 .{ .sal, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 4, .none },
567 .{ .sal, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 4, .rex },
568 .{ .sal, .mi, &.{ .rm16, .imm8 }, &.{ 0xc1 }, 4, .none },
569 .{ .sal, .mi, &.{ .rm32, .imm8 }, &.{ 0xc1 }, 4, .none },
570 .{ .sal, .mi, &.{ .rm64, .imm8 }, &.{ 0xc1 }, 4, .long },
571
572 .{ .sar, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 7, .none },
573 .{ .sar, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 7, .rex },
574 .{ .sar, .m1, &.{ .rm16, .unity }, &.{ 0xd1 }, 7, .none },
575 .{ .sar, .m1, &.{ .rm32, .unity }, &.{ 0xd1 }, 7, .none },
576 .{ .sar, .m1, &.{ .rm64, .unity }, &.{ 0xd1 }, 7, .long },
577 .{ .sar, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 7, .none },
578 .{ .sar, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 7, .rex },
579 .{ .sar, .mc, &.{ .rm16, .cl }, &.{ 0xd3 }, 7, .none },
580 .{ .sar, .mc, &.{ .rm32, .cl }, &.{ 0xd3 }, 7, .none },
581 .{ .sar, .mc, &.{ .rm64, .cl }, &.{ 0xd3 }, 7, .long },
582 .{ .sar, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 7, .none },
583 .{ .sar, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 7, .rex },
584 .{ .sar, .mi, &.{ .rm16, .imm8 }, &.{ 0xc1 }, 7, .none },
585 .{ .sar, .mi, &.{ .rm32, .imm8 }, &.{ 0xc1 }, 7, .none },
586 .{ .sar, .mi, &.{ .rm64, .imm8 }, &.{ 0xc1 }, 7, .long },
587
588 .{ .sbb, .zi, &.{ .al, .imm8 }, &.{ 0x1c }, 0, .none },
589 .{ .sbb, .zi, &.{ .ax, .imm16 }, &.{ 0x1d }, 0, .none },
590 .{ .sbb, .zi, &.{ .eax, .imm32 }, &.{ 0x1d }, 0, .none },
591 .{ .sbb, .zi, &.{ .rax, .imm32s }, &.{ 0x1d }, 0, .long },
592 .{ .sbb, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 3, .none },
593 .{ .sbb, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 3, .rex },
594 .{ .sbb, .mi, &.{ .rm16, .imm16 }, &.{ 0x81 }, 3, .none },
595 .{ .sbb, .mi, &.{ .rm32, .imm32 }, &.{ 0x81 }, 3, .none },
596 .{ .sbb, .mi, &.{ .rm64, .imm32s }, &.{ 0x81 }, 3, .long },
597 .{ .sbb, .mi, &.{ .rm16, .imm8s }, &.{ 0x83 }, 3, .none },
598 .{ .sbb, .mi, &.{ .rm32, .imm8s }, &.{ 0x83 }, 3, .none },
599 .{ .sbb, .mi, &.{ .rm64, .imm8s }, &.{ 0x83 }, 3, .long },
600 .{ .sbb, .mr, &.{ .rm8, .r8 }, &.{ 0x18 }, 0, .none },
601 .{ .sbb, .mr, &.{ .rm8, .r8 }, &.{ 0x18 }, 0, .rex },
602 .{ .sbb, .mr, &.{ .rm16, .r16 }, &.{ 0x19 }, 0, .none },
603 .{ .sbb, .mr, &.{ .rm32, .r32 }, &.{ 0x19 }, 0, .none },
604 .{ .sbb, .mr, &.{ .rm64, .r64 }, &.{ 0x19 }, 0, .long },
605 .{ .sbb, .rm, &.{ .r8, .rm8 }, &.{ 0x1a }, 0, .none },
606 .{ .sbb, .rm, &.{ .r8, .rm8 }, &.{ 0x1a }, 0, .rex },
607 .{ .sbb, .rm, &.{ .r16, .rm16 }, &.{ 0x1b }, 0, .none },
608 .{ .sbb, .rm, &.{ .r32, .rm32 }, &.{ 0x1b }, 0, .none },
609 .{ .sbb, .rm, &.{ .r64, .rm64 }, &.{ 0x1b }, 0, .long },
610
611 .{ .scas, .np, &.{ .m8 }, &.{ 0xae }, 0, .none },
612 .{ .scas, .np, &.{ .m16 }, &.{ 0xaf }, 0, .none },
613 .{ .scas, .np, &.{ .m32 }, &.{ 0xaf }, 0, .none },
614 .{ .scas, .np, &.{ .m64 }, &.{ 0xaf }, 0, .long },
615
616 .{ .scasb, .np, &.{}, &.{ 0xae }, 0, .none },
617 .{ .scasw, .np, &.{}, &.{ 0xaf }, 0, .short },
618 .{ .scasd, .np, &.{}, &.{ 0xaf }, 0, .none },
619 .{ .scasq, .np, &.{}, &.{ 0xaf }, 0, .long },
620
621 .{ .seta, .m, &.{ .rm8 }, &.{ 0x0f, 0x97 }, 0, .none },
622 .{ .seta, .m, &.{ .rm8 }, &.{ 0x0f, 0x97 }, 0, .rex },
623 .{ .setae, .m, &.{ .rm8 }, &.{ 0x0f, 0x93 }, 0, .none },
624 .{ .setae, .m, &.{ .rm8 }, &.{ 0x0f, 0x93 }, 0, .rex },
625 .{ .setb, .m, &.{ .rm8 }, &.{ 0x0f, 0x92 }, 0, .none },
626 .{ .setb, .m, &.{ .rm8 }, &.{ 0x0f, 0x92 }, 0, .rex },
627 .{ .setbe, .m, &.{ .rm8 }, &.{ 0x0f, 0x96 }, 0, .none },
628 .{ .setbe, .m, &.{ .rm8 }, &.{ 0x0f, 0x96 }, 0, .rex },
629 .{ .setc, .m, &.{ .rm8 }, &.{ 0x0f, 0x92 }, 0, .none },
630 .{ .setc, .m, &.{ .rm8 }, &.{ 0x0f, 0x92 }, 0, .rex },
631 .{ .sete, .m, &.{ .rm8 }, &.{ 0x0f, 0x94 }, 0, .none },
632 .{ .sete, .m, &.{ .rm8 }, &.{ 0x0f, 0x94 }, 0, .rex },
633 .{ .setg, .m, &.{ .rm8 }, &.{ 0x0f, 0x9f }, 0, .none },
634 .{ .setg, .m, &.{ .rm8 }, &.{ 0x0f, 0x9f }, 0, .rex },
635 .{ .setge, .m, &.{ .rm8 }, &.{ 0x0f, 0x9d }, 0, .none },
636 .{ .setge, .m, &.{ .rm8 }, &.{ 0x0f, 0x9d }, 0, .rex },
637 .{ .setl, .m, &.{ .rm8 }, &.{ 0x0f, 0x9c }, 0, .none },
638 .{ .setl, .m, &.{ .rm8 }, &.{ 0x0f, 0x9c }, 0, .rex },
639 .{ .setle, .m, &.{ .rm8 }, &.{ 0x0f, 0x9e }, 0, .none },
640 .{ .setle, .m, &.{ .rm8 }, &.{ 0x0f, 0x9e }, 0, .rex },
641 .{ .setna, .m, &.{ .rm8 }, &.{ 0x0f, 0x96 }, 0, .none },
642 .{ .setna, .m, &.{ .rm8 }, &.{ 0x0f, 0x96 }, 0, .rex },
643 .{ .setnae, .m, &.{ .rm8 }, &.{ 0x0f, 0x92 }, 0, .none },
644 .{ .setnae, .m, &.{ .rm8 }, &.{ 0x0f, 0x92 }, 0, .rex },
645 .{ .setnb, .m, &.{ .rm8 }, &.{ 0x0f, 0x93 }, 0, .none },
646 .{ .setnb, .m, &.{ .rm8 }, &.{ 0x0f, 0x93 }, 0, .rex },
647 .{ .setnbe, .m, &.{ .rm8 }, &.{ 0x0f, 0x97 }, 0, .none },
648 .{ .setnbe, .m, &.{ .rm8 }, &.{ 0x0f, 0x97 }, 0, .rex },
649 .{ .setnc, .m, &.{ .rm8 }, &.{ 0x0f, 0x93 }, 0, .none },
650 .{ .setnc, .m, &.{ .rm8 }, &.{ 0x0f, 0x93 }, 0, .rex },
651 .{ .setne, .m, &.{ .rm8 }, &.{ 0x0f, 0x95 }, 0, .none },
652 .{ .setne, .m, &.{ .rm8 }, &.{ 0x0f, 0x95 }, 0, .rex },
653 .{ .setng, .m, &.{ .rm8 }, &.{ 0x0f, 0x9e }, 0, .none },
654 .{ .setng, .m, &.{ .rm8 }, &.{ 0x0f, 0x9e }, 0, .rex },
655 .{ .setnge, .m, &.{ .rm8 }, &.{ 0x0f, 0x9c }, 0, .none },
656 .{ .setnge, .m, &.{ .rm8 }, &.{ 0x0f, 0x9c }, 0, .rex },
657 .{ .setnl, .m, &.{ .rm8 }, &.{ 0x0f, 0x9d }, 0, .none },
658 .{ .setnl, .m, &.{ .rm8 }, &.{ 0x0f, 0x9d }, 0, .rex },
659 .{ .setnle, .m, &.{ .rm8 }, &.{ 0x0f, 0x9f }, 0, .none },
660 .{ .setnle, .m, &.{ .rm8 }, &.{ 0x0f, 0x9f }, 0, .rex },
661 .{ .setno, .m, &.{ .rm8 }, &.{ 0x0f, 0x91 }, 0, .none },
662 .{ .setno, .m, &.{ .rm8 }, &.{ 0x0f, 0x91 }, 0, .rex },
663 .{ .setnp, .m, &.{ .rm8 }, &.{ 0x0f, 0x9b }, 0, .none },
664 .{ .setnp, .m, &.{ .rm8 }, &.{ 0x0f, 0x9b }, 0, .rex },
665 .{ .setns, .m, &.{ .rm8 }, &.{ 0x0f, 0x99 }, 0, .none },
666 .{ .setns, .m, &.{ .rm8 }, &.{ 0x0f, 0x99 }, 0, .rex },
667 .{ .setnz, .m, &.{ .rm8 }, &.{ 0x0f, 0x95 }, 0, .none },
668 .{ .setnz, .m, &.{ .rm8 }, &.{ 0x0f, 0x95 }, 0, .rex },
669 .{ .seto, .m, &.{ .rm8 }, &.{ 0x0f, 0x90 }, 0, .none },
670 .{ .seto, .m, &.{ .rm8 }, &.{ 0x0f, 0x90 }, 0, .rex },
671 .{ .setp, .m, &.{ .rm8 }, &.{ 0x0f, 0x9a }, 0, .none },
672 .{ .setp, .m, &.{ .rm8 }, &.{ 0x0f, 0x9a }, 0, .rex },
673 .{ .setpe, .m, &.{ .rm8 }, &.{ 0x0f, 0x9a }, 0, .none },
674 .{ .setpe, .m, &.{ .rm8 }, &.{ 0x0f, 0x9a }, 0, .rex },
675 .{ .setpo, .m, &.{ .rm8 }, &.{ 0x0f, 0x9b }, 0, .none },
676 .{ .setpo, .m, &.{ .rm8 }, &.{ 0x0f, 0x9b }, 0, .rex },
677 .{ .sets, .m, &.{ .rm8 }, &.{ 0x0f, 0x98 }, 0, .none },
678 .{ .sets, .m, &.{ .rm8 }, &.{ 0x0f, 0x98 }, 0, .rex },
679 .{ .setz, .m, &.{ .rm8 }, &.{ 0x0f, 0x94 }, 0, .none },
680 .{ .setz, .m, &.{ .rm8 }, &.{ 0x0f, 0x94 }, 0, .rex },
681
682 .{ .sfence, .np, &.{}, &.{ 0x0f, 0xae, 0xf8 }, 0, .none },
683
684 .{ .shl, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 4, .none },
685 .{ .shl, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 4, .rex },
686 .{ .shl, .m1, &.{ .rm16, .unity }, &.{ 0xd1 }, 4, .none },
687 .{ .shl, .m1, &.{ .rm32, .unity }, &.{ 0xd1 }, 4, .none },
688 .{ .shl, .m1, &.{ .rm64, .unity }, &.{ 0xd1 }, 4, .long },
689 .{ .shl, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 4, .none },
690 .{ .shl, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 4, .rex },
691 .{ .shl, .mc, &.{ .rm16, .cl }, &.{ 0xd3 }, 4, .none },
692 .{ .shl, .mc, &.{ .rm32, .cl }, &.{ 0xd3 }, 4, .none },
693 .{ .shl, .mc, &.{ .rm64, .cl }, &.{ 0xd3 }, 4, .long },
694 .{ .shl, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 4, .none },
695 .{ .shl, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 4, .rex },
696 .{ .shl, .mi, &.{ .rm16, .imm8 }, &.{ 0xc1 }, 4, .none },
697 .{ .shl, .mi, &.{ .rm32, .imm8 }, &.{ 0xc1 }, 4, .none },
698 .{ .shl, .mi, &.{ .rm64, .imm8 }, &.{ 0xc1 }, 4, .long },
699
700 .{ .shld, .mri, &.{ .rm16, .r16, .imm8 }, &.{ 0x0f, 0xa4 }, 0, .none },
701 .{ .shld, .mrc, &.{ .rm16, .r16, .cl }, &.{ 0x0f, 0xa5 }, 0, .none },
702 .{ .shld, .mri, &.{ .rm32, .r32, .imm8 }, &.{ 0x0f, 0xa4 }, 0, .none },
703 .{ .shld, .mri, &.{ .rm64, .r64, .imm8 }, &.{ 0x0f, 0xa4 }, 0, .long },
704 .{ .shld, .mrc, &.{ .rm32, .r32, .cl }, &.{ 0x0f, 0xa5 }, 0, .none },
705 .{ .shld, .mrc, &.{ .rm64, .r64, .cl }, &.{ 0x0f, 0xa5 }, 0, .long },
706
707 .{ .shr, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 5, .none },
708 .{ .shr, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 5, .rex },
709 .{ .shr, .m1, &.{ .rm16, .unity }, &.{ 0xd1 }, 5, .none },
710 .{ .shr, .m1, &.{ .rm32, .unity }, &.{ 0xd1 }, 5, .none },
711 .{ .shr, .m1, &.{ .rm64, .unity }, &.{ 0xd1 }, 5, .long },
712 .{ .shr, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 5, .none },
713 .{ .shr, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 5, .rex },
714 .{ .shr, .mc, &.{ .rm16, .cl }, &.{ 0xd3 }, 5, .none },
715 .{ .shr, .mc, &.{ .rm32, .cl }, &.{ 0xd3 }, 5, .none },
716 .{ .shr, .mc, &.{ .rm64, .cl }, &.{ 0xd3 }, 5, .long },
717 .{ .shr, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 5, .none },
718 .{ .shr, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 5, .rex },
719 .{ .shr, .mi, &.{ .rm16, .imm8 }, &.{ 0xc1 }, 5, .none },
720 .{ .shr, .mi, &.{ .rm32, .imm8 }, &.{ 0xc1 }, 5, .none },
721 .{ .shr, .mi, &.{ .rm64, .imm8 }, &.{ 0xc1 }, 5, .long },
722
723 .{ .shrd, .mri, &.{ .rm16, .r16, .imm8 }, &.{ 0x0f, 0xac }, 0, .none },
724 .{ .shrd, .mrc, &.{ .rm16, .r16, .cl }, &.{ 0x0f, 0xad }, 0, .none },
725 .{ .shrd, .mri, &.{ .rm32, .r32, .imm8 }, &.{ 0x0f, 0xac }, 0, .none },
726 .{ .shrd, .mri, &.{ .rm64, .r64, .imm8 }, &.{ 0x0f, 0xac }, 0, .long },
727 .{ .shrd, .mrc, &.{ .rm32, .r32, .cl }, &.{ 0x0f, 0xad }, 0, .none },
728 .{ .shrd, .mrc, &.{ .rm64, .r64, .cl }, &.{ 0x0f, 0xad }, 0, .long },
729
730 .{ .stos, .np, &.{ .m8 }, &.{ 0xaa }, 0, .none },
731 .{ .stos, .np, &.{ .m16 }, &.{ 0xab }, 0, .none },
732 .{ .stos, .np, &.{ .m32 }, &.{ 0xab }, 0, .none },
733 .{ .stos, .np, &.{ .m64 }, &.{ 0xab }, 0, .long },
734
735 .{ .stosb, .np, &.{}, &.{ 0xaa }, 0, .none },
736 .{ .stosw, .np, &.{}, &.{ 0xab }, 0, .short },
737 .{ .stosd, .np, &.{}, &.{ 0xab }, 0, .none },
738 .{ .stosq, .np, &.{}, &.{ 0xab }, 0, .long },
739
740 .{ .sub, .zi, &.{ .al, .imm8 }, &.{ 0x2c }, 0, .none },
741 .{ .sub, .zi, &.{ .ax, .imm16 }, &.{ 0x2d }, 0, .none },
742 .{ .sub, .zi, &.{ .eax, .imm32 }, &.{ 0x2d }, 0, .none },
743 .{ .sub, .zi, &.{ .rax, .imm32s }, &.{ 0x2d }, 0, .long },
744 .{ .sub, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 5, .none },
745 .{ .sub, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 5, .rex },
746 .{ .sub, .mi, &.{ .rm16, .imm16 }, &.{ 0x81 }, 5, .none },
747 .{ .sub, .mi, &.{ .rm32, .imm32 }, &.{ 0x81 }, 5, .none },
748 .{ .sub, .mi, &.{ .rm64, .imm32s }, &.{ 0x81 }, 5, .long },
749 .{ .sub, .mi, &.{ .rm16, .imm8s }, &.{ 0x83 }, 5, .none },
750 .{ .sub, .mi, &.{ .rm32, .imm8s }, &.{ 0x83 }, 5, .none },
751 .{ .sub, .mi, &.{ .rm64, .imm8s }, &.{ 0x83 }, 5, .long },
752 .{ .sub, .mr, &.{ .rm8, .r8 }, &.{ 0x28 }, 0, .none },
753 .{ .sub, .mr, &.{ .rm8, .r8 }, &.{ 0x28 }, 0, .rex },
754 .{ .sub, .mr, &.{ .rm16, .r16 }, &.{ 0x29 }, 0, .none },
755 .{ .sub, .mr, &.{ .rm32, .r32 }, &.{ 0x29 }, 0, .none },
756 .{ .sub, .mr, &.{ .rm64, .r64 }, &.{ 0x29 }, 0, .long },
757 .{ .sub, .rm, &.{ .r8, .rm8 }, &.{ 0x2a }, 0, .none },
758 .{ .sub, .rm, &.{ .r8, .rm8 }, &.{ 0x2a }, 0, .rex },
759 .{ .sub, .rm, &.{ .r16, .rm16 }, &.{ 0x2b }, 0, .none },
760 .{ .sub, .rm, &.{ .r32, .rm32 }, &.{ 0x2b }, 0, .none },
761 .{ .sub, .rm, &.{ .r64, .rm64 }, &.{ 0x2b }, 0, .long },
762
763 .{ .syscall, .np, &.{}, &.{ 0x0f, 0x05 }, 0, .none }
759764,
760 .{ .@"test", .zi, .al, .imm8, .none, .none, &.{ 0xa8 }, 0, .none },
761 .{ .@"test", .zi, .ax, .imm16, .none, .none, &.{ 0xa9 }, 0, .none },
762 .{ .@"test", .zi, .eax, .imm32, .none, .none, &.{ 0xa9 }, 0, .none },
763 .{ .@"test", .zi, .rax, .imm32s, .none, .none, &.{ 0xa9 }, 0, .long },
764 .{ .@"test", .mi, .rm8, .imm8, .none, .none, &.{ 0xf6 }, 0, .none },
765 .{ .@"test", .mi, .rm8, .imm8, .none, .none, &.{ 0xf6 }, 0, .rex },
766 .{ .@"test", .mi, .rm16, .imm16, .none, .none, &.{ 0xf7 }, 0, .none },
767 .{ .@"test", .mi, .rm32, .imm32, .none, .none, &.{ 0xf7 }, 0, .none },
768 .{ .@"test", .mi, .rm64, .imm32s, .none, .none, &.{ 0xf7 }, 0, .long },
769 .{ .@"test", .mr, .rm8, .r8, .none, .none, &.{ 0x84 }, 0, .none },
770 .{ .@"test", .mr, .rm8, .r8, .none, .none, &.{ 0x84 }, 0, .rex },
771 .{ .@"test", .mr, .rm16, .r16, .none, .none, &.{ 0x85 }, 0, .none },
772 .{ .@"test", .mr, .rm32, .r32, .none, .none, &.{ 0x85 }, 0, .none },
773 .{ .@"test", .mr, .rm64, .r64, .none, .none, &.{ 0x85 }, 0, .long },
774
775 .{ .tzcnt, .rm, .r16, .rm16, .none, .none, &.{ 0xf3, 0x0f, 0xbc }, 0, .none },
776 .{ .tzcnt, .rm, .r32, .rm32, .none, .none, &.{ 0xf3, 0x0f, 0xbc }, 0, .none },
777 .{ .tzcnt, .rm, .r64, .rm64, .none, .none, &.{ 0xf3, 0x0f, 0xbc }, 0, .long },
778
779 .{ .ud2, .np, .none, .none, .none, .none, &.{ 0x0f, 0x0b }, 0, .none },
780
781 .{ .xadd, .mr, .rm8, .r8, .none, .none, &.{ 0x0f, 0xc0 }, 0, .none },
782 .{ .xadd, .mr, .rm8, .r8, .none, .none, &.{ 0x0f, 0xc0 }, 0, .rex },
783 .{ .xadd, .mr, .rm16, .r16, .none, .none, &.{ 0x0f, 0xc1 }, 0, .none },
784 .{ .xadd, .mr, .rm32, .r32, .none, .none, &.{ 0x0f, 0xc1 }, 0, .none },
785 .{ .xadd, .mr, .rm64, .r64, .none, .none, &.{ 0x0f, 0xc1 }, 0, .long },
786
787 .{ .xchg, .o, .ax, .r16, .none, .none, &.{ 0x90 }, 0, .none },
788 .{ .xchg, .o, .r16, .ax, .none, .none, &.{ 0x90 }, 0, .none },
789 .{ .xchg, .o, .eax, .r32, .none, .none, &.{ 0x90 }, 0, .none },
790 .{ .xchg, .o, .rax, .r64, .none, .none, &.{ 0x90 }, 0, .long },
791 .{ .xchg, .o, .r32, .eax, .none, .none, &.{ 0x90 }, 0, .none },
792 .{ .xchg, .o, .r64, .rax, .none, .none, &.{ 0x90 }, 0, .long },
793 .{ .xchg, .mr, .rm8, .r8, .none, .none, &.{ 0x86 }, 0, .none },
794 .{ .xchg, .mr, .rm8, .r8, .none, .none, &.{ 0x86 }, 0, .rex },
795 .{ .xchg, .rm, .r8, .rm8, .none, .none, &.{ 0x86 }, 0, .none },
796 .{ .xchg, .rm, .r8, .rm8, .none, .none, &.{ 0x86 }, 0, .rex },
797 .{ .xchg, .mr, .rm16, .r16, .none, .none, &.{ 0x87 }, 0, .none },
798 .{ .xchg, .rm, .r16, .rm16, .none, .none, &.{ 0x87 }, 0, .none },
799 .{ .xchg, .mr, .rm32, .r32, .none, .none, &.{ 0x87 }, 0, .none },
800 .{ .xchg, .mr, .rm64, .r64, .none, .none, &.{ 0x87 }, 0, .long },
801 .{ .xchg, .rm, .r32, .rm32, .none, .none, &.{ 0x87 }, 0, .none },
802 .{ .xchg, .rm, .r64, .rm64, .none, .none, &.{ 0x87 }, 0, .long },
803
804 .{ .xor, .zi, .al, .imm8, .none, .none, &.{ 0x34 }, 0, .none },
805 .{ .xor, .zi, .ax, .imm16, .none, .none, &.{ 0x35 }, 0, .none },
806 .{ .xor, .zi, .eax, .imm32, .none, .none, &.{ 0x35 }, 0, .none },
807 .{ .xor, .zi, .rax, .imm32s, .none, .none, &.{ 0x35 }, 0, .long },
808 .{ .xor, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 6, .none },
809 .{ .xor, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 6, .rex },
810 .{ .xor, .mi, .rm16, .imm16, .none, .none, &.{ 0x81 }, 6, .none },
811 .{ .xor, .mi, .rm32, .imm32, .none, .none, &.{ 0x81 }, 6, .none },
812 .{ .xor, .mi, .rm64, .imm32s, .none, .none, &.{ 0x81 }, 6, .long },
813 .{ .xor, .mi, .rm16, .imm8s, .none, .none, &.{ 0x83 }, 6, .none },
814 .{ .xor, .mi, .rm32, .imm8s, .none, .none, &.{ 0x83 }, 6, .none },
815 .{ .xor, .mi, .rm64, .imm8s, .none, .none, &.{ 0x83 }, 6, .long },
816 .{ .xor, .mr, .rm8, .r8, .none, .none, &.{ 0x30 }, 0, .none },
817 .{ .xor, .mr, .rm8, .r8, .none, .none, &.{ 0x30 }, 0, .rex },
818 .{ .xor, .mr, .rm16, .r16, .none, .none, &.{ 0x31 }, 0, .none },
819 .{ .xor, .mr, .rm32, .r32, .none, .none, &.{ 0x31 }, 0, .none },
820 .{ .xor, .mr, .rm64, .r64, .none, .none, &.{ 0x31 }, 0, .long },
821 .{ .xor, .rm, .r8, .rm8, .none, .none, &.{ 0x32 }, 0, .none },
822 .{ .xor, .rm, .r8, .rm8, .none, .none, &.{ 0x32 }, 0, .rex },
823 .{ .xor, .rm, .r16, .rm16, .none, .none, &.{ 0x33 }, 0, .none },
824 .{ .xor, .rm, .r32, .rm32, .none, .none, &.{ 0x33 }, 0, .none },
825 .{ .xor, .rm, .r64, .rm64, .none, .none, &.{ 0x33 }, 0, .long },
765 .{ .@"test", .zi, &.{ .al, .imm8 }, &.{ 0xa8 }, 0, .none },
766 .{ .@"test", .zi, &.{ .ax, .imm16 }, &.{ 0xa9 }, 0, .none },
767 .{ .@"test", .zi, &.{ .eax, .imm32 }, &.{ 0xa9 }, 0, .none },
768 .{ .@"test", .zi, &.{ .rax, .imm32s }, &.{ 0xa9 }, 0, .long },
769 .{ .@"test", .mi, &.{ .rm8, .imm8 }, &.{ 0xf6 }, 0, .none },
770 .{ .@"test", .mi, &.{ .rm8, .imm8 }, &.{ 0xf6 }, 0, .rex },
771 .{ .@"test", .mi, &.{ .rm16, .imm16 }, &.{ 0xf7 }, 0, .none },
772 .{ .@"test", .mi, &.{ .rm32, .imm32 }, &.{ 0xf7 }, 0, .none },
773 .{ .@"test", .mi, &.{ .rm64, .imm32s }, &.{ 0xf7 }, 0, .long },
774 .{ .@"test", .mr, &.{ .rm8, .r8 }, &.{ 0x84 }, 0, .none },
775 .{ .@"test", .mr, &.{ .rm8, .r8 }, &.{ 0x84 }, 0, .rex },
776 .{ .@"test", .mr, &.{ .rm16, .r16 }, &.{ 0x85 }, 0, .none },
777 .{ .@"test", .mr, &.{ .rm32, .r32 }, &.{ 0x85 }, 0, .none },
778 .{ .@"test", .mr, &.{ .rm64, .r64 }, &.{ 0x85 }, 0, .long },
779
780 .{ .tzcnt, .rm, &.{ .r16, .rm16 }, &.{ 0xf3, 0x0f, 0xbc }, 0, .none },
781 .{ .tzcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xbc }, 0, .none },
782 .{ .tzcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xbc }, 0, .long },
783
784 .{ .ud2, .np, &.{}, &.{ 0x0f, 0x0b }, 0, .none },
785
786 .{ .xadd, .mr, &.{ .rm8, .r8 }, &.{ 0x0f, 0xc0 }, 0, .none },
787 .{ .xadd, .mr, &.{ .rm8, .r8 }, &.{ 0x0f, 0xc0 }, 0, .rex },
788 .{ .xadd, .mr, &.{ .rm16, .r16 }, &.{ 0x0f, 0xc1 }, 0, .none },
789 .{ .xadd, .mr, &.{ .rm32, .r32 }, &.{ 0x0f, 0xc1 }, 0, .none },
790 .{ .xadd, .mr, &.{ .rm64, .r64 }, &.{ 0x0f, 0xc1 }, 0, .long },
791
792 .{ .xchg, .o, &.{ .ax, .r16 }, &.{ 0x90 }, 0, .none },
793 .{ .xchg, .o, &.{ .r16, .ax }, &.{ 0x90 }, 0, .none },
794 .{ .xchg, .o, &.{ .eax, .r32 }, &.{ 0x90 }, 0, .none },
795 .{ .xchg, .o, &.{ .rax, .r64 }, &.{ 0x90 }, 0, .long },
796 .{ .xchg, .o, &.{ .r32, .eax }, &.{ 0x90 }, 0, .none },
797 .{ .xchg, .o, &.{ .r64, .rax }, &.{ 0x90 }, 0, .long },
798 .{ .xchg, .mr, &.{ .rm8, .r8 }, &.{ 0x86 }, 0, .none },
799 .{ .xchg, .mr, &.{ .rm8, .r8 }, &.{ 0x86 }, 0, .rex },
800 .{ .xchg, .rm, &.{ .r8, .rm8 }, &.{ 0x86 }, 0, .none },
801 .{ .xchg, .rm, &.{ .r8, .rm8 }, &.{ 0x86 }, 0, .rex },
802 .{ .xchg, .mr, &.{ .rm16, .r16 }, &.{ 0x87 }, 0, .none },
803 .{ .xchg, .rm, &.{ .r16, .rm16 }, &.{ 0x87 }, 0, .none },
804 .{ .xchg, .mr, &.{ .rm32, .r32 }, &.{ 0x87 }, 0, .none },
805 .{ .xchg, .mr, &.{ .rm64, .r64 }, &.{ 0x87 }, 0, .long },
806 .{ .xchg, .rm, &.{ .r32, .rm32 }, &.{ 0x87 }, 0, .none },
807 .{ .xchg, .rm, &.{ .r64, .rm64 }, &.{ 0x87 }, 0, .long },
808
809 .{ .xor, .zi, &.{ .al, .imm8 }, &.{ 0x34 }, 0, .none },
810 .{ .xor, .zi, &.{ .ax, .imm16 }, &.{ 0x35 }, 0, .none },
811 .{ .xor, .zi, &.{ .eax, .imm32 }, &.{ 0x35 }, 0, .none },
812 .{ .xor, .zi, &.{ .rax, .imm32s }, &.{ 0x35 }, 0, .long },
813 .{ .xor, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 6, .none },
814 .{ .xor, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 6, .rex },
815 .{ .xor, .mi, &.{ .rm16, .imm16 }, &.{ 0x81 }, 6, .none },
816 .{ .xor, .mi, &.{ .rm32, .imm32 }, &.{ 0x81 }, 6, .none },
817 .{ .xor, .mi, &.{ .rm64, .imm32s }, &.{ 0x81 }, 6, .long },
818 .{ .xor, .mi, &.{ .rm16, .imm8s }, &.{ 0x83 }, 6, .none },
819 .{ .xor, .mi, &.{ .rm32, .imm8s }, &.{ 0x83 }, 6, .none },
820 .{ .xor, .mi, &.{ .rm64, .imm8s }, &.{ 0x83 }, 6, .long },
821 .{ .xor, .mr, &.{ .rm8, .r8 }, &.{ 0x30 }, 0, .none },
822 .{ .xor, .mr, &.{ .rm8, .r8 }, &.{ 0x30 }, 0, .rex },
823 .{ .xor, .mr, &.{ .rm16, .r16 }, &.{ 0x31 }, 0, .none },
824 .{ .xor, .mr, &.{ .rm32, .r32 }, &.{ 0x31 }, 0, .none },
825 .{ .xor, .mr, &.{ .rm64, .r64 }, &.{ 0x31 }, 0, .long },
826 .{ .xor, .rm, &.{ .r8, .rm8 }, &.{ 0x32 }, 0, .none },
827 .{ .xor, .rm, &.{ .r8, .rm8 }, &.{ 0x32 }, 0, .rex },
828 .{ .xor, .rm, &.{ .r16, .rm16 }, &.{ 0x33 }, 0, .none },
829 .{ .xor, .rm, &.{ .r32, .rm32 }, &.{ 0x33 }, 0, .none },
830 .{ .xor, .rm, &.{ .r64, .rm64 }, &.{ 0x33 }, 0, .long },
826831
827832 // SSE
828 .{ .addss, .rm, .xmm, .xmm_m32, .none, .none, &.{ 0xf3, 0x0f, 0x58 }, 0, .sse },
833 .{ .addss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x58 }, 0, .sse },
829834
830 .{ .cmpss, .rmi, .xmm, .xmm_m32, .imm8, .none, &.{ 0xf3, 0x0f, 0xc2 }, 0, .sse },
835 .{ .cmpss, .rmi, &.{ .xmm, .xmm_m32, .imm8 }, &.{ 0xf3, 0x0f, 0xc2 }, 0, .sse },
831836
832 .{ .divss, .rm, .xmm, .xmm_m32, .none, .none, &.{ 0xf3, 0x0f, 0x5e }, 0, .sse },
837 .{ .divss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5e }, 0, .sse },
833838
834 .{ .maxss, .rm, .xmm, .xmm_m32, .none, .none, &.{ 0xf3, 0x0f, 0x5f }, 0, .sse },
839 .{ .maxss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5f }, 0, .sse },
835840
836 .{ .minss, .rm, .xmm, .xmm_m32, .none, .none, &.{ 0xf3, 0x0f, 0x5d }, 0, .sse },
841 .{ .minss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5d }, 0, .sse },
837842
838 .{ .movss, .rm, .xmm, .xmm_m32, .none, .none, &.{ 0xf3, 0x0f, 0x10 }, 0, .sse },
839 .{ .movss, .mr, .xmm_m32, .xmm, .none, .none, &.{ 0xf3, 0x0f, 0x11 }, 0, .sse },
843 .{ .movss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x10 }, 0, .sse },
844 .{ .movss, .mr, &.{ .xmm_m32, .xmm }, &.{ 0xf3, 0x0f, 0x11 }, 0, .sse },
840845
841 .{ .mulss, .rm, .xmm, .xmm_m32, .none, .none, &.{ 0xf3, 0x0f, 0x59 }, 0, .sse },
846 .{ .mulss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x59 }, 0, .sse },
842847
843 .{ .subss, .rm, .xmm, .xmm_m32, .none, .none, &.{ 0xf3, 0x0f, 0x5c }, 0, .sse },
848 .{ .subss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5c }, 0, .sse },
844849
845 .{ .ucomiss, .rm, .xmm, .xmm_m32, .none, .none, &.{ 0x0f, 0x2e }, 0, .sse },
850 .{ .ucomiss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0x0f, 0x2e }, 0, .sse },
846851
847852 // SSE2
848 .{ .addsd, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0xf2, 0x0f, 0x58 }, 0, .sse2 },
853 .{ .addsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x58 }, 0, .sse2 },
849854
850 .{ .cmpsd, .rmi, .xmm, .xmm_m64, .imm8, .none, &.{ 0xf2, 0x0f, 0xc2 }, 0, .sse2 },
855 .{ .cmpsd, .rmi, &.{ .xmm, .xmm_m64, .imm8 }, &.{ 0xf2, 0x0f, 0xc2 }, 0, .sse2 },
851856
852 .{ .divsd, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0xf2, 0x0f, 0x5e }, 0, .sse2 },
857 .{ .divsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5e }, 0, .sse2 },
853858
854 .{ .maxsd, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0xf2, 0x0f, 0x5f }, 0, .sse2 },
859 .{ .maxsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5f }, 0, .sse2 },
855860
856 .{ .minsd, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0xf2, 0x0f, 0x5d }, 0, .sse2 },
861 .{ .minsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5d }, 0, .sse2 },
857862
858 .{ .movq, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0xf3, 0x0f, 0x7e }, 0, .sse2 },
859 .{ .movq, .mr, .xmm_m64, .xmm, .none, .none, &.{ 0x66, 0x0f, 0xd6 }, 0, .sse2 },
863 .{ .movq, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf3, 0x0f, 0x7e }, 0, .sse2 },
864 .{ .movq, .mr, &.{ .xmm_m64, .xmm }, &.{ 0x66, 0x0f, 0xd6 }, 0, .sse2 },
860865
861 .{ .mulsd, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0xf2, 0x0f, 0x59 }, 0, .sse2 },
866 .{ .mulsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x59 }, 0, .sse2 },
862867
863 .{ .subsd, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0xf2, 0x0f, 0x5c }, 0, .sse2 },
868 .{ .subsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5c }, 0, .sse2 },
864869
865 .{ .movsd, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0xf2, 0x0f, 0x10 }, 0, .sse2 },
866 .{ .movsd, .mr, .xmm_m64, .xmm, .none, .none, &.{ 0xf2, 0x0f, 0x11 }, 0, .sse2 },
870 .{ .movsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x10 }, 0, .sse2 },
871 .{ .movsd, .mr, &.{ .xmm_m64, .xmm }, &.{ 0xf2, 0x0f, 0x11 }, 0, .sse2 },
867872
868 .{ .ucomisd, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0x66, 0x0f, 0x2e }, 0, .sse2 },
873 .{ .ucomisd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0x66, 0x0f, 0x2e }, 0, .sse2 },
869874
870875 // SSE4.1
871 .{ .roundss, .rmi, .xmm, .xmm_m32, .imm8, .none, &.{ 0x66, 0x0f, 0x3a, 0x0a }, 0, .sse4_1 },
872 .{ .roundsd, .rmi, .xmm, .xmm_m64, .imm8, .none, &.{ 0x66, 0x0f, 0x3a, 0x0b }, 0, .sse4_1 },
876 .{ .roundss, .rmi, &.{ .xmm, .xmm_m32, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0a }, 0, .sse4_1 },
877 .{ .roundsd, .rmi, &.{ .xmm, .xmm_m64, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0b }, 0, .sse4_1 },
873878};
874879// zig fmt: on