From 63862afb273b3c45d95df989413519fc71bc73f9 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 28 Aug 2015 12:04:44 -0400 Subject: [PATCH] cmd/internal/rsc.io: delete The code is now in cmd/vendor/golang.org/x/arch. Change-Id: I518d48c21b0d7fed914552b89ee41411f088456b Reviewed-on: https://go-review.googlesource.com/14021 Reviewed-by: Brad Fitzpatrick --- src/cmd/internal/rsc.io/arm/armasm/Makefile | 2 - src/cmd/internal/rsc.io/arm/armasm/decode.go | 567 - .../internal/rsc.io/arm/armasm/decode_test.go | 69 - .../internal/rsc.io/arm/armasm/ext_test.go | 614 -- src/cmd/internal/rsc.io/arm/armasm/gnu.go | 164 - src/cmd/internal/rsc.io/arm/armasm/inst.go | 438 - .../rsc.io/arm/armasm/objdump_test.go | 258 - .../rsc.io/arm/armasm/objdumpext_test.go | 260 - src/cmd/internal/rsc.io/arm/armasm/plan9x.go | 211 - src/cmd/internal/rsc.io/arm/armasm/tables.go | 9448 ---------------- .../rsc.io/arm/armasm/testdata/Makefile | 5 - .../rsc.io/arm/armasm/testdata/decode.txt | 306 - src/cmd/internal/rsc.io/x86/x86asm/Makefile | 3 - src/cmd/internal/rsc.io/x86/x86asm/decode.go | 1616 --- .../internal/rsc.io/x86/x86asm/decode_test.go | 71 - .../internal/rsc.io/x86/x86asm/ext_test.go | 811 -- src/cmd/internal/rsc.io/x86/x86asm/gnu.go | 926 -- src/cmd/internal/rsc.io/x86/x86asm/inst.go | 641 -- .../internal/rsc.io/x86/x86asm/inst_test.go | 20 - src/cmd/internal/rsc.io/x86/x86asm/intel.go | 518 - .../rsc.io/x86/x86asm/objdump_test.go | 383 - .../rsc.io/x86/x86asm/objdumpext_test.go | 314 - .../rsc.io/x86/x86asm/plan9ext_test.go | 120 - src/cmd/internal/rsc.io/x86/x86asm/plan9x.go | 346 - .../internal/rsc.io/x86/x86asm/plan9x_test.go | 54 - src/cmd/internal/rsc.io/x86/x86asm/tables.go | 9760 ----------------- .../rsc.io/x86/x86asm/testdata/Makefile | 12 - .../rsc.io/x86/x86asm/testdata/decode.txt | 6731 ------------ .../internal/rsc.io/x86/x86asm/xed_test.go | 211 - .../internal/rsc.io/x86/x86asm/xedext_test.go | 206 - 30 files changed, 35085 deletions(-) delete mode 100644 src/cmd/internal/rsc.io/arm/armasm/Makefile delete mode 100644 src/cmd/internal/rsc.io/arm/armasm/decode.go delete mode 100644 src/cmd/internal/rsc.io/arm/armasm/decode_test.go delete mode 100644 src/cmd/internal/rsc.io/arm/armasm/ext_test.go delete mode 100644 src/cmd/internal/rsc.io/arm/armasm/gnu.go delete mode 100644 src/cmd/internal/rsc.io/arm/armasm/inst.go delete mode 100644 src/cmd/internal/rsc.io/arm/armasm/objdump_test.go delete mode 100644 src/cmd/internal/rsc.io/arm/armasm/objdumpext_test.go delete mode 100644 src/cmd/internal/rsc.io/arm/armasm/plan9x.go delete mode 100644 src/cmd/internal/rsc.io/arm/armasm/tables.go delete mode 100644 src/cmd/internal/rsc.io/arm/armasm/testdata/Makefile delete mode 100644 src/cmd/internal/rsc.io/arm/armasm/testdata/decode.txt delete mode 100644 src/cmd/internal/rsc.io/x86/x86asm/Makefile delete mode 100644 src/cmd/internal/rsc.io/x86/x86asm/decode.go delete mode 100644 src/cmd/internal/rsc.io/x86/x86asm/decode_test.go delete mode 100644 src/cmd/internal/rsc.io/x86/x86asm/ext_test.go delete mode 100644 src/cmd/internal/rsc.io/x86/x86asm/gnu.go delete mode 100644 src/cmd/internal/rsc.io/x86/x86asm/inst.go delete mode 100644 src/cmd/internal/rsc.io/x86/x86asm/inst_test.go delete mode 100644 src/cmd/internal/rsc.io/x86/x86asm/intel.go delete mode 100644 src/cmd/internal/rsc.io/x86/x86asm/objdump_test.go delete mode 100644 src/cmd/internal/rsc.io/x86/x86asm/objdumpext_test.go delete mode 100644 src/cmd/internal/rsc.io/x86/x86asm/plan9ext_test.go delete mode 100644 src/cmd/internal/rsc.io/x86/x86asm/plan9x.go delete mode 100644 src/cmd/internal/rsc.io/x86/x86asm/plan9x_test.go delete mode 100644 src/cmd/internal/rsc.io/x86/x86asm/tables.go delete mode 100644 src/cmd/internal/rsc.io/x86/x86asm/testdata/Makefile delete mode 100644 src/cmd/internal/rsc.io/x86/x86asm/testdata/decode.txt delete mode 100644 src/cmd/internal/rsc.io/x86/x86asm/xed_test.go delete mode 100644 src/cmd/internal/rsc.io/x86/x86asm/xedext_test.go diff --git a/src/cmd/internal/rsc.io/arm/armasm/Makefile b/src/cmd/internal/rsc.io/arm/armasm/Makefile deleted file mode 100644 index a3f57001f6..0000000000 --- a/src/cmd/internal/rsc.io/arm/armasm/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -tables.go: ../armmap/map.go ../arm.csv - go run ../armmap/map.go -fmt=decoder ../arm.csv >_tables.go && gofmt _tables.go >tables.go && rm _tables.go diff --git a/src/cmd/internal/rsc.io/arm/armasm/decode.go b/src/cmd/internal/rsc.io/arm/armasm/decode.go deleted file mode 100644 index 6b4d73841b..0000000000 --- a/src/cmd/internal/rsc.io/arm/armasm/decode.go +++ /dev/null @@ -1,567 +0,0 @@ -// 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<> 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 [],+/- like [,+/-{,}]{!} - // 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 [,+/-]{!} like [,+/-{,}]{!} - // 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 [],+/-{,} like [,+/-{,}]{!} - // 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 [],+/-{,} like [,+/-{,}]{!} - // 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 [,#+/-] like [{,#+/-}]{!} - // 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 [],#+/- like [{,#+/-}]{!} - // 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 [],#+/- like [{,#+/-}]{!} - // 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) -} diff --git a/src/cmd/internal/rsc.io/arm/armasm/decode_test.go b/src/cmd/internal/rsc.io/arm/armasm/decode_test.go deleted file mode 100644 index 25a345a882..0000000000 --- a/src/cmd/internal/rsc.io/arm/armasm/decode_test.go +++ /dev/null @@ -1,69 +0,0 @@ -// 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/hex" - "io/ioutil" - "strconv" - "strings" - "testing" -) - -func TestDecode(t *testing.T) { - data, err := ioutil.ReadFile("testdata/decode.txt") - if err != nil { - t.Fatal(err) - } - all := string(data) - for strings.Contains(all, "\t\t") { - all = strings.Replace(all, "\t\t", "\t", -1) - } - for _, line := range strings.Split(all, "\n") { - line = strings.TrimSpace(line) - if line == "" || strings.HasPrefix(line, "#") { - continue - } - f := strings.SplitN(line, "\t", 4) - i := strings.Index(f[0], "|") - if i < 0 { - t.Errorf("parsing %q: missing | separator", f[0]) - continue - } - if i%2 != 0 { - t.Errorf("parsing %q: misaligned | separator", f[0]) - } - size := i / 2 - code, err := hex.DecodeString(f[0][:i] + f[0][i+1:]) - if err != nil { - t.Errorf("parsing %q: %v", f[0], err) - continue - } - mode, err := strconv.Atoi(f[1]) - if err != nil { - t.Errorf("invalid mode %q in: %s", f[1], line) - continue - } - syntax, asm := f[2], f[3] - inst, err := Decode(code, Mode(mode)) - var out string - if err != nil { - out = "error: " + err.Error() - } else { - switch syntax { - case "gnu": - out = GNUSyntax(inst) - case "plan9": - out = Plan9Syntax(inst, 0, nil, nil) - default: - t.Errorf("unknown syntax %q", syntax) - continue - } - } - if out != asm || inst.Len != size { - t.Errorf("Decode(%s) [%s] = %s, %d, want %s, %d", f[0], syntax, out, inst.Len, asm, size) - } - } -} diff --git a/src/cmd/internal/rsc.io/arm/armasm/ext_test.go b/src/cmd/internal/rsc.io/arm/armasm/ext_test.go deleted file mode 100644 index 429fd88694..0000000000 --- a/src/cmd/internal/rsc.io/arm/armasm/ext_test.go +++ /dev/null @@ -1,614 +0,0 @@ -// 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. - -// Support for testing against external disassembler program. -// Copied and simplified from rsc.io/x86/x86asm/ext_test.go. - -package armasm - -import ( - "bufio" - "bytes" - "encoding/hex" - "flag" - "fmt" - "io/ioutil" - "log" - "math/rand" - "os" - "os/exec" - "regexp" - "runtime" - "strings" - "testing" - "time" -) - -var ( - printTests = flag.Bool("printtests", false, "print test cases that exercise new code paths") - dumpTest = flag.Bool("dump", false, "dump all encodings") - mismatch = flag.Bool("mismatch", false, "log allowed mismatches") - longTest = flag.Bool("long", false, "long test") - keep = flag.Bool("keep", false, "keep object files around") - debug = false -) - -// A ExtInst represents a single decoded instruction parsed -// from an external disassembler's output. -type ExtInst struct { - addr uint32 - enc [4]byte - nenc int - text string -} - -func (r ExtInst) String() string { - return fmt.Sprintf("%#x: % x: %s", r.addr, r.enc, r.text) -} - -// An ExtDis is a connection between an external disassembler and a test. -type ExtDis struct { - Arch Mode - Dec chan ExtInst - File *os.File - Size int - KeepFile bool - Cmd *exec.Cmd -} - -// Run runs the given command - the external disassembler - and returns -// a buffered reader of its standard output. -func (ext *ExtDis) Run(cmd ...string) (*bufio.Reader, error) { - if *keep { - log.Printf("%s\n", strings.Join(cmd, " ")) - } - ext.Cmd = exec.Command(cmd[0], cmd[1:]...) - out, err := ext.Cmd.StdoutPipe() - if err != nil { - return nil, fmt.Errorf("stdoutpipe: %v", err) - } - if err := ext.Cmd.Start(); err != nil { - return nil, fmt.Errorf("exec: %v", err) - } - - b := bufio.NewReaderSize(out, 1<<20) - return b, nil -} - -// Wait waits for the command started with Run to exit. -func (ext *ExtDis) Wait() error { - return ext.Cmd.Wait() -} - -// testExtDis tests a set of byte sequences against an external disassembler. -// The disassembler is expected to produce the given syntax and be run -// in the given architecture mode (16, 32, or 64-bit). -// The extdis function must start the external disassembler -// and then parse its output, sending the parsed instructions on ext.Dec. -// The generate function calls its argument f once for each byte sequence -// to be tested. The generate function itself will be called twice, and it must -// make the same sequence of calls to f each time. -// When a disassembly does not match the internal decoding, -// allowedMismatch determines whether this mismatch should be -// allowed, or else considered an error. -func testExtDis( - t *testing.T, - syntax string, - arch Mode, - extdis func(ext *ExtDis) error, - generate func(f func([]byte)), - allowedMismatch func(text string, size int, inst *Inst, dec ExtInst) bool, -) { - start := time.Now() - ext := &ExtDis{ - Dec: make(chan ExtInst), - Arch: arch, - } - errc := make(chan error) - - // First pass: write instructions to input file for external disassembler. - file, f, size, err := writeInst(generate) - if err != nil { - t.Fatal(err) - } - ext.Size = size - ext.File = f - defer func() { - f.Close() - if !*keep { - os.Remove(file) - } - }() - - // Second pass: compare disassembly against our decodings. - var ( - totalTests = 0 - totalSkips = 0 - totalErrors = 0 - - errors = make([]string, 0, 100) // sampled errors, at most cap - ) - go func() { - errc <- extdis(ext) - }() - generate(func(enc []byte) { - dec, ok := <-ext.Dec - if !ok { - t.Errorf("decoding stream ended early") - return - } - inst, text := disasm(syntax, arch, pad(enc)) - totalTests++ - if *dumpTest { - fmt.Printf("%x -> %s [%d]\n", enc[:len(enc)], dec.text, dec.nenc) - } - if text != dec.text || inst.Len != dec.nenc { - suffix := "" - if allowedMismatch(text, size, &inst, dec) { - totalSkips++ - if !*mismatch { - return - } - suffix += " (allowed mismatch)" - } - totalErrors++ - if len(errors) >= cap(errors) { - j := rand.Intn(totalErrors) - if j >= cap(errors) { - return - } - errors = append(errors[:j], errors[j+1:]...) - } - errors = append(errors, fmt.Sprintf("decode(%x) = %q, %d, want %q, %d%s", enc, text, inst.Len, dec.text, dec.nenc, suffix)) - } - }) - - if *mismatch { - totalErrors -= totalSkips - } - - for _, b := range errors { - t.Log(b) - } - - if totalErrors > 0 { - t.Fail() - } - t.Logf("%d test cases, %d expected mismatches, %d failures; %.0f cases/second", totalTests, totalSkips, totalErrors, float64(totalTests)/time.Since(start).Seconds()) - - if err := <-errc; err != nil { - t.Fatalf("external disassembler: %v", err) - } - -} - -const start = 0x8000 // start address of text - -// writeInst writes the generated byte sequences to a new file -// starting at offset start. That file is intended to be the input to -// the external disassembler. -func writeInst(generate func(func([]byte))) (file string, f *os.File, size int, err error) { - f, err = ioutil.TempFile("", "armasm") - if err != nil { - return - } - - file = f.Name() - - f.Seek(start, 0) - w := bufio.NewWriter(f) - defer w.Flush() - size = 0 - generate(func(x []byte) { - if len(x) > 4 { - x = x[:4] - } - if debug { - fmt.Printf("%#x: %x%x\n", start+size, x, zeros[len(x):]) - } - w.Write(x) - w.Write(zeros[len(x):]) - size += len(zeros) - }) - return file, f, size, nil -} - -var zeros = []byte{0, 0, 0, 0} - -// pad pads the code sequence with pops. -func pad(enc []byte) []byte { - if len(enc) < 4 { - enc = append(enc[:len(enc):len(enc)], zeros[:4-len(enc)]...) - } - return enc -} - -// disasm returns the decoded instruction and text -// for the given source bytes, using the given syntax and mode. -func disasm(syntax string, mode Mode, src []byte) (inst Inst, text string) { - // If printTests is set, we record the coverage value - // before and after, and we write out the inputs for which - // coverage went up, in the format expected in testdata/decode.text. - // This produces a fairly small set of test cases that exercise nearly - // all the code. - var cover float64 - if *printTests { - cover -= coverage() - } - - inst, err := Decode(src, mode) - if err != nil { - text = "error: " + err.Error() - } else { - text = inst.String() - switch syntax { - //case "arm": - // text = ARMSyntax(inst) - case "gnu": - text = GNUSyntax(inst) - //case "plan9": - // text = Plan9Syntax(inst, 0, nil) - default: - text = "error: unknown syntax " + syntax - } - } - - if *printTests { - cover += coverage() - if cover > 0 { - max := len(src) - if max > 4 && inst.Len <= 4 { - max = 4 - } - fmt.Printf("%x|%x\t%d\t%s\t%s\n", src[:inst.Len], src[inst.Len:max], mode, syntax, text) - } - } - - return -} - -// coverage returns a floating point number denoting the -// test coverage until now. The number increases when new code paths are exercised, -// both in the Go program and in the decoder byte code. -func coverage() float64 { - /* - testing.Coverage is not in the main distribution. - The implementation, which must go in package testing, is: - - // Coverage reports the current code coverage as a fraction in the range [0, 1]. - func Coverage() float64 { - var n, d int64 - for _, counters := range cover.Counters { - for _, c := range counters { - if c > 0 { - n++ - } - d++ - } - } - if d == 0 { - return 0 - } - return float64(n) / float64(d) - } - */ - - var f float64 - f += testing.Coverage() - f += decodeCoverage() - return f -} - -func decodeCoverage() float64 { - n := 0 - for _, t := range decoderCover { - if t { - n++ - } - } - return float64(1+n) / float64(1+len(decoderCover)) -} - -// Helpers for writing disassembler output parsers. - -// hasPrefix reports whether any of the space-separated words in the text s -// begins with any of the given prefixes. -func hasPrefix(s string, prefixes ...string) bool { - for _, prefix := range prefixes { - for s := s; s != ""; { - if strings.HasPrefix(s, prefix) { - return true - } - i := strings.Index(s, " ") - if i < 0 { - break - } - s = s[i+1:] - } - } - return false -} - -// contains reports whether the text s contains any of the given substrings. -func contains(s string, substrings ...string) bool { - for _, sub := range substrings { - if strings.Contains(s, sub) { - return true - } - } - return false -} - -// isHex reports whether b is a hexadecimal character (0-9A-Fa-f). -func isHex(b byte) bool { return b == '0' || unhex[b] > 0 } - -// parseHex parses the hexadecimal byte dump in hex, -// appending the parsed bytes to raw and returning the updated slice. -// The returned bool signals whether any invalid hex was found. -// Spaces and tabs between bytes are okay but any other non-hex is not. -func parseHex(hex []byte, raw []byte) ([]byte, bool) { - hex = trimSpace(hex) - for j := 0; j < len(hex); { - for hex[j] == ' ' || hex[j] == '\t' { - j++ - } - if j >= len(hex) { - break - } - if j+2 > len(hex) || !isHex(hex[j]) || !isHex(hex[j+1]) { - return nil, false - } - raw = append(raw, unhex[hex[j]]<<4|unhex[hex[j+1]]) - j += 2 - } - return raw, true -} - -var unhex = [256]byte{ - '0': 0, - '1': 1, - '2': 2, - '3': 3, - '4': 4, - '5': 5, - '6': 6, - '7': 7, - '8': 8, - '9': 9, - 'A': 10, - 'B': 11, - 'C': 12, - 'D': 13, - 'E': 14, - 'F': 15, - 'a': 10, - 'b': 11, - 'c': 12, - 'd': 13, - 'e': 14, - 'f': 15, -} - -// index is like bytes.Index(s, []byte(t)) but avoids the allocation. -func index(s []byte, t string) int { - i := 0 - for { - j := bytes.IndexByte(s[i:], t[0]) - if j < 0 { - return -1 - } - i = i + j - if i+len(t) > len(s) { - return -1 - } - for k := 1; k < len(t); k++ { - if s[i+k] != t[k] { - goto nomatch - } - } - return i - nomatch: - i++ - } -} - -// fixSpace rewrites runs of spaces, tabs, and newline characters into single spaces in s. -// If s must be rewritten, it is rewritten in place. -func fixSpace(s []byte) []byte { - s = trimSpace(s) - for i := 0; i < len(s); i++ { - if s[i] == '\t' || s[i] == '\n' || i > 0 && s[i] == ' ' && s[i-1] == ' ' { - goto Fix - } - } - return s - -Fix: - b := s - w := 0 - for i := 0; i < len(s); i++ { - c := s[i] - if c == '\t' || c == '\n' { - c = ' ' - } - if c == ' ' && w > 0 && b[w-1] == ' ' { - continue - } - b[w] = c - w++ - } - if w > 0 && b[w-1] == ' ' { - w-- - } - return b[:w] -} - -// trimSpace trims leading and trailing space from s, returning a subslice of s. -func trimSpace(s []byte) []byte { - j := len(s) - for j > 0 && (s[j-1] == ' ' || s[j-1] == '\t' || s[j-1] == '\n') { - j-- - } - i := 0 - for i < j && (s[i] == ' ' || s[i] == '\t') { - i++ - } - return s[i:j] -} - -// pcrel matches instructions using relative addressing mode. -var ( - pcrel = regexp.MustCompile(`^((?:.* )?(?:b|bl)x?(?:eq|ne|cs|cc|mi|pl|vs|vc|hi|ls|ge|lt|gt|le)?) 0x([0-9a-f]+)$`) -) - -// Generators. -// -// The test cases are described as functions that invoke a callback repeatedly, -// with a new input sequence each time. These helpers make writing those -// a little easier. - -// condCases generates conditional instructions. -func condCases(t *testing.T) func(func([]byte)) { - return func(try func([]byte)) { - // All the strides are relatively prime to 2 and therefore to 2²⁸, - // so we will not repeat any instructions until we have tried all 2²⁸. - // Using a stride other than 1 is meant to visit the instructions in a - // pseudorandom order, which gives better variety in the set of - // test cases chosen by -printtests. - stride := uint32(10007) - n := 1 << 28 / 7 - if testing.Short() { - stride = 100003 - n = 1 << 28 / 1001 - } else if *longTest { - stride = 200000033 - n = 1 << 28 - } - x := uint32(0) - for i := 0; i < n; i++ { - enc := (x%15)<<28 | x&(1<<28-1) - try([]byte{byte(enc), byte(enc >> 8), byte(enc >> 16), byte(enc >> 24)}) - x += stride - } - } -} - -// uncondCases generates unconditional instructions. -func uncondCases(t *testing.T) func(func([]byte)) { - return func(try func([]byte)) { - condCases(t)(func(enc []byte) { - enc[3] |= 0xF0 - try(enc) - }) - } -} - -func countBits(x uint32) int { - n := 0 - for ; x != 0; x >>= 1 { - n += int(x & 1) - } - return n -} - -func expandBits(x, m uint32) uint32 { - var out uint32 - for i := uint(0); i < 32; i++ { - out >>= 1 - if m&1 != 0 { - out |= (x & 1) << 31 - x >>= 1 - } - m >>= 1 - } - return out -} - -func tryCondMask(mask, val uint32, try func([]byte)) { - n := countBits(^mask) - bits := uint32(0) - for i := 0; i < 1<> 8), byte(x >> 16), byte(x >> 24)}) - } -} - -// vfpCases generates VFP instructions. -func vfpCases(t *testing.T) func(func([]byte)) { - const ( - vfpmask uint32 = 0xFF00FE10 - vfp uint32 = 0x0E009A00 - ) - return func(try func([]byte)) { - tryCondMask(0xff00fe10, 0x0e009a00, try) // standard VFP instruction space - tryCondMask(0xffc00f7f, 0x0e000b10, try) // VFP MOV core reg to/from float64 half - tryCondMask(0xffe00f7f, 0x0e000a10, try) // VFP MOV core reg to/from float32 - tryCondMask(0xffef0fff, 0x0ee10a10, try) // VFP MOV core reg to/from cond codes - } -} - -// hexCases generates the cases written in hexadecimal in the encoded string. -// Spaces in 'encoded' separate entire test cases, not individual bytes. -func hexCases(t *testing.T, encoded string) func(func([]byte)) { - return func(try func([]byte)) { - for _, x := range strings.Fields(encoded) { - src, err := hex.DecodeString(x) - if err != nil { - t.Errorf("parsing %q: %v", x, err) - } - try(src) - } - } -} - -// testdataCases generates the test cases recorded in testdata/decode.txt. -// It only uses the inputs; it ignores the answers recorded in that file. -func testdataCases(t *testing.T) func(func([]byte)) { - var codes [][]byte - data, err := ioutil.ReadFile("testdata/decode.txt") - if err != nil { - t.Fatal(err) - } - for _, line := range strings.Split(string(data), "\n") { - line = strings.TrimSpace(line) - if line == "" || strings.HasPrefix(line, "#") { - continue - } - f := strings.Fields(line)[0] - i := strings.Index(f, "|") - if i < 0 { - t.Errorf("parsing %q: missing | separator", f) - continue - } - if i%2 != 0 { - t.Errorf("parsing %q: misaligned | separator", f) - } - code, err := hex.DecodeString(f[:i] + f[i+1:]) - if err != nil { - t.Errorf("parsing %q: %v", f, err) - continue - } - codes = append(codes, code) - } - - return func(try func([]byte)) { - for _, code := range codes { - try(code) - } - } -} - -func caller(skip int) string { - pc, _, _, _ := runtime.Caller(skip) - f := runtime.FuncForPC(pc) - name := "?" - if f != nil { - name = f.Name() - if i := strings.LastIndex(name, "."); i >= 0 { - name = name[i+1:] - } - } - return name -} diff --git a/src/cmd/internal/rsc.io/arm/armasm/gnu.go b/src/cmd/internal/rsc.io/arm/armasm/gnu.go deleted file mode 100644 index 1a97a5a844..0000000000 --- a/src/cmd/internal/rsc.io/arm/armasm/gnu.go +++ /dev/null @@ -1,164 +0,0 @@ -// 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<= 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<= 4 { - raw := binary.LittleEndian.Uint32(dec.enc[:4]) - - // word 21FFF0B5. - // the manual is clear that this is pre-indexed mode (with !) but libopcodes generates post-index (without !). - if raw&0x01200000 == 0x01200000 && strings.Replace(text, "!", "", -1) == dec.text { - return true - } - - // word C100543E: libopcodes says tst, but no evidence for that. - if strings.HasPrefix(dec.text, "tst") && raw&0x0ff00000 != 0x03100000 && raw&0x0ff00000 != 0x01100000 { - return true - } - - // word C3203CE8: libopcodes says teq, but no evidence for that. - if strings.HasPrefix(dec.text, "teq") && raw&0x0ff00000 != 0x03300000 && raw&0x0ff00000 != 0x01300000 { - return true - } - - // word D14C552E: libopcodes says cmp but no evidence for that. - if strings.HasPrefix(dec.text, "cmp") && raw&0x0ff00000 != 0x03500000 && raw&0x0ff00000 != 0x01500000 { - return true - } - - // word 2166AA4A: libopcodes says cmn but no evidence for that. - if strings.HasPrefix(dec.text, "cmn") && raw&0x0ff00000 != 0x03700000 && raw&0x0ff00000 != 0x01700000 { - return true - } - - // word E70AEEEF: libopcodes says str but no evidence for that. - if strings.HasPrefix(dec.text, "str") && len(dec.text) >= 5 && (dec.text[3] == ' ' || dec.text[5] == ' ') && raw&0x0e500018 != 0x06000000 && raw&0x0e500000 != 0x0400000 { - return true - } - - // word B0AF48F4: libopcodes says strd but P=0,W=1 which is unpredictable. - if hasPrefix(dec.text, "ldr", "str") && raw&0x01200000 == 0x00200000 { - return true - } - - // word B6CC1C76: libopcodes inexplicably says 'uxtab16lt r1, ip, r6, ROR #24' instead of 'uxtab16lt r1, ip, r6, ror #24' - if strings.ToLower(dec.text) == text { - return true - } - - // word F410FDA1: libopcodes says PLDW but the manual is clear that PLDW is F5/F7, not F4. - // word F7D0FB17: libopcodes says PLDW but the manual is clear that PLDW has 0x10 clear - if hasPrefix(dec.text, "pld") && raw&0xfd000010 != 0xf5000000 { - return true - } - - // word F650FE14: libopcodes says PLI but the manual is clear that PLI has 0x10 clear - if hasPrefix(dec.text, "pli") && raw&0xff000010 != 0xf6000000 { - return true - } - } - - return false -} - -// Instructions known to libopcodes (or xed) but not to us. -// Most of these are floating point coprocessor instructions. -var unsupported = strings.Fields(` - abs - acs - adf - aes - asn - atn - cdp - cf - cmf - cnf - cos - cps - crc32 - dvf - eret - exp - fadd - fcmp - fcpy - fcvt - fdiv - fdv - fix - fld - flt - fmac - fmd - fml - fmr - fms - fmul - fmx - fneg - fnm - frd - fsit - fsq - fst - fsu - fto - fui - hlt - hvc - lda - ldc - ldf - lfm - lgn - log - mar - mcr - mcrr - mia - mnf - mra - mrc - mrrc - mrs - msr - msr - muf - mvf - nrm - pol - pow - rdf - rfc - rfe - rfs - rmf - rnd - rpw - rsf - sdiv - sev - sfm - sha1 - sha256 - sin - smc - sqt - srs - stc - stf - stl - suf - tan - udf - udiv - urd - vfma - vfms - vfnma - vfnms - vrint - wfc - wfs -`) diff --git a/src/cmd/internal/rsc.io/arm/armasm/objdumpext_test.go b/src/cmd/internal/rsc.io/arm/armasm/objdumpext_test.go deleted file mode 100644 index d88c67fc05..0000000000 --- a/src/cmd/internal/rsc.io/arm/armasm/objdumpext_test.go +++ /dev/null @@ -1,260 +0,0 @@ -// 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. - -// Copied and simplified from rsc.io/x86/x86asm/objdumpext_test.go. - -package armasm - -import ( - "bytes" - "debug/elf" - "encoding/binary" - "fmt" - "io" - "log" - "os" - "strconv" - "strings" - "testing" -) - -const objdumpPath = "/usr/local/bin/arm-linux-elf-objdump" - -func testObjdumpARM(t *testing.T, generate func(func([]byte))) { - testObjdumpArch(t, generate, ModeARM) -} - -func testObjdumpArch(t *testing.T, generate func(func([]byte)), arch Mode) { - if testing.Short() { - t.Skip("skipping objdump test in short mode") - } - - if _, err := os.Stat(objdumpPath); err != nil { - t.Fatal(err) - } - - testExtDis(t, "gnu", arch, objdump, generate, allowedMismatchObjdump) -} - -func objdump(ext *ExtDis) error { - // File already written with instructions; add ELF header. - if ext.Arch == ModeARM { - if err := writeELF32(ext.File, ext.Size); err != nil { - return err - } - } else { - panic("unknown arch") - } - - b, err := ext.Run(objdumpPath, "-d", "-z", ext.File.Name()) - if err != nil { - return err - } - - var ( - nmatch int - reading bool - next uint32 = start - addr uint32 - encbuf [4]byte - enc []byte - text string - ) - flush := func() { - if addr == next { - if m := pcrel.FindStringSubmatch(text); m != nil { - targ, _ := strconv.ParseUint(m[2], 16, 64) - text = fmt.Sprintf("%s .%+#x", m[1], int32(uint32(targ)-addr-uint32(len(enc)))) - } - if strings.HasPrefix(text, "stmia") { - text = "stm" + text[5:] - } - if strings.HasPrefix(text, "stmfd") { - text = "stmdb" + text[5:] - } - if strings.HasPrefix(text, "ldmfd") { - text = "ldm" + text[5:] - } - text = strings.Replace(text, "#0.0", "#0", -1) - if text == "undefined" && len(enc) == 4 { - text = "error: unknown instruction" - enc = nil - } - if len(enc) == 4 { - // prints as word but we want to record bytes - enc[0], enc[3] = enc[3], enc[0] - enc[1], enc[2] = enc[2], enc[1] - } - ext.Dec <- ExtInst{addr, encbuf, len(enc), text} - encbuf = [4]byte{} - enc = nil - next += 4 - } - } - var textangle = []byte("<.text>:") - for { - line, err := b.ReadSlice('\n') - if err != nil { - if err == io.EOF { - break - } - return fmt.Errorf("reading objdump output: %v", err) - } - if bytes.Contains(line, textangle) { - reading = true - continue - } - if !reading { - continue - } - if debug { - os.Stdout.Write(line) - } - if enc1 := parseContinuation(line, encbuf[:len(enc)]); enc1 != nil { - enc = enc1 - continue - } - flush() - nmatch++ - addr, enc, text = parseLine(line, encbuf[:0]) - if addr > next { - return fmt.Errorf("address out of sync expected <= %#x at %q in:\n%s", next, line, line) - } - } - flush() - if next != start+uint32(ext.Size) { - return fmt.Errorf("not enough results found [%d %d]", next, start+ext.Size) - } - if err := ext.Wait(); err != nil { - return fmt.Errorf("exec: %v", err) - } - - return nil -} - -var ( - undefined = []byte("") - unpredictable = []byte("") - illegalShifter = []byte("") -) - -func parseLine(line []byte, encstart []byte) (addr uint32, enc []byte, text string) { - oline := line - i := index(line, ":\t") - if i < 0 { - log.Fatalf("cannot parse disassembly: %q", oline) - } - x, err := strconv.ParseUint(string(trimSpace(line[:i])), 16, 32) - if err != nil { - log.Fatalf("cannot parse disassembly: %q", oline) - } - addr = uint32(x) - line = line[i+2:] - i = bytes.IndexByte(line, '\t') - if i < 0 { - log.Fatalf("cannot parse disassembly: %q", oline) - } - enc, ok := parseHex(line[:i], encstart) - if !ok { - log.Fatalf("cannot parse disassembly: %q", oline) - } - line = trimSpace(line[i:]) - if bytes.Contains(line, undefined) { - text = "undefined" - return - } - if bytes.Contains(line, illegalShifter) { - text = "undefined" - return - } - if false && bytes.Contains(line, unpredictable) { - text = "unpredictable" - return - } - if i := bytes.IndexByte(line, ';'); i >= 0 { - line = trimSpace(line[:i]) - } - text = string(fixSpace(line)) - return -} - -func parseContinuation(line []byte, enc []byte) []byte { - i := index(line, ":\t") - if i < 0 { - return nil - } - line = line[i+1:] - enc, _ = parseHex(line, enc) - return enc -} - -// writeELF32 writes an ELF32 header to the file, -// describing a text segment that starts at start -// and extends for size bytes. -func writeELF32(f *os.File, size int) error { - f.Seek(0, 0) - var hdr elf.Header32 - var prog elf.Prog32 - var sect elf.Section32 - var buf bytes.Buffer - binary.Write(&buf, binary.LittleEndian, &hdr) - off1 := buf.Len() - binary.Write(&buf, binary.LittleEndian, &prog) - off2 := buf.Len() - binary.Write(&buf, binary.LittleEndian, §) - off3 := buf.Len() - buf.Reset() - data := byte(elf.ELFDATA2LSB) - hdr = elf.Header32{ - Ident: [16]byte{0x7F, 'E', 'L', 'F', 1, data, 1}, - Type: 2, - Machine: uint16(elf.EM_ARM), - Version: 1, - Entry: start, - Phoff: uint32(off1), - Shoff: uint32(off2), - Flags: 0x05000002, - Ehsize: uint16(off1), - Phentsize: uint16(off2 - off1), - Phnum: 1, - Shentsize: uint16(off3 - off2), - Shnum: 3, - Shstrndx: 2, - } - binary.Write(&buf, binary.LittleEndian, &hdr) - prog = elf.Prog32{ - Type: 1, - Off: start, - Vaddr: start, - Paddr: start, - Filesz: uint32(size), - Memsz: uint32(size), - Flags: 5, - Align: start, - } - binary.Write(&buf, binary.LittleEndian, &prog) - binary.Write(&buf, binary.LittleEndian, §) // NULL section - sect = elf.Section32{ - Name: 1, - Type: uint32(elf.SHT_PROGBITS), - Addr: start, - Off: start, - Size: uint32(size), - Flags: uint32(elf.SHF_ALLOC | elf.SHF_EXECINSTR), - Addralign: 4, - } - binary.Write(&buf, binary.LittleEndian, §) // .text - sect = elf.Section32{ - Name: uint32(len("\x00.text\x00")), - Type: uint32(elf.SHT_STRTAB), - Addr: 0, - Off: uint32(off2 + (off3-off2)*3), - Size: uint32(len("\x00.text\x00.shstrtab\x00")), - Addralign: 1, - } - binary.Write(&buf, binary.LittleEndian, §) - buf.WriteString("\x00.text\x00.shstrtab\x00") - f.Write(buf.Bytes()) - return nil -} diff --git a/src/cmd/internal/rsc.io/arm/armasm/plan9x.go b/src/cmd/internal/rsc.io/arm/armasm/plan9x.go deleted file mode 100644 index 952c5190b6..0000000000 --- a/src/cmd/internal/rsc.io/arm/armasm/plan9x.go +++ /dev/null @@ -1,211 +0,0 @@ -// 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" -) - -// Plan9Syntax 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 Plan9Syntax(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) - } - } - } - for i := 0; i < 16; i++ { - if a&(1< ,,# cond:4|0|0|1|0|1|0|1|S|Rn:4|Rd:4|imm12:12 - {0x0fe00090, 0x00a00010, 4, ADC_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_R}}, // ADC{S} ,,, cond:4|0|0|0|0|1|0|1|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4 - {0x0fe00010, 0x00a00000, 2, ADC_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_imm}}, // ADC{S} ,,{,} cond:4|0|0|0|0|1|0|1|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4 - {0x0fe00000, 0x02800000, 2, ADD_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_const}}, // ADD{S} ,,# cond:4|0|0|1|0|1|0|0|S|Rn:4|Rd:4|imm12:12 - {0x0fe00090, 0x00800010, 4, ADD_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_R}}, // ADD{S} ,,, cond:4|0|0|0|0|1|0|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4 - {0x0fe00010, 0x00800000, 2, ADD_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_imm}}, // ADD{S} ,,{,} cond:4|0|0|0|0|1|0|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4 - {0x0fef0000, 0x028d0000, 2, ADD_EQ, 0x14011c04, instArgs{arg_R_12, arg_SP, arg_const}}, // ADD{S} ,SP,# cond:4|0|0|1|0|1|0|0|S|1|1|0|1|Rd:4|imm12:12 - {0x0fef0010, 0x008d0000, 2, ADD_EQ, 0x14011c04, instArgs{arg_R_12, arg_SP, arg_R_shift_imm}}, // ADD{S} ,SP,{,} cond:4|0|0|0|0|1|0|0|S|1|1|0|1|Rd:4|imm5:5|type:2|0|Rm:4 - {0x0fe00000, 0x02000000, 2, AND_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_const}}, // AND{S} ,,# cond:4|0|0|1|0|0|0|0|S|Rn:4|Rd:4|imm12:12 - {0x0fe00090, 0x00000010, 4, AND_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_R}}, // AND{S} ,,, cond:4|0|0|0|0|0|0|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4 - {0x0fe00010, 0x00000000, 2, AND_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_imm}}, // AND{S} ,,{,} cond:4|0|0|0|0|0|0|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4 - {0x0fef0070, 0x01a00040, 4, ASR_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_0, arg_imm5_32}}, // ASR{S} ,,# cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|imm5:5|1|0|0|Rm:4 - {0x0fef00f0, 0x01a00050, 4, ASR_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_0, arg_R_8}}, // ASR{S} ,, cond:4|0|0|0|1|1|0|1|S|0|0|0|0|Rd:4|Rm:4|0|1|0|1|Rn:4 - {0x0f000000, 0x0a000000, 4, B_EQ, 0x1c04, instArgs{arg_label24}}, // B cond:4|1|0|1|0|imm24:24 - {0x0fe0007f, 0x07c0001f, 4, BFC_EQ, 0x1c04, instArgs{arg_R_12, arg_imm5, arg_lsb_width}}, // BFC ,#,# cond:4|0|1|1|1|1|1|0|msb:5|Rd:4|lsb:5|0|0|1|1|1|1|1 - {0x0fe00070, 0x07c00010, 2, BFI_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0, arg_imm5, arg_lsb_width}}, // BFI ,,#,# cond:4|0|1|1|1|1|1|0|msb:5|Rd:4|lsb:5|0|0|1|Rn:4 - {0x0fe00000, 0x03c00000, 2, BIC_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_const}}, // BIC{S} ,,# cond:4|0|0|1|1|1|1|0|S|Rn:4|Rd:4|imm12:12 - {0x0fe00090, 0x01c00010, 4, BIC_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_R}}, // BIC{S} ,,, cond:4|0|0|0|1|1|1|0|S|Rn:4|Rd:4|Rs:4|0|type:2|1|Rm:4 - {0x0fe00010, 0x01c00000, 2, BIC_EQ, 0x14011c04, instArgs{arg_R_12, arg_R_16, arg_R_shift_imm}}, // BIC{S} ,,{,} cond:4|0|0|0|1|1|1|0|S|Rn:4|Rd:4|imm5:5|type:2|0|Rm:4 - {0x0ff000f0, 0x01200070, 4, BKPT_EQ, 0x1c04, instArgs{arg_imm_12at8_4at0}}, // BKPT # cond:4|0|0|0|1|0|0|1|0|imm12:12|0|1|1|1|imm4:4 - {0x0f000000, 0x0b000000, 4, BL_EQ, 0x1c04, instArgs{arg_label24}}, // BL cond:4|1|0|1|1|imm24:24 - {0xfe000000, 0xfa000000, 4, BLX, 0x0, instArgs{arg_label24H}}, // BLX 1|1|1|1|1|0|1|H|imm24:24 - {0x0ffffff0, 0x012fff30, 4, BLX_EQ, 0x1c04, instArgs{arg_R_0}}, // BLX cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4 - {0x0ff000f0, 0x012fff30, 3, BLX_EQ, 0x1c04, instArgs{arg_R_0}}, // BLX cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|1|1|Rm:4 - {0x0ffffff0, 0x012fff10, 4, BX_EQ, 0x1c04, instArgs{arg_R_0}}, // BX cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4 - {0x0ff000f0, 0x012fff10, 3, BX_EQ, 0x1c04, instArgs{arg_R_0}}, // BX cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4 - {0x0ffffff0, 0x012fff20, 4, BXJ_EQ, 0x1c04, instArgs{arg_R_0}}, // BXJ cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|1|0|Rm:4 - {0x0ff000f0, 0x012fff20, 3, BXJ_EQ, 0x1c04, instArgs{arg_R_0}}, // BXJ cond:4|0|0|0|1|0|0|1|0|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|0|0|1|0|Rm:4 - {0xffffffff, 0xf57ff01f, 4, CLREX, 0x0, instArgs{}}, // CLREX 1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|1|(1)|(1)|(1)|(1) - {0xfff000f0, 0xf57ff01f, 3, CLREX, 0x0, instArgs{}}, // CLREX 1|1|1|1|0|1|0|1|0|1|1|1|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(1)|(0)|(0)|(0)|(0)|0|0|0|1|(1)|(1)|(1)|(1) - {0x0fff0ff0, 0x016f0f10, 4, CLZ_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0}}, // CLZ , cond:4|0|0|0|1|0|1|1|0|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4 - {0x0ff000f0, 0x016f0f10, 3, CLZ_EQ, 0x1c04, instArgs{arg_R_12, arg_R_0}}, // CLZ , cond:4|0|0|0|1|0|1|1|0|(1)|(1)|(1)|(1)|Rd:4|(1)|(1)|(1)|(1)|0|0|0|1|Rm:4 - {0x0ff0f000, 0x03700000, 4, CMN_EQ, 0x1c04, instArgs{arg_R_16, arg_const}}, // CMN ,# cond:4|0|0|1|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12 - {0x0ff00000, 0x03700000, 3, CMN_EQ, 0x1c04, instArgs{arg_R_16, arg_const}}, // CMN ,# cond:4|0|0|1|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12 - {0x0ff0f090, 0x01700010, 4, CMN_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_R}}, // CMN ,, cond:4|0|0|0|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4 - {0x0ff00090, 0x01700010, 3, CMN_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_R}}, // CMN ,, cond:4|0|0|0|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4 - {0x0ff0f010, 0x01700000, 4, CMN_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_imm}}, // CMN ,{,} cond:4|0|0|0|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4 - {0x0ff00010, 0x01700000, 3, CMN_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_imm}}, // CMN ,{,} cond:4|0|0|0|1|0|1|1|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4 - {0x0ff0f000, 0x03500000, 4, CMP_EQ, 0x1c04, instArgs{arg_R_16, arg_const}}, // CMP ,# cond:4|0|0|1|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12 - {0x0ff00000, 0x03500000, 3, CMP_EQ, 0x1c04, instArgs{arg_R_16, arg_const}}, // CMP ,# cond:4|0|0|1|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|imm12:12 - {0x0ff0f090, 0x01500010, 4, CMP_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_R}}, // CMP ,, cond:4|0|0|0|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4 - {0x0ff00090, 0x01500010, 3, CMP_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_R}}, // CMP ,, cond:4|0|0|0|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|Rs:4|0|type:2|1|Rm:4 - {0x0ff0f010, 0x01500000, 4, CMP_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_imm}}, // CMP ,{,} cond:4|0|0|0|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4 - {0x0ff00010, 0x01500000, 3, CMP_EQ, 0x1c04, instArgs{arg_R_16, arg_R_shift_imm}}, // CMP ,{,} cond:4|0|0|0|1|0|1|0|1|Rn:4|(0)|(0)|(0)|(0)|imm5:5|type:2|0|Rm:4 - {0x0ffffff0, 0x0320f0f0, 4, DBG_EQ, 0x1c04, instArgs{arg_option}}, // DBG #