cubefs
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// Package x86asm implements decoding of x86 machine code.
6package x86asm7
8import (9"bytes"10"fmt"11)
12
13// An Inst is a single instruction.
14type Inst struct {15Prefix Prefixes // Prefixes applied to the instruction.16Op Op // Opcode mnemonic17Opcode uint32 // Encoded opcode bits, left aligned (first byte is Opcode>>24, etc)18Args Args // Instruction arguments, in Intel order19Mode int // processor mode in bits: 16, 32, or 6420AddrSize int // address size in bits: 16, 32, or 6421DataSize int // operand size in bits: 16, 32, or 6422MemBytes int // size of memory argument in bytes: 1, 2, 4, 8, 16, and so on.23Len int // length of encoded instruction in bytes24PCRel int // length of PC-relative address in instruction encoding25PCRelOff int // index of start of PC-relative address in instruction encoding26}
27
28// Prefixes is an array of prefixes associated with a single instruction.
29// The prefixes are listed in the same order as found in the instruction:
30// each prefix byte corresponds to one slot in the array. The first zero
31// in the array marks the end of the prefixes.
32type Prefixes [14]Prefix33
34// A Prefix represents an Intel instruction prefix.
35// The low 8 bits are the actual prefix byte encoding,
36// and the top 8 bits contain distinguishing bits and metadata.
37type Prefix uint1638
39const (40// Metadata about the role of a prefix in an instruction.41PrefixImplicit Prefix = 0x8000 // prefix is implied by instruction text42PrefixIgnored Prefix = 0x4000 // prefix is ignored: either irrelevant or overridden by a later prefix43PrefixInvalid Prefix = 0x2000 // prefix makes entire instruction invalid (bad LOCK)44
45// Memory segment overrides.46PrefixES Prefix = 0x26 // ES segment override47PrefixCS Prefix = 0x2E // CS segment override48PrefixSS Prefix = 0x36 // SS segment override49PrefixDS Prefix = 0x3E // DS segment override50PrefixFS Prefix = 0x64 // FS segment override51PrefixGS Prefix = 0x65 // GS segment override52
53// Branch prediction.54PrefixPN Prefix = 0x12E // predict not taken (conditional branch only)55PrefixPT Prefix = 0x13E // predict taken (conditional branch only)56
57// Size attributes.58PrefixDataSize Prefix = 0x66 // operand size override59PrefixData16 Prefix = 0x16660PrefixData32 Prefix = 0x26661PrefixAddrSize Prefix = 0x67 // address size override62PrefixAddr16 Prefix = 0x16763PrefixAddr32 Prefix = 0x26764
65// One of a kind.66PrefixLOCK Prefix = 0xF0 // lock67PrefixREPN Prefix = 0xF2 // repeat not zero68PrefixXACQUIRE Prefix = 0x1F269PrefixBND Prefix = 0x2F270PrefixREP Prefix = 0xF3 // repeat71PrefixXRELEASE Prefix = 0x1F372
73// The REX prefixes must be in the range [PrefixREX, PrefixREX+0x10).74// the other bits are set or not according to the intended use.75PrefixREX Prefix = 0x40 // REX 64-bit extension prefix76PrefixREXW Prefix = 0x08 // extension bit W (64-bit instruction width)77PrefixREXR Prefix = 0x04 // extension bit R (r field in modrm)78PrefixREXX Prefix = 0x02 // extension bit X (index field in sib)79PrefixREXB Prefix = 0x01 // extension bit B (r/m field in modrm or base field in sib)80PrefixVEX2Bytes Prefix = 0xC5 // Short form of vex prefix81PrefixVEX3Bytes Prefix = 0xC4 // Long form of vex prefix82)
83
84// IsREX reports whether p is a REX prefix byte.
85func (p Prefix) IsREX() bool {86return p&0xF0 == PrefixREX87}
88
89func (p Prefix) IsVEX() bool {90return p&0xFF == PrefixVEX2Bytes || p&0xFF == PrefixVEX3Bytes91}
92
93func (p Prefix) String() string {94p &^= PrefixImplicit | PrefixIgnored | PrefixInvalid95if s := prefixNames[p]; s != "" {96return s97}98
99if p.IsREX() {100s := "REX."101if p&PrefixREXW != 0 {102s += "W"103}104if p&PrefixREXR != 0 {105s += "R"106}107if p&PrefixREXX != 0 {108s += "X"109}110if p&PrefixREXB != 0 {111s += "B"112}113return s114}115
116return fmt.Sprintf("Prefix(%#x)", int(p))117}
118
119// An Op is an x86 opcode.
120type Op uint32121
122func (op Op) String() string {123i := int(op)124if i < 0 || i >= len(opNames) || opNames[i] == "" {125return fmt.Sprintf("Op(%d)", i)126}127return opNames[i]128}
129
130// An Args holds the instruction arguments.
131// If an instruction has fewer than 4 arguments,
132// the final elements in the array are nil.
133type Args [4]Arg134
135// An Arg is a single instruction argument,
136// one of these types: Reg, Mem, Imm, Rel.
137type Arg interface {138String() string139isArg()140}
141
142// Note that the implements of Arg that follow are all sized
143// so that on a 64-bit machine the data can be inlined in
144// the interface value instead of requiring an allocation.
145
146// A Reg is a single register.
147// The zero Reg value has no name but indicates ``no register.''
148type Reg uint8149
150const (151_ Reg = iota152
153// 8-bit154AL
155CL
156DL
157BL
158AH
159CH
160DH
161BH
162SPB
163BPB
164SIB
165DIB
166R8B
167R9B
168R10B
169R11B
170R12B
171R13B
172R14B
173R15B
174
175// 16-bit176AX
177CX
178DX
179BX
180SP
181BP
182SI
183DI
184R8W
185R9W
186R10W
187R11W
188R12W
189R13W
190R14W
191R15W
192
193// 32-bit194EAX
195ECX
196EDX
197EBX
198ESP
199EBP
200ESI
201EDI
202R8L
203R9L
204R10L
205R11L
206R12L
207R13L
208R14L
209R15L
210
211// 64-bit212RAX
213RCX
214RDX
215RBX
216RSP
217RBP
218RSI
219RDI
220R8
221R9
222R10
223R11
224R12
225R13
226R14
227R15
228
229// Instruction pointer.230IP // 16-bit231EIP // 32-bit232RIP // 64-bit233
234// 387 floating point registers.235F0
236F1
237F2
238F3
239F4
240F5
241F6
242F7
243
244// MMX registers.245M0
246M1
247M2
248M3
249M4
250M5
251M6
252M7
253
254// XMM registers.255X0
256X1
257X2
258X3
259X4
260X5
261X6
262X7
263X8
264X9
265X10
266X11
267X12
268X13
269X14
270X15
271
272// Segment registers.273ES
274CS
275SS
276DS
277FS
278GS
279
280// System registers.281GDTR
282IDTR
283LDTR
284MSW
285TASK
286
287// Control registers.288CR0
289CR1
290CR2
291CR3
292CR4
293CR5
294CR6
295CR7
296CR8
297CR9
298CR10
299CR11
300CR12
301CR13
302CR14
303CR15
304
305// Debug registers.306DR0
307DR1
308DR2
309DR3
310DR4
311DR5
312DR6
313DR7
314DR8
315DR9
316DR10
317DR11
318DR12
319DR13
320DR14
321DR15
322
323// Task registers.324TR0
325TR1
326TR2
327TR3
328TR4
329TR5
330TR6
331TR7
332)
333
334const regMax = TR7335
336func (Reg) isArg() {}337
338func (r Reg) String() string {339i := int(r)340if i < 0 || i >= len(regNames) || regNames[i] == "" {341return fmt.Sprintf("Reg(%d)", i)342}343return regNames[i]344}
345
346// A Mem is a memory reference.
347// The general form is Segment:[Base+Scale*Index+Disp].
348type Mem struct {349Segment Reg
350Base Reg
351Scale uint8352Index Reg
353Disp int64354}
355
356func (Mem) isArg() {}357
358func (m Mem) String() string {359var base, plus, scale, index, disp string360
361if m.Base != 0 {362base = m.Base.String()363}364if m.Scale != 0 {365if m.Base != 0 {366plus = "+"367}368if m.Scale > 1 {369scale = fmt.Sprintf("%d*", m.Scale)370}371index = m.Index.String()372}373if m.Disp != 0 || m.Base == 0 && m.Scale == 0 {374disp = fmt.Sprintf("%+#x", m.Disp)375}376return "[" + base + plus + scale + index + disp + "]"377}
378
379// A Rel is an offset relative to the current instruction pointer.
380type Rel int32381
382func (Rel) isArg() {}383
384func (r Rel) String() string {385return fmt.Sprintf(".%+d", r)386}
387
388// An Imm is an integer constant.
389type Imm int64390
391func (Imm) isArg() {}392
393func (i Imm) String() string {394return fmt.Sprintf("%#x", int64(i))395}
396
397func (i Inst) String() string {398var buf bytes.Buffer399for _, p := range i.Prefix {400if p == 0 {401break402}403if p&PrefixImplicit != 0 {404continue405}406fmt.Fprintf(&buf, "%v ", p)407}408fmt.Fprintf(&buf, "%v", i.Op)409sep := " "410for _, v := range i.Args {411if v == nil {412break413}414fmt.Fprintf(&buf, "%s%v", sep, v)415sep = ", "416}417return buf.String()418}
419
420func isReg(a Arg) bool {421_, ok := a.(Reg)422return ok423}
424
425func isSegReg(a Arg) bool {426r, ok := a.(Reg)427return ok && ES <= r && r <= GS428}
429
430func isMem(a Arg) bool {431_, ok := a.(Mem)432return ok433}
434
435func isImm(a Arg) bool {436_, ok := a.(Imm)437return ok438}
439
440func regBytes(a Arg) int {441r, ok := a.(Reg)442if !ok {443return 0444}445if AL <= r && r <= R15B {446return 1447}448if AX <= r && r <= R15W {449return 2450}451if EAX <= r && r <= R15L {452return 4453}454if RAX <= r && r <= R15 {455return 8456}457return 0458}
459
460func isSegment(p Prefix) bool {461switch p {462case PrefixCS, PrefixDS, PrefixES, PrefixFS, PrefixGS, PrefixSS:463return true464}465return false466}
467
468// The Op definitions and string list are in tables.go.
469
470var prefixNames = map[Prefix]string{471PrefixCS: "CS",472PrefixDS: "DS",473PrefixES: "ES",474PrefixFS: "FS",475PrefixGS: "GS",476PrefixSS: "SS",477PrefixLOCK: "LOCK",478PrefixREP: "REP",479PrefixREPN: "REPN",480PrefixAddrSize: "ADDRSIZE",481PrefixDataSize: "DATASIZE",482PrefixAddr16: "ADDR16",483PrefixData16: "DATA16",484PrefixAddr32: "ADDR32",485PrefixData32: "DATA32",486PrefixBND: "BND",487PrefixXACQUIRE: "XACQUIRE",488PrefixXRELEASE: "XRELEASE",489PrefixREX: "REX",490PrefixPT: "PT",491PrefixPN: "PN",492}
493
494var regNames = [...]string{495AL: "AL",496CL: "CL",497BL: "BL",498DL: "DL",499AH: "AH",500CH: "CH",501BH: "BH",502DH: "DH",503SPB: "SPB",504BPB: "BPB",505SIB: "SIB",506DIB: "DIB",507R8B: "R8B",508R9B: "R9B",509R10B: "R10B",510R11B: "R11B",511R12B: "R12B",512R13B: "R13B",513R14B: "R14B",514R15B: "R15B",515AX: "AX",516CX: "CX",517BX: "BX",518DX: "DX",519SP: "SP",520BP: "BP",521SI: "SI",522DI: "DI",523R8W: "R8W",524R9W: "R9W",525R10W: "R10W",526R11W: "R11W",527R12W: "R12W",528R13W: "R13W",529R14W: "R14W",530R15W: "R15W",531EAX: "EAX",532ECX: "ECX",533EDX: "EDX",534EBX: "EBX",535ESP: "ESP",536EBP: "EBP",537ESI: "ESI",538EDI: "EDI",539R8L: "R8L",540R9L: "R9L",541R10L: "R10L",542R11L: "R11L",543R12L: "R12L",544R13L: "R13L",545R14L: "R14L",546R15L: "R15L",547RAX: "RAX",548RCX: "RCX",549RDX: "RDX",550RBX: "RBX",551RSP: "RSP",552RBP: "RBP",553RSI: "RSI",554RDI: "RDI",555R8: "R8",556R9: "R9",557R10: "R10",558R11: "R11",559R12: "R12",560R13: "R13",561R14: "R14",562R15: "R15",563IP: "IP",564EIP: "EIP",565RIP: "RIP",566F0: "F0",567F1: "F1",568F2: "F2",569F3: "F3",570F4: "F4",571F5: "F5",572F6: "F6",573F7: "F7",574M0: "M0",575M1: "M1",576M2: "M2",577M3: "M3",578M4: "M4",579M5: "M5",580M6: "M6",581M7: "M7",582X0: "X0",583X1: "X1",584X2: "X2",585X3: "X3",586X4: "X4",587X5: "X5",588X6: "X6",589X7: "X7",590X8: "X8",591X9: "X9",592X10: "X10",593X11: "X11",594X12: "X12",595X13: "X13",596X14: "X14",597X15: "X15",598CS: "CS",599SS: "SS",600DS: "DS",601ES: "ES",602FS: "FS",603GS: "GS",604GDTR: "GDTR",605IDTR: "IDTR",606LDTR: "LDTR",607MSW: "MSW",608TASK: "TASK",609CR0: "CR0",610CR1: "CR1",611CR2: "CR2",612CR3: "CR3",613CR4: "CR4",614CR5: "CR5",615CR6: "CR6",616CR7: "CR7",617CR8: "CR8",618CR9: "CR9",619CR10: "CR10",620CR11: "CR11",621CR12: "CR12",622CR13: "CR13",623CR14: "CR14",624CR15: "CR15",625DR0: "DR0",626DR1: "DR1",627DR2: "DR2",628DR3: "DR3",629DR4: "DR4",630DR5: "DR5",631DR6: "DR6",632DR7: "DR7",633DR8: "DR8",634DR9: "DR9",635DR10: "DR10",636DR11: "DR11",637DR12: "DR12",638DR13: "DR13",639DR14: "DR14",640DR15: "DR15",641TR0: "TR0",642TR1: "TR1",643TR2: "TR2",644TR3: "TR3",645TR4: "TR4",646TR5: "TR5",647TR6: "TR6",648TR7: "TR7",649}
650