aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/arch/x86_64/CodeGen.zig21
-rw-r--r--src/arch/x86_64/Emit.zig905
-rw-r--r--src/arch/x86_64/Encoding.zig294
-rw-r--r--src/arch/x86_64/Lower.zig465
-rw-r--r--src/arch/x86_64/Mir.zig19
-rw-r--r--src/arch/x86_64/bits.zig2
-rw-r--r--src/arch/x86_64/encoder.zig919
-rw-r--r--src/arch/x86_64/encodings.zig1669
8 files changed, 2167 insertions, 2127 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig
index b32d7ef214..5ab0e64615 100644
--- a/src/arch/x86_64/CodeGen.zig
+++ b/src/arch/x86_64/CodeGen.zig
@@ -341,19 +341,22 @@ pub fn generate(
defer mir.deinit(bin_file.allocator);
var emit = Emit{
- .mir = mir,
+ .lower = .{
+ .allocator = bin_file.allocator,
+ .mir = mir,
+ .target = &bin_file.options.target,
+ .src_loc = src_loc,
+ },
.bin_file = bin_file,
.debug_output = debug_output,
- .target = &bin_file.options.target,
- .src_loc = src_loc,
.code = code,
.prev_di_pc = 0,
.prev_di_line = module_fn.lbrace_line,
.prev_di_column = module_fn.lbrace_column,
};
defer emit.deinit();
- emit.lowerMir() catch |err| switch (err) {
- error.EmitFail => return Result{ .fail = emit.err_msg.? },
+ emit.emitMir() catch |err| switch (err) {
+ error.LowerFail, error.EmitFail => return Result{ .fail = emit.lower.err_msg.? },
error.InvalidInstruction, error.CannotEncode => |e| {
const msg = switch (e) {
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
if (reg.to64() == .rax) {
// If this is RAX, we can use a direct load.
// Otherwise, we need to load the address, then indirectly load the value.
- var moffs: Mir.MemoryMoffs = .{
- .seg = @enumToInt(Register.ds),
- .msb = undefined,
- .lsb = undefined,
- };
- moffs.encodeOffset(x);
_ = try self.addInst(.{
.tag = .mov_moffs,
.ops = .rax_moffs,
- .data = .{ .payload = try self.addExtra(moffs) },
+ .data = .{ .payload = try self.addExtra(Mir.MemoryMoffs.encode(.ds, x)) },
});
} else {
// Rather than duplicate the logic used for the move, we just use a self-call with a new MCValue.
diff --git a/src/arch/x86_64/Emit.zig b/src/arch/x86_64/Emit.zig
index b65d22807a..052139a4e5 100644
--- a/src/arch/x86_64/Emit.zig
+++ b/src/arch/x86_64/Emit.zig
@@ -1,40 +1,8 @@
-//! This file contains the functionality for lowering x86_64 MIR into
-//! machine code
+//! This file contains the functionality for emitting x86_64 MIR as machine code
-const Emit = @This();
-
-const std = @import("std");
-const assert = std.debug.assert;
-const bits = @import("bits.zig");
-const abi = @import("abi.zig");
-const encoder = @import("encoder.zig");
-const link = @import("../../link.zig");
-const log = std.log.scoped(.codegen);
-const math = std.math;
-const mem = std.mem;
-const testing = std.testing;
-
-const Air = @import("../../Air.zig");
-const Allocator = mem.Allocator;
-const CodeGen = @import("CodeGen.zig");
-const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput;
-const Encoder = bits.Encoder;
-const ErrorMsg = Module.ErrorMsg;
-const Immediate = bits.Immediate;
-const Instruction = encoder.Instruction;
-const MCValue = @import("CodeGen.zig").MCValue;
-const Memory = bits.Memory;
-const Mir = @import("Mir.zig");
-const Module = @import("../../Module.zig");
-const Register = bits.Register;
-const Type = @import("../../type.zig").Type;
-
-mir: Mir,
+lower: Lower,
bin_file: *link.File,
debug_output: DebugInfoOutput,
-target: *const std.Target,
-err_msg: ?*ErrorMsg = null,
-src_loc: Module.SrcLoc,
code: *std.ArrayList(u8),
prev_di_line: u32,
@@ -45,166 +13,176 @@ prev_di_pc: usize,
code_offset_mapping: std.AutoHashMapUnmanaged(Mir.Inst.Index, usize) = .{},
relocs: std.ArrayListUnmanaged(Reloc) = .{},
-const InnerError = error{
- OutOfMemory,
- EmitFail,
- InvalidInstruction,
- CannotEncode,
-};
-
-const Reloc = struct {
- /// Offset of the instruction.
- source: usize,
- /// Target of the relocation.
- target: Mir.Inst.Index,
- /// Offset of the relocation within the instruction.
- offset: usize,
- /// Length of the instruction.
- length: u5,
-};
-
-pub fn lowerMir(emit: *Emit) InnerError!void {
- const mir_tags = emit.mir.instructions.items(.tag);
-
- for (mir_tags, 0..) |tag, index| {
- const inst = @intCast(u32, index);
- try emit.code_offset_mapping.putNoClobber(emit.bin_file.allocator, inst, emit.code.items.len);
- switch (tag) {
- .adc,
- .add,
- .@"and",
- .bsf,
- .bsr,
- .bswap,
- .bt,
- .btc,
- .btr,
- .bts,
- .call,
- .cbw,
- .cwde,
- .cdqe,
- .cwd,
- .cdq,
- .cqo,
- .cmp,
- .cmpxchg,
- .div,
- .fisttp,
- .fld,
- .idiv,
- .imul,
- .int3,
- .jmp,
- .lea,
- .lfence,
- .lzcnt,
- .mfence,
- .mov,
- .movbe,
- .movzx,
- .mul,
- .neg,
- .nop,
- .not,
- .@"or",
- .pop,
- .popcnt,
- .push,
- .rcl,
- .rcr,
- .ret,
- .rol,
- .ror,
- .sal,
- .sar,
- .sbb,
- .sfence,
- .shl,
- .shld,
- .shr,
- .shrd,
- .sub,
- .syscall,
- .@"test",
- .tzcnt,
- .ud2,
- .xadd,
- .xchg,
- .xor,
-
- .addss,
- .cmpss,
- .divss,
- .maxss,
- .minss,
- .movss,
- .mulss,
- .roundss,
- .subss,
- .ucomiss,
- .addsd,
- .cmpsd,
- .divsd,
- .maxsd,
- .minsd,
- .movsd,
- .mulsd,
- .roundsd,
- .subsd,
- .ucomisd,
- => try emit.mirEncodeGeneric(tag, inst),
-
- .cmps,
- .lods,
- .movs,
- .scas,
- .stos,
- => try emit.mirString(tag, inst),
-
- .cmpxchgb => try emit.mirCmpxchgBytes(inst),
-
- .jmp_reloc => try emit.mirJmpReloc(inst),
-
- .call_extern => try emit.mirCallExtern(inst),
-
- .lea_linker => try emit.mirLeaLinker(inst),
-
- .mov_moffs => try emit.mirMovMoffs(inst),
-
- .movsx => try emit.mirMovsx(inst),
- .cmovcc => try emit.mirCmovcc(inst),
- .setcc => try emit.mirSetcc(inst),
- .jcc => try emit.mirJcc(inst),
+pub const Error = Lower.Error || error{EmitFail};
+
+pub fn emitMir(emit: *Emit) Error!void {
+ for (0..emit.lower.mir.instructions.len) |i| {
+ const index = @intCast(Mir.Inst.Index, i);
+ const inst = emit.lower.mir.instructions.get(index);
+
+ const start_offset = @intCast(u32, emit.code.items.len);
+ try emit.code_offset_mapping.putNoClobber(emit.lower.allocator, index, start_offset);
+ for (try emit.lower.lowerMir(inst)) |lower_inst| try lower_inst.encode(emit.code.writer());
+ const end_offset = @intCast(u32, emit.code.items.len);
+
+ switch (inst.tag) {
+ else => {},
+
+ .jmp_reloc => try emit.relocs.append(emit.lower.allocator, .{
+ .source = start_offset,
+ .target = inst.data.inst,
+ .offset = end_offset - 4,
+ .length = 5,
+ }),
+
+ .call_extern => if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
+ // Add relocation to the decl.
+ const atom_index = macho_file.getAtomIndexForSymbol(
+ .{ .sym_index = inst.data.relocation.atom_index, .file = null },
+ ).?;
+ const target = macho_file.getGlobalByIndex(inst.data.relocation.sym_index);
+ try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
+ .type = @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),
+ .target = target,
+ .offset = end_offset - 4,
+ .addend = 0,
+ .pcrel = true,
+ .length = 2,
+ });
+ } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
+ // Add relocation to the decl.
+ const atom_index = coff_file.getAtomIndexForSymbol(
+ .{ .sym_index = inst.data.relocation.atom_index, .file = null },
+ ).?;
+ const target = coff_file.getGlobalByIndex(inst.data.relocation.sym_index);
+ try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
+ .type = .direct,
+ .target = target,
+ .offset = end_offset - 4,
+ .addend = 0,
+ .pcrel = true,
+ .length = 2,
+ });
+ } else return emit.fail("TODO implement {} for {}", .{ inst.tag, emit.bin_file.tag }),
+
+ .lea_linker => if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
+ const metadata =
+ emit.lower.mir.extraData(Mir.LeaRegisterReloc, inst.data.payload).data;
+ const reloc_type = switch (inst.ops) {
+ .got_reloc => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_GOT),
+ .direct_reloc => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_SIGNED),
+ else => unreachable,
+ };
+ const atom_index = macho_file.getAtomIndexForSymbol(.{
+ .sym_index = metadata.atom_index,
+ .file = null,
+ }).?;
+ try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
+ .type = reloc_type,
+ .target = .{ .sym_index = metadata.sym_index, .file = null },
+ .offset = @intCast(u32, end_offset - 4),
+ .addend = 0,
+ .pcrel = true,
+ .length = 2,
+ });
+ } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
+ const metadata =
+ emit.lower.mir.extraData(Mir.LeaRegisterReloc, inst.data.payload).data;
+ const atom_index = coff_file.getAtomIndexForSymbol(.{
+ .sym_index = metadata.atom_index,
+ .file = null,
+ }).?;
+ try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
+ .type = switch (inst.ops) {
+ .got_reloc => .got,
+ .direct_reloc => .direct,
+ .import_reloc => .import,
+ else => unreachable,
+ },
+ .target = switch (inst.ops) {
+ .got_reloc,
+ .direct_reloc,
+ => .{ .sym_index = metadata.sym_index, .file = null },
+ .import_reloc => coff_file.getGlobalByIndex(metadata.sym_index),
+ else => unreachable,
+ },
+ .offset = @intCast(u32, end_offset - 4),
+ .addend = 0,
+ .pcrel = true,
+ .length = 2,
+ });
+ } else return emit.fail("TODO implement {} for {}", .{ inst.tag, emit.bin_file.tag }),
+
+ .jcc => try emit.relocs.append(emit.lower.allocator, .{
+ .source = start_offset,
+ .target = inst.data.inst_cc.inst,
+ .offset = end_offset - 4,
+ .length = 6,
+ }),
- .dbg_line => try emit.mirDbgLine(inst),
- .dbg_prologue_end => try emit.mirDbgPrologueEnd(inst),
- .dbg_epilogue_begin => try emit.mirDbgEpilogueBegin(inst),
+ .dbg_line => {
+ const dbg_line_column =
+ emit.lower.mir.extraData(Mir.DbgLineColumn, inst.data.payload).data;
+ try emit.dbgAdvancePCAndLine(dbg_line_column.line, dbg_line_column.column);
+ },
- .push_regs => try emit.mirPushPopRegisterList(.push, inst),
- .pop_regs => try emit.mirPushPopRegisterList(.pop, inst),
+ .dbg_prologue_end => {
+ switch (emit.debug_output) {
+ .dwarf => |dw| {
+ try dw.setPrologueEnd();
+ log.debug("mirDbgPrologueEnd (line={d}, col={d})", .{
+ emit.prev_di_line, emit.prev_di_column,
+ });
+ try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
+ },
+ .plan9 => {},
+ .none => {},
+ }
+ },
- .dead => {},
+ .dbg_epilogue_begin => {
+ switch (emit.debug_output) {
+ .dwarf => |dw| {
+ try dw.setEpilogueBegin();
+ log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{
+ emit.prev_di_line, emit.prev_di_column,
+ });
+ try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
+ },
+ .plan9 => {},
+ .none => {},
+ }
+ },
}
}
-
try emit.fixupRelocs();
}
pub fn deinit(emit: *Emit) void {
- emit.relocs.deinit(emit.bin_file.allocator);
- emit.code_offset_mapping.deinit(emit.bin_file.allocator);
+ emit.relocs.deinit(emit.lower.allocator);
+ emit.code_offset_mapping.deinit(emit.lower.allocator);
emit.* = undefined;
}
-fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError {
- @setCold(true);
- assert(emit.err_msg == null);
- emit.err_msg = try ErrorMsg.create(emit.bin_file.allocator, emit.src_loc, format, args);
- return error.EmitFail;
+fn fail(emit: *Emit, comptime format: []const u8, args: anytype) Error {
+ return switch (emit.lower.fail(format, args)) {
+ error.LowerFail => error.EmitFail,
+ else => |e| e,
+ };
}
-fn fixupRelocs(emit: *Emit) InnerError!void {
+const Reloc = struct {
+ /// Offset of the instruction.
+ source: usize,
+ /// Target of the relocation.
+ target: Mir.Inst.Index,
+ /// Offset of the relocation within the instruction.
+ offset: usize,
+ /// Length of the instruction.
+ length: u5,
+};
+
+fn fixupRelocs(emit: *Emit) Error!void {
// TODO this function currently assumes all relocs via JMP/CALL instructions are 32bit in size.
// This should be reversed like it is done in aarch64 MIR emit code: start with the smallest
// possible resolution, i.e., 8bit, and iteratively converge on the minimum required resolution
@@ -217,532 +195,7 @@ fn fixupRelocs(emit: *Emit) InnerError!void {
}
}
-fn encode(emit: *Emit, mnemonic: Instruction.Mnemonic, ops: Instruction.Init) InnerError!void {
- const inst = try Instruction.new(mnemonic, ops);
- return inst.encode(emit.code.writer());
-}
-
-fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void {
- const mnemonic = inline for (@typeInfo(Instruction.Mnemonic).Enum.fields) |field| {
- if (mem.eql(u8, field.name, @tagName(tag))) break @field(Instruction.Mnemonic, field.name);
- } else unreachable;
-
- const ops = emit.mir.instructions.items(.ops)[inst];
- const data = emit.mir.instructions.items(.data)[inst];
-
- const prefix: Instruction.Prefix = switch (ops) {
- .lock_m_sib,
- .lock_m_rip,
- .lock_mi_sib_u,
- .lock_mi_rip_u,
- .lock_mi_sib_s,
- .lock_mi_rip_s,
- .lock_mr_sib,
- .lock_mr_rip,
- .lock_moffs_rax,
- => .lock,
- else => .none,
- };
-
- var op1: Instruction.Operand = .none;
- var op2: Instruction.Operand = .none;
- var op3: Instruction.Operand = .none;
- var op4: Instruction.Operand = .none;
-
- switch (ops) {
- .none => {},
- .i_s => op1 = .{ .imm = Immediate.s(@bitCast(i32, data.i)) },
- .i_u => op1 = .{ .imm = Immediate.u(data.i) },
- .r => op1 = .{ .reg = data.r },
- .rr => {
- op1 = .{ .reg = data.rr.r1 };
- op2 = .{ .reg = data.rr.r2 };
- },
- .rrr => {
- op1 = .{ .reg = data.rrr.r1 };
- op2 = .{ .reg = data.rrr.r2 };
- op3 = .{ .reg = data.rrr.r3 };
- },
- .ri_s, .ri_u => {
- const imm = switch (ops) {
- .ri_s => Immediate.s(@bitCast(i32, data.ri.i)),
- .ri_u => Immediate.u(data.ri.i),
- else => unreachable,
- };
- op1 = .{ .reg = data.ri.r };
- op2 = .{ .imm = imm };
- },
- .ri64 => {
- const imm64 = emit.mir.extraData(Mir.Imm64, data.rx.payload).data;
- op1 = .{ .reg = data.rx.r };
- op2 = .{ .imm = Immediate.u(Mir.Imm64.decode(imm64)) };
- },
- .rri_s, .rri_u => {
- const imm = switch (ops) {
- .rri_s => Immediate.s(@bitCast(i32, data.rri.i)),
- .rri_u => Immediate.u(data.rri.i),
- else => unreachable,
- };
- op1 = .{ .reg = data.rri.r1 };
- op2 = .{ .reg = data.rri.r2 };
- op3 = .{ .imm = imm };
- },
- .m_sib, .lock_m_sib => {
- const msib = emit.mir.extraData(Mir.MemorySib, data.payload).data;
- op1 = .{ .mem = Mir.MemorySib.decode(msib) };
- },
- .m_rip, .lock_m_rip => {
- const mrip = emit.mir.extraData(Mir.MemoryRip, data.payload).data;
- op1 = .{ .mem = Mir.MemoryRip.decode(mrip) };
- },
- .mi_sib_s, .mi_sib_u, .lock_mi_sib_s, .lock_mi_sib_u => {
- const msib = emit.mir.extraData(Mir.MemorySib, data.ix.payload).data;
- const imm = switch (ops) {
- .mi_sib_s, .lock_mi_sib_s => Immediate.s(@bitCast(i32, data.ix.i)),
- .mi_sib_u, .lock_mi_sib_u => Immediate.u(data.ix.i),
- else => unreachable,
- };
- op1 = .{ .mem = Mir.MemorySib.decode(msib) };
- op2 = .{ .imm = imm };
- },
- .mi_rip_u, .mi_rip_s, .lock_mi_rip_u, .lock_mi_rip_s => {
- const mrip = emit.mir.extraData(Mir.MemoryRip, data.ix.payload).data;
- const imm = switch (ops) {
- .mi_rip_s, .lock_mi_rip_s => Immediate.s(@bitCast(i32, data.ix.i)),
- .mi_rip_u, .lock_mi_rip_u => Immediate.u(data.ix.i),
- else => unreachable,
- };
- op1 = .{ .mem = Mir.MemoryRip.decode(mrip) };
- op2 = .{ .imm = imm };
- },
- .rm_sib, .mr_sib, .lock_mr_sib => {
- const msib = emit.mir.extraData(Mir.MemorySib, data.rx.payload).data;
- const op_r = .{ .reg = data.rx.r };
- const op_m = .{ .mem = Mir.MemorySib.decode(msib) };
- switch (ops) {
- .rm_sib => {
- op1 = op_r;
- op2 = op_m;
- },
- .mr_sib, .lock_mr_sib => {
- op1 = op_m;
- op2 = op_r;
- },
- else => unreachable,
- }
- },
- .rm_rip, .mr_rip, .lock_mr_rip => {
- const mrip = emit.mir.extraData(Mir.MemoryRip, data.rx.payload).data;
- const op_r = .{ .reg = data.rx.r };
- const op_m = .{ .mem = Mir.MemoryRip.decode(mrip) };
- switch (ops) {
- .rm_rip => {
- op1 = op_r;
- op2 = op_m;
- },
- .mr_rip, .lock_mr_rip => {
- op1 = op_m;
- op2 = op_r;
- },
- else => unreachable,
- }
- },
- .mrr_sib => {
- const msib = emit.mir.extraData(Mir.MemorySib, data.rrx.payload).data;
- op1 = .{ .mem = Mir.MemorySib.decode(msib) };
- op2 = .{ .reg = data.rrx.r1 };
- op2 = .{ .reg = data.rrx.r2 };
- },
- .mrr_rip => {
- const mrip = emit.mir.extraData(Mir.MemoryRip, data.rrx.payload).data;
- op1 = .{ .mem = Mir.MemoryRip.decode(mrip) };
- op2 = .{ .reg = data.rrx.r1 };
- op2 = .{ .reg = data.rrx.r2 };
- },
- .mri_sib => {
- const msib = emit.mir.extraData(Mir.MemorySib, data.rix.payload).data;
- op1 = .{ .mem = Mir.MemorySib.decode(msib) };
- op2 = .{ .reg = data.rix.r };
- op3 = .{ .imm = Immediate.u(data.rix.i) };
- },
- .mri_rip => {
- const mrip = emit.mir.extraData(Mir.MemoryRip, data.rix.payload).data;
- op1 = .{ .mem = Mir.MemoryRip.decode(mrip) };
- op2 = .{ .reg = data.rix.r };
- op3 = .{ .imm = Immediate.u(data.rix.i) };
- },
- else => return emit.fail("TODO handle generic encoding: {s}, {s}", .{
- @tagName(mnemonic),
- @tagName(ops),
- }),
- }
-
- return emit.encode(mnemonic, .{
- .prefix = prefix,
- .op1 = op1,
- .op2 = op2,
- .op3 = op3,
- .op4 = op4,
- });
-}
-
-fn mirString(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void {
- const ops = emit.mir.instructions.items(.ops)[inst];
- switch (ops) {
- .string => {
- const data = emit.mir.instructions.items(.data)[inst].string;
- const mnemonic = switch (tag) {
- inline .cmps, .lods, .movs, .scas, .stos => |comptime_tag| switch (data.width) {
- inline else => |comptime_width| @field(
- Instruction.Mnemonic,
- @tagName(comptime_tag) ++ @tagName(comptime_width),
- ),
- },
- else => unreachable,
- };
- return emit.encode(mnemonic, .{ .prefix = switch (data.repeat) {
- inline else => |comptime_repeat| @field(Instruction.Prefix, @tagName(comptime_repeat)),
- } });
- },
- else => unreachable,
- }
-}
-
-fn mirCmpxchgBytes(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
- const ops = emit.mir.instructions.items(.ops)[inst];
- const data = emit.mir.instructions.items(.data)[inst];
-
- var op1: Instruction.Operand = .none;
- switch (ops) {
- .m_sib, .lock_m_sib => {
- const sib = emit.mir.extraData(Mir.MemorySib, data.payload).data;
- op1 = .{ .mem = Mir.MemorySib.decode(sib) };
- },
- .m_rip, .lock_m_rip => {
- const rip = emit.mir.extraData(Mir.MemoryRip, data.payload).data;
- op1 = .{ .mem = Mir.MemoryRip.decode(rip) };
- },
- else => unreachable,
- }
-
- const mnemonic: Instruction.Mnemonic = switch (op1.mem.bitSize()) {
- 64 => .cmpxchg8b,
- 128 => .cmpxchg16b,
- else => unreachable,
- };
-
- return emit.encode(mnemonic, .{
- .prefix = switch (ops) {
- .m_sib, .m_rip => .none,
- .lock_m_sib, .lock_m_rip => .lock,
- else => unreachable,
- },
- .op1 = op1,
- });
-}
-
-fn mirMovMoffs(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
- const ops = emit.mir.instructions.items(.ops)[inst];
- const payload = emit.mir.instructions.items(.data)[inst].payload;
- const moffs = emit.mir.extraData(Mir.MemoryMoffs, payload).data;
- const seg = @intToEnum(Register, moffs.seg);
- const offset = moffs.decodeOffset();
- switch (ops) {
- .rax_moffs => {
- try emit.encode(.mov, .{
- .op1 = .{ .reg = .rax },
- .op2 = .{ .mem = Memory.moffs(seg, offset) },
- });
- },
- .moffs_rax, .lock_moffs_rax => {
- try emit.encode(.mov, .{
- .prefix = switch (ops) {
- .moffs_rax => .none,
- .lock_moffs_rax => .lock,
- else => unreachable,
- },
- .op1 = .{ .mem = Memory.moffs(seg, offset) },
- .op2 = .{ .reg = .rax },
- });
- },
- else => unreachable,
- }
-}
-
-fn mirMovsx(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
- const ops = emit.mir.instructions.items(.ops)[inst];
- const data = emit.mir.instructions.items(.data)[inst];
-
- var op1: Instruction.Operand = .none;
- var op2: Instruction.Operand = .none;
- switch (ops) {
- .rr => {
- op1 = .{ .reg = data.rr.r1 };
- op2 = .{ .reg = data.rr.r2 };
- },
- .rm_sib => {
- const msib = emit.mir.extraData(Mir.MemorySib, data.rx.payload).data;
- op1 = .{ .reg = data.rx.r };
- op2 = .{ .mem = Mir.MemorySib.decode(msib) };
- },
- .rm_rip => {
- const mrip = emit.mir.extraData(Mir.MemoryRip, data.rx.payload).data;
- op1 = .{ .reg = data.rx.r };
- op2 = .{ .mem = Mir.MemoryRip.decode(mrip) };
- },
- else => unreachable, // TODO
- }
-
- const mnemonic: Instruction.Mnemonic = switch (op1.bitSize()) {
- 32, 64 => if (op2.bitSize() == 32) .movsxd else .movsx,
- else => .movsx,
- };
-
- return emit.encode(mnemonic, .{
- .op1 = op1,
- .op2 = op2,
- });
-}
-
-fn mnemonicFromConditionCode(comptime basename: []const u8, cc: bits.Condition) Instruction.Mnemonic {
- return switch (cc) {
- inline else => |comptime_cc| @field(Instruction.Mnemonic, basename ++ @tagName(comptime_cc)),
- };
-}
-
-fn mirCmovcc(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
- const ops = emit.mir.instructions.items(.ops)[inst];
- switch (ops) {
- .rr_cc => {
- const data = emit.mir.instructions.items(.data)[inst].rr_cc;
- const mnemonic = mnemonicFromConditionCode("cmov", data.cc);
- return emit.encode(mnemonic, .{
- .op1 = .{ .reg = data.r1 },
- .op2 = .{ .reg = data.r2 },
- });
- },
- .rm_sib_cc => {
- const data = emit.mir.instructions.items(.data)[inst].rx_cc;
- const extra = emit.mir.extraData(Mir.MemorySib, data.payload).data;
- const mnemonic = mnemonicFromConditionCode("cmov", data.cc);
- return emit.encode(mnemonic, .{
- .op1 = .{ .reg = data.r },
- .op2 = .{ .mem = Mir.MemorySib.decode(extra) },
- });
- },
- .rm_rip_cc => {
- const data = emit.mir.instructions.items(.data)[inst].rx_cc;
- const extra = emit.mir.extraData(Mir.MemoryRip, data.payload).data;
- const mnemonic = mnemonicFromConditionCode("cmov", data.cc);
- return emit.encode(mnemonic, .{
- .op1 = .{ .reg = data.r },
- .op2 = .{ .mem = Mir.MemoryRip.decode(extra) },
- });
- },
- else => unreachable,
- }
-}
-
-fn mirSetcc(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
- const ops = emit.mir.instructions.items(.ops)[inst];
- switch (ops) {
- .r_cc => {
- const data = emit.mir.instructions.items(.data)[inst].r_cc;
- const mnemonic = mnemonicFromConditionCode("set", data.cc);
- return emit.encode(mnemonic, .{
- .op1 = .{ .reg = data.r },
- });
- },
- .m_sib_cc => {
- const data = emit.mir.instructions.items(.data)[inst].x_cc;
- const extra = emit.mir.extraData(Mir.MemorySib, data.payload).data;
- const mnemonic = mnemonicFromConditionCode("set", data.cc);
- return emit.encode(mnemonic, .{
- .op1 = .{ .mem = Mir.MemorySib.decode(extra) },
- });
- },
- .m_rip_cc => {
- const data = emit.mir.instructions.items(.data)[inst].x_cc;
- const extra = emit.mir.extraData(Mir.MemoryRip, data.payload).data;
- const mnemonic = mnemonicFromConditionCode("set", data.cc);
- return emit.encode(mnemonic, .{
- .op1 = .{ .mem = Mir.MemoryRip.decode(extra) },
- });
- },
- else => unreachable, // TODO
- }
-}
-
-fn mirJcc(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
- const ops = emit.mir.instructions.items(.ops)[inst];
- switch (ops) {
- .inst_cc => {
- const data = emit.mir.instructions.items(.data)[inst].inst_cc;
- const mnemonic = mnemonicFromConditionCode("j", data.cc);
- const source = emit.code.items.len;
- try emit.encode(mnemonic, .{
- .op1 = .{ .imm = Immediate.s(0) },
- });
- try emit.relocs.append(emit.bin_file.allocator, .{
- .source = source,
- .target = data.inst,
- .offset = emit.code.items.len - 4,
- .length = 6,
- });
- },
- else => unreachable, // TODO
- }
-}
-
-fn mirJmpReloc(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
- const target = emit.mir.instructions.items(.data)[inst].inst;
- const source = emit.code.items.len;
- try emit.encode(.jmp, .{
- .op1 = .{ .imm = Immediate.s(0) },
- });
- try emit.relocs.append(emit.bin_file.allocator, .{
- .source = source,
- .target = target,
- .offset = emit.code.items.len - 4,
- .length = 5,
- });
-}
-
-fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
- const relocation = emit.mir.instructions.items(.data)[inst].relocation;
-
- const offset = blk: {
- try emit.encode(.call, .{
- .op1 = .{ .imm = Immediate.s(0) },
- });
- break :blk @intCast(u32, emit.code.items.len) - 4;
- };
-
- if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
- // Add relocation to the decl.
- const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
- const target = macho_file.getGlobalByIndex(relocation.sym_index);
- try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
- .type = @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),
- .target = target,
- .offset = offset,
- .addend = 0,
- .pcrel = true,
- .length = 2,
- });
- } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
- // Add relocation to the decl.
- const atom_index = coff_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
- const target = coff_file.getGlobalByIndex(relocation.sym_index);
- try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
- .type = .direct,
- .target = target,
- .offset = offset,
- .addend = 0,
- .pcrel = true,
- .length = 2,
- });
- } else {
- return emit.fail("TODO implement call_extern for linking backends different than MachO and COFF", .{});
- }
-}
-
-fn mirPushPopRegisterList(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void {
- const payload = emit.mir.instructions.items(.data)[inst].payload;
- const save_reg_list = emit.mir.extraData(Mir.SaveRegisterList, payload).data;
- const base = @intToEnum(Register, save_reg_list.base_reg);
- var disp: i32 = -@intCast(i32, save_reg_list.stack_end);
- const reg_list = Mir.RegisterList.fromInt(save_reg_list.register_list);
- const callee_preserved_regs = abi.getCalleePreservedRegs(emit.target.*);
- for (callee_preserved_regs) |reg| {
- if (reg_list.isSet(callee_preserved_regs, reg)) {
- const op1: Instruction.Operand = .{ .mem = Memory.sib(.qword, .{
- .base = base,
- .disp = disp,
- }) };
- const op2: Instruction.Operand = .{ .reg = reg };
- switch (tag) {
- .push => try emit.encode(.mov, .{
- .op1 = op1,
- .op2 = op2,
- }),
- .pop => try emit.encode(.mov, .{
- .op1 = op2,
- .op2 = op1,
- }),
- else => unreachable,
- }
- disp += 8;
- }
- }
-}
-
-fn mirLeaLinker(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
- const ops = emit.mir.instructions.items(.ops)[inst];
- const payload = emit.mir.instructions.items(.data)[inst].payload;
- const metadata = emit.mir.extraData(Mir.LeaRegisterReloc, payload).data;
- const reg = @intToEnum(Register, metadata.reg);
-
- try emit.encode(.lea, .{
- .op1 = .{ .reg = reg },
- .op2 = .{ .mem = Memory.rip(Memory.PtrSize.fromBitSize(reg.bitSize()), 0) },
- });
-
- const end_offset = emit.code.items.len;
-
- if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
- const reloc_type = switch (ops) {
- .got_reloc => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_GOT),
- .direct_reloc => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_SIGNED),
- else => unreachable,
- };
- const atom_index = macho_file.getAtomIndexForSymbol(.{
- .sym_index = metadata.atom_index,
- .file = null,
- }).?;
- try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
- .type = reloc_type,
- .target = .{ .sym_index = metadata.sym_index, .file = null },
- .offset = @intCast(u32, end_offset - 4),
- .addend = 0,
- .pcrel = true,
- .length = 2,
- });
- } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| {
- const atom_index = coff_file.getAtomIndexForSymbol(.{
- .sym_index = metadata.atom_index,
- .file = null,
- }).?;
- try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{
- .type = switch (ops) {
- .got_reloc => .got,
- .direct_reloc => .direct,
- .import_reloc => .import,
- else => unreachable,
- },
- .target = switch (ops) {
- .got_reloc, .direct_reloc => .{ .sym_index = metadata.sym_index, .file = null },
- .import_reloc => coff_file.getGlobalByIndex(metadata.sym_index),
- else => unreachable,
- },
- .offset = @intCast(u32, end_offset - 4),
- .addend = 0,
- .pcrel = true,
- .length = 2,
- });
- } else {
- return emit.fail("TODO implement lea reg, [rip + reloc] for linking backends different than MachO", .{});
- }
-}
-
-fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
- const payload = emit.mir.instructions.items(.data)[inst].payload;
- const dbg_line_column = emit.mir.extraData(Mir.DbgLineColumn, payload).data;
- log.debug("mirDbgLine", .{});
- try emit.dbgAdvancePCAndLine(dbg_line_column.line, dbg_line_column.column);
-}
-
-fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) InnerError!void {
+fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void {
const delta_line = @intCast(i32, line) - @intCast(i32, emit.prev_di_line);
const delta_pc: usize = emit.code.items.len - emit.prev_di_pc;
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 {
.plan9 => |dbg_out| {
if (delta_pc <= 0) return; // only do this when the pc changes
// we have already checked the target in the linker to make sure it is compatable
- const quant = @import("../../link/Plan9/aout.zig").getPCQuant(emit.target.cpu.arch) catch unreachable;
+ const quant = @import("../../link/Plan9/aout.zig").getPCQuant(emit.lower.target.cpu.arch) catch unreachable;
// increasing the line number
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 {
}
}
-fn mirDbgPrologueEnd(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
- _ = inst;
- switch (emit.debug_output) {
- .dwarf => |dw| {
- try dw.setPrologueEnd();
- log.debug("mirDbgPrologueEnd (line={d}, col={d})", .{
- emit.prev_di_line,
- emit.prev_di_column,
- });
- try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
- },
- .plan9 => {},
- .none => {},
- }
-}
+const link = @import("../../link.zig");
+const log = std.log.scoped(.emit);
+const mem = std.mem;
+const std = @import("std");
-fn mirDbgEpilogueBegin(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
- _ = inst;
- switch (emit.debug_output) {
- .dwarf => |dw| {
- try dw.setEpilogueBegin();
- log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{
- emit.prev_di_line,
- emit.prev_di_column,
- });
- try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
- },
- .plan9 => {},
- .none => {},
- }
-}
+const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput;
+const Emit = @This();
+const Lower = @import("Lower.zig");
+const Mir = @import("Mir.zig");
diff --git a/src/arch/x86_64/Encoding.zig b/src/arch/x86_64/Encoding.zig
index de669a9f8d..1361570405 100644
--- a/src/arch/x86_64/Encoding.zig
+++ b/src/arch/x86_64/Encoding.zig
@@ -7,30 +7,32 @@ const math = std.math;
const bits = @import("bits.zig");
const encoder = @import("encoder.zig");
const Instruction = encoder.Instruction;
+const Operand = Instruction.Operand;
+const Prefix = Instruction.Prefix;
const Register = bits.Register;
const Rex = encoder.Rex;
const LegacyPrefixes = encoder.LegacyPrefixes;
-const table = @import("encodings.zig").table;
-
mnemonic: Mnemonic,
-op_en: OpEn,
-op1: Op,
-op2: Op,
-op3: Op,
-op4: Op,
-opc_len: u3,
-opc: [7]u8,
-modrm_ext: u3,
-mode: Mode,
-
-pub fn findByMnemonic(mnemonic: Mnemonic, args: Instruction.Init) !?Encoding {
- const input_op1 = Op.fromOperand(args.op1);
- const input_op2 = Op.fromOperand(args.op2);
- const input_op3 = Op.fromOperand(args.op3);
- const input_op4 = Op.fromOperand(args.op4);
-
- const ops = &[_]Instruction.Operand{ args.op1, args.op2, args.op3, args.op4 };
+data: Data,
+
+const Data = struct {
+ op_en: OpEn,
+ ops: [4]Op,
+ opc_len: u3,
+ opc: [7]u8,
+ modrm_ext: u3,
+ mode: Mode,
+};
+
+pub fn findByMnemonic(
+ prefix: Instruction.Prefix,
+ mnemonic: Mnemonic,
+ ops: []const Instruction.Operand,
+) !?Encoding {
+ var input_ops = [1]Op{.none} ** 4;
+ for (input_ops[0..ops.len], ops) |*input_op, op| input_op.* = Op.fromOperand(op);
+
const rex_required = for (ops) |op| switch (op) {
.reg => |r| switch (r) {
.spl, .bpl, .sil, .dil => break true,
@@ -60,88 +62,29 @@ pub fn findByMnemonic(mnemonic: Mnemonic, args: Instruction.Init) !?Encoding {
if ((rex_required or rex_extended) and rex_invalid) return error.CannotEncode;
- // TODO work out what is the maximum number of variants we can actually find in one swoop.
- var candidates: [10]Encoding = undefined;
- var count: usize = 0;
- for (table) |entry| {
- var enc = Encoding{
- .mnemonic = entry[0],
- .op_en = entry[1],
- .op1 = entry[2],
- .op2 = entry[3],
- .op3 = entry[4],
- .op4 = entry[5],
- .opc_len = @intCast(u3, entry[6].len),
- .opc = undefined,
- .modrm_ext = entry[7],
- .mode = entry[8],
- };
- std.mem.copy(u8, &enc.opc, entry[6]);
- if (enc.mnemonic == mnemonic and
- input_op1.isSubset(enc.op1, enc.mode) and
- input_op2.isSubset(enc.op2, enc.mode) and
- input_op3.isSubset(enc.op3, enc.mode) and
- input_op4.isSubset(enc.op4, enc.mode))
- {
- if (rex_required) {
- switch (enc.mode) {
- .rex, .long => {
- candidates[count] = enc;
- count += 1;
- },
- else => {},
- }
- } else {
- if (enc.mode != .rex) {
- candidates[count] = enc;
- count += 1;
- }
- }
+ var shortest_enc: ?Encoding = null;
+ var shortest_len: ?usize = null;
+ next: for (mnemonic_to_encodings_map[@enumToInt(mnemonic)]) |data| {
+ switch (data.mode) {
+ .rex => if (!rex_required) continue,
+ .long => {},
+ else => if (rex_required) continue,
}
+ for (input_ops, data.ops) |input_op, data_op|
+ if (!input_op.isSubset(data_op, data.mode)) continue :next;
+
+ const enc = Encoding{ .mnemonic = mnemonic, .data = data };
+ if (shortest_enc) |previous_shortest_enc| {
+ const len = estimateInstructionLength(prefix, enc, ops);
+ const previous_shortest_len = shortest_len orelse
+ estimateInstructionLength(prefix, previous_shortest_enc, ops);
+ if (len < previous_shortest_len) {
+ shortest_enc = enc;
+ shortest_len = len;
+ } else shortest_len = previous_shortest_len;
+ } else shortest_enc = enc;
}
-
- if (count == 0) return null;
- if (count == 1) return candidates[0];
-
- const EncodingLength = struct {
- fn estimate(encoding: Encoding, params: Instruction.Init) usize {
- var inst = Instruction{
- .op1 = params.op1,
- .op2 = params.op2,
- .op3 = params.op3,
- .op4 = params.op4,
- .prefix = params.prefix,
- .encoding = encoding,
- };
- var cwriter = std.io.countingWriter(std.io.null_writer);
- inst.encode(cwriter.writer()) catch unreachable; // Not allowed to fail here unless OOM.
- return @intCast(usize, cwriter.bytes_written);
- }
- };
-
- var shortest_encoding: ?struct {
- index: usize,
- len: usize,
- } = null;
- var i: usize = 0;
- while (i < count) : (i += 1) {
- const candidate = candidates[i];
- switch (candidate.mode) {
- .long, .rex => if (rex_invalid) return error.CannotEncode,
- else => {},
- }
-
- const len = EncodingLength.estimate(candidate, args);
- const current = shortest_encoding orelse {
- shortest_encoding = .{ .index = i, .len = len };
- continue;
- };
- if (len < current.len) {
- shortest_encoding = .{ .index = i, .len = len };
- }
- }
-
- return candidates[shortest_encoding.?.index];
+ return shortest_enc;
}
/// Returns first matching encoding by opcode.
@@ -149,57 +92,45 @@ pub fn findByOpcode(opc: []const u8, prefixes: struct {
legacy: LegacyPrefixes,
rex: Rex,
}, modrm_ext: ?u3) ?Encoding {
- for (table) |entry| {
- const enc = Encoding{
- .mnemonic = entry[0],
- .op_en = entry[1],
- .op1 = entry[2],
- .op2 = entry[3],
- .op3 = entry[4],
- .op4 = entry[5],
- .opc_len = entry[6],
- .opc = .{ entry[7], entry[8], entry[9] },
- .modrm_ext = entry[10],
- .mode = entry[11],
- };
- const match = match: {
- if (modrm_ext) |ext| {
- break :match ext == enc.modrm_ext and std.mem.eql(u8, enc.opcode(), opc);
+ for (mnemonic_to_encodings_map, 0..) |encs, mnemonic_int| for (encs) |data| {
+ const enc = Encoding{ .mnemonic = @intToEnum(Mnemonic, mnemonic_int), .data = data };
+ if (modrm_ext) |ext| if (ext != data.modrm_ext) continue;
+ if (!std.mem.eql(u8, opc, enc.opcode())) continue;
+ if (prefixes.rex.w) {
+ switch (data.mode) {
+ .short, .fpu, .sse, .sse2, .sse4_1, .none => continue,
+ .long, .rex => {},
}
- break :match std.mem.eql(u8, enc.opcode(), opc);
- };
- if (match) {
- if (prefixes.rex.w) {
- switch (enc.mode) {
- .fpu, .sse, .sse2, .sse4_1, .none => {},
- .long, .rex => return enc,
- }
- } else if (prefixes.rex.present and !prefixes.rex.isSet()) {
- if (enc.mode == .rex) return enc;
- } else if (prefixes.legacy.prefix_66) {
- switch (enc.operandBitSize()) {
- 16 => return enc,
+ } else if (prefixes.rex.present and !prefixes.rex.isSet()) {
+ switch (data.mode) {
+ .rex => {},
+ else => continue,
+ }
+ } else if (prefixes.legacy.prefix_66) {
+ switch (enc.operandBitSize()) {
+ 16 => {},
+ else => continue,
+ }
+ } else {
+ switch (data.mode) {
+ .none => switch (enc.operandBitSize()) {
+ 16 => continue,
else => {},
- }
- } else {
- if (enc.mode == .none) {
- switch (enc.operandBitSize()) {
- 16 => {},
- else => return enc,
- }
- }
+ },
+ else => continue,
}
}
- }
+ return enc;
+ };
return null;
}
pub fn opcode(encoding: *const Encoding) []const u8 {
- return encoding.opc[0..encoding.opc_len];
+ return encoding.data.opc[0..encoding.data.opc_len];
}
pub fn mandatoryPrefix(encoding: *const Encoding) ?u8 {
- const prefix = encoding.opc[0];
+ const prefix = encoding.data.opc[0];
return switch (prefix) {
0x66, 0xf2, 0xf3 => prefix,
else => null,
@@ -207,27 +138,27 @@ pub fn mandatoryPrefix(encoding: *const Encoding) ?u8 {
}
pub fn modRmExt(encoding: Encoding) u3 {
- return switch (encoding.op_en) {
- .m, .mi, .m1, .mc => encoding.modrm_ext,
+ return switch (encoding.data.op_en) {
+ .m, .mi, .m1, .mc => encoding.data.modrm_ext,
else => unreachable,
};
}
pub fn operandBitSize(encoding: Encoding) u64 {
- switch (encoding.mode) {
+ switch (encoding.data.mode) {
.short => return 16,
.long => return 64,
else => {},
}
- const bit_size: u64 = switch (encoding.op_en) {
- .np => switch (encoding.op1) {
+ const bit_size: u64 = switch (encoding.data.op_en) {
+ .np => switch (encoding.data.ops[0]) {
.o16 => 16,
.o32 => 32,
.o64 => 64,
else => 32,
},
- .td => encoding.op2.bitSize(),
- else => encoding.op1.bitSize(),
+ .td => encoding.data.ops[1].bitSize(),
+ else => encoding.data.ops[0].bitSize(),
};
return bit_size;
}
@@ -240,7 +171,7 @@ pub fn format(
) !void {
_ = options;
_ = fmt;
- switch (encoding.mode) {
+ switch (encoding.data.mode) {
.long => try writer.writeAll("REX.W + "),
else => {},
}
@@ -249,10 +180,10 @@ pub fn format(
try writer.print("{x:0>2} ", .{byte});
}
- switch (encoding.op_en) {
+ switch (encoding.data.op_en) {
.np, .fd, .td, .i, .zi, .d => {},
.o, .oi => {
- const tag = switch (encoding.op1) {
+ const tag = switch (encoding.data.ops[0]) {
.r8 => "rb",
.r16 => "rw",
.r32 => "rd",
@@ -265,12 +196,12 @@ pub fn format(
.mr, .rm, .rmi, .mri, .mrc => try writer.writeAll("/r "),
}
- switch (encoding.op_en) {
+ switch (encoding.data.op_en) {
.i, .d, .zi, .oi, .mi, .rmi, .mri => {
- const op = switch (encoding.op_en) {
- .i, .d => encoding.op1,
- .zi, .oi, .mi => encoding.op2,
- .rmi, .mri => encoding.op3,
+ const op = switch (encoding.data.op_en) {
+ .i, .d => encoding.data.ops[0],
+ .zi, .oi, .mi => encoding.data.ops[1],
+ .rmi, .mri => encoding.data.ops[2],
else => unreachable,
};
const tag = switch (op) {
@@ -290,13 +221,12 @@ pub fn format(
try writer.print("{s} ", .{@tagName(encoding.mnemonic)});
- const ops = &[_]Op{ encoding.op1, encoding.op2, encoding.op3, encoding.op4 };
- for (ops) |op| switch (op) {
+ for (encoding.data.ops) |op| switch (op) {
.none, .o16, .o32, .o64 => break,
else => try writer.print("{s} ", .{@tagName(op)}),
};
- const op_en = switch (encoding.op_en) {
+ const op_en = switch (encoding.data.op_en) {
.zi => .i,
else => |op_en| op_en,
};
@@ -604,3 +534,53 @@ pub const Mode = enum {
sse2,
sse4_1,
};
+
+fn estimateInstructionLength(prefix: Prefix, encoding: Encoding, ops: []const Operand) usize {
+ var inst = Instruction{
+ .prefix = prefix,
+ .encoding = encoding,
+ .ops = [1]Operand{.none} ** 4,
+ };
+ std.mem.copy(Operand, &inst.ops, ops);
+
+ var cwriter = std.io.countingWriter(std.io.null_writer);
+ inst.encode(cwriter.writer()) catch unreachable; // Not allowed to fail here unless OOM.
+ return @intCast(usize, cwriter.bytes_written);
+}
+
+const mnemonic_to_encodings_map = init: {
+ @setEvalBranchQuota(100_000);
+ const encodings = @import("encodings.zig");
+ var entries = encodings.table;
+ std.sort.sort(encodings.Entry, &entries, {}, struct {
+ fn lessThan(_: void, lhs: encodings.Entry, rhs: encodings.Entry) bool {
+ return @enumToInt(lhs[0]) < @enumToInt(rhs[0]);
+ }
+ }.lessThan);
+ var data_storage: [entries.len]Data = undefined;
+ var mnemonic_map: [@typeInfo(Mnemonic).Enum.fields.len][]const Data = undefined;
+ var mnemonic_int = 0;
+ var mnemonic_start = 0;
+ for (&data_storage, entries, 0..) |*data, entry, data_index| {
+ data.* = .{
+ .op_en = entry[1],
+ .ops = undefined,
+ .opc_len = entry[3].len,
+ .opc = undefined,
+ .modrm_ext = entry[4],
+ .mode = entry[5],
+ };
+ std.mem.copy(Op, &data.ops, entry[2]);
+ std.mem.copy(u8, &data.opc, entry[3]);
+
+ while (mnemonic_int < @enumToInt(entry[0])) : (mnemonic_int += 1) {
+ mnemonic_map[mnemonic_int] = data_storage[mnemonic_start..data_index];
+ mnemonic_start = data_index;
+ }
+ }
+ while (mnemonic_int < mnemonic_map.len) : (mnemonic_int += 1) {
+ mnemonic_map[mnemonic_int] = data_storage[mnemonic_start..];
+ mnemonic_start = data_storage.len;
+ }
+ break :init mnemonic_map;
+};
diff --git a/src/arch/x86_64/Lower.zig b/src/arch/x86_64/Lower.zig
new file mode 100644
index 0000000000..f4d9db57e8
--- /dev/null
+++ b/src/arch/x86_64/Lower.zig
@@ -0,0 +1,465 @@
+//! This file contains the functionality for lowering x86_64 MIR to Instructions
+
+allocator: Allocator,
+mir: Mir,
+target: *const std.Target,
+err_msg: ?*ErrorMsg = null,
+src_loc: Module.SrcLoc,
+result: [
+ std.mem.max(usize, &.{
+ abi.Win64.callee_preserved_regs.len,
+ abi.SysV.callee_preserved_regs.len,
+ })
+]Instruction = undefined,
+result_len: usize = undefined,
+
+pub const Error = error{
+ OutOfMemory,
+ LowerFail,
+ InvalidInstruction,
+ CannotEncode,
+};
+
+/// The returned slice is overwritten by the next call to lowerMir.
+pub fn lowerMir(lower: *Lower, inst: Mir.Inst) Error![]const Instruction {
+ lower.result = undefined;
+ errdefer lower.result = undefined;
+ lower.result_len = 0;
+ defer lower.result_len = undefined;
+
+ switch (inst.tag) {
+ .adc,
+ .add,
+ .@"and",
+ .bsf,
+ .bsr,
+ .bswap,
+ .bt,
+ .btc,
+ .btr,
+ .bts,
+ .call,
+ .cbw,
+ .cwde,
+ .cdqe,
+ .cwd,
+ .cdq,
+ .cqo,
+ .cmp,
+ .cmpxchg,
+ .div,
+ .fisttp,
+ .fld,
+ .idiv,
+ .imul,
+ .int3,
+ .jmp,
+ .lea,
+ .lfence,
+ .lzcnt,
+ .mfence,
+ .mov,
+ .movbe,
+ .movzx,
+ .mul,
+ .neg,
+ .nop,
+ .not,
+ .@"or",
+ .pop,
+ .popcnt,
+ .push,
+ .rcl,
+ .rcr,
+ .ret,
+ .rol,
+ .ror,
+ .sal,
+ .sar,
+ .sbb,
+ .sfence,
+ .shl,
+ .shld,
+ .shr,
+ .shrd,
+ .sub,
+ .syscall,
+ .@"test",
+ .tzcnt,
+ .ud2,
+ .xadd,
+ .xchg,
+ .xor,
+
+ .addss,
+ .cmpss,
+ .divss,
+ .maxss,
+ .minss,
+ .movss,
+ .mulss,
+ .roundss,
+ .subss,
+ .ucomiss,
+ .addsd,
+ .cmpsd,
+ .divsd,
+ .maxsd,
+ .minsd,
+ .movsd,
+ .mulsd,
+ .roundsd,
+ .subsd,
+ .ucomisd,
+ => try lower.mirGeneric(inst),
+
+ .cmps,
+ .lods,
+ .movs,
+ .scas,
+ .stos,
+ => try lower.mirString(inst),
+
+ .cmpxchgb => try lower.mirCmpxchgBytes(inst),
+
+ .jmp_reloc => try lower.emit(.none, .jmp, &.{.{ .imm = Immediate.s(0) }}),
+
+ .call_extern => try lower.emit(.none, .call, &.{.{ .imm = Immediate.s(0) }}),
+
+ .lea_linker => try lower.mirLeaLinker(inst),
+
+ .mov_moffs => try lower.mirMovMoffs(inst),
+
+ .movsx => try lower.mirMovsx(inst),
+ .cmovcc => try lower.mirCmovcc(inst),
+ .setcc => try lower.mirSetcc(inst),
+ .jcc => try lower.emit(.none, mnem_cc(.j, inst.data.inst_cc.cc), &.{.{ .imm = Immediate.s(0) }}),
+
+ .push_regs, .pop_regs => try lower.mirPushPopRegisterList(inst),
+
+ .dbg_line,
+ .dbg_prologue_end,
+ .dbg_epilogue_begin,
+ .dead,
+ => {},
+ }
+
+ return lower.result[0..lower.result_len];
+}
+
+pub fn fail(lower: *Lower, comptime format: []const u8, args: anytype) Error {
+ @setCold(true);
+ assert(lower.err_msg == null);
+ lower.err_msg = try ErrorMsg.create(lower.allocator, lower.src_loc, format, args);
+ return error.LowerFail;
+}
+
+fn mnem_cc(comptime base: @Type(.EnumLiteral), cc: bits.Condition) Mnemonic {
+ return switch (cc) {
+ inline else => |c| @field(Mnemonic, @tagName(base) ++ @tagName(c)),
+ };
+}
+
+fn imm(lower: Lower, ops: Mir.Inst.Ops, i: u32) Immediate {
+ return switch (ops) {
+ .rri_s,
+ .ri_s,
+ .i_s,
+ .mi_sib_s,
+ .mi_rip_s,
+ .lock_mi_sib_s,
+ .lock_mi_rip_s,
+ => Immediate.s(@bitCast(i32, i)),
+
+ .rri_u,
+ .ri_u,
+ .i_u,
+ .mi_sib_u,
+ .mi_rip_u,
+ .lock_mi_sib_u,
+ .lock_mi_rip_u,
+ .mri_sib,
+ .mri_rip,
+ => Immediate.u(i),
+
+ .ri64 => Immediate.u(lower.mir.extraData(Mir.Imm64, i).data.decode()),
+
+ else => unreachable,
+ };
+}
+
+fn mem(lower: Lower, ops: Mir.Inst.Ops, payload: u32) Memory {
+ return switch (ops) {
+ .rm_sib,
+ .rm_sib_cc,
+ .m_sib,
+ .m_sib_cc,
+ .mi_sib_u,
+ .mi_sib_s,
+ .mr_sib,
+ .mrr_sib,
+ .mri_sib,
+ .lock_m_sib,
+ .lock_mi_sib_u,
+ .lock_mi_sib_s,
+ .lock_mr_sib,
+ => lower.mir.extraData(Mir.MemorySib, payload).data.decode(),
+
+ .rm_rip,
+ .rm_rip_cc,
+ .m_rip,
+ .m_rip_cc,
+ .mi_rip_u,
+ .mi_rip_s,
+ .mr_rip,
+ .mrr_rip,
+ .mri_rip,
+ .lock_m_rip,
+ .lock_mi_rip_u,
+ .lock_mi_rip_s,
+ .lock_mr_rip,
+ => lower.mir.extraData(Mir.MemoryRip, payload).data.decode(),
+
+ .rax_moffs,
+ .moffs_rax,
+ .lock_moffs_rax,
+ => lower.mir.extraData(Mir.MemoryMoffs, payload).data.decode(),
+
+ else => unreachable,
+ };
+}
+
+fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void {
+ lower.result[lower.result_len] = try Instruction.new(prefix, mnemonic, ops);
+ lower.result_len += 1;
+}
+
+fn mirGeneric(lower: *Lower, inst: Mir.Inst) Error!void {
+ try lower.emit(switch (inst.ops) {
+ else => .none,
+ .lock_m_sib,
+ .lock_m_rip,
+ .lock_mi_sib_u,
+ .lock_mi_rip_u,
+ .lock_mi_sib_s,
+ .lock_mi_rip_s,
+ .lock_mr_sib,
+ .lock_mr_rip,
+ .lock_moffs_rax,
+ => .lock,
+ }, switch (inst.tag) {
+ inline else => |tag| if (@hasField(Mnemonic, @tagName(tag)))
+ @field(Mnemonic, @tagName(tag))
+ else
+ unreachable,
+ }, switch (inst.ops) {
+ .none => &.{},
+ .i_s, .i_u => &.{
+ .{ .imm = lower.imm(inst.ops, inst.data.i) },
+ },
+ .r => &.{
+ .{ .reg = inst.data.r },
+ },
+ .rr => &.{
+ .{ .reg = inst.data.rr.r1 },
+ .{ .reg = inst.data.rr.r2 },
+ },
+ .rrr => &.{
+ .{ .reg = inst.data.rrr.r1 },
+ .{ .reg = inst.data.rrr.r2 },
+ .{ .reg = inst.data.rrr.r3 },
+ },
+ .ri_s, .ri_u => &.{
+ .{ .reg = inst.data.ri.r },
+ .{ .imm = lower.imm(inst.ops, inst.data.ri.i) },
+ },
+ .ri64 => &.{
+ .{ .reg = inst.data.rx.r },
+ .{ .imm = lower.imm(inst.ops, inst.data.rx.payload) },
+ },
+ .rri_s, .rri_u => &.{
+ .{ .reg = inst.data.rri.r1 },
+ .{ .reg = inst.data.rri.r2 },
+ .{ .imm = lower.imm(inst.ops, inst.data.rri.i) },
+ },
+ .m_sib, .lock_m_sib, .m_rip, .lock_m_rip => &.{
+ .{ .mem = lower.mem(inst.ops, inst.data.payload) },
+ },
+ .mi_sib_s,
+ .lock_mi_sib_s,
+ .mi_sib_u,
+ .lock_mi_sib_u,
+ .mi_rip_u,
+ .lock_mi_rip_u,
+ .mi_rip_s,
+ .lock_mi_rip_s,
+ => &.{
+ .{ .mem = lower.mem(inst.ops, inst.data.ix.payload) },
+ .{ .imm = lower.imm(inst.ops, inst.data.ix.i) },
+ },
+ .rm_sib, .rm_rip => &.{
+ .{ .reg = inst.data.rx.r },
+ .{ .mem = lower.mem(inst.ops, inst.data.rx.payload) },
+ },
+ .mr_sib, .lock_mr_sib, .mr_rip, .lock_mr_rip => &.{
+ .{ .mem = lower.mem(inst.ops, inst.data.rx.payload) },
+ .{ .reg = inst.data.rx.r },
+ },
+ .mrr_sib, .mrr_rip => &.{
+ .{ .mem = lower.mem(inst.ops, inst.data.rrx.payload) },
+ .{ .reg = inst.data.rrx.r1 },
+ .{ .reg = inst.data.rrx.r2 },
+ },
+ .mri_sib, .mri_rip => &.{
+ .{ .mem = lower.mem(inst.ops, inst.data.rix.payload) },
+ .{ .reg = inst.data.rix.r },
+ .{ .imm = lower.imm(inst.ops, inst.data.rix.i) },
+ },
+ else => return lower.fail("TODO lower {s} {s}", .{ @tagName(inst.tag), @tagName(inst.ops) }),
+ });
+}
+
+fn mirString(lower: *Lower, inst: Mir.Inst) Error!void {
+ switch (inst.ops) {
+ .string => try lower.emit(switch (inst.data.string.repeat) {
+ inline else => |repeat| @field(Prefix, @tagName(repeat)),
+ }, switch (inst.tag) {
+ inline .cmps, .lods, .movs, .scas, .stos => |tag| switch (inst.data.string.width) {
+ inline else => |width| @field(Mnemonic, @tagName(tag) ++ @tagName(width)),
+ },
+ else => unreachable,
+ }, &.{}),
+ else => return lower.fail("TODO lower {s} {s}", .{ @tagName(inst.tag), @tagName(inst.ops) }),
+ }
+}
+
+fn mirCmpxchgBytes(lower: *Lower, inst: Mir.Inst) Error!void {
+ const ops: [1]Operand = switch (inst.ops) {
+ .m_sib, .lock_m_sib, .m_rip, .lock_m_rip => .{
+ .{ .mem = lower.mem(inst.ops, inst.data.payload) },
+ },
+ else => return lower.fail("TODO lower {s} {s}", .{ @tagName(inst.tag), @tagName(inst.ops) }),
+ };
+ try lower.emit(switch (inst.ops) {
+ .m_sib, .m_rip => .none,
+ .lock_m_sib, .lock_m_rip => .lock,
+ else => unreachable,
+ }, switch (@divExact(ops[0].bitSize(), 8)) {
+ 8 => .cmpxchg8b,
+ 16 => .cmpxchg16b,
+ else => return lower.fail("invalid operand for {s}", .{@tagName(inst.tag)}),
+ }, &ops);
+}
+
+fn mirMovMoffs(lower: *Lower, inst: Mir.Inst) Error!void {
+ try lower.emit(switch (inst.ops) {
+ .rax_moffs, .moffs_rax => .none,
+ .lock_moffs_rax => .lock,
+ else => return lower.fail("TODO lower {s} {s}", .{ @tagName(inst.tag), @tagName(inst.ops) }),
+ }, .mov, switch (inst.ops) {
+ .rax_moffs => &.{
+ .{ .reg = .rax },
+ .{ .mem = lower.mem(inst.ops, inst.data.payload) },
+ },
+ .moffs_rax, .lock_moffs_rax => &.{
+ .{ .mem = lower.mem(inst.ops, inst.data.payload) },
+ .{ .reg = .rax },
+ },
+ else => unreachable,
+ });
+}
+
+fn mirMovsx(lower: *Lower, inst: Mir.Inst) Error!void {
+ const ops: [2]Operand = switch (inst.ops) {
+ .rr => .{
+ .{ .reg = inst.data.rr.r1 },
+ .{ .reg = inst.data.rr.r2 },
+ },
+ .rm_sib, .rm_rip => .{
+ .{ .reg = inst.data.rx.r },
+ .{ .mem = lower.mem(inst.ops, inst.data.rx.payload) },
+ },
+ else => return lower.fail("TODO lower {s} {s}", .{ @tagName(inst.tag), @tagName(inst.ops) }),
+ };
+ try lower.emit(.none, switch (ops[0].bitSize()) {
+ 32, 64 => switch (ops[1].bitSize()) {
+ 32 => .movsxd,
+ else => .movsx,
+ },
+ else => .movsx,
+ }, &ops);
+}
+
+fn mirCmovcc(lower: *Lower, inst: Mir.Inst) Error!void {
+ switch (inst.ops) {
+ .rr_cc => try lower.emit(.none, mnem_cc(.cmov, inst.data.rr_cc.cc), &.{
+ .{ .reg = inst.data.rr_cc.r1 },
+ .{ .reg = inst.data.rr_cc.r2 },
+ }),
+ .rm_sib_cc, .rm_rip_cc => try lower.emit(.none, mnem_cc(.cmov, inst.data.rx_cc.cc), &.{
+ .{ .reg = inst.data.rx_cc.r },
+ .{ .mem = lower.mem(inst.ops, inst.data.rx_cc.payload) },
+ }),
+ else => return lower.fail("TODO lower {s} {s}", .{ @tagName(inst.tag), @tagName(inst.ops) }),
+ }
+}
+
+fn mirSetcc(lower: *Lower, inst: Mir.Inst) Error!void {
+ switch (inst.ops) {
+ .r_cc => try lower.emit(.none, mnem_cc(.set, inst.data.r_cc.cc), &.{
+ .{ .reg = inst.data.r_cc.r },
+ }),
+ .m_sib_cc, .m_rip_cc => try lower.emit(.none, mnem_cc(.set, inst.data.x_cc.cc), &.{
+ .{ .mem = lower.mem(inst.ops, inst.data.x_cc.payload) },
+ }),
+ else => return lower.fail("TODO lower {s} {s}", .{ @tagName(inst.tag), @tagName(inst.ops) }),
+ }
+}
+
+fn mirPushPopRegisterList(lower: *Lower, inst: Mir.Inst) Error!void {
+ const save_reg_list = lower.mir.extraData(Mir.SaveRegisterList, inst.data.payload).data;
+ const base = @intToEnum(Register, save_reg_list.base_reg);
+ var disp: i32 = -@intCast(i32, save_reg_list.stack_end);
+ const reg_list = Mir.RegisterList.fromInt(save_reg_list.register_list);
+ const callee_preserved_regs = abi.getCalleePreservedRegs(lower.target.*);
+ for (callee_preserved_regs) |callee_preserved_reg| {
+ if (!reg_list.isSet(callee_preserved_regs, callee_preserved_reg)) continue;
+ const reg_op = Operand{ .reg = callee_preserved_reg };
+ const mem_op = Operand{ .mem = Memory.sib(.qword, .{ .base = base, .disp = disp }) };
+ try lower.emit(.none, .mov, switch (inst.tag) {
+ .push_regs => &.{ mem_op, reg_op },
+ .pop_regs => &.{ reg_op, mem_op },
+ else => unreachable,
+ });
+ disp += 8;
+ }
+}
+
+fn mirLeaLinker(lower: *Lower, inst: Mir.Inst) Error!void {
+ const metadata = lower.mir.extraData(Mir.LeaRegisterReloc, inst.data.payload).data;
+ const reg = @intToEnum(Register, metadata.reg);
+ try lower.emit(.none, .lea, &.{
+ .{ .reg = reg },
+ .{ .mem = Memory.rip(Memory.PtrSize.fromBitSize(reg.bitSize()), 0) },
+ });
+}
+
+const abi = @import("abi.zig");
+const assert = std.debug.assert;
+const bits = @import("bits.zig");
+const encoder = @import("encoder.zig");
+const std = @import("std");
+
+const Air = @import("../../Air.zig");
+const Allocator = std.mem.Allocator;
+const ErrorMsg = Module.ErrorMsg;
+const Immediate = bits.Immediate;
+const Instruction = encoder.Instruction;
+const Lower = @This();
+const Memory = bits.Memory;
+const Mir = @import("Mir.zig");
+const Mnemonic = Instruction.Mnemonic;
+const Module = @import("../../Module.zig");
+const Operand = Instruction.Operand;
+const Prefix = Instruction.Prefix;
+const Register = bits.Register;
diff --git a/src/arch/x86_64/Mir.zig b/src/arch/x86_64/Mir.zig
index a6a4115814..0ceee6bac1 100644
--- a/src/arch/x86_64/Mir.zig
+++ b/src/arch/x86_64/Mir.zig
@@ -655,16 +655,19 @@ pub const MemoryMoffs = struct {
msb: u32,
lsb: u32,
- pub fn encodeOffset(moffs: *MemoryMoffs, v: u64) void {
- moffs.msb = @truncate(u32, v >> 32);
- moffs.lsb = @truncate(u32, v);
+ pub fn encode(seg: Register, offset: u64) MemoryMoffs {
+ return .{
+ .seg = @enumToInt(seg),
+ .msb = @truncate(u32, offset >> 32),
+ .lsb = @truncate(u32, offset >> 0),
+ };
}
- pub fn decodeOffset(moffs: *const MemoryMoffs) u64 {
- var res: u64 = 0;
- res |= (@intCast(u64, moffs.msb) << 32);
- res |= @intCast(u64, moffs.lsb);
- return res;
+ pub fn decode(moffs: MemoryMoffs) Memory {
+ return .{ .moffs = .{
+ .seg = @intToEnum(Register, moffs.seg),
+ .offset = @as(u64, moffs.msb) << 32 | @as(u64, moffs.lsb) << 0,
+ } };
}
};
diff --git a/src/arch/x86_64/bits.zig b/src/arch/x86_64/bits.zig
index 76ad26a9a0..b2a6b31749 100644
--- a/src/arch/x86_64/bits.zig
+++ b/src/arch/x86_64/bits.zig
@@ -515,7 +515,7 @@ pub const Memory = union(enum) {
return switch (mem) {
.rip => |r| r.ptr_size.bitSize(),
.sib => |s| s.ptr_size.bitSize(),
- .moffs => unreachable,
+ .moffs => 64,
};
}
};
diff --git a/src/arch/x86_64/encoder.zig b/src/arch/x86_64/encoder.zig
index 05f66062ac..e7e231c063 100644
--- a/src/arch/x86_64/encoder.zig
+++ b/src/arch/x86_64/encoder.zig
@@ -11,12 +11,9 @@ const Memory = bits.Memory;
const Register = bits.Register;
pub const Instruction = struct {
- op1: Operand = .none,
- op2: Operand = .none,
- op3: Operand = .none,
- op4: Operand = .none,
prefix: Prefix = .none,
encoding: Encoding,
+ ops: [4]Operand = .{.none} ** 4,
pub const Mnemonic = Encoding.Mnemonic;
@@ -107,102 +104,87 @@ pub const Instruction = struct {
}
};
- pub const Init = struct {
- prefix: Prefix = .none,
- op1: Operand = .none,
- op2: Operand = .none,
- op3: Operand = .none,
- op4: Operand = .none,
- };
-
- pub fn new(mnemonic: Mnemonic, args: Init) !Instruction {
- const encoding = (try Encoding.findByMnemonic(mnemonic, args)) orelse {
+ pub fn new(prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) !Instruction {
+ const encoding = (try Encoding.findByMnemonic(prefix, mnemonic, ops)) orelse {
log.err("no encoding found for: {s} {s} {s} {s} {s} {s}", .{
- @tagName(args.prefix),
+ @tagName(prefix),
@tagName(mnemonic),
- @tagName(Encoding.Op.fromOperand(args.op1)),
- @tagName(Encoding.Op.fromOperand(args.op2)),
- @tagName(Encoding.Op.fromOperand(args.op3)),
- @tagName(Encoding.Op.fromOperand(args.op4)),
+ @tagName(if (ops.len > 0) Encoding.Op.fromOperand(ops[0]) else .none),
+ @tagName(if (ops.len > 1) Encoding.Op.fromOperand(ops[1]) else .none),
+ @tagName(if (ops.len > 2) Encoding.Op.fromOperand(ops[2]) else .none),
+ @tagName(if (ops.len > 3) Encoding.Op.fromOperand(ops[3]) else .none),
});
return error.InvalidInstruction;
};
log.debug("selected encoding: {}", .{encoding});
- return .{
- .prefix = args.prefix,
- .op1 = args.op1,
- .op2 = args.op2,
- .op3 = args.op3,
- .op4 = args.op4,
+
+ var inst = Instruction{
+ .prefix = prefix,
.encoding = encoding,
+ .ops = [1]Operand{.none} ** 4,
};
+ std.mem.copy(Operand, &inst.ops, ops);
+ return inst;
}
pub fn fmtPrint(inst: Instruction, writer: anytype) !void {
if (inst.prefix != .none) try writer.print("{s} ", .{@tagName(inst.prefix)});
try writer.print("{s}", .{@tagName(inst.encoding.mnemonic)});
- const ops = [_]struct { Operand, Encoding.Op }{
- .{ inst.op1, inst.encoding.op1 },
- .{ inst.op2, inst.encoding.op2 },
- .{ inst.op3, inst.encoding.op3 },
- .{ inst.op4, inst.encoding.op4 },
- };
- for (&ops, 0..) |op, i| {
- if (op[0] == .none) break;
- if (i > 0) {
- try writer.writeByte(',');
- }
+ for (inst.ops, inst.encodings.ops, 0..) |op, enc, i| {
+ if (op == .none) break;
+ if (i > 0) try writer.writeByte(',');
try writer.writeByte(' ');
- try op[0].fmtPrint(op[1], writer);
+ try op.fmtPrint(enc, writer);
}
}
pub fn encode(inst: Instruction, writer: anytype) !void {
const encoder = Encoder(@TypeOf(writer)){ .writer = writer };
- const encoding = inst.encoding;
+ const enc = inst.encoding;
+ const data = enc.data;
try inst.encodeLegacyPrefixes(encoder);
try inst.encodeMandatoryPrefix(encoder);
try inst.encodeRexPrefix(encoder);
try inst.encodeOpcode(encoder);
- switch (encoding.op_en) {
+ switch (data.op_en) {
.np, .o => {},
- .i, .d => try encodeImm(inst.op1.imm, encoding.op1, encoder),
- .zi, .oi => try encodeImm(inst.op2.imm, encoding.op2, encoder),
- .fd => try encoder.imm64(inst.op2.mem.moffs.offset),
- .td => try encoder.imm64(inst.op1.mem.moffs.offset),
+ .i, .d => try encodeImm(inst.ops[0].imm, data.ops[0], encoder),
+ .zi, .oi => try encodeImm(inst.ops[1].imm, data.ops[1], encoder),
+ .fd => try encoder.imm64(inst.ops[1].mem.moffs.offset),
+ .td => try encoder.imm64(inst.ops[0].mem.moffs.offset),
else => {
- const mem_op = switch (encoding.op_en) {
- .m, .mi, .m1, .mc, .mr, .mri, .mrc => inst.op1,
- .rm, .rmi => inst.op2,
+ const mem_op = switch (data.op_en) {
+ .m, .mi, .m1, .mc, .mr, .mri, .mrc => inst.ops[0],
+ .rm, .rmi => inst.ops[1],
else => unreachable,
};
switch (mem_op) {
.reg => |reg| {
- const rm = switch (encoding.op_en) {
- .m, .mi, .m1, .mc => encoding.modRmExt(),
- .mr, .mri, .mrc => inst.op2.reg.lowEnc(),
- .rm, .rmi => inst.op1.reg.lowEnc(),
+ const rm = switch (data.op_en) {
+ .m, .mi, .m1, .mc => enc.modRmExt(),
+ .mr, .mri, .mrc => inst.ops[1].reg.lowEnc(),
+ .rm, .rmi => inst.ops[0].reg.lowEnc(),
else => unreachable,
};
try encoder.modRm_direct(rm, reg.lowEnc());
},
.mem => |mem| {
- const op = switch (encoding.op_en) {
+ const op = switch (data.op_en) {
.m, .mi, .m1, .mc => .none,
- .mr, .mri, .mrc => inst.op2,
- .rm, .rmi => inst.op1,
+ .mr, .mri, .mrc => inst.ops[1],
+ .rm, .rmi => inst.ops[0],
else => unreachable,
};
- try encodeMemory(encoding, mem, op, encoder);
+ try encodeMemory(enc, mem, op, encoder);
},
else => unreachable,
}
- switch (encoding.op_en) {
- .mi => try encodeImm(inst.op2.imm, encoding.op2, encoder),
- .rmi, .mri => try encodeImm(inst.op3.imm, encoding.op3, encoder),
+ switch (data.op_en) {
+ .mi => try encodeImm(inst.ops[1].imm, data.ops[1], encoder),
+ .rmi, .mri => try encodeImm(inst.ops[2].imm, data.ops[2], encoder),
else => {},
}
},
@@ -214,15 +196,16 @@ pub const Instruction = struct {
const first = @boolToInt(inst.encoding.mandatoryPrefix() != null);
const final = opcode.len - 1;
for (opcode[first..final]) |byte| try encoder.opcode_1byte(byte);
- switch (inst.encoding.op_en) {
- .o, .oi => try encoder.opcode_withReg(opcode[final], inst.op1.reg.lowEnc()),
+ switch (inst.encoding.data.op_en) {
+ .o, .oi => try encoder.opcode_withReg(opcode[final], inst.ops[0].reg.lowEnc()),
else => try encoder.opcode_1byte(opcode[final]),
}
}
fn encodeLegacyPrefixes(inst: Instruction, encoder: anytype) !void {
const enc = inst.encoding;
- const op_en = enc.op_en;
+ const data = enc.data;
+ const op_en = data.op_en;
var legacy = LegacyPrefixes{};
@@ -233,7 +216,7 @@ pub const Instruction = struct {
.rep, .repe, .repz => legacy.prefix_f3 = true,
}
- if (enc.mode == .none) {
+ if (data.mode == .none) {
const bit_size = enc.operandBitSize();
if (bit_size == 16) {
legacy.set16BitOverride();
@@ -242,17 +225,17 @@ pub const Instruction = struct {
const segment_override: ?Register = switch (op_en) {
.i, .zi, .o, .oi, .d, .np => null,
- .fd => inst.op2.mem.base().?,
- .td => inst.op1.mem.base().?,
- .rm, .rmi => if (inst.op2.isSegmentRegister()) blk: {
- break :blk switch (inst.op2) {
+ .fd => inst.ops[1].mem.base().?,
+ .td => inst.ops[0].mem.base().?,
+ .rm, .rmi => if (inst.ops[1].isSegmentRegister()) blk: {
+ break :blk switch (inst.ops[1]) {
.reg => |r| r,
.mem => |m| m.base().?,
else => unreachable,
};
} else null,
- .m, .mi, .m1, .mc, .mr, .mri, .mrc => if (inst.op1.isSegmentRegister()) blk: {
- break :blk switch (inst.op1) {
+ .m, .mi, .m1, .mc, .mr, .mri, .mrc => if (inst.ops[0].isSegmentRegister()) blk: {
+ break :blk switch (inst.ops[0]) {
.reg => |r| r,
.mem => |m| m.base().?,
else => unreachable,
@@ -267,19 +250,19 @@ pub const Instruction = struct {
}
fn encodeRexPrefix(inst: Instruction, encoder: anytype) !void {
- const op_en = inst.encoding.op_en;
+ const op_en = inst.encoding.data.op_en;
var rex = Rex{};
- rex.present = inst.encoding.mode == .rex;
- rex.w = inst.encoding.mode == .long;
+ rex.present = inst.encoding.data.mode == .rex;
+ rex.w = inst.encoding.data.mode == .long;
switch (op_en) {
.np, .i, .zi, .fd, .td, .d => {},
- .o, .oi => rex.b = inst.op1.reg.isExtended(),
+ .o, .oi => rex.b = inst.ops[0].reg.isExtended(),
.m, .mi, .m1, .mc, .mr, .rm, .rmi, .mri, .mrc => {
const r_op = switch (op_en) {
- .rm, .rmi => inst.op1,
- .mr, .mri, .mrc => inst.op2,
+ .rm, .rmi => inst.ops[0],
+ .mr, .mri, .mrc => inst.ops[1],
else => null,
};
if (r_op) |op| {
@@ -287,8 +270,8 @@ pub const Instruction = struct {
}
const b_x_op = switch (op_en) {
- .rm, .rmi => inst.op2,
- .m, .mi, .m1, .mc, .mr, .mri, .mrc => inst.op1,
+ .rm, .rmi => inst.ops[1],
+ .m, .mi, .m1, .mc, .mr, .mri, .mrc => inst.ops[0],
else => unreachable,
};
switch (b_x_op) {
@@ -827,16 +810,14 @@ const TestEncode = struct {
buffer: [32]u8 = undefined,
index: usize = 0,
- fn encode(enc: *TestEncode, mnemonic: Instruction.Mnemonic, args: Instruction.Init) !void {
+ fn encode(
+ enc: *TestEncode,
+ mnemonic: Instruction.Mnemonic,
+ ops: []const Instruction.Operand,
+ ) !void {
var stream = std.io.fixedBufferStream(&enc.buffer);
var count_writer = std.io.countingWriter(stream.writer());
- const inst = try Instruction.new(mnemonic, .{
- .prefix = args.prefix,
- .op1 = args.op1,
- .op2 = args.op2,
- .op3 = args.op3,
- .op4 = args.op4,
- });
+ const inst = try Instruction.new(.none, mnemonic, ops);
try inst.encode(count_writer.writer());
enc.index = count_writer.bytes_written;
}
@@ -850,9 +831,9 @@ test "encode" {
var buf = std.ArrayList(u8).init(testing.allocator);
defer buf.deinit();
- const inst = try Instruction.new(.mov, .{
- .op1 = .{ .reg = .rbx },
- .op2 = .{ .imm = Immediate.u(4) },
+ const inst = try Instruction.new(.none, .mov, &.{
+ .{ .reg = .rbx },
+ .{ .imm = Immediate.u(4) },
});
try inst.encode(buf.writer());
try testing.expectEqualSlices(u8, &.{ 0x48, 0xc7, 0xc3, 0x4, 0x0, 0x0, 0x0 }, buf.items);
@@ -861,61 +842,94 @@ test "encode" {
test "lower I encoding" {
var enc = TestEncode{};
- try enc.encode(.push, .{ .op1 = .{ .imm = Immediate.u(0x10) } });
+ try enc.encode(.push, &.{
+ .{ .imm = Immediate.u(0x10) },
+ });
try expectEqualHexStrings("\x6A\x10", enc.code(), "push 0x10");
- try enc.encode(.push, .{ .op1 = .{ .imm = Immediate.u(0x1000) } });
+ try enc.encode(.push, &.{
+ .{ .imm = Immediate.u(0x1000) },
+ });
try expectEqualHexStrings("\x66\x68\x00\x10", enc.code(), "push 0x1000");
- try enc.encode(.push, .{ .op1 = .{ .imm = Immediate.u(0x10000000) } });
+ try enc.encode(.push, &.{
+ .{ .imm = Immediate.u(0x10000000) },
+ });
try expectEqualHexStrings("\x68\x00\x00\x00\x10", enc.code(), "push 0x10000000");
- try enc.encode(.adc, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .imm = Immediate.u(0x10000000) } });
+ try enc.encode(.adc, &.{
+ .{ .reg = .rax },
+ .{ .imm = Immediate.u(0x10000000) },
+ });
try expectEqualHexStrings("\x48\x15\x00\x00\x00\x10", enc.code(), "adc rax, 0x10000000");
- try enc.encode(.add, .{ .op1 = .{ .reg = .al }, .op2 = .{ .imm = Immediate.u(0x10) } });
+ try enc.encode(.add, &.{
+ .{ .reg = .al },
+ .{ .imm = Immediate.u(0x10) },
+ });
try expectEqualHexStrings("\x04\x10", enc.code(), "add al, 0x10");
- try enc.encode(.add, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .imm = Immediate.u(0x10) } });
+ try enc.encode(.add, &.{
+ .{ .reg = .rax },
+ .{ .imm = Immediate.u(0x10) },
+ });
try expectEqualHexStrings("\x48\x83\xC0\x10", enc.code(), "add rax, 0x10");
- try enc.encode(.sbb, .{ .op1 = .{ .reg = .ax }, .op2 = .{ .imm = Immediate.u(0x10) } });
+ try enc.encode(.sbb, &.{
+ .{ .reg = .ax },
+ .{ .imm = Immediate.u(0x10) },
+ });
try expectEqualHexStrings("\x66\x1D\x10\x00", enc.code(), "sbb ax, 0x10");
- try enc.encode(.xor, .{ .op1 = .{ .reg = .al }, .op2 = .{ .imm = Immediate.u(0x10) } });
+ try enc.encode(.xor, &.{
+ .{ .reg = .al },
+ .{ .imm = Immediate.u(0x10) },
+ });
try expectEqualHexStrings("\x34\x10", enc.code(), "xor al, 0x10");
}
test "lower MI encoding" {
var enc = TestEncode{};
- try enc.encode(.mov, .{ .op1 = .{ .reg = .r12 }, .op2 = .{ .imm = Immediate.u(0x1000) } });
+ try enc.encode(.mov, &.{
+ .{ .reg = .r12 },
+ .{ .imm = Immediate.u(0x1000) },
+ });
try expectEqualHexStrings("\x49\xC7\xC4\x00\x10\x00\x00", enc.code(), "mov r12, 0x1000");
- try enc.encode(.mov, .{
- .op1 = .{ .mem = Memory.sib(.byte, .{ .base = .r12 }) },
- .op2 = .{ .imm = Immediate.u(0x10) },
+ try enc.encode(.mov, &.{
+ .{ .mem = Memory.sib(.byte, .{ .base = .r12 }) },
+ .{ .imm = Immediate.u(0x10) },
});
try expectEqualHexStrings("\x41\xC6\x04\x24\x10", enc.code(), "mov BYTE PTR [r12], 0x10");
- try enc.encode(.mov, .{ .op1 = .{ .reg = .r12 }, .op2 = .{ .imm = Immediate.u(0x1000) } });
+ try enc.encode(.mov, &.{
+ .{ .reg = .r12 },
+ .{ .imm = Immediate.u(0x1000) },
+ });
try expectEqualHexStrings("\x49\xC7\xC4\x00\x10\x00\x00", enc.code(), "mov r12, 0x1000");
- try enc.encode(.mov, .{ .op1 = .{ .reg = .r12 }, .op2 = .{ .imm = Immediate.u(0x1000) } });
+ try enc.encode(.mov, &.{
+ .{ .reg = .r12 },
+ .{ .imm = Immediate.u(0x1000) },
+ });
try expectEqualHexStrings("\x49\xC7\xC4\x00\x10\x00\x00", enc.code(), "mov r12, 0x1000");
- try enc.encode(.mov, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .imm = Immediate.u(0x10) } });
+ try enc.encode(.mov, &.{
+ .{ .reg = .rax },
+ .{ .imm = Immediate.u(0x10) },
+ });
try expectEqualHexStrings("\x48\xc7\xc0\x10\x00\x00\x00", enc.code(), "mov rax, 0x10");
- try enc.encode(.mov, .{
- .op1 = .{ .mem = Memory.sib(.dword, .{ .base = .r11 }) },
- .op2 = .{ .imm = Immediate.u(0x10) },
+ try enc.encode(.mov, &.{
+ .{ .mem = Memory.sib(.dword, .{ .base = .r11 }) },
+ .{ .imm = Immediate.u(0x10) },
});
try expectEqualHexStrings("\x41\xc7\x03\x10\x00\x00\x00", enc.code(), "mov DWORD PTR [r11], 0x10");
- try enc.encode(.mov, .{
- .op1 = .{ .mem = Memory.rip(.qword, 0x10) },
- .op2 = .{ .imm = Immediate.u(0x10) },
+ try enc.encode(.mov, &.{
+ .{ .mem = Memory.rip(.qword, 0x10) },
+ .{ .imm = Immediate.u(0x10) },
});
try expectEqualHexStrings(
"\x48\xC7\x05\x10\x00\x00\x00\x10\x00\x00\x00",
@@ -923,99 +937,108 @@ test "lower MI encoding" {
"mov QWORD PTR [rip + 0x10], 0x10",
);
- try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.qword, .{
- .base = .rbp,
- .disp = -8,
- }) }, .op2 = .{ .imm = Immediate.u(0x10) } });
+ try enc.encode(.mov, &.{
+ .{ .mem = Memory.sib(.qword, .{ .base = .rbp, .disp = -8 }) },
+ .{ .imm = Immediate.u(0x10) },
+ });
try expectEqualHexStrings("\x48\xc7\x45\xf8\x10\x00\x00\x00", enc.code(), "mov QWORD PTR [rbp - 8], 0x10");
- try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.word, .{
- .base = .rbp,
- .disp = -2,
- }) }, .op2 = .{ .imm = Immediate.s(-16) } });
+ try enc.encode(.mov, &.{
+ .{ .mem = Memory.sib(.word, .{ .base = .rbp, .disp = -2 }) },
+ .{ .imm = Immediate.s(-16) },
+ });
try expectEqualHexStrings("\x66\xC7\x45\xFE\xF0\xFF", enc.code(), "mov WORD PTR [rbp - 2], -16");
- try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.byte, .{
- .base = .rbp,
- .disp = -1,
- }) }, .op2 = .{ .imm = Immediate.u(0x10) } });
+ try enc.encode(.mov, &.{
+ .{ .mem = Memory.sib(.byte, .{ .base = .rbp, .disp = -1 }) },
+ .{ .imm = Immediate.u(0x10) },
+ });
try expectEqualHexStrings("\xC6\x45\xFF\x10", enc.code(), "mov BYTE PTR [rbp - 1], 0x10");
- try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.qword, .{
- .base = .ds,
- .disp = 0x10000000,
- .scale_index = .{
- .scale = 2,
- .index = .rcx,
- },
- }) }, .op2 = .{ .imm = Immediate.u(0x10) } });
+ try enc.encode(.mov, &.{
+ .{ .mem = Memory.sib(.qword, .{
+ .base = .ds,
+ .disp = 0x10000000,
+ .scale_index = .{ .scale = 2, .index = .rcx },
+ }) },
+ .{ .imm = Immediate.u(0x10) },
+ });
try expectEqualHexStrings(
"\x48\xC7\x04\x4D\x00\x00\x00\x10\x10\x00\x00\x00",
enc.code(),
"mov QWORD PTR [rcx*2 + 0x10000000], 0x10",
);
- try enc.encode(.adc, .{ .op1 = .{ .mem = Memory.sib(.byte, .{
- .base = .rbp,
- .disp = -0x10,
- }) }, .op2 = .{ .imm = Immediate.u(0x10) } });
+ try enc.encode(.adc, &.{
+ .{ .mem = Memory.sib(.byte, .{ .base = .rbp, .disp = -0x10 }) },
+ .{ .imm = Immediate.u(0x10) },
+ });
try expectEqualHexStrings("\x80\x55\xF0\x10", enc.code(), "adc BYTE PTR [rbp - 0x10], 0x10");
- try enc.encode(.adc, .{ .op1 = .{ .mem = Memory.rip(.qword, 0) }, .op2 = .{ .imm = Immediate.u(0x10) } });
+ try enc.encode(.adc, &.{
+ .{ .mem = Memory.rip(.qword, 0) },
+ .{ .imm = Immediate.u(0x10) },
+ });
try expectEqualHexStrings("\x48\x83\x15\x00\x00\x00\x00\x10", enc.code(), "adc QWORD PTR [rip], 0x10");
- try enc.encode(.adc, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .imm = Immediate.u(0x10) } });
+ try enc.encode(.adc, &.{
+ .{ .reg = .rax },
+ .{ .imm = Immediate.u(0x10) },
+ });
try expectEqualHexStrings("\x48\x83\xD0\x10", enc.code(), "adc rax, 0x10");
- try enc.encode(.add, .{ .op1 = .{ .mem = Memory.sib(.dword, .{
- .base = .rdx,
- .disp = -8,
- }) }, .op2 = .{ .imm = Immediate.u(0x10) } });
+ try enc.encode(.add, &.{
+ .{ .mem = Memory.sib(.dword, .{ .base = .rdx, .disp = -8 }) },
+ .{ .imm = Immediate.u(0x10) },
+ });
try expectEqualHexStrings("\x83\x42\xF8\x10", enc.code(), "add DWORD PTR [rdx - 8], 0x10");
- try enc.encode(.add, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .imm = Immediate.u(0x10) } });
+ try enc.encode(.add, &.{
+ .{ .reg = .rax },
+ .{ .imm = Immediate.u(0x10) },
+ });
try expectEqualHexStrings("\x48\x83\xC0\x10", enc.code(), "add rax, 0x10");
- try enc.encode(.add, .{ .op1 = .{ .mem = Memory.sib(.qword, .{
- .base = .rbp,
- .disp = -0x10,
- }) }, .op2 = .{ .imm = Immediate.s(-0x10) } });
+ try enc.encode(.add, &.{
+ .{ .mem = Memory.sib(.qword, .{ .base = .rbp, .disp = -0x10 }) },
+ .{ .imm = Immediate.s(-0x10) },
+ });
try expectEqualHexStrings("\x48\x83\x45\xF0\xF0", enc.code(), "add QWORD PTR [rbp - 0x10], -0x10");
- try enc.encode(.@"and", .{ .op1 = .{ .mem = Memory.sib(.dword, .{
- .base = .ds,
- .disp = 0x10000000,
- }) }, .op2 = .{ .imm = Immediate.u(0x10) } });
+ try enc.encode(.@"and", &.{
+ .{ .mem = Memory.sib(.dword, .{ .base = .ds, .disp = 0x10000000 }) },
+ .{ .imm = Immediate.u(0x10) },
+ });
try expectEqualHexStrings(
"\x83\x24\x25\x00\x00\x00\x10\x10",
enc.code(),
"and DWORD PTR ds:0x10000000, 0x10",
);
- try enc.encode(.@"and", .{ .op1 = .{ .mem = Memory.sib(.dword, .{
- .base = .es,
- .disp = 0x10000000,
- }) }, .op2 = .{ .imm = Immediate.u(0x10) } });
+ try enc.encode(.@"and", &.{
+ .{ .mem = Memory.sib(.dword, .{ .base = .es, .disp = 0x10000000 }) },
+ .{ .imm = Immediate.u(0x10) },
+ });
try expectEqualHexStrings(
"\x26\x83\x24\x25\x00\x00\x00\x10\x10",
enc.code(),
"and DWORD PTR es:0x10000000, 0x10",
);
- try enc.encode(.@"and", .{ .op1 = .{ .mem = Memory.sib(.dword, .{
- .base = .r12,
- .disp = 0x10000000,
- }) }, .op2 = .{ .imm = Immediate.u(0x10) } });
+ try enc.encode(.@"and", &.{
+ .{ .mem = Memory.sib(.dword, .{ .base = .r12, .disp = 0x10000000 }) },
+ .{ .imm = Immediate.u(0x10) },
+ });
try expectEqualHexStrings(
"\x41\x83\xA4\x24\x00\x00\x00\x10\x10",
enc.code(),
"and DWORD PTR [r12 + 0x10000000], 0x10",
);
- try enc.encode(.sub, .{ .op1 = .{ .mem = Memory.sib(.dword, .{
- .base = .r11,
- .disp = 0x10000000,
- }) }, .op2 = .{ .imm = Immediate.u(0x10) } });
+ try enc.encode(.sub, &.{
+ .{ .mem = Memory.sib(.dword, .{ .base = .r11, .disp = 0x10000000 }) },
+ .{ .imm = Immediate.u(0x10) },
+ });
try expectEqualHexStrings(
"\x41\x83\xAB\x00\x00\x00\x10\x10",
enc.code(),
@@ -1026,185 +1049,227 @@ test "lower MI encoding" {
test "lower RM encoding" {
var enc = TestEncode{};
- try enc.encode(.mov, .{
- .op1 = .{ .reg = .rax },
- .op2 = .{ .mem = Memory.sib(.qword, .{ .base = .r11 }) },
+ try enc.encode(.mov, &.{
+ .{ .reg = .rax },
+ .{ .mem = Memory.sib(.qword, .{ .base = .r11 }) },
});
try expectEqualHexStrings("\x49\x8b\x03", enc.code(), "mov rax, QWORD PTR [r11]");
- try enc.encode(.mov, .{ .op1 = .{ .reg = .rbx }, .op2 = .{ .mem = Memory.sib(.qword, .{
- .base = .ds,
- .disp = 0x10,
- }) } });
+ try enc.encode(.mov, &.{
+ .{ .reg = .rbx },
+ .{ .mem = Memory.sib(.qword, .{ .base = .ds, .disp = 0x10 }) },
+ });
try expectEqualHexStrings("\x48\x8B\x1C\x25\x10\x00\x00\x00", enc.code(), "mov rbx, QWORD PTR ds:0x10");
- try enc.encode(.mov, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .mem = Memory.sib(.qword, .{
- .base = .rbp,
- .disp = -4,
- }) } });
+ try enc.encode(.mov, &.{
+ .{ .reg = .rax },
+ .{ .mem = Memory.sib(.qword, .{ .base = .rbp, .disp = -4 }) },
+ });
try expectEqualHexStrings("\x48\x8B\x45\xFC", enc.code(), "mov rax, QWORD PTR [rbp - 4]");
- try enc.encode(.mov, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .mem = Memory.sib(.qword, .{
- .base = .rbp,
- .scale_index = .{
- .scale = 1,
- .index = .rcx,
- },
- .disp = -8,
- }) } });
+ try enc.encode(.mov, &.{
+ .{ .reg = .rax },
+ .{ .mem = Memory.sib(.qword, .{
+ .base = .rbp,
+ .scale_index = .{ .scale = 1, .index = .rcx },
+ .disp = -8,
+ }) },
+ });
try expectEqualHexStrings("\x48\x8B\x44\x0D\xF8", enc.code(), "mov rax, QWORD PTR [rbp + rcx*1 - 8]");
- try enc.encode(.mov, .{ .op1 = .{ .reg = .eax }, .op2 = .{ .mem = Memory.sib(.dword, .{
- .base = .rbp,
- .scale_index = .{
- .scale = 4,
- .index = .rdx,
- },
- .disp = -4,
- }) } });
+ try enc.encode(.mov, &.{
+ .{ .reg = .eax },
+ .{ .mem = Memory.sib(.dword, .{
+ .base = .rbp,
+ .scale_index = .{ .scale = 4, .index = .rdx },
+ .disp = -4,
+ }) },
+ });
try expectEqualHexStrings("\x8B\x44\x95\xFC", enc.code(), "mov eax, dword ptr [rbp + rdx*4 - 4]");
- try enc.encode(.mov, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .mem = Memory.sib(.qword, .{
- .base = .rbp,
- .scale_index = .{
- .scale = 8,
- .index = .rcx,
- },
- .disp = -8,
- }) } });
+ try enc.encode(.mov, &.{
+ .{ .reg = .rax },
+ .{ .mem = Memory.sib(.qword, .{
+ .base = .rbp,
+ .scale_index = .{ .scale = 8, .index = .rcx },
+ .disp = -8,
+ }) },
+ });
try expectEqualHexStrings("\x48\x8B\x44\xCD\xF8", enc.code(), "mov rax, QWORD PTR [rbp + rcx*8 - 8]");
- try enc.encode(.mov, .{ .op1 = .{ .reg = .r8b }, .op2 = .{ .mem = Memory.sib(.byte, .{
- .base = .rsi,
- .scale_index = .{
- .scale = 1,
- .index = .rcx,
- },
- .disp = -24,
- }) } });
+ try enc.encode(.mov, &.{
+ .{ .reg = .r8b },
+ .{ .mem = Memory.sib(.byte, .{
+ .base = .rsi,
+ .scale_index = .{ .scale = 1, .index = .rcx },
+ .disp = -24,
+ }) },
+ });
try expectEqualHexStrings("\x44\x8A\x44\x0E\xE8", enc.code(), "mov r8b, BYTE PTR [rsi + rcx*1 - 24]");
// TODO this mnemonic needs cleanup as some prefixes are obsolete.
- try enc.encode(.mov, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .reg = .cs } });
+ try enc.encode(.mov, &.{
+ .{ .reg = .rax },
+ .{ .reg = .cs },
+ });
try expectEqualHexStrings("\x48\x8C\xC8", enc.code(), "mov rax, cs");
- try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.qword, .{
- .base = .rbp,
- .disp = -16,
- }) }, .op2 = .{ .reg = .fs } });
+ try enc.encode(.mov, &.{
+ .{ .mem = Memory.sib(.qword, .{ .base = .rbp, .disp = -16 }) },
+ .{ .reg = .fs },
+ });
try expectEqualHexStrings("\x48\x8C\x65\xF0", enc.code(), "mov QWORD PTR [rbp - 16], fs");
- try enc.encode(.mov, .{ .op1 = .{ .reg = .r12w }, .op2 = .{ .reg = .cs } });
+ try enc.encode(.mov, &.{
+ .{ .reg = .r12w },
+ .{ .reg = .cs },
+ });
try expectEqualHexStrings("\x66\x41\x8C\xCC", enc.code(), "mov r12w, cs");
- try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.word, .{
- .base = .rbp,
- .disp = -16,
- }) }, .op2 = .{ .reg = .fs } });
+ try enc.encode(.mov, &.{
+ .{ .mem = Memory.sib(.word, .{ .base = .rbp, .disp = -16 }) },
+ .{ .reg = .fs },
+ });
try expectEqualHexStrings("\x66\x8C\x65\xF0", enc.code(), "mov WORD PTR [rbp - 16], fs");
- try enc.encode(.movsx, .{ .op1 = .{ .reg = .eax }, .op2 = .{ .reg = .bx } });
+ try enc.encode(.movsx, &.{
+ .{ .reg = .eax },
+ .{ .reg = .bx },
+ });
try expectEqualHexStrings("\x0F\xBF\xC3", enc.code(), "movsx eax, bx");
- try enc.encode(.movsx, .{ .op1 = .{ .reg = .eax }, .op2 = .{ .reg = .bl } });
+ try enc.encode(.movsx, &.{
+ .{ .reg = .eax },
+ .{ .reg = .bl },
+ });
try expectEqualHexStrings("\x0F\xBE\xC3", enc.code(), "movsx eax, bl");
- try enc.encode(.movsx, .{ .op1 = .{ .reg = .ax }, .op2 = .{ .reg = .bl } });
+ try enc.encode(.movsx, &.{
+ .{ .reg = .ax },
+ .{ .reg = .bl },
+ });
try expectEqualHexStrings("\x66\x0F\xBE\xC3", enc.code(), "movsx ax, bl");
- try enc.encode(.movsx, .{
- .op1 = .{ .reg = .eax },
- .op2 = .{ .mem = Memory.sib(.word, .{ .base = .rbp }) },
+ try enc.encode(.movsx, &.{
+ .{ .reg = .eax },
+ .{ .mem = Memory.sib(.word, .{ .base = .rbp }) },
});
try expectEqualHexStrings("\x0F\xBF\x45\x00", enc.code(), "movsx eax, BYTE PTR [rbp]");
- try enc.encode(.movsx, .{
- .op1 = .{ .reg = .eax },
- .op2 = .{ .mem = Memory.sib(.byte, .{ .scale_index = .{ .index = .rax, .scale = 2 } }) },
+ try enc.encode(.movsx, &.{
+ .{ .reg = .eax },
+ .{ .mem = Memory.sib(.byte, .{ .scale_index = .{ .index = .rax, .scale = 2 } }) },
});
try expectEqualHexStrings("\x0F\xBE\x04\x45\x00\x00\x00\x00", enc.code(), "movsx eax, BYTE PTR [rax * 2]");
- try enc.encode(.movsx, .{ .op1 = .{ .reg = .ax }, .op2 = .{ .mem = Memory.rip(.byte, 0x10) } });
+ try enc.encode(.movsx, &.{
+ .{ .reg = .ax },
+ .{ .mem = Memory.rip(.byte, 0x10) },
+ });
try expectEqualHexStrings("\x66\x0F\xBE\x05\x10\x00\x00\x00", enc.code(), "movsx ax, BYTE PTR [rip + 0x10]");
- try enc.encode(.movsx, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .reg = .bx } });
+ try enc.encode(.movsx, &.{
+ .{ .reg = .rax },
+ .{ .reg = .bx },
+ });
try expectEqualHexStrings("\x48\x0F\xBF\xC3", enc.code(), "movsx rax, bx");
- try enc.encode(.movsxd, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .reg = .ebx } });
+ try enc.encode(.movsxd, &.{
+ .{ .reg = .rax },
+ .{ .reg = .ebx },
+ });
try expectEqualHexStrings("\x48\x63\xC3", enc.code(), "movsxd rax, ebx");
- try enc.encode(.lea, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .mem = Memory.rip(.qword, 0x10) } });
+ try enc.encode(.lea, &.{
+ .{ .reg = .rax },
+ .{ .mem = Memory.rip(.qword, 0x10) },
+ });
try expectEqualHexStrings("\x48\x8D\x05\x10\x00\x00\x00", enc.code(), "lea rax, QWORD PTR [rip + 0x10]");
- try enc.encode(.lea, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .mem = Memory.rip(.dword, 0x10) } });
+ try enc.encode(.lea, &.{
+ .{ .reg = .rax },
+ .{ .mem = Memory.rip(.dword, 0x10) },
+ });
try expectEqualHexStrings("\x48\x8D\x05\x10\x00\x00\x00", enc.code(), "lea rax, DWORD PTR [rip + 0x10]");
- try enc.encode(.lea, .{ .op1 = .{ .reg = .eax }, .op2 = .{ .mem = Memory.rip(.dword, 0x10) } });
+ try enc.encode(.lea, &.{
+ .{ .reg = .eax },
+ .{ .mem = Memory.rip(.dword, 0x10) },
+ });
try expectEqualHexStrings("\x8D\x05\x10\x00\x00\x00", enc.code(), "lea eax, DWORD PTR [rip + 0x10]");
- try enc.encode(.lea, .{ .op1 = .{ .reg = .eax }, .op2 = .{ .mem = Memory.rip(.word, 0x10) } });
+ try enc.encode(.lea, &.{
+ .{ .reg = .eax },
+ .{ .mem = Memory.rip(.word, 0x10) },
+ });
try expectEqualHexStrings("\x8D\x05\x10\x00\x00\x00", enc.code(), "lea eax, WORD PTR [rip + 0x10]");
- try enc.encode(.lea, .{ .op1 = .{ .reg = .ax }, .op2 = .{ .mem = Memory.rip(.byte, 0x10) } });
+ try enc.encode(.lea, &.{
+ .{ .reg = .ax },
+ .{ .mem = Memory.rip(.byte, 0x10) },
+ });
try expectEqualHexStrings("\x66\x8D\x05\x10\x00\x00\x00", enc.code(), "lea ax, BYTE PTR [rip + 0x10]");
- try enc.encode(.lea, .{
- .op1 = .{ .reg = .rsi },
- .op2 = .{ .mem = Memory.sib(.qword, .{
+ try enc.encode(.lea, &.{
+ .{ .reg = .rsi },
+ .{ .mem = Memory.sib(.qword, .{
.base = .rbp,
.scale_index = .{ .scale = 1, .index = .rcx },
}) },
});
try expectEqualHexStrings("\x48\x8D\x74\x0D\x00", enc.code(), "lea rsi, QWORD PTR [rbp + rcx*1 + 0]");
- try enc.encode(.add, .{ .op1 = .{ .reg = .r11 }, .op2 = .{ .mem = Memory.sib(.qword, .{
- .base = .ds,
- .disp = 0x10000000,
- }) } });
+ try enc.encode(.add, &.{
+ .{ .reg = .r11 },
+ .{ .mem = Memory.sib(.qword, .{ .base = .ds, .disp = 0x10000000 }) },
+ });
try expectEqualHexStrings("\x4C\x03\x1C\x25\x00\x00\x00\x10", enc.code(), "add r11, QWORD PTR ds:0x10000000");
- try enc.encode(.add, .{ .op1 = .{ .reg = .r12b }, .op2 = .{ .mem = Memory.sib(.byte, .{
- .base = .ds,
- .disp = 0x10000000,
- }) } });
+ try enc.encode(.add, &.{
+ .{ .reg = .r12b },
+ .{ .mem = Memory.sib(.byte, .{ .base = .ds, .disp = 0x10000000 }) },
+ });
try expectEqualHexStrings("\x44\x02\x24\x25\x00\x00\x00\x10", enc.code(), "add r11b, BYTE PTR ds:0x10000000");
- try enc.encode(.add, .{ .op1 = .{ .reg = .r12b }, .op2 = .{ .mem = Memory.sib(.byte, .{
- .base = .fs,
- .disp = 0x10000000,
- }) } });
+ try enc.encode(.add, &.{
+ .{ .reg = .r12b },
+ .{ .mem = Memory.sib(.byte, .{ .base = .fs, .disp = 0x10000000 }) },
+ });
try expectEqualHexStrings("\x64\x44\x02\x24\x25\x00\x00\x00\x10", enc.code(), "add r11b, BYTE PTR fs:0x10000000");
- try enc.encode(.sub, .{ .op1 = .{ .reg = .r11 }, .op2 = .{ .mem = Memory.sib(.qword, .{
- .base = .r13,
- .disp = 0x10000000,
- }) } });
+ try enc.encode(.sub, &.{
+ .{ .reg = .r11 },
+ .{ .mem = Memory.sib(.qword, .{ .base = .r13, .disp = 0x10000000 }) },
+ });
try expectEqualHexStrings("\x4D\x2B\x9D\x00\x00\x00\x10", enc.code(), "sub r11, QWORD PTR [r13 + 0x10000000]");
- try enc.encode(.sub, .{ .op1 = .{ .reg = .r11 }, .op2 = .{ .mem = Memory.sib(.qword, .{
- .base = .r12,
- .disp = 0x10000000,
- }) } });
+ try enc.encode(.sub, &.{
+ .{ .reg = .r11 },
+ .{ .mem = Memory.sib(.qword, .{ .base = .r12, .disp = 0x10000000 }) },
+ });
try expectEqualHexStrings("\x4D\x2B\x9C\x24\x00\x00\x00\x10", enc.code(), "sub r11, QWORD PTR [r12 + 0x10000000]");
- try enc.encode(.imul, .{ .op1 = .{ .reg = .r11 }, .op2 = .{ .reg = .r12 } });
+ try enc.encode(.imul, &.{
+ .{ .reg = .r11 },
+ .{ .reg = .r12 },
+ });
try expectEqualHexStrings("\x4D\x0F\xAF\xDC", enc.code(), "mov r11, r12");
}
test "lower RMI encoding" {
var enc = TestEncode{};
- try enc.encode(.imul, .{
- .op1 = .{ .reg = .r11 },
- .op2 = .{ .reg = .r12 },
- .op3 = .{ .imm = Immediate.s(-2) },
+ try enc.encode(.imul, &.{
+ .{ .reg = .r11 },
+ .{ .reg = .r12 },
+ .{ .imm = Immediate.s(-2) },
});
try expectEqualHexStrings("\x4D\x6B\xDC\xFE", enc.code(), "imul r11, r12, -2");
- try enc.encode(.imul, .{
- .op1 = .{ .reg = .r11 },
- .op2 = .{ .mem = Memory.rip(.qword, -16) },
- .op3 = .{ .imm = Immediate.s(-1024) },
+ try enc.encode(.imul, &.{
+ .{ .reg = .r11 },
+ .{ .mem = Memory.rip(.qword, -16) },
+ .{ .imm = Immediate.s(-1024) },
});
try expectEqualHexStrings(
"\x4C\x69\x1D\xF0\xFF\xFF\xFF\x00\xFC\xFF\xFF",
@@ -1212,13 +1277,10 @@ test "lower RMI encoding" {
"imul r11, QWORD PTR [rip - 16], -1024",
);
- try enc.encode(.imul, .{
- .op1 = .{ .reg = .bx },
- .op2 = .{ .mem = Memory.sib(.word, .{
- .base = .rbp,
- .disp = -16,
- }) },
- .op3 = .{ .imm = Immediate.s(-1024) },
+ try enc.encode(.imul, &.{
+ .{ .reg = .bx },
+ .{ .mem = Memory.sib(.word, .{ .base = .rbp, .disp = -16 }) },
+ .{ .imm = Immediate.s(-1024) },
});
try expectEqualHexStrings(
"\x66\x69\x5D\xF0\x00\xFC",
@@ -1226,13 +1288,10 @@ test "lower RMI encoding" {
"imul bx, WORD PTR [rbp - 16], -1024",
);
- try enc.encode(.imul, .{
- .op1 = .{ .reg = .bx },
- .op2 = .{ .mem = Memory.sib(.word, .{
- .base = .rbp,
- .disp = -16,
- }) },
- .op3 = .{ .imm = Immediate.u(1024) },
+ try enc.encode(.imul, &.{
+ .{ .reg = .bx },
+ .{ .mem = Memory.sib(.word, .{ .base = .rbp, .disp = -16 }) },
+ .{ .imm = Immediate.u(1024) },
});
try expectEqualHexStrings(
"\x66\x69\x5D\xF0\x00\x04",
@@ -1244,238 +1303,343 @@ test "lower RMI encoding" {
test "lower MR encoding" {
var enc = TestEncode{};
- try enc.encode(.mov, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .reg = .rbx } });
+ try enc.encode(.mov, &.{
+ .{ .reg = .rax },
+ .{ .reg = .rbx },
+ });
try expectEqualHexStrings("\x48\x89\xD8", enc.code(), "mov rax, rbx");
- try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.qword, .{
- .base = .rbp,
- .disp = -4,
- }) }, .op2 = .{ .reg = .r11 } });
+ try enc.encode(.mov, &.{
+ .{ .mem = Memory.sib(.qword, .{ .base = .rbp, .disp = -4 }) },
+ .{ .reg = .r11 },
+ });
try expectEqualHexStrings("\x4c\x89\x5d\xfc", enc.code(), "mov QWORD PTR [rbp - 4], r11");
- try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.rip(.qword, 0x10) }, .op2 = .{ .reg = .r12 } });
+ try enc.encode(.mov, &.{
+ .{ .mem = Memory.rip(.qword, 0x10) },
+ .{ .reg = .r12 },
+ });
try expectEqualHexStrings("\x4C\x89\x25\x10\x00\x00\x00", enc.code(), "mov QWORD PTR [rip + 0x10], r12");
- try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.qword, .{
- .base = .r11,
- .scale_index = .{
- .scale = 2,
- .index = .r12,
- },
- .disp = 0x10,
- }) }, .op2 = .{ .reg = .r13 } });
+ try enc.encode(.mov, &.{
+ .{ .mem = Memory.sib(.qword, .{
+ .base = .r11,
+ .scale_index = .{ .scale = 2, .index = .r12 },
+ .disp = 0x10,
+ }) },
+ .{ .reg = .r13 },
+ });
try expectEqualHexStrings("\x4F\x89\x6C\x63\x10", enc.code(), "mov QWORD PTR [r11 + 2 * r12 + 0x10], r13");
- try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.rip(.word, -0x10) }, .op2 = .{ .reg = .r12w } });
+ try enc.encode(.mov, &.{
+ .{ .mem = Memory.rip(.word, -0x10) },
+ .{ .reg = .r12w },
+ });
try expectEqualHexStrings("\x66\x44\x89\x25\xF0\xFF\xFF\xFF", enc.code(), "mov WORD PTR [rip - 0x10], r12w");
- try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.byte, .{
- .base = .r11,
- .scale_index = .{
- .scale = 2,
- .index = .r12,
- },
- .disp = 0x10,
- }) }, .op2 = .{ .reg = .r13b } });
+ try enc.encode(.mov, &.{
+ .{ .mem = Memory.sib(.byte, .{
+ .base = .r11,
+ .scale_index = .{ .scale = 2, .index = .r12 },
+ .disp = 0x10,
+ }) },
+ .{ .reg = .r13b },
+ });
try expectEqualHexStrings("\x47\x88\x6C\x63\x10", enc.code(), "mov BYTE PTR [r11 + 2 * r12 + 0x10], r13b");
- try enc.encode(.add, .{ .op1 = .{ .mem = Memory.sib(.byte, .{
- .base = .ds,
- .disp = 0x10000000,
- }) }, .op2 = .{ .reg = .r12b } });
+ try enc.encode(.add, &.{
+ .{ .mem = Memory.sib(.byte, .{ .base = .ds, .disp = 0x10000000 }) },
+ .{ .reg = .r12b },
+ });
try expectEqualHexStrings("\x44\x00\x24\x25\x00\x00\x00\x10", enc.code(), "add BYTE PTR ds:0x10000000, r12b");
- try enc.encode(.add, .{ .op1 = .{ .mem = Memory.sib(.dword, .{
- .base = .ds,
- .disp = 0x10000000,
- }) }, .op2 = .{ .reg = .r12d } });
+ try enc.encode(.add, &.{
+ .{ .mem = Memory.sib(.dword, .{ .base = .ds, .disp = 0x10000000 }) },
+ .{ .reg = .r12d },
+ });
try expectEqualHexStrings("\x44\x01\x24\x25\x00\x00\x00\x10", enc.code(), "add DWORD PTR [ds:0x10000000], r12d");
- try enc.encode(.add, .{ .op1 = .{ .mem = Memory.sib(.dword, .{
- .base = .gs,
- .disp = 0x10000000,
- }) }, .op2 = .{ .reg = .r12d } });
+ try enc.encode(.add, &.{
+ .{ .mem = Memory.sib(.dword, .{ .base = .gs, .disp = 0x10000000 }) },
+ .{ .reg = .r12d },
+ });
try expectEqualHexStrings("\x65\x44\x01\x24\x25\x00\x00\x00\x10", enc.code(), "add DWORD PTR [gs:0x10000000], r12d");
- try enc.encode(.sub, .{ .op1 = .{ .mem = Memory.sib(.qword, .{
- .base = .r11,
- .disp = 0x10000000,
- }) }, .op2 = .{ .reg = .r12 } });
+ try enc.encode(.sub, &.{
+ .{ .mem = Memory.sib(.qword, .{ .base = .r11, .disp = 0x10000000 }) },
+ .{ .reg = .r12 },
+ });
try expectEqualHexStrings("\x4D\x29\xA3\x00\x00\x00\x10", enc.code(), "sub QWORD PTR [r11 + 0x10000000], r12");
}
test "lower M encoding" {
var enc = TestEncode{};
- try enc.encode(.call, .{ .op1 = .{ .reg = .r12 } });
+ try enc.encode(.call, &.{
+ .{ .reg = .r12 },
+ });
try expectEqualHexStrings("\x41\xFF\xD4", enc.code(), "call r12");
- try enc.encode(.call, .{ .op1 = .{ .mem = Memory.sib(.qword, .{ .base = .r12 }) } });
+ try enc.encode(.call, &.{
+ .{ .mem = Memory.sib(.qword, .{ .base = .r12 }) },
+ });
try expectEqualHexStrings("\x41\xFF\x14\x24", enc.code(), "call QWORD PTR [r12]");
- try enc.encode(.call, .{
- .op1 = .{ .mem = Memory.sib(.qword, .{
+ try enc.encode(.call, &.{
+ .{ .mem = Memory.sib(.qword, .{
.base = null,
.scale_index = .{ .index = .r11, .scale = 2 },
}) },
});
try expectEqualHexStrings("\x42\xFF\x14\x5D\x00\x00\x00\x00", enc.code(), "call QWORD PTR [r11 * 2]");
- try enc.encode(.call, .{
- .op1 = .{ .mem = Memory.sib(.qword, .{
+ try enc.encode(.call, &.{
+ .{ .mem = Memory.sib(.qword, .{
.base = null,
.scale_index = .{ .index = .r12, .scale = 2 },
}) },
});
try expectEqualHexStrings("\x42\xFF\x14\x65\x00\x00\x00\x00", enc.code(), "call QWORD PTR [r12 * 2]");
- try enc.encode(.call, .{ .op1 = .{ .mem = Memory.sib(.qword, .{ .base = .gs }) } });
+ try enc.encode(.call, &.{
+ .{ .mem = Memory.sib(.qword, .{ .base = .gs }) },
+ });
try expectEqualHexStrings("\x65\xFF\x14\x25\x00\x00\x00\x00", enc.code(), "call gs:0x0");
- try enc.encode(.call, .{ .op1 = .{ .imm = Immediate.s(0) } });
+ try enc.encode(.call, &.{
+ .{ .imm = Immediate.s(0) },
+ });
try expectEqualHexStrings("\xE8\x00\x00\x00\x00", enc.code(), "call 0x0");
- try enc.encode(.push, .{ .op1 = .{ .mem = Memory.sib(.qword, .{ .base = .rbp }) } });
+ try enc.encode(.push, &.{
+ .{ .mem = Memory.sib(.qword, .{ .base = .rbp }) },
+ });
try expectEqualHexStrings("\xFF\x75\x00", enc.code(), "push QWORD PTR [rbp]");
- try enc.encode(.push, .{ .op1 = .{ .mem = Memory.sib(.word, .{ .base = .rbp }) } });
+ try enc.encode(.push, &.{
+ .{ .mem = Memory.sib(.word, .{ .base = .rbp }) },
+ });
try expectEqualHexStrings("\x66\xFF\x75\x00", enc.code(), "push QWORD PTR [rbp]");
- try enc.encode(.pop, .{ .op1 = .{ .mem = Memory.rip(.qword, 0) } });
+ try enc.encode(.pop, &.{
+ .{ .mem = Memory.rip(.qword, 0) },
+ });
try expectEqualHexStrings("\x8F\x05\x00\x00\x00\x00", enc.code(), "pop QWORD PTR [rip]");
- try enc.encode(.pop, .{ .op1 = .{ .mem = Memory.rip(.word, 0) } });
+ try enc.encode(.pop, &.{
+ .{ .mem = Memory.rip(.word, 0) },
+ });
try expectEqualHexStrings("\x66\x8F\x05\x00\x00\x00\x00", enc.code(), "pop WORD PTR [rbp]");
- try enc.encode(.imul, .{ .op1 = .{ .reg = .rax } });
+ try enc.encode(.imul, &.{
+ .{ .reg = .rax },
+ });
try expectEqualHexStrings("\x48\xF7\xE8", enc.code(), "imul rax");
- try enc.encode(.imul, .{ .op1 = .{ .reg = .r12 } });
+ try enc.encode(.imul, &.{
+ .{ .reg = .r12 },
+ });
try expectEqualHexStrings("\x49\xF7\xEC", enc.code(), "imul r12");
}
test "lower O encoding" {
var enc = TestEncode{};
- try enc.encode(.push, .{ .op1 = .{ .reg = .rax } });
+ try enc.encode(.push, &.{
+ .{ .reg = .rax },
+ });
try expectEqualHexStrings("\x50", enc.code(), "push rax");
- try enc.encode(.push, .{ .op1 = .{ .reg = .r12w } });
+ try enc.encode(.push, &.{
+ .{ .reg = .r12w },
+ });
try expectEqualHexStrings("\x66\x41\x54", enc.code(), "push r12w");
- try enc.encode(.pop, .{ .op1 = .{ .reg = .r12 } });
+ try enc.encode(.pop, &.{
+ .{ .reg = .r12 },
+ });
try expectEqualHexStrings("\x41\x5c", enc.code(), "pop r12");
}
test "lower OI encoding" {
var enc = TestEncode{};
- try enc.encode(.mov, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .imm = Immediate.u(0x1000000000000000) } });
+ try enc.encode(.mov, &.{
+ .{ .reg = .rax },
+ .{ .imm = Immediate.u(0x1000000000000000) },
+ });
try expectEqualHexStrings(
"\x48\xB8\x00\x00\x00\x00\x00\x00\x00\x10",
enc.code(),
"movabs rax, 0x1000000000000000",
);
- try enc.encode(.mov, .{ .op1 = .{ .reg = .r11 }, .op2 = .{ .imm = Immediate.u(0x1000000000000000) } });
+ try enc.encode(.mov, &.{
+ .{ .reg = .r11 },
+ .{ .imm = Immediate.u(0x1000000000000000) },
+ });
try expectEqualHexStrings(
"\x49\xBB\x00\x00\x00\x00\x00\x00\x00\x10",
enc.code(),
"movabs r11, 0x1000000000000000",
);
- try enc.encode(.mov, .{ .op1 = .{ .reg = .r11d }, .op2 = .{ .imm = Immediate.u(0x10000000) } });
+ try enc.encode(.mov, &.{
+ .{ .reg = .r11d },
+ .{ .imm = Immediate.u(0x10000000) },
+ });
try expectEqualHexStrings("\x41\xBB\x00\x00\x00\x10", enc.code(), "mov r11d, 0x10000000");
- try enc.encode(.mov, .{ .op1 = .{ .reg = .r11w }, .op2 = .{ .imm = Immediate.u(0x1000) } });
+ try enc.encode(.mov, &.{
+ .{ .reg = .r11w },
+ .{ .imm = Immediate.u(0x1000) },
+ });
try expectEqualHexStrings("\x66\x41\xBB\x00\x10", enc.code(), "mov r11w, 0x1000");
- try enc.encode(.mov, .{ .op1 = .{ .reg = .r11b }, .op2 = .{ .imm = Immediate.u(0x10) } });
+ try enc.encode(.mov, &.{
+ .{ .reg = .r11b },
+ .{ .imm = Immediate.u(0x10) },
+ });
try expectEqualHexStrings("\x41\xB3\x10", enc.code(), "mov r11b, 0x10");
}
test "lower FD/TD encoding" {
var enc = TestEncode{};
- try enc.encode(.mov, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .mem = Memory.moffs(.cs, 0x10) } });
+ try enc.encode(.mov, &.{
+ .{ .reg = .rax },
+ .{ .mem = Memory.moffs(.cs, 0x10) },
+ });
try expectEqualHexStrings("\x2E\x48\xA1\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs rax, cs:0x10");
- try enc.encode(.mov, .{ .op1 = .{ .reg = .eax }, .op2 = .{ .mem = Memory.moffs(.fs, 0x10) } });
+ try enc.encode(.mov, &.{
+ .{ .reg = .eax },
+ .{ .mem = Memory.moffs(.fs, 0x10) },
+ });
try expectEqualHexStrings("\x64\xA1\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs eax, fs:0x10");
- try enc.encode(.mov, .{ .op1 = .{ .reg = .ax }, .op2 = .{ .mem = Memory.moffs(.gs, 0x10) } });
+ try enc.encode(.mov, &.{
+ .{ .reg = .ax },
+ .{ .mem = Memory.moffs(.gs, 0x10) },
+ });
try expectEqualHexStrings("\x65\x66\xA1\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs ax, gs:0x10");
- try enc.encode(.mov, .{ .op1 = .{ .reg = .al }, .op2 = .{ .mem = Memory.moffs(.ds, 0x10) } });
+ try enc.encode(.mov, &.{
+ .{ .reg = .al },
+ .{ .mem = Memory.moffs(.ds, 0x10) },
+ });
try expectEqualHexStrings("\xA0\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs al, ds:0x10");
- try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.moffs(.cs, 0x10) }, .op2 = .{ .reg = .rax } });
+ try enc.encode(.mov, &.{
+ .{ .mem = Memory.moffs(.cs, 0x10) },
+ .{ .reg = .rax },
+ });
try expectEqualHexStrings("\x2E\x48\xA3\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs cs:0x10, rax");
- try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.moffs(.fs, 0x10) }, .op2 = .{ .reg = .eax } });
+ try enc.encode(.mov, &.{
+ .{ .mem = Memory.moffs(.fs, 0x10) },
+ .{ .reg = .eax },
+ });
try expectEqualHexStrings("\x64\xA3\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs fs:0x10, eax");
- try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.moffs(.gs, 0x10) }, .op2 = .{ .reg = .ax } });
+ try enc.encode(.mov, &.{
+ .{ .mem = Memory.moffs(.gs, 0x10) },
+ .{ .reg = .ax },
+ });
try expectEqualHexStrings("\x65\x66\xA3\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs gs:0x10, ax");
- try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.moffs(.ds, 0x10) }, .op2 = .{ .reg = .al } });
+ try enc.encode(.mov, &.{
+ .{ .mem = Memory.moffs(.ds, 0x10) },
+ .{ .reg = .al },
+ });
try expectEqualHexStrings("\xA2\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs ds:0x10, al");
}
test "lower NP encoding" {
var enc = TestEncode{};
- try enc.encode(.int3, .{});
+ try enc.encode(.int3, &.{});
try expectEqualHexStrings("\xCC", enc.code(), "int3");
- try enc.encode(.nop, .{});
+ try enc.encode(.nop, &.{});
try expectEqualHexStrings("\x90", enc.code(), "nop");
- try enc.encode(.ret, .{});
+ try enc.encode(.ret, &.{});
try expectEqualHexStrings("\xC3", enc.code(), "ret");
- try enc.encode(.syscall, .{});
+ try enc.encode(.syscall, &.{});
try expectEqualHexStrings("\x0f\x05", enc.code(), "syscall");
}
-fn invalidInstruction(mnemonic: Instruction.Mnemonic, args: Instruction.Init) !void {
- const err = Instruction.new(mnemonic, args);
+fn invalidInstruction(mnemonic: Instruction.Mnemonic, ops: []const Instruction.Operand) !void {
+ const err = Instruction.new(.none, mnemonic, ops);
try testing.expectError(error.InvalidInstruction, err);
}
test "invalid instruction" {
- try invalidInstruction(.call, .{ .op1 = .{ .reg = .eax } });
- try invalidInstruction(.call, .{ .op1 = .{ .reg = .ax } });
- try invalidInstruction(.call, .{ .op1 = .{ .reg = .al } });
- try invalidInstruction(.call, .{ .op1 = .{ .mem = Memory.rip(.dword, 0) } });
- try invalidInstruction(.call, .{ .op1 = .{ .mem = Memory.rip(.word, 0) } });
- try invalidInstruction(.call, .{ .op1 = .{ .mem = Memory.rip(.byte, 0) } });
- try invalidInstruction(.mov, .{ .op1 = .{ .mem = Memory.rip(.word, 0x10) }, .op2 = .{ .reg = .r12 } });
- try invalidInstruction(.lea, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .reg = .rbx } });
- try invalidInstruction(.lea, .{ .op1 = .{ .reg = .al }, .op2 = .{ .mem = Memory.rip(.byte, 0) } });
- try invalidInstruction(.pop, .{ .op1 = .{ .reg = .r12b } });
- try invalidInstruction(.pop, .{ .op1 = .{ .reg = .r12d } });
- try invalidInstruction(.push, .{ .op1 = .{ .reg = .r12b } });
- try invalidInstruction(.push, .{ .op1 = .{ .reg = .r12d } });
- try invalidInstruction(.push, .{ .op1 = .{ .imm = Immediate.u(0x1000000000000000) } });
+ try invalidInstruction(.call, &.{
+ .{ .reg = .eax },
+ });
+ try invalidInstruction(.call, &.{
+ .{ .reg = .ax },
+ });
+ try invalidInstruction(.call, &.{
+ .{ .reg = .al },
+ });
+ try invalidInstruction(.call, &.{
+ .{ .mem = Memory.rip(.dword, 0) },
+ });
+ try invalidInstruction(.call, &.{
+ .{ .mem = Memory.rip(.word, 0) },
+ });
+ try invalidInstruction(.call, &.{
+ .{ .mem = Memory.rip(.byte, 0) },
+ });
+ try invalidInstruction(.mov, &.{
+ .{ .mem = Memory.rip(.word, 0x10) },
+ .{ .reg = .r12 },
+ });
+ try invalidInstruction(.lea, &.{
+ .{ .reg = .rax },
+ .{ .reg = .rbx },
+ });
+ try invalidInstruction(.lea, &.{
+ .{ .reg = .al },
+ .{ .mem = Memory.rip(.byte, 0) },
+ });
+ try invalidInstruction(.pop, &.{
+ .{ .reg = .r12b },
+ });
+ try invalidInstruction(.pop, &.{
+ .{ .reg = .r12d },
+ });
+ try invalidInstruction(.push, &.{
+ .{ .reg = .r12b },
+ });
+ try invalidInstruction(.push, &.{
+ .{ .reg = .r12d },
+ });
+ try invalidInstruction(.push, &.{
+ .{ .imm = Immediate.u(0x1000000000000000) },
+ });
}
-fn cannotEncode(mnemonic: Instruction.Mnemonic, args: Instruction.Init) !void {
- try testing.expectError(error.CannotEncode, Instruction.new(mnemonic, args));
+fn cannotEncode(mnemonic: Instruction.Mnemonic, ops: []const Instruction.Operand) !void {
+ try testing.expectError(error.CannotEncode, Instruction.new(.none, mnemonic, ops));
}
test "cannot encode" {
- try cannotEncode(.@"test", .{
- .op1 = .{ .mem = Memory.sib(.byte, .{ .base = .r12 }) },
- .op2 = .{ .reg = .ah },
+ try cannotEncode(.@"test", &.{
+ .{ .mem = Memory.sib(.byte, .{ .base = .r12 }) },
+ .{ .reg = .ah },
});
- try cannotEncode(.@"test", .{
- .op1 = .{ .reg = .r11b },
- .op2 = .{ .reg = .bh },
+ try cannotEncode(.@"test", &.{
+ .{ .reg = .r11b },
+ .{ .reg = .bh },
});
- try cannotEncode(.mov, .{
- .op1 = .{ .reg = .sil },
- .op2 = .{ .reg = .ah },
+ try cannotEncode(.mov, &.{
+ .{ .reg = .sil },
+ .{ .reg = .ah },
});
}
@@ -1645,12 +1809,7 @@ const Assembler = struct {
pub fn assemble(as: *Assembler, writer: anytype) !void {
while (try as.next()) |parsed_inst| {
- const inst = try Instruction.new(parsed_inst.mnemonic, .{
- .op1 = parsed_inst.ops[0],
- .op2 = parsed_inst.ops[1],
- .op3 = parsed_inst.ops[2],
- .op4 = parsed_inst.ops[3],
- });
+ const inst = try Instruction.new(.none, parsed_inst.mnemonic, &parsed_inst.ops);
try inst.encode(writer);
}
}
diff --git a/src/arch/x86_64/encodings.zig b/src/arch/x86_64/encodings.zig
index 9683ef991a..05933b68bb 100644
--- a/src/arch/x86_64/encodings.zig
+++ b/src/arch/x86_64/encodings.zig
@@ -6,869 +6,874 @@ const Mode = Encoding.Mode;
const modrm_ext = u3;
-const Entry = struct { Mnemonic, OpEn, Op, Op, Op, Op, []const u8, modrm_ext, Mode };
+pub const Entry = struct { Mnemonic, OpEn, []const Op, []const u8, modrm_ext, Mode };
// TODO move this into a .zon file when Zig is capable of importing .zon files
// zig fmt: off
-pub const table = &[_]Entry{
+pub const table = [_]Entry{
// General-purpose
- .{ .adc, .zi, .al, .imm8, .none, .none, &.{ 0x14 }, 0, .none },
- .{ .adc, .zi, .ax, .imm16, .none, .none, &.{ 0x15 }, 0, .none },
- .{ .adc, .zi, .eax, .imm32, .none, .none, &.{ 0x15 }, 0, .none },
- .{ .adc, .zi, .rax, .imm32s, .none, .none, &.{ 0x15 }, 0, .long },
- .{ .adc, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 2, .none },
- .{ .adc, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 2, .rex },
- .{ .adc, .mi, .rm16, .imm16, .none, .none, &.{ 0x81 }, 2, .none },
- .{ .adc, .mi, .rm32, .imm32, .none, .none, &.{ 0x81 }, 2, .none },
- .{ .adc, .mi, .rm64, .imm32s, .none, .none, &.{ 0x81 }, 2, .long },
- .{ .adc, .mi, .rm16, .imm8s, .none, .none, &.{ 0x83 }, 2, .none },
- .{ .adc, .mi, .rm32, .imm8s, .none, .none, &.{ 0x83 }, 2, .none },
- .{ .adc, .mi, .rm64, .imm8s, .none, .none, &.{ 0x83 }, 2, .long },
- .{ .adc, .mr, .rm8, .r8, .none, .none, &.{ 0x10 }, 0, .none },
- .{ .adc, .mr, .rm8, .r8, .none, .none, &.{ 0x10 }, 0, .rex },
- .{ .adc, .mr, .rm16, .r16, .none, .none, &.{ 0x11 }, 0, .none },
- .{ .adc, .mr, .rm32, .r32, .none, .none, &.{ 0x11 }, 0, .none },
- .{ .adc, .mr, .rm64, .r64, .none, .none, &.{ 0x11 }, 0, .long },
- .{ .adc, .rm, .r8, .rm8, .none, .none, &.{ 0x12 }, 0, .none },
- .{ .adc, .rm, .r8, .rm8, .none, .none, &.{ 0x12 }, 0, .rex },
- .{ .adc, .rm, .r16, .rm16, .none, .none, &.{ 0x13 }, 0, .none },
- .{ .adc, .rm, .r32, .rm32, .none, .none, &.{ 0x13 }, 0, .none },
- .{ .adc, .rm, .r64, .rm64, .none, .none, &.{ 0x13 }, 0, .long },
-
- .{ .add, .zi, .al, .imm8, .none, .none, &.{ 0x04 }, 0, .none },
- .{ .add, .zi, .ax, .imm16, .none, .none, &.{ 0x05 }, 0, .none },
- .{ .add, .zi, .eax, .imm32, .none, .none, &.{ 0x05 }, 0, .none },
- .{ .add, .zi, .rax, .imm32s, .none, .none, &.{ 0x05 }, 0, .long },
- .{ .add, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 0, .none },
- .{ .add, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 0, .rex },
- .{ .add, .mi, .rm16, .imm16, .none, .none, &.{ 0x81 }, 0, .none },
- .{ .add, .mi, .rm32, .imm32, .none, .none, &.{ 0x81 }, 0, .none },
- .{ .add, .mi, .rm64, .imm32s, .none, .none, &.{ 0x81 }, 0, .long },
- .{ .add, .mi, .rm16, .imm8s, .none, .none, &.{ 0x83 }, 0, .none },
- .{ .add, .mi, .rm32, .imm8s, .none, .none, &.{ 0x83 }, 0, .none },
- .{ .add, .mi, .rm64, .imm8s, .none, .none, &.{ 0x83 }, 0, .long },
- .{ .add, .mr, .rm8, .r8, .none, .none, &.{ 0x00 }, 0, .none },
- .{ .add, .mr, .rm8, .r8, .none, .none, &.{ 0x00 }, 0, .rex },
- .{ .add, .mr, .rm16, .r16, .none, .none, &.{ 0x01 }, 0, .none },
- .{ .add, .mr, .rm32, .r32, .none, .none, &.{ 0x01 }, 0, .none },
- .{ .add, .mr, .rm64, .r64, .none, .none, &.{ 0x01 }, 0, .long },
- .{ .add, .rm, .r8, .rm8, .none, .none, &.{ 0x02 }, 0, .none },
- .{ .add, .rm, .r8, .rm8, .none, .none, &.{ 0x02 }, 0, .rex },
- .{ .add, .rm, .r16, .rm16, .none, .none, &.{ 0x03 }, 0, .none },
- .{ .add, .rm, .r32, .rm32, .none, .none, &.{ 0x03 }, 0, .none },
- .{ .add, .rm, .r64, .rm64, .none, .none, &.{ 0x03 }, 0, .long },
-
- .{ .@"and", .zi, .al, .imm8, .none, .none, &.{ 0x24 }, 0, .none },
- .{ .@"and", .zi, .ax, .imm16, .none, .none, &.{ 0x25 }, 0, .none },
- .{ .@"and", .zi, .eax, .imm32, .none, .none, &.{ 0x25 }, 0, .none },
- .{ .@"and", .zi, .rax, .imm32s, .none, .none, &.{ 0x25 }, 0, .long },
- .{ .@"and", .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 4, .none },
- .{ .@"and", .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 4, .rex },
- .{ .@"and", .mi, .rm16, .imm16, .none, .none, &.{ 0x81 }, 4, .none },
- .{ .@"and", .mi, .rm32, .imm32, .none, .none, &.{ 0x81 }, 4, .none },
- .{ .@"and", .mi, .rm64, .imm32s, .none, .none, &.{ 0x81 }, 4, .long },
- .{ .@"and", .mi, .rm16, .imm8s, .none, .none, &.{ 0x83 }, 4, .none },
- .{ .@"and", .mi, .rm32, .imm8s, .none, .none, &.{ 0x83 }, 4, .none },
- .{ .@"and", .mi, .rm64, .imm8s, .none, .none, &.{ 0x83 }, 4, .long },
- .{ .@"and", .mr, .rm8, .r8, .none, .none, &.{ 0x20 }, 0, .none },
- .{ .@"and", .mr, .rm8, .r8, .none, .none, &.{ 0x20 }, 0, .rex },
- .{ .@"and", .mr, .rm16, .r16, .none, .none, &.{ 0x21 }, 0, .none },
- .{ .@"and", .mr, .rm32, .r32, .none, .none, &.{ 0x21 }, 0, .none },
- .{ .@"and", .mr, .rm64, .r64, .none, .none, &.{ 0x21 }, 0, .long },
- .{ .@"and", .rm, .r8, .rm8, .none, .none, &.{ 0x22 }, 0, .none },
- .{ .@"and", .rm, .r8, .rm8, .none, .none, &.{ 0x22 }, 0, .rex },
- .{ .@"and", .rm, .r16, .rm16, .none, .none, &.{ 0x23 }, 0, .none },
- .{ .@"and", .rm, .r32, .rm32, .none, .none, &.{ 0x23 }, 0, .none },
- .{ .@"and", .rm, .r64, .rm64, .none, .none, &.{ 0x23 }, 0, .long },
-
- .{ .bsf, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0xbc }, 0, .none },
- .{ .bsf, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0xbc }, 0, .none },
- .{ .bsf, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0xbc }, 0, .long },
-
- .{ .bsr, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0xbd }, 0, .none },
- .{ .bsr, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0xbd }, 0, .none },
- .{ .bsr, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0xbd }, 0, .long },
-
- .{ .bswap, .o, .r32, .none, .none, .none, &.{ 0x0f, 0xc8 }, 0, .none },
- .{ .bswap, .o, .r64, .none, .none, .none, &.{ 0x0f, 0xc8 }, 0, .long },
-
- .{ .bt, .mr, .rm16, .r16, .none, .none, &.{ 0x0f, 0xa3 }, 0, .none },
- .{ .bt, .mr, .rm32, .r32, .none, .none, &.{ 0x0f, 0xa3 }, 0, .none },
- .{ .bt, .mr, .rm64, .r64, .none, .none, &.{ 0x0f, 0xa3 }, 0, .long },
- .{ .bt, .mi, .rm16, .imm8, .none, .none, &.{ 0x0f, 0xba }, 4, .none },
- .{ .bt, .mi, .rm32, .imm8, .none, .none, &.{ 0x0f, 0xba }, 4, .none },
- .{ .bt, .mi, .rm64, .imm8, .none, .none, &.{ 0x0f, 0xba }, 4, .long },
-
- .{ .btc, .mr, .rm16, .r16, .none, .none, &.{ 0x0f, 0xbb }, 0, .none },
- .{ .btc, .mr, .rm32, .r32, .none, .none, &.{ 0x0f, 0xbb }, 0, .none },
- .{ .btc, .mr, .rm64, .r64, .none, .none, &.{ 0x0f, 0xbb }, 0, .long },
- .{ .btc, .mi, .rm16, .imm8, .none, .none, &.{ 0x0f, 0xba }, 7, .none },
- .{ .btc, .mi, .rm32, .imm8, .none, .none, &.{ 0x0f, 0xba }, 7, .none },
- .{ .btc, .mi, .rm64, .imm8, .none, .none, &.{ 0x0f, 0xba }, 7, .long },
-
- .{ .btr, .mr, .rm16, .r16, .none, .none, &.{ 0x0f, 0xb3 }, 0, .none },
- .{ .btr, .mr, .rm32, .r32, .none, .none, &.{ 0x0f, 0xb3 }, 0, .none },
- .{ .btr, .mr, .rm64, .r64, .none, .none, &.{ 0x0f, 0xb3 }, 0, .long },
- .{ .btr, .mi, .rm16, .imm8, .none, .none, &.{ 0x0f, 0xba }, 6, .none },
- .{ .btr, .mi, .rm32, .imm8, .none, .none, &.{ 0x0f, 0xba }, 6, .none },
- .{ .btr, .mi, .rm64, .imm8, .none, .none, &.{ 0x0f, 0xba }, 6, .long },
-
- .{ .bts, .mr, .rm16, .r16, .none, .none, &.{ 0x0f, 0xab }, 0, .none },
- .{ .bts, .mr, .rm32, .r32, .none, .none, &.{ 0x0f, 0xab }, 0, .none },
- .{ .bts, .mr, .rm64, .r64, .none, .none, &.{ 0x0f, 0xab }, 0, .long },
- .{ .bts, .mi, .rm16, .imm8, .none, .none, &.{ 0x0f, 0xba }, 5, .none },
- .{ .bts, .mi, .rm32, .imm8, .none, .none, &.{ 0x0f, 0xba }, 5, .none },
- .{ .bts, .mi, .rm64, .imm8, .none, .none, &.{ 0x0f, 0xba }, 5, .long },
+ .{ .adc, .zi, &.{ .al, .imm8 }, &.{ 0x14 }, 0, .none },
+ .{ .adc, .zi, &.{ .ax, .imm16 }, &.{ 0x15 }, 0, .none },
+ .{ .adc, .zi, &.{ .eax, .imm32 }, &.{ 0x15 }, 0, .none },
+ .{ .adc, .zi, &.{ .rax, .imm32s }, &.{ 0x15 }, 0, .long },
+ .{ .adc, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 2, .none },
+ .{ .adc, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 2, .rex },
+ .{ .adc, .mi, &.{ .rm16, .imm16 }, &.{ 0x81 }, 2, .none },
+ .{ .adc, .mi, &.{ .rm32, .imm32 }, &.{ 0x81 }, 2, .none },
+ .{ .adc, .mi, &.{ .rm64, .imm32s }, &.{ 0x81 }, 2, .long },
+ .{ .adc, .mi, &.{ .rm16, .imm8s }, &.{ 0x83 }, 2, .none },
+ .{ .adc, .mi, &.{ .rm32, .imm8s }, &.{ 0x83 }, 2, .none },
+ .{ .adc, .mi, &.{ .rm64, .imm8s }, &.{ 0x83 }, 2, .long },
+ .{ .adc, .mr, &.{ .rm8, .r8 }, &.{ 0x10 }, 0, .none },
+ .{ .adc, .mr, &.{ .rm8, .r8 }, &.{ 0x10 }, 0, .rex },
+ .{ .adc, .mr, &.{ .rm16, .r16 }, &.{ 0x11 }, 0, .none },
+ .{ .adc, .mr, &.{ .rm32, .r32 }, &.{ 0x11 }, 0, .none },
+ .{ .adc, .mr, &.{ .rm64, .r64 }, &.{ 0x11 }, 0, .long },
+ .{ .adc, .rm, &.{ .r8, .rm8 }, &.{ 0x12 }, 0, .none },
+ .{ .adc, .rm, &.{ .r8, .rm8 }, &.{ 0x12 }, 0, .rex },
+ .{ .adc, .rm, &.{ .r16, .rm16 }, &.{ 0x13 }, 0, .none },
+ .{ .adc, .rm, &.{ .r32, .rm32 }, &.{ 0x13 }, 0, .none },
+ .{ .adc, .rm, &.{ .r64, .rm64 }, &.{ 0x13 }, 0, .long },
+
+ .{ .add, .zi, &.{ .al, .imm8 }, &.{ 0x04 }, 0, .none },
+ .{ .add, .zi, &.{ .ax, .imm16 }, &.{ 0x05 }, 0, .none },
+ .{ .add, .zi, &.{ .eax, .imm32 }, &.{ 0x05 }, 0, .none },
+ .{ .add, .zi, &.{ .rax, .imm32s }, &.{ 0x05 }, 0, .long },
+ .{ .add, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 0, .none },
+ .{ .add, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 0, .rex },
+ .{ .add, .mi, &.{ .rm16, .imm16 }, &.{ 0x81 }, 0, .none },
+ .{ .add, .mi, &.{ .rm32, .imm32 }, &.{ 0x81 }, 0, .none },
+ .{ .add, .mi, &.{ .rm64, .imm32s }, &.{ 0x81 }, 0, .long },
+ .{ .add, .mi, &.{ .rm16, .imm8s }, &.{ 0x83 }, 0, .none },
+ .{ .add, .mi, &.{ .rm32, .imm8s }, &.{ 0x83 }, 0, .none },
+ .{ .add, .mi, &.{ .rm64, .imm8s }, &.{ 0x83 }, 0, .long },
+ .{ .add, .mr, &.{ .rm8, .r8 }, &.{ 0x00 }, 0, .none },
+ .{ .add, .mr, &.{ .rm8, .r8 }, &.{ 0x00 }, 0, .rex },
+ .{ .add, .mr, &.{ .rm16, .r16 }, &.{ 0x01 }, 0, .none },
+ .{ .add, .mr, &.{ .rm32, .r32 }, &.{ 0x01 }, 0, .none },
+ .{ .add, .mr, &.{ .rm64, .r64 }, &.{ 0x01 }, 0, .long },
+ .{ .add, .rm, &.{ .r8, .rm8 }, &.{ 0x02 }, 0, .none },
+ .{ .add, .rm, &.{ .r8, .rm8 }, &.{ 0x02 }, 0, .rex },
+ .{ .add, .rm, &.{ .r16, .rm16 }, &.{ 0x03 }, 0, .none },
+ .{ .add, .rm, &.{ .r32, .rm32 }, &.{ 0x03 }, 0, .none },
+ .{ .add, .rm, &.{ .r64, .rm64 }, &.{ 0x03 }, 0, .long },
+
+ .{ .@"and", .zi, &.{ .al, .imm8 }, &.{ 0x24 }, 0, .none },
+ .{ .@"and", .zi, &.{ .ax, .imm16 }, &.{ 0x25 }, 0, .none },
+ .{ .@"and", .zi, &.{ .eax, .imm32 }, &.{ 0x25 }, 0, .none },
+ .{ .@"and", .zi, &.{ .rax, .imm32s }, &.{ 0x25 }, 0, .long },
+ .{ .@"and", .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 4, .none },
+ .{ .@"and", .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 4, .rex },
+ .{ .@"and", .mi, &.{ .rm16, .imm16 }, &.{ 0x81 }, 4, .none },
+ .{ .@"and", .mi, &.{ .rm32, .imm32 }, &.{ 0x81 }, 4, .none },
+ .{ .@"and", .mi, &.{ .rm64, .imm32s }, &.{ 0x81 }, 4, .long },
+ .{ .@"and", .mi, &.{ .rm16, .imm8s }, &.{ 0x83 }, 4, .none },
+ .{ .@"and", .mi, &.{ .rm32, .imm8s }, &.{ 0x83 }, 4, .none },
+ .{ .@"and", .mi, &.{ .rm64, .imm8s }, &.{ 0x83 }, 4, .long },
+ .{ .@"and", .mr, &.{ .rm8, .r8 }, &.{ 0x20 }, 0, .none },
+ .{ .@"and", .mr, &.{ .rm8, .r8 }, &.{ 0x20 }, 0, .rex },
+ .{ .@"and", .mr, &.{ .rm16, .r16 }, &.{ 0x21 }, 0, .none },
+ .{ .@"and", .mr, &.{ .rm32, .r32 }, &.{ 0x21 }, 0, .none },
+ .{ .@"and", .mr, &.{ .rm64, .r64 }, &.{ 0x21 }, 0, .long },
+ .{ .@"and", .rm, &.{ .r8, .rm8 }, &.{ 0x22 }, 0, .none },
+ .{ .@"and", .rm, &.{ .r8, .rm8 }, &.{ 0x22 }, 0, .rex },
+ .{ .@"and", .rm, &.{ .r16, .rm16 }, &.{ 0x23 }, 0, .none },
+ .{ .@"and", .rm, &.{ .r32, .rm32 }, &.{ 0x23 }, 0, .none },
+ .{ .@"and", .rm, &.{ .r64, .rm64 }, &.{ 0x23 }, 0, .long },
+
+ .{ .bsf, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0xbc }, 0, .none },
+ .{ .bsf, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0xbc }, 0, .none },
+ .{ .bsf, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0xbc }, 0, .long },
+
+ .{ .bsr, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0xbd }, 0, .none },
+ .{ .bsr, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0xbd }, 0, .none },
+ .{ .bsr, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0xbd }, 0, .long },
+
+ .{ .bswap, .o, &.{ .r32 }, &.{ 0x0f, 0xc8 }, 0, .none },
+ .{ .bswap, .o, &.{ .r64 }, &.{ 0x0f, 0xc8 }, 0, .long },
+
+ .{ .bt, .mr, &.{ .rm16, .r16 }, &.{ 0x0f, 0xa3 }, 0, .none },
+ .{ .bt, .mr, &.{ .rm32, .r32 }, &.{ 0x0f, 0xa3 }, 0, .none },
+ .{ .bt, .mr, &.{ .rm64, .r64 }, &.{ 0x0f, 0xa3 }, 0, .long },
+ .{ .bt, .mi, &.{ .rm16, .imm8 }, &.{ 0x0f, 0xba }, 4, .none },
+ .{ .bt, .mi, &.{ .rm32, .imm8 }, &.{ 0x0f, 0xba }, 4, .none },
+ .{ .bt, .mi, &.{ .rm64, .imm8 }, &.{ 0x0f, 0xba }, 4, .long },
+
+ .{ .btc, .mr, &.{ .rm16, .r16 }, &.{ 0x0f, 0xbb }, 0, .none },
+ .{ .btc, .mr, &.{ .rm32, .r32 }, &.{ 0x0f, 0xbb }, 0, .none },
+ .{ .btc, .mr, &.{ .rm64, .r64 }, &.{ 0x0f, 0xbb }, 0, .long },
+ .{ .btc, .mi, &.{ .rm16, .imm8 }, &.{ 0x0f, 0xba }, 7, .none },
+ .{ .btc, .mi, &.{ .rm32, .imm8 }, &.{ 0x0f, 0xba }, 7, .none },
+ .{ .btc, .mi, &.{ .rm64, .imm8 }, &.{ 0x0f, 0xba }, 7, .long },
+
+ .{ .btr, .mr, &.{ .rm16, .r16 }, &.{ 0x0f, 0xb3 }, 0, .none },
+ .{ .btr, .mr, &.{ .rm32, .r32 }, &.{ 0x0f, 0xb3 }, 0, .none },
+ .{ .btr, .mr, &.{ .rm64, .r64 }, &.{ 0x0f, 0xb3 }, 0, .long },
+ .{ .btr, .mi, &.{ .rm16, .imm8 }, &.{ 0x0f, 0xba }, 6, .none },
+ .{ .btr, .mi, &.{ .rm32, .imm8 }, &.{ 0x0f, 0xba }, 6, .none },
+ .{ .btr, .mi, &.{ .rm64, .imm8 }, &.{ 0x0f, 0xba }, 6, .long },
+
+ .{ .bts, .mr, &.{ .rm16, .r16 }, &.{ 0x0f, 0xab }, 0, .none },
+ .{ .bts, .mr, &.{ .rm32, .r32 }, &.{ 0x0f, 0xab }, 0, .none },
+ .{ .bts, .mr, &.{ .rm64, .r64 }, &.{ 0x0f, 0xab }, 0, .long },
+ .{ .bts, .mi, &.{ .rm16, .imm8 }, &.{ 0x0f, 0xba }, 5, .none },
+ .{ .bts, .mi, &.{ .rm32, .imm8 }, &.{ 0x0f, 0xba }, 5, .none },
+ .{ .bts, .mi, &.{ .rm64, .imm8 }, &.{ 0x0f, 0xba }, 5, .long },
// This is M encoding according to Intel, but D makes more sense here.
- .{ .call, .d, .rel32, .none, .none, .none, &.{ 0xe8 }, 0, .none },
- .{ .call, .m, .rm64, .none, .none, .none, &.{ 0xff }, 2, .none },
-
- .{ .cbw, .np, .o16, .none, .none, .none, &.{ 0x98 }, 0, .none },
- .{ .cwde, .np, .o32, .none, .none, .none, &.{ 0x98 }, 0, .none },
- .{ .cdqe, .np, .o64, .none, .none, .none, &.{ 0x98 }, 0, .long },
-
- .{ .cwd, .np, .o16, .none, .none, .none, &.{ 0x99 }, 0, .none },
- .{ .cdq, .np, .o32, .none, .none, .none, &.{ 0x99 }, 0, .none },
- .{ .cqo, .np, .o64, .none, .none, .none, &.{ 0x99 }, 0, .long },
-
- .{ .cmova, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x47 }, 0, .none },
- .{ .cmova, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x47 }, 0, .none },
- .{ .cmova, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x47 }, 0, .long },
- .{ .cmovae, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x43 }, 0, .none },
- .{ .cmovae, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x43 }, 0, .none },
- .{ .cmovae, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x43 }, 0, .long },
- .{ .cmovb, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x42 }, 0, .none },
- .{ .cmovb, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x42 }, 0, .none },
- .{ .cmovb, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x42 }, 0, .long },
- .{ .cmovbe, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x46 }, 0, .none },
- .{ .cmovbe, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x46 }, 0, .none },
- .{ .cmovbe, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x46 }, 0, .long },
- .{ .cmovc, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x42 }, 0, .none },
- .{ .cmovc, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x42 }, 0, .none },
- .{ .cmovc, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x42 }, 0, .long },
- .{ .cmove, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x44 }, 0, .none },
- .{ .cmove, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x44 }, 0, .none },
- .{ .cmove, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x44 }, 0, .long },
- .{ .cmovg, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4f }, 0, .none },
- .{ .cmovg, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4f }, 0, .none },
- .{ .cmovg, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4f }, 0, .long },
- .{ .cmovge, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4d }, 0, .none },
- .{ .cmovge, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4d }, 0, .none },
- .{ .cmovge, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4d }, 0, .long },
- .{ .cmovl, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4c }, 0, .none },
- .{ .cmovl, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4c }, 0, .none },
- .{ .cmovl, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4c }, 0, .long },
- .{ .cmovle, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4e }, 0, .none },
- .{ .cmovle, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4e }, 0, .none },
- .{ .cmovle, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4e }, 0, .long },
- .{ .cmovna, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x46 }, 0, .none },
- .{ .cmovna, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x46 }, 0, .none },
- .{ .cmovna, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x46 }, 0, .long },
- .{ .cmovnae, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x42 }, 0, .none },
- .{ .cmovnae, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x42 }, 0, .none },
- .{ .cmovnae, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x42 }, 0, .long },
- .{ .cmovnb, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x43 }, 0, .none },
- .{ .cmovnb, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x43 }, 0, .none },
- .{ .cmovnb, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x43 }, 0, .long },
- .{ .cmovnbe, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x47 }, 0, .none },
- .{ .cmovnbe, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x47 }, 0, .none },
- .{ .cmovnbe, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x47 }, 0, .long },
- .{ .cmovnc, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x43 }, 0, .none },
- .{ .cmovnc, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x43 }, 0, .none },
- .{ .cmovnc, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x43 }, 0, .long },
- .{ .cmovne, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x45 }, 0, .none },
- .{ .cmovne, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x45 }, 0, .none },
- .{ .cmovne, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x45 }, 0, .long },
- .{ .cmovng, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4e }, 0, .none },
- .{ .cmovng, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4e }, 0, .none },
- .{ .cmovng, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4e }, 0, .long },
- .{ .cmovnge, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4c }, 0, .none },
- .{ .cmovnge, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4c }, 0, .none },
- .{ .cmovnge, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4c }, 0, .long },
- .{ .cmovnl, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4d }, 0, .none },
- .{ .cmovnl, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4d }, 0, .none },
- .{ .cmovnl, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4d }, 0, .long },
- .{ .cmovnle, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4f }, 0, .none },
- .{ .cmovnle, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4f }, 0, .none },
- .{ .cmovnle, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4f }, 0, .long },
- .{ .cmovno, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x41 }, 0, .none },
- .{ .cmovno, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x41 }, 0, .none },
- .{ .cmovno, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x41 }, 0, .long },
- .{ .cmovnp, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4b }, 0, .none },
- .{ .cmovnp, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4b }, 0, .none },
- .{ .cmovnp, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4b }, 0, .long },
- .{ .cmovns, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x49 }, 0, .none },
- .{ .cmovns, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x49 }, 0, .none },
- .{ .cmovns, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x49 }, 0, .long },
- .{ .cmovnz, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x45 }, 0, .none },
- .{ .cmovnz, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x45 }, 0, .none },
- .{ .cmovnz, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x45 }, 0, .long },
- .{ .cmovo, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x40 }, 0, .none },
- .{ .cmovo, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x40 }, 0, .none },
- .{ .cmovo, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x40 }, 0, .long },
- .{ .cmovp, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4a }, 0, .none },
- .{ .cmovp, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4a }, 0, .none },
- .{ .cmovp, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4a }, 0, .long },
- .{ .cmovpe, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4a }, 0, .none },
- .{ .cmovpe, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4a }, 0, .none },
- .{ .cmovpe, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4a }, 0, .long },
- .{ .cmovpo, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4b }, 0, .none },
- .{ .cmovpo, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4b }, 0, .none },
- .{ .cmovpo, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4b }, 0, .long },
- .{ .cmovs, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x48 }, 0, .none },
- .{ .cmovs, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x48 }, 0, .none },
- .{ .cmovs, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x48 }, 0, .long },
- .{ .cmovz, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x44 }, 0, .none },
- .{ .cmovz, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x44 }, 0, .none },
- .{ .cmovz, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x44 }, 0, .long },
-
- .{ .cmp, .zi, .al, .imm8, .none, .none, &.{ 0x3c }, 0, .none },
- .{ .cmp, .zi, .ax, .imm16, .none, .none, &.{ 0x3d }, 0, .none },
- .{ .cmp, .zi, .eax, .imm32, .none, .none, &.{ 0x3d }, 0, .none },
- .{ .cmp, .zi, .rax, .imm32s, .none, .none, &.{ 0x3d }, 0, .long },
- .{ .cmp, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 7, .none },
- .{ .cmp, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 7, .rex },
- .{ .cmp, .mi, .rm16, .imm16, .none, .none, &.{ 0x81 }, 7, .none },
- .{ .cmp, .mi, .rm32, .imm32, .none, .none, &.{ 0x81 }, 7, .none },
- .{ .cmp, .mi, .rm64, .imm32s, .none, .none, &.{ 0x81 }, 7, .long },
- .{ .cmp, .mi, .rm16, .imm8s, .none, .none, &.{ 0x83 }, 7, .none },
- .{ .cmp, .mi, .rm32, .imm8s, .none, .none, &.{ 0x83 }, 7, .none },
- .{ .cmp, .mi, .rm64, .imm8s, .none, .none, &.{ 0x83 }, 7, .long },
- .{ .cmp, .mr, .rm8, .r8, .none, .none, &.{ 0x38 }, 0, .none },
- .{ .cmp, .mr, .rm8, .r8, .none, .none, &.{ 0x38 }, 0, .rex },
- .{ .cmp, .mr, .rm16, .r16, .none, .none, &.{ 0x39 }, 0, .none },
- .{ .cmp, .mr, .rm32, .r32, .none, .none, &.{ 0x39 }, 0, .none },
- .{ .cmp, .mr, .rm64, .r64, .none, .none, &.{ 0x39 }, 0, .long },
- .{ .cmp, .rm, .r8, .rm8, .none, .none, &.{ 0x3a }, 0, .none },
- .{ .cmp, .rm, .r8, .rm8, .none, .none, &.{ 0x3a }, 0, .rex },
- .{ .cmp, .rm, .r16, .rm16, .none, .none, &.{ 0x3b }, 0, .none },
- .{ .cmp, .rm, .r32, .rm32, .none, .none, &.{ 0x3b }, 0, .none },
- .{ .cmp, .rm, .r64, .rm64, .none, .none, &.{ 0x3b }, 0, .long },
-
- .{ .cmps, .np, .m8, .m8, .none, .none, &.{ 0xa6 }, 0, .none },
- .{ .cmps, .np, .m16, .m16, .none, .none, &.{ 0xa7 }, 0, .none },
- .{ .cmps, .np, .m32, .m32, .none, .none, &.{ 0xa7 }, 0, .none },
- .{ .cmps, .np, .m64, .m64, .none, .none, &.{ 0xa7 }, 0, .long },
- .{ .cmpsb, .np, .none, .none, .none, .none, &.{ 0xa6 }, 0, .none },
- .{ .cmpsw, .np, .none, .none, .none, .none, &.{ 0xa7 }, 0, .short },
- .{ .cmpsd, .np, .none, .none, .none, .none, &.{ 0xa7 }, 0, .none },
- .{ .cmpsq, .np, .none, .none, .none, .none, &.{ 0xa7 }, 0, .long },
-
- .{ .cmpxchg, .mr, .rm8, .r8, .none, .none, &.{ 0x0f, 0xb0 }, 0, .none },
- .{ .cmpxchg, .mr, .rm8, .r8, .none, .none, &.{ 0x0f, 0xb0 }, 0, .rex },
- .{ .cmpxchg, .mr, .rm16, .r16, .none, .none, &.{ 0x0f, 0xb1 }, 0, .none },
- .{ .cmpxchg, .mr, .rm32, .r32, .none, .none, &.{ 0x0f, 0xb1 }, 0, .none },
- .{ .cmpxchg, .mr, .rm64, .r64, .none, .none, &.{ 0x0f, 0xb1 }, 0, .long },
-
- .{ .cmpxchg8b , .m, .m64, .none, .none, .none, &.{ 0x0f, 0xc7 }, 1, .none },
- .{ .cmpxchg16b, .m, .m128, .none, .none, .none, &.{ 0x0f, 0xc7 }, 1, .long },
-
- .{ .div, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 6, .none },
- .{ .div, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 6, .rex },
- .{ .div, .m, .rm16, .none, .none, .none, &.{ 0xf7 }, 6, .none },
- .{ .div, .m, .rm32, .none, .none, .none, &.{ 0xf7 }, 6, .none },
- .{ .div, .m, .rm64, .none, .none, .none, &.{ 0xf7 }, 6, .long },
-
- .{ .fisttp, .m, .m16, .none, .none, .none, &.{ 0xdf }, 1, .fpu },
- .{ .fisttp, .m, .m32, .none, .none, .none, &.{ 0xdb }, 1, .fpu },
- .{ .fisttp, .m, .m64, .none, .none, .none, &.{ 0xdd }, 1, .fpu },
-
- .{ .fld, .m, .m32, .none, .none, .none, &.{ 0xd9 }, 0, .fpu },
- .{ .fld, .m, .m64, .none, .none, .none, &.{ 0xdd }, 0, .fpu },
- .{ .fld, .m, .m80, .none, .none, .none, &.{ 0xdb }, 5, .fpu },
-
- .{ .idiv, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 7, .none },
- .{ .idiv, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 7, .rex },
- .{ .idiv, .m, .rm16, .none, .none, .none, &.{ 0xf7 }, 7, .none },
- .{ .idiv, .m, .rm32, .none, .none, .none, &.{ 0xf7 }, 7, .none },
- .{ .idiv, .m, .rm64, .none, .none, .none, &.{ 0xf7 }, 7, .long },
-
- .{ .imul, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 5, .none },
- .{ .imul, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 5, .rex },
- .{ .imul, .m, .rm16, .none, .none, .none, &.{ 0xf7 }, 5, .none },
- .{ .imul, .m, .rm32, .none, .none, .none, &.{ 0xf7 }, 5, .none },
- .{ .imul, .m, .rm64, .none, .none, .none, &.{ 0xf7 }, 5, .long },
- .{ .imul, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0xaf }, 0, .none },
- .{ .imul, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0xaf }, 0, .none },
- .{ .imul, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0xaf }, 0, .long },
- .{ .imul, .rmi, .r16, .rm16, .imm8s, .none, &.{ 0x6b }, 0, .none },
- .{ .imul, .rmi, .r32, .rm32, .imm8s, .none, &.{ 0x6b }, 0, .none },
- .{ .imul, .rmi, .r64, .rm64, .imm8s, .none, &.{ 0x6b }, 0, .long },
- .{ .imul, .rmi, .r16, .rm16, .imm16, .none, &.{ 0x69 }, 0, .none },
- .{ .imul, .rmi, .r32, .rm32, .imm32, .none, &.{ 0x69 }, 0, .none },
- .{ .imul, .rmi, .r64, .rm64, .imm32, .none, &.{ 0x69 }, 0, .long },
-
- .{ .int3, .np, .none, .none, .none, .none, &.{ 0xcc }, 0, .none },
-
- .{ .ja, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x87 }, 0, .none },
- .{ .jae, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x83 }, 0, .none },
- .{ .jb, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x82 }, 0, .none },
- .{ .jbe, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x86 }, 0, .none },
- .{ .jc, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x82 }, 0, .none },
- .{ .jrcxz, .d, .rel32, .none, .none, .none, &.{ 0xe3 }, 0, .none },
- .{ .je, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x84 }, 0, .none },
- .{ .jg, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8f }, 0, .none },
- .{ .jge, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8d }, 0, .none },
- .{ .jl, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8c }, 0, .none },
- .{ .jle, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8e }, 0, .none },
- .{ .jna, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x86 }, 0, .none },
- .{ .jnae, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x82 }, 0, .none },
- .{ .jnb, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x83 }, 0, .none },
- .{ .jnbe, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x87 }, 0, .none },
- .{ .jnc, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x83 }, 0, .none },
- .{ .jne, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x85 }, 0, .none },
- .{ .jng, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8e }, 0, .none },
- .{ .jnge, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8c }, 0, .none },
- .{ .jnl, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8d }, 0, .none },
- .{ .jnle, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8f }, 0, .none },
- .{ .jno, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x81 }, 0, .none },
- .{ .jnp, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8b }, 0, .none },
- .{ .jns, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x89 }, 0, .none },
- .{ .jnz, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x85 }, 0, .none },
- .{ .jo, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x80 }, 0, .none },
- .{ .jp, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8a }, 0, .none },
- .{ .jpe, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8a }, 0, .none },
- .{ .jpo, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8b }, 0, .none },
- .{ .js, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x88 }, 0, .none },
- .{ .jz, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x84 }, 0, .none },
-
- .{ .jmp, .d, .rel32, .none, .none, .none, &.{ 0xe9 }, 0, .none },
- .{ .jmp, .m, .rm64, .none, .none, .none, &.{ 0xff }, 4, .none },
-
- .{ .lea, .rm, .r16, .m, .none, .none, &.{ 0x8d }, 0, .none },
- .{ .lea, .rm, .r32, .m, .none, .none, &.{ 0x8d }, 0, .none },
- .{ .lea, .rm, .r64, .m, .none, .none, &.{ 0x8d }, 0, .long },
-
- .{ .lfence, .np, .none, .none, .none, .none, &.{ 0x0f, 0xae, 0xe8 }, 0, .none },
-
- .{ .lods, .np, .m8, .none, .none, .none, &.{ 0xac }, 0, .none },
- .{ .lods, .np, .m16, .none, .none, .none, &.{ 0xad }, 0, .none },
- .{ .lods, .np, .m32, .none, .none, .none, &.{ 0xad }, 0, .none },
- .{ .lods, .np, .m64, .none, .none, .none, &.{ 0xad }, 0, .long },
- .{ .lodsb, .np, .none, .none, .none, .none, &.{ 0xac }, 0, .none },
- .{ .lodsw, .np, .none, .none, .none, .none, &.{ 0xad }, 0, .short },
- .{ .lodsd, .np, .none, .none, .none, .none, &.{ 0xad }, 0, .none },
- .{ .lodsq, .np, .none, .none, .none, .none, &.{ 0xad }, 0, .long },
-
- .{ .lzcnt, .rm, .r16, .rm16, .none, .none, &.{ 0xf3, 0x0f, 0xbd }, 0, .none },
- .{ .lzcnt, .rm, .r32, .rm32, .none, .none, &.{ 0xf3, 0x0f, 0xbd }, 0, .none },
- .{ .lzcnt, .rm, .r64, .rm64, .none, .none, &.{ 0xf3, 0x0f, 0xbd }, 0, .long },
-
- .{ .mfence, .np, .none, .none, .none, .none, &.{ 0x0f, 0xae, 0xf0 }, 0, .none },
-
- .{ .mov, .mr, .rm8, .r8, .none, .none, &.{ 0x88 }, 0, .none },
- .{ .mov, .mr, .rm8, .r8, .none, .none, &.{ 0x88 }, 0, .rex },
- .{ .mov, .mr, .rm16, .r16, .none, .none, &.{ 0x89 }, 0, .none },
- .{ .mov, .mr, .rm32, .r32, .none, .none, &.{ 0x89 }, 0, .none },
- .{ .mov, .mr, .rm64, .r64, .none, .none, &.{ 0x89 }, 0, .long },
- .{ .mov, .rm, .r8, .rm8, .none, .none, &.{ 0x8a }, 0, .none },
- .{ .mov, .rm, .r8, .rm8, .none, .none, &.{ 0x8a }, 0, .rex },
- .{ .mov, .rm, .r16, .rm16, .none, .none, &.{ 0x8b }, 0, .none },
- .{ .mov, .rm, .r32, .rm32, .none, .none, &.{ 0x8b }, 0, .none },
- .{ .mov, .rm, .r64, .rm64, .none, .none, &.{ 0x8b }, 0, .long },
- .{ .mov, .mr, .rm16, .sreg, .none, .none, &.{ 0x8c }, 0, .none },
- .{ .mov, .mr, .rm64, .sreg, .none, .none, &.{ 0x8c }, 0, .long },
- .{ .mov, .rm, .sreg, .rm16, .none, .none, &.{ 0x8e }, 0, .none },
- .{ .mov, .rm, .sreg, .rm64, .none, .none, &.{ 0x8e }, 0, .long },
- .{ .mov, .fd, .al, .moffs, .none, .none, &.{ 0xa0 }, 0, .none },
- .{ .mov, .fd, .ax, .moffs, .none, .none, &.{ 0xa1 }, 0, .none },
- .{ .mov, .fd, .eax, .moffs, .none, .none, &.{ 0xa1 }, 0, .none },
- .{ .mov, .fd, .rax, .moffs, .none, .none, &.{ 0xa1 }, 0, .long },
- .{ .mov, .td, .moffs, .al, .none, .none, &.{ 0xa2 }, 0, .none },
- .{ .mov, .td, .moffs, .ax, .none, .none, &.{ 0xa3 }, 0, .none },
- .{ .mov, .td, .moffs, .eax, .none, .none, &.{ 0xa3 }, 0, .none },
- .{ .mov, .td, .moffs, .rax, .none, .none, &.{ 0xa3 }, 0, .long },
- .{ .mov, .oi, .r8, .imm8, .none, .none, &.{ 0xb0 }, 0, .none },
- .{ .mov, .oi, .r8, .imm8, .none, .none, &.{ 0xb0 }, 0, .rex },
- .{ .mov, .oi, .r16, .imm16, .none, .none, &.{ 0xb8 }, 0, .none },
- .{ .mov, .oi, .r32, .imm32, .none, .none, &.{ 0xb8 }, 0, .none },
- .{ .mov, .oi, .r64, .imm64, .none, .none, &.{ 0xb8 }, 0, .long },
- .{ .mov, .mi, .rm8, .imm8, .none, .none, &.{ 0xc6 }, 0, .none },
- .{ .mov, .mi, .rm8, .imm8, .none, .none, &.{ 0xc6 }, 0, .rex },
- .{ .mov, .mi, .rm16, .imm16, .none, .none, &.{ 0xc7 }, 0, .none },
- .{ .mov, .mi, .rm32, .imm32, .none, .none, &.{ 0xc7 }, 0, .none },
- .{ .mov, .mi, .rm64, .imm32s, .none, .none, &.{ 0xc7 }, 0, .long },
-
- .{ .movbe, .rm, .r16, .m16, .none, .none, &.{ 0x0f, 0x38, 0xf0 }, 0, .none },
- .{ .movbe, .rm, .r32, .m32, .none, .none, &.{ 0x0f, 0x38, 0xf0 }, 0, .none },
- .{ .movbe, .rm, .r64, .m64, .none, .none, &.{ 0x0f, 0x38, 0xf0 }, 0, .long },
- .{ .movbe, .mr, .m16, .r16, .none, .none, &.{ 0x0f, 0x38, 0xf1 }, 0, .none },
- .{ .movbe, .mr, .m32, .r32, .none, .none, &.{ 0x0f, 0x38, 0xf1 }, 0, .none },
- .{ .movbe, .mr, .m64, .r64, .none, .none, &.{ 0x0f, 0x38, 0xf1 }, 0, .long },
-
- .{ .movs, .np, .m8, .m8, .none, .none, &.{ 0xa4 }, 0, .none },
- .{ .movs, .np, .m16, .m16, .none, .none, &.{ 0xa5 }, 0, .none },
- .{ .movs, .np, .m32, .m32, .none, .none, &.{ 0xa5 }, 0, .none },
- .{ .movs, .np, .m64, .m64, .none, .none, &.{ 0xa5 }, 0, .long },
- .{ .movsb, .np, .none, .none, .none, .none, &.{ 0xa4 }, 0, .none },
- .{ .movsw, .np, .none, .none, .none, .none, &.{ 0xa5 }, 0, .short },
- .{ .movsd, .np, .none, .none, .none, .none, &.{ 0xa5 }, 0, .none },
- .{ .movsq, .np, .none, .none, .none, .none, &.{ 0xa5 }, 0, .long },
-
- .{ .movsx, .rm, .r16, .rm8, .none, .none, &.{ 0x0f, 0xbe }, 0, .none },
- .{ .movsx, .rm, .r16, .rm8, .none, .none, &.{ 0x0f, 0xbe }, 0, .rex },
- .{ .movsx, .rm, .r32, .rm8, .none, .none, &.{ 0x0f, 0xbe }, 0, .none },
- .{ .movsx, .rm, .r32, .rm8, .none, .none, &.{ 0x0f, 0xbe }, 0, .rex },
- .{ .movsx, .rm, .r64, .rm8, .none, .none, &.{ 0x0f, 0xbe }, 0, .long },
- .{ .movsx, .rm, .r32, .rm16, .none, .none, &.{ 0x0f, 0xbf }, 0, .none },
- .{ .movsx, .rm, .r64, .rm16, .none, .none, &.{ 0x0f, 0xbf }, 0, .long },
+ .{ .call, .d, &.{ .rel32 }, &.{ 0xe8 }, 0, .none },
+ .{ .call, .m, &.{ .rm64 }, &.{ 0xff }, 2, .none },
+
+ .{ .cbw, .np, &.{ .o16 }, &.{ 0x98 }, 0, .none },
+ .{ .cwde, .np, &.{ .o32 }, &.{ 0x98 }, 0, .none },
+ .{ .cdqe, .np, &.{ .o64 }, &.{ 0x98 }, 0, .long },
+
+ .{ .cwd, .np, &.{ .o16 }, &.{ 0x99 }, 0, .none },
+ .{ .cdq, .np, &.{ .o32 }, &.{ 0x99 }, 0, .none },
+ .{ .cqo, .np, &.{ .o64 }, &.{ 0x99 }, 0, .long },
+
+ .{ .cmova, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x47 }, 0, .none },
+ .{ .cmova, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x47 }, 0, .none },
+ .{ .cmova, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x47 }, 0, .long },
+ .{ .cmovae, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x43 }, 0, .none },
+ .{ .cmovae, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x43 }, 0, .none },
+ .{ .cmovae, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x43 }, 0, .long },
+ .{ .cmovb, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x42 }, 0, .none },
+ .{ .cmovb, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x42 }, 0, .none },
+ .{ .cmovb, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x42 }, 0, .long },
+ .{ .cmovbe, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x46 }, 0, .none },
+ .{ .cmovbe, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x46 }, 0, .none },
+ .{ .cmovbe, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x46 }, 0, .long },
+ .{ .cmovc, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x42 }, 0, .none },
+ .{ .cmovc, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x42 }, 0, .none },
+ .{ .cmovc, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x42 }, 0, .long },
+ .{ .cmove, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x44 }, 0, .none },
+ .{ .cmove, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x44 }, 0, .none },
+ .{ .cmove, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x44 }, 0, .long },
+ .{ .cmovg, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4f }, 0, .none },
+ .{ .cmovg, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4f }, 0, .none },
+ .{ .cmovg, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4f }, 0, .long },
+ .{ .cmovge, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4d }, 0, .none },
+ .{ .cmovge, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4d }, 0, .none },
+ .{ .cmovge, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4d }, 0, .long },
+ .{ .cmovl, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4c }, 0, .none },
+ .{ .cmovl, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4c }, 0, .none },
+ .{ .cmovl, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4c }, 0, .long },
+ .{ .cmovle, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4e }, 0, .none },
+ .{ .cmovle, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4e }, 0, .none },
+ .{ .cmovle, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4e }, 0, .long },
+ .{ .cmovna, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x46 }, 0, .none },
+ .{ .cmovna, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x46 }, 0, .none },
+ .{ .cmovna, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x46 }, 0, .long },
+ .{ .cmovnae, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x42 }, 0, .none },
+ .{ .cmovnae, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x42 }, 0, .none },
+ .{ .cmovnae, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x42 }, 0, .long },
+ .{ .cmovnb, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x43 }, 0, .none },
+ .{ .cmovnb, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x43 }, 0, .none },
+ .{ .cmovnb, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x43 }, 0, .long },
+ .{ .cmovnbe, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x47 }, 0, .none },
+ .{ .cmovnbe, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x47 }, 0, .none },
+ .{ .cmovnbe, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x47 }, 0, .long },
+ .{ .cmovnc, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x43 }, 0, .none },
+ .{ .cmovnc, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x43 }, 0, .none },
+ .{ .cmovnc, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x43 }, 0, .long },
+ .{ .cmovne, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x45 }, 0, .none },
+ .{ .cmovne, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x45 }, 0, .none },
+ .{ .cmovne, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x45 }, 0, .long },
+ .{ .cmovng, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4e }, 0, .none },
+ .{ .cmovng, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4e }, 0, .none },
+ .{ .cmovng, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4e }, 0, .long },
+ .{ .cmovnge, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4c }, 0, .none },
+ .{ .cmovnge, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4c }, 0, .none },
+ .{ .cmovnge, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4c }, 0, .long },
+ .{ .cmovnl, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4d }, 0, .none },
+ .{ .cmovnl, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4d }, 0, .none },
+ .{ .cmovnl, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4d }, 0, .long },
+ .{ .cmovnle, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4f }, 0, .none },
+ .{ .cmovnle, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4f }, 0, .none },
+ .{ .cmovnle, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4f }, 0, .long },
+ .{ .cmovno, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x41 }, 0, .none },
+ .{ .cmovno, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x41 }, 0, .none },
+ .{ .cmovno, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x41 }, 0, .long },
+ .{ .cmovnp, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4b }, 0, .none },
+ .{ .cmovnp, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4b }, 0, .none },
+ .{ .cmovnp, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4b }, 0, .long },
+ .{ .cmovns, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x49 }, 0, .none },
+ .{ .cmovns, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x49 }, 0, .none },
+ .{ .cmovns, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x49 }, 0, .long },
+ .{ .cmovnz, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x45 }, 0, .none },
+ .{ .cmovnz, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x45 }, 0, .none },
+ .{ .cmovnz, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x45 }, 0, .long },
+ .{ .cmovo, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x40 }, 0, .none },
+ .{ .cmovo, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x40 }, 0, .none },
+ .{ .cmovo, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x40 }, 0, .long },
+ .{ .cmovp, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4a }, 0, .none },
+ .{ .cmovp, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4a }, 0, .none },
+ .{ .cmovp, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4a }, 0, .long },
+ .{ .cmovpe, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4a }, 0, .none },
+ .{ .cmovpe, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4a }, 0, .none },
+ .{ .cmovpe, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4a }, 0, .long },
+ .{ .cmovpo, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4b }, 0, .none },
+ .{ .cmovpo, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4b }, 0, .none },
+ .{ .cmovpo, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4b }, 0, .long },
+ .{ .cmovs, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x48 }, 0, .none },
+ .{ .cmovs, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x48 }, 0, .none },
+ .{ .cmovs, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x48 }, 0, .long },
+ .{ .cmovz, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x44 }, 0, .none },
+ .{ .cmovz, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x44 }, 0, .none },
+ .{ .cmovz, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x44 }, 0, .long },
+
+ .{ .cmp, .zi, &.{ .al, .imm8 }, &.{ 0x3c }, 0, .none },
+ .{ .cmp, .zi, &.{ .ax, .imm16 }, &.{ 0x3d }, 0, .none },
+ .{ .cmp, .zi, &.{ .eax, .imm32 }, &.{ 0x3d }, 0, .none },
+ .{ .cmp, .zi, &.{ .rax, .imm32s }, &.{ 0x3d }, 0, .long },
+ .{ .cmp, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 7, .none },
+ .{ .cmp, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 7, .rex },
+ .{ .cmp, .mi, &.{ .rm16, .imm16 }, &.{ 0x81 }, 7, .none },
+ .{ .cmp, .mi, &.{ .rm32, .imm32 }, &.{ 0x81 }, 7, .none },
+ .{ .cmp, .mi, &.{ .rm64, .imm32s }, &.{ 0x81 }, 7, .long },
+ .{ .cmp, .mi, &.{ .rm16, .imm8s }, &.{ 0x83 }, 7, .none },
+ .{ .cmp, .mi, &.{ .rm32, .imm8s }, &.{ 0x83 }, 7, .none },
+ .{ .cmp, .mi, &.{ .rm64, .imm8s }, &.{ 0x83 }, 7, .long },
+ .{ .cmp, .mr, &.{ .rm8, .r8 }, &.{ 0x38 }, 0, .none },
+ .{ .cmp, .mr, &.{ .rm8, .r8 }, &.{ 0x38 }, 0, .rex },
+ .{ .cmp, .mr, &.{ .rm16, .r16 }, &.{ 0x39 }, 0, .none },
+ .{ .cmp, .mr, &.{ .rm32, .r32 }, &.{ 0x39 }, 0, .none },
+ .{ .cmp, .mr, &.{ .rm64, .r64 }, &.{ 0x39 }, 0, .long },
+ .{ .cmp, .rm, &.{ .r8, .rm8 }, &.{ 0x3a }, 0, .none },
+ .{ .cmp, .rm, &.{ .r8, .rm8 }, &.{ 0x3a }, 0, .rex },
+ .{ .cmp, .rm, &.{ .r16, .rm16 }, &.{ 0x3b }, 0, .none },
+ .{ .cmp, .rm, &.{ .r32, .rm32 }, &.{ 0x3b }, 0, .none },
+ .{ .cmp, .rm, &.{ .r64, .rm64 }, &.{ 0x3b }, 0, .long },
+
+ .{ .cmps, .np, &.{ .m8, .m8 }, &.{ 0xa6 }, 0, .none },
+ .{ .cmps, .np, &.{ .m16, .m16 }, &.{ 0xa7 }, 0, .none },
+ .{ .cmps, .np, &.{ .m32, .m32 }, &.{ 0xa7 }, 0, .none },
+ .{ .cmps, .np, &.{ .m64, .m64 }, &.{ 0xa7 }, 0, .long },
+
+ .{ .cmpsb, .np, &.{}, &.{ 0xa6 }, 0, .none },
+ .{ .cmpsw, .np, &.{}, &.{ 0xa7 }, 0, .short },
+ .{ .cmpsd, .np, &.{}, &.{ 0xa7 }, 0, .none },
+ .{ .cmpsq, .np, &.{}, &.{ 0xa7 }, 0, .long },
+
+ .{ .cmpxchg, .mr, &.{ .rm8, .r8 }, &.{ 0x0f, 0xb0 }, 0, .none },
+ .{ .cmpxchg, .mr, &.{ .rm8, .r8 }, &.{ 0x0f, 0xb0 }, 0, .rex },
+ .{ .cmpxchg, .mr, &.{ .rm16, .r16 }, &.{ 0x0f, 0xb1 }, 0, .none },
+ .{ .cmpxchg, .mr, &.{ .rm32, .r32 }, &.{ 0x0f, 0xb1 }, 0, .none },
+ .{ .cmpxchg, .mr, &.{ .rm64, .r64 }, &.{ 0x0f, 0xb1 }, 0, .long },
+
+ .{ .cmpxchg8b , .m, &.{ .m64 }, &.{ 0x0f, 0xc7 }, 1, .none },
+ .{ .cmpxchg16b, .m, &.{ .m128 }, &.{ 0x0f, 0xc7 }, 1, .long },
+
+ .{ .div, .m, &.{ .rm8 }, &.{ 0xf6 }, 6, .none },
+ .{ .div, .m, &.{ .rm8 }, &.{ 0xf6 }, 6, .rex },
+ .{ .div, .m, &.{ .rm16 }, &.{ 0xf7 }, 6, .none },
+ .{ .div, .m, &.{ .rm32 }, &.{ 0xf7 }, 6, .none },
+ .{ .div, .m, &.{ .rm64 }, &.{ 0xf7 }, 6, .long },
+
+ .{ .fisttp, .m, &.{ .m16 }, &.{ 0xdf }, 1, .fpu },
+ .{ .fisttp, .m, &.{ .m32 }, &.{ 0xdb }, 1, .fpu },
+ .{ .fisttp, .m, &.{ .m64 }, &.{ 0xdd }, 1, .fpu },
+
+ .{ .fld, .m, &.{ .m32 }, &.{ 0xd9 }, 0, .fpu },
+ .{ .fld, .m, &.{ .m64 }, &.{ 0xdd }, 0, .fpu },
+ .{ .fld, .m, &.{ .m80 }, &.{ 0xdb }, 5, .fpu },
+
+ .{ .idiv, .m, &.{ .rm8 }, &.{ 0xf6 }, 7, .none },
+ .{ .idiv, .m, &.{ .rm8 }, &.{ 0xf6 }, 7, .rex },
+ .{ .idiv, .m, &.{ .rm16 }, &.{ 0xf7 }, 7, .none },
+ .{ .idiv, .m, &.{ .rm32 }, &.{ 0xf7 }, 7, .none },
+ .{ .idiv, .m, &.{ .rm64 }, &.{ 0xf7 }, 7, .long },
+
+ .{ .imul, .m, &.{ .rm8 }, &.{ 0xf6 }, 5, .none },
+ .{ .imul, .m, &.{ .rm8 }, &.{ 0xf6 }, 5, .rex },
+ .{ .imul, .m, &.{ .rm16, }, &.{ 0xf7 }, 5, .none },
+ .{ .imul, .m, &.{ .rm32, }, &.{ 0xf7 }, 5, .none },
+ .{ .imul, .m, &.{ .rm64, }, &.{ 0xf7 }, 5, .long },
+ .{ .imul, .rm, &.{ .r16, .rm16, }, &.{ 0x0f, 0xaf }, 0, .none },
+ .{ .imul, .rm, &.{ .r32, .rm32, }, &.{ 0x0f, 0xaf }, 0, .none },
+ .{ .imul, .rm, &.{ .r64, .rm64, }, &.{ 0x0f, 0xaf }, 0, .long },
+ .{ .imul, .rmi, &.{ .r16, .rm16, .imm8s }, &.{ 0x6b }, 0, .none },
+ .{ .imul, .rmi, &.{ .r32, .rm32, .imm8s }, &.{ 0x6b }, 0, .none },
+ .{ .imul, .rmi, &.{ .r64, .rm64, .imm8s }, &.{ 0x6b }, 0, .long },
+ .{ .imul, .rmi, &.{ .r16, .rm16, .imm16 }, &.{ 0x69 }, 0, .none },
+ .{ .imul, .rmi, &.{ .r32, .rm32, .imm32 }, &.{ 0x69 }, 0, .none },
+ .{ .imul, .rmi, &.{ .r64, .rm64, .imm32 }, &.{ 0x69 }, 0, .long },
+
+ .{ .int3, .np, &.{}, &.{ 0xcc }, 0, .none },
+
+ .{ .ja, .d, &.{ .rel32 }, &.{ 0x0f, 0x87 }, 0, .none },
+ .{ .jae, .d, &.{ .rel32 }, &.{ 0x0f, 0x83 }, 0, .none },
+ .{ .jb, .d, &.{ .rel32 }, &.{ 0x0f, 0x82 }, 0, .none },
+ .{ .jbe, .d, &.{ .rel32 }, &.{ 0x0f, 0x86 }, 0, .none },
+ .{ .jc, .d, &.{ .rel32 }, &.{ 0x0f, 0x82 }, 0, .none },
+ .{ .jrcxz, .d, &.{ .rel32 }, &.{ 0xe3 }, 0, .none },
+ .{ .je, .d, &.{ .rel32 }, &.{ 0x0f, 0x84 }, 0, .none },
+ .{ .jg, .d, &.{ .rel32 }, &.{ 0x0f, 0x8f }, 0, .none },
+ .{ .jge, .d, &.{ .rel32 }, &.{ 0x0f, 0x8d }, 0, .none },
+ .{ .jl, .d, &.{ .rel32 }, &.{ 0x0f, 0x8c }, 0, .none },
+ .{ .jle, .d, &.{ .rel32 }, &.{ 0x0f, 0x8e }, 0, .none },
+ .{ .jna, .d, &.{ .rel32 }, &.{ 0x0f, 0x86 }, 0, .none },
+ .{ .jnae, .d, &.{ .rel32 }, &.{ 0x0f, 0x82 }, 0, .none },
+ .{ .jnb, .d, &.{ .rel32 }, &.{ 0x0f, 0x83 }, 0, .none },
+ .{ .jnbe, .d, &.{ .rel32 }, &.{ 0x0f, 0x87 }, 0, .none },
+ .{ .jnc, .d, &.{ .rel32 }, &.{ 0x0f, 0x83 }, 0, .none },
+ .{ .jne, .d, &.{ .rel32 }, &.{ 0x0f, 0x85 }, 0, .none },
+ .{ .jng, .d, &.{ .rel32 }, &.{ 0x0f, 0x8e }, 0, .none },
+ .{ .jnge, .d, &.{ .rel32 }, &.{ 0x0f, 0x8c }, 0, .none },
+ .{ .jnl, .d, &.{ .rel32 }, &.{ 0x0f, 0x8d }, 0, .none },
+ .{ .jnle, .d, &.{ .rel32 }, &.{ 0x0f, 0x8f }, 0, .none },
+ .{ .jno, .d, &.{ .rel32 }, &.{ 0x0f, 0x81 }, 0, .none },
+ .{ .jnp, .d, &.{ .rel32 }, &.{ 0x0f, 0x8b }, 0, .none },
+ .{ .jns, .d, &.{ .rel32 }, &.{ 0x0f, 0x89 }, 0, .none },
+ .{ .jnz, .d, &.{ .rel32 }, &.{ 0x0f, 0x85 }, 0, .none },
+ .{ .jo, .d, &.{ .rel32 }, &.{ 0x0f, 0x80 }, 0, .none },
+ .{ .jp, .d, &.{ .rel32 }, &.{ 0x0f, 0x8a }, 0, .none },
+ .{ .jpe, .d, &.{ .rel32 }, &.{ 0x0f, 0x8a }, 0, .none },
+ .{ .jpo, .d, &.{ .rel32 }, &.{ 0x0f, 0x8b }, 0, .none },
+ .{ .js, .d, &.{ .rel32 }, &.{ 0x0f, 0x88 }, 0, .none },
+ .{ .jz, .d, &.{ .rel32 }, &.{ 0x0f, 0x84 }, 0, .none },
+
+ .{ .jmp, .d, &.{ .rel32 }, &.{ 0xe9 }, 0, .none },
+ .{ .jmp, .m, &.{ .rm64 }, &.{ 0xff }, 4, .none },
+
+ .{ .lea, .rm, &.{ .r16, .m }, &.{ 0x8d }, 0, .none },
+ .{ .lea, .rm, &.{ .r32, .m }, &.{ 0x8d }, 0, .none },
+ .{ .lea, .rm, &.{ .r64, .m }, &.{ 0x8d }, 0, .long },
+
+ .{ .lfence, .np, &.{}, &.{ 0x0f, 0xae, 0xe8 }, 0, .none },
+
+ .{ .lods, .np, &.{ .m8 }, &.{ 0xac }, 0, .none },
+ .{ .lods, .np, &.{ .m16 }, &.{ 0xad }, 0, .none },
+ .{ .lods, .np, &.{ .m32 }, &.{ 0xad }, 0, .none },
+ .{ .lods, .np, &.{ .m64 }, &.{ 0xad }, 0, .long },
+
+ .{ .lodsb, .np, &.{}, &.{ 0xac }, 0, .none },
+ .{ .lodsw, .np, &.{}, &.{ 0xad }, 0, .short },
+ .{ .lodsd, .np, &.{}, &.{ 0xad }, 0, .none },
+ .{ .lodsq, .np, &.{}, &.{ 0xad }, 0, .long },
+
+ .{ .lzcnt, .rm, &.{ .r16, .rm16 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .none },
+ .{ .lzcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .none },
+ .{ .lzcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .long },
+
+ .{ .mfence, .np, &.{}, &.{ 0x0f, 0xae, 0xf0 }, 0, .none },
+
+ .{ .mov, .mr, &.{ .rm8, .r8 }, &.{ 0x88 }, 0, .none },
+ .{ .mov, .mr, &.{ .rm8, .r8 }, &.{ 0x88 }, 0, .rex },
+ .{ .mov, .mr, &.{ .rm16, .r16 }, &.{ 0x89 }, 0, .none },
+ .{ .mov, .mr, &.{ .rm32, .r32 }, &.{ 0x89 }, 0, .none },
+ .{ .mov, .mr, &.{ .rm64, .r64 }, &.{ 0x89 }, 0, .long },
+ .{ .mov, .rm, &.{ .r8, .rm8 }, &.{ 0x8a }, 0, .none },
+ .{ .mov, .rm, &.{ .r8, .rm8 }, &.{ 0x8a }, 0, .rex },
+ .{ .mov, .rm, &.{ .r16, .rm16 }, &.{ 0x8b }, 0, .none },
+ .{ .mov, .rm, &.{ .r32, .rm32 }, &.{ 0x8b }, 0, .none },
+ .{ .mov, .rm, &.{ .r64, .rm64 }, &.{ 0x8b }, 0, .long },
+ .{ .mov, .mr, &.{ .rm16, .sreg }, &.{ 0x8c }, 0, .none },
+ .{ .mov, .mr, &.{ .rm64, .sreg }, &.{ 0x8c }, 0, .long },
+ .{ .mov, .rm, &.{ .sreg, .rm16 }, &.{ 0x8e }, 0, .none },
+ .{ .mov, .rm, &.{ .sreg, .rm64 }, &.{ 0x8e }, 0, .long },
+ .{ .mov, .fd, &.{ .al, .moffs }, &.{ 0xa0 }, 0, .none },
+ .{ .mov, .fd, &.{ .ax, .moffs }, &.{ 0xa1 }, 0, .none },
+ .{ .mov, .fd, &.{ .eax, .moffs }, &.{ 0xa1 }, 0, .none },
+ .{ .mov, .fd, &.{ .rax, .moffs }, &.{ 0xa1 }, 0, .long },
+ .{ .mov, .td, &.{ .moffs, .al }, &.{ 0xa2 }, 0, .none },
+ .{ .mov, .td, &.{ .moffs, .ax }, &.{ 0xa3 }, 0, .none },
+ .{ .mov, .td, &.{ .moffs, .eax }, &.{ 0xa3 }, 0, .none },
+ .{ .mov, .td, &.{ .moffs, .rax }, &.{ 0xa3 }, 0, .long },
+ .{ .mov, .oi, &.{ .r8, .imm8 }, &.{ 0xb0 }, 0, .none },
+ .{ .mov, .oi, &.{ .r8, .imm8 }, &.{ 0xb0 }, 0, .rex },
+ .{ .mov, .oi, &.{ .r16, .imm16 }, &.{ 0xb8 }, 0, .none },
+ .{ .mov, .oi, &.{ .r32, .imm32 }, &.{ 0xb8 }, 0, .none },
+ .{ .mov, .oi, &.{ .r64, .imm64 }, &.{ 0xb8 }, 0, .long },
+ .{ .mov, .mi, &.{ .rm8, .imm8 }, &.{ 0xc6 }, 0, .none },
+ .{ .mov, .mi, &.{ .rm8, .imm8 }, &.{ 0xc6 }, 0, .rex },
+ .{ .mov, .mi, &.{ .rm16, .imm16 }, &.{ 0xc7 }, 0, .none },
+ .{ .mov, .mi, &.{ .rm32, .imm32 }, &.{ 0xc7 }, 0, .none },
+ .{ .mov, .mi, &.{ .rm64, .imm32s }, &.{ 0xc7 }, 0, .long },
+
+ .{ .movbe, .rm, &.{ .r16, .m16 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .none },
+ .{ .movbe, .rm, &.{ .r32, .m32 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .none },
+ .{ .movbe, .rm, &.{ .r64, .m64 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .long },
+ .{ .movbe, .mr, &.{ .m16, .r16 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .none },
+ .{ .movbe, .mr, &.{ .m32, .r32 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .none },
+ .{ .movbe, .mr, &.{ .m64, .r64 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .long },
+
+ .{ .movs, .np, &.{ .m8, .m8 }, &.{ 0xa4 }, 0, .none },
+ .{ .movs, .np, &.{ .m16, .m16 }, &.{ 0xa5 }, 0, .none },
+ .{ .movs, .np, &.{ .m32, .m32 }, &.{ 0xa5 }, 0, .none },
+ .{ .movs, .np, &.{ .m64, .m64 }, &.{ 0xa5 }, 0, .long },
+
+ .{ .movsb, .np, &.{}, &.{ 0xa4 }, 0, .none },
+ .{ .movsw, .np, &.{}, &.{ 0xa5 }, 0, .short },
+ .{ .movsd, .np, &.{}, &.{ 0xa5 }, 0, .none },
+ .{ .movsq, .np, &.{}, &.{ 0xa5 }, 0, .long },
+
+ .{ .movsx, .rm, &.{ .r16, .rm8 }, &.{ 0x0f, 0xbe }, 0, .none },
+ .{ .movsx, .rm, &.{ .r16, .rm8 }, &.{ 0x0f, 0xbe }, 0, .rex },
+ .{ .movsx, .rm, &.{ .r32, .rm8 }, &.{ 0x0f, 0xbe }, 0, .none },
+ .{ .movsx, .rm, &.{ .r32, .rm8 }, &.{ 0x0f, 0xbe }, 0, .rex },
+ .{ .movsx, .rm, &.{ .r64, .rm8 }, &.{ 0x0f, 0xbe }, 0, .long },
+ .{ .movsx, .rm, &.{ .r32, .rm16 }, &.{ 0x0f, 0xbf }, 0, .none },
+ .{ .movsx, .rm, &.{ .r64, .rm16 }, &.{ 0x0f, 0xbf }, 0, .long },
// This instruction is discouraged.
- .{ .movsxd, .rm, .r32, .rm32, .none, .none, &.{ 0x63 }, 0, .none },
- .{ .movsxd, .rm, .r64, .rm32, .none, .none, &.{ 0x63 }, 0, .long },
-
- .{ .movzx, .rm, .r16, .rm8, .none, .none, &.{ 0x0f, 0xb6 }, 0, .none },
- .{ .movzx, .rm, .r32, .rm8, .none, .none, &.{ 0x0f, 0xb6 }, 0, .none },
- .{ .movzx, .rm, .r64, .rm8, .none, .none, &.{ 0x0f, 0xb6 }, 0, .long },
- .{ .movzx, .rm, .r32, .rm16, .none, .none, &.{ 0x0f, 0xb7 }, 0, .none },
- .{ .movzx, .rm, .r64, .rm16, .none, .none, &.{ 0x0f, 0xb7 }, 0, .long },
-
- .{ .mul, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 4, .none },
- .{ .mul, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 4, .rex },
- .{ .mul, .m, .rm16, .none, .none, .none, &.{ 0xf7 }, 4, .none },
- .{ .mul, .m, .rm32, .none, .none, .none, &.{ 0xf7 }, 4, .none },
- .{ .mul, .m, .rm64, .none, .none, .none, &.{ 0xf7 }, 4, .long },
-
- .{ .neg, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 3, .none },
- .{ .neg, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 3, .rex },
- .{ .neg, .m, .rm16, .none, .none, .none, &.{ 0xf7 }, 3, .none },
- .{ .neg, .m, .rm32, .none, .none, .none, &.{ 0xf7 }, 3, .none },
- .{ .neg, .m, .rm64, .none, .none, .none, &.{ 0xf7 }, 3, .long },
-
- .{ .nop, .np, .none, .none, .none, .none, &.{ 0x90 }, 0, .none },
-
- .{ .not, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 2, .none },
- .{ .not, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 2, .rex },
- .{ .not, .m, .rm16, .none, .none, .none, &.{ 0xf7 }, 2, .none },
- .{ .not, .m, .rm32, .none, .none, .none, &.{ 0xf7 }, 2, .none },
- .{ .not, .m, .rm64, .none, .none, .none, &.{ 0xf7 }, 2, .long },
-
- .{ .@"or", .zi, .al, .imm8, .none, .none, &.{ 0x0c }, 0, .none },
- .{ .@"or", .zi, .ax, .imm16, .none, .none, &.{ 0x0d }, 0, .none },
- .{ .@"or", .zi, .eax, .imm32, .none, .none, &.{ 0x0d }, 0, .none },
- .{ .@"or", .zi, .rax, .imm32s, .none, .none, &.{ 0x0d }, 0, .long },
- .{ .@"or", .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 1, .none },
- .{ .@"or", .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 1, .rex },
- .{ .@"or", .mi, .rm16, .imm16, .none, .none, &.{ 0x81 }, 1, .none },
- .{ .@"or", .mi, .rm32, .imm32, .none, .none, &.{ 0x81 }, 1, .none },
- .{ .@"or", .mi, .rm64, .imm32s, .none, .none, &.{ 0x81 }, 1, .long },
- .{ .@"or", .mi, .rm16, .imm8s, .none, .none, &.{ 0x83 }, 1, .none },
- .{ .@"or", .mi, .rm32, .imm8s, .none, .none, &.{ 0x83 }, 1, .none },
- .{ .@"or", .mi, .rm64, .imm8s, .none, .none, &.{ 0x83 }, 1, .long },
- .{ .@"or", .mr, .rm8, .r8, .none, .none, &.{ 0x08 }, 0, .none },
- .{ .@"or", .mr, .rm8, .r8, .none, .none, &.{ 0x08 }, 0, .rex },
- .{ .@"or", .mr, .rm16, .r16, .none, .none, &.{ 0x09 }, 0, .none },
- .{ .@"or", .mr, .rm32, .r32, .none, .none, &.{ 0x09 }, 0, .none },
- .{ .@"or", .mr, .rm64, .r64, .none, .none, &.{ 0x09 }, 0, .long },
- .{ .@"or", .rm, .r8, .rm8, .none, .none, &.{ 0x0a }, 0, .none },
- .{ .@"or", .rm, .r8, .rm8, .none, .none, &.{ 0x0a }, 0, .rex },
- .{ .@"or", .rm, .r16, .rm16, .none, .none, &.{ 0x0b }, 0, .none },
- .{ .@"or", .rm, .r32, .rm32, .none, .none, &.{ 0x0b }, 0, .none },
- .{ .@"or", .rm, .r64, .rm64, .none, .none, &.{ 0x0b }, 0, .long },
-
- .{ .pop, .o, .r16, .none, .none, .none, &.{ 0x58 }, 0, .none },
- .{ .pop, .o, .r64, .none, .none, .none, &.{ 0x58 }, 0, .none },
- .{ .pop, .m, .rm16, .none, .none, .none, &.{ 0x8f }, 0, .none },
- .{ .pop, .m, .rm64, .none, .none, .none, &.{ 0x8f }, 0, .none },
-
- .{ .popcnt, .rm, .r16, .rm16, .none, .none, &.{ 0xf3, 0x0f, 0xb8 }, 0, .none },
- .{ .popcnt, .rm, .r32, .rm32, .none, .none, &.{ 0xf3, 0x0f, 0xb8 }, 0, .none },
- .{ .popcnt, .rm, .r64, .rm64, .none, .none, &.{ 0xf3, 0x0f, 0xb8 }, 0, .long },
-
- .{ .push, .o, .r16, .none, .none, .none, &.{ 0x50 }, 0, .none },
- .{ .push, .o, .r64, .none, .none, .none, &.{ 0x50 }, 0, .none },
- .{ .push, .m, .rm16, .none, .none, .none, &.{ 0xff }, 6, .none },
- .{ .push, .m, .rm64, .none, .none, .none, &.{ 0xff }, 6, .none },
- .{ .push, .i, .imm8, .none, .none, .none, &.{ 0x6a }, 0, .none },
- .{ .push, .i, .imm16, .none, .none, .none, &.{ 0x68 }, 0, .none },
- .{ .push, .i, .imm32, .none, .none, .none, &.{ 0x68 }, 0, .none },
-
- .{ .ret, .np, .none, .none, .none, .none, &.{ 0xc3 }, 0, .none },
-
- .{ .rcl, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 2, .none },
- .{ .rcl, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 2, .rex },
- .{ .rcl, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 2, .none },
- .{ .rcl, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 2, .rex },
- .{ .rcl, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 2, .none },
- .{ .rcl, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 2, .rex },
- .{ .rcl, .m1, .rm16, .unity, .none, .none, &.{ 0xd1 }, 2, .none },
- .{ .rcl, .mc, .rm16, .cl, .none, .none, &.{ 0xd3 }, 2, .none },
- .{ .rcl, .mi, .rm16, .imm8, .none, .none, &.{ 0xc1 }, 2, .none },
- .{ .rcl, .m1, .rm32, .unity, .none, .none, &.{ 0xd1 }, 2, .none },
- .{ .rcl, .m1, .rm64, .unity, .none, .none, &.{ 0xd1 }, 2, .long },
- .{ .rcl, .mc, .rm32, .cl, .none, .none, &.{ 0xd3 }, 2, .none },
- .{ .rcl, .mc, .rm64, .cl, .none, .none, &.{ 0xd3 }, 2, .long },
- .{ .rcl, .mi, .rm32, .imm8, .none, .none, &.{ 0xc1 }, 2, .none },
- .{ .rcl, .mi, .rm64, .imm8, .none, .none, &.{ 0xc1 }, 2, .long },
-
- .{ .rcr, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 3, .none },
- .{ .rcr, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 3, .rex },
- .{ .rcr, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 3, .none },
- .{ .rcr, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 3, .rex },
- .{ .rcr, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 3, .none },
- .{ .rcr, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 3, .rex },
- .{ .rcr, .m1, .rm16, .unity, .none, .none, &.{ 0xd1 }, 3, .none },
- .{ .rcr, .mc, .rm16, .cl, .none, .none, &.{ 0xd3 }, 3, .none },
- .{ .rcr, .mi, .rm16, .imm8, .none, .none, &.{ 0xc1 }, 3, .none },
- .{ .rcr, .m1, .rm32, .unity, .none, .none, &.{ 0xd1 }, 3, .none },
- .{ .rcr, .m1, .rm64, .unity, .none, .none, &.{ 0xd1 }, 3, .long },
- .{ .rcr, .mc, .rm32, .cl, .none, .none, &.{ 0xd3 }, 3, .none },
- .{ .rcr, .mc, .rm64, .cl, .none, .none, &.{ 0xd3 }, 3, .long },
- .{ .rcr, .mi, .rm32, .imm8, .none, .none, &.{ 0xc1 }, 3, .none },
- .{ .rcr, .mi, .rm64, .imm8, .none, .none, &.{ 0xc1 }, 3, .long },
-
- .{ .rol, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 0, .none },
- .{ .rol, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 0, .rex },
- .{ .rol, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 0, .none },
- .{ .rol, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 0, .rex },
- .{ .rol, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 0, .none },
- .{ .rol, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 0, .rex },
- .{ .rol, .m1, .rm16, .unity, .none, .none, &.{ 0xd1 }, 0, .none },
- .{ .rol, .mc, .rm16, .cl, .none, .none, &.{ 0xd3 }, 0, .none },
- .{ .rol, .mi, .rm16, .imm8, .none, .none, &.{ 0xc1 }, 0, .none },
- .{ .rol, .m1, .rm32, .unity, .none, .none, &.{ 0xd1 }, 0, .none },
- .{ .rol, .m1, .rm64, .unity, .none, .none, &.{ 0xd1 }, 0, .long },
- .{ .rol, .mc, .rm32, .cl, .none, .none, &.{ 0xd3 }, 0, .none },
- .{ .rol, .mc, .rm64, .cl, .none, .none, &.{ 0xd3 }, 0, .long },
- .{ .rol, .mi, .rm32, .imm8, .none, .none, &.{ 0xc1 }, 0, .none },
- .{ .rol, .mi, .rm64, .imm8, .none, .none, &.{ 0xc1 }, 0, .long },
-
- .{ .ror, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 1, .none },
- .{ .ror, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 1, .rex },
- .{ .ror, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 1, .none },
- .{ .ror, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 1, .rex },
- .{ .ror, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 1, .none },
- .{ .ror, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 1, .rex },
- .{ .ror, .m1, .rm16, .unity, .none, .none, &.{ 0xd1 }, 1, .none },
- .{ .ror, .mc, .rm16, .cl, .none, .none, &.{ 0xd3 }, 1, .none },
- .{ .ror, .mi, .rm16, .imm8, .none, .none, &.{ 0xc1 }, 1, .none },
- .{ .ror, .m1, .rm32, .unity, .none, .none, &.{ 0xd1 }, 1, .none },
- .{ .ror, .m1, .rm64, .unity, .none, .none, &.{ 0xd1 }, 1, .long },
- .{ .ror, .mc, .rm32, .cl, .none, .none, &.{ 0xd3 }, 1, .none },
- .{ .ror, .mc, .rm64, .cl, .none, .none, &.{ 0xd3 }, 1, .long },
- .{ .ror, .mi, .rm32, .imm8, .none, .none, &.{ 0xc1 }, 1, .none },
- .{ .ror, .mi, .rm64, .imm8, .none, .none, &.{ 0xc1 }, 1, .long },
-
- .{ .sal, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 4, .none },
- .{ .sal, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 4, .rex },
- .{ .sal, .m1, .rm16, .unity, .none, .none, &.{ 0xd1 }, 4, .none },
- .{ .sal, .m1, .rm32, .unity, .none, .none, &.{ 0xd1 }, 4, .none },
- .{ .sal, .m1, .rm64, .unity, .none, .none, &.{ 0xd1 }, 4, .long },
- .{ .sal, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 4, .none },
- .{ .sal, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 4, .rex },
- .{ .sal, .mc, .rm16, .cl, .none, .none, &.{ 0xd3 }, 4, .none },
- .{ .sal, .mc, .rm32, .cl, .none, .none, &.{ 0xd3 }, 4, .none },
- .{ .sal, .mc, .rm64, .cl, .none, .none, &.{ 0xd3 }, 4, .long },
- .{ .sal, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 4, .none },
- .{ .sal, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 4, .rex },
- .{ .sal, .mi, .rm16, .imm8, .none, .none, &.{ 0xc1 }, 4, .none },
- .{ .sal, .mi, .rm32, .imm8, .none, .none, &.{ 0xc1 }, 4, .none },
- .{ .sal, .mi, .rm64, .imm8, .none, .none, &.{ 0xc1 }, 4, .long },
-
- .{ .sar, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 7, .none },
- .{ .sar, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 7, .rex },
- .{ .sar, .m1, .rm16, .unity, .none, .none, &.{ 0xd1 }, 7, .none },
- .{ .sar, .m1, .rm32, .unity, .none, .none, &.{ 0xd1 }, 7, .none },
- .{ .sar, .m1, .rm64, .unity, .none, .none, &.{ 0xd1 }, 7, .long },
- .{ .sar, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 7, .none },
- .{ .sar, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 7, .rex },
- .{ .sar, .mc, .rm16, .cl, .none, .none, &.{ 0xd3 }, 7, .none },
- .{ .sar, .mc, .rm32, .cl, .none, .none, &.{ 0xd3 }, 7, .none },
- .{ .sar, .mc, .rm64, .cl, .none, .none, &.{ 0xd3 }, 7, .long },
- .{ .sar, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 7, .none },
- .{ .sar, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 7, .rex },
- .{ .sar, .mi, .rm16, .imm8, .none, .none, &.{ 0xc1 }, 7, .none },
- .{ .sar, .mi, .rm32, .imm8, .none, .none, &.{ 0xc1 }, 7, .none },
- .{ .sar, .mi, .rm64, .imm8, .none, .none, &.{ 0xc1 }, 7, .long },
-
- .{ .sbb, .zi, .al, .imm8, .none, .none, &.{ 0x1c }, 0, .none },
- .{ .sbb, .zi, .ax, .imm16, .none, .none, &.{ 0x1d }, 0, .none },
- .{ .sbb, .zi, .eax, .imm32, .none, .none, &.{ 0x1d }, 0, .none },
- .{ .sbb, .zi, .rax, .imm32s, .none, .none, &.{ 0x1d }, 0, .long },
- .{ .sbb, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 3, .none },
- .{ .sbb, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 3, .rex },
- .{ .sbb, .mi, .rm16, .imm16, .none, .none, &.{ 0x81 }, 3, .none },
- .{ .sbb, .mi, .rm32, .imm32, .none, .none, &.{ 0x81 }, 3, .none },
- .{ .sbb, .mi, .rm64, .imm32s, .none, .none, &.{ 0x81 }, 3, .long },
- .{ .sbb, .mi, .rm16, .imm8s, .none, .none, &.{ 0x83 }, 3, .none },
- .{ .sbb, .mi, .rm32, .imm8s, .none, .none, &.{ 0x83 }, 3, .none },
- .{ .sbb, .mi, .rm64, .imm8s, .none, .none, &.{ 0x83 }, 3, .long },
- .{ .sbb, .mr, .rm8, .r8, .none, .none, &.{ 0x18 }, 0, .none },
- .{ .sbb, .mr, .rm8, .r8, .none, .none, &.{ 0x18 }, 0, .rex },
- .{ .sbb, .mr, .rm16, .r16, .none, .none, &.{ 0x19 }, 0, .none },
- .{ .sbb, .mr, .rm32, .r32, .none, .none, &.{ 0x19 }, 0, .none },
- .{ .sbb, .mr, .rm64, .r64, .none, .none, &.{ 0x19 }, 0, .long },
- .{ .sbb, .rm, .r8, .rm8, .none, .none, &.{ 0x1a }, 0, .none },
- .{ .sbb, .rm, .r8, .rm8, .none, .none, &.{ 0x1a }, 0, .rex },
- .{ .sbb, .rm, .r16, .rm16, .none, .none, &.{ 0x1b }, 0, .none },
- .{ .sbb, .rm, .r32, .rm32, .none, .none, &.{ 0x1b }, 0, .none },
- .{ .sbb, .rm, .r64, .rm64, .none, .none, &.{ 0x1b }, 0, .long },
-
- .{ .scas, .np, .m8, .none, .none, .none, &.{ 0xae }, 0, .none },
- .{ .scas, .np, .m16, .none, .none, .none, &.{ 0xaf }, 0, .none },
- .{ .scas, .np, .m32, .none, .none, .none, &.{ 0xaf }, 0, .none },
- .{ .scas, .np, .m64, .none, .none, .none, &.{ 0xaf }, 0, .long },
- .{ .scasb, .np, .none, .none, .none, .none, &.{ 0xae }, 0, .none },
- .{ .scasw, .np, .none, .none, .none, .none, &.{ 0xaf }, 0, .short },
- .{ .scasd, .np, .none, .none, .none, .none, &.{ 0xaf }, 0, .none },
- .{ .scasq, .np, .none, .none, .none, .none, &.{ 0xaf }, 0, .long },
-
- .{ .seta, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x97 }, 0, .none },
- .{ .seta, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x97 }, 0, .rex },
- .{ .setae, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x93 }, 0, .none },
- .{ .setae, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x93 }, 0, .rex },
- .{ .setb, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x92 }, 0, .none },
- .{ .setb, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x92 }, 0, .rex },
- .{ .setbe, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x96 }, 0, .none },
- .{ .setbe, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x96 }, 0, .rex },
- .{ .setc, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x92 }, 0, .none },
- .{ .setc, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x92 }, 0, .rex },
- .{ .sete, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x94 }, 0, .none },
- .{ .sete, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x94 }, 0, .rex },
- .{ .setg, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9f }, 0, .none },
- .{ .setg, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9f }, 0, .rex },
- .{ .setge, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9d }, 0, .none },
- .{ .setge, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9d }, 0, .rex },
- .{ .setl, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9c }, 0, .none },
- .{ .setl, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9c }, 0, .rex },
- .{ .setle, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9e }, 0, .none },
- .{ .setle, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9e }, 0, .rex },
- .{ .setna, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x96 }, 0, .none },
- .{ .setna, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x96 }, 0, .rex },
- .{ .setnae, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x92 }, 0, .none },
- .{ .setnae, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x92 }, 0, .rex },
- .{ .setnb, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x93 }, 0, .none },
- .{ .setnb, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x93 }, 0, .rex },
- .{ .setnbe, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x97 }, 0, .none },
- .{ .setnbe, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x97 }, 0, .rex },
- .{ .setnc, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x93 }, 0, .none },
- .{ .setnc, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x93 }, 0, .rex },
- .{ .setne, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x95 }, 0, .none },
- .{ .setne, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x95 }, 0, .rex },
- .{ .setng, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9e }, 0, .none },
- .{ .setng, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9e }, 0, .rex },
- .{ .setnge, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9c }, 0, .none },
- .{ .setnge, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9c }, 0, .rex },
- .{ .setnl, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9d }, 0, .none },
- .{ .setnl, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9d }, 0, .rex },
- .{ .setnle, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9f }, 0, .none },
- .{ .setnle, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9f }, 0, .rex },
- .{ .setno, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x91 }, 0, .none },
- .{ .setno, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x91 }, 0, .rex },
- .{ .setnp, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9b }, 0, .none },
- .{ .setnp, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9b }, 0, .rex },
- .{ .setns, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x99 }, 0, .none },
- .{ .setns, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x99 }, 0, .rex },
- .{ .setnz, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x95 }, 0, .none },
- .{ .setnz, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x95 }, 0, .rex },
- .{ .seto, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x90 }, 0, .none },
- .{ .seto, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x90 }, 0, .rex },
- .{ .setp, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9a }, 0, .none },
- .{ .setp, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9a }, 0, .rex },
- .{ .setpe, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9a }, 0, .none },
- .{ .setpe, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9a }, 0, .rex },
- .{ .setpo, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9b }, 0, .none },
- .{ .setpo, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9b }, 0, .rex },
- .{ .sets, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x98 }, 0, .none },
- .{ .sets, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x98 }, 0, .rex },
- .{ .setz, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x94 }, 0, .none },
- .{ .setz, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x94 }, 0, .rex },
-
- .{ .sfence, .np, .none, .none, .none, .none, &.{ 0x0f, 0xae, 0xf8 }, 0, .none },
-
- .{ .shl, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 4, .none },
- .{ .shl, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 4, .rex },
- .{ .shl, .m1, .rm16, .unity, .none, .none, &.{ 0xd1 }, 4, .none },
- .{ .shl, .m1, .rm32, .unity, .none, .none, &.{ 0xd1 }, 4, .none },
- .{ .shl, .m1, .rm64, .unity, .none, .none, &.{ 0xd1 }, 4, .long },
- .{ .shl, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 4, .none },
- .{ .shl, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 4, .rex },
- .{ .shl, .mc, .rm16, .cl, .none, .none, &.{ 0xd3 }, 4, .none },
- .{ .shl, .mc, .rm32, .cl, .none, .none, &.{ 0xd3 }, 4, .none },
- .{ .shl, .mc, .rm64, .cl, .none, .none, &.{ 0xd3 }, 4, .long },
- .{ .shl, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 4, .none },
- .{ .shl, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 4, .rex },
- .{ .shl, .mi, .rm16, .imm8, .none, .none, &.{ 0xc1 }, 4, .none },
- .{ .shl, .mi, .rm32, .imm8, .none, .none, &.{ 0xc1 }, 4, .none },
- .{ .shl, .mi, .rm64, .imm8, .none, .none, &.{ 0xc1 }, 4, .long },
-
- .{ .shld, .mri, .rm16, .r16, .imm8, .none, &.{ 0x0f, 0xa4 }, 0, .none },
- .{ .shld, .mrc, .rm16, .r16, .cl, .none, &.{ 0x0f, 0xa5 }, 0, .none },
- .{ .shld, .mri, .rm32, .r32, .imm8, .none, &.{ 0x0f, 0xa4 }, 0, .none },
- .{ .shld, .mri, .rm64, .r64, .imm8, .none, &.{ 0x0f, 0xa4 }, 0, .long },
- .{ .shld, .mrc, .rm32, .r32, .cl, .none, &.{ 0x0f, 0xa5 }, 0, .none },
- .{ .shld, .mrc, .rm64, .r64, .cl, .none, &.{ 0x0f, 0xa5 }, 0, .long },
-
- .{ .shr, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 5, .none },
- .{ .shr, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 5, .rex },
- .{ .shr, .m1, .rm16, .unity, .none, .none, &.{ 0xd1 }, 5, .none },
- .{ .shr, .m1, .rm32, .unity, .none, .none, &.{ 0xd1 }, 5, .none },
- .{ .shr, .m1, .rm64, .unity, .none, .none, &.{ 0xd1 }, 5, .long },
- .{ .shr, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 5, .none },
- .{ .shr, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 5, .rex },
- .{ .shr, .mc, .rm16, .cl, .none, .none, &.{ 0xd3 }, 5, .none },
- .{ .shr, .mc, .rm32, .cl, .none, .none, &.{ 0xd3 }, 5, .none },
- .{ .shr, .mc, .rm64, .cl, .none, .none, &.{ 0xd3 }, 5, .long },
- .{ .shr, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 5, .none },
- .{ .shr, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 5, .rex },
- .{ .shr, .mi, .rm16, .imm8, .none, .none, &.{ 0xc1 }, 5, .none },
- .{ .shr, .mi, .rm32, .imm8, .none, .none, &.{ 0xc1 }, 5, .none },
- .{ .shr, .mi, .rm64, .imm8, .none, .none, &.{ 0xc1 }, 5, .long },
-
- .{ .shrd, .mri, .rm16, .r16, .imm8, .none, &.{ 0x0f, 0xac }, 0, .none },
- .{ .shrd, .mrc, .rm16, .r16, .cl, .none, &.{ 0x0f, 0xad }, 0, .none },
- .{ .shrd, .mri, .rm32, .r32, .imm8, .none, &.{ 0x0f, 0xac }, 0, .none },
- .{ .shrd, .mri, .rm64, .r64, .imm8, .none, &.{ 0x0f, 0xac }, 0, .long },
- .{ .shrd, .mrc, .rm32, .r32, .cl, .none, &.{ 0x0f, 0xad }, 0, .none },
- .{ .shrd, .mrc, .rm64, .r64, .cl, .none, &.{ 0x0f, 0xad }, 0, .long },
-
- .{ .stos, .np, .m8, .none, .none, .none, &.{ 0xaa }, 0, .none },
- .{ .stos, .np, .m16, .none, .none, .none, &.{ 0xab }, 0, .none },
- .{ .stos, .np, .m32, .none, .none, .none, &.{ 0xab }, 0, .none },
- .{ .stos, .np, .m64, .none, .none, .none, &.{ 0xab }, 0, .long },
- .{ .stosb, .np, .none, .none, .none, .none, &.{ 0xaa }, 0, .none },
- .{ .stosw, .np, .none, .none, .none, .none, &.{ 0xab }, 0, .short },
- .{ .stosd, .np, .none, .none, .none, .none, &.{ 0xab }, 0, .none },
- .{ .stosq, .np, .none, .none, .none, .none, &.{ 0xab }, 0, .long },
-
- .{ .sub, .zi, .al, .imm8, .none, .none, &.{ 0x2c }, 0, .none },
- .{ .sub, .zi, .ax, .imm16, .none, .none, &.{ 0x2d }, 0, .none },
- .{ .sub, .zi, .eax, .imm32, .none, .none, &.{ 0x2d }, 0, .none },
- .{ .sub, .zi, .rax, .imm32s, .none, .none, &.{ 0x2d }, 0, .long },
- .{ .sub, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 5, .none },
- .{ .sub, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 5, .rex },
- .{ .sub, .mi, .rm16, .imm16, .none, .none, &.{ 0x81 }, 5, .none },
- .{ .sub, .mi, .rm32, .imm32, .none, .none, &.{ 0x81 }, 5, .none },
- .{ .sub, .mi, .rm64, .imm32s, .none, .none, &.{ 0x81 }, 5, .long },
- .{ .sub, .mi, .rm16, .imm8s, .none, .none, &.{ 0x83 }, 5, .none },
- .{ .sub, .mi, .rm32, .imm8s, .none, .none, &.{ 0x83 }, 5, .none },
- .{ .sub, .mi, .rm64, .imm8s, .none, .none, &.{ 0x83 }, 5, .long },
- .{ .sub, .mr, .rm8, .r8, .none, .none, &.{ 0x28 }, 0, .none },
- .{ .sub, .mr, .rm8, .r8, .none, .none, &.{ 0x28 }, 0, .rex },
- .{ .sub, .mr, .rm16, .r16, .none, .none, &.{ 0x29 }, 0, .none },
- .{ .sub, .mr, .rm32, .r32, .none, .none, &.{ 0x29 }, 0, .none },
- .{ .sub, .mr, .rm64, .r64, .none, .none, &.{ 0x29 }, 0, .long },
- .{ .sub, .rm, .r8, .rm8, .none, .none, &.{ 0x2a }, 0, .none },
- .{ .sub, .rm, .r8, .rm8, .none, .none, &.{ 0x2a }, 0, .rex },
- .{ .sub, .rm, .r16, .rm16, .none, .none, &.{ 0x2b }, 0, .none },
- .{ .sub, .rm, .r32, .rm32, .none, .none, &.{ 0x2b }, 0, .none },
- .{ .sub, .rm, .r64, .rm64, .none, .none, &.{ 0x2b }, 0, .long },
-
- .{ .syscall, .np, .none, .none, .none, .none, &.{ 0x0f, 0x05 }, 0, .none }
+ .{ .movsxd, .rm, &.{ .r32, .rm32 }, &.{ 0x63 }, 0, .none },
+ .{ .movsxd, .rm, &.{ .r64, .rm32 }, &.{ 0x63 }, 0, .long },
+
+ .{ .movzx, .rm, &.{ .r16, .rm8 }, &.{ 0x0f, 0xb6 }, 0, .none },
+ .{ .movzx, .rm, &.{ .r32, .rm8 }, &.{ 0x0f, 0xb6 }, 0, .none },
+ .{ .movzx, .rm, &.{ .r64, .rm8 }, &.{ 0x0f, 0xb6 }, 0, .long },
+ .{ .movzx, .rm, &.{ .r32, .rm16 }, &.{ 0x0f, 0xb7 }, 0, .none },
+ .{ .movzx, .rm, &.{ .r64, .rm16 }, &.{ 0x0f, 0xb7 }, 0, .long },
+
+ .{ .mul, .m, &.{ .rm8 }, &.{ 0xf6 }, 4, .none },
+ .{ .mul, .m, &.{ .rm8 }, &.{ 0xf6 }, 4, .rex },
+ .{ .mul, .m, &.{ .rm16 }, &.{ 0xf7 }, 4, .none },
+ .{ .mul, .m, &.{ .rm32 }, &.{ 0xf7 }, 4, .none },
+ .{ .mul, .m, &.{ .rm64 }, &.{ 0xf7 }, 4, .long },
+
+ .{ .neg, .m, &.{ .rm8 }, &.{ 0xf6 }, 3, .none },
+ .{ .neg, .m, &.{ .rm8 }, &.{ 0xf6 }, 3, .rex },
+ .{ .neg, .m, &.{ .rm16 }, &.{ 0xf7 }, 3, .none },
+ .{ .neg, .m, &.{ .rm32 }, &.{ 0xf7 }, 3, .none },
+ .{ .neg, .m, &.{ .rm64 }, &.{ 0xf7 }, 3, .long },
+
+ .{ .nop, .np, &.{}, &.{ 0x90 }, 0, .none },
+
+ .{ .not, .m, &.{ .rm8 }, &.{ 0xf6 }, 2, .none },
+ .{ .not, .m, &.{ .rm8 }, &.{ 0xf6 }, 2, .rex },
+ .{ .not, .m, &.{ .rm16 }, &.{ 0xf7 }, 2, .none },
+ .{ .not, .m, &.{ .rm32 }, &.{ 0xf7 }, 2, .none },
+ .{ .not, .m, &.{ .rm64 }, &.{ 0xf7 }, 2, .long },
+
+ .{ .@"or", .zi, &.{ .al, .imm8 }, &.{ 0x0c }, 0, .none },
+ .{ .@"or", .zi, &.{ .ax, .imm16 }, &.{ 0x0d }, 0, .none },
+ .{ .@"or", .zi, &.{ .eax, .imm32 }, &.{ 0x0d }, 0, .none },
+ .{ .@"or", .zi, &.{ .rax, .imm32s }, &.{ 0x0d }, 0, .long },
+ .{ .@"or", .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 1, .none },
+ .{ .@"or", .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 1, .rex },
+ .{ .@"or", .mi, &.{ .rm16, .imm16 }, &.{ 0x81 }, 1, .none },
+ .{ .@"or", .mi, &.{ .rm32, .imm32 }, &.{ 0x81 }, 1, .none },
+ .{ .@"or", .mi, &.{ .rm64, .imm32s }, &.{ 0x81 }, 1, .long },
+ .{ .@"or", .mi, &.{ .rm16, .imm8s }, &.{ 0x83 }, 1, .none },
+ .{ .@"or", .mi, &.{ .rm32, .imm8s }, &.{ 0x83 }, 1, .none },
+ .{ .@"or", .mi, &.{ .rm64, .imm8s }, &.{ 0x83 }, 1, .long },
+ .{ .@"or", .mr, &.{ .rm8, .r8 }, &.{ 0x08 }, 0, .none },
+ .{ .@"or", .mr, &.{ .rm8, .r8 }, &.{ 0x08 }, 0, .rex },
+ .{ .@"or", .mr, &.{ .rm16, .r16 }, &.{ 0x09 }, 0, .none },
+ .{ .@"or", .mr, &.{ .rm32, .r32 }, &.{ 0x09 }, 0, .none },
+ .{ .@"or", .mr, &.{ .rm64, .r64 }, &.{ 0x09 }, 0, .long },
+ .{ .@"or", .rm, &.{ .r8, .rm8 }, &.{ 0x0a }, 0, .none },
+ .{ .@"or", .rm, &.{ .r8, .rm8 }, &.{ 0x0a }, 0, .rex },
+ .{ .@"or", .rm, &.{ .r16, .rm16 }, &.{ 0x0b }, 0, .none },
+ .{ .@"or", .rm, &.{ .r32, .rm32 }, &.{ 0x0b }, 0, .none },
+ .{ .@"or", .rm, &.{ .r64, .rm64 }, &.{ 0x0b }, 0, .long },
+
+ .{ .pop, .o, &.{ .r16 }, &.{ 0x58 }, 0, .none },
+ .{ .pop, .o, &.{ .r64 }, &.{ 0x58 }, 0, .none },
+ .{ .pop, .m, &.{ .rm16 }, &.{ 0x8f }, 0, .none },
+ .{ .pop, .m, &.{ .rm64 }, &.{ 0x8f }, 0, .none },
+
+ .{ .popcnt, .rm, &.{ .r16, .rm16 }, &.{ 0xf3, 0x0f, 0xb8 }, 0, .none },
+ .{ .popcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xb8 }, 0, .none },
+ .{ .popcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xb8 }, 0, .long },
+
+ .{ .push, .o, &.{ .r16 }, &.{ 0x50 }, 0, .none },
+ .{ .push, .o, &.{ .r64 }, &.{ 0x50 }, 0, .none },
+ .{ .push, .m, &.{ .rm16 }, &.{ 0xff }, 6, .none },
+ .{ .push, .m, &.{ .rm64 }, &.{ 0xff }, 6, .none },
+ .{ .push, .i, &.{ .imm8 }, &.{ 0x6a }, 0, .none },
+ .{ .push, .i, &.{ .imm16 }, &.{ 0x68 }, 0, .none },
+ .{ .push, .i, &.{ .imm32 }, &.{ 0x68 }, 0, .none },
+
+ .{ .ret, .np, &.{}, &.{ 0xc3 }, 0, .none },
+
+ .{ .rcl, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 2, .none },
+ .{ .rcl, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 2, .rex },
+ .{ .rcl, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 2, .none },
+ .{ .rcl, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 2, .rex },
+ .{ .rcl, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 2, .none },
+ .{ .rcl, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 2, .rex },
+ .{ .rcl, .m1, &.{ .rm16, .unity }, &.{ 0xd1 }, 2, .none },
+ .{ .rcl, .mc, &.{ .rm16, .cl }, &.{ 0xd3 }, 2, .none },
+ .{ .rcl, .mi, &.{ .rm16, .imm8 }, &.{ 0xc1 }, 2, .none },
+ .{ .rcl, .m1, &.{ .rm32, .unity }, &.{ 0xd1 }, 2, .none },
+ .{ .rcl, .m1, &.{ .rm64, .unity }, &.{ 0xd1 }, 2, .long },
+ .{ .rcl, .mc, &.{ .rm32, .cl }, &.{ 0xd3 }, 2, .none },
+ .{ .rcl, .mc, &.{ .rm64, .cl }, &.{ 0xd3 }, 2, .long },
+ .{ .rcl, .mi, &.{ .rm32, .imm8 }, &.{ 0xc1 }, 2, .none },
+ .{ .rcl, .mi, &.{ .rm64, .imm8 }, &.{ 0xc1 }, 2, .long },
+
+ .{ .rcr, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 3, .none },
+ .{ .rcr, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 3, .rex },
+ .{ .rcr, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 3, .none },
+ .{ .rcr, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 3, .rex },
+ .{ .rcr, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 3, .none },
+ .{ .rcr, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 3, .rex },
+ .{ .rcr, .m1, &.{ .rm16, .unity }, &.{ 0xd1 }, 3, .none },
+ .{ .rcr, .mc, &.{ .rm16, .cl }, &.{ 0xd3 }, 3, .none },
+ .{ .rcr, .mi, &.{ .rm16, .imm8 }, &.{ 0xc1 }, 3, .none },
+ .{ .rcr, .m1, &.{ .rm32, .unity }, &.{ 0xd1 }, 3, .none },
+ .{ .rcr, .m1, &.{ .rm64, .unity }, &.{ 0xd1 }, 3, .long },
+ .{ .rcr, .mc, &.{ .rm32, .cl }, &.{ 0xd3 }, 3, .none },
+ .{ .rcr, .mc, &.{ .rm64, .cl }, &.{ 0xd3 }, 3, .long },
+ .{ .rcr, .mi, &.{ .rm32, .imm8 }, &.{ 0xc1 }, 3, .none },
+ .{ .rcr, .mi, &.{ .rm64, .imm8 }, &.{ 0xc1 }, 3, .long },
+
+ .{ .rol, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 0, .none },
+ .{ .rol, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 0, .rex },
+ .{ .rol, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 0, .none },
+ .{ .rol, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 0, .rex },
+ .{ .rol, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 0, .none },
+ .{ .rol, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 0, .rex },
+ .{ .rol, .m1, &.{ .rm16, .unity }, &.{ 0xd1 }, 0, .none },
+ .{ .rol, .mc, &.{ .rm16, .cl }, &.{ 0xd3 }, 0, .none },
+ .{ .rol, .mi, &.{ .rm16, .imm8 }, &.{ 0xc1 }, 0, .none },
+ .{ .rol, .m1, &.{ .rm32, .unity }, &.{ 0xd1 }, 0, .none },
+ .{ .rol, .m1, &.{ .rm64, .unity }, &.{ 0xd1 }, 0, .long },
+ .{ .rol, .mc, &.{ .rm32, .cl }, &.{ 0xd3 }, 0, .none },
+ .{ .rol, .mc, &.{ .rm64, .cl }, &.{ 0xd3 }, 0, .long },
+ .{ .rol, .mi, &.{ .rm32, .imm8 }, &.{ 0xc1 }, 0, .none },
+ .{ .rol, .mi, &.{ .rm64, .imm8 }, &.{ 0xc1 }, 0, .long },
+
+ .{ .ror, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 1, .none },
+ .{ .ror, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 1, .rex },
+ .{ .ror, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 1, .none },
+ .{ .ror, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 1, .rex },
+ .{ .ror, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 1, .none },
+ .{ .ror, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 1, .rex },
+ .{ .ror, .m1, &.{ .rm16, .unity }, &.{ 0xd1 }, 1, .none },
+ .{ .ror, .mc, &.{ .rm16, .cl }, &.{ 0xd3 }, 1, .none },
+ .{ .ror, .mi, &.{ .rm16, .imm8 }, &.{ 0xc1 }, 1, .none },
+ .{ .ror, .m1, &.{ .rm32, .unity }, &.{ 0xd1 }, 1, .none },
+ .{ .ror, .m1, &.{ .rm64, .unity }, &.{ 0xd1 }, 1, .long },
+ .{ .ror, .mc, &.{ .rm32, .cl }, &.{ 0xd3 }, 1, .none },
+ .{ .ror, .mc, &.{ .rm64, .cl }, &.{ 0xd3 }, 1, .long },
+ .{ .ror, .mi, &.{ .rm32, .imm8 }, &.{ 0xc1 }, 1, .none },
+ .{ .ror, .mi, &.{ .rm64, .imm8 }, &.{ 0xc1 }, 1, .long },
+
+ .{ .sal, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 4, .none },
+ .{ .sal, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 4, .rex },
+ .{ .sal, .m1, &.{ .rm16, .unity }, &.{ 0xd1 }, 4, .none },
+ .{ .sal, .m1, &.{ .rm32, .unity }, &.{ 0xd1 }, 4, .none },
+ .{ .sal, .m1, &.{ .rm64, .unity }, &.{ 0xd1 }, 4, .long },
+ .{ .sal, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 4, .none },
+ .{ .sal, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 4, .rex },
+ .{ .sal, .mc, &.{ .rm16, .cl }, &.{ 0xd3 }, 4, .none },
+ .{ .sal, .mc, &.{ .rm32, .cl }, &.{ 0xd3 }, 4, .none },
+ .{ .sal, .mc, &.{ .rm64, .cl }, &.{ 0xd3 }, 4, .long },
+ .{ .sal, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 4, .none },
+ .{ .sal, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 4, .rex },
+ .{ .sal, .mi, &.{ .rm16, .imm8 }, &.{ 0xc1 }, 4, .none },
+ .{ .sal, .mi, &.{ .rm32, .imm8 }, &.{ 0xc1 }, 4, .none },
+ .{ .sal, .mi, &.{ .rm64, .imm8 }, &.{ 0xc1 }, 4, .long },
+
+ .{ .sar, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 7, .none },
+ .{ .sar, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 7, .rex },
+ .{ .sar, .m1, &.{ .rm16, .unity }, &.{ 0xd1 }, 7, .none },
+ .{ .sar, .m1, &.{ .rm32, .unity }, &.{ 0xd1 }, 7, .none },
+ .{ .sar, .m1, &.{ .rm64, .unity }, &.{ 0xd1 }, 7, .long },
+ .{ .sar, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 7, .none },
+ .{ .sar, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 7, .rex },
+ .{ .sar, .mc, &.{ .rm16, .cl }, &.{ 0xd3 }, 7, .none },
+ .{ .sar, .mc, &.{ .rm32, .cl }, &.{ 0xd3 }, 7, .none },
+ .{ .sar, .mc, &.{ .rm64, .cl }, &.{ 0xd3 }, 7, .long },
+ .{ .sar, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 7, .none },
+ .{ .sar, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 7, .rex },
+ .{ .sar, .mi, &.{ .rm16, .imm8 }, &.{ 0xc1 }, 7, .none },
+ .{ .sar, .mi, &.{ .rm32, .imm8 }, &.{ 0xc1 }, 7, .none },
+ .{ .sar, .mi, &.{ .rm64, .imm8 }, &.{ 0xc1 }, 7, .long },
+
+ .{ .sbb, .zi, &.{ .al, .imm8 }, &.{ 0x1c }, 0, .none },
+ .{ .sbb, .zi, &.{ .ax, .imm16 }, &.{ 0x1d }, 0, .none },
+ .{ .sbb, .zi, &.{ .eax, .imm32 }, &.{ 0x1d }, 0, .none },
+ .{ .sbb, .zi, &.{ .rax, .imm32s }, &.{ 0x1d }, 0, .long },
+ .{ .sbb, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 3, .none },
+ .{ .sbb, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 3, .rex },
+ .{ .sbb, .mi, &.{ .rm16, .imm16 }, &.{ 0x81 }, 3, .none },
+ .{ .sbb, .mi, &.{ .rm32, .imm32 }, &.{ 0x81 }, 3, .none },
+ .{ .sbb, .mi, &.{ .rm64, .imm32s }, &.{ 0x81 }, 3, .long },
+ .{ .sbb, .mi, &.{ .rm16, .imm8s }, &.{ 0x83 }, 3, .none },
+ .{ .sbb, .mi, &.{ .rm32, .imm8s }, &.{ 0x83 }, 3, .none },
+ .{ .sbb, .mi, &.{ .rm64, .imm8s }, &.{ 0x83 }, 3, .long },
+ .{ .sbb, .mr, &.{ .rm8, .r8 }, &.{ 0x18 }, 0, .none },
+ .{ .sbb, .mr, &.{ .rm8, .r8 }, &.{ 0x18 }, 0, .rex },
+ .{ .sbb, .mr, &.{ .rm16, .r16 }, &.{ 0x19 }, 0, .none },
+ .{ .sbb, .mr, &.{ .rm32, .r32 }, &.{ 0x19 }, 0, .none },
+ .{ .sbb, .mr, &.{ .rm64, .r64 }, &.{ 0x19 }, 0, .long },
+ .{ .sbb, .rm, &.{ .r8, .rm8 }, &.{ 0x1a }, 0, .none },
+ .{ .sbb, .rm, &.{ .r8, .rm8 }, &.{ 0x1a }, 0, .rex },
+ .{ .sbb, .rm, &.{ .r16, .rm16 }, &.{ 0x1b }, 0, .none },
+ .{ .sbb, .rm, &.{ .r32, .rm32 }, &.{ 0x1b }, 0, .none },
+ .{ .sbb, .rm, &.{ .r64, .rm64 }, &.{ 0x1b }, 0, .long },
+
+ .{ .scas, .np, &.{ .m8 }, &.{ 0xae }, 0, .none },
+ .{ .scas, .np, &.{ .m16 }, &.{ 0xaf }, 0, .none },
+ .{ .scas, .np, &.{ .m32 }, &.{ 0xaf }, 0, .none },
+ .{ .scas, .np, &.{ .m64 }, &.{ 0xaf }, 0, .long },
+
+ .{ .scasb, .np, &.{}, &.{ 0xae }, 0, .none },
+ .{ .scasw, .np, &.{}, &.{ 0xaf }, 0, .short },
+ .{ .scasd, .np, &.{}, &.{ 0xaf }, 0, .none },
+ .{ .scasq, .np, &.{}, &.{ 0xaf }, 0, .long },
+
+ .{ .seta, .m, &.{ .rm8 }, &.{ 0x0f, 0x97 }, 0, .none },
+ .{ .seta, .m, &.{ .rm8 }, &.{ 0x0f, 0x97 }, 0, .rex },
+ .{ .setae, .m, &.{ .rm8 }, &.{ 0x0f, 0x93 }, 0, .none },
+ .{ .setae, .m, &.{ .rm8 }, &.{ 0x0f, 0x93 }, 0, .rex },
+ .{ .setb, .m, &.{ .rm8 }, &.{ 0x0f, 0x92 }, 0, .none },
+ .{ .setb, .m, &.{ .rm8 }, &.{ 0x0f, 0x92 }, 0, .rex },
+ .{ .setbe, .m, &.{ .rm8 }, &.{ 0x0f, 0x96 }, 0, .none },
+ .{ .setbe, .m, &.{ .rm8 }, &.{ 0x0f, 0x96 }, 0, .rex },
+ .{ .setc, .m, &.{ .rm8 }, &.{ 0x0f, 0x92 }, 0, .none },
+ .{ .setc, .m, &.{ .rm8 }, &.{ 0x0f, 0x92 }, 0, .rex },
+ .{ .sete, .m, &.{ .rm8 }, &.{ 0x0f, 0x94 }, 0, .none },
+ .{ .sete, .m, &.{ .rm8 }, &.{ 0x0f, 0x94 }, 0, .rex },
+ .{ .setg, .m, &.{ .rm8 }, &.{ 0x0f, 0x9f }, 0, .none },
+ .{ .setg, .m, &.{ .rm8 }, &.{ 0x0f, 0x9f }, 0, .rex },
+ .{ .setge, .m, &.{ .rm8 }, &.{ 0x0f, 0x9d }, 0, .none },
+ .{ .setge, .m, &.{ .rm8 }, &.{ 0x0f, 0x9d }, 0, .rex },
+ .{ .setl, .m, &.{ .rm8 }, &.{ 0x0f, 0x9c }, 0, .none },
+ .{ .setl, .m, &.{ .rm8 }, &.{ 0x0f, 0x9c }, 0, .rex },
+ .{ .setle, .m, &.{ .rm8 }, &.{ 0x0f, 0x9e }, 0, .none },
+ .{ .setle, .m, &.{ .rm8 }, &.{ 0x0f, 0x9e }, 0, .rex },
+ .{ .setna, .m, &.{ .rm8 }, &.{ 0x0f, 0x96 }, 0, .none },
+ .{ .setna, .m, &.{ .rm8 }, &.{ 0x0f, 0x96 }, 0, .rex },
+ .{ .setnae, .m, &.{ .rm8 }, &.{ 0x0f, 0x92 }, 0, .none },
+ .{ .setnae, .m, &.{ .rm8 }, &.{ 0x0f, 0x92 }, 0, .rex },
+ .{ .setnb, .m, &.{ .rm8 }, &.{ 0x0f, 0x93 }, 0, .none },
+ .{ .setnb, .m, &.{ .rm8 }, &.{ 0x0f, 0x93 }, 0, .rex },
+ .{ .setnbe, .m, &.{ .rm8 }, &.{ 0x0f, 0x97 }, 0, .none },
+ .{ .setnbe, .m, &.{ .rm8 }, &.{ 0x0f, 0x97 }, 0, .rex },
+ .{ .setnc, .m, &.{ .rm8 }, &.{ 0x0f, 0x93 }, 0, .none },
+ .{ .setnc, .m, &.{ .rm8 }, &.{ 0x0f, 0x93 }, 0, .rex },
+ .{ .setne, .m, &.{ .rm8 }, &.{ 0x0f, 0x95 }, 0, .none },
+ .{ .setne, .m, &.{ .rm8 }, &.{ 0x0f, 0x95 }, 0, .rex },
+ .{ .setng, .m, &.{ .rm8 }, &.{ 0x0f, 0x9e }, 0, .none },
+ .{ .setng, .m, &.{ .rm8 }, &.{ 0x0f, 0x9e }, 0, .rex },
+ .{ .setnge, .m, &.{ .rm8 }, &.{ 0x0f, 0x9c }, 0, .none },
+ .{ .setnge, .m, &.{ .rm8 }, &.{ 0x0f, 0x9c }, 0, .rex },
+ .{ .setnl, .m, &.{ .rm8 }, &.{ 0x0f, 0x9d }, 0, .none },
+ .{ .setnl, .m, &.{ .rm8 }, &.{ 0x0f, 0x9d }, 0, .rex },
+ .{ .setnle, .m, &.{ .rm8 }, &.{ 0x0f, 0x9f }, 0, .none },
+ .{ .setnle, .m, &.{ .rm8 }, &.{ 0x0f, 0x9f }, 0, .rex },
+ .{ .setno, .m, &.{ .rm8 }, &.{ 0x0f, 0x91 }, 0, .none },
+ .{ .setno, .m, &.{ .rm8 }, &.{ 0x0f, 0x91 }, 0, .rex },
+ .{ .setnp, .m, &.{ .rm8 }, &.{ 0x0f, 0x9b }, 0, .none },
+ .{ .setnp, .m, &.{ .rm8 }, &.{ 0x0f, 0x9b }, 0, .rex },
+ .{ .setns, .m, &.{ .rm8 }, &.{ 0x0f, 0x99 }, 0, .none },
+ .{ .setns, .m, &.{ .rm8 }, &.{ 0x0f, 0x99 }, 0, .rex },
+ .{ .setnz, .m, &.{ .rm8 }, &.{ 0x0f, 0x95 }, 0, .none },
+ .{ .setnz, .m, &.{ .rm8 }, &.{ 0x0f, 0x95 }, 0, .rex },
+ .{ .seto, .m, &.{ .rm8 }, &.{ 0x0f, 0x90 }, 0, .none },
+ .{ .seto, .m, &.{ .rm8 }, &.{ 0x0f, 0x90 }, 0, .rex },
+ .{ .setp, .m, &.{ .rm8 }, &.{ 0x0f, 0x9a }, 0, .none },
+ .{ .setp, .m, &.{ .rm8 }, &.{ 0x0f, 0x9a }, 0, .rex },
+ .{ .setpe, .m, &.{ .rm8 }, &.{ 0x0f, 0x9a }, 0, .none },
+ .{ .setpe, .m, &.{ .rm8 }, &.{ 0x0f, 0x9a }, 0, .rex },
+ .{ .setpo, .m, &.{ .rm8 }, &.{ 0x0f, 0x9b }, 0, .none },
+ .{ .setpo, .m, &.{ .rm8 }, &.{ 0x0f, 0x9b }, 0, .rex },
+ .{ .sets, .m, &.{ .rm8 }, &.{ 0x0f, 0x98 }, 0, .none },
+ .{ .sets, .m, &.{ .rm8 }, &.{ 0x0f, 0x98 }, 0, .rex },
+ .{ .setz, .m, &.{ .rm8 }, &.{ 0x0f, 0x94 }, 0, .none },
+ .{ .setz, .m, &.{ .rm8 }, &.{ 0x0f, 0x94 }, 0, .rex },
+
+ .{ .sfence, .np, &.{}, &.{ 0x0f, 0xae, 0xf8 }, 0, .none },
+
+ .{ .shl, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 4, .none },
+ .{ .shl, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 4, .rex },
+ .{ .shl, .m1, &.{ .rm16, .unity }, &.{ 0xd1 }, 4, .none },
+ .{ .shl, .m1, &.{ .rm32, .unity }, &.{ 0xd1 }, 4, .none },
+ .{ .shl, .m1, &.{ .rm64, .unity }, &.{ 0xd1 }, 4, .long },
+ .{ .shl, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 4, .none },
+ .{ .shl, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 4, .rex },
+ .{ .shl, .mc, &.{ .rm16, .cl }, &.{ 0xd3 }, 4, .none },
+ .{ .shl, .mc, &.{ .rm32, .cl }, &.{ 0xd3 }, 4, .none },
+ .{ .shl, .mc, &.{ .rm64, .cl }, &.{ 0xd3 }, 4, .long },
+ .{ .shl, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 4, .none },
+ .{ .shl, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 4, .rex },
+ .{ .shl, .mi, &.{ .rm16, .imm8 }, &.{ 0xc1 }, 4, .none },
+ .{ .shl, .mi, &.{ .rm32, .imm8 }, &.{ 0xc1 }, 4, .none },
+ .{ .shl, .mi, &.{ .rm64, .imm8 }, &.{ 0xc1 }, 4, .long },
+
+ .{ .shld, .mri, &.{ .rm16, .r16, .imm8 }, &.{ 0x0f, 0xa4 }, 0, .none },
+ .{ .shld, .mrc, &.{ .rm16, .r16, .cl }, &.{ 0x0f, 0xa5 }, 0, .none },
+ .{ .shld, .mri, &.{ .rm32, .r32, .imm8 }, &.{ 0x0f, 0xa4 }, 0, .none },
+ .{ .shld, .mri, &.{ .rm64, .r64, .imm8 }, &.{ 0x0f, 0xa4 }, 0, .long },
+ .{ .shld, .mrc, &.{ .rm32, .r32, .cl }, &.{ 0x0f, 0xa5 }, 0, .none },
+ .{ .shld, .mrc, &.{ .rm64, .r64, .cl }, &.{ 0x0f, 0xa5 }, 0, .long },
+
+ .{ .shr, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 5, .none },
+ .{ .shr, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 5, .rex },
+ .{ .shr, .m1, &.{ .rm16, .unity }, &.{ 0xd1 }, 5, .none },
+ .{ .shr, .m1, &.{ .rm32, .unity }, &.{ 0xd1 }, 5, .none },
+ .{ .shr, .m1, &.{ .rm64, .unity }, &.{ 0xd1 }, 5, .long },
+ .{ .shr, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 5, .none },
+ .{ .shr, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 5, .rex },
+ .{ .shr, .mc, &.{ .rm16, .cl }, &.{ 0xd3 }, 5, .none },
+ .{ .shr, .mc, &.{ .rm32, .cl }, &.{ 0xd3 }, 5, .none },
+ .{ .shr, .mc, &.{ .rm64, .cl }, &.{ 0xd3 }, 5, .long },
+ .{ .shr, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 5, .none },
+ .{ .shr, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 5, .rex },
+ .{ .shr, .mi, &.{ .rm16, .imm8 }, &.{ 0xc1 }, 5, .none },
+ .{ .shr, .mi, &.{ .rm32, .imm8 }, &.{ 0xc1 }, 5, .none },
+ .{ .shr, .mi, &.{ .rm64, .imm8 }, &.{ 0xc1 }, 5, .long },
+
+ .{ .shrd, .mri, &.{ .rm16, .r16, .imm8 }, &.{ 0x0f, 0xac }, 0, .none },
+ .{ .shrd, .mrc, &.{ .rm16, .r16, .cl }, &.{ 0x0f, 0xad }, 0, .none },
+ .{ .shrd, .mri, &.{ .rm32, .r32, .imm8 }, &.{ 0x0f, 0xac }, 0, .none },
+ .{ .shrd, .mri, &.{ .rm64, .r64, .imm8 }, &.{ 0x0f, 0xac }, 0, .long },
+ .{ .shrd, .mrc, &.{ .rm32, .r32, .cl }, &.{ 0x0f, 0xad }, 0, .none },
+ .{ .shrd, .mrc, &.{ .rm64, .r64, .cl }, &.{ 0x0f, 0xad }, 0, .long },
+
+ .{ .stos, .np, &.{ .m8 }, &.{ 0xaa }, 0, .none },
+ .{ .stos, .np, &.{ .m16 }, &.{ 0xab }, 0, .none },
+ .{ .stos, .np, &.{ .m32 }, &.{ 0xab }, 0, .none },
+ .{ .stos, .np, &.{ .m64 }, &.{ 0xab }, 0, .long },
+
+ .{ .stosb, .np, &.{}, &.{ 0xaa }, 0, .none },
+ .{ .stosw, .np, &.{}, &.{ 0xab }, 0, .short },
+ .{ .stosd, .np, &.{}, &.{ 0xab }, 0, .none },
+ .{ .stosq, .np, &.{}, &.{ 0xab }, 0, .long },
+
+ .{ .sub, .zi, &.{ .al, .imm8 }, &.{ 0x2c }, 0, .none },
+ .{ .sub, .zi, &.{ .ax, .imm16 }, &.{ 0x2d }, 0, .none },
+ .{ .sub, .zi, &.{ .eax, .imm32 }, &.{ 0x2d }, 0, .none },
+ .{ .sub, .zi, &.{ .rax, .imm32s }, &.{ 0x2d }, 0, .long },
+ .{ .sub, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 5, .none },
+ .{ .sub, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 5, .rex },
+ .{ .sub, .mi, &.{ .rm16, .imm16 }, &.{ 0x81 }, 5, .none },
+ .{ .sub, .mi, &.{ .rm32, .imm32 }, &.{ 0x81 }, 5, .none },
+ .{ .sub, .mi, &.{ .rm64, .imm32s }, &.{ 0x81 }, 5, .long },
+ .{ .sub, .mi, &.{ .rm16, .imm8s }, &.{ 0x83 }, 5, .none },
+ .{ .sub, .mi, &.{ .rm32, .imm8s }, &.{ 0x83 }, 5, .none },
+ .{ .sub, .mi, &.{ .rm64, .imm8s }, &.{ 0x83 }, 5, .long },
+ .{ .sub, .mr, &.{ .rm8, .r8 }, &.{ 0x28 }, 0, .none },
+ .{ .sub, .mr, &.{ .rm8, .r8 }, &.{ 0x28 }, 0, .rex },
+ .{ .sub, .mr, &.{ .rm16, .r16 }, &.{ 0x29 }, 0, .none },
+ .{ .sub, .mr, &.{ .rm32, .r32 }, &.{ 0x29 }, 0, .none },
+ .{ .sub, .mr, &.{ .rm64, .r64 }, &.{ 0x29 }, 0, .long },
+ .{ .sub, .rm, &.{ .r8, .rm8 }, &.{ 0x2a }, 0, .none },
+ .{ .sub, .rm, &.{ .r8, .rm8 }, &.{ 0x2a }, 0, .rex },
+ .{ .sub, .rm, &.{ .r16, .rm16 }, &.{ 0x2b }, 0, .none },
+ .{ .sub, .rm, &.{ .r32, .rm32 }, &.{ 0x2b }, 0, .none },
+ .{ .sub, .rm, &.{ .r64, .rm64 }, &.{ 0x2b }, 0, .long },
+
+ .{ .syscall, .np, &.{}, &.{ 0x0f, 0x05 }, 0, .none }
,
- .{ .@"test", .zi, .al, .imm8, .none, .none, &.{ 0xa8 }, 0, .none },
- .{ .@"test", .zi, .ax, .imm16, .none, .none, &.{ 0xa9 }, 0, .none },
- .{ .@"test", .zi, .eax, .imm32, .none, .none, &.{ 0xa9 }, 0, .none },
- .{ .@"test", .zi, .rax, .imm32s, .none, .none, &.{ 0xa9 }, 0, .long },
- .{ .@"test", .mi, .rm8, .imm8, .none, .none, &.{ 0xf6 }, 0, .none },
- .{ .@"test", .mi, .rm8, .imm8, .none, .none, &.{ 0xf6 }, 0, .rex },
- .{ .@"test", .mi, .rm16, .imm16, .none, .none, &.{ 0xf7 }, 0, .none },
- .{ .@"test", .mi, .rm32, .imm32, .none, .none, &.{ 0xf7 }, 0, .none },
- .{ .@"test", .mi, .rm64, .imm32s, .none, .none, &.{ 0xf7 }, 0, .long },
- .{ .@"test", .mr, .rm8, .r8, .none, .none, &.{ 0x84 }, 0, .none },
- .{ .@"test", .mr, .rm8, .r8, .none, .none, &.{ 0x84 }, 0, .rex },
- .{ .@"test", .mr, .rm16, .r16, .none, .none, &.{ 0x85 }, 0, .none },
- .{ .@"test", .mr, .rm32, .r32, .none, .none, &.{ 0x85 }, 0, .none },
- .{ .@"test", .mr, .rm64, .r64, .none, .none, &.{ 0x85 }, 0, .long },
-
- .{ .tzcnt, .rm, .r16, .rm16, .none, .none, &.{ 0xf3, 0x0f, 0xbc }, 0, .none },
- .{ .tzcnt, .rm, .r32, .rm32, .none, .none, &.{ 0xf3, 0x0f, 0xbc }, 0, .none },
- .{ .tzcnt, .rm, .r64, .rm64, .none, .none, &.{ 0xf3, 0x0f, 0xbc }, 0, .long },
-
- .{ .ud2, .np, .none, .none, .none, .none, &.{ 0x0f, 0x0b }, 0, .none },
-
- .{ .xadd, .mr, .rm8, .r8, .none, .none, &.{ 0x0f, 0xc0 }, 0, .none },
- .{ .xadd, .mr, .rm8, .r8, .none, .none, &.{ 0x0f, 0xc0 }, 0, .rex },
- .{ .xadd, .mr, .rm16, .r16, .none, .none, &.{ 0x0f, 0xc1 }, 0, .none },
- .{ .xadd, .mr, .rm32, .r32, .none, .none, &.{ 0x0f, 0xc1 }, 0, .none },
- .{ .xadd, .mr, .rm64, .r64, .none, .none, &.{ 0x0f, 0xc1 }, 0, .long },
-
- .{ .xchg, .o, .ax, .r16, .none, .none, &.{ 0x90 }, 0, .none },
- .{ .xchg, .o, .r16, .ax, .none, .none, &.{ 0x90 }, 0, .none },
- .{ .xchg, .o, .eax, .r32, .none, .none, &.{ 0x90 }, 0, .none },
- .{ .xchg, .o, .rax, .r64, .none, .none, &.{ 0x90 }, 0, .long },
- .{ .xchg, .o, .r32, .eax, .none, .none, &.{ 0x90 }, 0, .none },
- .{ .xchg, .o, .r64, .rax, .none, .none, &.{ 0x90 }, 0, .long },
- .{ .xchg, .mr, .rm8, .r8, .none, .none, &.{ 0x86 }, 0, .none },
- .{ .xchg, .mr, .rm8, .r8, .none, .none, &.{ 0x86 }, 0, .rex },
- .{ .xchg, .rm, .r8, .rm8, .none, .none, &.{ 0x86 }, 0, .none },
- .{ .xchg, .rm, .r8, .rm8, .none, .none, &.{ 0x86 }, 0, .rex },
- .{ .xchg, .mr, .rm16, .r16, .none, .none, &.{ 0x87 }, 0, .none },
- .{ .xchg, .rm, .r16, .rm16, .none, .none, &.{ 0x87 }, 0, .none },
- .{ .xchg, .mr, .rm32, .r32, .none, .none, &.{ 0x87 }, 0, .none },
- .{ .xchg, .mr, .rm64, .r64, .none, .none, &.{ 0x87 }, 0, .long },
- .{ .xchg, .rm, .r32, .rm32, .none, .none, &.{ 0x87 }, 0, .none },
- .{ .xchg, .rm, .r64, .rm64, .none, .none, &.{ 0x87 }, 0, .long },
-
- .{ .xor, .zi, .al, .imm8, .none, .none, &.{ 0x34 }, 0, .none },
- .{ .xor, .zi, .ax, .imm16, .none, .none, &.{ 0x35 }, 0, .none },
- .{ .xor, .zi, .eax, .imm32, .none, .none, &.{ 0x35 }, 0, .none },
- .{ .xor, .zi, .rax, .imm32s, .none, .none, &.{ 0x35 }, 0, .long },
- .{ .xor, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 6, .none },
- .{ .xor, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 6, .rex },
- .{ .xor, .mi, .rm16, .imm16, .none, .none, &.{ 0x81 }, 6, .none },
- .{ .xor, .mi, .rm32, .imm32, .none, .none, &.{ 0x81 }, 6, .none },
- .{ .xor, .mi, .rm64, .imm32s, .none, .none, &.{ 0x81 }, 6, .long },
- .{ .xor, .mi, .rm16, .imm8s, .none, .none, &.{ 0x83 }, 6, .none },
- .{ .xor, .mi, .rm32, .imm8s, .none, .none, &.{ 0x83 }, 6, .none },
- .{ .xor, .mi, .rm64, .imm8s, .none, .none, &.{ 0x83 }, 6, .long },
- .{ .xor, .mr, .rm8, .r8, .none, .none, &.{ 0x30 }, 0, .none },
- .{ .xor, .mr, .rm8, .r8, .none, .none, &.{ 0x30 }, 0, .rex },
- .{ .xor, .mr, .rm16, .r16, .none, .none, &.{ 0x31 }, 0, .none },
- .{ .xor, .mr, .rm32, .r32, .none, .none, &.{ 0x31 }, 0, .none },
- .{ .xor, .mr, .rm64, .r64, .none, .none, &.{ 0x31 }, 0, .long },
- .{ .xor, .rm, .r8, .rm8, .none, .none, &.{ 0x32 }, 0, .none },
- .{ .xor, .rm, .r8, .rm8, .none, .none, &.{ 0x32 }, 0, .rex },
- .{ .xor, .rm, .r16, .rm16, .none, .none, &.{ 0x33 }, 0, .none },
- .{ .xor, .rm, .r32, .rm32, .none, .none, &.{ 0x33 }, 0, .none },
- .{ .xor, .rm, .r64, .rm64, .none, .none, &.{ 0x33 }, 0, .long },
+ .{ .@"test", .zi, &.{ .al, .imm8 }, &.{ 0xa8 }, 0, .none },
+ .{ .@"test", .zi, &.{ .ax, .imm16 }, &.{ 0xa9 }, 0, .none },
+ .{ .@"test", .zi, &.{ .eax, .imm32 }, &.{ 0xa9 }, 0, .none },
+ .{ .@"test", .zi, &.{ .rax, .imm32s }, &.{ 0xa9 }, 0, .long },
+ .{ .@"test", .mi, &.{ .rm8, .imm8 }, &.{ 0xf6 }, 0, .none },
+ .{ .@"test", .mi, &.{ .rm8, .imm8 }, &.{ 0xf6 }, 0, .rex },
+ .{ .@"test", .mi, &.{ .rm16, .imm16 }, &.{ 0xf7 }, 0, .none },
+ .{ .@"test", .mi, &.{ .rm32, .imm32 }, &.{ 0xf7 }, 0, .none },
+ .{ .@"test", .mi, &.{ .rm64, .imm32s }, &.{ 0xf7 }, 0, .long },
+ .{ .@"test", .mr, &.{ .rm8, .r8 }, &.{ 0x84 }, 0, .none },
+ .{ .@"test", .mr, &.{ .rm8, .r8 }, &.{ 0x84 }, 0, .rex },
+ .{ .@"test", .mr, &.{ .rm16, .r16 }, &.{ 0x85 }, 0, .none },
+ .{ .@"test", .mr, &.{ .rm32, .r32 }, &.{ 0x85 }, 0, .none },
+ .{ .@"test", .mr, &.{ .rm64, .r64 }, &.{ 0x85 }, 0, .long },
+
+ .{ .tzcnt, .rm, &.{ .r16, .rm16 }, &.{ 0xf3, 0x0f, 0xbc }, 0, .none },
+ .{ .tzcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xbc }, 0, .none },
+ .{ .tzcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xbc }, 0, .long },
+
+ .{ .ud2, .np, &.{}, &.{ 0x0f, 0x0b }, 0, .none },
+
+ .{ .xadd, .mr, &.{ .rm8, .r8 }, &.{ 0x0f, 0xc0 }, 0, .none },
+ .{ .xadd, .mr, &.{ .rm8, .r8 }, &.{ 0x0f, 0xc0 }, 0, .rex },
+ .{ .xadd, .mr, &.{ .rm16, .r16 }, &.{ 0x0f, 0xc1 }, 0, .none },
+ .{ .xadd, .mr, &.{ .rm32, .r32 }, &.{ 0x0f, 0xc1 }, 0, .none },
+ .{ .xadd, .mr, &.{ .rm64, .r64 }, &.{ 0x0f, 0xc1 }, 0, .long },
+
+ .{ .xchg, .o, &.{ .ax, .r16 }, &.{ 0x90 }, 0, .none },
+ .{ .xchg, .o, &.{ .r16, .ax }, &.{ 0x90 }, 0, .none },
+ .{ .xchg, .o, &.{ .eax, .r32 }, &.{ 0x90 }, 0, .none },
+ .{ .xchg, .o, &.{ .rax, .r64 }, &.{ 0x90 }, 0, .long },
+ .{ .xchg, .o, &.{ .r32, .eax }, &.{ 0x90 }, 0, .none },
+ .{ .xchg, .o, &.{ .r64, .rax }, &.{ 0x90 }, 0, .long },
+ .{ .xchg, .mr, &.{ .rm8, .r8 }, &.{ 0x86 }, 0, .none },
+ .{ .xchg, .mr, &.{ .rm8, .r8 }, &.{ 0x86 }, 0, .rex },
+ .{ .xchg, .rm, &.{ .r8, .rm8 }, &.{ 0x86 }, 0, .none },
+ .{ .xchg, .rm, &.{ .r8, .rm8 }, &.{ 0x86 }, 0, .rex },
+ .{ .xchg, .mr, &.{ .rm16, .r16 }, &.{ 0x87 }, 0, .none },
+ .{ .xchg, .rm, &.{ .r16, .rm16 }, &.{ 0x87 }, 0, .none },
+ .{ .xchg, .mr, &.{ .rm32, .r32 }, &.{ 0x87 }, 0, .none },
+ .{ .xchg, .mr, &.{ .rm64, .r64 }, &.{ 0x87 }, 0, .long },
+ .{ .xchg, .rm, &.{ .r32, .rm32 }, &.{ 0x87 }, 0, .none },
+ .{ .xchg, .rm, &.{ .r64, .rm64 }, &.{ 0x87 }, 0, .long },
+
+ .{ .xor, .zi, &.{ .al, .imm8 }, &.{ 0x34 }, 0, .none },
+ .{ .xor, .zi, &.{ .ax, .imm16 }, &.{ 0x35 }, 0, .none },
+ .{ .xor, .zi, &.{ .eax, .imm32 }, &.{ 0x35 }, 0, .none },
+ .{ .xor, .zi, &.{ .rax, .imm32s }, &.{ 0x35 }, 0, .long },
+ .{ .xor, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 6, .none },
+ .{ .xor, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 6, .rex },
+ .{ .xor, .mi, &.{ .rm16, .imm16 }, &.{ 0x81 }, 6, .none },
+ .{ .xor, .mi, &.{ .rm32, .imm32 }, &.{ 0x81 }, 6, .none },
+ .{ .xor, .mi, &.{ .rm64, .imm32s }, &.{ 0x81 }, 6, .long },
+ .{ .xor, .mi, &.{ .rm16, .imm8s }, &.{ 0x83 }, 6, .none },
+ .{ .xor, .mi, &.{ .rm32, .imm8s }, &.{ 0x83 }, 6, .none },
+ .{ .xor, .mi, &.{ .rm64, .imm8s }, &.{ 0x83 }, 6, .long },
+ .{ .xor, .mr, &.{ .rm8, .r8 }, &.{ 0x30 }, 0, .none },
+ .{ .xor, .mr, &.{ .rm8, .r8 }, &.{ 0x30 }, 0, .rex },
+ .{ .xor, .mr, &.{ .rm16, .r16 }, &.{ 0x31 }, 0, .none },
+ .{ .xor, .mr, &.{ .rm32, .r32 }, &.{ 0x31 }, 0, .none },
+ .{ .xor, .mr, &.{ .rm64, .r64 }, &.{ 0x31 }, 0, .long },
+ .{ .xor, .rm, &.{ .r8, .rm8 }, &.{ 0x32 }, 0, .none },
+ .{ .xor, .rm, &.{ .r8, .rm8 }, &.{ 0x32 }, 0, .rex },
+ .{ .xor, .rm, &.{ .r16, .rm16 }, &.{ 0x33 }, 0, .none },
+ .{ .xor, .rm, &.{ .r32, .rm32 }, &.{ 0x33 }, 0, .none },
+ .{ .xor, .rm, &.{ .r64, .rm64 }, &.{ 0x33 }, 0, .long },
// SSE
- .{ .addss, .rm, .xmm, .xmm_m32, .none, .none, &.{ 0xf3, 0x0f, 0x58 }, 0, .sse },
+ .{ .addss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x58 }, 0, .sse },
- .{ .cmpss, .rmi, .xmm, .xmm_m32, .imm8, .none, &.{ 0xf3, 0x0f, 0xc2 }, 0, .sse },
+ .{ .cmpss, .rmi, &.{ .xmm, .xmm_m32, .imm8 }, &.{ 0xf3, 0x0f, 0xc2 }, 0, .sse },
- .{ .divss, .rm, .xmm, .xmm_m32, .none, .none, &.{ 0xf3, 0x0f, 0x5e }, 0, .sse },
+ .{ .divss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5e }, 0, .sse },
- .{ .maxss, .rm, .xmm, .xmm_m32, .none, .none, &.{ 0xf3, 0x0f, 0x5f }, 0, .sse },
+ .{ .maxss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5f }, 0, .sse },
- .{ .minss, .rm, .xmm, .xmm_m32, .none, .none, &.{ 0xf3, 0x0f, 0x5d }, 0, .sse },
+ .{ .minss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5d }, 0, .sse },
- .{ .movss, .rm, .xmm, .xmm_m32, .none, .none, &.{ 0xf3, 0x0f, 0x10 }, 0, .sse },
- .{ .movss, .mr, .xmm_m32, .xmm, .none, .none, &.{ 0xf3, 0x0f, 0x11 }, 0, .sse },
+ .{ .movss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x10 }, 0, .sse },
+ .{ .movss, .mr, &.{ .xmm_m32, .xmm }, &.{ 0xf3, 0x0f, 0x11 }, 0, .sse },
- .{ .mulss, .rm, .xmm, .xmm_m32, .none, .none, &.{ 0xf3, 0x0f, 0x59 }, 0, .sse },
+ .{ .mulss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x59 }, 0, .sse },
- .{ .subss, .rm, .xmm, .xmm_m32, .none, .none, &.{ 0xf3, 0x0f, 0x5c }, 0, .sse },
+ .{ .subss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5c }, 0, .sse },
- .{ .ucomiss, .rm, .xmm, .xmm_m32, .none, .none, &.{ 0x0f, 0x2e }, 0, .sse },
+ .{ .ucomiss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0x0f, 0x2e }, 0, .sse },
// SSE2
- .{ .addsd, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0xf2, 0x0f, 0x58 }, 0, .sse2 },
+ .{ .addsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x58 }, 0, .sse2 },
- .{ .cmpsd, .rmi, .xmm, .xmm_m64, .imm8, .none, &.{ 0xf2, 0x0f, 0xc2 }, 0, .sse2 },
+ .{ .cmpsd, .rmi, &.{ .xmm, .xmm_m64, .imm8 }, &.{ 0xf2, 0x0f, 0xc2 }, 0, .sse2 },
- .{ .divsd, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0xf2, 0x0f, 0x5e }, 0, .sse2 },
+ .{ .divsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5e }, 0, .sse2 },
- .{ .maxsd, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0xf2, 0x0f, 0x5f }, 0, .sse2 },
+ .{ .maxsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5f }, 0, .sse2 },
- .{ .minsd, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0xf2, 0x0f, 0x5d }, 0, .sse2 },
+ .{ .minsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5d }, 0, .sse2 },
- .{ .movq, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0xf3, 0x0f, 0x7e }, 0, .sse2 },
- .{ .movq, .mr, .xmm_m64, .xmm, .none, .none, &.{ 0x66, 0x0f, 0xd6 }, 0, .sse2 },
+ .{ .movq, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf3, 0x0f, 0x7e }, 0, .sse2 },
+ .{ .movq, .mr, &.{ .xmm_m64, .xmm }, &.{ 0x66, 0x0f, 0xd6 }, 0, .sse2 },
- .{ .mulsd, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0xf2, 0x0f, 0x59 }, 0, .sse2 },
+ .{ .mulsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x59 }, 0, .sse2 },
- .{ .subsd, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0xf2, 0x0f, 0x5c }, 0, .sse2 },
+ .{ .subsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5c }, 0, .sse2 },
- .{ .movsd, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0xf2, 0x0f, 0x10 }, 0, .sse2 },
- .{ .movsd, .mr, .xmm_m64, .xmm, .none, .none, &.{ 0xf2, 0x0f, 0x11 }, 0, .sse2 },
+ .{ .movsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x10 }, 0, .sse2 },
+ .{ .movsd, .mr, &.{ .xmm_m64, .xmm }, &.{ 0xf2, 0x0f, 0x11 }, 0, .sse2 },
- .{ .ucomisd, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0x66, 0x0f, 0x2e }, 0, .sse2 },
+ .{ .ucomisd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0x66, 0x0f, 0x2e }, 0, .sse2 },
// SSE4.1
- .{ .roundss, .rmi, .xmm, .xmm_m32, .imm8, .none, &.{ 0x66, 0x0f, 0x3a, 0x0a }, 0, .sse4_1 },
- .{ .roundsd, .rmi, .xmm, .xmm_m64, .imm8, .none, &.{ 0x66, 0x0f, 0x3a, 0x0b }, 0, .sse4_1 },
+ .{ .roundss, .rmi, &.{ .xmm, .xmm_m32, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0a }, 0, .sse4_1 },
+ .{ .roundsd, .rmi, &.{ .xmm, .xmm_m64, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0b }, 0, .sse4_1 },
};
// zig fmt: on