Commit aa0aa4fa31054a9488fd49c29c6ab12e2e85be58

Authored by bellard
1 parent 84fa15d8

added ARM and Sparc disassemblers


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@214 c046a42c-6fe2-441c-8c8c-71466251a162

Too many changes to show.

To preserve performance only 5 of 6 files are displayed.

arm-dis.c 0 → 100644
  1 +/* Instruction printing code for the ARM
  2 + Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
  3 + Free Software Foundation, Inc.
  4 + Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
  5 + Modification by James G. Smith (jsmith@cygnus.co.uk)
  6 +
  7 +This file is part of libopcodes.
  8 +
  9 +This program is free software; you can redistribute it and/or modify it under
  10 +the terms of the GNU General Public License as published by the Free
  11 +Software Foundation; either version 2 of the License, or (at your option)
  12 +any later version.
  13 +
  14 +This program is distributed in the hope that it will be useful, but WITHOUT
  15 +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  16 +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  17 +more details.
  18 +
  19 +You should have received a copy of the GNU General Public License
  20 +along with this program; if not, write to the Free Software
  21 +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
  22 +
  23 +#include "dis-asm.h"
  24 +
  25 +struct arm_opcode {
  26 + unsigned long value, mask; /* recognise instruction if (op&mask)==value */
  27 + char *assembler; /* how to disassemble this instruction */
  28 +};
  29 +
  30 +struct thumb_opcode
  31 +{
  32 + unsigned short value, mask; /* recognise instruction if (op&mask)==value */
  33 + char * assembler; /* how to disassemble this instruction */
  34 +};
  35 +
  36 +/* format of the assembler string :
  37 +
  38 + %% %
  39 + %<bitfield>d print the bitfield in decimal
  40 + %<bitfield>x print the bitfield in hex
  41 + %<bitfield>X print the bitfield as 1 hex digit without leading "0x"
  42 + %<bitfield>r print as an ARM register
  43 + %<bitfield>f print a floating point constant if >7 else a
  44 + floating point register
  45 + %<code>y print a single precision VFP reg.
  46 + Codes: 0=>Sm, 1=>Sd, 2=>Sn, 3=>multi-list, 4=>Sm pair
  47 + %<code>z print a double precision VFP reg
  48 + Codes: 0=>Dm, 1=>Dd, 2=>Dn, 3=>multi-list
  49 + %c print condition code (always bits 28-31)
  50 + %P print floating point precision in arithmetic insn
  51 + %Q print floating point precision in ldf/stf insn
  52 + %R print floating point rounding mode
  53 + %<bitnum>'c print specified char iff bit is one
  54 + %<bitnum>`c print specified char iff bit is zero
  55 + %<bitnum>?ab print a if bit is one else print b
  56 + %p print 'p' iff bits 12-15 are 15
  57 + %t print 't' iff bit 21 set and bit 24 clear
  58 + %o print operand2 (immediate or register + shift)
  59 + %a print address for ldr/str instruction
  60 + %s print address for ldr/str halfword/signextend instruction
  61 + %b print branch destination
  62 + %B print arm BLX(1) destination
  63 + %A print address for ldc/stc/ldf/stf instruction
  64 + %m print register mask for ldm/stm instruction
  65 + %C print the PSR sub type.
  66 + %F print the COUNT field of a LFM/SFM instruction.
  67 +Thumb specific format options:
  68 + %D print Thumb register (bits 0..2 as high number if bit 7 set)
  69 + %S print Thumb register (bits 3..5 as high number if bit 6 set)
  70 + %<bitfield>I print bitfield as a signed decimal
  71 + (top bit of range being the sign bit)
  72 + %M print Thumb register mask
  73 + %N print Thumb register mask (with LR)
  74 + %O print Thumb register mask (with PC)
  75 + %T print Thumb condition code (always bits 8-11)
  76 + %I print cirrus signed shift immediate: bits 0..3|4..6
  77 + %<bitfield>B print Thumb branch destination (signed displacement)
  78 + %<bitfield>W print (bitfield * 4) as a decimal
  79 + %<bitfield>H print (bitfield * 2) as a decimal
  80 + %<bitfield>a print (bitfield * 4) as a pc-rel offset + decoded symbol
  81 +*/
  82 +
  83 +/* Note: There is a partial ordering in this table - it must be searched from
  84 + the top to obtain a correct match. */
  85 +
  86 +static struct arm_opcode arm_opcodes[] =
  87 +{
  88 + /* ARM instructions. */
  89 + {0xe1a00000, 0xffffffff, "nop\t\t\t(mov r0,r0)"},
  90 + {0x012FFF10, 0x0ffffff0, "bx%c\t%0-3r"},
  91 + {0x00000090, 0x0fe000f0, "mul%c%20's\t%16-19r, %0-3r, %8-11r"},
  92 + {0x00200090, 0x0fe000f0, "mla%c%20's\t%16-19r, %0-3r, %8-11r, %12-15r"},
  93 + {0x01000090, 0x0fb00ff0, "swp%c%22'b\t%12-15r, %0-3r, [%16-19r]"},
  94 + {0x00800090, 0x0fa000f0, "%22?sumull%c%20's\t%12-15r, %16-19r, %0-3r, %8-11r"},
  95 + {0x00a00090, 0x0fa000f0, "%22?sumlal%c%20's\t%12-15r, %16-19r, %0-3r, %8-11r"},
  96 +
  97 + /* V5J instruction. */
  98 + {0x012fff20, 0x0ffffff0, "bxj%c\t%0-3r"},
  99 +
  100 + /* XScale instructions. */
  101 + {0x0e200010, 0x0fff0ff0, "mia%c\tacc0, %0-3r, %12-15r"},
  102 + {0x0e280010, 0x0fff0ff0, "miaph%c\tacc0, %0-3r, %12-15r"},
  103 + {0x0e2c0010, 0x0ffc0ff0, "mia%17'T%17`B%16'T%16`B%c\tacc0, %0-3r, %12-15r"},
  104 + {0x0c400000, 0x0ff00fff, "mar%c\tacc0, %12-15r, %16-19r"},
  105 + {0x0c500000, 0x0ff00fff, "mra%c\t%12-15r, %16-19r, acc0"},
  106 + {0xf450f000, 0xfc70f000, "pld\t%a"},
  107 +
  108 + /* V5 Instructions. */
  109 + {0xe1200070, 0xfff000f0, "bkpt\t0x%16-19X%12-15X%8-11X%0-3X"},
  110 + {0xfa000000, 0xfe000000, "blx\t%B"},
  111 + {0x012fff30, 0x0ffffff0, "blx%c\t%0-3r"},
  112 + {0x016f0f10, 0x0fff0ff0, "clz%c\t%12-15r, %0-3r"},
  113 + {0xfc100000, 0xfe100000, "ldc2%22'l\t%8-11d, cr%12-15d, %A"},
  114 + {0xfc000000, 0xfe100000, "stc2%22'l\t%8-11d, cr%12-15d, %A"},
  115 + {0xfe000000, 0xff000010, "cdp2\t%8-11d, %20-23d, cr%12-15d, cr%16-19d, cr%0-3d, {%5-7d}"},
  116 + {0xfe000010, 0xff100010, "mcr2\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
  117 + {0xfe100010, 0xff100010, "mrc2\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
  118 +
  119 + /* V5E "El Segundo" Instructions. */
  120 + {0x000000d0, 0x0e1000f0, "ldr%cd\t%12-15r, %s"},
  121 + {0x000000f0, 0x0e1000f0, "str%cd\t%12-15r, %s"},
  122 + {0x01000080, 0x0ff000f0, "smlabb%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
  123 + {0x010000a0, 0x0ff000f0, "smlatb%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
  124 + {0x010000c0, 0x0ff000f0, "smlabt%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
  125 + {0x010000e0, 0x0ff000f0, "smlatt%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
  126 +
  127 + {0x01200080, 0x0ff000f0, "smlawb%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
  128 + {0x012000c0, 0x0ff000f0, "smlawt%c\t%16-19r, %0-3r, %8-11r, %12-15r"},
  129 +
  130 + {0x01400080, 0x0ff000f0, "smlalbb%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
  131 + {0x014000a0, 0x0ff000f0, "smlaltb%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
  132 + {0x014000c0, 0x0ff000f0, "smlalbt%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
  133 + {0x014000e0, 0x0ff000f0, "smlaltt%c\t%12-15r, %16-19r, %0-3r, %8-11r"},
  134 +
  135 + {0x01600080, 0x0ff0f0f0, "smulbb%c\t%16-19r, %0-3r, %8-11r"},
  136 + {0x016000a0, 0x0ff0f0f0, "smultb%c\t%16-19r, %0-3r, %8-11r"},
  137 + {0x016000c0, 0x0ff0f0f0, "smulbt%c\t%16-19r, %0-3r, %8-11r"},
  138 + {0x016000e0, 0x0ff0f0f0, "smultt%c\t%16-19r, %0-3r, %8-11r"},
  139 +
  140 + {0x012000a0, 0x0ff0f0f0, "smulwb%c\t%16-19r, %0-3r, %8-11r"},
  141 + {0x012000e0, 0x0ff0f0f0, "smulwt%c\t%16-19r, %0-3r, %8-11r"},
  142 +
  143 + {0x01000050, 0x0ff00ff0, "qadd%c\t%12-15r, %0-3r, %16-19r"},
  144 + {0x01400050, 0x0ff00ff0, "qdadd%c\t%12-15r, %0-3r, %16-19r"},
  145 + {0x01200050, 0x0ff00ff0, "qsub%c\t%12-15r, %0-3r, %16-19r"},
  146 + {0x01600050, 0x0ff00ff0, "qdsub%c\t%12-15r, %0-3r, %16-19r"},
  147 +
  148 + {0x0c400000, 0x0ff00000, "mcrr%c\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"},
  149 + {0x0c500000, 0x0ff00000, "mrrc%c\t%8-11d, %4-7d, %12-15r, %16-19r, cr%0-3d"},
  150 +
  151 + /* ARM Instructions. */
  152 + {0x00000090, 0x0e100090, "str%c%6's%5?hb\t%12-15r, %s"},
  153 + {0x00100090, 0x0e100090, "ldr%c%6's%5?hb\t%12-15r, %s"},
  154 + {0x00000000, 0x0de00000, "and%c%20's\t%12-15r, %16-19r, %o"},
  155 + {0x00200000, 0x0de00000, "eor%c%20's\t%12-15r, %16-19r, %o"},
  156 + {0x00400000, 0x0de00000, "sub%c%20's\t%12-15r, %16-19r, %o"},
  157 + {0x00600000, 0x0de00000, "rsb%c%20's\t%12-15r, %16-19r, %o"},
  158 + {0x00800000, 0x0de00000, "add%c%20's\t%12-15r, %16-19r, %o"},
  159 + {0x00a00000, 0x0de00000, "adc%c%20's\t%12-15r, %16-19r, %o"},
  160 + {0x00c00000, 0x0de00000, "sbc%c%20's\t%12-15r, %16-19r, %o"},
  161 + {0x00e00000, 0x0de00000, "rsc%c%20's\t%12-15r, %16-19r, %o"},
  162 + {0x0120f000, 0x0db0f000, "msr%c\t%22?SCPSR%C, %o"},
  163 + {0x010f0000, 0x0fbf0fff, "mrs%c\t%12-15r, %22?SCPSR"},
  164 + {0x01000000, 0x0de00000, "tst%c%p\t%16-19r, %o"},
  165 + {0x01200000, 0x0de00000, "teq%c%p\t%16-19r, %o"},
  166 + {0x01400000, 0x0de00000, "cmp%c%p\t%16-19r, %o"},
  167 + {0x01600000, 0x0de00000, "cmn%c%p\t%16-19r, %o"},
  168 + {0x01800000, 0x0de00000, "orr%c%20's\t%12-15r, %16-19r, %o"},
  169 + {0x01a00000, 0x0de00000, "mov%c%20's\t%12-15r, %o"},
  170 + {0x01c00000, 0x0de00000, "bic%c%20's\t%12-15r, %16-19r, %o"},
  171 + {0x01e00000, 0x0de00000, "mvn%c%20's\t%12-15r, %o"},
  172 + {0x04000000, 0x0e100000, "str%c%22'b%t\t%12-15r, %a"},
  173 + {0x06000000, 0x0e100ff0, "str%c%22'b%t\t%12-15r, %a"},
  174 + {0x04000000, 0x0c100010, "str%c%22'b%t\t%12-15r, %a"},
  175 + {0x06000010, 0x0e000010, "undefined"},
  176 + {0x04100000, 0x0c100000, "ldr%c%22'b%t\t%12-15r, %a"},
  177 + {0x08000000, 0x0e100000, "stm%c%23?id%24?ba\t%16-19r%21'!, %m%22'^"},
  178 + {0x08100000, 0x0e100000, "ldm%c%23?id%24?ba\t%16-19r%21'!, %m%22'^"},
  179 + {0x0a000000, 0x0e000000, "b%24'l%c\t%b"},
  180 + {0x0f000000, 0x0f000000, "swi%c\t%0-23x"},
  181 +
  182 + /* Floating point coprocessor (FPA) instructions */
  183 + {0x0e000100, 0x0ff08f10, "adf%c%P%R\t%12-14f, %16-18f, %0-3f"},
  184 + {0x0e100100, 0x0ff08f10, "muf%c%P%R\t%12-14f, %16-18f, %0-3f"},
  185 + {0x0e200100, 0x0ff08f10, "suf%c%P%R\t%12-14f, %16-18f, %0-3f"},
  186 + {0x0e300100, 0x0ff08f10, "rsf%c%P%R\t%12-14f, %16-18f, %0-3f"},
  187 + {0x0e400100, 0x0ff08f10, "dvf%c%P%R\t%12-14f, %16-18f, %0-3f"},
  188 + {0x0e500100, 0x0ff08f10, "rdf%c%P%R\t%12-14f, %16-18f, %0-3f"},
  189 + {0x0e600100, 0x0ff08f10, "pow%c%P%R\t%12-14f, %16-18f, %0-3f"},
  190 + {0x0e700100, 0x0ff08f10, "rpw%c%P%R\t%12-14f, %16-18f, %0-3f"},
  191 + {0x0e800100, 0x0ff08f10, "rmf%c%P%R\t%12-14f, %16-18f, %0-3f"},
  192 + {0x0e900100, 0x0ff08f10, "fml%c%P%R\t%12-14f, %16-18f, %0-3f"},
  193 + {0x0ea00100, 0x0ff08f10, "fdv%c%P%R\t%12-14f, %16-18f, %0-3f"},
  194 + {0x0eb00100, 0x0ff08f10, "frd%c%P%R\t%12-14f, %16-18f, %0-3f"},
  195 + {0x0ec00100, 0x0ff08f10, "pol%c%P%R\t%12-14f, %16-18f, %0-3f"},
  196 + {0x0e008100, 0x0ff08f10, "mvf%c%P%R\t%12-14f, %0-3f"},
  197 + {0x0e108100, 0x0ff08f10, "mnf%c%P%R\t%12-14f, %0-3f"},
  198 + {0x0e208100, 0x0ff08f10, "abs%c%P%R\t%12-14f, %0-3f"},
  199 + {0x0e308100, 0x0ff08f10, "rnd%c%P%R\t%12-14f, %0-3f"},
  200 + {0x0e408100, 0x0ff08f10, "sqt%c%P%R\t%12-14f, %0-3f"},
  201 + {0x0e508100, 0x0ff08f10, "log%c%P%R\t%12-14f, %0-3f"},
  202 + {0x0e608100, 0x0ff08f10, "lgn%c%P%R\t%12-14f, %0-3f"},
  203 + {0x0e708100, 0x0ff08f10, "exp%c%P%R\t%12-14f, %0-3f"},
  204 + {0x0e808100, 0x0ff08f10, "sin%c%P%R\t%12-14f, %0-3f"},
  205 + {0x0e908100, 0x0ff08f10, "cos%c%P%R\t%12-14f, %0-3f"},
  206 + {0x0ea08100, 0x0ff08f10, "tan%c%P%R\t%12-14f, %0-3f"},
  207 + {0x0eb08100, 0x0ff08f10, "asn%c%P%R\t%12-14f, %0-3f"},
  208 + {0x0ec08100, 0x0ff08f10, "acs%c%P%R\t%12-14f, %0-3f"},
  209 + {0x0ed08100, 0x0ff08f10, "atn%c%P%R\t%12-14f, %0-3f"},
  210 + {0x0ee08100, 0x0ff08f10, "urd%c%P%R\t%12-14f, %0-3f"},
  211 + {0x0ef08100, 0x0ff08f10, "nrm%c%P%R\t%12-14f, %0-3f"},
  212 + {0x0e000110, 0x0ff00f1f, "flt%c%P%R\t%16-18f, %12-15r"},
  213 + {0x0e100110, 0x0fff0f98, "fix%c%R\t%12-15r, %0-2f"},
  214 + {0x0e200110, 0x0fff0fff, "wfs%c\t%12-15r"},
  215 + {0x0e300110, 0x0fff0fff, "rfs%c\t%12-15r"},
  216 + {0x0e400110, 0x0fff0fff, "wfc%c\t%12-15r"},
  217 + {0x0e500110, 0x0fff0fff, "rfc%c\t%12-15r"},
  218 + {0x0e90f110, 0x0ff8fff0, "cmf%c\t%16-18f, %0-3f"},
  219 + {0x0eb0f110, 0x0ff8fff0, "cnf%c\t%16-18f, %0-3f"},
  220 + {0x0ed0f110, 0x0ff8fff0, "cmfe%c\t%16-18f, %0-3f"},
  221 + {0x0ef0f110, 0x0ff8fff0, "cnfe%c\t%16-18f, %0-3f"},
  222 + {0x0c000100, 0x0e100f00, "stf%c%Q\t%12-14f, %A"},
  223 + {0x0c100100, 0x0e100f00, "ldf%c%Q\t%12-14f, %A"},
  224 + {0x0c000200, 0x0e100f00, "sfm%c\t%12-14f, %F, %A"},
  225 + {0x0c100200, 0x0e100f00, "lfm%c\t%12-14f, %F, %A"},
  226 +
  227 + /* Floating point coprocessor (VFP) instructions */
  228 + {0x0eb00bc0, 0x0fff0ff0, "fabsd%c\t%1z, %0z"},
  229 + {0x0eb00ac0, 0x0fbf0fd0, "fabss%c\t%1y, %0y"},
  230 + {0x0e300b00, 0x0ff00ff0, "faddd%c\t%1z, %2z, %0z"},
  231 + {0x0e300a00, 0x0fb00f50, "fadds%c\t%1y, %2y, %1y"},
  232 + {0x0eb40b40, 0x0fff0f70, "fcmp%7'ed%c\t%1z, %0z"},
  233 + {0x0eb40a40, 0x0fbf0f50, "fcmp%7'es%c\t%1y, %0y"},
  234 + {0x0eb50b40, 0x0fff0f70, "fcmp%7'ezd%c\t%1z"},
  235 + {0x0eb50a40, 0x0fbf0f70, "fcmp%7'ezs%c\t%1y"},
  236 + {0x0eb00b40, 0x0fff0ff0, "fcpyd%c\t%1z, %0z"},
  237 + {0x0eb00a40, 0x0fbf0fd0, "fcpys%c\t%1y, %0y"},
  238 + {0x0eb70ac0, 0x0fff0fd0, "fcvtds%c\t%1z, %0y"},
  239 + {0x0eb70bc0, 0x0fbf0ff0, "fcvtsd%c\t%1y, %0z"},
  240 + {0x0e800b00, 0x0ff00ff0, "fdivd%c\t%1z, %2z, %0z"},
  241 + {0x0e800a00, 0x0fb00f50, "fdivs%c\t%1y, %2y, %0y"},
  242 + {0x0d100b00, 0x0f700f00, "fldd%c\t%1z, %A"},
  243 + {0x0c900b00, 0x0fd00f00, "fldmia%0?xd%c\t%16-19r%21'!, %3z"},
  244 + {0x0d300b00, 0x0ff00f00, "fldmdb%0?xd%c\t%16-19r!, %3z"},
  245 + {0x0d100a00, 0x0f300f00, "flds%c\t%1y, %A"},
  246 + {0x0c900a00, 0x0f900f00, "fldmias%c\t%16-19r%21'!, %3y"},
  247 + {0x0d300a00, 0x0fb00f00, "fldmdbs%c\t%16-19r!, %3y"},
  248 + {0x0e000b00, 0x0ff00ff0, "fmacd%c\t%1z, %2z, %0z"},
  249 + {0x0e000a00, 0x0fb00f50, "fmacs%c\t%1y, %2y, %0y"},
  250 + {0x0e200b10, 0x0ff00fff, "fmdhr%c\t%2z, %12-15r"},
  251 + {0x0e000b10, 0x0ff00fff, "fmdlr%c\t%2z, %12-15r"},
  252 + {0x0c400b10, 0x0ff00ff0, "fmdrr%c\t%0z, %12-15r, %16-19r"},
  253 + {0x0e300b10, 0x0ff00fff, "fmrdh%c\t%12-15r, %2z"},
  254 + {0x0e100b10, 0x0ff00fff, "fmrdl%c\t%12-15r, %2z"},
  255 + {0x0c500b10, 0x0ff00ff0, "fmrrd%c\t%12-15r, %16-19r, %0z"},
  256 + {0x0c500a10, 0x0ff00fd0, "fmrrs%c\t%12-15r, %16-19r, %4y"},
  257 + {0x0e100a10, 0x0ff00f7f, "fmrs%c\t%12-15r, %2y"},
  258 + {0x0ef1fa10, 0x0fffffff, "fmstat%c"},
  259 + {0x0ef00a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpsid"},
  260 + {0x0ef10a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpscr"},
  261 + {0x0ef80a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpexc"},
  262 + {0x0ef90a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpinst\t@ Impl def"},
  263 + {0x0efa0a10, 0x0fff0fff, "fmrx%c\t%12-15r, fpinst2\t@ Impl def"},
  264 + {0x0ef00a10, 0x0ff00fff, "fmrx%c\t%12-15r, <impl def 0x%16-19x>"},
  265 + {0x0e100b00, 0x0ff00ff0, "fmscd%c\t%1z, %2z, %0z"},
  266 + {0x0e100a00, 0x0fb00f50, "fmscs%c\t%1y, %2y, %0y"},
  267 + {0x0e000a10, 0x0ff00f7f, "fmsr%c\t%2y, %12-15r"},
  268 + {0x0c400a10, 0x0ff00fd0, "fmsrr%c\t%12-15r, %16-19r, %4y"},
  269 + {0x0e200b00, 0x0ff00ff0, "fmuld%c\t%1z, %2z, %0z"},
  270 + {0x0e200a00, 0x0fb00f50, "fmuls%c\t%1y, %2y, %0y"},
  271 + {0x0ee00a10, 0x0fff0fff, "fmxr%c\tfpsid, %12-15r"},
  272 + {0x0ee10a10, 0x0fff0fff, "fmxr%c\tfpscr, %12-15r"},
  273 + {0x0ee80a10, 0x0fff0fff, "fmxr%c\tfpexc, %12-15r"},
  274 + {0x0ee90a10, 0x0fff0fff, "fmxr%c\tfpinst, %12-15r\t@ Impl def"},
  275 + {0x0eea0a10, 0x0fff0fff, "fmxr%c\tfpinst2, %12-15r\t@ Impl def"},
  276 + {0x0ee00a10, 0x0ff00fff, "fmxr%c\t<impl def 0x%16-19x>, %12-15r"},
  277 + {0x0eb10b40, 0x0fff0ff0, "fnegd%c\t%1z, %0z"},
  278 + {0x0eb10a40, 0x0fbf0fd0, "fnegs%c\t%1y, %0y"},
  279 + {0x0e000b40, 0x0ff00ff0, "fnmacd%c\t%1z, %2z, %0z"},
  280 + {0x0e000a40, 0x0fb00f50, "fnmacs%c\t%1y, %2y, %0y"},
  281 + {0x0e100b40, 0x0ff00ff0, "fnmscd%c\t%1z, %2z, %0z"},
  282 + {0x0e100a40, 0x0fb00f50, "fnmscs%c\t%1y, %2y, %0y"},
  283 + {0x0e200b40, 0x0ff00ff0, "fnmuld%c\t%1z, %2z, %0z"},
  284 + {0x0e200a40, 0x0fb00f50, "fnmuls%c\t%1y, %2y, %0y"},
  285 + {0x0eb80bc0, 0x0fff0fd0, "fsitod%c\t%1z, %0y"},
  286 + {0x0eb80ac0, 0x0fbf0fd0, "fsitos%c\t%1y, %0y"},
  287 + {0x0eb10bc0, 0x0fff0ff0, "fsqrtd%c\t%1z, %0z"},
  288 + {0x0eb10ac0, 0x0fbf0fd0, "fsqrts%c\t%1y, %0y"},
  289 + {0x0d000b00, 0x0f700f00, "fstd%c\t%1z, %A"},
  290 + {0x0c800b00, 0x0fd00f00, "fstmia%0?xd%c\t%16-19r%21'!, %3z"},
  291 + {0x0d200b00, 0x0ff00f00, "fstmdb%0?xd%c\t%16-19r!, %3z"},
  292 + {0x0d000a00, 0x0f300f00, "fsts%c\t%1y, %A"},
  293 + {0x0c800a00, 0x0f900f00, "fstmias%c\t%16-19r%21'!, %3y"},
  294 + {0x0d200a00, 0x0fb00f00, "fstmdbs%c\t%16-19r!, %3y"},
  295 + {0x0e300b40, 0x0ff00ff0, "fsubd%c\t%1z, %2z, %0z"},
  296 + {0x0e300a40, 0x0fb00f50, "fsubs%c\t%1y, %2y, %0y"},
  297 + {0x0ebc0b40, 0x0fbe0f70, "fto%16?sui%7'zd%c\t%1y, %0z"},
  298 + {0x0ebc0a40, 0x0fbe0f50, "fto%16?sui%7'zs%c\t%1y, %0y"},
  299 + {0x0eb80b40, 0x0fff0fd0, "fuitod%c\t%1z, %0y"},
  300 + {0x0eb80a40, 0x0fbf0fd0, "fuitos%c\t%1y, %0y"},
  301 +
  302 + /* Cirrus coprocessor instructions. */
  303 + {0x0d100400, 0x0f500f00, "cfldrs%c\tmvf%12-15d, %A"},
  304 + {0x0c100400, 0x0f500f00, "cfldrs%c\tmvf%12-15d, %A"},
  305 + {0x0d500400, 0x0f500f00, "cfldrd%c\tmvd%12-15d, %A"},
  306 + {0x0c500400, 0x0f500f00, "cfldrd%c\tmvd%12-15d, %A"},
  307 + {0x0d100500, 0x0f500f00, "cfldr32%c\tmvfx%12-15d, %A"},
  308 + {0x0c100500, 0x0f500f00, "cfldr32%c\tmvfx%12-15d, %A"},
  309 + {0x0d500500, 0x0f500f00, "cfldr64%c\tmvdx%12-15d, %A"},
  310 + {0x0c500500, 0x0f500f00, "cfldr64%c\tmvdx%12-15d, %A"},
  311 + {0x0d000400, 0x0f500f00, "cfstrs%c\tmvf%12-15d, %A"},
  312 + {0x0c000400, 0x0f500f00, "cfstrs%c\tmvf%12-15d, %A"},
  313 + {0x0d400400, 0x0f500f00, "cfstrd%c\tmvd%12-15d, %A"},
  314 + {0x0c400400, 0x0f500f00, "cfstrd%c\tmvd%12-15d, %A"},
  315 + {0x0d000500, 0x0f500f00, "cfstr32%c\tmvfx%12-15d, %A"},
  316 + {0x0c000500, 0x0f500f00, "cfstr32%c\tmvfx%12-15d, %A"},
  317 + {0x0d400500, 0x0f500f00, "cfstr64%c\tmvdx%12-15d, %A"},
  318 + {0x0c400500, 0x0f500f00, "cfstr64%c\tmvdx%12-15d, %A"},
  319 + {0x0e000450, 0x0ff00ff0, "cfmvsr%c\tmvf%16-19d, %12-15r"},
  320 + {0x0e100450, 0x0ff00ff0, "cfmvrs%c\t%12-15r, mvf%16-19d"},
  321 + {0x0e000410, 0x0ff00ff0, "cfmvdlr%c\tmvd%16-19d, %12-15r"},
  322 + {0x0e100410, 0x0ff00ff0, "cfmvrdl%c\t%12-15r, mvd%16-19d"},
  323 + {0x0e000430, 0x0ff00ff0, "cfmvdhr%c\tmvd%16-19d, %12-15r"},
  324 + {0x0e100430, 0x0ff00fff, "cfmvrdh%c\t%12-15r, mvd%16-19d"},
  325 + {0x0e000510, 0x0ff00fff, "cfmv64lr%c\tmvdx%16-19d, %12-15r"},
  326 + {0x0e100510, 0x0ff00fff, "cfmvr64l%c\t%12-15r, mvdx%16-19d"},
  327 + {0x0e000530, 0x0ff00fff, "cfmv64hr%c\tmvdx%16-19d, %12-15r"},
  328 + {0x0e100530, 0x0ff00fff, "cfmvr64h%c\t%12-15r, mvdx%16-19d"},
  329 + {0x0e100610, 0x0ff0fff0, "cfmval32%c\tmvax%0-3d, mvfx%16-19d"},
  330 + {0x0e000610, 0x0ff0fff0, "cfmv32al%c\tmvfx%0-3d, mvax%16-19d"},
  331 + {0x0e100630, 0x0ff0fff0, "cfmvam32%c\tmvax%0-3d, mvfx%16-19d"},
  332 + {0x0e000630, 0x0ff0fff0, "cfmv32am%c\tmvfx%0-3d, mvax%16-19d"},
  333 + {0x0e100650, 0x0ff0fff0, "cfmvah32%c\tmvax%0-3d, mvfx%16-19d"},
  334 + {0x0e000650, 0x0ff0fff0, "cfmv32ah%c\tmvfx%0-3d, mvax%16-19d"},
  335 + {0x0e000670, 0x0ff0fff0, "cfmv32a%c\tmvfx%0-3d, mvax%16-19d"},
  336 + {0x0e100670, 0x0ff0fff0, "cfmva32%c\tmvax%0-3d, mvfx%16-19d"},
  337 + {0x0e000690, 0x0ff0fff0, "cfmv64a%c\tmvdx%0-3d, mvax%16-19d"},
  338 + {0x0e100690, 0x0ff0fff0, "cfmva64%c\tmvax%0-3d, mvdx%16-19d"},
  339 + {0x0e1006b0, 0x0ff0fff0, "cfmvsc32%c\tdspsc, mvfx%16-19d"},
  340 + {0x0e0006b0, 0x0ff0fff0, "cfmv32sc%c\tmvfx%0-3d, dspsc"},
  341 + {0x0e000400, 0x0ff00fff, "cfcpys%c\tmvf%12-15d, mvf%16-19d"},
  342 + {0x0e000420, 0x0ff00fff, "cfcpyd%c\tmvd%12-15d, mvd%16-19d"},
  343 + {0x0e000460, 0x0ff00fff, "cfcvtsd%c\tmvd%12-15d, mvf%16-19d"},
  344 + {0x0e000440, 0x0ff00fff, "cfcvtds%c\tmvf%12-15d, mvd%16-19d"},
  345 + {0x0e000480, 0x0ff00fff, "cfcvt32s%c\tmvf%12-15d, mvfx%16-19d"},
  346 + {0x0e0004a0, 0x0ff00fff, "cfcvt32d%c\tmvd%12-15d, mvfx%16-19d"},
  347 + {0x0e0004c0, 0x0ff00fff, "cfcvt64s%c\tmvf%12-15d, mvdx%16-19d"},
  348 + {0x0e0004e0, 0x0ff00fff, "cfcvt64d%c\tmvd%12-15d, mvdx%16-19d"},
  349 + {0x0e100580, 0x0ff00fff, "cfcvts32%c\tmvfx%12-15d, mvf%16-19d"},
  350 + {0x0e1005a0, 0x0ff00fff, "cfcvtd32%c\tmvfx%12-15d, mvd%16-19d"},
  351 + {0x0e1005c0, 0x0ff00fff, "cftruncs32%c\tmvfx%12-15d, mvf%16-19d"},
  352 + {0x0e1005e0, 0x0ff00fff, "cftruncd32%c\tmvfx%12-15d, mvd%16-19d"},
  353 + {0x0e000550, 0x0ff00ff0, "cfrshl32%c\tmvfx%16-19d, mvfx%0-3d, %12-15r"},
  354 + {0x0e000570, 0x0ff00ff0, "cfrshl64%c\tmvdx%16-19d, mvdx%0-3d, %12-15r"},
  355 + {0x0e000500, 0x0ff00f00, "cfsh32%c\tmvfx%12-15d, mvfx%16-19d, #%I"},
  356 + {0x0e200500, 0x0ff00f00, "cfsh64%c\tmvdx%12-15d, mvdx%16-19d, #%I"},
  357 + {0x0e100490, 0x0ff00ff0, "cfcmps%c\t%12-15r, mvf%16-19d, mvf%0-3d"},
  358 + {0x0e1004b0, 0x0ff00ff0, "cfcmpd%c\t%12-15r, mvd%16-19d, mvd%0-3d"},
  359 + {0x0e100590, 0x0ff00ff0, "cfcmp32%c\t%12-15r, mvfx%16-19d, mvfx%0-3d"},
  360 + {0x0e1005b0, 0x0ff00ff0, "cfcmp64%c\t%12-15r, mvdx%16-19d, mvdx%0-3d"},
  361 + {0x0e300400, 0x0ff00fff, "cfabss%c\tmvf%12-15d, mvf%16-19d"},
  362 + {0x0e300420, 0x0ff00fff, "cfabsd%c\tmvd%12-15d, mvd%16-19d"},
  363 + {0x0e300440, 0x0ff00fff, "cfnegs%c\tmvf%12-15d, mvf%16-19d"},
  364 + {0x0e300460, 0x0ff00fff, "cfnegd%c\tmvd%12-15d, mvd%16-19d"},
  365 + {0x0e300480, 0x0ff00ff0, "cfadds%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"},
  366 + {0x0e3004a0, 0x0ff00ff0, "cfaddd%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"},
  367 + {0x0e3004c0, 0x0ff00ff0, "cfsubs%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"},
  368 + {0x0e3004e0, 0x0ff00ff0, "cfsubd%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"},
  369 + {0x0e100400, 0x0ff00ff0, "cfmuls%c\tmvf%12-15d, mvf%16-19d, mvf%0-3d"},
  370 + {0x0e100420, 0x0ff00ff0, "cfmuld%c\tmvd%12-15d, mvd%16-19d, mvd%0-3d"},
  371 + {0x0e300500, 0x0ff00fff, "cfabs32%c\tmvfx%12-15d, mvfx%16-19d"},
  372 + {0x0e300520, 0x0ff00fff, "cfabs64%c\tmvdx%12-15d, mvdx%16-19d"},
  373 + {0x0e300540, 0x0ff00fff, "cfneg32%c\tmvfx%12-15d, mvfx%16-19d"},
  374 + {0x0e300560, 0x0ff00fff, "cfneg64%c\tmvdx%12-15d, mvdx%16-19d"},
  375 + {0x0e300580, 0x0ff00ff0, "cfadd32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
  376 + {0x0e3005a0, 0x0ff00ff0, "cfadd64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"},
  377 + {0x0e3005c0, 0x0ff00ff0, "cfsub32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
  378 + {0x0e3005e0, 0x0ff00ff0, "cfsub64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"},
  379 + {0x0e100500, 0x0ff00ff0, "cfmul32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
  380 + {0x0e100520, 0x0ff00ff0, "cfmul64%c\tmvdx%12-15d, mvdx%16-19d, mvdx%0-3d"},
  381 + {0x0e100540, 0x0ff00ff0, "cfmac32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
  382 + {0x0e100560, 0x0ff00ff0, "cfmsc32%c\tmvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
  383 + {0x0e000600, 0x0ff00f00, "cfmadd32%c\tmvax%5-7d, mvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
  384 + {0x0e100600, 0x0ff00f00, "cfmsub32%c\tmvax%5-7d, mvfx%12-15d, mvfx%16-19d, mvfx%0-3d"},
  385 + {0x0e200600, 0x0ff00f00, "cfmadda32%c\tmvax%5-7d, mvax%12-15d, mvfx%16-19d, mvfx%0-3d"},
  386 + {0x0e300600, 0x0ff00f00, "cfmsuba32%c\tmvax%5-7d, mvax%12-15d, mvfx%16-19d, mvfx%0-3d"},
  387 +
  388 + /* Generic coprocessor instructions */
  389 + {0x0e000000, 0x0f000010, "cdp%c\t%8-11d, %20-23d, cr%12-15d, cr%16-19d, cr%0-3d, {%5-7d}"},
  390 + {0x0e100010, 0x0f100010, "mrc%c\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
  391 + {0x0e000010, 0x0f100010, "mcr%c\t%8-11d, %21-23d, %12-15r, cr%16-19d, cr%0-3d, {%5-7d}"},
  392 + {0x0c000000, 0x0e100000, "stc%c%22'l\t%8-11d, cr%12-15d, %A"},
  393 + {0x0c100000, 0x0e100000, "ldc%c%22'l\t%8-11d, cr%12-15d, %A"},
  394 +
  395 + /* The rest. */
  396 + {0x00000000, 0x00000000, "undefined instruction %0-31x"},
  397 + {0x00000000, 0x00000000, 0}
  398 +};
  399 +
  400 +#define BDISP(x) ((((x) & 0xffffff) ^ 0x800000) - 0x800000) /* 26 bit */
  401 +
  402 +static struct thumb_opcode thumb_opcodes[] =
  403 +{
  404 + /* Thumb instructions. */
  405 +
  406 + /* ARM V5 ISA extends Thumb. */
  407 + {0xbe00, 0xff00, "bkpt\t%0-7x"},
  408 + {0x4780, 0xff87, "blx\t%3-6r"}, /* note: 4 bit register number. */
  409 + /* Note: this is BLX(2). BLX(1) is done in arm-dis.c/print_insn_thumb()
  410 + as an extension of the special processing there for Thumb BL.
  411 + BL and BLX(1) involve 2 successive 16-bit instructions, which must
  412 + always appear together in the correct order. So, the empty
  413 + string is put in this table, and the string interpreter takes <empty>
  414 + to mean it has a pair of BL-ish instructions. */
  415 + {0x46C0, 0xFFFF, "nop\t\t\t(mov r8, r8)"},
  416 + /* Format 5 instructions do not update the PSR. */
  417 + {0x1C00, 0xFFC0, "mov\t%0-2r, %3-5r\t\t(add %0-2r, %3-5r, #%6-8d)"},
  418 + /* Format 4. */
  419 + {0x4000, 0xFFC0, "and\t%0-2r, %3-5r"},
  420 + {0x4040, 0xFFC0, "eor\t%0-2r, %3-5r"},
  421 + {0x4080, 0xFFC0, "lsl\t%0-2r, %3-5r"},
  422 + {0x40C0, 0xFFC0, "lsr\t%0-2r, %3-5r"},
  423 + {0x4100, 0xFFC0, "asr\t%0-2r, %3-5r"},
  424 + {0x4140, 0xFFC0, "adc\t%0-2r, %3-5r"},
  425 + {0x4180, 0xFFC0, "sbc\t%0-2r, %3-5r"},
  426 + {0x41C0, 0xFFC0, "ror\t%0-2r, %3-5r"},
  427 + {0x4200, 0xFFC0, "tst\t%0-2r, %3-5r"},
  428 + {0x4240, 0xFFC0, "neg\t%0-2r, %3-5r"},
  429 + {0x4280, 0xFFC0, "cmp\t%0-2r, %3-5r"},
  430 + {0x42C0, 0xFFC0, "cmn\t%0-2r, %3-5r"},
  431 + {0x4300, 0xFFC0, "orr\t%0-2r, %3-5r"},
  432 + {0x4340, 0xFFC0, "mul\t%0-2r, %3-5r"},
  433 + {0x4380, 0xFFC0, "bic\t%0-2r, %3-5r"},
  434 + {0x43C0, 0xFFC0, "mvn\t%0-2r, %3-5r"},
  435 + /* format 13 */
  436 + {0xB000, 0xFF80, "add\tsp, #%0-6W"},
  437 + {0xB080, 0xFF80, "sub\tsp, #%0-6W"},
  438 + /* format 5 */
  439 + {0x4700, 0xFF80, "bx\t%S"},
  440 + {0x4400, 0xFF00, "add\t%D, %S"},
  441 + {0x4500, 0xFF00, "cmp\t%D, %S"},
  442 + {0x4600, 0xFF00, "mov\t%D, %S"},
  443 + /* format 14 */
  444 + {0xB400, 0xFE00, "push\t%N"},
  445 + {0xBC00, 0xFE00, "pop\t%O"},
  446 + /* format 2 */
  447 + {0x1800, 0xFE00, "add\t%0-2r, %3-5r, %6-8r"},
  448 + {0x1A00, 0xFE00, "sub\t%0-2r, %3-5r, %6-8r"},
  449 + {0x1C00, 0xFE00, "add\t%0-2r, %3-5r, #%6-8d"},
  450 + {0x1E00, 0xFE00, "sub\t%0-2r, %3-5r, #%6-8d"},
  451 + /* format 8 */
  452 + {0x5200, 0xFE00, "strh\t%0-2r, [%3-5r, %6-8r]"},
  453 + {0x5A00, 0xFE00, "ldrh\t%0-2r, [%3-5r, %6-8r]"},
  454 + {0x5600, 0xF600, "ldrs%11?hb\t%0-2r, [%3-5r, %6-8r]"},
  455 + /* format 7 */
  456 + {0x5000, 0xFA00, "str%10'b\t%0-2r, [%3-5r, %6-8r]"},
  457 + {0x5800, 0xFA00, "ldr%10'b\t%0-2r, [%3-5r, %6-8r]"},
  458 + /* format 1 */
  459 + {0x0000, 0xF800, "lsl\t%0-2r, %3-5r, #%6-10d"},
  460 + {0x0800, 0xF800, "lsr\t%0-2r, %3-5r, #%6-10d"},
  461 + {0x1000, 0xF800, "asr\t%0-2r, %3-5r, #%6-10d"},
  462 + /* format 3 */
  463 + {0x2000, 0xF800, "mov\t%8-10r, #%0-7d"},
  464 + {0x2800, 0xF800, "cmp\t%8-10r, #%0-7d"},
  465 + {0x3000, 0xF800, "add\t%8-10r, #%0-7d"},
  466 + {0x3800, 0xF800, "sub\t%8-10r, #%0-7d"},
  467 + /* format 6 */
  468 + {0x4800, 0xF800, "ldr\t%8-10r, [pc, #%0-7W]\t(%0-7a)"}, /* TODO: Disassemble PC relative "LDR rD,=<symbolic>" */
  469 + /* format 9 */
  470 + {0x6000, 0xF800, "str\t%0-2r, [%3-5r, #%6-10W]"},
  471 + {0x6800, 0xF800, "ldr\t%0-2r, [%3-5r, #%6-10W]"},
  472 + {0x7000, 0xF800, "strb\t%0-2r, [%3-5r, #%6-10d]"},
  473 + {0x7800, 0xF800, "ldrb\t%0-2r, [%3-5r, #%6-10d]"},
  474 + /* format 10 */
  475 + {0x8000, 0xF800, "strh\t%0-2r, [%3-5r, #%6-10H]"},
  476 + {0x8800, 0xF800, "ldrh\t%0-2r, [%3-5r, #%6-10H]"},
  477 + /* format 11 */
  478 + {0x9000, 0xF800, "str\t%8-10r, [sp, #%0-7W]"},
  479 + {0x9800, 0xF800, "ldr\t%8-10r, [sp, #%0-7W]"},
  480 + /* format 12 */
  481 + {0xA000, 0xF800, "add\t%8-10r, pc, #%0-7W\t(adr %8-10r,%0-7a)"},
  482 + {0xA800, 0xF800, "add\t%8-10r, sp, #%0-7W"},
  483 + /* format 15 */
  484 + {0xC000, 0xF800, "stmia\t%8-10r!,%M"},
  485 + {0xC800, 0xF800, "ldmia\t%8-10r!,%M"},
  486 + /* format 18 */
  487 + {0xE000, 0xF800, "b\t%0-10B"},
  488 + {0xE800, 0xF800, "undefined"},
  489 + /* format 19 */
  490 + {0xF000, 0xF800, ""}, /* special processing required in disassembler */
  491 + {0xF800, 0xF800, "second half of BL instruction %0-15x"},
  492 + /* format 16 */
  493 + {0xD000, 0xFF00, "beq\t%0-7B"},
  494 + {0xD100, 0xFF00, "bne\t%0-7B"},
  495 + {0xD200, 0xFF00, "bcs\t%0-7B"},
  496 + {0xD300, 0xFF00, "bcc\t%0-7B"},
  497 + {0xD400, 0xFF00, "bmi\t%0-7B"},
  498 + {0xD500, 0xFF00, "bpl\t%0-7B"},
  499 + {0xD600, 0xFF00, "bvs\t%0-7B"},
  500 + {0xD700, 0xFF00, "bvc\t%0-7B"},
  501 + {0xD800, 0xFF00, "bhi\t%0-7B"},
  502 + {0xD900, 0xFF00, "bls\t%0-7B"},
  503 + {0xDA00, 0xFF00, "bge\t%0-7B"},
  504 + {0xDB00, 0xFF00, "blt\t%0-7B"},
  505 + {0xDC00, 0xFF00, "bgt\t%0-7B"},
  506 + {0xDD00, 0xFF00, "ble\t%0-7B"},
  507 + /* format 17 */
  508 + {0xDE00, 0xFF00, "bal\t%0-7B"},
  509 + {0xDF00, 0xFF00, "swi\t%0-7d"},
  510 + /* format 9 */
  511 + {0x6000, 0xF800, "str\t%0-2r, [%3-5r, #%6-10W]"},
  512 + {0x6800, 0xF800, "ldr\t%0-2r, [%3-5r, #%6-10W]"},
  513 + {0x7000, 0xF800, "strb\t%0-2r, [%3-5r, #%6-10d]"},
  514 + {0x7800, 0xF800, "ldrb\t%0-2r, [%3-5r, #%6-10d]"},
  515 + /* the rest */
  516 + {0x0000, 0x0000, "undefined instruction %0-15x"},
  517 + {0x0000, 0x0000, 0}
  518 +};
  519 +
  520 +#define BDISP23(x) ((((((x) & 0x07ff) << 11) | (((x) & 0x07ff0000) >> 16)) \
  521 + ^ 0x200000) - 0x200000) /* 23bit */
  522 +
  523 +#ifndef streq
  524 +#define streq(a,b) (strcmp ((a), (b)) == 0)
  525 +#endif
  526 +
  527 +#ifndef strneq
  528 +#define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0)
  529 +#endif
  530 +
  531 +#ifndef NUM_ELEM
  532 +#define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0])
  533 +#endif
  534 +
  535 +static char * arm_conditional[] =
  536 +{"eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
  537 + "hi", "ls", "ge", "lt", "gt", "le", "", "nv"};
  538 +
  539 +typedef struct
  540 +{
  541 + const char * name;
  542 + const char * description;
  543 + const char * reg_names[16];
  544 +}
  545 +arm_regname;
  546 +
  547 +static arm_regname regnames[] =
  548 +{
  549 + { "raw" , "Select raw register names",
  550 + { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"}},
  551 + { "gcc", "Select register names used by GCC",
  552 + { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc" }},
  553 + { "std", "Select register names used in ARM's ISA documentation",
  554 + { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc" }},
  555 + { "apcs", "Select register names used in the APCS",
  556 + { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "sl", "fp", "ip", "sp", "lr", "pc" }},
  557 + { "atpcs", "Select register names used in the ATPCS",
  558 + { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "v4", "v5", "v6", "v7", "v8", "IP", "SP", "LR", "PC" }},
  559 + { "special-atpcs", "Select special register names used in the ATPCS",
  560 + { "a1", "a2", "a3", "a4", "v1", "v2", "v3", "WR", "v5", "SB", "SL", "FP", "IP", "SP", "LR", "PC" }}
  561 +};
  562 +
  563 +/* Default to GCC register name set. */
  564 +static unsigned int regname_selected = 1;
  565 +
  566 +#define NUM_ARM_REGNAMES NUM_ELEM (regnames)
  567 +#define arm_regnames regnames[regname_selected].reg_names
  568 +
  569 +static boolean force_thumb = false;
  570 +
  571 +static char * arm_fp_const[] =
  572 +{"0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0"};
  573 +
  574 +static char * arm_shift[] =
  575 +{"lsl", "lsr", "asr", "ror"};
  576 +
  577 +/* Forward declarations. */
  578 +static void arm_decode_shift PARAMS ((long, fprintf_ftype, void *));
  579 +static int print_insn_arm1 PARAMS ((bfd_vma, struct disassemble_info *, long));
  580 +static int print_insn_thumb PARAMS ((bfd_vma, struct disassemble_info *, long));
  581 +static void parse_disassembler_options PARAMS ((char *));
  582 +int get_arm_regname_num_options (void);
  583 +int set_arm_regname_option (int option);
  584 +int get_arm_regnames (int option, const char **setname,
  585 + const char **setdescription,
  586 + const char ***register_names);
  587 +
  588 +/* Functions. */
  589 +int
  590 +get_arm_regname_num_options ()
  591 +{
  592 + return NUM_ARM_REGNAMES;
  593 +}
  594 +
  595 +int
  596 +set_arm_regname_option (option)
  597 + int option;
  598 +{
  599 + int old = regname_selected;
  600 + regname_selected = option;
  601 + return old;
  602 +}
  603 +
  604 +int
  605 +get_arm_regnames (option, setname, setdescription, register_names)
  606 + int option;
  607 + const char **setname;
  608 + const char **setdescription;
  609 + const char ***register_names;
  610 +{
  611 + *setname = regnames[option].name;
  612 + *setdescription = regnames[option].description;
  613 + *register_names = regnames[option].reg_names;
  614 + return 16;
  615 +}
  616 +
  617 +static void
  618 +arm_decode_shift (given, func, stream)
  619 + long given;
  620 + fprintf_ftype func;
  621 + void * stream;
  622 +{
  623 + func (stream, "%s", arm_regnames[given & 0xf]);
  624 +
  625 + if ((given & 0xff0) != 0)
  626 + {
  627 + if ((given & 0x10) == 0)
  628 + {
  629 + int amount = (given & 0xf80) >> 7;
  630 + int shift = (given & 0x60) >> 5;
  631 +
  632 + if (amount == 0)
  633 + {
  634 + if (shift == 3)
  635 + {
  636 + func (stream, ", rrx");
  637 + return;
  638 + }
  639 +
  640 + amount = 32;
  641 + }
  642 +
  643 + func (stream, ", %s #%d", arm_shift[shift], amount);
  644 + }
  645 + else
  646 + func (stream, ", %s %s", arm_shift[(given & 0x60) >> 5],
  647 + arm_regnames[(given & 0xf00) >> 8]);
  648 + }
  649 +}
  650 +
  651 +/* Print one instruction from PC on INFO->STREAM.
  652 + Return the size of the instruction (always 4 on ARM). */
  653 +
  654 +static int
  655 +print_insn_arm1 (pc, info, given)
  656 + bfd_vma pc;
  657 + struct disassemble_info * info;
  658 + long given;
  659 +{
  660 + struct arm_opcode * insn;
  661 + void * stream = info->stream;
  662 + fprintf_ftype func = info->fprintf_func;
  663 +
  664 + for (insn = arm_opcodes; insn->assembler; insn++)
  665 + {
  666 + if ((given & insn->mask) == insn->value)
  667 + {
  668 + char * c;
  669 +
  670 + for (c = insn->assembler; *c; c++)
  671 + {
  672 + if (*c == '%')
  673 + {
  674 + switch (*++c)
  675 + {
  676 + case '%':
  677 + func (stream, "%%");
  678 + break;
  679 +
  680 + case 'a':
  681 + if (((given & 0x000f0000) == 0x000f0000)
  682 + && ((given & 0x02000000) == 0))
  683 + {
  684 + int offset = given & 0xfff;
  685 +
  686 + func (stream, "[pc");
  687 +
  688 + if (given & 0x01000000)
  689 + {
  690 + if ((given & 0x00800000) == 0)
  691 + offset = - offset;
  692 +
  693 + /* Pre-indexed. */
  694 + func (stream, ", #%d]", offset);
  695 +
  696 + offset += pc + 8;
  697 +
  698 + /* Cope with the possibility of write-back
  699 + being used. Probably a very dangerous thing
  700 + for the programmer to do, but who are we to
  701 + argue ? */
  702 + if (given & 0x00200000)
  703 + func (stream, "!");
  704 + }
  705 + else
  706 + {
  707 + /* Post indexed. */
  708 + func (stream, "], #%d", offset);
  709 +
  710 + /* ie ignore the offset. */
  711 + offset = pc + 8;
  712 + }
  713 +
  714 + func (stream, "\t; ");
  715 + info->print_address_func (offset, info);
  716 + }
  717 + else
  718 + {
  719 + func (stream, "[%s",
  720 + arm_regnames[(given >> 16) & 0xf]);
  721 + if ((given & 0x01000000) != 0)
  722 + {
  723 + if ((given & 0x02000000) == 0)
  724 + {
  725 + int offset = given & 0xfff;
  726 + if (offset)
  727 + func (stream, ", %s#%d",
  728 + (((given & 0x00800000) == 0)
  729 + ? "-" : ""), offset);
  730 + }
  731 + else
  732 + {
  733 + func (stream, ", %s",
  734 + (((given & 0x00800000) == 0)
  735 + ? "-" : ""));
  736 + arm_decode_shift (given, func, stream);
  737 + }
  738 +
  739 + func (stream, "]%s",
  740 + ((given & 0x00200000) != 0) ? "!" : "");
  741 + }
  742 + else
  743 + {
  744 + if ((given & 0x02000000) == 0)
  745 + {
  746 + int offset = given & 0xfff;
  747 + if (offset)
  748 + func (stream, "], %s#%d",
  749 + (((given & 0x00800000) == 0)
  750 + ? "-" : ""), offset);
  751 + else
  752 + func (stream, "]");
  753 + }
  754 + else
  755 + {
  756 + func (stream, "], %s",
  757 + (((given & 0x00800000) == 0)
  758 + ? "-" : ""));
  759 + arm_decode_shift (given, func, stream);
  760 + }
  761 + }
  762 + }
  763 + break;
  764 +
  765 + case 's':
  766 + if ((given & 0x004f0000) == 0x004f0000)
  767 + {
  768 + /* PC relative with immediate offset. */
  769 + int offset = ((given & 0xf00) >> 4) | (given & 0xf);
  770 +
  771 + if ((given & 0x00800000) == 0)
  772 + offset = -offset;
  773 +
  774 + func (stream, "[pc, #%d]\t; ", offset);
  775 +
  776 + (*info->print_address_func)
  777 + (offset + pc + 8, info);
  778 + }
  779 + else
  780 + {
  781 + func (stream, "[%s",
  782 + arm_regnames[(given >> 16) & 0xf]);
  783 + if ((given & 0x01000000) != 0)
  784 + {
  785 + /* Pre-indexed. */
  786 + if ((given & 0x00400000) == 0x00400000)
  787 + {
  788 + /* Immediate. */
  789 + int offset = ((given & 0xf00) >> 4) | (given & 0xf);
  790 + if (offset)
  791 + func (stream, ", %s#%d",
  792 + (((given & 0x00800000) == 0)
  793 + ? "-" : ""), offset);
  794 + }
  795 + else
  796 + {
  797 + /* Register. */
  798 + func (stream, ", %s%s",
  799 + (((given & 0x00800000) == 0)
  800 + ? "-" : ""),
  801 + arm_regnames[given & 0xf]);
  802 + }
  803 +
  804 + func (stream, "]%s",
  805 + ((given & 0x00200000) != 0) ? "!" : "");
  806 + }
  807 + else
  808 + {
  809 + /* Post-indexed. */
  810 + if ((given & 0x00400000) == 0x00400000)
  811 + {
  812 + /* Immediate. */
  813 + int offset = ((given & 0xf00) >> 4) | (given & 0xf);
  814 + if (offset)
  815 + func (stream, "], %s#%d",
  816 + (((given & 0x00800000) == 0)
  817 + ? "-" : ""), offset);
  818 + else
  819 + func (stream, "]");
  820 + }
  821 + else
  822 + {
  823 + /* Register. */
  824 + func (stream, "], %s%s",
  825 + (((given & 0x00800000) == 0)
  826 + ? "-" : ""),
  827 + arm_regnames[given & 0xf]);
  828 + }
  829 + }
  830 + }
  831 + break;
  832 +
  833 + case 'b':
  834 + (*info->print_address_func)
  835 + (BDISP (given) * 4 + pc + 8, info);
  836 + break;
  837 +
  838 + case 'c':
  839 + func (stream, "%s",
  840 + arm_conditional [(given >> 28) & 0xf]);
  841 + break;
  842 +
  843 + case 'm':
  844 + {
  845 + int started = 0;
  846 + int reg;
  847 +
  848 + func (stream, "{");
  849 + for (reg = 0; reg < 16; reg++)
  850 + if ((given & (1 << reg)) != 0)
  851 + {
  852 + if (started)
  853 + func (stream, ", ");
  854 + started = 1;
  855 + func (stream, "%s", arm_regnames[reg]);
  856 + }
  857 + func (stream, "}");
  858 + }
  859 + break;
  860 +
  861 + case 'o':
  862 + if ((given & 0x02000000) != 0)
  863 + {
  864 + int rotate = (given & 0xf00) >> 7;
  865 + int immed = (given & 0xff);
  866 + immed = (((immed << (32 - rotate))
  867 + | (immed >> rotate)) & 0xffffffff);
  868 + func (stream, "#%d\t; 0x%x", immed, immed);
  869 + }
  870 + else
  871 + arm_decode_shift (given, func, stream);
  872 + break;
  873 +
  874 + case 'p':
  875 + if ((given & 0x0000f000) == 0x0000f000)
  876 + func (stream, "p");
  877 + break;
  878 +
  879 + case 't':
  880 + if ((given & 0x01200000) == 0x00200000)
  881 + func (stream, "t");
  882 + break;
  883 +
  884 + case 'A':
  885 + func (stream, "[%s", arm_regnames [(given >> 16) & 0xf]);
  886 + if ((given & 0x01000000) != 0)
  887 + {
  888 + int offset = given & 0xff;
  889 + if (offset)
  890 + func (stream, ", %s#%d]%s",
  891 + ((given & 0x00800000) == 0 ? "-" : ""),
  892 + offset * 4,
  893 + ((given & 0x00200000) != 0 ? "!" : ""));
  894 + else
  895 + func (stream, "]");
  896 + }
  897 + else
  898 + {
  899 + int offset = given & 0xff;
  900 + if (offset)
  901 + func (stream, "], %s#%d",
  902 + ((given & 0x00800000) == 0 ? "-" : ""),
  903 + offset * 4);
  904 + else
  905 + func (stream, "]");
  906 + }
  907 + break;
  908 +
  909 + case 'B':
  910 + /* Print ARM V5 BLX(1) address: pc+25 bits. */
  911 + {
  912 + bfd_vma address;
  913 + bfd_vma offset = 0;
  914 +
  915 + if (given & 0x00800000)
  916 + /* Is signed, hi bits should be ones. */
  917 + offset = (-1) ^ 0x00ffffff;
  918 +
  919 + /* Offset is (SignExtend(offset field)<<2). */
  920 + offset += given & 0x00ffffff;
  921 + offset <<= 2;
  922 + address = offset + pc + 8;
  923 +
  924 + if (given & 0x01000000)
  925 + /* H bit allows addressing to 2-byte boundaries. */
  926 + address += 2;
  927 +
  928 + info->print_address_func (address, info);
  929 + }
  930 + break;
  931 +
  932 + case 'I':
  933 + /* Print a Cirrus/DSP shift immediate. */
  934 + /* Immediates are 7bit signed ints with bits 0..3 in
  935 + bits 0..3 of opcode and bits 4..6 in bits 5..7
  936 + of opcode. */
  937 + {
  938 + int imm;
  939 +
  940 + imm = (given & 0xf) | ((given & 0xe0) >> 1);
  941 +
  942 + /* Is ``imm'' a negative number? */
  943 + if (imm & 0x40)
  944 + imm |= (-1 << 7);
  945 +
  946 + func (stream, "%d", imm);
  947 + }
  948 +
  949 + break;
  950 +
  951 + case 'C':
  952 + func (stream, "_");
  953 + if (given & 0x80000)
  954 + func (stream, "f");
  955 + if (given & 0x40000)
  956 + func (stream, "s");
  957 + if (given & 0x20000)
  958 + func (stream, "x");
  959 + if (given & 0x10000)
  960 + func (stream, "c");
  961 + break;
  962 +
  963 + case 'F':
  964 + switch (given & 0x00408000)
  965 + {
  966 + case 0:
  967 + func (stream, "4");
  968 + break;
  969 + case 0x8000:
  970 + func (stream, "1");
  971 + break;
  972 + case 0x00400000:
  973 + func (stream, "2");
  974 + break;
  975 + default:
  976 + func (stream, "3");
  977 + }
  978 + break;
  979 +
  980 + case 'P':
  981 + switch (given & 0x00080080)
  982 + {
  983 + case 0:
  984 + func (stream, "s");
  985 + break;
  986 + case 0x80:
  987 + func (stream, "d");
  988 + break;
  989 + case 0x00080000:
  990 + func (stream, "e");
  991 + break;
  992 + default:
  993 + func (stream, _("<illegal precision>"));
  994 + break;
  995 + }
  996 + break;
  997 + case 'Q':
  998 + switch (given & 0x00408000)
  999 + {
  1000 + case 0:
  1001 + func (stream, "s");
  1002 + break;
  1003 + case 0x8000:
  1004 + func (stream, "d");
  1005 + break;
  1006 + case 0x00400000:
  1007 + func (stream, "e");
  1008 + break;
  1009 + default:
  1010 + func (stream, "p");
  1011 + break;
  1012 + }
  1013 + break;
  1014 + case 'R':
  1015 + switch (given & 0x60)
  1016 + {
  1017 + case 0:
  1018 + break;
  1019 + case 0x20:
  1020 + func (stream, "p");
  1021 + break;
  1022 + case 0x40:
  1023 + func (stream, "m");
  1024 + break;
  1025 + default:
  1026 + func (stream, "z");
  1027 + break;
  1028 + }
  1029 + break;
  1030 +
  1031 + case '0': case '1': case '2': case '3': case '4':
  1032 + case '5': case '6': case '7': case '8': case '9':
  1033 + {
  1034 + int bitstart = *c++ - '0';
  1035 + int bitend = 0;
  1036 + while (*c >= '0' && *c <= '9')
  1037 + bitstart = (bitstart * 10) + *c++ - '0';
  1038 +
  1039 + switch (*c)
  1040 + {
  1041 + case '-':
  1042 + c++;
  1043 +
  1044 + while (*c >= '0' && *c <= '9')
  1045 + bitend = (bitend * 10) + *c++ - '0';
  1046 +
  1047 + if (!bitend)
  1048 + abort ();
  1049 +
  1050 + switch (*c)
  1051 + {
  1052 + case 'r':
  1053 + {
  1054 + long reg;
  1055 +
  1056 + reg = given >> bitstart;
  1057 + reg &= (2 << (bitend - bitstart)) - 1;
  1058 +
  1059 + func (stream, "%s", arm_regnames[reg]);
  1060 + }
  1061 + break;
  1062 + case 'd':
  1063 + {
  1064 + long reg;
  1065 +
  1066 + reg = given >> bitstart;
  1067 + reg &= (2 << (bitend - bitstart)) - 1;
  1068 +
  1069 + func (stream, "%d", reg);
  1070 + }
  1071 + break;
  1072 + case 'x':
  1073 + {
  1074 + long reg;
  1075 +
  1076 + reg = given >> bitstart;
  1077 + reg &= (2 << (bitend - bitstart)) - 1;
  1078 +
  1079 + func (stream, "0x%08x", reg);
  1080 +
  1081 + /* Some SWI instructions have special
  1082 + meanings. */
  1083 + if ((given & 0x0fffffff) == 0x0FF00000)
  1084 + func (stream, "\t; IMB");
  1085 + else if ((given & 0x0fffffff) == 0x0FF00001)
  1086 + func (stream, "\t; IMBRange");
  1087 + }
  1088 + break;
  1089 + case 'X':
  1090 + {
  1091 + long reg;
  1092 +
  1093 + reg = given >> bitstart;
  1094 + reg &= (2 << (bitend - bitstart)) - 1;
  1095 +
  1096 + func (stream, "%01x", reg & 0xf);
  1097 + }
  1098 + break;
  1099 + case 'f':
  1100 + {
  1101 + long reg;
  1102 +
  1103 + reg = given >> bitstart;
  1104 + reg &= (2 << (bitend - bitstart)) - 1;
  1105 +
  1106 + if (reg > 7)
  1107 + func (stream, "#%s",
  1108 + arm_fp_const[reg & 7]);
  1109 + else
  1110 + func (stream, "f%d", reg);
  1111 + }
  1112 + break;
  1113 + default:
  1114 + abort ();
  1115 + }
  1116 + break;
  1117 +
  1118 + case 'y':
  1119 + case 'z':
  1120 + {
  1121 + int single = *c == 'y';
  1122 + int regno;
  1123 +
  1124 + switch (bitstart)
  1125 + {
  1126 + case 4: /* Sm pair */
  1127 + func (stream, "{");
  1128 + /* Fall through. */
  1129 + case 0: /* Sm, Dm */
  1130 + regno = given & 0x0000000f;
  1131 + if (single)
  1132 + {
  1133 + regno <<= 1;
  1134 + regno += (given >> 5) & 1;
  1135 + }
  1136 + break;
  1137 +
  1138 + case 1: /* Sd, Dd */
  1139 + regno = (given >> 12) & 0x0000000f;
  1140 + if (single)
  1141 + {
  1142 + regno <<= 1;
  1143 + regno += (given >> 22) & 1;
  1144 + }
  1145 + break;
  1146 +
  1147 + case 2: /* Sn, Dn */
  1148 + regno = (given >> 16) & 0x0000000f;
  1149 + if (single)
  1150 + {
  1151 + regno <<= 1;
  1152 + regno += (given >> 7) & 1;
  1153 + }
  1154 + break;
  1155 +
  1156 + case 3: /* List */
  1157 + func (stream, "{");
  1158 + regno = (given >> 12) & 0x0000000f;
  1159 + if (single)
  1160 + {
  1161 + regno <<= 1;
  1162 + regno += (given >> 22) & 1;
  1163 + }
  1164 + break;
  1165 +
  1166 +
  1167 + default:
  1168 + abort ();
  1169 + }
  1170 +
  1171 + func (stream, "%c%d", single ? 's' : 'd', regno);
  1172 +
  1173 + if (bitstart == 3)
  1174 + {
  1175 + int count = given & 0xff;
  1176 +
  1177 + if (single == 0)
  1178 + count >>= 1;
  1179 +
  1180 + if (--count)
  1181 + {
  1182 + func (stream, "-%c%d",
  1183 + single ? 's' : 'd',
  1184 + regno + count);
  1185 + }
  1186 +
  1187 + func (stream, "}");
  1188 + }
  1189 + else if (bitstart == 4)
  1190 + func (stream, ", %c%d}", single ? 's' : 'd',
  1191 + regno + 1);
  1192 +
  1193 + break;
  1194 + }
  1195 +
  1196 + case '`':
  1197 + c++;
  1198 + if ((given & (1 << bitstart)) == 0)
  1199 + func (stream, "%c", *c);
  1200 + break;
  1201 + case '\'':
  1202 + c++;
  1203 + if ((given & (1 << bitstart)) != 0)
  1204 + func (stream, "%c", *c);
  1205 + break;
  1206 + case '?':
  1207 + ++c;
  1208 + if ((given & (1 << bitstart)) != 0)
  1209 + func (stream, "%c", *c++);
  1210 + else
  1211 + func (stream, "%c", *++c);
  1212 + break;
  1213 + default:
  1214 + abort ();
  1215 + }
  1216 + break;
  1217 +
  1218 + default:
  1219 + abort ();
  1220 + }
  1221 + }
  1222 + }
  1223 + else
  1224 + func (stream, "%c", *c);
  1225 + }
  1226 + return 4;
  1227 + }
  1228 + }
  1229 + abort ();
  1230 +}
  1231 +
  1232 +/* Print one instruction from PC on INFO->STREAM.
  1233 + Return the size of the instruction. */
  1234 +
  1235 +static int
  1236 +print_insn_thumb (pc, info, given)
  1237 + bfd_vma pc;
  1238 + struct disassemble_info * info;
  1239 + long given;
  1240 +{
  1241 + struct thumb_opcode * insn;
  1242 + void * stream = info->stream;
  1243 + fprintf_ftype func = info->fprintf_func;
  1244 +
  1245 + for (insn = thumb_opcodes; insn->assembler; insn++)
  1246 + {
  1247 + if ((given & insn->mask) == insn->value)
  1248 + {
  1249 + char * c = insn->assembler;
  1250 +
  1251 + /* Special processing for Thumb 2 instruction BL sequence: */
  1252 + if (!*c) /* Check for empty (not NULL) assembler string. */
  1253 + {
  1254 + long offset;
  1255 +
  1256 + info->bytes_per_chunk = 4;
  1257 + info->bytes_per_line = 4;
  1258 +
  1259 + offset = BDISP23 (given);
  1260 + offset = offset * 2 + pc + 4;
  1261 +
  1262 + if ((given & 0x10000000) == 0)
  1263 + {
  1264 + func (stream, "blx\t");
  1265 + offset &= 0xfffffffc;
  1266 + }
  1267 + else
  1268 + func (stream, "bl\t");
  1269 +
  1270 + info->print_address_func (offset, info);
  1271 + return 4;
  1272 + }
  1273 + else
  1274 + {
  1275 + info->bytes_per_chunk = 2;
  1276 + info->bytes_per_line = 4;
  1277 +
  1278 + given &= 0xffff;
  1279 +
  1280 + for (; *c; c++)
  1281 + {
  1282 + if (*c == '%')
  1283 + {
  1284 + int domaskpc = 0;
  1285 + int domasklr = 0;
  1286 +
  1287 + switch (*++c)
  1288 + {
  1289 + case '%':
  1290 + func (stream, "%%");
  1291 + break;
  1292 +
  1293 + case 'S':
  1294 + {
  1295 + long reg;
  1296 +
  1297 + reg = (given >> 3) & 0x7;
  1298 + if (given & (1 << 6))
  1299 + reg += 8;
  1300 +
  1301 + func (stream, "%s", arm_regnames[reg]);
  1302 + }
  1303 + break;
  1304 +
  1305 + case 'D':
  1306 + {
  1307 + long reg;
  1308 +
  1309 + reg = given & 0x7;
  1310 + if (given & (1 << 7))
  1311 + reg += 8;
  1312 +
  1313 + func (stream, "%s", arm_regnames[reg]);
  1314 + }
  1315 + break;
  1316 +
  1317 + case 'T':
  1318 + func (stream, "%s",
  1319 + arm_conditional [(given >> 8) & 0xf]);
  1320 + break;
  1321 +
  1322 + case 'N':
  1323 + if (given & (1 << 8))
  1324 + domasklr = 1;
  1325 + /* Fall through. */
  1326 + case 'O':
  1327 + if (*c == 'O' && (given & (1 << 8)))
  1328 + domaskpc = 1;
  1329 + /* Fall through. */
  1330 + case 'M':
  1331 + {
  1332 + int started = 0;
  1333 + int reg;
  1334 +
  1335 + func (stream, "{");
  1336 +
  1337 + /* It would be nice if we could spot
  1338 + ranges, and generate the rS-rE format: */
  1339 + for (reg = 0; (reg < 8); reg++)
  1340 + if ((given & (1 << reg)) != 0)
  1341 + {
  1342 + if (started)
  1343 + func (stream, ", ");
  1344 + started = 1;
  1345 + func (stream, "%s", arm_regnames[reg]);
  1346 + }
  1347 +
  1348 + if (domasklr)
  1349 + {
  1350 + if (started)
  1351 + func (stream, ", ");
  1352 + started = 1;
  1353 + func (stream, arm_regnames[14] /* "lr" */);
  1354 + }
  1355 +
  1356 + if (domaskpc)
  1357 + {
  1358 + if (started)
  1359 + func (stream, ", ");
  1360 + func (stream, arm_regnames[15] /* "pc" */);
  1361 + }
  1362 +
  1363 + func (stream, "}");
  1364 + }
  1365 + break;
  1366 +
  1367 +
  1368 + case '0': case '1': case '2': case '3': case '4':
  1369 + case '5': case '6': case '7': case '8': case '9':
  1370 + {
  1371 + int bitstart = *c++ - '0';
  1372 + int bitend = 0;
  1373 +
  1374 + while (*c >= '0' && *c <= '9')
  1375 + bitstart = (bitstart * 10) + *c++ - '0';
  1376 +
  1377 + switch (*c)
  1378 + {
  1379 + case '-':
  1380 + {
  1381 + long reg;
  1382 +
  1383 + c++;
  1384 + while (*c >= '0' && *c <= '9')
  1385 + bitend = (bitend * 10) + *c++ - '0';
  1386 + if (!bitend)
  1387 + abort ();
  1388 + reg = given >> bitstart;
  1389 + reg &= (2 << (bitend - bitstart)) - 1;
  1390 + switch (*c)
  1391 + {
  1392 + case 'r':
  1393 + func (stream, "%s", arm_regnames[reg]);
  1394 + break;
  1395 +
  1396 + case 'd':
  1397 + func (stream, "%d", reg);
  1398 + break;
  1399 +
  1400 + case 'H':
  1401 + func (stream, "%d", reg << 1);
  1402 + break;
  1403 +
  1404 + case 'W':
  1405 + func (stream, "%d", reg << 2);
  1406 + break;
  1407 +
  1408 + case 'a':
  1409 + /* PC-relative address -- the bottom two
  1410 + bits of the address are dropped
  1411 + before the calculation. */
  1412 + info->print_address_func
  1413 + (((pc + 4) & ~3) + (reg << 2), info);
  1414 + break;
  1415 +
  1416 + case 'x':
  1417 + func (stream, "0x%04x", reg);
  1418 + break;
  1419 +
  1420 + case 'I':
  1421 + reg = ((reg ^ (1 << bitend)) - (1 << bitend));
  1422 + func (stream, "%d", reg);
  1423 + break;
  1424 +
  1425 + case 'B':
  1426 + reg = ((reg ^ (1 << bitend)) - (1 << bitend));
  1427 + (*info->print_address_func)
  1428 + (reg * 2 + pc + 4, info);
  1429 + break;
  1430 +
  1431 + default:
  1432 + abort ();
  1433 + }
  1434 + }
  1435 + break;
  1436 +
  1437 + case '\'':
  1438 + c++;
  1439 + if ((given & (1 << bitstart)) != 0)
  1440 + func (stream, "%c", *c);
  1441 + break;
  1442 +
  1443 + case '?':
  1444 + ++c;
  1445 + if ((given & (1 << bitstart)) != 0)
  1446 + func (stream, "%c", *c++);
  1447 + else
  1448 + func (stream, "%c", *++c);
  1449 + break;
  1450 +
  1451 + default:
  1452 + abort ();
  1453 + }
  1454 + }
  1455 + break;
  1456 +
  1457 + default:
  1458 + abort ();
  1459 + }
  1460 + }
  1461 + else
  1462 + func (stream, "%c", *c);
  1463 + }
  1464 + }
  1465 + return 2;
  1466 + }
  1467 + }
  1468 +
  1469 + /* No match. */
  1470 + abort ();
  1471 +}
  1472 +
  1473 +/* Parse an individual disassembler option. */
  1474 +
  1475 +void
  1476 +parse_arm_disassembler_option (option)
  1477 + char * option;
  1478 +{
  1479 + if (option == NULL)
  1480 + return;
  1481 +
  1482 + if (strneq (option, "reg-names-", 10))
  1483 + {
  1484 + int i;
  1485 +
  1486 + option += 10;
  1487 +
  1488 + for (i = NUM_ARM_REGNAMES; i--;)
  1489 + if (streq (option, regnames[i].name))
  1490 + {
  1491 + regname_selected = i;
  1492 + break;
  1493 + }
  1494 +
  1495 + if (i < 0)
  1496 + fprintf (stderr, _("Unrecognised register name set: %s\n"), option);
  1497 + }
  1498 + else if (streq (option, "force-thumb"))
  1499 + force_thumb = 1;
  1500 + else if (streq (option, "no-force-thumb"))
  1501 + force_thumb = 0;
  1502 + else
  1503 + fprintf (stderr, _("Unrecognised disassembler option: %s\n"), option);
  1504 +
  1505 + return;
  1506 +}
  1507 +
  1508 +/* Parse the string of disassembler options, spliting it at whitespaces. */
  1509 +
  1510 +static void
  1511 +parse_disassembler_options (options)
  1512 + char * options;
  1513 +{
  1514 + char * space;
  1515 +
  1516 + if (options == NULL)
  1517 + return;
  1518 +
  1519 + do
  1520 + {
  1521 + space = strchr (options, ' ');
  1522 +
  1523 + if (space)
  1524 + {
  1525 + * space = '\0';
  1526 + parse_arm_disassembler_option (options);
  1527 + * space = ' ';
  1528 + options = space + 1;
  1529 + }
  1530 + else
  1531 + parse_arm_disassembler_option (options);
  1532 + }
  1533 + while (space);
  1534 +}
  1535 +
  1536 +/* NOTE: There are no checks in these routines that
  1537 + the relevant number of data bytes exist. */
  1538 +
  1539 +int
  1540 +print_insn_arm (pc, info)
  1541 + bfd_vma pc;
  1542 + struct disassemble_info * info;
  1543 +{
  1544 + unsigned char b[4];
  1545 + long given;
  1546 + int status;
  1547 + int is_thumb;
  1548 + int little;
  1549 +
  1550 + if (info->disassembler_options)
  1551 + {
  1552 + parse_disassembler_options (info->disassembler_options);
  1553 +
  1554 + /* To avoid repeated parsing of these options, we remove them here. */
  1555 + info->disassembler_options = NULL;
  1556 + }
  1557 +
  1558 + is_thumb = force_thumb;
  1559 +
  1560 +#if 0
  1561 + if (!is_thumb && info->symbols != NULL)
  1562 + {
  1563 + if (bfd_asymbol_flavour (*info->symbols) == bfd_target_coff_flavour)
  1564 + {
  1565 + coff_symbol_type * cs;
  1566 +
  1567 + cs = coffsymbol (*info->symbols);
  1568 + is_thumb = ( cs->native->u.syment.n_sclass == C_THUMBEXT
  1569 + || cs->native->u.syment.n_sclass == C_THUMBSTAT
  1570 + || cs->native->u.syment.n_sclass == C_THUMBLABEL
  1571 + || cs->native->u.syment.n_sclass == C_THUMBEXTFUNC
  1572 + || cs->native->u.syment.n_sclass == C_THUMBSTATFUNC);
  1573 + }
  1574 + else if (bfd_asymbol_flavour (*info->symbols) == bfd_target_elf_flavour)
  1575 + {
  1576 + elf_symbol_type * es;
  1577 + unsigned int type;
  1578 +
  1579 + es = *(elf_symbol_type **)(info->symbols);
  1580 + type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
  1581 +
  1582 + is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT);
  1583 + }
  1584 + }
  1585 +#endif
  1586 +
  1587 + little = (info->endian == BFD_ENDIAN_LITTLE);
  1588 + info->bytes_per_chunk = 4;
  1589 + info->display_endian = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG;
  1590 +
  1591 + if (little)
  1592 + {
  1593 + status = info->read_memory_func (pc, (bfd_byte *) &b[0], 4, info);
  1594 + if (status != 0 && is_thumb)
  1595 + {
  1596 + info->bytes_per_chunk = 2;
  1597 +
  1598 + status = info->read_memory_func (pc, (bfd_byte *) b, 2, info);
  1599 + b[3] = b[2] = 0;
  1600 + }
  1601 +
  1602 + if (status != 0)
  1603 + {
  1604 + info->memory_error_func (status, pc, info);
  1605 + return -1;
  1606 + }
  1607 +
  1608 + given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24);
  1609 + }
  1610 + else
  1611 + {
  1612 + status = info->read_memory_func
  1613 + (pc & ~ 0x3, (bfd_byte *) &b[0], 4, info);
  1614 + if (status != 0)
  1615 + {
  1616 + info->memory_error_func (status, pc, info);
  1617 + return -1;
  1618 + }
  1619 +
  1620 + if (is_thumb)
  1621 + {
  1622 + if (pc & 0x2)
  1623 + {
  1624 + given = (b[2] << 8) | b[3];
  1625 +
  1626 + status = info->read_memory_func
  1627 + ((pc + 4) & ~ 0x3, (bfd_byte *) b, 4, info);
  1628 + if (status != 0)
  1629 + {
  1630 + info->memory_error_func (status, pc + 4, info);
  1631 + return -1;
  1632 + }
  1633 +
  1634 + given |= (b[0] << 24) | (b[1] << 16);
  1635 + }
  1636 + else
  1637 + given = (b[0] << 8) | b[1] | (b[2] << 24) | (b[3] << 16);
  1638 + }
  1639 + else
  1640 + given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]);
  1641 + }
  1642 +
  1643 + if (info->flags & INSN_HAS_RELOC)
  1644 + /* If the instruction has a reloc associated with it, then
  1645 + the offset field in the instruction will actually be the
  1646 + addend for the reloc. (We are using REL type relocs).
  1647 + In such cases, we can ignore the pc when computing
  1648 + addresses, since the addend is not currently pc-relative. */
  1649 + pc = 0;
  1650 + if (is_thumb)
  1651 + status = print_insn_thumb (pc, info, given);
  1652 + else
  1653 + status = print_insn_arm1 (pc, info, given);
  1654 +
  1655 + return status;
  1656 +}
  1657 +
  1658 +void
  1659 +print_arm_disassembler_options (FILE * stream)
  1660 +{
  1661 + int i;
  1662 +
  1663 + fprintf (stream, _("\n\
  1664 +The following ARM specific disassembler options are supported for use with\n\
  1665 +the -M switch:\n"));
  1666 +
  1667 + for (i = NUM_ARM_REGNAMES; i--;)
  1668 + fprintf (stream, " reg-names-%s %*c%s\n",
  1669 + regnames[i].name,
  1670 + (int)(14 - strlen (regnames[i].name)), ' ',
  1671 + regnames[i].description);
  1672 +
  1673 + fprintf (stream, " force-thumb Assume all insns are Thumb insns\n");
  1674 + fprintf (stream, " no-force-thumb Examine preceeding label to determine an insn's type\n\n");
  1675 +}
... ...
dis-asm.h
... ... @@ -73,16 +73,20 @@ enum bfd_architecture
73 73 bfd_arch_a29k, /* AMD 29000 */
74 74 bfd_arch_sparc, /* SPARC */
75 75 #define bfd_mach_sparc 1
76   - /* The difference between v8plus and v9 is that v9 is a true 64 bit env. */
  76 +/* The difference between v8plus and v9 is that v9 is a true 64 bit env. */
77 77 #define bfd_mach_sparc_sparclet 2
78 78 #define bfd_mach_sparc_sparclite 3
79 79 #define bfd_mach_sparc_v8plus 4
80   -#define bfd_mach_sparc_v8plusa 5 /* with ultrasparc add'ns */
81   -#define bfd_mach_sparc_v9 6
82   -#define bfd_mach_sparc_v9a 7 /* with ultrasparc add'ns */
83   - /* Nonzero if MACH has the v9 instruction set. */
  80 +#define bfd_mach_sparc_v8plusa 5 /* with ultrasparc add'ns. */
  81 +#define bfd_mach_sparc_sparclite_le 6
  82 +#define bfd_mach_sparc_v9 7
  83 +#define bfd_mach_sparc_v9a 8 /* with ultrasparc add'ns. */
  84 +#define bfd_mach_sparc_v8plusb 9 /* with cheetah add'ns. */
  85 +#define bfd_mach_sparc_v9b 10 /* with cheetah add'ns. */
  86 +/* Nonzero if MACH has the v9 instruction set. */
84 87 #define bfd_mach_sparc_v9_p(mach) \
85   - ((mach) >= bfd_mach_sparc_v8plus && (mach) <= bfd_mach_sparc_v9a)
  88 + ((mach) >= bfd_mach_sparc_v8plus && (mach) <= bfd_mach_sparc_v9b \
  89 + && (mach) != bfd_mach_sparc_sparclite_le)
86 90 bfd_arch_mips, /* MIPS Rxxxx */
87 91 #define bfd_mach_mips3000 3000
88 92 #define bfd_mach_mips3900 3900
... ... @@ -279,6 +283,9 @@ typedef struct disassemble_info {
279 283 zero if unknown. */
280 284 bfd_vma target2; /* Second target address for dref2 */
281 285  
  286 + /* Command line options specific to the target disassembler. */
  287 + char * disassembler_options;
  288 +
282 289 } disassemble_info;
283 290  
284 291  
... ... @@ -299,8 +306,7 @@ extern int print_insn_h8300s PARAMS ((bfd_vma, disassemble_info*));
299 306 extern int print_insn_h8500 PARAMS ((bfd_vma, disassemble_info*));
300 307 extern int print_insn_alpha PARAMS ((bfd_vma, disassemble_info*));
301 308 extern disassembler_ftype arc_get_disassembler PARAMS ((int, int));
302   -extern int print_insn_big_arm PARAMS ((bfd_vma, disassemble_info*));
303   -extern int print_insn_little_arm PARAMS ((bfd_vma, disassemble_info*));
  309 +extern int print_insn_arm PARAMS ((bfd_vma, disassemble_info*));
304 310 extern int print_insn_sparc PARAMS ((bfd_vma, disassemble_info*));
305 311 extern int print_insn_big_a29k PARAMS ((bfd_vma, disassemble_info*));
306 312 extern int print_insn_little_a29k PARAMS ((bfd_vma, disassemble_info*));
... ... @@ -381,6 +387,15 @@ extern int generic_symbol_at_address
381 387 (INFO).bytes_per_line = 0, \
382 388 (INFO).bytes_per_chunk = 0, \
383 389 (INFO).display_endian = BFD_ENDIAN_UNKNOWN, \
  390 + (INFO).disassembler_options = NULL, \
384 391 (INFO).insn_info_valid = 0
385 392  
  393 +#define _(x) x
  394 +
  395 +/* from libbfd */
  396 +
  397 +bfd_vma bfd_getl32 (const bfd_byte *addr);
  398 +bfd_vma bfd_getb32 (const bfd_byte *addr);
  399 +typedef enum bfd_boolean {false, true} boolean;
  400 +
386 401 #endif /* ! defined (DIS_ASM_H) */
... ...
dis-buf.c deleted 100644 → 0
1   -/* Disassemble from a buffer, for GNU.
2   - Copyright (C) 1993, 1994 Free Software Foundation, Inc.
3   -
4   -This program is free software; you can redistribute it and/or modify
5   -it under the terms of the GNU General Public License as published by
6   -the Free Software Foundation; either version 2 of the License, or
7   -(at your option) any later version.
8   -
9   -This program is distributed in the hope that it will be useful,
10   -but WITHOUT ANY WARRANTY; without even the implied warranty of
11   -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12   -GNU General Public License for more details.
13   -
14   -You should have received a copy of the GNU General Public License
15   -along with this program; if not, write to the Free Software
16   -Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
17   -
18   -#include "dis-asm.h"
19   -#include <errno.h>
20   -
21   -/* Get LENGTH bytes from info's buffer, at target address memaddr.
22   - Transfer them to myaddr. */
23   -int
24   -buffer_read_memory (memaddr, myaddr, length, info)
25   - bfd_vma memaddr;
26   - bfd_byte *myaddr;
27   - int length;
28   - struct disassemble_info *info;
29   -{
30   - if (memaddr < info->buffer_vma
31   - || memaddr + length > info->buffer_vma + info->buffer_length)
32   - /* Out of bounds. Use EIO because GDB uses it. */
33   - return EIO;
34   - memcpy (myaddr, info->buffer + (memaddr - info->buffer_vma), length);
35   - return 0;
36   -}
37   -
38   -/* Print an error message. We can assume that this is in response to
39   - an error return from buffer_read_memory. */
40   -void
41   -perror_memory (status, memaddr, info)
42   - int status;
43   - bfd_vma memaddr;
44   - struct disassemble_info *info;
45   -{
46   - if (status != EIO)
47   - /* Can't happen. */
48   - (*info->fprintf_func) (info->stream, "Unknown error %d\n", status);
49   - else
50   - /* Actually, address between memaddr and memaddr + len was
51   - out of bounds. */
52   - (*info->fprintf_func) (info->stream,
53   - "Address 0x%x is out of bounds.\n", memaddr);
54   -}
55   -
56   -/* This could be in a separate file, to save miniscule amounts of space
57   - in statically linked executables. */
58   -
59   -/* Just print the address is hex. This is included for completeness even
60   - though both GDB and objdump provide their own (to print symbolic
61   - addresses). */
62   -
63   -void
64   -generic_print_address (addr, info)
65   - bfd_vma addr;
66   - struct disassemble_info *info;
67   -{
68   - (*info->fprintf_func) (info->stream, "0x%x", addr);
69   -}
70   -
71   -/* Just return the given address. */
72   -
73   -int
74   -generic_symbol_at_address (addr, info)
75   - bfd_vma addr;
76   - struct disassemble_info * info;
77   -{
78   - return 1;
79   -}
... ... @@ -2,12 +2,95 @@
2 2 #include "dis-asm.h"
3 3 #include "disas.h"
4 4 #include "elf.h"
  5 +#include <errno.h>
5 6  
6 7 /* Filled in by elfload.c. Simplistic, but will do for now. */
7 8 unsigned int disas_num_syms;
8 9 void *disas_symtab;
9 10 const char *disas_strtab;
10 11  
  12 +/* Get LENGTH bytes from info's buffer, at target address memaddr.
  13 + Transfer them to myaddr. */
  14 +int
  15 +buffer_read_memory (memaddr, myaddr, length, info)
  16 + bfd_vma memaddr;
  17 + bfd_byte *myaddr;
  18 + int length;
  19 + struct disassemble_info *info;
  20 +{
  21 + if (memaddr < info->buffer_vma
  22 + || memaddr + length > info->buffer_vma + info->buffer_length)
  23 + /* Out of bounds. Use EIO because GDB uses it. */
  24 + return EIO;
  25 + memcpy (myaddr, info->buffer + (memaddr - info->buffer_vma), length);
  26 + return 0;
  27 +}
  28 +
  29 +/* Print an error message. We can assume that this is in response to
  30 + an error return from buffer_read_memory. */
  31 +void
  32 +perror_memory (status, memaddr, info)
  33 + int status;
  34 + bfd_vma memaddr;
  35 + struct disassemble_info *info;
  36 +{
  37 + if (status != EIO)
  38 + /* Can't happen. */
  39 + (*info->fprintf_func) (info->stream, "Unknown error %d\n", status);
  40 + else
  41 + /* Actually, address between memaddr and memaddr + len was
  42 + out of bounds. */
  43 + (*info->fprintf_func) (info->stream,
  44 + "Address 0x%x is out of bounds.\n", memaddr);
  45 +}
  46 +
  47 +/* This could be in a separate file, to save miniscule amounts of space
  48 + in statically linked executables. */
  49 +
  50 +/* Just print the address is hex. This is included for completeness even
  51 + though both GDB and objdump provide their own (to print symbolic
  52 + addresses). */
  53 +
  54 +void
  55 +generic_print_address (addr, info)
  56 + bfd_vma addr;
  57 + struct disassemble_info *info;
  58 +{
  59 + (*info->fprintf_func) (info->stream, "0x%x", addr);
  60 +}
  61 +
  62 +/* Just return the given address. */
  63 +
  64 +int
  65 +generic_symbol_at_address (addr, info)
  66 + bfd_vma addr;
  67 + struct disassemble_info * info;
  68 +{
  69 + return 1;
  70 +}
  71 +
  72 +bfd_vma bfd_getl32 (const bfd_byte *addr)
  73 +{
  74 + unsigned long v;
  75 +
  76 + v = (unsigned long) addr[0];
  77 + v |= (unsigned long) addr[1] << 8;
  78 + v |= (unsigned long) addr[2] << 16;
  79 + v |= (unsigned long) addr[3] << 24;
  80 + return (bfd_vma) v;
  81 +}
  82 +
  83 +bfd_vma bfd_getb32 (const bfd_byte *addr)
  84 +{
  85 + unsigned long v;
  86 +
  87 + v = (unsigned long) addr[0] << 24;
  88 + v |= (unsigned long) addr[1] << 16;
  89 + v |= (unsigned long) addr[2] << 8;
  90 + v |= (unsigned long) addr[3];
  91 + return (bfd_vma) v;
  92 +}
  93 +
11 94 /* Disassemble this for me please... (debugging). */
12 95 void disas(FILE *out, void *code, unsigned long size, enum disas_type type)
13 96 {
... ... @@ -35,6 +118,10 @@ void disas(FILE *out, void *code, unsigned long size, enum disas_type type)
35 118 print_insn = print_insn_ppc;
36 119 #elif defined(__alpha__)
37 120 print_insn = print_insn_alpha;
  121 +#elif defined(__sparc__)
  122 + print_insn = print_insn_sparc;
  123 +#elif defined(__arm__)
  124 + print_insn = print_insn_arm;
38 125 #else
39 126 fprintf(out, "Asm output not supported on this arch\n");
40 127 return;
... ... @@ -51,6 +138,13 @@ void disas(FILE *out, void *code, unsigned long size, enum disas_type type)
51 138  
52 139 for (pc = code; pc < (uint8_t *)code + size; pc += count) {
53 140 fprintf(out, "0x%08lx: ", (long)pc);
  141 +#ifdef __arm__
  142 + /* since data are included in the code, it is better to
  143 + display code data too */
  144 + if (type == DISAS_TARGET) {
  145 + fprintf(out, "%08x ", (int)bfd_getl32((const bfd_byte *)pc));
  146 + }
  147 +#endif
54 148 count = print_insn((unsigned long)pc, &disasm_info);
55 149 fprintf(out, "\n");
56 150 if (count < 0)
... ...
i386-dis.c
... ... @@ -1164,8 +1164,8 @@ int
1164 1164 print_insn_x86 (pc, info, aflag, dflag)
1165 1165 bfd_vma pc;
1166 1166 disassemble_info *info;
1167   - int aflag;
1168   - int dflag;
  1167 + int volatile aflag;
  1168 + int volatile dflag;
1169 1169 {
1170 1170 struct dis386 *dp;
1171 1171 int i;
... ...