podman
1// Copyright 2014 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Table-driven decoding of x86 instructions.
6
7package x86asm8
9import (10"encoding/binary"11"errors"12"fmt"13"runtime"14)
15
16// Set trace to true to cause the decoder to print the PC sequence
17// of the executed instruction codes. This is typically only useful
18// when you are running a test of a single input case.
19const trace = false20
21// A decodeOp is a single instruction in the decoder bytecode program.
22//
23// The decodeOps correspond to consuming and conditionally branching
24// on input bytes, consuming additional fields, and then interpreting
25// consumed data as instruction arguments. The names of the xRead and xArg
26// operations are taken from the Intel manual conventions, for example
27// Volume 2, Section 3.1.1, page 487 of
28// http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-manual-325462.pdf
29//
30// The actual decoding program is generated by ../x86map.
31//
32// TODO(rsc): We may be able to merge various of the memory operands
33// since we don't care about, say, the distinction between m80dec and m80bcd.
34// Similarly, mm and mm1 have identical meaning, as do xmm and xmm1.
35
36type decodeOp uint1637
38const (39xFail decodeOp = iota // invalid instruction (return)40xMatch // completed match41xJump // jump to pc42
43xCondByte // switch on instruction byte value44xCondSlashR // read and switch on instruction /r value45xCondPrefix // switch on presence of instruction prefix46xCondIs64 // switch on 64-bit processor mode47xCondDataSize // switch on operand size48xCondAddrSize // switch on address size49xCondIsMem // switch on memory vs register argument50
51xSetOp // set instruction opcode52
53xReadSlashR // read /r54xReadIb // read ib55xReadIw // read iw56xReadId // read id57xReadIo // read io58xReadCb // read cb59xReadCw // read cw60xReadCd // read cd61xReadCp // read cp62xReadCm // read cm63
64xArg1 // arg 165xArg3 // arg 366xArgAL // arg AL67xArgAX // arg AX68xArgCL // arg CL69xArgCR0dashCR7 // arg CR0-CR770xArgCS // arg CS71xArgDR0dashDR7 // arg DR0-DR772xArgDS // arg DS73xArgDX // arg DX74xArgEAX // arg EAX75xArgEDX // arg EDX76xArgES // arg ES77xArgFS // arg FS78xArgGS // arg GS79xArgImm16 // arg imm1680xArgImm32 // arg imm3281xArgImm64 // arg imm6482xArgImm8 // arg imm883xArgImm8u // arg imm8 but record as unsigned84xArgImm16u // arg imm8 but record as unsigned85xArgM // arg m86xArgM128 // arg m12887xArgM256 // arg m25688xArgM1428byte // arg m14/28byte89xArgM16 // arg m1690xArgM16and16 // arg m16&1691xArgM16and32 // arg m16&3292xArgM16and64 // arg m16&6493xArgM16colon16 // arg m16:1694xArgM16colon32 // arg m16:3295xArgM16colon64 // arg m16:6496xArgM16int // arg m16int97xArgM2byte // arg m2byte98xArgM32 // arg m3299xArgM32and32 // arg m32&32100xArgM32fp // arg m32fp101xArgM32int // arg m32int102xArgM512byte // arg m512byte103xArgM64 // arg m64104xArgM64fp // arg m64fp105xArgM64int // arg m64int106xArgM8 // arg m8107xArgM80bcd // arg m80bcd108xArgM80dec // arg m80dec109xArgM80fp // arg m80fp110xArgM94108byte // arg m94/108byte111xArgMm // arg mm112xArgMm1 // arg mm1113xArgMm2 // arg mm2114xArgMm2M64 // arg mm2/m64115xArgMmM32 // arg mm/m32116xArgMmM64 // arg mm/m64117xArgMem // arg mem118xArgMoffs16 // arg moffs16119xArgMoffs32 // arg moffs32120xArgMoffs64 // arg moffs64121xArgMoffs8 // arg moffs8122xArgPtr16colon16 // arg ptr16:16123xArgPtr16colon32 // arg ptr16:32124xArgR16 // arg r16125xArgR16op // arg r16 with +rw in opcode126xArgR32 // arg r32127xArgR32M16 // arg r32/m16128xArgR32M8 // arg r32/m8129xArgR32op // arg r32 with +rd in opcode130xArgR64 // arg r64131xArgR64M16 // arg r64/m16132xArgR64op // arg r64 with +rd in opcode133xArgR8 // arg r8134xArgR8op // arg r8 with +rb in opcode135xArgRAX // arg RAX136xArgRDX // arg RDX137xArgRM // arg r/m138xArgRM16 // arg r/m16139xArgRM32 // arg r/m32140xArgRM64 // arg r/m64141xArgRM8 // arg r/m8142xArgReg // arg reg143xArgRegM16 // arg reg/m16144xArgRegM32 // arg reg/m32145xArgRegM8 // arg reg/m8146xArgRel16 // arg rel16147xArgRel32 // arg rel32148xArgRel8 // arg rel8149xArgSS // arg SS150xArgST // arg ST, aka ST(0)151xArgSTi // arg ST(i) with +i in opcode152xArgSreg // arg Sreg153xArgTR0dashTR7 // arg TR0-TR7154xArgXmm // arg xmm155xArgXMM0 // arg <XMM0>156xArgXmm1 // arg xmm1157xArgXmm2 // arg xmm2158xArgXmm2M128 // arg xmm2/m128159xArgYmm2M256 // arg ymm2/m256160xArgXmm2M16 // arg xmm2/m16161xArgXmm2M32 // arg xmm2/m32162xArgXmm2M64 // arg xmm2/m64163xArgXmmM128 // arg xmm/m128164xArgXmmM32 // arg xmm/m32165xArgXmmM64 // arg xmm/m64166xArgYmm1 // arg ymm1167xArgRmf16 // arg r/m16 but force mod=3168xArgRmf32 // arg r/m32 but force mod=3169xArgRmf64 // arg r/m64 but force mod=3170)
171
172// instPrefix returns an Inst describing just one prefix byte.
173// It is only used if there is a prefix followed by an unintelligible
174// or invalid instruction byte sequence.
175func instPrefix(b byte, mode int) (Inst, error) {176// When tracing it is useful to see what called instPrefix to report an error.177if trace {178_, file, line, _ := runtime.Caller(1)179fmt.Printf("%s:%d\n", file, line)180}181p := Prefix(b)182switch p {183case PrefixDataSize:184if mode == 16 {185p = PrefixData32186} else {187p = PrefixData16188}189case PrefixAddrSize:190if mode == 32 {191p = PrefixAddr16192} else {193p = PrefixAddr32194}195}196// Note: using composite literal with Prefix key confuses 'bundle' tool.197inst := Inst{Len: 1}198inst.Prefix = Prefixes{p}199return inst, nil200}
201
202// truncated reports a truncated instruction.
203// For now we use instPrefix but perhaps later we will return
204// a specific error here.
205func truncated(src []byte, mode int) (Inst, error) {206if len(src) == 0 {207return Inst{}, ErrTruncated208}209return instPrefix(src[0], mode) // too long210}
211
212// These are the errors returned by Decode.
213var (214ErrInvalidMode = errors.New("invalid x86 mode in Decode")215ErrTruncated = errors.New("truncated instruction")216ErrUnrecognized = errors.New("unrecognized instruction")217)
218
219// decoderCover records coverage information for which parts
220// of the byte code have been executed.
221var decoderCover []bool222
223// Decode decodes the leading bytes in src as a single instruction.
224// The mode arguments specifies the assumed processor mode:
225// 16, 32, or 64 for 16-, 32-, and 64-bit execution modes.
226func Decode(src []byte, mode int) (inst Inst, err error) {227return decode1(src, mode, false)228}
229
230// decode1 is the implementation of Decode but takes an extra
231// gnuCompat flag to cause it to change its behavior to mimic
232// bugs (or at least unique features) of GNU libopcodes as used
233// by objdump. We don't believe that logic is the right thing to do
234// in general, but when testing against libopcodes it simplifies the
235// comparison if we adjust a few small pieces of logic.
236// The affected logic is in the conditional branch for "mandatory" prefixes,
237// case xCondPrefix.
238func decode1(src []byte, mode int, gnuCompat bool) (Inst, error) {239switch mode {240case 16, 32, 64:241// ok242// TODO(rsc): 64-bit mode not tested, probably not working.243default:244return Inst{}, ErrInvalidMode245}246
247// Maximum instruction size is 15 bytes.248// If we need to read more, return 'truncated instruction.249if len(src) > 15 {250src = src[:15]251}252
253var (254// prefix decoding information255pos = 0 // position reading src256nprefix = 0 // number of prefixes257lockIndex = -1 // index of LOCK prefix in src and inst.Prefix258repIndex = -1 // index of REP/REPN prefix in src and inst.Prefix259segIndex = -1 // index of Group 2 prefix in src and inst.Prefix260dataSizeIndex = -1 // index of Group 3 prefix in src and inst.Prefix261addrSizeIndex = -1 // index of Group 4 prefix in src and inst.Prefix262rex Prefix // rex byte if present (or 0)263rexUsed Prefix // bits used in rex byte264rexIndex = -1 // index of rex byte265vex Prefix // use vex encoding266vexIndex = -1 // index of vex prefix267
268addrMode = mode // address mode (width in bits)269dataMode = mode // operand mode (width in bits)270
271// decoded ModR/M fields272haveModrm bool273modrm int274mod int275regop int276rm int277
278// if ModR/M is memory reference, Mem form279mem Mem
280haveMem bool281
282// decoded SIB fields283haveSIB bool284sib int285scale int286index int287base int288displen int289dispoff int290
291// decoded immediate values292imm int64293imm8 int8294immc int64295immcpos int296
297// output298opshift int299inst Inst
300narg int // number of arguments written to inst301)302
303if mode == 64 {304dataMode = 32305}306
307// Prefixes are certainly the most complex and underspecified part of308// decoding x86 instructions. Although the manuals say things like309// up to four prefixes, one from each group, nearly everyone seems to310// agree that in practice as many prefixes as possible, including multiple311// from a particular group or repetitions of a given prefix, can be used on312// an instruction, provided the total instruction length including prefixes313// does not exceed the agreed-upon maximum of 15 bytes.314// Everyone also agrees that if one of these prefixes is the LOCK prefix315// and the instruction is not one of the instructions that can be used with316// the LOCK prefix or if the destination is not a memory operand,317// then the instruction is invalid and produces the #UD exception.318// However, that is the end of any semblance of agreement.319//320// What happens if prefixes are given that conflict with other prefixes?321// For example, the memory segment overrides CS, DS, ES, FS, GS, SS322// conflict with each other: only one segment can be in effect.323// Disassemblers seem to agree that later prefixes take priority over324// earlier ones. I have not taken the time to write assembly programs325// to check to see if the hardware agrees.326//327// What happens if prefixes are given that have no meaning for the328// specific instruction to which they are attached? It depends.329// If they really have no meaning, they are ignored. However, a future330// processor may assign a different meaning. As a disassembler, we331// don't really know whether we're seeing a meaningless prefix or one332// whose meaning we simply haven't been told yet.333//334// Combining the two questions, what happens when conflicting335// extension prefixes are given? No one seems to know for sure.336// For example, MOVQ is 66 0F D6 /r, MOVDQ2Q is F2 0F D6 /r,337// and MOVQ2DQ is F3 0F D6 /r. What is '66 F2 F3 0F D6 /r'?338// Which prefix wins? See the xCondPrefix prefix for more.339//340// Writing assembly test cases to divine which interpretation the341// CPU uses might clarify the situation, but more likely it would342// make the situation even less clear.343
344// Read non-REX prefixes.345ReadPrefixes:346for ; pos < len(src); pos++ {347p := Prefix(src[pos])348switch p {349default:350nprefix = pos351break ReadPrefixes352
353// Group 1 - lock and repeat prefixes354// According to Intel, there should only be one from this set,355// but according to AMD both can be present.356case 0xF0:357if lockIndex >= 0 {358inst.Prefix[lockIndex] |= PrefixIgnored359}360lockIndex = pos361case 0xF2, 0xF3:362if repIndex >= 0 {363inst.Prefix[repIndex] |= PrefixIgnored364}365repIndex = pos366
367// Group 2 - segment override / branch hints368case 0x26, 0x2E, 0x36, 0x3E:369if mode == 64 {370p |= PrefixIgnored371break372}373fallthrough374case 0x64, 0x65:375if segIndex >= 0 {376inst.Prefix[segIndex] |= PrefixIgnored377}378segIndex = pos379
380// Group 3 - operand size override381case 0x66:382if mode == 16 {383dataMode = 32384p = PrefixData32385} else {386dataMode = 16387p = PrefixData16388}389if dataSizeIndex >= 0 {390inst.Prefix[dataSizeIndex] |= PrefixIgnored391}392dataSizeIndex = pos393
394// Group 4 - address size override395case 0x67:396if mode == 32 {397addrMode = 16398p = PrefixAddr16399} else {400addrMode = 32401p = PrefixAddr32402}403if addrSizeIndex >= 0 {404inst.Prefix[addrSizeIndex] |= PrefixIgnored405}406addrSizeIndex = pos407
408//Group 5 - Vex encoding409case 0xC5:410if pos == 0 && pos+1 < len(src) && (mode == 64 || (mode == 32 && src[pos+1]&0xc0 == 0xc0)) {411vex = p412vexIndex = pos413inst.Prefix[pos] = p414inst.Prefix[pos+1] = Prefix(src[pos+1])415pos += 1416continue417} else {418nprefix = pos419break ReadPrefixes420}421case 0xC4:422if pos == 0 && pos+2 < len(src) && (mode == 64 || (mode == 32 && src[pos+1]&0xc0 == 0xc0)) {423vex = p424vexIndex = pos425inst.Prefix[pos] = p426inst.Prefix[pos+1] = Prefix(src[pos+1])427inst.Prefix[pos+2] = Prefix(src[pos+2])428pos += 2429continue430} else {431nprefix = pos432break ReadPrefixes433}434}435
436if pos >= len(inst.Prefix) {437return instPrefix(src[0], mode) // too long438}439
440inst.Prefix[pos] = p441}442
443// Read REX prefix.444if pos < len(src) && mode == 64 && Prefix(src[pos]).IsREX() && vex == 0 {445rex = Prefix(src[pos])446rexIndex = pos447if pos >= len(inst.Prefix) {448return instPrefix(src[0], mode) // too long449}450inst.Prefix[pos] = rex451pos++452if rex&PrefixREXW != 0 {453dataMode = 64454if dataSizeIndex >= 0 {455inst.Prefix[dataSizeIndex] |= PrefixIgnored456}457}458}459
460// Decode instruction stream, interpreting decoding instructions.461// opshift gives the shift to use when saving the next462// opcode byte into inst.Opcode.463opshift = 24464
465// Decode loop, executing decoder program.466var oldPC, prevPC int467Decode:468for pc := 1; ; { // TODO uint469oldPC = prevPC470prevPC = pc471if trace {472println("run", pc)473}474x := decoder[pc]475if decoderCover != nil {476decoderCover[pc] = true477}478pc++479
480// Read and decode ModR/M if needed by opcode.481switch decodeOp(x) {482case xCondSlashR, xReadSlashR:483if haveModrm {484return Inst{Len: pos}, errInternal485}486haveModrm = true487if pos >= len(src) {488return truncated(src, mode)489}490modrm = int(src[pos])491pos++492if opshift >= 0 {493inst.Opcode |= uint32(modrm) << uint(opshift)494opshift -= 8495}496mod = modrm >> 6497regop = (modrm >> 3) & 07498rm = modrm & 07499if rex&PrefixREXR != 0 {500rexUsed |= PrefixREXR501regop |= 8502}503if addrMode == 16 {504// 16-bit modrm form505if mod != 3 {506haveMem = true507mem = addr16[rm]508if rm == 6 && mod == 0 {509mem.Base = 0510}511
512// Consume disp16 if present.513if mod == 0 && rm == 6 || mod == 2 {514if pos+2 > len(src) {515return truncated(src, mode)516}517mem.Disp = int64(binary.LittleEndian.Uint16(src[pos:]))518pos += 2519}520
521// Consume disp8 if present.522if mod == 1 {523if pos >= len(src) {524return truncated(src, mode)525}526mem.Disp = int64(int8(src[pos]))527pos++528}529}530} else {531haveMem = mod != 3532
533// 32-bit or 64-bit form534// Consume SIB encoding if present.535if rm == 4 && mod != 3 {536haveSIB = true537if pos >= len(src) {538return truncated(src, mode)539}540sib = int(src[pos])541pos++542if opshift >= 0 {543inst.Opcode |= uint32(sib) << uint(opshift)544opshift -= 8545}546scale = sib >> 6547index = (sib >> 3) & 07548base = sib & 07549if rex&PrefixREXB != 0 || vex == 0xC4 && inst.Prefix[vexIndex+1]&0x20 == 0 {550rexUsed |= PrefixREXB551base |= 8552}553if rex&PrefixREXX != 0 || vex == 0xC4 && inst.Prefix[vexIndex+1]&0x40 == 0 {554rexUsed |= PrefixREXX555index |= 8556}557
558mem.Scale = 1 << uint(scale)559if index == 4 {560// no mem.Index561} else {562mem.Index = baseRegForBits(addrMode) + Reg(index)563}564if base&7 == 5 && mod == 0 {565// no mem.Base566} else {567mem.Base = baseRegForBits(addrMode) + Reg(base)568}569} else {570if rex&PrefixREXB != 0 {571rexUsed |= PrefixREXB572rm |= 8573}574if mod == 0 && rm&7 == 5 || rm&7 == 4 {575// base omitted576} else if mod != 3 {577mem.Base = baseRegForBits(addrMode) + Reg(rm)578}579}580
581// Consume disp32 if present.582if mod == 0 && (rm&7 == 5 || haveSIB && base&7 == 5) || mod == 2 {583if pos+4 > len(src) {584return truncated(src, mode)585}586dispoff = pos587displen = 4588mem.Disp = int64(binary.LittleEndian.Uint32(src[pos:]))589pos += 4590}591
592// Consume disp8 if present.593if mod == 1 {594if pos >= len(src) {595return truncated(src, mode)596}597dispoff = pos598displen = 1599mem.Disp = int64(int8(src[pos]))600pos++601}602
603// In 64-bit, mod=0 rm=5 is PC-relative instead of just disp.604// See Vol 2A. Table 2-7.605if mode == 64 && mod == 0 && rm&7 == 5 {606if addrMode == 32 {607mem.Base = EIP608} else {609mem.Base = RIP610}611}612}613
614if segIndex >= 0 {615mem.Segment = prefixToSegment(inst.Prefix[segIndex])616}617}618
619// Execute single opcode.620switch decodeOp(x) {621default:622println("bad op", x, "at", pc-1, "from", oldPC)623return Inst{Len: pos}, errInternal624
625case xFail:626inst.Op = 0627break Decode628
629case xMatch:630break Decode631
632case xJump:633pc = int(decoder[pc])634
635// Conditional branches.636
637case xCondByte:638if pos >= len(src) {639return truncated(src, mode)640}641b := src[pos]642n := int(decoder[pc])643pc++644for i := 0; i < n; i++ {645xb, xpc := decoder[pc], int(decoder[pc+1])646pc += 2647if b == byte(xb) {648pc = xpc649pos++650if opshift >= 0 {651inst.Opcode |= uint32(b) << uint(opshift)652opshift -= 8653}654continue Decode655}656}657// xCondByte is the only conditional with a fall through,658// so that it can be used to pick off special cases before659// an xCondSlash. If the fallthrough instruction is xFail,660// advance the position so that the decoded instruction661// size includes the byte we just compared against.662if decodeOp(decoder[pc]) == xJump {663pc = int(decoder[pc+1])664}665if decodeOp(decoder[pc]) == xFail {666pos++667}668
669case xCondIs64:670if mode == 64 {671pc = int(decoder[pc+1])672} else {673pc = int(decoder[pc])674}675
676case xCondIsMem:677mem := haveMem678if !haveModrm {679if pos >= len(src) {680return instPrefix(src[0], mode) // too long681}682mem = src[pos]>>6 != 3683}684if mem {685pc = int(decoder[pc+1])686} else {687pc = int(decoder[pc])688}689
690case xCondDataSize:691switch dataMode {692case 16:693if dataSizeIndex >= 0 {694inst.Prefix[dataSizeIndex] |= PrefixImplicit695}696pc = int(decoder[pc])697case 32:698if dataSizeIndex >= 0 {699inst.Prefix[dataSizeIndex] |= PrefixImplicit700}701pc = int(decoder[pc+1])702case 64:703rexUsed |= PrefixREXW704pc = int(decoder[pc+2])705}706
707case xCondAddrSize:708switch addrMode {709case 16:710if addrSizeIndex >= 0 {711inst.Prefix[addrSizeIndex] |= PrefixImplicit712}713pc = int(decoder[pc])714case 32:715if addrSizeIndex >= 0 {716inst.Prefix[addrSizeIndex] |= PrefixImplicit717}718pc = int(decoder[pc+1])719case 64:720pc = int(decoder[pc+2])721}722
723case xCondPrefix:724// Conditional branch based on presence or absence of prefixes.725// The conflict cases here are completely undocumented and726// differ significantly between GNU libopcodes and Intel xed.727// I have not written assembly code to divine what various CPUs728// do, but it wouldn't surprise me if they are not consistent either.729//730// The basic idea is to switch on the presence of a prefix, so that731// for example:732//733// xCondPrefix, 4734// 0xF3, 123,735// 0xF2, 234,736// 0x66, 345,737// 0, 456738//739// branch to 123 if the F3 prefix is present, 234 if the F2 prefix740// is present, 66 if the 345 prefix is present, and 456 otherwise.741// The prefixes are given in descending order so that the 0 will be last.742//743// It is unclear what should happen if multiple conditions are744// satisfied: what if F2 and F3 are both present, or if 66 and F2745// are present, or if all three are present? The one chosen becomes746// part of the opcode and the others do not. Perhaps the answer747// depends on the specific opcodes in question.748//749// The only clear example is that CRC32 is F2 0F 38 F1 /r, and750// it comes in 16-bit and 32-bit forms based on the 66 prefix,751// so 66 F2 0F 38 F1 /r should be treated as F2 taking priority,752// with the 66 being only an operand size override, and probably753// F2 66 0F 38 F1 /r should be treated the same.754// Perhaps that rule is specific to the case of CRC32, since no755// 66 0F 38 F1 instruction is defined (today) (that we know of).756// However, both libopcodes and xed seem to generalize this757// example and choose F2/F3 in preference to 66, and we758// do the same.759//760// Next, what if both F2 and F3 are present? Which wins?761// The Intel xed rule, and ours, is that the one that occurs last wins.762// The GNU libopcodes rule, which we implement only in gnuCompat mode,763// is that F3 beats F2 unless F3 has no special meaning, in which764// case F3 can be a modified on an F2 special meaning.765//766// Concretely,767// 66 0F D6 /r is MOVQ768// F2 0F D6 /r is MOVDQ2Q769// F3 0F D6 /r is MOVQ2DQ.770//771// F2 66 0F D6 /r is 66 + MOVDQ2Q always.772// 66 F2 0F D6 /r is 66 + MOVDQ2Q always.773// F3 66 0F D6 /r is 66 + MOVQ2DQ always.774// 66 F3 0F D6 /r is 66 + MOVQ2DQ always.775// F2 F3 0F D6 /r is F2 + MOVQ2DQ always.776// F3 F2 0F D6 /r is F3 + MOVQ2DQ in Intel xed, but F2 + MOVQ2DQ in GNU libopcodes.777// Adding 66 anywhere in the prefix section of the778// last two cases does not change the outcome.779//780// Finally, what if there is a variant in which 66 is a mandatory781// prefix rather than an operand size override, but we know of782// no corresponding F2/F3 form, and we see both F2/F3 and 66.783// Does F2/F3 still take priority, so that the result is an unknown784// instruction, or does the 66 take priority, so that the extended785// 66 instruction should be interpreted as having a REP/REPN prefix?786// Intel xed does the former and GNU libopcodes does the latter.787// We side with Intel xed, unless we are trying to match libopcodes788// more closely during the comparison-based test suite.789//790// In 64-bit mode REX.W is another valid prefix to test for, but791// there is less ambiguity about that. When present, REX.W is792// always the first entry in the table.793n := int(decoder[pc])794pc++795sawF3 := false796for j := 0; j < n; j++ {797prefix := Prefix(decoder[pc+2*j])798if prefix.IsREX() {799rexUsed |= prefix800if rex&prefix == prefix {801pc = int(decoder[pc+2*j+1])802continue Decode803}804continue805}806ok := false807if prefix == 0 {808ok = true809} else if prefix.IsREX() {810rexUsed |= prefix811if rex&prefix == prefix {812ok = true813}814} else if prefix == 0xC5 || prefix == 0xC4 {815if vex == prefix {816ok = true817}818} else if vex != 0 && (prefix == 0x0F || prefix == 0x0F38 || prefix == 0x0F3A ||819prefix == 0x66 || prefix == 0xF2 || prefix == 0xF3) {820var vexM, vexP Prefix821if vex == 0xC5 {822vexM = 1 // 2 byte vex always implies 0F823vexP = inst.Prefix[vexIndex+1]824} else {825vexM = inst.Prefix[vexIndex+1]826vexP = inst.Prefix[vexIndex+2]827}828switch prefix {829case 0x66:830ok = vexP&3 == 1831case 0xF3:832ok = vexP&3 == 2833case 0xF2:834ok = vexP&3 == 3835case 0x0F:836ok = vexM&3 == 1837case 0x0F38:838ok = vexM&3 == 2839case 0x0F3A:840ok = vexM&3 == 3841}842} else {843if prefix == 0xF3 {844sawF3 = true845}846switch prefix {847case PrefixLOCK:848if lockIndex >= 0 {849inst.Prefix[lockIndex] |= PrefixImplicit850ok = true851}852case PrefixREP, PrefixREPN:853if repIndex >= 0 && inst.Prefix[repIndex]&0xFF == prefix {854inst.Prefix[repIndex] |= PrefixImplicit855ok = true856}857if gnuCompat && !ok && prefix == 0xF3 && repIndex >= 0 && (j+1 >= n || decoder[pc+2*(j+1)] != 0xF2) {858// Check to see if earlier prefix F3 is present.859for i := repIndex - 1; i >= 0; i-- {860if inst.Prefix[i]&0xFF == prefix {861inst.Prefix[i] |= PrefixImplicit862ok = true863}864}865}866if gnuCompat && !ok && prefix == 0xF2 && repIndex >= 0 && !sawF3 && inst.Prefix[repIndex]&0xFF == 0xF3 {867// Check to see if earlier prefix F2 is present.868for i := repIndex - 1; i >= 0; i-- {869if inst.Prefix[i]&0xFF == prefix {870inst.Prefix[i] |= PrefixImplicit871ok = true872}873}874}875case PrefixCS, PrefixDS, PrefixES, PrefixFS, PrefixGS, PrefixSS:876if segIndex >= 0 && inst.Prefix[segIndex]&0xFF == prefix {877inst.Prefix[segIndex] |= PrefixImplicit878ok = true879}880case PrefixDataSize:881// Looking for 66 mandatory prefix.882// The F2/F3 mandatory prefixes take priority when both are present.883// If we got this far in the xCondPrefix table and an F2/F3 is present,884// it means the table didn't have any entry for that prefix. But if 66 has885// special meaning, perhaps F2/F3 have special meaning that we don't know.886// Intel xed works this way, treating the F2/F3 as inhibiting the 66.887// GNU libopcodes allows the 66 to match. We do what Intel xed does888// except in gnuCompat mode.889if repIndex >= 0 && !gnuCompat {890inst.Op = 0891break Decode892}893if dataSizeIndex >= 0 {894inst.Prefix[dataSizeIndex] |= PrefixImplicit895ok = true896}897case PrefixAddrSize:898if addrSizeIndex >= 0 {899inst.Prefix[addrSizeIndex] |= PrefixImplicit900ok = true901}902}903}904if ok {905pc = int(decoder[pc+2*j+1])906continue Decode907}908}909inst.Op = 0910break Decode911
912case xCondSlashR:913pc = int(decoder[pc+regop&7])914
915// Input.916
917case xReadSlashR:918// done above919
920case xReadIb:921if pos >= len(src) {922return truncated(src, mode)923}924imm8 = int8(src[pos])925pos++926
927case xReadIw:928if pos+2 > len(src) {929return truncated(src, mode)930}931imm = int64(binary.LittleEndian.Uint16(src[pos:]))932pos += 2933
934case xReadId:935if pos+4 > len(src) {936return truncated(src, mode)937}938imm = int64(binary.LittleEndian.Uint32(src[pos:]))939pos += 4940
941case xReadIo:942if pos+8 > len(src) {943return truncated(src, mode)944}945imm = int64(binary.LittleEndian.Uint64(src[pos:]))946pos += 8947
948case xReadCb:949if pos >= len(src) {950return truncated(src, mode)951}952immcpos = pos953immc = int64(src[pos])954pos++955
956case xReadCw:957if pos+2 > len(src) {958return truncated(src, mode)959}960immcpos = pos961immc = int64(binary.LittleEndian.Uint16(src[pos:]))962pos += 2963
964case xReadCm:965immcpos = pos966if addrMode == 16 {967if pos+2 > len(src) {968return truncated(src, mode)969}970immc = int64(binary.LittleEndian.Uint16(src[pos:]))971pos += 2972} else if addrMode == 32 {973if pos+4 > len(src) {974return truncated(src, mode)975}976immc = int64(binary.LittleEndian.Uint32(src[pos:]))977pos += 4978} else {979if pos+8 > len(src) {980return truncated(src, mode)981}982immc = int64(binary.LittleEndian.Uint64(src[pos:]))983pos += 8984}985case xReadCd:986immcpos = pos987if pos+4 > len(src) {988return truncated(src, mode)989}990immc = int64(binary.LittleEndian.Uint32(src[pos:]))991pos += 4992
993case xReadCp:994immcpos = pos995if pos+6 > len(src) {996return truncated(src, mode)997}998w := binary.LittleEndian.Uint32(src[pos:])999w2 := binary.LittleEndian.Uint16(src[pos+4:])1000immc = int64(w2)<<32 | int64(w)1001pos += 61002
1003// Output.1004
1005case xSetOp:1006inst.Op = Op(decoder[pc])1007pc++1008
1009case xArg1,1010xArg3,1011xArgAL,1012xArgAX,1013xArgCL,1014xArgCS,1015xArgDS,1016xArgDX,1017xArgEAX,1018xArgEDX,1019xArgES,1020xArgFS,1021xArgGS,1022xArgRAX,1023xArgRDX,1024xArgSS,1025xArgST,1026xArgXMM0:1027inst.Args[narg] = fixedArg[x]1028narg++1029
1030case xArgImm8:1031inst.Args[narg] = Imm(imm8)1032narg++1033
1034case xArgImm8u:1035inst.Args[narg] = Imm(uint8(imm8))1036narg++1037
1038case xArgImm16:1039inst.Args[narg] = Imm(int16(imm))1040narg++1041
1042case xArgImm16u:1043inst.Args[narg] = Imm(uint16(imm))1044narg++1045
1046case xArgImm32:1047inst.Args[narg] = Imm(int32(imm))1048narg++1049
1050case xArgImm64:1051inst.Args[narg] = Imm(imm)1052narg++1053
1054case xArgM,1055xArgM128,1056xArgM256,1057xArgM1428byte,1058xArgM16,1059xArgM16and16,1060xArgM16and32,1061xArgM16and64,1062xArgM16colon16,1063xArgM16colon32,1064xArgM16colon64,1065xArgM16int,1066xArgM2byte,1067xArgM32,1068xArgM32and32,1069xArgM32fp,1070xArgM32int,1071xArgM512byte,1072xArgM64,1073xArgM64fp,1074xArgM64int,1075xArgM8,1076xArgM80bcd,1077xArgM80dec,1078xArgM80fp,1079xArgM94108byte,1080xArgMem:1081if !haveMem {1082inst.Op = 01083break Decode1084}1085inst.Args[narg] = mem1086inst.MemBytes = int(memBytes[decodeOp(x)])1087if mem.Base == RIP {1088inst.PCRel = displen1089inst.PCRelOff = dispoff1090}1091narg++1092
1093case xArgPtr16colon16:1094inst.Args[narg] = Imm(immc >> 16)1095inst.Args[narg+1] = Imm(immc & (1<<16 - 1))1096narg += 21097
1098case xArgPtr16colon32:1099inst.Args[narg] = Imm(immc >> 32)1100inst.Args[narg+1] = Imm(immc & (1<<32 - 1))1101narg += 21102
1103case xArgMoffs8, xArgMoffs16, xArgMoffs32, xArgMoffs64:1104// TODO(rsc): Can address be 64 bits?1105mem = Mem{Disp: int64(immc)}1106if segIndex >= 0 {1107mem.Segment = prefixToSegment(inst.Prefix[segIndex])1108inst.Prefix[segIndex] |= PrefixImplicit1109}1110inst.Args[narg] = mem1111inst.MemBytes = int(memBytes[decodeOp(x)])1112if mem.Base == RIP {1113inst.PCRel = displen1114inst.PCRelOff = dispoff1115}1116narg++1117
1118case xArgYmm1:1119base := baseReg[x]1120index := Reg(regop)1121if inst.Prefix[vexIndex+1]&0x80 == 0 {1122index += 81123}1124inst.Args[narg] = base + index1125narg++1126
1127case xArgR8, xArgR16, xArgR32, xArgR64, xArgXmm, xArgXmm1, xArgDR0dashDR7:1128base := baseReg[x]1129index := Reg(regop)1130if rex != 0 && base == AL && index >= 4 {1131rexUsed |= PrefixREX1132index -= 41133base = SPB1134}1135inst.Args[narg] = base + index1136narg++1137
1138case xArgMm, xArgMm1, xArgTR0dashTR7:1139inst.Args[narg] = baseReg[x] + Reg(regop&7)1140narg++1141
1142case xArgCR0dashCR7:1143// AMD documents an extension that the LOCK prefix1144// can be used in place of a REX prefix in order to access1145// CR8 from 32-bit mode. The LOCK prefix is allowed in1146// all modes, provided the corresponding CPUID bit is set.1147if lockIndex >= 0 {1148inst.Prefix[lockIndex] |= PrefixImplicit1149regop += 81150}1151inst.Args[narg] = CR0 + Reg(regop)1152narg++1153
1154case xArgSreg:1155regop &= 71156if regop >= 6 {1157inst.Op = 01158break Decode1159}1160inst.Args[narg] = ES + Reg(regop)1161narg++1162
1163case xArgRmf16, xArgRmf32, xArgRmf64:1164base := baseReg[x]1165index := Reg(modrm & 07)1166if rex&PrefixREXB != 0 {1167rexUsed |= PrefixREXB1168index += 81169}1170inst.Args[narg] = base + index1171narg++1172
1173case xArgR8op, xArgR16op, xArgR32op, xArgR64op, xArgSTi:1174n := inst.Opcode >> uint(opshift+8) & 071175base := baseReg[x]1176index := Reg(n)1177if rex&PrefixREXB != 0 && decodeOp(x) != xArgSTi {1178rexUsed |= PrefixREXB1179index += 81180}1181if rex != 0 && base == AL && index >= 4 {1182rexUsed |= PrefixREX1183index -= 41184base = SPB1185}1186inst.Args[narg] = base + index1187narg++1188case xArgRM8, xArgRM16, xArgRM32, xArgRM64, xArgR32M16, xArgR32M8, xArgR64M16,1189xArgMmM32, xArgMmM64, xArgMm2M64,1190xArgXmm2M16, xArgXmm2M32, xArgXmm2M64, xArgXmmM64, xArgXmmM128, xArgXmmM32, xArgXmm2M128,1191xArgYmm2M256:1192if haveMem {1193inst.Args[narg] = mem1194inst.MemBytes = int(memBytes[decodeOp(x)])1195if mem.Base == RIP {1196inst.PCRel = displen1197inst.PCRelOff = dispoff1198}1199} else {1200base := baseReg[x]1201index := Reg(rm)1202switch decodeOp(x) {1203case xArgMmM32, xArgMmM64, xArgMm2M64:1204// There are only 8 MMX registers, so these ignore the REX.X bit.1205index &= 71206case xArgRM8:1207if rex != 0 && index >= 4 {1208rexUsed |= PrefixREX1209index -= 41210base = SPB1211}1212case xArgYmm2M256:1213if vex == 0xC4 && inst.Prefix[vexIndex+1]&0x40 == 0x40 {1214index += 81215}1216}1217inst.Args[narg] = base + index1218}1219narg++1220
1221case xArgMm2: // register only; TODO(rsc): Handle with tag modrm_regonly tag1222if haveMem {1223inst.Op = 01224break Decode1225}1226inst.Args[narg] = baseReg[x] + Reg(rm&7)1227narg++1228
1229case xArgXmm2: // register only; TODO(rsc): Handle with tag modrm_regonly tag1230if haveMem {1231inst.Op = 01232break Decode1233}1234inst.Args[narg] = baseReg[x] + Reg(rm)1235narg++1236
1237case xArgRel8:1238inst.PCRelOff = immcpos1239inst.PCRel = 11240inst.Args[narg] = Rel(int8(immc))1241narg++1242
1243case xArgRel16:1244inst.PCRelOff = immcpos1245inst.PCRel = 21246inst.Args[narg] = Rel(int16(immc))1247narg++1248
1249case xArgRel32:1250inst.PCRelOff = immcpos1251inst.PCRel = 41252inst.Args[narg] = Rel(int32(immc))1253narg++1254}1255}1256
1257if inst.Op == 0 {1258// Invalid instruction.1259if nprefix > 0 {1260return instPrefix(src[0], mode) // invalid instruction1261}1262return Inst{Len: pos}, ErrUnrecognized1263}1264
1265// Matched! Hooray!1266
1267// 90 decodes as XCHG EAX, EAX but is NOP.1268// 66 90 decodes as XCHG AX, AX and is NOP too.1269// 48 90 decodes as XCHG RAX, RAX and is NOP too.1270// 43 90 decodes as XCHG R8D, EAX and is *not* NOP.1271// F3 90 decodes as REP XCHG EAX, EAX but is PAUSE.1272// It's all too special to handle in the decoding tables, at least for now.1273if inst.Op == XCHG && inst.Opcode>>24 == 0x90 {1274if inst.Args[0] == RAX || inst.Args[0] == EAX || inst.Args[0] == AX {1275inst.Op = NOP1276if dataSizeIndex >= 0 {1277inst.Prefix[dataSizeIndex] &^= PrefixImplicit1278}1279inst.Args[0] = nil1280inst.Args[1] = nil1281}1282if repIndex >= 0 && inst.Prefix[repIndex] == 0xF3 {1283inst.Prefix[repIndex] |= PrefixImplicit1284inst.Op = PAUSE1285inst.Args[0] = nil1286inst.Args[1] = nil1287} else if gnuCompat {1288for i := nprefix - 1; i >= 0; i-- {1289if inst.Prefix[i]&0xFF == 0xF3 {1290inst.Prefix[i] |= PrefixImplicit1291inst.Op = PAUSE1292inst.Args[0] = nil1293inst.Args[1] = nil1294break1295}1296}1297}1298}1299
1300// defaultSeg returns the default segment for an implicit1301// memory reference: the final override if present, or else DS.1302defaultSeg := func() Reg {1303if segIndex >= 0 {1304inst.Prefix[segIndex] |= PrefixImplicit1305return prefixToSegment(inst.Prefix[segIndex])1306}1307return DS1308}1309
1310// Add implicit arguments not present in the tables.1311// Normally we shy away from making implicit arguments explicit,1312// following the Intel manuals, but adding the arguments seems1313// the best way to express the effect of the segment override prefixes.1314// TODO(rsc): Perhaps add these to the tables and1315// create bytecode instructions for them.1316usedAddrSize := false1317switch inst.Op {1318case INSB, INSW, INSD:1319inst.Args[0] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX}1320inst.Args[1] = DX1321usedAddrSize = true1322
1323case OUTSB, OUTSW, OUTSD:1324inst.Args[0] = DX1325inst.Args[1] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + SI - AX}1326usedAddrSize = true1327
1328case MOVSB, MOVSW, MOVSD, MOVSQ:1329inst.Args[0] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX}1330inst.Args[1] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + SI - AX}1331usedAddrSize = true1332
1333case CMPSB, CMPSW, CMPSD, CMPSQ:1334inst.Args[0] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + SI - AX}1335inst.Args[1] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX}1336usedAddrSize = true1337
1338case LODSB, LODSW, LODSD, LODSQ:1339switch inst.Op {1340case LODSB:1341inst.Args[0] = AL1342case LODSW:1343inst.Args[0] = AX1344case LODSD:1345inst.Args[0] = EAX1346case LODSQ:1347inst.Args[0] = RAX1348}1349inst.Args[1] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + SI - AX}1350usedAddrSize = true1351
1352case STOSB, STOSW, STOSD, STOSQ:1353inst.Args[0] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX}1354switch inst.Op {1355case STOSB:1356inst.Args[1] = AL1357case STOSW:1358inst.Args[1] = AX1359case STOSD:1360inst.Args[1] = EAX1361case STOSQ:1362inst.Args[1] = RAX1363}1364usedAddrSize = true1365
1366case SCASB, SCASW, SCASD, SCASQ:1367inst.Args[1] = Mem{Segment: ES, Base: baseRegForBits(addrMode) + DI - AX}1368switch inst.Op {1369case SCASB:1370inst.Args[0] = AL1371case SCASW:1372inst.Args[0] = AX1373case SCASD:1374inst.Args[0] = EAX1375case SCASQ:1376inst.Args[0] = RAX1377}1378usedAddrSize = true1379
1380case XLATB:1381inst.Args[0] = Mem{Segment: defaultSeg(), Base: baseRegForBits(addrMode) + BX - AX}1382usedAddrSize = true1383}1384
1385// If we used the address size annotation to construct the1386// argument list, mark that prefix as implicit: it doesn't need1387// to be shown when printing the instruction.1388if haveMem || usedAddrSize {1389if addrSizeIndex >= 0 {1390inst.Prefix[addrSizeIndex] |= PrefixImplicit1391}1392}1393
1394// Similarly, if there's some memory operand, the segment1395// will be shown there and doesn't need to be shown as an1396// explicit prefix.1397if haveMem {1398if segIndex >= 0 {1399inst.Prefix[segIndex] |= PrefixImplicit1400}1401}1402
1403// Branch predict prefixes are overloaded segment prefixes,1404// since segment prefixes don't make sense on conditional jumps.1405// Rewrite final instance to prediction prefix.1406// The set of instructions to which the prefixes apply (other then the1407// Jcc conditional jumps) is not 100% clear from the manuals, but1408// the disassemblers seem to agree about the LOOP and JCXZ instructions,1409// so we'll follow along.1410// TODO(rsc): Perhaps this instruction class should be derived from the CSV.1411if isCondJmp[inst.Op] || isLoop[inst.Op] || inst.Op == JCXZ || inst.Op == JECXZ || inst.Op == JRCXZ {1412PredictLoop:1413for i := nprefix - 1; i >= 0; i-- {1414p := inst.Prefix[i]1415switch p & 0xFF {1416case PrefixCS:1417inst.Prefix[i] = PrefixPN1418break PredictLoop1419case PrefixDS:1420inst.Prefix[i] = PrefixPT1421break PredictLoop1422}1423}1424}1425
1426// The BND prefix is part of the Intel Memory Protection Extensions (MPX).1427// A REPN applied to certain control transfers is a BND prefix to bound1428// the range of possible destinations. There's surprisingly little documentation1429// about this, so we just do what libopcodes and xed agree on.1430// In particular, it's unclear why a REPN applied to LOOP or JCXZ instructions1431// does not turn into a BND.1432// TODO(rsc): Perhaps this instruction class should be derived from the CSV.1433if isCondJmp[inst.Op] || inst.Op == JMP || inst.Op == CALL || inst.Op == RET {1434for i := nprefix - 1; i >= 0; i-- {1435p := inst.Prefix[i]1436if p&^PrefixIgnored == PrefixREPN {1437inst.Prefix[i] = PrefixBND1438break1439}1440}1441}1442
1443// The LOCK prefix only applies to certain instructions, and then only1444// to instances of the instruction with a memory destination.1445// Other uses of LOCK are invalid and cause a processor exception,1446// in contrast to the "just ignore it" spirit applied to all other prefixes.1447// Mark invalid lock prefixes.1448hasLock := false1449if lockIndex >= 0 && inst.Prefix[lockIndex]&PrefixImplicit == 0 {1450switch inst.Op {1451// TODO(rsc): Perhaps this instruction class should be derived from the CSV.1452case ADD, ADC, AND, BTC, BTR, BTS, CMPXCHG, CMPXCHG8B, CMPXCHG16B, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD, XCHG:1453if isMem(inst.Args[0]) {1454hasLock = true1455break1456}1457fallthrough1458default:1459inst.Prefix[lockIndex] |= PrefixInvalid1460}1461}1462
1463// In certain cases, all of which require a memory destination,1464// the REPN and REP prefixes are interpreted as XACQUIRE and XRELEASE1465// from the Intel Transactional Synchroniation Extensions (TSX).1466//1467// The specific rules are:1468// (1) Any instruction with a valid LOCK prefix can have XACQUIRE or XRELEASE.1469// (2) Any XCHG, which always has an implicit LOCK, can have XACQUIRE or XRELEASE.1470// (3) Any 0x88-, 0x89-, 0xC6-, or 0xC7-opcode MOV can have XRELEASE.1471if isMem(inst.Args[0]) {1472if inst.Op == XCHG {1473hasLock = true1474}1475
1476for i := len(inst.Prefix) - 1; i >= 0; i-- {1477p := inst.Prefix[i] &^ PrefixIgnored1478switch p {1479case PrefixREPN:1480if hasLock {1481inst.Prefix[i] = inst.Prefix[i]&PrefixIgnored | PrefixXACQUIRE1482}1483
1484case PrefixREP:1485if hasLock {1486inst.Prefix[i] = inst.Prefix[i]&PrefixIgnored | PrefixXRELEASE1487}1488
1489if inst.Op == MOV {1490op := (inst.Opcode >> 24) &^ 11491if op == 0x88 || op == 0xC6 {1492inst.Prefix[i] = inst.Prefix[i]&PrefixIgnored | PrefixXRELEASE1493}1494}1495}1496}1497}1498
1499// If REP is used on a non-REP-able instruction, mark the prefix as ignored.1500if repIndex >= 0 {1501switch inst.Prefix[repIndex] {1502case PrefixREP, PrefixREPN:1503switch inst.Op {1504// According to the manuals, the REP/REPE prefix applies to all of these,1505// while the REPN applies only to some of them. However, both libopcodes1506// and xed show both prefixes explicitly for all instructions, so we do the same.1507// TODO(rsc): Perhaps this instruction class should be derived from the CSV.1508case INSB, INSW, INSD,1509MOVSB, MOVSW, MOVSD, MOVSQ,1510OUTSB, OUTSW, OUTSD,1511LODSB, LODSW, LODSD, LODSQ,1512CMPSB, CMPSW, CMPSD, CMPSQ,1513SCASB, SCASW, SCASD, SCASQ,1514STOSB, STOSW, STOSD, STOSQ:1515// ok1516default:1517inst.Prefix[repIndex] |= PrefixIgnored1518}1519}1520}1521
1522// If REX was present, mark implicit if all the 1 bits were consumed.1523if rexIndex >= 0 {1524if rexUsed != 0 {1525rexUsed |= PrefixREX1526}1527if rex&^rexUsed == 0 {1528inst.Prefix[rexIndex] |= PrefixImplicit1529}1530}1531
1532inst.DataSize = dataMode1533inst.AddrSize = addrMode1534inst.Mode = mode1535inst.Len = pos1536return inst, nil1537}
1538
1539var errInternal = errors.New("internal error")1540
1541// addr16 records the eight 16-bit addressing modes.
1542var addr16 = [8]Mem{1543{Base: BX, Scale: 1, Index: SI},1544{Base: BX, Scale: 1, Index: DI},1545{Base: BP, Scale: 1, Index: SI},1546{Base: BP, Scale: 1, Index: DI},1547{Base: SI},1548{Base: DI},1549{Base: BP},1550{Base: BX},1551}
1552
1553// baseRegForBits returns the base register for a given register size in bits.
1554func baseRegForBits(bits int) Reg {1555switch bits {1556case 8:1557return AL1558case 16:1559return AX1560case 32:1561return EAX1562case 64:1563return RAX1564}1565return 01566}
1567
1568// baseReg records the base register for argument types that specify
1569// a range of registers indexed by op, regop, or rm.
1570var baseReg = [...]Reg{1571xArgDR0dashDR7: DR0,1572xArgMm1: M0,1573xArgMm2: M0,1574xArgMm2M64: M0,1575xArgMm: M0,1576xArgMmM32: M0,1577xArgMmM64: M0,1578xArgR16: AX,1579xArgR16op: AX,1580xArgR32: EAX,1581xArgR32M16: EAX,1582xArgR32M8: EAX,1583xArgR32op: EAX,1584xArgR64: RAX,1585xArgR64M16: RAX,1586xArgR64op: RAX,1587xArgR8: AL,1588xArgR8op: AL,1589xArgRM16: AX,1590xArgRM32: EAX,1591xArgRM64: RAX,1592xArgRM8: AL,1593xArgRmf16: AX,1594xArgRmf32: EAX,1595xArgRmf64: RAX,1596xArgSTi: F0,1597xArgTR0dashTR7: TR0,1598xArgXmm1: X0,1599xArgYmm1: X0,1600xArgXmm2: X0,1601xArgXmm2M128: X0,1602xArgYmm2M256: X0,1603xArgXmm2M16: X0,1604xArgXmm2M32: X0,1605xArgXmm2M64: X0,1606xArgXmm: X0,1607xArgXmmM128: X0,1608xArgXmmM32: X0,1609xArgXmmM64: X0,1610}
1611
1612// prefixToSegment returns the segment register
1613// corresponding to a particular segment prefix.
1614func prefixToSegment(p Prefix) Reg {1615switch p &^ PrefixImplicit {1616case PrefixCS:1617return CS1618case PrefixDS:1619return DS1620case PrefixES:1621return ES1622case PrefixFS:1623return FS1624case PrefixGS:1625return GS1626case PrefixSS:1627return SS1628}1629return 01630}
1631
1632// fixedArg records the fixed arguments corresponding to the given bytecodes.
1633var fixedArg = [...]Arg{1634xArg1: Imm(1),1635xArg3: Imm(3),1636xArgAL: AL,1637xArgAX: AX,1638xArgDX: DX,1639xArgEAX: EAX,1640xArgEDX: EDX,1641xArgRAX: RAX,1642xArgRDX: RDX,1643xArgCL: CL,1644xArgCS: CS,1645xArgDS: DS,1646xArgES: ES,1647xArgFS: FS,1648xArgGS: GS,1649xArgSS: SS,1650xArgST: F0,1651xArgXMM0: X0,1652}
1653
1654// memBytes records the size of the memory pointed at
1655// by a memory argument of the given form.
1656var memBytes = [...]int8{1657xArgM128: 128 / 8,1658xArgM256: 256 / 8,1659xArgM16: 16 / 8,1660xArgM16and16: (16 + 16) / 8,1661xArgM16colon16: (16 + 16) / 8,1662xArgM16colon32: (16 + 32) / 8,1663xArgM16int: 16 / 8,1664xArgM2byte: 2,1665xArgM32: 32 / 8,1666xArgM32and32: (32 + 32) / 8,1667xArgM32fp: 32 / 8,1668xArgM32int: 32 / 8,1669xArgM64: 64 / 8,1670xArgM64fp: 64 / 8,1671xArgM64int: 64 / 8,1672xArgMm2M64: 64 / 8,1673xArgMmM32: 32 / 8,1674xArgMmM64: 64 / 8,1675xArgMoffs16: 16 / 8,1676xArgMoffs32: 32 / 8,1677xArgMoffs64: 64 / 8,1678xArgMoffs8: 8 / 8,1679xArgR32M16: 16 / 8,1680xArgR32M8: 8 / 8,1681xArgR64M16: 16 / 8,1682xArgRM16: 16 / 8,1683xArgRM32: 32 / 8,1684xArgRM64: 64 / 8,1685xArgRM8: 8 / 8,1686xArgXmm2M128: 128 / 8,1687xArgYmm2M256: 256 / 8,1688xArgXmm2M16: 16 / 8,1689xArgXmm2M32: 32 / 8,1690xArgXmm2M64: 64 / 8,1691xArgXmm: 128 / 8,1692xArgXmmM128: 128 / 8,1693xArgXmmM32: 32 / 8,1694xArgXmmM64: 64 / 8,1695}
1696
1697// isCondJmp records the conditional jumps.
1698var isCondJmp = [maxOp + 1]bool{1699JA: true,1700JAE: true,1701JB: true,1702JBE: true,1703JE: true,1704JG: true,1705JGE: true,1706JL: true,1707JLE: true,1708JNE: true,1709JNO: true,1710JNP: true,1711JNS: true,1712JO: true,1713JP: true,1714JS: true,1715}
1716
1717// isLoop records the loop operators.
1718var isLoop = [maxOp + 1]bool{1719LOOP: true,1720LOOPE: true,1721LOOPNE: true,1722JECXZ: true,1723JRCXZ: true,1724}
1725