Add support to the ARC disassembler for selecting instruction classes.
authorClaudiu Zissulescu <claziss@synopsys.com>
Wed, 20 Jul 2016 16:08:07 +0000 (17:08 +0100)
committerNick Clifton <nickc@redhat.com>
Wed, 20 Jul 2016 16:08:07 +0000 (17:08 +0100)
gas * testsuite/gas/arc/dsp.d: New file.
* testsuite/gas/arc/dsp.s: Likewise.
* testsuite/gas/arc/fpu.d: Likewise.
* testsuite/gas/arc/fpu.s: Likewise.
* testsuite/gas/arc/ext2op.d: Add specific disassembler option.
* testsuite/gas/arc/ext3op.d: Likewise.
* testsuite/gas/arc/tdpfp.d: Likewise.
* testsuite/gas/arc/tfpuda.d: Likewise.

opcodes * arc-dis.c (skipclass): New structure.
(decodelist): New variable.
(is_compatible_p): New function.
(new_element): Likewise.
(skip_class_p): Likewise.
(find_format_from_table): Use skip_class_p function.
(find_format): Decode first the extension instructions.
(print_insn_arc): Select either ARCEM or ARCHS based on elf
e_flags.
(parse_option): New function.
(parse_disassembler_options): Likewise.
(print_arc_disassembler_options): Likewise.
(print_insn_arc): Use parse_disassembler_options function.  Proper
select ARCv2 cpu variant.
* disassemble.c (disassembler_usage): Add ARC disassembler
options.

binutils* doc/binutils.texi (objdump): Add ARC disassembler options.
* testsuite/binutils-all/arc/dsp.s: New file.
* testsuite/binutils-all/arc/objdump.exp: Likewise.

include * dis-asm.h: Declare print_arc_disassembler_options.

19 files changed:
binutils/ChangeLog
binutils/NEWS
binutils/doc/binutils.texi
binutils/testsuite/binutils-all/arc/dsp.s [new file with mode: 0644]
binutils/testsuite/binutils-all/arc/objdump.exp [new file with mode: 0644]
gas/ChangeLog
gas/testsuite/gas/arc/dsp.d [new file with mode: 0644]
gas/testsuite/gas/arc/dsp.s [new file with mode: 0644]
gas/testsuite/gas/arc/ext2op.d
gas/testsuite/gas/arc/ext3op.d
gas/testsuite/gas/arc/fpu.d [new file with mode: 0644]
gas/testsuite/gas/arc/fpu.s [new file with mode: 0644]
gas/testsuite/gas/arc/tdpfp.d
gas/testsuite/gas/arc/tfpuda.d
include/ChangeLog
include/dis-asm.h
opcodes/ChangeLog
opcodes/arc-dis.c
opcodes/disassemble.c

index 6346e63..1d61f1c 100644 (file)
@@ -1,3 +1,10 @@
+2016-07-20  Claudiu Zissulescu  <claziss@synopsys.com>
+
+       * doc/binutils.texi (objdump): Add ARC disassembler options.
+       * testsuite/binutils-all/arc/dsp.s: New file.
+       * testsuite/binutils-all/arc/objdump.exp: Likewise.
+       * NEWS: Mention the new feature.
+
 2016-07-20  Nick Clifton  <nickc@redhat.com>
 
        * doc/binutils.texi (objcopy): Note that the localize symbol
index 56adfa2..9ec9724 100644 (file)
@@ -1,5 +1,8 @@
 -*- text -*-
 
+* The ARC port of objdump now accepts a -M option to specify the extra
+  instruction class(es) that should be disassembled.
+
 * The --remove-section option for objcopy and strip now accepts section
   patterns starting with an exclamation point to indicate a non-matching
   section.  A non-matching section is removed from the set of sections
index 2f4ea0a..6038c72 100644 (file)
@@ -2240,6 +2240,27 @@ some targets.  If it is necessary to specify more than one
 disassembler option then multiple @option{-M} options can be used or
 can be placed together into a comma separated list.
 
+For the ARC architecture the option can be used to specify the extra
+instruction classes that should be disassembled.  A comma separated
+list of one or more of the following values should be used:
+
+@table @code
+@item dsp
+Recognize DSP instructions.
+@item spfp
+Recognize FPX SP instructions.
+@item dpfp
+Recognize FPX DP instructions.
+@item quarkse_em
+Recognize FPU QuarkSE-EM instructions.
+@item fpuda
+Recognize double assist FPU instructions.
+@item fpus
+Recognize single precision FPU instructions.
+@item fpud
+Recognize double precision FPU instructions.
+@end table
+
 If the target is an ARM architecture then this switch can be used to
 select which register name set is used during disassembler.  Specifying
 @option{-M reg-names-std} (the default) will select the register names as
@@ -2367,6 +2388,15 @@ ROM dumps).  In these cases, the function entry mask would otherwise
 be decoded as VAX instructions, which would probably lead the rest
 of the function being wrongly disassembled.
 
+For ARC, @option{dsp} controls the printing of DSP instructions,
+@option{spfp} selects the printing of FPX single precision FP
+instructions, @option{dpfp} selects the printing of FPX double
+precision FP instructions, @option{quarkse_em} selects the printing of
+special QuarkSE-EM instructions, @option{fpuda} selects the printing
+of double precision assist instructions, @option{fpus} selects the
+printing of FPU single precision FP instructions, while @option{fpud}
+selects the printing of FPU souble precision FP instructions.
+
 @item -p
 @itemx --private-headers
 Print information that is specific to the object file format.  The exact
diff --git a/binutils/testsuite/binutils-all/arc/dsp.s b/binutils/testsuite/binutils-all/arc/dsp.s
new file mode 100644 (file)
index 0000000..8cca446
--- /dev/null
@@ -0,0 +1,5 @@
+       .cpu EM
+       .text
+       vmac2hnfr       r0,r2,r4
+       cmacchfr        r0,r2,r4
+       cmacchnfr       r0,r2,r4
diff --git a/binutils/testsuite/binutils-all/arc/objdump.exp b/binutils/testsuite/binutils-all/arc/objdump.exp
new file mode 100644 (file)
index 0000000..58c4a05
--- /dev/null
@@ -0,0 +1,55 @@
+#   Copyright (C) 2016 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
+
+if {![istarget "arc*-*-*"]} then {
+  return
+}
+
+if {[which $OBJDUMP] == 0} then {
+    perror "$OBJDUMP does not exist"
+    return
+}
+
+send_user "Version [binutil_version $OBJDUMP]"
+
+###########################
+# Set up the test of dsp.s
+###########################
+
+if {![binutils_assemble $srcdir/$subdir/dsp.s tmpdir/dsp.o]} then {
+    return
+}
+
+if [is_remote host] {
+    set objfile [remote_download host tmpdir/dsp.o]
+} else {
+    set objfile tmpdir/dsp.o
+}
+
+# Make sure that a warning message is generated (because the disassembly does
+# not match the assembled instructions, which has happened because the user
+# has not specified a -M option on the disassembler command line, and so the
+# disassembler has had to guess as the instruction class in use).
+
+set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS --disassemble $objfile"]
+
+set want "Warning: disassembly.*dsubh12\[ \t\]*r0,r2,r4.*dmulh12.f\[ \t\]*r0,r2,r4.*dmulh11.f"
+
+if [regexp $want $got] then {
+    pass "Warning test"
+} else {
+    fail "Warning test"
+}
index b3872ce..f0e5784 100644 (file)
@@ -1,3 +1,14 @@
+2016-07-20  Claudiu Zissulescu  <claziss@synopsys.com>
+
+       * testsuite/gas/arc/dsp.d: New file.
+       * testsuite/gas/arc/dsp.s: Likewise.
+       * testsuite/gas/arc/fpu.d: Likewise.
+       * testsuite/gas/arc/fpu.s: Likewise.
+       * testsuite/gas/arc/ext2op.d: Add specific disassembler option.
+       * testsuite/gas/arc/ext3op.d: Likewise.
+       * testsuite/gas/arc/tdpfp.d: Likewise.
+       * testsuite/gas/arc/tfpuda.d: Likewise.
+
 2016-07-20  Maciej W. Rozycki  <macro@imgtec.com>
 
        * config/tc-mips.c (mips_force_relocation): Remove
diff --git a/gas/testsuite/gas/arc/dsp.d b/gas/testsuite/gas/arc/dsp.d
new file mode 100644 (file)
index 0000000..22961ae
--- /dev/null
@@ -0,0 +1,96 @@
+#as: -mcpu=arcem
+#objdump: -dr --prefix-addresses --show-raw-insn -M dsp
+
+.*: +file format .*arc.*
+
+
+Disassembly of section .text:
+0x[0-9a-f]+ 3211 0100                  vmac2hnfr       r0,r2,r4
+0x[0-9a-f]+ 282f 0084                  abssh   r0,r2
+0x[0-9a-f]+ 282f 003f                  aslacc  r0
+0x[0-9a-f]+ 292f 003f                  aslsacc r0
+0x[0-9a-f]+ 2a0c 0100                  asrsr   r0,r2,r4
+0x[0-9a-f]+ 321b 8100                  cbflyhf0r       r0,r2,r4
+0x[0-9a-f]+ 302f 00b9                  cbflyhf1r       r0,r2
+0x[0-9a-f]+ 3209 8100                  cmacchfr        r0,r2,r4
+0x[0-9a-f]+ 3208 8100                  cmacchnfr       r0,r2,r4
+0x[0-9a-f]+ 3207 8100                  cmachfr r0,r2,r4
+0x[0-9a-f]+ 3206 8100                  cmachnfr        r0,r2,r4
+0x[0-9a-f]+ 3205 8100                  cmpychfr        r0,r2,r4
+0x[0-9a-f]+ 3202 8100                  cmpychnfr       r0,r2,r4
+0x[0-9a-f]+ 321b 0100                  cmpyhfmr        r0,r2,r4
+0x[0-9a-f]+ 3201 8100                  cmpyhfr r0,r2,r4
+0x[0-9a-f]+ 3200 8100                  cmpyhnfr        r0,r2,r4
+0x[0-9a-f]+ 2b2f 003f                  divacc  r0
+0x[0-9a-f]+ 3218 0100                  dmachbl r0,r2,r4
+0x[0-9a-f]+ 3219 0100                  dmachbm r0,r2,r4
+0x[0-9a-f]+ 2a2c 0100                  dmachf  r0,r2,r4
+0x[0-9a-f]+ 2a2d 0100                  dmachfr r0,r2,r4
+0x[0-9a-f]+ 3216 0100                  dmpyhbl r0,r2,r4
+0x[0-9a-f]+ 3217 0100                  dmpyhbm r0,r2,r4
+0x[0-9a-f]+ 2a2a 0100                  dmpyhf  r0,r2,r4
+0x[0-9a-f]+ 2a2b 0100                  dmpyhfr r0,r2,r4
+0x[0-9a-f]+ 2a28 0100                  dmpyhwf r0,r2,r4
+0x[0-9a-f]+ 2c2f 803f                  flagacc r0
+0x[0-9a-f]+ 282f 0098                  getacc  r0,r2
+0x[0-9a-f]+ 320c 0100                  macf    r0,r2,r4
+0x[0-9a-f]+ 320d 0100                  macfr   r0,r2,r4
+0x[0-9a-f]+ 3222 0100                  macwhfm r0,r2,r4
+0x[0-9a-f]+ 3223 0100                  macwhfmr        r0,r2,r4
+0x[0-9a-f]+ 321d 0100                  macwhl  r0,r2,r4
+0x[0-9a-f]+ 321f 0100                  macwhul r0,r2,r4
+0x[0-9a-f]+ 320a 0100                  mpyf    r0,r2,r4
+0x[0-9a-f]+ 320b 0100                  mpyfr   r0,r2,r4
+0x[0-9a-f]+ 3224 0100                  mpywhfl r0,r2,r4
+0x[0-9a-f]+ 3225 0100                  mpywhflr        r0,r2,r4
+0x[0-9a-f]+ 3220 0100                  mpywhfm r0,r2,r4
+0x[0-9a-f]+ 3221 0100                  mpywhfmr        r0,r2,r4
+0x[0-9a-f]+ 321c 0100                  mpywhl  r0,r2,r4
+0x[0-9a-f]+ 321e 0100                  mpywhul r0,r2,r4
+0x[0-9a-f]+ 3215 0100                  msubdf  r0,r2,r4
+0x[0-9a-f]+ 320e 0100                  msubf   r0,r2,r4
+0x[0-9a-f]+ 320f 0100                  msubfr  r0,r2,r4
+0x[0-9a-f]+ 282f 0086                  negsh   r0,r2
+0x[0-9a-f]+ 282f 0099                  normacc r0,r2
+0x[0-9a-f]+ 282f 0083                  rndh    r0,r2
+0x[0-9a-f]+ 282f 0082                  sath    r0,r2
+0x[0-9a-f]+ 2a0d 8100                  setacc  r0,r2,r4
+0x[0-9a-f]+ 2a2f 003f                  sqrtacc r0
+0x[0-9a-f]+ 282f 00a8                  vabs2h  r0,r2
+0x[0-9a-f]+ 282f 00a9                  vabss2h r0,r2
+0x[0-9a-f]+ 2a24 0100                  vadd4b  r0,r2,r4
+0x[0-9a-f]+ 2a14 8100                  vadds2h r0,r2,r4
+0x[0-9a-f]+ 2a16 8100                  vaddsubs2h      r0,r2,r4
+0x[0-9a-f]+ 2a0d 0100                  valgn2h r0,r2,r4
+0x[0-9a-f]+ 2a21 0100                  vasl2h  r0,r2,r4
+0x[0-9a-f]+ 2a21 8100                  vasls2h r0,r2,r4
+0x[0-9a-f]+ 2a22 0100                  vasr2h  r0,r2,r4
+0x[0-9a-f]+ 2a22 8100                  vasrs2h r0,r2,r4
+0x[0-9a-f]+ 2a23 8100                  vasrsr2h        r0,r2,r4
+0x[0-9a-f]+ 282f 00a4                  vext2bhl        r0,r2
+0x[0-9a-f]+ 282f 00a5                  vext2bhm        r0,r2
+0x[0-9a-f]+ 2a23 0100                  vlsr2h  r0,r2,r4
+0x[0-9a-f]+ 2a1e 0100                  vmac2h  r0,r2,r4
+0x[0-9a-f]+ 2a1e 8100                  vmac2hf r0,r2,r4
+0x[0-9a-f]+ 2a1f 8100                  vmac2hfr        r0,r2,r4
+0x[0-9a-f]+ 2a1f 0100                  vmac2hu r0,r2,r4
+0x[0-9a-f]+ 2a24 8100                  vmax2h  r0,r2,r4
+0x[0-9a-f]+ 2a25 8100                  vmin2h  r0,r2,r4
+0x[0-9a-f]+ 2a1c 0100                  vmpy2h  r0,r2,r4
+0x[0-9a-f]+ 2a1c 8100                  vmpy2hf r0,r2,r4
+0x[0-9a-f]+ 2a1d 8100                  vmpy2hfr        r0,r2,r4
+0x[0-9a-f]+ 2a1d 0100                  vmpy2hu r0,r2,r4
+0x[0-9a-f]+ 2a20 0100                  vmpy2hwf        r0,r2,r4
+0x[0-9a-f]+ 3204 0100                  vmsub2hf        r0,r2,r4
+0x[0-9a-f]+ 3203 0100                  vmsub2hfr       r0,r2,r4
+0x[0-9a-f]+ 3211 8100                  vmsub2hnfr      r0,r2,r4
+0x[0-9a-f]+ 282f 00aa                  vneg2h  r0,r2
+0x[0-9a-f]+ 282f 00ab                  vnegs2h r0,r2
+0x[0-9a-f]+ 282f 00ac                  vnorm2h r0,r2
+0x[0-9a-f]+ 282f 00a2                  vrep2hl r0,r2
+0x[0-9a-f]+ 282f 00a3                  vrep2hm r0,r2
+0x[0-9a-f]+ 282f 00a6                  vsext2bhl       r0,r2
+0x[0-9a-f]+ 282f 00a7                  vsext2bhm       r0,r2
+0x[0-9a-f]+ 2a25 0100                  vsub4b  r0,r2,r4
+0x[0-9a-f]+ 2a17 8100                  vsubadds2h      r0,r2,r4
+0x[0-9a-f]+ 2a15 8100                  vsubs2h r0,r2,r4
diff --git a/gas/testsuite/gas/arc/dsp.s b/gas/testsuite/gas/arc/dsp.s
new file mode 100644 (file)
index 0000000..2847af6
--- /dev/null
@@ -0,0 +1,90 @@
+#Test if disassembler correctly prints DSP instructions.
+       vmac2hnfr       r0,r2,r4
+       abssh           r0,r2
+       aslacc          r0
+       aslsacc         r0
+       asrsr           r0,r2,r4
+       cbflyhf0r       r0,r2,r4
+       cbflyhf1r       r0,r2
+       cmacchfr        r0,r2,r4
+       cmacchnfr       r0,r2,r4
+       cmachfr         r0,r2,r4
+       cmachnfr        r0,r2,r4
+       cmpychfr        r0,r2,r4
+       cmpychnfr       r0,r2,r4
+       cmpyhfmr        r0,r2,r4
+       cmpyhfr         r0,r2,r4
+       cmpyhnfr        r0,r2,r4
+       divacc          r0
+       dmachbl         r0,r2,r4
+       dmachbm         r0,r2,r4
+       dmachf          r0,r2,r4
+       dmachfr         r0,r2,r4
+       dmpyhbl         r0,r2,r4
+       dmpyhbm         r0,r2,r4
+       dmpyhf          r0,r2,r4
+       dmpyhfr         r0,r2,r4
+       dmpyhwf         r0,r2,r4
+       flagacc         r0
+       getacc          r0,r2
+       macf            r0,r2,r4
+       macfr           r0,r2,r4
+       macwhfm         r0,r2,r4
+       macwhfmr        r0,r2,r4
+       macwhl          r0,r2,r4
+       macwhul         r0,r2,r4
+       mpyf            r0,r2,r4
+       mpyfr           r0,r2,r4
+       mpywhfl         r0,r2,r4
+       mpywhflr        r0,r2,r4
+       mpywhfm         r0,r2,r4
+       mpywhfmr        r0,r2,r4
+       mpywhl          r0,r2,r4
+       mpywhul         r0,r2,r4
+       msubdf          r0,r2,r4
+       msubf           r0,r2,r4
+       msubfr          r0,r2,r4
+       negsh           r0,r2
+       normacc         r0,r2
+       rndh            r0,r2
+       sath            r0,r2
+       setacc          r0,r2,r4
+       sqrtacc         r0
+       vabs2h          r0,r2
+       vabss2h         r0,r2
+       vadd4b          r0,r2,r4
+       vadds2h         r0,r2,r4
+       vaddsubs2h      r0,r2,r4
+       valgn2h         r0,r2,r4
+       vasl2h          r0,r2,r4
+       vasls2h         r0,r2,r4
+       vasr2h          r0,r2,r4
+       vasrs2h         r0,r2,r4
+       vasrsr2h        r0,r2,r4
+       vext2bhl        r0,r2
+       vext2bhm        r0,r2
+       vlsr2h          r0,r2,r4
+       vmac2h          r0,r2,r4
+       vmac2hf         r0,r2,r4
+       vmac2hfr        r0,r2,r4
+       vmac2hu         r0,r2,r4
+       vmax2h          r0,r2,r4
+       vmin2h          r0,r2,r4
+       vmpy2h          r0,r2,r4
+       vmpy2hf         r0,r2,r4
+       vmpy2hfr        r0,r2,r4
+       vmpy2hu         r0,r2,r4
+       vmpy2hwf        r0,r2,r4
+       vmsub2hf        r0,r2,r4
+       vmsub2hfr       r0,r2,r4
+       vmsub2hnfr      r0,r2,r4
+       vneg2h          r0,r2
+       vnegs2h         r0,r2
+       vnorm2h         r0,r2
+       vrep2hl         r0,r2
+       vrep2hm         r0,r2
+       vsext2bhl       r0,r2
+       vsext2bhm       r0,r2
+       vsub4b          r0,r2,r4
+       vsubadds2h      r0,r2,r4
+       vsubs2h         r0,r2,r4
index 144989e..00ef6ac 100644 (file)
@@ -1,5 +1,5 @@
 #as: -mcpu=arcem
-#objdump: -dr
+#objdump: -dr -M quarkse_em
 
 .*: +file format .*arc.*
 
index 926a13c..7a63f14 100644 (file)
@@ -1,5 +1,5 @@
 #as: -mcpu=arcem
-#objdump: -dr
+#objdump: -dr -M quarkse_em
 
 .*: +file format .*arc.*
 
diff --git a/gas/testsuite/gas/arc/fpu.d b/gas/testsuite/gas/arc/fpu.d
new file mode 100644 (file)
index 0000000..ab805da
--- /dev/null
@@ -0,0 +1,29 @@
+#as: -mcpu=archs
+#objdump: -dr --prefix-addresses --show-raw-insn
+
+.*: +file format .*arc.*
+
+
+Disassembly of section .text:
+0x[0-9a-f]+ 3208 0100                  fcvt32  r0,r2,r4
+0x[0-9a-f]+ 3209 0100                  fcvt32_64       r0,r2,r4
+0x[0-9a-f]+ 3238 0100                  fcvt64  r0,r2,r4
+0x[0-9a-f]+ 3239 0100                  fcvt64_32       r0,r2,r4
+0x[0-9a-f]+ 3231 0100                  fdadd   r0,r2,r4
+0x[0-9a-f]+ 3033 8080                  fdcmp   r0,r2
+0x[0-9a-f]+ 3034 8080                  fdcmpf  r0,r2
+0x[0-9a-f]+ 3237 0100                  fddiv   r0,r2,r4
+0x[0-9a-f]+ 3235 0100                  fdmadd  r0,r2,r4
+0x[0-9a-f]+ 3236 0100                  fdmsub  r0,r2,r4
+0x[0-9a-f]+ 3230 0100                  fdmul   r0,r2,r4
+0x[0-9a-f]+ 302f 0081                  fdsqrt  r0,r2
+0x[0-9a-f]+ 3232 0100                  fdsub   r0,r2,r4
+0x[0-9a-f]+ 3201 0100                  fsadd   r0,r2,r4
+0x[0-9a-f]+ 3003 8080                  fscmp   r0,r2
+0x[0-9a-f]+ 3004 8080                  fscmpf  r0,r2
+0x[0-9a-f]+ 3207 0100                  fsdiv   r0,r2,r4
+0x[0-9a-f]+ 3205 0100                  fsmadd  r0,r2,r4
+0x[0-9a-f]+ 3206 0100                  fsmsub  r0,r2,r4
+0x[0-9a-f]+ 3200 0100                  fsmul   r0,r2,r4
+0x[0-9a-f]+ 302f 0080                  fssqrt  r0,r2
+0x[0-9a-f]+ 3202 0100                  fssub   r0,r2,r4
diff --git a/gas/testsuite/gas/arc/fpu.s b/gas/testsuite/gas/arc/fpu.s
new file mode 100644 (file)
index 0000000..78c18bf
--- /dev/null
@@ -0,0 +1,24 @@
+# Test if all fpu ops are correctly disassembled as they share the
+# same opcode space with FPX instructions.
+       fcvt32          r0,r2,r4
+       fcvt32_64       r0,r2,r4
+       fcvt64          r0,r2,r4
+       fcvt64_32       r0,r2,r4
+       fdadd           r0,r2,r4
+       fdcmp           r0,r2
+       fdcmpf          r0,r2
+       fddiv           r0,r2,r4
+       fdmadd          r0,r2,r4
+       fdmsub          r0,r2,r4
+       fdmul           r0,r2,r4
+       fdsqrt          r0,r2
+       fdsub           r0,r2,r4
+       fsadd           r0,r2,r4
+       fscmp           r0,r2
+       fscmpf          r0,r2
+       fsdiv           r0,r2,r4
+       fsmadd          r0,r2,r4
+       fsmsub          r0,r2,r4
+       fsmul           r0,r2,r4
+       fssqrt          r0,r2
+       fssub           r0,r2,r4
index 6475ebc..a2edb0e 100644 (file)
@@ -1,5 +1,5 @@
 #as:-mcpu=arcem -mdpfp
-#objdump: -dr
+#objdump: -dr -M dpfp
 #source: tfpx.s
 
 .*: +file format .*arc.*
index a6645a5..640500e 100644 (file)
@@ -1,5 +1,5 @@
 #as:-mcpu=arcem -mfpuda
-#objdump: -dr
+#objdump: -dr -M fpuda
 #source: tfpx.s
 
 .*: +file format .*arc.*
index f000f72..158be71 100644 (file)
@@ -1,3 +1,7 @@
+2016-07-20  Claudiu Zissulescu  <claziss@synopsys.com>
+
+       * dis-asm.h: Declare print_arc_disassembler_options.
+
 2016-07-15  Thomas Preud'homme  <thomas.preudhomme@arm.com>
 
        * bfdlink.h (struct bfd_link_info): Declare new ldscript_def and
index 60bbc8d..05bfa37 100644 (file)
@@ -328,6 +328,7 @@ extern void print_i386_disassembler_options (FILE *);
 extern void print_mips_disassembler_options (FILE *);
 extern void print_ppc_disassembler_options (FILE *);
 extern void print_arm_disassembler_options (FILE *);
+extern void print_arc_disassembler_options (FILE *);
 extern void parse_arm_disassembler_option (char *);
 extern void print_s390_disassembler_options (FILE *);
 extern int  get_arm_regname_num_options (void);
index 20bcdde..f073e32 100644 (file)
@@ -1,3 +1,22 @@
+2016-07-20  Claudiu Zissulescu  <claziss@synopsys.com>
+
+       * arc-dis.c (skipclass): New structure.
+       (decodelist): New variable.
+       (is_compatible_p): New function.
+       (new_element): Likewise.
+       (skip_class_p): Likewise.
+       (find_format_from_table): Use skip_class_p function.
+       (find_format): Decode first the extension instructions.
+       (print_insn_arc): Select either ARCEM or ARCHS based on elf
+       e_flags.
+       (parse_option): New function.
+       (parse_disassembler_options): Likewise.
+       (print_arc_disassembler_options): Likewise.
+       (print_insn_arc): Use parse_disassembler_options function.  Proper
+       select ARCv2 cpu variant.
+       * disassemble.c (disassembler_usage): Add ARC disassembler
+       options.
+
 2016-07-13  Maciej W. Rozycki  <macro@imgtec.com>
 
        * mips-opc.c (mips_builtin_opcodes): Remove the INSN2_ALIAS
index 1d1dcd8..7b78bdc 100644 (file)
 #include <assert.h>
 #include "dis-asm.h"
 #include "opcode/arc.h"
+#include "elf/arc.h"
 #include "arc-dis.h"
 #include "arc-ext.h"
+#include "elf-bfd.h"
+#include "libiberty.h"
+#include "opintl.h"
 
 /* Structure used to iterate over, and extract the values for, operands of
    an opcode.  */
@@ -81,6 +85,20 @@ static const char * const regnames[64] =
   "r56", "r57", "ACCL", "ACCH", "lp_count", "rezerved", "LIMM", "pcl"
 };
 
+/* This structure keeps track which instruction class(es)
+   should be ignored durring disassembling.  */
+
+typedef struct skipclass
+{
+  insn_class_t     insn_class;
+  insn_subclass_t  subclass;
+  struct skipclass *nxt;
+} skipclass_t, *linkclass;
+
+/* Intial classes of instructions to be consider first when
+   disassembling.  */
+static linkclass decodelist = NULL;
+
 /* Macros section.  */
 
 #ifdef DEBUG
@@ -101,6 +119,88 @@ static const char * const regnames[64] =
 
 /* Functions implementation.  */
 
+/* Return TRUE when two classes are not opcode conflicting.  */
+
+static bfd_boolean
+is_compatible_p (insn_class_t     classA,
+                insn_subclass_t  sclassA,
+                insn_class_t     classB,
+                insn_subclass_t  sclassB)
+{
+  if (classA == DSP && sclassB == DPX)
+    return FALSE;
+  if (sclassA == DPX && classB == DSP)
+    return FALSE;
+  return TRUE;
+}
+
+/* Add a new element to the decode list.  */
+
+static void
+add_to_decodelist (insn_class_t     insn_class,
+                  insn_subclass_t  subclass)
+{
+  linkclass t = (linkclass) xmalloc (sizeof (skipclass_t));
+
+  t->insn_class = insn_class;
+  t->subclass = subclass;
+  t->nxt = decodelist;
+  decodelist = t;
+}
+
+/* Return TRUE if we need to skip the opcode from being
+   disassembled.  */
+
+static bfd_boolean
+skip_this_opcode (const struct arc_opcode *  opcode,
+                 struct disassemble_info *  info)
+{
+  linkclass t = decodelist;
+  bfd_boolean addme = TRUE;
+
+  /* Check opcode for major 0x06, return if it is not in.  */
+  if (OPCODE (opcode->opcode) != 0x06)
+    return FALSE;
+
+  while (t != NULL
+        && is_compatible_p (t->insn_class, t->subclass,
+                            opcode->insn_class, opcode->subclass))
+    {
+      if ((t->insn_class == opcode->insn_class)
+         && (t->subclass == opcode->subclass))
+       addme = FALSE;
+      t = t->nxt;
+    }
+
+  /* If we found an incompatibility then we must skip.  */
+  if (t != NULL)
+    return TRUE;
+  
+  /* Even if we do not precisely know the if the right mnemonics
+     is correctly displayed, keep the disassmbled code class
+     consistent.  */
+  if (addme)
+    {
+      switch (opcode->insn_class)
+       {
+       case DSP:
+       case FLOAT:
+         /* Add to the conflict list only the classes which
+            counts.  */
+         add_to_decodelist (opcode->insn_class, opcode->subclass);
+         /* Warn if we have to decode an opcode and no preferred
+            classes have been chosen.  */
+         info->fprintf_func (info->stream, _("\n\
+Warning: disassembly may be wrong due to guessed opcode class choice.\n\
+ Use -M<class[,class]> to select the correct opcode class(es).\n\t\t\t\t"));
+         break;
+       default:
+         break;
+       }
+    }
+  return FALSE;
+}
+
 static bfd_vma
 bfd_getm32 (unsigned int data)
 {
@@ -111,7 +211,7 @@ bfd_getm32 (unsigned int data)
   return value;
 }
 
-static int
+static bfd_boolean
 special_flag_p (const char *opname,
                const char *flgname)
 {
@@ -133,124 +233,137 @@ special_flag_p (const char *opname,
            break; /* End of the array.  */
 
          if (strcmp (flgname, arc_flag_operands[flgidx].name) == 0)
-           return 1;
+           return TRUE;
        }
     }
-  return 0;
+  return FALSE;
 }
 
 /* Find opcode from ARC_TABLE given the instruction described by INSN and
    INSNLEN.  The ISA_MASK restricts the possible matches in ARC_TABLE.  */
 
 static const struct arc_opcode *
-find_format_from_table (const struct arc_opcode *arc_table,
-                        unsigned *insn, unsigned int insn_len,
-                        unsigned isa_mask, bfd_boolean *has_limm)
+find_format_from_table (struct disassemble_info *info,
+                       const struct arc_opcode *arc_table,
+                        unsigned *insn,
+                       unsigned int insn_len,
+                        unsigned isa_mask,
+                       bfd_boolean *has_limm,
+                       bfd_boolean overlaps)
 {
   unsigned int i = 0;
   const struct arc_opcode *opcode = NULL;
   const unsigned char *opidx;
   const unsigned char *flgidx;
 
-  do {
-    bfd_boolean invalid = FALSE;
+  do
+    {
+      bfd_boolean invalid = FALSE;
 
-    opcode = &arc_table[i++];
+      opcode = &arc_table[i++];
 
-    if (ARC_SHORT (opcode->mask) && (insn_len == 2))
-      {
-       if (OPCODE_AC (opcode->opcode) != OPCODE_AC (insn[0]))
-         continue;
-      }
-    else if (!ARC_SHORT (opcode->mask) && (insn_len == 4))
-      {
-       if (OPCODE (opcode->opcode) != OPCODE (insn[0]))
-         continue;
-      }
-    else
-      continue;
+      if (ARC_SHORT (opcode->mask) && (insn_len == 2))
+       {
+         if (OPCODE_AC (opcode->opcode) != OPCODE_AC (insn[0]))
+           continue;
+       }
+      else if (!ARC_SHORT (opcode->mask) && (insn_len == 4))
+       {
+         if (OPCODE (opcode->opcode) != OPCODE (insn[0]))
+           continue;
+       }
+      else
+       continue;
 
-    if ((insn[0] ^ opcode->opcode) & opcode->mask)
-      continue;
+      if ((insn[0] ^ opcode->opcode) & opcode->mask)
+       continue;
 
-    if (!(opcode->cpu & isa_mask))
-      continue;
+      if (!(opcode->cpu & isa_mask))
+       continue;
 
-    *has_limm = FALSE;
+      *has_limm = FALSE;
 
-    /* Possible candidate, check the operands.  */
-    for (opidx = opcode->operands; *opidx; opidx++)
-      {
-       int value;
-       const struct arc_operand *operand = &arc_operands[*opidx];
+      /* Possible candidate, check the operands.  */
+      for (opidx = opcode->operands; *opidx; opidx++)
+       {
+         int value;
+         const struct arc_operand *operand = &arc_operands[*opidx];
 
-       if (operand->flags & ARC_OPERAND_FAKE)
-         continue;
+         if (operand->flags & ARC_OPERAND_FAKE)
+           continue;
 
-       if (operand->extract)
-         value = (*operand->extract) (insn[0], &invalid);
-       else
-         value = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1);
-
-       /* Check for LIMM indicator.  If it is there, then make sure
-          we pick the right format.  */
-       if (operand->flags & ARC_OPERAND_IR
-           && !(operand->flags & ARC_OPERAND_LIMM))
-         {
-           if ((value == 0x3E && insn_len == 4)
-               || (value == 0x1E && insn_len == 2))
-             {
-               invalid = TRUE;
-               break;
-             }
-         }
-
-        if (operand->flags & ARC_OPERAND_LIMM
-            && !(operand->flags & ARC_OPERAND_DUPLICATE))
-          *has_limm = TRUE;
-      }
-
-    /* Check the flags.  */
-    for (flgidx = opcode->flags; *flgidx; flgidx++)
-      {
-       /* Get a valid flag class.  */
-       const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
-       const unsigned *flgopridx;
-       int foundA = 0, foundB = 0;
-       unsigned int value;
-
-       /* Check first the extensions.  */
-       if (cl_flags->flag_class & F_CLASS_EXTEND)
-         {
-           value = (insn[0] & 0x1F);
-           if (arcExtMap_condCodeName (value))
-             continue;
-         }
-       for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
-         {
-           const struct arc_flag_operand *flg_operand =
-             &arc_flag_operands[*flgopridx];
-
-           value = (insn[0] >> flg_operand->shift)
-             & ((1 << flg_operand->bits) - 1);
-           if (value == flg_operand->code)
-             foundA = 1;
-           if (value)
-             foundB = 1;
-         }
-       if (!foundA && foundB)
-         {
-           invalid = TRUE;
-           break;
-         }
-      }
-
-    if (invalid)
-      continue;
-
-    /* The instruction is valid.  */
-    return opcode;
-  } while (opcode->mask);
+         if (operand->extract)
+           value = (*operand->extract) (insn[0], &invalid);
+         else
+           value = (insn[0] >> operand->shift) & ((1 << operand->bits) - 1);
+
+         /* Check for LIMM indicator.  If it is there, then make sure
+            we pick the right format.  */
+         if (operand->flags & ARC_OPERAND_IR
+             && !(operand->flags & ARC_OPERAND_LIMM))
+           {
+             if ((value == 0x3E && insn_len == 4)
+                 || (value == 0x1E && insn_len == 2))
+               {
+                 invalid = TRUE;
+                 break;
+               }
+           }
+
+         if (operand->flags & ARC_OPERAND_LIMM
+             && !(operand->flags & ARC_OPERAND_DUPLICATE))
+           *has_limm = TRUE;
+       }
+
+      /* Check the flags.  */
+      for (flgidx = opcode->flags; *flgidx; flgidx++)
+       {
+         /* Get a valid flag class.  */
+         const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
+         const unsigned *flgopridx;
+         int foundA = 0, foundB = 0;
+         unsigned int value;
+
+         /* Check first the extensions.  */
+         if (cl_flags->flag_class & F_CLASS_EXTEND)
+           {
+             value = (insn[0] & 0x1F);
+             if (arcExtMap_condCodeName (value))
+               continue;
+           }
+
+         for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
+           {
+             const struct arc_flag_operand *flg_operand =
+               &arc_flag_operands[*flgopridx];
+
+             value = (insn[0] >> flg_operand->shift)
+               & ((1 << flg_operand->bits) - 1);
+             if (value == flg_operand->code)
+               foundA = 1;
+             if (value)
+               foundB = 1;
+           }
+
+         if (!foundA && foundB)
+           {
+             invalid = TRUE;
+             break;
+           }
+       }
+
+      if (invalid)
+       continue;
+
+      if (insn_len == 4
+         && overlaps
+         && skip_this_opcode (opcode, info))
+       continue;
+
+      /* The instruction is valid.  */
+      return opcode;
+    }
+  while (opcode->mask);
 
   return NULL;
 }
@@ -344,44 +457,42 @@ find_format_long_instructions (unsigned *insn,
    the opcode's operands.  */
 
 static bfd_boolean
-find_format (bfd_vma memaddr, unsigned *insn, unsigned int *insn_len,
-             unsigned isa_mask, struct disassemble_info *info,
-             const struct arc_opcode **opcode_result,
-             struct arc_operand_iterator *iter)
+find_format (bfd_vma                       memaddr,
+            unsigned *                    insn,
+            unsigned int *                insn_len,
+             unsigned                      isa_mask,
+            struct disassemble_info *     info,
+             const struct arc_opcode **    opcode_result,
+             struct arc_operand_iterator * iter)
 {
-  const struct arc_opcode *opcode;
+  const struct arc_opcode *opcode = NULL;
   bfd_boolean needs_limm;
+  const extInstruction_t *einsn;
 
-  /* Find the first match in the opcode table.  */
-  opcode = find_format_from_table (arc_opcodes, insn, *insn_len,
-                                   isa_mask, &needs_limm);
-
-  if (opcode == NULL)
+  /* First, try the extension instructions.  */
+  einsn = arcExtMap_insn (OPCODE (insn[0]), insn[0]);
+  if (einsn != NULL)
     {
-      const extInstruction_t *einsn;
+      const char *errmsg = NULL;
 
-      /* No instruction found.  Try the extensions.  */
-      einsn = arcExtMap_insn (OPCODE (insn[0]), insn[0]);
-      if (einsn != NULL)
+      opcode = arcExtMap_genOpcode (einsn, isa_mask, &errmsg);
+      if (opcode == NULL)
        {
-         const char *errmsg = NULL;
-         opcode = arcExtMap_genOpcode (einsn, isa_mask, &errmsg);
-         if (opcode == NULL)
-           {
-             (*info->fprintf_func) (info->stream,
-                                    "An error occured while "
-                                    "generating the extension instruction "
-                                    "operations");
-              *opcode_result = NULL;
-             return FALSE;
-           }
-
-         opcode = find_format_from_table (opcode, insn, *insn_len,
-                                           isa_mask, &needs_limm);
-         assert (opcode != NULL);
+         (*info->fprintf_func) (info->stream, "\
+An error occured while generating the extension instruction operations");
+         *opcode_result = NULL;
+         return FALSE;
        }
+
+      opcode = find_format_from_table (info, opcode, insn, *insn_len,
+                                      isa_mask, &needs_limm, FALSE);
     }
 
+  /* Then, try finding the first match in the opcode table.  */
+  if (opcode == NULL)
+    opcode = find_format_from_table (info, arc_opcodes, insn, *insn_len,
+                                    isa_mask, &needs_limm, TRUE);
+
   if (needs_limm && opcode != NULL)
     {
       bfd_byte buffer[4];
@@ -697,6 +808,65 @@ operand_iterator_next (struct arc_operand_iterator *iter,
   return TRUE;
 }
 
+/* Helper for parsing the options.  */
+
+static void
+parse_option (char *option)
+{
+  if (CONST_STRNEQ (option, "dsp"))
+    add_to_decodelist (DSP, NONE);
+
+  else if (CONST_STRNEQ (option, "spfp"))
+    add_to_decodelist (FLOAT, SPX);
+
+  else if (CONST_STRNEQ (option, "dpfp"))
+    add_to_decodelist (FLOAT, DPX);
+
+  else if (CONST_STRNEQ (option, "quarkse_em"))
+    add_to_decodelist (FLOAT, QUARKSE);
+
+  else if (CONST_STRNEQ (option, "fpuda"))
+    add_to_decodelist (FLOAT, DPA);
+
+  else if (CONST_STRNEQ (option, "fpud"))
+    {
+      add_to_decodelist (FLOAT, SP);
+      add_to_decodelist (FLOAT, CVT);
+    }
+
+  else if (CONST_STRNEQ (option, "fpus"))
+    {
+      add_to_decodelist (FLOAT, DP);
+      add_to_decodelist (FLOAT, CVT);
+    }
+  else
+    fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
+}
+
+/* Go over the options list and parse it.  */
+
+static void
+parse_disassembler_options (char *options)
+{
+  if (options == NULL)
+    return;
+
+  while (*options)
+    {
+      /* Skip empty options.  */
+      if (*options == ',')
+       {
+         ++ options;
+         continue;
+       }
+
+      parse_option (options);
+
+      while (*options != ',' && *options != '\0')
+       ++ options;
+    }
+}
+
 /* Disassemble ARC instructions.  */
 
 static int
@@ -716,11 +886,23 @@ print_insn_arc (bfd_vma memaddr,
   const struct arc_operand *operand;
   int value;
   struct arc_operand_iterator iter;
+  Elf_Internal_Ehdr *header = NULL;
+
+  if (info->disassembler_options)
+    {
+      parse_disassembler_options (info->disassembler_options);
+
+      /* Avoid repeated parsing of the options.  */
+      info->disassembler_options = NULL;
+    }
 
   memset (&iter, 0, sizeof (iter));
   lowbyte  = ((info->endian == BFD_ENDIAN_LITTLE) ? 1 : 0);
   highbyte = ((info->endian == BFD_ENDIAN_LITTLE) ? 0 : 1);
 
+  if (info->section && info->section->owner)
+    header = elf_elfheader (info->section->owner);
+
   switch (info->mach)
     {
     case bfd_mach_arc_arc700:
@@ -733,7 +915,15 @@ print_insn_arc (bfd_vma memaddr,
 
     case bfd_mach_arc_arcv2:
     default:
-      isa_mask = ARC_OPCODE_ARCv2HS | ARC_OPCODE_ARCv2EM;
+      isa_mask = ARC_OPCODE_ARCv2EM;
+      if ((header->e_flags & EF_ARC_MACH_MSK) == EF_ARC_CPU_ARCV2HS)
+       {
+         isa_mask = ARC_OPCODE_ARCv2HS;
+         /* FPU instructions are not extensions for HS.  */
+         add_to_decodelist (FLOAT, SP);
+         add_to_decodelist (FLOAT, DP);
+         add_to_decodelist (FLOAT, CVT);
+       }
       break;
     }
 
@@ -810,6 +1000,7 @@ print_insn_arc (bfd_vma memaddr,
 
   insn_len = arc_insn_length (buffer[lowbyte], buffer[highbyte], info);
   pr_debug ("instruction length = %d bytes\n", insn_len);
+
   switch (insn_len)
     {
     case 2:
@@ -1042,6 +1233,30 @@ arcAnalyzeInstr (bfd_vma memaddr,
   return ret;
 }
 
+void
+print_arc_disassembler_options (FILE *stream)
+{
+  fprintf (stream, _("\n\
+The following ARC specific disassembler options are supported for use \n\
+with -M switch (multiple options should be separated by commas):\n"));
+
+  fprintf (stream, _("\
+  dsp             Recognize DSP instructions.\n"));
+  fprintf (stream, _("\
+  spfp            Recognize FPX SP instructions.\n"));
+  fprintf (stream, _("\
+  dpfp            Recognize FPX DP instructions.\n"));
+  fprintf (stream, _("\
+  quarkse_em      Recognize FPU QuarkSE-EM instructions.\n"));
+  fprintf (stream, _("\
+  fpuda           Recognize double assist FPU instructions.\n"));
+  fprintf (stream, _("\
+  fpus            Recognize single precision FPU instructions.\n"));
+  fprintf (stream, _("\
+  fpud            Recognize double precision FPU instructions.\n"));
+}
+
+
 /* Local variables:
    eval: (c-set-style "gnu")
    indent-tabs-mode: t
index b818d8b..45ae34e 100644 (file)
@@ -547,6 +547,9 @@ disassembler_usage (FILE *stream ATTRIBUTE_UNUSED)
 #ifdef ARCH_aarch64
   print_aarch64_disassembler_options (stream);
 #endif
+#ifdef ARCH_arc
+  print_arc_disassembler_options (stream);
+#endif
 #ifdef ARCH_arm
   print_arm_disassembler_options (stream);
 #endif