...

Source file src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x.go

     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
     6	
     7	import (
     8		"fmt"
     9		"strings"
    10	)
    11	
    12	type SymLookup func(uint64) (string, uint64)
    13	
    14	// GoSyntax returns the Go assembler syntax for the instruction.
    15	// The syntax was originally defined by Plan 9.
    16	// The pc is the program counter of the instruction, used for expanding
    17	// PC-relative addresses into absolute ones.
    18	// The symname function queries the symbol table for the program
    19	// being disassembled. Given a target address it returns the name and base
    20	// address of the symbol containing the target, if any; otherwise it returns "", 0.
    21	func GoSyntax(inst Inst, pc uint64, symname SymLookup) string {
    22		if symname == nil {
    23			symname = func(uint64) (string, uint64) { return "", 0 }
    24		}
    25		var args []string
    26		for i := len(inst.Args) - 1; i >= 0; i-- {
    27			a := inst.Args[i]
    28			if a == nil {
    29				continue
    30			}
    31			args = append(args, plan9Arg(&inst, pc, symname, a))
    32		}
    33	
    34		var rep string
    35		var last Prefix
    36		for _, p := range inst.Prefix {
    37			if p == 0 || p.IsREX() || p.IsVEX() {
    38				break
    39			}
    40	
    41			switch {
    42			// Don't show prefixes implied by the instruction text.
    43			case p&0xFF00 == PrefixImplicit:
    44				continue
    45			// Only REP and REPN are recognized repeaters. Plan 9 syntax
    46			// treats them as separate opcodes.
    47			case p&0xFF == PrefixREP:
    48				rep = "REP; "
    49			case p&0xFF == PrefixREPN:
    50				rep = "REPNE; "
    51			default:
    52				last = p
    53			}
    54		}
    55	
    56		prefix := ""
    57		switch last & 0xFF {
    58		case 0, 0x66, 0x67:
    59			// ignore
    60		default:
    61			prefix += last.String() + " "
    62		}
    63	
    64		op := inst.Op.String()
    65		if plan9Suffix[inst.Op] {
    66			s := inst.DataSize
    67			if inst.MemBytes != 0 {
    68				s = inst.MemBytes * 8
    69			}
    70			switch s {
    71			case 8:
    72				op += "B"
    73			case 16:
    74				op += "W"
    75			case 32:
    76				op += "L"
    77			case 64:
    78				op += "Q"
    79			}
    80		}
    81	
    82		if args != nil {
    83			op += " " + strings.Join(args, ", ")
    84		}
    85	
    86		return rep + prefix + op
    87	}
    88	
    89	func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg Arg) string {
    90		switch a := arg.(type) {
    91		case Reg:
    92			return plan9Reg[a]
    93		case Rel:
    94			if pc == 0 {
    95				break
    96			}
    97			// If the absolute address is the start of a symbol, use the name.
    98			// Otherwise use the raw address, so that things like relative
    99			// jumps show up as JMP 0x123 instead of JMP f+10(SB).
   100			// It is usually easier to search for 0x123 than to do the mental
   101			// arithmetic to find f+10.
   102			addr := pc + uint64(inst.Len) + uint64(a)
   103			if s, base := symname(addr); s != "" && addr == base {
   104				return fmt.Sprintf("%s(SB)", s)
   105			}
   106			return fmt.Sprintf("%#x", addr)
   107	
   108		case Imm:
   109			if s, base := symname(uint64(a)); s != "" {
   110				suffix := ""
   111				if uint64(a) != base {
   112					suffix = fmt.Sprintf("%+d", uint64(a)-base)
   113				}
   114				return fmt.Sprintf("$%s%s(SB)", s, suffix)
   115			}
   116			if inst.Mode == 32 {
   117				return fmt.Sprintf("$%#x", uint32(a))
   118			}
   119			if Imm(int32(a)) == a {
   120				return fmt.Sprintf("$%#x", int64(a))
   121			}
   122			return fmt.Sprintf("$%#x", uint64(a))
   123		case Mem:
   124			if s, disp := memArgToSymbol(a, pc, inst.Len, symname); s != "" {
   125				suffix := ""
   126				if disp != 0 {
   127					suffix = fmt.Sprintf("%+d", disp)
   128				}
   129				return fmt.Sprintf("%s%s(SB)", s, suffix)
   130			}
   131			s := ""
   132			if a.Segment != 0 {
   133				s += fmt.Sprintf("%s:", plan9Reg[a.Segment])
   134			}
   135			if a.Disp != 0 {
   136				s += fmt.Sprintf("%#x", a.Disp)
   137			} else {
   138				s += "0"
   139			}
   140			if a.Base != 0 {
   141				s += fmt.Sprintf("(%s)", plan9Reg[a.Base])
   142			}
   143			if a.Index != 0 && a.Scale != 0 {
   144				s += fmt.Sprintf("(%s*%d)", plan9Reg[a.Index], a.Scale)
   145			}
   146			return s
   147		}
   148		return arg.String()
   149	}
   150	
   151	func memArgToSymbol(a Mem, pc uint64, instrLen int, symname SymLookup) (string, int64) {
   152		if a.Segment != 0 || a.Disp == 0 || a.Index != 0 || a.Scale != 0 {
   153			return "", 0
   154		}
   155	
   156		var disp uint64
   157		switch a.Base {
   158		case IP, EIP, RIP:
   159			disp = uint64(a.Disp + int64(pc) + int64(instrLen))
   160		case 0:
   161			disp = uint64(a.Disp)
   162		default:
   163			return "", 0
   164		}
   165	
   166		s, base := symname(disp)
   167		return s, int64(disp) - int64(base)
   168	}
   169	
   170	var plan9Suffix = [maxOp + 1]bool{
   171		ADC:       true,
   172		ADD:       true,
   173		AND:       true,
   174		BSF:       true,
   175		BSR:       true,
   176		BT:        true,
   177		BTC:       true,
   178		BTR:       true,
   179		BTS:       true,
   180		CMP:       true,
   181		CMPXCHG:   true,
   182		CVTSI2SD:  true,
   183		CVTSI2SS:  true,
   184		CVTSD2SI:  true,
   185		CVTSS2SI:  true,
   186		CVTTSD2SI: true,
   187		CVTTSS2SI: true,
   188		DEC:       true,
   189		DIV:       true,
   190		FLDENV:    true,
   191		FRSTOR:    true,
   192		IDIV:      true,
   193		IMUL:      true,
   194		IN:        true,
   195		INC:       true,
   196		LEA:       true,
   197		MOV:       true,
   198		MOVNTI:    true,
   199		MUL:       true,
   200		NEG:       true,
   201		NOP:       true,
   202		NOT:       true,
   203		OR:        true,
   204		OUT:       true,
   205		POP:       true,
   206		POPA:      true,
   207		PUSH:      true,
   208		PUSHA:     true,
   209		RCL:       true,
   210		RCR:       true,
   211		ROL:       true,
   212		ROR:       true,
   213		SAR:       true,
   214		SBB:       true,
   215		SHL:       true,
   216		SHLD:      true,
   217		SHR:       true,
   218		SHRD:      true,
   219		SUB:       true,
   220		TEST:      true,
   221		XADD:      true,
   222		XCHG:      true,
   223		XOR:       true,
   224	}
   225	
   226	var plan9Reg = [...]string{
   227		AL:   "AL",
   228		CL:   "CL",
   229		BL:   "BL",
   230		DL:   "DL",
   231		AH:   "AH",
   232		CH:   "CH",
   233		BH:   "BH",
   234		DH:   "DH",
   235		SPB:  "SP",
   236		BPB:  "BP",
   237		SIB:  "SI",
   238		DIB:  "DI",
   239		R8B:  "R8",
   240		R9B:  "R9",
   241		R10B: "R10",
   242		R11B: "R11",
   243		R12B: "R12",
   244		R13B: "R13",
   245		R14B: "R14",
   246		R15B: "R15",
   247		AX:   "AX",
   248		CX:   "CX",
   249		BX:   "BX",
   250		DX:   "DX",
   251		SP:   "SP",
   252		BP:   "BP",
   253		SI:   "SI",
   254		DI:   "DI",
   255		R8W:  "R8",
   256		R9W:  "R9",
   257		R10W: "R10",
   258		R11W: "R11",
   259		R12W: "R12",
   260		R13W: "R13",
   261		R14W: "R14",
   262		R15W: "R15",
   263		EAX:  "AX",
   264		ECX:  "CX",
   265		EDX:  "DX",
   266		EBX:  "BX",
   267		ESP:  "SP",
   268		EBP:  "BP",
   269		ESI:  "SI",
   270		EDI:  "DI",
   271		R8L:  "R8",
   272		R9L:  "R9",
   273		R10L: "R10",
   274		R11L: "R11",
   275		R12L: "R12",
   276		R13L: "R13",
   277		R14L: "R14",
   278		R15L: "R15",
   279		RAX:  "AX",
   280		RCX:  "CX",
   281		RDX:  "DX",
   282		RBX:  "BX",
   283		RSP:  "SP",
   284		RBP:  "BP",
   285		RSI:  "SI",
   286		RDI:  "DI",
   287		R8:   "R8",
   288		R9:   "R9",
   289		R10:  "R10",
   290		R11:  "R11",
   291		R12:  "R12",
   292		R13:  "R13",
   293		R14:  "R14",
   294		R15:  "R15",
   295		IP:   "IP",
   296		EIP:  "IP",
   297		RIP:  "IP",
   298		F0:   "F0",
   299		F1:   "F1",
   300		F2:   "F2",
   301		F3:   "F3",
   302		F4:   "F4",
   303		F5:   "F5",
   304		F6:   "F6",
   305		F7:   "F7",
   306		M0:   "M0",
   307		M1:   "M1",
   308		M2:   "M2",
   309		M3:   "M3",
   310		M4:   "M4",
   311		M5:   "M5",
   312		M6:   "M6",
   313		M7:   "M7",
   314		X0:   "X0",
   315		X1:   "X1",
   316		X2:   "X2",
   317		X3:   "X3",
   318		X4:   "X4",
   319		X5:   "X5",
   320		X6:   "X6",
   321		X7:   "X7",
   322		X8:   "X8",
   323		X9:   "X9",
   324		X10:  "X10",
   325		X11:  "X11",
   326		X12:  "X12",
   327		X13:  "X13",
   328		X14:  "X14",
   329		X15:  "X15",
   330		CS:   "CS",
   331		SS:   "SS",
   332		DS:   "DS",
   333		ES:   "ES",
   334		FS:   "FS",
   335		GS:   "GS",
   336		GDTR: "GDTR",
   337		IDTR: "IDTR",
   338		LDTR: "LDTR",
   339		MSW:  "MSW",
   340		TASK: "TASK",
   341		CR0:  "CR0",
   342		CR1:  "CR1",
   343		CR2:  "CR2",
   344		CR3:  "CR3",
   345		CR4:  "CR4",
   346		CR5:  "CR5",
   347		CR6:  "CR6",
   348		CR7:  "CR7",
   349		CR8:  "CR8",
   350		CR9:  "CR9",
   351		CR10: "CR10",
   352		CR11: "CR11",
   353		CR12: "CR12",
   354		CR13: "CR13",
   355		CR14: "CR14",
   356		CR15: "CR15",
   357		DR0:  "DR0",
   358		DR1:  "DR1",
   359		DR2:  "DR2",
   360		DR3:  "DR3",
   361		DR4:  "DR4",
   362		DR5:  "DR5",
   363		DR6:  "DR6",
   364		DR7:  "DR7",
   365		DR8:  "DR8",
   366		DR9:  "DR9",
   367		DR10: "DR10",
   368		DR11: "DR11",
   369		DR12: "DR12",
   370		DR13: "DR13",
   371		DR14: "DR14",
   372		DR15: "DR15",
   373		TR0:  "TR0",
   374		TR1:  "TR1",
   375		TR2:  "TR2",
   376		TR3:  "TR3",
   377		TR4:  "TR4",
   378		TR5:  "TR5",
   379		TR6:  "TR6",
   380		TR7:  "TR7",
   381	}
   382	

View as plain text