...

Source file src/pkg/cmd/vendor/golang.org/x/arch/arm/armasm/decode.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 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	}
   568	

View as plain text