Home | History | Annotate | Download | only in armasm
      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