Statistics
| Branch: | Revision:

root / arm-dis.c @ 14ce26e7

History | View | Annotate | Download (55.1 kB)

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 STD register name set.  */
564
static unsigned int regname_selected = 2;
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
}