4
0
mirror of https://github.com/cwinfo/matterbridge.git synced 2025-06-27 06:29:24 +00:00

Add gops agent

This commit is contained in:
Wim
2017-03-23 23:28:55 +01:00
parent efe641f202
commit 2f68519b3c
97 changed files with 78006 additions and 0 deletions

27
vendor/golang.org/x/arch/arm/armasm/LICENSE generated vendored Normal file
View 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
View 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
View 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
View 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
View 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

File diff suppressed because it is too large Load Diff