mirror of
https://github.com/cwinfo/matterbridge.git
synced 2025-06-27 04:09:24 +00:00
Add gops agent
This commit is contained in:
27
vendor/golang.org/x/arch/arm/armasm/LICENSE
generated
vendored
Normal file
27
vendor/golang.org/x/arch/arm/armasm/LICENSE
generated
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
Copyright (c) 2015 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
567
vendor/golang.org/x/arch/arm/armasm/decode.go
generated
vendored
Normal file
567
vendor/golang.org/x/arch/arm/armasm/decode.go
generated
vendored
Normal file
@ -0,0 +1,567 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package armasm
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// An instFormat describes the format of an instruction encoding.
|
||||
// An instruction with 32-bit value x matches the format if x&mask == value
|
||||
// and the condition matches.
|
||||
// The condition matches if x>>28 == 0xF && value>>28==0xF
|
||||
// or if x>>28 != 0xF and value>>28 == 0.
|
||||
// If x matches the format, then the rest of the fields describe how to interpret x.
|
||||
// The opBits describe bits that should be extracted from x and added to the opcode.
|
||||
// For example opBits = 0x1234 means that the value
|
||||
// (2 bits at offset 1) followed by (4 bits at offset 3)
|
||||
// should be added to op.
|
||||
// Finally the args describe how to decode the instruction arguments.
|
||||
// args is stored as a fixed-size array; if there are fewer than len(args) arguments,
|
||||
// args[i] == 0 marks the end of the argument list.
|
||||
type instFormat struct {
|
||||
mask uint32
|
||||
value uint32
|
||||
priority int8
|
||||
op Op
|
||||
opBits uint64
|
||||
args instArgs
|
||||
}
|
||||
|
||||
type instArgs [4]instArg
|
||||
|
||||
var (
|
||||
errMode = fmt.Errorf("unsupported execution mode")
|
||||
errShort = fmt.Errorf("truncated instruction")
|
||||
errUnknown = fmt.Errorf("unknown instruction")
|
||||
)
|
||||
|
||||
var decoderCover []bool
|
||||
|
||||
// Decode decodes the leading bytes in src as a single instruction.
|
||||
func Decode(src []byte, mode Mode) (inst Inst, err error) {
|
||||
if mode != ModeARM {
|
||||
return Inst{}, errMode
|
||||
}
|
||||
if len(src) < 4 {
|
||||
return Inst{}, errShort
|
||||
}
|
||||
|
||||
if decoderCover == nil {
|
||||
decoderCover = make([]bool, len(instFormats))
|
||||
}
|
||||
|
||||
x := binary.LittleEndian.Uint32(src)
|
||||
|
||||
// The instFormat table contains both conditional and unconditional instructions.
|
||||
// Considering only the top 4 bits, the conditional instructions use mask=0, value=0,
|
||||
// while the unconditional instructions use mask=f, value=f.
|
||||
// Prepare a version of x with the condition cleared to 0 in conditional instructions
|
||||
// and then assume mask=f during matching.
|
||||
const condMask = 0xf0000000
|
||||
xNoCond := x
|
||||
if x&condMask != condMask {
|
||||
xNoCond &^= condMask
|
||||
}
|
||||
var priority int8
|
||||
Search:
|
||||
for i := range instFormats {
|
||||
f := &instFormats[i]
|
||||
if xNoCond&(f.mask|condMask) != f.value || f.priority <= priority {
|
||||
continue
|
||||
}
|
||||
delta := uint32(0)
|
||||
deltaShift := uint(0)
|
||||
for opBits := f.opBits; opBits != 0; opBits >>= 16 {
|
||||
n := uint(opBits & 0xFF)
|
||||
off := uint((opBits >> 8) & 0xFF)
|
||||
delta |= (x >> off) & (1<<n - 1) << deltaShift
|
||||
deltaShift += n
|
||||
}
|
||||
op := f.op + Op(delta)
|
||||
|
||||
// Special case: BKPT encodes with condition but cannot have one.
|
||||
if op&^15 == BKPT_EQ && op != BKPT {
|
||||
continue Search
|
||||
}
|
||||
|
||||
var args Args
|
||||
for j, aop := range f.args {
|
||||
if aop == 0 {
|
||||
break
|
||||
}
|
||||
arg := decodeArg(aop, x)
|
||||
if arg == nil { // cannot decode argument
|
||||
continue Search
|
||||
}
|
||||
args[j] = arg
|
||||
}
|
||||
|
||||
decoderCover[i] = true
|
||||
|
||||
inst = Inst{
|
||||
Op: op,
|
||||
Args: args,
|
||||
Enc: x,
|
||||
Len: 4,
|
||||
}
|
||||
priority = f.priority
|
||||
continue Search
|
||||
}
|
||||
if inst.Op != 0 {
|
||||
return inst, nil
|
||||
}
|
||||
return Inst{}, errUnknown
|
||||
}
|
||||
|
||||
// An instArg describes the encoding of a single argument.
|
||||
// In the names used for arguments, _p_ means +, _m_ means -,
|
||||
// _pm_ means ± (usually keyed by the U bit).
|
||||
// The _W suffix indicates a general addressing mode based on the P and W bits.
|
||||
// The _offset and _postindex suffixes force the given addressing mode.
|
||||
// The rest should be somewhat self-explanatory, at least given
|
||||
// the decodeArg function.
|
||||
type instArg uint8
|
||||
|
||||
const (
|
||||
_ instArg = iota
|
||||
arg_APSR
|
||||
arg_FPSCR
|
||||
arg_Dn_half
|
||||
arg_R1_0
|
||||
arg_R1_12
|
||||
arg_R2_0
|
||||
arg_R2_12
|
||||
arg_R_0
|
||||
arg_R_12
|
||||
arg_R_12_nzcv
|
||||
arg_R_16
|
||||
arg_R_16_WB
|
||||
arg_R_8
|
||||
arg_R_rotate
|
||||
arg_R_shift_R
|
||||
arg_R_shift_imm
|
||||
arg_SP
|
||||
arg_Sd
|
||||
arg_Sd_Dd
|
||||
arg_Dd_Sd
|
||||
arg_Sm
|
||||
arg_Sm_Dm
|
||||
arg_Sn
|
||||
arg_Sn_Dn
|
||||
arg_const
|
||||
arg_endian
|
||||
arg_fbits
|
||||
arg_fp_0
|
||||
arg_imm24
|
||||
arg_imm5
|
||||
arg_imm5_32
|
||||
arg_imm5_nz
|
||||
arg_imm_12at8_4at0
|
||||
arg_imm_4at16_12at0
|
||||
arg_imm_vfp
|
||||
arg_label24
|
||||
arg_label24H
|
||||
arg_label_m_12
|
||||
arg_label_p_12
|
||||
arg_label_pm_12
|
||||
arg_label_pm_4_4
|
||||
arg_lsb_width
|
||||
arg_mem_R
|
||||
arg_mem_R_pm_R_W
|
||||
arg_mem_R_pm_R_postindex
|
||||
arg_mem_R_pm_R_shift_imm_W
|
||||
arg_mem_R_pm_R_shift_imm_offset
|
||||
arg_mem_R_pm_R_shift_imm_postindex
|
||||
arg_mem_R_pm_imm12_W
|
||||
arg_mem_R_pm_imm12_offset
|
||||
arg_mem_R_pm_imm12_postindex
|
||||
arg_mem_R_pm_imm8_W
|
||||
arg_mem_R_pm_imm8_postindex
|
||||
arg_mem_R_pm_imm8at0_offset
|
||||
arg_option
|
||||
arg_registers
|
||||
arg_registers1
|
||||
arg_registers2
|
||||
arg_satimm4
|
||||
arg_satimm5
|
||||
arg_satimm4m1
|
||||
arg_satimm5m1
|
||||
arg_widthm1
|
||||
)
|
||||
|
||||
// decodeArg decodes the arg described by aop from the instruction bits x.
|
||||
// It returns nil if x cannot be decoded according to aop.
|
||||
func decodeArg(aop instArg, x uint32) Arg {
|
||||
switch aop {
|
||||
default:
|
||||
return nil
|
||||
|
||||
case arg_APSR:
|
||||
return APSR
|
||||
case arg_FPSCR:
|
||||
return FPSCR
|
||||
|
||||
case arg_R_0:
|
||||
return Reg(x & (1<<4 - 1))
|
||||
case arg_R_8:
|
||||
return Reg((x >> 8) & (1<<4 - 1))
|
||||
case arg_R_12:
|
||||
return Reg((x >> 12) & (1<<4 - 1))
|
||||
case arg_R_16:
|
||||
return Reg((x >> 16) & (1<<4 - 1))
|
||||
|
||||
case arg_R_12_nzcv:
|
||||
r := Reg((x >> 12) & (1<<4 - 1))
|
||||
if r == R15 {
|
||||
return APSR_nzcv
|
||||
}
|
||||
return r
|
||||
|
||||
case arg_R_16_WB:
|
||||
mode := AddrLDM
|
||||
if (x>>21)&1 != 0 {
|
||||
mode = AddrLDM_WB
|
||||
}
|
||||
return Mem{Base: Reg((x >> 16) & (1<<4 - 1)), Mode: mode}
|
||||
|
||||
case arg_R_rotate:
|
||||
Rm := Reg(x & (1<<4 - 1))
|
||||
typ, count := decodeShift(x)
|
||||
// ROR #0 here means ROR #0, but decodeShift rewrites to RRX #1.
|
||||
if typ == RotateRightExt {
|
||||
return Reg(Rm)
|
||||
}
|
||||
return RegShift{Rm, typ, uint8(count)}
|
||||
|
||||
case arg_R_shift_R:
|
||||
Rm := Reg(x & (1<<4 - 1))
|
||||
Rs := Reg((x >> 8) & (1<<4 - 1))
|
||||
typ := Shift((x >> 5) & (1<<2 - 1))
|
||||
return RegShiftReg{Rm, typ, Rs}
|
||||
|
||||
case arg_R_shift_imm:
|
||||
Rm := Reg(x & (1<<4 - 1))
|
||||
typ, count := decodeShift(x)
|
||||
if typ == ShiftLeft && count == 0 {
|
||||
return Reg(Rm)
|
||||
}
|
||||
return RegShift{Rm, typ, uint8(count)}
|
||||
|
||||
case arg_R1_0:
|
||||
return Reg((x & (1<<4 - 1)))
|
||||
case arg_R1_12:
|
||||
return Reg(((x >> 12) & (1<<4 - 1)))
|
||||
case arg_R2_0:
|
||||
return Reg((x & (1<<4 - 1)) | 1)
|
||||
case arg_R2_12:
|
||||
return Reg(((x >> 12) & (1<<4 - 1)) | 1)
|
||||
|
||||
case arg_SP:
|
||||
return SP
|
||||
|
||||
case arg_Sd_Dd:
|
||||
v := (x >> 12) & (1<<4 - 1)
|
||||
vx := (x >> 22) & 1
|
||||
sz := (x >> 8) & 1
|
||||
if sz != 0 {
|
||||
return D0 + Reg(vx<<4+v)
|
||||
} else {
|
||||
return S0 + Reg(v<<1+vx)
|
||||
}
|
||||
|
||||
case arg_Dd_Sd:
|
||||
return decodeArg(arg_Sd_Dd, x^(1<<8))
|
||||
|
||||
case arg_Sd:
|
||||
v := (x >> 12) & (1<<4 - 1)
|
||||
vx := (x >> 22) & 1
|
||||
return S0 + Reg(v<<1+vx)
|
||||
|
||||
case arg_Sm_Dm:
|
||||
v := (x >> 0) & (1<<4 - 1)
|
||||
vx := (x >> 5) & 1
|
||||
sz := (x >> 8) & 1
|
||||
if sz != 0 {
|
||||
return D0 + Reg(vx<<4+v)
|
||||
} else {
|
||||
return S0 + Reg(v<<1+vx)
|
||||
}
|
||||
|
||||
case arg_Sm:
|
||||
v := (x >> 0) & (1<<4 - 1)
|
||||
vx := (x >> 5) & 1
|
||||
return S0 + Reg(v<<1+vx)
|
||||
|
||||
case arg_Dn_half:
|
||||
v := (x >> 16) & (1<<4 - 1)
|
||||
vx := (x >> 7) & 1
|
||||
return RegX{D0 + Reg(vx<<4+v), int((x >> 21) & 1)}
|
||||
|
||||
case arg_Sn_Dn:
|
||||
v := (x >> 16) & (1<<4 - 1)
|
||||
vx := (x >> 7) & 1
|
||||
sz := (x >> 8) & 1
|
||||
if sz != 0 {
|
||||
return D0 + Reg(vx<<4+v)
|
||||
} else {
|
||||
return S0 + Reg(v<<1+vx)
|
||||
}
|
||||
|
||||
case arg_Sn:
|
||||
v := (x >> 16) & (1<<4 - 1)
|
||||
vx := (x >> 7) & 1
|
||||
return S0 + Reg(v<<1+vx)
|
||||
|
||||
case arg_const:
|
||||
v := x & (1<<8 - 1)
|
||||
rot := (x >> 8) & (1<<4 - 1) * 2
|
||||
if rot > 0 && v&3 == 0 {
|
||||
// could rotate less
|
||||
return ImmAlt{uint8(v), uint8(rot)}
|
||||
}
|
||||
if rot >= 24 && ((v<<(32-rot))&0xFF)>>(32-rot) == v {
|
||||
// could wrap around to rot==0.
|
||||
return ImmAlt{uint8(v), uint8(rot)}
|
||||
}
|
||||
return Imm(v>>rot | v<<(32-rot))
|
||||
|
||||
case arg_endian:
|
||||
return Endian((x >> 9) & 1)
|
||||
|
||||
case arg_fbits:
|
||||
return Imm((16 << ((x >> 7) & 1)) - ((x&(1<<4-1))<<1 | (x>>5)&1))
|
||||
|
||||
case arg_fp_0:
|
||||
return Imm(0)
|
||||
|
||||
case arg_imm24:
|
||||
return Imm(x & (1<<24 - 1))
|
||||
|
||||
case arg_imm5:
|
||||
return Imm((x >> 7) & (1<<5 - 1))
|
||||
|
||||
case arg_imm5_32:
|
||||
x = (x >> 7) & (1<<5 - 1)
|
||||
if x == 0 {
|
||||
x = 32
|
||||
}
|
||||
return Imm(x)
|
||||
|
||||
case arg_imm5_nz:
|
||||
x = (x >> 7) & (1<<5 - 1)
|
||||
if x == 0 {
|
||||
return nil
|
||||
}
|
||||
return Imm(x)
|
||||
|
||||
case arg_imm_4at16_12at0:
|
||||
return Imm((x>>16)&(1<<4-1)<<12 | x&(1<<12-1))
|
||||
|
||||
case arg_imm_12at8_4at0:
|
||||
return Imm((x>>8)&(1<<12-1)<<4 | x&(1<<4-1))
|
||||
|
||||
case arg_imm_vfp:
|
||||
x = (x>>16)&(1<<4-1)<<4 | x&(1<<4-1)
|
||||
return Imm(x)
|
||||
|
||||
case arg_label24:
|
||||
imm := (x & (1<<24 - 1)) << 2
|
||||
return PCRel(int32(imm<<6) >> 6)
|
||||
|
||||
case arg_label24H:
|
||||
h := (x >> 24) & 1
|
||||
imm := (x&(1<<24-1))<<2 | h<<1
|
||||
return PCRel(int32(imm<<6) >> 6)
|
||||
|
||||
case arg_label_m_12:
|
||||
d := int32(x & (1<<12 - 1))
|
||||
return Mem{Base: PC, Mode: AddrOffset, Offset: int16(-d)}
|
||||
|
||||
case arg_label_p_12:
|
||||
d := int32(x & (1<<12 - 1))
|
||||
return Mem{Base: PC, Mode: AddrOffset, Offset: int16(d)}
|
||||
|
||||
case arg_label_pm_12:
|
||||
d := int32(x & (1<<12 - 1))
|
||||
u := (x >> 23) & 1
|
||||
if u == 0 {
|
||||
d = -d
|
||||
}
|
||||
return Mem{Base: PC, Mode: AddrOffset, Offset: int16(d)}
|
||||
|
||||
case arg_label_pm_4_4:
|
||||
d := int32((x>>8)&(1<<4-1)<<4 | x&(1<<4-1))
|
||||
u := (x >> 23) & 1
|
||||
if u == 0 {
|
||||
d = -d
|
||||
}
|
||||
return PCRel(d)
|
||||
|
||||
case arg_lsb_width:
|
||||
lsb := (x >> 7) & (1<<5 - 1)
|
||||
msb := (x >> 16) & (1<<5 - 1)
|
||||
if msb < lsb || msb >= 32 {
|
||||
return nil
|
||||
}
|
||||
return Imm(msb + 1 - lsb)
|
||||
|
||||
case arg_mem_R:
|
||||
Rn := Reg((x >> 16) & (1<<4 - 1))
|
||||
return Mem{Base: Rn, Mode: AddrOffset}
|
||||
|
||||
case arg_mem_R_pm_R_postindex:
|
||||
// Treat [<Rn>],+/-<Rm> like [<Rn>,+/-<Rm>{,<shift>}]{!}
|
||||
// by forcing shift bits to <<0 and P=0, W=0 (postindex=true).
|
||||
return decodeArg(arg_mem_R_pm_R_shift_imm_W, x&^((1<<7-1)<<5|1<<24|1<<21))
|
||||
|
||||
case arg_mem_R_pm_R_W:
|
||||
// Treat [<Rn>,+/-<Rm>]{!} like [<Rn>,+/-<Rm>{,<shift>}]{!}
|
||||
// by forcing shift bits to <<0.
|
||||
return decodeArg(arg_mem_R_pm_R_shift_imm_W, x&^((1<<7-1)<<5))
|
||||
|
||||
case arg_mem_R_pm_R_shift_imm_offset:
|
||||
// Treat [<Rn>],+/-<Rm>{,<shift>} like [<Rn>,+/-<Rm>{,<shift>}]{!}
|
||||
// by forcing P=1, W=0 (index=false, wback=false).
|
||||
return decodeArg(arg_mem_R_pm_R_shift_imm_W, x&^(1<<21)|1<<24)
|
||||
|
||||
case arg_mem_R_pm_R_shift_imm_postindex:
|
||||
// Treat [<Rn>],+/-<Rm>{,<shift>} like [<Rn>,+/-<Rm>{,<shift>}]{!}
|
||||
// by forcing P=0, W=0 (postindex=true).
|
||||
return decodeArg(arg_mem_R_pm_R_shift_imm_W, x&^(1<<24|1<<21))
|
||||
|
||||
case arg_mem_R_pm_R_shift_imm_W:
|
||||
Rn := Reg((x >> 16) & (1<<4 - 1))
|
||||
Rm := Reg(x & (1<<4 - 1))
|
||||
typ, count := decodeShift(x)
|
||||
u := (x >> 23) & 1
|
||||
w := (x >> 21) & 1
|
||||
p := (x >> 24) & 1
|
||||
if p == 0 && w == 1 {
|
||||
return nil
|
||||
}
|
||||
sign := int8(+1)
|
||||
if u == 0 {
|
||||
sign = -1
|
||||
}
|
||||
mode := AddrMode(uint8(p<<1) | uint8(w^1))
|
||||
return Mem{Base: Rn, Mode: mode, Sign: sign, Index: Rm, Shift: typ, Count: count}
|
||||
|
||||
case arg_mem_R_pm_imm12_offset:
|
||||
// Treat [<Rn>,#+/-<imm12>] like [<Rn>{,#+/-<imm12>}]{!}
|
||||
// by forcing P=1, W=0 (index=false, wback=false).
|
||||
return decodeArg(arg_mem_R_pm_imm12_W, x&^(1<<21)|1<<24)
|
||||
|
||||
case arg_mem_R_pm_imm12_postindex:
|
||||
// Treat [<Rn>],#+/-<imm12> like [<Rn>{,#+/-<imm12>}]{!}
|
||||
// by forcing P=0, W=0 (postindex=true).
|
||||
return decodeArg(arg_mem_R_pm_imm12_W, x&^(1<<24|1<<21))
|
||||
|
||||
case arg_mem_R_pm_imm12_W:
|
||||
Rn := Reg((x >> 16) & (1<<4 - 1))
|
||||
u := (x >> 23) & 1
|
||||
w := (x >> 21) & 1
|
||||
p := (x >> 24) & 1
|
||||
if p == 0 && w == 1 {
|
||||
return nil
|
||||
}
|
||||
sign := int8(+1)
|
||||
if u == 0 {
|
||||
sign = -1
|
||||
}
|
||||
imm := int16(x & (1<<12 - 1))
|
||||
mode := AddrMode(uint8(p<<1) | uint8(w^1))
|
||||
return Mem{Base: Rn, Mode: mode, Offset: int16(sign) * imm}
|
||||
|
||||
case arg_mem_R_pm_imm8_postindex:
|
||||
// Treat [<Rn>],#+/-<imm8> like [<Rn>{,#+/-<imm8>}]{!}
|
||||
// by forcing P=0, W=0 (postindex=true).
|
||||
return decodeArg(arg_mem_R_pm_imm8_W, x&^(1<<24|1<<21))
|
||||
|
||||
case arg_mem_R_pm_imm8_W:
|
||||
Rn := Reg((x >> 16) & (1<<4 - 1))
|
||||
u := (x >> 23) & 1
|
||||
w := (x >> 21) & 1
|
||||
p := (x >> 24) & 1
|
||||
if p == 0 && w == 1 {
|
||||
return nil
|
||||
}
|
||||
sign := int8(+1)
|
||||
if u == 0 {
|
||||
sign = -1
|
||||
}
|
||||
imm := int16((x>>8)&(1<<4-1)<<4 | x&(1<<4-1))
|
||||
mode := AddrMode(uint8(p<<1) | uint8(w^1))
|
||||
return Mem{Base: Rn, Mode: mode, Offset: int16(sign) * imm}
|
||||
|
||||
case arg_mem_R_pm_imm8at0_offset:
|
||||
Rn := Reg((x >> 16) & (1<<4 - 1))
|
||||
u := (x >> 23) & 1
|
||||
sign := int8(+1)
|
||||
if u == 0 {
|
||||
sign = -1
|
||||
}
|
||||
imm := int16(x&(1<<8-1)) << 2
|
||||
return Mem{Base: Rn, Mode: AddrOffset, Offset: int16(sign) * imm}
|
||||
|
||||
case arg_option:
|
||||
return Imm(x & (1<<4 - 1))
|
||||
|
||||
case arg_registers:
|
||||
return RegList(x & (1<<16 - 1))
|
||||
|
||||
case arg_registers2:
|
||||
x &= 1<<16 - 1
|
||||
n := 0
|
||||
for i := 0; i < 16; i++ {
|
||||
if x>>uint(i)&1 != 0 {
|
||||
n++
|
||||
}
|
||||
}
|
||||
if n < 2 {
|
||||
return nil
|
||||
}
|
||||
return RegList(x)
|
||||
|
||||
case arg_registers1:
|
||||
Rt := (x >> 12) & (1<<4 - 1)
|
||||
return RegList(1 << Rt)
|
||||
|
||||
case arg_satimm4:
|
||||
return Imm((x >> 16) & (1<<4 - 1))
|
||||
|
||||
case arg_satimm5:
|
||||
return Imm((x >> 16) & (1<<5 - 1))
|
||||
|
||||
case arg_satimm4m1:
|
||||
return Imm((x>>16)&(1<<4-1) + 1)
|
||||
|
||||
case arg_satimm5m1:
|
||||
return Imm((x>>16)&(1<<5-1) + 1)
|
||||
|
||||
case arg_widthm1:
|
||||
return Imm((x>>16)&(1<<5-1) + 1)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// decodeShift decodes the shift-by-immediate encoded in x.
|
||||
func decodeShift(x uint32) (Shift, uint8) {
|
||||
count := (x >> 7) & (1<<5 - 1)
|
||||
typ := Shift((x >> 5) & (1<<2 - 1))
|
||||
switch typ {
|
||||
case ShiftRight, ShiftRightSigned:
|
||||
if count == 0 {
|
||||
count = 32
|
||||
}
|
||||
case RotateRight:
|
||||
if count == 0 {
|
||||
typ = RotateRightExt
|
||||
count = 1
|
||||
}
|
||||
}
|
||||
return typ, uint8(count)
|
||||
}
|
164
vendor/golang.org/x/arch/arm/armasm/gnu.go
generated
vendored
Normal file
164
vendor/golang.org/x/arch/arm/armasm/gnu.go
generated
vendored
Normal file
@ -0,0 +1,164 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package armasm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var saveDot = strings.NewReplacer(
|
||||
".F16", "_dot_F16",
|
||||
".F32", "_dot_F32",
|
||||
".F64", "_dot_F64",
|
||||
".S32", "_dot_S32",
|
||||
".U32", "_dot_U32",
|
||||
".FXS", "_dot_S",
|
||||
".FXU", "_dot_U",
|
||||
".32", "_dot_32",
|
||||
)
|
||||
|
||||
// GNUSyntax returns the GNU assembler syntax for the instruction, as defined by GNU binutils.
|
||||
// This form typically matches the syntax defined in the ARM Reference Manual.
|
||||
func GNUSyntax(inst Inst) string {
|
||||
var buf bytes.Buffer
|
||||
op := inst.Op.String()
|
||||
op = saveDot.Replace(op)
|
||||
op = strings.Replace(op, ".", "", -1)
|
||||
op = strings.Replace(op, "_dot_", ".", -1)
|
||||
op = strings.ToLower(op)
|
||||
buf.WriteString(op)
|
||||
sep := " "
|
||||
for i, arg := range inst.Args {
|
||||
if arg == nil {
|
||||
break
|
||||
}
|
||||
text := gnuArg(&inst, i, arg)
|
||||
if text == "" {
|
||||
continue
|
||||
}
|
||||
buf.WriteString(sep)
|
||||
sep = ", "
|
||||
buf.WriteString(text)
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func gnuArg(inst *Inst, argIndex int, arg Arg) string {
|
||||
switch inst.Op &^ 15 {
|
||||
case LDRD_EQ, LDREXD_EQ, STRD_EQ:
|
||||
if argIndex == 1 {
|
||||
// second argument in consecutive pair not printed
|
||||
return ""
|
||||
}
|
||||
case STREXD_EQ:
|
||||
if argIndex == 2 {
|
||||
// second argument in consecutive pair not printed
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
switch arg := arg.(type) {
|
||||
case Imm:
|
||||
switch inst.Op &^ 15 {
|
||||
case BKPT_EQ:
|
||||
return fmt.Sprintf("%#04x", uint32(arg))
|
||||
case SVC_EQ:
|
||||
return fmt.Sprintf("%#08x", uint32(arg))
|
||||
}
|
||||
return fmt.Sprintf("#%d", int32(arg))
|
||||
|
||||
case ImmAlt:
|
||||
return fmt.Sprintf("#%d, %d", arg.Val, arg.Rot)
|
||||
|
||||
case Mem:
|
||||
R := gnuArg(inst, -1, arg.Base)
|
||||
X := ""
|
||||
if arg.Sign != 0 {
|
||||
X = ""
|
||||
if arg.Sign < 0 {
|
||||
X = "-"
|
||||
}
|
||||
X += gnuArg(inst, -1, arg.Index)
|
||||
if arg.Shift == ShiftLeft && arg.Count == 0 {
|
||||
// nothing
|
||||
} else if arg.Shift == RotateRightExt {
|
||||
X += ", rrx"
|
||||
} else {
|
||||
X += fmt.Sprintf(", %s #%d", strings.ToLower(arg.Shift.String()), arg.Count)
|
||||
}
|
||||
} else {
|
||||
X = fmt.Sprintf("#%d", arg.Offset)
|
||||
}
|
||||
|
||||
switch arg.Mode {
|
||||
case AddrOffset:
|
||||
if X == "#0" {
|
||||
return fmt.Sprintf("[%s]", R)
|
||||
}
|
||||
return fmt.Sprintf("[%s, %s]", R, X)
|
||||
case AddrPreIndex:
|
||||
return fmt.Sprintf("[%s, %s]!", R, X)
|
||||
case AddrPostIndex:
|
||||
return fmt.Sprintf("[%s], %s", R, X)
|
||||
case AddrLDM:
|
||||
if X == "#0" {
|
||||
return R
|
||||
}
|
||||
case AddrLDM_WB:
|
||||
if X == "#0" {
|
||||
return R + "!"
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("[%s Mode(%d) %s]", R, int(arg.Mode), X)
|
||||
|
||||
case PCRel:
|
||||
return fmt.Sprintf(".%+#x", int32(arg)+4)
|
||||
|
||||
case Reg:
|
||||
switch inst.Op &^ 15 {
|
||||
case LDREX_EQ:
|
||||
if argIndex == 0 {
|
||||
return fmt.Sprintf("r%d", int32(arg))
|
||||
}
|
||||
}
|
||||
switch arg {
|
||||
case R10:
|
||||
return "sl"
|
||||
case R11:
|
||||
return "fp"
|
||||
case R12:
|
||||
return "ip"
|
||||
}
|
||||
|
||||
case RegList:
|
||||
var buf bytes.Buffer
|
||||
fmt.Fprintf(&buf, "{")
|
||||
sep := ""
|
||||
for i := 0; i < 16; i++ {
|
||||
if arg&(1<<uint(i)) != 0 {
|
||||
fmt.Fprintf(&buf, "%s%s", sep, gnuArg(inst, -1, Reg(i)))
|
||||
sep = ", "
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(&buf, "}")
|
||||
return buf.String()
|
||||
|
||||
case RegShift:
|
||||
if arg.Shift == ShiftLeft && arg.Count == 0 {
|
||||
return gnuArg(inst, -1, arg.Reg)
|
||||
}
|
||||
if arg.Shift == RotateRightExt {
|
||||
return gnuArg(inst, -1, arg.Reg) + ", rrx"
|
||||
}
|
||||
return fmt.Sprintf("%s, %s #%d", gnuArg(inst, -1, arg.Reg), strings.ToLower(arg.Shift.String()), arg.Count)
|
||||
|
||||
case RegShiftReg:
|
||||
return fmt.Sprintf("%s, %s %s", gnuArg(inst, -1, arg.Reg), strings.ToLower(arg.Shift.String()), gnuArg(inst, -1, arg.RegCount))
|
||||
|
||||
}
|
||||
return strings.ToLower(arg.String())
|
||||
}
|
438
vendor/golang.org/x/arch/arm/armasm/inst.go
generated
vendored
Normal file
438
vendor/golang.org/x/arch/arm/armasm/inst.go
generated
vendored
Normal file
@ -0,0 +1,438 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package armasm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// A Mode is an instruction execution mode.
|
||||
type Mode int
|
||||
|
||||
const (
|
||||
_ Mode = iota
|
||||
ModeARM
|
||||
ModeThumb
|
||||
)
|
||||
|
||||
func (m Mode) String() string {
|
||||
switch m {
|
||||
case ModeARM:
|
||||
return "ARM"
|
||||
case ModeThumb:
|
||||
return "Thumb"
|
||||
}
|
||||
return fmt.Sprintf("Mode(%d)", int(m))
|
||||
}
|
||||
|
||||
// An Op is an ARM opcode.
|
||||
type Op uint16
|
||||
|
||||
// NOTE: The actual Op values are defined in tables.go.
|
||||
// They are chosen to simplify instruction decoding and
|
||||
// are not a dense packing from 0 to N, although the
|
||||
// density is high, probably at least 90%.
|
||||
|
||||
func (op Op) String() string {
|
||||
if op >= Op(len(opstr)) || opstr[op] == "" {
|
||||
return fmt.Sprintf("Op(%d)", int(op))
|
||||
}
|
||||
return opstr[op]
|
||||
}
|
||||
|
||||
// An Inst is a single instruction.
|
||||
type Inst struct {
|
||||
Op Op // Opcode mnemonic
|
||||
Enc uint32 // Raw encoding bits.
|
||||
Len int // Length of encoding in bytes.
|
||||
Args Args // Instruction arguments, in ARM manual order.
|
||||
}
|
||||
|
||||
func (i Inst) String() string {
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString(i.Op.String())
|
||||
for j, arg := range i.Args {
|
||||
if arg == nil {
|
||||
break
|
||||
}
|
||||
if j == 0 {
|
||||
buf.WriteString(" ")
|
||||
} else {
|
||||
buf.WriteString(", ")
|
||||
}
|
||||
buf.WriteString(arg.String())
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// An Args holds the instruction arguments.
|
||||
// If an instruction has fewer than 4 arguments,
|
||||
// the final elements in the array are nil.
|
||||
type Args [4]Arg
|
||||
|
||||
// An Arg is a single instruction argument, one of these types:
|
||||
// Endian, Imm, Mem, PCRel, Reg, RegList, RegShift, RegShiftReg.
|
||||
type Arg interface {
|
||||
IsArg()
|
||||
String() string
|
||||
}
|
||||
|
||||
type Float32Imm float32
|
||||
|
||||
func (Float32Imm) IsArg() {}
|
||||
|
||||
func (f Float32Imm) String() string {
|
||||
return fmt.Sprintf("#%v", float32(f))
|
||||
}
|
||||
|
||||
type Float64Imm float32
|
||||
|
||||
func (Float64Imm) IsArg() {}
|
||||
|
||||
func (f Float64Imm) String() string {
|
||||
return fmt.Sprintf("#%v", float64(f))
|
||||
}
|
||||
|
||||
// An Imm is an integer constant.
|
||||
type Imm uint32
|
||||
|
||||
func (Imm) IsArg() {}
|
||||
|
||||
func (i Imm) String() string {
|
||||
return fmt.Sprintf("#%#x", uint32(i))
|
||||
}
|
||||
|
||||
// A ImmAlt is an alternate encoding of an integer constant.
|
||||
type ImmAlt struct {
|
||||
Val uint8
|
||||
Rot uint8
|
||||
}
|
||||
|
||||
func (ImmAlt) IsArg() {}
|
||||
|
||||
func (i ImmAlt) Imm() Imm {
|
||||
v := uint32(i.Val)
|
||||
r := uint(i.Rot)
|
||||
return Imm(v>>r | v<<(32-r))
|
||||
}
|
||||
|
||||
func (i ImmAlt) String() string {
|
||||
return fmt.Sprintf("#%#x, %d", i.Val, i.Rot)
|
||||
}
|
||||
|
||||
// A Label is a text (code) address.
|
||||
type Label uint32
|
||||
|
||||
func (Label) IsArg() {}
|
||||
|
||||
func (i Label) String() string {
|
||||
return fmt.Sprintf("%#x", uint32(i))
|
||||
}
|
||||
|
||||
// A Reg is a single register.
|
||||
// The zero value denotes R0, not the absence of a register.
|
||||
type Reg uint8
|
||||
|
||||
const (
|
||||
R0 Reg = iota
|
||||
R1
|
||||
R2
|
||||
R3
|
||||
R4
|
||||
R5
|
||||
R6
|
||||
R7
|
||||
R8
|
||||
R9
|
||||
R10
|
||||
R11
|
||||
R12
|
||||
R13
|
||||
R14
|
||||
R15
|
||||
|
||||
S0
|
||||
S1
|
||||
S2
|
||||
S3
|
||||
S4
|
||||
S5
|
||||
S6
|
||||
S7
|
||||
S8
|
||||
S9
|
||||
S10
|
||||
S11
|
||||
S12
|
||||
S13
|
||||
S14
|
||||
S15
|
||||
S16
|
||||
S17
|
||||
S18
|
||||
S19
|
||||
S20
|
||||
S21
|
||||
S22
|
||||
S23
|
||||
S24
|
||||
S25
|
||||
S26
|
||||
S27
|
||||
S28
|
||||
S29
|
||||
S30
|
||||
S31
|
||||
|
||||
D0
|
||||
D1
|
||||
D2
|
||||
D3
|
||||
D4
|
||||
D5
|
||||
D6
|
||||
D7
|
||||
D8
|
||||
D9
|
||||
D10
|
||||
D11
|
||||
D12
|
||||
D13
|
||||
D14
|
||||
D15
|
||||
D16
|
||||
D17
|
||||
D18
|
||||
D19
|
||||
D20
|
||||
D21
|
||||
D22
|
||||
D23
|
||||
D24
|
||||
D25
|
||||
D26
|
||||
D27
|
||||
D28
|
||||
D29
|
||||
D30
|
||||
D31
|
||||
|
||||
APSR
|
||||
APSR_nzcv
|
||||
FPSCR
|
||||
|
||||
SP = R13
|
||||
LR = R14
|
||||
PC = R15
|
||||
)
|
||||
|
||||
func (Reg) IsArg() {}
|
||||
|
||||
func (r Reg) String() string {
|
||||
switch r {
|
||||
case APSR:
|
||||
return "APSR"
|
||||
case APSR_nzcv:
|
||||
return "APSR_nzcv"
|
||||
case FPSCR:
|
||||
return "FPSCR"
|
||||
case SP:
|
||||
return "SP"
|
||||
case PC:
|
||||
return "PC"
|
||||
case LR:
|
||||
return "LR"
|
||||
}
|
||||
if R0 <= r && r <= R15 {
|
||||
return fmt.Sprintf("R%d", int(r-R0))
|
||||
}
|
||||
if S0 <= r && r <= S31 {
|
||||
return fmt.Sprintf("S%d", int(r-S0))
|
||||
}
|
||||
if D0 <= r && r <= D31 {
|
||||
return fmt.Sprintf("D%d", int(r-D0))
|
||||
}
|
||||
return fmt.Sprintf("Reg(%d)", int(r))
|
||||
}
|
||||
|
||||
// A RegX represents a fraction of a multi-value register.
|
||||
// The Index field specifies the index number,
|
||||
// but the size of the fraction is not specified.
|
||||
// It must be inferred from the instruction and the register type.
|
||||
// For example, in a VMOV instruction, RegX{D5, 1} represents
|
||||
// the top 32 bits of the 64-bit D5 register.
|
||||
type RegX struct {
|
||||
Reg Reg
|
||||
Index int
|
||||
}
|
||||
|
||||
func (RegX) IsArg() {}
|
||||
|
||||
func (r RegX) String() string {
|
||||
return fmt.Sprintf("%s[%d]", r.Reg, r.Index)
|
||||
}
|
||||
|
||||
// A RegList is a register list.
|
||||
// Bits at indexes x = 0 through 15 indicate whether the corresponding Rx register is in the list.
|
||||
type RegList uint16
|
||||
|
||||
func (RegList) IsArg() {}
|
||||
|
||||
func (r RegList) String() string {
|
||||
var buf bytes.Buffer
|
||||
fmt.Fprintf(&buf, "{")
|
||||
sep := ""
|
||||
for i := 0; i < 16; i++ {
|
||||
if r&(1<<uint(i)) != 0 {
|
||||
fmt.Fprintf(&buf, "%s%s", sep, Reg(i).String())
|
||||
sep = ","
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(&buf, "}")
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// An Endian is the argument to the SETEND instruction.
|
||||
type Endian uint8
|
||||
|
||||
const (
|
||||
LittleEndian Endian = 0
|
||||
BigEndian Endian = 1
|
||||
)
|
||||
|
||||
func (Endian) IsArg() {}
|
||||
|
||||
func (e Endian) String() string {
|
||||
if e != 0 {
|
||||
return "BE"
|
||||
}
|
||||
return "LE"
|
||||
}
|
||||
|
||||
// A Shift describes an ARM shift operation.
|
||||
type Shift uint8
|
||||
|
||||
const (
|
||||
ShiftLeft Shift = 0 // left shift
|
||||
ShiftRight Shift = 1 // logical (unsigned) right shift
|
||||
ShiftRightSigned Shift = 2 // arithmetic (signed) right shift
|
||||
RotateRight Shift = 3 // right rotate
|
||||
RotateRightExt Shift = 4 // right rotate through carry (Count will always be 1)
|
||||
)
|
||||
|
||||
var shiftName = [...]string{
|
||||
"LSL", "LSR", "ASR", "ROR", "RRX",
|
||||
}
|
||||
|
||||
func (s Shift) String() string {
|
||||
if s < 5 {
|
||||
return shiftName[s]
|
||||
}
|
||||
return fmt.Sprintf("Shift(%d)", int(s))
|
||||
}
|
||||
|
||||
// A RegShift is a register shifted by a constant.
|
||||
type RegShift struct {
|
||||
Reg Reg
|
||||
Shift Shift
|
||||
Count uint8
|
||||
}
|
||||
|
||||
func (RegShift) IsArg() {}
|
||||
|
||||
func (r RegShift) String() string {
|
||||
return fmt.Sprintf("%s %s #%d", r.Reg, r.Shift, r.Count)
|
||||
}
|
||||
|
||||
// A RegShiftReg is a register shifted by a register.
|
||||
type RegShiftReg struct {
|
||||
Reg Reg
|
||||
Shift Shift
|
||||
RegCount Reg
|
||||
}
|
||||
|
||||
func (RegShiftReg) IsArg() {}
|
||||
|
||||
func (r RegShiftReg) String() string {
|
||||
return fmt.Sprintf("%s %s %s", r.Reg, r.Shift, r.RegCount)
|
||||
}
|
||||
|
||||
// A PCRel describes a memory address (usually a code label)
|
||||
// as a distance relative to the program counter.
|
||||
// TODO(rsc): Define which program counter (PC+4? PC+8? PC?).
|
||||
type PCRel int32
|
||||
|
||||
func (PCRel) IsArg() {}
|
||||
|
||||
func (r PCRel) String() string {
|
||||
return fmt.Sprintf("PC%+#x", int32(r))
|
||||
}
|
||||
|
||||
// An AddrMode is an ARM addressing mode.
|
||||
type AddrMode uint8
|
||||
|
||||
const (
|
||||
_ AddrMode = iota
|
||||
AddrPostIndex // [R], X – use address R, set R = R + X
|
||||
AddrPreIndex // [R, X]! – use address R + X, set R = R + X
|
||||
AddrOffset // [R, X] – use address R + X
|
||||
AddrLDM // R – [R] but formats as R, for LDM/STM only
|
||||
AddrLDM_WB // R! - [R], X where X is instruction-specific amount, for LDM/STM only
|
||||
)
|
||||
|
||||
// A Mem is a memory reference made up of a base R and index expression X.
|
||||
// The effective memory address is R or R+X depending on AddrMode.
|
||||
// The index expression is X = Sign*(Index Shift Count) + Offset,
|
||||
// but in any instruction either Sign = 0 or Offset = 0.
|
||||
type Mem struct {
|
||||
Base Reg
|
||||
Mode AddrMode
|
||||
Sign int8
|
||||
Index Reg
|
||||
Shift Shift
|
||||
Count uint8
|
||||
Offset int16
|
||||
}
|
||||
|
||||
func (Mem) IsArg() {}
|
||||
|
||||
func (m Mem) String() string {
|
||||
R := m.Base.String()
|
||||
X := ""
|
||||
if m.Sign != 0 {
|
||||
X = "+"
|
||||
if m.Sign < 0 {
|
||||
X = "-"
|
||||
}
|
||||
X += m.Index.String()
|
||||
if m.Shift != ShiftLeft || m.Count != 0 {
|
||||
X += fmt.Sprintf(", %s #%d", m.Shift, m.Count)
|
||||
}
|
||||
} else {
|
||||
X = fmt.Sprintf("#%d", m.Offset)
|
||||
}
|
||||
|
||||
switch m.Mode {
|
||||
case AddrOffset:
|
||||
if X == "#0" {
|
||||
return fmt.Sprintf("[%s]", R)
|
||||
}
|
||||
return fmt.Sprintf("[%s, %s]", R, X)
|
||||
case AddrPreIndex:
|
||||
return fmt.Sprintf("[%s, %s]!", R, X)
|
||||
case AddrPostIndex:
|
||||
return fmt.Sprintf("[%s], %s", R, X)
|
||||
case AddrLDM:
|
||||
if X == "#0" {
|
||||
return R
|
||||
}
|
||||
case AddrLDM_WB:
|
||||
if X == "#0" {
|
||||
return R + "!"
|
||||
}
|
||||
}
|
||||
return fmt.Sprintf("[%s Mode(%d) %s]", R, int(m.Mode), X)
|
||||
}
|
215
vendor/golang.org/x/arch/arm/armasm/plan9x.go
generated
vendored
Normal file
215
vendor/golang.org/x/arch/arm/armasm/plan9x.go
generated
vendored
Normal file
@ -0,0 +1,215 @@
|
||||
// Copyright 2014 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package armasm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// GoSyntax returns the Go assembler syntax for the instruction.
|
||||
// The syntax was originally defined by Plan 9.
|
||||
// The pc is the program counter of the instruction, used for expanding
|
||||
// PC-relative addresses into absolute ones.
|
||||
// The symname function queries the symbol table for the program
|
||||
// being disassembled. Given a target address it returns the name and base
|
||||
// address of the symbol containing the target, if any; otherwise it returns "", 0.
|
||||
// The reader r should read from the text segment using text addresses
|
||||
// as offsets; it is used to display pc-relative loads as constant loads.
|
||||
func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64), text io.ReaderAt) string {
|
||||
if symname == nil {
|
||||
symname = func(uint64) (string, uint64) { return "", 0 }
|
||||
}
|
||||
|
||||
var args []string
|
||||
for _, a := range inst.Args {
|
||||
if a == nil {
|
||||
break
|
||||
}
|
||||
args = append(args, plan9Arg(&inst, pc, symname, a))
|
||||
}
|
||||
|
||||
op := inst.Op.String()
|
||||
|
||||
switch inst.Op &^ 15 {
|
||||
case LDR_EQ, LDRB_EQ, LDRH_EQ:
|
||||
// Check for RET
|
||||
reg, _ := inst.Args[0].(Reg)
|
||||
mem, _ := inst.Args[1].(Mem)
|
||||
if inst.Op&^15 == LDR_EQ && reg == R15 && mem.Base == SP && mem.Sign == 0 && mem.Mode == AddrPostIndex {
|
||||
return fmt.Sprintf("RET%s #%d", op[3:], mem.Offset)
|
||||
}
|
||||
|
||||
// Check for PC-relative load.
|
||||
if mem.Base == PC && mem.Sign == 0 && mem.Mode == AddrOffset && text != nil {
|
||||
addr := uint32(pc) + 8 + uint32(mem.Offset)
|
||||
buf := make([]byte, 4)
|
||||
switch inst.Op &^ 15 {
|
||||
case LDRB_EQ:
|
||||
if _, err := text.ReadAt(buf[:1], int64(addr)); err != nil {
|
||||
break
|
||||
}
|
||||
args[1] = fmt.Sprintf("$%#x", buf[0])
|
||||
|
||||
case LDRH_EQ:
|
||||
if _, err := text.ReadAt(buf[:2], int64(addr)); err != nil {
|
||||
break
|
||||
}
|
||||
args[1] = fmt.Sprintf("$%#x", binary.LittleEndian.Uint16(buf))
|
||||
|
||||
case LDR_EQ:
|
||||
if _, err := text.ReadAt(buf, int64(addr)); err != nil {
|
||||
break
|
||||
}
|
||||
x := binary.LittleEndian.Uint32(buf)
|
||||
if s, base := symname(uint64(x)); s != "" && uint64(x) == base {
|
||||
args[1] = fmt.Sprintf("$%s(SB)", s)
|
||||
} else {
|
||||
args[1] = fmt.Sprintf("$%#x", x)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Move addressing mode into opcode suffix.
|
||||
suffix := ""
|
||||
switch inst.Op &^ 15 {
|
||||
case LDR_EQ, LDRB_EQ, LDRH_EQ, STR_EQ, STRB_EQ, STRH_EQ:
|
||||
mem, _ := inst.Args[1].(Mem)
|
||||
switch mem.Mode {
|
||||
case AddrOffset, AddrLDM:
|
||||
// no suffix
|
||||
case AddrPreIndex, AddrLDM_WB:
|
||||
suffix = ".W"
|
||||
case AddrPostIndex:
|
||||
suffix = ".P"
|
||||
}
|
||||
off := ""
|
||||
if mem.Offset != 0 {
|
||||
off = fmt.Sprintf("%#x", mem.Offset)
|
||||
}
|
||||
base := fmt.Sprintf("(R%d)", int(mem.Base))
|
||||
index := ""
|
||||
if mem.Sign != 0 {
|
||||
sign := ""
|
||||
if mem.Sign < 0 {
|
||||
sign = ""
|
||||
}
|
||||
shift := ""
|
||||
if mem.Count != 0 {
|
||||
shift = fmt.Sprintf("%s%d", plan9Shift[mem.Shift], mem.Count)
|
||||
}
|
||||
index = fmt.Sprintf("(%sR%d%s)", sign, int(mem.Index), shift)
|
||||
}
|
||||
args[1] = off + base + index
|
||||
}
|
||||
|
||||
// Reverse args, placing dest last.
|
||||
for i, j := 0, len(args)-1; i < j; i, j = i+1, j-1 {
|
||||
args[i], args[j] = args[j], args[i]
|
||||
}
|
||||
|
||||
switch inst.Op &^ 15 {
|
||||
case MOV_EQ:
|
||||
op = "MOVW" + op[3:]
|
||||
|
||||
case LDR_EQ:
|
||||
op = "MOVW" + op[3:] + suffix
|
||||
case LDRB_EQ:
|
||||
op = "MOVB" + op[4:] + suffix
|
||||
case LDRH_EQ:
|
||||
op = "MOVH" + op[4:] + suffix
|
||||
|
||||
case STR_EQ:
|
||||
op = "MOVW" + op[3:] + suffix
|
||||
args[0], args[1] = args[1], args[0]
|
||||
case STRB_EQ:
|
||||
op = "MOVB" + op[4:] + suffix
|
||||
args[0], args[1] = args[1], args[0]
|
||||
case STRH_EQ:
|
||||
op = "MOVH" + op[4:] + suffix
|
||||
args[0], args[1] = args[1], args[0]
|
||||
}
|
||||
|
||||
if args != nil {
|
||||
op += " " + strings.Join(args, ", ")
|
||||
}
|
||||
|
||||
return op
|
||||
}
|
||||
|
||||
// assembler syntax for the various shifts.
|
||||
// @x> is a lie; the assembler uses @> 0
|
||||
// instead of @x> 1, but i wanted to be clear that it
|
||||
// was a different operation (rotate right extended, not rotate right).
|
||||
var plan9Shift = []string{"<<", ">>", "->", "@>", "@x>"}
|
||||
|
||||
func plan9Arg(inst *Inst, pc uint64, symname func(uint64) (string, uint64), arg Arg) string {
|
||||
switch a := arg.(type) {
|
||||
case Endian:
|
||||
|
||||
case Imm:
|
||||
return fmt.Sprintf("$%d", int(a))
|
||||
|
||||
case Mem:
|
||||
|
||||
case PCRel:
|
||||
addr := uint32(pc) + 8 + uint32(a)
|
||||
if s, base := symname(uint64(addr)); s != "" && uint64(addr) == base {
|
||||
return fmt.Sprintf("%s(SB)", s)
|
||||
}
|
||||
return fmt.Sprintf("%#x", addr)
|
||||
|
||||
case Reg:
|
||||
if a < 16 {
|
||||
return fmt.Sprintf("R%d", int(a))
|
||||
}
|
||||
|
||||
case RegList:
|
||||
var buf bytes.Buffer
|
||||
start := -2
|
||||
end := -2
|
||||
fmt.Fprintf(&buf, "[")
|
||||
flush := func() {
|
||||
if start >= 0 {
|
||||
if buf.Len() > 1 {
|
||||
fmt.Fprintf(&buf, ",")
|
||||
}
|
||||
if start == end {
|
||||
fmt.Fprintf(&buf, "R%d", start)
|
||||
} else {
|
||||
fmt.Fprintf(&buf, "R%d-R%d", start, end)
|
||||
}
|
||||
start = -2
|
||||
end = -2
|
||||
}
|
||||
}
|
||||
for i := 0; i < 16; i++ {
|
||||
if a&(1<<uint(i)) != 0 {
|
||||
if i == end+1 {
|
||||
end++
|
||||
continue
|
||||
}
|
||||
start = i
|
||||
end = i
|
||||
} else {
|
||||
flush()
|
||||
}
|
||||
}
|
||||
flush()
|
||||
fmt.Fprintf(&buf, "]")
|
||||
return buf.String()
|
||||
|
||||
case RegShift:
|
||||
return fmt.Sprintf("R%d%s$%d", int(a.Reg), plan9Shift[a.Shift], int(a.Count))
|
||||
|
||||
case RegShiftReg:
|
||||
return fmt.Sprintf("R%d%sR%d", int(a.Reg), plan9Shift[a.Shift], int(a.RegCount))
|
||||
}
|
||||
return strings.ToUpper(arg.String())
|
||||
}
|
9448
vendor/golang.org/x/arch/arm/armasm/tables.go
generated
vendored
Normal file
9448
vendor/golang.org/x/arch/arm/armasm/tables.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user