]> Git Repo - binutils.git/blob - gas/config/tc-arm.c
* config/tc-i960.c (line_comment_chars): Add '#'.
[binutils.git] / gas / config / tc-arm.c
1 /* tc-arm.c -- Assemble for the ARM
2    Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
3    Free Software Foundation, Inc.
4    Contributed by Richard Earnshaw ([email protected])
5         Modified by David Taylor ([email protected])
6         Cirrus coprocessor mods by Aldy Hernandez ([email protected])
7
8    This file is part of GAS, the GNU Assembler.
9
10    GAS is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2, or (at your option)
13    any later version.
14
15    GAS is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with GAS; see the file COPYING.  If not, write to the Free
22    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.  */
24
25 #include <string.h>
26 #define  NO_RELOC 0
27 #include "as.h"
28 #include "safe-ctype.h"
29
30 /* Need TARGET_CPU.  */
31 #include "config.h"
32 #include "subsegs.h"
33 #include "obstack.h"
34 #include "symbols.h"
35 #include "listing.h"
36
37 #ifdef OBJ_ELF
38 #include "elf/arm.h"
39 #include "dwarf2dbg.h"
40 #endif
41
42 /* XXX Set this to 1 after the next binutils release */
43 #define WARN_DEPRECATED 0
44
45 /* The following bitmasks control CPU extensions:  */
46 #define ARM_EXT_V1       0x00000001     /* All processors (core set).  */
47 #define ARM_EXT_V2       0x00000002     /* Multiply instructions.  */
48 #define ARM_EXT_V2S      0x00000004     /* SWP instructions.       */
49 #define ARM_EXT_V3       0x00000008     /* MSR MRS.                */
50 #define ARM_EXT_V3M      0x00000010     /* Allow long multiplies.  */
51 #define ARM_EXT_V4       0x00000020     /* Allow half word loads.  */
52 #define ARM_EXT_V4T      0x00000040     /* Thumb v1.               */
53 #define ARM_EXT_V5       0x00000080     /* Allow CLZ, etc.         */
54 #define ARM_EXT_V5T      0x00000100     /* Thumb v2.               */
55 #define ARM_EXT_V5ExP    0x00000200     /* DSP core set.           */
56 #define ARM_EXT_V5E      0x00000400     /* DSP Double transfers.   */
57 #define ARM_EXT_V5J      0x00000800     /* Jazelle extension.      */
58
59 /* Co-processor space extensions.  */
60 #define ARM_CEXT_XSCALE   0x00800000    /* Allow MIA etc.          */
61 #define ARM_CEXT_MAVERICK 0x00400000    /* Use Cirrus/DSP coprocessor.  */
62 #define ARM_CEXT_IWMMXT   0x00200000    /* Intel Wireless MMX technology coprocessor.   */
63
64 /* Architectures are the sum of the base and extensions.  The ARM ARM (rev E)
65    defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
66    ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE.  To these we add
67    three more to cover cores prior to ARM6.  Finally, there are cores which
68    implement further extensions in the co-processor space.  */
69 #define ARM_ARCH_V1                       ARM_EXT_V1
70 #define ARM_ARCH_V2     (ARM_ARCH_V1    | ARM_EXT_V2)
71 #define ARM_ARCH_V2S    (ARM_ARCH_V2    | ARM_EXT_V2S)
72 #define ARM_ARCH_V3     (ARM_ARCH_V2S   | ARM_EXT_V3)
73 #define ARM_ARCH_V3M    (ARM_ARCH_V3    | ARM_EXT_V3M)
74 #define ARM_ARCH_V4xM   (ARM_ARCH_V3    | ARM_EXT_V4)
75 #define ARM_ARCH_V4     (ARM_ARCH_V3M   | ARM_EXT_V4)
76 #define ARM_ARCH_V4TxM  (ARM_ARCH_V4xM  | ARM_EXT_V4T)
77 #define ARM_ARCH_V4T    (ARM_ARCH_V4    | ARM_EXT_V4T)
78 #define ARM_ARCH_V5xM   (ARM_ARCH_V4xM  | ARM_EXT_V5)
79 #define ARM_ARCH_V5     (ARM_ARCH_V4    | ARM_EXT_V5)
80 #define ARM_ARCH_V5TxM  (ARM_ARCH_V5xM  | ARM_EXT_V4T | ARM_EXT_V5T)
81 #define ARM_ARCH_V5T    (ARM_ARCH_V5    | ARM_EXT_V4T | ARM_EXT_V5T)
82 #define ARM_ARCH_V5TExP (ARM_ARCH_V5T   | ARM_EXT_V5ExP)
83 #define ARM_ARCH_V5TE   (ARM_ARCH_V5TExP | ARM_EXT_V5E)
84 #define ARM_ARCH_V5TEJ  (ARM_ARCH_V5TE  | ARM_EXT_V5J)
85
86 /* Processors with specific extensions in the co-processor space.  */
87 #define ARM_ARCH_XSCALE (ARM_ARCH_V5TE  | ARM_CEXT_XSCALE)
88 #define ARM_ARCH_IWMMXT (ARM_ARCH_XSCALE | ARM_CEXT_IWMMXT)
89
90 /* Some useful combinations:  */
91 #define ARM_ANY         0x0000ffff      /* Any basic core.  */
92 #define ARM_ALL         0x00ffffff      /* Any core + co-processor */
93 #define CPROC_ANY       0x00ff0000      /* Any co-processor */
94 #define FPU_ANY         0xff000000      /* Note this is ~ARM_ALL.  */
95
96
97 #define FPU_FPA_EXT_V1   0x80000000     /* Base FPA instruction set.  */
98 #define FPU_FPA_EXT_V2   0x40000000     /* LFM/SFM.                   */
99 #define FPU_VFP_EXT_NONE 0x20000000     /* Use VFP word-ordering.     */
100 #define FPU_VFP_EXT_V1xD 0x10000000     /* Base VFP instruction set.  */
101 #define FPU_VFP_EXT_V1   0x08000000     /* Double-precision insns.    */
102 #define FPU_VFP_EXT_V2   0x04000000     /* ARM10E VFPr1.              */
103 #define FPU_NONE         0
104
105 #define FPU_ARCH_FPE     FPU_FPA_EXT_V1
106 #define FPU_ARCH_FPA    (FPU_ARCH_FPE | FPU_FPA_EXT_V2)
107
108 #define FPU_ARCH_VFP       FPU_VFP_EXT_NONE
109 #define FPU_ARCH_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_NONE)
110 #define FPU_ARCH_VFP_V1   (FPU_ARCH_VFP_V1xD | FPU_VFP_EXT_V1)
111 #define FPU_ARCH_VFP_V2   (FPU_ARCH_VFP_V1 | FPU_VFP_EXT_V2)
112
113 /* Types of processor to assemble for.  */
114 #define ARM_1           ARM_ARCH_V1
115 #define ARM_2           ARM_ARCH_V2
116 #define ARM_3           ARM_ARCH_V2S
117 #define ARM_250         ARM_ARCH_V2S
118 #define ARM_6           ARM_ARCH_V3
119 #define ARM_7           ARM_ARCH_V3
120 #define ARM_8           ARM_ARCH_V4
121 #define ARM_9           ARM_ARCH_V4T
122 #define ARM_STRONG      ARM_ARCH_V4
123 #define ARM_CPU_MASK    0x0000000f              /* XXX? */
124
125 #ifndef CPU_DEFAULT
126 #if defined __XSCALE__
127 #define CPU_DEFAULT     (ARM_ARCH_XSCALE)
128 #else
129 #if defined __thumb__
130 #define CPU_DEFAULT     (ARM_ARCH_V5T)
131 #else
132 #define CPU_DEFAULT     ARM_ANY
133 #endif
134 #endif
135 #endif
136
137 /* For backwards compatibility we default to the FPA.  */
138 #ifndef FPU_DEFAULT
139 #define FPU_DEFAULT FPU_ARCH_FPA
140 #endif
141
142 #define streq(a, b)           (strcmp (a, b) == 0)
143 #define skip_whitespace(str)  while (*(str) == ' ') ++(str)
144
145 static unsigned long cpu_variant;
146 static int target_oabi = 0;
147
148 /* Flags stored in private area of BFD structure.  */
149 static int uses_apcs_26      = FALSE;
150 static int atpcs             = FALSE;
151 static int support_interwork = FALSE;
152 static int uses_apcs_float   = FALSE;
153 static int pic_code          = FALSE;
154
155 /* Variables that we set while parsing command-line options.  Once all
156    options have been read we re-process these values to set the real
157    assembly flags.  */
158 static int legacy_cpu = -1;
159 static int legacy_fpu = -1;
160
161 static int mcpu_cpu_opt = -1;
162 static int mcpu_fpu_opt = -1;
163 static int march_cpu_opt = -1;
164 static int march_fpu_opt = -1;
165 static int mfpu_opt = -1;
166
167 /* This array holds the chars that always start a comment.  If the
168    pre-processor is disabled, these aren't very useful.  */
169 const char comment_chars[] = "@";
170
171 /* This array holds the chars that only start a comment at the beginning of
172    a line.  If the line seems to have the form '# 123 filename'
173    .line and .file directives will appear in the pre-processed output.  */
174 /* Note that input_file.c hand checks for '#' at the beginning of the
175    first line of the input file.  This is because the compiler outputs
176    #NO_APP at the beginning of its output.  */
177 /* Also note that comments like this one will always work.  */
178 const char line_comment_chars[] = "#";
179
180 const char line_separator_chars[] = ";";
181
182 /* Chars that can be used to separate mant
183    from exp in floating point numbers.  */
184 const char EXP_CHARS[] = "eE";
185
186 /* Chars that mean this number is a floating point constant.  */
187 /* As in 0f12.456  */
188 /* or    0d1.2345e12  */
189
190 const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
191
192 /* Prefix characters that indicate the start of an immediate
193    value.  */
194 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
195
196 #ifdef OBJ_ELF
197 /* Pre-defined "_GLOBAL_OFFSET_TABLE_"  */
198 symbolS * GOT_symbol;
199 #endif
200
201 /* Size of relocation record.  */
202 const int md_reloc_size = 8;
203
204 /* 0: assemble for ARM,
205    1: assemble for Thumb,
206    2: assemble for Thumb even though target CPU does not support thumb
207       instructions.  */
208 static int thumb_mode = 0;
209
210 typedef struct arm_fix
211 {
212   int thumb_mode;
213 } arm_fix_data;
214
215 struct arm_it
216 {
217   const char *  error;
218   unsigned long instruction;
219   int           size;
220   struct
221   {
222     bfd_reloc_code_real_type type;
223     expressionS              exp;
224     int                      pc_rel;
225   } reloc;
226 };
227
228 struct arm_it inst;
229
230 enum asm_shift_index
231 {
232   SHIFT_LSL = 0,
233   SHIFT_LSR,
234   SHIFT_ASR,
235   SHIFT_ROR,
236   SHIFT_RRX
237 };
238
239 struct asm_shift_properties
240 {
241   enum asm_shift_index index;
242   unsigned long        bit_field;
243   unsigned int         allows_0  : 1;
244   unsigned int         allows_32 : 1;
245 };
246
247 static const struct asm_shift_properties shift_properties [] =
248 {
249   { SHIFT_LSL, 0,    1, 0},
250   { SHIFT_LSR, 0x20, 0, 1},
251   { SHIFT_ASR, 0x40, 0, 1},
252   { SHIFT_ROR, 0x60, 0, 0},
253   { SHIFT_RRX, 0x60, 0, 0}
254 };
255
256 struct asm_shift_name
257 {
258   const char *                        name;
259   const struct asm_shift_properties * properties;
260 };
261
262 static const struct asm_shift_name shift_names [] =
263 {
264   { "asl", shift_properties + SHIFT_LSL },
265   { "lsl", shift_properties + SHIFT_LSL },
266   { "lsr", shift_properties + SHIFT_LSR },
267   { "asr", shift_properties + SHIFT_ASR },
268   { "ror", shift_properties + SHIFT_ROR },
269   { "rrx", shift_properties + SHIFT_RRX },
270   { "ASL", shift_properties + SHIFT_LSL },
271   { "LSL", shift_properties + SHIFT_LSL },
272   { "LSR", shift_properties + SHIFT_LSR },
273   { "ASR", shift_properties + SHIFT_ASR },
274   { "ROR", shift_properties + SHIFT_ROR },
275   { "RRX", shift_properties + SHIFT_RRX }
276 };
277
278 #define NO_SHIFT_RESTRICT 1
279 #define SHIFT_RESTRICT    0
280
281 #define NUM_FLOAT_VALS 8
282
283 const char * fp_const[] =
284 {
285   "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
286 };
287
288 /* Number of littlenums required to hold an extended precision number.  */
289 #define MAX_LITTLENUMS 6
290
291 LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
292
293 #define FAIL    (-1)
294 #define SUCCESS (0)
295
296 /* Whether a Co-processor load/store operation accepts write-back forms.  */
297 #define CP_WB_OK 1
298 #define CP_NO_WB 0
299
300 #define SUFF_S 1
301 #define SUFF_D 2
302 #define SUFF_E 3
303 #define SUFF_P 4
304
305 #define CP_T_X   0x00008000
306 #define CP_T_Y   0x00400000
307 #define CP_T_Pre 0x01000000
308 #define CP_T_UD  0x00800000
309 #define CP_T_WB  0x00200000
310
311 #define CONDS_BIT        0x00100000
312 #define LOAD_BIT         0x00100000
313
314 #define DOUBLE_LOAD_FLAG 0x00000001
315
316 struct asm_cond
317 {
318   const char *  template;
319   unsigned long value;
320 };
321
322 #define COND_ALWAYS 0xe0000000
323 #define COND_MASK   0xf0000000
324
325 static const struct asm_cond conds[] =
326 {
327   {"eq", 0x00000000},
328   {"ne", 0x10000000},
329   {"cs", 0x20000000}, {"hs", 0x20000000},
330   {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
331   {"mi", 0x40000000},
332   {"pl", 0x50000000},
333   {"vs", 0x60000000},
334   {"vc", 0x70000000},
335   {"hi", 0x80000000},
336   {"ls", 0x90000000},
337   {"ge", 0xa0000000},
338   {"lt", 0xb0000000},
339   {"gt", 0xc0000000},
340   {"le", 0xd0000000},
341   {"al", 0xe0000000},
342   {"nv", 0xf0000000}
343 };
344
345 struct asm_psr
346 {
347   const char *template;
348   bfd_boolean cpsr;
349   unsigned long field;
350 };
351
352 /* The bit that distnguishes CPSR and SPSR.  */
353 #define SPSR_BIT   (1 << 22)
354
355 /* How many bits to shift the PSR_xxx bits up by.  */
356 #define PSR_SHIFT  16
357
358 #define PSR_c   (1 << 0)
359 #define PSR_x   (1 << 1)
360 #define PSR_s   (1 << 2)
361 #define PSR_f   (1 << 3)
362
363 static const struct asm_psr psrs[] =
364 {
365   {"CPSR",      TRUE,  PSR_c | PSR_f},
366   {"CPSR_all",  TRUE,  PSR_c | PSR_f},
367   {"SPSR",      FALSE, PSR_c | PSR_f},
368   {"SPSR_all",  FALSE, PSR_c | PSR_f},
369   {"CPSR_flg",  TRUE,  PSR_f},
370   {"CPSR_f",    TRUE,  PSR_f},
371   {"SPSR_flg",  FALSE, PSR_f},
372   {"SPSR_f",    FALSE, PSR_f},
373   {"CPSR_c",    TRUE,  PSR_c},
374   {"CPSR_ctl",  TRUE,  PSR_c},
375   {"SPSR_c",    FALSE, PSR_c},
376   {"SPSR_ctl",  FALSE, PSR_c},
377   {"CPSR_x",    TRUE,  PSR_x},
378   {"CPSR_s",    TRUE,  PSR_s},
379   {"SPSR_x",    FALSE, PSR_x},
380   {"SPSR_s",    FALSE, PSR_s},
381   /* Combinations of flags.  */
382   {"CPSR_fs",   TRUE, PSR_f | PSR_s},
383   {"CPSR_fx",   TRUE, PSR_f | PSR_x},
384   {"CPSR_fc",   TRUE, PSR_f | PSR_c},
385   {"CPSR_sf",   TRUE, PSR_s | PSR_f},
386   {"CPSR_sx",   TRUE, PSR_s | PSR_x},
387   {"CPSR_sc",   TRUE, PSR_s | PSR_c},
388   {"CPSR_xf",   TRUE, PSR_x | PSR_f},
389   {"CPSR_xs",   TRUE, PSR_x | PSR_s},
390   {"CPSR_xc",   TRUE, PSR_x | PSR_c},
391   {"CPSR_cf",   TRUE, PSR_c | PSR_f},
392   {"CPSR_cs",   TRUE, PSR_c | PSR_s},
393   {"CPSR_cx",   TRUE, PSR_c | PSR_x},
394   {"CPSR_fsx",  TRUE, PSR_f | PSR_s | PSR_x},
395   {"CPSR_fsc",  TRUE, PSR_f | PSR_s | PSR_c},
396   {"CPSR_fxs",  TRUE, PSR_f | PSR_x | PSR_s},
397   {"CPSR_fxc",  TRUE, PSR_f | PSR_x | PSR_c},
398   {"CPSR_fcs",  TRUE, PSR_f | PSR_c | PSR_s},
399   {"CPSR_fcx",  TRUE, PSR_f | PSR_c | PSR_x},
400   {"CPSR_sfx",  TRUE, PSR_s | PSR_f | PSR_x},
401   {"CPSR_sfc",  TRUE, PSR_s | PSR_f | PSR_c},
402   {"CPSR_sxf",  TRUE, PSR_s | PSR_x | PSR_f},
403   {"CPSR_sxc",  TRUE, PSR_s | PSR_x | PSR_c},
404   {"CPSR_scf",  TRUE, PSR_s | PSR_c | PSR_f},
405   {"CPSR_scx",  TRUE, PSR_s | PSR_c | PSR_x},
406   {"CPSR_xfs",  TRUE, PSR_x | PSR_f | PSR_s},
407   {"CPSR_xfc",  TRUE, PSR_x | PSR_f | PSR_c},
408   {"CPSR_xsf",  TRUE, PSR_x | PSR_s | PSR_f},
409   {"CPSR_xsc",  TRUE, PSR_x | PSR_s | PSR_c},
410   {"CPSR_xcf",  TRUE, PSR_x | PSR_c | PSR_f},
411   {"CPSR_xcs",  TRUE, PSR_x | PSR_c | PSR_s},
412   {"CPSR_cfs",  TRUE, PSR_c | PSR_f | PSR_s},
413   {"CPSR_cfx",  TRUE, PSR_c | PSR_f | PSR_x},
414   {"CPSR_csf",  TRUE, PSR_c | PSR_s | PSR_f},
415   {"CPSR_csx",  TRUE, PSR_c | PSR_s | PSR_x},
416   {"CPSR_cxf",  TRUE, PSR_c | PSR_x | PSR_f},
417   {"CPSR_cxs",  TRUE, PSR_c | PSR_x | PSR_s},
418   {"CPSR_fsxc", TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
419   {"CPSR_fscx", TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
420   {"CPSR_fxsc", TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
421   {"CPSR_fxcs", TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
422   {"CPSR_fcsx", TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
423   {"CPSR_fcxs", TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
424   {"CPSR_sfxc", TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
425   {"CPSR_sfcx", TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
426   {"CPSR_sxfc", TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
427   {"CPSR_sxcf", TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
428   {"CPSR_scfx", TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
429   {"CPSR_scxf", TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
430   {"CPSR_xfsc", TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
431   {"CPSR_xfcs", TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
432   {"CPSR_xsfc", TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
433   {"CPSR_xscf", TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
434   {"CPSR_xcfs", TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
435   {"CPSR_xcsf", TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
436   {"CPSR_cfsx", TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
437   {"CPSR_cfxs", TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
438   {"CPSR_csfx", TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
439   {"CPSR_csxf", TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
440   {"CPSR_cxfs", TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
441   {"CPSR_cxsf", TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
442   {"SPSR_fs",   FALSE, PSR_f | PSR_s},
443   {"SPSR_fx",   FALSE, PSR_f | PSR_x},
444   {"SPSR_fc",   FALSE, PSR_f | PSR_c},
445   {"SPSR_sf",   FALSE, PSR_s | PSR_f},
446   {"SPSR_sx",   FALSE, PSR_s | PSR_x},
447   {"SPSR_sc",   FALSE, PSR_s | PSR_c},
448   {"SPSR_xf",   FALSE, PSR_x | PSR_f},
449   {"SPSR_xs",   FALSE, PSR_x | PSR_s},
450   {"SPSR_xc",   FALSE, PSR_x | PSR_c},
451   {"SPSR_cf",   FALSE, PSR_c | PSR_f},
452   {"SPSR_cs",   FALSE, PSR_c | PSR_s},
453   {"SPSR_cx",   FALSE, PSR_c | PSR_x},
454   {"SPSR_fsx",  FALSE, PSR_f | PSR_s | PSR_x},
455   {"SPSR_fsc",  FALSE, PSR_f | PSR_s | PSR_c},
456   {"SPSR_fxs",  FALSE, PSR_f | PSR_x | PSR_s},
457   {"SPSR_fxc",  FALSE, PSR_f | PSR_x | PSR_c},
458   {"SPSR_fcs",  FALSE, PSR_f | PSR_c | PSR_s},
459   {"SPSR_fcx",  FALSE, PSR_f | PSR_c | PSR_x},
460   {"SPSR_sfx",  FALSE, PSR_s | PSR_f | PSR_x},
461   {"SPSR_sfc",  FALSE, PSR_s | PSR_f | PSR_c},
462   {"SPSR_sxf",  FALSE, PSR_s | PSR_x | PSR_f},
463   {"SPSR_sxc",  FALSE, PSR_s | PSR_x | PSR_c},
464   {"SPSR_scf",  FALSE, PSR_s | PSR_c | PSR_f},
465   {"SPSR_scx",  FALSE, PSR_s | PSR_c | PSR_x},
466   {"SPSR_xfs",  FALSE, PSR_x | PSR_f | PSR_s},
467   {"SPSR_xfc",  FALSE, PSR_x | PSR_f | PSR_c},
468   {"SPSR_xsf",  FALSE, PSR_x | PSR_s | PSR_f},
469   {"SPSR_xsc",  FALSE, PSR_x | PSR_s | PSR_c},
470   {"SPSR_xcf",  FALSE, PSR_x | PSR_c | PSR_f},
471   {"SPSR_xcs",  FALSE, PSR_x | PSR_c | PSR_s},
472   {"SPSR_cfs",  FALSE, PSR_c | PSR_f | PSR_s},
473   {"SPSR_cfx",  FALSE, PSR_c | PSR_f | PSR_x},
474   {"SPSR_csf",  FALSE, PSR_c | PSR_s | PSR_f},
475   {"SPSR_csx",  FALSE, PSR_c | PSR_s | PSR_x},
476   {"SPSR_cxf",  FALSE, PSR_c | PSR_x | PSR_f},
477   {"SPSR_cxs",  FALSE, PSR_c | PSR_x | PSR_s},
478   {"SPSR_fsxc", FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
479   {"SPSR_fscx", FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
480   {"SPSR_fxsc", FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
481   {"SPSR_fxcs", FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
482   {"SPSR_fcsx", FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
483   {"SPSR_fcxs", FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
484   {"SPSR_sfxc", FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
485   {"SPSR_sfcx", FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
486   {"SPSR_sxfc", FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
487   {"SPSR_sxcf", FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
488   {"SPSR_scfx", FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
489   {"SPSR_scxf", FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
490   {"SPSR_xfsc", FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
491   {"SPSR_xfcs", FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
492   {"SPSR_xsfc", FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
493   {"SPSR_xscf", FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
494   {"SPSR_xcfs", FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
495   {"SPSR_xcsf", FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
496   {"SPSR_cfsx", FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
497   {"SPSR_cfxs", FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
498   {"SPSR_csfx", FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
499   {"SPSR_csxf", FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
500   {"SPSR_cxfs", FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
501   {"SPSR_cxsf", FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
502 };
503
504 enum wreg_type
505   {
506     IWMMXT_REG_WR = 0,
507     IWMMXT_REG_WC = 1,
508     IWMMXT_REG_WR_OR_WC = 2,
509     IWMMXT_REG_WCG
510   };
511
512 enum iwmmxt_insn_type
513 {
514   check_rd,
515   check_wr,
516   check_wrwr,
517   check_wrwrwr,
518   check_wrwrwcg,
519   check_tbcst,
520   check_tmovmsk,
521   check_tmia,
522   check_tmcrr,
523   check_tmrrc,
524   check_tmcr,
525   check_tmrc,
526   check_tinsr,
527   check_textrc,
528   check_waligni,
529   check_textrm,
530   check_wshufh
531 };
532
533 enum vfp_dp_reg_pos
534 {
535   VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
536 };
537
538 enum vfp_sp_reg_pos
539 {
540   VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
541 };
542
543 enum vfp_ldstm_type
544 {
545   VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
546 };
547
548 /* VFP system registers.  */
549 struct vfp_reg
550 {
551   const char *name;
552   unsigned long regno;
553 };
554
555 static const struct vfp_reg vfp_regs[] =
556 {
557   {"fpsid", 0x00000000},
558   {"FPSID", 0x00000000},
559   {"fpscr", 0x00010000},
560   {"FPSCR", 0x00010000},
561   {"fpexc", 0x00080000},
562   {"FPEXC", 0x00080000}
563 };
564
565 /* Structure for a hash table entry for a register.  */
566 struct reg_entry
567 {
568   const char * name;
569   int          number;
570 };
571
572 /* Some well known registers that we refer to directly elsewhere.  */
573 #define REG_SP  13
574 #define REG_LR  14
575 #define REG_PC  15
576
577 #define wr_register(reg)  ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
578 #define wc_register(reg)  ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
579 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
580
581 /* These are the standard names.  Users can add aliases with .req.  */
582 /* Integer Register Numbers.  */
583 static const struct reg_entry rn_table[] =
584 {
585   {"r0",  0},  {"r1",  1},      {"r2",  2},      {"r3",  3},
586   {"r4",  4},  {"r5",  5},      {"r6",  6},      {"r7",  7},
587   {"r8",  8},  {"r9",  9},      {"r10", 10},     {"r11", 11},
588   {"r12", 12}, {"r13", REG_SP}, {"r14", REG_LR}, {"r15", REG_PC},
589   /* ATPCS Synonyms.  */
590   {"a1",  0},  {"a2",  1},      {"a3",  2},      {"a4",  3},
591   {"v1",  4},  {"v2",  5},      {"v3",  6},      {"v4",  7},
592   {"v5",  8},  {"v6",  9},      {"v7",  10},     {"v8",  11},
593   /* Well-known aliases.  */
594                                                  {"wr",  7},
595                {"sb",  9},      {"sl",  10},     {"fp",  11},
596   {"ip",  12}, {"sp",  REG_SP}, {"lr",  REG_LR}, {"pc",  REG_PC},
597   {NULL, 0}
598 };
599
600 #define WR_PREFIX 0x200
601 #define WC_PREFIX 0x400
602
603 static const struct reg_entry iwmmxt_table[] =
604 {
605   /* Intel Wireless MMX technology register names.  */
606   {  "wr0", 0x0 | WR_PREFIX},   {"wr1", 0x1 | WR_PREFIX},
607   {  "wr2", 0x2 | WR_PREFIX},   {"wr3", 0x3 | WR_PREFIX},
608   {  "wr4", 0x4 | WR_PREFIX},   {"wr5", 0x5 | WR_PREFIX},
609   {  "wr6", 0x6 | WR_PREFIX},   {"wr7", 0x7 | WR_PREFIX},
610   {  "wr8", 0x8 | WR_PREFIX},   {"wr9", 0x9 | WR_PREFIX},
611   { "wr10", 0xa | WR_PREFIX},  {"wr11", 0xb | WR_PREFIX},
612   { "wr12", 0xc | WR_PREFIX},  {"wr13", 0xd | WR_PREFIX},
613   { "wr14", 0xe | WR_PREFIX},  {"wr15", 0xf | WR_PREFIX},
614   { "wcid", 0x0 | WC_PREFIX},  {"wcon", 0x1 | WC_PREFIX},
615   {"wcssf", 0x2 | WC_PREFIX}, {"wcasf", 0x3 | WC_PREFIX},
616   {"wcgr0", 0x8 | WC_PREFIX}, {"wcgr1", 0x9 | WC_PREFIX},
617   {"wcgr2", 0xa | WC_PREFIX}, {"wcgr3", 0xb | WC_PREFIX},
618
619   {  "wR0", 0x0 | WR_PREFIX},   {"wR1", 0x1 | WR_PREFIX},
620   {  "wR2", 0x2 | WR_PREFIX},   {"wR3", 0x3 | WR_PREFIX},
621   {  "wR4", 0x4 | WR_PREFIX},   {"wR5", 0x5 | WR_PREFIX},
622   {  "wR6", 0x6 | WR_PREFIX},   {"wR7", 0x7 | WR_PREFIX},
623   {  "wR8", 0x8 | WR_PREFIX},   {"wR9", 0x9 | WR_PREFIX},
624   { "wR10", 0xa | WR_PREFIX},  {"wR11", 0xb | WR_PREFIX},
625   { "wR12", 0xc | WR_PREFIX},  {"wR13", 0xd | WR_PREFIX},
626   { "wR14", 0xe | WR_PREFIX},  {"wR15", 0xf | WR_PREFIX},
627   { "wCID", 0x0 | WC_PREFIX},  {"wCon", 0x1 | WC_PREFIX},
628   {"wCSSF", 0x2 | WC_PREFIX}, {"wCASF", 0x3 | WC_PREFIX},
629   {"wCGR0", 0x8 | WC_PREFIX}, {"wCGR1", 0x9 | WC_PREFIX},
630   {"wCGR2", 0xa | WC_PREFIX}, {"wCGR3", 0xb | WC_PREFIX},
631   {NULL, 0}
632 };
633
634 /* Co-processor Numbers.  */
635 static const struct reg_entry cp_table[] =
636 {
637   {"p0",  0},  {"p1",  1},  {"p2",  2},  {"p3", 3},
638   {"p4",  4},  {"p5",  5},  {"p6",  6},  {"p7", 7},
639   {"p8",  8},  {"p9",  9},  {"p10", 10}, {"p11", 11},
640   {"p12", 12}, {"p13", 13}, {"p14", 14}, {"p15", 15},
641   {NULL, 0}
642 };
643
644 /* Co-processor Register Numbers.  */
645 static const struct reg_entry cn_table[] =
646 {
647   {"c0",   0},  {"c1",   1},  {"c2",   2},  {"c3",   3},
648   {"c4",   4},  {"c5",   5},  {"c6",   6},  {"c7",   7},
649   {"c8",   8},  {"c9",   9},  {"c10",  10}, {"c11",  11},
650   {"c12",  12}, {"c13",  13}, {"c14",  14}, {"c15",  15},
651   /* Not really valid, but kept for back-wards compatibility.  */
652   {"cr0",  0},  {"cr1",  1},  {"cr2",  2},  {"cr3",  3},
653   {"cr4",  4},  {"cr5",  5},  {"cr6",  6},  {"cr7",  7},
654   {"cr8",  8},  {"cr9",  9},  {"cr10", 10}, {"cr11", 11},
655   {"cr12", 12}, {"cr13", 13}, {"cr14", 14}, {"cr15", 15},
656   {NULL, 0}
657 };
658
659 /* FPA Registers.  */
660 static const struct reg_entry fn_table[] =
661 {
662   {"f0", 0},   {"f1", 1},   {"f2", 2},   {"f3", 3},
663   {"f4", 4},   {"f5", 5},   {"f6", 6},   {"f7", 7},
664   {NULL, 0}
665 };
666
667 /* VFP SP Registers.  */
668 static const struct reg_entry sn_table[] =
669 {
670   {"s0",  0},  {"s1",  1},  {"s2",  2},  {"s3", 3},
671   {"s4",  4},  {"s5",  5},  {"s6",  6},  {"s7", 7},
672   {"s8",  8},  {"s9",  9},  {"s10", 10}, {"s11", 11},
673   {"s12", 12}, {"s13", 13}, {"s14", 14}, {"s15", 15},
674   {"s16", 16}, {"s17", 17}, {"s18", 18}, {"s19", 19},
675   {"s20", 20}, {"s21", 21}, {"s22", 22}, {"s23", 23},
676   {"s24", 24}, {"s25", 25}, {"s26", 26}, {"s27", 27},
677   {"s28", 28}, {"s29", 29}, {"s30", 30}, {"s31", 31},
678   {NULL, 0}
679 };
680
681 /* VFP DP Registers.  */
682 static const struct reg_entry dn_table[] =
683 {
684   {"d0",  0},  {"d1",  1},  {"d2",  2},  {"d3", 3},
685   {"d4",  4},  {"d5",  5},  {"d6",  6},  {"d7", 7},
686   {"d8",  8},  {"d9",  9},  {"d10", 10}, {"d11", 11},
687   {"d12", 12}, {"d13", 13}, {"d14", 14}, {"d15", 15},
688   {NULL, 0}
689 };
690
691 /* Maverick DSP coprocessor registers.  */
692 static const struct reg_entry mav_mvf_table[] =
693 {
694   {"mvf0",  0},  {"mvf1",  1},  {"mvf2",  2},  {"mvf3",  3},
695   {"mvf4",  4},  {"mvf5",  5},  {"mvf6",  6},  {"mvf7",  7},
696   {"mvf8",  8},  {"mvf9",  9},  {"mvf10", 10}, {"mvf11", 11},
697   {"mvf12", 12}, {"mvf13", 13}, {"mvf14", 14}, {"mvf15", 15},
698   {NULL, 0}
699 };
700
701 static const struct reg_entry mav_mvd_table[] =
702 {
703   {"mvd0",  0},  {"mvd1",  1},  {"mvd2",  2},  {"mvd3",  3},
704   {"mvd4",  4},  {"mvd5",  5},  {"mvd6",  6},  {"mvd7",  7},
705   {"mvd8",  8},  {"mvd9",  9},  {"mvd10", 10}, {"mvd11", 11},
706   {"mvd12", 12}, {"mvd13", 13}, {"mvd14", 14}, {"mvd15", 15},
707   {NULL, 0}
708 };
709
710 static const struct reg_entry mav_mvfx_table[] =
711 {
712   {"mvfx0",  0},  {"mvfx1",  1},  {"mvfx2",  2},  {"mvfx3",  3},
713   {"mvfx4",  4},  {"mvfx5",  5},  {"mvfx6",  6},  {"mvfx7",  7},
714   {"mvfx8",  8},  {"mvfx9",  9},  {"mvfx10", 10}, {"mvfx11", 11},
715   {"mvfx12", 12}, {"mvfx13", 13}, {"mvfx14", 14}, {"mvfx15", 15},
716   {NULL, 0}
717 };
718
719 static const struct reg_entry mav_mvdx_table[] =
720 {
721   {"mvdx0",  0},  {"mvdx1",  1},  {"mvdx2",  2},  {"mvdx3",  3},
722   {"mvdx4",  4},  {"mvdx5",  5},  {"mvdx6",  6},  {"mvdx7",  7},
723   {"mvdx8",  8},  {"mvdx9",  9},  {"mvdx10", 10}, {"mvdx11", 11},
724   {"mvdx12", 12}, {"mvdx13", 13}, {"mvdx14", 14}, {"mvdx15", 15},
725   {NULL, 0}
726 };
727
728 static const struct reg_entry mav_mvax_table[] =
729 {
730   {"mvax0", 0}, {"mvax1", 1}, {"mvax2", 2}, {"mvax3", 3},
731   {NULL, 0}
732 };
733
734 static const struct reg_entry mav_dspsc_table[] =
735 {
736   {"dspsc", 0},
737   {NULL, 0}
738 };
739
740 struct reg_map
741 {
742   const struct reg_entry *names;
743   int max_regno;
744   struct hash_control *htab;
745   const char *expected;
746 };
747
748 struct reg_map all_reg_maps[] =
749 {
750   {rn_table,        15, NULL, N_("ARM register expected")},
751   {cp_table,        15, NULL, N_("bad or missing co-processor number")},
752   {cn_table,        15, NULL, N_("co-processor register expected")},
753   {fn_table,         7, NULL, N_("FPA register expected")},
754   {sn_table,        31, NULL, N_("VFP single precision register expected")},
755   {dn_table,        15, NULL, N_("VFP double precision register expected")},
756   {mav_mvf_table,   15, NULL, N_("Maverick MVF register expected")},
757   {mav_mvd_table,   15, NULL, N_("Maverick MVD register expected")},
758   {mav_mvfx_table,  15, NULL, N_("Maverick MVFX register expected")},
759   {mav_mvdx_table,  15, NULL, N_("Maverick MVFX register expected")},
760   {mav_mvax_table,   3, NULL, N_("Maverick MVAX register expected")},
761   {mav_dspsc_table,  0, NULL, N_("Maverick DSPSC register expected")},
762   {iwmmxt_table,    23, NULL, N_("Intel Wireless MMX technology register expected")},
763 };
764
765 /* Enumeration matching entries in table above.  */
766 enum arm_reg_type
767 {
768   REG_TYPE_RN = 0,
769 #define REG_TYPE_FIRST REG_TYPE_RN
770   REG_TYPE_CP = 1,
771   REG_TYPE_CN = 2,
772   REG_TYPE_FN = 3,
773   REG_TYPE_SN = 4,
774   REG_TYPE_DN = 5,
775   REG_TYPE_MVF = 6,
776   REG_TYPE_MVD = 7,
777   REG_TYPE_MVFX = 8,
778   REG_TYPE_MVDX = 9,
779   REG_TYPE_MVAX = 10,
780   REG_TYPE_DSPSC = 11,
781   REG_TYPE_IWMMXT = 12,
782
783   REG_TYPE_MAX = 13
784 };
785
786 /* Functions called by parser.  */
787 /* ARM instructions.  */
788 static void do_arit             PARAMS ((char *));
789 static void do_cmp              PARAMS ((char *));
790 static void do_mov              PARAMS ((char *));
791 static void do_ldst             PARAMS ((char *));
792 static void do_ldstt            PARAMS ((char *));
793 static void do_ldmstm           PARAMS ((char *));
794 static void do_branch           PARAMS ((char *));
795 static void do_swi              PARAMS ((char *));
796
797 /* Pseudo Op codes.  */
798 static void do_adr              PARAMS ((char *));
799 static void do_adrl             PARAMS ((char *));
800 static void do_empty            PARAMS ((char *));
801
802 /* ARM v2.  */
803 static void do_mul              PARAMS ((char *));
804 static void do_mla              PARAMS ((char *));
805
806 /* ARM v2S.  */
807 static void do_swap             PARAMS ((char *));
808
809 /* ARM v3.  */
810 static void do_msr              PARAMS ((char *));
811 static void do_mrs              PARAMS ((char *));
812
813 /* ARM v3M.  */
814 static void do_mull             PARAMS ((char *));
815
816 /* ARM v4.  */
817 static void do_ldstv4           PARAMS ((char *));
818
819 /* ARM v4T.  */
820 static void do_bx               PARAMS ((char *));
821
822 /* ARM v5T.  */
823 static void do_blx              PARAMS ((char *));
824 static void do_bkpt             PARAMS ((char *));
825 static void do_clz              PARAMS ((char *));
826 static void do_lstc2            PARAMS ((char *));
827 static void do_cdp2             PARAMS ((char *));
828 static void do_co_reg2          PARAMS ((char *));
829
830 /* ARM v5TExP.  */
831 static void do_smla             PARAMS ((char *));
832 static void do_smlal            PARAMS ((char *));
833 static void do_smul             PARAMS ((char *));
834 static void do_qadd             PARAMS ((char *));
835
836 /* ARM v5TE.  */
837 static void do_pld              PARAMS ((char *));
838 static void do_ldrd             PARAMS ((char *));
839 static void do_co_reg2c         PARAMS ((char *));
840
841 /* ARM v5TEJ.  */
842 static void do_bxj              PARAMS ((char *));
843
844 /* Coprocessor Instructions.  */
845 static void do_cdp              PARAMS ((char *));
846 static void do_lstc             PARAMS ((char *));
847 static void do_co_reg           PARAMS ((char *));
848
849 /* FPA instructions.  */
850 static void do_fpa_ctrl         PARAMS ((char *));
851 static void do_fpa_ldst         PARAMS ((char *));
852 static void do_fpa_ldmstm       PARAMS ((char *));
853 static void do_fpa_dyadic       PARAMS ((char *));
854 static void do_fpa_monadic      PARAMS ((char *));
855 static void do_fpa_cmp          PARAMS ((char *));
856 static void do_fpa_from_reg     PARAMS ((char *));
857 static void do_fpa_to_reg       PARAMS ((char *));
858
859 /* VFP instructions.  */
860 static void do_vfp_sp_monadic   PARAMS ((char *));
861 static void do_vfp_dp_monadic   PARAMS ((char *));
862 static void do_vfp_sp_dyadic    PARAMS ((char *));
863 static void do_vfp_dp_dyadic    PARAMS ((char *));
864 static void do_vfp_reg_from_sp  PARAMS ((char *));
865 static void do_vfp_sp_from_reg  PARAMS ((char *));
866 static void do_vfp_sp_reg2      PARAMS ((char *));
867 static void do_vfp_reg_from_dp  PARAMS ((char *));
868 static void do_vfp_reg2_from_dp PARAMS ((char *));
869 static void do_vfp_dp_from_reg  PARAMS ((char *));
870 static void do_vfp_dp_from_reg2 PARAMS ((char *));
871 static void do_vfp_reg_from_ctrl PARAMS ((char *));
872 static void do_vfp_ctrl_from_reg PARAMS ((char *));
873 static void do_vfp_sp_ldst      PARAMS ((char *));
874 static void do_vfp_dp_ldst      PARAMS ((char *));
875 static void do_vfp_sp_ldstmia   PARAMS ((char *));
876 static void do_vfp_sp_ldstmdb   PARAMS ((char *));
877 static void do_vfp_dp_ldstmia   PARAMS ((char *));
878 static void do_vfp_dp_ldstmdb   PARAMS ((char *));
879 static void do_vfp_xp_ldstmia   PARAMS ((char *));
880 static void do_vfp_xp_ldstmdb   PARAMS ((char *));
881 static void do_vfp_sp_compare_z PARAMS ((char *));
882 static void do_vfp_dp_compare_z PARAMS ((char *));
883 static void do_vfp_dp_sp_cvt    PARAMS ((char *));
884 static void do_vfp_sp_dp_cvt    PARAMS ((char *));
885
886 /* XScale.  */
887 static void do_xsc_mia          PARAMS ((char *));
888 static void do_xsc_mar          PARAMS ((char *));
889 static void do_xsc_mra          PARAMS ((char *));
890
891 /* Maverick.  */
892 static void do_mav_binops       PARAMS ((char *, int, enum arm_reg_type,
893                                          enum arm_reg_type));
894 static void do_mav_binops_1a    PARAMS ((char *));
895 static void do_mav_binops_1b    PARAMS ((char *));
896 static void do_mav_binops_1c    PARAMS ((char *));
897 static void do_mav_binops_1d    PARAMS ((char *));
898 static void do_mav_binops_1e    PARAMS ((char *));
899 static void do_mav_binops_1f    PARAMS ((char *));
900 static void do_mav_binops_1g    PARAMS ((char *));
901 static void do_mav_binops_1h    PARAMS ((char *));
902 static void do_mav_binops_1i    PARAMS ((char *));
903 static void do_mav_binops_1j    PARAMS ((char *));
904 static void do_mav_binops_1k    PARAMS ((char *));
905 static void do_mav_binops_1l    PARAMS ((char *));
906 static void do_mav_binops_1m    PARAMS ((char *));
907 static void do_mav_binops_1n    PARAMS ((char *));
908 static void do_mav_binops_1o    PARAMS ((char *));
909 static void do_mav_binops_2a    PARAMS ((char *));
910 static void do_mav_binops_2b    PARAMS ((char *));
911 static void do_mav_binops_2c    PARAMS ((char *));
912 static void do_mav_binops_3a    PARAMS ((char *));
913 static void do_mav_binops_3b    PARAMS ((char *));
914 static void do_mav_binops_3c    PARAMS ((char *));
915 static void do_mav_binops_3d    PARAMS ((char *));
916 static void do_mav_triple       PARAMS ((char *, int, enum arm_reg_type,
917                                          enum arm_reg_type,
918                                          enum arm_reg_type));
919 static void do_mav_triple_4a    PARAMS ((char *));
920 static void do_mav_triple_4b    PARAMS ((char *));
921 static void do_mav_triple_5a    PARAMS ((char *));
922 static void do_mav_triple_5b    PARAMS ((char *));
923 static void do_mav_triple_5c    PARAMS ((char *));
924 static void do_mav_triple_5d    PARAMS ((char *));
925 static void do_mav_triple_5e    PARAMS ((char *));
926 static void do_mav_triple_5f    PARAMS ((char *));
927 static void do_mav_triple_5g    PARAMS ((char *));
928 static void do_mav_triple_5h    PARAMS ((char *));
929 static void do_mav_quad         PARAMS ((char *, int, enum arm_reg_type,
930                                          enum arm_reg_type,
931                                          enum arm_reg_type,
932                                          enum arm_reg_type));
933 static void do_mav_quad_6a      PARAMS ((char *));
934 static void do_mav_quad_6b      PARAMS ((char *));
935 static void do_mav_dspsc_1      PARAMS ((char *));
936 static void do_mav_dspsc_2      PARAMS ((char *));
937 static void do_mav_shift        PARAMS ((char *, enum arm_reg_type,
938                                          enum arm_reg_type));
939 static void do_mav_shift_1      PARAMS ((char *));
940 static void do_mav_shift_2      PARAMS ((char *));
941 static void do_mav_ldst         PARAMS ((char *, enum arm_reg_type));
942 static void do_mav_ldst_1       PARAMS ((char *));
943 static void do_mav_ldst_2       PARAMS ((char *));
944 static void do_mav_ldst_3       PARAMS ((char *));
945 static void do_mav_ldst_4       PARAMS ((char *));
946
947 static int mav_reg_required_here        PARAMS ((char **, int,
948                                                  enum arm_reg_type));
949 static int mav_parse_offset     PARAMS ((char **, int *));
950
951 static void fix_new_arm         PARAMS ((fragS *, int, short, expressionS *,
952                                          int, int));
953 static int arm_reg_parse        PARAMS ((char **, struct hash_control *));
954 static enum arm_reg_type arm_reg_parse_any PARAMS ((char *));
955 static const struct asm_psr * arm_psr_parse PARAMS ((char **));
956 static void symbol_locate       PARAMS ((symbolS *, const char *, segT, valueT,
957                                          fragS *));
958 static int add_to_lit_pool      PARAMS ((void));
959 static unsigned validate_immediate PARAMS ((unsigned));
960 static unsigned validate_immediate_twopart PARAMS ((unsigned int,
961                                                     unsigned int *));
962 static int validate_offset_imm  PARAMS ((unsigned int, int));
963 static void opcode_select       PARAMS ((int));
964 static void end_of_line         PARAMS ((char *));
965 static int reg_required_here    PARAMS ((char **, int));
966 static int psr_required_here    PARAMS ((char **));
967 static int co_proc_number       PARAMS ((char **));
968 static int cp_opc_expr          PARAMS ((char **, int, int));
969 static int cp_reg_required_here PARAMS ((char **, int));
970 static int fp_reg_required_here PARAMS ((char **, int));
971 static int vfp_sp_reg_required_here PARAMS ((char **, enum vfp_sp_reg_pos));
972 static int vfp_dp_reg_required_here PARAMS ((char **, enum vfp_dp_reg_pos));
973 static void vfp_sp_ldstm        PARAMS ((char *, enum vfp_ldstm_type));
974 static void vfp_dp_ldstm        PARAMS ((char *, enum vfp_ldstm_type));
975 static long vfp_sp_reg_list     PARAMS ((char **, enum vfp_sp_reg_pos));
976 static long vfp_dp_reg_list     PARAMS ((char **));
977 static int vfp_psr_required_here PARAMS ((char **str));
978 static const struct vfp_reg *vfp_psr_parse PARAMS ((char **str));
979 static int cp_address_offset    PARAMS ((char **));
980 static int cp_address_required_here     PARAMS ((char **, int));
981 static int my_get_float_expression      PARAMS ((char **));
982 static int skip_past_comma      PARAMS ((char **));
983 static int walk_no_bignums      PARAMS ((symbolS *));
984 static int negate_data_op       PARAMS ((unsigned long *, unsigned long));
985 static int data_op2             PARAMS ((char **));
986 static int fp_op2               PARAMS ((char **));
987 static long reg_list            PARAMS ((char **));
988 static void thumb_load_store    PARAMS ((char *, int, int));
989 static int decode_shift         PARAMS ((char **, int));
990 static int ldst_extend          PARAMS ((char **));
991 static int ldst_extend_v4               PARAMS ((char **));
992 static void thumb_add_sub       PARAMS ((char *, int));
993 static void insert_reg          PARAMS ((const struct reg_entry *,
994                                          struct hash_control *));
995 static void thumb_shift         PARAMS ((char *, int));
996 static void thumb_mov_compare   PARAMS ((char *, int));
997 static void build_arm_ops_hsh   PARAMS ((void));
998 static void set_constant_flonums        PARAMS ((void));
999 static valueT md_chars_to_number        PARAMS ((char *, int));
1000 static void build_reg_hsh       PARAMS ((struct reg_map *));
1001 static void insert_reg_alias    PARAMS ((char *, int, struct hash_control *));
1002 static int create_register_alias        PARAMS ((char *, char *));
1003 static void output_inst         PARAMS ((const char *));
1004 static int accum0_required_here PARAMS ((char **));
1005 static int ld_mode_required_here PARAMS ((char **));
1006 static void do_branch25         PARAMS ((char *));
1007 static symbolS * find_real_start PARAMS ((symbolS *));
1008 #ifdef OBJ_ELF
1009 static bfd_reloc_code_real_type arm_parse_reloc PARAMS ((void));
1010 #endif
1011
1012 static int wreg_required_here   PARAMS ((char **, int, enum wreg_type));
1013 static void do_iwmmxt_byte_addr PARAMS ((char *));
1014 static void do_iwmmxt_tandc     PARAMS ((char *));
1015 static void do_iwmmxt_tbcst     PARAMS ((char *));
1016 static void do_iwmmxt_textrc    PARAMS ((char *));
1017 static void do_iwmmxt_textrm    PARAMS ((char *));
1018 static void do_iwmmxt_tinsr     PARAMS ((char *));
1019 static void do_iwmmxt_tmcr      PARAMS ((char *));
1020 static void do_iwmmxt_tmcrr     PARAMS ((char *));
1021 static void do_iwmmxt_tmia      PARAMS ((char *));
1022 static void do_iwmmxt_tmovmsk   PARAMS ((char *));
1023 static void do_iwmmxt_tmrc      PARAMS ((char *));
1024 static void do_iwmmxt_tmrrc     PARAMS ((char *));
1025 static void do_iwmmxt_torc      PARAMS ((char *));
1026 static void do_iwmmxt_waligni   PARAMS ((char *));
1027 static void do_iwmmxt_wmov      PARAMS ((char *));
1028 static void do_iwmmxt_word_addr PARAMS ((char *));
1029 static void do_iwmmxt_wrwr      PARAMS ((char *));
1030 static void do_iwmmxt_wrwrwcg   PARAMS ((char *));
1031 static void do_iwmmxt_wrwrwr    PARAMS ((char *));
1032 static void do_iwmmxt_wshufh    PARAMS ((char *));
1033 static void do_iwmmxt_wzero     PARAMS ((char *));
1034 static int cp_byte_address_offset         PARAMS ((char **));
1035 static int cp_byte_address_required_here  PARAMS ((char **));
1036
1037 /* ARM instructions take 4bytes in the object file, Thumb instructions
1038    take 2:  */
1039 #define INSN_SIZE       4
1040
1041 /* "INSN<cond> X,Y" where X:bit12, Y:bit16.  */
1042 #define MAV_MODE1       0x100c
1043
1044 /* "INSN<cond> X,Y" where X:bit16, Y:bit12.  */
1045 #define MAV_MODE2       0x0c10
1046
1047 /* "INSN<cond> X,Y" where X:0, Y:bit16.  */
1048 #define MAV_MODE3       0x1000
1049
1050 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12.  */
1051 #define MAV_MODE4       0x0c0010
1052
1053 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0.  */
1054 #define MAV_MODE5       0x00100c
1055
1056 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0.  */
1057 #define MAV_MODE6       0x00100c05
1058
1059 struct asm_opcode
1060 {
1061   /* Basic string to match.  */
1062   const char * template;
1063
1064   /* Basic instruction code.  */
1065   unsigned long value;
1066
1067   /* Offset into the template where the condition code (if any) will be.
1068      If zero, then the instruction is never conditional.  */
1069   unsigned cond_offset;
1070
1071   /* Which architecture variant provides this instruction.  */
1072   unsigned long variant;
1073
1074   /* Function to call to parse args.  */
1075   void (* parms) PARAMS ((char *));
1076 };
1077
1078 static const struct asm_opcode insns[] =
1079 {
1080   /* Core ARM Instructions.  */
1081   {"and",        0xe0000000, 3,  ARM_EXT_V1,       do_arit},
1082   {"ands",       0xe0100000, 3,  ARM_EXT_V1,       do_arit},
1083   {"eor",        0xe0200000, 3,  ARM_EXT_V1,       do_arit},
1084   {"eors",       0xe0300000, 3,  ARM_EXT_V1,       do_arit},
1085   {"sub",        0xe0400000, 3,  ARM_EXT_V1,       do_arit},
1086   {"subs",       0xe0500000, 3,  ARM_EXT_V1,       do_arit},
1087   {"rsb",        0xe0600000, 3,  ARM_EXT_V1,       do_arit},
1088   {"rsbs",       0xe0700000, 3,  ARM_EXT_V1,       do_arit},
1089   {"add",        0xe0800000, 3,  ARM_EXT_V1,       do_arit},
1090   {"adds",       0xe0900000, 3,  ARM_EXT_V1,       do_arit},
1091   {"adc",        0xe0a00000, 3,  ARM_EXT_V1,       do_arit},
1092   {"adcs",       0xe0b00000, 3,  ARM_EXT_V1,       do_arit},
1093   {"sbc",        0xe0c00000, 3,  ARM_EXT_V1,       do_arit},
1094   {"sbcs",       0xe0d00000, 3,  ARM_EXT_V1,       do_arit},
1095   {"rsc",        0xe0e00000, 3,  ARM_EXT_V1,       do_arit},
1096   {"rscs",       0xe0f00000, 3,  ARM_EXT_V1,       do_arit},
1097   {"orr",        0xe1800000, 3,  ARM_EXT_V1,       do_arit},
1098   {"orrs",       0xe1900000, 3,  ARM_EXT_V1,       do_arit},
1099   {"bic",        0xe1c00000, 3,  ARM_EXT_V1,       do_arit},
1100   {"bics",       0xe1d00000, 3,  ARM_EXT_V1,       do_arit},
1101
1102   {"tst",        0xe1100000, 3,  ARM_EXT_V1,       do_cmp},
1103   {"tsts",       0xe1100000, 3,  ARM_EXT_V1,       do_cmp},
1104   {"tstp",       0xe110f000, 3,  ARM_EXT_V1,       do_cmp},
1105   {"teq",        0xe1300000, 3,  ARM_EXT_V1,       do_cmp},
1106   {"teqs",       0xe1300000, 3,  ARM_EXT_V1,       do_cmp},
1107   {"teqp",       0xe130f000, 3,  ARM_EXT_V1,       do_cmp},
1108   {"cmp",        0xe1500000, 3,  ARM_EXT_V1,       do_cmp},
1109   {"cmps",       0xe1500000, 3,  ARM_EXT_V1,       do_cmp},
1110   {"cmpp",       0xe150f000, 3,  ARM_EXT_V1,       do_cmp},
1111   {"cmn",        0xe1700000, 3,  ARM_EXT_V1,       do_cmp},
1112   {"cmns",       0xe1700000, 3,  ARM_EXT_V1,       do_cmp},
1113   {"cmnp",       0xe170f000, 3,  ARM_EXT_V1,       do_cmp},
1114
1115   {"mov",        0xe1a00000, 3,  ARM_EXT_V1,       do_mov},
1116   {"movs",       0xe1b00000, 3,  ARM_EXT_V1,       do_mov},
1117   {"mvn",        0xe1e00000, 3,  ARM_EXT_V1,       do_mov},
1118   {"mvns",       0xe1f00000, 3,  ARM_EXT_V1,       do_mov},
1119
1120   {"ldr",        0xe4100000, 3,  ARM_EXT_V1,       do_ldst},
1121   {"ldrb",       0xe4500000, 3,  ARM_EXT_V1,       do_ldst},
1122   {"ldrt",       0xe4300000, 3,  ARM_EXT_V1,       do_ldstt},
1123   {"ldrbt",      0xe4700000, 3,  ARM_EXT_V1,       do_ldstt},
1124   {"str",        0xe4000000, 3,  ARM_EXT_V1,       do_ldst},
1125   {"strb",       0xe4400000, 3,  ARM_EXT_V1,       do_ldst},
1126   {"strt",       0xe4200000, 3,  ARM_EXT_V1,       do_ldstt},
1127   {"strbt",      0xe4600000, 3,  ARM_EXT_V1,       do_ldstt},
1128
1129   {"stmia",      0xe8800000, 3,  ARM_EXT_V1,       do_ldmstm},
1130   {"stmib",      0xe9800000, 3,  ARM_EXT_V1,       do_ldmstm},
1131   {"stmda",      0xe8000000, 3,  ARM_EXT_V1,       do_ldmstm},
1132   {"stmdb",      0xe9000000, 3,  ARM_EXT_V1,       do_ldmstm},
1133   {"stmfd",      0xe9000000, 3,  ARM_EXT_V1,       do_ldmstm},
1134   {"stmfa",      0xe9800000, 3,  ARM_EXT_V1,       do_ldmstm},
1135   {"stmea",      0xe8800000, 3,  ARM_EXT_V1,       do_ldmstm},
1136   {"stmed",      0xe8000000, 3,  ARM_EXT_V1,       do_ldmstm},
1137
1138   {"ldmia",      0xe8900000, 3,  ARM_EXT_V1,       do_ldmstm},
1139   {"ldmib",      0xe9900000, 3,  ARM_EXT_V1,       do_ldmstm},
1140   {"ldmda",      0xe8100000, 3,  ARM_EXT_V1,       do_ldmstm},
1141   {"ldmdb",      0xe9100000, 3,  ARM_EXT_V1,       do_ldmstm},
1142   {"ldmfd",      0xe8900000, 3,  ARM_EXT_V1,       do_ldmstm},
1143   {"ldmfa",      0xe8100000, 3,  ARM_EXT_V1,       do_ldmstm},
1144   {"ldmea",      0xe9100000, 3,  ARM_EXT_V1,       do_ldmstm},
1145   {"ldmed",      0xe9900000, 3,  ARM_EXT_V1,       do_ldmstm},
1146
1147   {"swi",        0xef000000, 3,  ARM_EXT_V1,       do_swi},
1148 #ifdef TE_WINCE
1149   /* XXX This is the wrong place to do this.  Think multi-arch.  */
1150   {"bl",         0xeb000000, 2,  ARM_EXT_V1,       do_branch},
1151   {"b",          0xea000000, 1,  ARM_EXT_V1,       do_branch},
1152 #else
1153   {"bl",         0xebfffffe, 2,  ARM_EXT_V1,       do_branch},
1154   {"b",          0xeafffffe, 1,  ARM_EXT_V1,       do_branch},
1155 #endif
1156
1157   /* Pseudo ops.  */
1158   {"adr",        0xe28f0000, 3,  ARM_EXT_V1,       do_adr},
1159   {"adrl",       0xe28f0000, 3,  ARM_EXT_V1,       do_adrl},
1160   {"nop",        0xe1a00000, 3,  ARM_EXT_V1,       do_empty},
1161
1162   /* ARM 2 multiplies.  */
1163   {"mul",        0xe0000090, 3,  ARM_EXT_V2,       do_mul},
1164   {"muls",       0xe0100090, 3,  ARM_EXT_V2,       do_mul},
1165   {"mla",        0xe0200090, 3,  ARM_EXT_V2,       do_mla},
1166   {"mlas",       0xe0300090, 3,  ARM_EXT_V2,       do_mla},
1167
1168   /* Generic copressor instructions.  */
1169   {"cdp",        0xee000000, 3,  ARM_EXT_V2,       do_cdp},
1170   {"ldc",        0xec100000, 3,  ARM_EXT_V2,       do_lstc},
1171   {"ldcl",       0xec500000, 3,  ARM_EXT_V2,       do_lstc},
1172   {"stc",        0xec000000, 3,  ARM_EXT_V2,       do_lstc},
1173   {"stcl",       0xec400000, 3,  ARM_EXT_V2,       do_lstc},
1174   {"mcr",        0xee000010, 3,  ARM_EXT_V2,       do_co_reg},
1175   {"mrc",        0xee100010, 3,  ARM_EXT_V2,       do_co_reg},
1176
1177   /* ARM 3 - swp instructions.  */
1178   {"swp",        0xe1000090, 3,  ARM_EXT_V2S,      do_swap},
1179   {"swpb",       0xe1400090, 3,  ARM_EXT_V2S,      do_swap},
1180
1181   /* ARM 6 Status register instructions.  */
1182   {"mrs",        0xe10f0000, 3,  ARM_EXT_V3,       do_mrs},
1183   {"msr",        0xe120f000, 3,  ARM_EXT_V3,       do_msr},
1184   /* ScottB: our code uses     0xe128f000 for msr.
1185      NickC:  but this is wrong because the bits 16 through 19 are
1186              handled by the PSR_xxx defines above.  */
1187
1188   /* ARM 7M long multiplies.  */
1189   {"smull",      0xe0c00090, 5,  ARM_EXT_V3M,      do_mull},
1190   {"smulls",     0xe0d00090, 5,  ARM_EXT_V3M,      do_mull},
1191   {"umull",      0xe0800090, 5,  ARM_EXT_V3M,      do_mull},
1192   {"umulls",     0xe0900090, 5,  ARM_EXT_V3M,      do_mull},
1193   {"smlal",      0xe0e00090, 5,  ARM_EXT_V3M,      do_mull},
1194   {"smlals",     0xe0f00090, 5,  ARM_EXT_V3M,      do_mull},
1195   {"umlal",      0xe0a00090, 5,  ARM_EXT_V3M,      do_mull},
1196   {"umlals",     0xe0b00090, 5,  ARM_EXT_V3M,      do_mull},
1197
1198   /* ARM Architecture 4.  */
1199   {"ldrh",       0xe01000b0, 3,  ARM_EXT_V4,       do_ldstv4},
1200   {"ldrsh",      0xe01000f0, 3,  ARM_EXT_V4,       do_ldstv4},
1201   {"ldrsb",      0xe01000d0, 3,  ARM_EXT_V4,       do_ldstv4},
1202   {"strh",       0xe00000b0, 3,  ARM_EXT_V4,       do_ldstv4},
1203
1204   /* ARM Architecture 4T.  */
1205   /* Note: bx (and blx) are required on V5, even if the processor does
1206      not support Thumb.  */
1207   {"bx",         0xe12fff10, 2,  ARM_EXT_V4T | ARM_EXT_V5, do_bx},
1208
1209   /*  ARM Architecture 5T.  */
1210   /* Note: blx has 2 variants, so the .value is set dynamically.
1211      Only one of the variants has conditional execution.  */
1212   {"blx",        0xe0000000, 3,  ARM_EXT_V5,       do_blx},
1213   {"clz",        0xe16f0f10, 3,  ARM_EXT_V5,       do_clz},
1214   {"bkpt",       0xe1200070, 0,  ARM_EXT_V5,       do_bkpt},
1215   {"ldc2",       0xfc100000, 0,  ARM_EXT_V5,       do_lstc2},
1216   {"ldc2l",      0xfc500000, 0,  ARM_EXT_V5,       do_lstc2},
1217   {"stc2",       0xfc000000, 0,  ARM_EXT_V5,       do_lstc2},
1218   {"stc2l",      0xfc400000, 0,  ARM_EXT_V5,       do_lstc2},
1219   {"cdp2",       0xfe000000, 0,  ARM_EXT_V5,       do_cdp2},
1220   {"mcr2",       0xfe000010, 0,  ARM_EXT_V5,       do_co_reg2},
1221   {"mrc2",       0xfe100010, 0,  ARM_EXT_V5,       do_co_reg2},
1222
1223   /*  ARM Architecture 5TExP.  */
1224   {"smlabb",     0xe1000080, 6,  ARM_EXT_V5ExP,    do_smla},
1225   {"smlatb",     0xe10000a0, 6,  ARM_EXT_V5ExP,    do_smla},
1226   {"smlabt",     0xe10000c0, 6,  ARM_EXT_V5ExP,    do_smla},
1227   {"smlatt",     0xe10000e0, 6,  ARM_EXT_V5ExP,    do_smla},
1228
1229   {"smlawb",     0xe1200080, 6,  ARM_EXT_V5ExP,    do_smla},
1230   {"smlawt",     0xe12000c0, 6,  ARM_EXT_V5ExP,    do_smla},
1231
1232   {"smlalbb",    0xe1400080, 7,  ARM_EXT_V5ExP,    do_smlal},
1233   {"smlaltb",    0xe14000a0, 7,  ARM_EXT_V5ExP,    do_smlal},
1234   {"smlalbt",    0xe14000c0, 7,  ARM_EXT_V5ExP,    do_smlal},
1235   {"smlaltt",    0xe14000e0, 7,  ARM_EXT_V5ExP,    do_smlal},
1236
1237   {"smulbb",     0xe1600080, 6,  ARM_EXT_V5ExP,    do_smul},
1238   {"smultb",     0xe16000a0, 6,  ARM_EXT_V5ExP,    do_smul},
1239   {"smulbt",     0xe16000c0, 6,  ARM_EXT_V5ExP,    do_smul},
1240   {"smultt",     0xe16000e0, 6,  ARM_EXT_V5ExP,    do_smul},
1241
1242   {"smulwb",     0xe12000a0, 6,  ARM_EXT_V5ExP,    do_smul},
1243   {"smulwt",     0xe12000e0, 6,  ARM_EXT_V5ExP,    do_smul},
1244
1245   {"qadd",       0xe1000050, 4,  ARM_EXT_V5ExP,    do_qadd},
1246   {"qdadd",      0xe1400050, 5,  ARM_EXT_V5ExP,    do_qadd},
1247   {"qsub",       0xe1200050, 4,  ARM_EXT_V5ExP,    do_qadd},
1248   {"qdsub",      0xe1600050, 5,  ARM_EXT_V5ExP,    do_qadd},
1249
1250   /*  ARM Architecture 5TE.  */
1251   {"pld",        0xf450f000, 0,  ARM_EXT_V5E,      do_pld},
1252   {"ldrd",       0xe00000d0, 3,  ARM_EXT_V5E,      do_ldrd},
1253   {"strd",       0xe00000f0, 3,  ARM_EXT_V5E,      do_ldrd},
1254
1255   {"mcrr",       0xec400000, 4,  ARM_EXT_V5E,      do_co_reg2c},
1256   {"mrrc",       0xec500000, 4,  ARM_EXT_V5E,      do_co_reg2c},
1257
1258   /*  ARM Architecture 5TEJ.  */
1259   {"bxj",        0xe12fff20, 3,  ARM_EXT_V5J,      do_bxj},
1260
1261   /* Core FPA instruction set (V1).  */
1262   {"wfs",        0xee200110, 3,  FPU_FPA_EXT_V1,   do_fpa_ctrl},
1263   {"rfs",        0xee300110, 3,  FPU_FPA_EXT_V1,   do_fpa_ctrl},
1264   {"wfc",        0xee400110, 3,  FPU_FPA_EXT_V1,   do_fpa_ctrl},
1265   {"rfc",        0xee500110, 3,  FPU_FPA_EXT_V1,   do_fpa_ctrl},
1266
1267   {"ldfs",       0xec100100, 3,  FPU_FPA_EXT_V1,   do_fpa_ldst},
1268   {"ldfd",       0xec108100, 3,  FPU_FPA_EXT_V1,   do_fpa_ldst},
1269   {"ldfe",       0xec500100, 3,  FPU_FPA_EXT_V1,   do_fpa_ldst},
1270   {"ldfp",       0xec508100, 3,  FPU_FPA_EXT_V1,   do_fpa_ldst},
1271
1272   {"stfs",       0xec000100, 3,  FPU_FPA_EXT_V1,   do_fpa_ldst},
1273   {"stfd",       0xec008100, 3,  FPU_FPA_EXT_V1,   do_fpa_ldst},
1274   {"stfe",       0xec400100, 3,  FPU_FPA_EXT_V1,   do_fpa_ldst},
1275   {"stfp",       0xec408100, 3,  FPU_FPA_EXT_V1,   do_fpa_ldst},
1276
1277   {"mvfs",       0xee008100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1278   {"mvfsp",      0xee008120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1279   {"mvfsm",      0xee008140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1280   {"mvfsz",      0xee008160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1281   {"mvfd",       0xee008180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1282   {"mvfdp",      0xee0081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1283   {"mvfdm",      0xee0081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1284   {"mvfdz",      0xee0081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1285   {"mvfe",       0xee088100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1286   {"mvfep",      0xee088120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1287   {"mvfem",      0xee088140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1288   {"mvfez",      0xee088160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1289
1290   {"mnfs",       0xee108100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1291   {"mnfsp",      0xee108120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1292   {"mnfsm",      0xee108140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1293   {"mnfsz",      0xee108160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1294   {"mnfd",       0xee108180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1295   {"mnfdp",      0xee1081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1296   {"mnfdm",      0xee1081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1297   {"mnfdz",      0xee1081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1298   {"mnfe",       0xee188100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1299   {"mnfep",      0xee188120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1300   {"mnfem",      0xee188140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1301   {"mnfez",      0xee188160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1302
1303   {"abss",       0xee208100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1304   {"abssp",      0xee208120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1305   {"abssm",      0xee208140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1306   {"abssz",      0xee208160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1307   {"absd",       0xee208180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1308   {"absdp",      0xee2081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1309   {"absdm",      0xee2081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1310   {"absdz",      0xee2081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1311   {"abse",       0xee288100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1312   {"absep",      0xee288120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1313   {"absem",      0xee288140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1314   {"absez",      0xee288160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1315
1316   {"rnds",       0xee308100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1317   {"rndsp",      0xee308120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1318   {"rndsm",      0xee308140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1319   {"rndsz",      0xee308160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1320   {"rndd",       0xee308180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1321   {"rnddp",      0xee3081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1322   {"rnddm",      0xee3081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1323   {"rnddz",      0xee3081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1324   {"rnde",       0xee388100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1325   {"rndep",      0xee388120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1326   {"rndem",      0xee388140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1327   {"rndez",      0xee388160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1328
1329   {"sqts",       0xee408100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1330   {"sqtsp",      0xee408120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1331   {"sqtsm",      0xee408140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1332   {"sqtsz",      0xee408160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1333   {"sqtd",       0xee408180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1334   {"sqtdp",      0xee4081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1335   {"sqtdm",      0xee4081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1336   {"sqtdz",      0xee4081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1337   {"sqte",       0xee488100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1338   {"sqtep",      0xee488120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1339   {"sqtem",      0xee488140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1340   {"sqtez",      0xee488160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1341
1342   {"logs",       0xee508100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1343   {"logsp",      0xee508120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1344   {"logsm",      0xee508140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1345   {"logsz",      0xee508160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1346   {"logd",       0xee508180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1347   {"logdp",      0xee5081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1348   {"logdm",      0xee5081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1349   {"logdz",      0xee5081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1350   {"loge",       0xee588100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1351   {"logep",      0xee588120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1352   {"logem",      0xee588140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1353   {"logez",      0xee588160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1354
1355   {"lgns",       0xee608100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1356   {"lgnsp",      0xee608120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1357   {"lgnsm",      0xee608140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1358   {"lgnsz",      0xee608160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1359   {"lgnd",       0xee608180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1360   {"lgndp",      0xee6081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1361   {"lgndm",      0xee6081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1362   {"lgndz",      0xee6081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1363   {"lgne",       0xee688100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1364   {"lgnep",      0xee688120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1365   {"lgnem",      0xee688140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1366   {"lgnez",      0xee688160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1367
1368   {"exps",       0xee708100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1369   {"expsp",      0xee708120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1370   {"expsm",      0xee708140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1371   {"expsz",      0xee708160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1372   {"expd",       0xee708180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1373   {"expdp",      0xee7081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1374   {"expdm",      0xee7081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1375   {"expdz",      0xee7081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1376   {"expe",       0xee788100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1377   {"expep",      0xee788120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1378   {"expem",      0xee788140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1379   {"expdz",      0xee788160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1380
1381   {"sins",       0xee808100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1382   {"sinsp",      0xee808120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1383   {"sinsm",      0xee808140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1384   {"sinsz",      0xee808160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1385   {"sind",       0xee808180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1386   {"sindp",      0xee8081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1387   {"sindm",      0xee8081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1388   {"sindz",      0xee8081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1389   {"sine",       0xee888100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1390   {"sinep",      0xee888120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1391   {"sinem",      0xee888140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1392   {"sinez",      0xee888160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1393
1394   {"coss",       0xee908100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1395   {"cossp",      0xee908120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1396   {"cossm",      0xee908140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1397   {"cossz",      0xee908160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1398   {"cosd",       0xee908180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1399   {"cosdp",      0xee9081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1400   {"cosdm",      0xee9081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1401   {"cosdz",      0xee9081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1402   {"cose",       0xee988100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1403   {"cosep",      0xee988120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1404   {"cosem",      0xee988140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1405   {"cosez",      0xee988160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1406
1407   {"tans",       0xeea08100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1408   {"tansp",      0xeea08120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1409   {"tansm",      0xeea08140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1410   {"tansz",      0xeea08160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1411   {"tand",       0xeea08180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1412   {"tandp",      0xeea081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1413   {"tandm",      0xeea081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1414   {"tandz",      0xeea081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1415   {"tane",       0xeea88100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1416   {"tanep",      0xeea88120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1417   {"tanem",      0xeea88140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1418   {"tanez",      0xeea88160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1419
1420   {"asns",       0xeeb08100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1421   {"asnsp",      0xeeb08120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1422   {"asnsm",      0xeeb08140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1423   {"asnsz",      0xeeb08160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1424   {"asnd",       0xeeb08180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1425   {"asndp",      0xeeb081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1426   {"asndm",      0xeeb081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1427   {"asndz",      0xeeb081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1428   {"asne",       0xeeb88100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1429   {"asnep",      0xeeb88120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1430   {"asnem",      0xeeb88140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1431   {"asnez",      0xeeb88160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1432
1433   {"acss",       0xeec08100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1434   {"acssp",      0xeec08120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1435   {"acssm",      0xeec08140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1436   {"acssz",      0xeec08160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1437   {"acsd",       0xeec08180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1438   {"acsdp",      0xeec081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1439   {"acsdm",      0xeec081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1440   {"acsdz",      0xeec081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1441   {"acse",       0xeec88100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1442   {"acsep",      0xeec88120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1443   {"acsem",      0xeec88140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1444   {"acsez",      0xeec88160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1445
1446   {"atns",       0xeed08100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1447   {"atnsp",      0xeed08120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1448   {"atnsm",      0xeed08140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1449   {"atnsz",      0xeed08160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1450   {"atnd",       0xeed08180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1451   {"atndp",      0xeed081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1452   {"atndm",      0xeed081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1453   {"atndz",      0xeed081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1454   {"atne",       0xeed88100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1455   {"atnep",      0xeed88120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1456   {"atnem",      0xeed88140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1457   {"atnez",      0xeed88160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1458
1459   {"urds",       0xeee08100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1460   {"urdsp",      0xeee08120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1461   {"urdsm",      0xeee08140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1462   {"urdsz",      0xeee08160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1463   {"urdd",       0xeee08180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1464   {"urddp",      0xeee081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1465   {"urddm",      0xeee081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1466   {"urddz",      0xeee081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1467   {"urde",       0xeee88100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1468   {"urdep",      0xeee88120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1469   {"urdem",      0xeee88140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1470   {"urdez",      0xeee88160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1471
1472   {"nrms",       0xeef08100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1473   {"nrmsp",      0xeef08120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1474   {"nrmsm",      0xeef08140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1475   {"nrmsz",      0xeef08160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1476   {"nrmd",       0xeef08180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1477   {"nrmdp",      0xeef081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1478   {"nrmdm",      0xeef081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1479   {"nrmdz",      0xeef081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1480   {"nrme",       0xeef88100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1481   {"nrmep",      0xeef88120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1482   {"nrmem",      0xeef88140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1483   {"nrmez",      0xeef88160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1484
1485   {"adfs",       0xee000100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1486   {"adfsp",      0xee000120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1487   {"adfsm",      0xee000140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1488   {"adfsz",      0xee000160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1489   {"adfd",       0xee000180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1490   {"adfdp",      0xee0001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1491   {"adfdm",      0xee0001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1492   {"adfdz",      0xee0001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1493   {"adfe",       0xee080100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1494   {"adfep",      0xee080120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1495   {"adfem",      0xee080140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1496   {"adfez",      0xee080160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1497
1498   {"sufs",       0xee200100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1499   {"sufsp",      0xee200120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1500   {"sufsm",      0xee200140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1501   {"sufsz",      0xee200160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1502   {"sufd",       0xee200180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1503   {"sufdp",      0xee2001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1504   {"sufdm",      0xee2001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1505   {"sufdz",      0xee2001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1506   {"sufe",       0xee280100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1507   {"sufep",      0xee280120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1508   {"sufem",      0xee280140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1509   {"sufez",      0xee280160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1510
1511   {"rsfs",       0xee300100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1512   {"rsfsp",      0xee300120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1513   {"rsfsm",      0xee300140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1514   {"rsfsz",      0xee300160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1515   {"rsfd",       0xee300180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1516   {"rsfdp",      0xee3001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1517   {"rsfdm",      0xee3001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1518   {"rsfdz",      0xee3001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1519   {"rsfe",       0xee380100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1520   {"rsfep",      0xee380120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1521   {"rsfem",      0xee380140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1522   {"rsfez",      0xee380160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1523
1524   {"mufs",       0xee100100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1525   {"mufsp",      0xee100120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1526   {"mufsm",      0xee100140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1527   {"mufsz",      0xee100160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1528   {"mufd",       0xee100180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1529   {"mufdp",      0xee1001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1530   {"mufdm",      0xee1001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1531   {"mufdz",      0xee1001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1532   {"mufe",       0xee180100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1533   {"mufep",      0xee180120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1534   {"mufem",      0xee180140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1535   {"mufez",      0xee180160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1536
1537   {"dvfs",       0xee400100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1538   {"dvfsp",      0xee400120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1539   {"dvfsm",      0xee400140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1540   {"dvfsz",      0xee400160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1541   {"dvfd",       0xee400180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1542   {"dvfdp",      0xee4001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1543   {"dvfdm",      0xee4001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1544   {"dvfdz",      0xee4001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1545   {"dvfe",       0xee480100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1546   {"dvfep",      0xee480120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1547   {"dvfem",      0xee480140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1548   {"dvfez",      0xee480160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1549
1550   {"rdfs",       0xee500100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1551   {"rdfsp",      0xee500120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1552   {"rdfsm",      0xee500140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1553   {"rdfsz",      0xee500160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1554   {"rdfd",       0xee500180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1555   {"rdfdp",      0xee5001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1556   {"rdfdm",      0xee5001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1557   {"rdfdz",      0xee5001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1558   {"rdfe",       0xee580100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1559   {"rdfep",      0xee580120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1560   {"rdfem",      0xee580140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1561   {"rdfez",      0xee580160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1562
1563   {"pows",       0xee600100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1564   {"powsp",      0xee600120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1565   {"powsm",      0xee600140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1566   {"powsz",      0xee600160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1567   {"powd",       0xee600180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1568   {"powdp",      0xee6001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1569   {"powdm",      0xee6001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1570   {"powdz",      0xee6001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1571   {"powe",       0xee680100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1572   {"powep",      0xee680120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1573   {"powem",      0xee680140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1574   {"powez",      0xee680160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1575
1576   {"rpws",       0xee700100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1577   {"rpwsp",      0xee700120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1578   {"rpwsm",      0xee700140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1579   {"rpwsz",      0xee700160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1580   {"rpwd",       0xee700180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1581   {"rpwdp",      0xee7001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1582   {"rpwdm",      0xee7001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1583   {"rpwdz",      0xee7001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1584   {"rpwe",       0xee780100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1585   {"rpwep",      0xee780120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1586   {"rpwem",      0xee780140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1587   {"rpwez",      0xee780160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1588
1589   {"rmfs",       0xee800100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1590   {"rmfsp",      0xee800120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1591   {"rmfsm",      0xee800140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1592   {"rmfsz",      0xee800160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1593   {"rmfd",       0xee800180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1594   {"rmfdp",      0xee8001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1595   {"rmfdm",      0xee8001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1596   {"rmfdz",      0xee8001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1597   {"rmfe",       0xee880100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1598   {"rmfep",      0xee880120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1599   {"rmfem",      0xee880140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1600   {"rmfez",      0xee880160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1601
1602   {"fmls",       0xee900100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1603   {"fmlsp",      0xee900120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1604   {"fmlsm",      0xee900140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1605   {"fmlsz",      0xee900160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1606   {"fmld",       0xee900180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1607   {"fmldp",      0xee9001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1608   {"fmldm",      0xee9001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1609   {"fmldz",      0xee9001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1610   {"fmle",       0xee980100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1611   {"fmlep",      0xee980120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1612   {"fmlem",      0xee980140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1613   {"fmlez",      0xee980160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1614
1615   {"fdvs",       0xeea00100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1616   {"fdvsp",      0xeea00120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1617   {"fdvsm",      0xeea00140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1618   {"fdvsz",      0xeea00160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1619   {"fdvd",       0xeea00180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1620   {"fdvdp",      0xeea001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1621   {"fdvdm",      0xeea001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1622   {"fdvdz",      0xeea001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1623   {"fdve",       0xeea80100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1624   {"fdvep",      0xeea80120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1625   {"fdvem",      0xeea80140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1626   {"fdvez",      0xeea80160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1627
1628   {"frds",       0xeeb00100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1629   {"frdsp",      0xeeb00120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1630   {"frdsm",      0xeeb00140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1631   {"frdsz",      0xeeb00160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1632   {"frdd",       0xeeb00180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1633   {"frddp",      0xeeb001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1634   {"frddm",      0xeeb001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1635   {"frddz",      0xeeb001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1636   {"frde",       0xeeb80100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1637   {"frdep",      0xeeb80120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1638   {"frdem",      0xeeb80140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1639   {"frdez",      0xeeb80160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1640
1641   {"pols",       0xeec00100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1642   {"polsp",      0xeec00120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1643   {"polsm",      0xeec00140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1644   {"polsz",      0xeec00160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1645   {"pold",       0xeec00180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1646   {"poldp",      0xeec001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1647   {"poldm",      0xeec001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1648   {"poldz",      0xeec001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1649   {"pole",       0xeec80100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1650   {"polep",      0xeec80120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1651   {"polem",      0xeec80140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1652   {"polez",      0xeec80160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1653
1654   {"cmf",        0xee90f110, 3,  FPU_FPA_EXT_V1,   do_fpa_cmp},
1655   {"cmfe",       0xeed0f110, 3,  FPU_FPA_EXT_V1,   do_fpa_cmp},
1656   {"cnf",        0xeeb0f110, 3,  FPU_FPA_EXT_V1,   do_fpa_cmp},
1657   {"cnfe",       0xeef0f110, 3,  FPU_FPA_EXT_V1,   do_fpa_cmp},
1658   /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1659      not be an optional suffix, but part of the instruction.  To be
1660      compatible, we accept either.  */
1661   {"cmfe",       0xeed0f110, 4,  FPU_FPA_EXT_V1,   do_fpa_cmp},
1662   {"cnfe",       0xeef0f110, 4,  FPU_FPA_EXT_V1,   do_fpa_cmp},
1663
1664   {"flts",       0xee000110, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
1665   {"fltsp",      0xee000130, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
1666   {"fltsm",      0xee000150, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
1667   {"fltsz",      0xee000170, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
1668   {"fltd",       0xee000190, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
1669   {"fltdp",      0xee0001b0, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
1670   {"fltdm",      0xee0001d0, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
1671   {"fltdz",      0xee0001f0, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
1672   {"flte",       0xee080110, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
1673   {"fltep",      0xee080130, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
1674   {"fltem",      0xee080150, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
1675   {"fltez",      0xee080170, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
1676
1677   /* The implementation of the FIX instruction is broken on some
1678      assemblers, in that it accepts a precision specifier as well as a
1679      rounding specifier, despite the fact that this is meaningless.
1680      To be more compatible, we accept it as well, though of course it
1681      does not set any bits.  */
1682   {"fix",        0xee100110, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
1683   {"fixp",       0xee100130, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
1684   {"fixm",       0xee100150, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
1685   {"fixz",       0xee100170, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
1686   {"fixsp",      0xee100130, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
1687   {"fixsm",      0xee100150, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
1688   {"fixsz",      0xee100170, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
1689   {"fixdp",      0xee100130, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
1690   {"fixdm",      0xee100150, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
1691   {"fixdz",      0xee100170, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
1692   {"fixep",      0xee100130, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
1693   {"fixem",      0xee100150, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
1694   {"fixez",      0xee100170, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
1695
1696   /* Instructions that were new with the real FPA, call them V2.  */
1697   {"lfm",        0xec100200, 3,  FPU_FPA_EXT_V2,   do_fpa_ldmstm},
1698   {"lfmfd",      0xec900200, 3,  FPU_FPA_EXT_V2,   do_fpa_ldmstm},
1699   {"lfmea",      0xed100200, 3,  FPU_FPA_EXT_V2,   do_fpa_ldmstm},
1700   {"sfm",        0xec000200, 3,  FPU_FPA_EXT_V2,   do_fpa_ldmstm},
1701   {"sfmfd",      0xed000200, 3,  FPU_FPA_EXT_V2,   do_fpa_ldmstm},
1702   {"sfmea",      0xec800200, 3,  FPU_FPA_EXT_V2,   do_fpa_ldmstm},
1703
1704   /* VFP V1xD (single precision).  */
1705   /* Moves and type conversions.  */
1706   {"fcpys",   0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1707   {"fmrs",    0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
1708   {"fmsr",    0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
1709   {"fmstat",  0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
1710   {"fsitos",  0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1711   {"fuitos",  0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1712   {"ftosis",  0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1713   {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1714   {"ftouis",  0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1715   {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1716   {"fmrx",    0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
1717   {"fmxr",    0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
1718
1719   /* Memory operations.  */
1720   {"flds",    0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1721   {"fsts",    0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1722   {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1723   {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1724   {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1725   {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1726   {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1727   {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1728   {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1729   {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1730   {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1731   {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1732   {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1733   {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1734   {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1735   {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1736   {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1737   {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1738
1739   /* Monadic operations.  */
1740   {"fabss",   0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1741   {"fnegs",   0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1742   {"fsqrts",  0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1743
1744   /* Dyadic operations.  */
1745   {"fadds",   0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1746   {"fsubs",   0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1747   {"fmuls",   0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1748   {"fdivs",   0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1749   {"fmacs",   0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1750   {"fmscs",   0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1751   {"fnmuls",  0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1752   {"fnmacs",  0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1753   {"fnmscs",  0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1754
1755   /* Comparisons.  */
1756   {"fcmps",   0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1757   {"fcmpzs",  0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1758   {"fcmpes",  0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1759   {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1760
1761   /* VFP V1 (Double precision).  */
1762   /* Moves and type conversions.  */
1763   {"fcpyd",   0xeeb00b40, 5, FPU_VFP_EXT_V1,   do_vfp_dp_monadic},
1764   {"fcvtds",  0xeeb70ac0, 6, FPU_VFP_EXT_V1,   do_vfp_dp_sp_cvt},
1765   {"fcvtsd",  0xeeb70bc0, 6, FPU_VFP_EXT_V1,   do_vfp_sp_dp_cvt},
1766   {"fmdhr",   0xee200b10, 5, FPU_VFP_EXT_V1,   do_vfp_dp_from_reg},
1767   {"fmdlr",   0xee000b10, 5, FPU_VFP_EXT_V1,   do_vfp_dp_from_reg},
1768   {"fmrdh",   0xee300b10, 5, FPU_VFP_EXT_V1,   do_vfp_reg_from_dp},
1769   {"fmrdl",   0xee100b10, 5, FPU_VFP_EXT_V1,   do_vfp_reg_from_dp},
1770   {"fsitod",  0xeeb80bc0, 6, FPU_VFP_EXT_V1,   do_vfp_dp_sp_cvt},
1771   {"fuitod",  0xeeb80b40, 6, FPU_VFP_EXT_V1,   do_vfp_dp_sp_cvt},
1772   {"ftosid",  0xeebd0b40, 6, FPU_VFP_EXT_V1,   do_vfp_sp_dp_cvt},
1773   {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1,   do_vfp_sp_dp_cvt},
1774   {"ftouid",  0xeebc0b40, 6, FPU_VFP_EXT_V1,   do_vfp_sp_dp_cvt},
1775   {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1,   do_vfp_sp_dp_cvt},
1776
1777   /* Memory operations.  */
1778   {"fldd",    0xed100b00, 4, FPU_VFP_EXT_V1,   do_vfp_dp_ldst},
1779   {"fstd",    0xed000b00, 4, FPU_VFP_EXT_V1,   do_vfp_dp_ldst},
1780   {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1,   do_vfp_dp_ldstmia},
1781   {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1,   do_vfp_dp_ldstmia},
1782   {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1,   do_vfp_dp_ldstmdb},
1783   {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1,   do_vfp_dp_ldstmdb},
1784   {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1,   do_vfp_dp_ldstmia},
1785   {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1,   do_vfp_dp_ldstmia},
1786   {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1,   do_vfp_dp_ldstmdb},
1787   {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1,   do_vfp_dp_ldstmdb},
1788
1789   /* Monadic operations.  */
1790   {"fabsd",   0xeeb00bc0, 5, FPU_VFP_EXT_V1,   do_vfp_dp_monadic},
1791   {"fnegd",   0xeeb10b40, 5, FPU_VFP_EXT_V1,   do_vfp_dp_monadic},
1792   {"fsqrtd",  0xeeb10bc0, 6, FPU_VFP_EXT_V1,   do_vfp_dp_monadic},
1793
1794   /* Dyadic operations.  */
1795   {"faddd",   0xee300b00, 5, FPU_VFP_EXT_V1,   do_vfp_dp_dyadic},
1796   {"fsubd",   0xee300b40, 5, FPU_VFP_EXT_V1,   do_vfp_dp_dyadic},
1797   {"fmuld",   0xee200b00, 5, FPU_VFP_EXT_V1,   do_vfp_dp_dyadic},
1798   {"fdivd",   0xee800b00, 5, FPU_VFP_EXT_V1,   do_vfp_dp_dyadic},
1799   {"fmacd",   0xee000b00, 5, FPU_VFP_EXT_V1,   do_vfp_dp_dyadic},
1800   {"fmscd",   0xee100b00, 5, FPU_VFP_EXT_V1,   do_vfp_dp_dyadic},
1801   {"fnmuld",  0xee200b40, 6, FPU_VFP_EXT_V1,   do_vfp_dp_dyadic},
1802   {"fnmacd",  0xee000b40, 6, FPU_VFP_EXT_V1,   do_vfp_dp_dyadic},
1803   {"fnmscd",  0xee100b40, 6, FPU_VFP_EXT_V1,   do_vfp_dp_dyadic},
1804
1805   /* Comparisons.  */
1806   {"fcmpd",   0xeeb40b40, 5, FPU_VFP_EXT_V1,   do_vfp_dp_monadic},
1807   {"fcmpzd",  0xeeb50b40, 6, FPU_VFP_EXT_V1,   do_vfp_dp_compare_z},
1808   {"fcmped",  0xeeb40bc0, 6, FPU_VFP_EXT_V1,   do_vfp_dp_monadic},
1809   {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1,   do_vfp_dp_compare_z},
1810
1811   /* VFP V2.  */
1812   {"fmsrr",   0xec400a10, 5, FPU_VFP_EXT_V2,   do_vfp_sp_reg2},
1813   {"fmrrs",   0xec500a10, 5, FPU_VFP_EXT_V2,   do_vfp_sp_reg2},
1814   {"fmdrr",   0xec400b10, 5, FPU_VFP_EXT_V2,   do_vfp_dp_from_reg2},
1815   {"fmrrd",   0xec500b10, 5, FPU_VFP_EXT_V2,   do_vfp_reg2_from_dp},
1816
1817   /* Intel XScale extensions to ARM V5 ISA.  (All use CP0).  */
1818   {"mia",        0xee200010, 3,  ARM_CEXT_XSCALE,   do_xsc_mia},
1819   {"miaph",      0xee280010, 5,  ARM_CEXT_XSCALE,   do_xsc_mia},
1820   {"miabb",      0xee2c0010, 5,  ARM_CEXT_XSCALE,   do_xsc_mia},
1821   {"miabt",      0xee2d0010, 5,  ARM_CEXT_XSCALE,   do_xsc_mia},
1822   {"miatb",      0xee2e0010, 5,  ARM_CEXT_XSCALE,   do_xsc_mia},
1823   {"miatt",      0xee2f0010, 5,  ARM_CEXT_XSCALE,   do_xsc_mia},
1824   {"mar",        0xec400000, 3,  ARM_CEXT_XSCALE,   do_xsc_mar},
1825   {"mra",        0xec500000, 3,  ARM_CEXT_XSCALE,   do_xsc_mra},
1826
1827   /* Intel Wireless MMX technology instructions.  */
1828   {"tandcb",     0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1829   {"tandch",     0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1830   {"tandcw",     0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1831   {"tbcstb",     0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
1832   {"tbcsth",     0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
1833   {"tbcstw",     0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
1834   {"textrcb",    0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
1835   {"textrch",    0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
1836   {"textrcw",    0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
1837   {"textrmub",   0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1838   {"textrmuh",   0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1839   {"textrmuw",   0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1840   {"textrmsb",   0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1841   {"textrmsh",   0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1842   {"textrmsw",   0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
1843   {"tinsrb",     0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
1844   {"tinsrh",     0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
1845   {"tinsrw",     0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
1846   {"tmcr",       0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
1847   {"tmcrr",      0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
1848   {"tmia",       0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1849   {"tmiaph",     0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1850   {"tmiabb",     0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1851   {"tmiabt",     0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1852   {"tmiatb",     0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1853   {"tmiatt",     0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
1854   {"tmovmskb",   0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
1855   {"tmovmskh",   0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
1856   {"tmovmskw",   0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
1857   {"tmrc",       0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
1858   {"tmrrc",      0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
1859   {"torcb",      0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
1860   {"torch",      0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
1861   {"torcw",      0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
1862   {"waccb",      0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1863   {"wacch",      0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1864   {"waccw",      0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1865   {"waddbss",    0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1866   {"waddb",      0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1867   {"waddbus",    0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1868   {"waddhss",    0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1869   {"waddh",      0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1870   {"waddhus",    0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1871   {"waddwss",    0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1872   {"waddw",      0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1873   {"waddwus",    0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1874   {"waligni",    0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
1875   {"walignr0",   0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1876   {"walignr1",   0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1877   {"walignr2",   0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1878   {"walignr3",   0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1879   {"wand",       0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1880   {"wandn",      0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1881   {"wavg2b",     0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1882   {"wavg2br",    0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1883   {"wavg2h",     0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1884   {"wavg2hr",    0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1885   {"wcmpeqb",    0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1886   {"wcmpeqh",    0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1887   {"wcmpeqw",    0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1888   {"wcmpgtub",   0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1889   {"wcmpgtuh",   0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1890   {"wcmpgtuw",   0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1891   {"wcmpgtsb",   0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1892   {"wcmpgtsh",   0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1893   {"wcmpgtsw",   0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1894   {"wldrb",      0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
1895   {"wldrh",      0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
1896   {"wldrw",      0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
1897   {"wldrd",      0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
1898   {"wmacs",      0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1899   {"wmacsz",     0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1900   {"wmacu",      0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1901   {"wmacuz",     0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1902   {"wmadds",     0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1903   {"wmaddu",     0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1904   {"wmaxsb",     0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1905   {"wmaxsh",     0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1906   {"wmaxsw",     0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1907   {"wmaxub",     0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1908   {"wmaxuh",     0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1909   {"wmaxuw",     0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1910   {"wminsb",     0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1911   {"wminsh",     0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1912   {"wminsw",     0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1913   {"wminub",     0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1914   {"wminuh",     0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1915   {"wminuw",     0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1916   {"wmov",       0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
1917   {"wmulsm",     0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1918   {"wmulsl",     0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1919   {"wmulum",     0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1920   {"wmulul",     0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1921   {"wor",        0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1922   {"wpackhss",   0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1923   {"wpackhus",   0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1924   {"wpackwss",   0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1925   {"wpackwus",   0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1926   {"wpackdss",   0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1927   {"wpackdus",   0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1928   {"wrorh",      0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1929   {"wrorhg",     0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1930   {"wrorw",      0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1931   {"wrorwg",     0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1932   {"wrord",      0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1933   {"wrordg",     0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1934   {"wsadb",      0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1935   {"wsadbz",     0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1936   {"wsadh",      0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1937   {"wsadhz",     0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1938   {"wshufh",     0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
1939   {"wsllh",      0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1940   {"wsllhg",     0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1941   {"wsllw",      0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1942   {"wsllwg",     0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1943   {"wslld",      0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1944   {"wslldg",     0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1945   {"wsrah",      0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1946   {"wsrahg",     0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1947   {"wsraw",      0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1948   {"wsrawg",     0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1949   {"wsrad",      0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1950   {"wsradg",     0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1951   {"wsrlh",      0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1952   {"wsrlhg",     0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1953   {"wsrlw",      0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1954   {"wsrlwg",     0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1955   {"wsrld",      0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1956   {"wsrldg",     0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
1957   {"wstrb",      0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
1958   {"wstrh",      0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
1959   {"wstrw",      0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
1960   {"wstrd",      0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
1961   {"wsubbss",    0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1962   {"wsubb",      0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1963   {"wsubbus",    0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1964   {"wsubhss",    0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1965   {"wsubh",      0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1966   {"wsubhus",    0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1967   {"wsubwss",    0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1968   {"wsubw",      0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1969   {"wsubwus",    0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1970   {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1971   {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1972   {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1973   {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1974   {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1975   {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1976   {"wunpckihb",  0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1977   {"wunpckihh",  0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1978   {"wunpckihw",  0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1979   {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1980   {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1981   {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1982   {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1983   {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1984   {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
1985   {"wunpckilb",  0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1986   {"wunpckilh",  0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1987   {"wunpckilw",  0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1988   {"wxor",       0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
1989   {"wzero",      0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
1990
1991   /* Cirrus Maverick instructions.  */
1992   {"cfldrs",     0xec100400, 6,  ARM_CEXT_MAVERICK, do_mav_ldst_1},
1993   {"cfldrd",     0xec500400, 6,  ARM_CEXT_MAVERICK, do_mav_ldst_2},
1994   {"cfldr32",    0xec100500, 7,  ARM_CEXT_MAVERICK, do_mav_ldst_3},
1995   {"cfldr64",    0xec500500, 7,  ARM_CEXT_MAVERICK, do_mav_ldst_4},
1996   {"cfstrs",     0xec000400, 6,  ARM_CEXT_MAVERICK, do_mav_ldst_1},
1997   {"cfstrd",     0xec400400, 6,  ARM_CEXT_MAVERICK, do_mav_ldst_2},
1998   {"cfstr32",    0xec000500, 7,  ARM_CEXT_MAVERICK, do_mav_ldst_3},
1999   {"cfstr64",    0xec400500, 7,  ARM_CEXT_MAVERICK, do_mav_ldst_4},
2000   {"cfmvsr",     0xee000450, 6,  ARM_CEXT_MAVERICK, do_mav_binops_2a},
2001   {"cfmvrs",     0xee100450, 6,  ARM_CEXT_MAVERICK, do_mav_binops_1a},
2002   {"cfmvdlr",    0xee000410, 7,  ARM_CEXT_MAVERICK, do_mav_binops_2b},
2003   {"cfmvrdl",    0xee100410, 7,  ARM_CEXT_MAVERICK, do_mav_binops_1b},
2004   {"cfmvdhr",    0xee000430, 7,  ARM_CEXT_MAVERICK, do_mav_binops_2b},
2005   {"cfmvrdh",    0xee100430, 7,  ARM_CEXT_MAVERICK, do_mav_binops_1b},
2006   {"cfmv64lr",   0xee000510, 8,  ARM_CEXT_MAVERICK, do_mav_binops_2c},
2007   {"cfmvr64l",   0xee100510, 8,  ARM_CEXT_MAVERICK, do_mav_binops_1c},
2008   {"cfmv64hr",   0xee000530, 8,  ARM_CEXT_MAVERICK, do_mav_binops_2c},
2009   {"cfmvr64h",   0xee100530, 8,  ARM_CEXT_MAVERICK, do_mav_binops_1c},
2010   {"cfmval32",   0xee100610, 8,  ARM_CEXT_MAVERICK, do_mav_binops_3a},
2011   {"cfmv32al",   0xee000610, 8,  ARM_CEXT_MAVERICK, do_mav_binops_3b},
2012   {"cfmvam32",   0xee100630, 8,  ARM_CEXT_MAVERICK, do_mav_binops_3a},
2013   {"cfmv32am",   0xee000630, 8,  ARM_CEXT_MAVERICK, do_mav_binops_3b},
2014   {"cfmvah32",   0xee100650, 8,  ARM_CEXT_MAVERICK, do_mav_binops_3a},
2015   {"cfmv32ah",   0xee000650, 8,  ARM_CEXT_MAVERICK, do_mav_binops_3b},
2016   {"cfmva32",    0xee100670, 7,  ARM_CEXT_MAVERICK, do_mav_binops_3a},
2017   {"cfmv32a",    0xee000670, 7,  ARM_CEXT_MAVERICK, do_mav_binops_3b},
2018   {"cfmva64",    0xee100690, 7,  ARM_CEXT_MAVERICK, do_mav_binops_3c},
2019   {"cfmv64a",    0xee000690, 7,  ARM_CEXT_MAVERICK, do_mav_binops_3d},
2020   {"cfmvsc32",   0xee1006b0, 8,  ARM_CEXT_MAVERICK, do_mav_dspsc_1},
2021   {"cfmv32sc",   0xee0006b0, 8,  ARM_CEXT_MAVERICK, do_mav_dspsc_2},
2022   {"cfcpys",     0xee000400, 6,  ARM_CEXT_MAVERICK, do_mav_binops_1d},
2023   {"cfcpyd",     0xee000420, 6,  ARM_CEXT_MAVERICK, do_mav_binops_1e},
2024   {"cfcvtsd",    0xee000460, 7,  ARM_CEXT_MAVERICK, do_mav_binops_1f},
2025   {"cfcvtds",    0xee000440, 7,  ARM_CEXT_MAVERICK, do_mav_binops_1g},
2026   {"cfcvt32s",   0xee000480, 8,  ARM_CEXT_MAVERICK, do_mav_binops_1h},
2027   {"cfcvt32d",   0xee0004a0, 8,  ARM_CEXT_MAVERICK, do_mav_binops_1i},
2028   {"cfcvt64s",   0xee0004c0, 8,  ARM_CEXT_MAVERICK, do_mav_binops_1j},
2029   {"cfcvt64d",   0xee0004e0, 8,  ARM_CEXT_MAVERICK, do_mav_binops_1k},
2030   {"cfcvts32",   0xee100580, 8,  ARM_CEXT_MAVERICK, do_mav_binops_1l},
2031   {"cfcvtd32",   0xee1005a0, 8,  ARM_CEXT_MAVERICK, do_mav_binops_1m},
2032   {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2033   {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2034   {"cfrshl32",   0xee000550, 8,  ARM_CEXT_MAVERICK, do_mav_triple_4a},
2035   {"cfrshl64",   0xee000570, 8,  ARM_CEXT_MAVERICK, do_mav_triple_4b},
2036   {"cfsh32",     0xee000500, 6,  ARM_CEXT_MAVERICK, do_mav_shift_1},
2037   {"cfsh64",     0xee200500, 6,  ARM_CEXT_MAVERICK, do_mav_shift_2},
2038   {"cfcmps",     0xee100490, 6,  ARM_CEXT_MAVERICK, do_mav_triple_5a},
2039   {"cfcmpd",     0xee1004b0, 6,  ARM_CEXT_MAVERICK, do_mav_triple_5b},
2040   {"cfcmp32",    0xee100590, 7,  ARM_CEXT_MAVERICK, do_mav_triple_5c},
2041   {"cfcmp64",    0xee1005b0, 7,  ARM_CEXT_MAVERICK, do_mav_triple_5d},
2042   {"cfabss",     0xee300400, 6,  ARM_CEXT_MAVERICK, do_mav_binops_1d},
2043   {"cfabsd",     0xee300420, 6,  ARM_CEXT_MAVERICK, do_mav_binops_1e},
2044   {"cfnegs",     0xee300440, 6,  ARM_CEXT_MAVERICK, do_mav_binops_1d},
2045   {"cfnegd",     0xee300460, 6,  ARM_CEXT_MAVERICK, do_mav_binops_1e},
2046   {"cfadds",     0xee300480, 6,  ARM_CEXT_MAVERICK, do_mav_triple_5e},
2047   {"cfaddd",     0xee3004a0, 6,  ARM_CEXT_MAVERICK, do_mav_triple_5f},
2048   {"cfsubs",     0xee3004c0, 6,  ARM_CEXT_MAVERICK, do_mav_triple_5e},
2049   {"cfsubd",     0xee3004e0, 6,  ARM_CEXT_MAVERICK, do_mav_triple_5f},
2050   {"cfmuls",     0xee100400, 6,  ARM_CEXT_MAVERICK, do_mav_triple_5e},
2051   {"cfmuld",     0xee100420, 6,  ARM_CEXT_MAVERICK, do_mav_triple_5f},
2052   {"cfabs32",    0xee300500, 7,  ARM_CEXT_MAVERICK, do_mav_binops_1n},
2053   {"cfabs64",    0xee300520, 7,  ARM_CEXT_MAVERICK, do_mav_binops_1o},
2054   {"cfneg32",    0xee300540, 7,  ARM_CEXT_MAVERICK, do_mav_binops_1n},
2055   {"cfneg64",    0xee300560, 7,  ARM_CEXT_MAVERICK, do_mav_binops_1o},
2056   {"cfadd32",    0xee300580, 7,  ARM_CEXT_MAVERICK, do_mav_triple_5g},
2057   {"cfadd64",    0xee3005a0, 7,  ARM_CEXT_MAVERICK, do_mav_triple_5h},
2058   {"cfsub32",    0xee3005c0, 7,  ARM_CEXT_MAVERICK, do_mav_triple_5g},
2059   {"cfsub64",    0xee3005e0, 7,  ARM_CEXT_MAVERICK, do_mav_triple_5h},
2060   {"cfmul32",    0xee100500, 7,  ARM_CEXT_MAVERICK, do_mav_triple_5g},
2061   {"cfmul64",    0xee100520, 7,  ARM_CEXT_MAVERICK, do_mav_triple_5h},
2062   {"cfmac32",    0xee100540, 7,  ARM_CEXT_MAVERICK, do_mav_triple_5g},
2063   {"cfmsc32",    0xee100560, 7,  ARM_CEXT_MAVERICK, do_mav_triple_5g},
2064   {"cfmadd32",   0xee000600, 8,  ARM_CEXT_MAVERICK, do_mav_quad_6a},
2065   {"cfmsub32",   0xee100600, 8,  ARM_CEXT_MAVERICK, do_mav_quad_6a},
2066   {"cfmadda32",  0xee200600, 9,  ARM_CEXT_MAVERICK, do_mav_quad_6b},
2067   {"cfmsuba32",  0xee300600, 9,  ARM_CEXT_MAVERICK, do_mav_quad_6b},
2068 };
2069
2070 /* Defines for various bits that we will want to toggle.  */
2071 #define INST_IMMEDIATE  0x02000000
2072 #define OFFSET_REG      0x02000000
2073 #define HWOFFSET_IMM    0x00400000
2074 #define SHIFT_BY_REG    0x00000010
2075 #define PRE_INDEX       0x01000000
2076 #define INDEX_UP        0x00800000
2077 #define WRITE_BACK      0x00200000
2078 #define LDM_TYPE_2_OR_3 0x00400000
2079
2080 #define LITERAL_MASK    0xf000f000
2081 #define OPCODE_MASK     0xfe1fffff
2082 #define V4_STR_BIT      0x00000020
2083
2084 #define DATA_OP_SHIFT   21
2085
2086 /* Codes to distinguish the arithmetic instructions.  */
2087 #define OPCODE_AND      0
2088 #define OPCODE_EOR      1
2089 #define OPCODE_SUB      2
2090 #define OPCODE_RSB      3
2091 #define OPCODE_ADD      4
2092 #define OPCODE_ADC      5
2093 #define OPCODE_SBC      6
2094 #define OPCODE_RSC      7
2095 #define OPCODE_TST      8
2096 #define OPCODE_TEQ      9
2097 #define OPCODE_CMP      10
2098 #define OPCODE_CMN      11
2099 #define OPCODE_ORR      12
2100 #define OPCODE_MOV      13
2101 #define OPCODE_BIC      14
2102 #define OPCODE_MVN      15
2103
2104 /* Thumb v1 (ARMv4T).  */
2105 static void do_t_nop            PARAMS ((char *));
2106 static void do_t_arit           PARAMS ((char *));
2107 static void do_t_add            PARAMS ((char *));
2108 static void do_t_asr            PARAMS ((char *));
2109 static void do_t_branch9        PARAMS ((char *));
2110 static void do_t_branch12       PARAMS ((char *));
2111 static void do_t_branch23       PARAMS ((char *));
2112 static void do_t_bx             PARAMS ((char *));
2113 static void do_t_compare        PARAMS ((char *));
2114 static void do_t_ldmstm         PARAMS ((char *));
2115 static void do_t_ldr            PARAMS ((char *));
2116 static void do_t_ldrb           PARAMS ((char *));
2117 static void do_t_ldrh           PARAMS ((char *));
2118 static void do_t_lds            PARAMS ((char *));
2119 static void do_t_lsl            PARAMS ((char *));
2120 static void do_t_lsr            PARAMS ((char *));
2121 static void do_t_mov            PARAMS ((char *));
2122 static void do_t_push_pop       PARAMS ((char *));
2123 static void do_t_str            PARAMS ((char *));
2124 static void do_t_strb           PARAMS ((char *));
2125 static void do_t_strh           PARAMS ((char *));
2126 static void do_t_sub            PARAMS ((char *));
2127 static void do_t_swi            PARAMS ((char *));
2128 static void do_t_adr            PARAMS ((char *));
2129
2130 /* Thumb v2 (ARMv5T).  */
2131 static void do_t_blx            PARAMS ((char *));
2132 static void do_t_bkpt           PARAMS ((char *));
2133
2134 #define T_OPCODE_MUL 0x4340
2135 #define T_OPCODE_TST 0x4200
2136 #define T_OPCODE_CMN 0x42c0
2137 #define T_OPCODE_NEG 0x4240
2138 #define T_OPCODE_MVN 0x43c0
2139
2140 #define T_OPCODE_ADD_R3 0x1800
2141 #define T_OPCODE_SUB_R3 0x1a00
2142 #define T_OPCODE_ADD_HI 0x4400
2143 #define T_OPCODE_ADD_ST 0xb000
2144 #define T_OPCODE_SUB_ST 0xb080
2145 #define T_OPCODE_ADD_SP 0xa800
2146 #define T_OPCODE_ADD_PC 0xa000
2147 #define T_OPCODE_ADD_I8 0x3000
2148 #define T_OPCODE_SUB_I8 0x3800
2149 #define T_OPCODE_ADD_I3 0x1c00
2150 #define T_OPCODE_SUB_I3 0x1e00
2151
2152 #define T_OPCODE_ASR_R  0x4100
2153 #define T_OPCODE_LSL_R  0x4080
2154 #define T_OPCODE_LSR_R  0x40c0
2155 #define T_OPCODE_ASR_I  0x1000
2156 #define T_OPCODE_LSL_I  0x0000
2157 #define T_OPCODE_LSR_I  0x0800
2158
2159 #define T_OPCODE_MOV_I8 0x2000
2160 #define T_OPCODE_CMP_I8 0x2800
2161 #define T_OPCODE_CMP_LR 0x4280
2162 #define T_OPCODE_MOV_HR 0x4600
2163 #define T_OPCODE_CMP_HR 0x4500
2164
2165 #define T_OPCODE_LDR_PC 0x4800
2166 #define T_OPCODE_LDR_SP 0x9800
2167 #define T_OPCODE_STR_SP 0x9000
2168 #define T_OPCODE_LDR_IW 0x6800
2169 #define T_OPCODE_STR_IW 0x6000
2170 #define T_OPCODE_LDR_IH 0x8800
2171 #define T_OPCODE_STR_IH 0x8000
2172 #define T_OPCODE_LDR_IB 0x7800
2173 #define T_OPCODE_STR_IB 0x7000
2174 #define T_OPCODE_LDR_RW 0x5800
2175 #define T_OPCODE_STR_RW 0x5000
2176 #define T_OPCODE_LDR_RH 0x5a00
2177 #define T_OPCODE_STR_RH 0x5200
2178 #define T_OPCODE_LDR_RB 0x5c00
2179 #define T_OPCODE_STR_RB 0x5400
2180
2181 #define T_OPCODE_PUSH   0xb400
2182 #define T_OPCODE_POP    0xbc00
2183
2184 #define T_OPCODE_BRANCH 0xe7fe
2185
2186 static int thumb_reg            PARAMS ((char ** str, int hi_lo));
2187
2188 #define THUMB_SIZE      2       /* Size of thumb instruction.  */
2189 #define THUMB_REG_LO    0x1
2190 #define THUMB_REG_HI    0x2
2191 #define THUMB_REG_ANY   0x3
2192
2193 #define THUMB_H1        0x0080
2194 #define THUMB_H2        0x0040
2195
2196 #define THUMB_ASR 0
2197 #define THUMB_LSL 1
2198 #define THUMB_LSR 2
2199
2200 #define THUMB_MOVE 0
2201 #define THUMB_COMPARE 1
2202
2203 #define THUMB_LOAD 0
2204 #define THUMB_STORE 1
2205
2206 #define THUMB_PP_PC_LR 0x0100
2207
2208 /* These three are used for immediate shifts, do not alter.  */
2209 #define THUMB_WORD 2
2210 #define THUMB_HALFWORD 1
2211 #define THUMB_BYTE 0
2212
2213 struct thumb_opcode
2214 {
2215   /* Basic string to match.  */
2216   const char * template;
2217
2218   /* Basic instruction code.  */
2219   unsigned long value;
2220
2221   int size;
2222
2223   /* Which CPU variants this exists for.  */
2224   unsigned long variant;
2225
2226   /* Function to call to parse args.  */
2227   void (* parms) PARAMS ((char *));
2228 };
2229
2230 static const struct thumb_opcode tinsns[] =
2231 {
2232   /* Thumb v1 (ARMv4T).  */
2233   {"adc",       0x4140,         2,      ARM_EXT_V4T, do_t_arit},
2234   {"add",       0x0000,         2,      ARM_EXT_V4T, do_t_add},
2235   {"and",       0x4000,         2,      ARM_EXT_V4T, do_t_arit},
2236   {"asr",       0x0000,         2,      ARM_EXT_V4T, do_t_asr},
2237   {"b",         T_OPCODE_BRANCH, 2,     ARM_EXT_V4T, do_t_branch12},
2238   {"beq",       0xd0fe,         2,      ARM_EXT_V4T, do_t_branch9},
2239   {"bne",       0xd1fe,         2,      ARM_EXT_V4T, do_t_branch9},
2240   {"bcs",       0xd2fe,         2,      ARM_EXT_V4T, do_t_branch9},
2241   {"bhs",       0xd2fe,         2,      ARM_EXT_V4T, do_t_branch9},
2242   {"bcc",       0xd3fe,         2,      ARM_EXT_V4T, do_t_branch9},
2243   {"bul",       0xd3fe,         2,      ARM_EXT_V4T, do_t_branch9},
2244   {"blo",       0xd3fe,         2,      ARM_EXT_V4T, do_t_branch9},
2245   {"bmi",       0xd4fe,         2,      ARM_EXT_V4T, do_t_branch9},
2246   {"bpl",       0xd5fe,         2,      ARM_EXT_V4T, do_t_branch9},
2247   {"bvs",       0xd6fe,         2,      ARM_EXT_V4T, do_t_branch9},
2248   {"bvc",       0xd7fe,         2,      ARM_EXT_V4T, do_t_branch9},
2249   {"bhi",       0xd8fe,         2,      ARM_EXT_V4T, do_t_branch9},
2250   {"bls",       0xd9fe,         2,      ARM_EXT_V4T, do_t_branch9},
2251   {"bge",       0xdafe,         2,      ARM_EXT_V4T, do_t_branch9},
2252   {"blt",       0xdbfe,         2,      ARM_EXT_V4T, do_t_branch9},
2253   {"bgt",       0xdcfe,         2,      ARM_EXT_V4T, do_t_branch9},
2254   {"ble",       0xddfe,         2,      ARM_EXT_V4T, do_t_branch9},
2255   {"bal",       0xdefe,         2,      ARM_EXT_V4T, do_t_branch9},
2256   {"bic",       0x4380,         2,      ARM_EXT_V4T, do_t_arit},
2257   {"bl",        0xf7fffffe,     4,      ARM_EXT_V4T, do_t_branch23},
2258   {"bx",        0x4700,         2,      ARM_EXT_V4T, do_t_bx},
2259   {"cmn",       T_OPCODE_CMN,   2,      ARM_EXT_V4T, do_t_arit},
2260   {"cmp",       0x0000,         2,      ARM_EXT_V4T, do_t_compare},
2261   {"eor",       0x4040,         2,      ARM_EXT_V4T, do_t_arit},
2262   {"ldmia",     0xc800,         2,      ARM_EXT_V4T, do_t_ldmstm},
2263   {"ldr",       0x0000,         2,      ARM_EXT_V4T, do_t_ldr},
2264   {"ldrb",      0x0000,         2,      ARM_EXT_V4T, do_t_ldrb},
2265   {"ldrh",      0x0000,         2,      ARM_EXT_V4T, do_t_ldrh},
2266   {"ldrsb",     0x5600,         2,      ARM_EXT_V4T, do_t_lds},
2267   {"ldrsh",     0x5e00,         2,      ARM_EXT_V4T, do_t_lds},
2268   {"ldsb",      0x5600,         2,      ARM_EXT_V4T, do_t_lds},
2269   {"ldsh",      0x5e00,         2,      ARM_EXT_V4T, do_t_lds},
2270   {"lsl",       0x0000,         2,      ARM_EXT_V4T, do_t_lsl},
2271   {"lsr",       0x0000,         2,      ARM_EXT_V4T, do_t_lsr},
2272   {"mov",       0x0000,         2,      ARM_EXT_V4T, do_t_mov},
2273   {"mul",       T_OPCODE_MUL,   2,      ARM_EXT_V4T, do_t_arit},
2274   {"mvn",       T_OPCODE_MVN,   2,      ARM_EXT_V4T, do_t_arit},
2275   {"neg",       T_OPCODE_NEG,   2,      ARM_EXT_V4T, do_t_arit},
2276   {"orr",       0x4300,         2,      ARM_EXT_V4T, do_t_arit},
2277   {"pop",       0xbc00,         2,      ARM_EXT_V4T, do_t_push_pop},
2278   {"push",      0xb400,         2,      ARM_EXT_V4T, do_t_push_pop},
2279   {"ror",       0x41c0,         2,      ARM_EXT_V4T, do_t_arit},
2280   {"sbc",       0x4180,         2,      ARM_EXT_V4T, do_t_arit},
2281   {"stmia",     0xc000,         2,      ARM_EXT_V4T, do_t_ldmstm},
2282   {"str",       0x0000,         2,      ARM_EXT_V4T, do_t_str},
2283   {"strb",      0x0000,         2,      ARM_EXT_V4T, do_t_strb},
2284   {"strh",      0x0000,         2,      ARM_EXT_V4T, do_t_strh},
2285   {"swi",       0xdf00,         2,      ARM_EXT_V4T, do_t_swi},
2286   {"sub",       0x0000,         2,      ARM_EXT_V4T, do_t_sub},
2287   {"tst",       T_OPCODE_TST,   2,      ARM_EXT_V4T, do_t_arit},
2288   /* Pseudo ops:  */
2289   {"adr",       0x0000,         2,      ARM_EXT_V4T, do_t_adr},
2290   {"nop",       0x46C0,         2,      ARM_EXT_V4T, do_t_nop},      /* mov r8,r8  */
2291   /* Thumb v2 (ARMv5T).  */
2292   {"blx",       0,              0,      ARM_EXT_V5T, do_t_blx},
2293   {"bkpt",      0xbe00,         2,      ARM_EXT_V5T, do_t_bkpt},
2294 };
2295
2296 #define BAD_ARGS        _("bad arguments to instruction")
2297 #define BAD_PC          _("r15 not allowed here")
2298 #define BAD_COND        _("instruction is not conditional")
2299 #define ERR_NO_ACCUM    _("acc0 expected")
2300
2301 static struct hash_control * arm_ops_hsh   = NULL;
2302 static struct hash_control * arm_tops_hsh  = NULL;
2303 static struct hash_control * arm_cond_hsh  = NULL;
2304 static struct hash_control * arm_shift_hsh = NULL;
2305 static struct hash_control * arm_psr_hsh   = NULL;
2306
2307 /* This table describes all the machine specific pseudo-ops the assembler
2308    has to support.  The fields are:
2309      pseudo-op name without dot
2310      function to call to execute this pseudo-op
2311      Integer arg to pass to the function.  */
2312
2313 static void s_req PARAMS ((int));
2314 static void s_align PARAMS ((int));
2315 static void s_bss PARAMS ((int));
2316 static void s_even PARAMS ((int));
2317 static void s_ltorg PARAMS ((int));
2318 static void s_arm PARAMS ((int));
2319 static void s_thumb PARAMS ((int));
2320 static void s_code PARAMS ((int));
2321 static void s_force_thumb PARAMS ((int));
2322 static void s_thumb_func PARAMS ((int));
2323 static void s_thumb_set PARAMS ((int));
2324 #ifdef OBJ_ELF
2325 static void s_arm_elf_cons PARAMS ((int));
2326 #endif
2327
2328 static int my_get_expression PARAMS ((expressionS *, char **));
2329
2330 const pseudo_typeS md_pseudo_table[] =
2331 {
2332   /* Never called becasue '.req' does not start line.  */
2333   { "req",         s_req,         0 },
2334   { "bss",         s_bss,         0 },
2335   { "align",       s_align,       0 },
2336   { "arm",         s_arm,         0 },
2337   { "thumb",       s_thumb,       0 },
2338   { "code",        s_code,        0 },
2339   { "force_thumb", s_force_thumb, 0 },
2340   { "thumb_func",  s_thumb_func,  0 },
2341   { "thumb_set",   s_thumb_set,   0 },
2342   { "even",        s_even,        0 },
2343   { "ltorg",       s_ltorg,       0 },
2344   { "pool",        s_ltorg,       0 },
2345 #ifdef OBJ_ELF
2346   { "word",        s_arm_elf_cons, 4 },
2347   { "long",        s_arm_elf_cons, 4 },
2348 #else
2349   { "word",        cons, 4},
2350 #endif
2351   { "extend",      float_cons, 'x' },
2352   { "ldouble",     float_cons, 'x' },
2353   { "packed",      float_cons, 'p' },
2354   { 0, 0, 0 }
2355 };
2356
2357 /* Other internal functions.  */
2358 static int arm_parse_extension PARAMS ((char *, int *));
2359 static int arm_parse_cpu PARAMS ((char *));
2360 static int arm_parse_arch PARAMS ((char *));
2361 static int arm_parse_fpu PARAMS ((char *));
2362 #if defined OBJ_COFF || defined OBJ_ELF
2363 static void arm_add_note PARAMS ((const char *, const char *, unsigned int));
2364 #endif
2365
2366 /* Stuff needed to resolve the label ambiguity
2367    As:
2368      ...
2369      label:   <insn>
2370    may differ from:
2371      ...
2372      label:
2373               <insn>
2374 */
2375
2376 symbolS *  last_label_seen;
2377 static int label_is_thumb_function_name = FALSE;
2378
2379 /* Literal Pool stuff.  */
2380
2381 #define MAX_LITERAL_POOL_SIZE 1024
2382
2383 /* Literal pool structure.  Held on a per-section
2384    and per-sub-section basis.  */
2385 typedef struct literal_pool
2386 {
2387   expressionS    literals [MAX_LITERAL_POOL_SIZE];
2388   unsigned int   next_free_entry;
2389   unsigned int   id;
2390   symbolS *      symbol;
2391   segT           section;
2392   subsegT        sub_section;
2393   struct literal_pool * next;
2394 } literal_pool;
2395
2396 /* Pointer to a linked list of literal pools.  */
2397 literal_pool * list_of_pools = NULL;
2398
2399 static literal_pool * find_literal_pool PARAMS ((void));
2400 static literal_pool * find_or_make_literal_pool PARAMS ((void));
2401
2402 static literal_pool *
2403 find_literal_pool ()
2404 {
2405   literal_pool * pool;
2406
2407   for (pool = list_of_pools; pool != NULL; pool = pool->next)
2408     {
2409       if (pool->section == now_seg
2410           && pool->sub_section == now_subseg)
2411         break;
2412     }
2413
2414   return pool;
2415 }
2416
2417 static literal_pool *
2418 find_or_make_literal_pool ()
2419 {
2420   /* Next literal pool ID number.  */
2421   static unsigned int latest_pool_num = 1;
2422   literal_pool *      pool;
2423
2424   pool = find_literal_pool ();
2425
2426   if (pool == NULL)
2427     {
2428       /* Create a new pool.  */
2429       pool = (literal_pool *) xmalloc (sizeof (* pool));
2430       if (! pool)
2431         return NULL;
2432
2433       pool->next_free_entry = 0;
2434       pool->section         = now_seg;
2435       pool->sub_section     = now_subseg;
2436       pool->next            = list_of_pools;
2437       pool->symbol          = NULL;
2438
2439       /* Add it to the list.  */
2440       list_of_pools = pool;
2441     }
2442
2443   /* New pools, and emptied pools, will have a NULL symbol.  */
2444   if (pool->symbol == NULL)
2445     {
2446       pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
2447                                     (valueT) 0, &zero_address_frag);
2448       pool->id = latest_pool_num ++;
2449     }
2450
2451   /* Done.  */
2452   return pool;
2453 }
2454
2455 /* Add the literal in the global 'inst'
2456    structure to the relevent literal pool.  */
2457 static int
2458 add_to_lit_pool ()
2459 {
2460   literal_pool * pool;
2461   unsigned int entry;
2462
2463   pool = find_or_make_literal_pool ();
2464
2465   /* Check if this literal value is already in the pool.  */
2466   for (entry = 0; entry < pool->next_free_entry; entry ++)
2467     {
2468       if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2469           && (inst.reloc.exp.X_op == O_constant)
2470           && (pool->literals[entry].X_add_number
2471               == inst.reloc.exp.X_add_number)
2472           && (pool->literals[entry].X_unsigned
2473               == inst.reloc.exp.X_unsigned))
2474         break;
2475
2476       if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2477           && (inst.reloc.exp.X_op == O_symbol)
2478           && (pool->literals[entry].X_add_number
2479               == inst.reloc.exp.X_add_number)
2480           && (pool->literals[entry].X_add_symbol
2481               == inst.reloc.exp.X_add_symbol)
2482           && (pool->literals[entry].X_op_symbol
2483               == inst.reloc.exp.X_op_symbol))
2484         break;
2485     }
2486
2487   /* Do we need to create a new entry?  */
2488   if (entry == pool->next_free_entry)
2489     {
2490       if (entry >= MAX_LITERAL_POOL_SIZE)
2491         {
2492           inst.error = _("literal pool overflow");
2493           return FAIL;
2494         }
2495
2496       pool->literals[entry] = inst.reloc.exp;
2497       pool->next_free_entry += 1;
2498     }
2499
2500   inst.reloc.exp.X_op         = O_symbol;
2501   inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
2502   inst.reloc.exp.X_add_symbol = pool->symbol;
2503
2504   return SUCCESS;
2505 }
2506
2507 /* Can't use symbol_new here, so have to create a symbol and then at
2508    a later date assign it a value. Thats what these functions do.  */
2509
2510 static void
2511 symbol_locate (symbolP, name, segment, valu, frag)
2512      symbolS *    symbolP;
2513      const char * name;         /* It is copied, the caller can modify.  */
2514      segT         segment;      /* Segment identifier (SEG_<something>).  */
2515      valueT       valu;         /* Symbol value.  */
2516      fragS *      frag;         /* Associated fragment.  */
2517 {
2518   unsigned int name_length;
2519   char * preserved_copy_of_name;
2520
2521   name_length = strlen (name) + 1;   /* +1 for \0.  */
2522   obstack_grow (&notes, name, name_length);
2523   preserved_copy_of_name = obstack_finish (&notes);
2524 #ifdef STRIP_UNDERSCORE
2525   if (preserved_copy_of_name[0] == '_')
2526     preserved_copy_of_name++;
2527 #endif
2528
2529 #ifdef tc_canonicalize_symbol_name
2530   preserved_copy_of_name =
2531     tc_canonicalize_symbol_name (preserved_copy_of_name);
2532 #endif
2533
2534   S_SET_NAME (symbolP, preserved_copy_of_name);
2535
2536   S_SET_SEGMENT (symbolP, segment);
2537   S_SET_VALUE (symbolP, valu);
2538   symbol_clear_list_pointers (symbolP);
2539
2540   symbol_set_frag (symbolP, frag);
2541
2542   /* Link to end of symbol chain.  */
2543   {
2544     extern int symbol_table_frozen;
2545     if (symbol_table_frozen)
2546       abort ();
2547   }
2548
2549   symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
2550
2551   obj_symbol_new_hook (symbolP);
2552
2553 #ifdef tc_symbol_new_hook
2554   tc_symbol_new_hook (symbolP);
2555 #endif
2556
2557 #ifdef DEBUG_SYMS
2558   verify_symbol_chain (symbol_rootP, symbol_lastP);
2559 #endif /* DEBUG_SYMS  */
2560 }
2561
2562 /* Check that an immediate is valid.
2563    If so, convert it to the right format.  */
2564
2565 static unsigned int
2566 validate_immediate (val)
2567      unsigned int val;
2568 {
2569   unsigned int a;
2570   unsigned int i;
2571
2572 #define rotate_left(v, n) (v << n | v >> (32 - n))
2573
2574   for (i = 0; i < 32; i += 2)
2575     if ((a = rotate_left (val, i)) <= 0xff)
2576       return a | (i << 7); /* 12-bit pack: [shift-cnt,const].  */
2577
2578   return FAIL;
2579 }
2580
2581 /* Check to see if an immediate can be computed as two seperate immediate
2582    values, added together.  We already know that this value cannot be
2583    computed by just one ARM instruction.  */
2584
2585 static unsigned int
2586 validate_immediate_twopart (val, highpart)
2587      unsigned int   val;
2588      unsigned int * highpart;
2589 {
2590   unsigned int a;
2591   unsigned int i;
2592
2593   for (i = 0; i < 32; i += 2)
2594     if (((a = rotate_left (val, i)) & 0xff) != 0)
2595       {
2596         if (a & 0xff00)
2597           {
2598             if (a & ~ 0xffff)
2599               continue;
2600             * highpart = (a  >> 8) | ((i + 24) << 7);
2601           }
2602         else if (a & 0xff0000)
2603           {
2604             if (a & 0xff000000)
2605               continue;
2606             * highpart = (a >> 16) | ((i + 16) << 7);
2607           }
2608         else
2609           {
2610             assert (a & 0xff000000);
2611             * highpart = (a >> 24) | ((i + 8) << 7);
2612           }
2613
2614         return (a & 0xff) | (i << 7);
2615       }
2616
2617   return FAIL;
2618 }
2619
2620 static int
2621 validate_offset_imm (val, hwse)
2622      unsigned int val;
2623      int hwse;
2624 {
2625   if ((hwse && val > 255) || val > 4095)
2626     return FAIL;
2627   return val;
2628 }
2629
2630 static void
2631 s_req (a)
2632      int a ATTRIBUTE_UNUSED;
2633 {
2634   as_bad (_("invalid syntax for .req directive"));
2635 }
2636
2637 static void
2638 s_bss (ignore)
2639      int ignore ATTRIBUTE_UNUSED;
2640 {
2641   /* We don't support putting frags in the BSS segment, we fake it by
2642      marking in_bss, then looking at s_skip for clues.  */
2643   subseg_set (bss_section, 0);
2644   demand_empty_rest_of_line ();
2645 }
2646
2647 static void
2648 s_even (ignore)
2649      int ignore ATTRIBUTE_UNUSED;
2650 {
2651   /* Never make frag if expect extra pass.  */
2652   if (!need_pass_2)
2653     frag_align (1, 0, 0);
2654
2655   record_alignment (now_seg, 1);
2656
2657   demand_empty_rest_of_line ();
2658 }
2659
2660 static void
2661 s_ltorg (ignored)
2662      int ignored ATTRIBUTE_UNUSED;
2663 {
2664   unsigned int entry;
2665   literal_pool * pool;
2666   char sym_name[20];
2667
2668   pool = find_literal_pool ();
2669   if (pool == NULL
2670       || pool->symbol == NULL
2671       || pool->next_free_entry == 0)
2672     return;
2673
2674   /* Align pool as you have word accesses.
2675      Only make a frag if we have to.  */
2676   if (!need_pass_2)
2677     frag_align (2, 0, 0);
2678
2679   record_alignment (now_seg, 2);
2680
2681   sprintf (sym_name, "$$lit_\002%x", pool->id);
2682
2683   symbol_locate (pool->symbol, sym_name, now_seg,
2684                  (valueT) frag_now_fix (), frag_now);
2685   symbol_table_insert (pool->symbol);
2686
2687   ARM_SET_THUMB (pool->symbol, thumb_mode);
2688
2689 #if defined OBJ_COFF || defined OBJ_ELF
2690   ARM_SET_INTERWORK (pool->symbol, support_interwork);
2691 #endif
2692
2693   for (entry = 0; entry < pool->next_free_entry; entry ++)
2694     /* First output the expression in the instruction to the pool.  */
2695     emit_expr (&(pool->literals[entry]), 4); /* .word  */
2696
2697   /* Mark the pool as empty.  */
2698   pool->next_free_entry = 0;
2699   pool->symbol = NULL;
2700 }
2701
2702 /* Same as s_align_ptwo but align 0 => align 2.  */
2703
2704 static void
2705 s_align (unused)
2706      int unused ATTRIBUTE_UNUSED;
2707 {
2708   register int temp;
2709   register long temp_fill;
2710   long max_alignment = 15;
2711
2712   temp = get_absolute_expression ();
2713   if (temp > max_alignment)
2714     as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
2715   else if (temp < 0)
2716     {
2717       as_bad (_("alignment negative. 0 assumed."));
2718       temp = 0;
2719     }
2720
2721   if (*input_line_pointer == ',')
2722     {
2723       input_line_pointer++;
2724       temp_fill = get_absolute_expression ();
2725     }
2726   else
2727     temp_fill = 0;
2728
2729   if (!temp)
2730     temp = 2;
2731
2732   /* Only make a frag if we HAVE to.  */
2733   if (temp && !need_pass_2)
2734     frag_align (temp, (int) temp_fill, 0);
2735   demand_empty_rest_of_line ();
2736
2737   record_alignment (now_seg, temp);
2738 }
2739
2740 static void
2741 s_force_thumb (ignore)
2742      int ignore ATTRIBUTE_UNUSED;
2743 {
2744   /* If we are not already in thumb mode go into it, EVEN if
2745      the target processor does not support thumb instructions.
2746      This is used by gcc/config/arm/lib1funcs.asm for example
2747      to compile interworking support functions even if the
2748      target processor should not support interworking.  */
2749   if (! thumb_mode)
2750     {
2751       thumb_mode = 2;
2752
2753       record_alignment (now_seg, 1);
2754     }
2755
2756   demand_empty_rest_of_line ();
2757 }
2758
2759 static void
2760 s_thumb_func (ignore)
2761      int ignore ATTRIBUTE_UNUSED;
2762 {
2763   if (! thumb_mode)
2764     opcode_select (16);
2765
2766   /* The following label is the name/address of the start of a Thumb function.
2767      We need to know this for the interworking support.  */
2768   label_is_thumb_function_name = TRUE;
2769
2770   demand_empty_rest_of_line ();
2771 }
2772
2773 /* Perform a .set directive, but also mark the alias as
2774    being a thumb function.  */
2775
2776 static void
2777 s_thumb_set (equiv)
2778      int equiv;
2779 {
2780   /* XXX the following is a duplicate of the code for s_set() in read.c
2781      We cannot just call that code as we need to get at the symbol that
2782      is created.  */
2783   register char *    name;
2784   register char      delim;
2785   register char *    end_name;
2786   register symbolS * symbolP;
2787
2788   /* Especial apologies for the random logic:
2789      This just grew, and could be parsed much more simply!
2790      Dean - in haste.  */
2791   name      = input_line_pointer;
2792   delim     = get_symbol_end ();
2793   end_name  = input_line_pointer;
2794   *end_name = delim;
2795
2796   SKIP_WHITESPACE ();
2797
2798   if (*input_line_pointer != ',')
2799     {
2800       *end_name = 0;
2801       as_bad (_("expected comma after name \"%s\""), name);
2802       *end_name = delim;
2803       ignore_rest_of_line ();
2804       return;
2805     }
2806
2807   input_line_pointer++;
2808   *end_name = 0;
2809
2810   if (name[0] == '.' && name[1] == '\0')
2811     {
2812       /* XXX - this should not happen to .thumb_set.  */
2813       abort ();
2814     }
2815
2816   if ((symbolP = symbol_find (name)) == NULL
2817       && (symbolP = md_undefined_symbol (name)) == NULL)
2818     {
2819 #ifndef NO_LISTING
2820       /* When doing symbol listings, play games with dummy fragments living
2821          outside the normal fragment chain to record the file and line info
2822          for this symbol.  */
2823       if (listing & LISTING_SYMBOLS)
2824         {
2825           extern struct list_info_struct * listing_tail;
2826           fragS * dummy_frag = (fragS *) xmalloc (sizeof (fragS));
2827
2828           memset (dummy_frag, 0, sizeof (fragS));
2829           dummy_frag->fr_type = rs_fill;
2830           dummy_frag->line = listing_tail;
2831           symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
2832           dummy_frag->fr_symbol = symbolP;
2833         }
2834       else
2835 #endif
2836         symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
2837
2838 #ifdef OBJ_COFF
2839       /* "set" symbols are local unless otherwise specified.  */
2840       SF_SET_LOCAL (symbolP);
2841 #endif /* OBJ_COFF  */
2842     }                           /* Make a new symbol.  */
2843
2844   symbol_table_insert (symbolP);
2845
2846   * end_name = delim;
2847
2848   if (equiv
2849       && S_IS_DEFINED (symbolP)
2850       && S_GET_SEGMENT (symbolP) != reg_section)
2851     as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
2852
2853   pseudo_set (symbolP);
2854
2855   demand_empty_rest_of_line ();
2856
2857   /* XXX Now we come to the Thumb specific bit of code.  */
2858
2859   THUMB_SET_FUNC (symbolP, 1);
2860   ARM_SET_THUMB (symbolP, 1);
2861 #if defined OBJ_ELF || defined OBJ_COFF
2862   ARM_SET_INTERWORK (symbolP, support_interwork);
2863 #endif
2864 }
2865
2866 static void
2867 opcode_select (width)
2868      int width;
2869 {
2870   switch (width)
2871     {
2872     case 16:
2873       if (! thumb_mode)
2874         {
2875           if (! (cpu_variant & ARM_EXT_V4T))
2876             as_bad (_("selected processor does not support THUMB opcodes"));
2877
2878           thumb_mode = 1;
2879           /* No need to force the alignment, since we will have been
2880              coming from ARM mode, which is word-aligned.  */
2881           record_alignment (now_seg, 1);
2882         }
2883       break;
2884
2885     case 32:
2886       if (thumb_mode)
2887         {
2888           if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
2889             as_bad (_("selected processor does not support ARM opcodes"));
2890
2891           thumb_mode = 0;
2892
2893           if (!need_pass_2)
2894             frag_align (2, 0, 0);
2895
2896           record_alignment (now_seg, 1);
2897         }
2898       break;
2899
2900     default:
2901       as_bad (_("invalid instruction size selected (%d)"), width);
2902     }
2903 }
2904
2905 static void
2906 s_arm (ignore)
2907      int ignore ATTRIBUTE_UNUSED;
2908 {
2909   opcode_select (32);
2910   demand_empty_rest_of_line ();
2911 }
2912
2913 static void
2914 s_thumb (ignore)
2915      int ignore ATTRIBUTE_UNUSED;
2916 {
2917   opcode_select (16);
2918   demand_empty_rest_of_line ();
2919 }
2920
2921 static void
2922 s_code (unused)
2923      int unused ATTRIBUTE_UNUSED;
2924 {
2925   register int temp;
2926
2927   temp = get_absolute_expression ();
2928   switch (temp)
2929     {
2930     case 16:
2931     case 32:
2932       opcode_select (temp);
2933       break;
2934
2935     default:
2936       as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
2937     }
2938 }
2939
2940 static void
2941 end_of_line (str)
2942      char *str;
2943 {
2944   skip_whitespace (str);
2945
2946   if (*str != '\0' && !inst.error)
2947     inst.error = _("garbage following instruction");
2948 }
2949
2950 static int
2951 skip_past_comma (str)
2952      char ** str;
2953 {
2954   char * p = * str, c;
2955   int comma = 0;
2956
2957   while ((c = *p) == ' ' || c == ',')
2958     {
2959       p++;
2960       if (c == ',' && comma++)
2961         return FAIL;
2962     }
2963
2964   if (c == '\0')
2965     return FAIL;
2966
2967   *str = p;
2968   return comma ? SUCCESS : FAIL;
2969 }
2970
2971 /* A standard register must be given at this point.
2972    SHIFT is the place to put it in inst.instruction.
2973    Restores input start point on error.
2974    Returns the reg#, or FAIL.  */
2975
2976 static int
2977 reg_required_here (str, shift)
2978      char ** str;
2979      int     shift;
2980 {
2981   static char buff [128]; /* XXX  */
2982   int         reg;
2983   char *      start = * str;
2984
2985   if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
2986     {
2987       if (shift >= 0)
2988         inst.instruction |= reg << shift;
2989       return reg;
2990     }
2991
2992   /* Restore the start point, we may have got a reg of the wrong class.  */
2993   *str = start;
2994
2995   /* In the few cases where we might be able to accept something else
2996      this error can be overridden.  */
2997   sprintf (buff, _("register expected, not '%.100s'"), start);
2998   inst.error = buff;
2999
3000   return FAIL;
3001 }
3002
3003 /* A Intel Wireless MMX technology register
3004    must be given at this point.
3005    Shift is the place to put it in inst.instruction.
3006    Restores input start point on err.
3007    Returns the reg#, or FAIL.  */
3008
3009 static int
3010 wreg_required_here (str, shift, reg_type)
3011      char ** str;
3012      int     shift;
3013      enum wreg_type reg_type;
3014 {
3015   static char buff [128];
3016   int    reg;
3017   char * start = *str;
3018
3019   if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
3020     {
3021       if (wr_register (reg)
3022           && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
3023         {
3024           if (shift >= 0)
3025             inst.instruction |= (reg ^ WR_PREFIX) << shift;
3026           return reg;
3027         }
3028       else if (wc_register (reg)
3029                && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
3030         {
3031           if (shift >= 0)
3032             inst.instruction |= (reg ^ WC_PREFIX) << shift;
3033           return reg;
3034         }
3035       else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
3036         {
3037           if (shift >= 0)
3038             inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
3039           return reg;
3040         }
3041     }
3042
3043   /* Restore the start point, we may have got a reg of the wrong class.  */
3044   *str = start;
3045
3046   /* In the few cases where we might be able to accept
3047      something else this error can be overridden.  */
3048   sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
3049   inst.error = buff;
3050
3051   return FAIL;
3052 }
3053
3054 static const struct asm_psr *
3055 arm_psr_parse (ccp)
3056      register char ** ccp;
3057 {
3058   char * start = * ccp;
3059   char   c;
3060   char * p;
3061   const struct asm_psr * psr;
3062
3063   p = start;
3064
3065   /* Skip to the end of the next word in the input stream.  */
3066   do
3067     {
3068       c = *p++;
3069     }
3070   while (ISALPHA (c) || c == '_');
3071
3072   /* Terminate the word.  */
3073   *--p = 0;
3074
3075   /* CPSR's and SPSR's can now be lowercase.  This is just a convenience
3076      feature for ease of use and backwards compatibility.  */
3077   if (!strncmp (start, "cpsr", 4))
3078     strncpy (start, "CPSR", 4);
3079   else if (!strncmp (start, "spsr", 4))
3080     strncpy (start, "SPSR", 4);
3081
3082   /* Now locate the word in the psr hash table.  */
3083   psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
3084
3085   /* Restore the input stream.  */
3086   *p = c;
3087
3088   /* If we found a valid match, advance the
3089      stream pointer past the end of the word.  */
3090   *ccp = p;
3091
3092   return psr;
3093 }
3094
3095 /* Parse the input looking for a PSR flag.  */
3096
3097 static int
3098 psr_required_here (str)
3099      char ** str;
3100 {
3101   char * start = * str;
3102   const struct asm_psr * psr;
3103
3104   psr = arm_psr_parse (str);
3105
3106   if (psr)
3107     {
3108       /* If this is the SPSR that is being modified, set the R bit.  */
3109       if (! psr->cpsr)
3110         inst.instruction |= SPSR_BIT;
3111
3112       /* Set the psr flags in the MSR instruction.  */
3113       inst.instruction |= psr->field << PSR_SHIFT;
3114
3115       return SUCCESS;
3116     }
3117
3118   /* In the few cases where we might be able to accept
3119      something else this error can be overridden.  */
3120   inst.error = _("flag for {c}psr instruction expected");
3121
3122   /* Restore the start point.  */
3123   *str = start;
3124   return FAIL;
3125 }
3126
3127 static int
3128 co_proc_number (str)
3129      char **str;
3130 {
3131   int processor, pchar;
3132   char *start;
3133
3134   skip_whitespace (*str);
3135   start = *str;
3136
3137   /* The data sheet seems to imply that just a number on its own is valid
3138      here, but the RISC iX assembler seems to accept a prefix 'p'.  We will
3139      accept either.  */
3140   if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
3141       == FAIL)
3142     {
3143       *str = start;
3144
3145       pchar = *(*str)++;
3146       if (pchar >= '0' && pchar <= '9')
3147         {
3148           processor = pchar - '0';
3149           if (**str >= '0' && **str <= '9')
3150             {
3151               processor = processor * 10 + *(*str)++ - '0';
3152               if (processor > 15)
3153                 {
3154                   inst.error = _("illegal co-processor number");
3155                   return FAIL;
3156                 }
3157             }
3158         }
3159       else
3160         {
3161           inst.error = _("bad or missing co-processor number");
3162           return FAIL;
3163         }
3164     }
3165
3166   inst.instruction |= processor << 8;
3167   return SUCCESS;
3168 }
3169
3170 static int
3171 cp_opc_expr (str, where, length)
3172      char ** str;
3173      int where;
3174      int length;
3175 {
3176   expressionS expr;
3177
3178   skip_whitespace (* str);
3179
3180   memset (&expr, '\0', sizeof (expr));
3181
3182   if (my_get_expression (&expr, str))
3183     return FAIL;
3184   if (expr.X_op != O_constant)
3185     {
3186       inst.error = _("bad or missing expression");
3187       return FAIL;
3188     }
3189
3190   if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
3191     {
3192       inst.error = _("immediate co-processor expression too large");
3193       return FAIL;
3194     }
3195
3196   inst.instruction |= expr.X_add_number << where;
3197   return SUCCESS;
3198 }
3199
3200 static int
3201 cp_reg_required_here (str, where)
3202      char ** str;
3203      int     where;
3204 {
3205   int    reg;
3206   char * start = *str;
3207
3208   if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
3209     {
3210       inst.instruction |= reg << where;
3211       return reg;
3212     }
3213
3214   /* In the few cases where we might be able to accept something else
3215      this error can be overridden.  */
3216   inst.error = _("co-processor register expected");
3217
3218   /* Restore the start point.  */
3219   *str = start;
3220   return FAIL;
3221 }
3222
3223 static int
3224 fp_reg_required_here (str, where)
3225      char ** str;
3226      int     where;
3227 {
3228   int    reg;
3229   char * start = * str;
3230
3231   if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
3232     {
3233       inst.instruction |= reg << where;
3234       return reg;
3235     }
3236
3237   /* In the few cases where we might be able to accept something else
3238      this error can be overridden.  */
3239   inst.error = _("floating point register expected");
3240
3241   /* Restore the start point.  */
3242   *str = start;
3243   return FAIL;
3244 }
3245
3246 static int
3247 cp_address_offset (str)
3248      char ** str;
3249 {
3250   int offset;
3251
3252   skip_whitespace (* str);
3253
3254   if (! is_immediate_prefix (**str))
3255     {
3256       inst.error = _("immediate expression expected");
3257       return FAIL;
3258     }
3259
3260   (*str)++;
3261
3262   if (my_get_expression (& inst.reloc.exp, str))
3263     return FAIL;
3264
3265   if (inst.reloc.exp.X_op == O_constant)
3266     {
3267       offset = inst.reloc.exp.X_add_number;
3268
3269       if (offset & 3)
3270         {
3271           inst.error = _("co-processor address must be word aligned");
3272           return FAIL;
3273         }
3274
3275       if (offset > 1023 || offset < -1023)
3276         {
3277           inst.error = _("offset too large");
3278           return FAIL;
3279         }
3280
3281       if (offset >= 0)
3282         inst.instruction |= INDEX_UP;
3283       else
3284         offset = -offset;
3285
3286       inst.instruction |= offset >> 2;
3287     }
3288   else
3289     inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3290
3291   return SUCCESS;
3292 }
3293
3294 static int
3295 cp_address_required_here (str, wb_ok)
3296      char ** str;
3297      int wb_ok;
3298 {
3299   char * p = * str;
3300   int    pre_inc = 0;
3301   int    write_back = 0;
3302
3303   if (*p == '[')
3304     {
3305       int reg;
3306
3307       p++;
3308       skip_whitespace (p);
3309
3310       if ((reg = reg_required_here (& p, 16)) == FAIL)
3311         return FAIL;
3312
3313       skip_whitespace (p);
3314
3315       if (*p == ']')
3316         {
3317           p++;
3318
3319           if (wb_ok && skip_past_comma (& p) == SUCCESS)
3320             {
3321               /* [Rn], #expr  */
3322               write_back = WRITE_BACK;
3323
3324               if (reg == REG_PC)
3325                 {
3326                   inst.error = _("pc may not be used in post-increment");
3327                   return FAIL;
3328                 }
3329
3330               if (cp_address_offset (& p) == FAIL)
3331                 return FAIL;
3332             }
3333           else
3334             pre_inc = PRE_INDEX | INDEX_UP;
3335         }
3336       else
3337         {
3338           /* '['Rn, #expr']'[!]  */
3339
3340           if (skip_past_comma (& p) == FAIL)
3341             {
3342               inst.error = _("pre-indexed expression expected");
3343               return FAIL;
3344             }
3345
3346           pre_inc = PRE_INDEX;
3347
3348           if (cp_address_offset (& p) == FAIL)
3349             return FAIL;
3350
3351           skip_whitespace (p);
3352
3353           if (*p++ != ']')
3354             {
3355               inst.error = _("missing ]");
3356               return FAIL;
3357             }
3358
3359           skip_whitespace (p);
3360
3361           if (wb_ok && *p == '!')
3362             {
3363               if (reg == REG_PC)
3364                 {
3365                   inst.error = _("pc may not be used with write-back");
3366                   return FAIL;
3367                 }
3368
3369               p++;
3370               write_back = WRITE_BACK;
3371             }
3372         }
3373     }
3374   else
3375     {
3376       if (my_get_expression (&inst.reloc.exp, &p))
3377         return FAIL;
3378
3379       inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3380       inst.reloc.exp.X_add_number -= 8;  /* PC rel adjust.  */
3381       inst.reloc.pc_rel = 1;
3382       inst.instruction |= (REG_PC << 16);
3383       pre_inc = PRE_INDEX;
3384     }
3385
3386   inst.instruction |= write_back | pre_inc;
3387   *str = p;
3388   return SUCCESS;
3389 }
3390
3391 static int
3392 cp_byte_address_offset (str)
3393      char ** str;
3394 {
3395   int offset;
3396
3397   skip_whitespace (* str);
3398
3399   if (! is_immediate_prefix (**str))
3400     {
3401       inst.error = _("immediate expression expected");
3402       return FAIL;
3403     }
3404
3405   (*str)++;
3406   
3407   if (my_get_expression (& inst.reloc.exp, str))
3408     return FAIL;
3409   
3410   if (inst.reloc.exp.X_op == O_constant)
3411     {
3412       offset = inst.reloc.exp.X_add_number;
3413       
3414       if (offset > 255 || offset < -255)
3415         {
3416           inst.error = _("offset too large");
3417           return FAIL;
3418         }
3419
3420       if (offset >= 0)
3421         inst.instruction |= INDEX_UP;
3422       else
3423         offset = -offset;
3424
3425       inst.instruction |= offset;
3426     }
3427   else
3428     inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3429
3430   return SUCCESS;
3431 }
3432
3433 static int
3434 cp_byte_address_required_here (str)
3435      char ** str;
3436 {
3437   char * p = * str;
3438   int    pre_inc = 0;
3439   int    write_back = 0;
3440
3441   if (*p == '[')
3442     {
3443       int reg;
3444
3445       p++;
3446       skip_whitespace (p);
3447
3448       if ((reg = reg_required_here (& p, 16)) == FAIL)
3449         return FAIL;
3450
3451       skip_whitespace (p);
3452
3453       if (*p == ']')
3454         {
3455           p++;
3456           
3457           if (skip_past_comma (& p) == SUCCESS)
3458             {
3459               /* [Rn], #expr */
3460               write_back = WRITE_BACK;
3461               
3462               if (reg == REG_PC)
3463                 {
3464                   inst.error = _("pc may not be used in post-increment");
3465                   return FAIL;
3466                 }
3467
3468               if (cp_byte_address_offset (& p) == FAIL)
3469                 return FAIL;
3470             }
3471           else
3472             pre_inc = PRE_INDEX | INDEX_UP;
3473         }
3474       else
3475         {
3476           /* '['Rn, #expr']'[!] */
3477
3478           if (skip_past_comma (& p) == FAIL)
3479             {
3480               inst.error = _("pre-indexed expression expected");
3481               return FAIL;
3482             }
3483
3484           pre_inc = PRE_INDEX;
3485           
3486           if (cp_byte_address_offset (& p) == FAIL)
3487             return FAIL;
3488
3489           skip_whitespace (p);
3490
3491           if (*p++ != ']')
3492             {
3493               inst.error = _("missing ]");
3494               return FAIL;
3495             }
3496
3497           skip_whitespace (p);
3498
3499           if (*p == '!')
3500             {
3501               if (reg == REG_PC)
3502                 {
3503                   inst.error = _("pc may not be used with write-back");
3504                   return FAIL;
3505                 }
3506
3507               p++;
3508               write_back = WRITE_BACK;
3509             }
3510         }
3511     }
3512   else
3513     {
3514       if (my_get_expression (&inst.reloc.exp, &p))
3515         return FAIL;
3516
3517       inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3518       inst.reloc.exp.X_add_number -= 8;  /* PC rel adjust.  */
3519       inst.reloc.pc_rel = 1;
3520       inst.instruction |= (REG_PC << 16);
3521       pre_inc = PRE_INDEX;
3522     }
3523
3524   inst.instruction |= write_back | pre_inc;
3525   *str = p;
3526   return SUCCESS;
3527 }
3528
3529 static void
3530 do_empty (str)
3531      char * str;
3532 {
3533   /* Do nothing really.  */
3534   end_of_line (str);
3535   return;
3536 }
3537
3538 static void
3539 do_mrs (str)
3540      char *str;
3541 {
3542   int skip = 0;
3543
3544   /* Only one syntax.  */
3545   skip_whitespace (str);
3546
3547   if (reg_required_here (&str, 12) == FAIL)
3548     {
3549       inst.error = BAD_ARGS;
3550       return;
3551     }
3552
3553   if (skip_past_comma (&str) == FAIL)
3554     {
3555       inst.error = _("comma expected after register name");
3556       return;
3557     }
3558
3559   skip_whitespace (str);
3560
3561   if (   strcmp (str, "CPSR") == 0
3562       || strcmp (str, "SPSR") == 0
3563          /* Lower case versions for backwards compatability.  */
3564       || strcmp (str, "cpsr") == 0
3565       || strcmp (str, "spsr") == 0)
3566     skip = 4;
3567
3568   /* This is for backwards compatability with older toolchains.  */
3569   else if (   strcmp (str, "cpsr_all") == 0
3570            || strcmp (str, "spsr_all") == 0)
3571     skip = 8;
3572   else
3573     {
3574       inst.error = _("CPSR or SPSR expected");
3575       return;
3576     }
3577
3578   if (* str == 's' || * str == 'S')
3579     inst.instruction |= SPSR_BIT;
3580   str += skip;
3581
3582   end_of_line (str);
3583 }
3584
3585 /* Two possible forms:
3586       "{C|S}PSR_<field>, Rm",
3587       "{C|S}PSR_f, #expression".  */
3588
3589 static void
3590 do_msr (str)
3591      char * str;
3592 {
3593   skip_whitespace (str);
3594
3595   if (psr_required_here (& str) == FAIL)
3596     return;
3597
3598   if (skip_past_comma (& str) == FAIL)
3599     {
3600       inst.error = _("comma missing after psr flags");
3601       return;
3602     }
3603
3604   skip_whitespace (str);
3605
3606   if (reg_required_here (& str, 0) != FAIL)
3607     {
3608       inst.error = NULL;
3609       end_of_line (str);
3610       return;
3611     }
3612
3613   if (! is_immediate_prefix (* str))
3614     {
3615       inst.error =
3616         _("only a register or immediate value can follow a psr flag");
3617       return;
3618     }
3619
3620   str ++;
3621   inst.error = NULL;
3622
3623   if (my_get_expression (& inst.reloc.exp, & str))
3624     {
3625       inst.error =
3626         _("only a register or immediate value can follow a psr flag");
3627       return;
3628     }
3629
3630 #if 0  /* The first edition of the ARM architecture manual stated that
3631           writing anything other than the flags with an immediate operation
3632           had UNPREDICTABLE effects.  This constraint was removed in the
3633           second edition of the specification.  */
3634   if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
3635       && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
3636     {
3637       inst.error = _("immediate value cannot be used to set this field");
3638       return;
3639     }
3640 #endif
3641
3642   inst.instruction |= INST_IMMEDIATE;
3643
3644   if (inst.reloc.exp.X_add_symbol)
3645     {
3646       inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
3647       inst.reloc.pc_rel = 0;
3648     }
3649   else
3650     {
3651       unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
3652
3653       if (value == (unsigned) FAIL)
3654         {
3655           inst.error = _("invalid constant");
3656           return;
3657         }
3658
3659       inst.instruction |= value;
3660     }
3661
3662   inst.error = NULL;
3663   end_of_line (str);
3664 }
3665
3666 /* Long Multiply Parser
3667    UMULL RdLo, RdHi, Rm, Rs
3668    SMULL RdLo, RdHi, Rm, Rs
3669    UMLAL RdLo, RdHi, Rm, Rs
3670    SMLAL RdLo, RdHi, Rm, Rs.  */
3671
3672 static void
3673 do_mull (str)
3674      char * str;
3675 {
3676   int rdlo, rdhi, rm, rs;
3677
3678   /* Only one format "rdlo, rdhi, rm, rs".  */
3679   skip_whitespace (str);
3680
3681   if ((rdlo = reg_required_here (&str, 12)) == FAIL)
3682     {
3683       inst.error = BAD_ARGS;
3684       return;
3685     }
3686
3687   if (skip_past_comma (&str) == FAIL
3688       || (rdhi = reg_required_here (&str, 16)) == FAIL)
3689     {
3690       inst.error = BAD_ARGS;
3691       return;
3692     }
3693
3694   if (skip_past_comma (&str) == FAIL
3695       || (rm = reg_required_here (&str, 0)) == FAIL)
3696     {
3697       inst.error = BAD_ARGS;
3698       return;
3699     }
3700
3701   /* rdhi, rdlo and rm must all be different.  */
3702   if (rdlo == rdhi || rdlo == rm || rdhi == rm)
3703     as_tsktsk (_("rdhi, rdlo and rm must all be different"));
3704
3705   if (skip_past_comma (&str) == FAIL
3706       || (rs = reg_required_here (&str, 8)) == FAIL)
3707     {
3708       inst.error = BAD_ARGS;
3709       return;
3710     }
3711
3712   if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
3713     {
3714       inst.error = BAD_PC;
3715       return;
3716     }
3717
3718   end_of_line (str);
3719   return;
3720 }
3721
3722 static void
3723 do_mul (str)
3724      char * str;
3725 {
3726   int rd, rm;
3727
3728   /* Only one format "rd, rm, rs".  */
3729   skip_whitespace (str);
3730
3731   if ((rd = reg_required_here (&str, 16)) == FAIL)
3732     {
3733       inst.error = BAD_ARGS;
3734       return;
3735     }
3736
3737   if (rd == REG_PC)
3738     {
3739       inst.error = BAD_PC;
3740       return;
3741     }
3742
3743   if (skip_past_comma (&str) == FAIL
3744       || (rm = reg_required_here (&str, 0)) == FAIL)
3745     {
3746       inst.error = BAD_ARGS;
3747       return;
3748     }
3749
3750   if (rm == REG_PC)
3751     {
3752       inst.error = BAD_PC;
3753       return;
3754     }
3755
3756   if (rm == rd)
3757     as_tsktsk (_("rd and rm should be different in mul"));
3758
3759   if (skip_past_comma (&str) == FAIL
3760       || (rm = reg_required_here (&str, 8)) == FAIL)
3761     {
3762       inst.error = BAD_ARGS;
3763       return;
3764     }
3765
3766   if (rm == REG_PC)
3767     {
3768       inst.error = BAD_PC;
3769       return;
3770     }
3771
3772   end_of_line (str);
3773   return;
3774 }
3775
3776 static void
3777 do_mla (str)
3778      char * str;
3779 {
3780   int rd, rm;
3781
3782   /* Only one format "rd, rm, rs, rn".  */
3783   skip_whitespace (str);
3784
3785   if ((rd = reg_required_here (&str, 16)) == FAIL)
3786     {
3787       inst.error = BAD_ARGS;
3788       return;
3789     }
3790
3791   if (rd == REG_PC)
3792     {
3793       inst.error = BAD_PC;
3794       return;
3795     }
3796
3797   if (skip_past_comma (&str) == FAIL
3798       || (rm = reg_required_here (&str, 0)) == FAIL)
3799     {
3800       inst.error = BAD_ARGS;
3801       return;
3802     }
3803
3804   if (rm == REG_PC)
3805     {
3806       inst.error = BAD_PC;
3807       return;
3808     }
3809
3810   if (rm == rd)
3811     as_tsktsk (_("rd and rm should be different in mla"));
3812
3813   if (skip_past_comma (&str) == FAIL
3814       || (rd = reg_required_here (&str, 8)) == FAIL
3815       || skip_past_comma (&str) == FAIL
3816       || (rm = reg_required_here (&str, 12)) == FAIL)
3817     {
3818       inst.error = BAD_ARGS;
3819       return;
3820     }
3821
3822   if (rd == REG_PC || rm == REG_PC)
3823     {
3824       inst.error = BAD_PC;
3825       return;
3826     }
3827
3828   end_of_line (str);
3829   return;
3830 }
3831
3832 /* Expects *str -> the characters "acc0", possibly with leading blanks.
3833    Advances *str to the next non-alphanumeric.
3834    Returns 0, or else FAIL (in which case sets inst.error).
3835
3836   (In a future XScale, there may be accumulators other than zero.
3837   At that time this routine and its callers can be upgraded to suit.)  */
3838
3839 static int
3840 accum0_required_here (str)
3841      char ** str;
3842 {
3843   static char buff [128];       /* Note the address is taken.  Hence, static.  */
3844   char * p = * str;
3845   char   c;
3846   int result = 0;               /* The accum number.  */
3847
3848   skip_whitespace (p);
3849
3850   *str = p;                     /* Advance caller's string pointer too.  */
3851   c = *p++;
3852   while (ISALNUM (c))
3853     c = *p++;
3854
3855   *--p = 0;                     /* Aap nul into input buffer at non-alnum.  */
3856
3857   if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
3858     {
3859       sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
3860       inst.error = buff;
3861       result = FAIL;
3862     }
3863
3864   *p = c;                       /* Unzap.  */
3865   *str = p;                     /* Caller's string pointer to after match.  */
3866   return result;
3867 }
3868
3869 /* Expects **str -> after a comma. May be leading blanks.
3870    Advances *str, recognizing a load  mode, and setting inst.instruction.
3871    Returns rn, or else FAIL (in which case may set inst.error
3872    and not advance str)
3873
3874    Note: doesn't know Rd, so no err checks that require such knowledge.  */
3875
3876 static int
3877 ld_mode_required_here (string)
3878      char ** string;
3879 {
3880   char * str = * string;
3881   int    rn;
3882   int    pre_inc = 0;
3883
3884   skip_whitespace (str);
3885
3886   if (* str == '[')
3887     {
3888       str++;
3889
3890       skip_whitespace (str);
3891
3892       if ((rn = reg_required_here (& str, 16)) == FAIL)
3893         return FAIL;
3894
3895       skip_whitespace (str);
3896
3897       if (* str == ']')
3898         {
3899           str ++;
3900
3901           if (skip_past_comma (& str) == SUCCESS)
3902             {
3903               /* [Rn],... (post inc) */
3904               if (ldst_extend_v4 (&str) == FAIL)
3905                 return FAIL;
3906             }
3907           else        /* [Rn] */
3908             {
3909               skip_whitespace (str);
3910
3911               if (* str == '!')
3912                 {
3913                   str ++;
3914                   inst.instruction |= WRITE_BACK;
3915                 }
3916
3917               inst.instruction |= INDEX_UP | HWOFFSET_IMM;
3918               pre_inc = 1;
3919             }
3920         }
3921       else        /* [Rn,...] */
3922         {
3923           if (skip_past_comma (& str) == FAIL)
3924             {
3925               inst.error = _("pre-indexed expression expected");
3926               return FAIL;
3927             }
3928
3929           pre_inc = 1;
3930
3931           if (ldst_extend_v4 (&str) == FAIL)
3932             return FAIL;
3933
3934           skip_whitespace (str);
3935
3936           if (* str ++ != ']')
3937             {
3938               inst.error = _("missing ]");
3939               return FAIL;
3940             }
3941
3942           skip_whitespace (str);
3943
3944           if (* str == '!')
3945             {
3946               str ++;
3947               inst.instruction |= WRITE_BACK;
3948             }
3949         }
3950     }
3951   else if (* str == '=')        /* ldr's "r,=label" syntax */
3952     /* We should never reach here, because <text> = <expression> is
3953        caught gas/read.c read_a_source_file() as a .set operation.  */
3954     return FAIL;
3955   else                          /* PC +- 8 bit immediate offset.  */
3956     {
3957       if (my_get_expression (& inst.reloc.exp, & str))
3958         return FAIL;
3959
3960       inst.instruction            |= HWOFFSET_IMM;      /* The I bit.  */
3961       inst.reloc.type              = BFD_RELOC_ARM_OFFSET_IMM8;
3962       inst.reloc.exp.X_add_number -= 8;                 /* PC rel adjust.  */
3963       inst.reloc.pc_rel            = 1;
3964       inst.instruction            |= (REG_PC << 16);
3965
3966       rn = REG_PC;
3967       pre_inc = 1;
3968     }
3969
3970   inst.instruction |= (pre_inc ? PRE_INDEX : 0);
3971   * string = str;
3972
3973   return rn;
3974 }
3975
3976 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3977    SMLAxy{cond} Rd,Rm,Rs,Rn
3978    SMLAWy{cond} Rd,Rm,Rs,Rn
3979    Error if any register is R15.  */
3980
3981 static void
3982 do_smla (str)
3983      char *        str;
3984 {
3985   int rd, rm, rs, rn;
3986
3987   skip_whitespace (str);
3988
3989   if ((rd = reg_required_here (& str, 16)) == FAIL
3990       || skip_past_comma (& str) == FAIL
3991       || (rm = reg_required_here (& str, 0)) == FAIL
3992       || skip_past_comma (& str) == FAIL
3993       || (rs = reg_required_here (& str, 8)) == FAIL
3994       || skip_past_comma (& str) == FAIL
3995       || (rn = reg_required_here (& str, 12)) == FAIL)
3996     inst.error = BAD_ARGS;
3997
3998   else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
3999     inst.error = BAD_PC;
4000
4001   else
4002     end_of_line (str);
4003 }
4004
4005 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4006    SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4007    Error if any register is R15.
4008    Warning if Rdlo == Rdhi.  */
4009
4010 static void
4011 do_smlal (str)
4012      char *        str;
4013 {
4014   int rdlo, rdhi, rm, rs;
4015
4016   skip_whitespace (str);
4017
4018   if ((rdlo = reg_required_here (& str, 12)) == FAIL
4019       || skip_past_comma (& str) == FAIL
4020       || (rdhi = reg_required_here (& str, 16)) == FAIL
4021       || skip_past_comma (& str) == FAIL
4022       || (rm = reg_required_here (& str, 0)) == FAIL
4023       || skip_past_comma (& str) == FAIL
4024       || (rs = reg_required_here (& str, 8)) == FAIL)
4025     {
4026       inst.error = BAD_ARGS;
4027       return;
4028     }
4029
4030   if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4031     {
4032       inst.error = BAD_PC;
4033       return;
4034     }
4035
4036   if (rdlo == rdhi)
4037     as_tsktsk (_("rdhi and rdlo must be different"));
4038
4039   end_of_line (str);
4040 }
4041
4042 /* ARM V5E (El Segundo) signed-multiply (argument parse)
4043    SMULxy{cond} Rd,Rm,Rs
4044    Error if any register is R15.  */
4045
4046 static void
4047 do_smul (str)
4048      char *        str;
4049 {
4050   int rd, rm, rs;
4051
4052   skip_whitespace (str);
4053
4054   if ((rd = reg_required_here (& str, 16)) == FAIL
4055       || skip_past_comma (& str) == FAIL
4056       || (rm = reg_required_here (& str, 0)) == FAIL
4057       || skip_past_comma (& str) == FAIL
4058       || (rs = reg_required_here (& str, 8)) == FAIL)
4059     inst.error = BAD_ARGS;
4060
4061   else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
4062     inst.error = BAD_PC;
4063
4064   else
4065     end_of_line (str);
4066 }
4067
4068 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4069    Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4070    Error if any register is R15.  */
4071
4072 static void
4073 do_qadd (str)
4074      char *        str;
4075 {
4076   int rd, rm, rn;
4077
4078   skip_whitespace (str);
4079
4080   if ((rd = reg_required_here (& str, 12)) == FAIL
4081       || skip_past_comma (& str) == FAIL
4082       || (rm = reg_required_here (& str, 0)) == FAIL
4083       || skip_past_comma (& str) == FAIL
4084       || (rn = reg_required_here (& str, 16)) == FAIL)
4085     inst.error = BAD_ARGS;
4086
4087   else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4088     inst.error = BAD_PC;
4089
4090   else
4091     end_of_line (str);
4092 }
4093
4094 /* ARM V5E (el Segundo)
4095    MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4096    MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4097
4098    These are equivalent to the XScale instructions MAR and MRA,
4099    respectively, when coproc == 0, opcode == 0, and CRm == 0.
4100
4101    Result unpredicatable if Rd or Rn is R15.  */
4102
4103 static void
4104 do_co_reg2c (str)
4105      char *        str;
4106 {
4107   int rd, rn;
4108
4109   skip_whitespace (str);
4110
4111   if (co_proc_number (& str) == FAIL)
4112     {
4113       if (!inst.error)
4114         inst.error = BAD_ARGS;
4115       return;
4116     }
4117
4118   if (skip_past_comma (& str) == FAIL
4119       || cp_opc_expr (& str, 4, 4) == FAIL)
4120     {
4121       if (!inst.error)
4122         inst.error = BAD_ARGS;
4123       return;
4124     }
4125
4126   if (skip_past_comma (& str) == FAIL
4127       || (rd = reg_required_here (& str, 12)) == FAIL)
4128     {
4129       if (!inst.error)
4130         inst.error = BAD_ARGS;
4131       return;
4132     }
4133
4134   if (skip_past_comma (& str) == FAIL
4135       || (rn = reg_required_here (& str, 16)) == FAIL)
4136     {
4137       if (!inst.error)
4138         inst.error = BAD_ARGS;
4139       return;
4140     }
4141
4142   /* Unpredictable result if rd or rn is R15.  */
4143   if (rd == REG_PC || rn == REG_PC)
4144     as_tsktsk
4145       (_("Warning: instruction unpredictable when using r15"));
4146
4147   if (skip_past_comma (& str) == FAIL
4148       || cp_reg_required_here (& str, 0) == FAIL)
4149     {
4150       if (!inst.error)
4151         inst.error = BAD_ARGS;
4152       return;
4153     }
4154
4155   end_of_line (str);
4156 }
4157
4158 /* ARM V5 count-leading-zeroes instruction (argument parse)
4159      CLZ{<cond>} <Rd>, <Rm>
4160      Condition defaults to COND_ALWAYS.
4161      Error if Rd or Rm are R15.  */
4162
4163 static void
4164 do_clz (str)
4165      char *        str;
4166 {
4167   int rd, rm;
4168
4169   skip_whitespace (str);
4170
4171   if (((rd = reg_required_here (& str, 12)) == FAIL)
4172       || (skip_past_comma (& str) == FAIL)
4173       || ((rm = reg_required_here (& str, 0)) == FAIL))
4174     inst.error = BAD_ARGS;
4175
4176   else if (rd == REG_PC || rm == REG_PC )
4177     inst.error = BAD_PC;
4178
4179   else
4180     end_of_line (str);
4181 }
4182
4183 /* ARM V5 (argument parse)
4184      LDC2{L} <coproc>, <CRd>, <addressing mode>
4185      STC2{L} <coproc>, <CRd>, <addressing mode>
4186      Instruction is not conditional, and has 0xf in the codition field.
4187      Otherwise, it's the same as LDC/STC.  */
4188
4189 static void
4190 do_lstc2 (str)
4191      char *        str;
4192 {
4193   skip_whitespace (str);
4194
4195   if (co_proc_number (& str) == FAIL)
4196     {
4197       if (!inst.error)
4198         inst.error = BAD_ARGS;
4199     }
4200   else if (skip_past_comma (& str) == FAIL
4201            || cp_reg_required_here (& str, 12) == FAIL)
4202     {
4203       if (!inst.error)
4204         inst.error = BAD_ARGS;
4205     }
4206   else if (skip_past_comma (& str) == FAIL
4207            || cp_address_required_here (&str, CP_WB_OK) == FAIL)
4208     {
4209       if (! inst.error)
4210         inst.error = BAD_ARGS;
4211     }
4212   else
4213     end_of_line (str);
4214 }
4215
4216 /* ARM V5 (argument parse)
4217      CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4218      Instruction is not conditional, and has 0xf in the condition field.
4219      Otherwise, it's the same as CDP.  */
4220
4221 static void
4222 do_cdp2 (str)
4223      char *        str;
4224 {
4225   skip_whitespace (str);
4226
4227   if (co_proc_number (& str) == FAIL)
4228     {
4229       if (!inst.error)
4230         inst.error = BAD_ARGS;
4231       return;
4232     }
4233
4234   if (skip_past_comma (& str) == FAIL
4235       || cp_opc_expr (& str, 20,4) == FAIL)
4236     {
4237       if (!inst.error)
4238         inst.error = BAD_ARGS;
4239       return;
4240     }
4241
4242   if (skip_past_comma (& str) == FAIL
4243       || cp_reg_required_here (& str, 12) == FAIL)
4244     {
4245       if (!inst.error)
4246         inst.error = BAD_ARGS;
4247       return;
4248     }
4249
4250   if (skip_past_comma (& str) == FAIL
4251       || cp_reg_required_here (& str, 16) == FAIL)
4252     {
4253       if (!inst.error)
4254         inst.error = BAD_ARGS;
4255       return;
4256     }
4257
4258   if (skip_past_comma (& str) == FAIL
4259       || cp_reg_required_here (& str, 0) == FAIL)
4260     {
4261       if (!inst.error)
4262         inst.error = BAD_ARGS;
4263       return;
4264     }
4265
4266   if (skip_past_comma (& str) == SUCCESS)
4267     {
4268       if (cp_opc_expr (& str, 5, 3) == FAIL)
4269         {
4270           if (!inst.error)
4271             inst.error = BAD_ARGS;
4272           return;
4273         }
4274     }
4275
4276   end_of_line (str);
4277 }
4278
4279 /* ARM V5 (argument parse)
4280      MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4281      MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4282      Instruction is not conditional, and has 0xf in the condition field.
4283      Otherwise, it's the same as MCR/MRC.  */
4284
4285 static void
4286 do_co_reg2 (str)
4287      char *        str;
4288 {
4289   skip_whitespace (str);
4290
4291   if (co_proc_number (& str) == FAIL)
4292     {
4293       if (!inst.error)
4294         inst.error = BAD_ARGS;
4295       return;
4296     }
4297
4298   if (skip_past_comma (& str) == FAIL
4299       || cp_opc_expr (& str, 21, 3) == FAIL)
4300     {
4301       if (!inst.error)
4302         inst.error = BAD_ARGS;
4303       return;
4304     }
4305
4306   if (skip_past_comma (& str) == FAIL
4307       || reg_required_here (& str, 12) == FAIL)
4308     {
4309       if (!inst.error)
4310         inst.error = BAD_ARGS;
4311       return;
4312     }
4313
4314   if (skip_past_comma (& str) == FAIL
4315       || cp_reg_required_here (& str, 16) == FAIL)
4316     {
4317       if (!inst.error)
4318         inst.error = BAD_ARGS;
4319       return;
4320     }
4321
4322   if (skip_past_comma (& str) == FAIL
4323       || cp_reg_required_here (& str, 0) == FAIL)
4324     {
4325       if (!inst.error)
4326         inst.error = BAD_ARGS;
4327       return;
4328     }
4329
4330   if (skip_past_comma (& str) == SUCCESS)
4331     {
4332       if (cp_opc_expr (& str, 5, 3) == FAIL)
4333         {
4334           if (!inst.error)
4335             inst.error = BAD_ARGS;
4336           return;
4337         }
4338     }
4339
4340   end_of_line (str);
4341 }
4342
4343 /* ARM v5TEJ.  Jump to Jazelle code.  */
4344 static void
4345 do_bxj (str)
4346      char * str;
4347 {
4348   int reg;
4349
4350   skip_whitespace (str);
4351
4352   if ((reg = reg_required_here (&str, 0)) == FAIL)
4353     {
4354       inst.error = BAD_ARGS;
4355       return;
4356     }
4357
4358   /* Note - it is not illegal to do a "bxj pc".  Useless, but not illegal.  */
4359   if (reg == REG_PC)
4360     as_tsktsk (_("use of r15 in bxj is not really useful"));
4361
4362   end_of_line (str);
4363 }
4364
4365 /* THUMB V5 breakpoint instruction (argument parse)
4366         BKPT <immed_8>.  */
4367
4368 static void
4369 do_t_bkpt (str)
4370      char * str;
4371 {
4372   expressionS expr;
4373   unsigned long number;
4374
4375   skip_whitespace (str);
4376
4377   /* Allow optional leading '#'.  */
4378   if (is_immediate_prefix (*str))
4379     str ++;
4380
4381   memset (& expr, '\0', sizeof (expr));
4382   if (my_get_expression (& expr, & str)
4383       || (expr.X_op != O_constant
4384           /* As a convenience we allow 'bkpt' without an operand.  */
4385           && expr.X_op != O_absent))
4386     {
4387       inst.error = _("bad expression");
4388       return;
4389     }
4390
4391   number = expr.X_add_number;
4392
4393   /* Check it fits an 8 bit unsigned.  */
4394   if (number != (number & 0xff))
4395     {
4396       inst.error = _("immediate value out of range");
4397       return;
4398     }
4399
4400   inst.instruction |= number;
4401
4402   end_of_line (str);
4403 }
4404
4405 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4406    Expects inst.instruction is set for BLX(1).
4407    Note: this is cloned from do_branch, and the reloc changed to be a
4408         new one that can cope with setting one extra bit (the H bit).  */
4409
4410 static void
4411 do_branch25 (str)
4412      char *        str;
4413 {
4414   if (my_get_expression (& inst.reloc.exp, & str))
4415     return;
4416
4417 #ifdef OBJ_ELF
4418   {
4419     char * save_in;
4420
4421     /* ScottB: February 5, 1998 */
4422     /* Check to see of PLT32 reloc required for the instruction.  */
4423
4424     /* arm_parse_reloc() works on input_line_pointer.
4425        We actually want to parse the operands to the branch instruction
4426        passed in 'str'.  Save the input pointer and restore it later.  */
4427     save_in = input_line_pointer;
4428     input_line_pointer = str;
4429
4430     if (inst.reloc.exp.X_op == O_symbol
4431         && *str == '('
4432         && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
4433       {
4434         inst.reloc.type   = BFD_RELOC_ARM_PLT32;
4435         inst.reloc.pc_rel = 0;
4436         /* Modify str to point to after parsed operands, otherwise
4437            end_of_line() will complain about the (PLT) left in str.  */
4438         str = input_line_pointer;
4439       }
4440     else
4441       {
4442         inst.reloc.type   = BFD_RELOC_ARM_PCREL_BLX;
4443         inst.reloc.pc_rel = 1;
4444       }
4445
4446     input_line_pointer = save_in;
4447   }
4448 #else
4449   inst.reloc.type   = BFD_RELOC_ARM_PCREL_BLX;
4450   inst.reloc.pc_rel = 1;
4451 #endif /* OBJ_ELF */
4452
4453   end_of_line (str);
4454 }
4455
4456 /* ARM V5 branch-link-exchange instruction (argument parse)
4457      BLX <target_addr>          ie BLX(1)
4458      BLX{<condition>} <Rm>      ie BLX(2)
4459    Unfortunately, there are two different opcodes for this mnemonic.
4460    So, the insns[].value is not used, and the code here zaps values
4461         into inst.instruction.
4462    Also, the <target_addr> can be 25 bits, hence has its own reloc.  */
4463
4464 static void
4465 do_blx (str)
4466      char *        str;
4467 {
4468   char * mystr = str;
4469   int rm;
4470
4471   skip_whitespace (mystr);
4472   rm = reg_required_here (& mystr, 0);
4473
4474   /* The above may set inst.error.  Ignore his opinion.  */
4475   inst.error = 0;
4476
4477   if (rm != FAIL)
4478     {
4479       /* Arg is a register.
4480          Use the condition code our caller put in inst.instruction.
4481          Pass ourselves off as a BX with a funny opcode.  */
4482       inst.instruction |= 0x012fff30;
4483       do_bx (str);
4484     }
4485   else
4486     {
4487       /* This must be is BLX <target address>, no condition allowed.  */
4488       if (inst.instruction != COND_ALWAYS)
4489         {
4490           inst.error = BAD_COND;
4491           return;
4492         }
4493
4494       inst.instruction = 0xfafffffe;
4495
4496       /* Process like a B/BL, but with a different reloc.
4497          Note that B/BL expecte fffffe, not 0, offset in the opcode table.  */
4498       do_branch25 (str);
4499     }
4500 }
4501
4502 /* ARM V5 Thumb BLX (argument parse)
4503         BLX <target_addr>       which is BLX(1)
4504         BLX <Rm>                which is BLX(2)
4505    Unfortunately, there are two different opcodes for this mnemonic.
4506    So, the tinsns[].value is not used, and the code here zaps values
4507         into inst.instruction.  */
4508
4509 static void
4510 do_t_blx (str)
4511      char * str;
4512 {
4513   char * mystr = str;
4514   int rm;
4515
4516   skip_whitespace (mystr);
4517   inst.instruction = 0x4780;
4518
4519   /* Note that this call is to the ARM register recognizer.  BLX(2)
4520      uses the ARM register space, not the Thumb one, so a call to
4521      thumb_reg() would be wrong.  */
4522   rm = reg_required_here (& mystr, 3);
4523   inst.error = 0;
4524
4525   if (rm != FAIL)
4526     {
4527       /* It's BLX(2).  The .instruction was zapped with rm & is final.  */
4528       inst.size = 2;
4529     }
4530   else
4531     {
4532       /* No ARM register.  This must be BLX(1).  Change the .instruction.  */
4533       inst.instruction = 0xf7ffeffe;
4534       inst.size = 4;
4535
4536       if (my_get_expression (& inst.reloc.exp, & mystr))
4537         return;
4538
4539       inst.reloc.type   = BFD_RELOC_THUMB_PCREL_BLX;
4540       inst.reloc.pc_rel = 1;
4541     }
4542
4543   end_of_line (mystr);
4544 }
4545
4546 /* ARM V5 breakpoint instruction (argument parse)
4547      BKPT <16 bit unsigned immediate>
4548      Instruction is not conditional.
4549         The bit pattern given in insns[] has the COND_ALWAYS condition,
4550         and it is an error if the caller tried to override that.  */
4551
4552 static void
4553 do_bkpt (str)
4554      char *        str;
4555 {
4556   expressionS expr;
4557   unsigned long number;
4558
4559   skip_whitespace (str);
4560
4561   /* Allow optional leading '#'.  */
4562   if (is_immediate_prefix (* str))
4563     str++;
4564
4565   memset (& expr, '\0', sizeof (expr));
4566
4567   if (my_get_expression (& expr, & str)
4568       || (expr.X_op != O_constant
4569           /* As a convenience we allow 'bkpt' without an operand.  */
4570           && expr.X_op != O_absent))
4571     {
4572       inst.error = _("bad expression");
4573       return;
4574     }
4575
4576   number = expr.X_add_number;
4577
4578   /* Check it fits a 16 bit unsigned.  */
4579   if (number != (number & 0xffff))
4580     {
4581       inst.error = _("immediate value out of range");
4582       return;
4583     }
4584
4585   /* Top 12 of 16 bits to bits 19:8.  */
4586   inst.instruction |= (number & 0xfff0) << 4;
4587
4588   /* Bottom 4 of 16 bits to bits 3:0.  */
4589   inst.instruction |= number & 0xf;
4590
4591   end_of_line (str);
4592 }
4593
4594 static unsigned long check_iwmmxt_insn PARAMS ((char *, enum iwmmxt_insn_type, int));
4595
4596 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate.  */
4597
4598 static unsigned long
4599 check_iwmmxt_insn (str, insn_type, immediate_size)
4600      char * str;
4601      enum iwmmxt_insn_type insn_type;
4602      int immediate_size;
4603 {
4604   int reg = 0;
4605   const char *  inst_error;
4606   expressionS expr;
4607   unsigned long number;
4608
4609   inst_error = inst.error;
4610   if (!inst.error)
4611     inst.error = BAD_ARGS;
4612   skip_whitespace (str);
4613
4614   switch (insn_type)
4615     {
4616     case check_rd:
4617       if ((reg = reg_required_here (&str, 12)) == FAIL)
4618         return FAIL;
4619       break;
4620       
4621     case check_wr:
4622        if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
4623          return FAIL;
4624        break;
4625        
4626     case check_wrwr:
4627       if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4628            || skip_past_comma (&str) == FAIL
4629            || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
4630         return FAIL;
4631       break;
4632       
4633     case check_wrwrwr:
4634       if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4635            || skip_past_comma (&str) == FAIL
4636            || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4637            || skip_past_comma (&str) == FAIL
4638            || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
4639         return FAIL;
4640       break;
4641       
4642     case check_wrwrwcg:
4643       if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4644            || skip_past_comma (&str) == FAIL
4645            || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4646            || skip_past_comma (&str) == FAIL
4647            || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
4648         return FAIL;
4649       break;
4650       
4651     case check_tbcst:
4652       if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4653            || skip_past_comma (&str) == FAIL
4654            || reg_required_here (&str, 12) == FAIL))
4655         return FAIL;
4656       break;
4657       
4658     case check_tmovmsk:
4659       if ((reg_required_here (&str, 12) == FAIL
4660            || skip_past_comma (&str) == FAIL
4661            || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
4662         return FAIL;
4663       break;
4664       
4665     case check_tmia:
4666       if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
4667            || skip_past_comma (&str) == FAIL
4668            || reg_required_here (&str, 0) == FAIL
4669            || skip_past_comma (&str) == FAIL
4670            || reg_required_here (&str, 12) == FAIL))
4671         return FAIL;
4672       break;
4673       
4674     case check_tmcrr:
4675       if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
4676            || skip_past_comma (&str) == FAIL
4677            || reg_required_here (&str, 12) == FAIL
4678            || skip_past_comma (&str) == FAIL
4679            || reg_required_here (&str, 16) == FAIL))
4680         return FAIL;
4681       break;
4682       
4683     case check_tmrrc:
4684       if ((reg_required_here (&str, 12) == FAIL
4685            || skip_past_comma (&str) == FAIL
4686            || reg_required_here (&str, 16) == FAIL
4687            || skip_past_comma (&str) == FAIL
4688            || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
4689         return FAIL;
4690       break;
4691       
4692     case check_tmcr:
4693       if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
4694            || skip_past_comma (&str) == FAIL
4695            || reg_required_here (&str, 12) == FAIL))
4696         return FAIL;
4697       break;
4698       
4699     case check_tmrc:
4700       if ((reg_required_here (&str, 12) == FAIL
4701            || skip_past_comma (&str) == FAIL
4702            || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
4703         return FAIL;
4704       break;
4705       
4706     case check_tinsr:
4707       if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4708            || skip_past_comma (&str) == FAIL
4709            || reg_required_here (&str, 12) == FAIL
4710            || skip_past_comma (&str) == FAIL))
4711         return FAIL;
4712       break;
4713       
4714     case check_textrc:
4715       if ((reg_required_here (&str, 12) == FAIL
4716            || skip_past_comma (&str) == FAIL))
4717         return FAIL;
4718       break;
4719       
4720     case check_waligni:
4721       if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4722            || skip_past_comma (&str) == FAIL
4723            || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4724            || skip_past_comma (&str) == FAIL
4725            || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
4726            || skip_past_comma (&str) == FAIL))
4727         return FAIL;
4728       break;
4729       
4730     case check_textrm:
4731       if ((reg_required_here (&str, 12) == FAIL
4732            || skip_past_comma (&str) == FAIL
4733            || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4734            || skip_past_comma (&str) == FAIL))
4735         return FAIL;
4736       break;
4737       
4738     case check_wshufh:
4739       if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4740            || skip_past_comma (&str) == FAIL
4741            || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4742            || skip_past_comma (&str) == FAIL))
4743         return FAIL;
4744       break;
4745     }
4746   
4747   if (immediate_size == 0)
4748     {
4749       end_of_line (str);
4750       inst.error = inst_error;
4751       return reg;
4752     }
4753   else
4754     {
4755       skip_whitespace (str);      
4756   
4757       /* Allow optional leading '#'. */
4758       if (is_immediate_prefix (* str))
4759         str++;
4760
4761       memset (& expr, '\0', sizeof (expr));
4762   
4763       if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
4764         {
4765           inst.error = _("bad or missing expression");
4766           return FAIL;
4767         }
4768   
4769       number = expr.X_add_number;
4770   
4771       if (number != (number & immediate_size))
4772         {
4773           inst.error = _("immediate value out of range");
4774           return FAIL;
4775         }
4776       end_of_line (str);
4777       inst.error = inst_error;
4778       return number;
4779     }
4780 }
4781
4782 static void
4783 do_iwmmxt_byte_addr (str)
4784      char * str;
4785 {
4786   int op = (inst.instruction & 0x300) >> 8;
4787   int reg;
4788
4789   inst.instruction &= ~0x300;
4790   inst.instruction |= (op & 1) << 22 | (op & 2) << 7;  
4791
4792   skip_whitespace (str);
4793
4794   if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
4795       || skip_past_comma (& str) == FAIL
4796       || cp_byte_address_required_here (&str) == FAIL)
4797     {
4798       if (! inst.error)
4799         inst.error = BAD_ARGS;
4800     }
4801   else
4802     end_of_line (str);
4803
4804   if (wc_register (reg))
4805     {
4806       inst.instruction |=  0xf0000100;
4807       inst.instruction &= ~0x00400000;
4808     }
4809 }
4810
4811 static void
4812 do_iwmmxt_tandc (str)
4813      char * str;
4814 {
4815   int reg;
4816
4817   reg = check_iwmmxt_insn (str, check_rd, 0);
4818
4819   if (reg != REG_PC && !inst.error)
4820     inst.error = _("only r15 allowed here");
4821   return;
4822 }
4823
4824 static void
4825 do_iwmmxt_tbcst (str)
4826      char * str;
4827 {
4828   check_iwmmxt_insn (str, check_tbcst, 0);
4829
4830   return;
4831 }
4832
4833 static void
4834 do_iwmmxt_textrc (str)
4835      char * str;
4836 {
4837   unsigned long number;
4838
4839   if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
4840     return;
4841
4842   inst.instruction |= number & 0x7;
4843   return;
4844 }
4845
4846 static void
4847 do_iwmmxt_textrm (str)
4848      char * str;
4849 {
4850   unsigned long number;
4851
4852   if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
4853     return;
4854
4855   inst.instruction |= number & 0x7;
4856 }
4857
4858 static void
4859 do_iwmmxt_tinsr (str)
4860      char * str;
4861 {
4862   unsigned long number;
4863
4864   if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
4865     return;
4866
4867   inst.instruction |= number & 0x7;
4868   return;
4869 }
4870
4871 static void
4872 do_iwmmxt_tmcr (str)
4873      char * str;
4874 {
4875   check_iwmmxt_insn (str, check_tmcr, 0);
4876
4877   return;
4878 }
4879
4880 static void
4881 do_iwmmxt_tmcrr (str)
4882      char * str;
4883 {
4884   check_iwmmxt_insn (str, check_tmcrr, 0);
4885
4886   return;
4887 }
4888
4889 static void
4890 do_iwmmxt_tmia (str)
4891      char * str;
4892 {
4893   check_iwmmxt_insn (str, check_tmia, 0);
4894
4895   return;
4896 }
4897
4898 static void
4899 do_iwmmxt_tmovmsk (str)
4900      char * str;
4901 {
4902   check_iwmmxt_insn (str, check_tmovmsk, 0);
4903
4904   return;
4905 }
4906
4907 static void
4908 do_iwmmxt_tmrc (str)
4909      char * str;
4910 {
4911   check_iwmmxt_insn (str, check_tmrc, 0);
4912
4913   return;
4914 }
4915
4916 static void
4917 do_iwmmxt_tmrrc (str)
4918      char * str;
4919 {
4920   check_iwmmxt_insn (str, check_tmrrc, 0);
4921
4922   return;
4923 }
4924
4925 static void
4926 do_iwmmxt_torc (str)
4927      char * str;
4928 {
4929   check_iwmmxt_insn (str, check_rd, 0);
4930   return;
4931 }
4932
4933 static void
4934 do_iwmmxt_waligni (str)
4935      char * str;
4936 {
4937   unsigned long number;
4938
4939   if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
4940     return;
4941
4942   inst.instruction |= ((number & 0x7) << 20);
4943   return;
4944 }
4945
4946 static void
4947 do_iwmmxt_wmov (str)
4948      char * str;
4949 {
4950   if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
4951     return;
4952   
4953   inst.instruction |= ((inst.instruction >> 16) & 0xf);
4954   return;
4955 }
4956
4957 static void
4958 do_iwmmxt_word_addr (str)
4959      char * str;
4960 {
4961   int op = (inst.instruction & 0x300) >> 8;
4962   int reg;
4963
4964   inst.instruction &= ~0x300;
4965   inst.instruction |= (op & 1) << 22 | (op & 2) << 7;  
4966
4967   skip_whitespace (str);
4968
4969   if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
4970       || skip_past_comma (& str) == FAIL
4971       || cp_address_required_here (& str, CP_WB_OK) == FAIL)
4972     {
4973       if (! inst.error)
4974         inst.error = BAD_ARGS;
4975     }
4976   else
4977     end_of_line (str);
4978
4979   if (wc_register (reg))
4980     {
4981       inst.instruction |=  0xf0000100;
4982       inst.instruction &= ~0x00400000;
4983     }
4984 }
4985
4986 static void
4987 do_iwmmxt_wrwr (str)
4988      char * str;
4989 {
4990   check_iwmmxt_insn (str, check_wrwr, 0);
4991   
4992   return;
4993 }
4994
4995 static void
4996 do_iwmmxt_wrwrwcg (str)
4997      char * str;
4998 {
4999   check_iwmmxt_insn (str, check_wrwrwcg, 0);
5000
5001   return;
5002 }
5003
5004 static void
5005 do_iwmmxt_wrwrwr (str)
5006      char * str;
5007 {
5008   check_iwmmxt_insn (str, check_wrwrwr, 0);
5009
5010   return;
5011 }
5012
5013 static void
5014 do_iwmmxt_wshufh (str)
5015      char * str;
5016 {
5017   unsigned long number;
5018
5019   if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
5020     return;
5021
5022   inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
5023   return;
5024 }
5025
5026 static void
5027 do_iwmmxt_wzero (str)
5028      char * str;
5029 {
5030   if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
5031     return;
5032
5033   inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
5034   return;
5035 }
5036
5037 /* Xscale multiply-accumulate (argument parse)
5038      MIAcc   acc0,Rm,Rs
5039      MIAPHcc acc0,Rm,Rs
5040      MIAxycc acc0,Rm,Rs.  */
5041
5042 static void
5043 do_xsc_mia (str)
5044      char * str;
5045 {
5046   int rs;
5047   int rm;
5048
5049   if (accum0_required_here (& str) == FAIL)
5050     inst.error = ERR_NO_ACCUM;
5051
5052   else if (skip_past_comma (& str) == FAIL
5053            || (rm = reg_required_here (& str, 0)) == FAIL)
5054     inst.error = BAD_ARGS;
5055
5056   else if (skip_past_comma (& str) == FAIL
5057            || (rs = reg_required_here (& str, 12)) == FAIL)
5058     inst.error = BAD_ARGS;
5059
5060   /* inst.instruction has now been zapped with both rm and rs.  */
5061   else if (rm == REG_PC || rs == REG_PC)
5062     inst.error = BAD_PC;        /* Undefined result if rm or rs is R15.  */
5063
5064   else
5065     end_of_line (str);
5066 }
5067
5068 /* Xscale move-accumulator-register (argument parse)
5069
5070      MARcc   acc0,RdLo,RdHi.  */
5071
5072 static void
5073 do_xsc_mar (str)
5074      char * str;
5075 {
5076   int rdlo, rdhi;
5077
5078   if (accum0_required_here (& str) == FAIL)
5079     inst.error = ERR_NO_ACCUM;
5080
5081   else if (skip_past_comma (& str) == FAIL
5082            || (rdlo = reg_required_here (& str, 12)) == FAIL)
5083     inst.error = BAD_ARGS;
5084
5085   else if (skip_past_comma (& str) == FAIL
5086            || (rdhi = reg_required_here (& str, 16)) == FAIL)
5087     inst.error = BAD_ARGS;
5088
5089   /* inst.instruction has now been zapped with both rdlo and rdhi.  */
5090   else if (rdlo == REG_PC || rdhi == REG_PC)
5091     inst.error = BAD_PC;        /* Undefined result if rdlo or rdhi is R15.  */
5092
5093   else
5094     end_of_line (str);
5095 }
5096
5097 /* Xscale move-register-accumulator (argument parse)
5098
5099      MRAcc   RdLo,RdHi,acc0.  */
5100
5101 static void
5102 do_xsc_mra (str)
5103      char * str;
5104 {
5105   int rdlo;
5106   int rdhi;
5107
5108   skip_whitespace (str);
5109
5110   if ((rdlo = reg_required_here (& str, 12)) == FAIL)
5111     inst.error = BAD_ARGS;
5112
5113   else if (skip_past_comma (& str) == FAIL
5114            || (rdhi = reg_required_here (& str, 16)) == FAIL)
5115     inst.error = BAD_ARGS;
5116
5117   else if  (skip_past_comma (& str) == FAIL
5118             || accum0_required_here (& str) == FAIL)
5119     inst.error = ERR_NO_ACCUM;
5120
5121   /* inst.instruction has now been zapped with both rdlo and rdhi.  */
5122   else if (rdlo == rdhi)
5123     inst.error = BAD_ARGS;      /* Undefined result if 2 writes to same reg.  */
5124
5125   else if (rdlo == REG_PC || rdhi == REG_PC)
5126     inst.error = BAD_PC;        /* Undefined result if rdlo or rdhi is R15.  */
5127   else
5128     end_of_line (str);
5129 }
5130
5131 /* ARMv5TE: Preload-Cache
5132
5133     PLD <addr_mode>
5134
5135   Syntactically, like LDR with B=1, W=0, L=1.  */
5136
5137 static void
5138 do_pld (str)
5139      char * str;
5140 {
5141   int rd;
5142
5143   skip_whitespace (str);
5144
5145   if (* str != '[')
5146     {
5147       inst.error = _("'[' expected after PLD mnemonic");
5148       return;
5149     }
5150
5151   ++str;
5152   skip_whitespace (str);
5153
5154   if ((rd = reg_required_here (& str, 16)) == FAIL)
5155     return;
5156
5157   skip_whitespace (str);
5158
5159   if (*str == ']')
5160     {
5161       /* [Rn], ... ?  */
5162       ++str;
5163       skip_whitespace (str);
5164
5165       /* Post-indexed addressing is not allowed with PLD.  */
5166       if (skip_past_comma (&str) == SUCCESS)
5167         {
5168           inst.error
5169             = _("post-indexed expression used in preload instruction");
5170           return;
5171         }
5172       else if (*str == '!') /* [Rn]! */
5173         {
5174           inst.error = _("writeback used in preload instruction");
5175           ++str;
5176         }
5177       else /* [Rn] */
5178         inst.instruction |= INDEX_UP | PRE_INDEX;
5179     }
5180   else /* [Rn, ...] */
5181     {
5182       if (skip_past_comma (& str) == FAIL)
5183         {
5184           inst.error = _("pre-indexed expression expected");
5185           return;
5186         }
5187
5188       if (ldst_extend (&str) == FAIL)
5189         return;
5190
5191       skip_whitespace (str);
5192
5193       if (* str != ']')
5194         {
5195           inst.error = _("missing ]");
5196           return;
5197         }
5198
5199       ++ str;
5200       skip_whitespace (str);
5201
5202       if (* str == '!') /* [Rn]! */
5203         {
5204           inst.error = _("writeback used in preload instruction");
5205           ++ str;
5206         }
5207
5208       inst.instruction |= PRE_INDEX;
5209     }
5210
5211   end_of_line (str);
5212 }
5213
5214 /* ARMv5TE load-consecutive (argument parse)
5215    Mode is like LDRH.
5216
5217      LDRccD R, mode
5218      STRccD R, mode.  */
5219
5220 static void
5221 do_ldrd (str)
5222      char * str;
5223 {
5224   int rd;
5225   int rn;
5226
5227   skip_whitespace (str);
5228
5229   if ((rd = reg_required_here (& str, 12)) == FAIL)
5230     {
5231       inst.error = BAD_ARGS;
5232       return;
5233     }
5234
5235   if (skip_past_comma (& str) == FAIL
5236       || (rn = ld_mode_required_here (& str)) == FAIL)
5237     {
5238       if (!inst.error)
5239         inst.error = BAD_ARGS;
5240       return;
5241     }
5242
5243   /* inst.instruction has now been zapped with Rd and the addressing mode.  */
5244   if (rd & 1)           /* Unpredictable result if Rd is odd.  */
5245     {
5246       inst.error = _("destination register must be even");
5247       return;
5248     }
5249
5250   if (rd == REG_LR)
5251     {
5252       inst.error = _("r14 not allowed here");
5253       return;
5254     }
5255
5256   if (((rd == rn) || (rd + 1 == rn))
5257       && ((inst.instruction & WRITE_BACK)
5258           || (!(inst.instruction & PRE_INDEX))))
5259     as_warn (_("pre/post-indexing used when modified address register is destination"));
5260
5261   /* For an index-register load, the index register must not overlap the
5262      destination (even if not write-back).  */
5263   if ((inst.instruction & V4_STR_BIT) == 0
5264       && (inst.instruction & HWOFFSET_IMM) == 0)
5265     {
5266       int rm = inst.instruction & 0x0000000f;
5267
5268       if (rm == rd || (rm == rd + 1))
5269         as_warn (_("ldrd destination registers must not overlap index register"));
5270     }
5271
5272   end_of_line (str);
5273 }
5274
5275 /* Returns the index into fp_values of a floating point number,
5276    or -1 if not in the table.  */
5277
5278 static int
5279 my_get_float_expression (str)
5280      char ** str;
5281 {
5282   LITTLENUM_TYPE words[MAX_LITTLENUMS];
5283   char *         save_in;
5284   expressionS    exp;
5285   int            i;
5286   int            j;
5287
5288   memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
5289
5290   /* Look for a raw floating point number.  */
5291   if ((save_in = atof_ieee (*str, 'x', words)) != NULL
5292       && is_end_of_line[(unsigned char) *save_in])
5293     {
5294       for (i = 0; i < NUM_FLOAT_VALS; i++)
5295         {
5296           for (j = 0; j < MAX_LITTLENUMS; j++)
5297             {
5298               if (words[j] != fp_values[i][j])
5299                 break;
5300             }
5301
5302           if (j == MAX_LITTLENUMS)
5303             {
5304               *str = save_in;
5305               return i;
5306             }
5307         }
5308     }
5309
5310   /* Try and parse a more complex expression, this will probably fail
5311      unless the code uses a floating point prefix (eg "0f").  */
5312   save_in = input_line_pointer;
5313   input_line_pointer = *str;
5314   if (expression (&exp) == absolute_section
5315       && exp.X_op == O_big
5316       && exp.X_add_number < 0)
5317     {
5318       /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5319          Ditto for 15.  */
5320       if (gen_to_words (words, 5, (long) 15) == 0)
5321         {
5322           for (i = 0; i < NUM_FLOAT_VALS; i++)
5323             {
5324               for (j = 0; j < MAX_LITTLENUMS; j++)
5325                 {
5326                   if (words[j] != fp_values[i][j])
5327                     break;
5328                 }
5329
5330               if (j == MAX_LITTLENUMS)
5331                 {
5332                   *str = input_line_pointer;
5333                   input_line_pointer = save_in;
5334                   return i;
5335                 }
5336             }
5337         }
5338     }
5339
5340   *str = input_line_pointer;
5341   input_line_pointer = save_in;
5342   return -1;
5343 }
5344
5345 /* Return TRUE if anything in the expression is a bignum.  */
5346
5347 static int
5348 walk_no_bignums (sp)
5349      symbolS * sp;
5350 {
5351   if (symbol_get_value_expression (sp)->X_op == O_big)
5352     return 1;
5353
5354   if (symbol_get_value_expression (sp)->X_add_symbol)
5355     {
5356       return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
5357               || (symbol_get_value_expression (sp)->X_op_symbol
5358                   && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
5359     }
5360
5361   return 0;
5362 }
5363
5364 static int in_my_get_expression = 0;
5365
5366 static int
5367 my_get_expression (ep, str)
5368      expressionS * ep;
5369      char ** str;
5370 {
5371   char * save_in;
5372   segT   seg;
5373
5374   save_in = input_line_pointer;
5375   input_line_pointer = *str;
5376   in_my_get_expression = 1;
5377   seg = expression (ep);
5378   in_my_get_expression = 0;
5379
5380   if (ep->X_op == O_illegal)
5381     {
5382       /* We found a bad expression in md_operand().  */
5383       *str = input_line_pointer;
5384       input_line_pointer = save_in;
5385       return 1;
5386     }
5387
5388 #ifdef OBJ_AOUT
5389   if (seg != absolute_section
5390       && seg != text_section
5391       && seg != data_section
5392       && seg != bss_section
5393       && seg != undefined_section)
5394     {
5395       inst.error = _("bad_segment");
5396       *str = input_line_pointer;
5397       input_line_pointer = save_in;
5398       return 1;
5399     }
5400 #endif
5401
5402   /* Get rid of any bignums now, so that we don't generate an error for which
5403      we can't establish a line number later on.  Big numbers are never valid
5404      in instructions, which is where this routine is always called.  */
5405   if (ep->X_op == O_big
5406       || (ep->X_add_symbol
5407           && (walk_no_bignums (ep->X_add_symbol)
5408               || (ep->X_op_symbol
5409                   && walk_no_bignums (ep->X_op_symbol)))))
5410     {
5411       inst.error = _("invalid constant");
5412       *str = input_line_pointer;
5413       input_line_pointer = save_in;
5414       return 1;
5415     }
5416
5417   *str = input_line_pointer;
5418   input_line_pointer = save_in;
5419   return 0;
5420 }
5421
5422 /* We handle all bad expressions here, so that we can report the faulty
5423    instruction in the error message.  */
5424 void
5425 md_operand (expr)
5426      expressionS *expr;
5427 {
5428   if (in_my_get_expression)
5429     {
5430       expr->X_op = O_illegal;
5431       if (inst.error == NULL)
5432         inst.error = _("bad expression");
5433     }
5434 }
5435
5436 /* UNRESTRICT should be one if <shift> <register> is permitted for this
5437    instruction.  */
5438
5439 static int
5440 decode_shift (str, unrestrict)
5441      char ** str;
5442      int     unrestrict;
5443 {
5444   const struct asm_shift_name * shift;
5445   char * p;
5446   char   c;
5447
5448   skip_whitespace (* str);
5449
5450   for (p = * str; ISALPHA (* p); p ++)
5451     ;
5452
5453   if (p == * str)
5454     {
5455       inst.error = _("shift expression expected");
5456       return FAIL;
5457     }
5458
5459   c = * p;
5460   * p = '\0';
5461   shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
5462   * p = c;
5463
5464   if (shift == NULL)
5465     {
5466       inst.error = _("shift expression expected");
5467       return FAIL;
5468     }
5469
5470   assert (shift->properties->index == shift_properties[shift->properties->index].index);
5471
5472   if (shift->properties->index == SHIFT_RRX)
5473     {
5474       * str = p;
5475       inst.instruction |= shift->properties->bit_field;
5476       return SUCCESS;
5477     }
5478
5479   skip_whitespace (p);
5480
5481   if (unrestrict && reg_required_here (& p, 8) != FAIL)
5482     {
5483       inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
5484       * str = p;
5485       return SUCCESS;
5486     }
5487   else if (! is_immediate_prefix (* p))
5488     {
5489       inst.error = (unrestrict
5490                     ? _("shift requires register or #expression")
5491                     : _("shift requires #expression"));
5492       * str = p;
5493       return FAIL;
5494     }
5495
5496   inst.error = NULL;
5497   p ++;
5498
5499   if (my_get_expression (& inst.reloc.exp, & p))
5500     return FAIL;
5501
5502   /* Validate some simple #expressions.  */
5503   if (inst.reloc.exp.X_op == O_constant)
5504     {
5505       unsigned num = inst.reloc.exp.X_add_number;
5506
5507       /* Reject operations greater than 32.  */
5508       if (num > 32
5509           /* Reject a shift of 0 unless the mode allows it.  */
5510           || (num == 0 && shift->properties->allows_0 == 0)
5511           /* Reject a shift of 32 unless the mode allows it.  */
5512           || (num == 32 && shift->properties->allows_32 == 0)
5513           )
5514         {
5515           /* As a special case we allow a shift of zero for
5516              modes that do not support it to be recoded as an
5517              logical shift left of zero (ie nothing).  We warn
5518              about this though.  */
5519           if (num == 0)
5520             {
5521               as_warn (_("shift of 0 ignored."));
5522               shift = & shift_names[0];
5523               assert (shift->properties->index == SHIFT_LSL);
5524             }
5525           else
5526             {
5527               inst.error = _("invalid immediate shift");
5528               return FAIL;
5529             }
5530         }
5531
5532       /* Shifts of 32 are encoded as 0, for those shifts that
5533          support it.  */
5534       if (num == 32)
5535         num = 0;
5536
5537       inst.instruction |= (num << 7) | shift->properties->bit_field;
5538     }
5539   else
5540     {
5541       inst.reloc.type   = BFD_RELOC_ARM_SHIFT_IMM;
5542       inst.reloc.pc_rel = 0;
5543       inst.instruction |= shift->properties->bit_field;
5544     }
5545
5546   * str = p;
5547   return SUCCESS;
5548 }
5549
5550 /* Do those data_ops which can take a negative immediate constant
5551    by altering the instuction.  A bit of a hack really.
5552         MOV <-> MVN
5553         AND <-> BIC
5554         ADC <-> SBC
5555         by inverting the second operand, and
5556         ADD <-> SUB
5557         CMP <-> CMN
5558         by negating the second operand.  */
5559
5560 static int
5561 negate_data_op (instruction, value)
5562      unsigned long * instruction;
5563      unsigned long   value;
5564 {
5565   int op, new_inst;
5566   unsigned long negated, inverted;
5567
5568   negated = validate_immediate (-value);
5569   inverted = validate_immediate (~value);
5570
5571   op = (*instruction >> DATA_OP_SHIFT) & 0xf;
5572   switch (op)
5573     {
5574       /* First negates.  */
5575     case OPCODE_SUB:             /* ADD <-> SUB  */
5576       new_inst = OPCODE_ADD;
5577       value = negated;
5578       break;
5579
5580     case OPCODE_ADD:
5581       new_inst = OPCODE_SUB;
5582       value = negated;
5583       break;
5584
5585     case OPCODE_CMP:             /* CMP <-> CMN  */
5586       new_inst = OPCODE_CMN;
5587       value = negated;
5588       break;
5589
5590     case OPCODE_CMN:
5591       new_inst = OPCODE_CMP;
5592       value = negated;
5593       break;
5594
5595       /* Now Inverted ops.  */
5596     case OPCODE_MOV:             /* MOV <-> MVN  */
5597       new_inst = OPCODE_MVN;
5598       value = inverted;
5599       break;
5600
5601     case OPCODE_MVN:
5602       new_inst = OPCODE_MOV;
5603       value = inverted;
5604       break;
5605
5606     case OPCODE_AND:             /* AND <-> BIC  */
5607       new_inst = OPCODE_BIC;
5608       value = inverted;
5609       break;
5610
5611     case OPCODE_BIC:
5612       new_inst = OPCODE_AND;
5613       value = inverted;
5614       break;
5615
5616     case OPCODE_ADC:              /* ADC <-> SBC  */
5617       new_inst = OPCODE_SBC;
5618       value = inverted;
5619       break;
5620
5621     case OPCODE_SBC:
5622       new_inst = OPCODE_ADC;
5623       value = inverted;
5624       break;
5625
5626       /* We cannot do anything.  */
5627     default:
5628       return FAIL;
5629     }
5630
5631   if (value == (unsigned) FAIL)
5632     return FAIL;
5633
5634   *instruction &= OPCODE_MASK;
5635   *instruction |= new_inst << DATA_OP_SHIFT;
5636   return value;
5637 }
5638
5639 static int
5640 data_op2 (str)
5641      char ** str;
5642 {
5643   int value;
5644   expressionS expr;
5645
5646   skip_whitespace (* str);
5647
5648   if (reg_required_here (str, 0) != FAIL)
5649     {
5650       if (skip_past_comma (str) == SUCCESS)
5651         /* Shift operation on register.  */
5652         return decode_shift (str, NO_SHIFT_RESTRICT);
5653
5654       return SUCCESS;
5655     }
5656   else
5657     {
5658       /* Immediate expression.  */
5659       if (is_immediate_prefix (**str))
5660         {
5661           (*str)++;
5662           inst.error = NULL;
5663
5664           if (my_get_expression (&inst.reloc.exp, str))
5665             return FAIL;
5666
5667           if (inst.reloc.exp.X_add_symbol)
5668             {
5669               inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
5670               inst.reloc.pc_rel = 0;
5671             }
5672           else
5673             {
5674               if (skip_past_comma (str) == SUCCESS)
5675                 {
5676                   /* #x, y -- ie explicit rotation by Y.  */
5677                   if (my_get_expression (&expr, str))
5678                     return FAIL;
5679
5680                   if (expr.X_op != O_constant)
5681                     {
5682                       inst.error = _("constant expression expected");
5683                       return FAIL;
5684                     }
5685
5686                   /* Rotate must be a multiple of 2.  */
5687                   if (((unsigned) expr.X_add_number) > 30
5688                       || (expr.X_add_number & 1) != 0
5689                       || ((unsigned) inst.reloc.exp.X_add_number) > 255)
5690                     {
5691                       inst.error = _("invalid constant");
5692                       return FAIL;
5693                     }
5694                   inst.instruction |= INST_IMMEDIATE;
5695                   inst.instruction |= inst.reloc.exp.X_add_number;
5696                   inst.instruction |= expr.X_add_number << 7;
5697                   return SUCCESS;
5698                 }
5699
5700               /* Implicit rotation, select a suitable one.  */
5701               value = validate_immediate (inst.reloc.exp.X_add_number);
5702
5703               if (value == FAIL)
5704                 {
5705                   /* Can't be done.  Perhaps the code reads something like
5706                      "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK.  */
5707                   if ((value = negate_data_op (&inst.instruction,
5708                                                inst.reloc.exp.X_add_number))
5709                       == FAIL)
5710                     {
5711                       inst.error = _("invalid constant");
5712                       return FAIL;
5713                     }
5714                 }
5715
5716               inst.instruction |= value;
5717             }
5718
5719           inst.instruction |= INST_IMMEDIATE;
5720           return SUCCESS;
5721         }
5722
5723       (*str)++;
5724       inst.error = _("register or shift expression expected");
5725       return FAIL;
5726     }
5727 }
5728
5729 static int
5730 fp_op2 (str)
5731      char ** str;
5732 {
5733   skip_whitespace (* str);
5734
5735   if (fp_reg_required_here (str, 0) != FAIL)
5736     return SUCCESS;
5737   else
5738     {
5739       /* Immediate expression.  */
5740       if (*((*str)++) == '#')
5741         {
5742           int i;
5743
5744           inst.error = NULL;
5745
5746           skip_whitespace (* str);
5747
5748           /* First try and match exact strings, this is to guarantee
5749              that some formats will work even for cross assembly.  */
5750
5751           for (i = 0; fp_const[i]; i++)
5752             {
5753               if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
5754                 {
5755                   char *start = *str;
5756
5757                   *str += strlen (fp_const[i]);
5758                   if (is_end_of_line[(unsigned char) **str])
5759                     {
5760                       inst.instruction |= i + 8;
5761                       return SUCCESS;
5762                     }
5763                   *str = start;
5764                 }
5765             }
5766
5767           /* Just because we didn't get a match doesn't mean that the
5768              constant isn't valid, just that it is in a format that we
5769              don't automatically recognize.  Try parsing it with
5770              the standard expression routines.  */
5771           if ((i = my_get_float_expression (str)) >= 0)
5772             {
5773               inst.instruction |= i + 8;
5774               return SUCCESS;
5775             }
5776
5777           inst.error = _("invalid floating point immediate expression");
5778           return FAIL;
5779         }
5780       inst.error =
5781         _("floating point register or immediate expression expected");
5782       return FAIL;
5783     }
5784 }
5785
5786 static void
5787 do_arit (str)
5788      char * str;
5789 {
5790   skip_whitespace (str);
5791
5792   if (reg_required_here (&str, 12) == FAIL
5793       || skip_past_comma (&str) == FAIL
5794       || reg_required_here (&str, 16) == FAIL
5795       || skip_past_comma (&str) == FAIL
5796       || data_op2 (&str) == FAIL)
5797     {
5798       if (!inst.error)
5799         inst.error = BAD_ARGS;
5800       return;
5801     }
5802
5803   end_of_line (str);
5804   return;
5805 }
5806
5807 static void
5808 do_adr (str)
5809      char * str;
5810 {
5811   /* This is a pseudo-op of the form "adr rd, label" to be converted
5812      into a relative address of the form "add rd, pc, #label-.-8".  */
5813   skip_whitespace (str);
5814
5815   if (reg_required_here (&str, 12) == FAIL
5816       || skip_past_comma (&str) == FAIL
5817       || my_get_expression (&inst.reloc.exp, &str))
5818     {
5819       if (!inst.error)
5820         inst.error = BAD_ARGS;
5821       return;
5822     }
5823
5824   /* Frag hacking will turn this into a sub instruction if the offset turns
5825      out to be negative.  */
5826   inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
5827   inst.reloc.exp.X_add_number -= 8; /* PC relative adjust.  */
5828   inst.reloc.pc_rel = 1;
5829
5830   end_of_line (str);
5831 }
5832
5833 static void
5834 do_adrl (str)
5835      char * str;
5836 {
5837   /* This is a pseudo-op of the form "adrl rd, label" to be converted
5838      into a relative address of the form:
5839      add rd, pc, #low(label-.-8)"
5840      add rd, rd, #high(label-.-8)"  */
5841
5842   skip_whitespace (str);
5843
5844   if (reg_required_here (&str, 12) == FAIL
5845       || skip_past_comma (&str) == FAIL
5846       || my_get_expression (&inst.reloc.exp, &str))
5847     {
5848       if (!inst.error)
5849         inst.error = BAD_ARGS;
5850
5851       return;
5852     }
5853
5854   end_of_line (str);
5855   /* Frag hacking will turn this into a sub instruction if the offset turns
5856      out to be negative.  */
5857   inst.reloc.type              = BFD_RELOC_ARM_ADRL_IMMEDIATE;
5858   inst.reloc.exp.X_add_number -= 8; /* PC relative adjust  */
5859   inst.reloc.pc_rel            = 1;
5860   inst.size                    = INSN_SIZE * 2;
5861
5862   return;
5863 }
5864
5865 static void
5866 do_cmp (str)
5867      char * str;
5868 {
5869   skip_whitespace (str);
5870
5871   if (reg_required_here (&str, 16) == FAIL)
5872     {
5873       if (!inst.error)
5874         inst.error = BAD_ARGS;
5875       return;
5876     }
5877
5878   if (skip_past_comma (&str) == FAIL
5879       || data_op2 (&str) == FAIL)
5880     {
5881       if (!inst.error)
5882         inst.error = BAD_ARGS;
5883       return;
5884     }
5885
5886   end_of_line (str);
5887   return;
5888 }
5889
5890 static void
5891 do_mov (str)
5892      char * str;
5893 {
5894   skip_whitespace (str);
5895
5896   if (reg_required_here (&str, 12) == FAIL)
5897     {
5898       if (!inst.error)
5899         inst.error = BAD_ARGS;
5900       return;
5901     }
5902
5903   if (skip_past_comma (&str) == FAIL
5904       || data_op2 (&str) == FAIL)
5905     {
5906       if (!inst.error)
5907         inst.error = BAD_ARGS;
5908       return;
5909     }
5910
5911   end_of_line (str);
5912   return;
5913 }
5914
5915 static int
5916 ldst_extend (str)
5917      char ** str;
5918 {
5919   int add = INDEX_UP;
5920
5921   switch (**str)
5922     {
5923     case '#':
5924     case '$':
5925       (*str)++;
5926       if (my_get_expression (& inst.reloc.exp, str))
5927         return FAIL;
5928
5929       if (inst.reloc.exp.X_op == O_constant)
5930         {
5931           int value = inst.reloc.exp.X_add_number;
5932
5933           if (value < -4095 || value > 4095)
5934             {
5935               inst.error = _("address offset too large");
5936               return FAIL;
5937             }
5938
5939           if (value < 0)
5940             {
5941               value = -value;
5942               add = 0;
5943             }
5944
5945           inst.instruction |= add | value;
5946         }
5947       else
5948         {
5949           inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
5950           inst.reloc.pc_rel = 0;
5951         }
5952       return SUCCESS;
5953
5954     case '-':
5955       add = 0;
5956       /* Fall through.  */
5957
5958     case '+':
5959       (*str)++;
5960       /* Fall through.  */
5961
5962     default:
5963       if (reg_required_here (str, 0) == FAIL)
5964         return FAIL;
5965
5966       inst.instruction |= add | OFFSET_REG;
5967       if (skip_past_comma (str) == SUCCESS)
5968         return decode_shift (str, SHIFT_RESTRICT);
5969
5970       return SUCCESS;
5971     }
5972 }
5973
5974 static void
5975 do_ldst (str)
5976      char *        str;
5977 {
5978   int pre_inc = 0;
5979   int conflict_reg;
5980   int value;
5981
5982   skip_whitespace (str);
5983
5984   if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
5985     {
5986       if (!inst.error)
5987         inst.error = BAD_ARGS;
5988       return;
5989     }
5990
5991   if (skip_past_comma (&str) == FAIL)
5992     {
5993       inst.error = _("address expected");
5994       return;
5995     }
5996
5997   if (*str == '[')
5998     {
5999       int reg;
6000
6001       str++;
6002
6003       skip_whitespace (str);
6004
6005       if ((reg = reg_required_here (&str, 16)) == FAIL)
6006         return;
6007
6008       /* Conflicts can occur on stores as well as loads.  */
6009       conflict_reg = (conflict_reg == reg);
6010
6011       skip_whitespace (str);
6012
6013       if (*str == ']')
6014         {
6015           str ++;
6016
6017           if (skip_past_comma (&str) == SUCCESS)
6018             {
6019               /* [Rn],... (post inc)  */
6020               if (ldst_extend (&str) == FAIL)
6021                 return;
6022               if (conflict_reg)
6023                 as_warn (_("%s register same as write-back base"),
6024                          ((inst.instruction & LOAD_BIT)
6025                           ? _("destination") : _("source")));
6026             }
6027           else
6028             {
6029               /* [Rn]  */
6030               skip_whitespace (str);
6031
6032               if (*str == '!')
6033                 {
6034                   if (conflict_reg)
6035                     as_warn (_("%s register same as write-back base"),
6036                              ((inst.instruction & LOAD_BIT)
6037                               ? _("destination") : _("source")));
6038                   str++;
6039                   inst.instruction |= WRITE_BACK;
6040                 }
6041
6042               inst.instruction |= INDEX_UP;
6043               pre_inc = 1;
6044             }
6045         }
6046       else
6047         {
6048           /* [Rn,...]  */
6049           if (skip_past_comma (&str) == FAIL)
6050             {
6051               inst.error = _("pre-indexed expression expected");
6052               return;
6053             }
6054
6055           pre_inc = 1;
6056           if (ldst_extend (&str) == FAIL)
6057             return;
6058
6059           skip_whitespace (str);
6060
6061           if (*str++ != ']')
6062             {
6063               inst.error = _("missing ]");
6064               return;
6065             }
6066
6067           skip_whitespace (str);
6068
6069           if (*str == '!')
6070             {
6071               if (conflict_reg)
6072                 as_warn (_("%s register same as write-back base"),
6073                          ((inst.instruction & LOAD_BIT)
6074                           ? _("destination") : _("source")));
6075               str++;
6076               inst.instruction |= WRITE_BACK;
6077             }
6078         }
6079     }
6080   else if (*str == '=')
6081     {
6082       if ((inst.instruction & LOAD_BIT) == 0)
6083         {
6084           inst.error = _("invalid pseudo operation");
6085           return;
6086         }
6087
6088       /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op.  */
6089       str++;
6090
6091       skip_whitespace (str);
6092
6093       if (my_get_expression (&inst.reloc.exp, &str))
6094         return;
6095
6096       if (inst.reloc.exp.X_op != O_constant
6097           && inst.reloc.exp.X_op != O_symbol)
6098         {
6099           inst.error = _("constant expression expected");
6100           return;
6101         }
6102
6103       if (inst.reloc.exp.X_op == O_constant)
6104         {
6105           value = validate_immediate (inst.reloc.exp.X_add_number);
6106
6107           if (value != FAIL)
6108             {
6109               /* This can be done with a mov instruction.  */
6110               inst.instruction &= LITERAL_MASK;
6111               inst.instruction |= (INST_IMMEDIATE
6112                                    | (OPCODE_MOV << DATA_OP_SHIFT));
6113               inst.instruction |= value & 0xfff;
6114               end_of_line (str);
6115               return;
6116             }
6117
6118           value = validate_immediate (~inst.reloc.exp.X_add_number);
6119
6120           if (value != FAIL)
6121             {
6122               /* This can be done with a mvn instruction.  */
6123               inst.instruction &= LITERAL_MASK;
6124               inst.instruction |= (INST_IMMEDIATE
6125                                    | (OPCODE_MVN << DATA_OP_SHIFT));
6126               inst.instruction |= value & 0xfff;
6127               end_of_line (str);
6128               return;
6129             }
6130         }
6131
6132       /* Insert into literal pool.  */
6133       if (add_to_lit_pool () == FAIL)
6134         {
6135           if (!inst.error)
6136             inst.error = _("literal pool insertion failed");
6137           return;
6138         }
6139
6140       /* Change the instruction exp to point to the pool.  */
6141       inst.reloc.type = BFD_RELOC_ARM_LITERAL;
6142       inst.reloc.pc_rel = 1;
6143       inst.instruction |= (REG_PC << 16);
6144       pre_inc = 1;
6145     }
6146   else
6147     {
6148       if (my_get_expression (&inst.reloc.exp, &str))
6149         return;
6150
6151       inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
6152 #ifndef TE_WINCE
6153       /* PC rel adjust.  */
6154       inst.reloc.exp.X_add_number -= 8;
6155 #endif
6156       inst.reloc.pc_rel = 1;
6157       inst.instruction |= (REG_PC << 16);
6158       pre_inc = 1;
6159     }
6160
6161   inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6162   end_of_line (str);
6163   return;
6164 }
6165
6166 static void
6167 do_ldstt (str)
6168      char *        str;
6169 {
6170   int conflict_reg;
6171
6172   skip_whitespace (str);
6173
6174   if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6175     {
6176       if (!inst.error)
6177         inst.error = BAD_ARGS;
6178       return;
6179     }
6180
6181   if (skip_past_comma (& str) == FAIL)
6182     {
6183       inst.error = _("address expected");
6184       return;
6185     }
6186
6187   if (*str == '[')
6188     {
6189       int reg;
6190
6191       str++;
6192
6193       skip_whitespace (str);
6194
6195       if ((reg = reg_required_here (&str, 16)) == FAIL)
6196         return;
6197
6198       /* ldrt/strt always use post-indexed addressing, so if the base is
6199          the same as Rd, we warn.  */
6200       if (conflict_reg == reg)
6201         as_warn (_("%s register same as write-back base"),
6202                  ((inst.instruction & LOAD_BIT)
6203                   ? _("destination") : _("source")));
6204
6205       skip_whitespace (str);
6206
6207       if (*str == ']')
6208         {
6209           str ++;
6210
6211           if (skip_past_comma (&str) == SUCCESS)
6212             {
6213               /* [Rn],... (post inc)  */
6214               if (ldst_extend (&str) == FAIL)
6215                 return;
6216             }
6217           else
6218             {
6219               /* [Rn]  */
6220               skip_whitespace (str);
6221
6222               /* Skip a write-back '!'.  */
6223               if (*str == '!')
6224                 str++;
6225
6226               inst.instruction |= INDEX_UP;
6227             }
6228         }
6229       else
6230         {
6231           inst.error = _("post-indexed expression expected");
6232           return;
6233         }
6234     }
6235   else
6236     {
6237       inst.error = _("post-indexed expression expected");
6238       return;
6239     }
6240
6241   end_of_line (str);
6242   return;
6243 }
6244
6245 static int
6246 ldst_extend_v4 (str)
6247      char ** str;
6248 {
6249   int add = INDEX_UP;
6250
6251   switch (**str)
6252     {
6253     case '#':
6254     case '$':
6255       (*str)++;
6256       if (my_get_expression (& inst.reloc.exp, str))
6257         return FAIL;
6258
6259       if (inst.reloc.exp.X_op == O_constant)
6260         {
6261           int value = inst.reloc.exp.X_add_number;
6262
6263           if (value < -255 || value > 255)
6264             {
6265               inst.error = _("address offset too large");
6266               return FAIL;
6267             }
6268
6269           if (value < 0)
6270             {
6271               value = -value;
6272               add = 0;
6273             }
6274
6275           /* Halfword and signextension instructions have the
6276              immediate value split across bits 11..8 and bits 3..0.  */
6277           inst.instruction |= (add | HWOFFSET_IMM
6278                                | ((value >> 4) << 8) | (value & 0xF));
6279         }
6280       else
6281         {
6282           inst.instruction |= HWOFFSET_IMM;
6283           inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
6284           inst.reloc.pc_rel = 0;
6285         }
6286       return SUCCESS;
6287
6288     case '-':
6289       add = 0;
6290       /* Fall through.  */
6291
6292     case '+':
6293       (*str)++;
6294       /* Fall through.  */
6295
6296     default:
6297       if (reg_required_here (str, 0) == FAIL)
6298         return FAIL;
6299
6300       inst.instruction |= add;
6301       return SUCCESS;
6302     }
6303 }
6304
6305 /* Halfword and signed-byte load/store operations.  */
6306 static void
6307 do_ldstv4 (str)
6308      char *        str;
6309 {
6310   int pre_inc = 0;
6311   int conflict_reg;
6312   int value;
6313
6314   skip_whitespace (str);
6315
6316   if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6317     {
6318       if (!inst.error)
6319         inst.error = BAD_ARGS;
6320       return;
6321     }
6322
6323   if (skip_past_comma (& str) == FAIL)
6324     {
6325       inst.error = _("address expected");
6326       return;
6327     }
6328
6329   if (*str == '[')
6330     {
6331       int reg;
6332
6333       str++;
6334
6335       skip_whitespace (str);
6336
6337       if ((reg = reg_required_here (&str, 16)) == FAIL)
6338         return;
6339
6340       /* Conflicts can occur on stores as well as loads.  */
6341       conflict_reg = (conflict_reg == reg);
6342
6343       skip_whitespace (str);
6344
6345       if (*str == ']')
6346         {
6347           str ++;
6348
6349           if (skip_past_comma (&str) == SUCCESS)
6350             {
6351               /* [Rn],... (post inc)  */
6352               if (ldst_extend_v4 (&str) == FAIL)
6353                 return;
6354               if (conflict_reg)
6355                 as_warn (_("%s register same as write-back base"),
6356                          ((inst.instruction & LOAD_BIT)
6357                           ? _("destination") : _("source")));
6358             }
6359           else
6360             {
6361               /* [Rn]  */
6362               inst.instruction |= HWOFFSET_IMM;
6363
6364               skip_whitespace (str);
6365
6366               if (*str == '!')
6367                 {
6368                   if (conflict_reg)
6369                     as_warn (_("%s register same as write-back base"),
6370                              ((inst.instruction & LOAD_BIT)
6371                               ? _("destination") : _("source")));
6372                   str++;
6373                   inst.instruction |= WRITE_BACK;
6374                 }
6375
6376               inst.instruction |= INDEX_UP;
6377               pre_inc = 1;
6378             }
6379         }
6380       else
6381         {
6382           /* [Rn,...]  */
6383           if (skip_past_comma (&str) == FAIL)
6384             {
6385               inst.error = _("pre-indexed expression expected");
6386               return;
6387             }
6388
6389           pre_inc = 1;
6390           if (ldst_extend_v4 (&str) == FAIL)
6391             return;
6392
6393           skip_whitespace (str);
6394
6395           if (*str++ != ']')
6396             {
6397               inst.error = _("missing ]");
6398               return;
6399             }
6400
6401           skip_whitespace (str);
6402
6403           if (*str == '!')
6404             {
6405               if (conflict_reg)
6406                 as_warn (_("%s register same as write-back base"),
6407                          ((inst.instruction & LOAD_BIT)
6408                           ? _("destination") : _("source")));
6409               str++;
6410               inst.instruction |= WRITE_BACK;
6411             }
6412         }
6413     }
6414   else if (*str == '=')
6415     {
6416       if ((inst.instruction & LOAD_BIT) == 0)
6417         {
6418           inst.error = _("invalid pseudo operation");
6419           return;
6420         }
6421
6422       /* XXX Does this work correctly for half-word/byte ops?  */
6423       /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op.  */
6424       str++;
6425
6426       skip_whitespace (str);
6427
6428       if (my_get_expression (&inst.reloc.exp, &str))
6429         return;
6430
6431       if (inst.reloc.exp.X_op != O_constant
6432           && inst.reloc.exp.X_op != O_symbol)
6433         {
6434           inst.error = _("constant expression expected");
6435           return;
6436         }
6437
6438       if (inst.reloc.exp.X_op == O_constant)
6439         {
6440           value = validate_immediate (inst.reloc.exp.X_add_number);
6441
6442           if (value != FAIL)
6443             {
6444               /* This can be done with a mov instruction.  */
6445               inst.instruction &= LITERAL_MASK;
6446               inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
6447               inst.instruction |= value & 0xfff;
6448               end_of_line (str);
6449               return;
6450             }
6451
6452           value = validate_immediate (~ inst.reloc.exp.X_add_number);
6453
6454           if (value != FAIL)
6455             {
6456               /* This can be done with a mvn instruction.  */
6457               inst.instruction &= LITERAL_MASK;
6458               inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
6459               inst.instruction |= value & 0xfff;
6460               end_of_line (str);
6461               return;
6462             }
6463         }
6464
6465       /* Insert into literal pool.  */
6466       if (add_to_lit_pool () == FAIL)
6467         {
6468           if (!inst.error)
6469             inst.error = _("literal pool insertion failed");
6470           return;
6471         }
6472
6473       /* Change the instruction exp to point to the pool.  */
6474       inst.instruction |= HWOFFSET_IMM;
6475       inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
6476       inst.reloc.pc_rel = 1;
6477       inst.instruction |= (REG_PC << 16);
6478       pre_inc = 1;
6479     }
6480   else
6481     {
6482       if (my_get_expression (&inst.reloc.exp, &str))
6483         return;
6484
6485       inst.instruction |= HWOFFSET_IMM;
6486       inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
6487 #ifndef TE_WINCE
6488       /* PC rel adjust.  */
6489       inst.reloc.exp.X_add_number -= 8;
6490 #endif
6491       inst.reloc.pc_rel = 1;
6492       inst.instruction |= (REG_PC << 16);
6493       pre_inc = 1;
6494     }
6495
6496   inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6497   end_of_line (str);
6498   return;
6499 }
6500
6501 static long
6502 reg_list (strp)
6503      char ** strp;
6504 {
6505   char * str = * strp;
6506   long   range = 0;
6507   int    another_range;
6508
6509   /* We come back here if we get ranges concatenated by '+' or '|'.  */
6510   do
6511     {
6512       another_range = 0;
6513
6514       if (*str == '{')
6515         {
6516           int in_range = 0;
6517           int cur_reg = -1;
6518
6519           str++;
6520           do
6521             {
6522               int reg;
6523
6524               skip_whitespace (str);
6525
6526               if ((reg = reg_required_here (& str, -1)) == FAIL)
6527                 return FAIL;
6528
6529               if (in_range)
6530                 {
6531                   int i;
6532
6533                   if (reg <= cur_reg)
6534                     {
6535                       inst.error = _("bad range in register list");
6536                       return FAIL;
6537                     }
6538
6539                   for (i = cur_reg + 1; i < reg; i++)
6540                     {
6541                       if (range & (1 << i))
6542                         as_tsktsk
6543                           (_("Warning: duplicated register (r%d) in register list"),
6544                            i);
6545                       else
6546                         range |= 1 << i;
6547                     }
6548                   in_range = 0;
6549                 }
6550
6551               if (range & (1 << reg))
6552                 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6553                            reg);
6554               else if (reg <= cur_reg)
6555                 as_tsktsk (_("Warning: register range not in ascending order"));
6556
6557               range |= 1 << reg;
6558               cur_reg = reg;
6559             }
6560           while (skip_past_comma (&str) != FAIL
6561                  || (in_range = 1, *str++ == '-'));
6562           str--;
6563           skip_whitespace (str);
6564
6565           if (*str++ != '}')
6566             {
6567               inst.error = _("missing `}'");
6568               return FAIL;
6569             }
6570         }
6571       else
6572         {
6573           expressionS expr;
6574
6575           if (my_get_expression (&expr, &str))
6576             return FAIL;
6577
6578           if (expr.X_op == O_constant)
6579             {
6580               if (expr.X_add_number
6581                   != (expr.X_add_number & 0x0000ffff))
6582                 {
6583                   inst.error = _("invalid register mask");
6584                   return FAIL;
6585                 }
6586
6587               if ((range & expr.X_add_number) != 0)
6588                 {
6589                   int regno = range & expr.X_add_number;
6590
6591                   regno &= -regno;
6592                   regno = (1 << regno) - 1;
6593                   as_tsktsk
6594                     (_("Warning: duplicated register (r%d) in register list"),
6595                      regno);
6596                 }
6597
6598               range |= expr.X_add_number;
6599             }
6600           else
6601             {
6602               if (inst.reloc.type != 0)
6603                 {
6604                   inst.error = _("expression too complex");
6605                   return FAIL;
6606                 }
6607
6608               memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
6609               inst.reloc.type = BFD_RELOC_ARM_MULTI;
6610               inst.reloc.pc_rel = 0;
6611             }
6612         }
6613
6614       skip_whitespace (str);
6615
6616       if (*str == '|' || *str == '+')
6617         {
6618           str++;
6619           another_range = 1;
6620         }
6621     }
6622   while (another_range);
6623
6624   *strp = str;
6625   return range;
6626 }
6627
6628 static void
6629 do_ldmstm (str)
6630      char * str;
6631 {
6632   int base_reg;
6633   long range;
6634
6635   skip_whitespace (str);
6636
6637   if ((base_reg = reg_required_here (&str, 16)) == FAIL)
6638     return;
6639
6640   if (base_reg == REG_PC)
6641     {
6642       inst.error = _("r15 not allowed as base register");
6643       return;
6644     }
6645
6646   skip_whitespace (str);
6647
6648   if (*str == '!')
6649     {
6650       inst.instruction |= WRITE_BACK;
6651       str++;
6652     }
6653
6654   if (skip_past_comma (&str) == FAIL
6655       || (range = reg_list (&str)) == FAIL)
6656     {
6657       if (! inst.error)
6658         inst.error = BAD_ARGS;
6659       return;
6660     }
6661
6662   if (*str == '^')
6663     {
6664       str++;
6665       inst.instruction |= LDM_TYPE_2_OR_3;
6666     }
6667
6668   if (inst.instruction & WRITE_BACK)
6669     {
6670       /* Check for unpredictable uses of writeback.  */
6671       if (inst.instruction & LOAD_BIT)
6672         {
6673           /* Not allowed in LDM type 2.  */
6674           if ((inst.instruction & LDM_TYPE_2_OR_3)
6675               && ((range & (1 << REG_PC)) == 0))
6676             as_warn (_("writeback of base register is UNPREDICTABLE"));
6677           /* Only allowed if base reg not in list for other types.  */
6678           else if (range & (1 << base_reg))
6679             as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
6680         }
6681       else /* STM.  */
6682         {
6683           /* Not allowed for type 2.  */
6684           if (inst.instruction & LDM_TYPE_2_OR_3)
6685             as_warn (_("writeback of base register is UNPREDICTABLE"));
6686           /* Only allowed if base reg not in list, or first in list.  */
6687           else if ((range & (1 << base_reg))
6688                    && (range & ((1 << base_reg) - 1)))
6689             as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
6690         }
6691     }
6692
6693   inst.instruction |= range;
6694   end_of_line (str);
6695   return;
6696 }
6697
6698 static void
6699 do_swi (str)
6700      char * str;
6701 {
6702   skip_whitespace (str);
6703
6704   /* Allow optional leading '#'.  */
6705   if (is_immediate_prefix (*str))
6706     str++;
6707
6708   if (my_get_expression (& inst.reloc.exp, & str))
6709     return;
6710
6711   inst.reloc.type = BFD_RELOC_ARM_SWI;
6712   inst.reloc.pc_rel = 0;
6713   end_of_line (str);
6714
6715   return;
6716 }
6717
6718 static void
6719 do_swap (str)
6720      char * str;
6721 {
6722   int reg;
6723
6724   skip_whitespace (str);
6725
6726   if ((reg = reg_required_here (&str, 12)) == FAIL)
6727     return;
6728
6729   if (reg == REG_PC)
6730     {
6731       inst.error = _("r15 not allowed in swap");
6732       return;
6733     }
6734
6735   if (skip_past_comma (&str) == FAIL
6736       || (reg = reg_required_here (&str, 0)) == FAIL)
6737     {
6738       if (!inst.error)
6739         inst.error = BAD_ARGS;
6740       return;
6741     }
6742
6743   if (reg == REG_PC)
6744     {
6745       inst.error = _("r15 not allowed in swap");
6746       return;
6747     }
6748
6749   if (skip_past_comma (&str) == FAIL
6750       || *str++ != '[')
6751     {
6752       inst.error = BAD_ARGS;
6753       return;
6754     }
6755
6756   skip_whitespace (str);
6757
6758   if ((reg = reg_required_here (&str, 16)) == FAIL)
6759     return;
6760
6761   if (reg == REG_PC)
6762     {
6763       inst.error = BAD_PC;
6764       return;
6765     }
6766
6767   skip_whitespace (str);
6768
6769   if (*str++ != ']')
6770     {
6771       inst.error = _("missing ]");
6772       return;
6773     }
6774
6775   end_of_line (str);
6776   return;
6777 }
6778
6779 static void
6780 do_branch (str)
6781      char * str;
6782 {
6783   if (my_get_expression (&inst.reloc.exp, &str))
6784     return;
6785
6786 #ifdef OBJ_ELF
6787   {
6788     char * save_in;
6789
6790     /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
6791        required for the instruction.  */
6792
6793     /* arm_parse_reloc () works on input_line_pointer.
6794        We actually want to parse the operands to the branch instruction
6795        passed in 'str'.  Save the input pointer and restore it later.  */
6796     save_in = input_line_pointer;
6797     input_line_pointer = str;
6798     if (inst.reloc.exp.X_op == O_symbol
6799         && *str == '('
6800         && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
6801       {
6802         inst.reloc.type   = BFD_RELOC_ARM_PLT32;
6803         inst.reloc.pc_rel = 0;
6804         /* Modify str to point to after parsed operands, otherwise
6805            end_of_line() will complain about the (PLT) left in str.  */
6806         str = input_line_pointer;
6807       }
6808     else
6809       {
6810         inst.reloc.type   = BFD_RELOC_ARM_PCREL_BRANCH;
6811         inst.reloc.pc_rel = 1;
6812       }
6813     input_line_pointer = save_in;
6814   }
6815 #else
6816   inst.reloc.type   = BFD_RELOC_ARM_PCREL_BRANCH;
6817   inst.reloc.pc_rel = 1;
6818 #endif /* OBJ_ELF  */
6819
6820   end_of_line (str);
6821   return;
6822 }
6823
6824 static void
6825 do_bx (str)
6826      char * str;
6827 {
6828   int reg;
6829
6830   skip_whitespace (str);
6831
6832   if ((reg = reg_required_here (&str, 0)) == FAIL)
6833     {
6834       inst.error = BAD_ARGS;
6835       return;
6836     }
6837
6838   /* Note - it is not illegal to do a "bx pc".  Useless, but not illegal.  */
6839   if (reg == REG_PC)
6840     as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
6841
6842   end_of_line (str);
6843 }
6844
6845 static void
6846 do_cdp (str)
6847      char * str;
6848 {
6849   /* Co-processor data operation.
6850      Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>}  */
6851   skip_whitespace (str);
6852
6853   if (co_proc_number (&str) == FAIL)
6854     {
6855       if (!inst.error)
6856         inst.error = BAD_ARGS;
6857       return;
6858     }
6859
6860   if (skip_past_comma (&str) == FAIL
6861       || cp_opc_expr (&str, 20,4) == FAIL)
6862     {
6863       if (!inst.error)
6864         inst.error = BAD_ARGS;
6865       return;
6866     }
6867
6868   if (skip_past_comma (&str) == FAIL
6869       || cp_reg_required_here (&str, 12) == FAIL)
6870     {
6871       if (!inst.error)
6872         inst.error = BAD_ARGS;
6873       return;
6874     }
6875
6876   if (skip_past_comma (&str) == FAIL
6877       || cp_reg_required_here (&str, 16) == FAIL)
6878     {
6879       if (!inst.error)
6880         inst.error = BAD_ARGS;
6881       return;
6882     }
6883
6884   if (skip_past_comma (&str) == FAIL
6885       || cp_reg_required_here (&str, 0) == FAIL)
6886     {
6887       if (!inst.error)
6888         inst.error = BAD_ARGS;
6889       return;
6890     }
6891
6892   if (skip_past_comma (&str) == SUCCESS)
6893     {
6894       if (cp_opc_expr (&str, 5, 3) == FAIL)
6895         {
6896           if (!inst.error)
6897             inst.error = BAD_ARGS;
6898           return;
6899         }
6900     }
6901
6902   end_of_line (str);
6903   return;
6904 }
6905
6906 static void
6907 do_lstc (str)
6908      char * str;
6909 {
6910   /* Co-processor register load/store.
6911      Format: <LDC|STC{cond}[L] CP#,CRd,<address>  */
6912
6913   skip_whitespace (str);
6914
6915   if (co_proc_number (&str) == FAIL)
6916     {
6917       if (!inst.error)
6918         inst.error = BAD_ARGS;
6919       return;
6920     }
6921
6922   if (skip_past_comma (&str) == FAIL
6923       || cp_reg_required_here (&str, 12) == FAIL)
6924     {
6925       if (!inst.error)
6926         inst.error = BAD_ARGS;
6927       return;
6928     }
6929
6930   if (skip_past_comma (&str) == FAIL
6931       || cp_address_required_here (&str, CP_WB_OK) == FAIL)
6932     {
6933       if (! inst.error)
6934         inst.error = BAD_ARGS;
6935       return;
6936     }
6937
6938   end_of_line (str);
6939   return;
6940 }
6941
6942 static void
6943 do_co_reg (str)
6944      char * str;
6945 {
6946   /* Co-processor register transfer.
6947      Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>}  */
6948
6949   skip_whitespace (str);
6950
6951   if (co_proc_number (&str) == FAIL)
6952     {
6953       if (!inst.error)
6954         inst.error = BAD_ARGS;
6955       return;
6956     }
6957
6958   if (skip_past_comma (&str) == FAIL
6959       || cp_opc_expr (&str, 21, 3) == FAIL)
6960     {
6961       if (!inst.error)
6962         inst.error = BAD_ARGS;
6963       return;
6964     }
6965
6966   if (skip_past_comma (&str) == FAIL
6967       || reg_required_here (&str, 12) == FAIL)
6968     {
6969       if (!inst.error)
6970         inst.error = BAD_ARGS;
6971       return;
6972     }
6973
6974   if (skip_past_comma (&str) == FAIL
6975       || cp_reg_required_here (&str, 16) == FAIL)
6976     {
6977       if (!inst.error)
6978         inst.error = BAD_ARGS;
6979       return;
6980     }
6981
6982   if (skip_past_comma (&str) == FAIL
6983       || cp_reg_required_here (&str, 0) == FAIL)
6984     {
6985       if (!inst.error)
6986         inst.error = BAD_ARGS;
6987       return;
6988     }
6989
6990   if (skip_past_comma (&str) == SUCCESS)
6991     {
6992       if (cp_opc_expr (&str, 5, 3) == FAIL)
6993         {
6994           if (!inst.error)
6995             inst.error = BAD_ARGS;
6996           return;
6997         }
6998     }
6999
7000   end_of_line (str);
7001   return;
7002 }
7003
7004 static void
7005 do_fpa_ctrl (str)
7006      char * str;
7007 {
7008   /* FP control registers.
7009      Format: <WFS|RFS|WFC|RFC>{cond} Rn  */
7010
7011   skip_whitespace (str);
7012
7013   if (reg_required_here (&str, 12) == FAIL)
7014     {
7015       if (!inst.error)
7016         inst.error = BAD_ARGS;
7017       return;
7018     }
7019
7020   end_of_line (str);
7021   return;
7022 }
7023
7024 static void
7025 do_fpa_ldst (str)
7026      char * str;
7027 {
7028   skip_whitespace (str);
7029
7030   if (fp_reg_required_here (&str, 12) == FAIL)
7031     {
7032       if (!inst.error)
7033         inst.error = BAD_ARGS;
7034       return;
7035     }
7036
7037   if (skip_past_comma (&str) == FAIL
7038       || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7039     {
7040       if (!inst.error)
7041         inst.error = BAD_ARGS;
7042       return;
7043     }
7044
7045   end_of_line (str);
7046 }
7047
7048 static void
7049 do_fpa_ldmstm (str)
7050      char * str;
7051 {
7052   int num_regs;
7053
7054   skip_whitespace (str);
7055
7056   if (fp_reg_required_here (&str, 12) == FAIL)
7057     {
7058       if (! inst.error)
7059         inst.error = BAD_ARGS;
7060       return;
7061     }
7062
7063   /* Get Number of registers to transfer.  */
7064   if (skip_past_comma (&str) == FAIL
7065       || my_get_expression (&inst.reloc.exp, &str))
7066     {
7067       if (! inst.error)
7068         inst.error = _("constant expression expected");
7069       return;
7070     }
7071
7072   if (inst.reloc.exp.X_op != O_constant)
7073     {
7074       inst.error = _("constant value required for number of registers");
7075       return;
7076     }
7077
7078   num_regs = inst.reloc.exp.X_add_number;
7079
7080   if (num_regs < 1 || num_regs > 4)
7081     {
7082       inst.error = _("number of registers must be in the range [1:4]");
7083       return;
7084     }
7085
7086   switch (num_regs)
7087     {
7088     case 1:
7089       inst.instruction |= CP_T_X;
7090       break;
7091     case 2:
7092       inst.instruction |= CP_T_Y;
7093       break;
7094     case 3:
7095       inst.instruction |= CP_T_Y | CP_T_X;
7096       break;
7097     case 4:
7098       break;
7099     default:
7100       abort ();
7101     }
7102
7103   if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format.  */
7104     {
7105       int reg;
7106       int write_back;
7107       int offset;
7108
7109       /* The instruction specified "ea" or "fd", so we can only accept
7110          [Rn]{!}.  The instruction does not really support stacking or
7111          unstacking, so we have to emulate these by setting appropriate
7112          bits and offsets.  */
7113       if (skip_past_comma (&str) == FAIL
7114           || *str != '[')
7115         {
7116           if (! inst.error)
7117             inst.error = BAD_ARGS;
7118           return;
7119         }
7120
7121       str++;
7122       skip_whitespace (str);
7123
7124       if ((reg = reg_required_here (&str, 16)) == FAIL)
7125         return;
7126
7127       skip_whitespace (str);
7128
7129       if (*str != ']')
7130         {
7131           inst.error = BAD_ARGS;
7132           return;
7133         }
7134
7135       str++;
7136       if (*str == '!')
7137         {
7138           write_back = 1;
7139           str++;
7140           if (reg == REG_PC)
7141             {
7142               inst.error =
7143                 _("r15 not allowed as base register with write-back");
7144               return;
7145             }
7146         }
7147       else
7148         write_back = 0;
7149
7150       if (inst.instruction & CP_T_Pre)
7151         {
7152           /* Pre-decrement.  */
7153           offset = 3 * num_regs;
7154           if (write_back)
7155             inst.instruction |= CP_T_WB;
7156         }
7157       else
7158         {
7159           /* Post-increment.  */
7160           if (write_back)
7161             {
7162               inst.instruction |= CP_T_WB;
7163               offset = 3 * num_regs;
7164             }
7165           else
7166             {
7167               /* No write-back, so convert this into a standard pre-increment
7168                  instruction -- aesthetically more pleasing.  */
7169               inst.instruction |= CP_T_Pre | CP_T_UD;
7170               offset = 0;
7171             }
7172         }
7173
7174       inst.instruction |= offset;
7175     }
7176   else if (skip_past_comma (&str) == FAIL
7177            || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7178     {
7179       if (! inst.error)
7180         inst.error = BAD_ARGS;
7181       return;
7182     }
7183
7184   end_of_line (str);
7185 }
7186
7187 static void
7188 do_fpa_dyadic (str)
7189      char * str;
7190 {
7191   skip_whitespace (str);
7192
7193   if (fp_reg_required_here (&str, 12) == FAIL)
7194     {
7195       if (! inst.error)
7196         inst.error = BAD_ARGS;
7197       return;
7198     }
7199
7200   if (skip_past_comma (&str) == FAIL
7201       || fp_reg_required_here (&str, 16) == FAIL)
7202     {
7203       if (! inst.error)
7204         inst.error = BAD_ARGS;
7205       return;
7206     }
7207
7208   if (skip_past_comma (&str) == FAIL
7209       || fp_op2 (&str) == FAIL)
7210     {
7211       if (! inst.error)
7212         inst.error = BAD_ARGS;
7213       return;
7214     }
7215
7216   end_of_line (str);
7217   return;
7218 }
7219
7220 static void
7221 do_fpa_monadic (str)
7222      char * str;
7223 {
7224   skip_whitespace (str);
7225
7226   if (fp_reg_required_here (&str, 12) == FAIL)
7227     {
7228       if (! inst.error)
7229         inst.error = BAD_ARGS;
7230       return;
7231     }
7232
7233   if (skip_past_comma (&str) == FAIL
7234       || fp_op2 (&str) == FAIL)
7235     {
7236       if (! inst.error)
7237         inst.error = BAD_ARGS;
7238       return;
7239     }
7240
7241   end_of_line (str);
7242   return;
7243 }
7244
7245 static void
7246 do_fpa_cmp (str)
7247      char * str;
7248 {
7249   skip_whitespace (str);
7250
7251   if (fp_reg_required_here (&str, 16) == FAIL)
7252     {
7253       if (! inst.error)
7254         inst.error = BAD_ARGS;
7255       return;
7256     }
7257
7258   if (skip_past_comma (&str) == FAIL
7259       || fp_op2 (&str) == FAIL)
7260     {
7261       if (! inst.error)
7262         inst.error = BAD_ARGS;
7263       return;
7264     }
7265
7266   end_of_line (str);
7267   return;
7268 }
7269
7270 static void
7271 do_fpa_from_reg (str)
7272      char * str;
7273 {
7274   skip_whitespace (str);
7275
7276   if (fp_reg_required_here (&str, 16) == FAIL)
7277     {
7278       if (! inst.error)
7279         inst.error = BAD_ARGS;
7280       return;
7281     }
7282
7283   if (skip_past_comma (&str) == FAIL
7284       || reg_required_here (&str, 12) == FAIL)
7285     {
7286       if (! inst.error)
7287         inst.error = BAD_ARGS;
7288       return;
7289     }
7290
7291   end_of_line (str);
7292   return;
7293 }
7294
7295 static void
7296 do_fpa_to_reg (str)
7297      char * str;
7298 {
7299   skip_whitespace (str);
7300
7301   if (reg_required_here (&str, 12) == FAIL)
7302     return;
7303
7304   if (skip_past_comma (&str) == FAIL
7305       || fp_reg_required_here (&str, 0) == FAIL)
7306     {
7307       if (! inst.error)
7308         inst.error = BAD_ARGS;
7309       return;
7310     }
7311
7312   end_of_line (str);
7313   return;
7314 }
7315
7316 static int
7317 vfp_sp_reg_required_here (str, pos)
7318      char **str;
7319      enum vfp_sp_reg_pos pos;
7320 {
7321   int    reg;
7322   char *start = *str;
7323
7324   if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
7325     {
7326       switch (pos)
7327         {
7328         case VFP_REG_Sd:
7329           inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
7330           break;
7331
7332         case VFP_REG_Sn:
7333           inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
7334           break;
7335
7336         case VFP_REG_Sm:
7337           inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
7338           break;
7339
7340         default:
7341           abort ();
7342         }
7343       return reg;
7344     }
7345
7346   /* In the few cases where we might be able to accept something else
7347      this error can be overridden.  */
7348   inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7349
7350   /* Restore the start point.  */
7351   *str = start;
7352   return FAIL;
7353 }
7354
7355 static int
7356 vfp_dp_reg_required_here (str, pos)
7357      char **str;
7358      enum vfp_dp_reg_pos pos;
7359 {
7360   int   reg;
7361   char *start = *str;
7362
7363   if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
7364     {
7365       switch (pos)
7366         {
7367         case VFP_REG_Dd:
7368           inst.instruction |= reg << 12;
7369           break;
7370
7371         case VFP_REG_Dn:
7372           inst.instruction |= reg << 16;
7373           break;
7374
7375         case VFP_REG_Dm:
7376           inst.instruction |= reg << 0;
7377           break;
7378
7379         default:
7380           abort ();
7381         }
7382       return reg;
7383     }
7384
7385   /* In the few cases where we might be able to accept something else
7386      this error can be overridden.  */
7387   inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
7388
7389   /* Restore the start point.  */
7390   *str = start;
7391   return FAIL;
7392 }
7393
7394 static void
7395 do_vfp_sp_monadic (str)
7396      char *str;
7397 {
7398   skip_whitespace (str);
7399
7400   if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7401     return;
7402
7403   if (skip_past_comma (&str) == FAIL
7404       || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7405     {
7406       if (! inst.error)
7407         inst.error = BAD_ARGS;
7408       return;
7409     }
7410
7411   end_of_line (str);
7412   return;
7413 }
7414
7415 static void
7416 do_vfp_dp_monadic (str)
7417      char *str;
7418 {
7419   skip_whitespace (str);
7420
7421   if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7422     return;
7423
7424   if (skip_past_comma (&str) == FAIL
7425       || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7426     {
7427       if (! inst.error)
7428         inst.error = BAD_ARGS;
7429       return;
7430     }
7431
7432   end_of_line (str);
7433   return;
7434 }
7435
7436 static void
7437 do_vfp_sp_dyadic (str)
7438      char *str;
7439 {
7440   skip_whitespace (str);
7441
7442   if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7443     return;
7444
7445   if (skip_past_comma (&str) == FAIL
7446       || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
7447       || skip_past_comma (&str) == FAIL
7448       || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7449     {
7450       if (! inst.error)
7451         inst.error = BAD_ARGS;
7452       return;
7453     }
7454
7455   end_of_line (str);
7456   return;
7457 }
7458
7459 static void
7460 do_vfp_dp_dyadic (str)
7461      char *str;
7462 {
7463   skip_whitespace (str);
7464
7465   if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7466     return;
7467
7468   if (skip_past_comma (&str) == FAIL
7469       || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
7470       || skip_past_comma (&str) == FAIL
7471       || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7472     {
7473       if (! inst.error)
7474         inst.error = BAD_ARGS;
7475       return;
7476     }
7477
7478   end_of_line (str);
7479   return;
7480 }
7481
7482 static void
7483 do_vfp_reg_from_sp (str)
7484      char *str;
7485 {
7486   skip_whitespace (str);
7487
7488   if (reg_required_here (&str, 12) == FAIL)
7489     return;
7490
7491   if (skip_past_comma (&str) == FAIL
7492       || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7493     {
7494       if (! inst.error)
7495         inst.error = BAD_ARGS;
7496       return;
7497     }
7498
7499   end_of_line (str);
7500   return;
7501 }
7502
7503 static void
7504 do_vfp_sp_reg2 (str)
7505      char *str;
7506 {
7507   skip_whitespace (str);
7508
7509   if (reg_required_here (&str, 12) == FAIL)
7510     return;
7511
7512   if (skip_past_comma (&str) == FAIL
7513       || reg_required_here (&str, 16) == FAIL
7514       || skip_past_comma (&str) == FAIL)
7515     {
7516       if (! inst.error)
7517         inst.error = BAD_ARGS;
7518       return;
7519     }
7520
7521   /* We require exactly two consecutive SP registers.  */
7522   if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
7523     {
7524       if (! inst.error)
7525         inst.error = _("only two consecutive VFP SP registers allowed here");
7526     }
7527
7528   end_of_line (str);
7529   return;
7530 }
7531
7532 static void
7533 do_vfp_sp_from_reg (str)
7534      char *str;
7535 {
7536   skip_whitespace (str);
7537
7538   if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7539     return;
7540
7541   if (skip_past_comma (&str) == FAIL
7542       || reg_required_here (&str, 12) == FAIL)
7543     {
7544       if (! inst.error)
7545         inst.error = BAD_ARGS;
7546       return;
7547     }
7548
7549   end_of_line (str);
7550   return;
7551 }
7552
7553 static void
7554 do_vfp_reg_from_dp (str)
7555      char *str;
7556 {
7557   skip_whitespace (str);
7558
7559   if (reg_required_here (&str, 12) == FAIL)
7560     return;
7561
7562   if (skip_past_comma (&str) == FAIL
7563       || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
7564     {
7565       if (! inst.error)
7566         inst.error = BAD_ARGS;
7567       return;
7568     }
7569
7570   end_of_line (str);
7571   return;
7572 }
7573
7574 static void
7575 do_vfp_reg2_from_dp (str)
7576      char *str;
7577 {
7578   skip_whitespace (str);
7579
7580   if (reg_required_here (&str, 12) == FAIL)
7581     return;
7582
7583   if (skip_past_comma (&str) == FAIL
7584       || reg_required_here (&str, 16) == FAIL
7585       || skip_past_comma (&str) == FAIL
7586       || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7587     {
7588       if (! inst.error)
7589         inst.error = BAD_ARGS;
7590       return;
7591     }
7592
7593   end_of_line (str);
7594   return;
7595 }
7596
7597 static void
7598 do_vfp_dp_from_reg (str)
7599      char *str;
7600 {
7601   skip_whitespace (str);
7602
7603   if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
7604     return;
7605
7606   if (skip_past_comma (&str) == FAIL
7607       || reg_required_here (&str, 12) == FAIL)
7608     {
7609       if (! inst.error)
7610         inst.error = BAD_ARGS;
7611       return;
7612     }
7613
7614   end_of_line (str);
7615   return;
7616 }
7617
7618 static void
7619 do_vfp_dp_from_reg2 (str)
7620      char *str;
7621 {
7622   skip_whitespace (str);
7623
7624   if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7625     return;
7626
7627   if (skip_past_comma (&str) == FAIL
7628       || reg_required_here (&str, 12) == FAIL
7629       || skip_past_comma (&str) == FAIL
7630       || reg_required_here (&str, 16))
7631     {
7632       if (! inst.error)
7633         inst.error = BAD_ARGS;
7634       return;
7635     }
7636
7637   end_of_line (str);
7638   return;
7639 }
7640
7641 static const struct vfp_reg *
7642 vfp_psr_parse (str)
7643      char **str;
7644 {
7645   char *start = *str;
7646   char  c;
7647   char *p;
7648   const struct vfp_reg *vreg;
7649
7650   p = start;
7651
7652   /* Find the end of the current token.  */
7653   do
7654     {
7655       c = *p++;
7656     }
7657   while (ISALPHA (c));
7658
7659   /* Mark it.  */
7660   *--p = 0;
7661
7662   for (vreg = vfp_regs + 0;
7663        vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
7664        vreg++)
7665     {
7666       if (strcmp (start, vreg->name) == 0)
7667         {
7668           *p = c;
7669           *str = p;
7670           return vreg;
7671         }
7672     }
7673
7674   *p = c;
7675   return NULL;
7676 }
7677
7678 static int
7679 vfp_psr_required_here (str)
7680      char **str;
7681 {
7682   char *start = *str;
7683   const struct vfp_reg *vreg;
7684
7685   vreg = vfp_psr_parse (str);
7686
7687   if (vreg)
7688     {
7689       inst.instruction |= vreg->regno;
7690       return SUCCESS;
7691     }
7692
7693   inst.error = _("VFP system register expected");
7694
7695   *str = start;
7696   return FAIL;
7697 }
7698
7699 static void
7700 do_vfp_reg_from_ctrl (str)
7701      char *str;
7702 {
7703   skip_whitespace (str);
7704
7705   if (reg_required_here (&str, 12) == FAIL)
7706     return;
7707
7708   if (skip_past_comma (&str) == FAIL
7709       || vfp_psr_required_here (&str) == FAIL)
7710     {
7711       if (! inst.error)
7712         inst.error = BAD_ARGS;
7713       return;
7714     }
7715
7716   end_of_line (str);
7717   return;
7718 }
7719
7720 static void
7721 do_vfp_ctrl_from_reg (str)
7722      char *str;
7723 {
7724   skip_whitespace (str);
7725
7726   if (vfp_psr_required_here (&str) == FAIL)
7727     return;
7728
7729   if (skip_past_comma (&str) == FAIL
7730       || reg_required_here (&str, 12) == FAIL)
7731     {
7732       if (! inst.error)
7733         inst.error = BAD_ARGS;
7734       return;
7735     }
7736
7737   end_of_line (str);
7738   return;
7739 }
7740
7741 static void
7742 do_vfp_sp_ldst (str)
7743      char *str;
7744 {
7745   skip_whitespace (str);
7746
7747   if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7748     {
7749       if (!inst.error)
7750         inst.error = BAD_ARGS;
7751       return;
7752     }
7753
7754   if (skip_past_comma (&str) == FAIL
7755       || cp_address_required_here (&str, CP_NO_WB) == FAIL)
7756     {
7757       if (!inst.error)
7758         inst.error = BAD_ARGS;
7759       return;
7760     }
7761
7762   end_of_line (str);
7763   return;
7764 }
7765
7766 static void
7767 do_vfp_dp_ldst (str)
7768      char *str;
7769 {
7770   skip_whitespace (str);
7771
7772   if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7773     {
7774       if (!inst.error)
7775         inst.error = BAD_ARGS;
7776       return;
7777     }
7778
7779   if (skip_past_comma (&str) == FAIL
7780       || cp_address_required_here (&str, CP_NO_WB) == FAIL)
7781     {
7782       if (!inst.error)
7783         inst.error = BAD_ARGS;
7784       return;
7785     }
7786
7787   end_of_line (str);
7788   return;
7789 }
7790
7791 /* Parse and encode a VFP SP register list, storing the initial
7792    register in position POS and returning the range as the result.  If
7793    the string is invalid return FAIL (an invalid range).  */
7794 static long
7795 vfp_sp_reg_list (str, pos)
7796      char **str;
7797      enum vfp_sp_reg_pos pos;
7798 {
7799   long range = 0;
7800   int base_reg = 0;
7801   int new_base;
7802   long base_bits = 0;
7803   int count = 0;
7804   long tempinst;
7805   unsigned long mask = 0;
7806   int warned = 0;
7807
7808   if (**str != '{')
7809     return FAIL;
7810
7811   (*str)++;
7812   skip_whitespace (*str);
7813
7814   tempinst = inst.instruction;
7815
7816   do
7817     {
7818       inst.instruction = 0;
7819
7820       if ((new_base = vfp_sp_reg_required_here (str, pos)) == FAIL)
7821         return FAIL;
7822
7823       if (count == 0 || base_reg > new_base)
7824         {
7825           base_reg = new_base;
7826           base_bits = inst.instruction;
7827         }
7828
7829       if (mask & (1 << new_base))
7830         {
7831           inst.error = _("invalid register list");
7832           return FAIL;
7833         }
7834
7835       if ((mask >> new_base) != 0 && ! warned)
7836         {
7837           as_tsktsk (_("register list not in ascending order"));
7838           warned = 1;
7839         }
7840
7841       mask |= 1 << new_base;
7842       count++;
7843
7844       skip_whitespace (*str);
7845
7846       if (**str == '-') /* We have the start of a range expression */
7847         {
7848           int high_range;
7849
7850           (*str)++;
7851
7852           if ((high_range
7853                = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab))
7854               == FAIL)
7855             {
7856               inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7857               return FAIL;
7858             }
7859
7860           if (high_range <= new_base)
7861             {
7862               inst.error = _("register range not in ascending order");
7863               return FAIL;
7864             }
7865
7866           for (new_base++; new_base <= high_range; new_base++)
7867             {
7868               if (mask & (1 << new_base))
7869                 {
7870                   inst.error = _("invalid register list");
7871                   return FAIL;
7872                 }
7873
7874               mask |= 1 << new_base;
7875               count++;
7876             }
7877         }
7878     }
7879   while (skip_past_comma (str) != FAIL);
7880
7881   if (**str != '}')
7882     {
7883       inst.error = _("invalid register list");
7884       return FAIL;
7885     }
7886
7887   (*str)++;
7888
7889   range = count;
7890
7891   /* Sanity check -- should have raised a parse error above.  */
7892   if (count == 0 || count > 32)
7893     abort ();
7894
7895   /* Final test -- the registers must be consecutive.  */
7896   while (count--)
7897     {
7898       if ((mask & (1 << base_reg++)) == 0)
7899         {
7900           inst.error = _("non-contiguous register range");
7901           return FAIL;
7902         }
7903     }
7904
7905   inst.instruction = tempinst | base_bits;
7906   return range;
7907 }
7908
7909 static long
7910 vfp_dp_reg_list (str)
7911      char **str;
7912 {
7913   long range = 0;
7914   int base_reg = 0;
7915   int new_base;
7916   int count = 0;
7917   long tempinst;
7918   unsigned long mask = 0;
7919   int warned = 0;
7920
7921   if (**str != '{')
7922     return FAIL;
7923
7924   (*str)++;
7925   skip_whitespace (*str);
7926
7927   tempinst = inst.instruction;
7928
7929   do
7930     {
7931       inst.instruction = 0;
7932
7933       if ((new_base = vfp_dp_reg_required_here (str, VFP_REG_Dd)) == FAIL)
7934         return FAIL;
7935
7936       if (count == 0 || base_reg > new_base)
7937         {
7938           base_reg = new_base;
7939           range = inst.instruction;
7940         }
7941
7942       if (mask & (1 << new_base))
7943         {
7944           inst.error = _("invalid register list");
7945           return FAIL;
7946         }
7947
7948       if ((mask >> new_base) != 0 && ! warned)
7949         {
7950           as_tsktsk (_("register list not in ascending order"));
7951           warned = 1;
7952         }
7953
7954       mask |= 1 << new_base;
7955       count++;
7956
7957       skip_whitespace (*str);
7958
7959       if (**str == '-') /* We have the start of a range expression */
7960         {
7961           int high_range;
7962
7963           (*str)++;
7964
7965           if ((high_range
7966                = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab))
7967               == FAIL)
7968             {
7969               inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
7970               return FAIL;
7971             }
7972
7973           if (high_range <= new_base)
7974             {
7975               inst.error = _("register range not in ascending order");
7976               return FAIL;
7977             }
7978
7979           for (new_base++; new_base <= high_range; new_base++)
7980             {
7981               if (mask & (1 << new_base))
7982                 {
7983                   inst.error = _("invalid register list");
7984                   return FAIL;
7985                 }
7986
7987               mask |= 1 << new_base;
7988               count++;
7989             }
7990         }
7991     }
7992   while (skip_past_comma (str) != FAIL);
7993
7994   if (**str != '}')
7995     {
7996       inst.error = _("invalid register list");
7997       return FAIL;
7998     }
7999
8000   (*str)++;
8001
8002   range |= 2 * count;
8003
8004   /* Sanity check -- should have raised a parse error above.  */
8005   if (count == 0 || count > 16)
8006     abort ();
8007
8008   /* Final test -- the registers must be consecutive.  */
8009   while (count--)
8010     {
8011       if ((mask & (1 << base_reg++)) == 0)
8012         {
8013           inst.error = _("non-contiguous register range");
8014           return FAIL;
8015         }
8016     }
8017
8018   inst.instruction = tempinst;
8019   return range;
8020 }
8021
8022 static void
8023 vfp_sp_ldstm (str, ldstm_type)
8024      char *str;
8025      enum vfp_ldstm_type ldstm_type;
8026 {
8027   long range;
8028
8029   skip_whitespace (str);
8030
8031   if (reg_required_here (&str, 16) == FAIL)
8032     return;
8033
8034   skip_whitespace (str);
8035
8036   if (*str == '!')
8037     {
8038       inst.instruction |= WRITE_BACK;
8039       str++;
8040     }
8041   else if (ldstm_type != VFP_LDSTMIA)
8042     {
8043       inst.error = _("this addressing mode requires base-register writeback");
8044       return;
8045     }
8046
8047   if (skip_past_comma (&str) == FAIL
8048       || (range = vfp_sp_reg_list (&str, VFP_REG_Sd)) == FAIL)
8049     {
8050       if (!inst.error)
8051         inst.error = BAD_ARGS;
8052       return;
8053     }
8054
8055   inst.instruction |= range;
8056   end_of_line (str);
8057 }
8058
8059 static void
8060 vfp_dp_ldstm (str, ldstm_type)
8061      char *str;
8062      enum vfp_ldstm_type ldstm_type;
8063 {
8064   long range;
8065
8066   skip_whitespace (str);
8067
8068   if (reg_required_here (&str, 16) == FAIL)
8069     return;
8070
8071   skip_whitespace (str);
8072
8073   if (*str == '!')
8074     {
8075       inst.instruction |= WRITE_BACK;
8076       str++;
8077     }
8078   else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
8079     {
8080       inst.error = _("this addressing mode requires base-register writeback");
8081       return;
8082     }
8083
8084   if (skip_past_comma (&str) == FAIL
8085       || (range = vfp_dp_reg_list (&str)) == FAIL)
8086     {
8087       if (!inst.error)
8088         inst.error = BAD_ARGS;
8089       return;
8090     }
8091
8092   if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
8093     range += 1;
8094
8095   inst.instruction |= range;
8096   end_of_line (str);
8097 }
8098
8099 static void
8100 do_vfp_sp_ldstmia (str)
8101      char *str;
8102 {
8103   vfp_sp_ldstm (str, VFP_LDSTMIA);
8104 }
8105
8106 static void
8107 do_vfp_sp_ldstmdb (str)
8108      char *str;
8109 {
8110   vfp_sp_ldstm (str, VFP_LDSTMDB);
8111 }
8112
8113 static void
8114 do_vfp_dp_ldstmia (str)
8115      char *str;
8116 {
8117   vfp_dp_ldstm (str, VFP_LDSTMIA);
8118 }
8119
8120 static void
8121 do_vfp_dp_ldstmdb (str)
8122      char *str;
8123 {
8124   vfp_dp_ldstm (str, VFP_LDSTMDB);
8125 }
8126
8127 static void
8128 do_vfp_xp_ldstmia (str)
8129      char *str;
8130 {
8131   vfp_dp_ldstm (str, VFP_LDSTMIAX);
8132 }
8133
8134 static void
8135 do_vfp_xp_ldstmdb (str)
8136      char *str;
8137 {
8138   vfp_dp_ldstm (str, VFP_LDSTMDBX);
8139 }
8140
8141 static void
8142 do_vfp_sp_compare_z (str)
8143      char *str;
8144 {
8145   skip_whitespace (str);
8146
8147   if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8148     {
8149       if (!inst.error)
8150         inst.error = BAD_ARGS;
8151       return;
8152     }
8153
8154   end_of_line (str);
8155   return;
8156 }
8157
8158 static void
8159 do_vfp_dp_compare_z (str)
8160      char *str;
8161 {
8162   skip_whitespace (str);
8163
8164   if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8165     {
8166       if (!inst.error)
8167         inst.error = BAD_ARGS;
8168       return;
8169     }
8170
8171   end_of_line (str);
8172   return;
8173 }
8174
8175 static void
8176 do_vfp_dp_sp_cvt (str)
8177      char *str;
8178 {
8179   skip_whitespace (str);
8180
8181   if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8182     return;
8183
8184   if (skip_past_comma (&str) == FAIL
8185       || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8186     {
8187       if (! inst.error)
8188         inst.error = BAD_ARGS;
8189       return;
8190     }
8191
8192   end_of_line (str);
8193   return;
8194 }
8195
8196 static void
8197 do_vfp_sp_dp_cvt (str)
8198      char *str;
8199 {
8200   skip_whitespace (str);
8201
8202   if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8203     return;
8204
8205   if (skip_past_comma (&str) == FAIL
8206       || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8207     {
8208       if (! inst.error)
8209         inst.error = BAD_ARGS;
8210       return;
8211     }
8212
8213   end_of_line (str);
8214   return;
8215 }
8216
8217 /* Thumb specific routines.  */
8218
8219 /* Parse and validate that a register is of the right form, this saves
8220    repeated checking of this information in many similar cases.
8221    Unlike the 32-bit case we do not insert the register into the opcode
8222    here, since the position is often unknown until the full instruction
8223    has been parsed.  */
8224
8225 static int
8226 thumb_reg (strp, hi_lo)
8227      char ** strp;
8228      int     hi_lo;
8229 {
8230   int reg;
8231
8232   if ((reg = reg_required_here (strp, -1)) == FAIL)
8233     return FAIL;
8234
8235   switch (hi_lo)
8236     {
8237     case THUMB_REG_LO:
8238       if (reg > 7)
8239         {
8240           inst.error = _("lo register required");
8241           return FAIL;
8242         }
8243       break;
8244
8245     case THUMB_REG_HI:
8246       if (reg < 8)
8247         {
8248           inst.error = _("hi register required");
8249           return FAIL;
8250         }
8251       break;
8252
8253     default:
8254       break;
8255     }
8256
8257   return reg;
8258 }
8259
8260 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8261    was SUB.  */
8262
8263 static void
8264 thumb_add_sub (str, subtract)
8265      char * str;
8266      int    subtract;
8267 {
8268   int Rd, Rs, Rn = FAIL;
8269
8270   skip_whitespace (str);
8271
8272   if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8273       || skip_past_comma (&str) == FAIL)
8274     {
8275       if (! inst.error)
8276         inst.error = BAD_ARGS;
8277       return;
8278     }
8279
8280   if (is_immediate_prefix (*str))
8281     {
8282       Rs = Rd;
8283       str++;
8284       if (my_get_expression (&inst.reloc.exp, &str))
8285         return;
8286     }
8287   else
8288     {
8289       if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8290         return;
8291
8292       if (skip_past_comma (&str) == FAIL)
8293         {
8294           /* Two operand format, shuffle the registers
8295              and pretend there are 3.  */
8296           Rn = Rs;
8297           Rs = Rd;
8298         }
8299       else if (is_immediate_prefix (*str))
8300         {
8301           str++;
8302           if (my_get_expression (&inst.reloc.exp, &str))
8303             return;
8304         }
8305       else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8306         return;
8307     }
8308
8309   /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8310      for the latter case, EXPR contains the immediate that was found.  */
8311   if (Rn != FAIL)
8312     {
8313       /* All register format.  */
8314       if (Rd > 7 || Rs > 7 || Rn > 7)
8315         {
8316           if (Rs != Rd)
8317             {
8318               inst.error = _("dest and source1 must be the same register");
8319               return;
8320             }
8321
8322           /* Can't do this for SUB.  */
8323           if (subtract)
8324             {
8325               inst.error = _("subtract valid only on lo regs");
8326               return;
8327             }
8328
8329           inst.instruction = (T_OPCODE_ADD_HI
8330                               | (Rd > 7 ? THUMB_H1 : 0)
8331                               | (Rn > 7 ? THUMB_H2 : 0));
8332           inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
8333         }
8334       else
8335         {
8336           inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
8337           inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
8338         }
8339     }
8340   else
8341     {
8342       /* Immediate expression, now things start to get nasty.  */
8343
8344       /* First deal with HI regs, only very restricted cases allowed:
8345          Adjusting SP, and using PC or SP to get an address.  */
8346       if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
8347           || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
8348         {
8349           inst.error = _("invalid Hi register with immediate");
8350           return;
8351         }
8352
8353       if (inst.reloc.exp.X_op != O_constant)
8354         {
8355           /* Value isn't known yet, all we can do is store all the fragments
8356              we know about in the instruction and let the reloc hacking
8357              work it all out.  */
8358           inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
8359           inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
8360         }
8361       else
8362         {
8363           int offset = inst.reloc.exp.X_add_number;
8364
8365           if (subtract)
8366             offset = - offset;
8367
8368           if (offset < 0)
8369             {
8370               offset = - offset;
8371               subtract = 1;
8372
8373               /* Quick check, in case offset is MIN_INT.  */
8374               if (offset < 0)
8375                 {
8376                   inst.error = _("immediate value out of range");
8377                   return;
8378                 }
8379             }
8380           /* Note - you cannot convert a subtract of 0 into an
8381              add of 0 because the carry flag is set differently.  */
8382           else if (offset > 0)
8383             subtract = 0;
8384
8385           if (Rd == REG_SP)
8386             {
8387               if (offset & ~0x1fc)
8388                 {
8389                   inst.error = _("invalid immediate value for stack adjust");
8390                   return;
8391                 }
8392               inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
8393               inst.instruction |= offset >> 2;
8394             }
8395           else if (Rs == REG_PC || Rs == REG_SP)
8396             {
8397               if (subtract
8398                   || (offset & ~0x3fc))
8399                 {
8400                   inst.error = _("invalid immediate for address calculation");
8401                   return;
8402                 }
8403               inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
8404                                   : T_OPCODE_ADD_SP);
8405               inst.instruction |= (Rd << 8) | (offset >> 2);
8406             }
8407           else if (Rs == Rd)
8408             {
8409               if (offset & ~0xff)
8410                 {
8411                   inst.error = _("immediate value out of range");
8412                   return;
8413                 }
8414               inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
8415               inst.instruction |= (Rd << 8) | offset;
8416             }
8417           else
8418             {
8419               if (offset & ~0x7)
8420                 {
8421                   inst.error = _("immediate value out of range");
8422                   return;
8423                 }
8424               inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
8425               inst.instruction |= Rd | (Rs << 3) | (offset << 6);
8426             }
8427         }
8428     }
8429
8430   end_of_line (str);
8431 }
8432
8433 static void
8434 thumb_shift (str, shift)
8435      char * str;
8436      int    shift;
8437 {
8438   int Rd, Rs, Rn = FAIL;
8439
8440   skip_whitespace (str);
8441
8442   if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8443       || skip_past_comma (&str) == FAIL)
8444     {
8445       if (! inst.error)
8446         inst.error = BAD_ARGS;
8447       return;
8448     }
8449
8450   if (is_immediate_prefix (*str))
8451     {
8452       /* Two operand immediate format, set Rs to Rd.  */
8453       Rs = Rd;
8454       str ++;
8455       if (my_get_expression (&inst.reloc.exp, &str))
8456         return;
8457     }
8458   else
8459     {
8460       if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8461         return;
8462
8463       if (skip_past_comma (&str) == FAIL)
8464         {
8465           /* Two operand format, shuffle the registers
8466              and pretend there are 3.  */
8467           Rn = Rs;
8468           Rs = Rd;
8469         }
8470       else if (is_immediate_prefix (*str))
8471         {
8472           str++;
8473           if (my_get_expression (&inst.reloc.exp, &str))
8474             return;
8475         }
8476       else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8477         return;
8478     }
8479
8480   /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8481      for the latter case, EXPR contains the immediate that was found.  */
8482
8483   if (Rn != FAIL)
8484     {
8485       if (Rs != Rd)
8486         {
8487           inst.error = _("source1 and dest must be same register");
8488           return;
8489         }
8490
8491       switch (shift)
8492         {
8493         case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
8494         case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
8495         case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
8496         }
8497
8498       inst.instruction |= Rd | (Rn << 3);
8499     }
8500   else
8501     {
8502       switch (shift)
8503         {
8504         case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
8505         case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
8506         case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
8507         }
8508
8509       if (inst.reloc.exp.X_op != O_constant)
8510         {
8511           /* Value isn't known yet, create a dummy reloc and let reloc
8512              hacking fix it up.  */
8513           inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
8514         }
8515       else
8516         {
8517           unsigned shift_value = inst.reloc.exp.X_add_number;
8518
8519           if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
8520             {
8521               inst.error = _("invalid immediate for shift");
8522               return;
8523             }
8524
8525           /* Shifts of zero are handled by converting to LSL.  */
8526           if (shift_value == 0)
8527             inst.instruction = T_OPCODE_LSL_I;
8528
8529           /* Shifts of 32 are encoded as a shift of zero.  */
8530           if (shift_value == 32)
8531             shift_value = 0;
8532
8533           inst.instruction |= shift_value << 6;
8534         }
8535
8536       inst.instruction |= Rd | (Rs << 3);
8537     }
8538
8539   end_of_line (str);
8540 }
8541
8542 static void
8543 thumb_mov_compare (str, move)
8544      char * str;
8545      int    move;
8546 {
8547   int Rd, Rs = FAIL;
8548
8549   skip_whitespace (str);
8550
8551   if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8552       || skip_past_comma (&str) == FAIL)
8553     {
8554       if (! inst.error)
8555         inst.error = BAD_ARGS;
8556       return;
8557     }
8558
8559   if (is_immediate_prefix (*str))
8560     {
8561       str++;
8562       if (my_get_expression (&inst.reloc.exp, &str))
8563         return;
8564     }
8565   else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8566     return;
8567
8568   if (Rs != FAIL)
8569     {
8570       if (Rs < 8 && Rd < 8)
8571         {
8572           if (move == THUMB_MOVE)
8573             /* A move of two lowregs is encoded as ADD Rd, Rs, #0
8574                since a MOV instruction produces unpredictable results.  */
8575             inst.instruction = T_OPCODE_ADD_I3;
8576           else
8577             inst.instruction = T_OPCODE_CMP_LR;
8578           inst.instruction |= Rd | (Rs << 3);
8579         }
8580       else
8581         {
8582           if (move == THUMB_MOVE)
8583             inst.instruction = T_OPCODE_MOV_HR;
8584           else
8585             inst.instruction = T_OPCODE_CMP_HR;
8586
8587           if (Rd > 7)
8588             inst.instruction |= THUMB_H1;
8589
8590           if (Rs > 7)
8591             inst.instruction |= THUMB_H2;
8592
8593           inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
8594         }
8595     }
8596   else
8597     {
8598       if (Rd > 7)
8599         {
8600           inst.error = _("only lo regs allowed with immediate");
8601           return;
8602         }
8603
8604       if (move == THUMB_MOVE)
8605         inst.instruction = T_OPCODE_MOV_I8;
8606       else
8607         inst.instruction = T_OPCODE_CMP_I8;
8608
8609       inst.instruction |= Rd << 8;
8610
8611       if (inst.reloc.exp.X_op != O_constant)
8612         inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
8613       else
8614         {
8615           unsigned value = inst.reloc.exp.X_add_number;
8616
8617           if (value > 255)
8618             {
8619               inst.error = _("invalid immediate");
8620               return;
8621             }
8622
8623           inst.instruction |= value;
8624         }
8625     }
8626
8627   end_of_line (str);
8628 }
8629
8630 static void
8631 thumb_load_store (str, load_store, size)
8632      char * str;
8633      int    load_store;
8634      int    size;
8635 {
8636   int Rd, Rb, Ro = FAIL;
8637
8638   skip_whitespace (str);
8639
8640   if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8641       || skip_past_comma (&str) == FAIL)
8642     {
8643       if (! inst.error)
8644         inst.error = BAD_ARGS;
8645       return;
8646     }
8647
8648   if (*str == '[')
8649     {
8650       str++;
8651       if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8652         return;
8653
8654       if (skip_past_comma (&str) != FAIL)
8655         {
8656           if (is_immediate_prefix (*str))
8657             {
8658               str++;
8659               if (my_get_expression (&inst.reloc.exp, &str))
8660                 return;
8661             }
8662           else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8663             return;
8664         }
8665       else
8666         {
8667           inst.reloc.exp.X_op = O_constant;
8668           inst.reloc.exp.X_add_number = 0;
8669         }
8670
8671       if (*str != ']')
8672         {
8673           inst.error = _("expected ']'");
8674           return;
8675         }
8676       str++;
8677     }
8678   else if (*str == '=')
8679     {
8680       if (load_store != THUMB_LOAD)
8681         {
8682           inst.error = _("invalid pseudo operation");
8683           return;
8684         }
8685
8686       /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op.  */
8687       str++;
8688
8689       skip_whitespace (str);
8690
8691       if (my_get_expression (& inst.reloc.exp, & str))
8692         return;
8693
8694       end_of_line (str);
8695
8696       if (   inst.reloc.exp.X_op != O_constant
8697           && inst.reloc.exp.X_op != O_symbol)
8698         {
8699           inst.error = "Constant expression expected";
8700           return;
8701         }
8702
8703       if (inst.reloc.exp.X_op == O_constant
8704           && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
8705         {
8706           /* This can be done with a mov instruction.  */
8707
8708           inst.instruction  = T_OPCODE_MOV_I8 | (Rd << 8);
8709           inst.instruction |= inst.reloc.exp.X_add_number;
8710           return;
8711         }
8712
8713       /* Insert into literal pool.  */
8714       if (add_to_lit_pool () == FAIL)
8715         {
8716           if (!inst.error)
8717             inst.error = "literal pool insertion failed";
8718           return;
8719         }
8720
8721       inst.reloc.type   = BFD_RELOC_ARM_THUMB_OFFSET;
8722       inst.reloc.pc_rel = 1;
8723       inst.instruction  = T_OPCODE_LDR_PC | (Rd << 8);
8724       /* Adjust ARM pipeline offset to Thumb.  */
8725       inst.reloc.exp.X_add_number += 4;
8726
8727       return;
8728     }
8729   else
8730     {
8731       if (my_get_expression (&inst.reloc.exp, &str))
8732         return;
8733
8734       inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8735       inst.reloc.pc_rel = 1;
8736       inst.reloc.exp.X_add_number -= 4; /* Pipeline offset.  */
8737       inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8738       end_of_line (str);
8739       return;
8740     }
8741
8742   if (Rb == REG_PC || Rb == REG_SP)
8743     {
8744       if (size != THUMB_WORD)
8745         {
8746           inst.error = _("byte or halfword not valid for base register");
8747           return;
8748         }
8749       else if (Rb == REG_PC && load_store != THUMB_LOAD)
8750         {
8751           inst.error = _("r15 based store not allowed");
8752           return;
8753         }
8754       else if (Ro != FAIL)
8755         {
8756           inst.error = _("invalid base register for register offset");
8757           return;
8758         }
8759
8760       if (Rb == REG_PC)
8761         inst.instruction = T_OPCODE_LDR_PC;
8762       else if (load_store == THUMB_LOAD)
8763         inst.instruction = T_OPCODE_LDR_SP;
8764       else
8765         inst.instruction = T_OPCODE_STR_SP;
8766
8767       inst.instruction |= Rd << 8;
8768       if (inst.reloc.exp.X_op == O_constant)
8769         {
8770           unsigned offset = inst.reloc.exp.X_add_number;
8771
8772           if (offset & ~0x3fc)
8773             {
8774               inst.error = _("invalid offset");
8775               return;
8776             }
8777
8778           inst.instruction |= offset >> 2;
8779         }
8780       else
8781         inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8782     }
8783   else if (Rb > 7)
8784     {
8785       inst.error = _("invalid base register in load/store");
8786       return;
8787     }
8788   else if (Ro == FAIL)
8789     {
8790       /* Immediate offset.  */
8791       if (size == THUMB_WORD)
8792         inst.instruction = (load_store == THUMB_LOAD
8793                             ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
8794       else if (size == THUMB_HALFWORD)
8795         inst.instruction = (load_store == THUMB_LOAD
8796                             ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
8797       else
8798         inst.instruction = (load_store == THUMB_LOAD
8799                             ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
8800
8801       inst.instruction |= Rd | (Rb << 3);
8802
8803       if (inst.reloc.exp.X_op == O_constant)
8804         {
8805           unsigned offset = inst.reloc.exp.X_add_number;
8806
8807           if (offset & ~(0x1f << size))
8808             {
8809               inst.error = _("invalid offset");
8810               return;
8811             }
8812           inst.instruction |= (offset >> size) << 6;
8813         }
8814       else
8815         inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8816     }
8817   else
8818     {
8819       /* Register offset.  */
8820       if (size == THUMB_WORD)
8821         inst.instruction = (load_store == THUMB_LOAD
8822                             ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
8823       else if (size == THUMB_HALFWORD)
8824         inst.instruction = (load_store == THUMB_LOAD
8825                             ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
8826       else
8827         inst.instruction = (load_store == THUMB_LOAD
8828                             ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
8829
8830       inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
8831     }
8832
8833   end_of_line (str);
8834 }
8835
8836 /* A register must be given at this point.
8837
8838    Shift is the place to put it in inst.instruction.
8839
8840    Restores input start point on err.
8841    Returns the reg#, or FAIL.  */
8842
8843 static int
8844 mav_reg_required_here (str, shift, regtype)
8845      char ** str;
8846      int shift;
8847      enum arm_reg_type regtype;
8848 {
8849   int   reg;
8850   char *start = *str;
8851
8852   if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
8853     {
8854       if (shift >= 0)
8855         inst.instruction |= reg << shift;
8856
8857       return reg;
8858     }
8859
8860   /* Restore the start point.  */
8861   *str = start;
8862
8863   /* In the few cases where we might be able to accept something else
8864      this error can be overridden.  */
8865   inst.error = _(all_reg_maps[regtype].expected);
8866
8867   return FAIL;
8868 }
8869
8870 /* Cirrus Maverick Instructions.  */
8871
8872 /* Wrapper functions.  */
8873
8874 static void
8875 do_mav_binops_1a (str)
8876      char * str;
8877 {
8878   do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
8879 }
8880
8881 static void
8882 do_mav_binops_1b (str)
8883      char * str;
8884 {
8885   do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
8886 }
8887
8888 static void
8889 do_mav_binops_1c (str)
8890      char * str;
8891 {
8892   do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
8893 }
8894
8895 static void
8896 do_mav_binops_1d (str)
8897      char * str;
8898 {
8899   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
8900 }
8901
8902 static void
8903 do_mav_binops_1e (str)
8904      char * str;
8905 {
8906   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
8907 }
8908
8909 static void
8910 do_mav_binops_1f (str)
8911      char * str;
8912 {
8913   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
8914 }
8915
8916 static void
8917 do_mav_binops_1g (str)
8918      char * str;
8919 {
8920   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
8921 }
8922
8923 static void
8924 do_mav_binops_1h (str)
8925      char * str;
8926 {
8927   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
8928 }
8929
8930 static void
8931 do_mav_binops_1i (str)
8932      char * str;
8933 {
8934   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
8935 }
8936
8937 static void
8938 do_mav_binops_1j (str)
8939      char * str;
8940 {
8941   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
8942 }
8943
8944 static void
8945 do_mav_binops_1k (str)
8946      char * str;
8947 {
8948   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
8949 }
8950
8951 static void
8952 do_mav_binops_1l (str)
8953      char * str;
8954 {
8955   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
8956 }
8957
8958 static void
8959 do_mav_binops_1m (str)
8960      char * str;
8961 {
8962   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
8963 }
8964
8965 static void
8966 do_mav_binops_1n (str)
8967      char * str;
8968 {
8969   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
8970 }
8971
8972 static void
8973 do_mav_binops_1o (str)
8974      char * str;
8975 {
8976   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
8977 }
8978
8979 static void
8980 do_mav_binops_2a (str)
8981      char * str;
8982 {
8983   do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
8984 }
8985
8986 static void
8987 do_mav_binops_2b (str)
8988      char * str;
8989 {
8990   do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
8991 }
8992
8993 static void
8994 do_mav_binops_2c (str)
8995      char * str;
8996 {
8997   do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
8998 }
8999
9000 static void
9001 do_mav_binops_3a (str)
9002      char * str;
9003 {
9004   do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
9005 }
9006
9007 static void
9008 do_mav_binops_3b (str)
9009      char * str;
9010 {
9011   do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
9012 }
9013
9014 static void
9015 do_mav_binops_3c (str)
9016      char * str;
9017 {
9018   do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
9019 }
9020
9021 static void
9022 do_mav_binops_3d (str)
9023      char * str;
9024 {
9025   do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
9026 }
9027
9028 static void
9029 do_mav_triple_4a (str)
9030      char * str;
9031 {
9032   do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
9033 }
9034
9035 static void
9036 do_mav_triple_4b (str)
9037      char * str;
9038 {
9039   do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
9040 }
9041
9042 static void
9043 do_mav_triple_5a (str)
9044      char * str;
9045 {
9046   do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
9047 }
9048
9049 static void
9050 do_mav_triple_5b (str)
9051      char * str;
9052 {
9053   do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
9054 }
9055
9056 static void
9057 do_mav_triple_5c (str)
9058      char * str;
9059 {
9060   do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
9061 }
9062
9063 static void
9064 do_mav_triple_5d (str)
9065      char * str;
9066 {
9067   do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
9068 }
9069
9070 static void
9071 do_mav_triple_5e (str)
9072      char * str;
9073 {
9074   do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
9075 }
9076
9077 static void
9078 do_mav_triple_5f (str)
9079      char * str;
9080 {
9081   do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
9082 }
9083
9084 static void
9085 do_mav_triple_5g (str)
9086      char * str;
9087 {
9088   do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
9089 }
9090
9091 static void
9092 do_mav_triple_5h (str)
9093      char * str;
9094 {
9095   do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
9096 }
9097
9098 static void
9099 do_mav_quad_6a (str)
9100      char * str;
9101 {
9102   do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
9103              REG_TYPE_MVFX);
9104 }
9105
9106 static void
9107 do_mav_quad_6b (str)
9108      char * str;
9109 {
9110   do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
9111              REG_TYPE_MVFX);
9112 }
9113
9114 /* cfmvsc32<cond> DSPSC,MVFX[15:0].  */
9115 static void
9116 do_mav_dspsc_1 (str)
9117      char * str;
9118 {
9119   skip_whitespace (str);
9120
9121   /* cfmvsc32.  */
9122   if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
9123       || skip_past_comma (&str) == FAIL
9124       || mav_reg_required_here (&str, 16, REG_TYPE_MVFX) == FAIL)
9125     {
9126       if (!inst.error)
9127         inst.error = BAD_ARGS;
9128
9129       return;
9130     }
9131
9132   end_of_line (str);
9133 }
9134
9135 /* cfmv32sc<cond> MVFX[15:0],DSPSC.  */
9136 static void
9137 do_mav_dspsc_2 (str)
9138      char * str;
9139 {
9140   skip_whitespace (str);
9141
9142   /* cfmv32sc.  */
9143   if (mav_reg_required_here (&str, 0, REG_TYPE_MVFX) == FAIL
9144       || skip_past_comma (&str) == FAIL
9145       || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
9146     {
9147       if (!inst.error)
9148         inst.error = BAD_ARGS;
9149
9150       return;
9151     }
9152
9153   end_of_line (str);
9154 }
9155
9156 static void
9157 do_mav_shift_1 (str)
9158      char * str;
9159 {
9160   do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
9161 }
9162
9163 static void
9164 do_mav_shift_2 (str)
9165      char * str;
9166 {
9167   do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
9168 }
9169
9170 static void
9171 do_mav_ldst_1 (str)
9172      char * str;
9173 {
9174   do_mav_ldst (str, REG_TYPE_MVF);
9175 }
9176
9177 static void
9178 do_mav_ldst_2 (str)
9179      char * str;
9180 {
9181   do_mav_ldst (str, REG_TYPE_MVD);
9182 }
9183
9184 static void
9185 do_mav_ldst_3 (str)
9186      char * str;
9187 {
9188   do_mav_ldst (str, REG_TYPE_MVFX);
9189 }
9190
9191 static void
9192 do_mav_ldst_4 (str)
9193      char * str;
9194 {
9195   do_mav_ldst (str, REG_TYPE_MVDX);
9196 }
9197
9198 /* Isnsn like "foo X,Y".  */
9199
9200 static void
9201 do_mav_binops (str, mode, reg0, reg1)
9202      char * str;
9203      int mode;
9204      enum arm_reg_type reg0;
9205      enum arm_reg_type reg1;
9206 {
9207   int shift0, shift1;
9208
9209   shift0 = mode & 0xff;
9210   shift1 = (mode >> 8) & 0xff;
9211
9212   skip_whitespace (str);
9213
9214   if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9215       || skip_past_comma (&str) == FAIL
9216       || mav_reg_required_here (&str, shift1, reg1) == FAIL)
9217     {
9218       if (!inst.error)
9219         inst.error = BAD_ARGS;
9220     }
9221   else
9222     end_of_line (str);
9223 }
9224
9225 /* Isnsn like "foo X,Y,Z".  */
9226
9227 static void
9228 do_mav_triple (str, mode, reg0, reg1, reg2)
9229      char * str;
9230      int mode;
9231      enum arm_reg_type reg0;
9232      enum arm_reg_type reg1;
9233      enum arm_reg_type reg2;
9234 {
9235   int shift0, shift1, shift2;
9236
9237   shift0 = mode & 0xff;
9238   shift1 = (mode >> 8) & 0xff;
9239   shift2 = (mode >> 16) & 0xff;
9240
9241   skip_whitespace (str);
9242
9243   if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9244       || skip_past_comma (&str) == FAIL
9245       || mav_reg_required_here (&str, shift1, reg1) == FAIL
9246       || skip_past_comma (&str) == FAIL
9247       || mav_reg_required_here (&str, shift2, reg2) == FAIL)
9248     {
9249       if (!inst.error)
9250         inst.error = BAD_ARGS;
9251     }
9252   else
9253     end_of_line (str);
9254 }
9255
9256 /* Isnsn like "foo W,X,Y,Z".
9257     where W=MVAX[0:3] and X,Y,Z=MVFX[0:15].  */
9258
9259 static void
9260 do_mav_quad (str, mode, reg0, reg1, reg2, reg3)
9261      char * str;
9262      int mode;
9263      enum arm_reg_type reg0;
9264      enum arm_reg_type reg1;
9265      enum arm_reg_type reg2;
9266      enum arm_reg_type reg3;
9267 {
9268   int shift0, shift1, shift2, shift3;
9269
9270   shift0= mode & 0xff;
9271   shift1 = (mode >> 8) & 0xff;
9272   shift2 = (mode >> 16) & 0xff;
9273   shift3 = (mode >> 24) & 0xff;
9274
9275   skip_whitespace (str);
9276
9277   if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9278       || skip_past_comma (&str) == FAIL
9279       || mav_reg_required_here (&str, shift1, reg1) == FAIL
9280       || skip_past_comma (&str) == FAIL
9281       || mav_reg_required_here (&str, shift2, reg2) == FAIL
9282       || skip_past_comma (&str) == FAIL
9283       || mav_reg_required_here (&str, shift3, reg3) == FAIL)
9284     {
9285       if (!inst.error)
9286         inst.error = BAD_ARGS;
9287     }
9288   else
9289     end_of_line (str);
9290 }
9291
9292 /* Maverick shift immediate instructions.
9293    cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9294    cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0].  */
9295
9296 static void
9297 do_mav_shift (str, reg0, reg1)
9298      char * str;
9299      enum arm_reg_type reg0;
9300      enum arm_reg_type reg1;
9301 {
9302   int error;
9303   int imm, neg = 0;
9304
9305   skip_whitespace (str);
9306
9307   error = 0;
9308
9309   if (mav_reg_required_here (&str, 12, reg0) == FAIL
9310       || skip_past_comma (&str) == FAIL
9311       || mav_reg_required_here (&str, 16, reg1) == FAIL
9312       || skip_past_comma  (&str) == FAIL)
9313     {
9314       if (!inst.error)
9315         inst.error = BAD_ARGS;
9316       return;
9317     }
9318
9319   /* Calculate the immediate operand.
9320      The operand is a 7bit signed number.  */
9321   skip_whitespace (str);
9322
9323   if (*str == '#')
9324     ++str;
9325
9326   if (!ISDIGIT (*str) && *str != '-')
9327     {
9328       inst.error = _("expecting immediate, 7bit operand");
9329       return;
9330     }
9331
9332   if (*str == '-')
9333     {
9334       neg = 1;
9335       ++str;
9336     }
9337
9338   for (imm = 0; *str && ISDIGIT (*str); ++str)
9339     imm = imm * 10 + *str - '0';
9340
9341   if (imm > 64)
9342     {
9343       inst.error = _("immediate out of range");
9344       return;
9345     }
9346
9347   /* Make negative imm's into 7bit signed numbers.  */
9348   if (neg)
9349     {
9350       imm = -imm;
9351       imm &= 0x0000007f;
9352     }
9353
9354   /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9355      Bits 5-7 of the insn should have bits 4-6 of the immediate.
9356      Bit 4 should be 0.  */
9357   imm = (imm & 0xf) | ((imm & 0x70) << 1);
9358
9359   inst.instruction |= imm;
9360   end_of_line (str);
9361 }
9362
9363 static int
9364 mav_parse_offset (str, negative)
9365      char ** str;
9366      int *negative;
9367 {
9368   char * p = *str;
9369   int offset;
9370
9371   *negative = 0;
9372
9373   skip_whitespace (p);
9374
9375   if (*p == '#')
9376     ++p;
9377
9378   if (*p == '-')
9379     {
9380       *negative = 1;
9381       ++p;
9382     }
9383
9384   if (!ISDIGIT (*p))
9385     {
9386       inst.error = _("offset expected");
9387       return 0;
9388     }
9389
9390   for (offset = 0; *p && ISDIGIT (*p); ++p)
9391     offset = offset * 10 + *p - '0';
9392
9393   if (offset > 0xff)
9394     {
9395       inst.error = _("offset out of range");
9396       return 0;
9397     }
9398
9399   *str = p;
9400
9401   return *negative ? -offset : offset;
9402 }
9403
9404 /* Maverick load/store instructions.
9405   <insn><cond> CRd,[Rn,<offset>]{!}.
9406   <insn><cond> CRd,[Rn],<offset>.  */
9407
9408 static void
9409 do_mav_ldst (str, reg0)
9410      char * str;
9411      enum arm_reg_type reg0;
9412 {
9413   int offset, negative;
9414
9415   skip_whitespace (str);
9416
9417   if (mav_reg_required_here (&str, 12, reg0) == FAIL
9418       || skip_past_comma (&str) == FAIL
9419       || *str++ != '['
9420       || reg_required_here (&str, 16) == FAIL)
9421     goto fail_ldst;
9422
9423   if (skip_past_comma (&str) == SUCCESS)
9424     {
9425       /* You are here: "<offset>]{!}".  */
9426       inst.instruction |= PRE_INDEX;
9427
9428       offset = mav_parse_offset (&str, &negative);
9429
9430       if (inst.error)
9431         return;
9432
9433       if (*str++ != ']')
9434         {
9435           inst.error = _("missing ]");
9436           return;
9437         }
9438
9439       if (*str == '!')
9440         {
9441           inst.instruction |= WRITE_BACK;
9442           ++str;
9443         }
9444     }
9445   else
9446     {
9447       /* You are here: "], <offset>".  */
9448       if (*str++ != ']')
9449         {
9450           inst.error = _("missing ]");
9451           return;
9452         }
9453
9454       if (skip_past_comma (&str) == FAIL
9455           || (offset = mav_parse_offset (&str, &negative), inst.error))
9456         goto fail_ldst;
9457
9458       inst.instruction |= CP_T_WB; /* Post indexed, set bit W.  */
9459     }
9460
9461   if (negative)
9462     offset = -offset;
9463   else
9464     inst.instruction |= CP_T_UD; /* Postive, so set bit U.  */
9465
9466   inst.instruction |= offset >> 2;
9467   end_of_line (str);
9468   return;
9469
9470 fail_ldst:
9471   if (!inst.error)
9472      inst.error = BAD_ARGS;
9473   return;
9474 }
9475
9476 static void
9477 do_t_nop (str)
9478      char * str;
9479 {
9480   /* Do nothing.  */
9481   end_of_line (str);
9482   return;
9483 }
9484
9485 /* Handle the Format 4 instructions that do not have equivalents in other
9486    formats.  That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9487    BIC and MVN.  */
9488
9489 static void
9490 do_t_arit (str)
9491      char * str;
9492 {
9493   int Rd, Rs, Rn;
9494
9495   skip_whitespace (str);
9496
9497   if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9498       || skip_past_comma (&str) == FAIL
9499       || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9500     {
9501       inst.error = BAD_ARGS;
9502       return;
9503     }
9504
9505   if (skip_past_comma (&str) != FAIL)
9506     {
9507       /* Three operand format not allowed for TST, CMN, NEG and MVN.
9508          (It isn't allowed for CMP either, but that isn't handled by this
9509          function.)  */
9510       if (inst.instruction == T_OPCODE_TST
9511           || inst.instruction == T_OPCODE_CMN
9512           || inst.instruction == T_OPCODE_NEG
9513           || inst.instruction == T_OPCODE_MVN)
9514         {
9515           inst.error = BAD_ARGS;
9516           return;
9517         }
9518
9519       if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9520         return;
9521
9522       if (Rs != Rd)
9523         {
9524           inst.error = _("dest and source1 must be the same register");
9525           return;
9526         }
9527       Rs = Rn;
9528     }
9529
9530   if (inst.instruction == T_OPCODE_MUL
9531       && Rs == Rd)
9532     as_tsktsk (_("Rs and Rd must be different in MUL"));
9533
9534   inst.instruction |= Rd | (Rs << 3);
9535   end_of_line (str);
9536 }
9537
9538 static void
9539 do_t_add (str)
9540      char * str;
9541 {
9542   thumb_add_sub (str, 0);
9543 }
9544
9545 static void
9546 do_t_asr (str)
9547      char * str;
9548 {
9549   thumb_shift (str, THUMB_ASR);
9550 }
9551
9552 static void
9553 do_t_branch9 (str)
9554      char * str;
9555 {
9556   if (my_get_expression (&inst.reloc.exp, &str))
9557     return;
9558   inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
9559   inst.reloc.pc_rel = 1;
9560   end_of_line (str);
9561 }
9562
9563 static void
9564 do_t_branch12 (str)
9565      char * str;
9566 {
9567   if (my_get_expression (&inst.reloc.exp, &str))
9568     return;
9569   inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
9570   inst.reloc.pc_rel = 1;
9571   end_of_line (str);
9572 }
9573
9574 /* Find the real, Thumb encoded start of a Thumb function.  */
9575
9576 static symbolS *
9577 find_real_start (symbolP)
9578      symbolS * symbolP;
9579 {
9580   char *       real_start;
9581   const char * name = S_GET_NAME (symbolP);
9582   symbolS *    new_target;
9583
9584   /* This definiton must agree with the one in gcc/config/arm/thumb.c.  */
9585 #define STUB_NAME ".real_start_of"
9586
9587   if (name == NULL)
9588     abort ();
9589
9590   /* Names that start with '.' are local labels, not function entry points.
9591      The compiler may generate BL instructions to these labels because it
9592      needs to perform a branch to a far away location.  */
9593   if (name[0] == '.')
9594     return symbolP;
9595
9596   real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
9597   sprintf (real_start, "%s%s", STUB_NAME, name);
9598
9599   new_target = symbol_find (real_start);
9600
9601   if (new_target == NULL)
9602     {
9603       as_warn ("Failed to find real start of function: %s\n", name);
9604       new_target = symbolP;
9605     }
9606
9607   free (real_start);
9608
9609   return new_target;
9610 }
9611
9612 static void
9613 do_t_branch23 (str)
9614      char * str;
9615 {
9616   if (my_get_expression (& inst.reloc.exp, & str))
9617     return;
9618
9619   inst.reloc.type   = BFD_RELOC_THUMB_PCREL_BRANCH23;
9620   inst.reloc.pc_rel = 1;
9621   end_of_line (str);
9622
9623   /* If the destination of the branch is a defined symbol which does not have
9624      the THUMB_FUNC attribute, then we must be calling a function which has
9625      the (interfacearm) attribute.  We look for the Thumb entry point to that
9626      function and change the branch to refer to that function instead.  */
9627   if (   inst.reloc.exp.X_op == O_symbol
9628       && inst.reloc.exp.X_add_symbol != NULL
9629       && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
9630       && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
9631     inst.reloc.exp.X_add_symbol =
9632       find_real_start (inst.reloc.exp.X_add_symbol);
9633 }
9634
9635 static void
9636 do_t_bx (str)
9637      char * str;
9638 {
9639   int reg;
9640
9641   skip_whitespace (str);
9642
9643   if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9644     return;
9645
9646   /* This sets THUMB_H2 from the top bit of reg.  */
9647   inst.instruction |= reg << 3;
9648
9649   /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC.  The reloc
9650      should cause the alignment to be checked once it is known.  This is
9651      because BX PC only works if the instruction is word aligned.  */
9652
9653   end_of_line (str);
9654 }
9655
9656 static void
9657 do_t_compare (str)
9658      char * str;
9659 {
9660   thumb_mov_compare (str, THUMB_COMPARE);
9661 }
9662
9663 static void
9664 do_t_ldmstm (str)
9665      char * str;
9666 {
9667   int Rb;
9668   long range;
9669
9670   skip_whitespace (str);
9671
9672   if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9673     return;
9674
9675   if (*str != '!')
9676     as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9677   else
9678     str++;
9679
9680   if (skip_past_comma (&str) == FAIL
9681       || (range = reg_list (&str)) == FAIL)
9682     {
9683       if (! inst.error)
9684         inst.error = BAD_ARGS;
9685       return;
9686     }
9687
9688   if (inst.reloc.type != BFD_RELOC_NONE)
9689     {
9690       /* This really doesn't seem worth it.  */
9691       inst.reloc.type = BFD_RELOC_NONE;
9692       inst.error = _("expression too complex");
9693       return;
9694     }
9695
9696   if (range & ~0xff)
9697     {
9698       inst.error = _("only lo-regs valid in load/store multiple");
9699       return;
9700     }
9701
9702   inst.instruction |= (Rb << 8) | range;
9703   end_of_line (str);
9704 }
9705
9706 static void
9707 do_t_ldr (str)
9708      char * str;
9709 {
9710   thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
9711 }
9712
9713 static void
9714 do_t_ldrb (str)
9715      char * str;
9716 {
9717   thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
9718 }
9719
9720 static void
9721 do_t_ldrh (str)
9722      char * str;
9723 {
9724   thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
9725 }
9726
9727 static void
9728 do_t_lds (str)
9729      char * str;
9730 {
9731   int Rd, Rb, Ro;
9732
9733   skip_whitespace (str);
9734
9735   if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9736       || skip_past_comma (&str) == FAIL
9737       || *str++ != '['
9738       || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9739       || skip_past_comma (&str) == FAIL
9740       || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9741       || *str++ != ']')
9742     {
9743       if (! inst.error)
9744         inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
9745       return;
9746     }
9747
9748   inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
9749   end_of_line (str);
9750 }
9751
9752 static void
9753 do_t_lsl (str)
9754      char * str;
9755 {
9756   thumb_shift (str, THUMB_LSL);
9757 }
9758
9759 static void
9760 do_t_lsr (str)
9761      char * str;
9762 {
9763   thumb_shift (str, THUMB_LSR);
9764 }
9765
9766 static void
9767 do_t_mov (str)
9768      char * str;
9769 {
9770   thumb_mov_compare (str, THUMB_MOVE);
9771 }
9772
9773 static void
9774 do_t_push_pop (str)
9775      char * str;
9776 {
9777   long range;
9778
9779   skip_whitespace (str);
9780
9781   if ((range = reg_list (&str)) == FAIL)
9782     {
9783       if (! inst.error)
9784         inst.error = BAD_ARGS;
9785       return;
9786     }
9787
9788   if (inst.reloc.type != BFD_RELOC_NONE)
9789     {
9790       /* This really doesn't seem worth it.  */
9791       inst.reloc.type = BFD_RELOC_NONE;
9792       inst.error = _("expression too complex");
9793       return;
9794     }
9795
9796   if (range & ~0xff)
9797     {
9798       if ((inst.instruction == T_OPCODE_PUSH
9799            && (range & ~0xff) == 1 << REG_LR)
9800           || (inst.instruction == T_OPCODE_POP
9801               && (range & ~0xff) == 1 << REG_PC))
9802         {
9803           inst.instruction |= THUMB_PP_PC_LR;
9804           range &= 0xff;
9805         }
9806       else
9807         {
9808           inst.error = _("invalid register list to push/pop instruction");
9809           return;
9810         }
9811     }
9812
9813   inst.instruction |= range;
9814   end_of_line (str);
9815 }
9816
9817 static void
9818 do_t_str (str)
9819      char * str;
9820 {
9821   thumb_load_store (str, THUMB_STORE, THUMB_WORD);
9822 }
9823
9824 static void
9825 do_t_strb (str)
9826      char * str;
9827 {
9828   thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
9829 }
9830
9831 static void
9832 do_t_strh (str)
9833      char * str;
9834 {
9835   thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
9836 }
9837
9838 static void
9839 do_t_sub (str)
9840      char * str;
9841 {
9842   thumb_add_sub (str, 1);
9843 }
9844
9845 static void
9846 do_t_swi (str)
9847      char * str;
9848 {
9849   skip_whitespace (str);
9850
9851   if (my_get_expression (&inst.reloc.exp, &str))
9852     return;
9853
9854   inst.reloc.type = BFD_RELOC_ARM_SWI;
9855   end_of_line (str);
9856   return;
9857 }
9858
9859 static void
9860 do_t_adr (str)
9861      char * str;
9862 {
9863   int reg;
9864
9865   /* This is a pseudo-op of the form "adr rd, label" to be converted
9866      into a relative address of the form "add rd, pc, #label-.-4".  */
9867   skip_whitespace (str);
9868
9869   /* Store Rd in temporary location inside instruction.  */
9870   if ((reg = reg_required_here (&str, 4)) == FAIL
9871       || (reg > 7)  /* For Thumb reg must be r0..r7.  */
9872       || skip_past_comma (&str) == FAIL
9873       || my_get_expression (&inst.reloc.exp, &str))
9874     {
9875       if (!inst.error)
9876         inst.error = BAD_ARGS;
9877       return;
9878     }
9879
9880   inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9881   inst.reloc.exp.X_add_number -= 4; /* PC relative adjust.  */
9882   inst.reloc.pc_rel = 1;
9883   inst.instruction |= REG_PC; /* Rd is already placed into the instruction.  */
9884
9885   end_of_line (str);
9886 }
9887
9888 static void
9889 insert_reg (r, htab)
9890      const struct reg_entry *r;
9891      struct hash_control *htab;
9892 {
9893   int    len  = strlen (r->name) + 2;
9894   char * buf  = (char *) xmalloc (len);
9895   char * buf2 = (char *) xmalloc (len);
9896   int    i    = 0;
9897
9898 #ifdef REGISTER_PREFIX
9899   buf[i++] = REGISTER_PREFIX;
9900 #endif
9901
9902   strcpy (buf + i, r->name);
9903
9904   for (i = 0; buf[i]; i++)
9905     buf2[i] = TOUPPER (buf[i]);
9906
9907   buf2[i] = '\0';
9908
9909   hash_insert (htab, buf,  (PTR) r);
9910   hash_insert (htab, buf2, (PTR) r);
9911 }
9912
9913 static void
9914 build_reg_hsh (map)
9915      struct reg_map *map;
9916 {
9917   const struct reg_entry *r;
9918
9919   if ((map->htab = hash_new ()) == NULL)
9920     as_fatal (_("virtual memory exhausted"));
9921
9922   for (r = map->names; r->name != NULL; r++)
9923     insert_reg (r, map->htab);
9924 }
9925
9926 static void
9927 insert_reg_alias (str, regnum, htab)
9928      char *str;
9929      int regnum;
9930      struct hash_control *htab;
9931 {
9932   struct reg_entry *new =
9933     (struct reg_entry *) xmalloc (sizeof (struct reg_entry));
9934   char *name = xmalloc (strlen (str) + 1);
9935   strcpy (name, str);
9936
9937   new->name = name;
9938   new->number = regnum;
9939
9940   hash_insert (htab, name, (PTR) new);
9941 }
9942
9943 /* Look for the .req directive.  This is of the form:
9944
9945         newname .req existing_name
9946
9947    If we find one, or if it looks sufficiently like one that we want to
9948    handle any error here, return non-zero.  Otherwise return zero.  */
9949 static int
9950 create_register_alias (newname, p)
9951      char *newname;
9952      char *p;
9953 {
9954   char *q;
9955   char c;
9956
9957   q = p;
9958   skip_whitespace (q);
9959
9960   c = *p;
9961   *p = '\0';
9962
9963   if (*q && !strncmp (q, ".req ", 5))
9964     {
9965       char *copy_of_str;
9966       char *r;
9967
9968 #ifdef IGNORE_OPCODE_CASE
9969       newname = original_case_string;
9970 #endif
9971       copy_of_str = newname;
9972
9973       q += 4;
9974       skip_whitespace (q);
9975
9976       for (r = q; *r != '\0'; r++)
9977         if (*r == ' ')
9978           break;
9979
9980       if (r != q)
9981         {
9982           enum arm_reg_type new_type, old_type;
9983           int old_regno;
9984           char d = *r;
9985
9986           *r = '\0';
9987           old_type = arm_reg_parse_any (q);
9988           *r = d;
9989
9990           new_type = arm_reg_parse_any (newname);
9991
9992           if (new_type == REG_TYPE_MAX)
9993             {
9994               if (old_type != REG_TYPE_MAX)
9995                 {
9996                   old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
9997                   insert_reg_alias (newname, old_regno,
9998                                     all_reg_maps[old_type].htab);
9999                 }
10000               else
10001                 as_warn (_("register '%s' does not exist\n"), q);
10002             }
10003           else if (old_type == REG_TYPE_MAX)
10004             {
10005               as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
10006                        copy_of_str, q);
10007             }
10008           else
10009             {
10010               /* Do not warn about redefinitions to the same alias.  */
10011               if (new_type != old_type
10012                   || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
10013                       != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
10014                 as_warn (_("ignoring redefinition of register alias '%s'"),
10015                          copy_of_str);
10016
10017             }
10018         }
10019       else
10020         as_warn (_("ignoring incomplete .req pseuso op"));
10021
10022       *p = c;
10023       return 1;
10024     }
10025   *p = c;
10026   return 0;
10027 }
10028
10029 static void
10030 set_constant_flonums ()
10031 {
10032   int i;
10033
10034   for (i = 0; i < NUM_FLOAT_VALS; i++)
10035     if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
10036       abort ();
10037 }
10038
10039 /* Iterate over the base tables to create the instruction patterns.  */
10040 static void
10041 build_arm_ops_hsh ()
10042 {
10043   unsigned int i;
10044   unsigned int j;
10045   static struct obstack insn_obstack;
10046
10047   obstack_begin (&insn_obstack, 4000);
10048
10049   for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
10050     {
10051       const struct asm_opcode *insn = insns + i;
10052
10053       if (insn->cond_offset != 0)
10054         {
10055           /* Insn supports conditional execution.  Build the varaints
10056              and insert them in the hash table.  */
10057           for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
10058             {
10059               unsigned len = strlen (insn->template);
10060               struct asm_opcode *new;
10061               char *template;
10062
10063               new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
10064               /* All condition codes are two characters.  */
10065               template = obstack_alloc (&insn_obstack, len + 3);
10066
10067               strncpy (template, insn->template, insn->cond_offset);
10068               strcpy (template + insn->cond_offset, conds[j].template);
10069               if (len > insn->cond_offset)
10070                 strcpy (template + insn->cond_offset + 2,
10071                         insn->template + insn->cond_offset);
10072               new->template = template;
10073               new->cond_offset = 0;
10074               new->variant = insn->variant;
10075               new->parms = insn->parms;
10076               new->value = (insn->value & ~COND_MASK) | conds[j].value;
10077
10078               hash_insert (arm_ops_hsh, new->template, (PTR) new);
10079             }
10080         }
10081       /* Finally, insert the unconditional insn in the table directly;
10082          no need to build a copy.  */
10083       hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
10084     }
10085 }
10086
10087 #if defined OBJ_ELF || defined OBJ_COFF
10088
10089 #ifdef OBJ_ELF
10090 #define arm_Note Elf_External_Note
10091 #else
10092 typedef struct
10093 {
10094   unsigned char namesz[4];      /* Size of entry's owner string.  */
10095   unsigned char descsz[4];      /* Size of the note descriptor.  */
10096   unsigned char type[4];        /* Interpretation of the descriptor.  */
10097   char          name[1];        /* Start of the name+desc data.  */
10098 } arm_Note;
10099 #endif
10100
10101 /* The description is kept to a fix sized in order to make updating
10102    it and merging it easier.  */
10103 #define ARM_NOTE_DESCRIPTION_LENGTH     8
10104
10105 static void
10106 arm_add_note (name, description, type)
10107      const char * name;
10108      const char * description;
10109      unsigned int type;
10110 {
10111   arm_Note     note ATTRIBUTE_UNUSED;
10112   char *       p;
10113   unsigned int name_len;
10114
10115   name_len = (strlen (name) + 1 + 3) & ~3;
10116   
10117   p = frag_more (sizeof (note.namesz));
10118   md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
10119
10120   p = frag_more (sizeof (note.descsz));
10121   md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
10122
10123   p = frag_more (sizeof (note.type));
10124   md_number_to_chars (p, (valueT) type, sizeof (note.type));
10125
10126   p = frag_more (name_len);
10127   strcpy (p, name);
10128
10129   p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
10130   strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
10131   frag_align (2, 0, 0);
10132 }
10133 #endif
10134
10135 void
10136 md_begin ()
10137 {
10138   unsigned mach;
10139   unsigned int i;
10140
10141   if (   (arm_ops_hsh = hash_new ()) == NULL
10142       || (arm_tops_hsh = hash_new ()) == NULL
10143       || (arm_cond_hsh = hash_new ()) == NULL
10144       || (arm_shift_hsh = hash_new ()) == NULL
10145       || (arm_psr_hsh = hash_new ()) == NULL)
10146     as_fatal (_("virtual memory exhausted"));
10147
10148   build_arm_ops_hsh ();
10149   for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
10150     hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
10151   for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
10152     hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
10153   for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
10154     hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
10155   for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
10156     hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
10157
10158   for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
10159     build_reg_hsh (all_reg_maps + i);
10160
10161   set_constant_flonums ();
10162
10163   /* Set the cpu variant based on the command-line options.  We prefer
10164      -mcpu= over -march= if both are set (as for GCC); and we prefer
10165      -mfpu= over any other way of setting the floating point unit.
10166      Use of legacy options with new options are faulted.  */
10167   if (legacy_cpu != -1)
10168     {
10169       if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
10170         as_bad (_("use of old and new-style options to set CPU type"));
10171
10172       mcpu_cpu_opt = legacy_cpu;
10173     }
10174   else if (mcpu_cpu_opt == -1)
10175     mcpu_cpu_opt = march_cpu_opt;
10176
10177   if (legacy_fpu != -1)
10178     {
10179       if (mfpu_opt != -1)
10180         as_bad (_("use of old and new-style options to set FPU type"));
10181
10182       mfpu_opt = legacy_fpu;
10183     }
10184   else if (mfpu_opt == -1)
10185     {
10186       if (mcpu_fpu_opt != -1)
10187         mfpu_opt = mcpu_fpu_opt;
10188       else
10189         mfpu_opt = march_fpu_opt;
10190     }
10191
10192   if (mfpu_opt == -1)
10193     {
10194       if (mcpu_cpu_opt == -1)
10195         mfpu_opt = FPU_DEFAULT;
10196       else if (mcpu_cpu_opt & ARM_EXT_V5)
10197         mfpu_opt = FPU_ARCH_VFP_V2;
10198       else
10199         mfpu_opt = FPU_ARCH_FPA;
10200     }
10201
10202   if (mcpu_cpu_opt == -1)
10203     mcpu_cpu_opt = CPU_DEFAULT;
10204
10205   cpu_variant = mcpu_cpu_opt | mfpu_opt;
10206
10207 #if defined OBJ_COFF || defined OBJ_ELF
10208   {
10209     unsigned int flags = 0;
10210
10211     /* Set the flags in the private structure.  */
10212     if (uses_apcs_26)      flags |= F_APCS26;
10213     if (support_interwork) flags |= F_INTERWORK;
10214     if (uses_apcs_float)   flags |= F_APCS_FLOAT;
10215     if (pic_code)          flags |= F_PIC;
10216     if ((cpu_variant & FPU_ANY) == FPU_NONE
10217         || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only.  */
10218       flags |= F_SOFT_FLOAT;
10219     /* Using VFP conventions (even if soft-float).  */
10220     if (cpu_variant & FPU_VFP_EXT_NONE) flags |= F_VFP_FLOAT;
10221
10222 #if defined OBJ_ELF
10223     if (cpu_variant & ARM_CEXT_MAVERICK)
10224       {
10225         flags ^= F_SOFT_FLOAT;
10226         flags |= EF_ARM_MAVERICK_FLOAT;
10227       }
10228 #endif
10229
10230     bfd_set_private_flags (stdoutput, flags);
10231
10232     /* We have run out flags in the COFF header to encode the
10233        status of ATPCS support, so instead we create a dummy,
10234        empty, debug section called .arm.atpcs.  */
10235     if (atpcs)
10236       {
10237         asection * sec;
10238
10239         sec = bfd_make_section (stdoutput, ".arm.atpcs");
10240
10241         if (sec != NULL)
10242           {
10243             bfd_set_section_flags
10244               (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
10245             bfd_set_section_size (stdoutput, sec, 0);
10246             bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
10247           }
10248       }
10249   }
10250 #endif
10251
10252   /* Record the CPU type as well.  */
10253   switch (cpu_variant & ARM_CPU_MASK)
10254     {
10255     case ARM_2:
10256       mach = bfd_mach_arm_2;
10257       break;
10258
10259     case ARM_3:                 /* Also ARM_250.  */
10260       mach = bfd_mach_arm_2a;
10261       break;
10262
10263     case ARM_6:                 /* Also ARM_7.  */
10264       mach = bfd_mach_arm_3;
10265       break;
10266
10267     default:
10268       mach = bfd_mach_arm_unknown;
10269       break;
10270     }
10271
10272   /* Catch special cases.  */
10273   if (cpu_variant & ARM_CEXT_IWMMXT)
10274     mach = bfd_mach_arm_iWMMXt;
10275   else if (cpu_variant & ARM_CEXT_XSCALE)
10276     mach = bfd_mach_arm_XScale;
10277   else if (cpu_variant & ARM_CEXT_MAVERICK)
10278     mach = bfd_mach_arm_ep9312;
10279   else if (cpu_variant & ARM_EXT_V5E)
10280     mach = bfd_mach_arm_5TE;
10281   else if (cpu_variant & ARM_EXT_V5)
10282     {
10283       if (cpu_variant & ARM_EXT_V4T)
10284         mach = bfd_mach_arm_5T;
10285       else
10286         mach = bfd_mach_arm_5;
10287     }
10288   else if (cpu_variant & ARM_EXT_V4)
10289     {
10290       if (cpu_variant & ARM_EXT_V4T)
10291         mach = bfd_mach_arm_4T;
10292       else
10293         mach = bfd_mach_arm_4;
10294     }
10295   else if (cpu_variant & ARM_EXT_V3M)
10296     mach = bfd_mach_arm_3M;
10297
10298 #if 0 /* Suppressed - for now.  */
10299 #if defined (OBJ_ELF) || defined (OBJ_COFF)
10300
10301   /* Create a .note section to fully identify this arm binary.  */
10302
10303 #define NOTE_ARCH_STRING        "arch: "
10304
10305 #if defined OBJ_COFF && ! defined NT_VERSION
10306 #define NT_VERSION  1
10307 #define NT_ARCH     2
10308 #endif
10309   
10310   {
10311     segT current_seg = now_seg;
10312     subsegT current_subseg = now_subseg;
10313     asection * arm_arch;
10314     const char * arch_string;
10315
10316     arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
10317
10318 #ifdef OBJ_COFF
10319     bfd_set_section_flags (stdoutput, arm_arch,
10320                            SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
10321                            | SEC_HAS_CONTENTS);
10322 #endif
10323     arm_arch->output_section = arm_arch;
10324     subseg_set (arm_arch, 0);
10325
10326     switch (mach)
10327       {
10328       default:
10329       case bfd_mach_arm_unknown: arch_string = "unknown"; break;
10330       case bfd_mach_arm_2:       arch_string = "armv2"; break;
10331       case bfd_mach_arm_2a:      arch_string = "armv2a"; break;
10332       case bfd_mach_arm_3:       arch_string = "armv3"; break;
10333       case bfd_mach_arm_3M:      arch_string = "armv3M"; break;
10334       case bfd_mach_arm_4:       arch_string = "armv4"; break;
10335       case bfd_mach_arm_4T:      arch_string = "armv4t"; break;
10336       case bfd_mach_arm_5:       arch_string = "armv5"; break;
10337       case bfd_mach_arm_5T:      arch_string = "armv5t"; break;
10338       case bfd_mach_arm_5TE:     arch_string = "armv5te"; break;
10339       case bfd_mach_arm_XScale:  arch_string = "XScale"; break;
10340       case bfd_mach_arm_ep9312:  arch_string = "ep9312"; break;
10341       case bfd_mach_arm_iWMMXt:  arch_string = "iWMMXt"; break; 
10342       }
10343
10344     arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
10345
10346     subseg_set (current_seg, current_subseg);
10347   }
10348 #endif
10349 #endif /* Suppressed code.  */
10350   
10351   bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
10352 }
10353
10354 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
10355    for use in the a.out file, and stores them in the array pointed to by buf.
10356    This knows about the endian-ness of the target machine and does
10357    THE RIGHT THING, whatever it is.  Possible values for n are 1 (byte)
10358    2 (short) and 4 (long)  Floating numbers are put out as a series of
10359    LITTLENUMS (shorts, here at least).  */
10360
10361 void
10362 md_number_to_chars (buf, val, n)
10363      char * buf;
10364      valueT val;
10365      int    n;
10366 {
10367   if (target_big_endian)
10368     number_to_chars_bigendian (buf, val, n);
10369   else
10370     number_to_chars_littleendian (buf, val, n);
10371 }
10372
10373 static valueT
10374 md_chars_to_number (buf, n)
10375      char * buf;
10376      int    n;
10377 {
10378   valueT result = 0;
10379   unsigned char * where = (unsigned char *) buf;
10380
10381   if (target_big_endian)
10382     {
10383       while (n--)
10384         {
10385           result <<= 8;
10386           result |= (*where++ & 255);
10387         }
10388     }
10389   else
10390     {
10391       while (n--)
10392         {
10393           result <<= 8;
10394           result |= (where[n] & 255);
10395         }
10396     }
10397
10398   return result;
10399 }
10400
10401 /* Turn a string in input_line_pointer into a floating point constant
10402    of type TYPE, and store the appropriate bytes in *LITP.  The number
10403    of LITTLENUMS emitted is stored in *SIZEP.  An error message is
10404    returned, or NULL on OK.
10405
10406    Note that fp constants aren't represent in the normal way on the ARM.
10407    In big endian mode, things are as expected.  However, in little endian
10408    mode fp constants are big-endian word-wise, and little-endian byte-wise
10409    within the words.  For example, (double) 1.1 in big endian mode is
10410    the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
10411    the byte sequence 99 99 f1 3f 9a 99 99 99.
10412
10413    ??? The format of 12 byte floats is uncertain according to gcc's arm.h.  */
10414
10415 char *
10416 md_atof (type, litP, sizeP)
10417      char   type;
10418      char * litP;
10419      int *  sizeP;
10420 {
10421   int prec;
10422   LITTLENUM_TYPE words[MAX_LITTLENUMS];
10423   char *t;
10424   int i;
10425
10426   switch (type)
10427     {
10428     case 'f':
10429     case 'F':
10430     case 's':
10431     case 'S':
10432       prec = 2;
10433       break;
10434
10435     case 'd':
10436     case 'D':
10437     case 'r':
10438     case 'R':
10439       prec = 4;
10440       break;
10441
10442     case 'x':
10443     case 'X':
10444       prec = 6;
10445       break;
10446
10447     case 'p':
10448     case 'P':
10449       prec = 6;
10450       break;
10451
10452     default:
10453       *sizeP = 0;
10454       return _("bad call to MD_ATOF()");
10455     }
10456
10457   t = atof_ieee (input_line_pointer, type, words);
10458   if (t)
10459     input_line_pointer = t;
10460   *sizeP = prec * 2;
10461
10462   if (target_big_endian)
10463     {
10464       for (i = 0; i < prec; i++)
10465         {
10466           md_number_to_chars (litP, (valueT) words[i], 2);
10467           litP += 2;
10468         }
10469     }
10470   else
10471     {
10472       if (cpu_variant & FPU_ARCH_VFP)
10473         for (i = prec - 1; i >= 0; i--)
10474           {
10475             md_number_to_chars (litP, (valueT) words[i], 2);
10476             litP += 2;
10477           }
10478       else
10479         /* For a 4 byte float the order of elements in `words' is 1 0.
10480            For an 8 byte float the order is 1 0 3 2.  */
10481         for (i = 0; i < prec; i += 2)
10482           {
10483             md_number_to_chars (litP, (valueT) words[i + 1], 2);
10484             md_number_to_chars (litP + 2, (valueT) words[i], 2);
10485             litP += 4;
10486           }
10487     }
10488
10489   return 0;
10490 }
10491
10492 /* The knowledge of the PC's pipeline offset is built into the insns
10493    themselves.  */
10494
10495 long
10496 md_pcrel_from (fixP)
10497      fixS * fixP;
10498 {
10499   if (fixP->fx_addsy
10500       && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
10501       && fixP->fx_subsy == NULL)
10502     return 0;
10503
10504   if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
10505     {
10506       /* PC relative addressing on the Thumb is slightly odd
10507          as the bottom two bits of the PC are forced to zero
10508          for the calculation.  */
10509       return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
10510     }
10511
10512 #ifdef TE_WINCE
10513   /* The pattern was adjusted to accomodate CE's off-by-one fixups,
10514      so we un-adjust here to compensate for the accomodation.  */
10515   return fixP->fx_where + fixP->fx_frag->fr_address + 8;
10516 #else
10517   return fixP->fx_where + fixP->fx_frag->fr_address;
10518 #endif
10519 }
10520
10521 /* Round up a section size to the appropriate boundary.  */
10522
10523 valueT
10524 md_section_align (segment, size)
10525      segT   segment ATTRIBUTE_UNUSED;
10526      valueT size;
10527 {
10528 #ifdef OBJ_ELF
10529   return size;
10530 #else
10531   /* Round all sects to multiple of 4.  */
10532   return (size + 3) & ~3;
10533 #endif
10534 }
10535
10536 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
10537    Otherwise we have no need to default values of symbols.  */
10538
10539 symbolS *
10540 md_undefined_symbol (name)
10541      char * name ATTRIBUTE_UNUSED;
10542 {
10543 #ifdef OBJ_ELF
10544   if (name[0] == '_' && name[1] == 'G'
10545       && streq (name, GLOBAL_OFFSET_TABLE_NAME))
10546     {
10547       if (!GOT_symbol)
10548         {
10549           if (symbol_find (name))
10550             as_bad ("GOT already in the symbol table");
10551
10552           GOT_symbol = symbol_new (name, undefined_section,
10553                                    (valueT) 0, & zero_address_frag);
10554         }
10555
10556       return GOT_symbol;
10557     }
10558 #endif
10559
10560   return 0;
10561 }
10562
10563 /* arm_reg_parse () := if it looks like a register, return its token and
10564    advance the pointer.  */
10565
10566 static int
10567 arm_reg_parse (ccp, htab)
10568      register char ** ccp;
10569      struct hash_control *htab;
10570 {
10571   char * start = * ccp;
10572   char   c;
10573   char * p;
10574   struct reg_entry * reg;
10575
10576 #ifdef REGISTER_PREFIX
10577   if (*start != REGISTER_PREFIX)
10578     return FAIL;
10579   p = start + 1;
10580 #else
10581   p = start;
10582 #ifdef OPTIONAL_REGISTER_PREFIX
10583   if (*p == OPTIONAL_REGISTER_PREFIX)
10584     p++, start++;
10585 #endif
10586 #endif
10587   if (!ISALPHA (*p) || !is_name_beginner (*p))
10588     return FAIL;
10589
10590   c = *p++;
10591   while (ISALPHA (c) || ISDIGIT (c) || c == '_')
10592     c = *p++;
10593
10594   *--p = 0;
10595   reg = (struct reg_entry *) hash_find (htab, start);
10596   *p = c;
10597
10598   if (reg)
10599     {
10600       *ccp = p;
10601       return reg->number;
10602     }
10603
10604   return FAIL;
10605 }
10606
10607 /* Search for the following register name in each of the possible reg name
10608    tables.  Return the classification if found, or REG_TYPE_MAX if not
10609    present.  */
10610 static enum arm_reg_type
10611 arm_reg_parse_any (cp)
10612      char *cp;
10613 {
10614   int i;
10615
10616   for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
10617     if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
10618       return (enum arm_reg_type) i;
10619
10620   return REG_TYPE_MAX;
10621 }
10622
10623 void
10624 md_apply_fix3 (fixP, valP, seg)
10625      fixS *   fixP;
10626      valueT * valP;
10627      segT     seg;
10628 {
10629   offsetT        value = * valP;
10630   offsetT        newval;
10631   unsigned int   newimm;
10632   unsigned long  temp;
10633   int            sign;
10634   char *         buf = fixP->fx_where + fixP->fx_frag->fr_literal;
10635   arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
10636
10637   assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
10638
10639   /* Note whether this will delete the relocation.  */
10640 #if 0
10641   /* Patch from REarnshaw to JDavis (disabled for the moment, since it
10642      doesn't work fully.)  */
10643   if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
10644       && !fixP->fx_pcrel)
10645 #else
10646   if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
10647 #endif
10648     fixP->fx_done = 1;
10649
10650   /* If this symbol is in a different section then we need to leave it for
10651      the linker to deal with.  Unfortunately, md_pcrel_from can't tell,
10652      so we have to undo it's effects here.  */
10653   if (fixP->fx_pcrel)
10654     {
10655       if (fixP->fx_addsy != NULL
10656           && S_IS_DEFINED (fixP->fx_addsy)
10657           && S_GET_SEGMENT (fixP->fx_addsy) != seg)
10658         {
10659           if (target_oabi
10660               && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
10661                   || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
10662                   ))
10663             value = 0;
10664           else
10665             value += md_pcrel_from (fixP);
10666         }
10667     }
10668
10669   /* Remember value for emit_reloc.  */
10670   fixP->fx_addnumber = value;
10671
10672   switch (fixP->fx_r_type)
10673     {
10674     case BFD_RELOC_ARM_IMMEDIATE:
10675       newimm = validate_immediate (value);
10676       temp = md_chars_to_number (buf, INSN_SIZE);
10677
10678       /* If the instruction will fail, see if we can fix things up by
10679          changing the opcode.  */
10680       if (newimm == (unsigned int) FAIL
10681           && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
10682         {
10683           as_bad_where (fixP->fx_file, fixP->fx_line,
10684                         _("invalid constant (%lx) after fixup"),
10685                         (unsigned long) value);
10686           break;
10687         }
10688
10689       newimm |= (temp & 0xfffff000);
10690       md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
10691       fixP->fx_done = 1;
10692       break;
10693
10694     case BFD_RELOC_ARM_ADRL_IMMEDIATE:
10695       {
10696         unsigned int highpart = 0;
10697         unsigned int newinsn  = 0xe1a00000; /* nop.  */
10698
10699         newimm = validate_immediate (value);
10700         temp = md_chars_to_number (buf, INSN_SIZE);
10701
10702         /* If the instruction will fail, see if we can fix things up by
10703            changing the opcode.  */
10704         if (newimm == (unsigned int) FAIL
10705             && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
10706           {
10707             /* No ?  OK - try using two ADD instructions to generate
10708                the value.  */
10709             newimm = validate_immediate_twopart (value, & highpart);
10710
10711             /* Yes - then make sure that the second instruction is
10712                also an add.  */
10713             if (newimm != (unsigned int) FAIL)
10714               newinsn = temp;
10715             /* Still No ?  Try using a negated value.  */
10716             else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
10717               temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
10718             /* Otherwise - give up.  */
10719             else
10720               {
10721                 as_bad_where (fixP->fx_file, fixP->fx_line,
10722                               _("unable to compute ADRL instructions for PC offset of 0x%lx"),
10723                               (long) value);
10724                 break;
10725               }
10726
10727             /* Replace the first operand in the 2nd instruction (which
10728                is the PC) with the destination register.  We have
10729                already added in the PC in the first instruction and we
10730                do not want to do it again.  */
10731             newinsn &= ~ 0xf0000;
10732             newinsn |= ((newinsn & 0x0f000) << 4);
10733           }
10734
10735         newimm |= (temp & 0xfffff000);
10736         md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
10737
10738         highpart |= (newinsn & 0xfffff000);
10739         md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
10740       }
10741       break;
10742
10743     case BFD_RELOC_ARM_OFFSET_IMM:
10744       sign = value >= 0;
10745
10746       if (value < 0)
10747         value = - value;
10748
10749       if (validate_offset_imm (value, 0) == FAIL)
10750         {
10751           as_bad_where (fixP->fx_file, fixP->fx_line,
10752                         _("bad immediate value for offset (%ld)"),
10753                         (long) value);
10754           break;
10755         }
10756
10757       newval = md_chars_to_number (buf, INSN_SIZE);
10758       newval &= 0xff7ff000;
10759       newval |= value | (sign ? INDEX_UP : 0);
10760       md_number_to_chars (buf, newval, INSN_SIZE);
10761       break;
10762
10763     case BFD_RELOC_ARM_OFFSET_IMM8:
10764     case BFD_RELOC_ARM_HWLITERAL:
10765       sign = value >= 0;
10766
10767       if (value < 0)
10768         value = - value;
10769
10770       if (validate_offset_imm (value, 1) == FAIL)
10771         {
10772           if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
10773             as_bad_where (fixP->fx_file, fixP->fx_line,
10774                           _("invalid literal constant: pool needs to be closer"));
10775           else
10776             as_bad (_("bad immediate value for half-word offset (%ld)"),
10777                     (long) value);
10778           break;
10779         }
10780
10781       newval = md_chars_to_number (buf, INSN_SIZE);
10782       newval &= 0xff7ff0f0;
10783       newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
10784       md_number_to_chars (buf, newval, INSN_SIZE);
10785       break;
10786
10787     case BFD_RELOC_ARM_LITERAL:
10788       sign = value >= 0;
10789
10790       if (value < 0)
10791         value = - value;
10792
10793       if (validate_offset_imm (value, 0) == FAIL)
10794         {
10795           as_bad_where (fixP->fx_file, fixP->fx_line,
10796                         _("invalid literal constant: pool needs to be closer"));
10797           break;
10798         }
10799
10800       newval = md_chars_to_number (buf, INSN_SIZE);
10801       newval &= 0xff7ff000;
10802       newval |= value | (sign ? INDEX_UP : 0);
10803       md_number_to_chars (buf, newval, INSN_SIZE);
10804       break;
10805
10806     case BFD_RELOC_ARM_SHIFT_IMM:
10807       newval = md_chars_to_number (buf, INSN_SIZE);
10808       if (((unsigned long) value) > 32
10809           || (value == 32
10810               && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
10811         {
10812           as_bad_where (fixP->fx_file, fixP->fx_line,
10813                         _("shift expression is too large"));
10814           break;
10815         }
10816
10817       if (value == 0)
10818         /* Shifts of zero must be done as lsl.  */
10819         newval &= ~0x60;
10820       else if (value == 32)
10821         value = 0;
10822       newval &= 0xfffff07f;
10823       newval |= (value & 0x1f) << 7;
10824       md_number_to_chars (buf, newval, INSN_SIZE);
10825       break;
10826
10827     case BFD_RELOC_ARM_SWI:
10828       if (arm_data->thumb_mode)
10829         {
10830           if (((unsigned long) value) > 0xff)
10831             as_bad_where (fixP->fx_file, fixP->fx_line,
10832                           _("invalid swi expression"));
10833           newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
10834           newval |= value;
10835           md_number_to_chars (buf, newval, THUMB_SIZE);
10836         }
10837       else
10838         {
10839           if (((unsigned long) value) > 0x00ffffff)
10840             as_bad_where (fixP->fx_file, fixP->fx_line,
10841                           _("invalid swi expression"));
10842           newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
10843           newval |= value;
10844           md_number_to_chars (buf, newval, INSN_SIZE);
10845         }
10846       break;
10847
10848     case BFD_RELOC_ARM_MULTI:
10849       if (((unsigned long) value) > 0xffff)
10850         as_bad_where (fixP->fx_file, fixP->fx_line,
10851                       _("invalid expression in load/store multiple"));
10852       newval = value | md_chars_to_number (buf, INSN_SIZE);
10853       md_number_to_chars (buf, newval, INSN_SIZE);
10854       break;
10855
10856     case BFD_RELOC_ARM_PCREL_BRANCH:
10857       newval = md_chars_to_number (buf, INSN_SIZE);
10858
10859       /* Sign-extend a 24-bit number.  */
10860 #define SEXT24(x)       ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
10861
10862 #ifdef OBJ_ELF
10863       if (! target_oabi)
10864         value = fixP->fx_offset;
10865 #endif
10866
10867       /* We are going to store value (shifted right by two) in the
10868          instruction, in a 24 bit, signed field.  Thus we need to check
10869          that none of the top 8 bits of the shifted value (top 7 bits of
10870          the unshifted, unsigned value) are set, or that they are all set.  */
10871       if ((value & ~ ((offsetT) 0x1ffffff)) != 0
10872           && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
10873         {
10874 #ifdef OBJ_ELF
10875           /* Normally we would be stuck at this point, since we cannot store
10876              the absolute address that is the destination of the branch in the
10877              24 bits of the branch instruction.  If however, we happen to know
10878              that the destination of the branch is in the same section as the
10879              branch instruciton itself, then we can compute the relocation for
10880              ourselves and not have to bother the linker with it.
10881
10882              FIXME: The tests for OBJ_ELF and ! target_oabi are only here
10883              because I have not worked out how to do this for OBJ_COFF or
10884              target_oabi.  */
10885           if (! target_oabi
10886               && fixP->fx_addsy != NULL
10887               && S_IS_DEFINED (fixP->fx_addsy)
10888               && S_GET_SEGMENT (fixP->fx_addsy) == seg)
10889             {
10890               /* Get pc relative value to go into the branch.  */
10891               value = * valP;
10892
10893               /* Permit a backward branch provided that enough bits
10894                  are set.  Allow a forwards branch, provided that
10895                  enough bits are clear.  */
10896               if (   (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
10897                   || (value & ~ ((offsetT) 0x1ffffff)) == 0)
10898                 fixP->fx_done = 1;
10899             }
10900
10901           if (! fixP->fx_done)
10902 #endif
10903             as_bad_where (fixP->fx_file, fixP->fx_line,
10904                           _("GAS can't handle same-section branch dest >= 0x04000000"));
10905         }
10906
10907       value >>= 2;
10908       value += SEXT24 (newval);
10909
10910       if (    (value & ~ ((offsetT) 0xffffff)) != 0
10911           && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
10912         as_bad_where (fixP->fx_file, fixP->fx_line,
10913                       _("out of range branch"));
10914
10915       newval = (value & 0x00ffffff) | (newval & 0xff000000);
10916       md_number_to_chars (buf, newval, INSN_SIZE);
10917       break;
10918
10919     case BFD_RELOC_ARM_PCREL_BLX:
10920       {
10921         offsetT hbit;
10922         newval = md_chars_to_number (buf, INSN_SIZE);
10923
10924 #ifdef OBJ_ELF
10925         if (! target_oabi)
10926           value = fixP->fx_offset;
10927 #endif
10928         hbit   = (value >> 1) & 1;
10929         value  = (value >> 2) & 0x00ffffff;
10930         value  = (value + (newval & 0x00ffffff)) & 0x00ffffff;
10931         newval = value | (newval & 0xfe000000) | (hbit << 24);
10932         md_number_to_chars (buf, newval, INSN_SIZE);
10933       }
10934       break;
10935
10936     case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch.  */
10937       newval = md_chars_to_number (buf, THUMB_SIZE);
10938       {
10939         addressT diff = (newval & 0xff) << 1;
10940         if (diff & 0x100)
10941           diff |= ~0xff;
10942
10943         value += diff;
10944         if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
10945           as_bad_where (fixP->fx_file, fixP->fx_line,
10946                         _("branch out of range"));
10947         newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
10948       }
10949       md_number_to_chars (buf, newval, THUMB_SIZE);
10950       break;
10951
10952     case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch.  */
10953       newval = md_chars_to_number (buf, THUMB_SIZE);
10954       {
10955         addressT diff = (newval & 0x7ff) << 1;
10956         if (diff & 0x800)
10957           diff |= ~0x7ff;
10958
10959         value += diff;
10960         if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
10961           as_bad_where (fixP->fx_file, fixP->fx_line,
10962                         _("branch out of range"));
10963         newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
10964       }
10965       md_number_to_chars (buf, newval, THUMB_SIZE);
10966       break;
10967
10968     case BFD_RELOC_THUMB_PCREL_BLX:
10969     case BFD_RELOC_THUMB_PCREL_BRANCH23:
10970       {
10971         offsetT newval2;
10972         addressT diff;
10973
10974         newval  = md_chars_to_number (buf, THUMB_SIZE);
10975         newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
10976         diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
10977         if (diff & 0x400000)
10978           diff |= ~0x3fffff;
10979 #ifdef OBJ_ELF
10980         value = fixP->fx_offset;
10981 #endif
10982         value += diff;
10983
10984         if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
10985           as_bad_where (fixP->fx_file, fixP->fx_line,
10986                         _("branch with link out of range"));
10987
10988         newval  = (newval  & 0xf800) | ((value & 0x7fffff) >> 12);
10989         newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
10990         if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
10991           /* For a BLX instruction, make sure that the relocation is rounded up
10992              to a word boundary.  This follows the semantics of the instruction
10993              which specifies that bit 1 of the target address will come from bit
10994              1 of the base address.  */
10995           newval2 = (newval2 + 1) & ~ 1;
10996         md_number_to_chars (buf, newval, THUMB_SIZE);
10997         md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
10998       }
10999       break;
11000
11001     case BFD_RELOC_8:
11002       if (fixP->fx_done || fixP->fx_pcrel)
11003         md_number_to_chars (buf, value, 1);
11004 #ifdef OBJ_ELF
11005       else if (!target_oabi)
11006         {
11007           value = fixP->fx_offset;
11008           md_number_to_chars (buf, value, 1);
11009         }
11010 #endif
11011       break;
11012
11013     case BFD_RELOC_16:
11014       if (fixP->fx_done || fixP->fx_pcrel)
11015         md_number_to_chars (buf, value, 2);
11016 #ifdef OBJ_ELF
11017       else if (!target_oabi)
11018         {
11019           value = fixP->fx_offset;
11020           md_number_to_chars (buf, value, 2);
11021         }
11022 #endif
11023       break;
11024
11025 #ifdef OBJ_ELF
11026     case BFD_RELOC_ARM_GOT32:
11027     case BFD_RELOC_ARM_GOTOFF:
11028       md_number_to_chars (buf, 0, 4);
11029       break;
11030 #endif
11031
11032     case BFD_RELOC_RVA:
11033     case BFD_RELOC_32:
11034       if (fixP->fx_done || fixP->fx_pcrel)
11035         md_number_to_chars (buf, value, 4);
11036 #ifdef OBJ_ELF
11037       else if (!target_oabi)
11038         {
11039           value = fixP->fx_offset;
11040           md_number_to_chars (buf, value, 4);
11041         }
11042 #endif
11043       break;
11044
11045 #ifdef OBJ_ELF
11046     case BFD_RELOC_ARM_PLT32:
11047       /* It appears the instruction is fully prepared at this point.  */
11048       break;
11049 #endif
11050
11051     case BFD_RELOC_ARM_CP_OFF_IMM:
11052       sign = value >= 0;
11053       if (value < -1023 || value > 1023 || (value & 3))
11054         as_bad_where (fixP->fx_file, fixP->fx_line,
11055                       _("illegal value for co-processor offset"));
11056       if (value < 0)
11057         value = -value;
11058       newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11059       newval |= (value >> 2) | (sign ? INDEX_UP : 0);
11060       md_number_to_chars (buf, newval, INSN_SIZE);
11061       break;
11062
11063     case BFD_RELOC_ARM_CP_OFF_IMM_S2:
11064       sign = value >= 0;
11065       if (value < -255 || value > 255)
11066         as_bad_where (fixP->fx_file, fixP->fx_line,
11067                       _("Illegal value for co-processor offset"));
11068       if (value < 0)
11069         value = -value;
11070       newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11071       newval |= value | (sign ?  INDEX_UP : 0);
11072       md_number_to_chars (buf, newval , INSN_SIZE);
11073       break;
11074
11075     case BFD_RELOC_ARM_THUMB_OFFSET:
11076       newval = md_chars_to_number (buf, THUMB_SIZE);
11077       /* Exactly what ranges, and where the offset is inserted depends
11078          on the type of instruction, we can establish this from the
11079          top 4 bits.  */
11080       switch (newval >> 12)
11081         {
11082         case 4: /* PC load.  */
11083           /* Thumb PC loads are somewhat odd, bit 1 of the PC is
11084              forced to zero for these loads, so we will need to round
11085              up the offset if the instruction address is not word
11086              aligned (since the final address produced must be, and
11087              we can only describe word-aligned immediate offsets).  */
11088
11089           if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
11090             as_bad_where (fixP->fx_file, fixP->fx_line,
11091                           _("invalid offset, target not word aligned (0x%08X)"),
11092                           (unsigned int) (fixP->fx_frag->fr_address
11093                                           + fixP->fx_where + value));
11094
11095           if ((value + 2) & ~0x3fe)
11096             as_bad_where (fixP->fx_file, fixP->fx_line,
11097                           _("invalid offset, value too big (0x%08lX)"),
11098                           (long) value);
11099
11100           /* Round up, since pc will be rounded down.  */
11101           newval |= (value + 2) >> 2;
11102           break;
11103
11104         case 9: /* SP load/store.  */
11105           if (value & ~0x3fc)
11106             as_bad_where (fixP->fx_file, fixP->fx_line,
11107                           _("invalid offset, value too big (0x%08lX)"),
11108                           (long) value);
11109           newval |= value >> 2;
11110           break;
11111
11112         case 6: /* Word load/store.  */
11113           if (value & ~0x7c)
11114             as_bad_where (fixP->fx_file, fixP->fx_line,
11115                           _("invalid offset, value too big (0x%08lX)"),
11116                           (long) value);
11117           newval |= value << 4; /* 6 - 2.  */
11118           break;
11119
11120         case 7: /* Byte load/store.  */
11121           if (value & ~0x1f)
11122             as_bad_where (fixP->fx_file, fixP->fx_line,
11123                           _("invalid offset, value too big (0x%08lX)"),
11124                           (long) value);
11125           newval |= value << 6;
11126           break;
11127
11128         case 8: /* Halfword load/store.  */
11129           if (value & ~0x3e)
11130             as_bad_where (fixP->fx_file, fixP->fx_line,
11131                           _("invalid offset, value too big (0x%08lX)"),
11132                           (long) value);
11133           newval |= value << 5; /* 6 - 1.  */
11134           break;
11135
11136         default:
11137           as_bad_where (fixP->fx_file, fixP->fx_line,
11138                         "Unable to process relocation for thumb opcode: %lx",
11139                         (unsigned long) newval);
11140           break;
11141         }
11142       md_number_to_chars (buf, newval, THUMB_SIZE);
11143       break;
11144
11145     case BFD_RELOC_ARM_THUMB_ADD:
11146       /* This is a complicated relocation, since we use it for all of
11147          the following immediate relocations:
11148
11149             3bit ADD/SUB
11150             8bit ADD/SUB
11151             9bit ADD/SUB SP word-aligned
11152            10bit ADD PC/SP word-aligned
11153
11154          The type of instruction being processed is encoded in the
11155          instruction field:
11156
11157            0x8000  SUB
11158            0x00F0  Rd
11159            0x000F  Rs
11160       */
11161       newval = md_chars_to_number (buf, THUMB_SIZE);
11162       {
11163         int rd = (newval >> 4) & 0xf;
11164         int rs = newval & 0xf;
11165         int subtract = newval & 0x8000;
11166
11167         if (rd == REG_SP)
11168           {
11169             if (value & ~0x1fc)
11170               as_bad_where (fixP->fx_file, fixP->fx_line,
11171                             _("invalid immediate for stack address calculation"));
11172             newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
11173             newval |= value >> 2;
11174           }
11175         else if (rs == REG_PC || rs == REG_SP)
11176           {
11177             if (subtract ||
11178                 value & ~0x3fc)
11179               as_bad_where (fixP->fx_file, fixP->fx_line,
11180                             _("invalid immediate for address calculation (value = 0x%08lX)"),
11181                             (unsigned long) value);
11182             newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
11183             newval |= rd << 8;
11184             newval |= value >> 2;
11185           }
11186         else if (rs == rd)
11187           {
11188             if (value & ~0xff)
11189               as_bad_where (fixP->fx_file, fixP->fx_line,
11190                             _("invalid 8bit immediate"));
11191             newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
11192             newval |= (rd << 8) | value;
11193           }
11194         else
11195           {
11196             if (value & ~0x7)
11197               as_bad_where (fixP->fx_file, fixP->fx_line,
11198                             _("invalid 3bit immediate"));
11199             newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
11200             newval |= rd | (rs << 3) | (value << 6);
11201           }
11202       }
11203       md_number_to_chars (buf, newval, THUMB_SIZE);
11204       break;
11205
11206     case BFD_RELOC_ARM_THUMB_IMM:
11207       newval = md_chars_to_number (buf, THUMB_SIZE);
11208       switch (newval >> 11)
11209         {
11210         case 0x04: /* 8bit immediate MOV.  */
11211         case 0x05: /* 8bit immediate CMP.  */
11212           if (value < 0 || value > 255)
11213             as_bad_where (fixP->fx_file, fixP->fx_line,
11214                           _("invalid immediate: %ld is too large"),
11215                           (long) value);
11216           newval |= value;
11217           break;
11218
11219         default:
11220           abort ();
11221         }
11222       md_number_to_chars (buf, newval, THUMB_SIZE);
11223       break;
11224
11225     case BFD_RELOC_ARM_THUMB_SHIFT:
11226       /* 5bit shift value (0..31).  */
11227       if (value < 0 || value > 31)
11228         as_bad_where (fixP->fx_file, fixP->fx_line,
11229                       _("illegal Thumb shift value: %ld"), (long) value);
11230       newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
11231       newval |= value << 6;
11232       md_number_to_chars (buf, newval, THUMB_SIZE);
11233       break;
11234
11235     case BFD_RELOC_VTABLE_INHERIT:
11236     case BFD_RELOC_VTABLE_ENTRY:
11237       fixP->fx_done = 0;
11238       return;
11239
11240     case BFD_RELOC_NONE:
11241     default:
11242       as_bad_where (fixP->fx_file, fixP->fx_line,
11243                     _("bad relocation fixup type (%d)"), fixP->fx_r_type);
11244     }
11245 }
11246
11247 /* Translate internal representation of relocation info to BFD target
11248    format.  */
11249
11250 arelent *
11251 tc_gen_reloc (section, fixp)
11252      asection * section ATTRIBUTE_UNUSED;
11253      fixS * fixp;
11254 {
11255   arelent * reloc;
11256   bfd_reloc_code_real_type code;
11257
11258   reloc = (arelent *) xmalloc (sizeof (arelent));
11259
11260   reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
11261   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
11262   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
11263
11264   /* @@ Why fx_addnumber sometimes and fx_offset other times?  */
11265 #ifndef OBJ_ELF
11266   if (fixp->fx_pcrel == 0)
11267     reloc->addend = fixp->fx_offset;
11268   else
11269     reloc->addend = fixp->fx_offset = reloc->address;
11270 #else  /* OBJ_ELF */
11271   reloc->addend = fixp->fx_offset;
11272 #endif
11273
11274   switch (fixp->fx_r_type)
11275     {
11276     case BFD_RELOC_8:
11277       if (fixp->fx_pcrel)
11278         {
11279           code = BFD_RELOC_8_PCREL;
11280           break;
11281         }
11282
11283     case BFD_RELOC_16:
11284       if (fixp->fx_pcrel)
11285         {
11286           code = BFD_RELOC_16_PCREL;
11287           break;
11288         }
11289
11290     case BFD_RELOC_32:
11291       if (fixp->fx_pcrel)
11292         {
11293           code = BFD_RELOC_32_PCREL;
11294           break;
11295         }
11296
11297     case BFD_RELOC_ARM_PCREL_BRANCH:
11298     case BFD_RELOC_ARM_PCREL_BLX:
11299     case BFD_RELOC_RVA:
11300     case BFD_RELOC_THUMB_PCREL_BRANCH9:
11301     case BFD_RELOC_THUMB_PCREL_BRANCH12:
11302     case BFD_RELOC_THUMB_PCREL_BRANCH23:
11303     case BFD_RELOC_THUMB_PCREL_BLX:
11304     case BFD_RELOC_VTABLE_ENTRY:
11305     case BFD_RELOC_VTABLE_INHERIT:
11306       code = fixp->fx_r_type;
11307       break;
11308
11309     case BFD_RELOC_ARM_LITERAL:
11310     case BFD_RELOC_ARM_HWLITERAL:
11311       /* If this is called then the a literal has
11312          been referenced across a section boundary.  */
11313       as_bad_where (fixp->fx_file, fixp->fx_line,
11314                     _("literal referenced across section boundary"));
11315       return NULL;
11316
11317 #ifdef OBJ_ELF
11318     case BFD_RELOC_ARM_GOT32:
11319     case BFD_RELOC_ARM_GOTOFF:
11320     case BFD_RELOC_ARM_PLT32:
11321       code = fixp->fx_r_type;
11322       break;
11323 #endif
11324
11325     case BFD_RELOC_ARM_IMMEDIATE:
11326       as_bad_where (fixp->fx_file, fixp->fx_line,
11327                     _("internal relocation (type: IMMEDIATE) not fixed up"));
11328       return NULL;
11329
11330     case BFD_RELOC_ARM_ADRL_IMMEDIATE:
11331       as_bad_where (fixp->fx_file, fixp->fx_line,
11332                     _("ADRL used for a symbol not defined in the same file"));
11333       return NULL;
11334
11335     case BFD_RELOC_ARM_OFFSET_IMM:
11336       as_bad_where (fixp->fx_file, fixp->fx_line,
11337                     _("internal_relocation (type: OFFSET_IMM) not fixed up"));
11338       return NULL;
11339
11340     default:
11341       {
11342         char * type;
11343
11344         switch (fixp->fx_r_type)
11345           {
11346           case BFD_RELOC_ARM_OFFSET_IMM8:  type = "OFFSET_IMM8";  break;
11347           case BFD_RELOC_ARM_SHIFT_IMM:    type = "SHIFT_IMM";    break;
11348           case BFD_RELOC_ARM_SWI:          type = "SWI";          break;
11349           case BFD_RELOC_ARM_MULTI:        type = "MULTI";        break;
11350           case BFD_RELOC_ARM_CP_OFF_IMM:   type = "CP_OFF_IMM";   break;
11351           case BFD_RELOC_ARM_THUMB_ADD:    type = "THUMB_ADD";    break;
11352           case BFD_RELOC_ARM_THUMB_SHIFT:  type = "THUMB_SHIFT";  break;
11353           case BFD_RELOC_ARM_THUMB_IMM:    type = "THUMB_IMM";    break;
11354           case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
11355           default:                         type = _("<unknown>"); break;
11356           }
11357         as_bad_where (fixp->fx_file, fixp->fx_line,
11358                       _("cannot represent %s relocation in this object file format"),
11359                       type);
11360         return NULL;
11361       }
11362     }
11363
11364 #ifdef OBJ_ELF
11365   if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
11366       && GOT_symbol
11367       && fixp->fx_addsy == GOT_symbol)
11368     {
11369       code = BFD_RELOC_ARM_GOTPC;
11370       reloc->addend = fixp->fx_offset = reloc->address;
11371     }
11372 #endif
11373
11374   reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
11375
11376   if (reloc->howto == NULL)
11377     {
11378       as_bad_where (fixp->fx_file, fixp->fx_line,
11379                     _("cannot represent %s relocation in this object file format"),
11380                     bfd_get_reloc_code_name (code));
11381       return NULL;
11382     }
11383
11384   /* HACK: Since arm ELF uses Rel instead of Rela, encode the
11385      vtable entry to be used in the relocation's section offset.  */
11386   if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
11387     reloc->address = fixp->fx_offset;
11388
11389   return reloc;
11390 }
11391
11392 int
11393 md_estimate_size_before_relax (fragP, segtype)
11394      fragS * fragP ATTRIBUTE_UNUSED;
11395      segT    segtype ATTRIBUTE_UNUSED;
11396 {
11397   as_fatal (_("md_estimate_size_before_relax\n"));
11398   return 1;
11399 }
11400
11401 static void
11402 output_inst (str)
11403      const char *str;
11404 {
11405   char * to = NULL;
11406
11407   if (inst.error)
11408     {
11409       as_bad ("%s -- `%s'", inst.error, str);
11410       return;
11411     }
11412
11413   to = frag_more (inst.size);
11414
11415   if (thumb_mode && (inst.size > THUMB_SIZE))
11416     {
11417       assert (inst.size == (2 * THUMB_SIZE));
11418       md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
11419       md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
11420     }
11421   else if (inst.size > INSN_SIZE)
11422     {
11423       assert (inst.size == (2 * INSN_SIZE));
11424       md_number_to_chars (to, inst.instruction, INSN_SIZE);
11425       md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
11426     }
11427   else
11428     md_number_to_chars (to, inst.instruction, inst.size);
11429
11430   if (inst.reloc.type != BFD_RELOC_NONE)
11431     fix_new_arm (frag_now, to - frag_now->fr_literal,
11432                  inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
11433                  inst.reloc.type);
11434
11435 #ifdef OBJ_ELF
11436   dwarf2_emit_insn (inst.size);
11437 #endif
11438 }
11439
11440 void
11441 md_assemble (str)
11442      char * str;
11443 {
11444   char  c;
11445   char *p;
11446   char *start;
11447
11448   /* Align the instruction.
11449      This may not be the right thing to do but ...  */
11450 #if 0
11451   arm_align (2, 0);
11452 #endif
11453
11454   /* Align the previous label if needed.  */
11455   if (last_label_seen != NULL)
11456     {
11457       symbol_set_frag (last_label_seen, frag_now);
11458       S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
11459       S_SET_SEGMENT (last_label_seen, now_seg);
11460     }
11461
11462   memset (&inst, '\0', sizeof (inst));
11463   inst.reloc.type = BFD_RELOC_NONE;
11464
11465   skip_whitespace (str);
11466
11467   /* Scan up to the end of the op-code, which must end in white space or
11468      end of string.  */
11469   for (start = p = str; *p != '\0'; p++)
11470     if (*p == ' ')
11471       break;
11472
11473   if (p == str)
11474     {
11475       as_bad (_("no operator -- statement `%s'\n"), str);
11476       return;
11477     }
11478
11479   if (thumb_mode)
11480     {
11481       const struct thumb_opcode * opcode;
11482
11483       c = *p;
11484       *p = '\0';
11485       opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
11486       *p = c;
11487
11488       if (opcode)
11489         {
11490           /* Check that this instruction is supported for this CPU.  */
11491           if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
11492             {
11493               as_bad (_("selected processor does not support `%s'"), str);
11494               return;
11495             }
11496
11497           inst.instruction = opcode->value;
11498           inst.size = opcode->size;
11499           (*opcode->parms) (p);
11500           output_inst (str);
11501           return;
11502         }
11503     }
11504   else
11505     {
11506       const struct asm_opcode * opcode;
11507
11508       c = *p;
11509       *p = '\0';
11510       opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
11511       *p = c;
11512
11513       if (opcode)
11514         {
11515           /* Check that this instruction is supported for this CPU.  */
11516           if ((opcode->variant & cpu_variant) == 0)
11517             {
11518               as_bad (_("selected processor does not support `%s'"), str);
11519               return;
11520             }
11521
11522           inst.instruction = opcode->value;
11523           inst.size = INSN_SIZE;
11524           (*opcode->parms) (p);
11525           output_inst (str);
11526           return;
11527         }
11528     }
11529
11530   /* It wasn't an instruction, but it might be a register alias of the form
11531      alias .req reg.  */
11532   if (create_register_alias (str, p))
11533     return;
11534
11535   as_bad (_("bad instruction `%s'"), start);
11536 }
11537
11538 /* md_parse_option
11539       Invocation line includes a switch not recognized by the base assembler.
11540       See if it's a processor-specific option.
11541
11542       This routine is somewhat complicated by the need for backwards
11543       compatibility (since older releases of gcc can't be changed).
11544       The new options try to make the interface as compatible as
11545       possible with GCC.
11546
11547       New options (supported) are:
11548
11549               -mcpu=<cpu name>           Assemble for selected processor
11550               -march=<architecture name> Assemble for selected architecture
11551               -mfpu=<fpu architecture>   Assemble for selected FPU.
11552               -EB/-mbig-endian           Big-endian
11553               -EL/-mlittle-endian        Little-endian
11554               -k                         Generate PIC code
11555               -mthumb                    Start in Thumb mode
11556               -mthumb-interwork          Code supports ARM/Thumb interworking
11557
11558       For now we will also provide support for:
11559
11560               -mapcs-32                  32-bit Program counter
11561               -mapcs-26                  26-bit Program counter
11562               -macps-float               Floats passed in FP registers
11563               -mapcs-reentrant           Reentrant code
11564               -matpcs
11565       (sometime these will probably be replaced with -mapcs=<list of options>
11566       and -matpcs=<list of options>)
11567
11568       The remaining options are only supported for back-wards compatibility.
11569       Cpu variants, the arm part is optional:
11570               -m[arm]1                Currently not supported.
11571               -m[arm]2, -m[arm]250    Arm 2 and Arm 250 processor
11572               -m[arm]3                Arm 3 processor
11573               -m[arm]6[xx],           Arm 6 processors
11574               -m[arm]7[xx][t][[d]m]   Arm 7 processors
11575               -m[arm]8[10]            Arm 8 processors
11576               -m[arm]9[20][tdmi]      Arm 9 processors
11577               -mstrongarm[110[0]]     StrongARM processors
11578               -mxscale                XScale processors
11579               -m[arm]v[2345[t[e]]]    Arm architectures
11580               -mall                   All (except the ARM1)
11581       FP variants:
11582               -mfpa10, -mfpa11        FPA10 and 11 co-processor instructions
11583               -mfpe-old               (No float load/store multiples)
11584               -mvfpxd                 VFP Single precision
11585               -mvfp                   All VFP
11586               -mno-fpu                Disable all floating point instructions
11587
11588       The following CPU names are recognized:
11589               arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
11590               arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
11591               arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
11592               arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
11593               arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
11594               arm10t arm10e, arm1020t, arm1020e, arm10200e,
11595               strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
11596
11597       */
11598
11599 const char * md_shortopts = "m:k";
11600
11601 #ifdef ARM_BI_ENDIAN
11602 #define OPTION_EB (OPTION_MD_BASE + 0)
11603 #define OPTION_EL (OPTION_MD_BASE + 1)
11604 #else
11605 #if TARGET_BYTES_BIG_ENDIAN
11606 #define OPTION_EB (OPTION_MD_BASE + 0)
11607 #else
11608 #define OPTION_EL (OPTION_MD_BASE + 1)
11609 #endif
11610 #endif
11611
11612 struct option md_longopts[] =
11613 {
11614 #ifdef OPTION_EB
11615   {"EB", no_argument, NULL, OPTION_EB},
11616 #endif
11617 #ifdef OPTION_EL
11618   {"EL", no_argument, NULL, OPTION_EL},
11619 #endif
11620   {NULL, no_argument, NULL, 0}
11621 };
11622
11623 size_t md_longopts_size = sizeof (md_longopts);
11624
11625 struct arm_option_table
11626 {
11627   char *option;         /* Option name to match.  */
11628   char *help;           /* Help information.  */
11629   int  *var;            /* Variable to change.  */
11630   int   value;          /* What to change it to.  */
11631   char *deprecated;     /* If non-null, print this message.  */
11632 };
11633
11634 struct arm_option_table arm_opts[] =
11635 {
11636   {"k",      N_("generate PIC code"),      &pic_code,    1, NULL},
11637   {"mthumb", N_("assemble Thumb code"),    &thumb_mode,  1, NULL},
11638   {"mthumb-interwork", N_("support ARM/Thumb interworking"),
11639    &support_interwork, 1, NULL},
11640   {"moabi",  N_("use old ABI (ELF only)"), &target_oabi, 1, NULL},
11641   {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
11642   {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
11643   {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
11644    1, NULL},
11645   {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
11646   {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
11647   {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
11648   {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
11649    NULL},
11650
11651   /* These are recognized by the assembler, but have no affect on code.  */
11652   {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
11653   {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
11654
11655   /* DON'T add any new processors to this list -- we want the whole list
11656      to go away...  Add them to the processors table instead.  */
11657   {"marm1",      NULL, &legacy_cpu, ARM_ARCH_V1,  N_("use -mcpu=arm1")},
11658   {"m1",         NULL, &legacy_cpu, ARM_ARCH_V1,  N_("use -mcpu=arm1")},
11659   {"marm2",      NULL, &legacy_cpu, ARM_ARCH_V2,  N_("use -mcpu=arm2")},
11660   {"m2",         NULL, &legacy_cpu, ARM_ARCH_V2,  N_("use -mcpu=arm2")},
11661   {"marm250",    NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
11662   {"m250",       NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
11663   {"marm3",      NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
11664   {"m3",         NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
11665   {"marm6",      NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm6")},
11666   {"m6",         NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm6")},
11667   {"marm600",    NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm600")},
11668   {"m600",       NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm600")},
11669   {"marm610",    NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm610")},
11670   {"m610",       NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm610")},
11671   {"marm620",    NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm620")},
11672   {"m620",       NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm620")},
11673   {"marm7",      NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7")},
11674   {"m7",         NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7")},
11675   {"marm70",     NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm70")},
11676   {"m70",        NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm70")},
11677   {"marm700",    NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm700")},
11678   {"m700",       NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm700")},
11679   {"marm700i",   NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm700i")},
11680   {"m700i",      NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm700i")},
11681   {"marm710",    NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm710")},
11682   {"m710",       NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm710")},
11683   {"marm710c",   NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm710c")},
11684   {"m710c",      NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm710c")},
11685   {"marm720",    NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm720")},
11686   {"m720",       NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm720")},
11687   {"marm7d",     NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7d")},
11688   {"m7d",        NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7d")},
11689   {"marm7di",    NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7di")},
11690   {"m7di",       NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7di")},
11691   {"marm7m",     NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
11692   {"m7m",        NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
11693   {"marm7dm",    NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
11694   {"m7dm",       NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
11695   {"marm7dmi",   NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
11696   {"m7dmi",      NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
11697   {"marm7100",   NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7100")},
11698   {"m7100",      NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7100")},
11699   {"marm7500",   NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7500")},
11700   {"m7500",      NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7500")},
11701   {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7500fe")},
11702   {"m7500fe",    NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7500fe")},
11703   {"marm7t",     NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
11704   {"m7t",        NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
11705   {"marm7tdmi",  NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
11706   {"m7tdmi",     NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
11707   {"marm710t",   NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
11708   {"m710t",      NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
11709   {"marm720t",   NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
11710   {"m720t",      NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
11711   {"marm740t",   NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
11712   {"m740t",      NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
11713   {"marm8",      NULL, &legacy_cpu, ARM_ARCH_V4,  N_("use -mcpu=arm8")},
11714   {"m8",         NULL, &legacy_cpu, ARM_ARCH_V4,  N_("use -mcpu=arm8")},
11715   {"marm810",    NULL, &legacy_cpu, ARM_ARCH_V4,  N_("use -mcpu=arm810")},
11716   {"m810",       NULL, &legacy_cpu, ARM_ARCH_V4,  N_("use -mcpu=arm810")},
11717   {"marm9",      NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
11718   {"m9",         NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
11719   {"marm9tdmi",  NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
11720   {"m9tdmi",     NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
11721   {"marm920",    NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
11722   {"m920",       NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
11723   {"marm940",    NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
11724   {"m940",       NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
11725   {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4,  N_("use -mcpu=strongarm")},
11726   {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
11727    N_("use -mcpu=strongarm110")},
11728   {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
11729    N_("use -mcpu=strongarm1100")},
11730   {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
11731    N_("use -mcpu=strongarm1110")},
11732   {"mxscale",    NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
11733   {"miwmmxt",    NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
11734   {"mall",       NULL, &legacy_cpu, ARM_ANY,      N_("use -mcpu=all")},
11735
11736   /* Architecture variants -- don't add any more to this list either.  */
11737   {"mv2",        NULL, &legacy_cpu, ARM_ARCH_V2,  N_("use -march=armv2")},
11738   {"marmv2",     NULL, &legacy_cpu, ARM_ARCH_V2,  N_("use -march=armv2")},
11739   {"mv2a",       NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
11740   {"marmv2a",    NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
11741   {"mv3",        NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -march=armv3")},
11742   {"marmv3",     NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -march=armv3")},
11743   {"mv3m",       NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
11744   {"marmv3m",    NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
11745   {"mv4",        NULL, &legacy_cpu, ARM_ARCH_V4,  N_("use -march=armv4")},
11746   {"marmv4",     NULL, &legacy_cpu, ARM_ARCH_V4,  N_("use -march=armv4")},
11747   {"mv4t",       NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
11748   {"marmv4t",    NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
11749   {"mv5",        NULL, &legacy_cpu, ARM_ARCH_V5,  N_("use -march=armv5")},
11750   {"marmv5",     NULL, &legacy_cpu, ARM_ARCH_V5,  N_("use -march=armv5")},
11751   {"mv5t",       NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
11752   {"marmv5t",    NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
11753   {"mv5e",       NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
11754   {"marmv5e",    NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
11755
11756   /* Floating point variants -- don't add any more to this list either.  */
11757   {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
11758   {"mfpa10",   NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
11759   {"mfpa11",   NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
11760   {"mno-fpu",  NULL, &legacy_fpu, 0,
11761    N_("use either -mfpu=softfpa or -mfpu=softvfp")},
11762
11763   {NULL, NULL, NULL, 0, NULL}
11764 };
11765
11766 struct arm_cpu_option_table
11767 {
11768   char *name;
11769   int   value;
11770   /* For some CPUs we assume an FPU unless the user explicitly sets
11771      -mfpu=...  */
11772   int   default_fpu;
11773 };
11774
11775 /* This list should, at a minimum, contain all the cpu names
11776    recognized by GCC.  */
11777 static struct arm_cpu_option_table arm_cpus[] =
11778 {
11779   {"all",               ARM_ANY,         FPU_ARCH_FPA},
11780   {"arm1",              ARM_ARCH_V1,     FPU_ARCH_FPA},
11781   {"arm2",              ARM_ARCH_V2,     FPU_ARCH_FPA},
11782   {"arm250",            ARM_ARCH_V2S,    FPU_ARCH_FPA},
11783   {"arm3",              ARM_ARCH_V2S,    FPU_ARCH_FPA},
11784   {"arm6",              ARM_ARCH_V3,     FPU_ARCH_FPA},
11785   {"arm60",             ARM_ARCH_V3,     FPU_ARCH_FPA},
11786   {"arm600",            ARM_ARCH_V3,     FPU_ARCH_FPA},
11787   {"arm610",            ARM_ARCH_V3,     FPU_ARCH_FPA},
11788   {"arm620",            ARM_ARCH_V3,     FPU_ARCH_FPA},
11789   {"arm7",              ARM_ARCH_V3,     FPU_ARCH_FPA},
11790   {"arm7m",             ARM_ARCH_V3M,    FPU_ARCH_FPA},
11791   {"arm7d",             ARM_ARCH_V3,     FPU_ARCH_FPA},
11792   {"arm7dm",            ARM_ARCH_V3M,    FPU_ARCH_FPA},
11793   {"arm7di",            ARM_ARCH_V3,     FPU_ARCH_FPA},
11794   {"arm7dmi",           ARM_ARCH_V3M,    FPU_ARCH_FPA},
11795   {"arm70",             ARM_ARCH_V3,     FPU_ARCH_FPA},
11796   {"arm700",            ARM_ARCH_V3,     FPU_ARCH_FPA},
11797   {"arm700i",           ARM_ARCH_V3,     FPU_ARCH_FPA},
11798   {"arm710",            ARM_ARCH_V3,     FPU_ARCH_FPA},
11799   {"arm710t",           ARM_ARCH_V4T,    FPU_ARCH_FPA},
11800   {"arm720",            ARM_ARCH_V3,     FPU_ARCH_FPA},
11801   {"arm720t",           ARM_ARCH_V4T,    FPU_ARCH_FPA},
11802   {"arm740t",           ARM_ARCH_V4T,    FPU_ARCH_FPA},
11803   {"arm710c",           ARM_ARCH_V3,     FPU_ARCH_FPA},
11804   {"arm7100",           ARM_ARCH_V3,     FPU_ARCH_FPA},
11805   {"arm7500",           ARM_ARCH_V3,     FPU_ARCH_FPA},
11806   {"arm7500fe",         ARM_ARCH_V3,     FPU_ARCH_FPA},
11807   {"arm7t",             ARM_ARCH_V4T,    FPU_ARCH_FPA},
11808   {"arm7tdmi",          ARM_ARCH_V4T,    FPU_ARCH_FPA},
11809   {"arm8",              ARM_ARCH_V4,     FPU_ARCH_FPA},
11810   {"arm810",            ARM_ARCH_V4,     FPU_ARCH_FPA},
11811   {"strongarm",         ARM_ARCH_V4,     FPU_ARCH_FPA},
11812   {"strongarm1",        ARM_ARCH_V4,     FPU_ARCH_FPA},
11813   {"strongarm110",      ARM_ARCH_V4,     FPU_ARCH_FPA},
11814   {"strongarm1100",     ARM_ARCH_V4,     FPU_ARCH_FPA},
11815   {"strongarm1110",     ARM_ARCH_V4,     FPU_ARCH_FPA},
11816   {"arm9",              ARM_ARCH_V4T,    FPU_ARCH_FPA},
11817   {"arm920",            ARM_ARCH_V4T,    FPU_ARCH_FPA},
11818   {"arm920t",           ARM_ARCH_V4T,    FPU_ARCH_FPA},
11819   {"arm922t",           ARM_ARCH_V4T,    FPU_ARCH_FPA},
11820   {"arm940t",           ARM_ARCH_V4T,    FPU_ARCH_FPA},
11821   {"arm9tdmi",          ARM_ARCH_V4T,    FPU_ARCH_FPA},
11822   /* For V5 or later processors we default to using VFP; but the user
11823      should really set the FPU type explicitly.  */
11824   {"arm9e-r0",          ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
11825   {"arm9e",             ARM_ARCH_V5TE,   FPU_ARCH_VFP_V2},
11826   {"arm926ej",          ARM_ARCH_V5TEJ,  FPU_ARCH_VFP_V2},
11827   {"arm946e-r0",        ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
11828   {"arm946e",           ARM_ARCH_V5TE,   FPU_ARCH_VFP_V2},
11829   {"arm966e-r0",        ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
11830   {"arm966e",           ARM_ARCH_V5TE,   FPU_ARCH_VFP_V2},
11831   {"arm10t",            ARM_ARCH_V5T,    FPU_ARCH_VFP_V1},
11832   {"arm10e",            ARM_ARCH_V5TE,   FPU_ARCH_VFP_V2},
11833   {"arm1020",           ARM_ARCH_V5TE,   FPU_ARCH_VFP_V2},
11834   {"arm1020t",          ARM_ARCH_V5T,    FPU_ARCH_VFP_V1},
11835   {"arm1020e",          ARM_ARCH_V5TE,   FPU_ARCH_VFP_V2},
11836   /* ??? XSCALE is really an architecture.  */
11837   {"xscale",            ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
11838   /* ??? iwmmxt is not a processor.  */
11839   {"iwmmxt",            ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
11840   {"i80200",            ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
11841   /* Maverick */
11842   {"ep9312",            ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_NONE},
11843   {NULL, 0, 0}
11844 };
11845
11846 struct arm_arch_option_table
11847 {
11848   char *name;
11849   int   value;
11850   int   default_fpu;
11851 };
11852
11853 /* This list should, at a minimum, contain all the architecture names
11854    recognized by GCC.  */
11855 static struct arm_arch_option_table arm_archs[] =
11856 {
11857   {"all",               ARM_ANY,         FPU_ARCH_FPA},
11858   {"armv1",             ARM_ARCH_V1,     FPU_ARCH_FPA},
11859   {"armv2",             ARM_ARCH_V2,     FPU_ARCH_FPA},
11860   {"armv2a",            ARM_ARCH_V2S,    FPU_ARCH_FPA},
11861   {"armv2s",            ARM_ARCH_V2S,    FPU_ARCH_FPA},
11862   {"armv3",             ARM_ARCH_V3,     FPU_ARCH_FPA},
11863   {"armv3m",            ARM_ARCH_V3M,    FPU_ARCH_FPA},
11864   {"armv4",             ARM_ARCH_V4,     FPU_ARCH_FPA},
11865   {"armv4xm",           ARM_ARCH_V4xM,   FPU_ARCH_FPA},
11866   {"armv4t",            ARM_ARCH_V4T,    FPU_ARCH_FPA},
11867   {"armv4txm",          ARM_ARCH_V4TxM,  FPU_ARCH_FPA},
11868   {"armv5",             ARM_ARCH_V5,     FPU_ARCH_VFP},
11869   {"armv5t",            ARM_ARCH_V5T,    FPU_ARCH_VFP},
11870   {"armv5txm",          ARM_ARCH_V5TxM,  FPU_ARCH_VFP},
11871   {"armv5te",           ARM_ARCH_V5TE,   FPU_ARCH_VFP},
11872   {"armv5texp",         ARM_ARCH_V5TExP, FPU_ARCH_VFP},
11873   {"armv5tej",          ARM_ARCH_V5TEJ,  FPU_ARCH_VFP},
11874   {"xscale",            ARM_ARCH_XSCALE, FPU_ARCH_VFP},
11875   {NULL, 0, 0}
11876 };
11877
11878 /* ISA extensions in the co-processor space.  */
11879 struct arm_arch_extension_table
11880 {
11881   char *name;
11882   int value;
11883 };
11884
11885 static struct arm_arch_extension_table arm_extensions[] =
11886 {
11887   {"maverick",          ARM_CEXT_MAVERICK},
11888   {"xscale",            ARM_CEXT_XSCALE},
11889   {"iwmmxt",            ARM_CEXT_IWMMXT},
11890   {NULL,                0}
11891 };
11892
11893 struct arm_fpu_option_table
11894 {
11895   char *name;
11896   int   value;
11897 };
11898
11899 /* This list should, at a minimum, contain all the fpu names
11900    recognized by GCC.  */
11901 static struct arm_fpu_option_table arm_fpus[] =
11902 {
11903   {"softfpa",           FPU_NONE},
11904   {"fpe",               FPU_ARCH_FPE},
11905   {"fpe2",              FPU_ARCH_FPE},
11906   {"fpe3",              FPU_ARCH_FPA},  /* Third release supports LFM/SFM.  */
11907   {"fpa",               FPU_ARCH_FPA},
11908   {"fpa10",             FPU_ARCH_FPA},
11909   {"fpa11",             FPU_ARCH_FPA},
11910   {"arm7500fe",         FPU_ARCH_FPA},
11911   {"softvfp",           FPU_ARCH_VFP},
11912   {"softvfp+vfp",       FPU_ARCH_VFP_V2},
11913   {"vfp",               FPU_ARCH_VFP_V2},
11914   {"vfp9",              FPU_ARCH_VFP_V2},
11915   {"vfp10",             FPU_ARCH_VFP_V2},
11916   {"vfp10-r0",          FPU_ARCH_VFP_V1},
11917   {"vfpxd",             FPU_ARCH_VFP_V1xD},
11918   {"arm1020t",          FPU_ARCH_VFP_V1},
11919   {"arm1020e",          FPU_ARCH_VFP_V2},
11920   {NULL, 0}
11921 };
11922
11923 struct arm_long_option_table
11924 {
11925   char *option;         /* Substring to match.  */
11926   char *help;           /* Help information.  */
11927   int (*func) PARAMS ((char *subopt));  /* Function to decode sub-option.  */
11928   char *deprecated;     /* If non-null, print this message.  */
11929 };
11930
11931 static int
11932 arm_parse_extension (str, opt_p)
11933      char *str;
11934      int *opt_p;
11935 {
11936   while (str != NULL && *str != 0)
11937     {
11938       struct arm_arch_extension_table *opt;
11939       char *ext;
11940       int optlen;
11941
11942       if (*str != '+')
11943         {
11944           as_bad (_("invalid architectural extension"));
11945           return 0;
11946         }
11947
11948       str++;
11949       ext = strchr (str, '+');
11950
11951       if (ext != NULL)
11952         optlen = ext - str;
11953       else
11954         optlen = strlen (str);
11955
11956       if (optlen == 0)
11957         {
11958           as_bad (_("missing architectural extension"));
11959           return 0;
11960         }
11961
11962       for (opt = arm_extensions; opt->name != NULL; opt++)
11963         if (strncmp (opt->name, str, optlen) == 0)
11964           {
11965             *opt_p |= opt->value;
11966             break;
11967           }
11968
11969       if (opt->name == NULL)
11970         {
11971           as_bad (_("unknown architectural extnsion `%s'"), str);
11972           return 0;
11973         }
11974
11975       str = ext;
11976     };
11977
11978   return 1;
11979 }
11980
11981 static int
11982 arm_parse_cpu (str)
11983      char *str;
11984 {
11985   struct arm_cpu_option_table *opt;
11986   char *ext = strchr (str, '+');
11987   int optlen;
11988
11989   if (ext != NULL)
11990     optlen = ext - str;
11991   else
11992     optlen = strlen (str);
11993
11994   if (optlen == 0)
11995     {
11996       as_bad (_("missing cpu name `%s'"), str);
11997       return 0;
11998     }
11999
12000   for (opt = arm_cpus; opt->name != NULL; opt++)
12001     if (strncmp (opt->name, str, optlen) == 0)
12002       {
12003         mcpu_cpu_opt = opt->value;
12004         mcpu_fpu_opt = opt->default_fpu;
12005
12006         if (ext != NULL)
12007           return arm_parse_extension (ext, &mcpu_cpu_opt);
12008
12009         return 1;
12010       }
12011
12012   as_bad (_("unknown cpu `%s'"), str);
12013   return 0;
12014 }
12015
12016 static int
12017 arm_parse_arch (str)
12018      char *str;
12019 {
12020   struct arm_arch_option_table *opt;
12021   char *ext = strchr (str, '+');
12022   int optlen;
12023
12024   if (ext != NULL)
12025     optlen = ext - str;
12026   else
12027     optlen = strlen (str);
12028
12029   if (optlen == 0)
12030     {
12031       as_bad (_("missing architecture name `%s'"), str);
12032       return 0;
12033     }
12034
12035
12036   for (opt = arm_archs; opt->name != NULL; opt++)
12037     if (strcmp (opt->name, str) == 0)
12038       {
12039         march_cpu_opt = opt->value;
12040         march_fpu_opt = opt->default_fpu;
12041
12042         if (ext != NULL)
12043           return arm_parse_extension (ext, &march_cpu_opt);
12044
12045         return 1;
12046       }
12047
12048   as_bad (_("unknown architecture `%s'\n"), str);
12049   return 0;
12050 }
12051
12052 static int
12053 arm_parse_fpu (str)
12054      char *str;
12055 {
12056   struct arm_fpu_option_table *opt;
12057
12058   for (opt = arm_fpus; opt->name != NULL; opt++)
12059     if (strcmp (opt->name, str) == 0)
12060       {
12061         mfpu_opt = opt->value;
12062         return 1;
12063       }
12064
12065   as_bad (_("unknown floating point format `%s'\n"), str);
12066   return 0;
12067 }
12068
12069 struct arm_long_option_table arm_long_opts[] =
12070 {
12071   {"mcpu=", N_("<cpu name>\t  assemble for CPU <cpu name>"),
12072    arm_parse_cpu, NULL},
12073   {"march=", N_("<arch name>\t  assemble for architecture <arch name>"),
12074    arm_parse_arch, NULL},
12075   {"mfpu=", N_("<fpu name>\t  assemble for FPU architecture <fpu name>"),
12076    arm_parse_fpu, NULL},
12077   {NULL, NULL, 0, NULL}
12078 };
12079
12080 int
12081 md_parse_option (c, arg)
12082      int    c;
12083      char * arg;
12084 {
12085   struct arm_option_table *opt;
12086   struct arm_long_option_table *lopt;
12087
12088   switch (c)
12089     {
12090 #ifdef OPTION_EB
12091     case OPTION_EB:
12092       target_big_endian = 1;
12093       break;
12094 #endif
12095
12096 #ifdef OPTION_EL
12097     case OPTION_EL:
12098       target_big_endian = 0;
12099       break;
12100 #endif
12101
12102     case 'a':
12103       /* Listing option.  Just ignore these, we don't support additional
12104          ones.  */
12105       return 0;
12106
12107     default:
12108       for (opt = arm_opts; opt->option != NULL; opt++)
12109         {
12110           if (c == opt->option[0]
12111               && ((arg == NULL && opt->option[1] == 0)
12112                   || strcmp (arg, opt->option + 1) == 0))
12113             {
12114 #if WARN_DEPRECATED
12115               /* If the option is deprecated, tell the user.  */
12116               if (opt->deprecated != NULL)
12117                 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
12118                            arg ? arg : "", _(opt->deprecated));
12119 #endif
12120
12121               if (opt->var != NULL)
12122                 *opt->var = opt->value;
12123
12124               return 1;
12125             }
12126         }
12127
12128       for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
12129         {
12130           /* These options are expected to have an argument.  */
12131           if (c == lopt->option[0]
12132               && arg != NULL
12133               && strncmp (arg, lopt->option + 1,
12134                           strlen (lopt->option + 1)) == 0)
12135             {
12136 #if WARN_DEPRECATED
12137               /* If the option is deprecated, tell the user.  */
12138               if (lopt->deprecated != NULL)
12139                 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
12140                            _(lopt->deprecated));
12141 #endif
12142
12143               /* Call the sup-option parser.  */
12144               return (*lopt->func)(arg + strlen (lopt->option) - 1);
12145             }
12146         }
12147
12148       as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : "");
12149       return 0;
12150     }
12151
12152   return 1;
12153 }
12154
12155 void
12156 md_show_usage (fp)
12157      FILE * fp;
12158 {
12159   struct arm_option_table *opt;
12160   struct arm_long_option_table *lopt;
12161
12162   fprintf (fp, _(" ARM-specific assembler options:\n"));
12163
12164   for (opt = arm_opts; opt->option != NULL; opt++)
12165     if (opt->help != NULL)
12166       fprintf (fp, "  -%-23s%s\n", opt->option, _(opt->help));
12167
12168   for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
12169     if (lopt->help != NULL)
12170       fprintf (fp, "  -%s%s\n", lopt->option, _(lopt->help));
12171
12172 #ifdef OPTION_EB
12173   fprintf (fp, _("\
12174   -EB                     assemble code for a big-endian cpu\n"));
12175 #endif
12176
12177 #ifdef OPTION_EL
12178   fprintf (fp, _("\
12179   -EL                     assemble code for a little-endian cpu\n"));
12180 #endif
12181 }
12182
12183 /* We need to be able to fix up arbitrary expressions in some statements.
12184    This is so that we can handle symbols that are an arbitrary distance from
12185    the pc.  The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12186    which returns part of an address in a form which will be valid for
12187    a data instruction.  We do this by pushing the expression into a symbol
12188    in the expr_section, and creating a fix for that.  */
12189
12190 static void
12191 fix_new_arm (frag, where, size, exp, pc_rel, reloc)
12192      fragS *       frag;
12193      int           where;
12194      short int     size;
12195      expressionS * exp;
12196      int           pc_rel;
12197      int           reloc;
12198 {
12199   fixS *           new_fix;
12200   arm_fix_data *   arm_data;
12201
12202   switch (exp->X_op)
12203     {
12204     case O_constant:
12205     case O_symbol:
12206     case O_add:
12207     case O_subtract:
12208       new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
12209       break;
12210
12211     default:
12212       new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
12213                          pc_rel, reloc);
12214       break;
12215     }
12216
12217   /* Mark whether the fix is to a THUMB instruction, or an ARM
12218      instruction.  */
12219   arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
12220   new_fix->tc_fix_data = (PTR) arm_data;
12221   arm_data->thumb_mode = thumb_mode;
12222
12223   return;
12224 }
12225
12226 /* This fix_new is called by cons via TC_CONS_FIX_NEW.  */
12227
12228 void
12229 cons_fix_new_arm (frag, where, size, exp)
12230      fragS *       frag;
12231      int           where;
12232      int           size;
12233      expressionS * exp;
12234 {
12235   bfd_reloc_code_real_type type;
12236   int pcrel = 0;
12237
12238   /* Pick a reloc.
12239      FIXME: @@ Should look at CPU word size.  */
12240   switch (size)
12241     {
12242     case 1:
12243       type = BFD_RELOC_8;
12244       break;
12245     case 2:
12246       type = BFD_RELOC_16;
12247       break;
12248     case 4:
12249     default:
12250       type = BFD_RELOC_32;
12251       break;
12252     case 8:
12253       type = BFD_RELOC_64;
12254       break;
12255     }
12256
12257   fix_new_exp (frag, where, (int) size, exp, pcrel, type);
12258 }
12259
12260 /* A good place to do this, although this was probably not intended
12261    for this kind of use.  We need to dump the literal pool before
12262    references are made to a null symbol pointer.  */
12263
12264 void
12265 arm_cleanup ()
12266 {
12267   literal_pool * pool;
12268
12269   for (pool = list_of_pools; pool; pool = pool->next)
12270     {
12271       /* Put it at the end of the relevent section.  */
12272       subseg_set (pool->section, pool->sub_section);
12273       s_ltorg (0);
12274     }
12275 }
12276
12277 void
12278 arm_start_line_hook ()
12279 {
12280   last_label_seen = NULL;
12281 }
12282
12283 void
12284 arm_frob_label (sym)
12285      symbolS * sym;
12286 {
12287   last_label_seen = sym;
12288
12289   ARM_SET_THUMB (sym, thumb_mode);
12290
12291 #if defined OBJ_COFF || defined OBJ_ELF
12292   ARM_SET_INTERWORK (sym, support_interwork);
12293 #endif
12294
12295   /* Note - do not allow local symbols (.Lxxx) to be labeled
12296      as Thumb functions.  This is because these labels, whilst
12297      they exist inside Thumb code, are not the entry points for
12298      possible ARM->Thumb calls.  Also, these labels can be used
12299      as part of a computed goto or switch statement.  eg gcc
12300      can generate code that looks like this:
12301
12302                 ldr  r2, [pc, .Laaa]
12303                 lsl  r3, r3, #2
12304                 ldr  r2, [r3, r2]
12305                 mov  pc, r2
12306
12307        .Lbbb:  .word .Lxxx
12308        .Lccc:  .word .Lyyy
12309        ..etc...
12310        .Laaa:   .word Lbbb
12311
12312      The first instruction loads the address of the jump table.
12313      The second instruction converts a table index into a byte offset.
12314      The third instruction gets the jump address out of the table.
12315      The fourth instruction performs the jump.
12316
12317      If the address stored at .Laaa is that of a symbol which has the
12318      Thumb_Func bit set, then the linker will arrange for this address
12319      to have the bottom bit set, which in turn would mean that the
12320      address computation performed by the third instruction would end
12321      up with the bottom bit set.  Since the ARM is capable of unaligned
12322      word loads, the instruction would then load the incorrect address
12323      out of the jump table, and chaos would ensue.  */
12324   if (label_is_thumb_function_name
12325       && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
12326       && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
12327     {
12328       /* When the address of a Thumb function is taken the bottom
12329          bit of that address should be set.  This will allow
12330          interworking between Arm and Thumb functions to work
12331          correctly.  */
12332
12333       THUMB_SET_FUNC (sym, 1);
12334
12335       label_is_thumb_function_name = FALSE;
12336     }
12337 }
12338
12339 /* Adjust the symbol table.  This marks Thumb symbols as distinct from
12340    ARM ones.  */
12341
12342 void
12343 arm_adjust_symtab ()
12344 {
12345 #ifdef OBJ_COFF
12346   symbolS * sym;
12347
12348   for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
12349     {
12350       if (ARM_IS_THUMB (sym))
12351         {
12352           if (THUMB_IS_FUNC (sym))
12353             {
12354               /* Mark the symbol as a Thumb function.  */
12355               if (   S_GET_STORAGE_CLASS (sym) == C_STAT
12356                   || S_GET_STORAGE_CLASS (sym) == C_LABEL)  /* This can happen!  */
12357                 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
12358
12359               else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
12360                 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
12361               else
12362                 as_bad (_("%s: unexpected function type: %d"),
12363                         S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
12364             }
12365           else switch (S_GET_STORAGE_CLASS (sym))
12366             {
12367             case C_EXT:
12368               S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
12369               break;
12370             case C_STAT:
12371               S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
12372               break;
12373             case C_LABEL:
12374               S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
12375               break;
12376             default:
12377               /* Do nothing.  */
12378               break;
12379             }
12380         }
12381
12382       if (ARM_IS_INTERWORK (sym))
12383         coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
12384     }
12385 #endif
12386 #ifdef OBJ_ELF
12387   symbolS * sym;
12388   char      bind;
12389
12390   for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
12391     {
12392       if (ARM_IS_THUMB (sym))
12393         {
12394           elf_symbol_type * elf_sym;
12395
12396           elf_sym = elf_symbol (symbol_get_bfdsym (sym));
12397           bind = ELF_ST_BIND (elf_sym);
12398
12399           /* If it's a .thumb_func, declare it as so,
12400              otherwise tag label as .code 16.  */
12401           if (THUMB_IS_FUNC (sym))
12402             elf_sym->internal_elf_sym.st_info =
12403               ELF_ST_INFO (bind, STT_ARM_TFUNC);
12404           else
12405             elf_sym->internal_elf_sym.st_info =
12406               ELF_ST_INFO (bind, STT_ARM_16BIT);
12407         }
12408     }
12409 #endif
12410 }
12411
12412 int
12413 arm_data_in_code ()
12414 {
12415   if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
12416     {
12417       *input_line_pointer = '/';
12418       input_line_pointer += 5;
12419       *input_line_pointer = 0;
12420       return 1;
12421     }
12422
12423   return 0;
12424 }
12425
12426 char *
12427 arm_canonicalize_symbol_name (name)
12428      char * name;
12429 {
12430   int len;
12431
12432   if (thumb_mode && (len = strlen (name)) > 5
12433       && streq (name + len - 5, "/data"))
12434     *(name + len - 5) = 0;
12435
12436   return name;
12437 }
12438
12439 #if defined OBJ_COFF || defined OBJ_ELF
12440 void
12441 arm_validate_fix (fixP)
12442      fixS * fixP;
12443 {
12444   /* If the destination of the branch is a defined symbol which does not have
12445      the THUMB_FUNC attribute, then we must be calling a function which has
12446      the (interfacearm) attribute.  We look for the Thumb entry point to that
12447      function and change the branch to refer to that function instead.  */
12448   if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
12449       && fixP->fx_addsy != NULL
12450       && S_IS_DEFINED (fixP->fx_addsy)
12451       && ! THUMB_IS_FUNC (fixP->fx_addsy))
12452     {
12453       fixP->fx_addsy = find_real_start (fixP->fx_addsy);
12454     }
12455 }
12456 #endif
12457
12458 int
12459 arm_force_relocation (fixp)
12460      struct fix * fixp;
12461 {
12462 #if defined (OBJ_COFF) && defined (TE_PE)
12463   if (fixp->fx_r_type == BFD_RELOC_RVA)
12464     return 1;
12465 #endif
12466 #ifdef OBJ_ELF
12467   if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
12468       || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
12469       || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
12470       || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
12471     return 1;
12472 #endif
12473
12474   /* Resolve these relocations even if the symbol is extern or weak.  */
12475   if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
12476       || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
12477       || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
12478     return 0;
12479
12480   return generic_force_reloc (fixp);
12481 }
12482
12483 #ifdef OBJ_COFF
12484 /* This is a little hack to help the gas/arm/adrl.s test.  It prevents
12485    local labels from being added to the output symbol table when they
12486    are used with the ADRL pseudo op.  The ADRL relocation should always
12487    be resolved before the binbary is emitted, so it is safe to say that
12488    it is adjustable.  */
12489
12490 bfd_boolean
12491 arm_fix_adjustable (fixP)
12492    fixS * fixP;
12493 {
12494   if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
12495     return 1;
12496   return 0;
12497 }
12498 #endif
12499
12500 #ifdef OBJ_ELF
12501 /* Relocations against Thumb function names must be left unadjusted,
12502    so that the linker can use this information to correctly set the
12503    bottom bit of their addresses.  The MIPS version of this function
12504    also prevents relocations that are mips-16 specific, but I do not
12505    know why it does this.
12506
12507    FIXME:
12508    There is one other problem that ought to be addressed here, but
12509    which currently is not:  Taking the address of a label (rather
12510    than a function) and then later jumping to that address.  Such
12511    addresses also ought to have their bottom bit set (assuming that
12512    they reside in Thumb code), but at the moment they will not.  */
12513
12514 bfd_boolean
12515 arm_fix_adjustable (fixP)
12516    fixS * fixP;
12517 {
12518   if (fixP->fx_addsy == NULL)
12519     return 1;
12520
12521   if (THUMB_IS_FUNC (fixP->fx_addsy)
12522       && fixP->fx_subsy == NULL)
12523     return 0;
12524
12525   /* We need the symbol name for the VTABLE entries.  */
12526   if (   fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
12527       || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12528     return 0;
12529
12530   /* Don't allow symbols to be discarded on GOT related relocs.  */
12531   if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
12532       || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
12533       || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF)
12534     return 0;
12535
12536   return 1;
12537 }
12538
12539 const char *
12540 elf32_arm_target_format ()
12541 {
12542   if (target_big_endian)
12543     {
12544       if (target_oabi)
12545         return "elf32-bigarm-oabi";
12546       else
12547         return "elf32-bigarm";
12548     }
12549   else
12550     {
12551       if (target_oabi)
12552         return "elf32-littlearm-oabi";
12553       else
12554         return "elf32-littlearm";
12555     }
12556 }
12557
12558 void
12559 armelf_frob_symbol (symp, puntp)
12560      symbolS * symp;
12561      int *     puntp;
12562 {
12563   elf_frob_symbol (symp, puntp);
12564 }
12565
12566 static bfd_reloc_code_real_type
12567 arm_parse_reloc ()
12568 {
12569   char         id [16];
12570   char *       ip;
12571   unsigned int i;
12572   static struct
12573   {
12574     char * str;
12575     int    len;
12576     bfd_reloc_code_real_type reloc;
12577   }
12578   reloc_map[] =
12579   {
12580 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
12581     MAP ("(got)",    BFD_RELOC_ARM_GOT32),
12582     MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
12583     /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
12584        branch instructions generated by GCC for PLT relocs.  */
12585     MAP ("(plt)",    BFD_RELOC_ARM_PLT32),
12586     { NULL, 0,         BFD_RELOC_UNUSED }
12587 #undef MAP
12588   };
12589
12590   for (i = 0, ip = input_line_pointer;
12591        i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
12592        i++, ip++)
12593     id[i] = TOLOWER (*ip);
12594
12595   for (i = 0; reloc_map[i].str; i++)
12596     if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
12597       break;
12598
12599   input_line_pointer += reloc_map[i].len;
12600
12601   return reloc_map[i].reloc;
12602 }
12603
12604 static void
12605 s_arm_elf_cons (nbytes)
12606      int nbytes;
12607 {
12608   expressionS exp;
12609
12610 #ifdef md_flush_pending_output
12611   md_flush_pending_output ();
12612 #endif
12613
12614   if (is_it_end_of_statement ())
12615     {
12616       demand_empty_rest_of_line ();
12617       return;
12618     }
12619
12620 #ifdef md_cons_align
12621   md_cons_align (nbytes);
12622 #endif
12623
12624   do
12625     {
12626       bfd_reloc_code_real_type reloc;
12627
12628       expression (& exp);
12629
12630       if (exp.X_op == O_symbol
12631           && * input_line_pointer == '('
12632           && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
12633         {
12634           reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
12635           int size = bfd_get_reloc_size (howto);
12636
12637           if (size > nbytes)
12638             as_bad ("%s relocations do not fit in %d bytes",
12639                     howto->name, nbytes);
12640           else
12641             {
12642               register char *p = frag_more ((int) nbytes);
12643               int offset = nbytes - size;
12644
12645               fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
12646                            &exp, 0, reloc);
12647             }
12648         }
12649       else
12650         emit_expr (&exp, (unsigned int) nbytes);
12651     }
12652   while (*input_line_pointer++ == ',');
12653
12654   /* Put terminator back into stream.  */
12655   input_line_pointer --;
12656   demand_empty_rest_of_line ();
12657 }
12658
12659 #endif /* OBJ_ELF */
12660
12661 /* This is called from HANDLE_ALIGN in write.c.  Fill in the contents
12662    of an rs_align_code fragment.  */
12663
12664 void
12665 arm_handle_align (fragP)
12666      fragS *fragP;
12667 {
12668   static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
12669   static char const thumb_noop[2] = { 0xc0, 0x46 };
12670   static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
12671   static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
12672
12673   int bytes, fix, noop_size;
12674   char * p;
12675   const char * noop;
12676
12677   if (fragP->fr_type != rs_align_code)
12678     return;
12679
12680   bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
12681   p = fragP->fr_literal + fragP->fr_fix;
12682   fix = 0;
12683
12684   if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
12685     bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
12686
12687   if (fragP->tc_frag_data)
12688     {
12689       if (target_big_endian)
12690         noop = thumb_bigend_noop;
12691       else
12692         noop = thumb_noop;
12693       noop_size = sizeof (thumb_noop);
12694     }
12695   else
12696     {
12697       if (target_big_endian)
12698         noop = arm_bigend_noop;
12699       else
12700         noop = arm_noop;
12701       noop_size = sizeof (arm_noop);
12702     }
12703
12704   if (bytes & (noop_size - 1))
12705     {
12706       fix = bytes & (noop_size - 1);
12707       memset (p, 0, fix);
12708       p += fix;
12709       bytes -= fix;
12710     }
12711
12712   while (bytes >= noop_size)
12713     {
12714       memcpy (p, noop, noop_size);
12715       p += noop_size;
12716       bytes -= noop_size;
12717       fix += noop_size;
12718     }
12719
12720   fragP->fr_fix += fix;
12721   fragP->fr_var = noop_size;
12722 }
12723
12724 /* Called from md_do_align.  Used to create an alignment
12725    frag in a code section.  */
12726
12727 void
12728 arm_frag_align_code (n, max)
12729      int n;
12730      int max;
12731 {
12732   char * p;
12733
12734   /* We assume that there will never be a requirment
12735      to support alignments greater than 32 bytes.  */
12736   if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
12737     as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
12738
12739   p = frag_var (rs_align_code,
12740                 MAX_MEM_FOR_RS_ALIGN_CODE,
12741                 1,
12742                 (relax_substateT) max,
12743                 (symbolS *) NULL,
12744                 (offsetT) n,
12745                 (char *) NULL);
12746   *p = 0;
12747
12748 }
12749
12750 /* Perform target specific initialisation of a frag.  */
12751
12752 void
12753 arm_init_frag (fragP)
12754      fragS *fragP;
12755 {
12756   /* Record whether this frag is in an ARM or a THUMB area.  */
12757   fragP->tc_frag_data = thumb_mode;
12758 }
This page took 0.708636 seconds and 4 git commands to generate.