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  }