github.com/ccccaoqing/test@v0.0.0-20220510085219-3985d23445c0/src/cmd/internal/rsc.io/arm/armasm/decode.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 armasm 6 7 import ( 8 "encoding/binary" 9 "fmt" 10 ) 11 12 // An instFormat describes the format of an instruction encoding. 13 // An instruction with 32-bit value x matches the format if x&mask == value 14 // and the condition matches. 15 // The condition matches if x>>28 == 0xF && value>>28==0xF 16 // or if x>>28 != 0xF and value>>28 == 0. 17 // If x matches the format, then the rest of the fields describe how to interpret x. 18 // The opBits describe bits that should be extracted from x and added to the opcode. 19 // For example opBits = 0x1234 means that the value 20 // (2 bits at offset 1) followed by (4 bits at offset 3) 21 // should be added to op. 22 // Finally the args describe how to decode the instruction arguments. 23 // args is stored as a fixed-size array; if there are fewer than len(args) arguments, 24 // args[i] == 0 marks the end of the argument list. 25 type instFormat struct { 26 mask uint32 27 value uint32 28 priority int8 29 op Op 30 opBits uint64 31 args instArgs 32 } 33 34 type instArgs [4]instArg 35 36 var ( 37 errMode = fmt.Errorf("unsupported execution mode") 38 errShort = fmt.Errorf("truncated instruction") 39 errUnknown = fmt.Errorf("unknown instruction") 40 ) 41 42 var decoderCover []bool 43 44 // Decode decodes the leading bytes in src as a single instruction. 45 func Decode(src []byte, mode Mode) (inst Inst, err error) { 46 if mode != ModeARM { 47 return Inst{}, errMode 48 } 49 if len(src) < 4 { 50 return Inst{}, errShort 51 } 52 53 if decoderCover == nil { 54 decoderCover = make([]bool, len(instFormats)) 55 } 56 57 x := binary.LittleEndian.Uint32(src) 58 59 // The instFormat table contains both conditional and unconditional instructions. 60 // Considering only the top 4 bits, the conditional instructions use mask=0, value=0, 61 // while the unconditional instructions use mask=f, value=f. 62 // Prepare a version of x with the condition cleared to 0 in conditional instructions 63 // and then assume mask=f during matching. 64 const condMask = 0xf0000000 65 xNoCond := x 66 if x&condMask != condMask { 67 xNoCond &^= condMask 68 } 69 var priority int8 70 Search: 71 for i := range instFormats { 72 f := &instFormats[i] 73 if xNoCond&(f.mask|condMask) != f.value || f.priority <= priority { 74 continue 75 } 76 delta := uint32(0) 77 deltaShift := uint(0) 78 for opBits := f.opBits; opBits != 0; opBits >>= 16 { 79 n := uint(opBits & 0xFF) 80 off := uint((opBits >> 8) & 0xFF) 81 delta |= (x >> off) & (1<<n - 1) << deltaShift 82 deltaShift += n 83 } 84 op := f.op + Op(delta) 85 86 // Special case: BKPT encodes with condition but cannot have one. 87 if op&^15 == BKPT_EQ && op != BKPT { 88 continue Search 89 } 90 91 var args Args 92 for j, aop := range f.args { 93 if aop == 0 { 94 break 95 } 96 arg := decodeArg(aop, x) 97 if arg == nil { // cannot decode argument 98 continue Search 99 } 100 args[j] = arg 101 } 102 103 decoderCover[i] = true 104 105 inst = Inst{ 106 Op: op, 107 Args: args, 108 Enc: x, 109 Len: 4, 110 } 111 priority = f.priority 112 continue Search 113 } 114 if inst.Op != 0 { 115 return inst, nil 116 } 117 return Inst{}, errUnknown 118 } 119 120 // An instArg describes the encoding of a single argument. 121 // In the names used for arguments, _p_ means +, _m_ means -, 122 // _pm_ means ± (usually keyed by the U bit). 123 // The _W suffix indicates a general addressing mode based on the P and W bits. 124 // The _offset and _postindex suffixes force the given addressing mode. 125 // The rest should be somewhat self-explanatory, at least given 126 // the decodeArg function. 127 type instArg uint8 128 129 const ( 130 _ instArg = iota 131 arg_APSR 132 arg_FPSCR 133 arg_Dn_half 134 arg_R1_0 135 arg_R1_12 136 arg_R2_0 137 arg_R2_12 138 arg_R_0 139 arg_R_12 140 arg_R_12_nzcv 141 arg_R_16 142 arg_R_16_WB 143 arg_R_8 144 arg_R_rotate 145 arg_R_shift_R 146 arg_R_shift_imm 147 arg_SP 148 arg_Sd 149 arg_Sd_Dd 150 arg_Dd_Sd 151 arg_Sm 152 arg_Sm_Dm 153 arg_Sn 154 arg_Sn_Dn 155 arg_const 156 arg_endian 157 arg_fbits 158 arg_fp_0 159 arg_imm24 160 arg_imm5 161 arg_imm5_32 162 arg_imm5_nz 163 arg_imm_12at8_4at0 164 arg_imm_4at16_12at0 165 arg_imm_vfp 166 arg_label24 167 arg_label24H 168 arg_label_m_12 169 arg_label_p_12 170 arg_label_pm_12 171 arg_label_pm_4_4 172 arg_lsb_width 173 arg_mem_R 174 arg_mem_R_pm_R_W 175 arg_mem_R_pm_R_postindex 176 arg_mem_R_pm_R_shift_imm_W 177 arg_mem_R_pm_R_shift_imm_offset 178 arg_mem_R_pm_R_shift_imm_postindex 179 arg_mem_R_pm_imm12_W 180 arg_mem_R_pm_imm12_offset 181 arg_mem_R_pm_imm12_postindex 182 arg_mem_R_pm_imm8_W 183 arg_mem_R_pm_imm8_postindex 184 arg_mem_R_pm_imm8at0_offset 185 arg_option 186 arg_registers 187 arg_registers1 188 arg_registers2 189 arg_satimm4 190 arg_satimm5 191 arg_satimm4m1 192 arg_satimm5m1 193 arg_widthm1 194 ) 195 196 // decodeArg decodes the arg described by aop from the instruction bits x. 197 // It returns nil if x cannot be decoded according to aop. 198 func decodeArg(aop instArg, x uint32) Arg { 199 switch aop { 200 default: 201 return nil 202 203 case arg_APSR: 204 return APSR 205 case arg_FPSCR: 206 return FPSCR 207 208 case arg_R_0: 209 return Reg(x & (1<<4 - 1)) 210 case arg_R_8: 211 return Reg((x >> 8) & (1<<4 - 1)) 212 case arg_R_12: 213 return Reg((x >> 12) & (1<<4 - 1)) 214 case arg_R_16: 215 return Reg((x >> 16) & (1<<4 - 1)) 216 217 case arg_R_12_nzcv: 218 r := Reg((x >> 12) & (1<<4 - 1)) 219 if r == R15 { 220 return APSR_nzcv 221 } 222 return r 223 224 case arg_R_16_WB: 225 mode := AddrLDM 226 if (x>>21)&1 != 0 { 227 mode = AddrLDM_WB 228 } 229 return Mem{Base: Reg((x >> 16) & (1<<4 - 1)), Mode: mode} 230 231 case arg_R_rotate: 232 Rm := Reg(x & (1<<4 - 1)) 233 typ, count := decodeShift(x) 234 // ROR #0 here means ROR #0, but decodeShift rewrites to RRX #1. 235 if typ == RotateRightExt { 236 return Reg(Rm) 237 } 238 return RegShift{Rm, typ, uint8(count)} 239 240 case arg_R_shift_R: 241 Rm := Reg(x & (1<<4 - 1)) 242 Rs := Reg((x >> 8) & (1<<4 - 1)) 243 typ := Shift((x >> 5) & (1<<2 - 1)) 244 return RegShiftReg{Rm, typ, Rs} 245 246 case arg_R_shift_imm: 247 Rm := Reg(x & (1<<4 - 1)) 248 typ, count := decodeShift(x) 249 if typ == ShiftLeft && count == 0 { 250 return Reg(Rm) 251 } 252 return RegShift{Rm, typ, uint8(count)} 253 254 case arg_R1_0: 255 return Reg((x & (1<<4 - 1))) 256 case arg_R1_12: 257 return Reg(((x >> 12) & (1<<4 - 1))) 258 case arg_R2_0: 259 return Reg((x & (1<<4 - 1)) | 1) 260 case arg_R2_12: 261 return Reg(((x >> 12) & (1<<4 - 1)) | 1) 262 263 case arg_SP: 264 return SP 265 266 case arg_Sd_Dd: 267 v := (x >> 12) & (1<<4 - 1) 268 vx := (x >> 22) & 1 269 sz := (x >> 8) & 1 270 if sz != 0 { 271 return D0 + Reg(vx<<4+v) 272 } else { 273 return S0 + Reg(v<<1+vx) 274 } 275 276 case arg_Dd_Sd: 277 return decodeArg(arg_Sd_Dd, x^(1<<8)) 278 279 case arg_Sd: 280 v := (x >> 12) & (1<<4 - 1) 281 vx := (x >> 22) & 1 282 return S0 + Reg(v<<1+vx) 283 284 case arg_Sm_Dm: 285 v := (x >> 0) & (1<<4 - 1) 286 vx := (x >> 5) & 1 287 sz := (x >> 8) & 1 288 if sz != 0 { 289 return D0 + Reg(vx<<4+v) 290 } else { 291 return S0 + Reg(v<<1+vx) 292 } 293 294 case arg_Sm: 295 v := (x >> 0) & (1<<4 - 1) 296 vx := (x >> 5) & 1 297 return S0 + Reg(v<<1+vx) 298 299 case arg_Dn_half: 300 v := (x >> 16) & (1<<4 - 1) 301 vx := (x >> 7) & 1 302 return RegX{D0 + Reg(vx<<4+v), int((x >> 21) & 1)} 303 304 case arg_Sn_Dn: 305 v := (x >> 16) & (1<<4 - 1) 306 vx := (x >> 7) & 1 307 sz := (x >> 8) & 1 308 if sz != 0 { 309 return D0 + Reg(vx<<4+v) 310 } else { 311 return S0 + Reg(v<<1+vx) 312 } 313 314 case arg_Sn: 315 v := (x >> 16) & (1<<4 - 1) 316 vx := (x >> 7) & 1 317 return S0 + Reg(v<<1+vx) 318 319 case arg_const: 320 v := x & (1<<8 - 1) 321 rot := (x >> 8) & (1<<4 - 1) * 2 322 if rot > 0 && v&3 == 0 { 323 // could rotate less 324 return ImmAlt{uint8(v), uint8(rot)} 325 } 326 if rot >= 24 && ((v<<(32-rot))&0xFF)>>(32-rot) == v { 327 // could wrap around to rot==0. 328 return ImmAlt{uint8(v), uint8(rot)} 329 } 330 return Imm(v>>rot | v<<(32-rot)) 331 332 case arg_endian: 333 return Endian((x >> 9) & 1) 334 335 case arg_fbits: 336 return Imm((16 << ((x >> 7) & 1)) - ((x&(1<<4-1))<<1 | (x>>5)&1)) 337 338 case arg_fp_0: 339 return Imm(0) 340 341 case arg_imm24: 342 return Imm(x & (1<<24 - 1)) 343 344 case arg_imm5: 345 return Imm((x >> 7) & (1<<5 - 1)) 346 347 case arg_imm5_32: 348 x = (x >> 7) & (1<<5 - 1) 349 if x == 0 { 350 x = 32 351 } 352 return Imm(x) 353 354 case arg_imm5_nz: 355 x = (x >> 7) & (1<<5 - 1) 356 if x == 0 { 357 return nil 358 } 359 return Imm(x) 360 361 case arg_imm_4at16_12at0: 362 return Imm((x>>16)&(1<<4-1)<<12 | x&(1<<12-1)) 363 364 case arg_imm_12at8_4at0: 365 return Imm((x>>8)&(1<<12-1)<<4 | x&(1<<4-1)) 366 367 case arg_imm_vfp: 368 x = (x>>16)&(1<<4-1)<<4 | x&(1<<4-1) 369 return Imm(x) 370 371 case arg_label24: 372 imm := (x & (1<<24 - 1)) << 2 373 return PCRel(int32(imm<<6) >> 6) 374 375 case arg_label24H: 376 h := (x >> 24) & 1 377 imm := (x&(1<<24-1))<<2 | h<<1 378 return PCRel(int32(imm<<6) >> 6) 379 380 case arg_label_m_12: 381 d := int32(x & (1<<12 - 1)) 382 return Mem{Base: PC, Mode: AddrOffset, Offset: int16(-d)} 383 384 case arg_label_p_12: 385 d := int32(x & (1<<12 - 1)) 386 return Mem{Base: PC, Mode: AddrOffset, Offset: int16(d)} 387 388 case arg_label_pm_12: 389 d := int32(x & (1<<12 - 1)) 390 u := (x >> 23) & 1 391 if u == 0 { 392 d = -d 393 } 394 return Mem{Base: PC, Mode: AddrOffset, Offset: int16(d)} 395 396 case arg_label_pm_4_4: 397 d := int32((x>>8)&(1<<4-1)<<4 | x&(1<<4-1)) 398 u := (x >> 23) & 1 399 if u == 0 { 400 d = -d 401 } 402 return PCRel(d) 403 404 case arg_lsb_width: 405 lsb := (x >> 7) & (1<<5 - 1) 406 msb := (x >> 16) & (1<<5 - 1) 407 if msb < lsb || msb >= 32 { 408 return nil 409 } 410 return Imm(msb + 1 - lsb) 411 412 case arg_mem_R: 413 Rn := Reg((x >> 16) & (1<<4 - 1)) 414 return Mem{Base: Rn, Mode: AddrOffset} 415 416 case arg_mem_R_pm_R_postindex: 417 // Treat [<Rn>],+/-<Rm> like [<Rn>,+/-<Rm>{,<shift>}]{!} 418 // by forcing shift bits to <<0 and P=0, W=0 (postindex=true). 419 return decodeArg(arg_mem_R_pm_R_shift_imm_W, x&^((1<<7-1)<<5|1<<24|1<<21)) 420 421 case arg_mem_R_pm_R_W: 422 // Treat [<Rn>,+/-<Rm>]{!} like [<Rn>,+/-<Rm>{,<shift>}]{!} 423 // by forcing shift bits to <<0. 424 return decodeArg(arg_mem_R_pm_R_shift_imm_W, x&^((1<<7-1)<<5)) 425 426 case arg_mem_R_pm_R_shift_imm_offset: 427 // Treat [<Rn>],+/-<Rm>{,<shift>} like [<Rn>,+/-<Rm>{,<shift>}]{!} 428 // by forcing P=1, W=0 (index=false, wback=false). 429 return decodeArg(arg_mem_R_pm_R_shift_imm_W, x&^(1<<21)|1<<24) 430 431 case arg_mem_R_pm_R_shift_imm_postindex: 432 // Treat [<Rn>],+/-<Rm>{,<shift>} like [<Rn>,+/-<Rm>{,<shift>}]{!} 433 // by forcing P=0, W=0 (postindex=true). 434 return decodeArg(arg_mem_R_pm_R_shift_imm_W, x&^(1<<24|1<<21)) 435 436 case arg_mem_R_pm_R_shift_imm_W: 437 Rn := Reg((x >> 16) & (1<<4 - 1)) 438 Rm := Reg(x & (1<<4 - 1)) 439 typ, count := decodeShift(x) 440 u := (x >> 23) & 1 441 w := (x >> 21) & 1 442 p := (x >> 24) & 1 443 if p == 0 && w == 1 { 444 return nil 445 } 446 sign := int8(+1) 447 if u == 0 { 448 sign = -1 449 } 450 mode := AddrMode(uint8(p<<1) | uint8(w^1)) 451 return Mem{Base: Rn, Mode: mode, Sign: sign, Index: Rm, Shift: typ, Count: count} 452 453 case arg_mem_R_pm_imm12_offset: 454 // Treat [<Rn>,#+/-<imm12>] like [<Rn>{,#+/-<imm12>}]{!} 455 // by forcing P=1, W=0 (index=false, wback=false). 456 return decodeArg(arg_mem_R_pm_imm12_W, x&^(1<<21)|1<<24) 457 458 case arg_mem_R_pm_imm12_postindex: 459 // Treat [<Rn>],#+/-<imm12> like [<Rn>{,#+/-<imm12>}]{!} 460 // by forcing P=0, W=0 (postindex=true). 461 return decodeArg(arg_mem_R_pm_imm12_W, x&^(1<<24|1<<21)) 462 463 case arg_mem_R_pm_imm12_W: 464 Rn := Reg((x >> 16) & (1<<4 - 1)) 465 u := (x >> 23) & 1 466 w := (x >> 21) & 1 467 p := (x >> 24) & 1 468 if p == 0 && w == 1 { 469 return nil 470 } 471 sign := int8(+1) 472 if u == 0 { 473 sign = -1 474 } 475 imm := int16(x & (1<<12 - 1)) 476 mode := AddrMode(uint8(p<<1) | uint8(w^1)) 477 return Mem{Base: Rn, Mode: mode, Offset: int16(sign) * imm} 478 479 case arg_mem_R_pm_imm8_postindex: 480 // Treat [<Rn>],#+/-<imm8> like [<Rn>{,#+/-<imm8>}]{!} 481 // by forcing P=0, W=0 (postindex=true). 482 return decodeArg(arg_mem_R_pm_imm8_W, x&^(1<<24|1<<21)) 483 484 case arg_mem_R_pm_imm8_W: 485 Rn := Reg((x >> 16) & (1<<4 - 1)) 486 u := (x >> 23) & 1 487 w := (x >> 21) & 1 488 p := (x >> 24) & 1 489 if p == 0 && w == 1 { 490 return nil 491 } 492 sign := int8(+1) 493 if u == 0 { 494 sign = -1 495 } 496 imm := int16((x>>8)&(1<<4-1)<<4 | x&(1<<4-1)) 497 mode := AddrMode(uint8(p<<1) | uint8(w^1)) 498 return Mem{Base: Rn, Mode: mode, Offset: int16(sign) * imm} 499 500 case arg_mem_R_pm_imm8at0_offset: 501 Rn := Reg((x >> 16) & (1<<4 - 1)) 502 u := (x >> 23) & 1 503 sign := int8(+1) 504 if u == 0 { 505 sign = -1 506 } 507 imm := int16(x&(1<<8-1)) << 2 508 return Mem{Base: Rn, Mode: AddrOffset, Offset: int16(sign) * imm} 509 510 case arg_option: 511 return Imm(x & (1<<4 - 1)) 512 513 case arg_registers: 514 return RegList(x & (1<<16 - 1)) 515 516 case arg_registers2: 517 x &= 1<<16 - 1 518 n := 0 519 for i := 0; i < 16; i++ { 520 if x>>uint(i)&1 != 0 { 521 n++ 522 } 523 } 524 if n < 2 { 525 return nil 526 } 527 return RegList(x) 528 529 case arg_registers1: 530 Rt := (x >> 12) & (1<<4 - 1) 531 return RegList(1 << Rt) 532 533 case arg_satimm4: 534 return Imm((x >> 16) & (1<<4 - 1)) 535 536 case arg_satimm5: 537 return Imm((x >> 16) & (1<<5 - 1)) 538 539 case arg_satimm4m1: 540 return Imm((x>>16)&(1<<4-1) + 1) 541 542 case arg_satimm5m1: 543 return Imm((x>>16)&(1<<5-1) + 1) 544 545 case arg_widthm1: 546 return Imm((x>>16)&(1<<5-1) + 1) 547 548 } 549 } 550 551 // decodeShift decodes the shift-by-immediate encoded in x. 552 func decodeShift(x uint32) (Shift, uint8) { 553 count := (x >> 7) & (1<<5 - 1) 554 typ := Shift((x >> 5) & (1<<2 - 1)) 555 switch typ { 556 case ShiftRight, ShiftRightSigned: 557 if count == 0 { 558 count = 32 559 } 560 case RotateRight: 561 if count == 0 { 562 typ = RotateRightExt 563 count = 1 564 } 565 } 566 return typ, uint8(count) 567 }