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