| author | |
| committer | |
| log | abb37a7cb8d4bfae2da6d2cb9e9e6305ef6e52c4 |
| tree | fb30cd3257f76d7026d1fd930c8157b959b50e38 |
| parent | 0e5e001278465e508130eb159327e6aa11895f1c |
8 files changed, 2167 insertions(+), 2127 deletions(-)
src/arch/x86_64/CodeGen.zig+9-12| ... | @@ -341,19 +341,22 @@ pub fn generate( | ... | @@ -341,19 +341,22 @@ pub fn generate( |
| 341 | defer mir.deinit(bin_file.allocator); | 341 | defer mir.deinit(bin_file.allocator); |
| 342 | 342 | ||
| 343 | var emit = Emit{ | 343 | var emit = Emit{ |
| 344 | .mir = mir, | 344 | .lower = .{ |
| 345 | .allocator = bin_file.allocator, | ||
| 346 | .mir = mir, | ||
| 347 | .target = &bin_file.options.target, | ||
| 348 | .src_loc = src_loc, | ||
| 349 | }, | ||
| 345 | .bin_file = bin_file, | 350 | .bin_file = bin_file, |
| 346 | .debug_output = debug_output, | 351 | .debug_output = debug_output, |
| 347 | .target = &bin_file.options.target, | ||
| 348 | .src_loc = src_loc, | ||
| 349 | .code = code, | 352 | .code = code, |
| 350 | .prev_di_pc = 0, | 353 | .prev_di_pc = 0, |
| 351 | .prev_di_line = module_fn.lbrace_line, | 354 | .prev_di_line = module_fn.lbrace_line, |
| 352 | .prev_di_column = module_fn.lbrace_column, | 355 | .prev_di_column = module_fn.lbrace_column, |
| 353 | }; | 356 | }; |
| 354 | defer emit.deinit(); | 357 | defer emit.deinit(); |
| 355 | emit.lowerMir() catch |err| switch (err) { | 358 | emit.emitMir() catch |err| switch (err) { |
| 356 | error.EmitFail => return Result{ .fail = emit.err_msg.? }, | 359 | error.LowerFail, error.EmitFail => return Result{ .fail = emit.lower.err_msg.? }, |
| 357 | error.InvalidInstruction, error.CannotEncode => |e| { | 360 | error.InvalidInstruction, error.CannotEncode => |e| { |
| 358 | const msg = switch (e) { | 361 | const msg = switch (e) { |
| 359 | error.InvalidInstruction => "CodeGen failed to find a viable instruction.", | 362 | 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 | ... | @@ -7070,16 +7073,10 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 7070 | if (reg.to64() == .rax) { | 7073 | if (reg.to64() == .rax) { |
| 7071 | // If this is RAX, we can use a direct load. | 7074 | // If this is RAX, we can use a direct load. |
| 7072 | // Otherwise, we need to load the address, then indirectly load the value. | 7075 | // Otherwise, we need to load the address, then indirectly load the value. |
| 7073 | var moffs: Mir.MemoryMoffs = .{ | ||
| 7074 | .seg = @enumToInt(Register.ds), | ||
| 7075 | .msb = undefined, | ||
| 7076 | .lsb = undefined, | ||
| 7077 | }; | ||
| 7078 | moffs.encodeOffset(x); | ||
| 7079 | _ = try self.addInst(.{ | 7076 | _ = try self.addInst(.{ |
| 7080 | .tag = .mov_moffs, | 7077 | .tag = .mov_moffs, |
| 7081 | .ops = .rax_moffs, | 7078 | .ops = .rax_moffs, |
| 7082 | .data = .{ .payload = try self.addExtra(moffs) }, | 7079 | .data = .{ .payload = try self.addExtra(Mir.MemoryMoffs.encode(.ds, x)) }, |
| 7083 | }); | 7080 | }); |
| 7084 | } else { | 7081 | } else { |
| 7085 | // Rather than duplicate the logic used for the move, we just use a self-call with a new MCValue. | 7082 | // Rather than duplicate the logic used for the move, we just use a self-call with a new MCValue. |
src/arch/x86_64/Emit.zig+168-737| ... | @@ -1,40 +1,8 @@ | ... | @@ -1,40 +1,8 @@ |
| 1 | //! This file contains the functionality for lowering x86_64 MIR into | 1 | //! This file contains the functionality for emitting x86_64 MIR as machine code |
| 2 | //! machine code | ||
| 3 | 2 | ||
| 4 | const Emit = @This(); | 3 | lower: Lower, |
| 5 | |||
| 6 | const std = @import("std"); | ||
| 7 | const assert = std.debug.assert; | ||
| 8 | const bits = @import("bits.zig"); | ||
| 9 | const abi = @import("abi.zig"); | ||
| 10 | const encoder = @import("encoder.zig"); | ||
| 11 | const link = @import("../../link.zig"); | ||
| 12 | const log = std.log.scoped(.codegen); | ||
| 13 | const math = std.math; | ||
| 14 | const mem = std.mem; | ||
| 15 | const testing = std.testing; | ||
| 16 | |||
| 17 | const Air = @import("../../Air.zig"); | ||
| 18 | const Allocator = mem.Allocator; | ||
| 19 | const CodeGen = @import("CodeGen.zig"); | ||
| 20 | const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput; | ||
| 21 | const Encoder = bits.Encoder; | ||
| 22 | const ErrorMsg = Module.ErrorMsg; | ||
| 23 | const Immediate = bits.Immediate; | ||
| 24 | const Instruction = encoder.Instruction; | ||
| 25 | const MCValue = @import("CodeGen.zig").MCValue; | ||
| 26 | const Memory = bits.Memory; | ||
| 27 | const Mir = @import("Mir.zig"); | ||
| 28 | const Module = @import("../../Module.zig"); | ||
| 29 | const Register = bits.Register; | ||
| 30 | const Type = @import("../../type.zig").Type; | ||
| 31 | |||
| 32 | mir: Mir, | ||
| 33 | bin_file: *link.File, | 4 | bin_file: *link.File, |
| 34 | debug_output: DebugInfoOutput, | 5 | debug_output: DebugInfoOutput, |
| 35 | target: *const std.Target, | ||
| 36 | err_msg: ?*ErrorMsg = null, | ||
| 37 | src_loc: Module.SrcLoc, | ||
| 38 | code: *std.ArrayList(u8), | 6 | code: *std.ArrayList(u8), |
| 39 | 7 | ||
| 40 | prev_di_line: u32, | 8 | prev_di_line: u32, |
| ... | @@ -45,166 +13,176 @@ prev_di_pc: usize, | ... | @@ -45,166 +13,176 @@ prev_di_pc: usize, |
| 45 | code_offset_mapping: std.AutoHashMapUnmanaged(Mir.Inst.Index, usize) = .{}, | 13 | code_offset_mapping: std.AutoHashMapUnmanaged(Mir.Inst.Index, usize) = .{}, |
| 46 | relocs: std.ArrayListUnmanaged(Reloc) = .{}, | 14 | relocs: std.ArrayListUnmanaged(Reloc) = .{}, |
| 47 | 15 | ||
| 48 | const InnerError = error{ | 16 | pub const Error = Lower.Error || error{EmitFail}; |
| 49 | OutOfMemory, | 17 | |
| 50 | EmitFail, | 18 | pub fn emitMir(emit: *Emit) Error!void { |
| 51 | InvalidInstruction, | 19 | for (0..emit.lower.mir.instructions.len) |i| { |
| 52 | CannotEncode, | 20 | const index = @intCast(Mir.Inst.Index, i); |
| 53 | }; | 21 | const inst = emit.lower.mir.instructions.get(index); |
| 54 | 22 | ||
| 55 | const Reloc = struct { | 23 | const start_offset = @intCast(u32, emit.code.items.len); |
| 56 | /// Offset of the instruction. | 24 | try emit.code_offset_mapping.putNoClobber(emit.lower.allocator, index, start_offset); |
| 57 | source: usize, | 25 | for (try emit.lower.lowerMir(inst)) |lower_inst| try lower_inst.encode(emit.code.writer()); |
| 58 | /// Target of the relocation. | 26 | const end_offset = @intCast(u32, emit.code.items.len); |
| 59 | target: Mir.Inst.Index, | 27 | |
| 60 | /// Offset of the relocation within the instruction. | 28 | switch (inst.tag) { |
| 61 | offset: usize, | 29 | else => {}, |
| 62 | /// Length of the instruction. | 30 | |
| 63 | length: u5, | 31 | .jmp_reloc => try emit.relocs.append(emit.lower.allocator, .{ |
| 64 | }; | 32 | .source = start_offset, |
| 65 | 33 | .target = inst.data.inst, | |
| 66 | pub fn lowerMir(emit: *Emit) InnerError!void { | 34 | .offset = end_offset - 4, |
| 67 | const mir_tags = emit.mir.instructions.items(.tag); | 35 | .length = 5, |
| 68 | 36 | }), | |
| 69 | for (mir_tags, 0..) |tag, index| { | 37 | |
| 70 | const inst = @intCast(u32, index); | 38 | .call_extern => if (emit.bin_file.cast(link.File.MachO)) |macho_file| { |
| 71 | try emit.code_offset_mapping.putNoClobber(emit.bin_file.allocator, inst, emit.code.items.len); | 39 | // Add relocation to the decl. |
| 72 | switch (tag) { | 40 | const atom_index = macho_file.getAtomIndexForSymbol( |
| 73 | .adc, | 41 | .{ .sym_index = inst.data.relocation.atom_index, .file = null }, |
| 74 | .add, | 42 | ).?; |
| 75 | .@"and", | 43 | const target = macho_file.getGlobalByIndex(inst.data.relocation.sym_index); |
| 76 | .bsf, | 44 | try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{ |
| 77 | .bsr, | 45 | .type = @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_BRANCH), |
| 78 | .bswap, | 46 | .target = target, |
| 79 | .bt, | 47 | .offset = end_offset - 4, |
| 80 | .btc, | 48 | .addend = 0, |
| 81 | .btr, | 49 | .pcrel = true, |
| 82 | .bts, | 50 | .length = 2, |
| 83 | .call, | 51 | }); |
| 84 | .cbw, | 52 | } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| { |
| 85 | .cwde, | 53 | // Add relocation to the decl. |
| 86 | .cdqe, | 54 | const atom_index = coff_file.getAtomIndexForSymbol( |
| 87 | .cwd, | 55 | .{ .sym_index = inst.data.relocation.atom_index, .file = null }, |
| 88 | .cdq, | 56 | ).?; |
| 89 | .cqo, | 57 | const target = coff_file.getGlobalByIndex(inst.data.relocation.sym_index); |
| 90 | .cmp, | 58 | try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{ |
| 91 | .cmpxchg, | 59 | .type = .direct, |
| 92 | .div, | 60 | .target = target, |
| 93 | .fisttp, | 61 | .offset = end_offset - 4, |
| 94 | .fld, | 62 | .addend = 0, |
| 95 | .idiv, | 63 | .pcrel = true, |
| 96 | .imul, | 64 | .length = 2, |
| 97 | .int3, | 65 | }); |
| 98 | .jmp, | 66 | } else return emit.fail("TODO implement {} for {}", .{ inst.tag, emit.bin_file.tag }), |
| 99 | .lea, | 67 | |
| 100 | .lfence, | 68 | .lea_linker => if (emit.bin_file.cast(link.File.MachO)) |macho_file| { |
| 101 | .lzcnt, | 69 | const metadata = |
| 102 | .mfence, | 70 | emit.lower.mir.extraData(Mir.LeaRegisterReloc, inst.data.payload).data; |
| 103 | .mov, | 71 | const reloc_type = switch (inst.ops) { |
| 104 | .movbe, | 72 | .got_reloc => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_GOT), |
| 105 | .movzx, | 73 | .direct_reloc => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_SIGNED), |
| 106 | .mul, | 74 | else => unreachable, |
| 107 | .neg, | 75 | }; |
| 108 | .nop, | 76 | const atom_index = macho_file.getAtomIndexForSymbol(.{ |
| 109 | .not, | 77 | .sym_index = metadata.atom_index, |
| 110 | .@"or", | 78 | .file = null, |
| 111 | .pop, | 79 | }).?; |
| 112 | .popcnt, | 80 | try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{ |
| 113 | .push, | 81 | .type = reloc_type, |
| 114 | .rcl, | 82 | .target = .{ .sym_index = metadata.sym_index, .file = null }, |
| 115 | .rcr, | 83 | .offset = @intCast(u32, end_offset - 4), |
| 116 | .ret, | 84 | .addend = 0, |
| 117 | .rol, | 85 | .pcrel = true, |
| 118 | .ror, | 86 | .length = 2, |
| 119 | .sal, | 87 | }); |
| 120 | .sar, | 88 | } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| { |
| 121 | .sbb, | 89 | const metadata = |
| 122 | .sfence, | 90 | emit.lower.mir.extraData(Mir.LeaRegisterReloc, inst.data.payload).data; |
| 123 | .shl, | 91 | const atom_index = coff_file.getAtomIndexForSymbol(.{ |
| 124 | .shld, | 92 | .sym_index = metadata.atom_index, |
| 125 | .shr, | 93 | .file = null, |
| 126 | .shrd, | 94 | }).?; |
| 127 | .sub, | 95 | try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{ |
| 128 | .syscall, | 96 | .type = switch (inst.ops) { |
| 129 | .@"test", | 97 | .got_reloc => .got, |
| 130 | .tzcnt, | 98 | .direct_reloc => .direct, |
| 131 | .ud2, | 99 | .import_reloc => .import, |
| 132 | .xadd, | 100 | else => unreachable, |
| 133 | .xchg, | 101 | }, |
| 134 | .xor, | 102 | .target = switch (inst.ops) { |
| 135 | 103 | .got_reloc, | |
| 136 | .addss, | 104 | .direct_reloc, |
| 137 | .cmpss, | 105 | => .{ .sym_index = metadata.sym_index, .file = null }, |
| 138 | .divss, | 106 | .import_reloc => coff_file.getGlobalByIndex(metadata.sym_index), |
| 139 | .maxss, | 107 | else => unreachable, |
| 140 | .minss, | 108 | }, |
| 141 | .movss, | 109 | .offset = @intCast(u32, end_offset - 4), |
| 142 | .mulss, | 110 | .addend = 0, |
| 143 | .roundss, | 111 | .pcrel = true, |
| 144 | .subss, | 112 | .length = 2, |
| 145 | .ucomiss, | 113 | }); |
| 146 | .addsd, | 114 | } else return emit.fail("TODO implement {} for {}", .{ inst.tag, emit.bin_file.tag }), |
| 147 | .cmpsd, | 115 | |
| 148 | .divsd, | 116 | .jcc => try emit.relocs.append(emit.lower.allocator, .{ |
| 149 | .maxsd, | 117 | .source = start_offset, |
| 150 | .minsd, | 118 | .target = inst.data.inst_cc.inst, |
| 151 | .movsd, | 119 | .offset = end_offset - 4, |
| 152 | .mulsd, | 120 | .length = 6, |
| 153 | .roundsd, | 121 | }), |
| 154 | .subsd, | ||
| 155 | .ucomisd, | ||
| 156 | => try emit.mirEncodeGeneric(tag, inst), | ||
| 157 | |||
| 158 | .cmps, | ||
| 159 | .lods, | ||
| 160 | .movs, | ||
| 161 | .scas, | ||
| 162 | .stos, | ||
| 163 | => try emit.mirString(tag, inst), | ||
| 164 | |||
| 165 | .cmpxchgb => try emit.mirCmpxchgBytes(inst), | ||
| 166 | |||
| 167 | .jmp_reloc => try emit.mirJmpReloc(inst), | ||
| 168 | |||
| 169 | .call_extern => try emit.mirCallExtern(inst), | ||
| 170 | |||
| 171 | .lea_linker => try emit.mirLeaLinker(inst), | ||
| 172 | |||
| 173 | .mov_moffs => try emit.mirMovMoffs(inst), | ||
| 174 | |||
| 175 | .movsx => try emit.mirMovsx(inst), | ||
| 176 | .cmovcc => try emit.mirCmovcc(inst), | ||
| 177 | .setcc => try emit.mirSetcc(inst), | ||
| 178 | .jcc => try emit.mirJcc(inst), | ||
| 179 | 122 | ||
| 180 | .dbg_line => try emit.mirDbgLine(inst), | 123 | .dbg_line => { |
| 181 | .dbg_prologue_end => try emit.mirDbgPrologueEnd(inst), | 124 | const dbg_line_column = |
| 182 | .dbg_epilogue_begin => try emit.mirDbgEpilogueBegin(inst), | 125 | emit.lower.mir.extraData(Mir.DbgLineColumn, inst.data.payload).data; |
| 126 | try emit.dbgAdvancePCAndLine(dbg_line_column.line, dbg_line_column.column); | ||
| 127 | }, | ||
| 183 | 128 | ||
| 184 | .push_regs => try emit.mirPushPopRegisterList(.push, inst), | 129 | .dbg_prologue_end => { |
| 185 | .pop_regs => try emit.mirPushPopRegisterList(.pop, inst), | 130 | switch (emit.debug_output) { |
| 131 | .dwarf => |dw| { | ||
| 132 | try dw.setPrologueEnd(); | ||
| 133 | log.debug("mirDbgPrologueEnd (line={d}, col={d})", .{ | ||
| 134 | emit.prev_di_line, emit.prev_di_column, | ||
| 135 | }); | ||
| 136 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); | ||
| 137 | }, | ||
| 138 | .plan9 => {}, | ||
| 139 | .none => {}, | ||
| 140 | } | ||
| 141 | }, | ||
| 186 | 142 | ||
| 187 | .dead => {}, | 143 | .dbg_epilogue_begin => { |
| 144 | switch (emit.debug_output) { | ||
| 145 | .dwarf => |dw| { | ||
| 146 | try dw.setEpilogueBegin(); | ||
| 147 | log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{ | ||
| 148 | emit.prev_di_line, emit.prev_di_column, | ||
| 149 | }); | ||
| 150 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); | ||
| 151 | }, | ||
| 152 | .plan9 => {}, | ||
| 153 | .none => {}, | ||
| 154 | } | ||
| 155 | }, | ||
| 188 | } | 156 | } |
| 189 | } | 157 | } |
| 190 | |||
| 191 | try emit.fixupRelocs(); | 158 | try emit.fixupRelocs(); |
| 192 | } | 159 | } |
| 193 | 160 | ||
| 194 | pub fn deinit(emit: *Emit) void { | 161 | pub fn deinit(emit: *Emit) void { |
| 195 | emit.relocs.deinit(emit.bin_file.allocator); | 162 | emit.relocs.deinit(emit.lower.allocator); |
| 196 | emit.code_offset_mapping.deinit(emit.bin_file.allocator); | 163 | emit.code_offset_mapping.deinit(emit.lower.allocator); |
| 197 | emit.* = undefined; | 164 | emit.* = undefined; |
| 198 | } | 165 | } |
| 199 | 166 | ||
| 200 | fn fail(emit: *Emit, comptime format: []const u8, args: anytype) InnerError { | 167 | fn fail(emit: *Emit, comptime format: []const u8, args: anytype) Error { |
| 201 | @setCold(true); | 168 | return switch (emit.lower.fail(format, args)) { |
| 202 | assert(emit.err_msg == null); | 169 | error.LowerFail => error.EmitFail, |
| 203 | emit.err_msg = try ErrorMsg.create(emit.bin_file.allocator, emit.src_loc, format, args); | 170 | else => |e| e, |
| 204 | return error.EmitFail; | 171 | }; |
| 205 | } | 172 | } |
| 206 | 173 | ||
| 207 | fn fixupRelocs(emit: *Emit) InnerError!void { | 174 | const Reloc = struct { |
| 175 | /// Offset of the instruction. | ||
| 176 | source: usize, | ||
| 177 | /// Target of the relocation. | ||
| 178 | target: Mir.Inst.Index, | ||
| 179 | /// Offset of the relocation within the instruction. | ||
| 180 | offset: usize, | ||
| 181 | /// Length of the instruction. | ||
| 182 | length: u5, | ||
| 183 | }; | ||
| 184 | |||
| 185 | fn fixupRelocs(emit: *Emit) Error!void { | ||
| 208 | // TODO this function currently assumes all relocs via JMP/CALL instructions are 32bit in size. | 186 | // TODO this function currently assumes all relocs via JMP/CALL instructions are 32bit in size. |
| 209 | // This should be reversed like it is done in aarch64 MIR emit code: start with the smallest | 187 | // This should be reversed like it is done in aarch64 MIR emit code: start with the smallest |
| 210 | // possible resolution, i.e., 8bit, and iteratively converge on the minimum required resolution | 188 | // possible resolution, i.e., 8bit, and iteratively converge on the minimum required resolution |
| ... | @@ -217,532 +195,7 @@ fn fixupRelocs(emit: *Emit) InnerError!void { | ... | @@ -217,532 +195,7 @@ fn fixupRelocs(emit: *Emit) InnerError!void { |
| 217 | } | 195 | } |
| 218 | } | 196 | } |
| 219 | 197 | ||
| 220 | fn encode(emit: *Emit, mnemonic: Instruction.Mnemonic, ops: Instruction.Init) InnerError!void { | 198 | fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void { |
| 221 | const inst = try Instruction.new(mnemonic, ops); | ||
| 222 | return inst.encode(emit.code.writer()); | ||
| 223 | } | ||
| 224 | |||
| 225 | fn mirEncodeGeneric(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void { | ||
| 226 | const mnemonic = inline for (@typeInfo(Instruction.Mnemonic).Enum.fields) |field| { | ||
| 227 | if (mem.eql(u8, field.name, @tagName(tag))) break @field(Instruction.Mnemonic, field.name); | ||
| 228 | } else unreachable; | ||
| 229 | |||
| 230 | const ops = emit.mir.instructions.items(.ops)[inst]; | ||
| 231 | const data = emit.mir.instructions.items(.data)[inst]; | ||
| 232 | |||
| 233 | const prefix: Instruction.Prefix = switch (ops) { | ||
| 234 | .lock_m_sib, | ||
| 235 | .lock_m_rip, | ||
| 236 | .lock_mi_sib_u, | ||
| 237 | .lock_mi_rip_u, | ||
| 238 | .lock_mi_sib_s, | ||
| 239 | .lock_mi_rip_s, | ||
| 240 | .lock_mr_sib, | ||
| 241 | .lock_mr_rip, | ||
| 242 | .lock_moffs_rax, | ||
| 243 | => .lock, | ||
| 244 | else => .none, | ||
| 245 | }; | ||
| 246 | |||
| 247 | var op1: Instruction.Operand = .none; | ||
| 248 | var op2: Instruction.Operand = .none; | ||
| 249 | var op3: Instruction.Operand = .none; | ||
| 250 | var op4: Instruction.Operand = .none; | ||
| 251 | |||
| 252 | switch (ops) { | ||
| 253 | .none => {}, | ||
| 254 | .i_s => op1 = .{ .imm = Immediate.s(@bitCast(i32, data.i)) }, | ||
| 255 | .i_u => op1 = .{ .imm = Immediate.u(data.i) }, | ||
| 256 | .r => op1 = .{ .reg = data.r }, | ||
| 257 | .rr => { | ||
| 258 | op1 = .{ .reg = data.rr.r1 }; | ||
| 259 | op2 = .{ .reg = data.rr.r2 }; | ||
| 260 | }, | ||
| 261 | .rrr => { | ||
| 262 | op1 = .{ .reg = data.rrr.r1 }; | ||
| 263 | op2 = .{ .reg = data.rrr.r2 }; | ||
| 264 | op3 = .{ .reg = data.rrr.r3 }; | ||
| 265 | }, | ||
| 266 | .ri_s, .ri_u => { | ||
| 267 | const imm = switch (ops) { | ||
| 268 | .ri_s => Immediate.s(@bitCast(i32, data.ri.i)), | ||
| 269 | .ri_u => Immediate.u(data.ri.i), | ||
| 270 | else => unreachable, | ||
| 271 | }; | ||
| 272 | op1 = .{ .reg = data.ri.r }; | ||
| 273 | op2 = .{ .imm = imm }; | ||
| 274 | }, | ||
| 275 | .ri64 => { | ||
| 276 | const imm64 = emit.mir.extraData(Mir.Imm64, data.rx.payload).data; | ||
| 277 | op1 = .{ .reg = data.rx.r }; | ||
| 278 | op2 = .{ .imm = Immediate.u(Mir.Imm64.decode(imm64)) }; | ||
| 279 | }, | ||
| 280 | .rri_s, .rri_u => { | ||
| 281 | const imm = switch (ops) { | ||
| 282 | .rri_s => Immediate.s(@bitCast(i32, data.rri.i)), | ||
| 283 | .rri_u => Immediate.u(data.rri.i), | ||
| 284 | else => unreachable, | ||
| 285 | }; | ||
| 286 | op1 = .{ .reg = data.rri.r1 }; | ||
| 287 | op2 = .{ .reg = data.rri.r2 }; | ||
| 288 | op3 = .{ .imm = imm }; | ||
| 289 | }, | ||
| 290 | .m_sib, .lock_m_sib => { | ||
| 291 | const msib = emit.mir.extraData(Mir.MemorySib, data.payload).data; | ||
| 292 | op1 = .{ .mem = Mir.MemorySib.decode(msib) }; | ||
| 293 | }, | ||
| 294 | .m_rip, .lock_m_rip => { | ||
| 295 | const mrip = emit.mir.extraData(Mir.MemoryRip, data.payload).data; | ||
| 296 | op1 = .{ .mem = Mir.MemoryRip.decode(mrip) }; | ||
| 297 | }, | ||
| 298 | .mi_sib_s, .mi_sib_u, .lock_mi_sib_s, .lock_mi_sib_u => { | ||
| 299 | const msib = emit.mir.extraData(Mir.MemorySib, data.ix.payload).data; | ||
| 300 | const imm = switch (ops) { | ||
| 301 | .mi_sib_s, .lock_mi_sib_s => Immediate.s(@bitCast(i32, data.ix.i)), | ||
| 302 | .mi_sib_u, .lock_mi_sib_u => Immediate.u(data.ix.i), | ||
| 303 | else => unreachable, | ||
| 304 | }; | ||
| 305 | op1 = .{ .mem = Mir.MemorySib.decode(msib) }; | ||
| 306 | op2 = .{ .imm = imm }; | ||
| 307 | }, | ||
| 308 | .mi_rip_u, .mi_rip_s, .lock_mi_rip_u, .lock_mi_rip_s => { | ||
| 309 | const mrip = emit.mir.extraData(Mir.MemoryRip, data.ix.payload).data; | ||
| 310 | const imm = switch (ops) { | ||
| 311 | .mi_rip_s, .lock_mi_rip_s => Immediate.s(@bitCast(i32, data.ix.i)), | ||
| 312 | .mi_rip_u, .lock_mi_rip_u => Immediate.u(data.ix.i), | ||
| 313 | else => unreachable, | ||
| 314 | }; | ||
| 315 | op1 = .{ .mem = Mir.MemoryRip.decode(mrip) }; | ||
| 316 | op2 = .{ .imm = imm }; | ||
| 317 | }, | ||
| 318 | .rm_sib, .mr_sib, .lock_mr_sib => { | ||
| 319 | const msib = emit.mir.extraData(Mir.MemorySib, data.rx.payload).data; | ||
| 320 | const op_r = .{ .reg = data.rx.r }; | ||
| 321 | const op_m = .{ .mem = Mir.MemorySib.decode(msib) }; | ||
| 322 | switch (ops) { | ||
| 323 | .rm_sib => { | ||
| 324 | op1 = op_r; | ||
| 325 | op2 = op_m; | ||
| 326 | }, | ||
| 327 | .mr_sib, .lock_mr_sib => { | ||
| 328 | op1 = op_m; | ||
| 329 | op2 = op_r; | ||
| 330 | }, | ||
| 331 | else => unreachable, | ||
| 332 | } | ||
| 333 | }, | ||
| 334 | .rm_rip, .mr_rip, .lock_mr_rip => { | ||
| 335 | const mrip = emit.mir.extraData(Mir.MemoryRip, data.rx.payload).data; | ||
| 336 | const op_r = .{ .reg = data.rx.r }; | ||
| 337 | const op_m = .{ .mem = Mir.MemoryRip.decode(mrip) }; | ||
| 338 | switch (ops) { | ||
| 339 | .rm_rip => { | ||
| 340 | op1 = op_r; | ||
| 341 | op2 = op_m; | ||
| 342 | }, | ||
| 343 | .mr_rip, .lock_mr_rip => { | ||
| 344 | op1 = op_m; | ||
| 345 | op2 = op_r; | ||
| 346 | }, | ||
| 347 | else => unreachable, | ||
| 348 | } | ||
| 349 | }, | ||
| 350 | .mrr_sib => { | ||
| 351 | const msib = emit.mir.extraData(Mir.MemorySib, data.rrx.payload).data; | ||
| 352 | op1 = .{ .mem = Mir.MemorySib.decode(msib) }; | ||
| 353 | op2 = .{ .reg = data.rrx.r1 }; | ||
| 354 | op2 = .{ .reg = data.rrx.r2 }; | ||
| 355 | }, | ||
| 356 | .mrr_rip => { | ||
| 357 | const mrip = emit.mir.extraData(Mir.MemoryRip, data.rrx.payload).data; | ||
| 358 | op1 = .{ .mem = Mir.MemoryRip.decode(mrip) }; | ||
| 359 | op2 = .{ .reg = data.rrx.r1 }; | ||
| 360 | op2 = .{ .reg = data.rrx.r2 }; | ||
| 361 | }, | ||
| 362 | .mri_sib => { | ||
| 363 | const msib = emit.mir.extraData(Mir.MemorySib, data.rix.payload).data; | ||
| 364 | op1 = .{ .mem = Mir.MemorySib.decode(msib) }; | ||
| 365 | op2 = .{ .reg = data.rix.r }; | ||
| 366 | op3 = .{ .imm = Immediate.u(data.rix.i) }; | ||
| 367 | }, | ||
| 368 | .mri_rip => { | ||
| 369 | const mrip = emit.mir.extraData(Mir.MemoryRip, data.rix.payload).data; | ||
| 370 | op1 = .{ .mem = Mir.MemoryRip.decode(mrip) }; | ||
| 371 | op2 = .{ .reg = data.rix.r }; | ||
| 372 | op3 = .{ .imm = Immediate.u(data.rix.i) }; | ||
| 373 | }, | ||
| 374 | else => return emit.fail("TODO handle generic encoding: {s}, {s}", .{ | ||
| 375 | @tagName(mnemonic), | ||
| 376 | @tagName(ops), | ||
| 377 | }), | ||
| 378 | } | ||
| 379 | |||
| 380 | return emit.encode(mnemonic, .{ | ||
| 381 | .prefix = prefix, | ||
| 382 | .op1 = op1, | ||
| 383 | .op2 = op2, | ||
| 384 | .op3 = op3, | ||
| 385 | .op4 = op4, | ||
| 386 | }); | ||
| 387 | } | ||
| 388 | |||
| 389 | fn mirString(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void { | ||
| 390 | const ops = emit.mir.instructions.items(.ops)[inst]; | ||
| 391 | switch (ops) { | ||
| 392 | .string => { | ||
| 393 | const data = emit.mir.instructions.items(.data)[inst].string; | ||
| 394 | const mnemonic = switch (tag) { | ||
| 395 | inline .cmps, .lods, .movs, .scas, .stos => |comptime_tag| switch (data.width) { | ||
| 396 | inline else => |comptime_width| @field( | ||
| 397 | Instruction.Mnemonic, | ||
| 398 | @tagName(comptime_tag) ++ @tagName(comptime_width), | ||
| 399 | ), | ||
| 400 | }, | ||
| 401 | else => unreachable, | ||
| 402 | }; | ||
| 403 | return emit.encode(mnemonic, .{ .prefix = switch (data.repeat) { | ||
| 404 | inline else => |comptime_repeat| @field(Instruction.Prefix, @tagName(comptime_repeat)), | ||
| 405 | } }); | ||
| 406 | }, | ||
| 407 | else => unreachable, | ||
| 408 | } | ||
| 409 | } | ||
| 410 | |||
| 411 | fn mirCmpxchgBytes(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { | ||
| 412 | const ops = emit.mir.instructions.items(.ops)[inst]; | ||
| 413 | const data = emit.mir.instructions.items(.data)[inst]; | ||
| 414 | |||
| 415 | var op1: Instruction.Operand = .none; | ||
| 416 | switch (ops) { | ||
| 417 | .m_sib, .lock_m_sib => { | ||
| 418 | const sib = emit.mir.extraData(Mir.MemorySib, data.payload).data; | ||
| 419 | op1 = .{ .mem = Mir.MemorySib.decode(sib) }; | ||
| 420 | }, | ||
| 421 | .m_rip, .lock_m_rip => { | ||
| 422 | const rip = emit.mir.extraData(Mir.MemoryRip, data.payload).data; | ||
| 423 | op1 = .{ .mem = Mir.MemoryRip.decode(rip) }; | ||
| 424 | }, | ||
| 425 | else => unreachable, | ||
| 426 | } | ||
| 427 | |||
| 428 | const mnemonic: Instruction.Mnemonic = switch (op1.mem.bitSize()) { | ||
| 429 | 64 => .cmpxchg8b, | ||
| 430 | 128 => .cmpxchg16b, | ||
| 431 | else => unreachable, | ||
| 432 | }; | ||
| 433 | |||
| 434 | return emit.encode(mnemonic, .{ | ||
| 435 | .prefix = switch (ops) { | ||
| 436 | .m_sib, .m_rip => .none, | ||
| 437 | .lock_m_sib, .lock_m_rip => .lock, | ||
| 438 | else => unreachable, | ||
| 439 | }, | ||
| 440 | .op1 = op1, | ||
| 441 | }); | ||
| 442 | } | ||
| 443 | |||
| 444 | fn mirMovMoffs(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { | ||
| 445 | const ops = emit.mir.instructions.items(.ops)[inst]; | ||
| 446 | const payload = emit.mir.instructions.items(.data)[inst].payload; | ||
| 447 | const moffs = emit.mir.extraData(Mir.MemoryMoffs, payload).data; | ||
| 448 | const seg = @intToEnum(Register, moffs.seg); | ||
| 449 | const offset = moffs.decodeOffset(); | ||
| 450 | switch (ops) { | ||
| 451 | .rax_moffs => { | ||
| 452 | try emit.encode(.mov, .{ | ||
| 453 | .op1 = .{ .reg = .rax }, | ||
| 454 | .op2 = .{ .mem = Memory.moffs(seg, offset) }, | ||
| 455 | }); | ||
| 456 | }, | ||
| 457 | .moffs_rax, .lock_moffs_rax => { | ||
| 458 | try emit.encode(.mov, .{ | ||
| 459 | .prefix = switch (ops) { | ||
| 460 | .moffs_rax => .none, | ||
| 461 | .lock_moffs_rax => .lock, | ||
| 462 | else => unreachable, | ||
| 463 | }, | ||
| 464 | .op1 = .{ .mem = Memory.moffs(seg, offset) }, | ||
| 465 | .op2 = .{ .reg = .rax }, | ||
| 466 | }); | ||
| 467 | }, | ||
| 468 | else => unreachable, | ||
| 469 | } | ||
| 470 | } | ||
| 471 | |||
| 472 | fn mirMovsx(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { | ||
| 473 | const ops = emit.mir.instructions.items(.ops)[inst]; | ||
| 474 | const data = emit.mir.instructions.items(.data)[inst]; | ||
| 475 | |||
| 476 | var op1: Instruction.Operand = .none; | ||
| 477 | var op2: Instruction.Operand = .none; | ||
| 478 | switch (ops) { | ||
| 479 | .rr => { | ||
| 480 | op1 = .{ .reg = data.rr.r1 }; | ||
| 481 | op2 = .{ .reg = data.rr.r2 }; | ||
| 482 | }, | ||
| 483 | .rm_sib => { | ||
| 484 | const msib = emit.mir.extraData(Mir.MemorySib, data.rx.payload).data; | ||
| 485 | op1 = .{ .reg = data.rx.r }; | ||
| 486 | op2 = .{ .mem = Mir.MemorySib.decode(msib) }; | ||
| 487 | }, | ||
| 488 | .rm_rip => { | ||
| 489 | const mrip = emit.mir.extraData(Mir.MemoryRip, data.rx.payload).data; | ||
| 490 | op1 = .{ .reg = data.rx.r }; | ||
| 491 | op2 = .{ .mem = Mir.MemoryRip.decode(mrip) }; | ||
| 492 | }, | ||
| 493 | else => unreachable, // TODO | ||
| 494 | } | ||
| 495 | |||
| 496 | const mnemonic: Instruction.Mnemonic = switch (op1.bitSize()) { | ||
| 497 | 32, 64 => if (op2.bitSize() == 32) .movsxd else .movsx, | ||
| 498 | else => .movsx, | ||
| 499 | }; | ||
| 500 | |||
| 501 | return emit.encode(mnemonic, .{ | ||
| 502 | .op1 = op1, | ||
| 503 | .op2 = op2, | ||
| 504 | }); | ||
| 505 | } | ||
| 506 | |||
| 507 | fn mnemonicFromConditionCode(comptime basename: []const u8, cc: bits.Condition) Instruction.Mnemonic { | ||
| 508 | return switch (cc) { | ||
| 509 | inline else => |comptime_cc| @field(Instruction.Mnemonic, basename ++ @tagName(comptime_cc)), | ||
| 510 | }; | ||
| 511 | } | ||
| 512 | |||
| 513 | fn mirCmovcc(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { | ||
| 514 | const ops = emit.mir.instructions.items(.ops)[inst]; | ||
| 515 | switch (ops) { | ||
| 516 | .rr_cc => { | ||
| 517 | const data = emit.mir.instructions.items(.data)[inst].rr_cc; | ||
| 518 | const mnemonic = mnemonicFromConditionCode("cmov", data.cc); | ||
| 519 | return emit.encode(mnemonic, .{ | ||
| 520 | .op1 = .{ .reg = data.r1 }, | ||
| 521 | .op2 = .{ .reg = data.r2 }, | ||
| 522 | }); | ||
| 523 | }, | ||
| 524 | .rm_sib_cc => { | ||
| 525 | const data = emit.mir.instructions.items(.data)[inst].rx_cc; | ||
| 526 | const extra = emit.mir.extraData(Mir.MemorySib, data.payload).data; | ||
| 527 | const mnemonic = mnemonicFromConditionCode("cmov", data.cc); | ||
| 528 | return emit.encode(mnemonic, .{ | ||
| 529 | .op1 = .{ .reg = data.r }, | ||
| 530 | .op2 = .{ .mem = Mir.MemorySib.decode(extra) }, | ||
| 531 | }); | ||
| 532 | }, | ||
| 533 | .rm_rip_cc => { | ||
| 534 | const data = emit.mir.instructions.items(.data)[inst].rx_cc; | ||
| 535 | const extra = emit.mir.extraData(Mir.MemoryRip, data.payload).data; | ||
| 536 | const mnemonic = mnemonicFromConditionCode("cmov", data.cc); | ||
| 537 | return emit.encode(mnemonic, .{ | ||
| 538 | .op1 = .{ .reg = data.r }, | ||
| 539 | .op2 = .{ .mem = Mir.MemoryRip.decode(extra) }, | ||
| 540 | }); | ||
| 541 | }, | ||
| 542 | else => unreachable, | ||
| 543 | } | ||
| 544 | } | ||
| 545 | |||
| 546 | fn mirSetcc(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { | ||
| 547 | const ops = emit.mir.instructions.items(.ops)[inst]; | ||
| 548 | switch (ops) { | ||
| 549 | .r_cc => { | ||
| 550 | const data = emit.mir.instructions.items(.data)[inst].r_cc; | ||
| 551 | const mnemonic = mnemonicFromConditionCode("set", data.cc); | ||
| 552 | return emit.encode(mnemonic, .{ | ||
| 553 | .op1 = .{ .reg = data.r }, | ||
| 554 | }); | ||
| 555 | }, | ||
| 556 | .m_sib_cc => { | ||
| 557 | const data = emit.mir.instructions.items(.data)[inst].x_cc; | ||
| 558 | const extra = emit.mir.extraData(Mir.MemorySib, data.payload).data; | ||
| 559 | const mnemonic = mnemonicFromConditionCode("set", data.cc); | ||
| 560 | return emit.encode(mnemonic, .{ | ||
| 561 | .op1 = .{ .mem = Mir.MemorySib.decode(extra) }, | ||
| 562 | }); | ||
| 563 | }, | ||
| 564 | .m_rip_cc => { | ||
| 565 | const data = emit.mir.instructions.items(.data)[inst].x_cc; | ||
| 566 | const extra = emit.mir.extraData(Mir.MemoryRip, data.payload).data; | ||
| 567 | const mnemonic = mnemonicFromConditionCode("set", data.cc); | ||
| 568 | return emit.encode(mnemonic, .{ | ||
| 569 | .op1 = .{ .mem = Mir.MemoryRip.decode(extra) }, | ||
| 570 | }); | ||
| 571 | }, | ||
| 572 | else => unreachable, // TODO | ||
| 573 | } | ||
| 574 | } | ||
| 575 | |||
| 576 | fn mirJcc(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { | ||
| 577 | const ops = emit.mir.instructions.items(.ops)[inst]; | ||
| 578 | switch (ops) { | ||
| 579 | .inst_cc => { | ||
| 580 | const data = emit.mir.instructions.items(.data)[inst].inst_cc; | ||
| 581 | const mnemonic = mnemonicFromConditionCode("j", data.cc); | ||
| 582 | const source = emit.code.items.len; | ||
| 583 | try emit.encode(mnemonic, .{ | ||
| 584 | .op1 = .{ .imm = Immediate.s(0) }, | ||
| 585 | }); | ||
| 586 | try emit.relocs.append(emit.bin_file.allocator, .{ | ||
| 587 | .source = source, | ||
| 588 | .target = data.inst, | ||
| 589 | .offset = emit.code.items.len - 4, | ||
| 590 | .length = 6, | ||
| 591 | }); | ||
| 592 | }, | ||
| 593 | else => unreachable, // TODO | ||
| 594 | } | ||
| 595 | } | ||
| 596 | |||
| 597 | fn mirJmpReloc(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { | ||
| 598 | const target = emit.mir.instructions.items(.data)[inst].inst; | ||
| 599 | const source = emit.code.items.len; | ||
| 600 | try emit.encode(.jmp, .{ | ||
| 601 | .op1 = .{ .imm = Immediate.s(0) }, | ||
| 602 | }); | ||
| 603 | try emit.relocs.append(emit.bin_file.allocator, .{ | ||
| 604 | .source = source, | ||
| 605 | .target = target, | ||
| 606 | .offset = emit.code.items.len - 4, | ||
| 607 | .length = 5, | ||
| 608 | }); | ||
| 609 | } | ||
| 610 | |||
| 611 | fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { | ||
| 612 | const relocation = emit.mir.instructions.items(.data)[inst].relocation; | ||
| 613 | |||
| 614 | const offset = blk: { | ||
| 615 | try emit.encode(.call, .{ | ||
| 616 | .op1 = .{ .imm = Immediate.s(0) }, | ||
| 617 | }); | ||
| 618 | break :blk @intCast(u32, emit.code.items.len) - 4; | ||
| 619 | }; | ||
| 620 | |||
| 621 | if (emit.bin_file.cast(link.File.MachO)) |macho_file| { | ||
| 622 | // Add relocation to the decl. | ||
| 623 | const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?; | ||
| 624 | const target = macho_file.getGlobalByIndex(relocation.sym_index); | ||
| 625 | try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{ | ||
| 626 | .type = @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_BRANCH), | ||
| 627 | .target = target, | ||
| 628 | .offset = offset, | ||
| 629 | .addend = 0, | ||
| 630 | .pcrel = true, | ||
| 631 | .length = 2, | ||
| 632 | }); | ||
| 633 | } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| { | ||
| 634 | // Add relocation to the decl. | ||
| 635 | const atom_index = coff_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?; | ||
| 636 | const target = coff_file.getGlobalByIndex(relocation.sym_index); | ||
| 637 | try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{ | ||
| 638 | .type = .direct, | ||
| 639 | .target = target, | ||
| 640 | .offset = offset, | ||
| 641 | .addend = 0, | ||
| 642 | .pcrel = true, | ||
| 643 | .length = 2, | ||
| 644 | }); | ||
| 645 | } else { | ||
| 646 | return emit.fail("TODO implement call_extern for linking backends different than MachO and COFF", .{}); | ||
| 647 | } | ||
| 648 | } | ||
| 649 | |||
| 650 | fn mirPushPopRegisterList(emit: *Emit, tag: Mir.Inst.Tag, inst: Mir.Inst.Index) InnerError!void { | ||
| 651 | const payload = emit.mir.instructions.items(.data)[inst].payload; | ||
| 652 | const save_reg_list = emit.mir.extraData(Mir.SaveRegisterList, payload).data; | ||
| 653 | const base = @intToEnum(Register, save_reg_list.base_reg); | ||
| 654 | var disp: i32 = -@intCast(i32, save_reg_list.stack_end); | ||
| 655 | const reg_list = Mir.RegisterList.fromInt(save_reg_list.register_list); | ||
| 656 | const callee_preserved_regs = abi.getCalleePreservedRegs(emit.target.*); | ||
| 657 | for (callee_preserved_regs) |reg| { | ||
| 658 | if (reg_list.isSet(callee_preserved_regs, reg)) { | ||
| 659 | const op1: Instruction.Operand = .{ .mem = Memory.sib(.qword, .{ | ||
| 660 | .base = base, | ||
| 661 | .disp = disp, | ||
| 662 | }) }; | ||
| 663 | const op2: Instruction.Operand = .{ .reg = reg }; | ||
| 664 | switch (tag) { | ||
| 665 | .push => try emit.encode(.mov, .{ | ||
| 666 | .op1 = op1, | ||
| 667 | .op2 = op2, | ||
| 668 | }), | ||
| 669 | .pop => try emit.encode(.mov, .{ | ||
| 670 | .op1 = op2, | ||
| 671 | .op2 = op1, | ||
| 672 | }), | ||
| 673 | else => unreachable, | ||
| 674 | } | ||
| 675 | disp += 8; | ||
| 676 | } | ||
| 677 | } | ||
| 678 | } | ||
| 679 | |||
| 680 | fn mirLeaLinker(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { | ||
| 681 | const ops = emit.mir.instructions.items(.ops)[inst]; | ||
| 682 | const payload = emit.mir.instructions.items(.data)[inst].payload; | ||
| 683 | const metadata = emit.mir.extraData(Mir.LeaRegisterReloc, payload).data; | ||
| 684 | const reg = @intToEnum(Register, metadata.reg); | ||
| 685 | |||
| 686 | try emit.encode(.lea, .{ | ||
| 687 | .op1 = .{ .reg = reg }, | ||
| 688 | .op2 = .{ .mem = Memory.rip(Memory.PtrSize.fromBitSize(reg.bitSize()), 0) }, | ||
| 689 | }); | ||
| 690 | |||
| 691 | const end_offset = emit.code.items.len; | ||
| 692 | |||
| 693 | if (emit.bin_file.cast(link.File.MachO)) |macho_file| { | ||
| 694 | const reloc_type = switch (ops) { | ||
| 695 | .got_reloc => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_GOT), | ||
| 696 | .direct_reloc => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_SIGNED), | ||
| 697 | else => unreachable, | ||
| 698 | }; | ||
| 699 | const atom_index = macho_file.getAtomIndexForSymbol(.{ | ||
| 700 | .sym_index = metadata.atom_index, | ||
| 701 | .file = null, | ||
| 702 | }).?; | ||
| 703 | try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{ | ||
| 704 | .type = reloc_type, | ||
| 705 | .target = .{ .sym_index = metadata.sym_index, .file = null }, | ||
| 706 | .offset = @intCast(u32, end_offset - 4), | ||
| 707 | .addend = 0, | ||
| 708 | .pcrel = true, | ||
| 709 | .length = 2, | ||
| 710 | }); | ||
| 711 | } else if (emit.bin_file.cast(link.File.Coff)) |coff_file| { | ||
| 712 | const atom_index = coff_file.getAtomIndexForSymbol(.{ | ||
| 713 | .sym_index = metadata.atom_index, | ||
| 714 | .file = null, | ||
| 715 | }).?; | ||
| 716 | try link.File.Coff.Atom.addRelocation(coff_file, atom_index, .{ | ||
| 717 | .type = switch (ops) { | ||
| 718 | .got_reloc => .got, | ||
| 719 | .direct_reloc => .direct, | ||
| 720 | .import_reloc => .import, | ||
| 721 | else => unreachable, | ||
| 722 | }, | ||
| 723 | .target = switch (ops) { | ||
| 724 | .got_reloc, .direct_reloc => .{ .sym_index = metadata.sym_index, .file = null }, | ||
| 725 | .import_reloc => coff_file.getGlobalByIndex(metadata.sym_index), | ||
| 726 | else => unreachable, | ||
| 727 | }, | ||
| 728 | .offset = @intCast(u32, end_offset - 4), | ||
| 729 | .addend = 0, | ||
| 730 | .pcrel = true, | ||
| 731 | .length = 2, | ||
| 732 | }); | ||
| 733 | } else { | ||
| 734 | return emit.fail("TODO implement lea reg, [rip + reloc] for linking backends different than MachO", .{}); | ||
| 735 | } | ||
| 736 | } | ||
| 737 | |||
| 738 | fn mirDbgLine(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { | ||
| 739 | const payload = emit.mir.instructions.items(.data)[inst].payload; | ||
| 740 | const dbg_line_column = emit.mir.extraData(Mir.DbgLineColumn, payload).data; | ||
| 741 | log.debug("mirDbgLine", .{}); | ||
| 742 | try emit.dbgAdvancePCAndLine(dbg_line_column.line, dbg_line_column.column); | ||
| 743 | } | ||
| 744 | |||
| 745 | fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) InnerError!void { | ||
| 746 | const delta_line = @intCast(i32, line) - @intCast(i32, emit.prev_di_line); | 199 | const delta_line = @intCast(i32, line) - @intCast(i32, emit.prev_di_line); |
| 747 | const delta_pc: usize = emit.code.items.len - emit.prev_di_pc; | 200 | const delta_pc: usize = emit.code.items.len - emit.prev_di_pc; |
| 748 | log.debug(" (advance pc={d} and line={d})", .{ delta_line, delta_pc }); | 201 | 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 { | ... | @@ -756,7 +209,7 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) InnerError!void { |
| 756 | .plan9 => |dbg_out| { | 209 | .plan9 => |dbg_out| { |
| 757 | if (delta_pc <= 0) return; // only do this when the pc changes | 210 | if (delta_pc <= 0) return; // only do this when the pc changes |
| 758 | // we have already checked the target in the linker to make sure it is compatable | 211 | // we have already checked the target in the linker to make sure it is compatable |
| 759 | const quant = @import("../../link/Plan9/aout.zig").getPCQuant(emit.target.cpu.arch) catch unreachable; | 212 | const quant = @import("../../link/Plan9/aout.zig").getPCQuant(emit.lower.target.cpu.arch) catch unreachable; |
| 760 | 213 | ||
| 761 | // increasing the line number | 214 | // increasing the line number |
| 762 | try @import("../../link/Plan9.zig").changeLine(dbg_out.dbg_line, delta_line); | 215 | 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 { | ... | @@ -792,34 +245,12 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) InnerError!void { |
| 792 | } | 245 | } |
| 793 | } | 246 | } |
| 794 | 247 | ||
| 795 | fn mirDbgPrologueEnd(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { | 248 | const link = @import("../../link.zig"); |
| 796 | _ = inst; | 249 | const log = std.log.scoped(.emit); |
| 797 | switch (emit.debug_output) { | 250 | const mem = std.mem; |
| 798 | .dwarf => |dw| { | 251 | const std = @import("std"); |
| 799 | try dw.setPrologueEnd(); | ||
| 800 | log.debug("mirDbgPrologueEnd (line={d}, col={d})", .{ | ||
| 801 | emit.prev_di_line, | ||
| 802 | emit.prev_di_column, | ||
| 803 | }); | ||
| 804 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); | ||
| 805 | }, | ||
| 806 | .plan9 => {}, | ||
| 807 | .none => {}, | ||
| 808 | } | ||
| 809 | } | ||
| 810 | 252 | ||
| 811 | fn mirDbgEpilogueBegin(emit: *Emit, inst: Mir.Inst.Index) InnerError!void { | 253 | const DebugInfoOutput = @import("../../codegen.zig").DebugInfoOutput; |
| 812 | _ = inst; | 254 | const Emit = @This(); |
| 813 | switch (emit.debug_output) { | 255 | const Lower = @import("Lower.zig"); |
| 814 | .dwarf => |dw| { | 256 | const Mir = @import("Mir.zig"); |
| 815 | try dw.setEpilogueBegin(); | ||
| 816 | log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{ | ||
| 817 | emit.prev_di_line, | ||
| 818 | emit.prev_di_column, | ||
| 819 | }); | ||
| 820 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); | ||
| 821 | }, | ||
| 822 | .plan9 => {}, | ||
| 823 | .none => {}, | ||
| 824 | } | ||
| 825 | } |
src/arch/x86_64/Encoding.zig+137-157| ... | @@ -7,30 +7,32 @@ const math = std.math; | ... | @@ -7,30 +7,32 @@ const math = std.math; |
| 7 | const bits = @import("bits.zig"); | 7 | const bits = @import("bits.zig"); |
| 8 | const encoder = @import("encoder.zig"); | 8 | const encoder = @import("encoder.zig"); |
| 9 | const Instruction = encoder.Instruction; | 9 | const Instruction = encoder.Instruction; |
| 10 | const Operand = Instruction.Operand; | ||
| 11 | const Prefix = Instruction.Prefix; | ||
| 10 | const Register = bits.Register; | 12 | const Register = bits.Register; |
| 11 | const Rex = encoder.Rex; | 13 | const Rex = encoder.Rex; |
| 12 | const LegacyPrefixes = encoder.LegacyPrefixes; | 14 | const LegacyPrefixes = encoder.LegacyPrefixes; |
| 13 | 15 | ||
| 14 | const table = @import("encodings.zig").table; | ||
| 15 | |||
| 16 | mnemonic: Mnemonic, | 16 | mnemonic: Mnemonic, |
| 17 | op_en: OpEn, | 17 | data: Data, |
| 18 | op1: Op, | 18 | |
| 19 | op2: Op, | 19 | const Data = struct { |
| 20 | op3: Op, | 20 | op_en: OpEn, |
| 21 | op4: Op, | 21 | ops: [4]Op, |
| 22 | opc_len: u3, | 22 | opc_len: u3, |
| 23 | opc: [7]u8, | 23 | opc: [7]u8, |
| 24 | modrm_ext: u3, | 24 | modrm_ext: u3, |
| 25 | mode: Mode, | 25 | mode: Mode, |
| 26 | 26 | }; | |
| 27 | pub fn findByMnemonic(mnemonic: Mnemonic, args: Instruction.Init) !?Encoding { | 27 | |
| 28 | const input_op1 = Op.fromOperand(args.op1); | 28 | pub fn findByMnemonic( |
| 29 | const input_op2 = Op.fromOperand(args.op2); | 29 | prefix: Instruction.Prefix, |
| 30 | const input_op3 = Op.fromOperand(args.op3); | 30 | mnemonic: Mnemonic, |
| 31 | const input_op4 = Op.fromOperand(args.op4); | 31 | ops: []const Instruction.Operand, |
| 32 | 32 | ) !?Encoding { | |
| 33 | const ops = &[_]Instruction.Operand{ args.op1, args.op2, args.op3, args.op4 }; | 33 | var input_ops = [1]Op{.none} ** 4; |
| 34 | for (input_ops[0..ops.len], ops) |*input_op, op| input_op.* = Op.fromOperand(op); | ||
| 35 | |||
| 34 | const rex_required = for (ops) |op| switch (op) { | 36 | const rex_required = for (ops) |op| switch (op) { |
| 35 | .reg => |r| switch (r) { | 37 | .reg => |r| switch (r) { |
| 36 | .spl, .bpl, .sil, .dil => break true, | 38 | .spl, .bpl, .sil, .dil => break true, |
| ... | @@ -60,88 +62,29 @@ pub fn findByMnemonic(mnemonic: Mnemonic, args: Instruction.Init) !?Encoding { | ... | @@ -60,88 +62,29 @@ pub fn findByMnemonic(mnemonic: Mnemonic, args: Instruction.Init) !?Encoding { |
| 60 | 62 | ||
| 61 | if ((rex_required or rex_extended) and rex_invalid) return error.CannotEncode; | 63 | if ((rex_required or rex_extended) and rex_invalid) return error.CannotEncode; |
| 62 | 64 | ||
| 63 | // TODO work out what is the maximum number of variants we can actually find in one swoop. | 65 | var shortest_enc: ?Encoding = null; |
| 64 | var candidates: [10]Encoding = undefined; | 66 | var shortest_len: ?usize = null; |
| 65 | var count: usize = 0; | 67 | next: for (mnemonic_to_encodings_map[@enumToInt(mnemonic)]) |data| { |
| 66 | for (table) |entry| { | 68 | switch (data.mode) { |
| 67 | var enc = Encoding{ | 69 | .rex => if (!rex_required) continue, |
| 68 | .mnemonic = entry[0], | 70 | .long => {}, |
| 69 | .op_en = entry[1], | 71 | else => if (rex_required) continue, |
| 70 | .op1 = entry[2], | ||
| 71 | .op2 = entry[3], | ||
| 72 | .op3 = entry[4], | ||
| 73 | .op4 = entry[5], | ||
| 74 | .opc_len = @intCast(u3, entry[6].len), | ||
| 75 | .opc = undefined, | ||
| 76 | .modrm_ext = entry[7], | ||
| 77 | .mode = entry[8], | ||
| 78 | }; | ||
| 79 | std.mem.copy(u8, &enc.opc, entry[6]); | ||
| 80 | if (enc.mnemonic == mnemonic and | ||
| 81 | input_op1.isSubset(enc.op1, enc.mode) and | ||
| 82 | input_op2.isSubset(enc.op2, enc.mode) and | ||
| 83 | input_op3.isSubset(enc.op3, enc.mode) and | ||
| 84 | input_op4.isSubset(enc.op4, enc.mode)) | ||
| 85 | { | ||
| 86 | if (rex_required) { | ||
| 87 | switch (enc.mode) { | ||
| 88 | .rex, .long => { | ||
| 89 | candidates[count] = enc; | ||
| 90 | count += 1; | ||
| 91 | }, | ||
| 92 | else => {}, | ||
| 93 | } | ||
| 94 | } else { | ||
| 95 | if (enc.mode != .rex) { | ||
| 96 | candidates[count] = enc; | ||
| 97 | count += 1; | ||
| 98 | } | ||
| 99 | } | ||
| 100 | } | 72 | } |
| 73 | for (input_ops, data.ops) |input_op, data_op| | ||
| 74 | if (!input_op.isSubset(data_op, data.mode)) continue :next; | ||
| 75 | |||
| 76 | const enc = Encoding{ .mnemonic = mnemonic, .data = data }; | ||
| 77 | if (shortest_enc) |previous_shortest_enc| { | ||
| 78 | const len = estimateInstructionLength(prefix, enc, ops); | ||
| 79 | const previous_shortest_len = shortest_len orelse | ||
| 80 | estimateInstructionLength(prefix, previous_shortest_enc, ops); | ||
| 81 | if (len < previous_shortest_len) { | ||
| 82 | shortest_enc = enc; | ||
| 83 | shortest_len = len; | ||
| 84 | } else shortest_len = previous_shortest_len; | ||
| 85 | } else shortest_enc = enc; | ||
| 101 | } | 86 | } |
| 102 | 87 | return shortest_enc; | |
| 103 | if (count == 0) return null; | ||
| 104 | if (count == 1) return candidates[0]; | ||
| 105 | |||
| 106 | const EncodingLength = struct { | ||
| 107 | fn estimate(encoding: Encoding, params: Instruction.Init) usize { | ||
| 108 | var inst = Instruction{ | ||
| 109 | .op1 = params.op1, | ||
| 110 | .op2 = params.op2, | ||
| 111 | .op3 = params.op3, | ||
| 112 | .op4 = params.op4, | ||
| 113 | .prefix = params.prefix, | ||
| 114 | .encoding = encoding, | ||
| 115 | }; | ||
| 116 | var cwriter = std.io.countingWriter(std.io.null_writer); | ||
| 117 | inst.encode(cwriter.writer()) catch unreachable; // Not allowed to fail here unless OOM. | ||
| 118 | return @intCast(usize, cwriter.bytes_written); | ||
| 119 | } | ||
| 120 | }; | ||
| 121 | |||
| 122 | var shortest_encoding: ?struct { | ||
| 123 | index: usize, | ||
| 124 | len: usize, | ||
| 125 | } = null; | ||
| 126 | var i: usize = 0; | ||
| 127 | while (i < count) : (i += 1) { | ||
| 128 | const candidate = candidates[i]; | ||
| 129 | switch (candidate.mode) { | ||
| 130 | .long, .rex => if (rex_invalid) return error.CannotEncode, | ||
| 131 | else => {}, | ||
| 132 | } | ||
| 133 | |||
| 134 | const len = EncodingLength.estimate(candidate, args); | ||
| 135 | const current = shortest_encoding orelse { | ||
| 136 | shortest_encoding = .{ .index = i, .len = len }; | ||
| 137 | continue; | ||
| 138 | }; | ||
| 139 | if (len < current.len) { | ||
| 140 | shortest_encoding = .{ .index = i, .len = len }; | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | return candidates[shortest_encoding.?.index]; | ||
| 145 | } | 88 | } |
| 146 | 89 | ||
| 147 | /// Returns first matching encoding by opcode. | 90 | /// Returns first matching encoding by opcode. |
| ... | @@ -149,57 +92,45 @@ pub fn findByOpcode(opc: []const u8, prefixes: struct { | ... | @@ -149,57 +92,45 @@ pub fn findByOpcode(opc: []const u8, prefixes: struct { |
| 149 | legacy: LegacyPrefixes, | 92 | legacy: LegacyPrefixes, |
| 150 | rex: Rex, | 93 | rex: Rex, |
| 151 | }, modrm_ext: ?u3) ?Encoding { | 94 | }, modrm_ext: ?u3) ?Encoding { |
| 152 | for (table) |entry| { | 95 | for (mnemonic_to_encodings_map, 0..) |encs, mnemonic_int| for (encs) |data| { |
| 153 | const enc = Encoding{ | 96 | const enc = Encoding{ .mnemonic = @intToEnum(Mnemonic, mnemonic_int), .data = data }; |
| 154 | .mnemonic = entry[0], | 97 | if (modrm_ext) |ext| if (ext != data.modrm_ext) continue; |
| 155 | .op_en = entry[1], | 98 | if (!std.mem.eql(u8, opc, enc.opcode())) continue; |
| 156 | .op1 = entry[2], | 99 | if (prefixes.rex.w) { |
| 157 | .op2 = entry[3], | 100 | switch (data.mode) { |
| 158 | .op3 = entry[4], | 101 | .short, .fpu, .sse, .sse2, .sse4_1, .none => continue, |
| 159 | .op4 = entry[5], | 102 | .long, .rex => {}, |
| 160 | .opc_len = entry[6], | ||
| 161 | .opc = .{ entry[7], entry[8], entry[9] }, | ||
| 162 | .modrm_ext = entry[10], | ||
| 163 | .mode = entry[11], | ||
| 164 | }; | ||
| 165 | const match = match: { | ||
| 166 | if (modrm_ext) |ext| { | ||
| 167 | break :match ext == enc.modrm_ext and std.mem.eql(u8, enc.opcode(), opc); | ||
| 168 | } | 103 | } |
| 169 | break :match std.mem.eql(u8, enc.opcode(), opc); | 104 | } else if (prefixes.rex.present and !prefixes.rex.isSet()) { |
| 170 | }; | 105 | switch (data.mode) { |
| 171 | if (match) { | 106 | .rex => {}, |
| 172 | if (prefixes.rex.w) { | 107 | else => continue, |
| 173 | switch (enc.mode) { | 108 | } |
| 174 | .fpu, .sse, .sse2, .sse4_1, .none => {}, | 109 | } else if (prefixes.legacy.prefix_66) { |
| 175 | .long, .rex => return enc, | 110 | switch (enc.operandBitSize()) { |
| 176 | } | 111 | 16 => {}, |
| 177 | } else if (prefixes.rex.present and !prefixes.rex.isSet()) { | 112 | else => continue, |
| 178 | if (enc.mode == .rex) return enc; | 113 | } |
| 179 | } else if (prefixes.legacy.prefix_66) { | 114 | } else { |
| 180 | switch (enc.operandBitSize()) { | 115 | switch (data.mode) { |
| 181 | 16 => return enc, | 116 | .none => switch (enc.operandBitSize()) { |
| 117 | 16 => continue, | ||
| 182 | else => {}, | 118 | else => {}, |
| 183 | } | 119 | }, |
| 184 | } else { | 120 | else => continue, |
| 185 | if (enc.mode == .none) { | ||
| 186 | switch (enc.operandBitSize()) { | ||
| 187 | 16 => {}, | ||
| 188 | else => return enc, | ||
| 189 | } | ||
| 190 | } | ||
| 191 | } | 121 | } |
| 192 | } | 122 | } |
| 193 | } | 123 | return enc; |
| 124 | }; | ||
| 194 | return null; | 125 | return null; |
| 195 | } | 126 | } |
| 196 | 127 | ||
| 197 | pub fn opcode(encoding: *const Encoding) []const u8 { | 128 | pub fn opcode(encoding: *const Encoding) []const u8 { |
| 198 | return encoding.opc[0..encoding.opc_len]; | 129 | return encoding.data.opc[0..encoding.data.opc_len]; |
| 199 | } | 130 | } |
| 200 | 131 | ||
| 201 | pub fn mandatoryPrefix(encoding: *const Encoding) ?u8 { | 132 | pub fn mandatoryPrefix(encoding: *const Encoding) ?u8 { |
| 202 | const prefix = encoding.opc[0]; | 133 | const prefix = encoding.data.opc[0]; |
| 203 | return switch (prefix) { | 134 | return switch (prefix) { |
| 204 | 0x66, 0xf2, 0xf3 => prefix, | 135 | 0x66, 0xf2, 0xf3 => prefix, |
| 205 | else => null, | 136 | else => null, |
| ... | @@ -207,27 +138,27 @@ pub fn mandatoryPrefix(encoding: *const Encoding) ?u8 { | ... | @@ -207,27 +138,27 @@ pub fn mandatoryPrefix(encoding: *const Encoding) ?u8 { |
| 207 | } | 138 | } |
| 208 | 139 | ||
| 209 | pub fn modRmExt(encoding: Encoding) u3 { | 140 | pub fn modRmExt(encoding: Encoding) u3 { |
| 210 | return switch (encoding.op_en) { | 141 | return switch (encoding.data.op_en) { |
| 211 | .m, .mi, .m1, .mc => encoding.modrm_ext, | 142 | .m, .mi, .m1, .mc => encoding.data.modrm_ext, |
| 212 | else => unreachable, | 143 | else => unreachable, |
| 213 | }; | 144 | }; |
| 214 | } | 145 | } |
| 215 | 146 | ||
| 216 | pub fn operandBitSize(encoding: Encoding) u64 { | 147 | pub fn operandBitSize(encoding: Encoding) u64 { |
| 217 | switch (encoding.mode) { | 148 | switch (encoding.data.mode) { |
| 218 | .short => return 16, | 149 | .short => return 16, |
| 219 | .long => return 64, | 150 | .long => return 64, |
| 220 | else => {}, | 151 | else => {}, |
| 221 | } | 152 | } |
| 222 | const bit_size: u64 = switch (encoding.op_en) { | 153 | const bit_size: u64 = switch (encoding.data.op_en) { |
| 223 | .np => switch (encoding.op1) { | 154 | .np => switch (encoding.data.ops[0]) { |
| 224 | .o16 => 16, | 155 | .o16 => 16, |
| 225 | .o32 => 32, | 156 | .o32 => 32, |
| 226 | .o64 => 64, | 157 | .o64 => 64, |
| 227 | else => 32, | 158 | else => 32, |
| 228 | }, | 159 | }, |
| 229 | .td => encoding.op2.bitSize(), | 160 | .td => encoding.data.ops[1].bitSize(), |
| 230 | else => encoding.op1.bitSize(), | 161 | else => encoding.data.ops[0].bitSize(), |
| 231 | }; | 162 | }; |
| 232 | return bit_size; | 163 | return bit_size; |
| 233 | } | 164 | } |
| ... | @@ -240,7 +171,7 @@ pub fn format( | ... | @@ -240,7 +171,7 @@ pub fn format( |
| 240 | ) !void { | 171 | ) !void { |
| 241 | _ = options; | 172 | _ = options; |
| 242 | _ = fmt; | 173 | _ = fmt; |
| 243 | switch (encoding.mode) { | 174 | switch (encoding.data.mode) { |
| 244 | .long => try writer.writeAll("REX.W + "), | 175 | .long => try writer.writeAll("REX.W + "), |
| 245 | else => {}, | 176 | else => {}, |
| 246 | } | 177 | } |
| ... | @@ -249,10 +180,10 @@ pub fn format( | ... | @@ -249,10 +180,10 @@ pub fn format( |
| 249 | try writer.print("{x:0>2} ", .{byte}); | 180 | try writer.print("{x:0>2} ", .{byte}); |
| 250 | } | 181 | } |
| 251 | 182 | ||
| 252 | switch (encoding.op_en) { | 183 | switch (encoding.data.op_en) { |
| 253 | .np, .fd, .td, .i, .zi, .d => {}, | 184 | .np, .fd, .td, .i, .zi, .d => {}, |
| 254 | .o, .oi => { | 185 | .o, .oi => { |
| 255 | const tag = switch (encoding.op1) { | 186 | const tag = switch (encoding.data.ops[0]) { |
| 256 | .r8 => "rb", | 187 | .r8 => "rb", |
| 257 | .r16 => "rw", | 188 | .r16 => "rw", |
| 258 | .r32 => "rd", | 189 | .r32 => "rd", |
| ... | @@ -265,12 +196,12 @@ pub fn format( | ... | @@ -265,12 +196,12 @@ pub fn format( |
| 265 | .mr, .rm, .rmi, .mri, .mrc => try writer.writeAll("/r "), | 196 | .mr, .rm, .rmi, .mri, .mrc => try writer.writeAll("/r "), |
| 266 | } | 197 | } |
| 267 | 198 | ||
| 268 | switch (encoding.op_en) { | 199 | switch (encoding.data.op_en) { |
| 269 | .i, .d, .zi, .oi, .mi, .rmi, .mri => { | 200 | .i, .d, .zi, .oi, .mi, .rmi, .mri => { |
| 270 | const op = switch (encoding.op_en) { | 201 | const op = switch (encoding.data.op_en) { |
| 271 | .i, .d => encoding.op1, | 202 | .i, .d => encoding.data.ops[0], |
| 272 | .zi, .oi, .mi => encoding.op2, | 203 | .zi, .oi, .mi => encoding.data.ops[1], |
| 273 | .rmi, .mri => encoding.op3, | 204 | .rmi, .mri => encoding.data.ops[2], |
| 274 | else => unreachable, | 205 | else => unreachable, |
| 275 | }; | 206 | }; |
| 276 | const tag = switch (op) { | 207 | const tag = switch (op) { |
| ... | @@ -290,13 +221,12 @@ pub fn format( | ... | @@ -290,13 +221,12 @@ pub fn format( |
| 290 | 221 | ||
| 291 | try writer.print("{s} ", .{@tagName(encoding.mnemonic)}); | 222 | try writer.print("{s} ", .{@tagName(encoding.mnemonic)}); |
| 292 | 223 | ||
| 293 | const ops = &[_]Op{ encoding.op1, encoding.op2, encoding.op3, encoding.op4 }; | 224 | for (encoding.data.ops) |op| switch (op) { |
| 294 | for (ops) |op| switch (op) { | ||
| 295 | .none, .o16, .o32, .o64 => break, | 225 | .none, .o16, .o32, .o64 => break, |
| 296 | else => try writer.print("{s} ", .{@tagName(op)}), | 226 | else => try writer.print("{s} ", .{@tagName(op)}), |
| 297 | }; | 227 | }; |
| 298 | 228 | ||
| 299 | const op_en = switch (encoding.op_en) { | 229 | const op_en = switch (encoding.data.op_en) { |
| 300 | .zi => .i, | 230 | .zi => .i, |
| 301 | else => |op_en| op_en, | 231 | else => |op_en| op_en, |
| 302 | }; | 232 | }; |
| ... | @@ -604,3 +534,53 @@ pub const Mode = enum { | ... | @@ -604,3 +534,53 @@ pub const Mode = enum { |
| 604 | sse2, | 534 | sse2, |
| 605 | sse4_1, | 535 | sse4_1, |
| 606 | }; | 536 | }; |
| 537 | |||
| 538 | fn estimateInstructionLength(prefix: Prefix, encoding: Encoding, ops: []const Operand) usize { | ||
| 539 | var inst = Instruction{ | ||
| 540 | .prefix = prefix, | ||
| 541 | .encoding = encoding, | ||
| 542 | .ops = [1]Operand{.none} ** 4, | ||
| 543 | }; | ||
| 544 | std.mem.copy(Operand, &inst.ops, ops); | ||
| 545 | |||
| 546 | var cwriter = std.io.countingWriter(std.io.null_writer); | ||
| 547 | inst.encode(cwriter.writer()) catch unreachable; // Not allowed to fail here unless OOM. | ||
| 548 | return @intCast(usize, cwriter.bytes_written); | ||
| 549 | } | ||
| 550 | |||
| 551 | const mnemonic_to_encodings_map = init: { | ||
| 552 | @setEvalBranchQuota(100_000); | ||
| 553 | const encodings = @import("encodings.zig"); | ||
| 554 | var entries = encodings.table; | ||
| 555 | std.sort.sort(encodings.Entry, &entries, {}, struct { | ||
| 556 | fn lessThan(_: void, lhs: encodings.Entry, rhs: encodings.Entry) bool { | ||
| 557 | return @enumToInt(lhs[0]) < @enumToInt(rhs[0]); | ||
| 558 | } | ||
| 559 | }.lessThan); | ||
| 560 | var data_storage: [entries.len]Data = undefined; | ||
| 561 | var mnemonic_map: [@typeInfo(Mnemonic).Enum.fields.len][]const Data = undefined; | ||
| 562 | var mnemonic_int = 0; | ||
| 563 | var mnemonic_start = 0; | ||
| 564 | for (&data_storage, entries, 0..) |*data, entry, data_index| { | ||
| 565 | data.* = .{ | ||
| 566 | .op_en = entry[1], | ||
| 567 | .ops = undefined, | ||
| 568 | .opc_len = entry[3].len, | ||
| 569 | .opc = undefined, | ||
| 570 | .modrm_ext = entry[4], | ||
| 571 | .mode = entry[5], | ||
| 572 | }; | ||
| 573 | std.mem.copy(Op, &data.ops, entry[2]); | ||
| 574 | std.mem.copy(u8, &data.opc, entry[3]); | ||
| 575 | |||
| 576 | while (mnemonic_int < @enumToInt(entry[0])) : (mnemonic_int += 1) { | ||
| 577 | mnemonic_map[mnemonic_int] = data_storage[mnemonic_start..data_index]; | ||
| 578 | mnemonic_start = data_index; | ||
| 579 | } | ||
| 580 | } | ||
| 581 | while (mnemonic_int < mnemonic_map.len) : (mnemonic_int += 1) { | ||
| 582 | mnemonic_map[mnemonic_int] = data_storage[mnemonic_start..]; | ||
| 583 | mnemonic_start = data_storage.len; | ||
| 584 | } | ||
| 585 | break :init mnemonic_map; | ||
| 586 | }; |
src/arch/x86_64/Lower.zig created+465| ... | @@ -0,0 +1,465 @@ | ||
| 1 | //! This file contains the functionality for lowering x86_64 MIR to Instructions | ||
| 2 | |||
| 3 | allocator: Allocator, | ||
| 4 | mir: Mir, | ||
| 5 | target: *const std.Target, | ||
| 6 | err_msg: ?*ErrorMsg = null, | ||
| 7 | src_loc: Module.SrcLoc, | ||
| 8 | result: [ | ||
| 9 | std.mem.max(usize, &.{ | ||
| 10 | abi.Win64.callee_preserved_regs.len, | ||
| 11 | abi.SysV.callee_preserved_regs.len, | ||
| 12 | }) | ||
| 13 | ]Instruction = undefined, | ||
| 14 | result_len: usize = undefined, | ||
| 15 | |||
| 16 | pub const Error = error{ | ||
| 17 | OutOfMemory, | ||
| 18 | LowerFail, | ||
| 19 | InvalidInstruction, | ||
| 20 | CannotEncode, | ||
| 21 | }; | ||
| 22 | |||
| 23 | /// The returned slice is overwritten by the next call to lowerMir. | ||
| 24 | pub fn lowerMir(lower: *Lower, inst: Mir.Inst) Error![]const Instruction { | ||
| 25 | lower.result = undefined; | ||
| 26 | errdefer lower.result = undefined; | ||
| 27 | lower.result_len = 0; | ||
| 28 | defer lower.result_len = undefined; | ||
| 29 | |||
| 30 | switch (inst.tag) { | ||
| 31 | .adc, | ||
| 32 | .add, | ||
| 33 | .@"and", | ||
| 34 | .bsf, | ||
| 35 | .bsr, | ||
| 36 | .bswap, | ||
| 37 | .bt, | ||
| 38 | .btc, | ||
| 39 | .btr, | ||
| 40 | .bts, | ||
| 41 | .call, | ||
| 42 | .cbw, | ||
| 43 | .cwde, | ||
| 44 | .cdqe, | ||
| 45 | .cwd, | ||
| 46 | .cdq, | ||
| 47 | .cqo, | ||
| 48 | .cmp, | ||
| 49 | .cmpxchg, | ||
| 50 | .div, | ||
| 51 | .fisttp, | ||
| 52 | .fld, | ||
| 53 | .idiv, | ||
| 54 | .imul, | ||
| 55 | .int3, | ||
| 56 | .jmp, | ||
| 57 | .lea, | ||
| 58 | .lfence, | ||
| 59 | .lzcnt, | ||
| 60 | .mfence, | ||
| 61 | .mov, | ||
| 62 | .movbe, | ||
| 63 | .movzx, | ||
| 64 | .mul, | ||
| 65 | .neg, | ||
| 66 | .nop, | ||
| 67 | .not, | ||
| 68 | .@"or", | ||
| 69 | .pop, | ||
| 70 | .popcnt, | ||
| 71 | .push, | ||
| 72 | .rcl, | ||
| 73 | .rcr, | ||
| 74 | .ret, | ||
| 75 | .rol, | ||
| 76 | .ror, | ||
| 77 | .sal, | ||
| 78 | .sar, | ||
| 79 | .sbb, | ||
| 80 | .sfence, | ||
| 81 | .shl, | ||
| 82 | .shld, | ||
| 83 | .shr, | ||
| 84 | .shrd, | ||
| 85 | .sub, | ||
| 86 | .syscall, | ||
| 87 | .@"test", | ||
| 88 | .tzcnt, | ||
| 89 | .ud2, | ||
| 90 | .xadd, | ||
| 91 | .xchg, | ||
| 92 | .xor, | ||
| 93 | |||
| 94 | .addss, | ||
| 95 | .cmpss, | ||
| 96 | .divss, | ||
| 97 | .maxss, | ||
| 98 | .minss, | ||
| 99 | .movss, | ||
| 100 | .mulss, | ||
| 101 | .roundss, | ||
| 102 | .subss, | ||
| 103 | .ucomiss, | ||
| 104 | .addsd, | ||
| 105 | .cmpsd, | ||
| 106 | .divsd, | ||
| 107 | .maxsd, | ||
| 108 | .minsd, | ||
| 109 | .movsd, | ||
| 110 | .mulsd, | ||
| 111 | .roundsd, | ||
| 112 | .subsd, | ||
| 113 | .ucomisd, | ||
| 114 | => try lower.mirGeneric(inst), | ||
| 115 | |||
| 116 | .cmps, | ||
| 117 | .lods, | ||
| 118 | .movs, | ||
| 119 | .scas, | ||
| 120 | .stos, | ||
| 121 | => try lower.mirString(inst), | ||
| 122 | |||
| 123 | .cmpxchgb => try lower.mirCmpxchgBytes(inst), | ||
| 124 | |||
| 125 | .jmp_reloc => try lower.emit(.none, .jmp, &.{.{ .imm = Immediate.s(0) }}), | ||
| 126 | |||
| 127 | .call_extern => try lower.emit(.none, .call, &.{.{ .imm = Immediate.s(0) }}), | ||
| 128 | |||
| 129 | .lea_linker => try lower.mirLeaLinker(inst), | ||
| 130 | |||
| 131 | .mov_moffs => try lower.mirMovMoffs(inst), | ||
| 132 | |||
| 133 | .movsx => try lower.mirMovsx(inst), | ||
| 134 | .cmovcc => try lower.mirCmovcc(inst), | ||
| 135 | .setcc => try lower.mirSetcc(inst), | ||
| 136 | .jcc => try lower.emit(.none, mnem_cc(.j, inst.data.inst_cc.cc), &.{.{ .imm = Immediate.s(0) }}), | ||
| 137 | |||
| 138 | .push_regs, .pop_regs => try lower.mirPushPopRegisterList(inst), | ||
| 139 | |||
| 140 | .dbg_line, | ||
| 141 | .dbg_prologue_end, | ||
| 142 | .dbg_epilogue_begin, | ||
| 143 | .dead, | ||
| 144 | => {}, | ||
| 145 | } | ||
| 146 | |||
| 147 | return lower.result[0..lower.result_len]; | ||
| 148 | } | ||
| 149 | |||
| 150 | pub fn fail(lower: *Lower, comptime format: []const u8, args: anytype) Error { | ||
| 151 | @setCold(true); | ||
| 152 | assert(lower.err_msg == null); | ||
| 153 | lower.err_msg = try ErrorMsg.create(lower.allocator, lower.src_loc, format, args); | ||
| 154 | return error.LowerFail; | ||
| 155 | } | ||
| 156 | |||
| 157 | fn mnem_cc(comptime base: @Type(.EnumLiteral), cc: bits.Condition) Mnemonic { | ||
| 158 | return switch (cc) { | ||
| 159 | inline else => |c| @field(Mnemonic, @tagName(base) ++ @tagName(c)), | ||
| 160 | }; | ||
| 161 | } | ||
| 162 | |||
| 163 | fn imm(lower: Lower, ops: Mir.Inst.Ops, i: u32) Immediate { | ||
| 164 | return switch (ops) { | ||
| 165 | .rri_s, | ||
| 166 | .ri_s, | ||
| 167 | .i_s, | ||
| 168 | .mi_sib_s, | ||
| 169 | .mi_rip_s, | ||
| 170 | .lock_mi_sib_s, | ||
| 171 | .lock_mi_rip_s, | ||
| 172 | => Immediate.s(@bitCast(i32, i)), | ||
| 173 | |||
| 174 | .rri_u, | ||
| 175 | .ri_u, | ||
| 176 | .i_u, | ||
| 177 | .mi_sib_u, | ||
| 178 | .mi_rip_u, | ||
| 179 | .lock_mi_sib_u, | ||
| 180 | .lock_mi_rip_u, | ||
| 181 | .mri_sib, | ||
| 182 | .mri_rip, | ||
| 183 | => Immediate.u(i), | ||
| 184 | |||
| 185 | .ri64 => Immediate.u(lower.mir.extraData(Mir.Imm64, i).data.decode()), | ||
| 186 | |||
| 187 | else => unreachable, | ||
| 188 | }; | ||
| 189 | } | ||
| 190 | |||
| 191 | fn mem(lower: Lower, ops: Mir.Inst.Ops, payload: u32) Memory { | ||
| 192 | return switch (ops) { | ||
| 193 | .rm_sib, | ||
| 194 | .rm_sib_cc, | ||
| 195 | .m_sib, | ||
| 196 | .m_sib_cc, | ||
| 197 | .mi_sib_u, | ||
| 198 | .mi_sib_s, | ||
| 199 | .mr_sib, | ||
| 200 | .mrr_sib, | ||
| 201 | .mri_sib, | ||
| 202 | .lock_m_sib, | ||
| 203 | .lock_mi_sib_u, | ||
| 204 | .lock_mi_sib_s, | ||
| 205 | .lock_mr_sib, | ||
| 206 | => lower.mir.extraData(Mir.MemorySib, payload).data.decode(), | ||
| 207 | |||
| 208 | .rm_rip, | ||
| 209 | .rm_rip_cc, | ||
| 210 | .m_rip, | ||
| 211 | .m_rip_cc, | ||
| 212 | .mi_rip_u, | ||
| 213 | .mi_rip_s, | ||
| 214 | .mr_rip, | ||
| 215 | .mrr_rip, | ||
| 216 | .mri_rip, | ||
| 217 | .lock_m_rip, | ||
| 218 | .lock_mi_rip_u, | ||
| 219 | .lock_mi_rip_s, | ||
| 220 | .lock_mr_rip, | ||
| 221 | => lower.mir.extraData(Mir.MemoryRip, payload).data.decode(), | ||
| 222 | |||
| 223 | .rax_moffs, | ||
| 224 | .moffs_rax, | ||
| 225 | .lock_moffs_rax, | ||
| 226 | => lower.mir.extraData(Mir.MemoryMoffs, payload).data.decode(), | ||
| 227 | |||
| 228 | else => unreachable, | ||
| 229 | }; | ||
| 230 | } | ||
| 231 | |||
| 232 | fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) Error!void { | ||
| 233 | lower.result[lower.result_len] = try Instruction.new(prefix, mnemonic, ops); | ||
| 234 | lower.result_len += 1; | ||
| 235 | } | ||
| 236 | |||
| 237 | fn mirGeneric(lower: *Lower, inst: Mir.Inst) Error!void { | ||
| 238 | try lower.emit(switch (inst.ops) { | ||
| 239 | else => .none, | ||
| 240 | .lock_m_sib, | ||
| 241 | .lock_m_rip, | ||
| 242 | .lock_mi_sib_u, | ||
| 243 | .lock_mi_rip_u, | ||
| 244 | .lock_mi_sib_s, | ||
| 245 | .lock_mi_rip_s, | ||
| 246 | .lock_mr_sib, | ||
| 247 | .lock_mr_rip, | ||
| 248 | .lock_moffs_rax, | ||
| 249 | => .lock, | ||
| 250 | }, switch (inst.tag) { | ||
| 251 | inline else => |tag| if (@hasField(Mnemonic, @tagName(tag))) | ||
| 252 | @field(Mnemonic, @tagName(tag)) | ||
| 253 | else | ||
| 254 | unreachable, | ||
| 255 | }, switch (inst.ops) { | ||
| 256 | .none => &.{}, | ||
| 257 | .i_s, .i_u => &.{ | ||
| 258 | .{ .imm = lower.imm(inst.ops, inst.data.i) }, | ||
| 259 | }, | ||
| 260 | .r => &.{ | ||
| 261 | .{ .reg = inst.data.r }, | ||
| 262 | }, | ||
| 263 | .rr => &.{ | ||
| 264 | .{ .reg = inst.data.rr.r1 }, | ||
| 265 | .{ .reg = inst.data.rr.r2 }, | ||
| 266 | }, | ||
| 267 | .rrr => &.{ | ||
| 268 | .{ .reg = inst.data.rrr.r1 }, | ||
| 269 | .{ .reg = inst.data.rrr.r2 }, | ||
| 270 | .{ .reg = inst.data.rrr.r3 }, | ||
| 271 | }, | ||
| 272 | .ri_s, .ri_u => &.{ | ||
| 273 | .{ .reg = inst.data.ri.r }, | ||
| 274 | .{ .imm = lower.imm(inst.ops, inst.data.ri.i) }, | ||
| 275 | }, | ||
| 276 | .ri64 => &.{ | ||
| 277 | .{ .reg = inst.data.rx.r }, | ||
| 278 | .{ .imm = lower.imm(inst.ops, inst.data.rx.payload) }, | ||
| 279 | }, | ||
| 280 | .rri_s, .rri_u => &.{ | ||
| 281 | .{ .reg = inst.data.rri.r1 }, | ||
| 282 | .{ .reg = inst.data.rri.r2 }, | ||
| 283 | .{ .imm = lower.imm(inst.ops, inst.data.rri.i) }, | ||
| 284 | }, | ||
| 285 | .m_sib, .lock_m_sib, .m_rip, .lock_m_rip => &.{ | ||
| 286 | .{ .mem = lower.mem(inst.ops, inst.data.payload) }, | ||
| 287 | }, | ||
| 288 | .mi_sib_s, | ||
| 289 | .lock_mi_sib_s, | ||
| 290 | .mi_sib_u, | ||
| 291 | .lock_mi_sib_u, | ||
| 292 | .mi_rip_u, | ||
| 293 | .lock_mi_rip_u, | ||
| 294 | .mi_rip_s, | ||
| 295 | .lock_mi_rip_s, | ||
| 296 | => &.{ | ||
| 297 | .{ .mem = lower.mem(inst.ops, inst.data.ix.payload) }, | ||
| 298 | .{ .imm = lower.imm(inst.ops, inst.data.ix.i) }, | ||
| 299 | }, | ||
| 300 | .rm_sib, .rm_rip => &.{ | ||
| 301 | .{ .reg = inst.data.rx.r }, | ||
| 302 | .{ .mem = lower.mem(inst.ops, inst.data.rx.payload) }, | ||
| 303 | }, | ||
| 304 | .mr_sib, .lock_mr_sib, .mr_rip, .lock_mr_rip => &.{ | ||
| 305 | .{ .mem = lower.mem(inst.ops, inst.data.rx.payload) }, | ||
| 306 | .{ .reg = inst.data.rx.r }, | ||
| 307 | }, | ||
| 308 | .mrr_sib, .mrr_rip => &.{ | ||
| 309 | .{ .mem = lower.mem(inst.ops, inst.data.rrx.payload) }, | ||
| 310 | .{ .reg = inst.data.rrx.r1 }, | ||
| 311 | .{ .reg = inst.data.rrx.r2 }, | ||
| 312 | }, | ||
| 313 | .mri_sib, .mri_rip => &.{ | ||
| 314 | .{ .mem = lower.mem(inst.ops, inst.data.rix.payload) }, | ||
| 315 | .{ .reg = inst.data.rix.r }, | ||
| 316 | .{ .imm = lower.imm(inst.ops, inst.data.rix.i) }, | ||
| 317 | }, | ||
| 318 | else => return lower.fail("TODO lower {s} {s}", .{ @tagName(inst.tag), @tagName(inst.ops) }), | ||
| 319 | }); | ||
| 320 | } | ||
| 321 | |||
| 322 | fn mirString(lower: *Lower, inst: Mir.Inst) Error!void { | ||
| 323 | switch (inst.ops) { | ||
| 324 | .string => try lower.emit(switch (inst.data.string.repeat) { | ||
| 325 | inline else => |repeat| @field(Prefix, @tagName(repeat)), | ||
| 326 | }, switch (inst.tag) { | ||
| 327 | inline .cmps, .lods, .movs, .scas, .stos => |tag| switch (inst.data.string.width) { | ||
| 328 | inline else => |width| @field(Mnemonic, @tagName(tag) ++ @tagName(width)), | ||
| 329 | }, | ||
| 330 | else => unreachable, | ||
| 331 | }, &.{}), | ||
| 332 | else => return lower.fail("TODO lower {s} {s}", .{ @tagName(inst.tag), @tagName(inst.ops) }), | ||
| 333 | } | ||
| 334 | } | ||
| 335 | |||
| 336 | fn mirCmpxchgBytes(lower: *Lower, inst: Mir.Inst) Error!void { | ||
| 337 | const ops: [1]Operand = switch (inst.ops) { | ||
| 338 | .m_sib, .lock_m_sib, .m_rip, .lock_m_rip => .{ | ||
| 339 | .{ .mem = lower.mem(inst.ops, inst.data.payload) }, | ||
| 340 | }, | ||
| 341 | else => return lower.fail("TODO lower {s} {s}", .{ @tagName(inst.tag), @tagName(inst.ops) }), | ||
| 342 | }; | ||
| 343 | try lower.emit(switch (inst.ops) { | ||
| 344 | .m_sib, .m_rip => .none, | ||
| 345 | .lock_m_sib, .lock_m_rip => .lock, | ||
| 346 | else => unreachable, | ||
| 347 | }, switch (@divExact(ops[0].bitSize(), 8)) { | ||
| 348 | 8 => .cmpxchg8b, | ||
| 349 | 16 => .cmpxchg16b, | ||
| 350 | else => return lower.fail("invalid operand for {s}", .{@tagName(inst.tag)}), | ||
| 351 | }, &ops); | ||
| 352 | } | ||
| 353 | |||
| 354 | fn mirMovMoffs(lower: *Lower, inst: Mir.Inst) Error!void { | ||
| 355 | try lower.emit(switch (inst.ops) { | ||
| 356 | .rax_moffs, .moffs_rax => .none, | ||
| 357 | .lock_moffs_rax => .lock, | ||
| 358 | else => return lower.fail("TODO lower {s} {s}", .{ @tagName(inst.tag), @tagName(inst.ops) }), | ||
| 359 | }, .mov, switch (inst.ops) { | ||
| 360 | .rax_moffs => &.{ | ||
| 361 | .{ .reg = .rax }, | ||
| 362 | .{ .mem = lower.mem(inst.ops, inst.data.payload) }, | ||
| 363 | }, | ||
| 364 | .moffs_rax, .lock_moffs_rax => &.{ | ||
| 365 | .{ .mem = lower.mem(inst.ops, inst.data.payload) }, | ||
| 366 | .{ .reg = .rax }, | ||
| 367 | }, | ||
| 368 | else => unreachable, | ||
| 369 | }); | ||
| 370 | } | ||
| 371 | |||
| 372 | fn mirMovsx(lower: *Lower, inst: Mir.Inst) Error!void { | ||
| 373 | const ops: [2]Operand = switch (inst.ops) { | ||
| 374 | .rr => .{ | ||
| 375 | .{ .reg = inst.data.rr.r1 }, | ||
| 376 | .{ .reg = inst.data.rr.r2 }, | ||
| 377 | }, | ||
| 378 | .rm_sib, .rm_rip => .{ | ||
| 379 | .{ .reg = inst.data.rx.r }, | ||
| 380 | .{ .mem = lower.mem(inst.ops, inst.data.rx.payload) }, | ||
| 381 | }, | ||
| 382 | else => return lower.fail("TODO lower {s} {s}", .{ @tagName(inst.tag), @tagName(inst.ops) }), | ||
| 383 | }; | ||
| 384 | try lower.emit(.none, switch (ops[0].bitSize()) { | ||
| 385 | 32, 64 => switch (ops[1].bitSize()) { | ||
| 386 | 32 => .movsxd, | ||
| 387 | else => .movsx, | ||
| 388 | }, | ||
| 389 | else => .movsx, | ||
| 390 | }, &ops); | ||
| 391 | } | ||
| 392 | |||
| 393 | fn mirCmovcc(lower: *Lower, inst: Mir.Inst) Error!void { | ||
| 394 | switch (inst.ops) { | ||
| 395 | .rr_cc => try lower.emit(.none, mnem_cc(.cmov, inst.data.rr_cc.cc), &.{ | ||
| 396 | .{ .reg = inst.data.rr_cc.r1 }, | ||
| 397 | .{ .reg = inst.data.rr_cc.r2 }, | ||
| 398 | }), | ||
| 399 | .rm_sib_cc, .rm_rip_cc => try lower.emit(.none, mnem_cc(.cmov, inst.data.rx_cc.cc), &.{ | ||
| 400 | .{ .reg = inst.data.rx_cc.r }, | ||
| 401 | .{ .mem = lower.mem(inst.ops, inst.data.rx_cc.payload) }, | ||
| 402 | }), | ||
| 403 | else => return lower.fail("TODO lower {s} {s}", .{ @tagName(inst.tag), @tagName(inst.ops) }), | ||
| 404 | } | ||
| 405 | } | ||
| 406 | |||
| 407 | fn mirSetcc(lower: *Lower, inst: Mir.Inst) Error!void { | ||
| 408 | switch (inst.ops) { | ||
| 409 | .r_cc => try lower.emit(.none, mnem_cc(.set, inst.data.r_cc.cc), &.{ | ||
| 410 | .{ .reg = inst.data.r_cc.r }, | ||
| 411 | }), | ||
| 412 | .m_sib_cc, .m_rip_cc => try lower.emit(.none, mnem_cc(.set, inst.data.x_cc.cc), &.{ | ||
| 413 | .{ .mem = lower.mem(inst.ops, inst.data.x_cc.payload) }, | ||
| 414 | }), | ||
| 415 | else => return lower.fail("TODO lower {s} {s}", .{ @tagName(inst.tag), @tagName(inst.ops) }), | ||
| 416 | } | ||
| 417 | } | ||
| 418 | |||
| 419 | fn mirPushPopRegisterList(lower: *Lower, inst: Mir.Inst) Error!void { | ||
| 420 | const save_reg_list = lower.mir.extraData(Mir.SaveRegisterList, inst.data.payload).data; | ||
| 421 | const base = @intToEnum(Register, save_reg_list.base_reg); | ||
| 422 | var disp: i32 = -@intCast(i32, save_reg_list.stack_end); | ||
| 423 | const reg_list = Mir.RegisterList.fromInt(save_reg_list.register_list); | ||
| 424 | const callee_preserved_regs = abi.getCalleePreservedRegs(lower.target.*); | ||
| 425 | for (callee_preserved_regs) |callee_preserved_reg| { | ||
| 426 | if (!reg_list.isSet(callee_preserved_regs, callee_preserved_reg)) continue; | ||
| 427 | const reg_op = Operand{ .reg = callee_preserved_reg }; | ||
| 428 | const mem_op = Operand{ .mem = Memory.sib(.qword, .{ .base = base, .disp = disp }) }; | ||
| 429 | try lower.emit(.none, .mov, switch (inst.tag) { | ||
| 430 | .push_regs => &.{ mem_op, reg_op }, | ||
| 431 | .pop_regs => &.{ reg_op, mem_op }, | ||
| 432 | else => unreachable, | ||
| 433 | }); | ||
| 434 | disp += 8; | ||
| 435 | } | ||
| 436 | } | ||
| 437 | |||
| 438 | fn mirLeaLinker(lower: *Lower, inst: Mir.Inst) Error!void { | ||
| 439 | const metadata = lower.mir.extraData(Mir.LeaRegisterReloc, inst.data.payload).data; | ||
| 440 | const reg = @intToEnum(Register, metadata.reg); | ||
| 441 | try lower.emit(.none, .lea, &.{ | ||
| 442 | .{ .reg = reg }, | ||
| 443 | .{ .mem = Memory.rip(Memory.PtrSize.fromBitSize(reg.bitSize()), 0) }, | ||
| 444 | }); | ||
| 445 | } | ||
| 446 | |||
| 447 | const abi = @import("abi.zig"); | ||
| 448 | const assert = std.debug.assert; | ||
| 449 | const bits = @import("bits.zig"); | ||
| 450 | const encoder = @import("encoder.zig"); | ||
| 451 | const std = @import("std"); | ||
| 452 | |||
| 453 | const Air = @import("../../Air.zig"); | ||
| 454 | const Allocator = std.mem.Allocator; | ||
| 455 | const ErrorMsg = Module.ErrorMsg; | ||
| 456 | const Immediate = bits.Immediate; | ||
| 457 | const Instruction = encoder.Instruction; | ||
| 458 | const Lower = @This(); | ||
| 459 | const Memory = bits.Memory; | ||
| 460 | const Mir = @import("Mir.zig"); | ||
| 461 | const Mnemonic = Instruction.Mnemonic; | ||
| 462 | const Module = @import("../../Module.zig"); | ||
| 463 | const Operand = Instruction.Operand; | ||
| 464 | const Prefix = Instruction.Prefix; | ||
| 465 | const Register = bits.Register; | ||
src/arch/x86_64/Mir.zig+11-8| ... | @@ -655,16 +655,19 @@ pub const MemoryMoffs = struct { | ... | @@ -655,16 +655,19 @@ pub const MemoryMoffs = struct { |
| 655 | msb: u32, | 655 | msb: u32, |
| 656 | lsb: u32, | 656 | lsb: u32, |
| 657 | 657 | ||
| 658 | pub fn encodeOffset(moffs: *MemoryMoffs, v: u64) void { | 658 | pub fn encode(seg: Register, offset: u64) MemoryMoffs { |
| 659 | moffs.msb = @truncate(u32, v >> 32); | 659 | return .{ |
| 660 | moffs.lsb = @truncate(u32, v); | 660 | .seg = @enumToInt(seg), |
| 661 | .msb = @truncate(u32, offset >> 32), | ||
| 662 | .lsb = @truncate(u32, offset >> 0), | ||
| 663 | }; | ||
| 661 | } | 664 | } |
| 662 | 665 | ||
| 663 | pub fn decodeOffset(moffs: *const MemoryMoffs) u64 { | 666 | pub fn decode(moffs: MemoryMoffs) Memory { |
| 664 | var res: u64 = 0; | 667 | return .{ .moffs = .{ |
| 665 | res |= (@intCast(u64, moffs.msb) << 32); | 668 | .seg = @intToEnum(Register, moffs.seg), |
| 666 | res |= @intCast(u64, moffs.lsb); | 669 | .offset = @as(u64, moffs.msb) << 32 | @as(u64, moffs.lsb) << 0, |
| 667 | return res; | 670 | } }; |
| 668 | } | 671 | } |
| 669 | }; | 672 | }; |
| 670 | 673 |
src/arch/x86_64/bits.zig+1-1| ... | @@ -515,7 +515,7 @@ pub const Memory = union(enum) { | ... | @@ -515,7 +515,7 @@ pub const Memory = union(enum) { |
| 515 | return switch (mem) { | 515 | return switch (mem) { |
| 516 | .rip => |r| r.ptr_size.bitSize(), | 516 | .rip => |r| r.ptr_size.bitSize(), |
| 517 | .sib => |s| s.ptr_size.bitSize(), | 517 | .sib => |s| s.ptr_size.bitSize(), |
| 518 | .moffs => unreachable, | 518 | .moffs => 64, |
| 519 | }; | 519 | }; |
| 520 | } | 520 | } |
| 521 | }; | 521 | }; |
src/arch/x86_64/encoder.zig+539-380| ... | @@ -11,12 +11,9 @@ const Memory = bits.Memory; | ... | @@ -11,12 +11,9 @@ const Memory = bits.Memory; |
| 11 | const Register = bits.Register; | 11 | const Register = bits.Register; |
| 12 | 12 | ||
| 13 | pub const Instruction = struct { | 13 | pub const Instruction = struct { |
| 14 | op1: Operand = .none, | ||
| 15 | op2: Operand = .none, | ||
| 16 | op3: Operand = .none, | ||
| 17 | op4: Operand = .none, | ||
| 18 | prefix: Prefix = .none, | 14 | prefix: Prefix = .none, |
| 19 | encoding: Encoding, | 15 | encoding: Encoding, |
| 16 | ops: [4]Operand = .{.none} ** 4, | ||
| 20 | 17 | ||
| 21 | pub const Mnemonic = Encoding.Mnemonic; | 18 | pub const Mnemonic = Encoding.Mnemonic; |
| 22 | 19 | ||
| ... | @@ -107,102 +104,87 @@ pub const Instruction = struct { | ... | @@ -107,102 +104,87 @@ pub const Instruction = struct { |
| 107 | } | 104 | } |
| 108 | }; | 105 | }; |
| 109 | 106 | ||
| 110 | pub const Init = struct { | 107 | pub fn new(prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand) !Instruction { |
| 111 | prefix: Prefix = .none, | 108 | const encoding = (try Encoding.findByMnemonic(prefix, mnemonic, ops)) orelse { |
| 112 | op1: Operand = .none, | ||
| 113 | op2: Operand = .none, | ||
| 114 | op3: Operand = .none, | ||
| 115 | op4: Operand = .none, | ||
| 116 | }; | ||
| 117 | |||
| 118 | pub fn new(mnemonic: Mnemonic, args: Init) !Instruction { | ||
| 119 | const encoding = (try Encoding.findByMnemonic(mnemonic, args)) orelse { | ||
| 120 | log.err("no encoding found for: {s} {s} {s} {s} {s} {s}", .{ | 109 | log.err("no encoding found for: {s} {s} {s} {s} {s} {s}", .{ |
| 121 | @tagName(args.prefix), | 110 | @tagName(prefix), |
| 122 | @tagName(mnemonic), | 111 | @tagName(mnemonic), |
| 123 | @tagName(Encoding.Op.fromOperand(args.op1)), | 112 | @tagName(if (ops.len > 0) Encoding.Op.fromOperand(ops[0]) else .none), |
| 124 | @tagName(Encoding.Op.fromOperand(args.op2)), | 113 | @tagName(if (ops.len > 1) Encoding.Op.fromOperand(ops[1]) else .none), |
| 125 | @tagName(Encoding.Op.fromOperand(args.op3)), | 114 | @tagName(if (ops.len > 2) Encoding.Op.fromOperand(ops[2]) else .none), |
| 126 | @tagName(Encoding.Op.fromOperand(args.op4)), | 115 | @tagName(if (ops.len > 3) Encoding.Op.fromOperand(ops[3]) else .none), |
| 127 | }); | 116 | }); |
| 128 | return error.InvalidInstruction; | 117 | return error.InvalidInstruction; |
| 129 | }; | 118 | }; |
| 130 | log.debug("selected encoding: {}", .{encoding}); | 119 | log.debug("selected encoding: {}", .{encoding}); |
| 131 | return .{ | 120 | |
| 132 | .prefix = args.prefix, | 121 | var inst = Instruction{ |
| 133 | .op1 = args.op1, | 122 | .prefix = prefix, |
| 134 | .op2 = args.op2, | ||
| 135 | .op3 = args.op3, | ||
| 136 | .op4 = args.op4, | ||
| 137 | .encoding = encoding, | 123 | .encoding = encoding, |
| 124 | .ops = [1]Operand{.none} ** 4, | ||
| 138 | }; | 125 | }; |
| 126 | std.mem.copy(Operand, &inst.ops, ops); | ||
| 127 | return inst; | ||
| 139 | } | 128 | } |
| 140 | 129 | ||
| 141 | pub fn fmtPrint(inst: Instruction, writer: anytype) !void { | 130 | pub fn fmtPrint(inst: Instruction, writer: anytype) !void { |
| 142 | if (inst.prefix != .none) try writer.print("{s} ", .{@tagName(inst.prefix)}); | 131 | if (inst.prefix != .none) try writer.print("{s} ", .{@tagName(inst.prefix)}); |
| 143 | try writer.print("{s}", .{@tagName(inst.encoding.mnemonic)}); | 132 | try writer.print("{s}", .{@tagName(inst.encoding.mnemonic)}); |
| 144 | const ops = [_]struct { Operand, Encoding.Op }{ | 133 | for (inst.ops, inst.encodings.ops, 0..) |op, enc, i| { |
| 145 | .{ inst.op1, inst.encoding.op1 }, | 134 | if (op == .none) break; |
| 146 | .{ inst.op2, inst.encoding.op2 }, | 135 | if (i > 0) try writer.writeByte(','); |
| 147 | .{ inst.op3, inst.encoding.op3 }, | ||
| 148 | .{ inst.op4, inst.encoding.op4 }, | ||
| 149 | }; | ||
| 150 | for (&ops, 0..) |op, i| { | ||
| 151 | if (op[0] == .none) break; | ||
| 152 | if (i > 0) { | ||
| 153 | try writer.writeByte(','); | ||
| 154 | } | ||
| 155 | try writer.writeByte(' '); | 136 | try writer.writeByte(' '); |
| 156 | try op[0].fmtPrint(op[1], writer); | 137 | try op.fmtPrint(enc, writer); |
| 157 | } | 138 | } |
| 158 | } | 139 | } |
| 159 | 140 | ||
| 160 | pub fn encode(inst: Instruction, writer: anytype) !void { | 141 | pub fn encode(inst: Instruction, writer: anytype) !void { |
| 161 | const encoder = Encoder(@TypeOf(writer)){ .writer = writer }; | 142 | const encoder = Encoder(@TypeOf(writer)){ .writer = writer }; |
| 162 | const encoding = inst.encoding; | 143 | const enc = inst.encoding; |
| 144 | const data = enc.data; | ||
| 163 | 145 | ||
| 164 | try inst.encodeLegacyPrefixes(encoder); | 146 | try inst.encodeLegacyPrefixes(encoder); |
| 165 | try inst.encodeMandatoryPrefix(encoder); | 147 | try inst.encodeMandatoryPrefix(encoder); |
| 166 | try inst.encodeRexPrefix(encoder); | 148 | try inst.encodeRexPrefix(encoder); |
| 167 | try inst.encodeOpcode(encoder); | 149 | try inst.encodeOpcode(encoder); |
| 168 | 150 | ||
| 169 | switch (encoding.op_en) { | 151 | switch (data.op_en) { |
| 170 | .np, .o => {}, | 152 | .np, .o => {}, |
| 171 | .i, .d => try encodeImm(inst.op1.imm, encoding.op1, encoder), | 153 | .i, .d => try encodeImm(inst.ops[0].imm, data.ops[0], encoder), |
| 172 | .zi, .oi => try encodeImm(inst.op2.imm, encoding.op2, encoder), | 154 | .zi, .oi => try encodeImm(inst.ops[1].imm, data.ops[1], encoder), |
| 173 | .fd => try encoder.imm64(inst.op2.mem.moffs.offset), | 155 | .fd => try encoder.imm64(inst.ops[1].mem.moffs.offset), |
| 174 | .td => try encoder.imm64(inst.op1.mem.moffs.offset), | 156 | .td => try encoder.imm64(inst.ops[0].mem.moffs.offset), |
| 175 | else => { | 157 | else => { |
| 176 | const mem_op = switch (encoding.op_en) { | 158 | const mem_op = switch (data.op_en) { |
| 177 | .m, .mi, .m1, .mc, .mr, .mri, .mrc => inst.op1, | 159 | .m, .mi, .m1, .mc, .mr, .mri, .mrc => inst.ops[0], |
| 178 | .rm, .rmi => inst.op2, | 160 | .rm, .rmi => inst.ops[1], |
| 179 | else => unreachable, | 161 | else => unreachable, |
| 180 | }; | 162 | }; |
| 181 | switch (mem_op) { | 163 | switch (mem_op) { |
| 182 | .reg => |reg| { | 164 | .reg => |reg| { |
| 183 | const rm = switch (encoding.op_en) { | 165 | const rm = switch (data.op_en) { |
| 184 | .m, .mi, .m1, .mc => encoding.modRmExt(), | 166 | .m, .mi, .m1, .mc => enc.modRmExt(), |
| 185 | .mr, .mri, .mrc => inst.op2.reg.lowEnc(), | 167 | .mr, .mri, .mrc => inst.ops[1].reg.lowEnc(), |
| 186 | .rm, .rmi => inst.op1.reg.lowEnc(), | 168 | .rm, .rmi => inst.ops[0].reg.lowEnc(), |
| 187 | else => unreachable, | 169 | else => unreachable, |
| 188 | }; | 170 | }; |
| 189 | try encoder.modRm_direct(rm, reg.lowEnc()); | 171 | try encoder.modRm_direct(rm, reg.lowEnc()); |
| 190 | }, | 172 | }, |
| 191 | .mem => |mem| { | 173 | .mem => |mem| { |
| 192 | const op = switch (encoding.op_en) { | 174 | const op = switch (data.op_en) { |
| 193 | .m, .mi, .m1, .mc => .none, | 175 | .m, .mi, .m1, .mc => .none, |
| 194 | .mr, .mri, .mrc => inst.op2, | 176 | .mr, .mri, .mrc => inst.ops[1], |
| 195 | .rm, .rmi => inst.op1, | 177 | .rm, .rmi => inst.ops[0], |
| 196 | else => unreachable, | 178 | else => unreachable, |
| 197 | }; | 179 | }; |
| 198 | try encodeMemory(encoding, mem, op, encoder); | 180 | try encodeMemory(enc, mem, op, encoder); |
| 199 | }, | 181 | }, |
| 200 | else => unreachable, | 182 | else => unreachable, |
| 201 | } | 183 | } |
| 202 | 184 | ||
| 203 | switch (encoding.op_en) { | 185 | switch (data.op_en) { |
| 204 | .mi => try encodeImm(inst.op2.imm, encoding.op2, encoder), | 186 | .mi => try encodeImm(inst.ops[1].imm, data.ops[1], encoder), |
| 205 | .rmi, .mri => try encodeImm(inst.op3.imm, encoding.op3, encoder), | 187 | .rmi, .mri => try encodeImm(inst.ops[2].imm, data.ops[2], encoder), |
| 206 | else => {}, | 188 | else => {}, |
| 207 | } | 189 | } |
| 208 | }, | 190 | }, |
| ... | @@ -214,15 +196,16 @@ pub const Instruction = struct { | ... | @@ -214,15 +196,16 @@ pub const Instruction = struct { |
| 214 | const first = @boolToInt(inst.encoding.mandatoryPrefix() != null); | 196 | const first = @boolToInt(inst.encoding.mandatoryPrefix() != null); |
| 215 | const final = opcode.len - 1; | 197 | const final = opcode.len - 1; |
| 216 | for (opcode[first..final]) |byte| try encoder.opcode_1byte(byte); | 198 | for (opcode[first..final]) |byte| try encoder.opcode_1byte(byte); |
| 217 | switch (inst.encoding.op_en) { | 199 | switch (inst.encoding.data.op_en) { |
| 218 | .o, .oi => try encoder.opcode_withReg(opcode[final], inst.op1.reg.lowEnc()), | 200 | .o, .oi => try encoder.opcode_withReg(opcode[final], inst.ops[0].reg.lowEnc()), |
| 219 | else => try encoder.opcode_1byte(opcode[final]), | 201 | else => try encoder.opcode_1byte(opcode[final]), |
| 220 | } | 202 | } |
| 221 | } | 203 | } |
| 222 | 204 | ||
| 223 | fn encodeLegacyPrefixes(inst: Instruction, encoder: anytype) !void { | 205 | fn encodeLegacyPrefixes(inst: Instruction, encoder: anytype) !void { |
| 224 | const enc = inst.encoding; | 206 | const enc = inst.encoding; |
| 225 | const op_en = enc.op_en; | 207 | const data = enc.data; |
| 208 | const op_en = data.op_en; | ||
| 226 | 209 | ||
| 227 | var legacy = LegacyPrefixes{}; | 210 | var legacy = LegacyPrefixes{}; |
| 228 | 211 | ||
| ... | @@ -233,7 +216,7 @@ pub const Instruction = struct { | ... | @@ -233,7 +216,7 @@ pub const Instruction = struct { |
| 233 | .rep, .repe, .repz => legacy.prefix_f3 = true, | 216 | .rep, .repe, .repz => legacy.prefix_f3 = true, |
| 234 | } | 217 | } |
| 235 | 218 | ||
| 236 | if (enc.mode == .none) { | 219 | if (data.mode == .none) { |
| 237 | const bit_size = enc.operandBitSize(); | 220 | const bit_size = enc.operandBitSize(); |
| 238 | if (bit_size == 16) { | 221 | if (bit_size == 16) { |
| 239 | legacy.set16BitOverride(); | 222 | legacy.set16BitOverride(); |
| ... | @@ -242,17 +225,17 @@ pub const Instruction = struct { | ... | @@ -242,17 +225,17 @@ pub const Instruction = struct { |
| 242 | 225 | ||
| 243 | const segment_override: ?Register = switch (op_en) { | 226 | const segment_override: ?Register = switch (op_en) { |
| 244 | .i, .zi, .o, .oi, .d, .np => null, | 227 | .i, .zi, .o, .oi, .d, .np => null, |
| 245 | .fd => inst.op2.mem.base().?, | 228 | .fd => inst.ops[1].mem.base().?, |
| 246 | .td => inst.op1.mem.base().?, | 229 | .td => inst.ops[0].mem.base().?, |
| 247 | .rm, .rmi => if (inst.op2.isSegmentRegister()) blk: { | 230 | .rm, .rmi => if (inst.ops[1].isSegmentRegister()) blk: { |
| 248 | break :blk switch (inst.op2) { | 231 | break :blk switch (inst.ops[1]) { |
| 249 | .reg => |r| r, | 232 | .reg => |r| r, |
| 250 | .mem => |m| m.base().?, | 233 | .mem => |m| m.base().?, |
| 251 | else => unreachable, | 234 | else => unreachable, |
| 252 | }; | 235 | }; |
| 253 | } else null, | 236 | } else null, |
| 254 | .m, .mi, .m1, .mc, .mr, .mri, .mrc => if (inst.op1.isSegmentRegister()) blk: { | 237 | .m, .mi, .m1, .mc, .mr, .mri, .mrc => if (inst.ops[0].isSegmentRegister()) blk: { |
| 255 | break :blk switch (inst.op1) { | 238 | break :blk switch (inst.ops[0]) { |
| 256 | .reg => |r| r, | 239 | .reg => |r| r, |
| 257 | .mem => |m| m.base().?, | 240 | .mem => |m| m.base().?, |
| 258 | else => unreachable, | 241 | else => unreachable, |
| ... | @@ -267,19 +250,19 @@ pub const Instruction = struct { | ... | @@ -267,19 +250,19 @@ pub const Instruction = struct { |
| 267 | } | 250 | } |
| 268 | 251 | ||
| 269 | fn encodeRexPrefix(inst: Instruction, encoder: anytype) !void { | 252 | fn encodeRexPrefix(inst: Instruction, encoder: anytype) !void { |
| 270 | const op_en = inst.encoding.op_en; | 253 | const op_en = inst.encoding.data.op_en; |
| 271 | 254 | ||
| 272 | var rex = Rex{}; | 255 | var rex = Rex{}; |
| 273 | rex.present = inst.encoding.mode == .rex; | 256 | rex.present = inst.encoding.data.mode == .rex; |
| 274 | rex.w = inst.encoding.mode == .long; | 257 | rex.w = inst.encoding.data.mode == .long; |
| 275 | 258 | ||
| 276 | switch (op_en) { | 259 | switch (op_en) { |
| 277 | .np, .i, .zi, .fd, .td, .d => {}, | 260 | .np, .i, .zi, .fd, .td, .d => {}, |
| 278 | .o, .oi => rex.b = inst.op1.reg.isExtended(), | 261 | .o, .oi => rex.b = inst.ops[0].reg.isExtended(), |
| 279 | .m, .mi, .m1, .mc, .mr, .rm, .rmi, .mri, .mrc => { | 262 | .m, .mi, .m1, .mc, .mr, .rm, .rmi, .mri, .mrc => { |
| 280 | const r_op = switch (op_en) { | 263 | const r_op = switch (op_en) { |
| 281 | .rm, .rmi => inst.op1, | 264 | .rm, .rmi => inst.ops[0], |
| 282 | .mr, .mri, .mrc => inst.op2, | 265 | .mr, .mri, .mrc => inst.ops[1], |
| 283 | else => null, | 266 | else => null, |
| 284 | }; | 267 | }; |
| 285 | if (r_op) |op| { | 268 | if (r_op) |op| { |
| ... | @@ -287,8 +270,8 @@ pub const Instruction = struct { | ... | @@ -287,8 +270,8 @@ pub const Instruction = struct { |
| 287 | } | 270 | } |
| 288 | 271 | ||
| 289 | const b_x_op = switch (op_en) { | 272 | const b_x_op = switch (op_en) { |
| 290 | .rm, .rmi => inst.op2, | 273 | .rm, .rmi => inst.ops[1], |
| 291 | .m, .mi, .m1, .mc, .mr, .mri, .mrc => inst.op1, | 274 | .m, .mi, .m1, .mc, .mr, .mri, .mrc => inst.ops[0], |
| 292 | else => unreachable, | 275 | else => unreachable, |
| 293 | }; | 276 | }; |
| 294 | switch (b_x_op) { | 277 | switch (b_x_op) { |
| ... | @@ -827,16 +810,14 @@ const TestEncode = struct { | ... | @@ -827,16 +810,14 @@ const TestEncode = struct { |
| 827 | buffer: [32]u8 = undefined, | 810 | buffer: [32]u8 = undefined, |
| 828 | index: usize = 0, | 811 | index: usize = 0, |
| 829 | 812 | ||
| 830 | fn encode(enc: *TestEncode, mnemonic: Instruction.Mnemonic, args: Instruction.Init) !void { | 813 | fn encode( |
| 814 | enc: *TestEncode, | ||
| 815 | mnemonic: Instruction.Mnemonic, | ||
| 816 | ops: []const Instruction.Operand, | ||
| 817 | ) !void { | ||
| 831 | var stream = std.io.fixedBufferStream(&enc.buffer); | 818 | var stream = std.io.fixedBufferStream(&enc.buffer); |
| 832 | var count_writer = std.io.countingWriter(stream.writer()); | 819 | var count_writer = std.io.countingWriter(stream.writer()); |
| 833 | const inst = try Instruction.new(mnemonic, .{ | 820 | const inst = try Instruction.new(.none, mnemonic, ops); |
| 834 | .prefix = args.prefix, | ||
| 835 | .op1 = args.op1, | ||
| 836 | .op2 = args.op2, | ||
| 837 | .op3 = args.op3, | ||
| 838 | .op4 = args.op4, | ||
| 839 | }); | ||
| 840 | try inst.encode(count_writer.writer()); | 821 | try inst.encode(count_writer.writer()); |
| 841 | enc.index = count_writer.bytes_written; | 822 | enc.index = count_writer.bytes_written; |
| 842 | } | 823 | } |
| ... | @@ -850,9 +831,9 @@ test "encode" { | ... | @@ -850,9 +831,9 @@ test "encode" { |
| 850 | var buf = std.ArrayList(u8).init(testing.allocator); | 831 | var buf = std.ArrayList(u8).init(testing.allocator); |
| 851 | defer buf.deinit(); | 832 | defer buf.deinit(); |
| 852 | 833 | ||
| 853 | const inst = try Instruction.new(.mov, .{ | 834 | const inst = try Instruction.new(.none, .mov, &.{ |
| 854 | .op1 = .{ .reg = .rbx }, | 835 | .{ .reg = .rbx }, |
| 855 | .op2 = .{ .imm = Immediate.u(4) }, | 836 | .{ .imm = Immediate.u(4) }, |
| 856 | }); | 837 | }); |
| 857 | try inst.encode(buf.writer()); | 838 | try inst.encode(buf.writer()); |
| 858 | try testing.expectEqualSlices(u8, &.{ 0x48, 0xc7, 0xc3, 0x4, 0x0, 0x0, 0x0 }, buf.items); | 839 | try testing.expectEqualSlices(u8, &.{ 0x48, 0xc7, 0xc3, 0x4, 0x0, 0x0, 0x0 }, buf.items); |
| ... | @@ -861,61 +842,94 @@ test "encode" { | ... | @@ -861,61 +842,94 @@ test "encode" { |
| 861 | test "lower I encoding" { | 842 | test "lower I encoding" { |
| 862 | var enc = TestEncode{}; | 843 | var enc = TestEncode{}; |
| 863 | 844 | ||
| 864 | try enc.encode(.push, .{ .op1 = .{ .imm = Immediate.u(0x10) } }); | 845 | try enc.encode(.push, &.{ |
| 846 | .{ .imm = Immediate.u(0x10) }, | ||
| 847 | }); | ||
| 865 | try expectEqualHexStrings("\x6A\x10", enc.code(), "push 0x10"); | 848 | try expectEqualHexStrings("\x6A\x10", enc.code(), "push 0x10"); |
| 866 | 849 | ||
| 867 | try enc.encode(.push, .{ .op1 = .{ .imm = Immediate.u(0x1000) } }); | 850 | try enc.encode(.push, &.{ |
| 851 | .{ .imm = Immediate.u(0x1000) }, | ||
| 852 | }); | ||
| 868 | try expectEqualHexStrings("\x66\x68\x00\x10", enc.code(), "push 0x1000"); | 853 | try expectEqualHexStrings("\x66\x68\x00\x10", enc.code(), "push 0x1000"); |
| 869 | 854 | ||
| 870 | try enc.encode(.push, .{ .op1 = .{ .imm = Immediate.u(0x10000000) } }); | 855 | try enc.encode(.push, &.{ |
| 856 | .{ .imm = Immediate.u(0x10000000) }, | ||
| 857 | }); | ||
| 871 | try expectEqualHexStrings("\x68\x00\x00\x00\x10", enc.code(), "push 0x10000000"); | 858 | try expectEqualHexStrings("\x68\x00\x00\x00\x10", enc.code(), "push 0x10000000"); |
| 872 | 859 | ||
| 873 | try enc.encode(.adc, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .imm = Immediate.u(0x10000000) } }); | 860 | try enc.encode(.adc, &.{ |
| 861 | .{ .reg = .rax }, | ||
| 862 | .{ .imm = Immediate.u(0x10000000) }, | ||
| 863 | }); | ||
| 874 | try expectEqualHexStrings("\x48\x15\x00\x00\x00\x10", enc.code(), "adc rax, 0x10000000"); | 864 | try expectEqualHexStrings("\x48\x15\x00\x00\x00\x10", enc.code(), "adc rax, 0x10000000"); |
| 875 | 865 | ||
| 876 | try enc.encode(.add, .{ .op1 = .{ .reg = .al }, .op2 = .{ .imm = Immediate.u(0x10) } }); | 866 | try enc.encode(.add, &.{ |
| 867 | .{ .reg = .al }, | ||
| 868 | .{ .imm = Immediate.u(0x10) }, | ||
| 869 | }); | ||
| 877 | try expectEqualHexStrings("\x04\x10", enc.code(), "add al, 0x10"); | 870 | try expectEqualHexStrings("\x04\x10", enc.code(), "add al, 0x10"); |
| 878 | 871 | ||
| 879 | try enc.encode(.add, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .imm = Immediate.u(0x10) } }); | 872 | try enc.encode(.add, &.{ |
| 873 | .{ .reg = .rax }, | ||
| 874 | .{ .imm = Immediate.u(0x10) }, | ||
| 875 | }); | ||
| 880 | try expectEqualHexStrings("\x48\x83\xC0\x10", enc.code(), "add rax, 0x10"); | 876 | try expectEqualHexStrings("\x48\x83\xC0\x10", enc.code(), "add rax, 0x10"); |
| 881 | 877 | ||
| 882 | try enc.encode(.sbb, .{ .op1 = .{ .reg = .ax }, .op2 = .{ .imm = Immediate.u(0x10) } }); | 878 | try enc.encode(.sbb, &.{ |
| 879 | .{ .reg = .ax }, | ||
| 880 | .{ .imm = Immediate.u(0x10) }, | ||
| 881 | }); | ||
| 883 | try expectEqualHexStrings("\x66\x1D\x10\x00", enc.code(), "sbb ax, 0x10"); | 882 | try expectEqualHexStrings("\x66\x1D\x10\x00", enc.code(), "sbb ax, 0x10"); |
| 884 | 883 | ||
| 885 | try enc.encode(.xor, .{ .op1 = .{ .reg = .al }, .op2 = .{ .imm = Immediate.u(0x10) } }); | 884 | try enc.encode(.xor, &.{ |
| 885 | .{ .reg = .al }, | ||
| 886 | .{ .imm = Immediate.u(0x10) }, | ||
| 887 | }); | ||
| 886 | try expectEqualHexStrings("\x34\x10", enc.code(), "xor al, 0x10"); | 888 | try expectEqualHexStrings("\x34\x10", enc.code(), "xor al, 0x10"); |
| 887 | } | 889 | } |
| 888 | 890 | ||
| 889 | test "lower MI encoding" { | 891 | test "lower MI encoding" { |
| 890 | var enc = TestEncode{}; | 892 | var enc = TestEncode{}; |
| 891 | 893 | ||
| 892 | try enc.encode(.mov, .{ .op1 = .{ .reg = .r12 }, .op2 = .{ .imm = Immediate.u(0x1000) } }); | 894 | try enc.encode(.mov, &.{ |
| 895 | .{ .reg = .r12 }, | ||
| 896 | .{ .imm = Immediate.u(0x1000) }, | ||
| 897 | }); | ||
| 893 | try expectEqualHexStrings("\x49\xC7\xC4\x00\x10\x00\x00", enc.code(), "mov r12, 0x1000"); | 898 | try expectEqualHexStrings("\x49\xC7\xC4\x00\x10\x00\x00", enc.code(), "mov r12, 0x1000"); |
| 894 | 899 | ||
| 895 | try enc.encode(.mov, .{ | 900 | try enc.encode(.mov, &.{ |
| 896 | .op1 = .{ .mem = Memory.sib(.byte, .{ .base = .r12 }) }, | 901 | .{ .mem = Memory.sib(.byte, .{ .base = .r12 }) }, |
| 897 | .op2 = .{ .imm = Immediate.u(0x10) }, | 902 | .{ .imm = Immediate.u(0x10) }, |
| 898 | }); | 903 | }); |
| 899 | try expectEqualHexStrings("\x41\xC6\x04\x24\x10", enc.code(), "mov BYTE PTR [r12], 0x10"); | 904 | try expectEqualHexStrings("\x41\xC6\x04\x24\x10", enc.code(), "mov BYTE PTR [r12], 0x10"); |
| 900 | 905 | ||
| 901 | try enc.encode(.mov, .{ .op1 = .{ .reg = .r12 }, .op2 = .{ .imm = Immediate.u(0x1000) } }); | 906 | try enc.encode(.mov, &.{ |
| 907 | .{ .reg = .r12 }, | ||
| 908 | .{ .imm = Immediate.u(0x1000) }, | ||
| 909 | }); | ||
| 902 | try expectEqualHexStrings("\x49\xC7\xC4\x00\x10\x00\x00", enc.code(), "mov r12, 0x1000"); | 910 | try expectEqualHexStrings("\x49\xC7\xC4\x00\x10\x00\x00", enc.code(), "mov r12, 0x1000"); |
| 903 | 911 | ||
| 904 | try enc.encode(.mov, .{ .op1 = .{ .reg = .r12 }, .op2 = .{ .imm = Immediate.u(0x1000) } }); | 912 | try enc.encode(.mov, &.{ |
| 913 | .{ .reg = .r12 }, | ||
| 914 | .{ .imm = Immediate.u(0x1000) }, | ||
| 915 | }); | ||
| 905 | try expectEqualHexStrings("\x49\xC7\xC4\x00\x10\x00\x00", enc.code(), "mov r12, 0x1000"); | 916 | try expectEqualHexStrings("\x49\xC7\xC4\x00\x10\x00\x00", enc.code(), "mov r12, 0x1000"); |
| 906 | 917 | ||
| 907 | try enc.encode(.mov, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .imm = Immediate.u(0x10) } }); | 918 | try enc.encode(.mov, &.{ |
| 919 | .{ .reg = .rax }, | ||
| 920 | .{ .imm = Immediate.u(0x10) }, | ||
| 921 | }); | ||
| 908 | try expectEqualHexStrings("\x48\xc7\xc0\x10\x00\x00\x00", enc.code(), "mov rax, 0x10"); | 922 | try expectEqualHexStrings("\x48\xc7\xc0\x10\x00\x00\x00", enc.code(), "mov rax, 0x10"); |
| 909 | 923 | ||
| 910 | try enc.encode(.mov, .{ | 924 | try enc.encode(.mov, &.{ |
| 911 | .op1 = .{ .mem = Memory.sib(.dword, .{ .base = .r11 }) }, | 925 | .{ .mem = Memory.sib(.dword, .{ .base = .r11 }) }, |
| 912 | .op2 = .{ .imm = Immediate.u(0x10) }, | 926 | .{ .imm = Immediate.u(0x10) }, |
| 913 | }); | 927 | }); |
| 914 | try expectEqualHexStrings("\x41\xc7\x03\x10\x00\x00\x00", enc.code(), "mov DWORD PTR [r11], 0x10"); | 928 | try expectEqualHexStrings("\x41\xc7\x03\x10\x00\x00\x00", enc.code(), "mov DWORD PTR [r11], 0x10"); |
| 915 | 929 | ||
| 916 | try enc.encode(.mov, .{ | 930 | try enc.encode(.mov, &.{ |
| 917 | .op1 = .{ .mem = Memory.rip(.qword, 0x10) }, | 931 | .{ .mem = Memory.rip(.qword, 0x10) }, |
| 918 | .op2 = .{ .imm = Immediate.u(0x10) }, | 932 | .{ .imm = Immediate.u(0x10) }, |
| 919 | }); | 933 | }); |
| 920 | try expectEqualHexStrings( | 934 | try expectEqualHexStrings( |
| 921 | "\x48\xC7\x05\x10\x00\x00\x00\x10\x00\x00\x00", | 935 | "\x48\xC7\x05\x10\x00\x00\x00\x10\x00\x00\x00", |
| ... | @@ -923,99 +937,108 @@ test "lower MI encoding" { | ... | @@ -923,99 +937,108 @@ test "lower MI encoding" { |
| 923 | "mov QWORD PTR [rip + 0x10], 0x10", | 937 | "mov QWORD PTR [rip + 0x10], 0x10", |
| 924 | ); | 938 | ); |
| 925 | 939 | ||
| 926 | try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.qword, .{ | 940 | try enc.encode(.mov, &.{ |
| 927 | .base = .rbp, | 941 | .{ .mem = Memory.sib(.qword, .{ .base = .rbp, .disp = -8 }) }, |
| 928 | .disp = -8, | 942 | .{ .imm = Immediate.u(0x10) }, |
| 929 | }) }, .op2 = .{ .imm = Immediate.u(0x10) } }); | 943 | }); |
| 930 | try expectEqualHexStrings("\x48\xc7\x45\xf8\x10\x00\x00\x00", enc.code(), "mov QWORD PTR [rbp - 8], 0x10"); | 944 | try expectEqualHexStrings("\x48\xc7\x45\xf8\x10\x00\x00\x00", enc.code(), "mov QWORD PTR [rbp - 8], 0x10"); |
| 931 | 945 | ||
| 932 | try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.word, .{ | 946 | try enc.encode(.mov, &.{ |
| 933 | .base = .rbp, | 947 | .{ .mem = Memory.sib(.word, .{ .base = .rbp, .disp = -2 }) }, |
| 934 | .disp = -2, | 948 | .{ .imm = Immediate.s(-16) }, |
| 935 | }) }, .op2 = .{ .imm = Immediate.s(-16) } }); | 949 | }); |
| 936 | try expectEqualHexStrings("\x66\xC7\x45\xFE\xF0\xFF", enc.code(), "mov WORD PTR [rbp - 2], -16"); | 950 | try expectEqualHexStrings("\x66\xC7\x45\xFE\xF0\xFF", enc.code(), "mov WORD PTR [rbp - 2], -16"); |
| 937 | 951 | ||
| 938 | try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.byte, .{ | 952 | try enc.encode(.mov, &.{ |
| 939 | .base = .rbp, | 953 | .{ .mem = Memory.sib(.byte, .{ .base = .rbp, .disp = -1 }) }, |
| 940 | .disp = -1, | 954 | .{ .imm = Immediate.u(0x10) }, |
| 941 | }) }, .op2 = .{ .imm = Immediate.u(0x10) } }); | 955 | }); |
| 942 | try expectEqualHexStrings("\xC6\x45\xFF\x10", enc.code(), "mov BYTE PTR [rbp - 1], 0x10"); | 956 | try expectEqualHexStrings("\xC6\x45\xFF\x10", enc.code(), "mov BYTE PTR [rbp - 1], 0x10"); |
| 943 | 957 | ||
| 944 | try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.qword, .{ | 958 | try enc.encode(.mov, &.{ |
| 945 | .base = .ds, | 959 | .{ .mem = Memory.sib(.qword, .{ |
| 946 | .disp = 0x10000000, | 960 | .base = .ds, |
| 947 | .scale_index = .{ | 961 | .disp = 0x10000000, |
| 948 | .scale = 2, | 962 | .scale_index = .{ .scale = 2, .index = .rcx }, |
| 949 | .index = .rcx, | 963 | }) }, |
| 950 | }, | 964 | .{ .imm = Immediate.u(0x10) }, |
| 951 | }) }, .op2 = .{ .imm = Immediate.u(0x10) } }); | 965 | }); |
| 952 | try expectEqualHexStrings( | 966 | try expectEqualHexStrings( |
| 953 | "\x48\xC7\x04\x4D\x00\x00\x00\x10\x10\x00\x00\x00", | 967 | "\x48\xC7\x04\x4D\x00\x00\x00\x10\x10\x00\x00\x00", |
| 954 | enc.code(), | 968 | enc.code(), |
| 955 | "mov QWORD PTR [rcx*2 + 0x10000000], 0x10", | 969 | "mov QWORD PTR [rcx*2 + 0x10000000], 0x10", |
| 956 | ); | 970 | ); |
| 957 | 971 | ||
| 958 | try enc.encode(.adc, .{ .op1 = .{ .mem = Memory.sib(.byte, .{ | 972 | try enc.encode(.adc, &.{ |
| 959 | .base = .rbp, | 973 | .{ .mem = Memory.sib(.byte, .{ .base = .rbp, .disp = -0x10 }) }, |
| 960 | .disp = -0x10, | 974 | .{ .imm = Immediate.u(0x10) }, |
| 961 | }) }, .op2 = .{ .imm = Immediate.u(0x10) } }); | 975 | }); |
| 962 | try expectEqualHexStrings("\x80\x55\xF0\x10", enc.code(), "adc BYTE PTR [rbp - 0x10], 0x10"); | 976 | try expectEqualHexStrings("\x80\x55\xF0\x10", enc.code(), "adc BYTE PTR [rbp - 0x10], 0x10"); |
| 963 | 977 | ||
| 964 | try enc.encode(.adc, .{ .op1 = .{ .mem = Memory.rip(.qword, 0) }, .op2 = .{ .imm = Immediate.u(0x10) } }); | 978 | try enc.encode(.adc, &.{ |
| 979 | .{ .mem = Memory.rip(.qword, 0) }, | ||
| 980 | .{ .imm = Immediate.u(0x10) }, | ||
| 981 | }); | ||
| 965 | try expectEqualHexStrings("\x48\x83\x15\x00\x00\x00\x00\x10", enc.code(), "adc QWORD PTR [rip], 0x10"); | 982 | try expectEqualHexStrings("\x48\x83\x15\x00\x00\x00\x00\x10", enc.code(), "adc QWORD PTR [rip], 0x10"); |
| 966 | 983 | ||
| 967 | try enc.encode(.adc, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .imm = Immediate.u(0x10) } }); | 984 | try enc.encode(.adc, &.{ |
| 985 | .{ .reg = .rax }, | ||
| 986 | .{ .imm = Immediate.u(0x10) }, | ||
| 987 | }); | ||
| 968 | try expectEqualHexStrings("\x48\x83\xD0\x10", enc.code(), "adc rax, 0x10"); | 988 | try expectEqualHexStrings("\x48\x83\xD0\x10", enc.code(), "adc rax, 0x10"); |
| 969 | 989 | ||
| 970 | try enc.encode(.add, .{ .op1 = .{ .mem = Memory.sib(.dword, .{ | 990 | try enc.encode(.add, &.{ |
| 971 | .base = .rdx, | 991 | .{ .mem = Memory.sib(.dword, .{ .base = .rdx, .disp = -8 }) }, |
| 972 | .disp = -8, | 992 | .{ .imm = Immediate.u(0x10) }, |
| 973 | }) }, .op2 = .{ .imm = Immediate.u(0x10) } }); | 993 | }); |
| 974 | try expectEqualHexStrings("\x83\x42\xF8\x10", enc.code(), "add DWORD PTR [rdx - 8], 0x10"); | 994 | try expectEqualHexStrings("\x83\x42\xF8\x10", enc.code(), "add DWORD PTR [rdx - 8], 0x10"); |
| 975 | 995 | ||
| 976 | try enc.encode(.add, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .imm = Immediate.u(0x10) } }); | 996 | try enc.encode(.add, &.{ |
| 997 | .{ .reg = .rax }, | ||
| 998 | .{ .imm = Immediate.u(0x10) }, | ||
| 999 | }); | ||
| 977 | try expectEqualHexStrings("\x48\x83\xC0\x10", enc.code(), "add rax, 0x10"); | 1000 | try expectEqualHexStrings("\x48\x83\xC0\x10", enc.code(), "add rax, 0x10"); |
| 978 | 1001 | ||
| 979 | try enc.encode(.add, .{ .op1 = .{ .mem = Memory.sib(.qword, .{ | 1002 | try enc.encode(.add, &.{ |
| 980 | .base = .rbp, | 1003 | .{ .mem = Memory.sib(.qword, .{ .base = .rbp, .disp = -0x10 }) }, |
| 981 | .disp = -0x10, | 1004 | .{ .imm = Immediate.s(-0x10) }, |
| 982 | }) }, .op2 = .{ .imm = Immediate.s(-0x10) } }); | 1005 | }); |
| 983 | try expectEqualHexStrings("\x48\x83\x45\xF0\xF0", enc.code(), "add QWORD PTR [rbp - 0x10], -0x10"); | 1006 | try expectEqualHexStrings("\x48\x83\x45\xF0\xF0", enc.code(), "add QWORD PTR [rbp - 0x10], -0x10"); |
| 984 | 1007 | ||
| 985 | try enc.encode(.@"and", .{ .op1 = .{ .mem = Memory.sib(.dword, .{ | 1008 | try enc.encode(.@"and", &.{ |
| 986 | .base = .ds, | 1009 | .{ .mem = Memory.sib(.dword, .{ .base = .ds, .disp = 0x10000000 }) }, |
| 987 | .disp = 0x10000000, | 1010 | .{ .imm = Immediate.u(0x10) }, |
| 988 | }) }, .op2 = .{ .imm = Immediate.u(0x10) } }); | 1011 | }); |
| 989 | try expectEqualHexStrings( | 1012 | try expectEqualHexStrings( |
| 990 | "\x83\x24\x25\x00\x00\x00\x10\x10", | 1013 | "\x83\x24\x25\x00\x00\x00\x10\x10", |
| 991 | enc.code(), | 1014 | enc.code(), |
| 992 | "and DWORD PTR ds:0x10000000, 0x10", | 1015 | "and DWORD PTR ds:0x10000000, 0x10", |
| 993 | ); | 1016 | ); |
| 994 | 1017 | ||
| 995 | try enc.encode(.@"and", .{ .op1 = .{ .mem = Memory.sib(.dword, .{ | 1018 | try enc.encode(.@"and", &.{ |
| 996 | .base = .es, | 1019 | .{ .mem = Memory.sib(.dword, .{ .base = .es, .disp = 0x10000000 }) }, |
| 997 | .disp = 0x10000000, | 1020 | .{ .imm = Immediate.u(0x10) }, |
| 998 | }) }, .op2 = .{ .imm = Immediate.u(0x10) } }); | 1021 | }); |
| 999 | try expectEqualHexStrings( | 1022 | try expectEqualHexStrings( |
| 1000 | "\x26\x83\x24\x25\x00\x00\x00\x10\x10", | 1023 | "\x26\x83\x24\x25\x00\x00\x00\x10\x10", |
| 1001 | enc.code(), | 1024 | enc.code(), |
| 1002 | "and DWORD PTR es:0x10000000, 0x10", | 1025 | "and DWORD PTR es:0x10000000, 0x10", |
| 1003 | ); | 1026 | ); |
| 1004 | 1027 | ||
| 1005 | try enc.encode(.@"and", .{ .op1 = .{ .mem = Memory.sib(.dword, .{ | 1028 | try enc.encode(.@"and", &.{ |
| 1006 | .base = .r12, | 1029 | .{ .mem = Memory.sib(.dword, .{ .base = .r12, .disp = 0x10000000 }) }, |
| 1007 | .disp = 0x10000000, | 1030 | .{ .imm = Immediate.u(0x10) }, |
| 1008 | }) }, .op2 = .{ .imm = Immediate.u(0x10) } }); | 1031 | }); |
| 1009 | try expectEqualHexStrings( | 1032 | try expectEqualHexStrings( |
| 1010 | "\x41\x83\xA4\x24\x00\x00\x00\x10\x10", | 1033 | "\x41\x83\xA4\x24\x00\x00\x00\x10\x10", |
| 1011 | enc.code(), | 1034 | enc.code(), |
| 1012 | "and DWORD PTR [r12 + 0x10000000], 0x10", | 1035 | "and DWORD PTR [r12 + 0x10000000], 0x10", |
| 1013 | ); | 1036 | ); |
| 1014 | 1037 | ||
| 1015 | try enc.encode(.sub, .{ .op1 = .{ .mem = Memory.sib(.dword, .{ | 1038 | try enc.encode(.sub, &.{ |
| 1016 | .base = .r11, | 1039 | .{ .mem = Memory.sib(.dword, .{ .base = .r11, .disp = 0x10000000 }) }, |
| 1017 | .disp = 0x10000000, | 1040 | .{ .imm = Immediate.u(0x10) }, |
| 1018 | }) }, .op2 = .{ .imm = Immediate.u(0x10) } }); | 1041 | }); |
| 1019 | try expectEqualHexStrings( | 1042 | try expectEqualHexStrings( |
| 1020 | "\x41\x83\xAB\x00\x00\x00\x10\x10", | 1043 | "\x41\x83\xAB\x00\x00\x00\x10\x10", |
| 1021 | enc.code(), | 1044 | enc.code(), |
| ... | @@ -1026,185 +1049,227 @@ test "lower MI encoding" { | ... | @@ -1026,185 +1049,227 @@ test "lower MI encoding" { |
| 1026 | test "lower RM encoding" { | 1049 | test "lower RM encoding" { |
| 1027 | var enc = TestEncode{}; | 1050 | var enc = TestEncode{}; |
| 1028 | 1051 | ||
| 1029 | try enc.encode(.mov, .{ | 1052 | try enc.encode(.mov, &.{ |
| 1030 | .op1 = .{ .reg = .rax }, | 1053 | .{ .reg = .rax }, |
| 1031 | .op2 = .{ .mem = Memory.sib(.qword, .{ .base = .r11 }) }, | 1054 | .{ .mem = Memory.sib(.qword, .{ .base = .r11 }) }, |
| 1032 | }); | 1055 | }); |
| 1033 | try expectEqualHexStrings("\x49\x8b\x03", enc.code(), "mov rax, QWORD PTR [r11]"); | 1056 | try expectEqualHexStrings("\x49\x8b\x03", enc.code(), "mov rax, QWORD PTR [r11]"); |
| 1034 | 1057 | ||
| 1035 | try enc.encode(.mov, .{ .op1 = .{ .reg = .rbx }, .op2 = .{ .mem = Memory.sib(.qword, .{ | 1058 | try enc.encode(.mov, &.{ |
| 1036 | .base = .ds, | 1059 | .{ .reg = .rbx }, |
| 1037 | .disp = 0x10, | 1060 | .{ .mem = Memory.sib(.qword, .{ .base = .ds, .disp = 0x10 }) }, |
| 1038 | }) } }); | 1061 | }); |
| 1039 | try expectEqualHexStrings("\x48\x8B\x1C\x25\x10\x00\x00\x00", enc.code(), "mov rbx, QWORD PTR ds:0x10"); | 1062 | try expectEqualHexStrings("\x48\x8B\x1C\x25\x10\x00\x00\x00", enc.code(), "mov rbx, QWORD PTR ds:0x10"); |
| 1040 | 1063 | ||
| 1041 | try enc.encode(.mov, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .mem = Memory.sib(.qword, .{ | 1064 | try enc.encode(.mov, &.{ |
| 1042 | .base = .rbp, | 1065 | .{ .reg = .rax }, |
| 1043 | .disp = -4, | 1066 | .{ .mem = Memory.sib(.qword, .{ .base = .rbp, .disp = -4 }) }, |
| 1044 | }) } }); | 1067 | }); |
| 1045 | try expectEqualHexStrings("\x48\x8B\x45\xFC", enc.code(), "mov rax, QWORD PTR [rbp - 4]"); | 1068 | try expectEqualHexStrings("\x48\x8B\x45\xFC", enc.code(), "mov rax, QWORD PTR [rbp - 4]"); |
| 1046 | 1069 | ||
| 1047 | try enc.encode(.mov, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .mem = Memory.sib(.qword, .{ | 1070 | try enc.encode(.mov, &.{ |
| 1048 | .base = .rbp, | 1071 | .{ .reg = .rax }, |
| 1049 | .scale_index = .{ | 1072 | .{ .mem = Memory.sib(.qword, .{ |
| 1050 | .scale = 1, | 1073 | .base = .rbp, |
| 1051 | .index = .rcx, | 1074 | .scale_index = .{ .scale = 1, .index = .rcx }, |
| 1052 | }, | 1075 | .disp = -8, |
| 1053 | .disp = -8, | 1076 | }) }, |
| 1054 | }) } }); | 1077 | }); |
| 1055 | try expectEqualHexStrings("\x48\x8B\x44\x0D\xF8", enc.code(), "mov rax, QWORD PTR [rbp + rcx*1 - 8]"); | 1078 | try expectEqualHexStrings("\x48\x8B\x44\x0D\xF8", enc.code(), "mov rax, QWORD PTR [rbp + rcx*1 - 8]"); |
| 1056 | 1079 | ||
| 1057 | try enc.encode(.mov, .{ .op1 = .{ .reg = .eax }, .op2 = .{ .mem = Memory.sib(.dword, .{ | 1080 | try enc.encode(.mov, &.{ |
| 1058 | .base = .rbp, | 1081 | .{ .reg = .eax }, |
| 1059 | .scale_index = .{ | 1082 | .{ .mem = Memory.sib(.dword, .{ |
| 1060 | .scale = 4, | 1083 | .base = .rbp, |
| 1061 | .index = .rdx, | 1084 | .scale_index = .{ .scale = 4, .index = .rdx }, |
| 1062 | }, | 1085 | .disp = -4, |
| 1063 | .disp = -4, | 1086 | }) }, |
| 1064 | }) } }); | 1087 | }); |
| 1065 | try expectEqualHexStrings("\x8B\x44\x95\xFC", enc.code(), "mov eax, dword ptr [rbp + rdx*4 - 4]"); | 1088 | try expectEqualHexStrings("\x8B\x44\x95\xFC", enc.code(), "mov eax, dword ptr [rbp + rdx*4 - 4]"); |
| 1066 | 1089 | ||
| 1067 | try enc.encode(.mov, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .mem = Memory.sib(.qword, .{ | 1090 | try enc.encode(.mov, &.{ |
| 1068 | .base = .rbp, | 1091 | .{ .reg = .rax }, |
| 1069 | .scale_index = .{ | 1092 | .{ .mem = Memory.sib(.qword, .{ |
| 1070 | .scale = 8, | 1093 | .base = .rbp, |
| 1071 | .index = .rcx, | 1094 | .scale_index = .{ .scale = 8, .index = .rcx }, |
| 1072 | }, | 1095 | .disp = -8, |
| 1073 | .disp = -8, | 1096 | }) }, |
| 1074 | }) } }); | 1097 | }); |
| 1075 | try expectEqualHexStrings("\x48\x8B\x44\xCD\xF8", enc.code(), "mov rax, QWORD PTR [rbp + rcx*8 - 8]"); | 1098 | try expectEqualHexStrings("\x48\x8B\x44\xCD\xF8", enc.code(), "mov rax, QWORD PTR [rbp + rcx*8 - 8]"); |
| 1076 | 1099 | ||
| 1077 | try enc.encode(.mov, .{ .op1 = .{ .reg = .r8b }, .op2 = .{ .mem = Memory.sib(.byte, .{ | 1100 | try enc.encode(.mov, &.{ |
| 1078 | .base = .rsi, | 1101 | .{ .reg = .r8b }, |
| 1079 | .scale_index = .{ | 1102 | .{ .mem = Memory.sib(.byte, .{ |
| 1080 | .scale = 1, | 1103 | .base = .rsi, |
| 1081 | .index = .rcx, | 1104 | .scale_index = .{ .scale = 1, .index = .rcx }, |
| 1082 | }, | 1105 | .disp = -24, |
| 1083 | .disp = -24, | 1106 | }) }, |
| 1084 | }) } }); | 1107 | }); |
| 1085 | try expectEqualHexStrings("\x44\x8A\x44\x0E\xE8", enc.code(), "mov r8b, BYTE PTR [rsi + rcx*1 - 24]"); | 1108 | try expectEqualHexStrings("\x44\x8A\x44\x0E\xE8", enc.code(), "mov r8b, BYTE PTR [rsi + rcx*1 - 24]"); |
| 1086 | 1109 | ||
| 1087 | // TODO this mnemonic needs cleanup as some prefixes are obsolete. | 1110 | // TODO this mnemonic needs cleanup as some prefixes are obsolete. |
| 1088 | try enc.encode(.mov, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .reg = .cs } }); | 1111 | try enc.encode(.mov, &.{ |
| 1112 | .{ .reg = .rax }, | ||
| 1113 | .{ .reg = .cs }, | ||
| 1114 | }); | ||
| 1089 | try expectEqualHexStrings("\x48\x8C\xC8", enc.code(), "mov rax, cs"); | 1115 | try expectEqualHexStrings("\x48\x8C\xC8", enc.code(), "mov rax, cs"); |
| 1090 | 1116 | ||
| 1091 | try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.qword, .{ | 1117 | try enc.encode(.mov, &.{ |
| 1092 | .base = .rbp, | 1118 | .{ .mem = Memory.sib(.qword, .{ .base = .rbp, .disp = -16 }) }, |
| 1093 | .disp = -16, | 1119 | .{ .reg = .fs }, |
| 1094 | }) }, .op2 = .{ .reg = .fs } }); | 1120 | }); |
| 1095 | try expectEqualHexStrings("\x48\x8C\x65\xF0", enc.code(), "mov QWORD PTR [rbp - 16], fs"); | 1121 | try expectEqualHexStrings("\x48\x8C\x65\xF0", enc.code(), "mov QWORD PTR [rbp - 16], fs"); |
| 1096 | 1122 | ||
| 1097 | try enc.encode(.mov, .{ .op1 = .{ .reg = .r12w }, .op2 = .{ .reg = .cs } }); | 1123 | try enc.encode(.mov, &.{ |
| 1124 | .{ .reg = .r12w }, | ||
| 1125 | .{ .reg = .cs }, | ||
| 1126 | }); | ||
| 1098 | try expectEqualHexStrings("\x66\x41\x8C\xCC", enc.code(), "mov r12w, cs"); | 1127 | try expectEqualHexStrings("\x66\x41\x8C\xCC", enc.code(), "mov r12w, cs"); |
| 1099 | 1128 | ||
| 1100 | try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.word, .{ | 1129 | try enc.encode(.mov, &.{ |
| 1101 | .base = .rbp, | 1130 | .{ .mem = Memory.sib(.word, .{ .base = .rbp, .disp = -16 }) }, |
| 1102 | .disp = -16, | 1131 | .{ .reg = .fs }, |
| 1103 | }) }, .op2 = .{ .reg = .fs } }); | 1132 | }); |
| 1104 | try expectEqualHexStrings("\x66\x8C\x65\xF0", enc.code(), "mov WORD PTR [rbp - 16], fs"); | 1133 | try expectEqualHexStrings("\x66\x8C\x65\xF0", enc.code(), "mov WORD PTR [rbp - 16], fs"); |
| 1105 | 1134 | ||
| 1106 | try enc.encode(.movsx, .{ .op1 = .{ .reg = .eax }, .op2 = .{ .reg = .bx } }); | 1135 | try enc.encode(.movsx, &.{ |
| 1136 | .{ .reg = .eax }, | ||
| 1137 | .{ .reg = .bx }, | ||
| 1138 | }); | ||
| 1107 | try expectEqualHexStrings("\x0F\xBF\xC3", enc.code(), "movsx eax, bx"); | 1139 | try expectEqualHexStrings("\x0F\xBF\xC3", enc.code(), "movsx eax, bx"); |
| 1108 | 1140 | ||
| 1109 | try enc.encode(.movsx, .{ .op1 = .{ .reg = .eax }, .op2 = .{ .reg = .bl } }); | 1141 | try enc.encode(.movsx, &.{ |
| 1142 | .{ .reg = .eax }, | ||
| 1143 | .{ .reg = .bl }, | ||
| 1144 | }); | ||
| 1110 | try expectEqualHexStrings("\x0F\xBE\xC3", enc.code(), "movsx eax, bl"); | 1145 | try expectEqualHexStrings("\x0F\xBE\xC3", enc.code(), "movsx eax, bl"); |
| 1111 | 1146 | ||
| 1112 | try enc.encode(.movsx, .{ .op1 = .{ .reg = .ax }, .op2 = .{ .reg = .bl } }); | 1147 | try enc.encode(.movsx, &.{ |
| 1148 | .{ .reg = .ax }, | ||
| 1149 | .{ .reg = .bl }, | ||
| 1150 | }); | ||
| 1113 | try expectEqualHexStrings("\x66\x0F\xBE\xC3", enc.code(), "movsx ax, bl"); | 1151 | try expectEqualHexStrings("\x66\x0F\xBE\xC3", enc.code(), "movsx ax, bl"); |
| 1114 | 1152 | ||
| 1115 | try enc.encode(.movsx, .{ | 1153 | try enc.encode(.movsx, &.{ |
| 1116 | .op1 = .{ .reg = .eax }, | 1154 | .{ .reg = .eax }, |
| 1117 | .op2 = .{ .mem = Memory.sib(.word, .{ .base = .rbp }) }, | 1155 | .{ .mem = Memory.sib(.word, .{ .base = .rbp }) }, |
| 1118 | }); | 1156 | }); |
| 1119 | try expectEqualHexStrings("\x0F\xBF\x45\x00", enc.code(), "movsx eax, BYTE PTR [rbp]"); | 1157 | try expectEqualHexStrings("\x0F\xBF\x45\x00", enc.code(), "movsx eax, BYTE PTR [rbp]"); |
| 1120 | 1158 | ||
| 1121 | try enc.encode(.movsx, .{ | 1159 | try enc.encode(.movsx, &.{ |
| 1122 | .op1 = .{ .reg = .eax }, | 1160 | .{ .reg = .eax }, |
| 1123 | .op2 = .{ .mem = Memory.sib(.byte, .{ .scale_index = .{ .index = .rax, .scale = 2 } }) }, | 1161 | .{ .mem = Memory.sib(.byte, .{ .scale_index = .{ .index = .rax, .scale = 2 } }) }, |
| 1124 | }); | 1162 | }); |
| 1125 | try expectEqualHexStrings("\x0F\xBE\x04\x45\x00\x00\x00\x00", enc.code(), "movsx eax, BYTE PTR [rax * 2]"); | 1163 | try expectEqualHexStrings("\x0F\xBE\x04\x45\x00\x00\x00\x00", enc.code(), "movsx eax, BYTE PTR [rax * 2]"); |
| 1126 | 1164 | ||
| 1127 | try enc.encode(.movsx, .{ .op1 = .{ .reg = .ax }, .op2 = .{ .mem = Memory.rip(.byte, 0x10) } }); | 1165 | try enc.encode(.movsx, &.{ |
| 1166 | .{ .reg = .ax }, | ||
| 1167 | .{ .mem = Memory.rip(.byte, 0x10) }, | ||
| 1168 | }); | ||
| 1128 | try expectEqualHexStrings("\x66\x0F\xBE\x05\x10\x00\x00\x00", enc.code(), "movsx ax, BYTE PTR [rip + 0x10]"); | 1169 | try expectEqualHexStrings("\x66\x0F\xBE\x05\x10\x00\x00\x00", enc.code(), "movsx ax, BYTE PTR [rip + 0x10]"); |
| 1129 | 1170 | ||
| 1130 | try enc.encode(.movsx, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .reg = .bx } }); | 1171 | try enc.encode(.movsx, &.{ |
| 1172 | .{ .reg = .rax }, | ||
| 1173 | .{ .reg = .bx }, | ||
| 1174 | }); | ||
| 1131 | try expectEqualHexStrings("\x48\x0F\xBF\xC3", enc.code(), "movsx rax, bx"); | 1175 | try expectEqualHexStrings("\x48\x0F\xBF\xC3", enc.code(), "movsx rax, bx"); |
| 1132 | 1176 | ||
| 1133 | try enc.encode(.movsxd, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .reg = .ebx } }); | 1177 | try enc.encode(.movsxd, &.{ |
| 1178 | .{ .reg = .rax }, | ||
| 1179 | .{ .reg = .ebx }, | ||
| 1180 | }); | ||
| 1134 | try expectEqualHexStrings("\x48\x63\xC3", enc.code(), "movsxd rax, ebx"); | 1181 | try expectEqualHexStrings("\x48\x63\xC3", enc.code(), "movsxd rax, ebx"); |
| 1135 | 1182 | ||
| 1136 | try enc.encode(.lea, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .mem = Memory.rip(.qword, 0x10) } }); | 1183 | try enc.encode(.lea, &.{ |
| 1184 | .{ .reg = .rax }, | ||
| 1185 | .{ .mem = Memory.rip(.qword, 0x10) }, | ||
| 1186 | }); | ||
| 1137 | try expectEqualHexStrings("\x48\x8D\x05\x10\x00\x00\x00", enc.code(), "lea rax, QWORD PTR [rip + 0x10]"); | 1187 | try expectEqualHexStrings("\x48\x8D\x05\x10\x00\x00\x00", enc.code(), "lea rax, QWORD PTR [rip + 0x10]"); |
| 1138 | 1188 | ||
| 1139 | try enc.encode(.lea, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .mem = Memory.rip(.dword, 0x10) } }); | 1189 | try enc.encode(.lea, &.{ |
| 1190 | .{ .reg = .rax }, | ||
| 1191 | .{ .mem = Memory.rip(.dword, 0x10) }, | ||
| 1192 | }); | ||
| 1140 | try expectEqualHexStrings("\x48\x8D\x05\x10\x00\x00\x00", enc.code(), "lea rax, DWORD PTR [rip + 0x10]"); | 1193 | try expectEqualHexStrings("\x48\x8D\x05\x10\x00\x00\x00", enc.code(), "lea rax, DWORD PTR [rip + 0x10]"); |
| 1141 | 1194 | ||
| 1142 | try enc.encode(.lea, .{ .op1 = .{ .reg = .eax }, .op2 = .{ .mem = Memory.rip(.dword, 0x10) } }); | 1195 | try enc.encode(.lea, &.{ |
| 1196 | .{ .reg = .eax }, | ||
| 1197 | .{ .mem = Memory.rip(.dword, 0x10) }, | ||
| 1198 | }); | ||
| 1143 | try expectEqualHexStrings("\x8D\x05\x10\x00\x00\x00", enc.code(), "lea eax, DWORD PTR [rip + 0x10]"); | 1199 | try expectEqualHexStrings("\x8D\x05\x10\x00\x00\x00", enc.code(), "lea eax, DWORD PTR [rip + 0x10]"); |
| 1144 | 1200 | ||
| 1145 | try enc.encode(.lea, .{ .op1 = .{ .reg = .eax }, .op2 = .{ .mem = Memory.rip(.word, 0x10) } }); | 1201 | try enc.encode(.lea, &.{ |
| 1202 | .{ .reg = .eax }, | ||
| 1203 | .{ .mem = Memory.rip(.word, 0x10) }, | ||
| 1204 | }); | ||
| 1146 | try expectEqualHexStrings("\x8D\x05\x10\x00\x00\x00", enc.code(), "lea eax, WORD PTR [rip + 0x10]"); | 1205 | try expectEqualHexStrings("\x8D\x05\x10\x00\x00\x00", enc.code(), "lea eax, WORD PTR [rip + 0x10]"); |
| 1147 | 1206 | ||
| 1148 | try enc.encode(.lea, .{ .op1 = .{ .reg = .ax }, .op2 = .{ .mem = Memory.rip(.byte, 0x10) } }); | 1207 | try enc.encode(.lea, &.{ |
| 1208 | .{ .reg = .ax }, | ||
| 1209 | .{ .mem = Memory.rip(.byte, 0x10) }, | ||
| 1210 | }); | ||
| 1149 | try expectEqualHexStrings("\x66\x8D\x05\x10\x00\x00\x00", enc.code(), "lea ax, BYTE PTR [rip + 0x10]"); | 1211 | try expectEqualHexStrings("\x66\x8D\x05\x10\x00\x00\x00", enc.code(), "lea ax, BYTE PTR [rip + 0x10]"); |
| 1150 | 1212 | ||
| 1151 | try enc.encode(.lea, .{ | 1213 | try enc.encode(.lea, &.{ |
| 1152 | .op1 = .{ .reg = .rsi }, | 1214 | .{ .reg = .rsi }, |
| 1153 | .op2 = .{ .mem = Memory.sib(.qword, .{ | 1215 | .{ .mem = Memory.sib(.qword, .{ |
| 1154 | .base = .rbp, | 1216 | .base = .rbp, |
| 1155 | .scale_index = .{ .scale = 1, .index = .rcx }, | 1217 | .scale_index = .{ .scale = 1, .index = .rcx }, |
| 1156 | }) }, | 1218 | }) }, |
| 1157 | }); | 1219 | }); |
| 1158 | try expectEqualHexStrings("\x48\x8D\x74\x0D\x00", enc.code(), "lea rsi, QWORD PTR [rbp + rcx*1 + 0]"); | 1220 | try expectEqualHexStrings("\x48\x8D\x74\x0D\x00", enc.code(), "lea rsi, QWORD PTR [rbp + rcx*1 + 0]"); |
| 1159 | 1221 | ||
| 1160 | try enc.encode(.add, .{ .op1 = .{ .reg = .r11 }, .op2 = .{ .mem = Memory.sib(.qword, .{ | 1222 | try enc.encode(.add, &.{ |
| 1161 | .base = .ds, | 1223 | .{ .reg = .r11 }, |
| 1162 | .disp = 0x10000000, | 1224 | .{ .mem = Memory.sib(.qword, .{ .base = .ds, .disp = 0x10000000 }) }, |
| 1163 | }) } }); | 1225 | }); |
| 1164 | try expectEqualHexStrings("\x4C\x03\x1C\x25\x00\x00\x00\x10", enc.code(), "add r11, QWORD PTR ds:0x10000000"); | 1226 | try expectEqualHexStrings("\x4C\x03\x1C\x25\x00\x00\x00\x10", enc.code(), "add r11, QWORD PTR ds:0x10000000"); |
| 1165 | 1227 | ||
| 1166 | try enc.encode(.add, .{ .op1 = .{ .reg = .r12b }, .op2 = .{ .mem = Memory.sib(.byte, .{ | 1228 | try enc.encode(.add, &.{ |
| 1167 | .base = .ds, | 1229 | .{ .reg = .r12b }, |
| 1168 | .disp = 0x10000000, | 1230 | .{ .mem = Memory.sib(.byte, .{ .base = .ds, .disp = 0x10000000 }) }, |
| 1169 | }) } }); | 1231 | }); |
| 1170 | try expectEqualHexStrings("\x44\x02\x24\x25\x00\x00\x00\x10", enc.code(), "add r11b, BYTE PTR ds:0x10000000"); | 1232 | try expectEqualHexStrings("\x44\x02\x24\x25\x00\x00\x00\x10", enc.code(), "add r11b, BYTE PTR ds:0x10000000"); |
| 1171 | 1233 | ||
| 1172 | try enc.encode(.add, .{ .op1 = .{ .reg = .r12b }, .op2 = .{ .mem = Memory.sib(.byte, .{ | 1234 | try enc.encode(.add, &.{ |
| 1173 | .base = .fs, | 1235 | .{ .reg = .r12b }, |
| 1174 | .disp = 0x10000000, | 1236 | .{ .mem = Memory.sib(.byte, .{ .base = .fs, .disp = 0x10000000 }) }, |
| 1175 | }) } }); | 1237 | }); |
| 1176 | try expectEqualHexStrings("\x64\x44\x02\x24\x25\x00\x00\x00\x10", enc.code(), "add r11b, BYTE PTR fs:0x10000000"); | 1238 | try expectEqualHexStrings("\x64\x44\x02\x24\x25\x00\x00\x00\x10", enc.code(), "add r11b, BYTE PTR fs:0x10000000"); |
| 1177 | 1239 | ||
| 1178 | try enc.encode(.sub, .{ .op1 = .{ .reg = .r11 }, .op2 = .{ .mem = Memory.sib(.qword, .{ | 1240 | try enc.encode(.sub, &.{ |
| 1179 | .base = .r13, | 1241 | .{ .reg = .r11 }, |
| 1180 | .disp = 0x10000000, | 1242 | .{ .mem = Memory.sib(.qword, .{ .base = .r13, .disp = 0x10000000 }) }, |
| 1181 | }) } }); | 1243 | }); |
| 1182 | try expectEqualHexStrings("\x4D\x2B\x9D\x00\x00\x00\x10", enc.code(), "sub r11, QWORD PTR [r13 + 0x10000000]"); | 1244 | try expectEqualHexStrings("\x4D\x2B\x9D\x00\x00\x00\x10", enc.code(), "sub r11, QWORD PTR [r13 + 0x10000000]"); |
| 1183 | 1245 | ||
| 1184 | try enc.encode(.sub, .{ .op1 = .{ .reg = .r11 }, .op2 = .{ .mem = Memory.sib(.qword, .{ | 1246 | try enc.encode(.sub, &.{ |
| 1185 | .base = .r12, | 1247 | .{ .reg = .r11 }, |
| 1186 | .disp = 0x10000000, | 1248 | .{ .mem = Memory.sib(.qword, .{ .base = .r12, .disp = 0x10000000 }) }, |
| 1187 | }) } }); | 1249 | }); |
| 1188 | try expectEqualHexStrings("\x4D\x2B\x9C\x24\x00\x00\x00\x10", enc.code(), "sub r11, QWORD PTR [r12 + 0x10000000]"); | 1250 | try expectEqualHexStrings("\x4D\x2B\x9C\x24\x00\x00\x00\x10", enc.code(), "sub r11, QWORD PTR [r12 + 0x10000000]"); |
| 1189 | 1251 | ||
| 1190 | try enc.encode(.imul, .{ .op1 = .{ .reg = .r11 }, .op2 = .{ .reg = .r12 } }); | 1252 | try enc.encode(.imul, &.{ |
| 1253 | .{ .reg = .r11 }, | ||
| 1254 | .{ .reg = .r12 }, | ||
| 1255 | }); | ||
| 1191 | try expectEqualHexStrings("\x4D\x0F\xAF\xDC", enc.code(), "mov r11, r12"); | 1256 | try expectEqualHexStrings("\x4D\x0F\xAF\xDC", enc.code(), "mov r11, r12"); |
| 1192 | } | 1257 | } |
| 1193 | 1258 | ||
| 1194 | test "lower RMI encoding" { | 1259 | test "lower RMI encoding" { |
| 1195 | var enc = TestEncode{}; | 1260 | var enc = TestEncode{}; |
| 1196 | 1261 | ||
| 1197 | try enc.encode(.imul, .{ | 1262 | try enc.encode(.imul, &.{ |
| 1198 | .op1 = .{ .reg = .r11 }, | 1263 | .{ .reg = .r11 }, |
| 1199 | .op2 = .{ .reg = .r12 }, | 1264 | .{ .reg = .r12 }, |
| 1200 | .op3 = .{ .imm = Immediate.s(-2) }, | 1265 | .{ .imm = Immediate.s(-2) }, |
| 1201 | }); | 1266 | }); |
| 1202 | try expectEqualHexStrings("\x4D\x6B\xDC\xFE", enc.code(), "imul r11, r12, -2"); | 1267 | try expectEqualHexStrings("\x4D\x6B\xDC\xFE", enc.code(), "imul r11, r12, -2"); |
| 1203 | 1268 | ||
| 1204 | try enc.encode(.imul, .{ | 1269 | try enc.encode(.imul, &.{ |
| 1205 | .op1 = .{ .reg = .r11 }, | 1270 | .{ .reg = .r11 }, |
| 1206 | .op2 = .{ .mem = Memory.rip(.qword, -16) }, | 1271 | .{ .mem = Memory.rip(.qword, -16) }, |
| 1207 | .op3 = .{ .imm = Immediate.s(-1024) }, | 1272 | .{ .imm = Immediate.s(-1024) }, |
| 1208 | }); | 1273 | }); |
| 1209 | try expectEqualHexStrings( | 1274 | try expectEqualHexStrings( |
| 1210 | "\x4C\x69\x1D\xF0\xFF\xFF\xFF\x00\xFC\xFF\xFF", | 1275 | "\x4C\x69\x1D\xF0\xFF\xFF\xFF\x00\xFC\xFF\xFF", |
| ... | @@ -1212,13 +1277,10 @@ test "lower RMI encoding" { | ... | @@ -1212,13 +1277,10 @@ test "lower RMI encoding" { |
| 1212 | "imul r11, QWORD PTR [rip - 16], -1024", | 1277 | "imul r11, QWORD PTR [rip - 16], -1024", |
| 1213 | ); | 1278 | ); |
| 1214 | 1279 | ||
| 1215 | try enc.encode(.imul, .{ | 1280 | try enc.encode(.imul, &.{ |
| 1216 | .op1 = .{ .reg = .bx }, | 1281 | .{ .reg = .bx }, |
| 1217 | .op2 = .{ .mem = Memory.sib(.word, .{ | 1282 | .{ .mem = Memory.sib(.word, .{ .base = .rbp, .disp = -16 }) }, |
| 1218 | .base = .rbp, | 1283 | .{ .imm = Immediate.s(-1024) }, |
| 1219 | .disp = -16, | ||
| 1220 | }) }, | ||
| 1221 | .op3 = .{ .imm = Immediate.s(-1024) }, | ||
| 1222 | }); | 1284 | }); |
| 1223 | try expectEqualHexStrings( | 1285 | try expectEqualHexStrings( |
| 1224 | "\x66\x69\x5D\xF0\x00\xFC", | 1286 | "\x66\x69\x5D\xF0\x00\xFC", |
| ... | @@ -1226,13 +1288,10 @@ test "lower RMI encoding" { | ... | @@ -1226,13 +1288,10 @@ test "lower RMI encoding" { |
| 1226 | "imul bx, WORD PTR [rbp - 16], -1024", | 1288 | "imul bx, WORD PTR [rbp - 16], -1024", |
| 1227 | ); | 1289 | ); |
| 1228 | 1290 | ||
| 1229 | try enc.encode(.imul, .{ | 1291 | try enc.encode(.imul, &.{ |
| 1230 | .op1 = .{ .reg = .bx }, | 1292 | .{ .reg = .bx }, |
| 1231 | .op2 = .{ .mem = Memory.sib(.word, .{ | 1293 | .{ .mem = Memory.sib(.word, .{ .base = .rbp, .disp = -16 }) }, |
| 1232 | .base = .rbp, | 1294 | .{ .imm = Immediate.u(1024) }, |
| 1233 | .disp = -16, | ||
| 1234 | }) }, | ||
| 1235 | .op3 = .{ .imm = Immediate.u(1024) }, | ||
| 1236 | }); | 1295 | }); |
| 1237 | try expectEqualHexStrings( | 1296 | try expectEqualHexStrings( |
| 1238 | "\x66\x69\x5D\xF0\x00\x04", | 1297 | "\x66\x69\x5D\xF0\x00\x04", |
| ... | @@ -1244,238 +1303,343 @@ test "lower RMI encoding" { | ... | @@ -1244,238 +1303,343 @@ test "lower RMI encoding" { |
| 1244 | test "lower MR encoding" { | 1303 | test "lower MR encoding" { |
| 1245 | var enc = TestEncode{}; | 1304 | var enc = TestEncode{}; |
| 1246 | 1305 | ||
| 1247 | try enc.encode(.mov, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .reg = .rbx } }); | 1306 | try enc.encode(.mov, &.{ |
| 1307 | .{ .reg = .rax }, | ||
| 1308 | .{ .reg = .rbx }, | ||
| 1309 | }); | ||
| 1248 | try expectEqualHexStrings("\x48\x89\xD8", enc.code(), "mov rax, rbx"); | 1310 | try expectEqualHexStrings("\x48\x89\xD8", enc.code(), "mov rax, rbx"); |
| 1249 | 1311 | ||
| 1250 | try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.qword, .{ | 1312 | try enc.encode(.mov, &.{ |
| 1251 | .base = .rbp, | 1313 | .{ .mem = Memory.sib(.qword, .{ .base = .rbp, .disp = -4 }) }, |
| 1252 | .disp = -4, | 1314 | .{ .reg = .r11 }, |
| 1253 | }) }, .op2 = .{ .reg = .r11 } }); | 1315 | }); |
| 1254 | try expectEqualHexStrings("\x4c\x89\x5d\xfc", enc.code(), "mov QWORD PTR [rbp - 4], r11"); | 1316 | try expectEqualHexStrings("\x4c\x89\x5d\xfc", enc.code(), "mov QWORD PTR [rbp - 4], r11"); |
| 1255 | 1317 | ||
| 1256 | try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.rip(.qword, 0x10) }, .op2 = .{ .reg = .r12 } }); | 1318 | try enc.encode(.mov, &.{ |
| 1319 | .{ .mem = Memory.rip(.qword, 0x10) }, | ||
| 1320 | .{ .reg = .r12 }, | ||
| 1321 | }); | ||
| 1257 | try expectEqualHexStrings("\x4C\x89\x25\x10\x00\x00\x00", enc.code(), "mov QWORD PTR [rip + 0x10], r12"); | 1322 | try expectEqualHexStrings("\x4C\x89\x25\x10\x00\x00\x00", enc.code(), "mov QWORD PTR [rip + 0x10], r12"); |
| 1258 | 1323 | ||
| 1259 | try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.qword, .{ | 1324 | try enc.encode(.mov, &.{ |
| 1260 | .base = .r11, | 1325 | .{ .mem = Memory.sib(.qword, .{ |
| 1261 | .scale_index = .{ | 1326 | .base = .r11, |
| 1262 | .scale = 2, | 1327 | .scale_index = .{ .scale = 2, .index = .r12 }, |
| 1263 | .index = .r12, | 1328 | .disp = 0x10, |
| 1264 | }, | 1329 | }) }, |
| 1265 | .disp = 0x10, | 1330 | .{ .reg = .r13 }, |
| 1266 | }) }, .op2 = .{ .reg = .r13 } }); | 1331 | }); |
| 1267 | try expectEqualHexStrings("\x4F\x89\x6C\x63\x10", enc.code(), "mov QWORD PTR [r11 + 2 * r12 + 0x10], r13"); | 1332 | try expectEqualHexStrings("\x4F\x89\x6C\x63\x10", enc.code(), "mov QWORD PTR [r11 + 2 * r12 + 0x10], r13"); |
| 1268 | 1333 | ||
| 1269 | try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.rip(.word, -0x10) }, .op2 = .{ .reg = .r12w } }); | 1334 | try enc.encode(.mov, &.{ |
| 1335 | .{ .mem = Memory.rip(.word, -0x10) }, | ||
| 1336 | .{ .reg = .r12w }, | ||
| 1337 | }); | ||
| 1270 | try expectEqualHexStrings("\x66\x44\x89\x25\xF0\xFF\xFF\xFF", enc.code(), "mov WORD PTR [rip - 0x10], r12w"); | 1338 | try expectEqualHexStrings("\x66\x44\x89\x25\xF0\xFF\xFF\xFF", enc.code(), "mov WORD PTR [rip - 0x10], r12w"); |
| 1271 | 1339 | ||
| 1272 | try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.sib(.byte, .{ | 1340 | try enc.encode(.mov, &.{ |
| 1273 | .base = .r11, | 1341 | .{ .mem = Memory.sib(.byte, .{ |
| 1274 | .scale_index = .{ | 1342 | .base = .r11, |
| 1275 | .scale = 2, | 1343 | .scale_index = .{ .scale = 2, .index = .r12 }, |
| 1276 | .index = .r12, | 1344 | .disp = 0x10, |
| 1277 | }, | 1345 | }) }, |
| 1278 | .disp = 0x10, | 1346 | .{ .reg = .r13b }, |
| 1279 | }) }, .op2 = .{ .reg = .r13b } }); | 1347 | }); |
| 1280 | try expectEqualHexStrings("\x47\x88\x6C\x63\x10", enc.code(), "mov BYTE PTR [r11 + 2 * r12 + 0x10], r13b"); | 1348 | try expectEqualHexStrings("\x47\x88\x6C\x63\x10", enc.code(), "mov BYTE PTR [r11 + 2 * r12 + 0x10], r13b"); |
| 1281 | 1349 | ||
| 1282 | try enc.encode(.add, .{ .op1 = .{ .mem = Memory.sib(.byte, .{ | 1350 | try enc.encode(.add, &.{ |
| 1283 | .base = .ds, | 1351 | .{ .mem = Memory.sib(.byte, .{ .base = .ds, .disp = 0x10000000 }) }, |
| 1284 | .disp = 0x10000000, | 1352 | .{ .reg = .r12b }, |
| 1285 | }) }, .op2 = .{ .reg = .r12b } }); | 1353 | }); |
| 1286 | try expectEqualHexStrings("\x44\x00\x24\x25\x00\x00\x00\x10", enc.code(), "add BYTE PTR ds:0x10000000, r12b"); | 1354 | try expectEqualHexStrings("\x44\x00\x24\x25\x00\x00\x00\x10", enc.code(), "add BYTE PTR ds:0x10000000, r12b"); |
| 1287 | 1355 | ||
| 1288 | try enc.encode(.add, .{ .op1 = .{ .mem = Memory.sib(.dword, .{ | 1356 | try enc.encode(.add, &.{ |
| 1289 | .base = .ds, | 1357 | .{ .mem = Memory.sib(.dword, .{ .base = .ds, .disp = 0x10000000 }) }, |
| 1290 | .disp = 0x10000000, | 1358 | .{ .reg = .r12d }, |
| 1291 | }) }, .op2 = .{ .reg = .r12d } }); | 1359 | }); |
| 1292 | try expectEqualHexStrings("\x44\x01\x24\x25\x00\x00\x00\x10", enc.code(), "add DWORD PTR [ds:0x10000000], r12d"); | 1360 | try expectEqualHexStrings("\x44\x01\x24\x25\x00\x00\x00\x10", enc.code(), "add DWORD PTR [ds:0x10000000], r12d"); |
| 1293 | 1361 | ||
| 1294 | try enc.encode(.add, .{ .op1 = .{ .mem = Memory.sib(.dword, .{ | 1362 | try enc.encode(.add, &.{ |
| 1295 | .base = .gs, | 1363 | .{ .mem = Memory.sib(.dword, .{ .base = .gs, .disp = 0x10000000 }) }, |
| 1296 | .disp = 0x10000000, | 1364 | .{ .reg = .r12d }, |
| 1297 | }) }, .op2 = .{ .reg = .r12d } }); | 1365 | }); |
| 1298 | try expectEqualHexStrings("\x65\x44\x01\x24\x25\x00\x00\x00\x10", enc.code(), "add DWORD PTR [gs:0x10000000], r12d"); | 1366 | try expectEqualHexStrings("\x65\x44\x01\x24\x25\x00\x00\x00\x10", enc.code(), "add DWORD PTR [gs:0x10000000], r12d"); |
| 1299 | 1367 | ||
| 1300 | try enc.encode(.sub, .{ .op1 = .{ .mem = Memory.sib(.qword, .{ | 1368 | try enc.encode(.sub, &.{ |
| 1301 | .base = .r11, | 1369 | .{ .mem = Memory.sib(.qword, .{ .base = .r11, .disp = 0x10000000 }) }, |
| 1302 | .disp = 0x10000000, | 1370 | .{ .reg = .r12 }, |
| 1303 | }) }, .op2 = .{ .reg = .r12 } }); | 1371 | }); |
| 1304 | try expectEqualHexStrings("\x4D\x29\xA3\x00\x00\x00\x10", enc.code(), "sub QWORD PTR [r11 + 0x10000000], r12"); | 1372 | try expectEqualHexStrings("\x4D\x29\xA3\x00\x00\x00\x10", enc.code(), "sub QWORD PTR [r11 + 0x10000000], r12"); |
| 1305 | } | 1373 | } |
| 1306 | 1374 | ||
| 1307 | test "lower M encoding" { | 1375 | test "lower M encoding" { |
| 1308 | var enc = TestEncode{}; | 1376 | var enc = TestEncode{}; |
| 1309 | 1377 | ||
| 1310 | try enc.encode(.call, .{ .op1 = .{ .reg = .r12 } }); | 1378 | try enc.encode(.call, &.{ |
| 1379 | .{ .reg = .r12 }, | ||
| 1380 | }); | ||
| 1311 | try expectEqualHexStrings("\x41\xFF\xD4", enc.code(), "call r12"); | 1381 | try expectEqualHexStrings("\x41\xFF\xD4", enc.code(), "call r12"); |
| 1312 | 1382 | ||
| 1313 | try enc.encode(.call, .{ .op1 = .{ .mem = Memory.sib(.qword, .{ .base = .r12 }) } }); | 1383 | try enc.encode(.call, &.{ |
| 1384 | .{ .mem = Memory.sib(.qword, .{ .base = .r12 }) }, | ||
| 1385 | }); | ||
| 1314 | try expectEqualHexStrings("\x41\xFF\x14\x24", enc.code(), "call QWORD PTR [r12]"); | 1386 | try expectEqualHexStrings("\x41\xFF\x14\x24", enc.code(), "call QWORD PTR [r12]"); |
| 1315 | 1387 | ||
| 1316 | try enc.encode(.call, .{ | 1388 | try enc.encode(.call, &.{ |
| 1317 | .op1 = .{ .mem = Memory.sib(.qword, .{ | 1389 | .{ .mem = Memory.sib(.qword, .{ |
| 1318 | .base = null, | 1390 | .base = null, |
| 1319 | .scale_index = .{ .index = .r11, .scale = 2 }, | 1391 | .scale_index = .{ .index = .r11, .scale = 2 }, |
| 1320 | }) }, | 1392 | }) }, |
| 1321 | }); | 1393 | }); |
| 1322 | try expectEqualHexStrings("\x42\xFF\x14\x5D\x00\x00\x00\x00", enc.code(), "call QWORD PTR [r11 * 2]"); | 1394 | try expectEqualHexStrings("\x42\xFF\x14\x5D\x00\x00\x00\x00", enc.code(), "call QWORD PTR [r11 * 2]"); |
| 1323 | 1395 | ||
| 1324 | try enc.encode(.call, .{ | 1396 | try enc.encode(.call, &.{ |
| 1325 | .op1 = .{ .mem = Memory.sib(.qword, .{ | 1397 | .{ .mem = Memory.sib(.qword, .{ |
| 1326 | .base = null, | 1398 | .base = null, |
| 1327 | .scale_index = .{ .index = .r12, .scale = 2 }, | 1399 | .scale_index = .{ .index = .r12, .scale = 2 }, |
| 1328 | }) }, | 1400 | }) }, |
| 1329 | }); | 1401 | }); |
| 1330 | try expectEqualHexStrings("\x42\xFF\x14\x65\x00\x00\x00\x00", enc.code(), "call QWORD PTR [r12 * 2]"); | 1402 | try expectEqualHexStrings("\x42\xFF\x14\x65\x00\x00\x00\x00", enc.code(), "call QWORD PTR [r12 * 2]"); |
| 1331 | 1403 | ||
| 1332 | try enc.encode(.call, .{ .op1 = .{ .mem = Memory.sib(.qword, .{ .base = .gs }) } }); | 1404 | try enc.encode(.call, &.{ |
| 1405 | .{ .mem = Memory.sib(.qword, .{ .base = .gs }) }, | ||
| 1406 | }); | ||
| 1333 | try expectEqualHexStrings("\x65\xFF\x14\x25\x00\x00\x00\x00", enc.code(), "call gs:0x0"); | 1407 | try expectEqualHexStrings("\x65\xFF\x14\x25\x00\x00\x00\x00", enc.code(), "call gs:0x0"); |
| 1334 | 1408 | ||
| 1335 | try enc.encode(.call, .{ .op1 = .{ .imm = Immediate.s(0) } }); | 1409 | try enc.encode(.call, &.{ |
| 1410 | .{ .imm = Immediate.s(0) }, | ||
| 1411 | }); | ||
| 1336 | try expectEqualHexStrings("\xE8\x00\x00\x00\x00", enc.code(), "call 0x0"); | 1412 | try expectEqualHexStrings("\xE8\x00\x00\x00\x00", enc.code(), "call 0x0"); |
| 1337 | 1413 | ||
| 1338 | try enc.encode(.push, .{ .op1 = .{ .mem = Memory.sib(.qword, .{ .base = .rbp }) } }); | 1414 | try enc.encode(.push, &.{ |
| 1415 | .{ .mem = Memory.sib(.qword, .{ .base = .rbp }) }, | ||
| 1416 | }); | ||
| 1339 | try expectEqualHexStrings("\xFF\x75\x00", enc.code(), "push QWORD PTR [rbp]"); | 1417 | try expectEqualHexStrings("\xFF\x75\x00", enc.code(), "push QWORD PTR [rbp]"); |
| 1340 | 1418 | ||
| 1341 | try enc.encode(.push, .{ .op1 = .{ .mem = Memory.sib(.word, .{ .base = .rbp }) } }); | 1419 | try enc.encode(.push, &.{ |
| 1420 | .{ .mem = Memory.sib(.word, .{ .base = .rbp }) }, | ||
| 1421 | }); | ||
| 1342 | try expectEqualHexStrings("\x66\xFF\x75\x00", enc.code(), "push QWORD PTR [rbp]"); | 1422 | try expectEqualHexStrings("\x66\xFF\x75\x00", enc.code(), "push QWORD PTR [rbp]"); |
| 1343 | 1423 | ||
| 1344 | try enc.encode(.pop, .{ .op1 = .{ .mem = Memory.rip(.qword, 0) } }); | 1424 | try enc.encode(.pop, &.{ |
| 1425 | .{ .mem = Memory.rip(.qword, 0) }, | ||
| 1426 | }); | ||
| 1345 | try expectEqualHexStrings("\x8F\x05\x00\x00\x00\x00", enc.code(), "pop QWORD PTR [rip]"); | 1427 | try expectEqualHexStrings("\x8F\x05\x00\x00\x00\x00", enc.code(), "pop QWORD PTR [rip]"); |
| 1346 | 1428 | ||
| 1347 | try enc.encode(.pop, .{ .op1 = .{ .mem = Memory.rip(.word, 0) } }); | 1429 | try enc.encode(.pop, &.{ |
| 1430 | .{ .mem = Memory.rip(.word, 0) }, | ||
| 1431 | }); | ||
| 1348 | try expectEqualHexStrings("\x66\x8F\x05\x00\x00\x00\x00", enc.code(), "pop WORD PTR [rbp]"); | 1432 | try expectEqualHexStrings("\x66\x8F\x05\x00\x00\x00\x00", enc.code(), "pop WORD PTR [rbp]"); |
| 1349 | 1433 | ||
| 1350 | try enc.encode(.imul, .{ .op1 = .{ .reg = .rax } }); | 1434 | try enc.encode(.imul, &.{ |
| 1435 | .{ .reg = .rax }, | ||
| 1436 | }); | ||
| 1351 | try expectEqualHexStrings("\x48\xF7\xE8", enc.code(), "imul rax"); | 1437 | try expectEqualHexStrings("\x48\xF7\xE8", enc.code(), "imul rax"); |
| 1352 | 1438 | ||
| 1353 | try enc.encode(.imul, .{ .op1 = .{ .reg = .r12 } }); | 1439 | try enc.encode(.imul, &.{ |
| 1440 | .{ .reg = .r12 }, | ||
| 1441 | }); | ||
| 1354 | try expectEqualHexStrings("\x49\xF7\xEC", enc.code(), "imul r12"); | 1442 | try expectEqualHexStrings("\x49\xF7\xEC", enc.code(), "imul r12"); |
| 1355 | } | 1443 | } |
| 1356 | 1444 | ||
| 1357 | test "lower O encoding" { | 1445 | test "lower O encoding" { |
| 1358 | var enc = TestEncode{}; | 1446 | var enc = TestEncode{}; |
| 1359 | 1447 | ||
| 1360 | try enc.encode(.push, .{ .op1 = .{ .reg = .rax } }); | 1448 | try enc.encode(.push, &.{ |
| 1449 | .{ .reg = .rax }, | ||
| 1450 | }); | ||
| 1361 | try expectEqualHexStrings("\x50", enc.code(), "push rax"); | 1451 | try expectEqualHexStrings("\x50", enc.code(), "push rax"); |
| 1362 | 1452 | ||
| 1363 | try enc.encode(.push, .{ .op1 = .{ .reg = .r12w } }); | 1453 | try enc.encode(.push, &.{ |
| 1454 | .{ .reg = .r12w }, | ||
| 1455 | }); | ||
| 1364 | try expectEqualHexStrings("\x66\x41\x54", enc.code(), "push r12w"); | 1456 | try expectEqualHexStrings("\x66\x41\x54", enc.code(), "push r12w"); |
| 1365 | 1457 | ||
| 1366 | try enc.encode(.pop, .{ .op1 = .{ .reg = .r12 } }); | 1458 | try enc.encode(.pop, &.{ |
| 1459 | .{ .reg = .r12 }, | ||
| 1460 | }); | ||
| 1367 | try expectEqualHexStrings("\x41\x5c", enc.code(), "pop r12"); | 1461 | try expectEqualHexStrings("\x41\x5c", enc.code(), "pop r12"); |
| 1368 | } | 1462 | } |
| 1369 | 1463 | ||
| 1370 | test "lower OI encoding" { | 1464 | test "lower OI encoding" { |
| 1371 | var enc = TestEncode{}; | 1465 | var enc = TestEncode{}; |
| 1372 | 1466 | ||
| 1373 | try enc.encode(.mov, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .imm = Immediate.u(0x1000000000000000) } }); | 1467 | try enc.encode(.mov, &.{ |
| 1468 | .{ .reg = .rax }, | ||
| 1469 | .{ .imm = Immediate.u(0x1000000000000000) }, | ||
| 1470 | }); | ||
| 1374 | try expectEqualHexStrings( | 1471 | try expectEqualHexStrings( |
| 1375 | "\x48\xB8\x00\x00\x00\x00\x00\x00\x00\x10", | 1472 | "\x48\xB8\x00\x00\x00\x00\x00\x00\x00\x10", |
| 1376 | enc.code(), | 1473 | enc.code(), |
| 1377 | "movabs rax, 0x1000000000000000", | 1474 | "movabs rax, 0x1000000000000000", |
| 1378 | ); | 1475 | ); |
| 1379 | 1476 | ||
| 1380 | try enc.encode(.mov, .{ .op1 = .{ .reg = .r11 }, .op2 = .{ .imm = Immediate.u(0x1000000000000000) } }); | 1477 | try enc.encode(.mov, &.{ |
| 1478 | .{ .reg = .r11 }, | ||
| 1479 | .{ .imm = Immediate.u(0x1000000000000000) }, | ||
| 1480 | }); | ||
| 1381 | try expectEqualHexStrings( | 1481 | try expectEqualHexStrings( |
| 1382 | "\x49\xBB\x00\x00\x00\x00\x00\x00\x00\x10", | 1482 | "\x49\xBB\x00\x00\x00\x00\x00\x00\x00\x10", |
| 1383 | enc.code(), | 1483 | enc.code(), |
| 1384 | "movabs r11, 0x1000000000000000", | 1484 | "movabs r11, 0x1000000000000000", |
| 1385 | ); | 1485 | ); |
| 1386 | 1486 | ||
| 1387 | try enc.encode(.mov, .{ .op1 = .{ .reg = .r11d }, .op2 = .{ .imm = Immediate.u(0x10000000) } }); | 1487 | try enc.encode(.mov, &.{ |
| 1488 | .{ .reg = .r11d }, | ||
| 1489 | .{ .imm = Immediate.u(0x10000000) }, | ||
| 1490 | }); | ||
| 1388 | try expectEqualHexStrings("\x41\xBB\x00\x00\x00\x10", enc.code(), "mov r11d, 0x10000000"); | 1491 | try expectEqualHexStrings("\x41\xBB\x00\x00\x00\x10", enc.code(), "mov r11d, 0x10000000"); |
| 1389 | 1492 | ||
| 1390 | try enc.encode(.mov, .{ .op1 = .{ .reg = .r11w }, .op2 = .{ .imm = Immediate.u(0x1000) } }); | 1493 | try enc.encode(.mov, &.{ |
| 1494 | .{ .reg = .r11w }, | ||
| 1495 | .{ .imm = Immediate.u(0x1000) }, | ||
| 1496 | }); | ||
| 1391 | try expectEqualHexStrings("\x66\x41\xBB\x00\x10", enc.code(), "mov r11w, 0x1000"); | 1497 | try expectEqualHexStrings("\x66\x41\xBB\x00\x10", enc.code(), "mov r11w, 0x1000"); |
| 1392 | 1498 | ||
| 1393 | try enc.encode(.mov, .{ .op1 = .{ .reg = .r11b }, .op2 = .{ .imm = Immediate.u(0x10) } }); | 1499 | try enc.encode(.mov, &.{ |
| 1500 | .{ .reg = .r11b }, | ||
| 1501 | .{ .imm = Immediate.u(0x10) }, | ||
| 1502 | }); | ||
| 1394 | try expectEqualHexStrings("\x41\xB3\x10", enc.code(), "mov r11b, 0x10"); | 1503 | try expectEqualHexStrings("\x41\xB3\x10", enc.code(), "mov r11b, 0x10"); |
| 1395 | } | 1504 | } |
| 1396 | 1505 | ||
| 1397 | test "lower FD/TD encoding" { | 1506 | test "lower FD/TD encoding" { |
| 1398 | var enc = TestEncode{}; | 1507 | var enc = TestEncode{}; |
| 1399 | 1508 | ||
| 1400 | try enc.encode(.mov, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .mem = Memory.moffs(.cs, 0x10) } }); | 1509 | try enc.encode(.mov, &.{ |
| 1510 | .{ .reg = .rax }, | ||
| 1511 | .{ .mem = Memory.moffs(.cs, 0x10) }, | ||
| 1512 | }); | ||
| 1401 | try expectEqualHexStrings("\x2E\x48\xA1\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs rax, cs:0x10"); | 1513 | try expectEqualHexStrings("\x2E\x48\xA1\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs rax, cs:0x10"); |
| 1402 | 1514 | ||
| 1403 | try enc.encode(.mov, .{ .op1 = .{ .reg = .eax }, .op2 = .{ .mem = Memory.moffs(.fs, 0x10) } }); | 1515 | try enc.encode(.mov, &.{ |
| 1516 | .{ .reg = .eax }, | ||
| 1517 | .{ .mem = Memory.moffs(.fs, 0x10) }, | ||
| 1518 | }); | ||
| 1404 | try expectEqualHexStrings("\x64\xA1\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs eax, fs:0x10"); | 1519 | try expectEqualHexStrings("\x64\xA1\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs eax, fs:0x10"); |
| 1405 | 1520 | ||
| 1406 | try enc.encode(.mov, .{ .op1 = .{ .reg = .ax }, .op2 = .{ .mem = Memory.moffs(.gs, 0x10) } }); | 1521 | try enc.encode(.mov, &.{ |
| 1522 | .{ .reg = .ax }, | ||
| 1523 | .{ .mem = Memory.moffs(.gs, 0x10) }, | ||
| 1524 | }); | ||
| 1407 | try expectEqualHexStrings("\x65\x66\xA1\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs ax, gs:0x10"); | 1525 | try expectEqualHexStrings("\x65\x66\xA1\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs ax, gs:0x10"); |
| 1408 | 1526 | ||
| 1409 | try enc.encode(.mov, .{ .op1 = .{ .reg = .al }, .op2 = .{ .mem = Memory.moffs(.ds, 0x10) } }); | 1527 | try enc.encode(.mov, &.{ |
| 1528 | .{ .reg = .al }, | ||
| 1529 | .{ .mem = Memory.moffs(.ds, 0x10) }, | ||
| 1530 | }); | ||
| 1410 | try expectEqualHexStrings("\xA0\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs al, ds:0x10"); | 1531 | try expectEqualHexStrings("\xA0\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs al, ds:0x10"); |
| 1411 | 1532 | ||
| 1412 | try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.moffs(.cs, 0x10) }, .op2 = .{ .reg = .rax } }); | 1533 | try enc.encode(.mov, &.{ |
| 1534 | .{ .mem = Memory.moffs(.cs, 0x10) }, | ||
| 1535 | .{ .reg = .rax }, | ||
| 1536 | }); | ||
| 1413 | try expectEqualHexStrings("\x2E\x48\xA3\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs cs:0x10, rax"); | 1537 | try expectEqualHexStrings("\x2E\x48\xA3\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs cs:0x10, rax"); |
| 1414 | 1538 | ||
| 1415 | try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.moffs(.fs, 0x10) }, .op2 = .{ .reg = .eax } }); | 1539 | try enc.encode(.mov, &.{ |
| 1540 | .{ .mem = Memory.moffs(.fs, 0x10) }, | ||
| 1541 | .{ .reg = .eax }, | ||
| 1542 | }); | ||
| 1416 | try expectEqualHexStrings("\x64\xA3\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs fs:0x10, eax"); | 1543 | try expectEqualHexStrings("\x64\xA3\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs fs:0x10, eax"); |
| 1417 | 1544 | ||
| 1418 | try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.moffs(.gs, 0x10) }, .op2 = .{ .reg = .ax } }); | 1545 | try enc.encode(.mov, &.{ |
| 1546 | .{ .mem = Memory.moffs(.gs, 0x10) }, | ||
| 1547 | .{ .reg = .ax }, | ||
| 1548 | }); | ||
| 1419 | try expectEqualHexStrings("\x65\x66\xA3\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs gs:0x10, ax"); | 1549 | try expectEqualHexStrings("\x65\x66\xA3\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs gs:0x10, ax"); |
| 1420 | 1550 | ||
| 1421 | try enc.encode(.mov, .{ .op1 = .{ .mem = Memory.moffs(.ds, 0x10) }, .op2 = .{ .reg = .al } }); | 1551 | try enc.encode(.mov, &.{ |
| 1552 | .{ .mem = Memory.moffs(.ds, 0x10) }, | ||
| 1553 | .{ .reg = .al }, | ||
| 1554 | }); | ||
| 1422 | try expectEqualHexStrings("\xA2\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs ds:0x10, al"); | 1555 | try expectEqualHexStrings("\xA2\x10\x00\x00\x00\x00\x00\x00\x00", enc.code(), "movabs ds:0x10, al"); |
| 1423 | } | 1556 | } |
| 1424 | 1557 | ||
| 1425 | test "lower NP encoding" { | 1558 | test "lower NP encoding" { |
| 1426 | var enc = TestEncode{}; | 1559 | var enc = TestEncode{}; |
| 1427 | 1560 | ||
| 1428 | try enc.encode(.int3, .{}); | 1561 | try enc.encode(.int3, &.{}); |
| 1429 | try expectEqualHexStrings("\xCC", enc.code(), "int3"); | 1562 | try expectEqualHexStrings("\xCC", enc.code(), "int3"); |
| 1430 | 1563 | ||
| 1431 | try enc.encode(.nop, .{}); | 1564 | try enc.encode(.nop, &.{}); |
| 1432 | try expectEqualHexStrings("\x90", enc.code(), "nop"); | 1565 | try expectEqualHexStrings("\x90", enc.code(), "nop"); |
| 1433 | 1566 | ||
| 1434 | try enc.encode(.ret, .{}); | 1567 | try enc.encode(.ret, &.{}); |
| 1435 | try expectEqualHexStrings("\xC3", enc.code(), "ret"); | 1568 | try expectEqualHexStrings("\xC3", enc.code(), "ret"); |
| 1436 | 1569 | ||
| 1437 | try enc.encode(.syscall, .{}); | 1570 | try enc.encode(.syscall, &.{}); |
| 1438 | try expectEqualHexStrings("\x0f\x05", enc.code(), "syscall"); | 1571 | try expectEqualHexStrings("\x0f\x05", enc.code(), "syscall"); |
| 1439 | } | 1572 | } |
| 1440 | 1573 | ||
| 1441 | fn invalidInstruction(mnemonic: Instruction.Mnemonic, args: Instruction.Init) !void { | 1574 | fn invalidInstruction(mnemonic: Instruction.Mnemonic, ops: []const Instruction.Operand) !void { |
| 1442 | const err = Instruction.new(mnemonic, args); | 1575 | const err = Instruction.new(.none, mnemonic, ops); |
| 1443 | try testing.expectError(error.InvalidInstruction, err); | 1576 | try testing.expectError(error.InvalidInstruction, err); |
| 1444 | } | 1577 | } |
| 1445 | 1578 | ||
| 1446 | test "invalid instruction" { | 1579 | test "invalid instruction" { |
| 1447 | try invalidInstruction(.call, .{ .op1 = .{ .reg = .eax } }); | 1580 | try invalidInstruction(.call, &.{ |
| 1448 | try invalidInstruction(.call, .{ .op1 = .{ .reg = .ax } }); | 1581 | .{ .reg = .eax }, |
| 1449 | try invalidInstruction(.call, .{ .op1 = .{ .reg = .al } }); | 1582 | }); |
| 1450 | try invalidInstruction(.call, .{ .op1 = .{ .mem = Memory.rip(.dword, 0) } }); | 1583 | try invalidInstruction(.call, &.{ |
| 1451 | try invalidInstruction(.call, .{ .op1 = .{ .mem = Memory.rip(.word, 0) } }); | 1584 | .{ .reg = .ax }, |
| 1452 | try invalidInstruction(.call, .{ .op1 = .{ .mem = Memory.rip(.byte, 0) } }); | 1585 | }); |
| 1453 | try invalidInstruction(.mov, .{ .op1 = .{ .mem = Memory.rip(.word, 0x10) }, .op2 = .{ .reg = .r12 } }); | 1586 | try invalidInstruction(.call, &.{ |
| 1454 | try invalidInstruction(.lea, .{ .op1 = .{ .reg = .rax }, .op2 = .{ .reg = .rbx } }); | 1587 | .{ .reg = .al }, |
| 1455 | try invalidInstruction(.lea, .{ .op1 = .{ .reg = .al }, .op2 = .{ .mem = Memory.rip(.byte, 0) } }); | 1588 | }); |
| 1456 | try invalidInstruction(.pop, .{ .op1 = .{ .reg = .r12b } }); | 1589 | try invalidInstruction(.call, &.{ |
| 1457 | try invalidInstruction(.pop, .{ .op1 = .{ .reg = .r12d } }); | 1590 | .{ .mem = Memory.rip(.dword, 0) }, |
| 1458 | try invalidInstruction(.push, .{ .op1 = .{ .reg = .r12b } }); | 1591 | }); |
| 1459 | try invalidInstruction(.push, .{ .op1 = .{ .reg = .r12d } }); | 1592 | try invalidInstruction(.call, &.{ |
| 1460 | try invalidInstruction(.push, .{ .op1 = .{ .imm = Immediate.u(0x1000000000000000) } }); | 1593 | .{ .mem = Memory.rip(.word, 0) }, |
| 1594 | }); | ||
| 1595 | try invalidInstruction(.call, &.{ | ||
| 1596 | .{ .mem = Memory.rip(.byte, 0) }, | ||
| 1597 | }); | ||
| 1598 | try invalidInstruction(.mov, &.{ | ||
| 1599 | .{ .mem = Memory.rip(.word, 0x10) }, | ||
| 1600 | .{ .reg = .r12 }, | ||
| 1601 | }); | ||
| 1602 | try invalidInstruction(.lea, &.{ | ||
| 1603 | .{ .reg = .rax }, | ||
| 1604 | .{ .reg = .rbx }, | ||
| 1605 | }); | ||
| 1606 | try invalidInstruction(.lea, &.{ | ||
| 1607 | .{ .reg = .al }, | ||
| 1608 | .{ .mem = Memory.rip(.byte, 0) }, | ||
| 1609 | }); | ||
| 1610 | try invalidInstruction(.pop, &.{ | ||
| 1611 | .{ .reg = .r12b }, | ||
| 1612 | }); | ||
| 1613 | try invalidInstruction(.pop, &.{ | ||
| 1614 | .{ .reg = .r12d }, | ||
| 1615 | }); | ||
| 1616 | try invalidInstruction(.push, &.{ | ||
| 1617 | .{ .reg = .r12b }, | ||
| 1618 | }); | ||
| 1619 | try invalidInstruction(.push, &.{ | ||
| 1620 | .{ .reg = .r12d }, | ||
| 1621 | }); | ||
| 1622 | try invalidInstruction(.push, &.{ | ||
| 1623 | .{ .imm = Immediate.u(0x1000000000000000) }, | ||
| 1624 | }); | ||
| 1461 | } | 1625 | } |
| 1462 | 1626 | ||
| 1463 | fn cannotEncode(mnemonic: Instruction.Mnemonic, args: Instruction.Init) !void { | 1627 | fn cannotEncode(mnemonic: Instruction.Mnemonic, ops: []const Instruction.Operand) !void { |
| 1464 | try testing.expectError(error.CannotEncode, Instruction.new(mnemonic, args)); | 1628 | try testing.expectError(error.CannotEncode, Instruction.new(.none, mnemonic, ops)); |
| 1465 | } | 1629 | } |
| 1466 | 1630 | ||
| 1467 | test "cannot encode" { | 1631 | test "cannot encode" { |
| 1468 | try cannotEncode(.@"test", .{ | 1632 | try cannotEncode(.@"test", &.{ |
| 1469 | .op1 = .{ .mem = Memory.sib(.byte, .{ .base = .r12 }) }, | 1633 | .{ .mem = Memory.sib(.byte, .{ .base = .r12 }) }, |
| 1470 | .op2 = .{ .reg = .ah }, | 1634 | .{ .reg = .ah }, |
| 1471 | }); | 1635 | }); |
| 1472 | try cannotEncode(.@"test", .{ | 1636 | try cannotEncode(.@"test", &.{ |
| 1473 | .op1 = .{ .reg = .r11b }, | 1637 | .{ .reg = .r11b }, |
| 1474 | .op2 = .{ .reg = .bh }, | 1638 | .{ .reg = .bh }, |
| 1475 | }); | 1639 | }); |
| 1476 | try cannotEncode(.mov, .{ | 1640 | try cannotEncode(.mov, &.{ |
| 1477 | .op1 = .{ .reg = .sil }, | 1641 | .{ .reg = .sil }, |
| 1478 | .op2 = .{ .reg = .ah }, | 1642 | .{ .reg = .ah }, |
| 1479 | }); | 1643 | }); |
| 1480 | } | 1644 | } |
| 1481 | 1645 | ||
| ... | @@ -1645,12 +1809,7 @@ const Assembler = struct { | ... | @@ -1645,12 +1809,7 @@ const Assembler = struct { |
| 1645 | 1809 | ||
| 1646 | pub fn assemble(as: *Assembler, writer: anytype) !void { | 1810 | pub fn assemble(as: *Assembler, writer: anytype) !void { |
| 1647 | while (try as.next()) |parsed_inst| { | 1811 | while (try as.next()) |parsed_inst| { |
| 1648 | const inst = try Instruction.new(parsed_inst.mnemonic, .{ | 1812 | const inst = try Instruction.new(.none, parsed_inst.mnemonic, &parsed_inst.ops); |
| 1649 | .op1 = parsed_inst.ops[0], | ||
| 1650 | .op2 = parsed_inst.ops[1], | ||
| 1651 | .op3 = parsed_inst.ops[2], | ||
| 1652 | .op4 = parsed_inst.ops[3], | ||
| 1653 | }); | ||
| 1654 | try inst.encode(writer); | 1813 | try inst.encode(writer); |
| 1655 | } | 1814 | } |
| 1656 | } | 1815 | } |
src/arch/x86_64/encodings.zig+837-832| ... | @@ -6,869 +6,874 @@ const Mode = Encoding.Mode; | ... | @@ -6,869 +6,874 @@ const Mode = Encoding.Mode; |
| 6 | 6 | ||
| 7 | const modrm_ext = u3; | 7 | const modrm_ext = u3; |
| 8 | 8 | ||
| 9 | const Entry = struct { Mnemonic, OpEn, Op, Op, Op, Op, []const u8, modrm_ext, Mode }; | 9 | pub const Entry = struct { Mnemonic, OpEn, []const Op, []const u8, modrm_ext, Mode }; |
| 10 | 10 | ||
| 11 | // TODO move this into a .zon file when Zig is capable of importing .zon files | 11 | // TODO move this into a .zon file when Zig is capable of importing .zon files |
| 12 | // zig fmt: off | 12 | // zig fmt: off |
| 13 | pub const table = &[_]Entry{ | 13 | pub const table = [_]Entry{ |
| 14 | // General-purpose | 14 | // General-purpose |
| 15 | .{ .adc, .zi, .al, .imm8, .none, .none, &.{ 0x14 }, 0, .none }, | 15 | .{ .adc, .zi, &.{ .al, .imm8 }, &.{ 0x14 }, 0, .none }, |
| 16 | .{ .adc, .zi, .ax, .imm16, .none, .none, &.{ 0x15 }, 0, .none }, | 16 | .{ .adc, .zi, &.{ .ax, .imm16 }, &.{ 0x15 }, 0, .none }, |
| 17 | .{ .adc, .zi, .eax, .imm32, .none, .none, &.{ 0x15 }, 0, .none }, | 17 | .{ .adc, .zi, &.{ .eax, .imm32 }, &.{ 0x15 }, 0, .none }, |
| 18 | .{ .adc, .zi, .rax, .imm32s, .none, .none, &.{ 0x15 }, 0, .long }, | 18 | .{ .adc, .zi, &.{ .rax, .imm32s }, &.{ 0x15 }, 0, .long }, |
| 19 | .{ .adc, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 2, .none }, | 19 | .{ .adc, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 2, .none }, |
| 20 | .{ .adc, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 2, .rex }, | 20 | .{ .adc, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 2, .rex }, |
| 21 | .{ .adc, .mi, .rm16, .imm16, .none, .none, &.{ 0x81 }, 2, .none }, | 21 | .{ .adc, .mi, &.{ .rm16, .imm16 }, &.{ 0x81 }, 2, .none }, |
| 22 | .{ .adc, .mi, .rm32, .imm32, .none, .none, &.{ 0x81 }, 2, .none }, | 22 | .{ .adc, .mi, &.{ .rm32, .imm32 }, &.{ 0x81 }, 2, .none }, |
| 23 | .{ .adc, .mi, .rm64, .imm32s, .none, .none, &.{ 0x81 }, 2, .long }, | 23 | .{ .adc, .mi, &.{ .rm64, .imm32s }, &.{ 0x81 }, 2, .long }, |
| 24 | .{ .adc, .mi, .rm16, .imm8s, .none, .none, &.{ 0x83 }, 2, .none }, | 24 | .{ .adc, .mi, &.{ .rm16, .imm8s }, &.{ 0x83 }, 2, .none }, |
| 25 | .{ .adc, .mi, .rm32, .imm8s, .none, .none, &.{ 0x83 }, 2, .none }, | 25 | .{ .adc, .mi, &.{ .rm32, .imm8s }, &.{ 0x83 }, 2, .none }, |
| 26 | .{ .adc, .mi, .rm64, .imm8s, .none, .none, &.{ 0x83 }, 2, .long }, | 26 | .{ .adc, .mi, &.{ .rm64, .imm8s }, &.{ 0x83 }, 2, .long }, |
| 27 | .{ .adc, .mr, .rm8, .r8, .none, .none, &.{ 0x10 }, 0, .none }, | 27 | .{ .adc, .mr, &.{ .rm8, .r8 }, &.{ 0x10 }, 0, .none }, |
| 28 | .{ .adc, .mr, .rm8, .r8, .none, .none, &.{ 0x10 }, 0, .rex }, | 28 | .{ .adc, .mr, &.{ .rm8, .r8 }, &.{ 0x10 }, 0, .rex }, |
| 29 | .{ .adc, .mr, .rm16, .r16, .none, .none, &.{ 0x11 }, 0, .none }, | 29 | .{ .adc, .mr, &.{ .rm16, .r16 }, &.{ 0x11 }, 0, .none }, |
| 30 | .{ .adc, .mr, .rm32, .r32, .none, .none, &.{ 0x11 }, 0, .none }, | 30 | .{ .adc, .mr, &.{ .rm32, .r32 }, &.{ 0x11 }, 0, .none }, |
| 31 | .{ .adc, .mr, .rm64, .r64, .none, .none, &.{ 0x11 }, 0, .long }, | 31 | .{ .adc, .mr, &.{ .rm64, .r64 }, &.{ 0x11 }, 0, .long }, |
| 32 | .{ .adc, .rm, .r8, .rm8, .none, .none, &.{ 0x12 }, 0, .none }, | 32 | .{ .adc, .rm, &.{ .r8, .rm8 }, &.{ 0x12 }, 0, .none }, |
| 33 | .{ .adc, .rm, .r8, .rm8, .none, .none, &.{ 0x12 }, 0, .rex }, | 33 | .{ .adc, .rm, &.{ .r8, .rm8 }, &.{ 0x12 }, 0, .rex }, |
| 34 | .{ .adc, .rm, .r16, .rm16, .none, .none, &.{ 0x13 }, 0, .none }, | 34 | .{ .adc, .rm, &.{ .r16, .rm16 }, &.{ 0x13 }, 0, .none }, |
| 35 | .{ .adc, .rm, .r32, .rm32, .none, .none, &.{ 0x13 }, 0, .none }, | 35 | .{ .adc, .rm, &.{ .r32, .rm32 }, &.{ 0x13 }, 0, .none }, |
| 36 | .{ .adc, .rm, .r64, .rm64, .none, .none, &.{ 0x13 }, 0, .long }, | 36 | .{ .adc, .rm, &.{ .r64, .rm64 }, &.{ 0x13 }, 0, .long }, |
| 37 | 37 | ||
| 38 | .{ .add, .zi, .al, .imm8, .none, .none, &.{ 0x04 }, 0, .none }, | 38 | .{ .add, .zi, &.{ .al, .imm8 }, &.{ 0x04 }, 0, .none }, |
| 39 | .{ .add, .zi, .ax, .imm16, .none, .none, &.{ 0x05 }, 0, .none }, | 39 | .{ .add, .zi, &.{ .ax, .imm16 }, &.{ 0x05 }, 0, .none }, |
| 40 | .{ .add, .zi, .eax, .imm32, .none, .none, &.{ 0x05 }, 0, .none }, | 40 | .{ .add, .zi, &.{ .eax, .imm32 }, &.{ 0x05 }, 0, .none }, |
| 41 | .{ .add, .zi, .rax, .imm32s, .none, .none, &.{ 0x05 }, 0, .long }, | 41 | .{ .add, .zi, &.{ .rax, .imm32s }, &.{ 0x05 }, 0, .long }, |
| 42 | .{ .add, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 0, .none }, | 42 | .{ .add, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 0, .none }, |
| 43 | .{ .add, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 0, .rex }, | 43 | .{ .add, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 0, .rex }, |
| 44 | .{ .add, .mi, .rm16, .imm16, .none, .none, &.{ 0x81 }, 0, .none }, | 44 | .{ .add, .mi, &.{ .rm16, .imm16 }, &.{ 0x81 }, 0, .none }, |
| 45 | .{ .add, .mi, .rm32, .imm32, .none, .none, &.{ 0x81 }, 0, .none }, | 45 | .{ .add, .mi, &.{ .rm32, .imm32 }, &.{ 0x81 }, 0, .none }, |
| 46 | .{ .add, .mi, .rm64, .imm32s, .none, .none, &.{ 0x81 }, 0, .long }, | 46 | .{ .add, .mi, &.{ .rm64, .imm32s }, &.{ 0x81 }, 0, .long }, |
| 47 | .{ .add, .mi, .rm16, .imm8s, .none, .none, &.{ 0x83 }, 0, .none }, | 47 | .{ .add, .mi, &.{ .rm16, .imm8s }, &.{ 0x83 }, 0, .none }, |
| 48 | .{ .add, .mi, .rm32, .imm8s, .none, .none, &.{ 0x83 }, 0, .none }, | 48 | .{ .add, .mi, &.{ .rm32, .imm8s }, &.{ 0x83 }, 0, .none }, |
| 49 | .{ .add, .mi, .rm64, .imm8s, .none, .none, &.{ 0x83 }, 0, .long }, | 49 | .{ .add, .mi, &.{ .rm64, .imm8s }, &.{ 0x83 }, 0, .long }, |
| 50 | .{ .add, .mr, .rm8, .r8, .none, .none, &.{ 0x00 }, 0, .none }, | 50 | .{ .add, .mr, &.{ .rm8, .r8 }, &.{ 0x00 }, 0, .none }, |
| 51 | .{ .add, .mr, .rm8, .r8, .none, .none, &.{ 0x00 }, 0, .rex }, | 51 | .{ .add, .mr, &.{ .rm8, .r8 }, &.{ 0x00 }, 0, .rex }, |
| 52 | .{ .add, .mr, .rm16, .r16, .none, .none, &.{ 0x01 }, 0, .none }, | 52 | .{ .add, .mr, &.{ .rm16, .r16 }, &.{ 0x01 }, 0, .none }, |
| 53 | .{ .add, .mr, .rm32, .r32, .none, .none, &.{ 0x01 }, 0, .none }, | 53 | .{ .add, .mr, &.{ .rm32, .r32 }, &.{ 0x01 }, 0, .none }, |
| 54 | .{ .add, .mr, .rm64, .r64, .none, .none, &.{ 0x01 }, 0, .long }, | 54 | .{ .add, .mr, &.{ .rm64, .r64 }, &.{ 0x01 }, 0, .long }, |
| 55 | .{ .add, .rm, .r8, .rm8, .none, .none, &.{ 0x02 }, 0, .none }, | 55 | .{ .add, .rm, &.{ .r8, .rm8 }, &.{ 0x02 }, 0, .none }, |
| 56 | .{ .add, .rm, .r8, .rm8, .none, .none, &.{ 0x02 }, 0, .rex }, | 56 | .{ .add, .rm, &.{ .r8, .rm8 }, &.{ 0x02 }, 0, .rex }, |
| 57 | .{ .add, .rm, .r16, .rm16, .none, .none, &.{ 0x03 }, 0, .none }, | 57 | .{ .add, .rm, &.{ .r16, .rm16 }, &.{ 0x03 }, 0, .none }, |
| 58 | .{ .add, .rm, .r32, .rm32, .none, .none, &.{ 0x03 }, 0, .none }, | 58 | .{ .add, .rm, &.{ .r32, .rm32 }, &.{ 0x03 }, 0, .none }, |
| 59 | .{ .add, .rm, .r64, .rm64, .none, .none, &.{ 0x03 }, 0, .long }, | 59 | .{ .add, .rm, &.{ .r64, .rm64 }, &.{ 0x03 }, 0, .long }, |
| 60 | 60 | ||
| 61 | .{ .@"and", .zi, .al, .imm8, .none, .none, &.{ 0x24 }, 0, .none }, | 61 | .{ .@"and", .zi, &.{ .al, .imm8 }, &.{ 0x24 }, 0, .none }, |
| 62 | .{ .@"and", .zi, .ax, .imm16, .none, .none, &.{ 0x25 }, 0, .none }, | 62 | .{ .@"and", .zi, &.{ .ax, .imm16 }, &.{ 0x25 }, 0, .none }, |
| 63 | .{ .@"and", .zi, .eax, .imm32, .none, .none, &.{ 0x25 }, 0, .none }, | 63 | .{ .@"and", .zi, &.{ .eax, .imm32 }, &.{ 0x25 }, 0, .none }, |
| 64 | .{ .@"and", .zi, .rax, .imm32s, .none, .none, &.{ 0x25 }, 0, .long }, | 64 | .{ .@"and", .zi, &.{ .rax, .imm32s }, &.{ 0x25 }, 0, .long }, |
| 65 | .{ .@"and", .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 4, .none }, | 65 | .{ .@"and", .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 4, .none }, |
| 66 | .{ .@"and", .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 4, .rex }, | 66 | .{ .@"and", .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 4, .rex }, |
| 67 | .{ .@"and", .mi, .rm16, .imm16, .none, .none, &.{ 0x81 }, 4, .none }, | 67 | .{ .@"and", .mi, &.{ .rm16, .imm16 }, &.{ 0x81 }, 4, .none }, |
| 68 | .{ .@"and", .mi, .rm32, .imm32, .none, .none, &.{ 0x81 }, 4, .none }, | 68 | .{ .@"and", .mi, &.{ .rm32, .imm32 }, &.{ 0x81 }, 4, .none }, |
| 69 | .{ .@"and", .mi, .rm64, .imm32s, .none, .none, &.{ 0x81 }, 4, .long }, | 69 | .{ .@"and", .mi, &.{ .rm64, .imm32s }, &.{ 0x81 }, 4, .long }, |
| 70 | .{ .@"and", .mi, .rm16, .imm8s, .none, .none, &.{ 0x83 }, 4, .none }, | 70 | .{ .@"and", .mi, &.{ .rm16, .imm8s }, &.{ 0x83 }, 4, .none }, |
| 71 | .{ .@"and", .mi, .rm32, .imm8s, .none, .none, &.{ 0x83 }, 4, .none }, | 71 | .{ .@"and", .mi, &.{ .rm32, .imm8s }, &.{ 0x83 }, 4, .none }, |
| 72 | .{ .@"and", .mi, .rm64, .imm8s, .none, .none, &.{ 0x83 }, 4, .long }, | 72 | .{ .@"and", .mi, &.{ .rm64, .imm8s }, &.{ 0x83 }, 4, .long }, |
| 73 | .{ .@"and", .mr, .rm8, .r8, .none, .none, &.{ 0x20 }, 0, .none }, | 73 | .{ .@"and", .mr, &.{ .rm8, .r8 }, &.{ 0x20 }, 0, .none }, |
| 74 | .{ .@"and", .mr, .rm8, .r8, .none, .none, &.{ 0x20 }, 0, .rex }, | 74 | .{ .@"and", .mr, &.{ .rm8, .r8 }, &.{ 0x20 }, 0, .rex }, |
| 75 | .{ .@"and", .mr, .rm16, .r16, .none, .none, &.{ 0x21 }, 0, .none }, | 75 | .{ .@"and", .mr, &.{ .rm16, .r16 }, &.{ 0x21 }, 0, .none }, |
| 76 | .{ .@"and", .mr, .rm32, .r32, .none, .none, &.{ 0x21 }, 0, .none }, | 76 | .{ .@"and", .mr, &.{ .rm32, .r32 }, &.{ 0x21 }, 0, .none }, |
| 77 | .{ .@"and", .mr, .rm64, .r64, .none, .none, &.{ 0x21 }, 0, .long }, | 77 | .{ .@"and", .mr, &.{ .rm64, .r64 }, &.{ 0x21 }, 0, .long }, |
| 78 | .{ .@"and", .rm, .r8, .rm8, .none, .none, &.{ 0x22 }, 0, .none }, | 78 | .{ .@"and", .rm, &.{ .r8, .rm8 }, &.{ 0x22 }, 0, .none }, |
| 79 | .{ .@"and", .rm, .r8, .rm8, .none, .none, &.{ 0x22 }, 0, .rex }, | 79 | .{ .@"and", .rm, &.{ .r8, .rm8 }, &.{ 0x22 }, 0, .rex }, |
| 80 | .{ .@"and", .rm, .r16, .rm16, .none, .none, &.{ 0x23 }, 0, .none }, | 80 | .{ .@"and", .rm, &.{ .r16, .rm16 }, &.{ 0x23 }, 0, .none }, |
| 81 | .{ .@"and", .rm, .r32, .rm32, .none, .none, &.{ 0x23 }, 0, .none }, | 81 | .{ .@"and", .rm, &.{ .r32, .rm32 }, &.{ 0x23 }, 0, .none }, |
| 82 | .{ .@"and", .rm, .r64, .rm64, .none, .none, &.{ 0x23 }, 0, .long }, | 82 | .{ .@"and", .rm, &.{ .r64, .rm64 }, &.{ 0x23 }, 0, .long }, |
| 83 | 83 | ||
| 84 | .{ .bsf, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0xbc }, 0, .none }, | 84 | .{ .bsf, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0xbc }, 0, .none }, |
| 85 | .{ .bsf, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0xbc }, 0, .none }, | 85 | .{ .bsf, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0xbc }, 0, .none }, |
| 86 | .{ .bsf, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0xbc }, 0, .long }, | 86 | .{ .bsf, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0xbc }, 0, .long }, |
| 87 | 87 | ||
| 88 | .{ .bsr, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0xbd }, 0, .none }, | 88 | .{ .bsr, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0xbd }, 0, .none }, |
| 89 | .{ .bsr, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0xbd }, 0, .none }, | 89 | .{ .bsr, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0xbd }, 0, .none }, |
| 90 | .{ .bsr, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0xbd }, 0, .long }, | 90 | .{ .bsr, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0xbd }, 0, .long }, |
| 91 | 91 | ||
| 92 | .{ .bswap, .o, .r32, .none, .none, .none, &.{ 0x0f, 0xc8 }, 0, .none }, | 92 | .{ .bswap, .o, &.{ .r32 }, &.{ 0x0f, 0xc8 }, 0, .none }, |
| 93 | .{ .bswap, .o, .r64, .none, .none, .none, &.{ 0x0f, 0xc8 }, 0, .long }, | 93 | .{ .bswap, .o, &.{ .r64 }, &.{ 0x0f, 0xc8 }, 0, .long }, |
| 94 | 94 | ||
| 95 | .{ .bt, .mr, .rm16, .r16, .none, .none, &.{ 0x0f, 0xa3 }, 0, .none }, | 95 | .{ .bt, .mr, &.{ .rm16, .r16 }, &.{ 0x0f, 0xa3 }, 0, .none }, |
| 96 | .{ .bt, .mr, .rm32, .r32, .none, .none, &.{ 0x0f, 0xa3 }, 0, .none }, | 96 | .{ .bt, .mr, &.{ .rm32, .r32 }, &.{ 0x0f, 0xa3 }, 0, .none }, |
| 97 | .{ .bt, .mr, .rm64, .r64, .none, .none, &.{ 0x0f, 0xa3 }, 0, .long }, | 97 | .{ .bt, .mr, &.{ .rm64, .r64 }, &.{ 0x0f, 0xa3 }, 0, .long }, |
| 98 | .{ .bt, .mi, .rm16, .imm8, .none, .none, &.{ 0x0f, 0xba }, 4, .none }, | 98 | .{ .bt, .mi, &.{ .rm16, .imm8 }, &.{ 0x0f, 0xba }, 4, .none }, |
| 99 | .{ .bt, .mi, .rm32, .imm8, .none, .none, &.{ 0x0f, 0xba }, 4, .none }, | 99 | .{ .bt, .mi, &.{ .rm32, .imm8 }, &.{ 0x0f, 0xba }, 4, .none }, |
| 100 | .{ .bt, .mi, .rm64, .imm8, .none, .none, &.{ 0x0f, 0xba }, 4, .long }, | 100 | .{ .bt, .mi, &.{ .rm64, .imm8 }, &.{ 0x0f, 0xba }, 4, .long }, |
| 101 | 101 | ||
| 102 | .{ .btc, .mr, .rm16, .r16, .none, .none, &.{ 0x0f, 0xbb }, 0, .none }, | 102 | .{ .btc, .mr, &.{ .rm16, .r16 }, &.{ 0x0f, 0xbb }, 0, .none }, |
| 103 | .{ .btc, .mr, .rm32, .r32, .none, .none, &.{ 0x0f, 0xbb }, 0, .none }, | 103 | .{ .btc, .mr, &.{ .rm32, .r32 }, &.{ 0x0f, 0xbb }, 0, .none }, |
| 104 | .{ .btc, .mr, .rm64, .r64, .none, .none, &.{ 0x0f, 0xbb }, 0, .long }, | 104 | .{ .btc, .mr, &.{ .rm64, .r64 }, &.{ 0x0f, 0xbb }, 0, .long }, |
| 105 | .{ .btc, .mi, .rm16, .imm8, .none, .none, &.{ 0x0f, 0xba }, 7, .none }, | 105 | .{ .btc, .mi, &.{ .rm16, .imm8 }, &.{ 0x0f, 0xba }, 7, .none }, |
| 106 | .{ .btc, .mi, .rm32, .imm8, .none, .none, &.{ 0x0f, 0xba }, 7, .none }, | 106 | .{ .btc, .mi, &.{ .rm32, .imm8 }, &.{ 0x0f, 0xba }, 7, .none }, |
| 107 | .{ .btc, .mi, .rm64, .imm8, .none, .none, &.{ 0x0f, 0xba }, 7, .long }, | 107 | .{ .btc, .mi, &.{ .rm64, .imm8 }, &.{ 0x0f, 0xba }, 7, .long }, |
| 108 | 108 | ||
| 109 | .{ .btr, .mr, .rm16, .r16, .none, .none, &.{ 0x0f, 0xb3 }, 0, .none }, | 109 | .{ .btr, .mr, &.{ .rm16, .r16 }, &.{ 0x0f, 0xb3 }, 0, .none }, |
| 110 | .{ .btr, .mr, .rm32, .r32, .none, .none, &.{ 0x0f, 0xb3 }, 0, .none }, | 110 | .{ .btr, .mr, &.{ .rm32, .r32 }, &.{ 0x0f, 0xb3 }, 0, .none }, |
| 111 | .{ .btr, .mr, .rm64, .r64, .none, .none, &.{ 0x0f, 0xb3 }, 0, .long }, | 111 | .{ .btr, .mr, &.{ .rm64, .r64 }, &.{ 0x0f, 0xb3 }, 0, .long }, |
| 112 | .{ .btr, .mi, .rm16, .imm8, .none, .none, &.{ 0x0f, 0xba }, 6, .none }, | 112 | .{ .btr, .mi, &.{ .rm16, .imm8 }, &.{ 0x0f, 0xba }, 6, .none }, |
| 113 | .{ .btr, .mi, .rm32, .imm8, .none, .none, &.{ 0x0f, 0xba }, 6, .none }, | 113 | .{ .btr, .mi, &.{ .rm32, .imm8 }, &.{ 0x0f, 0xba }, 6, .none }, |
| 114 | .{ .btr, .mi, .rm64, .imm8, .none, .none, &.{ 0x0f, 0xba }, 6, .long }, | 114 | .{ .btr, .mi, &.{ .rm64, .imm8 }, &.{ 0x0f, 0xba }, 6, .long }, |
| 115 | 115 | ||
| 116 | .{ .bts, .mr, .rm16, .r16, .none, .none, &.{ 0x0f, 0xab }, 0, .none }, | 116 | .{ .bts, .mr, &.{ .rm16, .r16 }, &.{ 0x0f, 0xab }, 0, .none }, |
| 117 | .{ .bts, .mr, .rm32, .r32, .none, .none, &.{ 0x0f, 0xab }, 0, .none }, | 117 | .{ .bts, .mr, &.{ .rm32, .r32 }, &.{ 0x0f, 0xab }, 0, .none }, |
| 118 | .{ .bts, .mr, .rm64, .r64, .none, .none, &.{ 0x0f, 0xab }, 0, .long }, | 118 | .{ .bts, .mr, &.{ .rm64, .r64 }, &.{ 0x0f, 0xab }, 0, .long }, |
| 119 | .{ .bts, .mi, .rm16, .imm8, .none, .none, &.{ 0x0f, 0xba }, 5, .none }, | 119 | .{ .bts, .mi, &.{ .rm16, .imm8 }, &.{ 0x0f, 0xba }, 5, .none }, |
| 120 | .{ .bts, .mi, .rm32, .imm8, .none, .none, &.{ 0x0f, 0xba }, 5, .none }, | 120 | .{ .bts, .mi, &.{ .rm32, .imm8 }, &.{ 0x0f, 0xba }, 5, .none }, |
| 121 | .{ .bts, .mi, .rm64, .imm8, .none, .none, &.{ 0x0f, 0xba }, 5, .long }, | 121 | .{ .bts, .mi, &.{ .rm64, .imm8 }, &.{ 0x0f, 0xba }, 5, .long }, |
| 122 | 122 | ||
| 123 | // This is M encoding according to Intel, but D makes more sense here. | 123 | // This is M encoding according to Intel, but D makes more sense here. |
| 124 | .{ .call, .d, .rel32, .none, .none, .none, &.{ 0xe8 }, 0, .none }, | 124 | .{ .call, .d, &.{ .rel32 }, &.{ 0xe8 }, 0, .none }, |
| 125 | .{ .call, .m, .rm64, .none, .none, .none, &.{ 0xff }, 2, .none }, | 125 | .{ .call, .m, &.{ .rm64 }, &.{ 0xff }, 2, .none }, |
| 126 | 126 | ||
| 127 | .{ .cbw, .np, .o16, .none, .none, .none, &.{ 0x98 }, 0, .none }, | 127 | .{ .cbw, .np, &.{ .o16 }, &.{ 0x98 }, 0, .none }, |
| 128 | .{ .cwde, .np, .o32, .none, .none, .none, &.{ 0x98 }, 0, .none }, | 128 | .{ .cwde, .np, &.{ .o32 }, &.{ 0x98 }, 0, .none }, |
| 129 | .{ .cdqe, .np, .o64, .none, .none, .none, &.{ 0x98 }, 0, .long }, | 129 | .{ .cdqe, .np, &.{ .o64 }, &.{ 0x98 }, 0, .long }, |
| 130 | 130 | ||
| 131 | .{ .cwd, .np, .o16, .none, .none, .none, &.{ 0x99 }, 0, .none }, | 131 | .{ .cwd, .np, &.{ .o16 }, &.{ 0x99 }, 0, .none }, |
| 132 | .{ .cdq, .np, .o32, .none, .none, .none, &.{ 0x99 }, 0, .none }, | 132 | .{ .cdq, .np, &.{ .o32 }, &.{ 0x99 }, 0, .none }, |
| 133 | .{ .cqo, .np, .o64, .none, .none, .none, &.{ 0x99 }, 0, .long }, | 133 | .{ .cqo, .np, &.{ .o64 }, &.{ 0x99 }, 0, .long }, |
| 134 | 134 | ||
| 135 | .{ .cmova, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x47 }, 0, .none }, | 135 | .{ .cmova, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x47 }, 0, .none }, |
| 136 | .{ .cmova, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x47 }, 0, .none }, | 136 | .{ .cmova, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x47 }, 0, .none }, |
| 137 | .{ .cmova, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x47 }, 0, .long }, | 137 | .{ .cmova, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x47 }, 0, .long }, |
| 138 | .{ .cmovae, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x43 }, 0, .none }, | 138 | .{ .cmovae, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x43 }, 0, .none }, |
| 139 | .{ .cmovae, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x43 }, 0, .none }, | 139 | .{ .cmovae, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x43 }, 0, .none }, |
| 140 | .{ .cmovae, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x43 }, 0, .long }, | 140 | .{ .cmovae, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x43 }, 0, .long }, |
| 141 | .{ .cmovb, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x42 }, 0, .none }, | 141 | .{ .cmovb, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x42 }, 0, .none }, |
| 142 | .{ .cmovb, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x42 }, 0, .none }, | 142 | .{ .cmovb, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x42 }, 0, .none }, |
| 143 | .{ .cmovb, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x42 }, 0, .long }, | 143 | .{ .cmovb, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x42 }, 0, .long }, |
| 144 | .{ .cmovbe, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x46 }, 0, .none }, | 144 | .{ .cmovbe, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x46 }, 0, .none }, |
| 145 | .{ .cmovbe, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x46 }, 0, .none }, | 145 | .{ .cmovbe, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x46 }, 0, .none }, |
| 146 | .{ .cmovbe, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x46 }, 0, .long }, | 146 | .{ .cmovbe, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x46 }, 0, .long }, |
| 147 | .{ .cmovc, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x42 }, 0, .none }, | 147 | .{ .cmovc, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x42 }, 0, .none }, |
| 148 | .{ .cmovc, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x42 }, 0, .none }, | 148 | .{ .cmovc, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x42 }, 0, .none }, |
| 149 | .{ .cmovc, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x42 }, 0, .long }, | 149 | .{ .cmovc, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x42 }, 0, .long }, |
| 150 | .{ .cmove, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x44 }, 0, .none }, | 150 | .{ .cmove, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x44 }, 0, .none }, |
| 151 | .{ .cmove, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x44 }, 0, .none }, | 151 | .{ .cmove, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x44 }, 0, .none }, |
| 152 | .{ .cmove, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x44 }, 0, .long }, | 152 | .{ .cmove, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x44 }, 0, .long }, |
| 153 | .{ .cmovg, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4f }, 0, .none }, | 153 | .{ .cmovg, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4f }, 0, .none }, |
| 154 | .{ .cmovg, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4f }, 0, .none }, | 154 | .{ .cmovg, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4f }, 0, .none }, |
| 155 | .{ .cmovg, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4f }, 0, .long }, | 155 | .{ .cmovg, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4f }, 0, .long }, |
| 156 | .{ .cmovge, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4d }, 0, .none }, | 156 | .{ .cmovge, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4d }, 0, .none }, |
| 157 | .{ .cmovge, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4d }, 0, .none }, | 157 | .{ .cmovge, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4d }, 0, .none }, |
| 158 | .{ .cmovge, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4d }, 0, .long }, | 158 | .{ .cmovge, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4d }, 0, .long }, |
| 159 | .{ .cmovl, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4c }, 0, .none }, | 159 | .{ .cmovl, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4c }, 0, .none }, |
| 160 | .{ .cmovl, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4c }, 0, .none }, | 160 | .{ .cmovl, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4c }, 0, .none }, |
| 161 | .{ .cmovl, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4c }, 0, .long }, | 161 | .{ .cmovl, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4c }, 0, .long }, |
| 162 | .{ .cmovle, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4e }, 0, .none }, | 162 | .{ .cmovle, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4e }, 0, .none }, |
| 163 | .{ .cmovle, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4e }, 0, .none }, | 163 | .{ .cmovle, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4e }, 0, .none }, |
| 164 | .{ .cmovle, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4e }, 0, .long }, | 164 | .{ .cmovle, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4e }, 0, .long }, |
| 165 | .{ .cmovna, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x46 }, 0, .none }, | 165 | .{ .cmovna, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x46 }, 0, .none }, |
| 166 | .{ .cmovna, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x46 }, 0, .none }, | 166 | .{ .cmovna, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x46 }, 0, .none }, |
| 167 | .{ .cmovna, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x46 }, 0, .long }, | 167 | .{ .cmovna, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x46 }, 0, .long }, |
| 168 | .{ .cmovnae, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x42 }, 0, .none }, | 168 | .{ .cmovnae, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x42 }, 0, .none }, |
| 169 | .{ .cmovnae, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x42 }, 0, .none }, | 169 | .{ .cmovnae, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x42 }, 0, .none }, |
| 170 | .{ .cmovnae, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x42 }, 0, .long }, | 170 | .{ .cmovnae, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x42 }, 0, .long }, |
| 171 | .{ .cmovnb, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x43 }, 0, .none }, | 171 | .{ .cmovnb, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x43 }, 0, .none }, |
| 172 | .{ .cmovnb, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x43 }, 0, .none }, | 172 | .{ .cmovnb, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x43 }, 0, .none }, |
| 173 | .{ .cmovnb, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x43 }, 0, .long }, | 173 | .{ .cmovnb, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x43 }, 0, .long }, |
| 174 | .{ .cmovnbe, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x47 }, 0, .none }, | 174 | .{ .cmovnbe, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x47 }, 0, .none }, |
| 175 | .{ .cmovnbe, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x47 }, 0, .none }, | 175 | .{ .cmovnbe, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x47 }, 0, .none }, |
| 176 | .{ .cmovnbe, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x47 }, 0, .long }, | 176 | .{ .cmovnbe, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x47 }, 0, .long }, |
| 177 | .{ .cmovnc, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x43 }, 0, .none }, | 177 | .{ .cmovnc, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x43 }, 0, .none }, |
| 178 | .{ .cmovnc, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x43 }, 0, .none }, | 178 | .{ .cmovnc, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x43 }, 0, .none }, |
| 179 | .{ .cmovnc, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x43 }, 0, .long }, | 179 | .{ .cmovnc, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x43 }, 0, .long }, |
| 180 | .{ .cmovne, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x45 }, 0, .none }, | 180 | .{ .cmovne, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x45 }, 0, .none }, |
| 181 | .{ .cmovne, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x45 }, 0, .none }, | 181 | .{ .cmovne, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x45 }, 0, .none }, |
| 182 | .{ .cmovne, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x45 }, 0, .long }, | 182 | .{ .cmovne, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x45 }, 0, .long }, |
| 183 | .{ .cmovng, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4e }, 0, .none }, | 183 | .{ .cmovng, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4e }, 0, .none }, |
| 184 | .{ .cmovng, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4e }, 0, .none }, | 184 | .{ .cmovng, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4e }, 0, .none }, |
| 185 | .{ .cmovng, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4e }, 0, .long }, | 185 | .{ .cmovng, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4e }, 0, .long }, |
| 186 | .{ .cmovnge, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4c }, 0, .none }, | 186 | .{ .cmovnge, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4c }, 0, .none }, |
| 187 | .{ .cmovnge, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4c }, 0, .none }, | 187 | .{ .cmovnge, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4c }, 0, .none }, |
| 188 | .{ .cmovnge, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4c }, 0, .long }, | 188 | .{ .cmovnge, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4c }, 0, .long }, |
| 189 | .{ .cmovnl, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4d }, 0, .none }, | 189 | .{ .cmovnl, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4d }, 0, .none }, |
| 190 | .{ .cmovnl, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4d }, 0, .none }, | 190 | .{ .cmovnl, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4d }, 0, .none }, |
| 191 | .{ .cmovnl, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4d }, 0, .long }, | 191 | .{ .cmovnl, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4d }, 0, .long }, |
| 192 | .{ .cmovnle, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4f }, 0, .none }, | 192 | .{ .cmovnle, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4f }, 0, .none }, |
| 193 | .{ .cmovnle, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4f }, 0, .none }, | 193 | .{ .cmovnle, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4f }, 0, .none }, |
| 194 | .{ .cmovnle, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4f }, 0, .long }, | 194 | .{ .cmovnle, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4f }, 0, .long }, |
| 195 | .{ .cmovno, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x41 }, 0, .none }, | 195 | .{ .cmovno, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x41 }, 0, .none }, |
| 196 | .{ .cmovno, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x41 }, 0, .none }, | 196 | .{ .cmovno, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x41 }, 0, .none }, |
| 197 | .{ .cmovno, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x41 }, 0, .long }, | 197 | .{ .cmovno, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x41 }, 0, .long }, |
| 198 | .{ .cmovnp, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4b }, 0, .none }, | 198 | .{ .cmovnp, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4b }, 0, .none }, |
| 199 | .{ .cmovnp, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4b }, 0, .none }, | 199 | .{ .cmovnp, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4b }, 0, .none }, |
| 200 | .{ .cmovnp, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4b }, 0, .long }, | 200 | .{ .cmovnp, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4b }, 0, .long }, |
| 201 | .{ .cmovns, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x49 }, 0, .none }, | 201 | .{ .cmovns, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x49 }, 0, .none }, |
| 202 | .{ .cmovns, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x49 }, 0, .none }, | 202 | .{ .cmovns, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x49 }, 0, .none }, |
| 203 | .{ .cmovns, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x49 }, 0, .long }, | 203 | .{ .cmovns, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x49 }, 0, .long }, |
| 204 | .{ .cmovnz, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x45 }, 0, .none }, | 204 | .{ .cmovnz, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x45 }, 0, .none }, |
| 205 | .{ .cmovnz, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x45 }, 0, .none }, | 205 | .{ .cmovnz, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x45 }, 0, .none }, |
| 206 | .{ .cmovnz, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x45 }, 0, .long }, | 206 | .{ .cmovnz, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x45 }, 0, .long }, |
| 207 | .{ .cmovo, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x40 }, 0, .none }, | 207 | .{ .cmovo, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x40 }, 0, .none }, |
| 208 | .{ .cmovo, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x40 }, 0, .none }, | 208 | .{ .cmovo, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x40 }, 0, .none }, |
| 209 | .{ .cmovo, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x40 }, 0, .long }, | 209 | .{ .cmovo, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x40 }, 0, .long }, |
| 210 | .{ .cmovp, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4a }, 0, .none }, | 210 | .{ .cmovp, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4a }, 0, .none }, |
| 211 | .{ .cmovp, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4a }, 0, .none }, | 211 | .{ .cmovp, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4a }, 0, .none }, |
| 212 | .{ .cmovp, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4a }, 0, .long }, | 212 | .{ .cmovp, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4a }, 0, .long }, |
| 213 | .{ .cmovpe, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4a }, 0, .none }, | 213 | .{ .cmovpe, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4a }, 0, .none }, |
| 214 | .{ .cmovpe, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4a }, 0, .none }, | 214 | .{ .cmovpe, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4a }, 0, .none }, |
| 215 | .{ .cmovpe, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4a }, 0, .long }, | 215 | .{ .cmovpe, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4a }, 0, .long }, |
| 216 | .{ .cmovpo, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x4b }, 0, .none }, | 216 | .{ .cmovpo, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x4b }, 0, .none }, |
| 217 | .{ .cmovpo, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x4b }, 0, .none }, | 217 | .{ .cmovpo, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x4b }, 0, .none }, |
| 218 | .{ .cmovpo, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x4b }, 0, .long }, | 218 | .{ .cmovpo, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x4b }, 0, .long }, |
| 219 | .{ .cmovs, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x48 }, 0, .none }, | 219 | .{ .cmovs, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x48 }, 0, .none }, |
| 220 | .{ .cmovs, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x48 }, 0, .none }, | 220 | .{ .cmovs, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x48 }, 0, .none }, |
| 221 | .{ .cmovs, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x48 }, 0, .long }, | 221 | .{ .cmovs, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x48 }, 0, .long }, |
| 222 | .{ .cmovz, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0x44 }, 0, .none }, | 222 | .{ .cmovz, .rm, &.{ .r16, .rm16 }, &.{ 0x0f, 0x44 }, 0, .none }, |
| 223 | .{ .cmovz, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0x44 }, 0, .none }, | 223 | .{ .cmovz, .rm, &.{ .r32, .rm32 }, &.{ 0x0f, 0x44 }, 0, .none }, |
| 224 | .{ .cmovz, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0x44 }, 0, .long }, | 224 | .{ .cmovz, .rm, &.{ .r64, .rm64 }, &.{ 0x0f, 0x44 }, 0, .long }, |
| 225 | 225 | ||
| 226 | .{ .cmp, .zi, .al, .imm8, .none, .none, &.{ 0x3c }, 0, .none }, | 226 | .{ .cmp, .zi, &.{ .al, .imm8 }, &.{ 0x3c }, 0, .none }, |
| 227 | .{ .cmp, .zi, .ax, .imm16, .none, .none, &.{ 0x3d }, 0, .none }, | 227 | .{ .cmp, .zi, &.{ .ax, .imm16 }, &.{ 0x3d }, 0, .none }, |
| 228 | .{ .cmp, .zi, .eax, .imm32, .none, .none, &.{ 0x3d }, 0, .none }, | 228 | .{ .cmp, .zi, &.{ .eax, .imm32 }, &.{ 0x3d }, 0, .none }, |
| 229 | .{ .cmp, .zi, .rax, .imm32s, .none, .none, &.{ 0x3d }, 0, .long }, | 229 | .{ .cmp, .zi, &.{ .rax, .imm32s }, &.{ 0x3d }, 0, .long }, |
| 230 | .{ .cmp, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 7, .none }, | 230 | .{ .cmp, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 7, .none }, |
| 231 | .{ .cmp, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 7, .rex }, | 231 | .{ .cmp, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 7, .rex }, |
| 232 | .{ .cmp, .mi, .rm16, .imm16, .none, .none, &.{ 0x81 }, 7, .none }, | 232 | .{ .cmp, .mi, &.{ .rm16, .imm16 }, &.{ 0x81 }, 7, .none }, |
| 233 | .{ .cmp, .mi, .rm32, .imm32, .none, .none, &.{ 0x81 }, 7, .none }, | 233 | .{ .cmp, .mi, &.{ .rm32, .imm32 }, &.{ 0x81 }, 7, .none }, |
| 234 | .{ .cmp, .mi, .rm64, .imm32s, .none, .none, &.{ 0x81 }, 7, .long }, | 234 | .{ .cmp, .mi, &.{ .rm64, .imm32s }, &.{ 0x81 }, 7, .long }, |
| 235 | .{ .cmp, .mi, .rm16, .imm8s, .none, .none, &.{ 0x83 }, 7, .none }, | 235 | .{ .cmp, .mi, &.{ .rm16, .imm8s }, &.{ 0x83 }, 7, .none }, |
| 236 | .{ .cmp, .mi, .rm32, .imm8s, .none, .none, &.{ 0x83 }, 7, .none }, | 236 | .{ .cmp, .mi, &.{ .rm32, .imm8s }, &.{ 0x83 }, 7, .none }, |
| 237 | .{ .cmp, .mi, .rm64, .imm8s, .none, .none, &.{ 0x83 }, 7, .long }, | 237 | .{ .cmp, .mi, &.{ .rm64, .imm8s }, &.{ 0x83 }, 7, .long }, |
| 238 | .{ .cmp, .mr, .rm8, .r8, .none, .none, &.{ 0x38 }, 0, .none }, | 238 | .{ .cmp, .mr, &.{ .rm8, .r8 }, &.{ 0x38 }, 0, .none }, |
| 239 | .{ .cmp, .mr, .rm8, .r8, .none, .none, &.{ 0x38 }, 0, .rex }, | 239 | .{ .cmp, .mr, &.{ .rm8, .r8 }, &.{ 0x38 }, 0, .rex }, |
| 240 | .{ .cmp, .mr, .rm16, .r16, .none, .none, &.{ 0x39 }, 0, .none }, | 240 | .{ .cmp, .mr, &.{ .rm16, .r16 }, &.{ 0x39 }, 0, .none }, |
| 241 | .{ .cmp, .mr, .rm32, .r32, .none, .none, &.{ 0x39 }, 0, .none }, | 241 | .{ .cmp, .mr, &.{ .rm32, .r32 }, &.{ 0x39 }, 0, .none }, |
| 242 | .{ .cmp, .mr, .rm64, .r64, .none, .none, &.{ 0x39 }, 0, .long }, | 242 | .{ .cmp, .mr, &.{ .rm64, .r64 }, &.{ 0x39 }, 0, .long }, |
| 243 | .{ .cmp, .rm, .r8, .rm8, .none, .none, &.{ 0x3a }, 0, .none }, | 243 | .{ .cmp, .rm, &.{ .r8, .rm8 }, &.{ 0x3a }, 0, .none }, |
| 244 | .{ .cmp, .rm, .r8, .rm8, .none, .none, &.{ 0x3a }, 0, .rex }, | 244 | .{ .cmp, .rm, &.{ .r8, .rm8 }, &.{ 0x3a }, 0, .rex }, |
| 245 | .{ .cmp, .rm, .r16, .rm16, .none, .none, &.{ 0x3b }, 0, .none }, | 245 | .{ .cmp, .rm, &.{ .r16, .rm16 }, &.{ 0x3b }, 0, .none }, |
| 246 | .{ .cmp, .rm, .r32, .rm32, .none, .none, &.{ 0x3b }, 0, .none }, | 246 | .{ .cmp, .rm, &.{ .r32, .rm32 }, &.{ 0x3b }, 0, .none }, |
| 247 | .{ .cmp, .rm, .r64, .rm64, .none, .none, &.{ 0x3b }, 0, .long }, | 247 | .{ .cmp, .rm, &.{ .r64, .rm64 }, &.{ 0x3b }, 0, .long }, |
| 248 | 248 | ||
| 249 | .{ .cmps, .np, .m8, .m8, .none, .none, &.{ 0xa6 }, 0, .none }, | 249 | .{ .cmps, .np, &.{ .m8, .m8 }, &.{ 0xa6 }, 0, .none }, |
| 250 | .{ .cmps, .np, .m16, .m16, .none, .none, &.{ 0xa7 }, 0, .none }, | 250 | .{ .cmps, .np, &.{ .m16, .m16 }, &.{ 0xa7 }, 0, .none }, |
| 251 | .{ .cmps, .np, .m32, .m32, .none, .none, &.{ 0xa7 }, 0, .none }, | 251 | .{ .cmps, .np, &.{ .m32, .m32 }, &.{ 0xa7 }, 0, .none }, |
| 252 | .{ .cmps, .np, .m64, .m64, .none, .none, &.{ 0xa7 }, 0, .long }, | 252 | .{ .cmps, .np, &.{ .m64, .m64 }, &.{ 0xa7 }, 0, .long }, |
| 253 | .{ .cmpsb, .np, .none, .none, .none, .none, &.{ 0xa6 }, 0, .none }, | 253 | |
| 254 | .{ .cmpsw, .np, .none, .none, .none, .none, &.{ 0xa7 }, 0, .short }, | 254 | .{ .cmpsb, .np, &.{}, &.{ 0xa6 }, 0, .none }, |
| 255 | .{ .cmpsd, .np, .none, .none, .none, .none, &.{ 0xa7 }, 0, .none }, | 255 | .{ .cmpsw, .np, &.{}, &.{ 0xa7 }, 0, .short }, |
| 256 | .{ .cmpsq, .np, .none, .none, .none, .none, &.{ 0xa7 }, 0, .long }, | 256 | .{ .cmpsd, .np, &.{}, &.{ 0xa7 }, 0, .none }, |
| 257 | 257 | .{ .cmpsq, .np, &.{}, &.{ 0xa7 }, 0, .long }, | |
| 258 | .{ .cmpxchg, .mr, .rm8, .r8, .none, .none, &.{ 0x0f, 0xb0 }, 0, .none }, | 258 | |
| 259 | .{ .cmpxchg, .mr, .rm8, .r8, .none, .none, &.{ 0x0f, 0xb0 }, 0, .rex }, | 259 | .{ .cmpxchg, .mr, &.{ .rm8, .r8 }, &.{ 0x0f, 0xb0 }, 0, .none }, |
| 260 | .{ .cmpxchg, .mr, .rm16, .r16, .none, .none, &.{ 0x0f, 0xb1 }, 0, .none }, | 260 | .{ .cmpxchg, .mr, &.{ .rm8, .r8 }, &.{ 0x0f, 0xb0 }, 0, .rex }, |
| 261 | .{ .cmpxchg, .mr, .rm32, .r32, .none, .none, &.{ 0x0f, 0xb1 }, 0, .none }, | 261 | .{ .cmpxchg, .mr, &.{ .rm16, .r16 }, &.{ 0x0f, 0xb1 }, 0, .none }, |
| 262 | .{ .cmpxchg, .mr, .rm64, .r64, .none, .none, &.{ 0x0f, 0xb1 }, 0, .long }, | 262 | .{ .cmpxchg, .mr, &.{ .rm32, .r32 }, &.{ 0x0f, 0xb1 }, 0, .none }, |
| 263 | 263 | .{ .cmpxchg, .mr, &.{ .rm64, .r64 }, &.{ 0x0f, 0xb1 }, 0, .long }, | |
| 264 | .{ .cmpxchg8b , .m, .m64, .none, .none, .none, &.{ 0x0f, 0xc7 }, 1, .none }, | 264 | |
| 265 | .{ .cmpxchg16b, .m, .m128, .none, .none, .none, &.{ 0x0f, 0xc7 }, 1, .long }, | 265 | .{ .cmpxchg8b , .m, &.{ .m64 }, &.{ 0x0f, 0xc7 }, 1, .none }, |
| 266 | 266 | .{ .cmpxchg16b, .m, &.{ .m128 }, &.{ 0x0f, 0xc7 }, 1, .long }, | |
| 267 | .{ .div, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 6, .none }, | 267 | |
| 268 | .{ .div, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 6, .rex }, | 268 | .{ .div, .m, &.{ .rm8 }, &.{ 0xf6 }, 6, .none }, |
| 269 | .{ .div, .m, .rm16, .none, .none, .none, &.{ 0xf7 }, 6, .none }, | 269 | .{ .div, .m, &.{ .rm8 }, &.{ 0xf6 }, 6, .rex }, |
| 270 | .{ .div, .m, .rm32, .none, .none, .none, &.{ 0xf7 }, 6, .none }, | 270 | .{ .div, .m, &.{ .rm16 }, &.{ 0xf7 }, 6, .none }, |
| 271 | .{ .div, .m, .rm64, .none, .none, .none, &.{ 0xf7 }, 6, .long }, | 271 | .{ .div, .m, &.{ .rm32 }, &.{ 0xf7 }, 6, .none }, |
| 272 | 272 | .{ .div, .m, &.{ .rm64 }, &.{ 0xf7 }, 6, .long }, | |
| 273 | .{ .fisttp, .m, .m16, .none, .none, .none, &.{ 0xdf }, 1, .fpu }, | 273 | |
| 274 | .{ .fisttp, .m, .m32, .none, .none, .none, &.{ 0xdb }, 1, .fpu }, | 274 | .{ .fisttp, .m, &.{ .m16 }, &.{ 0xdf }, 1, .fpu }, |
| 275 | .{ .fisttp, .m, .m64, .none, .none, .none, &.{ 0xdd }, 1, .fpu }, | 275 | .{ .fisttp, .m, &.{ .m32 }, &.{ 0xdb }, 1, .fpu }, |
| 276 | 276 | .{ .fisttp, .m, &.{ .m64 }, &.{ 0xdd }, 1, .fpu }, | |
| 277 | .{ .fld, .m, .m32, .none, .none, .none, &.{ 0xd9 }, 0, .fpu }, | 277 | |
| 278 | .{ .fld, .m, .m64, .none, .none, .none, &.{ 0xdd }, 0, .fpu }, | 278 | .{ .fld, .m, &.{ .m32 }, &.{ 0xd9 }, 0, .fpu }, |
| 279 | .{ .fld, .m, .m80, .none, .none, .none, &.{ 0xdb }, 5, .fpu }, | 279 | .{ .fld, .m, &.{ .m64 }, &.{ 0xdd }, 0, .fpu }, |
| 280 | 280 | .{ .fld, .m, &.{ .m80 }, &.{ 0xdb }, 5, .fpu }, | |
| 281 | .{ .idiv, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 7, .none }, | 281 | |
| 282 | .{ .idiv, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 7, .rex }, | 282 | .{ .idiv, .m, &.{ .rm8 }, &.{ 0xf6 }, 7, .none }, |
| 283 | .{ .idiv, .m, .rm16, .none, .none, .none, &.{ 0xf7 }, 7, .none }, | 283 | .{ .idiv, .m, &.{ .rm8 }, &.{ 0xf6 }, 7, .rex }, |
| 284 | .{ .idiv, .m, .rm32, .none, .none, .none, &.{ 0xf7 }, 7, .none }, | 284 | .{ .idiv, .m, &.{ .rm16 }, &.{ 0xf7 }, 7, .none }, |
| 285 | .{ .idiv, .m, .rm64, .none, .none, .none, &.{ 0xf7 }, 7, .long }, | 285 | .{ .idiv, .m, &.{ .rm32 }, &.{ 0xf7 }, 7, .none }, |
| 286 | 286 | .{ .idiv, .m, &.{ .rm64 }, &.{ 0xf7 }, 7, .long }, | |
| 287 | .{ .imul, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 5, .none }, | 287 | |
| 288 | .{ .imul, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 5, .rex }, | 288 | .{ .imul, .m, &.{ .rm8 }, &.{ 0xf6 }, 5, .none }, |
| 289 | .{ .imul, .m, .rm16, .none, .none, .none, &.{ 0xf7 }, 5, .none }, | 289 | .{ .imul, .m, &.{ .rm8 }, &.{ 0xf6 }, 5, .rex }, |
| 290 | .{ .imul, .m, .rm32, .none, .none, .none, &.{ 0xf7 }, 5, .none }, | 290 | .{ .imul, .m, &.{ .rm16, }, &.{ 0xf7 }, 5, .none }, |
| 291 | .{ .imul, .m, .rm64, .none, .none, .none, &.{ 0xf7 }, 5, .long }, | 291 | .{ .imul, .m, &.{ .rm32, }, &.{ 0xf7 }, 5, .none }, |
| 292 | .{ .imul, .rm, .r16, .rm16, .none, .none, &.{ 0x0f, 0xaf }, 0, .none }, | 292 | .{ .imul, .m, &.{ .rm64, }, &.{ 0xf7 }, 5, .long }, |
| 293 | .{ .imul, .rm, .r32, .rm32, .none, .none, &.{ 0x0f, 0xaf }, 0, .none }, | 293 | .{ .imul, .rm, &.{ .r16, .rm16, }, &.{ 0x0f, 0xaf }, 0, .none }, |
| 294 | .{ .imul, .rm, .r64, .rm64, .none, .none, &.{ 0x0f, 0xaf }, 0, .long }, | 294 | .{ .imul, .rm, &.{ .r32, .rm32, }, &.{ 0x0f, 0xaf }, 0, .none }, |
| 295 | .{ .imul, .rmi, .r16, .rm16, .imm8s, .none, &.{ 0x6b }, 0, .none }, | 295 | .{ .imul, .rm, &.{ .r64, .rm64, }, &.{ 0x0f, 0xaf }, 0, .long }, |
| 296 | .{ .imul, .rmi, .r32, .rm32, .imm8s, .none, &.{ 0x6b }, 0, .none }, | 296 | .{ .imul, .rmi, &.{ .r16, .rm16, .imm8s }, &.{ 0x6b }, 0, .none }, |
| 297 | .{ .imul, .rmi, .r64, .rm64, .imm8s, .none, &.{ 0x6b }, 0, .long }, | 297 | .{ .imul, .rmi, &.{ .r32, .rm32, .imm8s }, &.{ 0x6b }, 0, .none }, |
| 298 | .{ .imul, .rmi, .r16, .rm16, .imm16, .none, &.{ 0x69 }, 0, .none }, | 298 | .{ .imul, .rmi, &.{ .r64, .rm64, .imm8s }, &.{ 0x6b }, 0, .long }, |
| 299 | .{ .imul, .rmi, .r32, .rm32, .imm32, .none, &.{ 0x69 }, 0, .none }, | 299 | .{ .imul, .rmi, &.{ .r16, .rm16, .imm16 }, &.{ 0x69 }, 0, .none }, |
| 300 | .{ .imul, .rmi, .r64, .rm64, .imm32, .none, &.{ 0x69 }, 0, .long }, | 300 | .{ .imul, .rmi, &.{ .r32, .rm32, .imm32 }, &.{ 0x69 }, 0, .none }, |
| 301 | 301 | .{ .imul, .rmi, &.{ .r64, .rm64, .imm32 }, &.{ 0x69 }, 0, .long }, | |
| 302 | .{ .int3, .np, .none, .none, .none, .none, &.{ 0xcc }, 0, .none }, | 302 | |
| 303 | 303 | .{ .int3, .np, &.{}, &.{ 0xcc }, 0, .none }, | |
| 304 | .{ .ja, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x87 }, 0, .none }, | 304 | |
| 305 | .{ .jae, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x83 }, 0, .none }, | 305 | .{ .ja, .d, &.{ .rel32 }, &.{ 0x0f, 0x87 }, 0, .none }, |
| 306 | .{ .jb, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x82 }, 0, .none }, | 306 | .{ .jae, .d, &.{ .rel32 }, &.{ 0x0f, 0x83 }, 0, .none }, |
| 307 | .{ .jbe, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x86 }, 0, .none }, | 307 | .{ .jb, .d, &.{ .rel32 }, &.{ 0x0f, 0x82 }, 0, .none }, |
| 308 | .{ .jc, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x82 }, 0, .none }, | 308 | .{ .jbe, .d, &.{ .rel32 }, &.{ 0x0f, 0x86 }, 0, .none }, |
| 309 | .{ .jrcxz, .d, .rel32, .none, .none, .none, &.{ 0xe3 }, 0, .none }, | 309 | .{ .jc, .d, &.{ .rel32 }, &.{ 0x0f, 0x82 }, 0, .none }, |
| 310 | .{ .je, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x84 }, 0, .none }, | 310 | .{ .jrcxz, .d, &.{ .rel32 }, &.{ 0xe3 }, 0, .none }, |
| 311 | .{ .jg, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8f }, 0, .none }, | 311 | .{ .je, .d, &.{ .rel32 }, &.{ 0x0f, 0x84 }, 0, .none }, |
| 312 | .{ .jge, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8d }, 0, .none }, | 312 | .{ .jg, .d, &.{ .rel32 }, &.{ 0x0f, 0x8f }, 0, .none }, |
| 313 | .{ .jl, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8c }, 0, .none }, | 313 | .{ .jge, .d, &.{ .rel32 }, &.{ 0x0f, 0x8d }, 0, .none }, |
| 314 | .{ .jle, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8e }, 0, .none }, | 314 | .{ .jl, .d, &.{ .rel32 }, &.{ 0x0f, 0x8c }, 0, .none }, |
| 315 | .{ .jna, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x86 }, 0, .none }, | 315 | .{ .jle, .d, &.{ .rel32 }, &.{ 0x0f, 0x8e }, 0, .none }, |
| 316 | .{ .jnae, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x82 }, 0, .none }, | 316 | .{ .jna, .d, &.{ .rel32 }, &.{ 0x0f, 0x86 }, 0, .none }, |
| 317 | .{ .jnb, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x83 }, 0, .none }, | 317 | .{ .jnae, .d, &.{ .rel32 }, &.{ 0x0f, 0x82 }, 0, .none }, |
| 318 | .{ .jnbe, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x87 }, 0, .none }, | 318 | .{ .jnb, .d, &.{ .rel32 }, &.{ 0x0f, 0x83 }, 0, .none }, |
| 319 | .{ .jnc, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x83 }, 0, .none }, | 319 | .{ .jnbe, .d, &.{ .rel32 }, &.{ 0x0f, 0x87 }, 0, .none }, |
| 320 | .{ .jne, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x85 }, 0, .none }, | 320 | .{ .jnc, .d, &.{ .rel32 }, &.{ 0x0f, 0x83 }, 0, .none }, |
| 321 | .{ .jng, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8e }, 0, .none }, | 321 | .{ .jne, .d, &.{ .rel32 }, &.{ 0x0f, 0x85 }, 0, .none }, |
| 322 | .{ .jnge, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8c }, 0, .none }, | 322 | .{ .jng, .d, &.{ .rel32 }, &.{ 0x0f, 0x8e }, 0, .none }, |
| 323 | .{ .jnl, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8d }, 0, .none }, | 323 | .{ .jnge, .d, &.{ .rel32 }, &.{ 0x0f, 0x8c }, 0, .none }, |
| 324 | .{ .jnle, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8f }, 0, .none }, | 324 | .{ .jnl, .d, &.{ .rel32 }, &.{ 0x0f, 0x8d }, 0, .none }, |
| 325 | .{ .jno, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x81 }, 0, .none }, | 325 | .{ .jnle, .d, &.{ .rel32 }, &.{ 0x0f, 0x8f }, 0, .none }, |
| 326 | .{ .jnp, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8b }, 0, .none }, | 326 | .{ .jno, .d, &.{ .rel32 }, &.{ 0x0f, 0x81 }, 0, .none }, |
| 327 | .{ .jns, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x89 }, 0, .none }, | 327 | .{ .jnp, .d, &.{ .rel32 }, &.{ 0x0f, 0x8b }, 0, .none }, |
| 328 | .{ .jnz, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x85 }, 0, .none }, | 328 | .{ .jns, .d, &.{ .rel32 }, &.{ 0x0f, 0x89 }, 0, .none }, |
| 329 | .{ .jo, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x80 }, 0, .none }, | 329 | .{ .jnz, .d, &.{ .rel32 }, &.{ 0x0f, 0x85 }, 0, .none }, |
| 330 | .{ .jp, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8a }, 0, .none }, | 330 | .{ .jo, .d, &.{ .rel32 }, &.{ 0x0f, 0x80 }, 0, .none }, |
| 331 | .{ .jpe, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8a }, 0, .none }, | 331 | .{ .jp, .d, &.{ .rel32 }, &.{ 0x0f, 0x8a }, 0, .none }, |
| 332 | .{ .jpo, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x8b }, 0, .none }, | 332 | .{ .jpe, .d, &.{ .rel32 }, &.{ 0x0f, 0x8a }, 0, .none }, |
| 333 | .{ .js, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x88 }, 0, .none }, | 333 | .{ .jpo, .d, &.{ .rel32 }, &.{ 0x0f, 0x8b }, 0, .none }, |
| 334 | .{ .jz, .d, .rel32, .none, .none, .none, &.{ 0x0f, 0x84 }, 0, .none }, | 334 | .{ .js, .d, &.{ .rel32 }, &.{ 0x0f, 0x88 }, 0, .none }, |
| 335 | 335 | .{ .jz, .d, &.{ .rel32 }, &.{ 0x0f, 0x84 }, 0, .none }, | |
| 336 | .{ .jmp, .d, .rel32, .none, .none, .none, &.{ 0xe9 }, 0, .none }, | 336 | |
| 337 | .{ .jmp, .m, .rm64, .none, .none, .none, &.{ 0xff }, 4, .none }, | 337 | .{ .jmp, .d, &.{ .rel32 }, &.{ 0xe9 }, 0, .none }, |
| 338 | 338 | .{ .jmp, .m, &.{ .rm64 }, &.{ 0xff }, 4, .none }, | |
| 339 | .{ .lea, .rm, .r16, .m, .none, .none, &.{ 0x8d }, 0, .none }, | 339 | |
| 340 | .{ .lea, .rm, .r32, .m, .none, .none, &.{ 0x8d }, 0, .none }, | 340 | .{ .lea, .rm, &.{ .r16, .m }, &.{ 0x8d }, 0, .none }, |
| 341 | .{ .lea, .rm, .r64, .m, .none, .none, &.{ 0x8d }, 0, .long }, | 341 | .{ .lea, .rm, &.{ .r32, .m }, &.{ 0x8d }, 0, .none }, |
| 342 | 342 | .{ .lea, .rm, &.{ .r64, .m }, &.{ 0x8d }, 0, .long }, | |
| 343 | .{ .lfence, .np, .none, .none, .none, .none, &.{ 0x0f, 0xae, 0xe8 }, 0, .none }, | 343 | |
| 344 | 344 | .{ .lfence, .np, &.{}, &.{ 0x0f, 0xae, 0xe8 }, 0, .none }, | |
| 345 | .{ .lods, .np, .m8, .none, .none, .none, &.{ 0xac }, 0, .none }, | 345 | |
| 346 | .{ .lods, .np, .m16, .none, .none, .none, &.{ 0xad }, 0, .none }, | 346 | .{ .lods, .np, &.{ .m8 }, &.{ 0xac }, 0, .none }, |
| 347 | .{ .lods, .np, .m32, .none, .none, .none, &.{ 0xad }, 0, .none }, | 347 | .{ .lods, .np, &.{ .m16 }, &.{ 0xad }, 0, .none }, |
| 348 | .{ .lods, .np, .m64, .none, .none, .none, &.{ 0xad }, 0, .long }, | 348 | .{ .lods, .np, &.{ .m32 }, &.{ 0xad }, 0, .none }, |
| 349 | .{ .lodsb, .np, .none, .none, .none, .none, &.{ 0xac }, 0, .none }, | 349 | .{ .lods, .np, &.{ .m64 }, &.{ 0xad }, 0, .long }, |
| 350 | .{ .lodsw, .np, .none, .none, .none, .none, &.{ 0xad }, 0, .short }, | 350 | |
| 351 | .{ .lodsd, .np, .none, .none, .none, .none, &.{ 0xad }, 0, .none }, | 351 | .{ .lodsb, .np, &.{}, &.{ 0xac }, 0, .none }, |
| 352 | .{ .lodsq, .np, .none, .none, .none, .none, &.{ 0xad }, 0, .long }, | 352 | .{ .lodsw, .np, &.{}, &.{ 0xad }, 0, .short }, |
| 353 | 353 | .{ .lodsd, .np, &.{}, &.{ 0xad }, 0, .none }, | |
| 354 | .{ .lzcnt, .rm, .r16, .rm16, .none, .none, &.{ 0xf3, 0x0f, 0xbd }, 0, .none }, | 354 | .{ .lodsq, .np, &.{}, &.{ 0xad }, 0, .long }, |
| 355 | .{ .lzcnt, .rm, .r32, .rm32, .none, .none, &.{ 0xf3, 0x0f, 0xbd }, 0, .none }, | 355 | |
| 356 | .{ .lzcnt, .rm, .r64, .rm64, .none, .none, &.{ 0xf3, 0x0f, 0xbd }, 0, .long }, | 356 | .{ .lzcnt, .rm, &.{ .r16, .rm16 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .none }, |
| 357 | 357 | .{ .lzcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .none }, | |
| 358 | .{ .mfence, .np, .none, .none, .none, .none, &.{ 0x0f, 0xae, 0xf0 }, 0, .none }, | 358 | .{ .lzcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xbd }, 0, .long }, |
| 359 | 359 | ||
| 360 | .{ .mov, .mr, .rm8, .r8, .none, .none, &.{ 0x88 }, 0, .none }, | 360 | .{ .mfence, .np, &.{}, &.{ 0x0f, 0xae, 0xf0 }, 0, .none }, |
| 361 | .{ .mov, .mr, .rm8, .r8, .none, .none, &.{ 0x88 }, 0, .rex }, | 361 | |
| 362 | .{ .mov, .mr, .rm16, .r16, .none, .none, &.{ 0x89 }, 0, .none }, | 362 | .{ .mov, .mr, &.{ .rm8, .r8 }, &.{ 0x88 }, 0, .none }, |
| 363 | .{ .mov, .mr, .rm32, .r32, .none, .none, &.{ 0x89 }, 0, .none }, | 363 | .{ .mov, .mr, &.{ .rm8, .r8 }, &.{ 0x88 }, 0, .rex }, |
| 364 | .{ .mov, .mr, .rm64, .r64, .none, .none, &.{ 0x89 }, 0, .long }, | 364 | .{ .mov, .mr, &.{ .rm16, .r16 }, &.{ 0x89 }, 0, .none }, |
| 365 | .{ .mov, .rm, .r8, .rm8, .none, .none, &.{ 0x8a }, 0, .none }, | 365 | .{ .mov, .mr, &.{ .rm32, .r32 }, &.{ 0x89 }, 0, .none }, |
| 366 | .{ .mov, .rm, .r8, .rm8, .none, .none, &.{ 0x8a }, 0, .rex }, | 366 | .{ .mov, .mr, &.{ .rm64, .r64 }, &.{ 0x89 }, 0, .long }, |
| 367 | .{ .mov, .rm, .r16, .rm16, .none, .none, &.{ 0x8b }, 0, .none }, | 367 | .{ .mov, .rm, &.{ .r8, .rm8 }, &.{ 0x8a }, 0, .none }, |
| 368 | .{ .mov, .rm, .r32, .rm32, .none, .none, &.{ 0x8b }, 0, .none }, | 368 | .{ .mov, .rm, &.{ .r8, .rm8 }, &.{ 0x8a }, 0, .rex }, |
| 369 | .{ .mov, .rm, .r64, .rm64, .none, .none, &.{ 0x8b }, 0, .long }, | 369 | .{ .mov, .rm, &.{ .r16, .rm16 }, &.{ 0x8b }, 0, .none }, |
| 370 | .{ .mov, .mr, .rm16, .sreg, .none, .none, &.{ 0x8c }, 0, .none }, | 370 | .{ .mov, .rm, &.{ .r32, .rm32 }, &.{ 0x8b }, 0, .none }, |
| 371 | .{ .mov, .mr, .rm64, .sreg, .none, .none, &.{ 0x8c }, 0, .long }, | 371 | .{ .mov, .rm, &.{ .r64, .rm64 }, &.{ 0x8b }, 0, .long }, |
| 372 | .{ .mov, .rm, .sreg, .rm16, .none, .none, &.{ 0x8e }, 0, .none }, | 372 | .{ .mov, .mr, &.{ .rm16, .sreg }, &.{ 0x8c }, 0, .none }, |
| 373 | .{ .mov, .rm, .sreg, .rm64, .none, .none, &.{ 0x8e }, 0, .long }, | 373 | .{ .mov, .mr, &.{ .rm64, .sreg }, &.{ 0x8c }, 0, .long }, |
| 374 | .{ .mov, .fd, .al, .moffs, .none, .none, &.{ 0xa0 }, 0, .none }, | 374 | .{ .mov, .rm, &.{ .sreg, .rm16 }, &.{ 0x8e }, 0, .none }, |
| 375 | .{ .mov, .fd, .ax, .moffs, .none, .none, &.{ 0xa1 }, 0, .none }, | 375 | .{ .mov, .rm, &.{ .sreg, .rm64 }, &.{ 0x8e }, 0, .long }, |
| 376 | .{ .mov, .fd, .eax, .moffs, .none, .none, &.{ 0xa1 }, 0, .none }, | 376 | .{ .mov, .fd, &.{ .al, .moffs }, &.{ 0xa0 }, 0, .none }, |
| 377 | .{ .mov, .fd, .rax, .moffs, .none, .none, &.{ 0xa1 }, 0, .long }, | 377 | .{ .mov, .fd, &.{ .ax, .moffs }, &.{ 0xa1 }, 0, .none }, |
| 378 | .{ .mov, .td, .moffs, .al, .none, .none, &.{ 0xa2 }, 0, .none }, | 378 | .{ .mov, .fd, &.{ .eax, .moffs }, &.{ 0xa1 }, 0, .none }, |
| 379 | .{ .mov, .td, .moffs, .ax, .none, .none, &.{ 0xa3 }, 0, .none }, | 379 | .{ .mov, .fd, &.{ .rax, .moffs }, &.{ 0xa1 }, 0, .long }, |
| 380 | .{ .mov, .td, .moffs, .eax, .none, .none, &.{ 0xa3 }, 0, .none }, | 380 | .{ .mov, .td, &.{ .moffs, .al }, &.{ 0xa2 }, 0, .none }, |
| 381 | .{ .mov, .td, .moffs, .rax, .none, .none, &.{ 0xa3 }, 0, .long }, | 381 | .{ .mov, .td, &.{ .moffs, .ax }, &.{ 0xa3 }, 0, .none }, |
| 382 | .{ .mov, .oi, .r8, .imm8, .none, .none, &.{ 0xb0 }, 0, .none }, | 382 | .{ .mov, .td, &.{ .moffs, .eax }, &.{ 0xa3 }, 0, .none }, |
| 383 | .{ .mov, .oi, .r8, .imm8, .none, .none, &.{ 0xb0 }, 0, .rex }, | 383 | .{ .mov, .td, &.{ .moffs, .rax }, &.{ 0xa3 }, 0, .long }, |
| 384 | .{ .mov, .oi, .r16, .imm16, .none, .none, &.{ 0xb8 }, 0, .none }, | 384 | .{ .mov, .oi, &.{ .r8, .imm8 }, &.{ 0xb0 }, 0, .none }, |
| 385 | .{ .mov, .oi, .r32, .imm32, .none, .none, &.{ 0xb8 }, 0, .none }, | 385 | .{ .mov, .oi, &.{ .r8, .imm8 }, &.{ 0xb0 }, 0, .rex }, |
| 386 | .{ .mov, .oi, .r64, .imm64, .none, .none, &.{ 0xb8 }, 0, .long }, | 386 | .{ .mov, .oi, &.{ .r16, .imm16 }, &.{ 0xb8 }, 0, .none }, |
| 387 | .{ .mov, .mi, .rm8, .imm8, .none, .none, &.{ 0xc6 }, 0, .none }, | 387 | .{ .mov, .oi, &.{ .r32, .imm32 }, &.{ 0xb8 }, 0, .none }, |
| 388 | .{ .mov, .mi, .rm8, .imm8, .none, .none, &.{ 0xc6 }, 0, .rex }, | 388 | .{ .mov, .oi, &.{ .r64, .imm64 }, &.{ 0xb8 }, 0, .long }, |
| 389 | .{ .mov, .mi, .rm16, .imm16, .none, .none, &.{ 0xc7 }, 0, .none }, | 389 | .{ .mov, .mi, &.{ .rm8, .imm8 }, &.{ 0xc6 }, 0, .none }, |
| 390 | .{ .mov, .mi, .rm32, .imm32, .none, .none, &.{ 0xc7 }, 0, .none }, | 390 | .{ .mov, .mi, &.{ .rm8, .imm8 }, &.{ 0xc6 }, 0, .rex }, |
| 391 | .{ .mov, .mi, .rm64, .imm32s, .none, .none, &.{ 0xc7 }, 0, .long }, | 391 | .{ .mov, .mi, &.{ .rm16, .imm16 }, &.{ 0xc7 }, 0, .none }, |
| 392 | 392 | .{ .mov, .mi, &.{ .rm32, .imm32 }, &.{ 0xc7 }, 0, .none }, | |
| 393 | .{ .movbe, .rm, .r16, .m16, .none, .none, &.{ 0x0f, 0x38, 0xf0 }, 0, .none }, | 393 | .{ .mov, .mi, &.{ .rm64, .imm32s }, &.{ 0xc7 }, 0, .long }, |
| 394 | .{ .movbe, .rm, .r32, .m32, .none, .none, &.{ 0x0f, 0x38, 0xf0 }, 0, .none }, | 394 | |
| 395 | .{ .movbe, .rm, .r64, .m64, .none, .none, &.{ 0x0f, 0x38, 0xf0 }, 0, .long }, | 395 | .{ .movbe, .rm, &.{ .r16, .m16 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .none }, |
| 396 | .{ .movbe, .mr, .m16, .r16, .none, .none, &.{ 0x0f, 0x38, 0xf1 }, 0, .none }, | 396 | .{ .movbe, .rm, &.{ .r32, .m32 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .none }, |
| 397 | .{ .movbe, .mr, .m32, .r32, .none, .none, &.{ 0x0f, 0x38, 0xf1 }, 0, .none }, | 397 | .{ .movbe, .rm, &.{ .r64, .m64 }, &.{ 0x0f, 0x38, 0xf0 }, 0, .long }, |
| 398 | .{ .movbe, .mr, .m64, .r64, .none, .none, &.{ 0x0f, 0x38, 0xf1 }, 0, .long }, | 398 | .{ .movbe, .mr, &.{ .m16, .r16 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .none }, |
| 399 | 399 | .{ .movbe, .mr, &.{ .m32, .r32 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .none }, | |
| 400 | .{ .movs, .np, .m8, .m8, .none, .none, &.{ 0xa4 }, 0, .none }, | 400 | .{ .movbe, .mr, &.{ .m64, .r64 }, &.{ 0x0f, 0x38, 0xf1 }, 0, .long }, |
| 401 | .{ .movs, .np, .m16, .m16, .none, .none, &.{ 0xa5 }, 0, .none }, | 401 | |
| 402 | .{ .movs, .np, .m32, .m32, .none, .none, &.{ 0xa5 }, 0, .none }, | 402 | .{ .movs, .np, &.{ .m8, .m8 }, &.{ 0xa4 }, 0, .none }, |
| 403 | .{ .movs, .np, .m64, .m64, .none, .none, &.{ 0xa5 }, 0, .long }, | 403 | .{ .movs, .np, &.{ .m16, .m16 }, &.{ 0xa5 }, 0, .none }, |
| 404 | .{ .movsb, .np, .none, .none, .none, .none, &.{ 0xa4 }, 0, .none }, | 404 | .{ .movs, .np, &.{ .m32, .m32 }, &.{ 0xa5 }, 0, .none }, |
| 405 | .{ .movsw, .np, .none, .none, .none, .none, &.{ 0xa5 }, 0, .short }, | 405 | .{ .movs, .np, &.{ .m64, .m64 }, &.{ 0xa5 }, 0, .long }, |
| 406 | .{ .movsd, .np, .none, .none, .none, .none, &.{ 0xa5 }, 0, .none }, | 406 | |
| 407 | .{ .movsq, .np, .none, .none, .none, .none, &.{ 0xa5 }, 0, .long }, | 407 | .{ .movsb, .np, &.{}, &.{ 0xa4 }, 0, .none }, |
| 408 | 408 | .{ .movsw, .np, &.{}, &.{ 0xa5 }, 0, .short }, | |
| 409 | .{ .movsx, .rm, .r16, .rm8, .none, .none, &.{ 0x0f, 0xbe }, 0, .none }, | 409 | .{ .movsd, .np, &.{}, &.{ 0xa5 }, 0, .none }, |
| 410 | .{ .movsx, .rm, .r16, .rm8, .none, .none, &.{ 0x0f, 0xbe }, 0, .rex }, | 410 | .{ .movsq, .np, &.{}, &.{ 0xa5 }, 0, .long }, |
| 411 | .{ .movsx, .rm, .r32, .rm8, .none, .none, &.{ 0x0f, 0xbe }, 0, .none }, | 411 | |
| 412 | .{ .movsx, .rm, .r32, .rm8, .none, .none, &.{ 0x0f, 0xbe }, 0, .rex }, | 412 | .{ .movsx, .rm, &.{ .r16, .rm8 }, &.{ 0x0f, 0xbe }, 0, .none }, |
| 413 | .{ .movsx, .rm, .r64, .rm8, .none, .none, &.{ 0x0f, 0xbe }, 0, .long }, | 413 | .{ .movsx, .rm, &.{ .r16, .rm8 }, &.{ 0x0f, 0xbe }, 0, .rex }, |
| 414 | .{ .movsx, .rm, .r32, .rm16, .none, .none, &.{ 0x0f, 0xbf }, 0, .none }, | 414 | .{ .movsx, .rm, &.{ .r32, .rm8 }, &.{ 0x0f, 0xbe }, 0, .none }, |
| 415 | .{ .movsx, .rm, .r64, .rm16, .none, .none, &.{ 0x0f, 0xbf }, 0, .long }, | 415 | .{ .movsx, .rm, &.{ .r32, .rm8 }, &.{ 0x0f, 0xbe }, 0, .rex }, |
| 416 | .{ .movsx, .rm, &.{ .r64, .rm8 }, &.{ 0x0f, 0xbe }, 0, .long }, | ||
| 417 | .{ .movsx, .rm, &.{ .r32, .rm16 }, &.{ 0x0f, 0xbf }, 0, .none }, | ||
| 418 | .{ .movsx, .rm, &.{ .r64, .rm16 }, &.{ 0x0f, 0xbf }, 0, .long }, | ||
| 416 | 419 | ||
| 417 | // This instruction is discouraged. | 420 | // This instruction is discouraged. |
| 418 | .{ .movsxd, .rm, .r32, .rm32, .none, .none, &.{ 0x63 }, 0, .none }, | 421 | .{ .movsxd, .rm, &.{ .r32, .rm32 }, &.{ 0x63 }, 0, .none }, |
| 419 | .{ .movsxd, .rm, .r64, .rm32, .none, .none, &.{ 0x63 }, 0, .long }, | 422 | .{ .movsxd, .rm, &.{ .r64, .rm32 }, &.{ 0x63 }, 0, .long }, |
| 420 | 423 | ||
| 421 | .{ .movzx, .rm, .r16, .rm8, .none, .none, &.{ 0x0f, 0xb6 }, 0, .none }, | 424 | .{ .movzx, .rm, &.{ .r16, .rm8 }, &.{ 0x0f, 0xb6 }, 0, .none }, |
| 422 | .{ .movzx, .rm, .r32, .rm8, .none, .none, &.{ 0x0f, 0xb6 }, 0, .none }, | 425 | .{ .movzx, .rm, &.{ .r32, .rm8 }, &.{ 0x0f, 0xb6 }, 0, .none }, |
| 423 | .{ .movzx, .rm, .r64, .rm8, .none, .none, &.{ 0x0f, 0xb6 }, 0, .long }, | 426 | .{ .movzx, .rm, &.{ .r64, .rm8 }, &.{ 0x0f, 0xb6 }, 0, .long }, |
| 424 | .{ .movzx, .rm, .r32, .rm16, .none, .none, &.{ 0x0f, 0xb7 }, 0, .none }, | 427 | .{ .movzx, .rm, &.{ .r32, .rm16 }, &.{ 0x0f, 0xb7 }, 0, .none }, |
| 425 | .{ .movzx, .rm, .r64, .rm16, .none, .none, &.{ 0x0f, 0xb7 }, 0, .long }, | 428 | .{ .movzx, .rm, &.{ .r64, .rm16 }, &.{ 0x0f, 0xb7 }, 0, .long }, |
| 426 | 429 | ||
| 427 | .{ .mul, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 4, .none }, | 430 | .{ .mul, .m, &.{ .rm8 }, &.{ 0xf6 }, 4, .none }, |
| 428 | .{ .mul, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 4, .rex }, | 431 | .{ .mul, .m, &.{ .rm8 }, &.{ 0xf6 }, 4, .rex }, |
| 429 | .{ .mul, .m, .rm16, .none, .none, .none, &.{ 0xf7 }, 4, .none }, | 432 | .{ .mul, .m, &.{ .rm16 }, &.{ 0xf7 }, 4, .none }, |
| 430 | .{ .mul, .m, .rm32, .none, .none, .none, &.{ 0xf7 }, 4, .none }, | 433 | .{ .mul, .m, &.{ .rm32 }, &.{ 0xf7 }, 4, .none }, |
| 431 | .{ .mul, .m, .rm64, .none, .none, .none, &.{ 0xf7 }, 4, .long }, | 434 | .{ .mul, .m, &.{ .rm64 }, &.{ 0xf7 }, 4, .long }, |
| 432 | 435 | ||
| 433 | .{ .neg, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 3, .none }, | 436 | .{ .neg, .m, &.{ .rm8 }, &.{ 0xf6 }, 3, .none }, |
| 434 | .{ .neg, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 3, .rex }, | 437 | .{ .neg, .m, &.{ .rm8 }, &.{ 0xf6 }, 3, .rex }, |
| 435 | .{ .neg, .m, .rm16, .none, .none, .none, &.{ 0xf7 }, 3, .none }, | 438 | .{ .neg, .m, &.{ .rm16 }, &.{ 0xf7 }, 3, .none }, |
| 436 | .{ .neg, .m, .rm32, .none, .none, .none, &.{ 0xf7 }, 3, .none }, | 439 | .{ .neg, .m, &.{ .rm32 }, &.{ 0xf7 }, 3, .none }, |
| 437 | .{ .neg, .m, .rm64, .none, .none, .none, &.{ 0xf7 }, 3, .long }, | 440 | .{ .neg, .m, &.{ .rm64 }, &.{ 0xf7 }, 3, .long }, |
| 438 | 441 | ||
| 439 | .{ .nop, .np, .none, .none, .none, .none, &.{ 0x90 }, 0, .none }, | 442 | .{ .nop, .np, &.{}, &.{ 0x90 }, 0, .none }, |
| 440 | 443 | ||
| 441 | .{ .not, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 2, .none }, | 444 | .{ .not, .m, &.{ .rm8 }, &.{ 0xf6 }, 2, .none }, |
| 442 | .{ .not, .m, .rm8, .none, .none, .none, &.{ 0xf6 }, 2, .rex }, | 445 | .{ .not, .m, &.{ .rm8 }, &.{ 0xf6 }, 2, .rex }, |
| 443 | .{ .not, .m, .rm16, .none, .none, .none, &.{ 0xf7 }, 2, .none }, | 446 | .{ .not, .m, &.{ .rm16 }, &.{ 0xf7 }, 2, .none }, |
| 444 | .{ .not, .m, .rm32, .none, .none, .none, &.{ 0xf7 }, 2, .none }, | 447 | .{ .not, .m, &.{ .rm32 }, &.{ 0xf7 }, 2, .none }, |
| 445 | .{ .not, .m, .rm64, .none, .none, .none, &.{ 0xf7 }, 2, .long }, | 448 | .{ .not, .m, &.{ .rm64 }, &.{ 0xf7 }, 2, .long }, |
| 446 | 449 | ||
| 447 | .{ .@"or", .zi, .al, .imm8, .none, .none, &.{ 0x0c }, 0, .none }, | 450 | .{ .@"or", .zi, &.{ .al, .imm8 }, &.{ 0x0c }, 0, .none }, |
| 448 | .{ .@"or", .zi, .ax, .imm16, .none, .none, &.{ 0x0d }, 0, .none }, | 451 | .{ .@"or", .zi, &.{ .ax, .imm16 }, &.{ 0x0d }, 0, .none }, |
| 449 | .{ .@"or", .zi, .eax, .imm32, .none, .none, &.{ 0x0d }, 0, .none }, | 452 | .{ .@"or", .zi, &.{ .eax, .imm32 }, &.{ 0x0d }, 0, .none }, |
| 450 | .{ .@"or", .zi, .rax, .imm32s, .none, .none, &.{ 0x0d }, 0, .long }, | 453 | .{ .@"or", .zi, &.{ .rax, .imm32s }, &.{ 0x0d }, 0, .long }, |
| 451 | .{ .@"or", .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 1, .none }, | 454 | .{ .@"or", .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 1, .none }, |
| 452 | .{ .@"or", .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 1, .rex }, | 455 | .{ .@"or", .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 1, .rex }, |
| 453 | .{ .@"or", .mi, .rm16, .imm16, .none, .none, &.{ 0x81 }, 1, .none }, | 456 | .{ .@"or", .mi, &.{ .rm16, .imm16 }, &.{ 0x81 }, 1, .none }, |
| 454 | .{ .@"or", .mi, .rm32, .imm32, .none, .none, &.{ 0x81 }, 1, .none }, | 457 | .{ .@"or", .mi, &.{ .rm32, .imm32 }, &.{ 0x81 }, 1, .none }, |
| 455 | .{ .@"or", .mi, .rm64, .imm32s, .none, .none, &.{ 0x81 }, 1, .long }, | 458 | .{ .@"or", .mi, &.{ .rm64, .imm32s }, &.{ 0x81 }, 1, .long }, |
| 456 | .{ .@"or", .mi, .rm16, .imm8s, .none, .none, &.{ 0x83 }, 1, .none }, | 459 | .{ .@"or", .mi, &.{ .rm16, .imm8s }, &.{ 0x83 }, 1, .none }, |
| 457 | .{ .@"or", .mi, .rm32, .imm8s, .none, .none, &.{ 0x83 }, 1, .none }, | 460 | .{ .@"or", .mi, &.{ .rm32, .imm8s }, &.{ 0x83 }, 1, .none }, |
| 458 | .{ .@"or", .mi, .rm64, .imm8s, .none, .none, &.{ 0x83 }, 1, .long }, | 461 | .{ .@"or", .mi, &.{ .rm64, .imm8s }, &.{ 0x83 }, 1, .long }, |
| 459 | .{ .@"or", .mr, .rm8, .r8, .none, .none, &.{ 0x08 }, 0, .none }, | 462 | .{ .@"or", .mr, &.{ .rm8, .r8 }, &.{ 0x08 }, 0, .none }, |
| 460 | .{ .@"or", .mr, .rm8, .r8, .none, .none, &.{ 0x08 }, 0, .rex }, | 463 | .{ .@"or", .mr, &.{ .rm8, .r8 }, &.{ 0x08 }, 0, .rex }, |
| 461 | .{ .@"or", .mr, .rm16, .r16, .none, .none, &.{ 0x09 }, 0, .none }, | 464 | .{ .@"or", .mr, &.{ .rm16, .r16 }, &.{ 0x09 }, 0, .none }, |
| 462 | .{ .@"or", .mr, .rm32, .r32, .none, .none, &.{ 0x09 }, 0, .none }, | 465 | .{ .@"or", .mr, &.{ .rm32, .r32 }, &.{ 0x09 }, 0, .none }, |
| 463 | .{ .@"or", .mr, .rm64, .r64, .none, .none, &.{ 0x09 }, 0, .long }, | 466 | .{ .@"or", .mr, &.{ .rm64, .r64 }, &.{ 0x09 }, 0, .long }, |
| 464 | .{ .@"or", .rm, .r8, .rm8, .none, .none, &.{ 0x0a }, 0, .none }, | 467 | .{ .@"or", .rm, &.{ .r8, .rm8 }, &.{ 0x0a }, 0, .none }, |
| 465 | .{ .@"or", .rm, .r8, .rm8, .none, .none, &.{ 0x0a }, 0, .rex }, | 468 | .{ .@"or", .rm, &.{ .r8, .rm8 }, &.{ 0x0a }, 0, .rex }, |
| 466 | .{ .@"or", .rm, .r16, .rm16, .none, .none, &.{ 0x0b }, 0, .none }, | 469 | .{ .@"or", .rm, &.{ .r16, .rm16 }, &.{ 0x0b }, 0, .none }, |
| 467 | .{ .@"or", .rm, .r32, .rm32, .none, .none, &.{ 0x0b }, 0, .none }, | 470 | .{ .@"or", .rm, &.{ .r32, .rm32 }, &.{ 0x0b }, 0, .none }, |
| 468 | .{ .@"or", .rm, .r64, .rm64, .none, .none, &.{ 0x0b }, 0, .long }, | 471 | .{ .@"or", .rm, &.{ .r64, .rm64 }, &.{ 0x0b }, 0, .long }, |
| 469 | 472 | ||
| 470 | .{ .pop, .o, .r16, .none, .none, .none, &.{ 0x58 }, 0, .none }, | 473 | .{ .pop, .o, &.{ .r16 }, &.{ 0x58 }, 0, .none }, |
| 471 | .{ .pop, .o, .r64, .none, .none, .none, &.{ 0x58 }, 0, .none }, | 474 | .{ .pop, .o, &.{ .r64 }, &.{ 0x58 }, 0, .none }, |
| 472 | .{ .pop, .m, .rm16, .none, .none, .none, &.{ 0x8f }, 0, .none }, | 475 | .{ .pop, .m, &.{ .rm16 }, &.{ 0x8f }, 0, .none }, |
| 473 | .{ .pop, .m, .rm64, .none, .none, .none, &.{ 0x8f }, 0, .none }, | 476 | .{ .pop, .m, &.{ .rm64 }, &.{ 0x8f }, 0, .none }, |
| 474 | 477 | ||
| 475 | .{ .popcnt, .rm, .r16, .rm16, .none, .none, &.{ 0xf3, 0x0f, 0xb8 }, 0, .none }, | 478 | .{ .popcnt, .rm, &.{ .r16, .rm16 }, &.{ 0xf3, 0x0f, 0xb8 }, 0, .none }, |
| 476 | .{ .popcnt, .rm, .r32, .rm32, .none, .none, &.{ 0xf3, 0x0f, 0xb8 }, 0, .none }, | 479 | .{ .popcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xb8 }, 0, .none }, |
| 477 | .{ .popcnt, .rm, .r64, .rm64, .none, .none, &.{ 0xf3, 0x0f, 0xb8 }, 0, .long }, | 480 | .{ .popcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xb8 }, 0, .long }, |
| 478 | 481 | ||
| 479 | .{ .push, .o, .r16, .none, .none, .none, &.{ 0x50 }, 0, .none }, | 482 | .{ .push, .o, &.{ .r16 }, &.{ 0x50 }, 0, .none }, |
| 480 | .{ .push, .o, .r64, .none, .none, .none, &.{ 0x50 }, 0, .none }, | 483 | .{ .push, .o, &.{ .r64 }, &.{ 0x50 }, 0, .none }, |
| 481 | .{ .push, .m, .rm16, .none, .none, .none, &.{ 0xff }, 6, .none }, | 484 | .{ .push, .m, &.{ .rm16 }, &.{ 0xff }, 6, .none }, |
| 482 | .{ .push, .m, .rm64, .none, .none, .none, &.{ 0xff }, 6, .none }, | 485 | .{ .push, .m, &.{ .rm64 }, &.{ 0xff }, 6, .none }, |
| 483 | .{ .push, .i, .imm8, .none, .none, .none, &.{ 0x6a }, 0, .none }, | 486 | .{ .push, .i, &.{ .imm8 }, &.{ 0x6a }, 0, .none }, |
| 484 | .{ .push, .i, .imm16, .none, .none, .none, &.{ 0x68 }, 0, .none }, | 487 | .{ .push, .i, &.{ .imm16 }, &.{ 0x68 }, 0, .none }, |
| 485 | .{ .push, .i, .imm32, .none, .none, .none, &.{ 0x68 }, 0, .none }, | 488 | .{ .push, .i, &.{ .imm32 }, &.{ 0x68 }, 0, .none }, |
| 486 | 489 | ||
| 487 | .{ .ret, .np, .none, .none, .none, .none, &.{ 0xc3 }, 0, .none }, | 490 | .{ .ret, .np, &.{}, &.{ 0xc3 }, 0, .none }, |
| 488 | 491 | ||
| 489 | .{ .rcl, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 2, .none }, | 492 | .{ .rcl, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 2, .none }, |
| 490 | .{ .rcl, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 2, .rex }, | 493 | .{ .rcl, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 2, .rex }, |
| 491 | .{ .rcl, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 2, .none }, | 494 | .{ .rcl, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 2, .none }, |
| 492 | .{ .rcl, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 2, .rex }, | 495 | .{ .rcl, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 2, .rex }, |
| 493 | .{ .rcl, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 2, .none }, | 496 | .{ .rcl, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 2, .none }, |
| 494 | .{ .rcl, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 2, .rex }, | 497 | .{ .rcl, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 2, .rex }, |
| 495 | .{ .rcl, .m1, .rm16, .unity, .none, .none, &.{ 0xd1 }, 2, .none }, | 498 | .{ .rcl, .m1, &.{ .rm16, .unity }, &.{ 0xd1 }, 2, .none }, |
| 496 | .{ .rcl, .mc, .rm16, .cl, .none, .none, &.{ 0xd3 }, 2, .none }, | 499 | .{ .rcl, .mc, &.{ .rm16, .cl }, &.{ 0xd3 }, 2, .none }, |
| 497 | .{ .rcl, .mi, .rm16, .imm8, .none, .none, &.{ 0xc1 }, 2, .none }, | 500 | .{ .rcl, .mi, &.{ .rm16, .imm8 }, &.{ 0xc1 }, 2, .none }, |
| 498 | .{ .rcl, .m1, .rm32, .unity, .none, .none, &.{ 0xd1 }, 2, .none }, | 501 | .{ .rcl, .m1, &.{ .rm32, .unity }, &.{ 0xd1 }, 2, .none }, |
| 499 | .{ .rcl, .m1, .rm64, .unity, .none, .none, &.{ 0xd1 }, 2, .long }, | 502 | .{ .rcl, .m1, &.{ .rm64, .unity }, &.{ 0xd1 }, 2, .long }, |
| 500 | .{ .rcl, .mc, .rm32, .cl, .none, .none, &.{ 0xd3 }, 2, .none }, | 503 | .{ .rcl, .mc, &.{ .rm32, .cl }, &.{ 0xd3 }, 2, .none }, |
| 501 | .{ .rcl, .mc, .rm64, .cl, .none, .none, &.{ 0xd3 }, 2, .long }, | 504 | .{ .rcl, .mc, &.{ .rm64, .cl }, &.{ 0xd3 }, 2, .long }, |
| 502 | .{ .rcl, .mi, .rm32, .imm8, .none, .none, &.{ 0xc1 }, 2, .none }, | 505 | .{ .rcl, .mi, &.{ .rm32, .imm8 }, &.{ 0xc1 }, 2, .none }, |
| 503 | .{ .rcl, .mi, .rm64, .imm8, .none, .none, &.{ 0xc1 }, 2, .long }, | 506 | .{ .rcl, .mi, &.{ .rm64, .imm8 }, &.{ 0xc1 }, 2, .long }, |
| 504 | 507 | ||
| 505 | .{ .rcr, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 3, .none }, | 508 | .{ .rcr, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 3, .none }, |
| 506 | .{ .rcr, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 3, .rex }, | 509 | .{ .rcr, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 3, .rex }, |
| 507 | .{ .rcr, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 3, .none }, | 510 | .{ .rcr, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 3, .none }, |
| 508 | .{ .rcr, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 3, .rex }, | 511 | .{ .rcr, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 3, .rex }, |
| 509 | .{ .rcr, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 3, .none }, | 512 | .{ .rcr, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 3, .none }, |
| 510 | .{ .rcr, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 3, .rex }, | 513 | .{ .rcr, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 3, .rex }, |
| 511 | .{ .rcr, .m1, .rm16, .unity, .none, .none, &.{ 0xd1 }, 3, .none }, | 514 | .{ .rcr, .m1, &.{ .rm16, .unity }, &.{ 0xd1 }, 3, .none }, |
| 512 | .{ .rcr, .mc, .rm16, .cl, .none, .none, &.{ 0xd3 }, 3, .none }, | 515 | .{ .rcr, .mc, &.{ .rm16, .cl }, &.{ 0xd3 }, 3, .none }, |
| 513 | .{ .rcr, .mi, .rm16, .imm8, .none, .none, &.{ 0xc1 }, 3, .none }, | 516 | .{ .rcr, .mi, &.{ .rm16, .imm8 }, &.{ 0xc1 }, 3, .none }, |
| 514 | .{ .rcr, .m1, .rm32, .unity, .none, .none, &.{ 0xd1 }, 3, .none }, | 517 | .{ .rcr, .m1, &.{ .rm32, .unity }, &.{ 0xd1 }, 3, .none }, |
| 515 | .{ .rcr, .m1, .rm64, .unity, .none, .none, &.{ 0xd1 }, 3, .long }, | 518 | .{ .rcr, .m1, &.{ .rm64, .unity }, &.{ 0xd1 }, 3, .long }, |
| 516 | .{ .rcr, .mc, .rm32, .cl, .none, .none, &.{ 0xd3 }, 3, .none }, | 519 | .{ .rcr, .mc, &.{ .rm32, .cl }, &.{ 0xd3 }, 3, .none }, |
| 517 | .{ .rcr, .mc, .rm64, .cl, .none, .none, &.{ 0xd3 }, 3, .long }, | 520 | .{ .rcr, .mc, &.{ .rm64, .cl }, &.{ 0xd3 }, 3, .long }, |
| 518 | .{ .rcr, .mi, .rm32, .imm8, .none, .none, &.{ 0xc1 }, 3, .none }, | 521 | .{ .rcr, .mi, &.{ .rm32, .imm8 }, &.{ 0xc1 }, 3, .none }, |
| 519 | .{ .rcr, .mi, .rm64, .imm8, .none, .none, &.{ 0xc1 }, 3, .long }, | 522 | .{ .rcr, .mi, &.{ .rm64, .imm8 }, &.{ 0xc1 }, 3, .long }, |
| 520 | 523 | ||
| 521 | .{ .rol, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 0, .none }, | 524 | .{ .rol, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 0, .none }, |
| 522 | .{ .rol, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 0, .rex }, | 525 | .{ .rol, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 0, .rex }, |
| 523 | .{ .rol, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 0, .none }, | 526 | .{ .rol, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 0, .none }, |
| 524 | .{ .rol, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 0, .rex }, | 527 | .{ .rol, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 0, .rex }, |
| 525 | .{ .rol, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 0, .none }, | 528 | .{ .rol, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 0, .none }, |
| 526 | .{ .rol, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 0, .rex }, | 529 | .{ .rol, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 0, .rex }, |
| 527 | .{ .rol, .m1, .rm16, .unity, .none, .none, &.{ 0xd1 }, 0, .none }, | 530 | .{ .rol, .m1, &.{ .rm16, .unity }, &.{ 0xd1 }, 0, .none }, |
| 528 | .{ .rol, .mc, .rm16, .cl, .none, .none, &.{ 0xd3 }, 0, .none }, | 531 | .{ .rol, .mc, &.{ .rm16, .cl }, &.{ 0xd3 }, 0, .none }, |
| 529 | .{ .rol, .mi, .rm16, .imm8, .none, .none, &.{ 0xc1 }, 0, .none }, | 532 | .{ .rol, .mi, &.{ .rm16, .imm8 }, &.{ 0xc1 }, 0, .none }, |
| 530 | .{ .rol, .m1, .rm32, .unity, .none, .none, &.{ 0xd1 }, 0, .none }, | 533 | .{ .rol, .m1, &.{ .rm32, .unity }, &.{ 0xd1 }, 0, .none }, |
| 531 | .{ .rol, .m1, .rm64, .unity, .none, .none, &.{ 0xd1 }, 0, .long }, | 534 | .{ .rol, .m1, &.{ .rm64, .unity }, &.{ 0xd1 }, 0, .long }, |
| 532 | .{ .rol, .mc, .rm32, .cl, .none, .none, &.{ 0xd3 }, 0, .none }, | 535 | .{ .rol, .mc, &.{ .rm32, .cl }, &.{ 0xd3 }, 0, .none }, |
| 533 | .{ .rol, .mc, .rm64, .cl, .none, .none, &.{ 0xd3 }, 0, .long }, | 536 | .{ .rol, .mc, &.{ .rm64, .cl }, &.{ 0xd3 }, 0, .long }, |
| 534 | .{ .rol, .mi, .rm32, .imm8, .none, .none, &.{ 0xc1 }, 0, .none }, | 537 | .{ .rol, .mi, &.{ .rm32, .imm8 }, &.{ 0xc1 }, 0, .none }, |
| 535 | .{ .rol, .mi, .rm64, .imm8, .none, .none, &.{ 0xc1 }, 0, .long }, | 538 | .{ .rol, .mi, &.{ .rm64, .imm8 }, &.{ 0xc1 }, 0, .long }, |
| 536 | 539 | ||
| 537 | .{ .ror, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 1, .none }, | 540 | .{ .ror, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 1, .none }, |
| 538 | .{ .ror, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 1, .rex }, | 541 | .{ .ror, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 1, .rex }, |
| 539 | .{ .ror, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 1, .none }, | 542 | .{ .ror, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 1, .none }, |
| 540 | .{ .ror, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 1, .rex }, | 543 | .{ .ror, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 1, .rex }, |
| 541 | .{ .ror, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 1, .none }, | 544 | .{ .ror, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 1, .none }, |
| 542 | .{ .ror, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 1, .rex }, | 545 | .{ .ror, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 1, .rex }, |
| 543 | .{ .ror, .m1, .rm16, .unity, .none, .none, &.{ 0xd1 }, 1, .none }, | 546 | .{ .ror, .m1, &.{ .rm16, .unity }, &.{ 0xd1 }, 1, .none }, |
| 544 | .{ .ror, .mc, .rm16, .cl, .none, .none, &.{ 0xd3 }, 1, .none }, | 547 | .{ .ror, .mc, &.{ .rm16, .cl }, &.{ 0xd3 }, 1, .none }, |
| 545 | .{ .ror, .mi, .rm16, .imm8, .none, .none, &.{ 0xc1 }, 1, .none }, | 548 | .{ .ror, .mi, &.{ .rm16, .imm8 }, &.{ 0xc1 }, 1, .none }, |
| 546 | .{ .ror, .m1, .rm32, .unity, .none, .none, &.{ 0xd1 }, 1, .none }, | 549 | .{ .ror, .m1, &.{ .rm32, .unity }, &.{ 0xd1 }, 1, .none }, |
| 547 | .{ .ror, .m1, .rm64, .unity, .none, .none, &.{ 0xd1 }, 1, .long }, | 550 | .{ .ror, .m1, &.{ .rm64, .unity }, &.{ 0xd1 }, 1, .long }, |
| 548 | .{ .ror, .mc, .rm32, .cl, .none, .none, &.{ 0xd3 }, 1, .none }, | 551 | .{ .ror, .mc, &.{ .rm32, .cl }, &.{ 0xd3 }, 1, .none }, |
| 549 | .{ .ror, .mc, .rm64, .cl, .none, .none, &.{ 0xd3 }, 1, .long }, | 552 | .{ .ror, .mc, &.{ .rm64, .cl }, &.{ 0xd3 }, 1, .long }, |
| 550 | .{ .ror, .mi, .rm32, .imm8, .none, .none, &.{ 0xc1 }, 1, .none }, | 553 | .{ .ror, .mi, &.{ .rm32, .imm8 }, &.{ 0xc1 }, 1, .none }, |
| 551 | .{ .ror, .mi, .rm64, .imm8, .none, .none, &.{ 0xc1 }, 1, .long }, | 554 | .{ .ror, .mi, &.{ .rm64, .imm8 }, &.{ 0xc1 }, 1, .long }, |
| 552 | 555 | ||
| 553 | .{ .sal, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 4, .none }, | 556 | .{ .sal, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 4, .none }, |
| 554 | .{ .sal, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 4, .rex }, | 557 | .{ .sal, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 4, .rex }, |
| 555 | .{ .sal, .m1, .rm16, .unity, .none, .none, &.{ 0xd1 }, 4, .none }, | 558 | .{ .sal, .m1, &.{ .rm16, .unity }, &.{ 0xd1 }, 4, .none }, |
| 556 | .{ .sal, .m1, .rm32, .unity, .none, .none, &.{ 0xd1 }, 4, .none }, | 559 | .{ .sal, .m1, &.{ .rm32, .unity }, &.{ 0xd1 }, 4, .none }, |
| 557 | .{ .sal, .m1, .rm64, .unity, .none, .none, &.{ 0xd1 }, 4, .long }, | 560 | .{ .sal, .m1, &.{ .rm64, .unity }, &.{ 0xd1 }, 4, .long }, |
| 558 | .{ .sal, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 4, .none }, | 561 | .{ .sal, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 4, .none }, |
| 559 | .{ .sal, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 4, .rex }, | 562 | .{ .sal, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 4, .rex }, |
| 560 | .{ .sal, .mc, .rm16, .cl, .none, .none, &.{ 0xd3 }, 4, .none }, | 563 | .{ .sal, .mc, &.{ .rm16, .cl }, &.{ 0xd3 }, 4, .none }, |
| 561 | .{ .sal, .mc, .rm32, .cl, .none, .none, &.{ 0xd3 }, 4, .none }, | 564 | .{ .sal, .mc, &.{ .rm32, .cl }, &.{ 0xd3 }, 4, .none }, |
| 562 | .{ .sal, .mc, .rm64, .cl, .none, .none, &.{ 0xd3 }, 4, .long }, | 565 | .{ .sal, .mc, &.{ .rm64, .cl }, &.{ 0xd3 }, 4, .long }, |
| 563 | .{ .sal, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 4, .none }, | 566 | .{ .sal, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 4, .none }, |
| 564 | .{ .sal, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 4, .rex }, | 567 | .{ .sal, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 4, .rex }, |
| 565 | .{ .sal, .mi, .rm16, .imm8, .none, .none, &.{ 0xc1 }, 4, .none }, | 568 | .{ .sal, .mi, &.{ .rm16, .imm8 }, &.{ 0xc1 }, 4, .none }, |
| 566 | .{ .sal, .mi, .rm32, .imm8, .none, .none, &.{ 0xc1 }, 4, .none }, | 569 | .{ .sal, .mi, &.{ .rm32, .imm8 }, &.{ 0xc1 }, 4, .none }, |
| 567 | .{ .sal, .mi, .rm64, .imm8, .none, .none, &.{ 0xc1 }, 4, .long }, | 570 | .{ .sal, .mi, &.{ .rm64, .imm8 }, &.{ 0xc1 }, 4, .long }, |
| 568 | 571 | ||
| 569 | .{ .sar, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 7, .none }, | 572 | .{ .sar, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 7, .none }, |
| 570 | .{ .sar, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 7, .rex }, | 573 | .{ .sar, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 7, .rex }, |
| 571 | .{ .sar, .m1, .rm16, .unity, .none, .none, &.{ 0xd1 }, 7, .none }, | 574 | .{ .sar, .m1, &.{ .rm16, .unity }, &.{ 0xd1 }, 7, .none }, |
| 572 | .{ .sar, .m1, .rm32, .unity, .none, .none, &.{ 0xd1 }, 7, .none }, | 575 | .{ .sar, .m1, &.{ .rm32, .unity }, &.{ 0xd1 }, 7, .none }, |
| 573 | .{ .sar, .m1, .rm64, .unity, .none, .none, &.{ 0xd1 }, 7, .long }, | 576 | .{ .sar, .m1, &.{ .rm64, .unity }, &.{ 0xd1 }, 7, .long }, |
| 574 | .{ .sar, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 7, .none }, | 577 | .{ .sar, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 7, .none }, |
| 575 | .{ .sar, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 7, .rex }, | 578 | .{ .sar, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 7, .rex }, |
| 576 | .{ .sar, .mc, .rm16, .cl, .none, .none, &.{ 0xd3 }, 7, .none }, | 579 | .{ .sar, .mc, &.{ .rm16, .cl }, &.{ 0xd3 }, 7, .none }, |
| 577 | .{ .sar, .mc, .rm32, .cl, .none, .none, &.{ 0xd3 }, 7, .none }, | 580 | .{ .sar, .mc, &.{ .rm32, .cl }, &.{ 0xd3 }, 7, .none }, |
| 578 | .{ .sar, .mc, .rm64, .cl, .none, .none, &.{ 0xd3 }, 7, .long }, | 581 | .{ .sar, .mc, &.{ .rm64, .cl }, &.{ 0xd3 }, 7, .long }, |
| 579 | .{ .sar, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 7, .none }, | 582 | .{ .sar, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 7, .none }, |
| 580 | .{ .sar, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 7, .rex }, | 583 | .{ .sar, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 7, .rex }, |
| 581 | .{ .sar, .mi, .rm16, .imm8, .none, .none, &.{ 0xc1 }, 7, .none }, | 584 | .{ .sar, .mi, &.{ .rm16, .imm8 }, &.{ 0xc1 }, 7, .none }, |
| 582 | .{ .sar, .mi, .rm32, .imm8, .none, .none, &.{ 0xc1 }, 7, .none }, | 585 | .{ .sar, .mi, &.{ .rm32, .imm8 }, &.{ 0xc1 }, 7, .none }, |
| 583 | .{ .sar, .mi, .rm64, .imm8, .none, .none, &.{ 0xc1 }, 7, .long }, | 586 | .{ .sar, .mi, &.{ .rm64, .imm8 }, &.{ 0xc1 }, 7, .long }, |
| 584 | 587 | ||
| 585 | .{ .sbb, .zi, .al, .imm8, .none, .none, &.{ 0x1c }, 0, .none }, | 588 | .{ .sbb, .zi, &.{ .al, .imm8 }, &.{ 0x1c }, 0, .none }, |
| 586 | .{ .sbb, .zi, .ax, .imm16, .none, .none, &.{ 0x1d }, 0, .none }, | 589 | .{ .sbb, .zi, &.{ .ax, .imm16 }, &.{ 0x1d }, 0, .none }, |
| 587 | .{ .sbb, .zi, .eax, .imm32, .none, .none, &.{ 0x1d }, 0, .none }, | 590 | .{ .sbb, .zi, &.{ .eax, .imm32 }, &.{ 0x1d }, 0, .none }, |
| 588 | .{ .sbb, .zi, .rax, .imm32s, .none, .none, &.{ 0x1d }, 0, .long }, | 591 | .{ .sbb, .zi, &.{ .rax, .imm32s }, &.{ 0x1d }, 0, .long }, |
| 589 | .{ .sbb, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 3, .none }, | 592 | .{ .sbb, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 3, .none }, |
| 590 | .{ .sbb, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 3, .rex }, | 593 | .{ .sbb, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 3, .rex }, |
| 591 | .{ .sbb, .mi, .rm16, .imm16, .none, .none, &.{ 0x81 }, 3, .none }, | 594 | .{ .sbb, .mi, &.{ .rm16, .imm16 }, &.{ 0x81 }, 3, .none }, |
| 592 | .{ .sbb, .mi, .rm32, .imm32, .none, .none, &.{ 0x81 }, 3, .none }, | 595 | .{ .sbb, .mi, &.{ .rm32, .imm32 }, &.{ 0x81 }, 3, .none }, |
| 593 | .{ .sbb, .mi, .rm64, .imm32s, .none, .none, &.{ 0x81 }, 3, .long }, | 596 | .{ .sbb, .mi, &.{ .rm64, .imm32s }, &.{ 0x81 }, 3, .long }, |
| 594 | .{ .sbb, .mi, .rm16, .imm8s, .none, .none, &.{ 0x83 }, 3, .none }, | 597 | .{ .sbb, .mi, &.{ .rm16, .imm8s }, &.{ 0x83 }, 3, .none }, |
| 595 | .{ .sbb, .mi, .rm32, .imm8s, .none, .none, &.{ 0x83 }, 3, .none }, | 598 | .{ .sbb, .mi, &.{ .rm32, .imm8s }, &.{ 0x83 }, 3, .none }, |
| 596 | .{ .sbb, .mi, .rm64, .imm8s, .none, .none, &.{ 0x83 }, 3, .long }, | 599 | .{ .sbb, .mi, &.{ .rm64, .imm8s }, &.{ 0x83 }, 3, .long }, |
| 597 | .{ .sbb, .mr, .rm8, .r8, .none, .none, &.{ 0x18 }, 0, .none }, | 600 | .{ .sbb, .mr, &.{ .rm8, .r8 }, &.{ 0x18 }, 0, .none }, |
| 598 | .{ .sbb, .mr, .rm8, .r8, .none, .none, &.{ 0x18 }, 0, .rex }, | 601 | .{ .sbb, .mr, &.{ .rm8, .r8 }, &.{ 0x18 }, 0, .rex }, |
| 599 | .{ .sbb, .mr, .rm16, .r16, .none, .none, &.{ 0x19 }, 0, .none }, | 602 | .{ .sbb, .mr, &.{ .rm16, .r16 }, &.{ 0x19 }, 0, .none }, |
| 600 | .{ .sbb, .mr, .rm32, .r32, .none, .none, &.{ 0x19 }, 0, .none }, | 603 | .{ .sbb, .mr, &.{ .rm32, .r32 }, &.{ 0x19 }, 0, .none }, |
| 601 | .{ .sbb, .mr, .rm64, .r64, .none, .none, &.{ 0x19 }, 0, .long }, | 604 | .{ .sbb, .mr, &.{ .rm64, .r64 }, &.{ 0x19 }, 0, .long }, |
| 602 | .{ .sbb, .rm, .r8, .rm8, .none, .none, &.{ 0x1a }, 0, .none }, | 605 | .{ .sbb, .rm, &.{ .r8, .rm8 }, &.{ 0x1a }, 0, .none }, |
| 603 | .{ .sbb, .rm, .r8, .rm8, .none, .none, &.{ 0x1a }, 0, .rex }, | 606 | .{ .sbb, .rm, &.{ .r8, .rm8 }, &.{ 0x1a }, 0, .rex }, |
| 604 | .{ .sbb, .rm, .r16, .rm16, .none, .none, &.{ 0x1b }, 0, .none }, | 607 | .{ .sbb, .rm, &.{ .r16, .rm16 }, &.{ 0x1b }, 0, .none }, |
| 605 | .{ .sbb, .rm, .r32, .rm32, .none, .none, &.{ 0x1b }, 0, .none }, | 608 | .{ .sbb, .rm, &.{ .r32, .rm32 }, &.{ 0x1b }, 0, .none }, |
| 606 | .{ .sbb, .rm, .r64, .rm64, .none, .none, &.{ 0x1b }, 0, .long }, | 609 | .{ .sbb, .rm, &.{ .r64, .rm64 }, &.{ 0x1b }, 0, .long }, |
| 607 | 610 | ||
| 608 | .{ .scas, .np, .m8, .none, .none, .none, &.{ 0xae }, 0, .none }, | 611 | .{ .scas, .np, &.{ .m8 }, &.{ 0xae }, 0, .none }, |
| 609 | .{ .scas, .np, .m16, .none, .none, .none, &.{ 0xaf }, 0, .none }, | 612 | .{ .scas, .np, &.{ .m16 }, &.{ 0xaf }, 0, .none }, |
| 610 | .{ .scas, .np, .m32, .none, .none, .none, &.{ 0xaf }, 0, .none }, | 613 | .{ .scas, .np, &.{ .m32 }, &.{ 0xaf }, 0, .none }, |
| 611 | .{ .scas, .np, .m64, .none, .none, .none, &.{ 0xaf }, 0, .long }, | 614 | .{ .scas, .np, &.{ .m64 }, &.{ 0xaf }, 0, .long }, |
| 612 | .{ .scasb, .np, .none, .none, .none, .none, &.{ 0xae }, 0, .none }, | 615 | |
| 613 | .{ .scasw, .np, .none, .none, .none, .none, &.{ 0xaf }, 0, .short }, | 616 | .{ .scasb, .np, &.{}, &.{ 0xae }, 0, .none }, |
| 614 | .{ .scasd, .np, .none, .none, .none, .none, &.{ 0xaf }, 0, .none }, | 617 | .{ .scasw, .np, &.{}, &.{ 0xaf }, 0, .short }, |
| 615 | .{ .scasq, .np, .none, .none, .none, .none, &.{ 0xaf }, 0, .long }, | 618 | .{ .scasd, .np, &.{}, &.{ 0xaf }, 0, .none }, |
| 616 | 619 | .{ .scasq, .np, &.{}, &.{ 0xaf }, 0, .long }, | |
| 617 | .{ .seta, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x97 }, 0, .none }, | 620 | |
| 618 | .{ .seta, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x97 }, 0, .rex }, | 621 | .{ .seta, .m, &.{ .rm8 }, &.{ 0x0f, 0x97 }, 0, .none }, |
| 619 | .{ .setae, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x93 }, 0, .none }, | 622 | .{ .seta, .m, &.{ .rm8 }, &.{ 0x0f, 0x97 }, 0, .rex }, |
| 620 | .{ .setae, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x93 }, 0, .rex }, | 623 | .{ .setae, .m, &.{ .rm8 }, &.{ 0x0f, 0x93 }, 0, .none }, |
| 621 | .{ .setb, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x92 }, 0, .none }, | 624 | .{ .setae, .m, &.{ .rm8 }, &.{ 0x0f, 0x93 }, 0, .rex }, |
| 622 | .{ .setb, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x92 }, 0, .rex }, | 625 | .{ .setb, .m, &.{ .rm8 }, &.{ 0x0f, 0x92 }, 0, .none }, |
| 623 | .{ .setbe, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x96 }, 0, .none }, | 626 | .{ .setb, .m, &.{ .rm8 }, &.{ 0x0f, 0x92 }, 0, .rex }, |
| 624 | .{ .setbe, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x96 }, 0, .rex }, | 627 | .{ .setbe, .m, &.{ .rm8 }, &.{ 0x0f, 0x96 }, 0, .none }, |
| 625 | .{ .setc, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x92 }, 0, .none }, | 628 | .{ .setbe, .m, &.{ .rm8 }, &.{ 0x0f, 0x96 }, 0, .rex }, |
| 626 | .{ .setc, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x92 }, 0, .rex }, | 629 | .{ .setc, .m, &.{ .rm8 }, &.{ 0x0f, 0x92 }, 0, .none }, |
| 627 | .{ .sete, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x94 }, 0, .none }, | 630 | .{ .setc, .m, &.{ .rm8 }, &.{ 0x0f, 0x92 }, 0, .rex }, |
| 628 | .{ .sete, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x94 }, 0, .rex }, | 631 | .{ .sete, .m, &.{ .rm8 }, &.{ 0x0f, 0x94 }, 0, .none }, |
| 629 | .{ .setg, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9f }, 0, .none }, | 632 | .{ .sete, .m, &.{ .rm8 }, &.{ 0x0f, 0x94 }, 0, .rex }, |
| 630 | .{ .setg, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9f }, 0, .rex }, | 633 | .{ .setg, .m, &.{ .rm8 }, &.{ 0x0f, 0x9f }, 0, .none }, |
| 631 | .{ .setge, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9d }, 0, .none }, | 634 | .{ .setg, .m, &.{ .rm8 }, &.{ 0x0f, 0x9f }, 0, .rex }, |
| 632 | .{ .setge, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9d }, 0, .rex }, | 635 | .{ .setge, .m, &.{ .rm8 }, &.{ 0x0f, 0x9d }, 0, .none }, |
| 633 | .{ .setl, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9c }, 0, .none }, | 636 | .{ .setge, .m, &.{ .rm8 }, &.{ 0x0f, 0x9d }, 0, .rex }, |
| 634 | .{ .setl, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9c }, 0, .rex }, | 637 | .{ .setl, .m, &.{ .rm8 }, &.{ 0x0f, 0x9c }, 0, .none }, |
| 635 | .{ .setle, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9e }, 0, .none }, | 638 | .{ .setl, .m, &.{ .rm8 }, &.{ 0x0f, 0x9c }, 0, .rex }, |
| 636 | .{ .setle, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9e }, 0, .rex }, | 639 | .{ .setle, .m, &.{ .rm8 }, &.{ 0x0f, 0x9e }, 0, .none }, |
| 637 | .{ .setna, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x96 }, 0, .none }, | 640 | .{ .setle, .m, &.{ .rm8 }, &.{ 0x0f, 0x9e }, 0, .rex }, |
| 638 | .{ .setna, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x96 }, 0, .rex }, | 641 | .{ .setna, .m, &.{ .rm8 }, &.{ 0x0f, 0x96 }, 0, .none }, |
| 639 | .{ .setnae, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x92 }, 0, .none }, | 642 | .{ .setna, .m, &.{ .rm8 }, &.{ 0x0f, 0x96 }, 0, .rex }, |
| 640 | .{ .setnae, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x92 }, 0, .rex }, | 643 | .{ .setnae, .m, &.{ .rm8 }, &.{ 0x0f, 0x92 }, 0, .none }, |
| 641 | .{ .setnb, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x93 }, 0, .none }, | 644 | .{ .setnae, .m, &.{ .rm8 }, &.{ 0x0f, 0x92 }, 0, .rex }, |
| 642 | .{ .setnb, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x93 }, 0, .rex }, | 645 | .{ .setnb, .m, &.{ .rm8 }, &.{ 0x0f, 0x93 }, 0, .none }, |
| 643 | .{ .setnbe, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x97 }, 0, .none }, | 646 | .{ .setnb, .m, &.{ .rm8 }, &.{ 0x0f, 0x93 }, 0, .rex }, |
| 644 | .{ .setnbe, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x97 }, 0, .rex }, | 647 | .{ .setnbe, .m, &.{ .rm8 }, &.{ 0x0f, 0x97 }, 0, .none }, |
| 645 | .{ .setnc, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x93 }, 0, .none }, | 648 | .{ .setnbe, .m, &.{ .rm8 }, &.{ 0x0f, 0x97 }, 0, .rex }, |
| 646 | .{ .setnc, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x93 }, 0, .rex }, | 649 | .{ .setnc, .m, &.{ .rm8 }, &.{ 0x0f, 0x93 }, 0, .none }, |
| 647 | .{ .setne, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x95 }, 0, .none }, | 650 | .{ .setnc, .m, &.{ .rm8 }, &.{ 0x0f, 0x93 }, 0, .rex }, |
| 648 | .{ .setne, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x95 }, 0, .rex }, | 651 | .{ .setne, .m, &.{ .rm8 }, &.{ 0x0f, 0x95 }, 0, .none }, |
| 649 | .{ .setng, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9e }, 0, .none }, | 652 | .{ .setne, .m, &.{ .rm8 }, &.{ 0x0f, 0x95 }, 0, .rex }, |
| 650 | .{ .setng, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9e }, 0, .rex }, | 653 | .{ .setng, .m, &.{ .rm8 }, &.{ 0x0f, 0x9e }, 0, .none }, |
| 651 | .{ .setnge, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9c }, 0, .none }, | 654 | .{ .setng, .m, &.{ .rm8 }, &.{ 0x0f, 0x9e }, 0, .rex }, |
| 652 | .{ .setnge, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9c }, 0, .rex }, | 655 | .{ .setnge, .m, &.{ .rm8 }, &.{ 0x0f, 0x9c }, 0, .none }, |
| 653 | .{ .setnl, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9d }, 0, .none }, | 656 | .{ .setnge, .m, &.{ .rm8 }, &.{ 0x0f, 0x9c }, 0, .rex }, |
| 654 | .{ .setnl, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9d }, 0, .rex }, | 657 | .{ .setnl, .m, &.{ .rm8 }, &.{ 0x0f, 0x9d }, 0, .none }, |
| 655 | .{ .setnle, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9f }, 0, .none }, | 658 | .{ .setnl, .m, &.{ .rm8 }, &.{ 0x0f, 0x9d }, 0, .rex }, |
| 656 | .{ .setnle, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9f }, 0, .rex }, | 659 | .{ .setnle, .m, &.{ .rm8 }, &.{ 0x0f, 0x9f }, 0, .none }, |
| 657 | .{ .setno, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x91 }, 0, .none }, | 660 | .{ .setnle, .m, &.{ .rm8 }, &.{ 0x0f, 0x9f }, 0, .rex }, |
| 658 | .{ .setno, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x91 }, 0, .rex }, | 661 | .{ .setno, .m, &.{ .rm8 }, &.{ 0x0f, 0x91 }, 0, .none }, |
| 659 | .{ .setnp, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9b }, 0, .none }, | 662 | .{ .setno, .m, &.{ .rm8 }, &.{ 0x0f, 0x91 }, 0, .rex }, |
| 660 | .{ .setnp, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9b }, 0, .rex }, | 663 | .{ .setnp, .m, &.{ .rm8 }, &.{ 0x0f, 0x9b }, 0, .none }, |
| 661 | .{ .setns, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x99 }, 0, .none }, | 664 | .{ .setnp, .m, &.{ .rm8 }, &.{ 0x0f, 0x9b }, 0, .rex }, |
| 662 | .{ .setns, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x99 }, 0, .rex }, | 665 | .{ .setns, .m, &.{ .rm8 }, &.{ 0x0f, 0x99 }, 0, .none }, |
| 663 | .{ .setnz, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x95 }, 0, .none }, | 666 | .{ .setns, .m, &.{ .rm8 }, &.{ 0x0f, 0x99 }, 0, .rex }, |
| 664 | .{ .setnz, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x95 }, 0, .rex }, | 667 | .{ .setnz, .m, &.{ .rm8 }, &.{ 0x0f, 0x95 }, 0, .none }, |
| 665 | .{ .seto, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x90 }, 0, .none }, | 668 | .{ .setnz, .m, &.{ .rm8 }, &.{ 0x0f, 0x95 }, 0, .rex }, |
| 666 | .{ .seto, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x90 }, 0, .rex }, | 669 | .{ .seto, .m, &.{ .rm8 }, &.{ 0x0f, 0x90 }, 0, .none }, |
| 667 | .{ .setp, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9a }, 0, .none }, | 670 | .{ .seto, .m, &.{ .rm8 }, &.{ 0x0f, 0x90 }, 0, .rex }, |
| 668 | .{ .setp, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9a }, 0, .rex }, | 671 | .{ .setp, .m, &.{ .rm8 }, &.{ 0x0f, 0x9a }, 0, .none }, |
| 669 | .{ .setpe, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9a }, 0, .none }, | 672 | .{ .setp, .m, &.{ .rm8 }, &.{ 0x0f, 0x9a }, 0, .rex }, |
| 670 | .{ .setpe, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9a }, 0, .rex }, | 673 | .{ .setpe, .m, &.{ .rm8 }, &.{ 0x0f, 0x9a }, 0, .none }, |
| 671 | .{ .setpo, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9b }, 0, .none }, | 674 | .{ .setpe, .m, &.{ .rm8 }, &.{ 0x0f, 0x9a }, 0, .rex }, |
| 672 | .{ .setpo, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x9b }, 0, .rex }, | 675 | .{ .setpo, .m, &.{ .rm8 }, &.{ 0x0f, 0x9b }, 0, .none }, |
| 673 | .{ .sets, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x98 }, 0, .none }, | 676 | .{ .setpo, .m, &.{ .rm8 }, &.{ 0x0f, 0x9b }, 0, .rex }, |
| 674 | .{ .sets, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x98 }, 0, .rex }, | 677 | .{ .sets, .m, &.{ .rm8 }, &.{ 0x0f, 0x98 }, 0, .none }, |
| 675 | .{ .setz, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x94 }, 0, .none }, | 678 | .{ .sets, .m, &.{ .rm8 }, &.{ 0x0f, 0x98 }, 0, .rex }, |
| 676 | .{ .setz, .m, .rm8, .none, .none, .none, &.{ 0x0f, 0x94 }, 0, .rex }, | 679 | .{ .setz, .m, &.{ .rm8 }, &.{ 0x0f, 0x94 }, 0, .none }, |
| 677 | 680 | .{ .setz, .m, &.{ .rm8 }, &.{ 0x0f, 0x94 }, 0, .rex }, | |
| 678 | .{ .sfence, .np, .none, .none, .none, .none, &.{ 0x0f, 0xae, 0xf8 }, 0, .none }, | 681 | |
| 679 | 682 | .{ .sfence, .np, &.{}, &.{ 0x0f, 0xae, 0xf8 }, 0, .none }, | |
| 680 | .{ .shl, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 4, .none }, | 683 | |
| 681 | .{ .shl, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 4, .rex }, | 684 | .{ .shl, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 4, .none }, |
| 682 | .{ .shl, .m1, .rm16, .unity, .none, .none, &.{ 0xd1 }, 4, .none }, | 685 | .{ .shl, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 4, .rex }, |
| 683 | .{ .shl, .m1, .rm32, .unity, .none, .none, &.{ 0xd1 }, 4, .none }, | 686 | .{ .shl, .m1, &.{ .rm16, .unity }, &.{ 0xd1 }, 4, .none }, |
| 684 | .{ .shl, .m1, .rm64, .unity, .none, .none, &.{ 0xd1 }, 4, .long }, | 687 | .{ .shl, .m1, &.{ .rm32, .unity }, &.{ 0xd1 }, 4, .none }, |
| 685 | .{ .shl, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 4, .none }, | 688 | .{ .shl, .m1, &.{ .rm64, .unity }, &.{ 0xd1 }, 4, .long }, |
| 686 | .{ .shl, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 4, .rex }, | 689 | .{ .shl, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 4, .none }, |
| 687 | .{ .shl, .mc, .rm16, .cl, .none, .none, &.{ 0xd3 }, 4, .none }, | 690 | .{ .shl, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 4, .rex }, |
| 688 | .{ .shl, .mc, .rm32, .cl, .none, .none, &.{ 0xd3 }, 4, .none }, | 691 | .{ .shl, .mc, &.{ .rm16, .cl }, &.{ 0xd3 }, 4, .none }, |
| 689 | .{ .shl, .mc, .rm64, .cl, .none, .none, &.{ 0xd3 }, 4, .long }, | 692 | .{ .shl, .mc, &.{ .rm32, .cl }, &.{ 0xd3 }, 4, .none }, |
| 690 | .{ .shl, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 4, .none }, | 693 | .{ .shl, .mc, &.{ .rm64, .cl }, &.{ 0xd3 }, 4, .long }, |
| 691 | .{ .shl, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 4, .rex }, | 694 | .{ .shl, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 4, .none }, |
| 692 | .{ .shl, .mi, .rm16, .imm8, .none, .none, &.{ 0xc1 }, 4, .none }, | 695 | .{ .shl, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 4, .rex }, |
| 693 | .{ .shl, .mi, .rm32, .imm8, .none, .none, &.{ 0xc1 }, 4, .none }, | 696 | .{ .shl, .mi, &.{ .rm16, .imm8 }, &.{ 0xc1 }, 4, .none }, |
| 694 | .{ .shl, .mi, .rm64, .imm8, .none, .none, &.{ 0xc1 }, 4, .long }, | 697 | .{ .shl, .mi, &.{ .rm32, .imm8 }, &.{ 0xc1 }, 4, .none }, |
| 695 | 698 | .{ .shl, .mi, &.{ .rm64, .imm8 }, &.{ 0xc1 }, 4, .long }, | |
| 696 | .{ .shld, .mri, .rm16, .r16, .imm8, .none, &.{ 0x0f, 0xa4 }, 0, .none }, | 699 | |
| 697 | .{ .shld, .mrc, .rm16, .r16, .cl, .none, &.{ 0x0f, 0xa5 }, 0, .none }, | 700 | .{ .shld, .mri, &.{ .rm16, .r16, .imm8 }, &.{ 0x0f, 0xa4 }, 0, .none }, |
| 698 | .{ .shld, .mri, .rm32, .r32, .imm8, .none, &.{ 0x0f, 0xa4 }, 0, .none }, | 701 | .{ .shld, .mrc, &.{ .rm16, .r16, .cl }, &.{ 0x0f, 0xa5 }, 0, .none }, |
| 699 | .{ .shld, .mri, .rm64, .r64, .imm8, .none, &.{ 0x0f, 0xa4 }, 0, .long }, | 702 | .{ .shld, .mri, &.{ .rm32, .r32, .imm8 }, &.{ 0x0f, 0xa4 }, 0, .none }, |
| 700 | .{ .shld, .mrc, .rm32, .r32, .cl, .none, &.{ 0x0f, 0xa5 }, 0, .none }, | 703 | .{ .shld, .mri, &.{ .rm64, .r64, .imm8 }, &.{ 0x0f, 0xa4 }, 0, .long }, |
| 701 | .{ .shld, .mrc, .rm64, .r64, .cl, .none, &.{ 0x0f, 0xa5 }, 0, .long }, | 704 | .{ .shld, .mrc, &.{ .rm32, .r32, .cl }, &.{ 0x0f, 0xa5 }, 0, .none }, |
| 702 | 705 | .{ .shld, .mrc, &.{ .rm64, .r64, .cl }, &.{ 0x0f, 0xa5 }, 0, .long }, | |
| 703 | .{ .shr, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 5, .none }, | 706 | |
| 704 | .{ .shr, .m1, .rm8, .unity, .none, .none, &.{ 0xd0 }, 5, .rex }, | 707 | .{ .shr, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 5, .none }, |
| 705 | .{ .shr, .m1, .rm16, .unity, .none, .none, &.{ 0xd1 }, 5, .none }, | 708 | .{ .shr, .m1, &.{ .rm8, .unity }, &.{ 0xd0 }, 5, .rex }, |
| 706 | .{ .shr, .m1, .rm32, .unity, .none, .none, &.{ 0xd1 }, 5, .none }, | 709 | .{ .shr, .m1, &.{ .rm16, .unity }, &.{ 0xd1 }, 5, .none }, |
| 707 | .{ .shr, .m1, .rm64, .unity, .none, .none, &.{ 0xd1 }, 5, .long }, | 710 | .{ .shr, .m1, &.{ .rm32, .unity }, &.{ 0xd1 }, 5, .none }, |
| 708 | .{ .shr, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 5, .none }, | 711 | .{ .shr, .m1, &.{ .rm64, .unity }, &.{ 0xd1 }, 5, .long }, |
| 709 | .{ .shr, .mc, .rm8, .cl, .none, .none, &.{ 0xd2 }, 5, .rex }, | 712 | .{ .shr, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 5, .none }, |
| 710 | .{ .shr, .mc, .rm16, .cl, .none, .none, &.{ 0xd3 }, 5, .none }, | 713 | .{ .shr, .mc, &.{ .rm8, .cl }, &.{ 0xd2 }, 5, .rex }, |
| 711 | .{ .shr, .mc, .rm32, .cl, .none, .none, &.{ 0xd3 }, 5, .none }, | 714 | .{ .shr, .mc, &.{ .rm16, .cl }, &.{ 0xd3 }, 5, .none }, |
| 712 | .{ .shr, .mc, .rm64, .cl, .none, .none, &.{ 0xd3 }, 5, .long }, | 715 | .{ .shr, .mc, &.{ .rm32, .cl }, &.{ 0xd3 }, 5, .none }, |
| 713 | .{ .shr, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 5, .none }, | 716 | .{ .shr, .mc, &.{ .rm64, .cl }, &.{ 0xd3 }, 5, .long }, |
| 714 | .{ .shr, .mi, .rm8, .imm8, .none, .none, &.{ 0xc0 }, 5, .rex }, | 717 | .{ .shr, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 5, .none }, |
| 715 | .{ .shr, .mi, .rm16, .imm8, .none, .none, &.{ 0xc1 }, 5, .none }, | 718 | .{ .shr, .mi, &.{ .rm8, .imm8 }, &.{ 0xc0 }, 5, .rex }, |
| 716 | .{ .shr, .mi, .rm32, .imm8, .none, .none, &.{ 0xc1 }, 5, .none }, | 719 | .{ .shr, .mi, &.{ .rm16, .imm8 }, &.{ 0xc1 }, 5, .none }, |
| 717 | .{ .shr, .mi, .rm64, .imm8, .none, .none, &.{ 0xc1 }, 5, .long }, | 720 | .{ .shr, .mi, &.{ .rm32, .imm8 }, &.{ 0xc1 }, 5, .none }, |
| 718 | 721 | .{ .shr, .mi, &.{ .rm64, .imm8 }, &.{ 0xc1 }, 5, .long }, | |
| 719 | .{ .shrd, .mri, .rm16, .r16, .imm8, .none, &.{ 0x0f, 0xac }, 0, .none }, | 722 | |
| 720 | .{ .shrd, .mrc, .rm16, .r16, .cl, .none, &.{ 0x0f, 0xad }, 0, .none }, | 723 | .{ .shrd, .mri, &.{ .rm16, .r16, .imm8 }, &.{ 0x0f, 0xac }, 0, .none }, |
| 721 | .{ .shrd, .mri, .rm32, .r32, .imm8, .none, &.{ 0x0f, 0xac }, 0, .none }, | 724 | .{ .shrd, .mrc, &.{ .rm16, .r16, .cl }, &.{ 0x0f, 0xad }, 0, .none }, |
| 722 | .{ .shrd, .mri, .rm64, .r64, .imm8, .none, &.{ 0x0f, 0xac }, 0, .long }, | 725 | .{ .shrd, .mri, &.{ .rm32, .r32, .imm8 }, &.{ 0x0f, 0xac }, 0, .none }, |
| 723 | .{ .shrd, .mrc, .rm32, .r32, .cl, .none, &.{ 0x0f, 0xad }, 0, .none }, | 726 | .{ .shrd, .mri, &.{ .rm64, .r64, .imm8 }, &.{ 0x0f, 0xac }, 0, .long }, |
| 724 | .{ .shrd, .mrc, .rm64, .r64, .cl, .none, &.{ 0x0f, 0xad }, 0, .long }, | 727 | .{ .shrd, .mrc, &.{ .rm32, .r32, .cl }, &.{ 0x0f, 0xad }, 0, .none }, |
| 725 | 728 | .{ .shrd, .mrc, &.{ .rm64, .r64, .cl }, &.{ 0x0f, 0xad }, 0, .long }, | |
| 726 | .{ .stos, .np, .m8, .none, .none, .none, &.{ 0xaa }, 0, .none }, | 729 | |
| 727 | .{ .stos, .np, .m16, .none, .none, .none, &.{ 0xab }, 0, .none }, | 730 | .{ .stos, .np, &.{ .m8 }, &.{ 0xaa }, 0, .none }, |
| 728 | .{ .stos, .np, .m32, .none, .none, .none, &.{ 0xab }, 0, .none }, | 731 | .{ .stos, .np, &.{ .m16 }, &.{ 0xab }, 0, .none }, |
| 729 | .{ .stos, .np, .m64, .none, .none, .none, &.{ 0xab }, 0, .long }, | 732 | .{ .stos, .np, &.{ .m32 }, &.{ 0xab }, 0, .none }, |
| 730 | .{ .stosb, .np, .none, .none, .none, .none, &.{ 0xaa }, 0, .none }, | 733 | .{ .stos, .np, &.{ .m64 }, &.{ 0xab }, 0, .long }, |
| 731 | .{ .stosw, .np, .none, .none, .none, .none, &.{ 0xab }, 0, .short }, | 734 | |
| 732 | .{ .stosd, .np, .none, .none, .none, .none, &.{ 0xab }, 0, .none }, | 735 | .{ .stosb, .np, &.{}, &.{ 0xaa }, 0, .none }, |
| 733 | .{ .stosq, .np, .none, .none, .none, .none, &.{ 0xab }, 0, .long }, | 736 | .{ .stosw, .np, &.{}, &.{ 0xab }, 0, .short }, |
| 734 | 737 | .{ .stosd, .np, &.{}, &.{ 0xab }, 0, .none }, | |
| 735 | .{ .sub, .zi, .al, .imm8, .none, .none, &.{ 0x2c }, 0, .none }, | 738 | .{ .stosq, .np, &.{}, &.{ 0xab }, 0, .long }, |
| 736 | .{ .sub, .zi, .ax, .imm16, .none, .none, &.{ 0x2d }, 0, .none }, | 739 | |
| 737 | .{ .sub, .zi, .eax, .imm32, .none, .none, &.{ 0x2d }, 0, .none }, | 740 | .{ .sub, .zi, &.{ .al, .imm8 }, &.{ 0x2c }, 0, .none }, |
| 738 | .{ .sub, .zi, .rax, .imm32s, .none, .none, &.{ 0x2d }, 0, .long }, | 741 | .{ .sub, .zi, &.{ .ax, .imm16 }, &.{ 0x2d }, 0, .none }, |
| 739 | .{ .sub, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 5, .none }, | 742 | .{ .sub, .zi, &.{ .eax, .imm32 }, &.{ 0x2d }, 0, .none }, |
| 740 | .{ .sub, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 5, .rex }, | 743 | .{ .sub, .zi, &.{ .rax, .imm32s }, &.{ 0x2d }, 0, .long }, |
| 741 | .{ .sub, .mi, .rm16, .imm16, .none, .none, &.{ 0x81 }, 5, .none }, | 744 | .{ .sub, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 5, .none }, |
| 742 | .{ .sub, .mi, .rm32, .imm32, .none, .none, &.{ 0x81 }, 5, .none }, | 745 | .{ .sub, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 5, .rex }, |
| 743 | .{ .sub, .mi, .rm64, .imm32s, .none, .none, &.{ 0x81 }, 5, .long }, | 746 | .{ .sub, .mi, &.{ .rm16, .imm16 }, &.{ 0x81 }, 5, .none }, |
| 744 | .{ .sub, .mi, .rm16, .imm8s, .none, .none, &.{ 0x83 }, 5, .none }, | 747 | .{ .sub, .mi, &.{ .rm32, .imm32 }, &.{ 0x81 }, 5, .none }, |
| 745 | .{ .sub, .mi, .rm32, .imm8s, .none, .none, &.{ 0x83 }, 5, .none }, | 748 | .{ .sub, .mi, &.{ .rm64, .imm32s }, &.{ 0x81 }, 5, .long }, |
| 746 | .{ .sub, .mi, .rm64, .imm8s, .none, .none, &.{ 0x83 }, 5, .long }, | 749 | .{ .sub, .mi, &.{ .rm16, .imm8s }, &.{ 0x83 }, 5, .none }, |
| 747 | .{ .sub, .mr, .rm8, .r8, .none, .none, &.{ 0x28 }, 0, .none }, | 750 | .{ .sub, .mi, &.{ .rm32, .imm8s }, &.{ 0x83 }, 5, .none }, |
| 748 | .{ .sub, .mr, .rm8, .r8, .none, .none, &.{ 0x28 }, 0, .rex }, | 751 | .{ .sub, .mi, &.{ .rm64, .imm8s }, &.{ 0x83 }, 5, .long }, |
| 749 | .{ .sub, .mr, .rm16, .r16, .none, .none, &.{ 0x29 }, 0, .none }, | 752 | .{ .sub, .mr, &.{ .rm8, .r8 }, &.{ 0x28 }, 0, .none }, |
| 750 | .{ .sub, .mr, .rm32, .r32, .none, .none, &.{ 0x29 }, 0, .none }, | 753 | .{ .sub, .mr, &.{ .rm8, .r8 }, &.{ 0x28 }, 0, .rex }, |
| 751 | .{ .sub, .mr, .rm64, .r64, .none, .none, &.{ 0x29 }, 0, .long }, | 754 | .{ .sub, .mr, &.{ .rm16, .r16 }, &.{ 0x29 }, 0, .none }, |
| 752 | .{ .sub, .rm, .r8, .rm8, .none, .none, &.{ 0x2a }, 0, .none }, | 755 | .{ .sub, .mr, &.{ .rm32, .r32 }, &.{ 0x29 }, 0, .none }, |
| 753 | .{ .sub, .rm, .r8, .rm8, .none, .none, &.{ 0x2a }, 0, .rex }, | 756 | .{ .sub, .mr, &.{ .rm64, .r64 }, &.{ 0x29 }, 0, .long }, |
| 754 | .{ .sub, .rm, .r16, .rm16, .none, .none, &.{ 0x2b }, 0, .none }, | 757 | .{ .sub, .rm, &.{ .r8, .rm8 }, &.{ 0x2a }, 0, .none }, |
| 755 | .{ .sub, .rm, .r32, .rm32, .none, .none, &.{ 0x2b }, 0, .none }, | 758 | .{ .sub, .rm, &.{ .r8, .rm8 }, &.{ 0x2a }, 0, .rex }, |
| 756 | .{ .sub, .rm, .r64, .rm64, .none, .none, &.{ 0x2b }, 0, .long }, | 759 | .{ .sub, .rm, &.{ .r16, .rm16 }, &.{ 0x2b }, 0, .none }, |
| 757 | 760 | .{ .sub, .rm, &.{ .r32, .rm32 }, &.{ 0x2b }, 0, .none }, | |
| 758 | .{ .syscall, .np, .none, .none, .none, .none, &.{ 0x0f, 0x05 }, 0, .none } | 761 | .{ .sub, .rm, &.{ .r64, .rm64 }, &.{ 0x2b }, 0, .long }, |
| 762 | |||
| 763 | .{ .syscall, .np, &.{}, &.{ 0x0f, 0x05 }, 0, .none } | ||
| 759 | , | 764 | , |
| 760 | .{ .@"test", .zi, .al, .imm8, .none, .none, &.{ 0xa8 }, 0, .none }, | 765 | .{ .@"test", .zi, &.{ .al, .imm8 }, &.{ 0xa8 }, 0, .none }, |
| 761 | .{ .@"test", .zi, .ax, .imm16, .none, .none, &.{ 0xa9 }, 0, .none }, | 766 | .{ .@"test", .zi, &.{ .ax, .imm16 }, &.{ 0xa9 }, 0, .none }, |
| 762 | .{ .@"test", .zi, .eax, .imm32, .none, .none, &.{ 0xa9 }, 0, .none }, | 767 | .{ .@"test", .zi, &.{ .eax, .imm32 }, &.{ 0xa9 }, 0, .none }, |
| 763 | .{ .@"test", .zi, .rax, .imm32s, .none, .none, &.{ 0xa9 }, 0, .long }, | 768 | .{ .@"test", .zi, &.{ .rax, .imm32s }, &.{ 0xa9 }, 0, .long }, |
| 764 | .{ .@"test", .mi, .rm8, .imm8, .none, .none, &.{ 0xf6 }, 0, .none }, | 769 | .{ .@"test", .mi, &.{ .rm8, .imm8 }, &.{ 0xf6 }, 0, .none }, |
| 765 | .{ .@"test", .mi, .rm8, .imm8, .none, .none, &.{ 0xf6 }, 0, .rex }, | 770 | .{ .@"test", .mi, &.{ .rm8, .imm8 }, &.{ 0xf6 }, 0, .rex }, |
| 766 | .{ .@"test", .mi, .rm16, .imm16, .none, .none, &.{ 0xf7 }, 0, .none }, | 771 | .{ .@"test", .mi, &.{ .rm16, .imm16 }, &.{ 0xf7 }, 0, .none }, |
| 767 | .{ .@"test", .mi, .rm32, .imm32, .none, .none, &.{ 0xf7 }, 0, .none }, | 772 | .{ .@"test", .mi, &.{ .rm32, .imm32 }, &.{ 0xf7 }, 0, .none }, |
| 768 | .{ .@"test", .mi, .rm64, .imm32s, .none, .none, &.{ 0xf7 }, 0, .long }, | 773 | .{ .@"test", .mi, &.{ .rm64, .imm32s }, &.{ 0xf7 }, 0, .long }, |
| 769 | .{ .@"test", .mr, .rm8, .r8, .none, .none, &.{ 0x84 }, 0, .none }, | 774 | .{ .@"test", .mr, &.{ .rm8, .r8 }, &.{ 0x84 }, 0, .none }, |
| 770 | .{ .@"test", .mr, .rm8, .r8, .none, .none, &.{ 0x84 }, 0, .rex }, | 775 | .{ .@"test", .mr, &.{ .rm8, .r8 }, &.{ 0x84 }, 0, .rex }, |
| 771 | .{ .@"test", .mr, .rm16, .r16, .none, .none, &.{ 0x85 }, 0, .none }, | 776 | .{ .@"test", .mr, &.{ .rm16, .r16 }, &.{ 0x85 }, 0, .none }, |
| 772 | .{ .@"test", .mr, .rm32, .r32, .none, .none, &.{ 0x85 }, 0, .none }, | 777 | .{ .@"test", .mr, &.{ .rm32, .r32 }, &.{ 0x85 }, 0, .none }, |
| 773 | .{ .@"test", .mr, .rm64, .r64, .none, .none, &.{ 0x85 }, 0, .long }, | 778 | .{ .@"test", .mr, &.{ .rm64, .r64 }, &.{ 0x85 }, 0, .long }, |
| 774 | 779 | ||
| 775 | .{ .tzcnt, .rm, .r16, .rm16, .none, .none, &.{ 0xf3, 0x0f, 0xbc }, 0, .none }, | 780 | .{ .tzcnt, .rm, &.{ .r16, .rm16 }, &.{ 0xf3, 0x0f, 0xbc }, 0, .none }, |
| 776 | .{ .tzcnt, .rm, .r32, .rm32, .none, .none, &.{ 0xf3, 0x0f, 0xbc }, 0, .none }, | 781 | .{ .tzcnt, .rm, &.{ .r32, .rm32 }, &.{ 0xf3, 0x0f, 0xbc }, 0, .none }, |
| 777 | .{ .tzcnt, .rm, .r64, .rm64, .none, .none, &.{ 0xf3, 0x0f, 0xbc }, 0, .long }, | 782 | .{ .tzcnt, .rm, &.{ .r64, .rm64 }, &.{ 0xf3, 0x0f, 0xbc }, 0, .long }, |
| 778 | 783 | ||
| 779 | .{ .ud2, .np, .none, .none, .none, .none, &.{ 0x0f, 0x0b }, 0, .none }, | 784 | .{ .ud2, .np, &.{}, &.{ 0x0f, 0x0b }, 0, .none }, |
| 780 | 785 | ||
| 781 | .{ .xadd, .mr, .rm8, .r8, .none, .none, &.{ 0x0f, 0xc0 }, 0, .none }, | 786 | .{ .xadd, .mr, &.{ .rm8, .r8 }, &.{ 0x0f, 0xc0 }, 0, .none }, |
| 782 | .{ .xadd, .mr, .rm8, .r8, .none, .none, &.{ 0x0f, 0xc0 }, 0, .rex }, | 787 | .{ .xadd, .mr, &.{ .rm8, .r8 }, &.{ 0x0f, 0xc0 }, 0, .rex }, |
| 783 | .{ .xadd, .mr, .rm16, .r16, .none, .none, &.{ 0x0f, 0xc1 }, 0, .none }, | 788 | .{ .xadd, .mr, &.{ .rm16, .r16 }, &.{ 0x0f, 0xc1 }, 0, .none }, |
| 784 | .{ .xadd, .mr, .rm32, .r32, .none, .none, &.{ 0x0f, 0xc1 }, 0, .none }, | 789 | .{ .xadd, .mr, &.{ .rm32, .r32 }, &.{ 0x0f, 0xc1 }, 0, .none }, |
| 785 | .{ .xadd, .mr, .rm64, .r64, .none, .none, &.{ 0x0f, 0xc1 }, 0, .long }, | 790 | .{ .xadd, .mr, &.{ .rm64, .r64 }, &.{ 0x0f, 0xc1 }, 0, .long }, |
| 786 | 791 | ||
| 787 | .{ .xchg, .o, .ax, .r16, .none, .none, &.{ 0x90 }, 0, .none }, | 792 | .{ .xchg, .o, &.{ .ax, .r16 }, &.{ 0x90 }, 0, .none }, |
| 788 | .{ .xchg, .o, .r16, .ax, .none, .none, &.{ 0x90 }, 0, .none }, | 793 | .{ .xchg, .o, &.{ .r16, .ax }, &.{ 0x90 }, 0, .none }, |
| 789 | .{ .xchg, .o, .eax, .r32, .none, .none, &.{ 0x90 }, 0, .none }, | 794 | .{ .xchg, .o, &.{ .eax, .r32 }, &.{ 0x90 }, 0, .none }, |
| 790 | .{ .xchg, .o, .rax, .r64, .none, .none, &.{ 0x90 }, 0, .long }, | 795 | .{ .xchg, .o, &.{ .rax, .r64 }, &.{ 0x90 }, 0, .long }, |
| 791 | .{ .xchg, .o, .r32, .eax, .none, .none, &.{ 0x90 }, 0, .none }, | 796 | .{ .xchg, .o, &.{ .r32, .eax }, &.{ 0x90 }, 0, .none }, |
| 792 | .{ .xchg, .o, .r64, .rax, .none, .none, &.{ 0x90 }, 0, .long }, | 797 | .{ .xchg, .o, &.{ .r64, .rax }, &.{ 0x90 }, 0, .long }, |
| 793 | .{ .xchg, .mr, .rm8, .r8, .none, .none, &.{ 0x86 }, 0, .none }, | 798 | .{ .xchg, .mr, &.{ .rm8, .r8 }, &.{ 0x86 }, 0, .none }, |
| 794 | .{ .xchg, .mr, .rm8, .r8, .none, .none, &.{ 0x86 }, 0, .rex }, | 799 | .{ .xchg, .mr, &.{ .rm8, .r8 }, &.{ 0x86 }, 0, .rex }, |
| 795 | .{ .xchg, .rm, .r8, .rm8, .none, .none, &.{ 0x86 }, 0, .none }, | 800 | .{ .xchg, .rm, &.{ .r8, .rm8 }, &.{ 0x86 }, 0, .none }, |
| 796 | .{ .xchg, .rm, .r8, .rm8, .none, .none, &.{ 0x86 }, 0, .rex }, | 801 | .{ .xchg, .rm, &.{ .r8, .rm8 }, &.{ 0x86 }, 0, .rex }, |
| 797 | .{ .xchg, .mr, .rm16, .r16, .none, .none, &.{ 0x87 }, 0, .none }, | 802 | .{ .xchg, .mr, &.{ .rm16, .r16 }, &.{ 0x87 }, 0, .none }, |
| 798 | .{ .xchg, .rm, .r16, .rm16, .none, .none, &.{ 0x87 }, 0, .none }, | 803 | .{ .xchg, .rm, &.{ .r16, .rm16 }, &.{ 0x87 }, 0, .none }, |
| 799 | .{ .xchg, .mr, .rm32, .r32, .none, .none, &.{ 0x87 }, 0, .none }, | 804 | .{ .xchg, .mr, &.{ .rm32, .r32 }, &.{ 0x87 }, 0, .none }, |
| 800 | .{ .xchg, .mr, .rm64, .r64, .none, .none, &.{ 0x87 }, 0, .long }, | 805 | .{ .xchg, .mr, &.{ .rm64, .r64 }, &.{ 0x87 }, 0, .long }, |
| 801 | .{ .xchg, .rm, .r32, .rm32, .none, .none, &.{ 0x87 }, 0, .none }, | 806 | .{ .xchg, .rm, &.{ .r32, .rm32 }, &.{ 0x87 }, 0, .none }, |
| 802 | .{ .xchg, .rm, .r64, .rm64, .none, .none, &.{ 0x87 }, 0, .long }, | 807 | .{ .xchg, .rm, &.{ .r64, .rm64 }, &.{ 0x87 }, 0, .long }, |
| 803 | 808 | ||
| 804 | .{ .xor, .zi, .al, .imm8, .none, .none, &.{ 0x34 }, 0, .none }, | 809 | .{ .xor, .zi, &.{ .al, .imm8 }, &.{ 0x34 }, 0, .none }, |
| 805 | .{ .xor, .zi, .ax, .imm16, .none, .none, &.{ 0x35 }, 0, .none }, | 810 | .{ .xor, .zi, &.{ .ax, .imm16 }, &.{ 0x35 }, 0, .none }, |
| 806 | .{ .xor, .zi, .eax, .imm32, .none, .none, &.{ 0x35 }, 0, .none }, | 811 | .{ .xor, .zi, &.{ .eax, .imm32 }, &.{ 0x35 }, 0, .none }, |
| 807 | .{ .xor, .zi, .rax, .imm32s, .none, .none, &.{ 0x35 }, 0, .long }, | 812 | .{ .xor, .zi, &.{ .rax, .imm32s }, &.{ 0x35 }, 0, .long }, |
| 808 | .{ .xor, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 6, .none }, | 813 | .{ .xor, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 6, .none }, |
| 809 | .{ .xor, .mi, .rm8, .imm8, .none, .none, &.{ 0x80 }, 6, .rex }, | 814 | .{ .xor, .mi, &.{ .rm8, .imm8 }, &.{ 0x80 }, 6, .rex }, |
| 810 | .{ .xor, .mi, .rm16, .imm16, .none, .none, &.{ 0x81 }, 6, .none }, | 815 | .{ .xor, .mi, &.{ .rm16, .imm16 }, &.{ 0x81 }, 6, .none }, |
| 811 | .{ .xor, .mi, .rm32, .imm32, .none, .none, &.{ 0x81 }, 6, .none }, | 816 | .{ .xor, .mi, &.{ .rm32, .imm32 }, &.{ 0x81 }, 6, .none }, |
| 812 | .{ .xor, .mi, .rm64, .imm32s, .none, .none, &.{ 0x81 }, 6, .long }, | 817 | .{ .xor, .mi, &.{ .rm64, .imm32s }, &.{ 0x81 }, 6, .long }, |
| 813 | .{ .xor, .mi, .rm16, .imm8s, .none, .none, &.{ 0x83 }, 6, .none }, | 818 | .{ .xor, .mi, &.{ .rm16, .imm8s }, &.{ 0x83 }, 6, .none }, |
| 814 | .{ .xor, .mi, .rm32, .imm8s, .none, .none, &.{ 0x83 }, 6, .none }, | 819 | .{ .xor, .mi, &.{ .rm32, .imm8s }, &.{ 0x83 }, 6, .none }, |
| 815 | .{ .xor, .mi, .rm64, .imm8s, .none, .none, &.{ 0x83 }, 6, .long }, | 820 | .{ .xor, .mi, &.{ .rm64, .imm8s }, &.{ 0x83 }, 6, .long }, |
| 816 | .{ .xor, .mr, .rm8, .r8, .none, .none, &.{ 0x30 }, 0, .none }, | 821 | .{ .xor, .mr, &.{ .rm8, .r8 }, &.{ 0x30 }, 0, .none }, |
| 817 | .{ .xor, .mr, .rm8, .r8, .none, .none, &.{ 0x30 }, 0, .rex }, | 822 | .{ .xor, .mr, &.{ .rm8, .r8 }, &.{ 0x30 }, 0, .rex }, |
| 818 | .{ .xor, .mr, .rm16, .r16, .none, .none, &.{ 0x31 }, 0, .none }, | 823 | .{ .xor, .mr, &.{ .rm16, .r16 }, &.{ 0x31 }, 0, .none }, |
| 819 | .{ .xor, .mr, .rm32, .r32, .none, .none, &.{ 0x31 }, 0, .none }, | 824 | .{ .xor, .mr, &.{ .rm32, .r32 }, &.{ 0x31 }, 0, .none }, |
| 820 | .{ .xor, .mr, .rm64, .r64, .none, .none, &.{ 0x31 }, 0, .long }, | 825 | .{ .xor, .mr, &.{ .rm64, .r64 }, &.{ 0x31 }, 0, .long }, |
| 821 | .{ .xor, .rm, .r8, .rm8, .none, .none, &.{ 0x32 }, 0, .none }, | 826 | .{ .xor, .rm, &.{ .r8, .rm8 }, &.{ 0x32 }, 0, .none }, |
| 822 | .{ .xor, .rm, .r8, .rm8, .none, .none, &.{ 0x32 }, 0, .rex }, | 827 | .{ .xor, .rm, &.{ .r8, .rm8 }, &.{ 0x32 }, 0, .rex }, |
| 823 | .{ .xor, .rm, .r16, .rm16, .none, .none, &.{ 0x33 }, 0, .none }, | 828 | .{ .xor, .rm, &.{ .r16, .rm16 }, &.{ 0x33 }, 0, .none }, |
| 824 | .{ .xor, .rm, .r32, .rm32, .none, .none, &.{ 0x33 }, 0, .none }, | 829 | .{ .xor, .rm, &.{ .r32, .rm32 }, &.{ 0x33 }, 0, .none }, |
| 825 | .{ .xor, .rm, .r64, .rm64, .none, .none, &.{ 0x33 }, 0, .long }, | 830 | .{ .xor, .rm, &.{ .r64, .rm64 }, &.{ 0x33 }, 0, .long }, |
| 826 | 831 | ||
| 827 | // SSE | 832 | // SSE |
| 828 | .{ .addss, .rm, .xmm, .xmm_m32, .none, .none, &.{ 0xf3, 0x0f, 0x58 }, 0, .sse }, | 833 | .{ .addss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x58 }, 0, .sse }, |
| 829 | 834 | ||
| 830 | .{ .cmpss, .rmi, .xmm, .xmm_m32, .imm8, .none, &.{ 0xf3, 0x0f, 0xc2 }, 0, .sse }, | 835 | .{ .cmpss, .rmi, &.{ .xmm, .xmm_m32, .imm8 }, &.{ 0xf3, 0x0f, 0xc2 }, 0, .sse }, |
| 831 | 836 | ||
| 832 | .{ .divss, .rm, .xmm, .xmm_m32, .none, .none, &.{ 0xf3, 0x0f, 0x5e }, 0, .sse }, | 837 | .{ .divss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5e }, 0, .sse }, |
| 833 | 838 | ||
| 834 | .{ .maxss, .rm, .xmm, .xmm_m32, .none, .none, &.{ 0xf3, 0x0f, 0x5f }, 0, .sse }, | 839 | .{ .maxss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5f }, 0, .sse }, |
| 835 | 840 | ||
| 836 | .{ .minss, .rm, .xmm, .xmm_m32, .none, .none, &.{ 0xf3, 0x0f, 0x5d }, 0, .sse }, | 841 | .{ .minss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5d }, 0, .sse }, |
| 837 | 842 | ||
| 838 | .{ .movss, .rm, .xmm, .xmm_m32, .none, .none, &.{ 0xf3, 0x0f, 0x10 }, 0, .sse }, | 843 | .{ .movss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x10 }, 0, .sse }, |
| 839 | .{ .movss, .mr, .xmm_m32, .xmm, .none, .none, &.{ 0xf3, 0x0f, 0x11 }, 0, .sse }, | 844 | .{ .movss, .mr, &.{ .xmm_m32, .xmm }, &.{ 0xf3, 0x0f, 0x11 }, 0, .sse }, |
| 840 | 845 | ||
| 841 | .{ .mulss, .rm, .xmm, .xmm_m32, .none, .none, &.{ 0xf3, 0x0f, 0x59 }, 0, .sse }, | 846 | .{ .mulss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x59 }, 0, .sse }, |
| 842 | 847 | ||
| 843 | .{ .subss, .rm, .xmm, .xmm_m32, .none, .none, &.{ 0xf3, 0x0f, 0x5c }, 0, .sse }, | 848 | .{ .subss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0xf3, 0x0f, 0x5c }, 0, .sse }, |
| 844 | 849 | ||
| 845 | .{ .ucomiss, .rm, .xmm, .xmm_m32, .none, .none, &.{ 0x0f, 0x2e }, 0, .sse }, | 850 | .{ .ucomiss, .rm, &.{ .xmm, .xmm_m32 }, &.{ 0x0f, 0x2e }, 0, .sse }, |
| 846 | 851 | ||
| 847 | // SSE2 | 852 | // SSE2 |
| 848 | .{ .addsd, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0xf2, 0x0f, 0x58 }, 0, .sse2 }, | 853 | .{ .addsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x58 }, 0, .sse2 }, |
| 849 | 854 | ||
| 850 | .{ .cmpsd, .rmi, .xmm, .xmm_m64, .imm8, .none, &.{ 0xf2, 0x0f, 0xc2 }, 0, .sse2 }, | 855 | .{ .cmpsd, .rmi, &.{ .xmm, .xmm_m64, .imm8 }, &.{ 0xf2, 0x0f, 0xc2 }, 0, .sse2 }, |
| 851 | 856 | ||
| 852 | .{ .divsd, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0xf2, 0x0f, 0x5e }, 0, .sse2 }, | 857 | .{ .divsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5e }, 0, .sse2 }, |
| 853 | 858 | ||
| 854 | .{ .maxsd, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0xf2, 0x0f, 0x5f }, 0, .sse2 }, | 859 | .{ .maxsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5f }, 0, .sse2 }, |
| 855 | 860 | ||
| 856 | .{ .minsd, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0xf2, 0x0f, 0x5d }, 0, .sse2 }, | 861 | .{ .minsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5d }, 0, .sse2 }, |
| 857 | 862 | ||
| 858 | .{ .movq, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0xf3, 0x0f, 0x7e }, 0, .sse2 }, | 863 | .{ .movq, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf3, 0x0f, 0x7e }, 0, .sse2 }, |
| 859 | .{ .movq, .mr, .xmm_m64, .xmm, .none, .none, &.{ 0x66, 0x0f, 0xd6 }, 0, .sse2 }, | 864 | .{ .movq, .mr, &.{ .xmm_m64, .xmm }, &.{ 0x66, 0x0f, 0xd6 }, 0, .sse2 }, |
| 860 | 865 | ||
| 861 | .{ .mulsd, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0xf2, 0x0f, 0x59 }, 0, .sse2 }, | 866 | .{ .mulsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x59 }, 0, .sse2 }, |
| 862 | 867 | ||
| 863 | .{ .subsd, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0xf2, 0x0f, 0x5c }, 0, .sse2 }, | 868 | .{ .subsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x5c }, 0, .sse2 }, |
| 864 | 869 | ||
| 865 | .{ .movsd, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0xf2, 0x0f, 0x10 }, 0, .sse2 }, | 870 | .{ .movsd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0xf2, 0x0f, 0x10 }, 0, .sse2 }, |
| 866 | .{ .movsd, .mr, .xmm_m64, .xmm, .none, .none, &.{ 0xf2, 0x0f, 0x11 }, 0, .sse2 }, | 871 | .{ .movsd, .mr, &.{ .xmm_m64, .xmm }, &.{ 0xf2, 0x0f, 0x11 }, 0, .sse2 }, |
| 867 | 872 | ||
| 868 | .{ .ucomisd, .rm, .xmm, .xmm_m64, .none, .none, &.{ 0x66, 0x0f, 0x2e }, 0, .sse2 }, | 873 | .{ .ucomisd, .rm, &.{ .xmm, .xmm_m64 }, &.{ 0x66, 0x0f, 0x2e }, 0, .sse2 }, |
| 869 | 874 | ||
| 870 | // SSE4.1 | 875 | // SSE4.1 |
| 871 | .{ .roundss, .rmi, .xmm, .xmm_m32, .imm8, .none, &.{ 0x66, 0x0f, 0x3a, 0x0a }, 0, .sse4_1 }, | 876 | .{ .roundss, .rmi, &.{ .xmm, .xmm_m32, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0a }, 0, .sse4_1 }, |
| 872 | .{ .roundsd, .rmi, .xmm, .xmm_m64, .imm8, .none, &.{ 0x66, 0x0f, 0x3a, 0x0b }, 0, .sse4_1 }, | 877 | .{ .roundsd, .rmi, &.{ .xmm, .xmm_m64, .imm8 }, &.{ 0x66, 0x0f, 0x3a, 0x0b }, 0, .sse4_1 }, |
| 873 | }; | 878 | }; |
| 874 | // zig fmt: on | 879 | // zig fmt: on |