33b0bea0350ccd3ca91b14fd5cf2725a1dba151b
[external/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 (rwe@pegasus.esprit.ec.org)
5         Modified by David Taylor (dtaylor@armltd.co.uk)
6         Cirrus coprocessor mods by Aldy Hernandez (aldyh@redhat.com)
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   { "file",        (void (*) PARAMS ((int))) dwarf2_directive_file, 0 },
2349   { "loc",         dwarf2_directive_loc,  0 },
2350 #else
2351   { "word",        cons, 4},
2352 #endif
2353   { "extend",      float_cons, 'x' },
2354   { "ldouble",     float_cons, 'x' },
2355   { "packed",      float_cons, 'p' },
2356   { 0, 0, 0 }
2357 };
2358
2359 /* Other internal functions.  */
2360 static int arm_parse_extension PARAMS ((char *, int *));
2361 static int arm_parse_cpu PARAMS ((char *));
2362 static int arm_parse_arch PARAMS ((char *));
2363 static int arm_parse_fpu PARAMS ((char *));
2364 #if defined OBJ_COFF || defined OBJ_ELF
2365 static void arm_add_note PARAMS ((const char *, const char *, unsigned int));
2366 #endif
2367
2368 /* Stuff needed to resolve the label ambiguity
2369    As:
2370      ...
2371      label:   <insn>
2372    may differ from:
2373      ...
2374      label:
2375               <insn>
2376 */
2377
2378 symbolS *  last_label_seen;
2379 static int label_is_thumb_function_name = FALSE;
2380
2381 /* Literal Pool stuff.  */
2382
2383 #define MAX_LITERAL_POOL_SIZE 1024
2384
2385 /* Literal pool structure.  Held on a per-section
2386    and per-sub-section basis.  */
2387 typedef struct literal_pool
2388 {
2389   expressionS    literals [MAX_LITERAL_POOL_SIZE];
2390   unsigned int   next_free_entry;
2391   unsigned int   id;
2392   symbolS *      symbol;
2393   segT           section;
2394   subsegT        sub_section;
2395   struct literal_pool * next;
2396 } literal_pool;
2397
2398 /* Pointer to a linked list of literal pools.  */
2399 literal_pool * list_of_pools = NULL;
2400
2401 static literal_pool * find_literal_pool PARAMS ((void));
2402 static literal_pool * find_or_make_literal_pool PARAMS ((void));
2403
2404 static literal_pool *
2405 find_literal_pool ()
2406 {
2407   literal_pool * pool;
2408
2409   for (pool = list_of_pools; pool != NULL; pool = pool->next)
2410     {
2411       if (pool->section == now_seg
2412           && pool->sub_section == now_subseg)
2413         break;
2414     }
2415
2416   return pool;
2417 }
2418
2419 static literal_pool *
2420 find_or_make_literal_pool ()
2421 {
2422   /* Next literal pool ID number.  */
2423   static unsigned int latest_pool_num = 1;
2424   literal_pool *      pool;
2425
2426   pool = find_literal_pool ();
2427
2428   if (pool == NULL)
2429     {
2430       /* Create a new pool.  */
2431       pool = (literal_pool *) xmalloc (sizeof (* pool));
2432       if (! pool)
2433         return NULL;
2434
2435       pool->next_free_entry = 0;
2436       pool->section         = now_seg;
2437       pool->sub_section     = now_subseg;
2438       pool->next            = list_of_pools;
2439       pool->symbol          = NULL;
2440
2441       /* Add it to the list.  */
2442       list_of_pools = pool;
2443     }
2444
2445   /* New pools, and emptied pools, will have a NULL symbol.  */
2446   if (pool->symbol == NULL)
2447     {
2448       pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
2449                                     (valueT) 0, &zero_address_frag);
2450       pool->id = latest_pool_num ++;
2451     }
2452
2453   /* Done.  */
2454   return pool;
2455 }
2456
2457 /* Add the literal in the global 'inst'
2458    structure to the relevent literal pool.  */
2459 static int
2460 add_to_lit_pool ()
2461 {
2462   literal_pool * pool;
2463   unsigned int entry;
2464
2465   pool = find_or_make_literal_pool ();
2466
2467   /* Check if this literal value is already in the pool.  */
2468   for (entry = 0; entry < pool->next_free_entry; entry ++)
2469     {
2470       if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2471           && (inst.reloc.exp.X_op == O_constant)
2472           && (pool->literals[entry].X_add_number
2473               == inst.reloc.exp.X_add_number)
2474           && (pool->literals[entry].X_unsigned
2475               == inst.reloc.exp.X_unsigned))
2476         break;
2477
2478       if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2479           && (inst.reloc.exp.X_op == O_symbol)
2480           && (pool->literals[entry].X_add_number
2481               == inst.reloc.exp.X_add_number)
2482           && (pool->literals[entry].X_add_symbol
2483               == inst.reloc.exp.X_add_symbol)
2484           && (pool->literals[entry].X_op_symbol
2485               == inst.reloc.exp.X_op_symbol))
2486         break;
2487     }
2488
2489   /* Do we need to create a new entry?  */
2490   if (entry == pool->next_free_entry)
2491     {
2492       if (entry >= MAX_LITERAL_POOL_SIZE)
2493         {
2494           inst.error = _("literal pool overflow");
2495           return FAIL;
2496         }
2497
2498       pool->literals[entry] = inst.reloc.exp;
2499       pool->next_free_entry += 1;
2500     }
2501
2502   inst.reloc.exp.X_op         = O_symbol;
2503   inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
2504   inst.reloc.exp.X_add_symbol = pool->symbol;
2505
2506   return SUCCESS;
2507 }
2508
2509 /* Can't use symbol_new here, so have to create a symbol and then at
2510    a later date assign it a value. Thats what these functions do.  */
2511
2512 static void
2513 symbol_locate (symbolP, name, segment, valu, frag)
2514      symbolS *    symbolP;
2515      const char * name;         /* It is copied, the caller can modify.  */
2516      segT         segment;      /* Segment identifier (SEG_<something>).  */
2517      valueT       valu;         /* Symbol value.  */
2518      fragS *      frag;         /* Associated fragment.  */
2519 {
2520   unsigned int name_length;
2521   char * preserved_copy_of_name;
2522
2523   name_length = strlen (name) + 1;   /* +1 for \0.  */
2524   obstack_grow (&notes, name, name_length);
2525   preserved_copy_of_name = obstack_finish (&notes);
2526 #ifdef STRIP_UNDERSCORE
2527   if (preserved_copy_of_name[0] == '_')
2528     preserved_copy_of_name++;
2529 #endif
2530
2531 #ifdef tc_canonicalize_symbol_name
2532   preserved_copy_of_name =
2533     tc_canonicalize_symbol_name (preserved_copy_of_name);
2534 #endif
2535
2536   S_SET_NAME (symbolP, preserved_copy_of_name);
2537
2538   S_SET_SEGMENT (symbolP, segment);
2539   S_SET_VALUE (symbolP, valu);
2540   symbol_clear_list_pointers (symbolP);
2541
2542   symbol_set_frag (symbolP, frag);
2543
2544   /* Link to end of symbol chain.  */
2545   {
2546     extern int symbol_table_frozen;
2547     if (symbol_table_frozen)
2548       abort ();
2549   }
2550
2551   symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
2552
2553   obj_symbol_new_hook (symbolP);
2554
2555 #ifdef tc_symbol_new_hook
2556   tc_symbol_new_hook (symbolP);
2557 #endif
2558
2559 #ifdef DEBUG_SYMS
2560   verify_symbol_chain (symbol_rootP, symbol_lastP);
2561 #endif /* DEBUG_SYMS  */
2562 }
2563
2564 /* Check that an immediate is valid.
2565    If so, convert it to the right format.  */
2566
2567 static unsigned int
2568 validate_immediate (val)
2569      unsigned int val;
2570 {
2571   unsigned int a;
2572   unsigned int i;
2573
2574 #define rotate_left(v, n) (v << n | v >> (32 - n))
2575
2576   for (i = 0; i < 32; i += 2)
2577     if ((a = rotate_left (val, i)) <= 0xff)
2578       return a | (i << 7); /* 12-bit pack: [shift-cnt,const].  */
2579
2580   return FAIL;
2581 }
2582
2583 /* Check to see if an immediate can be computed as two seperate immediate
2584    values, added together.  We already know that this value cannot be
2585    computed by just one ARM instruction.  */
2586
2587 static unsigned int
2588 validate_immediate_twopart (val, highpart)
2589      unsigned int   val;
2590      unsigned int * highpart;
2591 {
2592   unsigned int a;
2593   unsigned int i;
2594
2595   for (i = 0; i < 32; i += 2)
2596     if (((a = rotate_left (val, i)) & 0xff) != 0)
2597       {
2598         if (a & 0xff00)
2599           {
2600             if (a & ~ 0xffff)
2601               continue;
2602             * highpart = (a  >> 8) | ((i + 24) << 7);
2603           }
2604         else if (a & 0xff0000)
2605           {
2606             if (a & 0xff000000)
2607               continue;
2608             * highpart = (a >> 16) | ((i + 16) << 7);
2609           }
2610         else
2611           {
2612             assert (a & 0xff000000);
2613             * highpart = (a >> 24) | ((i + 8) << 7);
2614           }
2615
2616         return (a & 0xff) | (i << 7);
2617       }
2618
2619   return FAIL;
2620 }
2621
2622 static int
2623 validate_offset_imm (val, hwse)
2624      unsigned int val;
2625      int hwse;
2626 {
2627   if ((hwse && val > 255) || val > 4095)
2628     return FAIL;
2629   return val;
2630 }
2631
2632 static void
2633 s_req (a)
2634      int a ATTRIBUTE_UNUSED;
2635 {
2636   as_bad (_("invalid syntax for .req directive"));
2637 }
2638
2639 static void
2640 s_bss (ignore)
2641      int ignore ATTRIBUTE_UNUSED;
2642 {
2643   /* We don't support putting frags in the BSS segment, we fake it by
2644      marking in_bss, then looking at s_skip for clues.  */
2645   subseg_set (bss_section, 0);
2646   demand_empty_rest_of_line ();
2647 }
2648
2649 static void
2650 s_even (ignore)
2651      int ignore ATTRIBUTE_UNUSED;
2652 {
2653   /* Never make frag if expect extra pass.  */
2654   if (!need_pass_2)
2655     frag_align (1, 0, 0);
2656
2657   record_alignment (now_seg, 1);
2658
2659   demand_empty_rest_of_line ();
2660 }
2661
2662 static void
2663 s_ltorg (ignored)
2664      int ignored ATTRIBUTE_UNUSED;
2665 {
2666   unsigned int entry;
2667   literal_pool * pool;
2668   char sym_name[20];
2669
2670   pool = find_literal_pool ();
2671   if (pool == NULL
2672       || pool->symbol == NULL
2673       || pool->next_free_entry == 0)
2674     return;
2675
2676   /* Align pool as you have word accesses.
2677      Only make a frag if we have to.  */
2678   if (!need_pass_2)
2679     frag_align (2, 0, 0);
2680
2681   record_alignment (now_seg, 2);
2682
2683   sprintf (sym_name, "$$lit_\002%x", pool->id);
2684
2685   symbol_locate (pool->symbol, sym_name, now_seg,
2686                  (valueT) frag_now_fix (), frag_now);
2687   symbol_table_insert (pool->symbol);
2688
2689   ARM_SET_THUMB (pool->symbol, thumb_mode);
2690
2691 #if defined OBJ_COFF || defined OBJ_ELF
2692   ARM_SET_INTERWORK (pool->symbol, support_interwork);
2693 #endif
2694
2695   for (entry = 0; entry < pool->next_free_entry; entry ++)
2696     /* First output the expression in the instruction to the pool.  */
2697     emit_expr (&(pool->literals[entry]), 4); /* .word  */
2698
2699   /* Mark the pool as empty.  */
2700   pool->next_free_entry = 0;
2701   pool->symbol = NULL;
2702 }
2703
2704 /* Same as s_align_ptwo but align 0 => align 2.  */
2705
2706 static void
2707 s_align (unused)
2708      int unused ATTRIBUTE_UNUSED;
2709 {
2710   register int temp;
2711   register long temp_fill;
2712   long max_alignment = 15;
2713
2714   temp = get_absolute_expression ();
2715   if (temp > max_alignment)
2716     as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
2717   else if (temp < 0)
2718     {
2719       as_bad (_("alignment negative. 0 assumed."));
2720       temp = 0;
2721     }
2722
2723   if (*input_line_pointer == ',')
2724     {
2725       input_line_pointer++;
2726       temp_fill = get_absolute_expression ();
2727     }
2728   else
2729     temp_fill = 0;
2730
2731   if (!temp)
2732     temp = 2;
2733
2734   /* Only make a frag if we HAVE to.  */
2735   if (temp && !need_pass_2)
2736     frag_align (temp, (int) temp_fill, 0);
2737   demand_empty_rest_of_line ();
2738
2739   record_alignment (now_seg, temp);
2740 }
2741
2742 static void
2743 s_force_thumb (ignore)
2744      int ignore ATTRIBUTE_UNUSED;
2745 {
2746   /* If we are not already in thumb mode go into it, EVEN if
2747      the target processor does not support thumb instructions.
2748      This is used by gcc/config/arm/lib1funcs.asm for example
2749      to compile interworking support functions even if the
2750      target processor should not support interworking.  */
2751   if (! thumb_mode)
2752     {
2753       thumb_mode = 2;
2754
2755       record_alignment (now_seg, 1);
2756     }
2757
2758   demand_empty_rest_of_line ();
2759 }
2760
2761 static void
2762 s_thumb_func (ignore)
2763      int ignore ATTRIBUTE_UNUSED;
2764 {
2765   if (! thumb_mode)
2766     opcode_select (16);
2767
2768   /* The following label is the name/address of the start of a Thumb function.
2769      We need to know this for the interworking support.  */
2770   label_is_thumb_function_name = TRUE;
2771
2772   demand_empty_rest_of_line ();
2773 }
2774
2775 /* Perform a .set directive, but also mark the alias as
2776    being a thumb function.  */
2777
2778 static void
2779 s_thumb_set (equiv)
2780      int equiv;
2781 {
2782   /* XXX the following is a duplicate of the code for s_set() in read.c
2783      We cannot just call that code as we need to get at the symbol that
2784      is created.  */
2785   register char *    name;
2786   register char      delim;
2787   register char *    end_name;
2788   register symbolS * symbolP;
2789
2790   /* Especial apologies for the random logic:
2791      This just grew, and could be parsed much more simply!
2792      Dean - in haste.  */
2793   name      = input_line_pointer;
2794   delim     = get_symbol_end ();
2795   end_name  = input_line_pointer;
2796   *end_name = delim;
2797
2798   SKIP_WHITESPACE ();
2799
2800   if (*input_line_pointer != ',')
2801     {
2802       *end_name = 0;
2803       as_bad (_("expected comma after name \"%s\""), name);
2804       *end_name = delim;
2805       ignore_rest_of_line ();
2806       return;
2807     }
2808
2809   input_line_pointer++;
2810   *end_name = 0;
2811
2812   if (name[0] == '.' && name[1] == '\0')
2813     {
2814       /* XXX - this should not happen to .thumb_set.  */
2815       abort ();
2816     }
2817
2818   if ((symbolP = symbol_find (name)) == NULL
2819       && (symbolP = md_undefined_symbol (name)) == NULL)
2820     {
2821 #ifndef NO_LISTING
2822       /* When doing symbol listings, play games with dummy fragments living
2823          outside the normal fragment chain to record the file and line info
2824          for this symbol.  */
2825       if (listing & LISTING_SYMBOLS)
2826         {
2827           extern struct list_info_struct * listing_tail;
2828           fragS * dummy_frag = (fragS *) xmalloc (sizeof (fragS));
2829
2830           memset (dummy_frag, 0, sizeof (fragS));
2831           dummy_frag->fr_type = rs_fill;
2832           dummy_frag->line = listing_tail;
2833           symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
2834           dummy_frag->fr_symbol = symbolP;
2835         }
2836       else
2837 #endif
2838         symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
2839
2840 #ifdef OBJ_COFF
2841       /* "set" symbols are local unless otherwise specified.  */
2842       SF_SET_LOCAL (symbolP);
2843 #endif /* OBJ_COFF  */
2844     }                           /* Make a new symbol.  */
2845
2846   symbol_table_insert (symbolP);
2847
2848   * end_name = delim;
2849
2850   if (equiv
2851       && S_IS_DEFINED (symbolP)
2852       && S_GET_SEGMENT (symbolP) != reg_section)
2853     as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
2854
2855   pseudo_set (symbolP);
2856
2857   demand_empty_rest_of_line ();
2858
2859   /* XXX Now we come to the Thumb specific bit of code.  */
2860
2861   THUMB_SET_FUNC (symbolP, 1);
2862   ARM_SET_THUMB (symbolP, 1);
2863 #if defined OBJ_ELF || defined OBJ_COFF
2864   ARM_SET_INTERWORK (symbolP, support_interwork);
2865 #endif
2866 }
2867
2868 static void
2869 opcode_select (width)
2870      int width;
2871 {
2872   switch (width)
2873     {
2874     case 16:
2875       if (! thumb_mode)
2876         {
2877           if (! (cpu_variant & ARM_EXT_V4T))
2878             as_bad (_("selected processor does not support THUMB opcodes"));
2879
2880           thumb_mode = 1;
2881           /* No need to force the alignment, since we will have been
2882              coming from ARM mode, which is word-aligned.  */
2883           record_alignment (now_seg, 1);
2884         }
2885       break;
2886
2887     case 32:
2888       if (thumb_mode)
2889         {
2890           if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
2891             as_bad (_("selected processor does not support ARM opcodes"));
2892
2893           thumb_mode = 0;
2894
2895           if (!need_pass_2)
2896             frag_align (2, 0, 0);
2897
2898           record_alignment (now_seg, 1);
2899         }
2900       break;
2901
2902     default:
2903       as_bad (_("invalid instruction size selected (%d)"), width);
2904     }
2905 }
2906
2907 static void
2908 s_arm (ignore)
2909      int ignore ATTRIBUTE_UNUSED;
2910 {
2911   opcode_select (32);
2912   demand_empty_rest_of_line ();
2913 }
2914
2915 static void
2916 s_thumb (ignore)
2917      int ignore ATTRIBUTE_UNUSED;
2918 {
2919   opcode_select (16);
2920   demand_empty_rest_of_line ();
2921 }
2922
2923 static void
2924 s_code (unused)
2925      int unused ATTRIBUTE_UNUSED;
2926 {
2927   register int temp;
2928
2929   temp = get_absolute_expression ();
2930   switch (temp)
2931     {
2932     case 16:
2933     case 32:
2934       opcode_select (temp);
2935       break;
2936
2937     default:
2938       as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
2939     }
2940 }
2941
2942 static void
2943 end_of_line (str)
2944      char *str;
2945 {
2946   skip_whitespace (str);
2947
2948   if (*str != '\0' && !inst.error)
2949     inst.error = _("garbage following instruction");
2950 }
2951
2952 static int
2953 skip_past_comma (str)
2954      char ** str;
2955 {
2956   char * p = * str, c;
2957   int comma = 0;
2958
2959   while ((c = *p) == ' ' || c == ',')
2960     {
2961       p++;
2962       if (c == ',' && comma++)
2963         return FAIL;
2964     }
2965
2966   if (c == '\0')
2967     return FAIL;
2968
2969   *str = p;
2970   return comma ? SUCCESS : FAIL;
2971 }
2972
2973 /* A standard register must be given at this point.
2974    SHIFT is the place to put it in inst.instruction.
2975    Restores input start point on error.
2976    Returns the reg#, or FAIL.  */
2977
2978 static int
2979 reg_required_here (str, shift)
2980      char ** str;
2981      int     shift;
2982 {
2983   static char buff [128]; /* XXX  */
2984   int         reg;
2985   char *      start = * str;
2986
2987   if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
2988     {
2989       if (shift >= 0)
2990         inst.instruction |= reg << shift;
2991       return reg;
2992     }
2993
2994   /* Restore the start point, we may have got a reg of the wrong class.  */
2995   *str = start;
2996
2997   /* In the few cases where we might be able to accept something else
2998      this error can be overridden.  */
2999   sprintf (buff, _("register expected, not '%.100s'"), start);
3000   inst.error = buff;
3001
3002   return FAIL;
3003 }
3004
3005 /* A Intel Wireless MMX technology register
3006    must be given at this point.
3007    Shift is the place to put it in inst.instruction.
3008    Restores input start point on err.
3009    Returns the reg#, or FAIL.  */
3010
3011 static int
3012 wreg_required_here (str, shift, reg_type)
3013      char ** str;
3014      int     shift;
3015      enum wreg_type reg_type;
3016 {
3017   static char buff [128];
3018   int    reg;
3019   char * start = *str;
3020
3021   if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
3022     {
3023       if (wr_register (reg)
3024           && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
3025         {
3026           if (shift >= 0)
3027             inst.instruction |= (reg ^ WR_PREFIX) << shift;
3028           return reg;
3029         }
3030       else if (wc_register (reg)
3031                && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
3032         {
3033           if (shift >= 0)
3034             inst.instruction |= (reg ^ WC_PREFIX) << shift;
3035           return reg;
3036         }
3037       else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
3038         {
3039           if (shift >= 0)
3040             inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
3041           return reg;
3042         }
3043     }
3044
3045   /* Restore the start point, we may have got a reg of the wrong class.  */
3046   *str = start;
3047
3048   /* In the few cases where we might be able to accept
3049      something else this error can be overridden.  */
3050   sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
3051   inst.error = buff;
3052
3053   return FAIL;
3054 }
3055
3056 static const struct asm_psr *
3057 arm_psr_parse (ccp)
3058      register char ** ccp;
3059 {
3060   char * start = * ccp;
3061   char   c;
3062   char * p;
3063   const struct asm_psr * psr;
3064
3065   p = start;
3066
3067   /* Skip to the end of the next word in the input stream.  */
3068   do
3069     {
3070       c = *p++;
3071     }
3072   while (ISALPHA (c) || c == '_');
3073
3074   /* Terminate the word.  */
3075   *--p = 0;
3076
3077   /* CPSR's and SPSR's can now be lowercase.  This is just a convenience
3078      feature for ease of use and backwards compatibility.  */
3079   if (!strncmp (start, "cpsr", 4))
3080     strncpy (start, "CPSR", 4);
3081   else if (!strncmp (start, "spsr", 4))
3082     strncpy (start, "SPSR", 4);
3083
3084   /* Now locate the word in the psr hash table.  */
3085   psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
3086
3087   /* Restore the input stream.  */
3088   *p = c;
3089
3090   /* If we found a valid match, advance the
3091      stream pointer past the end of the word.  */
3092   *ccp = p;
3093
3094   return psr;
3095 }
3096
3097 /* Parse the input looking for a PSR flag.  */
3098
3099 static int
3100 psr_required_here (str)
3101      char ** str;
3102 {
3103   char * start = * str;
3104   const struct asm_psr * psr;
3105
3106   psr = arm_psr_parse (str);
3107
3108   if (psr)
3109     {
3110       /* If this is the SPSR that is being modified, set the R bit.  */
3111       if (! psr->cpsr)
3112         inst.instruction |= SPSR_BIT;
3113
3114       /* Set the psr flags in the MSR instruction.  */
3115       inst.instruction |= psr->field << PSR_SHIFT;
3116
3117       return SUCCESS;
3118     }
3119
3120   /* In the few cases where we might be able to accept
3121      something else this error can be overridden.  */
3122   inst.error = _("flag for {c}psr instruction expected");
3123
3124   /* Restore the start point.  */
3125   *str = start;
3126   return FAIL;
3127 }
3128
3129 static int
3130 co_proc_number (str)
3131      char **str;
3132 {
3133   int processor, pchar;
3134   char *start;
3135
3136   skip_whitespace (*str);
3137   start = *str;
3138
3139   /* The data sheet seems to imply that just a number on its own is valid
3140      here, but the RISC iX assembler seems to accept a prefix 'p'.  We will
3141      accept either.  */
3142   if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
3143       == FAIL)
3144     {
3145       *str = start;
3146
3147       pchar = *(*str)++;
3148       if (pchar >= '0' && pchar <= '9')
3149         {
3150           processor = pchar - '0';
3151           if (**str >= '0' && **str <= '9')
3152             {
3153               processor = processor * 10 + *(*str)++ - '0';
3154               if (processor > 15)
3155                 {
3156                   inst.error = _("illegal co-processor number");
3157                   return FAIL;
3158                 }
3159             }
3160         }
3161       else
3162         {
3163           inst.error = _("bad or missing co-processor number");
3164           return FAIL;
3165         }
3166     }
3167
3168   inst.instruction |= processor << 8;
3169   return SUCCESS;
3170 }
3171
3172 static int
3173 cp_opc_expr (str, where, length)
3174      char ** str;
3175      int where;
3176      int length;
3177 {
3178   expressionS expr;
3179
3180   skip_whitespace (* str);
3181
3182   memset (&expr, '\0', sizeof (expr));
3183
3184   if (my_get_expression (&expr, str))
3185     return FAIL;
3186   if (expr.X_op != O_constant)
3187     {
3188       inst.error = _("bad or missing expression");
3189       return FAIL;
3190     }
3191
3192   if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
3193     {
3194       inst.error = _("immediate co-processor expression too large");
3195       return FAIL;
3196     }
3197
3198   inst.instruction |= expr.X_add_number << where;
3199   return SUCCESS;
3200 }
3201
3202 static int
3203 cp_reg_required_here (str, where)
3204      char ** str;
3205      int     where;
3206 {
3207   int    reg;
3208   char * start = *str;
3209
3210   if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
3211     {
3212       inst.instruction |= reg << where;
3213       return reg;
3214     }
3215
3216   /* In the few cases where we might be able to accept something else
3217      this error can be overridden.  */
3218   inst.error = _("co-processor register expected");
3219
3220   /* Restore the start point.  */
3221   *str = start;
3222   return FAIL;
3223 }
3224
3225 static int
3226 fp_reg_required_here (str, where)
3227      char ** str;
3228      int     where;
3229 {
3230   int    reg;
3231   char * start = * str;
3232
3233   if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
3234     {
3235       inst.instruction |= reg << where;
3236       return reg;
3237     }
3238
3239   /* In the few cases where we might be able to accept something else
3240      this error can be overridden.  */
3241   inst.error = _("floating point register expected");
3242
3243   /* Restore the start point.  */
3244   *str = start;
3245   return FAIL;
3246 }
3247
3248 static int
3249 cp_address_offset (str)
3250      char ** str;
3251 {
3252   int offset;
3253
3254   skip_whitespace (* str);
3255
3256   if (! is_immediate_prefix (**str))
3257     {
3258       inst.error = _("immediate expression expected");
3259       return FAIL;
3260     }
3261
3262   (*str)++;
3263
3264   if (my_get_expression (& inst.reloc.exp, str))
3265     return FAIL;
3266
3267   if (inst.reloc.exp.X_op == O_constant)
3268     {
3269       offset = inst.reloc.exp.X_add_number;
3270
3271       if (offset & 3)
3272         {
3273           inst.error = _("co-processor address must be word aligned");
3274           return FAIL;
3275         }
3276
3277       if (offset > 1023 || offset < -1023)
3278         {
3279           inst.error = _("offset too large");
3280           return FAIL;
3281         }
3282
3283       if (offset >= 0)
3284         inst.instruction |= INDEX_UP;
3285       else
3286         offset = -offset;
3287
3288       inst.instruction |= offset >> 2;
3289     }
3290   else
3291     inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3292
3293   return SUCCESS;
3294 }
3295
3296 static int
3297 cp_address_required_here (str, wb_ok)
3298      char ** str;
3299      int wb_ok;
3300 {
3301   char * p = * str;
3302   int    pre_inc = 0;
3303   int    write_back = 0;
3304
3305   if (*p == '[')
3306     {
3307       int reg;
3308
3309       p++;
3310       skip_whitespace (p);
3311
3312       if ((reg = reg_required_here (& p, 16)) == FAIL)
3313         return FAIL;
3314
3315       skip_whitespace (p);
3316
3317       if (*p == ']')
3318         {
3319           p++;
3320
3321           if (wb_ok && skip_past_comma (& p) == SUCCESS)
3322             {
3323               /* [Rn], #expr  */
3324               write_back = WRITE_BACK;
3325
3326               if (reg == REG_PC)
3327                 {
3328                   inst.error = _("pc may not be used in post-increment");
3329                   return FAIL;
3330                 }
3331
3332               if (cp_address_offset (& p) == FAIL)
3333                 return FAIL;
3334             }
3335           else
3336             pre_inc = PRE_INDEX | INDEX_UP;
3337         }
3338       else
3339         {
3340           /* '['Rn, #expr']'[!]  */
3341
3342           if (skip_past_comma (& p) == FAIL)
3343             {
3344               inst.error = _("pre-indexed expression expected");
3345               return FAIL;
3346             }
3347
3348           pre_inc = PRE_INDEX;
3349
3350           if (cp_address_offset (& p) == FAIL)
3351             return FAIL;
3352
3353           skip_whitespace (p);
3354
3355           if (*p++ != ']')
3356             {
3357               inst.error = _("missing ]");
3358               return FAIL;
3359             }
3360
3361           skip_whitespace (p);
3362
3363           if (wb_ok && *p == '!')
3364             {
3365               if (reg == REG_PC)
3366                 {
3367                   inst.error = _("pc may not be used with write-back");
3368                   return FAIL;
3369                 }
3370
3371               p++;
3372               write_back = WRITE_BACK;
3373             }
3374         }
3375     }
3376   else
3377     {
3378       if (my_get_expression (&inst.reloc.exp, &p))
3379         return FAIL;
3380
3381       inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3382       inst.reloc.exp.X_add_number -= 8;  /* PC rel adjust.  */
3383       inst.reloc.pc_rel = 1;
3384       inst.instruction |= (REG_PC << 16);
3385       pre_inc = PRE_INDEX;
3386     }
3387
3388   inst.instruction |= write_back | pre_inc;
3389   *str = p;
3390   return SUCCESS;
3391 }
3392
3393 static int
3394 cp_byte_address_offset (str)
3395      char ** str;
3396 {
3397   int offset;
3398
3399   skip_whitespace (* str);
3400
3401   if (! is_immediate_prefix (**str))
3402     {
3403       inst.error = _("immediate expression expected");
3404       return FAIL;
3405     }
3406
3407   (*str)++;
3408   
3409   if (my_get_expression (& inst.reloc.exp, str))
3410     return FAIL;
3411   
3412   if (inst.reloc.exp.X_op == O_constant)
3413     {
3414       offset = inst.reloc.exp.X_add_number;
3415       
3416       if (offset > 255 || offset < -255)
3417         {
3418           inst.error = _("offset too large");
3419           return FAIL;
3420         }
3421
3422       if (offset >= 0)
3423         inst.instruction |= INDEX_UP;
3424       else
3425         offset = -offset;
3426
3427       inst.instruction |= offset;
3428     }
3429   else
3430     inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3431
3432   return SUCCESS;
3433 }
3434
3435 static int
3436 cp_byte_address_required_here (str)
3437      char ** str;
3438 {
3439   char * p = * str;
3440   int    pre_inc = 0;
3441   int    write_back = 0;
3442
3443   if (*p == '[')
3444     {
3445       int reg;
3446
3447       p++;
3448       skip_whitespace (p);
3449
3450       if ((reg = reg_required_here (& p, 16)) == FAIL)
3451         return FAIL;
3452
3453       skip_whitespace (p);
3454
3455       if (*p == ']')
3456         {
3457           p++;
3458           
3459           if (skip_past_comma (& p) == SUCCESS)
3460             {
3461               /* [Rn], #expr */
3462               write_back = WRITE_BACK;
3463               
3464               if (reg == REG_PC)
3465                 {
3466                   inst.error = _("pc may not be used in post-increment");
3467                   return FAIL;
3468                 }
3469
3470               if (cp_byte_address_offset (& p) == FAIL)
3471                 return FAIL;
3472             }
3473           else
3474             pre_inc = PRE_INDEX | INDEX_UP;
3475         }
3476       else
3477         {
3478           /* '['Rn, #expr']'[!] */
3479
3480           if (skip_past_comma (& p) == FAIL)
3481             {
3482               inst.error = _("pre-indexed expression expected");
3483               return FAIL;
3484             }
3485
3486           pre_inc = PRE_INDEX;
3487           
3488           if (cp_byte_address_offset (& p) == FAIL)
3489             return FAIL;
3490
3491           skip_whitespace (p);
3492
3493           if (*p++ != ']')
3494             {
3495               inst.error = _("missing ]");
3496               return FAIL;
3497             }
3498
3499           skip_whitespace (p);
3500
3501           if (*p == '!')
3502             {
3503               if (reg == REG_PC)
3504                 {
3505                   inst.error = _("pc may not be used with write-back");
3506                   return FAIL;
3507                 }
3508
3509               p++;
3510               write_back = WRITE_BACK;
3511             }
3512         }
3513     }
3514   else
3515     {
3516       if (my_get_expression (&inst.reloc.exp, &p))
3517         return FAIL;
3518
3519       inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3520       inst.reloc.exp.X_add_number -= 8;  /* PC rel adjust.  */
3521       inst.reloc.pc_rel = 1;
3522       inst.instruction |= (REG_PC << 16);
3523       pre_inc = PRE_INDEX;
3524     }
3525
3526   inst.instruction |= write_back | pre_inc;
3527   *str = p;
3528   return SUCCESS;
3529 }
3530
3531 static void
3532 do_empty (str)
3533      char * str;
3534 {
3535   /* Do nothing really.  */
3536   end_of_line (str);
3537   return;
3538 }
3539
3540 static void
3541 do_mrs (str)
3542      char *str;
3543 {
3544   int skip = 0;
3545
3546   /* Only one syntax.  */
3547   skip_whitespace (str);
3548
3549   if (reg_required_here (&str, 12) == FAIL)
3550     {
3551       inst.error = BAD_ARGS;
3552       return;
3553     }
3554
3555   if (skip_past_comma (&str) == FAIL)
3556     {
3557       inst.error = _("comma expected after register name");
3558       return;
3559     }
3560
3561   skip_whitespace (str);
3562
3563   if (   strcmp (str, "CPSR") == 0
3564       || strcmp (str, "SPSR") == 0
3565          /* Lower case versions for backwards compatability.  */
3566       || strcmp (str, "cpsr") == 0
3567       || strcmp (str, "spsr") == 0)
3568     skip = 4;
3569
3570   /* This is for backwards compatability with older toolchains.  */
3571   else if (   strcmp (str, "cpsr_all") == 0
3572            || strcmp (str, "spsr_all") == 0)
3573     skip = 8;
3574   else
3575     {
3576       inst.error = _("CPSR or SPSR expected");
3577       return;
3578     }
3579
3580   if (* str == 's' || * str == 'S')
3581     inst.instruction |= SPSR_BIT;
3582   str += skip;
3583
3584   end_of_line (str);
3585 }
3586
3587 /* Two possible forms:
3588       "{C|S}PSR_<field>, Rm",
3589       "{C|S}PSR_f, #expression".  */
3590
3591 static void
3592 do_msr (str)
3593      char * str;
3594 {
3595   skip_whitespace (str);
3596
3597   if (psr_required_here (& str) == FAIL)
3598     return;
3599
3600   if (skip_past_comma (& str) == FAIL)
3601     {
3602       inst.error = _("comma missing after psr flags");
3603       return;
3604     }
3605
3606   skip_whitespace (str);
3607
3608   if (reg_required_here (& str, 0) != FAIL)
3609     {
3610       inst.error = NULL;
3611       end_of_line (str);
3612       return;
3613     }
3614
3615   if (! is_immediate_prefix (* str))
3616     {
3617       inst.error =
3618         _("only a register or immediate value can follow a psr flag");
3619       return;
3620     }
3621
3622   str ++;
3623   inst.error = NULL;
3624
3625   if (my_get_expression (& inst.reloc.exp, & str))
3626     {
3627       inst.error =
3628         _("only a register or immediate value can follow a psr flag");
3629       return;
3630     }
3631
3632 #if 0  /* The first edition of the ARM architecture manual stated that
3633           writing anything other than the flags with an immediate operation
3634           had UNPREDICTABLE effects.  This constraint was removed in the
3635           second edition of the specification.  */
3636   if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
3637       && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
3638     {
3639       inst.error = _("immediate value cannot be used to set this field");
3640       return;
3641     }
3642 #endif
3643
3644   inst.instruction |= INST_IMMEDIATE;
3645
3646   if (inst.reloc.exp.X_add_symbol)
3647     {
3648       inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
3649       inst.reloc.pc_rel = 0;
3650     }
3651   else
3652     {
3653       unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
3654
3655       if (value == (unsigned) FAIL)
3656         {
3657           inst.error = _("invalid constant");
3658           return;
3659         }
3660
3661       inst.instruction |= value;
3662     }
3663
3664   inst.error = NULL;
3665   end_of_line (str);
3666 }
3667
3668 /* Long Multiply Parser
3669    UMULL RdLo, RdHi, Rm, Rs
3670    SMULL RdLo, RdHi, Rm, Rs
3671    UMLAL RdLo, RdHi, Rm, Rs
3672    SMLAL RdLo, RdHi, Rm, Rs.  */
3673
3674 static void
3675 do_mull (str)
3676      char * str;
3677 {
3678   int rdlo, rdhi, rm, rs;
3679
3680   /* Only one format "rdlo, rdhi, rm, rs".  */
3681   skip_whitespace (str);
3682
3683   if ((rdlo = reg_required_here (&str, 12)) == FAIL)
3684     {
3685       inst.error = BAD_ARGS;
3686       return;
3687     }
3688
3689   if (skip_past_comma (&str) == FAIL
3690       || (rdhi = reg_required_here (&str, 16)) == FAIL)
3691     {
3692       inst.error = BAD_ARGS;
3693       return;
3694     }
3695
3696   if (skip_past_comma (&str) == FAIL
3697       || (rm = reg_required_here (&str, 0)) == FAIL)
3698     {
3699       inst.error = BAD_ARGS;
3700       return;
3701     }
3702
3703   /* rdhi, rdlo and rm must all be different.  */
3704   if (rdlo == rdhi || rdlo == rm || rdhi == rm)
3705     as_tsktsk (_("rdhi, rdlo and rm must all be different"));
3706
3707   if (skip_past_comma (&str) == FAIL
3708       || (rs = reg_required_here (&str, 8)) == FAIL)
3709     {
3710       inst.error = BAD_ARGS;
3711       return;
3712     }
3713
3714   if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
3715     {
3716       inst.error = BAD_PC;
3717       return;
3718     }
3719
3720   end_of_line (str);
3721   return;
3722 }
3723
3724 static void
3725 do_mul (str)
3726      char * str;
3727 {
3728   int rd, rm;
3729
3730   /* Only one format "rd, rm, rs".  */
3731   skip_whitespace (str);
3732
3733   if ((rd = reg_required_here (&str, 16)) == FAIL)
3734     {
3735       inst.error = BAD_ARGS;
3736       return;
3737     }
3738
3739   if (rd == REG_PC)
3740     {
3741       inst.error = BAD_PC;
3742       return;
3743     }
3744
3745   if (skip_past_comma (&str) == FAIL
3746       || (rm = reg_required_here (&str, 0)) == FAIL)
3747     {
3748       inst.error = BAD_ARGS;
3749       return;
3750     }
3751
3752   if (rm == REG_PC)
3753     {
3754       inst.error = BAD_PC;
3755       return;
3756     }
3757
3758   if (rm == rd)
3759     as_tsktsk (_("rd and rm should be different in mul"));
3760
3761   if (skip_past_comma (&str) == FAIL
3762       || (rm = reg_required_here (&str, 8)) == FAIL)
3763     {
3764       inst.error = BAD_ARGS;
3765       return;
3766     }
3767
3768   if (rm == REG_PC)
3769     {
3770       inst.error = BAD_PC;
3771       return;
3772     }
3773
3774   end_of_line (str);
3775   return;
3776 }
3777
3778 static void
3779 do_mla (str)
3780      char * str;
3781 {
3782   int rd, rm;
3783
3784   /* Only one format "rd, rm, rs, rn".  */
3785   skip_whitespace (str);
3786
3787   if ((rd = reg_required_here (&str, 16)) == FAIL)
3788     {
3789       inst.error = BAD_ARGS;
3790       return;
3791     }
3792
3793   if (rd == REG_PC)
3794     {
3795       inst.error = BAD_PC;
3796       return;
3797     }
3798
3799   if (skip_past_comma (&str) == FAIL
3800       || (rm = reg_required_here (&str, 0)) == FAIL)
3801     {
3802       inst.error = BAD_ARGS;
3803       return;
3804     }
3805
3806   if (rm == REG_PC)
3807     {
3808       inst.error = BAD_PC;
3809       return;
3810     }
3811
3812   if (rm == rd)
3813     as_tsktsk (_("rd and rm should be different in mla"));
3814
3815   if (skip_past_comma (&str) == FAIL
3816       || (rd = reg_required_here (&str, 8)) == FAIL
3817       || skip_past_comma (&str) == FAIL
3818       || (rm = reg_required_here (&str, 12)) == FAIL)
3819     {
3820       inst.error = BAD_ARGS;
3821       return;
3822     }
3823
3824   if (rd == REG_PC || rm == REG_PC)
3825     {
3826       inst.error = BAD_PC;
3827       return;
3828     }
3829
3830   end_of_line (str);
3831   return;
3832 }
3833
3834 /* Expects *str -> the characters "acc0", possibly with leading blanks.
3835    Advances *str to the next non-alphanumeric.
3836    Returns 0, or else FAIL (in which case sets inst.error).
3837
3838   (In a future XScale, there may be accumulators other than zero.
3839   At that time this routine and its callers can be upgraded to suit.)  */
3840
3841 static int
3842 accum0_required_here (str)
3843      char ** str;
3844 {
3845   static char buff [128];       /* Note the address is taken.  Hence, static.  */
3846   char * p = * str;
3847   char   c;
3848   int result = 0;               /* The accum number.  */
3849
3850   skip_whitespace (p);
3851
3852   *str = p;                     /* Advance caller's string pointer too.  */
3853   c = *p++;
3854   while (ISALNUM (c))
3855     c = *p++;
3856
3857   *--p = 0;                     /* Aap nul into input buffer at non-alnum.  */
3858
3859   if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
3860     {
3861       sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
3862       inst.error = buff;
3863       result = FAIL;
3864     }
3865
3866   *p = c;                       /* Unzap.  */
3867   *str = p;                     /* Caller's string pointer to after match.  */
3868   return result;
3869 }
3870
3871 /* Expects **str -> after a comma. May be leading blanks.
3872    Advances *str, recognizing a load  mode, and setting inst.instruction.
3873    Returns rn, or else FAIL (in which case may set inst.error
3874    and not advance str)
3875
3876    Note: doesn't know Rd, so no err checks that require such knowledge.  */
3877
3878 static int
3879 ld_mode_required_here (string)
3880      char ** string;
3881 {
3882   char * str = * string;
3883   int    rn;
3884   int    pre_inc = 0;
3885
3886   skip_whitespace (str);
3887
3888   if (* str == '[')
3889     {
3890       str++;
3891
3892       skip_whitespace (str);
3893
3894       if ((rn = reg_required_here (& str, 16)) == FAIL)
3895         return FAIL;
3896
3897       skip_whitespace (str);
3898
3899       if (* str == ']')
3900         {
3901           str ++;
3902
3903           if (skip_past_comma (& str) == SUCCESS)
3904             {
3905               /* [Rn],... (post inc) */
3906               if (ldst_extend_v4 (&str) == FAIL)
3907                 return FAIL;
3908             }
3909           else        /* [Rn] */
3910             {
3911               skip_whitespace (str);
3912
3913               if (* str == '!')
3914                 {
3915                   str ++;
3916                   inst.instruction |= WRITE_BACK;
3917                 }
3918
3919               inst.instruction |= INDEX_UP | HWOFFSET_IMM;
3920               pre_inc = 1;
3921             }
3922         }
3923       else        /* [Rn,...] */
3924         {
3925           if (skip_past_comma (& str) == FAIL)
3926             {
3927               inst.error = _("pre-indexed expression expected");
3928               return FAIL;
3929             }
3930
3931           pre_inc = 1;
3932
3933           if (ldst_extend_v4 (&str) == FAIL)
3934             return FAIL;
3935
3936           skip_whitespace (str);
3937
3938           if (* str ++ != ']')
3939             {
3940               inst.error = _("missing ]");
3941               return FAIL;
3942             }
3943
3944           skip_whitespace (str);
3945
3946           if (* str == '!')
3947             {
3948               str ++;
3949               inst.instruction |= WRITE_BACK;
3950             }
3951         }
3952     }
3953   else if (* str == '=')        /* ldr's "r,=label" syntax */
3954     /* We should never reach here, because <text> = <expression> is
3955        caught gas/read.c read_a_source_file() as a .set operation.  */
3956     return FAIL;
3957   else                          /* PC +- 8 bit immediate offset.  */
3958     {
3959       if (my_get_expression (& inst.reloc.exp, & str))
3960         return FAIL;
3961
3962       inst.instruction            |= HWOFFSET_IMM;      /* The I bit.  */
3963       inst.reloc.type              = BFD_RELOC_ARM_OFFSET_IMM8;
3964       inst.reloc.exp.X_add_number -= 8;                 /* PC rel adjust.  */
3965       inst.reloc.pc_rel            = 1;
3966       inst.instruction            |= (REG_PC << 16);
3967
3968       rn = REG_PC;
3969       pre_inc = 1;
3970     }
3971
3972   inst.instruction |= (pre_inc ? PRE_INDEX : 0);
3973   * string = str;
3974
3975   return rn;
3976 }
3977
3978 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
3979    SMLAxy{cond} Rd,Rm,Rs,Rn
3980    SMLAWy{cond} Rd,Rm,Rs,Rn
3981    Error if any register is R15.  */
3982
3983 static void
3984 do_smla (str)
3985      char *        str;
3986 {
3987   int rd, rm, rs, rn;
3988
3989   skip_whitespace (str);
3990
3991   if ((rd = reg_required_here (& str, 16)) == FAIL
3992       || skip_past_comma (& str) == FAIL
3993       || (rm = reg_required_here (& str, 0)) == FAIL
3994       || skip_past_comma (& str) == FAIL
3995       || (rs = reg_required_here (& str, 8)) == FAIL
3996       || skip_past_comma (& str) == FAIL
3997       || (rn = reg_required_here (& str, 12)) == FAIL)
3998     inst.error = BAD_ARGS;
3999
4000   else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
4001     inst.error = BAD_PC;
4002
4003   else
4004     end_of_line (str);
4005 }
4006
4007 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4008    SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4009    Error if any register is R15.
4010    Warning if Rdlo == Rdhi.  */
4011
4012 static void
4013 do_smlal (str)
4014      char *        str;
4015 {
4016   int rdlo, rdhi, rm, rs;
4017
4018   skip_whitespace (str);
4019
4020   if ((rdlo = reg_required_here (& str, 12)) == FAIL
4021       || skip_past_comma (& str) == FAIL
4022       || (rdhi = reg_required_here (& str, 16)) == FAIL
4023       || skip_past_comma (& str) == FAIL
4024       || (rm = reg_required_here (& str, 0)) == FAIL
4025       || skip_past_comma (& str) == FAIL
4026       || (rs = reg_required_here (& str, 8)) == FAIL)
4027     {
4028       inst.error = BAD_ARGS;
4029       return;
4030     }
4031
4032   if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4033     {
4034       inst.error = BAD_PC;
4035       return;
4036     }
4037
4038   if (rdlo == rdhi)
4039     as_tsktsk (_("rdhi and rdlo must be different"));
4040
4041   end_of_line (str);
4042 }
4043
4044 /* ARM V5E (El Segundo) signed-multiply (argument parse)
4045    SMULxy{cond} Rd,Rm,Rs
4046    Error if any register is R15.  */
4047
4048 static void
4049 do_smul (str)
4050      char *        str;
4051 {
4052   int rd, rm, rs;
4053
4054   skip_whitespace (str);
4055
4056   if ((rd = reg_required_here (& str, 16)) == FAIL
4057       || skip_past_comma (& str) == FAIL
4058       || (rm = reg_required_here (& str, 0)) == FAIL
4059       || skip_past_comma (& str) == FAIL
4060       || (rs = reg_required_here (& str, 8)) == FAIL)
4061     inst.error = BAD_ARGS;
4062
4063   else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
4064     inst.error = BAD_PC;
4065
4066   else
4067     end_of_line (str);
4068 }
4069
4070 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4071    Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4072    Error if any register is R15.  */
4073
4074 static void
4075 do_qadd (str)
4076      char *        str;
4077 {
4078   int rd, rm, rn;
4079
4080   skip_whitespace (str);
4081
4082   if ((rd = reg_required_here (& str, 12)) == FAIL
4083       || skip_past_comma (& str) == FAIL
4084       || (rm = reg_required_here (& str, 0)) == FAIL
4085       || skip_past_comma (& str) == FAIL
4086       || (rn = reg_required_here (& str, 16)) == FAIL)
4087     inst.error = BAD_ARGS;
4088
4089   else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4090     inst.error = BAD_PC;
4091
4092   else
4093     end_of_line (str);
4094 }
4095
4096 /* ARM V5E (el Segundo)
4097    MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4098    MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4099
4100    These are equivalent to the XScale instructions MAR and MRA,
4101    respectively, when coproc == 0, opcode == 0, and CRm == 0.
4102
4103    Result unpredicatable if Rd or Rn is R15.  */
4104
4105 static void
4106 do_co_reg2c (str)
4107      char *        str;
4108 {
4109   int rd, rn;
4110
4111   skip_whitespace (str);
4112
4113   if (co_proc_number (& str) == FAIL)
4114     {
4115       if (!inst.error)
4116         inst.error = BAD_ARGS;
4117       return;
4118     }
4119
4120   if (skip_past_comma (& str) == FAIL
4121       || cp_opc_expr (& str, 4, 4) == FAIL)
4122     {
4123       if (!inst.error)
4124         inst.error = BAD_ARGS;
4125       return;
4126     }
4127
4128   if (skip_past_comma (& str) == FAIL
4129       || (rd = reg_required_here (& str, 12)) == FAIL)
4130     {
4131       if (!inst.error)
4132         inst.error = BAD_ARGS;
4133       return;
4134     }
4135
4136   if (skip_past_comma (& str) == FAIL
4137       || (rn = reg_required_here (& str, 16)) == FAIL)
4138     {
4139       if (!inst.error)
4140         inst.error = BAD_ARGS;
4141       return;
4142     }
4143
4144   /* Unpredictable result if rd or rn is R15.  */
4145   if (rd == REG_PC || rn == REG_PC)
4146     as_tsktsk
4147       (_("Warning: instruction unpredictable when using r15"));
4148
4149   if (skip_past_comma (& str) == FAIL
4150       || cp_reg_required_here (& str, 0) == FAIL)
4151     {
4152       if (!inst.error)
4153         inst.error = BAD_ARGS;
4154       return;
4155     }
4156
4157   end_of_line (str);
4158 }
4159
4160 /* ARM V5 count-leading-zeroes instruction (argument parse)
4161      CLZ{<cond>} <Rd>, <Rm>
4162      Condition defaults to COND_ALWAYS.
4163      Error if Rd or Rm are R15.  */
4164
4165 static void
4166 do_clz (str)
4167      char *        str;
4168 {
4169   int rd, rm;
4170
4171   skip_whitespace (str);
4172
4173   if (((rd = reg_required_here (& str, 12)) == FAIL)
4174       || (skip_past_comma (& str) == FAIL)
4175       || ((rm = reg_required_here (& str, 0)) == FAIL))
4176     inst.error = BAD_ARGS;
4177
4178   else if (rd == REG_PC || rm == REG_PC )
4179     inst.error = BAD_PC;
4180
4181   else
4182     end_of_line (str);
4183 }
4184
4185 /* ARM V5 (argument parse)
4186      LDC2{L} <coproc>, <CRd>, <addressing mode>
4187      STC2{L} <coproc>, <CRd>, <addressing mode>
4188      Instruction is not conditional, and has 0xf in the codition field.
4189      Otherwise, it's the same as LDC/STC.  */
4190
4191 static void
4192 do_lstc2 (str)
4193      char *        str;
4194 {
4195   skip_whitespace (str);
4196
4197   if (co_proc_number (& str) == FAIL)
4198     {
4199       if (!inst.error)
4200         inst.error = BAD_ARGS;
4201     }
4202   else if (skip_past_comma (& str) == FAIL
4203            || cp_reg_required_here (& str, 12) == FAIL)
4204     {
4205       if (!inst.error)
4206         inst.error = BAD_ARGS;
4207     }
4208   else if (skip_past_comma (& str) == FAIL
4209            || cp_address_required_here (&str, CP_WB_OK) == FAIL)
4210     {
4211       if (! inst.error)
4212         inst.error = BAD_ARGS;
4213     }
4214   else
4215     end_of_line (str);
4216 }
4217
4218 /* ARM V5 (argument parse)
4219      CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4220      Instruction is not conditional, and has 0xf in the condition field.
4221      Otherwise, it's the same as CDP.  */
4222
4223 static void
4224 do_cdp2 (str)
4225      char *        str;
4226 {
4227   skip_whitespace (str);
4228
4229   if (co_proc_number (& str) == FAIL)
4230     {
4231       if (!inst.error)
4232         inst.error = BAD_ARGS;
4233       return;
4234     }
4235
4236   if (skip_past_comma (& str) == FAIL
4237       || cp_opc_expr (& str, 20,4) == FAIL)
4238     {
4239       if (!inst.error)
4240         inst.error = BAD_ARGS;
4241       return;
4242     }
4243
4244   if (skip_past_comma (& str) == FAIL
4245       || cp_reg_required_here (& str, 12) == FAIL)
4246     {
4247       if (!inst.error)
4248         inst.error = BAD_ARGS;
4249       return;
4250     }
4251
4252   if (skip_past_comma (& str) == FAIL
4253       || cp_reg_required_here (& str, 16) == FAIL)
4254     {
4255       if (!inst.error)
4256         inst.error = BAD_ARGS;
4257       return;
4258     }
4259
4260   if (skip_past_comma (& str) == FAIL
4261       || cp_reg_required_here (& str, 0) == FAIL)
4262     {
4263       if (!inst.error)
4264         inst.error = BAD_ARGS;
4265       return;
4266     }
4267
4268   if (skip_past_comma (& str) == SUCCESS)
4269     {
4270       if (cp_opc_expr (& str, 5, 3) == FAIL)
4271         {
4272           if (!inst.error)
4273             inst.error = BAD_ARGS;
4274           return;
4275         }
4276     }
4277
4278   end_of_line (str);
4279 }
4280
4281 /* ARM V5 (argument parse)
4282      MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4283      MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4284      Instruction is not conditional, and has 0xf in the condition field.
4285      Otherwise, it's the same as MCR/MRC.  */
4286
4287 static void
4288 do_co_reg2 (str)
4289      char *        str;
4290 {
4291   skip_whitespace (str);
4292
4293   if (co_proc_number (& str) == FAIL)
4294     {
4295       if (!inst.error)
4296         inst.error = BAD_ARGS;
4297       return;
4298     }
4299
4300   if (skip_past_comma (& str) == FAIL
4301       || cp_opc_expr (& str, 21, 3) == FAIL)
4302     {
4303       if (!inst.error)
4304         inst.error = BAD_ARGS;
4305       return;
4306     }
4307
4308   if (skip_past_comma (& str) == FAIL
4309       || reg_required_here (& str, 12) == FAIL)
4310     {
4311       if (!inst.error)
4312         inst.error = BAD_ARGS;
4313       return;
4314     }
4315
4316   if (skip_past_comma (& str) == FAIL
4317       || cp_reg_required_here (& str, 16) == FAIL)
4318     {
4319       if (!inst.error)
4320         inst.error = BAD_ARGS;
4321       return;
4322     }
4323
4324   if (skip_past_comma (& str) == FAIL
4325       || cp_reg_required_here (& str, 0) == FAIL)
4326     {
4327       if (!inst.error)
4328         inst.error = BAD_ARGS;
4329       return;
4330     }
4331
4332   if (skip_past_comma (& str) == SUCCESS)
4333     {
4334       if (cp_opc_expr (& str, 5, 3) == FAIL)
4335         {
4336           if (!inst.error)
4337             inst.error = BAD_ARGS;
4338           return;
4339         }
4340     }
4341
4342   end_of_line (str);
4343 }
4344
4345 /* ARM v5TEJ.  Jump to Jazelle code.  */
4346 static void
4347 do_bxj (str)
4348      char * str;
4349 {
4350   int reg;
4351
4352   skip_whitespace (str);
4353
4354   if ((reg = reg_required_here (&str, 0)) == FAIL)
4355     {
4356       inst.error = BAD_ARGS;
4357       return;
4358     }
4359
4360   /* Note - it is not illegal to do a "bxj pc".  Useless, but not illegal.  */
4361   if (reg == REG_PC)
4362     as_tsktsk (_("use of r15 in bxj is not really useful"));
4363
4364   end_of_line (str);
4365 }
4366
4367 /* THUMB V5 breakpoint instruction (argument parse)
4368         BKPT <immed_8>.  */
4369
4370 static void
4371 do_t_bkpt (str)
4372      char * str;
4373 {
4374   expressionS expr;
4375   unsigned long number;
4376
4377   skip_whitespace (str);
4378
4379   /* Allow optional leading '#'.  */
4380   if (is_immediate_prefix (*str))
4381     str ++;
4382
4383   memset (& expr, '\0', sizeof (expr));
4384   if (my_get_expression (& expr, & str)
4385       || (expr.X_op != O_constant
4386           /* As a convenience we allow 'bkpt' without an operand.  */
4387           && expr.X_op != O_absent))
4388     {
4389       inst.error = _("bad expression");
4390       return;
4391     }
4392
4393   number = expr.X_add_number;
4394
4395   /* Check it fits an 8 bit unsigned.  */
4396   if (number != (number & 0xff))
4397     {
4398       inst.error = _("immediate value out of range");
4399       return;
4400     }
4401
4402   inst.instruction |= number;
4403
4404   end_of_line (str);
4405 }
4406
4407 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
4408    Expects inst.instruction is set for BLX(1).
4409    Note: this is cloned from do_branch, and the reloc changed to be a
4410         new one that can cope with setting one extra bit (the H bit).  */
4411
4412 static void
4413 do_branch25 (str)
4414      char *        str;
4415 {
4416   if (my_get_expression (& inst.reloc.exp, & str))
4417     return;
4418
4419 #ifdef OBJ_ELF
4420   {
4421     char * save_in;
4422
4423     /* ScottB: February 5, 1998 */
4424     /* Check to see of PLT32 reloc required for the instruction.  */
4425
4426     /* arm_parse_reloc() works on input_line_pointer.
4427        We actually want to parse the operands to the branch instruction
4428        passed in 'str'.  Save the input pointer and restore it later.  */
4429     save_in = input_line_pointer;
4430     input_line_pointer = str;
4431
4432     if (inst.reloc.exp.X_op == O_symbol
4433         && *str == '('
4434         && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
4435       {
4436         inst.reloc.type   = BFD_RELOC_ARM_PLT32;
4437         inst.reloc.pc_rel = 0;
4438         /* Modify str to point to after parsed operands, otherwise
4439            end_of_line() will complain about the (PLT) left in str.  */
4440         str = input_line_pointer;
4441       }
4442     else
4443       {
4444         inst.reloc.type   = BFD_RELOC_ARM_PCREL_BLX;
4445         inst.reloc.pc_rel = 1;
4446       }
4447
4448     input_line_pointer = save_in;
4449   }
4450 #else
4451   inst.reloc.type   = BFD_RELOC_ARM_PCREL_BLX;
4452   inst.reloc.pc_rel = 1;
4453 #endif /* OBJ_ELF */
4454
4455   end_of_line (str);
4456 }
4457
4458 /* ARM V5 branch-link-exchange instruction (argument parse)
4459      BLX <target_addr>          ie BLX(1)
4460      BLX{<condition>} <Rm>      ie BLX(2)
4461    Unfortunately, there are two different opcodes for this mnemonic.
4462    So, the insns[].value is not used, and the code here zaps values
4463         into inst.instruction.
4464    Also, the <target_addr> can be 25 bits, hence has its own reloc.  */
4465
4466 static void
4467 do_blx (str)
4468      char *        str;
4469 {
4470   char * mystr = str;
4471   int rm;
4472
4473   skip_whitespace (mystr);
4474   rm = reg_required_here (& mystr, 0);
4475
4476   /* The above may set inst.error.  Ignore his opinion.  */
4477   inst.error = 0;
4478
4479   if (rm != FAIL)
4480     {
4481       /* Arg is a register.
4482          Use the condition code our caller put in inst.instruction.
4483          Pass ourselves off as a BX with a funny opcode.  */
4484       inst.instruction |= 0x012fff30;
4485       do_bx (str);
4486     }
4487   else
4488     {
4489       /* This must be is BLX <target address>, no condition allowed.  */
4490       if (inst.instruction != COND_ALWAYS)
4491         {
4492           inst.error = BAD_COND;
4493           return;
4494         }
4495
4496       inst.instruction = 0xfafffffe;
4497
4498       /* Process like a B/BL, but with a different reloc.
4499          Note that B/BL expecte fffffe, not 0, offset in the opcode table.  */
4500       do_branch25 (str);
4501     }
4502 }
4503
4504 /* ARM V5 Thumb BLX (argument parse)
4505         BLX <target_addr>       which is BLX(1)
4506         BLX <Rm>                which is BLX(2)
4507    Unfortunately, there are two different opcodes for this mnemonic.
4508    So, the tinsns[].value is not used, and the code here zaps values
4509         into inst.instruction.  */
4510
4511 static void
4512 do_t_blx (str)
4513      char * str;
4514 {
4515   char * mystr = str;
4516   int rm;
4517
4518   skip_whitespace (mystr);
4519   inst.instruction = 0x4780;
4520
4521   /* Note that this call is to the ARM register recognizer.  BLX(2)
4522      uses the ARM register space, not the Thumb one, so a call to
4523      thumb_reg() would be wrong.  */
4524   rm = reg_required_here (& mystr, 3);
4525   inst.error = 0;
4526
4527   if (rm != FAIL)
4528     {
4529       /* It's BLX(2).  The .instruction was zapped with rm & is final.  */
4530       inst.size = 2;
4531     }
4532   else
4533     {
4534       /* No ARM register.  This must be BLX(1).  Change the .instruction.  */
4535       inst.instruction = 0xf7ffeffe;
4536       inst.size = 4;
4537
4538       if (my_get_expression (& inst.reloc.exp, & mystr))
4539         return;
4540
4541       inst.reloc.type   = BFD_RELOC_THUMB_PCREL_BLX;
4542       inst.reloc.pc_rel = 1;
4543     }
4544
4545   end_of_line (mystr);
4546 }
4547
4548 /* ARM V5 breakpoint instruction (argument parse)
4549      BKPT <16 bit unsigned immediate>
4550      Instruction is not conditional.
4551         The bit pattern given in insns[] has the COND_ALWAYS condition,
4552         and it is an error if the caller tried to override that.  */
4553
4554 static void
4555 do_bkpt (str)
4556      char *        str;
4557 {
4558   expressionS expr;
4559   unsigned long number;
4560
4561   skip_whitespace (str);
4562
4563   /* Allow optional leading '#'.  */
4564   if (is_immediate_prefix (* str))
4565     str++;
4566
4567   memset (& expr, '\0', sizeof (expr));
4568
4569   if (my_get_expression (& expr, & str)
4570       || (expr.X_op != O_constant
4571           /* As a convenience we allow 'bkpt' without an operand.  */
4572           && expr.X_op != O_absent))
4573     {
4574       inst.error = _("bad expression");
4575       return;
4576     }
4577
4578   number = expr.X_add_number;
4579
4580   /* Check it fits a 16 bit unsigned.  */
4581   if (number != (number & 0xffff))
4582     {
4583       inst.error = _("immediate value out of range");
4584       return;
4585     }
4586
4587   /* Top 12 of 16 bits to bits 19:8.  */
4588   inst.instruction |= (number & 0xfff0) << 4;
4589
4590   /* Bottom 4 of 16 bits to bits 3:0.  */
4591   inst.instruction |= number & 0xf;
4592
4593   end_of_line (str);
4594 }
4595
4596 static unsigned long check_iwmmxt_insn PARAMS ((char *, enum iwmmxt_insn_type, int));
4597
4598 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate.  */
4599
4600 static unsigned long
4601 check_iwmmxt_insn (str, insn_type, immediate_size)
4602      char * str;
4603      enum iwmmxt_insn_type insn_type;
4604      int immediate_size;
4605 {
4606   int reg = 0;
4607   const char *  inst_error;
4608   expressionS expr;
4609   unsigned long number;
4610
4611   inst_error = inst.error;
4612   if (!inst.error)
4613     inst.error = BAD_ARGS;
4614   skip_whitespace (str);
4615
4616   switch (insn_type)
4617     {
4618     case check_rd:
4619       if ((reg = reg_required_here (&str, 12)) == FAIL)
4620         return FAIL;
4621       break;
4622       
4623     case check_wr:
4624        if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
4625          return FAIL;
4626        break;
4627        
4628     case check_wrwr:
4629       if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4630            || skip_past_comma (&str) == FAIL
4631            || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
4632         return FAIL;
4633       break;
4634       
4635     case check_wrwrwr:
4636       if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4637            || skip_past_comma (&str) == FAIL
4638            || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4639            || skip_past_comma (&str) == FAIL
4640            || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
4641         return FAIL;
4642       break;
4643       
4644     case check_wrwrwcg:
4645       if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4646            || skip_past_comma (&str) == FAIL
4647            || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4648            || skip_past_comma (&str) == FAIL
4649            || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
4650         return FAIL;
4651       break;
4652       
4653     case check_tbcst:
4654       if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4655            || skip_past_comma (&str) == FAIL
4656            || reg_required_here (&str, 12) == FAIL))
4657         return FAIL;
4658       break;
4659       
4660     case check_tmovmsk:
4661       if ((reg_required_here (&str, 12) == FAIL
4662            || skip_past_comma (&str) == FAIL
4663            || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
4664         return FAIL;
4665       break;
4666       
4667     case check_tmia:
4668       if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
4669            || skip_past_comma (&str) == FAIL
4670            || reg_required_here (&str, 0) == FAIL
4671            || skip_past_comma (&str) == FAIL
4672            || reg_required_here (&str, 12) == FAIL))
4673         return FAIL;
4674       break;
4675       
4676     case check_tmcrr:
4677       if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
4678            || skip_past_comma (&str) == FAIL
4679            || reg_required_here (&str, 12) == FAIL
4680            || skip_past_comma (&str) == FAIL
4681            || reg_required_here (&str, 16) == FAIL))
4682         return FAIL;
4683       break;
4684       
4685     case check_tmrrc:
4686       if ((reg_required_here (&str, 12) == FAIL
4687            || skip_past_comma (&str) == FAIL
4688            || reg_required_here (&str, 16) == FAIL
4689            || skip_past_comma (&str) == FAIL
4690            || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
4691         return FAIL;
4692       break;
4693       
4694     case check_tmcr:
4695       if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
4696            || skip_past_comma (&str) == FAIL
4697            || reg_required_here (&str, 12) == FAIL))
4698         return FAIL;
4699       break;
4700       
4701     case check_tmrc:
4702       if ((reg_required_here (&str, 12) == FAIL
4703            || skip_past_comma (&str) == FAIL
4704            || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
4705         return FAIL;
4706       break;
4707       
4708     case check_tinsr:
4709       if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4710            || skip_past_comma (&str) == FAIL
4711            || reg_required_here (&str, 12) == FAIL
4712            || skip_past_comma (&str) == FAIL))
4713         return FAIL;
4714       break;
4715       
4716     case check_textrc:
4717       if ((reg_required_here (&str, 12) == FAIL
4718            || skip_past_comma (&str) == FAIL))
4719         return FAIL;
4720       break;
4721       
4722     case check_waligni:
4723       if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4724            || skip_past_comma (&str) == FAIL
4725            || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4726            || skip_past_comma (&str) == FAIL
4727            || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
4728            || skip_past_comma (&str) == FAIL))
4729         return FAIL;
4730       break;
4731       
4732     case check_textrm:
4733       if ((reg_required_here (&str, 12) == FAIL
4734            || skip_past_comma (&str) == FAIL
4735            || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4736            || skip_past_comma (&str) == FAIL))
4737         return FAIL;
4738       break;
4739       
4740     case check_wshufh:
4741       if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
4742            || skip_past_comma (&str) == FAIL
4743            || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
4744            || skip_past_comma (&str) == FAIL))
4745         return FAIL;
4746       break;
4747     }
4748   
4749   if (immediate_size == 0)
4750     {
4751       end_of_line (str);
4752       inst.error = inst_error;
4753       return reg;
4754     }
4755   else
4756     {
4757       skip_whitespace (str);      
4758   
4759       /* Allow optional leading '#'. */
4760       if (is_immediate_prefix (* str))
4761         str++;
4762
4763       memset (& expr, '\0', sizeof (expr));
4764   
4765       if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
4766         {
4767           inst.error = _("bad or missing expression");
4768           return FAIL;
4769         }
4770   
4771       number = expr.X_add_number;
4772   
4773       if (number != (number & immediate_size))
4774         {
4775           inst.error = _("immediate value out of range");
4776           return FAIL;
4777         }
4778       end_of_line (str);
4779       inst.error = inst_error;
4780       return number;
4781     }
4782 }
4783
4784 static void
4785 do_iwmmxt_byte_addr (str)
4786      char * str;
4787 {
4788   int op = (inst.instruction & 0x300) >> 8;
4789   int reg;
4790
4791   inst.instruction &= ~0x300;
4792   inst.instruction |= (op & 1) << 22 | (op & 2) << 7;  
4793
4794   skip_whitespace (str);
4795
4796   if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
4797       || skip_past_comma (& str) == FAIL
4798       || cp_byte_address_required_here (&str) == FAIL)
4799     {
4800       if (! inst.error)
4801         inst.error = BAD_ARGS;
4802     }
4803   else
4804     end_of_line (str);
4805
4806   if (wc_register (reg))
4807     {
4808       inst.instruction |=  0xf0000100;
4809       inst.instruction &= ~0x00400000;
4810     }
4811 }
4812
4813 static void
4814 do_iwmmxt_tandc (str)
4815      char * str;
4816 {
4817   int reg;
4818
4819   reg = check_iwmmxt_insn (str, check_rd, 0);
4820
4821   if (reg != REG_PC && !inst.error)
4822     inst.error = _("only r15 allowed here");
4823   return;
4824 }
4825
4826 static void
4827 do_iwmmxt_tbcst (str)
4828      char * str;
4829 {
4830   check_iwmmxt_insn (str, check_tbcst, 0);
4831
4832   return;
4833 }
4834
4835 static void
4836 do_iwmmxt_textrc (str)
4837      char * str;
4838 {
4839   unsigned long number;
4840
4841   if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
4842     return;
4843
4844   inst.instruction |= number & 0x7;
4845   return;
4846 }
4847
4848 static void
4849 do_iwmmxt_textrm (str)
4850      char * str;
4851 {
4852   unsigned long number;
4853
4854   if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
4855     return;
4856
4857   inst.instruction |= number & 0x7;
4858 }
4859
4860 static void
4861 do_iwmmxt_tinsr (str)
4862      char * str;
4863 {
4864   unsigned long number;
4865
4866   if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
4867     return;
4868
4869   inst.instruction |= number & 0x7;
4870   return;
4871 }
4872
4873 static void
4874 do_iwmmxt_tmcr (str)
4875      char * str;
4876 {
4877   check_iwmmxt_insn (str, check_tmcr, 0);
4878
4879   return;
4880 }
4881
4882 static void
4883 do_iwmmxt_tmcrr (str)
4884      char * str;
4885 {
4886   check_iwmmxt_insn (str, check_tmcrr, 0);
4887
4888   return;
4889 }
4890
4891 static void
4892 do_iwmmxt_tmia (str)
4893      char * str;
4894 {
4895   check_iwmmxt_insn (str, check_tmia, 0);
4896
4897   return;
4898 }
4899
4900 static void
4901 do_iwmmxt_tmovmsk (str)
4902      char * str;
4903 {
4904   check_iwmmxt_insn (str, check_tmovmsk, 0);
4905
4906   return;
4907 }
4908
4909 static void
4910 do_iwmmxt_tmrc (str)
4911      char * str;
4912 {
4913   check_iwmmxt_insn (str, check_tmrc, 0);
4914
4915   return;
4916 }
4917
4918 static void
4919 do_iwmmxt_tmrrc (str)
4920      char * str;
4921 {
4922   check_iwmmxt_insn (str, check_tmrrc, 0);
4923
4924   return;
4925 }
4926
4927 static void
4928 do_iwmmxt_torc (str)
4929      char * str;
4930 {
4931   check_iwmmxt_insn (str, check_rd, 0);
4932   return;
4933 }
4934
4935 static void
4936 do_iwmmxt_waligni (str)
4937      char * str;
4938 {
4939   unsigned long number;
4940
4941   if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
4942     return;
4943
4944   inst.instruction |= ((number & 0x7) << 20);
4945   return;
4946 }
4947
4948 static void
4949 do_iwmmxt_wmov (str)
4950      char * str;
4951 {
4952   if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
4953     return;
4954   
4955   inst.instruction |= ((inst.instruction >> 16) & 0xf);
4956   return;
4957 }
4958
4959 static void
4960 do_iwmmxt_word_addr (str)
4961      char * str;
4962 {
4963   int op = (inst.instruction & 0x300) >> 8;
4964   int reg;
4965
4966   inst.instruction &= ~0x300;
4967   inst.instruction |= (op & 1) << 22 | (op & 2) << 7;  
4968
4969   skip_whitespace (str);
4970
4971   if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
4972       || skip_past_comma (& str) == FAIL
4973       || cp_address_required_here (& str, CP_WB_OK) == FAIL)
4974     {
4975       if (! inst.error)
4976         inst.error = BAD_ARGS;
4977     }
4978   else
4979     end_of_line (str);
4980
4981   if (wc_register (reg))
4982     {
4983       inst.instruction |=  0xf0000100;
4984       inst.instruction &= ~0x00400000;
4985     }
4986 }
4987
4988 static void
4989 do_iwmmxt_wrwr (str)
4990      char * str;
4991 {
4992   check_iwmmxt_insn (str, check_wrwr, 0);
4993   
4994   return;
4995 }
4996
4997 static void
4998 do_iwmmxt_wrwrwcg (str)
4999      char * str;
5000 {
5001   check_iwmmxt_insn (str, check_wrwrwcg, 0);
5002
5003   return;
5004 }
5005
5006 static void
5007 do_iwmmxt_wrwrwr (str)
5008      char * str;
5009 {
5010   check_iwmmxt_insn (str, check_wrwrwr, 0);
5011
5012   return;
5013 }
5014
5015 static void
5016 do_iwmmxt_wshufh (str)
5017      char * str;
5018 {
5019   unsigned long number;
5020
5021   if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
5022     return;
5023
5024   inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
5025   return;
5026 }
5027
5028 static void
5029 do_iwmmxt_wzero (str)
5030      char * str;
5031 {
5032   if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
5033     return;
5034
5035   inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
5036   return;
5037 }
5038
5039 /* Xscale multiply-accumulate (argument parse)
5040      MIAcc   acc0,Rm,Rs
5041      MIAPHcc acc0,Rm,Rs
5042      MIAxycc acc0,Rm,Rs.  */
5043
5044 static void
5045 do_xsc_mia (str)
5046      char * str;
5047 {
5048   int rs;
5049   int rm;
5050
5051   if (accum0_required_here (& str) == FAIL)
5052     inst.error = ERR_NO_ACCUM;
5053
5054   else if (skip_past_comma (& str) == FAIL
5055            || (rm = reg_required_here (& str, 0)) == FAIL)
5056     inst.error = BAD_ARGS;
5057
5058   else if (skip_past_comma (& str) == FAIL
5059            || (rs = reg_required_here (& str, 12)) == FAIL)
5060     inst.error = BAD_ARGS;
5061
5062   /* inst.instruction has now been zapped with both rm and rs.  */
5063   else if (rm == REG_PC || rs == REG_PC)
5064     inst.error = BAD_PC;        /* Undefined result if rm or rs is R15.  */
5065
5066   else
5067     end_of_line (str);
5068 }
5069
5070 /* Xscale move-accumulator-register (argument parse)
5071
5072      MARcc   acc0,RdLo,RdHi.  */
5073
5074 static void
5075 do_xsc_mar (str)
5076      char * str;
5077 {
5078   int rdlo, rdhi;
5079
5080   if (accum0_required_here (& str) == FAIL)
5081     inst.error = ERR_NO_ACCUM;
5082
5083   else if (skip_past_comma (& str) == FAIL
5084            || (rdlo = reg_required_here (& str, 12)) == FAIL)
5085     inst.error = BAD_ARGS;
5086
5087   else if (skip_past_comma (& str) == FAIL
5088            || (rdhi = reg_required_here (& str, 16)) == FAIL)
5089     inst.error = BAD_ARGS;
5090
5091   /* inst.instruction has now been zapped with both rdlo and rdhi.  */
5092   else if (rdlo == REG_PC || rdhi == REG_PC)
5093     inst.error = BAD_PC;        /* Undefined result if rdlo or rdhi is R15.  */
5094
5095   else
5096     end_of_line (str);
5097 }
5098
5099 /* Xscale move-register-accumulator (argument parse)
5100
5101      MRAcc   RdLo,RdHi,acc0.  */
5102
5103 static void
5104 do_xsc_mra (str)
5105      char * str;
5106 {
5107   int rdlo;
5108   int rdhi;
5109
5110   skip_whitespace (str);
5111
5112   if ((rdlo = reg_required_here (& str, 12)) == FAIL)
5113     inst.error = BAD_ARGS;
5114
5115   else if (skip_past_comma (& str) == FAIL
5116            || (rdhi = reg_required_here (& str, 16)) == FAIL)
5117     inst.error = BAD_ARGS;
5118
5119   else if  (skip_past_comma (& str) == FAIL
5120             || accum0_required_here (& str) == FAIL)
5121     inst.error = ERR_NO_ACCUM;
5122
5123   /* inst.instruction has now been zapped with both rdlo and rdhi.  */
5124   else if (rdlo == rdhi)
5125     inst.error = BAD_ARGS;      /* Undefined result if 2 writes to same reg.  */
5126
5127   else if (rdlo == REG_PC || rdhi == REG_PC)
5128     inst.error = BAD_PC;        /* Undefined result if rdlo or rdhi is R15.  */
5129   else
5130     end_of_line (str);
5131 }
5132
5133 /* ARMv5TE: Preload-Cache
5134
5135     PLD <addr_mode>
5136
5137   Syntactically, like LDR with B=1, W=0, L=1.  */
5138
5139 static void
5140 do_pld (str)
5141      char * str;
5142 {
5143   int rd;
5144
5145   skip_whitespace (str);
5146
5147   if (* str != '[')
5148     {
5149       inst.error = _("'[' expected after PLD mnemonic");
5150       return;
5151     }
5152
5153   ++str;
5154   skip_whitespace (str);
5155
5156   if ((rd = reg_required_here (& str, 16)) == FAIL)
5157     return;
5158
5159   skip_whitespace (str);
5160
5161   if (*str == ']')
5162     {
5163       /* [Rn], ... ?  */
5164       ++str;
5165       skip_whitespace (str);
5166
5167       /* Post-indexed addressing is not allowed with PLD.  */
5168       if (skip_past_comma (&str) == SUCCESS)
5169         {
5170           inst.error
5171             = _("post-indexed expression used in preload instruction");
5172           return;
5173         }
5174       else if (*str == '!') /* [Rn]! */
5175         {
5176           inst.error = _("writeback used in preload instruction");
5177           ++str;
5178         }
5179       else /* [Rn] */
5180         inst.instruction |= INDEX_UP | PRE_INDEX;
5181     }
5182   else /* [Rn, ...] */
5183     {
5184       if (skip_past_comma (& str) == FAIL)
5185         {
5186           inst.error = _("pre-indexed expression expected");
5187           return;
5188         }
5189
5190       if (ldst_extend (&str) == FAIL)
5191         return;
5192
5193       skip_whitespace (str);
5194
5195       if (* str != ']')
5196         {
5197           inst.error = _("missing ]");
5198           return;
5199         }
5200
5201       ++ str;
5202       skip_whitespace (str);
5203
5204       if (* str == '!') /* [Rn]! */
5205         {
5206           inst.error = _("writeback used in preload instruction");
5207           ++ str;
5208         }
5209
5210       inst.instruction |= PRE_INDEX;
5211     }
5212
5213   end_of_line (str);
5214 }
5215
5216 /* ARMv5TE load-consecutive (argument parse)
5217    Mode is like LDRH.
5218
5219      LDRccD R, mode
5220      STRccD R, mode.  */
5221
5222 static void
5223 do_ldrd (str)
5224      char * str;
5225 {
5226   int rd;
5227   int rn;
5228
5229   skip_whitespace (str);
5230
5231   if ((rd = reg_required_here (& str, 12)) == FAIL)
5232     {
5233       inst.error = BAD_ARGS;
5234       return;
5235     }
5236
5237   if (skip_past_comma (& str) == FAIL
5238       || (rn = ld_mode_required_here (& str)) == FAIL)
5239     {
5240       if (!inst.error)
5241         inst.error = BAD_ARGS;
5242       return;
5243     }
5244
5245   /* inst.instruction has now been zapped with Rd and the addressing mode.  */
5246   if (rd & 1)           /* Unpredictable result if Rd is odd.  */
5247     {
5248       inst.error = _("destination register must be even");
5249       return;
5250     }
5251
5252   if (rd == REG_LR)
5253     {
5254       inst.error = _("r14 not allowed here");
5255       return;
5256     }
5257
5258   if (((rd == rn) || (rd + 1 == rn))
5259       && ((inst.instruction & WRITE_BACK)
5260           || (!(inst.instruction & PRE_INDEX))))
5261     as_warn (_("pre/post-indexing used when modified address register is destination"));
5262
5263   /* For an index-register load, the index register must not overlap the
5264      destination (even if not write-back).  */
5265   if ((inst.instruction & V4_STR_BIT) == 0
5266       && (inst.instruction & HWOFFSET_IMM) == 0)
5267     {
5268       int rm = inst.instruction & 0x0000000f;
5269
5270       if (rm == rd || (rm == rd + 1))
5271         as_warn (_("ldrd destination registers must not overlap index register"));
5272     }
5273
5274   end_of_line (str);
5275 }
5276
5277 /* Returns the index into fp_values of a floating point number,
5278    or -1 if not in the table.  */
5279
5280 static int
5281 my_get_float_expression (str)
5282      char ** str;
5283 {
5284   LITTLENUM_TYPE words[MAX_LITTLENUMS];
5285   char *         save_in;
5286   expressionS    exp;
5287   int            i;
5288   int            j;
5289
5290   memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
5291
5292   /* Look for a raw floating point number.  */
5293   if ((save_in = atof_ieee (*str, 'x', words)) != NULL
5294       && is_end_of_line[(unsigned char) *save_in])
5295     {
5296       for (i = 0; i < NUM_FLOAT_VALS; i++)
5297         {
5298           for (j = 0; j < MAX_LITTLENUMS; j++)
5299             {
5300               if (words[j] != fp_values[i][j])
5301                 break;
5302             }
5303
5304           if (j == MAX_LITTLENUMS)
5305             {
5306               *str = save_in;
5307               return i;
5308             }
5309         }
5310     }
5311
5312   /* Try and parse a more complex expression, this will probably fail
5313      unless the code uses a floating point prefix (eg "0f").  */
5314   save_in = input_line_pointer;
5315   input_line_pointer = *str;
5316   if (expression (&exp) == absolute_section
5317       && exp.X_op == O_big
5318       && exp.X_add_number < 0)
5319     {
5320       /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
5321          Ditto for 15.  */
5322       if (gen_to_words (words, 5, (long) 15) == 0)
5323         {
5324           for (i = 0; i < NUM_FLOAT_VALS; i++)
5325             {
5326               for (j = 0; j < MAX_LITTLENUMS; j++)
5327                 {
5328                   if (words[j] != fp_values[i][j])
5329                     break;
5330                 }
5331
5332               if (j == MAX_LITTLENUMS)
5333                 {
5334                   *str = input_line_pointer;
5335                   input_line_pointer = save_in;
5336                   return i;
5337                 }
5338             }
5339         }
5340     }
5341
5342   *str = input_line_pointer;
5343   input_line_pointer = save_in;
5344   return -1;
5345 }
5346
5347 /* Return TRUE if anything in the expression is a bignum.  */
5348
5349 static int
5350 walk_no_bignums (sp)
5351      symbolS * sp;
5352 {
5353   if (symbol_get_value_expression (sp)->X_op == O_big)
5354     return 1;
5355
5356   if (symbol_get_value_expression (sp)->X_add_symbol)
5357     {
5358       return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
5359               || (symbol_get_value_expression (sp)->X_op_symbol
5360                   && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
5361     }
5362
5363   return 0;
5364 }
5365
5366 static int in_my_get_expression = 0;
5367
5368 static int
5369 my_get_expression (ep, str)
5370      expressionS * ep;
5371      char ** str;
5372 {
5373   char * save_in;
5374   segT   seg;
5375
5376   save_in = input_line_pointer;
5377   input_line_pointer = *str;
5378   in_my_get_expression = 1;
5379   seg = expression (ep);
5380   in_my_get_expression = 0;
5381
5382   if (ep->X_op == O_illegal)
5383     {
5384       /* We found a bad expression in md_operand().  */
5385       *str = input_line_pointer;
5386       input_line_pointer = save_in;
5387       return 1;
5388     }
5389
5390 #ifdef OBJ_AOUT
5391   if (seg != absolute_section
5392       && seg != text_section
5393       && seg != data_section
5394       && seg != bss_section
5395       && seg != undefined_section)
5396     {
5397       inst.error = _("bad_segment");
5398       *str = input_line_pointer;
5399       input_line_pointer = save_in;
5400       return 1;
5401     }
5402 #endif
5403
5404   /* Get rid of any bignums now, so that we don't generate an error for which
5405      we can't establish a line number later on.  Big numbers are never valid
5406      in instructions, which is where this routine is always called.  */
5407   if (ep->X_op == O_big
5408       || (ep->X_add_symbol
5409           && (walk_no_bignums (ep->X_add_symbol)
5410               || (ep->X_op_symbol
5411                   && walk_no_bignums (ep->X_op_symbol)))))
5412     {
5413       inst.error = _("invalid constant");
5414       *str = input_line_pointer;
5415       input_line_pointer = save_in;
5416       return 1;
5417     }
5418
5419   *str = input_line_pointer;
5420   input_line_pointer = save_in;
5421   return 0;
5422 }
5423
5424 /* We handle all bad expressions here, so that we can report the faulty
5425    instruction in the error message.  */
5426 void
5427 md_operand (expr)
5428      expressionS *expr;
5429 {
5430   if (in_my_get_expression)
5431     {
5432       expr->X_op = O_illegal;
5433       if (inst.error == NULL)
5434         inst.error = _("bad expression");
5435     }
5436 }
5437
5438 /* UNRESTRICT should be one if <shift> <register> is permitted for this
5439    instruction.  */
5440
5441 static int
5442 decode_shift (str, unrestrict)
5443      char ** str;
5444      int     unrestrict;
5445 {
5446   const struct asm_shift_name * shift;
5447   char * p;
5448   char   c;
5449
5450   skip_whitespace (* str);
5451
5452   for (p = * str; ISALPHA (* p); p ++)
5453     ;
5454
5455   if (p == * str)
5456     {
5457       inst.error = _("shift expression expected");
5458       return FAIL;
5459     }
5460
5461   c = * p;
5462   * p = '\0';
5463   shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
5464   * p = c;
5465
5466   if (shift == NULL)
5467     {
5468       inst.error = _("shift expression expected");
5469       return FAIL;
5470     }
5471
5472   assert (shift->properties->index == shift_properties[shift->properties->index].index);
5473
5474   if (shift->properties->index == SHIFT_RRX)
5475     {
5476       * str = p;
5477       inst.instruction |= shift->properties->bit_field;
5478       return SUCCESS;
5479     }
5480
5481   skip_whitespace (p);
5482
5483   if (unrestrict && reg_required_here (& p, 8) != FAIL)
5484     {
5485       inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
5486       * str = p;
5487       return SUCCESS;
5488     }
5489   else if (! is_immediate_prefix (* p))
5490     {
5491       inst.error = (unrestrict
5492                     ? _("shift requires register or #expression")
5493                     : _("shift requires #expression"));
5494       * str = p;
5495       return FAIL;
5496     }
5497
5498   inst.error = NULL;
5499   p ++;
5500
5501   if (my_get_expression (& inst.reloc.exp, & p))
5502     return FAIL;
5503
5504   /* Validate some simple #expressions.  */
5505   if (inst.reloc.exp.X_op == O_constant)
5506     {
5507       unsigned num = inst.reloc.exp.X_add_number;
5508
5509       /* Reject operations greater than 32.  */
5510       if (num > 32
5511           /* Reject a shift of 0 unless the mode allows it.  */
5512           || (num == 0 && shift->properties->allows_0 == 0)
5513           /* Reject a shift of 32 unless the mode allows it.  */
5514           || (num == 32 && shift->properties->allows_32 == 0)
5515           )
5516         {
5517           /* As a special case we allow a shift of zero for
5518              modes that do not support it to be recoded as an
5519              logical shift left of zero (ie nothing).  We warn
5520              about this though.  */
5521           if (num == 0)
5522             {
5523               as_warn (_("shift of 0 ignored."));
5524               shift = & shift_names[0];
5525               assert (shift->properties->index == SHIFT_LSL);
5526             }
5527           else
5528             {
5529               inst.error = _("invalid immediate shift");
5530               return FAIL;
5531             }
5532         }
5533
5534       /* Shifts of 32 are encoded as 0, for those shifts that
5535          support it.  */
5536       if (num == 32)
5537         num = 0;
5538
5539       inst.instruction |= (num << 7) | shift->properties->bit_field;
5540     }
5541   else
5542     {
5543       inst.reloc.type   = BFD_RELOC_ARM_SHIFT_IMM;
5544       inst.reloc.pc_rel = 0;
5545       inst.instruction |= shift->properties->bit_field;
5546     }
5547
5548   * str = p;
5549   return SUCCESS;
5550 }
5551
5552 /* Do those data_ops which can take a negative immediate constant
5553    by altering the instuction.  A bit of a hack really.
5554         MOV <-> MVN
5555         AND <-> BIC
5556         ADC <-> SBC
5557         by inverting the second operand, and
5558         ADD <-> SUB
5559         CMP <-> CMN
5560         by negating the second operand.  */
5561
5562 static int
5563 negate_data_op (instruction, value)
5564      unsigned long * instruction;
5565      unsigned long   value;
5566 {
5567   int op, new_inst;
5568   unsigned long negated, inverted;
5569
5570   negated = validate_immediate (-value);
5571   inverted = validate_immediate (~value);
5572
5573   op = (*instruction >> DATA_OP_SHIFT) & 0xf;
5574   switch (op)
5575     {
5576       /* First negates.  */
5577     case OPCODE_SUB:             /* ADD <-> SUB  */
5578       new_inst = OPCODE_ADD;
5579       value = negated;
5580       break;
5581
5582     case OPCODE_ADD:
5583       new_inst = OPCODE_SUB;
5584       value = negated;
5585       break;
5586
5587     case OPCODE_CMP:             /* CMP <-> CMN  */
5588       new_inst = OPCODE_CMN;
5589       value = negated;
5590       break;
5591
5592     case OPCODE_CMN:
5593       new_inst = OPCODE_CMP;
5594       value = negated;
5595       break;
5596
5597       /* Now Inverted ops.  */
5598     case OPCODE_MOV:             /* MOV <-> MVN  */
5599       new_inst = OPCODE_MVN;
5600       value = inverted;
5601       break;
5602
5603     case OPCODE_MVN:
5604       new_inst = OPCODE_MOV;
5605       value = inverted;
5606       break;
5607
5608     case OPCODE_AND:             /* AND <-> BIC  */
5609       new_inst = OPCODE_BIC;
5610       value = inverted;
5611       break;
5612
5613     case OPCODE_BIC:
5614       new_inst = OPCODE_AND;
5615       value = inverted;
5616       break;
5617
5618     case OPCODE_ADC:              /* ADC <-> SBC  */
5619       new_inst = OPCODE_SBC;
5620       value = inverted;
5621       break;
5622
5623     case OPCODE_SBC:
5624       new_inst = OPCODE_ADC;
5625       value = inverted;
5626       break;
5627
5628       /* We cannot do anything.  */
5629     default:
5630       return FAIL;
5631     }
5632
5633   if (value == (unsigned) FAIL)
5634     return FAIL;
5635
5636   *instruction &= OPCODE_MASK;
5637   *instruction |= new_inst << DATA_OP_SHIFT;
5638   return value;
5639 }
5640
5641 static int
5642 data_op2 (str)
5643      char ** str;
5644 {
5645   int value;
5646   expressionS expr;
5647
5648   skip_whitespace (* str);
5649
5650   if (reg_required_here (str, 0) != FAIL)
5651     {
5652       if (skip_past_comma (str) == SUCCESS)
5653         /* Shift operation on register.  */
5654         return decode_shift (str, NO_SHIFT_RESTRICT);
5655
5656       return SUCCESS;
5657     }
5658   else
5659     {
5660       /* Immediate expression.  */
5661       if (is_immediate_prefix (**str))
5662         {
5663           (*str)++;
5664           inst.error = NULL;
5665
5666           if (my_get_expression (&inst.reloc.exp, str))
5667             return FAIL;
5668
5669           if (inst.reloc.exp.X_add_symbol)
5670             {
5671               inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
5672               inst.reloc.pc_rel = 0;
5673             }
5674           else
5675             {
5676               if (skip_past_comma (str) == SUCCESS)
5677                 {
5678                   /* #x, y -- ie explicit rotation by Y.  */
5679                   if (my_get_expression (&expr, str))
5680                     return FAIL;
5681
5682                   if (expr.X_op != O_constant)
5683                     {
5684                       inst.error = _("constant expression expected");
5685                       return FAIL;
5686                     }
5687
5688                   /* Rotate must be a multiple of 2.  */
5689                   if (((unsigned) expr.X_add_number) > 30
5690                       || (expr.X_add_number & 1) != 0
5691                       || ((unsigned) inst.reloc.exp.X_add_number) > 255)
5692                     {
5693                       inst.error = _("invalid constant");
5694                       return FAIL;
5695                     }
5696                   inst.instruction |= INST_IMMEDIATE;
5697                   inst.instruction |= inst.reloc.exp.X_add_number;
5698                   inst.instruction |= expr.X_add_number << 7;
5699                   return SUCCESS;
5700                 }
5701
5702               /* Implicit rotation, select a suitable one.  */
5703               value = validate_immediate (inst.reloc.exp.X_add_number);
5704
5705               if (value == FAIL)
5706                 {
5707                   /* Can't be done.  Perhaps the code reads something like
5708                      "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK.  */
5709                   if ((value = negate_data_op (&inst.instruction,
5710                                                inst.reloc.exp.X_add_number))
5711                       == FAIL)
5712                     {
5713                       inst.error = _("invalid constant");
5714                       return FAIL;
5715                     }
5716                 }
5717
5718               inst.instruction |= value;
5719             }
5720
5721           inst.instruction |= INST_IMMEDIATE;
5722           return SUCCESS;
5723         }
5724
5725       (*str)++;
5726       inst.error = _("register or shift expression expected");
5727       return FAIL;
5728     }
5729 }
5730
5731 static int
5732 fp_op2 (str)
5733      char ** str;
5734 {
5735   skip_whitespace (* str);
5736
5737   if (fp_reg_required_here (str, 0) != FAIL)
5738     return SUCCESS;
5739   else
5740     {
5741       /* Immediate expression.  */
5742       if (*((*str)++) == '#')
5743         {
5744           int i;
5745
5746           inst.error = NULL;
5747
5748           skip_whitespace (* str);
5749
5750           /* First try and match exact strings, this is to guarantee
5751              that some formats will work even for cross assembly.  */
5752
5753           for (i = 0; fp_const[i]; i++)
5754             {
5755               if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
5756                 {
5757                   char *start = *str;
5758
5759                   *str += strlen (fp_const[i]);
5760                   if (is_end_of_line[(unsigned char) **str])
5761                     {
5762                       inst.instruction |= i + 8;
5763                       return SUCCESS;
5764                     }
5765                   *str = start;
5766                 }
5767             }
5768
5769           /* Just because we didn't get a match doesn't mean that the
5770              constant isn't valid, just that it is in a format that we
5771              don't automatically recognize.  Try parsing it with
5772              the standard expression routines.  */
5773           if ((i = my_get_float_expression (str)) >= 0)
5774             {
5775               inst.instruction |= i + 8;
5776               return SUCCESS;
5777             }
5778
5779           inst.error = _("invalid floating point immediate expression");
5780           return FAIL;
5781         }
5782       inst.error =
5783         _("floating point register or immediate expression expected");
5784       return FAIL;
5785     }
5786 }
5787
5788 static void
5789 do_arit (str)
5790      char * str;
5791 {
5792   skip_whitespace (str);
5793
5794   if (reg_required_here (&str, 12) == FAIL
5795       || skip_past_comma (&str) == FAIL
5796       || reg_required_here (&str, 16) == FAIL
5797       || skip_past_comma (&str) == FAIL
5798       || data_op2 (&str) == FAIL)
5799     {
5800       if (!inst.error)
5801         inst.error = BAD_ARGS;
5802       return;
5803     }
5804
5805   end_of_line (str);
5806   return;
5807 }
5808
5809 static void
5810 do_adr (str)
5811      char * str;
5812 {
5813   /* This is a pseudo-op of the form "adr rd, label" to be converted
5814      into a relative address of the form "add rd, pc, #label-.-8".  */
5815   skip_whitespace (str);
5816
5817   if (reg_required_here (&str, 12) == FAIL
5818       || skip_past_comma (&str) == FAIL
5819       || my_get_expression (&inst.reloc.exp, &str))
5820     {
5821       if (!inst.error)
5822         inst.error = BAD_ARGS;
5823       return;
5824     }
5825
5826   /* Frag hacking will turn this into a sub instruction if the offset turns
5827      out to be negative.  */
5828   inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
5829   inst.reloc.exp.X_add_number -= 8; /* PC relative adjust.  */
5830   inst.reloc.pc_rel = 1;
5831
5832   end_of_line (str);
5833 }
5834
5835 static void
5836 do_adrl (str)
5837      char * str;
5838 {
5839   /* This is a pseudo-op of the form "adrl rd, label" to be converted
5840      into a relative address of the form:
5841      add rd, pc, #low(label-.-8)"
5842      add rd, rd, #high(label-.-8)"  */
5843
5844   skip_whitespace (str);
5845
5846   if (reg_required_here (&str, 12) == FAIL
5847       || skip_past_comma (&str) == FAIL
5848       || my_get_expression (&inst.reloc.exp, &str))
5849     {
5850       if (!inst.error)
5851         inst.error = BAD_ARGS;
5852
5853       return;
5854     }
5855
5856   end_of_line (str);
5857   /* Frag hacking will turn this into a sub instruction if the offset turns
5858      out to be negative.  */
5859   inst.reloc.type              = BFD_RELOC_ARM_ADRL_IMMEDIATE;
5860   inst.reloc.exp.X_add_number -= 8; /* PC relative adjust  */
5861   inst.reloc.pc_rel            = 1;
5862   inst.size                    = INSN_SIZE * 2;
5863
5864   return;
5865 }
5866
5867 static void
5868 do_cmp (str)
5869      char * str;
5870 {
5871   skip_whitespace (str);
5872
5873   if (reg_required_here (&str, 16) == FAIL)
5874     {
5875       if (!inst.error)
5876         inst.error = BAD_ARGS;
5877       return;
5878     }
5879
5880   if (skip_past_comma (&str) == FAIL
5881       || data_op2 (&str) == FAIL)
5882     {
5883       if (!inst.error)
5884         inst.error = BAD_ARGS;
5885       return;
5886     }
5887
5888   end_of_line (str);
5889   return;
5890 }
5891
5892 static void
5893 do_mov (str)
5894      char * str;
5895 {
5896   skip_whitespace (str);
5897
5898   if (reg_required_here (&str, 12) == FAIL)
5899     {
5900       if (!inst.error)
5901         inst.error = BAD_ARGS;
5902       return;
5903     }
5904
5905   if (skip_past_comma (&str) == FAIL
5906       || data_op2 (&str) == FAIL)
5907     {
5908       if (!inst.error)
5909         inst.error = BAD_ARGS;
5910       return;
5911     }
5912
5913   end_of_line (str);
5914   return;
5915 }
5916
5917 static int
5918 ldst_extend (str)
5919      char ** str;
5920 {
5921   int add = INDEX_UP;
5922
5923   switch (**str)
5924     {
5925     case '#':
5926     case '$':
5927       (*str)++;
5928       if (my_get_expression (& inst.reloc.exp, str))
5929         return FAIL;
5930
5931       if (inst.reloc.exp.X_op == O_constant)
5932         {
5933           int value = inst.reloc.exp.X_add_number;
5934
5935           if (value < -4095 || value > 4095)
5936             {
5937               inst.error = _("address offset too large");
5938               return FAIL;
5939             }
5940
5941           if (value < 0)
5942             {
5943               value = -value;
5944               add = 0;
5945             }
5946
5947           inst.instruction |= add | value;
5948         }
5949       else
5950         {
5951           inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
5952           inst.reloc.pc_rel = 0;
5953         }
5954       return SUCCESS;
5955
5956     case '-':
5957       add = 0;
5958       /* Fall through.  */
5959
5960     case '+':
5961       (*str)++;
5962       /* Fall through.  */
5963
5964     default:
5965       if (reg_required_here (str, 0) == FAIL)
5966         return FAIL;
5967
5968       inst.instruction |= add | OFFSET_REG;
5969       if (skip_past_comma (str) == SUCCESS)
5970         return decode_shift (str, SHIFT_RESTRICT);
5971
5972       return SUCCESS;
5973     }
5974 }
5975
5976 static void
5977 do_ldst (str)
5978      char *        str;
5979 {
5980   int pre_inc = 0;
5981   int conflict_reg;
5982   int value;
5983
5984   skip_whitespace (str);
5985
5986   if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
5987     {
5988       if (!inst.error)
5989         inst.error = BAD_ARGS;
5990       return;
5991     }
5992
5993   if (skip_past_comma (&str) == FAIL)
5994     {
5995       inst.error = _("address expected");
5996       return;
5997     }
5998
5999   if (*str == '[')
6000     {
6001       int reg;
6002
6003       str++;
6004
6005       skip_whitespace (str);
6006
6007       if ((reg = reg_required_here (&str, 16)) == FAIL)
6008         return;
6009
6010       /* Conflicts can occur on stores as well as loads.  */
6011       conflict_reg = (conflict_reg == reg);
6012
6013       skip_whitespace (str);
6014
6015       if (*str == ']')
6016         {
6017           str ++;
6018
6019           if (skip_past_comma (&str) == SUCCESS)
6020             {
6021               /* [Rn],... (post inc)  */
6022               if (ldst_extend (&str) == FAIL)
6023                 return;
6024               if (conflict_reg)
6025                 as_warn (_("%s register same as write-back base"),
6026                          ((inst.instruction & LOAD_BIT)
6027                           ? _("destination") : _("source")));
6028             }
6029           else
6030             {
6031               /* [Rn]  */
6032               skip_whitespace (str);
6033
6034               if (*str == '!')
6035                 {
6036                   if (conflict_reg)
6037                     as_warn (_("%s register same as write-back base"),
6038                              ((inst.instruction & LOAD_BIT)
6039                               ? _("destination") : _("source")));
6040                   str++;
6041                   inst.instruction |= WRITE_BACK;
6042                 }
6043
6044               inst.instruction |= INDEX_UP;
6045               pre_inc = 1;
6046             }
6047         }
6048       else
6049         {
6050           /* [Rn,...]  */
6051           if (skip_past_comma (&str) == FAIL)
6052             {
6053               inst.error = _("pre-indexed expression expected");
6054               return;
6055             }
6056
6057           pre_inc = 1;
6058           if (ldst_extend (&str) == FAIL)
6059             return;
6060
6061           skip_whitespace (str);
6062
6063           if (*str++ != ']')
6064             {
6065               inst.error = _("missing ]");
6066               return;
6067             }
6068
6069           skip_whitespace (str);
6070
6071           if (*str == '!')
6072             {
6073               if (conflict_reg)
6074                 as_warn (_("%s register same as write-back base"),
6075                          ((inst.instruction & LOAD_BIT)
6076                           ? _("destination") : _("source")));
6077               str++;
6078               inst.instruction |= WRITE_BACK;
6079             }
6080         }
6081     }
6082   else if (*str == '=')
6083     {
6084       if ((inst.instruction & LOAD_BIT) == 0)
6085         {
6086           inst.error = _("invalid pseudo operation");
6087           return;
6088         }
6089
6090       /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op.  */
6091       str++;
6092
6093       skip_whitespace (str);
6094
6095       if (my_get_expression (&inst.reloc.exp, &str))
6096         return;
6097
6098       if (inst.reloc.exp.X_op != O_constant
6099           && inst.reloc.exp.X_op != O_symbol)
6100         {
6101           inst.error = _("constant expression expected");
6102           return;
6103         }
6104
6105       if (inst.reloc.exp.X_op == O_constant)
6106         {
6107           value = validate_immediate (inst.reloc.exp.X_add_number);
6108
6109           if (value != FAIL)
6110             {
6111               /* This can be done with a mov instruction.  */
6112               inst.instruction &= LITERAL_MASK;
6113               inst.instruction |= (INST_IMMEDIATE
6114                                    | (OPCODE_MOV << DATA_OP_SHIFT));
6115               inst.instruction |= value & 0xfff;
6116               end_of_line (str);
6117               return;
6118             }
6119
6120           value = validate_immediate (~inst.reloc.exp.X_add_number);
6121
6122           if (value != FAIL)
6123             {
6124               /* This can be done with a mvn instruction.  */
6125               inst.instruction &= LITERAL_MASK;
6126               inst.instruction |= (INST_IMMEDIATE
6127                                    | (OPCODE_MVN << DATA_OP_SHIFT));
6128               inst.instruction |= value & 0xfff;
6129               end_of_line (str);
6130               return;
6131             }
6132         }
6133
6134       /* Insert into literal pool.  */
6135       if (add_to_lit_pool () == FAIL)
6136         {
6137           if (!inst.error)
6138             inst.error = _("literal pool insertion failed");
6139           return;
6140         }
6141
6142       /* Change the instruction exp to point to the pool.  */
6143       inst.reloc.type = BFD_RELOC_ARM_LITERAL;
6144       inst.reloc.pc_rel = 1;
6145       inst.instruction |= (REG_PC << 16);
6146       pre_inc = 1;
6147     }
6148   else
6149     {
6150       if (my_get_expression (&inst.reloc.exp, &str))
6151         return;
6152
6153       inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
6154 #ifndef TE_WINCE
6155       /* PC rel adjust.  */
6156       inst.reloc.exp.X_add_number -= 8;
6157 #endif
6158       inst.reloc.pc_rel = 1;
6159       inst.instruction |= (REG_PC << 16);
6160       pre_inc = 1;
6161     }
6162
6163   inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6164   end_of_line (str);
6165   return;
6166 }
6167
6168 static void
6169 do_ldstt (str)
6170      char *        str;
6171 {
6172   int conflict_reg;
6173
6174   skip_whitespace (str);
6175
6176   if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6177     {
6178       if (!inst.error)
6179         inst.error = BAD_ARGS;
6180       return;
6181     }
6182
6183   if (skip_past_comma (& str) == FAIL)
6184     {
6185       inst.error = _("address expected");
6186       return;
6187     }
6188
6189   if (*str == '[')
6190     {
6191       int reg;
6192
6193       str++;
6194
6195       skip_whitespace (str);
6196
6197       if ((reg = reg_required_here (&str, 16)) == FAIL)
6198         return;
6199
6200       /* ldrt/strt always use post-indexed addressing, so if the base is
6201          the same as Rd, we warn.  */
6202       if (conflict_reg == reg)
6203         as_warn (_("%s register same as write-back base"),
6204                  ((inst.instruction & LOAD_BIT)
6205                   ? _("destination") : _("source")));
6206
6207       skip_whitespace (str);
6208
6209       if (*str == ']')
6210         {
6211           str ++;
6212
6213           if (skip_past_comma (&str) == SUCCESS)
6214             {
6215               /* [Rn],... (post inc)  */
6216               if (ldst_extend (&str) == FAIL)
6217                 return;
6218             }
6219           else
6220             {
6221               /* [Rn]  */
6222               skip_whitespace (str);
6223
6224               /* Skip a write-back '!'.  */
6225               if (*str == '!')
6226                 str++;
6227
6228               inst.instruction |= INDEX_UP;
6229             }
6230         }
6231       else
6232         {
6233           inst.error = _("post-indexed expression expected");
6234           return;
6235         }
6236     }
6237   else
6238     {
6239       inst.error = _("post-indexed expression expected");
6240       return;
6241     }
6242
6243   end_of_line (str);
6244   return;
6245 }
6246
6247 static int
6248 ldst_extend_v4 (str)
6249      char ** str;
6250 {
6251   int add = INDEX_UP;
6252
6253   switch (**str)
6254     {
6255     case '#':
6256     case '$':
6257       (*str)++;
6258       if (my_get_expression (& inst.reloc.exp, str))
6259         return FAIL;
6260
6261       if (inst.reloc.exp.X_op == O_constant)
6262         {
6263           int value = inst.reloc.exp.X_add_number;
6264
6265           if (value < -255 || value > 255)
6266             {
6267               inst.error = _("address offset too large");
6268               return FAIL;
6269             }
6270
6271           if (value < 0)
6272             {
6273               value = -value;
6274               add = 0;
6275             }
6276
6277           /* Halfword and signextension instructions have the
6278              immediate value split across bits 11..8 and bits 3..0.  */
6279           inst.instruction |= (add | HWOFFSET_IMM
6280                                | ((value >> 4) << 8) | (value & 0xF));
6281         }
6282       else
6283         {
6284           inst.instruction |= HWOFFSET_IMM;
6285           inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
6286           inst.reloc.pc_rel = 0;
6287         }
6288       return SUCCESS;
6289
6290     case '-':
6291       add = 0;
6292       /* Fall through.  */
6293
6294     case '+':
6295       (*str)++;
6296       /* Fall through.  */
6297
6298     default:
6299       if (reg_required_here (str, 0) == FAIL)
6300         return FAIL;
6301
6302       inst.instruction |= add;
6303       return SUCCESS;
6304     }
6305 }
6306
6307 /* Halfword and signed-byte load/store operations.  */
6308 static void
6309 do_ldstv4 (str)
6310      char *        str;
6311 {
6312   int pre_inc = 0;
6313   int conflict_reg;
6314   int value;
6315
6316   skip_whitespace (str);
6317
6318   if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
6319     {
6320       if (!inst.error)
6321         inst.error = BAD_ARGS;
6322       return;
6323     }
6324
6325   if (skip_past_comma (& str) == FAIL)
6326     {
6327       inst.error = _("address expected");
6328       return;
6329     }
6330
6331   if (*str == '[')
6332     {
6333       int reg;
6334
6335       str++;
6336
6337       skip_whitespace (str);
6338
6339       if ((reg = reg_required_here (&str, 16)) == FAIL)
6340         return;
6341
6342       /* Conflicts can occur on stores as well as loads.  */
6343       conflict_reg = (conflict_reg == reg);
6344
6345       skip_whitespace (str);
6346
6347       if (*str == ']')
6348         {
6349           str ++;
6350
6351           if (skip_past_comma (&str) == SUCCESS)
6352             {
6353               /* [Rn],... (post inc)  */
6354               if (ldst_extend_v4 (&str) == FAIL)
6355                 return;
6356               if (conflict_reg)
6357                 as_warn (_("%s register same as write-back base"),
6358                          ((inst.instruction & LOAD_BIT)
6359                           ? _("destination") : _("source")));
6360             }
6361           else
6362             {
6363               /* [Rn]  */
6364               inst.instruction |= HWOFFSET_IMM;
6365
6366               skip_whitespace (str);
6367
6368               if (*str == '!')
6369                 {
6370                   if (conflict_reg)
6371                     as_warn (_("%s register same as write-back base"),
6372                              ((inst.instruction & LOAD_BIT)
6373                               ? _("destination") : _("source")));
6374                   str++;
6375                   inst.instruction |= WRITE_BACK;
6376                 }
6377
6378               inst.instruction |= INDEX_UP;
6379               pre_inc = 1;
6380             }
6381         }
6382       else
6383         {
6384           /* [Rn,...]  */
6385           if (skip_past_comma (&str) == FAIL)
6386             {
6387               inst.error = _("pre-indexed expression expected");
6388               return;
6389             }
6390
6391           pre_inc = 1;
6392           if (ldst_extend_v4 (&str) == FAIL)
6393             return;
6394
6395           skip_whitespace (str);
6396
6397           if (*str++ != ']')
6398             {
6399               inst.error = _("missing ]");
6400               return;
6401             }
6402
6403           skip_whitespace (str);
6404
6405           if (*str == '!')
6406             {
6407               if (conflict_reg)
6408                 as_warn (_("%s register same as write-back base"),
6409                          ((inst.instruction & LOAD_BIT)
6410                           ? _("destination") : _("source")));
6411               str++;
6412               inst.instruction |= WRITE_BACK;
6413             }
6414         }
6415     }
6416   else if (*str == '=')
6417     {
6418       if ((inst.instruction & LOAD_BIT) == 0)
6419         {
6420           inst.error = _("invalid pseudo operation");
6421           return;
6422         }
6423
6424       /* XXX Does this work correctly for half-word/byte ops?  */
6425       /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op.  */
6426       str++;
6427
6428       skip_whitespace (str);
6429
6430       if (my_get_expression (&inst.reloc.exp, &str))
6431         return;
6432
6433       if (inst.reloc.exp.X_op != O_constant
6434           && inst.reloc.exp.X_op != O_symbol)
6435         {
6436           inst.error = _("constant expression expected");
6437           return;
6438         }
6439
6440       if (inst.reloc.exp.X_op == O_constant)
6441         {
6442           value = validate_immediate (inst.reloc.exp.X_add_number);
6443
6444           if (value != FAIL)
6445             {
6446               /* This can be done with a mov instruction.  */
6447               inst.instruction &= LITERAL_MASK;
6448               inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
6449               inst.instruction |= value & 0xfff;
6450               end_of_line (str);
6451               return;
6452             }
6453
6454           value = validate_immediate (~ inst.reloc.exp.X_add_number);
6455
6456           if (value != FAIL)
6457             {
6458               /* This can be done with a mvn instruction.  */
6459               inst.instruction &= LITERAL_MASK;
6460               inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
6461               inst.instruction |= value & 0xfff;
6462               end_of_line (str);
6463               return;
6464             }
6465         }
6466
6467       /* Insert into literal pool.  */
6468       if (add_to_lit_pool () == FAIL)
6469         {
6470           if (!inst.error)
6471             inst.error = _("literal pool insertion failed");
6472           return;
6473         }
6474
6475       /* Change the instruction exp to point to the pool.  */
6476       inst.instruction |= HWOFFSET_IMM;
6477       inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
6478       inst.reloc.pc_rel = 1;
6479       inst.instruction |= (REG_PC << 16);
6480       pre_inc = 1;
6481     }
6482   else
6483     {
6484       if (my_get_expression (&inst.reloc.exp, &str))
6485         return;
6486
6487       inst.instruction |= HWOFFSET_IMM;
6488       inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
6489 #ifndef TE_WINCE
6490       /* PC rel adjust.  */
6491       inst.reloc.exp.X_add_number -= 8;
6492 #endif
6493       inst.reloc.pc_rel = 1;
6494       inst.instruction |= (REG_PC << 16);
6495       pre_inc = 1;
6496     }
6497
6498   inst.instruction |= (pre_inc ? PRE_INDEX : 0);
6499   end_of_line (str);
6500   return;
6501 }
6502
6503 static long
6504 reg_list (strp)
6505      char ** strp;
6506 {
6507   char * str = * strp;
6508   long   range = 0;
6509   int    another_range;
6510
6511   /* We come back here if we get ranges concatenated by '+' or '|'.  */
6512   do
6513     {
6514       another_range = 0;
6515
6516       if (*str == '{')
6517         {
6518           int in_range = 0;
6519           int cur_reg = -1;
6520
6521           str++;
6522           do
6523             {
6524               int reg;
6525
6526               skip_whitespace (str);
6527
6528               if ((reg = reg_required_here (& str, -1)) == FAIL)
6529                 return FAIL;
6530
6531               if (in_range)
6532                 {
6533                   int i;
6534
6535                   if (reg <= cur_reg)
6536                     {
6537                       inst.error = _("bad range in register list");
6538                       return FAIL;
6539                     }
6540
6541                   for (i = cur_reg + 1; i < reg; i++)
6542                     {
6543                       if (range & (1 << i))
6544                         as_tsktsk
6545                           (_("Warning: duplicated register (r%d) in register list"),
6546                            i);
6547                       else
6548                         range |= 1 << i;
6549                     }
6550                   in_range = 0;
6551                 }
6552
6553               if (range & (1 << reg))
6554                 as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
6555                            reg);
6556               else if (reg <= cur_reg)
6557                 as_tsktsk (_("Warning: register range not in ascending order"));
6558
6559               range |= 1 << reg;
6560               cur_reg = reg;
6561             }
6562           while (skip_past_comma (&str) != FAIL
6563                  || (in_range = 1, *str++ == '-'));
6564           str--;
6565           skip_whitespace (str);
6566
6567           if (*str++ != '}')
6568             {
6569               inst.error = _("missing `}'");
6570               return FAIL;
6571             }
6572         }
6573       else
6574         {
6575           expressionS expr;
6576
6577           if (my_get_expression (&expr, &str))
6578             return FAIL;
6579
6580           if (expr.X_op == O_constant)
6581             {
6582               if (expr.X_add_number
6583                   != (expr.X_add_number & 0x0000ffff))
6584                 {
6585                   inst.error = _("invalid register mask");
6586                   return FAIL;
6587                 }
6588
6589               if ((range & expr.X_add_number) != 0)
6590                 {
6591                   int regno = range & expr.X_add_number;
6592
6593                   regno &= -regno;
6594                   regno = (1 << regno) - 1;
6595                   as_tsktsk
6596                     (_("Warning: duplicated register (r%d) in register list"),
6597                      regno);
6598                 }
6599
6600               range |= expr.X_add_number;
6601             }
6602           else
6603             {
6604               if (inst.reloc.type != 0)
6605                 {
6606                   inst.error = _("expression too complex");
6607                   return FAIL;
6608                 }
6609
6610               memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
6611               inst.reloc.type = BFD_RELOC_ARM_MULTI;
6612               inst.reloc.pc_rel = 0;
6613             }
6614         }
6615
6616       skip_whitespace (str);
6617
6618       if (*str == '|' || *str == '+')
6619         {
6620           str++;
6621           another_range = 1;
6622         }
6623     }
6624   while (another_range);
6625
6626   *strp = str;
6627   return range;
6628 }
6629
6630 static void
6631 do_ldmstm (str)
6632      char * str;
6633 {
6634   int base_reg;
6635   long range;
6636
6637   skip_whitespace (str);
6638
6639   if ((base_reg = reg_required_here (&str, 16)) == FAIL)
6640     return;
6641
6642   if (base_reg == REG_PC)
6643     {
6644       inst.error = _("r15 not allowed as base register");
6645       return;
6646     }
6647
6648   skip_whitespace (str);
6649
6650   if (*str == '!')
6651     {
6652       inst.instruction |= WRITE_BACK;
6653       str++;
6654     }
6655
6656   if (skip_past_comma (&str) == FAIL
6657       || (range = reg_list (&str)) == FAIL)
6658     {
6659       if (! inst.error)
6660         inst.error = BAD_ARGS;
6661       return;
6662     }
6663
6664   if (*str == '^')
6665     {
6666       str++;
6667       inst.instruction |= LDM_TYPE_2_OR_3;
6668     }
6669
6670   if (inst.instruction & WRITE_BACK)
6671     {
6672       /* Check for unpredictable uses of writeback.  */
6673       if (inst.instruction & LOAD_BIT)
6674         {
6675           /* Not allowed in LDM type 2.  */
6676           if ((inst.instruction & LDM_TYPE_2_OR_3)
6677               && ((range & (1 << REG_PC)) == 0))
6678             as_warn (_("writeback of base register is UNPREDICTABLE"));
6679           /* Only allowed if base reg not in list for other types.  */
6680           else if (range & (1 << base_reg))
6681             as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
6682         }
6683       else /* STM.  */
6684         {
6685           /* Not allowed for type 2.  */
6686           if (inst.instruction & LDM_TYPE_2_OR_3)
6687             as_warn (_("writeback of base register is UNPREDICTABLE"));
6688           /* Only allowed if base reg not in list, or first in list.  */
6689           else if ((range & (1 << base_reg))
6690                    && (range & ((1 << base_reg) - 1)))
6691             as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
6692         }
6693     }
6694
6695   inst.instruction |= range;
6696   end_of_line (str);
6697   return;
6698 }
6699
6700 static void
6701 do_swi (str)
6702      char * str;
6703 {
6704   skip_whitespace (str);
6705
6706   /* Allow optional leading '#'.  */
6707   if (is_immediate_prefix (*str))
6708     str++;
6709
6710   if (my_get_expression (& inst.reloc.exp, & str))
6711     return;
6712
6713   inst.reloc.type = BFD_RELOC_ARM_SWI;
6714   inst.reloc.pc_rel = 0;
6715   end_of_line (str);
6716
6717   return;
6718 }
6719
6720 static void
6721 do_swap (str)
6722      char * str;
6723 {
6724   int reg;
6725
6726   skip_whitespace (str);
6727
6728   if ((reg = reg_required_here (&str, 12)) == FAIL)
6729     return;
6730
6731   if (reg == REG_PC)
6732     {
6733       inst.error = _("r15 not allowed in swap");
6734       return;
6735     }
6736
6737   if (skip_past_comma (&str) == FAIL
6738       || (reg = reg_required_here (&str, 0)) == FAIL)
6739     {
6740       if (!inst.error)
6741         inst.error = BAD_ARGS;
6742       return;
6743     }
6744
6745   if (reg == REG_PC)
6746     {
6747       inst.error = _("r15 not allowed in swap");
6748       return;
6749     }
6750
6751   if (skip_past_comma (&str) == FAIL
6752       || *str++ != '[')
6753     {
6754       inst.error = BAD_ARGS;
6755       return;
6756     }
6757
6758   skip_whitespace (str);
6759
6760   if ((reg = reg_required_here (&str, 16)) == FAIL)
6761     return;
6762
6763   if (reg == REG_PC)
6764     {
6765       inst.error = BAD_PC;
6766       return;
6767     }
6768
6769   skip_whitespace (str);
6770
6771   if (*str++ != ']')
6772     {
6773       inst.error = _("missing ]");
6774       return;
6775     }
6776
6777   end_of_line (str);
6778   return;
6779 }
6780
6781 static void
6782 do_branch (str)
6783      char * str;
6784 {
6785   if (my_get_expression (&inst.reloc.exp, &str))
6786     return;
6787
6788 #ifdef OBJ_ELF
6789   {
6790     char * save_in;
6791
6792     /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
6793        required for the instruction.  */
6794
6795     /* arm_parse_reloc () works on input_line_pointer.
6796        We actually want to parse the operands to the branch instruction
6797        passed in 'str'.  Save the input pointer and restore it later.  */
6798     save_in = input_line_pointer;
6799     input_line_pointer = str;
6800     if (inst.reloc.exp.X_op == O_symbol
6801         && *str == '('
6802         && arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
6803       {
6804         inst.reloc.type   = BFD_RELOC_ARM_PLT32;
6805         inst.reloc.pc_rel = 0;
6806         /* Modify str to point to after parsed operands, otherwise
6807            end_of_line() will complain about the (PLT) left in str.  */
6808         str = input_line_pointer;
6809       }
6810     else
6811       {
6812         inst.reloc.type   = BFD_RELOC_ARM_PCREL_BRANCH;
6813         inst.reloc.pc_rel = 1;
6814       }
6815     input_line_pointer = save_in;
6816   }
6817 #else
6818   inst.reloc.type   = BFD_RELOC_ARM_PCREL_BRANCH;
6819   inst.reloc.pc_rel = 1;
6820 #endif /* OBJ_ELF  */
6821
6822   end_of_line (str);
6823   return;
6824 }
6825
6826 static void
6827 do_bx (str)
6828      char * str;
6829 {
6830   int reg;
6831
6832   skip_whitespace (str);
6833
6834   if ((reg = reg_required_here (&str, 0)) == FAIL)
6835     {
6836       inst.error = BAD_ARGS;
6837       return;
6838     }
6839
6840   /* Note - it is not illegal to do a "bx pc".  Useless, but not illegal.  */
6841   if (reg == REG_PC)
6842     as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
6843
6844   end_of_line (str);
6845 }
6846
6847 static void
6848 do_cdp (str)
6849      char * str;
6850 {
6851   /* Co-processor data operation.
6852      Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>}  */
6853   skip_whitespace (str);
6854
6855   if (co_proc_number (&str) == FAIL)
6856     {
6857       if (!inst.error)
6858         inst.error = BAD_ARGS;
6859       return;
6860     }
6861
6862   if (skip_past_comma (&str) == FAIL
6863       || cp_opc_expr (&str, 20,4) == FAIL)
6864     {
6865       if (!inst.error)
6866         inst.error = BAD_ARGS;
6867       return;
6868     }
6869
6870   if (skip_past_comma (&str) == FAIL
6871       || cp_reg_required_here (&str, 12) == FAIL)
6872     {
6873       if (!inst.error)
6874         inst.error = BAD_ARGS;
6875       return;
6876     }
6877
6878   if (skip_past_comma (&str) == FAIL
6879       || cp_reg_required_here (&str, 16) == FAIL)
6880     {
6881       if (!inst.error)
6882         inst.error = BAD_ARGS;
6883       return;
6884     }
6885
6886   if (skip_past_comma (&str) == FAIL
6887       || cp_reg_required_here (&str, 0) == FAIL)
6888     {
6889       if (!inst.error)
6890         inst.error = BAD_ARGS;
6891       return;
6892     }
6893
6894   if (skip_past_comma (&str) == SUCCESS)
6895     {
6896       if (cp_opc_expr (&str, 5, 3) == FAIL)
6897         {
6898           if (!inst.error)
6899             inst.error = BAD_ARGS;
6900           return;
6901         }
6902     }
6903
6904   end_of_line (str);
6905   return;
6906 }
6907
6908 static void
6909 do_lstc (str)
6910      char * str;
6911 {
6912   /* Co-processor register load/store.
6913      Format: <LDC|STC{cond}[L] CP#,CRd,<address>  */
6914
6915   skip_whitespace (str);
6916
6917   if (co_proc_number (&str) == FAIL)
6918     {
6919       if (!inst.error)
6920         inst.error = BAD_ARGS;
6921       return;
6922     }
6923
6924   if (skip_past_comma (&str) == FAIL
6925       || cp_reg_required_here (&str, 12) == FAIL)
6926     {
6927       if (!inst.error)
6928         inst.error = BAD_ARGS;
6929       return;
6930     }
6931
6932   if (skip_past_comma (&str) == FAIL
6933       || cp_address_required_here (&str, CP_WB_OK) == FAIL)
6934     {
6935       if (! inst.error)
6936         inst.error = BAD_ARGS;
6937       return;
6938     }
6939
6940   end_of_line (str);
6941   return;
6942 }
6943
6944 static void
6945 do_co_reg (str)
6946      char * str;
6947 {
6948   /* Co-processor register transfer.
6949      Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>}  */
6950
6951   skip_whitespace (str);
6952
6953   if (co_proc_number (&str) == FAIL)
6954     {
6955       if (!inst.error)
6956         inst.error = BAD_ARGS;
6957       return;
6958     }
6959
6960   if (skip_past_comma (&str) == FAIL
6961       || cp_opc_expr (&str, 21, 3) == FAIL)
6962     {
6963       if (!inst.error)
6964         inst.error = BAD_ARGS;
6965       return;
6966     }
6967
6968   if (skip_past_comma (&str) == FAIL
6969       || reg_required_here (&str, 12) == FAIL)
6970     {
6971       if (!inst.error)
6972         inst.error = BAD_ARGS;
6973       return;
6974     }
6975
6976   if (skip_past_comma (&str) == FAIL
6977       || cp_reg_required_here (&str, 16) == FAIL)
6978     {
6979       if (!inst.error)
6980         inst.error = BAD_ARGS;
6981       return;
6982     }
6983
6984   if (skip_past_comma (&str) == FAIL
6985       || cp_reg_required_here (&str, 0) == FAIL)
6986     {
6987       if (!inst.error)
6988         inst.error = BAD_ARGS;
6989       return;
6990     }
6991
6992   if (skip_past_comma (&str) == SUCCESS)
6993     {
6994       if (cp_opc_expr (&str, 5, 3) == FAIL)
6995         {
6996           if (!inst.error)
6997             inst.error = BAD_ARGS;
6998           return;
6999         }
7000     }
7001
7002   end_of_line (str);
7003   return;
7004 }
7005
7006 static void
7007 do_fpa_ctrl (str)
7008      char * str;
7009 {
7010   /* FP control registers.
7011      Format: <WFS|RFS|WFC|RFC>{cond} Rn  */
7012
7013   skip_whitespace (str);
7014
7015   if (reg_required_here (&str, 12) == FAIL)
7016     {
7017       if (!inst.error)
7018         inst.error = BAD_ARGS;
7019       return;
7020     }
7021
7022   end_of_line (str);
7023   return;
7024 }
7025
7026 static void
7027 do_fpa_ldst (str)
7028      char * str;
7029 {
7030   skip_whitespace (str);
7031
7032   if (fp_reg_required_here (&str, 12) == FAIL)
7033     {
7034       if (!inst.error)
7035         inst.error = BAD_ARGS;
7036       return;
7037     }
7038
7039   if (skip_past_comma (&str) == FAIL
7040       || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7041     {
7042       if (!inst.error)
7043         inst.error = BAD_ARGS;
7044       return;
7045     }
7046
7047   end_of_line (str);
7048 }
7049
7050 static void
7051 do_fpa_ldmstm (str)
7052      char * str;
7053 {
7054   int num_regs;
7055
7056   skip_whitespace (str);
7057
7058   if (fp_reg_required_here (&str, 12) == FAIL)
7059     {
7060       if (! inst.error)
7061         inst.error = BAD_ARGS;
7062       return;
7063     }
7064
7065   /* Get Number of registers to transfer.  */
7066   if (skip_past_comma (&str) == FAIL
7067       || my_get_expression (&inst.reloc.exp, &str))
7068     {
7069       if (! inst.error)
7070         inst.error = _("constant expression expected");
7071       return;
7072     }
7073
7074   if (inst.reloc.exp.X_op != O_constant)
7075     {
7076       inst.error = _("constant value required for number of registers");
7077       return;
7078     }
7079
7080   num_regs = inst.reloc.exp.X_add_number;
7081
7082   if (num_regs < 1 || num_regs > 4)
7083     {
7084       inst.error = _("number of registers must be in the range [1:4]");
7085       return;
7086     }
7087
7088   switch (num_regs)
7089     {
7090     case 1:
7091       inst.instruction |= CP_T_X;
7092       break;
7093     case 2:
7094       inst.instruction |= CP_T_Y;
7095       break;
7096     case 3:
7097       inst.instruction |= CP_T_Y | CP_T_X;
7098       break;
7099     case 4:
7100       break;
7101     default:
7102       abort ();
7103     }
7104
7105   if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format.  */
7106     {
7107       int reg;
7108       int write_back;
7109       int offset;
7110
7111       /* The instruction specified "ea" or "fd", so we can only accept
7112          [Rn]{!}.  The instruction does not really support stacking or
7113          unstacking, so we have to emulate these by setting appropriate
7114          bits and offsets.  */
7115       if (skip_past_comma (&str) == FAIL
7116           || *str != '[')
7117         {
7118           if (! inst.error)
7119             inst.error = BAD_ARGS;
7120           return;
7121         }
7122
7123       str++;
7124       skip_whitespace (str);
7125
7126       if ((reg = reg_required_here (&str, 16)) == FAIL)
7127         return;
7128
7129       skip_whitespace (str);
7130
7131       if (*str != ']')
7132         {
7133           inst.error = BAD_ARGS;
7134           return;
7135         }
7136
7137       str++;
7138       if (*str == '!')
7139         {
7140           write_back = 1;
7141           str++;
7142           if (reg == REG_PC)
7143             {
7144               inst.error =
7145                 _("r15 not allowed as base register with write-back");
7146               return;
7147             }
7148         }
7149       else
7150         write_back = 0;
7151
7152       if (inst.instruction & CP_T_Pre)
7153         {
7154           /* Pre-decrement.  */
7155           offset = 3 * num_regs;
7156           if (write_back)
7157             inst.instruction |= CP_T_WB;
7158         }
7159       else
7160         {
7161           /* Post-increment.  */
7162           if (write_back)
7163             {
7164               inst.instruction |= CP_T_WB;
7165               offset = 3 * num_regs;
7166             }
7167           else
7168             {
7169               /* No write-back, so convert this into a standard pre-increment
7170                  instruction -- aesthetically more pleasing.  */
7171               inst.instruction |= CP_T_Pre | CP_T_UD;
7172               offset = 0;
7173             }
7174         }
7175
7176       inst.instruction |= offset;
7177     }
7178   else if (skip_past_comma (&str) == FAIL
7179            || cp_address_required_here (&str, CP_WB_OK) == FAIL)
7180     {
7181       if (! inst.error)
7182         inst.error = BAD_ARGS;
7183       return;
7184     }
7185
7186   end_of_line (str);
7187 }
7188
7189 static void
7190 do_fpa_dyadic (str)
7191      char * str;
7192 {
7193   skip_whitespace (str);
7194
7195   if (fp_reg_required_here (&str, 12) == FAIL)
7196     {
7197       if (! inst.error)
7198         inst.error = BAD_ARGS;
7199       return;
7200     }
7201
7202   if (skip_past_comma (&str) == FAIL
7203       || fp_reg_required_here (&str, 16) == FAIL)
7204     {
7205       if (! inst.error)
7206         inst.error = BAD_ARGS;
7207       return;
7208     }
7209
7210   if (skip_past_comma (&str) == FAIL
7211       || fp_op2 (&str) == FAIL)
7212     {
7213       if (! inst.error)
7214         inst.error = BAD_ARGS;
7215       return;
7216     }
7217
7218   end_of_line (str);
7219   return;
7220 }
7221
7222 static void
7223 do_fpa_monadic (str)
7224      char * str;
7225 {
7226   skip_whitespace (str);
7227
7228   if (fp_reg_required_here (&str, 12) == FAIL)
7229     {
7230       if (! inst.error)
7231         inst.error = BAD_ARGS;
7232       return;
7233     }
7234
7235   if (skip_past_comma (&str) == FAIL
7236       || fp_op2 (&str) == FAIL)
7237     {
7238       if (! inst.error)
7239         inst.error = BAD_ARGS;
7240       return;
7241     }
7242
7243   end_of_line (str);
7244   return;
7245 }
7246
7247 static void
7248 do_fpa_cmp (str)
7249      char * str;
7250 {
7251   skip_whitespace (str);
7252
7253   if (fp_reg_required_here (&str, 16) == FAIL)
7254     {
7255       if (! inst.error)
7256         inst.error = BAD_ARGS;
7257       return;
7258     }
7259
7260   if (skip_past_comma (&str) == FAIL
7261       || fp_op2 (&str) == FAIL)
7262     {
7263       if (! inst.error)
7264         inst.error = BAD_ARGS;
7265       return;
7266     }
7267
7268   end_of_line (str);
7269   return;
7270 }
7271
7272 static void
7273 do_fpa_from_reg (str)
7274      char * str;
7275 {
7276   skip_whitespace (str);
7277
7278   if (fp_reg_required_here (&str, 16) == FAIL)
7279     {
7280       if (! inst.error)
7281         inst.error = BAD_ARGS;
7282       return;
7283     }
7284
7285   if (skip_past_comma (&str) == FAIL
7286       || reg_required_here (&str, 12) == FAIL)
7287     {
7288       if (! inst.error)
7289         inst.error = BAD_ARGS;
7290       return;
7291     }
7292
7293   end_of_line (str);
7294   return;
7295 }
7296
7297 static void
7298 do_fpa_to_reg (str)
7299      char * str;
7300 {
7301   skip_whitespace (str);
7302
7303   if (reg_required_here (&str, 12) == FAIL)
7304     return;
7305
7306   if (skip_past_comma (&str) == FAIL
7307       || fp_reg_required_here (&str, 0) == FAIL)
7308     {
7309       if (! inst.error)
7310         inst.error = BAD_ARGS;
7311       return;
7312     }
7313
7314   end_of_line (str);
7315   return;
7316 }
7317
7318 static int
7319 vfp_sp_reg_required_here (str, pos)
7320      char **str;
7321      enum vfp_sp_reg_pos pos;
7322 {
7323   int    reg;
7324   char *start = *str;
7325
7326   if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
7327     {
7328       switch (pos)
7329         {
7330         case VFP_REG_Sd:
7331           inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
7332           break;
7333
7334         case VFP_REG_Sn:
7335           inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
7336           break;
7337
7338         case VFP_REG_Sm:
7339           inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
7340           break;
7341
7342         default:
7343           abort ();
7344         }
7345       return reg;
7346     }
7347
7348   /* In the few cases where we might be able to accept something else
7349      this error can be overridden.  */
7350   inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7351
7352   /* Restore the start point.  */
7353   *str = start;
7354   return FAIL;
7355 }
7356
7357 static int
7358 vfp_dp_reg_required_here (str, pos)
7359      char **str;
7360      enum vfp_dp_reg_pos pos;
7361 {
7362   int   reg;
7363   char *start = *str;
7364
7365   if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
7366     {
7367       switch (pos)
7368         {
7369         case VFP_REG_Dd:
7370           inst.instruction |= reg << 12;
7371           break;
7372
7373         case VFP_REG_Dn:
7374           inst.instruction |= reg << 16;
7375           break;
7376
7377         case VFP_REG_Dm:
7378           inst.instruction |= reg << 0;
7379           break;
7380
7381         default:
7382           abort ();
7383         }
7384       return reg;
7385     }
7386
7387   /* In the few cases where we might be able to accept something else
7388      this error can be overridden.  */
7389   inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
7390
7391   /* Restore the start point.  */
7392   *str = start;
7393   return FAIL;
7394 }
7395
7396 static void
7397 do_vfp_sp_monadic (str)
7398      char *str;
7399 {
7400   skip_whitespace (str);
7401
7402   if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7403     return;
7404
7405   if (skip_past_comma (&str) == FAIL
7406       || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7407     {
7408       if (! inst.error)
7409         inst.error = BAD_ARGS;
7410       return;
7411     }
7412
7413   end_of_line (str);
7414   return;
7415 }
7416
7417 static void
7418 do_vfp_dp_monadic (str)
7419      char *str;
7420 {
7421   skip_whitespace (str);
7422
7423   if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7424     return;
7425
7426   if (skip_past_comma (&str) == FAIL
7427       || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7428     {
7429       if (! inst.error)
7430         inst.error = BAD_ARGS;
7431       return;
7432     }
7433
7434   end_of_line (str);
7435   return;
7436 }
7437
7438 static void
7439 do_vfp_sp_dyadic (str)
7440      char *str;
7441 {
7442   skip_whitespace (str);
7443
7444   if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7445     return;
7446
7447   if (skip_past_comma (&str) == FAIL
7448       || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
7449       || skip_past_comma (&str) == FAIL
7450       || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
7451     {
7452       if (! inst.error)
7453         inst.error = BAD_ARGS;
7454       return;
7455     }
7456
7457   end_of_line (str);
7458   return;
7459 }
7460
7461 static void
7462 do_vfp_dp_dyadic (str)
7463      char *str;
7464 {
7465   skip_whitespace (str);
7466
7467   if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7468     return;
7469
7470   if (skip_past_comma (&str) == FAIL
7471       || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
7472       || skip_past_comma (&str) == FAIL
7473       || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7474     {
7475       if (! inst.error)
7476         inst.error = BAD_ARGS;
7477       return;
7478     }
7479
7480   end_of_line (str);
7481   return;
7482 }
7483
7484 static void
7485 do_vfp_reg_from_sp (str)
7486      char *str;
7487 {
7488   skip_whitespace (str);
7489
7490   if (reg_required_here (&str, 12) == FAIL)
7491     return;
7492
7493   if (skip_past_comma (&str) == FAIL
7494       || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7495     {
7496       if (! inst.error)
7497         inst.error = BAD_ARGS;
7498       return;
7499     }
7500
7501   end_of_line (str);
7502   return;
7503 }
7504
7505 static void
7506 do_vfp_sp_reg2 (str)
7507      char *str;
7508 {
7509   skip_whitespace (str);
7510
7511   if (reg_required_here (&str, 12) == FAIL)
7512     return;
7513
7514   if (skip_past_comma (&str) == FAIL
7515       || reg_required_here (&str, 16) == FAIL
7516       || skip_past_comma (&str) == FAIL)
7517     {
7518       if (! inst.error)
7519         inst.error = BAD_ARGS;
7520       return;
7521     }
7522
7523   /* We require exactly two consecutive SP registers.  */
7524   if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
7525     {
7526       if (! inst.error)
7527         inst.error = _("only two consecutive VFP SP registers allowed here");
7528     }
7529
7530   end_of_line (str);
7531   return;
7532 }
7533
7534 static void
7535 do_vfp_sp_from_reg (str)
7536      char *str;
7537 {
7538   skip_whitespace (str);
7539
7540   if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
7541     return;
7542
7543   if (skip_past_comma (&str) == FAIL
7544       || reg_required_here (&str, 12) == FAIL)
7545     {
7546       if (! inst.error)
7547         inst.error = BAD_ARGS;
7548       return;
7549     }
7550
7551   end_of_line (str);
7552   return;
7553 }
7554
7555 static void
7556 do_vfp_reg_from_dp (str)
7557      char *str;
7558 {
7559   skip_whitespace (str);
7560
7561   if (reg_required_here (&str, 12) == FAIL)
7562     return;
7563
7564   if (skip_past_comma (&str) == FAIL
7565       || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
7566     {
7567       if (! inst.error)
7568         inst.error = BAD_ARGS;
7569       return;
7570     }
7571
7572   end_of_line (str);
7573   return;
7574 }
7575
7576 static void
7577 do_vfp_reg2_from_dp (str)
7578      char *str;
7579 {
7580   skip_whitespace (str);
7581
7582   if (reg_required_here (&str, 12) == FAIL)
7583     return;
7584
7585   if (skip_past_comma (&str) == FAIL
7586       || reg_required_here (&str, 16) == FAIL
7587       || skip_past_comma (&str) == FAIL
7588       || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7589     {
7590       if (! inst.error)
7591         inst.error = BAD_ARGS;
7592       return;
7593     }
7594
7595   end_of_line (str);
7596   return;
7597 }
7598
7599 static void
7600 do_vfp_dp_from_reg (str)
7601      char *str;
7602 {
7603   skip_whitespace (str);
7604
7605   if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
7606     return;
7607
7608   if (skip_past_comma (&str) == FAIL
7609       || reg_required_here (&str, 12) == FAIL)
7610     {
7611       if (! inst.error)
7612         inst.error = BAD_ARGS;
7613       return;
7614     }
7615
7616   end_of_line (str);
7617   return;
7618 }
7619
7620 static void
7621 do_vfp_dp_from_reg2 (str)
7622      char *str;
7623 {
7624   skip_whitespace (str);
7625
7626   if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
7627     return;
7628
7629   if (skip_past_comma (&str) == FAIL
7630       || reg_required_here (&str, 12) == FAIL
7631       || skip_past_comma (&str) == FAIL
7632       || reg_required_here (&str, 16))
7633     {
7634       if (! inst.error)
7635         inst.error = BAD_ARGS;
7636       return;
7637     }
7638
7639   end_of_line (str);
7640   return;
7641 }
7642
7643 static const struct vfp_reg *
7644 vfp_psr_parse (str)
7645      char **str;
7646 {
7647   char *start = *str;
7648   char  c;
7649   char *p;
7650   const struct vfp_reg *vreg;
7651
7652   p = start;
7653
7654   /* Find the end of the current token.  */
7655   do
7656     {
7657       c = *p++;
7658     }
7659   while (ISALPHA (c));
7660
7661   /* Mark it.  */
7662   *--p = 0;
7663
7664   for (vreg = vfp_regs + 0;
7665        vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
7666        vreg++)
7667     {
7668       if (strcmp (start, vreg->name) == 0)
7669         {
7670           *p = c;
7671           *str = p;
7672           return vreg;
7673         }
7674     }
7675
7676   *p = c;
7677   return NULL;
7678 }
7679
7680 static int
7681 vfp_psr_required_here (str)
7682      char **str;
7683 {
7684   char *start = *str;
7685   const struct vfp_reg *vreg;
7686
7687   vreg = vfp_psr_parse (str);
7688
7689   if (vreg)
7690     {
7691       inst.instruction |= vreg->regno;
7692       return SUCCESS;
7693     }
7694
7695   inst.error = _("VFP system register expected");
7696
7697   *str = start;
7698   return FAIL;
7699 }
7700
7701 static void
7702 do_vfp_reg_from_ctrl (str)
7703      char *str;
7704 {
7705   skip_whitespace (str);
7706
7707   if (reg_required_here (&str, 12) == FAIL)
7708     return;
7709
7710   if (skip_past_comma (&str) == FAIL
7711       || vfp_psr_required_here (&str) == FAIL)
7712     {
7713       if (! inst.error)
7714         inst.error = BAD_ARGS;
7715       return;
7716     }
7717
7718   end_of_line (str);
7719   return;
7720 }
7721
7722 static void
7723 do_vfp_ctrl_from_reg (str)
7724      char *str;
7725 {
7726   skip_whitespace (str);
7727
7728   if (vfp_psr_required_here (&str) == FAIL)
7729     return;
7730
7731   if (skip_past_comma (&str) == FAIL
7732       || reg_required_here (&str, 12) == FAIL)
7733     {
7734       if (! inst.error)
7735         inst.error = BAD_ARGS;
7736       return;
7737     }
7738
7739   end_of_line (str);
7740   return;
7741 }
7742
7743 static void
7744 do_vfp_sp_ldst (str)
7745      char *str;
7746 {
7747   skip_whitespace (str);
7748
7749   if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
7750     {
7751       if (!inst.error)
7752         inst.error = BAD_ARGS;
7753       return;
7754     }
7755
7756   if (skip_past_comma (&str) == FAIL
7757       || cp_address_required_here (&str, CP_NO_WB) == FAIL)
7758     {
7759       if (!inst.error)
7760         inst.error = BAD_ARGS;
7761       return;
7762     }
7763
7764   end_of_line (str);
7765   return;
7766 }
7767
7768 static void
7769 do_vfp_dp_ldst (str)
7770      char *str;
7771 {
7772   skip_whitespace (str);
7773
7774   if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
7775     {
7776       if (!inst.error)
7777         inst.error = BAD_ARGS;
7778       return;
7779     }
7780
7781   if (skip_past_comma (&str) == FAIL
7782       || cp_address_required_here (&str, CP_NO_WB) == FAIL)
7783     {
7784       if (!inst.error)
7785         inst.error = BAD_ARGS;
7786       return;
7787     }
7788
7789   end_of_line (str);
7790   return;
7791 }
7792
7793 /* Parse and encode a VFP SP register list, storing the initial
7794    register in position POS and returning the range as the result.  If
7795    the string is invalid return FAIL (an invalid range).  */
7796 static long
7797 vfp_sp_reg_list (str, pos)
7798      char **str;
7799      enum vfp_sp_reg_pos pos;
7800 {
7801   long range = 0;
7802   int base_reg = 0;
7803   int new_base;
7804   long base_bits = 0;
7805   int count = 0;
7806   long tempinst;
7807   unsigned long mask = 0;
7808   int warned = 0;
7809
7810   if (**str != '{')
7811     return FAIL;
7812
7813   (*str)++;
7814   skip_whitespace (*str);
7815
7816   tempinst = inst.instruction;
7817
7818   do
7819     {
7820       inst.instruction = 0;
7821
7822       if ((new_base = vfp_sp_reg_required_here (str, pos)) == FAIL)
7823         return FAIL;
7824
7825       if (count == 0 || base_reg > new_base)
7826         {
7827           base_reg = new_base;
7828           base_bits = inst.instruction;
7829         }
7830
7831       if (mask & (1 << new_base))
7832         {
7833           inst.error = _("invalid register list");
7834           return FAIL;
7835         }
7836
7837       if ((mask >> new_base) != 0 && ! warned)
7838         {
7839           as_tsktsk (_("register list not in ascending order"));
7840           warned = 1;
7841         }
7842
7843       mask |= 1 << new_base;
7844       count++;
7845
7846       skip_whitespace (*str);
7847
7848       if (**str == '-') /* We have the start of a range expression */
7849         {
7850           int high_range;
7851
7852           (*str)++;
7853
7854           if ((high_range
7855                = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab))
7856               == FAIL)
7857             {
7858               inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
7859               return FAIL;
7860             }
7861
7862           if (high_range <= new_base)
7863             {
7864               inst.error = _("register range not in ascending order");
7865               return FAIL;
7866             }
7867
7868           for (new_base++; new_base <= high_range; new_base++)
7869             {
7870               if (mask & (1 << new_base))
7871                 {
7872                   inst.error = _("invalid register list");
7873                   return FAIL;
7874                 }
7875
7876               mask |= 1 << new_base;
7877               count++;
7878             }
7879         }
7880     }
7881   while (skip_past_comma (str) != FAIL);
7882
7883   if (**str != '}')
7884     {
7885       inst.error = _("invalid register list");
7886       return FAIL;
7887     }
7888
7889   (*str)++;
7890
7891   range = count;
7892
7893   /* Sanity check -- should have raised a parse error above.  */
7894   if (count == 0 || count > 32)
7895     abort ();
7896
7897   /* Final test -- the registers must be consecutive.  */
7898   while (count--)
7899     {
7900       if ((mask & (1 << base_reg++)) == 0)
7901         {
7902           inst.error = _("non-contiguous register range");
7903           return FAIL;
7904         }
7905     }
7906
7907   inst.instruction = tempinst | base_bits;
7908   return range;
7909 }
7910
7911 static long
7912 vfp_dp_reg_list (str)
7913      char **str;
7914 {
7915   long range = 0;
7916   int base_reg = 0;
7917   int new_base;
7918   int count = 0;
7919   long tempinst;
7920   unsigned long mask = 0;
7921   int warned = 0;
7922
7923   if (**str != '{')
7924     return FAIL;
7925
7926   (*str)++;
7927   skip_whitespace (*str);
7928
7929   tempinst = inst.instruction;
7930
7931   do
7932     {
7933       inst.instruction = 0;
7934
7935       if ((new_base = vfp_dp_reg_required_here (str, VFP_REG_Dd)) == FAIL)
7936         return FAIL;
7937
7938       if (count == 0 || base_reg > new_base)
7939         {
7940           base_reg = new_base;
7941           range = inst.instruction;
7942         }
7943
7944       if (mask & (1 << new_base))
7945         {
7946           inst.error = _("invalid register list");
7947           return FAIL;
7948         }
7949
7950       if ((mask >> new_base) != 0 && ! warned)
7951         {
7952           as_tsktsk (_("register list not in ascending order"));
7953           warned = 1;
7954         }
7955
7956       mask |= 1 << new_base;
7957       count++;
7958
7959       skip_whitespace (*str);
7960
7961       if (**str == '-') /* We have the start of a range expression */
7962         {
7963           int high_range;
7964
7965           (*str)++;
7966
7967           if ((high_range
7968                = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab))
7969               == FAIL)
7970             {
7971               inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
7972               return FAIL;
7973             }
7974
7975           if (high_range <= new_base)
7976             {
7977               inst.error = _("register range not in ascending order");
7978               return FAIL;
7979             }
7980
7981           for (new_base++; new_base <= high_range; new_base++)
7982             {
7983               if (mask & (1 << new_base))
7984                 {
7985                   inst.error = _("invalid register list");
7986                   return FAIL;
7987                 }
7988
7989               mask |= 1 << new_base;
7990               count++;
7991             }
7992         }
7993     }
7994   while (skip_past_comma (str) != FAIL);
7995
7996   if (**str != '}')
7997     {
7998       inst.error = _("invalid register list");
7999       return FAIL;
8000     }
8001
8002   (*str)++;
8003
8004   range |= 2 * count;
8005
8006   /* Sanity check -- should have raised a parse error above.  */
8007   if (count == 0 || count > 16)
8008     abort ();
8009
8010   /* Final test -- the registers must be consecutive.  */
8011   while (count--)
8012     {
8013       if ((mask & (1 << base_reg++)) == 0)
8014         {
8015           inst.error = _("non-contiguous register range");
8016           return FAIL;
8017         }
8018     }
8019
8020   inst.instruction = tempinst;
8021   return range;
8022 }
8023
8024 static void
8025 vfp_sp_ldstm (str, ldstm_type)
8026      char *str;
8027      enum vfp_ldstm_type ldstm_type;
8028 {
8029   long range;
8030
8031   skip_whitespace (str);
8032
8033   if (reg_required_here (&str, 16) == FAIL)
8034     return;
8035
8036   skip_whitespace (str);
8037
8038   if (*str == '!')
8039     {
8040       inst.instruction |= WRITE_BACK;
8041       str++;
8042     }
8043   else if (ldstm_type != VFP_LDSTMIA)
8044     {
8045       inst.error = _("this addressing mode requires base-register writeback");
8046       return;
8047     }
8048
8049   if (skip_past_comma (&str) == FAIL
8050       || (range = vfp_sp_reg_list (&str, VFP_REG_Sd)) == FAIL)
8051     {
8052       if (!inst.error)
8053         inst.error = BAD_ARGS;
8054       return;
8055     }
8056
8057   inst.instruction |= range;
8058   end_of_line (str);
8059 }
8060
8061 static void
8062 vfp_dp_ldstm (str, ldstm_type)
8063      char *str;
8064      enum vfp_ldstm_type ldstm_type;
8065 {
8066   long range;
8067
8068   skip_whitespace (str);
8069
8070   if (reg_required_here (&str, 16) == FAIL)
8071     return;
8072
8073   skip_whitespace (str);
8074
8075   if (*str == '!')
8076     {
8077       inst.instruction |= WRITE_BACK;
8078       str++;
8079     }
8080   else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
8081     {
8082       inst.error = _("this addressing mode requires base-register writeback");
8083       return;
8084     }
8085
8086   if (skip_past_comma (&str) == FAIL
8087       || (range = vfp_dp_reg_list (&str)) == FAIL)
8088     {
8089       if (!inst.error)
8090         inst.error = BAD_ARGS;
8091       return;
8092     }
8093
8094   if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
8095     range += 1;
8096
8097   inst.instruction |= range;
8098   end_of_line (str);
8099 }
8100
8101 static void
8102 do_vfp_sp_ldstmia (str)
8103      char *str;
8104 {
8105   vfp_sp_ldstm (str, VFP_LDSTMIA);
8106 }
8107
8108 static void
8109 do_vfp_sp_ldstmdb (str)
8110      char *str;
8111 {
8112   vfp_sp_ldstm (str, VFP_LDSTMDB);
8113 }
8114
8115 static void
8116 do_vfp_dp_ldstmia (str)
8117      char *str;
8118 {
8119   vfp_dp_ldstm (str, VFP_LDSTMIA);
8120 }
8121
8122 static void
8123 do_vfp_dp_ldstmdb (str)
8124      char *str;
8125 {
8126   vfp_dp_ldstm (str, VFP_LDSTMDB);
8127 }
8128
8129 static void
8130 do_vfp_xp_ldstmia (str)
8131      char *str;
8132 {
8133   vfp_dp_ldstm (str, VFP_LDSTMIAX);
8134 }
8135
8136 static void
8137 do_vfp_xp_ldstmdb (str)
8138      char *str;
8139 {
8140   vfp_dp_ldstm (str, VFP_LDSTMDBX);
8141 }
8142
8143 static void
8144 do_vfp_sp_compare_z (str)
8145      char *str;
8146 {
8147   skip_whitespace (str);
8148
8149   if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8150     {
8151       if (!inst.error)
8152         inst.error = BAD_ARGS;
8153       return;
8154     }
8155
8156   end_of_line (str);
8157   return;
8158 }
8159
8160 static void
8161 do_vfp_dp_compare_z (str)
8162      char *str;
8163 {
8164   skip_whitespace (str);
8165
8166   if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8167     {
8168       if (!inst.error)
8169         inst.error = BAD_ARGS;
8170       return;
8171     }
8172
8173   end_of_line (str);
8174   return;
8175 }
8176
8177 static void
8178 do_vfp_dp_sp_cvt (str)
8179      char *str;
8180 {
8181   skip_whitespace (str);
8182
8183   if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8184     return;
8185
8186   if (skip_past_comma (&str) == FAIL
8187       || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8188     {
8189       if (! inst.error)
8190         inst.error = BAD_ARGS;
8191       return;
8192     }
8193
8194   end_of_line (str);
8195   return;
8196 }
8197
8198 static void
8199 do_vfp_sp_dp_cvt (str)
8200      char *str;
8201 {
8202   skip_whitespace (str);
8203
8204   if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8205     return;
8206
8207   if (skip_past_comma (&str) == FAIL
8208       || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8209     {
8210       if (! inst.error)
8211         inst.error = BAD_ARGS;
8212       return;
8213     }
8214
8215   end_of_line (str);
8216   return;
8217 }
8218
8219 /* Thumb specific routines.  */
8220
8221 /* Parse and validate that a register is of the right form, this saves
8222    repeated checking of this information in many similar cases.
8223    Unlike the 32-bit case we do not insert the register into the opcode
8224    here, since the position is often unknown until the full instruction
8225    has been parsed.  */
8226
8227 static int
8228 thumb_reg (strp, hi_lo)
8229      char ** strp;
8230      int     hi_lo;
8231 {
8232   int reg;
8233
8234   if ((reg = reg_required_here (strp, -1)) == FAIL)
8235     return FAIL;
8236
8237   switch (hi_lo)
8238     {
8239     case THUMB_REG_LO:
8240       if (reg > 7)
8241         {
8242           inst.error = _("lo register required");
8243           return FAIL;
8244         }
8245       break;
8246
8247     case THUMB_REG_HI:
8248       if (reg < 8)
8249         {
8250           inst.error = _("hi register required");
8251           return FAIL;
8252         }
8253       break;
8254
8255     default:
8256       break;
8257     }
8258
8259   return reg;
8260 }
8261
8262 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
8263    was SUB.  */
8264
8265 static void
8266 thumb_add_sub (str, subtract)
8267      char * str;
8268      int    subtract;
8269 {
8270   int Rd, Rs, Rn = FAIL;
8271
8272   skip_whitespace (str);
8273
8274   if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8275       || skip_past_comma (&str) == FAIL)
8276     {
8277       if (! inst.error)
8278         inst.error = BAD_ARGS;
8279       return;
8280     }
8281
8282   if (is_immediate_prefix (*str))
8283     {
8284       Rs = Rd;
8285       str++;
8286       if (my_get_expression (&inst.reloc.exp, &str))
8287         return;
8288     }
8289   else
8290     {
8291       if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8292         return;
8293
8294       if (skip_past_comma (&str) == FAIL)
8295         {
8296           /* Two operand format, shuffle the registers
8297              and pretend there are 3.  */
8298           Rn = Rs;
8299           Rs = Rd;
8300         }
8301       else if (is_immediate_prefix (*str))
8302         {
8303           str++;
8304           if (my_get_expression (&inst.reloc.exp, &str))
8305             return;
8306         }
8307       else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8308         return;
8309     }
8310
8311   /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8312      for the latter case, EXPR contains the immediate that was found.  */
8313   if (Rn != FAIL)
8314     {
8315       /* All register format.  */
8316       if (Rd > 7 || Rs > 7 || Rn > 7)
8317         {
8318           if (Rs != Rd)
8319             {
8320               inst.error = _("dest and source1 must be the same register");
8321               return;
8322             }
8323
8324           /* Can't do this for SUB.  */
8325           if (subtract)
8326             {
8327               inst.error = _("subtract valid only on lo regs");
8328               return;
8329             }
8330
8331           inst.instruction = (T_OPCODE_ADD_HI
8332                               | (Rd > 7 ? THUMB_H1 : 0)
8333                               | (Rn > 7 ? THUMB_H2 : 0));
8334           inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
8335         }
8336       else
8337         {
8338           inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
8339           inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
8340         }
8341     }
8342   else
8343     {
8344       /* Immediate expression, now things start to get nasty.  */
8345
8346       /* First deal with HI regs, only very restricted cases allowed:
8347          Adjusting SP, and using PC or SP to get an address.  */
8348       if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
8349           || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
8350         {
8351           inst.error = _("invalid Hi register with immediate");
8352           return;
8353         }
8354
8355       if (inst.reloc.exp.X_op != O_constant)
8356         {
8357           /* Value isn't known yet, all we can do is store all the fragments
8358              we know about in the instruction and let the reloc hacking
8359              work it all out.  */
8360           inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
8361           inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
8362         }
8363       else
8364         {
8365           int offset = inst.reloc.exp.X_add_number;
8366
8367           if (subtract)
8368             offset = - offset;
8369
8370           if (offset < 0)
8371             {
8372               offset = - offset;
8373               subtract = 1;
8374
8375               /* Quick check, in case offset is MIN_INT.  */
8376               if (offset < 0)
8377                 {
8378                   inst.error = _("immediate value out of range");
8379                   return;
8380                 }
8381             }
8382           /* Note - you cannot convert a subtract of 0 into an
8383              add of 0 because the carry flag is set differently.  */
8384           else if (offset > 0)
8385             subtract = 0;
8386
8387           if (Rd == REG_SP)
8388             {
8389               if (offset & ~0x1fc)
8390                 {
8391                   inst.error = _("invalid immediate value for stack adjust");
8392                   return;
8393                 }
8394               inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
8395               inst.instruction |= offset >> 2;
8396             }
8397           else if (Rs == REG_PC || Rs == REG_SP)
8398             {
8399               if (subtract
8400                   || (offset & ~0x3fc))
8401                 {
8402                   inst.error = _("invalid immediate for address calculation");
8403                   return;
8404                 }
8405               inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
8406                                   : T_OPCODE_ADD_SP);
8407               inst.instruction |= (Rd << 8) | (offset >> 2);
8408             }
8409           else if (Rs == Rd)
8410             {
8411               if (offset & ~0xff)
8412                 {
8413                   inst.error = _("immediate value out of range");
8414                   return;
8415                 }
8416               inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
8417               inst.instruction |= (Rd << 8) | offset;
8418             }
8419           else
8420             {
8421               if (offset & ~0x7)
8422                 {
8423                   inst.error = _("immediate value out of range");
8424                   return;
8425                 }
8426               inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
8427               inst.instruction |= Rd | (Rs << 3) | (offset << 6);
8428             }
8429         }
8430     }
8431
8432   end_of_line (str);
8433 }
8434
8435 static void
8436 thumb_shift (str, shift)
8437      char * str;
8438      int    shift;
8439 {
8440   int Rd, Rs, Rn = FAIL;
8441
8442   skip_whitespace (str);
8443
8444   if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8445       || skip_past_comma (&str) == FAIL)
8446     {
8447       if (! inst.error)
8448         inst.error = BAD_ARGS;
8449       return;
8450     }
8451
8452   if (is_immediate_prefix (*str))
8453     {
8454       /* Two operand immediate format, set Rs to Rd.  */
8455       Rs = Rd;
8456       str ++;
8457       if (my_get_expression (&inst.reloc.exp, &str))
8458         return;
8459     }
8460   else
8461     {
8462       if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8463         return;
8464
8465       if (skip_past_comma (&str) == FAIL)
8466         {
8467           /* Two operand format, shuffle the registers
8468              and pretend there are 3.  */
8469           Rn = Rs;
8470           Rs = Rd;
8471         }
8472       else if (is_immediate_prefix (*str))
8473         {
8474           str++;
8475           if (my_get_expression (&inst.reloc.exp, &str))
8476             return;
8477         }
8478       else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8479         return;
8480     }
8481
8482   /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
8483      for the latter case, EXPR contains the immediate that was found.  */
8484
8485   if (Rn != FAIL)
8486     {
8487       if (Rs != Rd)
8488         {
8489           inst.error = _("source1 and dest must be same register");
8490           return;
8491         }
8492
8493       switch (shift)
8494         {
8495         case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
8496         case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
8497         case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
8498         }
8499
8500       inst.instruction |= Rd | (Rn << 3);
8501     }
8502   else
8503     {
8504       switch (shift)
8505         {
8506         case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
8507         case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
8508         case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
8509         }
8510
8511       if (inst.reloc.exp.X_op != O_constant)
8512         {
8513           /* Value isn't known yet, create a dummy reloc and let reloc
8514              hacking fix it up.  */
8515           inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
8516         }
8517       else
8518         {
8519           unsigned shift_value = inst.reloc.exp.X_add_number;
8520
8521           if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
8522             {
8523               inst.error = _("invalid immediate for shift");
8524               return;
8525             }
8526
8527           /* Shifts of zero are handled by converting to LSL.  */
8528           if (shift_value == 0)
8529             inst.instruction = T_OPCODE_LSL_I;
8530
8531           /* Shifts of 32 are encoded as a shift of zero.  */
8532           if (shift_value == 32)
8533             shift_value = 0;
8534
8535           inst.instruction |= shift_value << 6;
8536         }
8537
8538       inst.instruction |= Rd | (Rs << 3);
8539     }
8540
8541   end_of_line (str);
8542 }
8543
8544 static void
8545 thumb_mov_compare (str, move)
8546      char * str;
8547      int    move;
8548 {
8549   int Rd, Rs = FAIL;
8550
8551   skip_whitespace (str);
8552
8553   if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
8554       || skip_past_comma (&str) == FAIL)
8555     {
8556       if (! inst.error)
8557         inst.error = BAD_ARGS;
8558       return;
8559     }
8560
8561   if (is_immediate_prefix (*str))
8562     {
8563       str++;
8564       if (my_get_expression (&inst.reloc.exp, &str))
8565         return;
8566     }
8567   else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8568     return;
8569
8570   if (Rs != FAIL)
8571     {
8572       if (Rs < 8 && Rd < 8)
8573         {
8574           if (move == THUMB_MOVE)
8575             /* A move of two lowregs is encoded as ADD Rd, Rs, #0
8576                since a MOV instruction produces unpredictable results.  */
8577             inst.instruction = T_OPCODE_ADD_I3;
8578           else
8579             inst.instruction = T_OPCODE_CMP_LR;
8580           inst.instruction |= Rd | (Rs << 3);
8581         }
8582       else
8583         {
8584           if (move == THUMB_MOVE)
8585             inst.instruction = T_OPCODE_MOV_HR;
8586           else
8587             inst.instruction = T_OPCODE_CMP_HR;
8588
8589           if (Rd > 7)
8590             inst.instruction |= THUMB_H1;
8591
8592           if (Rs > 7)
8593             inst.instruction |= THUMB_H2;
8594
8595           inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
8596         }
8597     }
8598   else
8599     {
8600       if (Rd > 7)
8601         {
8602           inst.error = _("only lo regs allowed with immediate");
8603           return;
8604         }
8605
8606       if (move == THUMB_MOVE)
8607         inst.instruction = T_OPCODE_MOV_I8;
8608       else
8609         inst.instruction = T_OPCODE_CMP_I8;
8610
8611       inst.instruction |= Rd << 8;
8612
8613       if (inst.reloc.exp.X_op != O_constant)
8614         inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
8615       else
8616         {
8617           unsigned value = inst.reloc.exp.X_add_number;
8618
8619           if (value > 255)
8620             {
8621               inst.error = _("invalid immediate");
8622               return;
8623             }
8624
8625           inst.instruction |= value;
8626         }
8627     }
8628
8629   end_of_line (str);
8630 }
8631
8632 static void
8633 thumb_load_store (str, load_store, size)
8634      char * str;
8635      int    load_store;
8636      int    size;
8637 {
8638   int Rd, Rb, Ro = FAIL;
8639
8640   skip_whitespace (str);
8641
8642   if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
8643       || skip_past_comma (&str) == FAIL)
8644     {
8645       if (! inst.error)
8646         inst.error = BAD_ARGS;
8647       return;
8648     }
8649
8650   if (*str == '[')
8651     {
8652       str++;
8653       if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
8654         return;
8655
8656       if (skip_past_comma (&str) != FAIL)
8657         {
8658           if (is_immediate_prefix (*str))
8659             {
8660               str++;
8661               if (my_get_expression (&inst.reloc.exp, &str))
8662                 return;
8663             }
8664           else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
8665             return;
8666         }
8667       else
8668         {
8669           inst.reloc.exp.X_op = O_constant;
8670           inst.reloc.exp.X_add_number = 0;
8671         }
8672
8673       if (*str != ']')
8674         {
8675           inst.error = _("expected ']'");
8676           return;
8677         }
8678       str++;
8679     }
8680   else if (*str == '=')
8681     {
8682       if (load_store != THUMB_LOAD)
8683         {
8684           inst.error = _("invalid pseudo operation");
8685           return;
8686         }
8687
8688       /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op.  */
8689       str++;
8690
8691       skip_whitespace (str);
8692
8693       if (my_get_expression (& inst.reloc.exp, & str))
8694         return;
8695
8696       end_of_line (str);
8697
8698       if (   inst.reloc.exp.X_op != O_constant
8699           && inst.reloc.exp.X_op != O_symbol)
8700         {
8701           inst.error = "Constant expression expected";
8702           return;
8703         }
8704
8705       if (inst.reloc.exp.X_op == O_constant
8706           && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
8707         {
8708           /* This can be done with a mov instruction.  */
8709
8710           inst.instruction  = T_OPCODE_MOV_I8 | (Rd << 8);
8711           inst.instruction |= inst.reloc.exp.X_add_number;
8712           return;
8713         }
8714
8715       /* Insert into literal pool.  */
8716       if (add_to_lit_pool () == FAIL)
8717         {
8718           if (!inst.error)
8719             inst.error = "literal pool insertion failed";
8720           return;
8721         }
8722
8723       inst.reloc.type   = BFD_RELOC_ARM_THUMB_OFFSET;
8724       inst.reloc.pc_rel = 1;
8725       inst.instruction  = T_OPCODE_LDR_PC | (Rd << 8);
8726       /* Adjust ARM pipeline offset to Thumb.  */
8727       inst.reloc.exp.X_add_number += 4;
8728
8729       return;
8730     }
8731   else
8732     {
8733       if (my_get_expression (&inst.reloc.exp, &str))
8734         return;
8735
8736       inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
8737       inst.reloc.pc_rel = 1;
8738       inst.reloc.exp.X_add_number -= 4; /* Pipeline offset.  */
8739       inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8740       end_of_line (str);
8741       return;
8742     }
8743
8744   if (Rb == REG_PC || Rb == REG_SP)
8745     {
8746       if (size != THUMB_WORD)
8747         {
8748           inst.error = _("byte or halfword not valid for base register");
8749           return;
8750         }
8751       else if (Rb == REG_PC && load_store != THUMB_LOAD)
8752         {
8753           inst.error = _("r15 based store not allowed");
8754           return;
8755         }
8756       else if (Ro != FAIL)
8757         {
8758           inst.error = _("invalid base register for register offset");
8759           return;
8760         }
8761
8762       if (Rb == REG_PC)
8763         inst.instruction = T_OPCODE_LDR_PC;
8764       else if (load_store == THUMB_LOAD)
8765         inst.instruction = T_OPCODE_LDR_SP;
8766       else
8767         inst.instruction = T_OPCODE_STR_SP;
8768
8769       inst.instruction |= Rd << 8;
8770       if (inst.reloc.exp.X_op == O_constant)
8771         {
8772           unsigned offset = inst.reloc.exp.X_add_number;
8773
8774           if (offset & ~0x3fc)
8775             {
8776               inst.error = _("invalid offset");
8777               return;
8778             }
8779
8780           inst.instruction |= offset >> 2;
8781         }
8782       else
8783         inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8784     }
8785   else if (Rb > 7)
8786     {
8787       inst.error = _("invalid base register in load/store");
8788       return;
8789     }
8790   else if (Ro == FAIL)
8791     {
8792       /* Immediate offset.  */
8793       if (size == THUMB_WORD)
8794         inst.instruction = (load_store == THUMB_LOAD
8795                             ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
8796       else if (size == THUMB_HALFWORD)
8797         inst.instruction = (load_store == THUMB_LOAD
8798                             ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
8799       else
8800         inst.instruction = (load_store == THUMB_LOAD
8801                             ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
8802
8803       inst.instruction |= Rd | (Rb << 3);
8804
8805       if (inst.reloc.exp.X_op == O_constant)
8806         {
8807           unsigned offset = inst.reloc.exp.X_add_number;
8808
8809           if (offset & ~(0x1f << size))
8810             {
8811               inst.error = _("invalid offset");
8812               return;
8813             }
8814           inst.instruction |= (offset >> size) << 6;
8815         }
8816       else
8817         inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
8818     }
8819   else
8820     {
8821       /* Register offset.  */
8822       if (size == THUMB_WORD)
8823         inst.instruction = (load_store == THUMB_LOAD
8824                             ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
8825       else if (size == THUMB_HALFWORD)
8826         inst.instruction = (load_store == THUMB_LOAD
8827                             ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
8828       else
8829         inst.instruction = (load_store == THUMB_LOAD
8830                             ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
8831
8832       inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
8833     }
8834
8835   end_of_line (str);
8836 }
8837
8838 /* A register must be given at this point.
8839
8840    Shift is the place to put it in inst.instruction.
8841
8842    Restores input start point on err.
8843    Returns the reg#, or FAIL.  */
8844
8845 static int
8846 mav_reg_required_here (str, shift, regtype)
8847      char ** str;
8848      int shift;
8849      enum arm_reg_type regtype;
8850 {
8851   int   reg;
8852   char *start = *str;
8853
8854   if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
8855     {
8856       if (shift >= 0)
8857         inst.instruction |= reg << shift;
8858
8859       return reg;
8860     }
8861
8862   /* Restore the start point.  */
8863   *str = start;
8864
8865   /* In the few cases where we might be able to accept something else
8866      this error can be overridden.  */
8867   inst.error = _(all_reg_maps[regtype].expected);
8868
8869   return FAIL;
8870 }
8871
8872 /* Cirrus Maverick Instructions.  */
8873
8874 /* Wrapper functions.  */
8875
8876 static void
8877 do_mav_binops_1a (str)
8878      char * str;
8879 {
8880   do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
8881 }
8882
8883 static void
8884 do_mav_binops_1b (str)
8885      char * str;
8886 {
8887   do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
8888 }
8889
8890 static void
8891 do_mav_binops_1c (str)
8892      char * str;
8893 {
8894   do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
8895 }
8896
8897 static void
8898 do_mav_binops_1d (str)
8899      char * str;
8900 {
8901   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
8902 }
8903
8904 static void
8905 do_mav_binops_1e (str)
8906      char * str;
8907 {
8908   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
8909 }
8910
8911 static void
8912 do_mav_binops_1f (str)
8913      char * str;
8914 {
8915   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
8916 }
8917
8918 static void
8919 do_mav_binops_1g (str)
8920      char * str;
8921 {
8922   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
8923 }
8924
8925 static void
8926 do_mav_binops_1h (str)
8927      char * str;
8928 {
8929   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
8930 }
8931
8932 static void
8933 do_mav_binops_1i (str)
8934      char * str;
8935 {
8936   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
8937 }
8938
8939 static void
8940 do_mav_binops_1j (str)
8941      char * str;
8942 {
8943   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
8944 }
8945
8946 static void
8947 do_mav_binops_1k (str)
8948      char * str;
8949 {
8950   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
8951 }
8952
8953 static void
8954 do_mav_binops_1l (str)
8955      char * str;
8956 {
8957   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
8958 }
8959
8960 static void
8961 do_mav_binops_1m (str)
8962      char * str;
8963 {
8964   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
8965 }
8966
8967 static void
8968 do_mav_binops_1n (str)
8969      char * str;
8970 {
8971   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
8972 }
8973
8974 static void
8975 do_mav_binops_1o (str)
8976      char * str;
8977 {
8978   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
8979 }
8980
8981 static void
8982 do_mav_binops_2a (str)
8983      char * str;
8984 {
8985   do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
8986 }
8987
8988 static void
8989 do_mav_binops_2b (str)
8990      char * str;
8991 {
8992   do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
8993 }
8994
8995 static void
8996 do_mav_binops_2c (str)
8997      char * str;
8998 {
8999   do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
9000 }
9001
9002 static void
9003 do_mav_binops_3a (str)
9004      char * str;
9005 {
9006   do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
9007 }
9008
9009 static void
9010 do_mav_binops_3b (str)
9011      char * str;
9012 {
9013   do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
9014 }
9015
9016 static void
9017 do_mav_binops_3c (str)
9018      char * str;
9019 {
9020   do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
9021 }
9022
9023 static void
9024 do_mav_binops_3d (str)
9025      char * str;
9026 {
9027   do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
9028 }
9029
9030 static void
9031 do_mav_triple_4a (str)
9032      char * str;
9033 {
9034   do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
9035 }
9036
9037 static void
9038 do_mav_triple_4b (str)
9039      char * str;
9040 {
9041   do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
9042 }
9043
9044 static void
9045 do_mav_triple_5a (str)
9046      char * str;
9047 {
9048   do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
9049 }
9050
9051 static void
9052 do_mav_triple_5b (str)
9053      char * str;
9054 {
9055   do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
9056 }
9057
9058 static void
9059 do_mav_triple_5c (str)
9060      char * str;
9061 {
9062   do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
9063 }
9064
9065 static void
9066 do_mav_triple_5d (str)
9067      char * str;
9068 {
9069   do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
9070 }
9071
9072 static void
9073 do_mav_triple_5e (str)
9074      char * str;
9075 {
9076   do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
9077 }
9078
9079 static void
9080 do_mav_triple_5f (str)
9081      char * str;
9082 {
9083   do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
9084 }
9085
9086 static void
9087 do_mav_triple_5g (str)
9088      char * str;
9089 {
9090   do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
9091 }
9092
9093 static void
9094 do_mav_triple_5h (str)
9095      char * str;
9096 {
9097   do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
9098 }
9099
9100 static void
9101 do_mav_quad_6a (str)
9102      char * str;
9103 {
9104   do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
9105              REG_TYPE_MVFX);
9106 }
9107
9108 static void
9109 do_mav_quad_6b (str)
9110      char * str;
9111 {
9112   do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
9113              REG_TYPE_MVFX);
9114 }
9115
9116 /* cfmvsc32<cond> DSPSC,MVFX[15:0].  */
9117 static void
9118 do_mav_dspsc_1 (str)
9119      char * str;
9120 {
9121   skip_whitespace (str);
9122
9123   /* cfmvsc32.  */
9124   if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
9125       || skip_past_comma (&str) == FAIL
9126       || mav_reg_required_here (&str, 16, REG_TYPE_MVFX) == FAIL)
9127     {
9128       if (!inst.error)
9129         inst.error = BAD_ARGS;
9130
9131       return;
9132     }
9133
9134   end_of_line (str);
9135 }
9136
9137 /* cfmv32sc<cond> MVFX[15:0],DSPSC.  */
9138 static void
9139 do_mav_dspsc_2 (str)
9140      char * str;
9141 {
9142   skip_whitespace (str);
9143
9144   /* cfmv32sc.  */
9145   if (mav_reg_required_here (&str, 0, REG_TYPE_MVFX) == FAIL
9146       || skip_past_comma (&str) == FAIL
9147       || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
9148     {
9149       if (!inst.error)
9150         inst.error = BAD_ARGS;
9151
9152       return;
9153     }
9154
9155   end_of_line (str);
9156 }
9157
9158 static void
9159 do_mav_shift_1 (str)
9160      char * str;
9161 {
9162   do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
9163 }
9164
9165 static void
9166 do_mav_shift_2 (str)
9167      char * str;
9168 {
9169   do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
9170 }
9171
9172 static void
9173 do_mav_ldst_1 (str)
9174      char * str;
9175 {
9176   do_mav_ldst (str, REG_TYPE_MVF);
9177 }
9178
9179 static void
9180 do_mav_ldst_2 (str)
9181      char * str;
9182 {
9183   do_mav_ldst (str, REG_TYPE_MVD);
9184 }
9185
9186 static void
9187 do_mav_ldst_3 (str)
9188      char * str;
9189 {
9190   do_mav_ldst (str, REG_TYPE_MVFX);
9191 }
9192
9193 static void
9194 do_mav_ldst_4 (str)
9195      char * str;
9196 {
9197   do_mav_ldst (str, REG_TYPE_MVDX);
9198 }
9199
9200 /* Isnsn like "foo X,Y".  */
9201
9202 static void
9203 do_mav_binops (str, mode, reg0, reg1)
9204      char * str;
9205      int mode;
9206      enum arm_reg_type reg0;
9207      enum arm_reg_type reg1;
9208 {
9209   int shift0, shift1;
9210
9211   shift0 = mode & 0xff;
9212   shift1 = (mode >> 8) & 0xff;
9213
9214   skip_whitespace (str);
9215
9216   if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9217       || skip_past_comma (&str) == FAIL
9218       || mav_reg_required_here (&str, shift1, reg1) == FAIL)
9219     {
9220       if (!inst.error)
9221         inst.error = BAD_ARGS;
9222     }
9223   else
9224     end_of_line (str);
9225 }
9226
9227 /* Isnsn like "foo X,Y,Z".  */
9228
9229 static void
9230 do_mav_triple (str, mode, reg0, reg1, reg2)
9231      char * str;
9232      int mode;
9233      enum arm_reg_type reg0;
9234      enum arm_reg_type reg1;
9235      enum arm_reg_type reg2;
9236 {
9237   int shift0, shift1, shift2;
9238
9239   shift0 = mode & 0xff;
9240   shift1 = (mode >> 8) & 0xff;
9241   shift2 = (mode >> 16) & 0xff;
9242
9243   skip_whitespace (str);
9244
9245   if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9246       || skip_past_comma (&str) == FAIL
9247       || mav_reg_required_here (&str, shift1, reg1) == FAIL
9248       || skip_past_comma (&str) == FAIL
9249       || mav_reg_required_here (&str, shift2, reg2) == FAIL)
9250     {
9251       if (!inst.error)
9252         inst.error = BAD_ARGS;
9253     }
9254   else
9255     end_of_line (str);
9256 }
9257
9258 /* Isnsn like "foo W,X,Y,Z".
9259     where W=MVAX[0:3] and X,Y,Z=MVFX[0:15].  */
9260
9261 static void
9262 do_mav_quad (str, mode, reg0, reg1, reg2, reg3)
9263      char * str;
9264      int mode;
9265      enum arm_reg_type reg0;
9266      enum arm_reg_type reg1;
9267      enum arm_reg_type reg2;
9268      enum arm_reg_type reg3;
9269 {
9270   int shift0, shift1, shift2, shift3;
9271
9272   shift0= mode & 0xff;
9273   shift1 = (mode >> 8) & 0xff;
9274   shift2 = (mode >> 16) & 0xff;
9275   shift3 = (mode >> 24) & 0xff;
9276
9277   skip_whitespace (str);
9278
9279   if (mav_reg_required_here (&str, shift0, reg0) == FAIL
9280       || skip_past_comma (&str) == FAIL
9281       || mav_reg_required_here (&str, shift1, reg1) == FAIL
9282       || skip_past_comma (&str) == FAIL
9283       || mav_reg_required_here (&str, shift2, reg2) == FAIL
9284       || skip_past_comma (&str) == FAIL
9285       || mav_reg_required_here (&str, shift3, reg3) == FAIL)
9286     {
9287       if (!inst.error)
9288         inst.error = BAD_ARGS;
9289     }
9290   else
9291     end_of_line (str);
9292 }
9293
9294 /* Maverick shift immediate instructions.
9295    cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
9296    cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0].  */
9297
9298 static void
9299 do_mav_shift (str, reg0, reg1)
9300      char * str;
9301      enum arm_reg_type reg0;
9302      enum arm_reg_type reg1;
9303 {
9304   int error;
9305   int imm, neg = 0;
9306
9307   skip_whitespace (str);
9308
9309   error = 0;
9310
9311   if (mav_reg_required_here (&str, 12, reg0) == FAIL
9312       || skip_past_comma (&str) == FAIL
9313       || mav_reg_required_here (&str, 16, reg1) == FAIL
9314       || skip_past_comma  (&str) == FAIL)
9315     {
9316       if (!inst.error)
9317         inst.error = BAD_ARGS;
9318       return;
9319     }
9320
9321   /* Calculate the immediate operand.
9322      The operand is a 7bit signed number.  */
9323   skip_whitespace (str);
9324
9325   if (*str == '#')
9326     ++str;
9327
9328   if (!ISDIGIT (*str) && *str != '-')
9329     {
9330       inst.error = _("expecting immediate, 7bit operand");
9331       return;
9332     }
9333
9334   if (*str == '-')
9335     {
9336       neg = 1;
9337       ++str;
9338     }
9339
9340   for (imm = 0; *str && ISDIGIT (*str); ++str)
9341     imm = imm * 10 + *str - '0';
9342
9343   if (imm > 64)
9344     {
9345       inst.error = _("immediate out of range");
9346       return;
9347     }
9348
9349   /* Make negative imm's into 7bit signed numbers.  */
9350   if (neg)
9351     {
9352       imm = -imm;
9353       imm &= 0x0000007f;
9354     }
9355
9356   /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
9357      Bits 5-7 of the insn should have bits 4-6 of the immediate.
9358      Bit 4 should be 0.  */
9359   imm = (imm & 0xf) | ((imm & 0x70) << 1);
9360
9361   inst.instruction |= imm;
9362   end_of_line (str);
9363 }
9364
9365 static int
9366 mav_parse_offset (str, negative)
9367      char ** str;
9368      int *negative;
9369 {
9370   char * p = *str;
9371   int offset;
9372
9373   *negative = 0;
9374
9375   skip_whitespace (p);
9376
9377   if (*p == '#')
9378     ++p;
9379
9380   if (*p == '-')
9381     {
9382       *negative = 1;
9383       ++p;
9384     }
9385
9386   if (!ISDIGIT (*p))
9387     {
9388       inst.error = _("offset expected");
9389       return 0;
9390     }
9391
9392   for (offset = 0; *p && ISDIGIT (*p); ++p)
9393     offset = offset * 10 + *p - '0';
9394
9395   if (offset > 0xff)
9396     {
9397       inst.error = _("offset out of range");
9398       return 0;
9399     }
9400
9401   *str = p;
9402
9403   return *negative ? -offset : offset;
9404 }
9405
9406 /* Maverick load/store instructions.
9407   <insn><cond> CRd,[Rn,<offset>]{!}.
9408   <insn><cond> CRd,[Rn],<offset>.  */
9409
9410 static void
9411 do_mav_ldst (str, reg0)
9412      char * str;
9413      enum arm_reg_type reg0;
9414 {
9415   int offset, negative;
9416
9417   skip_whitespace (str);
9418
9419   if (mav_reg_required_here (&str, 12, reg0) == FAIL
9420       || skip_past_comma (&str) == FAIL
9421       || *str++ != '['
9422       || reg_required_here (&str, 16) == FAIL)
9423     goto fail_ldst;
9424
9425   if (skip_past_comma (&str) == SUCCESS)
9426     {
9427       /* You are here: "<offset>]{!}".  */
9428       inst.instruction |= PRE_INDEX;
9429
9430       offset = mav_parse_offset (&str, &negative);
9431
9432       if (inst.error)
9433         return;
9434
9435       if (*str++ != ']')
9436         {
9437           inst.error = _("missing ]");
9438           return;
9439         }
9440
9441       if (*str == '!')
9442         {
9443           inst.instruction |= WRITE_BACK;
9444           ++str;
9445         }
9446     }
9447   else
9448     {
9449       /* You are here: "], <offset>".  */
9450       if (*str++ != ']')
9451         {
9452           inst.error = _("missing ]");
9453           return;
9454         }
9455
9456       if (skip_past_comma (&str) == FAIL
9457           || (offset = mav_parse_offset (&str, &negative), inst.error))
9458         goto fail_ldst;
9459
9460       inst.instruction |= CP_T_WB; /* Post indexed, set bit W.  */
9461     }
9462
9463   if (negative)
9464     offset = -offset;
9465   else
9466     inst.instruction |= CP_T_UD; /* Postive, so set bit U.  */
9467
9468   inst.instruction |= offset >> 2;
9469   end_of_line (str);
9470   return;
9471
9472 fail_ldst:
9473   if (!inst.error)
9474      inst.error = BAD_ARGS;
9475   return;
9476 }
9477
9478 static void
9479 do_t_nop (str)
9480      char * str;
9481 {
9482   /* Do nothing.  */
9483   end_of_line (str);
9484   return;
9485 }
9486
9487 /* Handle the Format 4 instructions that do not have equivalents in other
9488    formats.  That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
9489    BIC and MVN.  */
9490
9491 static void
9492 do_t_arit (str)
9493      char * str;
9494 {
9495   int Rd, Rs, Rn;
9496
9497   skip_whitespace (str);
9498
9499   if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9500       || skip_past_comma (&str) == FAIL
9501       || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9502     {
9503       inst.error = BAD_ARGS;
9504       return;
9505     }
9506
9507   if (skip_past_comma (&str) != FAIL)
9508     {
9509       /* Three operand format not allowed for TST, CMN, NEG and MVN.
9510          (It isn't allowed for CMP either, but that isn't handled by this
9511          function.)  */
9512       if (inst.instruction == T_OPCODE_TST
9513           || inst.instruction == T_OPCODE_CMN
9514           || inst.instruction == T_OPCODE_NEG
9515           || inst.instruction == T_OPCODE_MVN)
9516         {
9517           inst.error = BAD_ARGS;
9518           return;
9519         }
9520
9521       if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9522         return;
9523
9524       if (Rs != Rd)
9525         {
9526           inst.error = _("dest and source1 must be the same register");
9527           return;
9528         }
9529       Rs = Rn;
9530     }
9531
9532   if (inst.instruction == T_OPCODE_MUL
9533       && Rs == Rd)
9534     as_tsktsk (_("Rs and Rd must be different in MUL"));
9535
9536   inst.instruction |= Rd | (Rs << 3);
9537   end_of_line (str);
9538 }
9539
9540 static void
9541 do_t_add (str)
9542      char * str;
9543 {
9544   thumb_add_sub (str, 0);
9545 }
9546
9547 static void
9548 do_t_asr (str)
9549      char * str;
9550 {
9551   thumb_shift (str, THUMB_ASR);
9552 }
9553
9554 static void
9555 do_t_branch9 (str)
9556      char * str;
9557 {
9558   if (my_get_expression (&inst.reloc.exp, &str))
9559     return;
9560   inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
9561   inst.reloc.pc_rel = 1;
9562   end_of_line (str);
9563 }
9564
9565 static void
9566 do_t_branch12 (str)
9567      char * str;
9568 {
9569   if (my_get_expression (&inst.reloc.exp, &str))
9570     return;
9571   inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
9572   inst.reloc.pc_rel = 1;
9573   end_of_line (str);
9574 }
9575
9576 /* Find the real, Thumb encoded start of a Thumb function.  */
9577
9578 static symbolS *
9579 find_real_start (symbolP)
9580      symbolS * symbolP;
9581 {
9582   char *       real_start;
9583   const char * name = S_GET_NAME (symbolP);
9584   symbolS *    new_target;
9585
9586   /* This definiton must agree with the one in gcc/config/arm/thumb.c.  */
9587 #define STUB_NAME ".real_start_of"
9588
9589   if (name == NULL)
9590     abort ();
9591
9592   /* Names that start with '.' are local labels, not function entry points.
9593      The compiler may generate BL instructions to these labels because it
9594      needs to perform a branch to a far away location.  */
9595   if (name[0] == '.')
9596     return symbolP;
9597
9598   real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
9599   sprintf (real_start, "%s%s", STUB_NAME, name);
9600
9601   new_target = symbol_find (real_start);
9602
9603   if (new_target == NULL)
9604     {
9605       as_warn ("Failed to find real start of function: %s\n", name);
9606       new_target = symbolP;
9607     }
9608
9609   free (real_start);
9610
9611   return new_target;
9612 }
9613
9614 static void
9615 do_t_branch23 (str)
9616      char * str;
9617 {
9618   if (my_get_expression (& inst.reloc.exp, & str))
9619     return;
9620
9621   inst.reloc.type   = BFD_RELOC_THUMB_PCREL_BRANCH23;
9622   inst.reloc.pc_rel = 1;
9623   end_of_line (str);
9624
9625   /* If the destination of the branch is a defined symbol which does not have
9626      the THUMB_FUNC attribute, then we must be calling a function which has
9627      the (interfacearm) attribute.  We look for the Thumb entry point to that
9628      function and change the branch to refer to that function instead.  */
9629   if (   inst.reloc.exp.X_op == O_symbol
9630       && inst.reloc.exp.X_add_symbol != NULL
9631       && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
9632       && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
9633     inst.reloc.exp.X_add_symbol =
9634       find_real_start (inst.reloc.exp.X_add_symbol);
9635 }
9636
9637 static void
9638 do_t_bx (str)
9639      char * str;
9640 {
9641   int reg;
9642
9643   skip_whitespace (str);
9644
9645   if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9646     return;
9647
9648   /* This sets THUMB_H2 from the top bit of reg.  */
9649   inst.instruction |= reg << 3;
9650
9651   /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC.  The reloc
9652      should cause the alignment to be checked once it is known.  This is
9653      because BX PC only works if the instruction is word aligned.  */
9654
9655   end_of_line (str);
9656 }
9657
9658 static void
9659 do_t_compare (str)
9660      char * str;
9661 {
9662   thumb_mov_compare (str, THUMB_COMPARE);
9663 }
9664
9665 static void
9666 do_t_ldmstm (str)
9667      char * str;
9668 {
9669   int Rb;
9670   long range;
9671
9672   skip_whitespace (str);
9673
9674   if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9675     return;
9676
9677   if (*str != '!')
9678     as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
9679   else
9680     str++;
9681
9682   if (skip_past_comma (&str) == FAIL
9683       || (range = reg_list (&str)) == FAIL)
9684     {
9685       if (! inst.error)
9686         inst.error = BAD_ARGS;
9687       return;
9688     }
9689
9690   if (inst.reloc.type != BFD_RELOC_NONE)
9691     {
9692       /* This really doesn't seem worth it.  */
9693       inst.reloc.type = BFD_RELOC_NONE;
9694       inst.error = _("expression too complex");
9695       return;
9696     }
9697
9698   if (range & ~0xff)
9699     {
9700       inst.error = _("only lo-regs valid in load/store multiple");
9701       return;
9702     }
9703
9704   inst.instruction |= (Rb << 8) | range;
9705   end_of_line (str);
9706 }
9707
9708 static void
9709 do_t_ldr (str)
9710      char * str;
9711 {
9712   thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
9713 }
9714
9715 static void
9716 do_t_ldrb (str)
9717      char * str;
9718 {
9719   thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
9720 }
9721
9722 static void
9723 do_t_ldrh (str)
9724      char * str;
9725 {
9726   thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
9727 }
9728
9729 static void
9730 do_t_lds (str)
9731      char * str;
9732 {
9733   int Rd, Rb, Ro;
9734
9735   skip_whitespace (str);
9736
9737   if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9738       || skip_past_comma (&str) == FAIL
9739       || *str++ != '['
9740       || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9741       || skip_past_comma (&str) == FAIL
9742       || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9743       || *str++ != ']')
9744     {
9745       if (! inst.error)
9746         inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
9747       return;
9748     }
9749
9750   inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
9751   end_of_line (str);
9752 }
9753
9754 static void
9755 do_t_lsl (str)
9756      char * str;
9757 {
9758   thumb_shift (str, THUMB_LSL);
9759 }
9760
9761 static void
9762 do_t_lsr (str)
9763      char * str;
9764 {
9765   thumb_shift (str, THUMB_LSR);
9766 }
9767
9768 static void
9769 do_t_mov (str)
9770      char * str;
9771 {
9772   thumb_mov_compare (str, THUMB_MOVE);
9773 }
9774
9775 static void
9776 do_t_push_pop (str)
9777      char * str;
9778 {
9779   long range;
9780
9781   skip_whitespace (str);
9782
9783   if ((range = reg_list (&str)) == FAIL)
9784     {
9785       if (! inst.error)
9786         inst.error = BAD_ARGS;
9787       return;
9788     }
9789
9790   if (inst.reloc.type != BFD_RELOC_NONE)
9791     {
9792       /* This really doesn't seem worth it.  */
9793       inst.reloc.type = BFD_RELOC_NONE;
9794       inst.error = _("expression too complex");
9795       return;
9796     }
9797
9798   if (range & ~0xff)
9799     {
9800       if ((inst.instruction == T_OPCODE_PUSH
9801            && (range & ~0xff) == 1 << REG_LR)
9802           || (inst.instruction == T_OPCODE_POP
9803               && (range & ~0xff) == 1 << REG_PC))
9804         {
9805           inst.instruction |= THUMB_PP_PC_LR;
9806           range &= 0xff;
9807         }
9808       else
9809         {
9810           inst.error = _("invalid register list to push/pop instruction");
9811           return;
9812         }
9813     }
9814
9815   inst.instruction |= range;
9816   end_of_line (str);
9817 }
9818
9819 static void
9820 do_t_str (str)
9821      char * str;
9822 {
9823   thumb_load_store (str, THUMB_STORE, THUMB_WORD);
9824 }
9825
9826 static void
9827 do_t_strb (str)
9828      char * str;
9829 {
9830   thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
9831 }
9832
9833 static void
9834 do_t_strh (str)
9835      char * str;
9836 {
9837   thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
9838 }
9839
9840 static void
9841 do_t_sub (str)
9842      char * str;
9843 {
9844   thumb_add_sub (str, 1);
9845 }
9846
9847 static void
9848 do_t_swi (str)
9849      char * str;
9850 {
9851   skip_whitespace (str);
9852
9853   if (my_get_expression (&inst.reloc.exp, &str))
9854     return;
9855
9856   inst.reloc.type = BFD_RELOC_ARM_SWI;
9857   end_of_line (str);
9858   return;
9859 }
9860
9861 static void
9862 do_t_adr (str)
9863      char * str;
9864 {
9865   int reg;
9866
9867   /* This is a pseudo-op of the form "adr rd, label" to be converted
9868      into a relative address of the form "add rd, pc, #label-.-4".  */
9869   skip_whitespace (str);
9870
9871   /* Store Rd in temporary location inside instruction.  */
9872   if ((reg = reg_required_here (&str, 4)) == FAIL
9873       || (reg > 7)  /* For Thumb reg must be r0..r7.  */
9874       || skip_past_comma (&str) == FAIL
9875       || my_get_expression (&inst.reloc.exp, &str))
9876     {
9877       if (!inst.error)
9878         inst.error = BAD_ARGS;
9879       return;
9880     }
9881
9882   inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9883   inst.reloc.exp.X_add_number -= 4; /* PC relative adjust.  */
9884   inst.reloc.pc_rel = 1;
9885   inst.instruction |= REG_PC; /* Rd is already placed into the instruction.  */
9886
9887   end_of_line (str);
9888 }
9889
9890 static void
9891 insert_reg (r, htab)
9892      const struct reg_entry *r;
9893      struct hash_control *htab;
9894 {
9895   int    len  = strlen (r->name) + 2;
9896   char * buf  = (char *) xmalloc (len);
9897   char * buf2 = (char *) xmalloc (len);
9898   int    i    = 0;
9899
9900 #ifdef REGISTER_PREFIX
9901   buf[i++] = REGISTER_PREFIX;
9902 #endif
9903
9904   strcpy (buf + i, r->name);
9905
9906   for (i = 0; buf[i]; i++)
9907     buf2[i] = TOUPPER (buf[i]);
9908
9909   buf2[i] = '\0';
9910
9911   hash_insert (htab, buf,  (PTR) r);
9912   hash_insert (htab, buf2, (PTR) r);
9913 }
9914
9915 static void
9916 build_reg_hsh (map)
9917      struct reg_map *map;
9918 {
9919   const struct reg_entry *r;
9920
9921   if ((map->htab = hash_new ()) == NULL)
9922     as_fatal (_("virtual memory exhausted"));
9923
9924   for (r = map->names; r->name != NULL; r++)
9925     insert_reg (r, map->htab);
9926 }
9927
9928 static void
9929 insert_reg_alias (str, regnum, htab)
9930      char *str;
9931      int regnum;
9932      struct hash_control *htab;
9933 {
9934   struct reg_entry *new =
9935     (struct reg_entry *) xmalloc (sizeof (struct reg_entry));
9936   char *name = xmalloc (strlen (str) + 1);
9937   strcpy (name, str);
9938
9939   new->name = name;
9940   new->number = regnum;
9941
9942   hash_insert (htab, name, (PTR) new);
9943 }
9944
9945 /* Look for the .req directive.  This is of the form:
9946
9947         newname .req existing_name
9948
9949    If we find one, or if it looks sufficiently like one that we want to
9950    handle any error here, return non-zero.  Otherwise return zero.  */
9951 static int
9952 create_register_alias (newname, p)
9953      char *newname;
9954      char *p;
9955 {
9956   char *q;
9957   char c;
9958
9959   q = p;
9960   skip_whitespace (q);
9961
9962   c = *p;
9963   *p = '\0';
9964
9965   if (*q && !strncmp (q, ".req ", 5))
9966     {
9967       char *copy_of_str;
9968       char *r;
9969
9970 #ifdef IGNORE_OPCODE_CASE
9971       newname = original_case_string;
9972 #endif
9973       copy_of_str = newname;
9974
9975       q += 4;
9976       skip_whitespace (q);
9977
9978       for (r = q; *r != '\0'; r++)
9979         if (*r == ' ')
9980           break;
9981
9982       if (r != q)
9983         {
9984           enum arm_reg_type new_type, old_type;
9985           int old_regno;
9986           char d = *r;
9987
9988           *r = '\0';
9989           old_type = arm_reg_parse_any (q);
9990           *r = d;
9991
9992           new_type = arm_reg_parse_any (newname);
9993
9994           if (new_type == REG_TYPE_MAX)
9995             {
9996               if (old_type != REG_TYPE_MAX)
9997                 {
9998                   old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
9999                   insert_reg_alias (newname, old_regno,
10000                                     all_reg_maps[old_type].htab);
10001                 }
10002               else
10003                 as_warn (_("register '%s' does not exist\n"), q);
10004             }
10005           else if (old_type == REG_TYPE_MAX)
10006             {
10007               as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
10008                        copy_of_str, q);
10009             }
10010           else
10011             {
10012               /* Do not warn about redefinitions to the same alias.  */
10013               if (new_type != old_type
10014                   || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
10015                       != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
10016                 as_warn (_("ignoring redefinition of register alias '%s'"),
10017                          copy_of_str);
10018
10019             }
10020         }
10021       else
10022         as_warn (_("ignoring incomplete .req pseuso op"));
10023
10024       *p = c;
10025       return 1;
10026     }
10027   *p = c;
10028   return 0;
10029 }
10030
10031 static void
10032 set_constant_flonums ()
10033 {
10034   int i;
10035
10036   for (i = 0; i < NUM_FLOAT_VALS; i++)
10037     if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
10038       abort ();
10039 }
10040
10041 /* Iterate over the base tables to create the instruction patterns.  */
10042 static void
10043 build_arm_ops_hsh ()
10044 {
10045   unsigned int i;
10046   unsigned int j;
10047   static struct obstack insn_obstack;
10048
10049   obstack_begin (&insn_obstack, 4000);
10050
10051   for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
10052     {
10053       const struct asm_opcode *insn = insns + i;
10054
10055       if (insn->cond_offset != 0)
10056         {
10057           /* Insn supports conditional execution.  Build the varaints
10058              and insert them in the hash table.  */
10059           for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
10060             {
10061               unsigned len = strlen (insn->template);
10062               struct asm_opcode *new;
10063               char *template;
10064
10065               new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
10066               /* All condition codes are two characters.  */
10067               template = obstack_alloc (&insn_obstack, len + 3);
10068
10069               strncpy (template, insn->template, insn->cond_offset);
10070               strcpy (template + insn->cond_offset, conds[j].template);
10071               if (len > insn->cond_offset)
10072                 strcpy (template + insn->cond_offset + 2,
10073                         insn->template + insn->cond_offset);
10074               new->template = template;
10075               new->cond_offset = 0;
10076               new->variant = insn->variant;
10077               new->parms = insn->parms;
10078               new->value = (insn->value & ~COND_MASK) | conds[j].value;
10079
10080               hash_insert (arm_ops_hsh, new->template, (PTR) new);
10081             }
10082         }
10083       /* Finally, insert the unconditional insn in the table directly;
10084          no need to build a copy.  */
10085       hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
10086     }
10087 }
10088
10089 #if defined OBJ_ELF || defined OBJ_COFF
10090
10091 #ifdef OBJ_ELF
10092 #define arm_Note Elf_External_Note
10093 #else
10094 typedef struct
10095 {
10096   unsigned char namesz[4];      /* Size of entry's owner string.  */
10097   unsigned char descsz[4];      /* Size of the note descriptor.  */
10098   unsigned char type[4];        /* Interpretation of the descriptor.  */
10099   char          name[1];        /* Start of the name+desc data.  */
10100 } arm_Note;
10101 #endif
10102
10103 /* The description is kept to a fix sized in order to make updating
10104    it and merging it easier.  */
10105 #define ARM_NOTE_DESCRIPTION_LENGTH     8
10106
10107 static void
10108 arm_add_note (name, description, type)
10109      const char * name;
10110      const char * description;
10111      unsigned int type;
10112 {
10113   arm_Note     note ATTRIBUTE_UNUSED;
10114   char *       p;
10115   unsigned int name_len;
10116
10117   name_len = (strlen (name) + 1 + 3) & ~3;
10118   
10119   p = frag_more (sizeof (note.namesz));
10120   md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
10121
10122   p = frag_more (sizeof (note.descsz));
10123   md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
10124
10125   p = frag_more (sizeof (note.type));
10126   md_number_to_chars (p, (valueT) type, sizeof (note.type));
10127
10128   p = frag_more (name_len);
10129   strcpy (p, name);
10130
10131   p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
10132   strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
10133   frag_align (2, 0, 0);
10134 }
10135 #endif
10136
10137 void
10138 md_begin ()
10139 {
10140   unsigned mach;
10141   unsigned int i;
10142
10143   if (   (arm_ops_hsh = hash_new ()) == NULL
10144       || (arm_tops_hsh = hash_new ()) == NULL
10145       || (arm_cond_hsh = hash_new ()) == NULL
10146       || (arm_shift_hsh = hash_new ()) == NULL
10147       || (arm_psr_hsh = hash_new ()) == NULL)
10148     as_fatal (_("virtual memory exhausted"));
10149
10150   build_arm_ops_hsh ();
10151   for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
10152     hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
10153   for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
10154     hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
10155   for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
10156     hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
10157   for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
10158     hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
10159
10160   for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
10161     build_reg_hsh (all_reg_maps + i);
10162
10163   set_constant_flonums ();
10164
10165   /* Set the cpu variant based on the command-line options.  We prefer
10166      -mcpu= over -march= if both are set (as for GCC); and we prefer
10167      -mfpu= over any other way of setting the floating point unit.
10168      Use of legacy options with new options are faulted.  */
10169   if (legacy_cpu != -1)
10170     {
10171       if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
10172         as_bad (_("use of old and new-style options to set CPU type"));
10173
10174       mcpu_cpu_opt = legacy_cpu;
10175     }
10176   else if (mcpu_cpu_opt == -1)
10177     mcpu_cpu_opt = march_cpu_opt;
10178
10179   if (legacy_fpu != -1)
10180     {
10181       if (mfpu_opt != -1)
10182         as_bad (_("use of old and new-style options to set FPU type"));
10183
10184       mfpu_opt = legacy_fpu;
10185     }
10186   else if (mfpu_opt == -1)
10187     {
10188       if (mcpu_fpu_opt != -1)
10189         mfpu_opt = mcpu_fpu_opt;
10190       else
10191         mfpu_opt = march_fpu_opt;
10192     }
10193
10194   if (mfpu_opt == -1)
10195     {
10196       if (mcpu_cpu_opt == -1)
10197         mfpu_opt = FPU_DEFAULT;
10198       else if (mcpu_cpu_opt & ARM_EXT_V5)
10199         mfpu_opt = FPU_ARCH_VFP_V2;
10200       else
10201         mfpu_opt = FPU_ARCH_FPA;
10202     }
10203
10204   if (mcpu_cpu_opt == -1)
10205     mcpu_cpu_opt = CPU_DEFAULT;
10206
10207   cpu_variant = mcpu_cpu_opt | mfpu_opt;
10208
10209 #if defined OBJ_COFF || defined OBJ_ELF
10210   {
10211     unsigned int flags = 0;
10212
10213     /* Set the flags in the private structure.  */
10214     if (uses_apcs_26)      flags |= F_APCS26;
10215     if (support_interwork) flags |= F_INTERWORK;
10216     if (uses_apcs_float)   flags |= F_APCS_FLOAT;
10217     if (pic_code)          flags |= F_PIC;
10218     if ((cpu_variant & FPU_ANY) == FPU_NONE
10219         || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only.  */
10220       flags |= F_SOFT_FLOAT;
10221     /* Using VFP conventions (even if soft-float).  */
10222     if (cpu_variant & FPU_VFP_EXT_NONE) flags |= F_VFP_FLOAT;
10223
10224 #if defined OBJ_ELF
10225     if (cpu_variant & ARM_CEXT_MAVERICK)
10226       {
10227         flags ^= F_SOFT_FLOAT;
10228         flags |= EF_ARM_MAVERICK_FLOAT;
10229       }
10230 #endif
10231
10232     bfd_set_private_flags (stdoutput, flags);
10233
10234     /* We have run out flags in the COFF header to encode the
10235        status of ATPCS support, so instead we create a dummy,
10236        empty, debug section called .arm.atpcs.  */
10237     if (atpcs)
10238       {
10239         asection * sec;
10240
10241         sec = bfd_make_section (stdoutput, ".arm.atpcs");
10242
10243         if (sec != NULL)
10244           {
10245             bfd_set_section_flags
10246               (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
10247             bfd_set_section_size (stdoutput, sec, 0);
10248             bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
10249           }
10250       }
10251   }
10252 #endif
10253
10254   /* Record the CPU type as well.  */
10255   switch (cpu_variant & ARM_CPU_MASK)
10256     {
10257     case ARM_2:
10258       mach = bfd_mach_arm_2;
10259       break;
10260
10261     case ARM_3:                 /* Also ARM_250.  */
10262       mach = bfd_mach_arm_2a;
10263       break;
10264
10265     case ARM_6:                 /* Also ARM_7.  */
10266       mach = bfd_mach_arm_3;
10267       break;
10268
10269     default:
10270       mach = bfd_mach_arm_unknown;
10271       break;
10272     }
10273
10274   /* Catch special cases.  */
10275   if (cpu_variant & ARM_CEXT_IWMMXT)
10276     mach = bfd_mach_arm_iWMMXt;
10277   else if (cpu_variant & ARM_CEXT_XSCALE)
10278     mach = bfd_mach_arm_XScale;
10279   else if (cpu_variant & ARM_CEXT_MAVERICK)
10280     mach = bfd_mach_arm_ep9312;
10281   else if (cpu_variant & ARM_EXT_V5E)
10282     mach = bfd_mach_arm_5TE;
10283   else if (cpu_variant & ARM_EXT_V5)
10284     {
10285       if (cpu_variant & ARM_EXT_V4T)
10286         mach = bfd_mach_arm_5T;
10287       else
10288         mach = bfd_mach_arm_5;
10289     }
10290   else if (cpu_variant & ARM_EXT_V4)
10291     {
10292       if (cpu_variant & ARM_EXT_V4T)
10293         mach = bfd_mach_arm_4T;
10294       else
10295         mach = bfd_mach_arm_4;
10296     }
10297   else if (cpu_variant & ARM_EXT_V3M)
10298     mach = bfd_mach_arm_3M;
10299
10300 #if 0 /* Suppressed - for now.  */
10301 #if defined (OBJ_ELF) || defined (OBJ_COFF)
10302
10303   /* Create a .note section to fully identify this arm binary.  */
10304
10305 #define NOTE_ARCH_STRING        "arch: "
10306
10307 #if defined OBJ_COFF && ! defined NT_VERSION
10308 #define NT_VERSION  1
10309 #define NT_ARCH     2
10310 #endif
10311   
10312   {
10313     segT current_seg = now_seg;
10314     subsegT current_subseg = now_subseg;
10315     asection * arm_arch;
10316     const char * arch_string;
10317
10318     arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
10319
10320 #ifdef OBJ_COFF
10321     bfd_set_section_flags (stdoutput, arm_arch,
10322                            SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
10323                            | SEC_HAS_CONTENTS);
10324 #endif
10325     arm_arch->output_section = arm_arch;
10326     subseg_set (arm_arch, 0);
10327
10328     switch (mach)
10329       {
10330       default:
10331       case bfd_mach_arm_unknown: arch_string = "unknown"; break;
10332       case bfd_mach_arm_2:       arch_string = "armv2"; break;
10333       case bfd_mach_arm_2a:      arch_string = "armv2a"; break;
10334       case bfd_mach_arm_3:       arch_string = "armv3"; break;
10335       case bfd_mach_arm_3M:      arch_string = "armv3M"; break;
10336       case bfd_mach_arm_4:       arch_string = "armv4"; break;
10337       case bfd_mach_arm_4T:      arch_string = "armv4t"; break;
10338       case bfd_mach_arm_5:       arch_string = "armv5"; break;
10339       case bfd_mach_arm_5T:      arch_string = "armv5t"; break;
10340       case bfd_mach_arm_5TE:     arch_string = "armv5te"; break;
10341       case bfd_mach_arm_XScale:  arch_string = "XScale"; break;
10342       case bfd_mach_arm_ep9312:  arch_string = "ep9312"; break;
10343       case bfd_mach_arm_iWMMXt:  arch_string = "iWMMXt"; break; 
10344       }
10345
10346     arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
10347
10348     subseg_set (current_seg, current_subseg);
10349   }
10350 #endif
10351 #endif /* Suppressed code.  */
10352   
10353   bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
10354 }
10355
10356 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
10357    for use in the a.out file, and stores them in the array pointed to by buf.
10358    This knows about the endian-ness of the target machine and does
10359    THE RIGHT THING, whatever it is.  Possible values for n are 1 (byte)
10360    2 (short) and 4 (long)  Floating numbers are put out as a series of
10361    LITTLENUMS (shorts, here at least).  */
10362
10363 void
10364 md_number_to_chars (buf, val, n)
10365      char * buf;
10366      valueT val;
10367      int    n;
10368 {
10369   if (target_big_endian)
10370     number_to_chars_bigendian (buf, val, n);
10371   else
10372     number_to_chars_littleendian (buf, val, n);
10373 }
10374
10375 static valueT
10376 md_chars_to_number (buf, n)
10377      char * buf;
10378      int    n;
10379 {
10380   valueT result = 0;
10381   unsigned char * where = (unsigned char *) buf;
10382
10383   if (target_big_endian)
10384     {
10385       while (n--)
10386         {
10387           result <<= 8;
10388           result |= (*where++ & 255);
10389         }
10390     }
10391   else
10392     {
10393       while (n--)
10394         {
10395           result <<= 8;
10396           result |= (where[n] & 255);
10397         }
10398     }
10399
10400   return result;
10401 }
10402
10403 /* Turn a string in input_line_pointer into a floating point constant
10404    of type TYPE, and store the appropriate bytes in *LITP.  The number
10405    of LITTLENUMS emitted is stored in *SIZEP.  An error message is
10406    returned, or NULL on OK.
10407
10408    Note that fp constants aren't represent in the normal way on the ARM.
10409    In big endian mode, things are as expected.  However, in little endian
10410    mode fp constants are big-endian word-wise, and little-endian byte-wise
10411    within the words.  For example, (double) 1.1 in big endian mode is
10412    the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
10413    the byte sequence 99 99 f1 3f 9a 99 99 99.
10414
10415    ??? The format of 12 byte floats is uncertain according to gcc's arm.h.  */
10416
10417 char *
10418 md_atof (type, litP, sizeP)
10419      char   type;
10420      char * litP;
10421      int *  sizeP;
10422 {
10423   int prec;
10424   LITTLENUM_TYPE words[MAX_LITTLENUMS];
10425   char *t;
10426   int i;
10427
10428   switch (type)
10429     {
10430     case 'f':
10431     case 'F':
10432     case 's':
10433     case 'S':
10434       prec = 2;
10435       break;
10436
10437     case 'd':
10438     case 'D':
10439     case 'r':
10440     case 'R':
10441       prec = 4;
10442       break;
10443
10444     case 'x':
10445     case 'X':
10446       prec = 6;
10447       break;
10448
10449     case 'p':
10450     case 'P':
10451       prec = 6;
10452       break;
10453
10454     default:
10455       *sizeP = 0;
10456       return _("bad call to MD_ATOF()");
10457     }
10458
10459   t = atof_ieee (input_line_pointer, type, words);
10460   if (t)
10461     input_line_pointer = t;
10462   *sizeP = prec * 2;
10463
10464   if (target_big_endian)
10465     {
10466       for (i = 0; i < prec; i++)
10467         {
10468           md_number_to_chars (litP, (valueT) words[i], 2);
10469           litP += 2;
10470         }
10471     }
10472   else
10473     {
10474       if (cpu_variant & FPU_ARCH_VFP)
10475         for (i = prec - 1; i >= 0; i--)
10476           {
10477             md_number_to_chars (litP, (valueT) words[i], 2);
10478             litP += 2;
10479           }
10480       else
10481         /* For a 4 byte float the order of elements in `words' is 1 0.
10482            For an 8 byte float the order is 1 0 3 2.  */
10483         for (i = 0; i < prec; i += 2)
10484           {
10485             md_number_to_chars (litP, (valueT) words[i + 1], 2);
10486             md_number_to_chars (litP + 2, (valueT) words[i], 2);
10487             litP += 4;
10488           }
10489     }
10490
10491   return 0;
10492 }
10493
10494 /* The knowledge of the PC's pipeline offset is built into the insns
10495    themselves.  */
10496
10497 long
10498 md_pcrel_from (fixP)
10499      fixS * fixP;
10500 {
10501   if (fixP->fx_addsy
10502       && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
10503       && fixP->fx_subsy == NULL)
10504     return 0;
10505
10506   if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
10507     {
10508       /* PC relative addressing on the Thumb is slightly odd
10509          as the bottom two bits of the PC are forced to zero
10510          for the calculation.  */
10511       return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
10512     }
10513
10514 #ifdef TE_WINCE
10515   /* The pattern was adjusted to accomodate CE's off-by-one fixups,
10516      so we un-adjust here to compensate for the accomodation.  */
10517   return fixP->fx_where + fixP->fx_frag->fr_address + 8;
10518 #else
10519   return fixP->fx_where + fixP->fx_frag->fr_address;
10520 #endif
10521 }
10522
10523 /* Round up a section size to the appropriate boundary.  */
10524
10525 valueT
10526 md_section_align (segment, size)
10527      segT   segment ATTRIBUTE_UNUSED;
10528      valueT size;
10529 {
10530 #ifdef OBJ_ELF
10531   return size;
10532 #else
10533   /* Round all sects to multiple of 4.  */
10534   return (size + 3) & ~3;
10535 #endif
10536 }
10537
10538 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
10539    Otherwise we have no need to default values of symbols.  */
10540
10541 symbolS *
10542 md_undefined_symbol (name)
10543      char * name ATTRIBUTE_UNUSED;
10544 {
10545 #ifdef OBJ_ELF
10546   if (name[0] == '_' && name[1] == 'G'
10547       && streq (name, GLOBAL_OFFSET_TABLE_NAME))
10548     {
10549       if (!GOT_symbol)
10550         {
10551           if (symbol_find (name))
10552             as_bad ("GOT already in the symbol table");
10553
10554           GOT_symbol = symbol_new (name, undefined_section,
10555                                    (valueT) 0, & zero_address_frag);
10556         }
10557
10558       return GOT_symbol;
10559     }
10560 #endif
10561
10562   return 0;
10563 }
10564
10565 /* arm_reg_parse () := if it looks like a register, return its token and
10566    advance the pointer.  */
10567
10568 static int
10569 arm_reg_parse (ccp, htab)
10570      register char ** ccp;
10571      struct hash_control *htab;
10572 {
10573   char * start = * ccp;
10574   char   c;
10575   char * p;
10576   struct reg_entry * reg;
10577
10578 #ifdef REGISTER_PREFIX
10579   if (*start != REGISTER_PREFIX)
10580     return FAIL;
10581   p = start + 1;
10582 #else
10583   p = start;
10584 #ifdef OPTIONAL_REGISTER_PREFIX
10585   if (*p == OPTIONAL_REGISTER_PREFIX)
10586     p++, start++;
10587 #endif
10588 #endif
10589   if (!ISALPHA (*p) || !is_name_beginner (*p))
10590     return FAIL;
10591
10592   c = *p++;
10593   while (ISALPHA (c) || ISDIGIT (c) || c == '_')
10594     c = *p++;
10595
10596   *--p = 0;
10597   reg = (struct reg_entry *) hash_find (htab, start);
10598   *p = c;
10599
10600   if (reg)
10601     {
10602       *ccp = p;
10603       return reg->number;
10604     }
10605
10606   return FAIL;
10607 }
10608
10609 /* Search for the following register name in each of the possible reg name
10610    tables.  Return the classification if found, or REG_TYPE_MAX if not
10611    present.  */
10612 static enum arm_reg_type
10613 arm_reg_parse_any (cp)
10614      char *cp;
10615 {
10616   int i;
10617
10618   for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
10619     if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
10620       return (enum arm_reg_type) i;
10621
10622   return REG_TYPE_MAX;
10623 }
10624
10625 void
10626 md_apply_fix3 (fixP, valP, seg)
10627      fixS *   fixP;
10628      valueT * valP;
10629      segT     seg;
10630 {
10631   offsetT        value = * valP;
10632   offsetT        newval;
10633   unsigned int   newimm;
10634   unsigned long  temp;
10635   int            sign;
10636   char *         buf = fixP->fx_where + fixP->fx_frag->fr_literal;
10637   arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
10638
10639   assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
10640
10641   /* Note whether this will delete the relocation.  */
10642 #if 0
10643   /* Patch from REarnshaw to JDavis (disabled for the moment, since it
10644      doesn't work fully.)  */
10645   if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
10646       && !fixP->fx_pcrel)
10647 #else
10648   if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
10649 #endif
10650     fixP->fx_done = 1;
10651
10652   /* If this symbol is in a different section then we need to leave it for
10653      the linker to deal with.  Unfortunately, md_pcrel_from can't tell,
10654      so we have to undo it's effects here.  */
10655   if (fixP->fx_pcrel)
10656     {
10657       if (fixP->fx_addsy != NULL
10658           && S_IS_DEFINED (fixP->fx_addsy)
10659           && S_GET_SEGMENT (fixP->fx_addsy) != seg)
10660         {
10661           if (target_oabi
10662               && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
10663                   || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
10664                   ))
10665             value = 0;
10666           else
10667             value += md_pcrel_from (fixP);
10668         }
10669     }
10670
10671   /* Remember value for emit_reloc.  */
10672   fixP->fx_addnumber = value;
10673
10674   switch (fixP->fx_r_type)
10675     {
10676     case BFD_RELOC_ARM_IMMEDIATE:
10677       newimm = validate_immediate (value);
10678       temp = md_chars_to_number (buf, INSN_SIZE);
10679
10680       /* If the instruction will fail, see if we can fix things up by
10681          changing the opcode.  */
10682       if (newimm == (unsigned int) FAIL
10683           && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
10684         {
10685           as_bad_where (fixP->fx_file, fixP->fx_line,
10686                         _("invalid constant (%lx) after fixup"),
10687                         (unsigned long) value);
10688           break;
10689         }
10690
10691       newimm |= (temp & 0xfffff000);
10692       md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
10693       fixP->fx_done = 1;
10694       break;
10695
10696     case BFD_RELOC_ARM_ADRL_IMMEDIATE:
10697       {
10698         unsigned int highpart = 0;
10699         unsigned int newinsn  = 0xe1a00000; /* nop.  */
10700
10701         newimm = validate_immediate (value);
10702         temp = md_chars_to_number (buf, INSN_SIZE);
10703
10704         /* If the instruction will fail, see if we can fix things up by
10705            changing the opcode.  */
10706         if (newimm == (unsigned int) FAIL
10707             && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
10708           {
10709             /* No ?  OK - try using two ADD instructions to generate
10710                the value.  */
10711             newimm = validate_immediate_twopart (value, & highpart);
10712
10713             /* Yes - then make sure that the second instruction is
10714                also an add.  */
10715             if (newimm != (unsigned int) FAIL)
10716               newinsn = temp;
10717             /* Still No ?  Try using a negated value.  */
10718             else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
10719               temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
10720             /* Otherwise - give up.  */
10721             else
10722               {
10723                 as_bad_where (fixP->fx_file, fixP->fx_line,
10724                               _("unable to compute ADRL instructions for PC offset of 0x%lx"),
10725                               (long) value);
10726                 break;
10727               }
10728
10729             /* Replace the first operand in the 2nd instruction (which
10730                is the PC) with the destination register.  We have
10731                already added in the PC in the first instruction and we
10732                do not want to do it again.  */
10733             newinsn &= ~ 0xf0000;
10734             newinsn |= ((newinsn & 0x0f000) << 4);
10735           }
10736
10737         newimm |= (temp & 0xfffff000);
10738         md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
10739
10740         highpart |= (newinsn & 0xfffff000);
10741         md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
10742       }
10743       break;
10744
10745     case BFD_RELOC_ARM_OFFSET_IMM:
10746       sign = value >= 0;
10747
10748       if (value < 0)
10749         value = - value;
10750
10751       if (validate_offset_imm (value, 0) == FAIL)
10752         {
10753           as_bad_where (fixP->fx_file, fixP->fx_line,
10754                         _("bad immediate value for offset (%ld)"),
10755                         (long) value);
10756           break;
10757         }
10758
10759       newval = md_chars_to_number (buf, INSN_SIZE);
10760       newval &= 0xff7ff000;
10761       newval |= value | (sign ? INDEX_UP : 0);
10762       md_number_to_chars (buf, newval, INSN_SIZE);
10763       break;
10764
10765     case BFD_RELOC_ARM_OFFSET_IMM8:
10766     case BFD_RELOC_ARM_HWLITERAL:
10767       sign = value >= 0;
10768
10769       if (value < 0)
10770         value = - value;
10771
10772       if (validate_offset_imm (value, 1) == FAIL)
10773         {
10774           if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
10775             as_bad_where (fixP->fx_file, fixP->fx_line,
10776                           _("invalid literal constant: pool needs to be closer"));
10777           else
10778             as_bad (_("bad immediate value for half-word offset (%ld)"),
10779                     (long) value);
10780           break;
10781         }
10782
10783       newval = md_chars_to_number (buf, INSN_SIZE);
10784       newval &= 0xff7ff0f0;
10785       newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
10786       md_number_to_chars (buf, newval, INSN_SIZE);
10787       break;
10788
10789     case BFD_RELOC_ARM_LITERAL:
10790       sign = value >= 0;
10791
10792       if (value < 0)
10793         value = - value;
10794
10795       if (validate_offset_imm (value, 0) == FAIL)
10796         {
10797           as_bad_where (fixP->fx_file, fixP->fx_line,
10798                         _("invalid literal constant: pool needs to be closer"));
10799           break;
10800         }
10801
10802       newval = md_chars_to_number (buf, INSN_SIZE);
10803       newval &= 0xff7ff000;
10804       newval |= value | (sign ? INDEX_UP : 0);
10805       md_number_to_chars (buf, newval, INSN_SIZE);
10806       break;
10807
10808     case BFD_RELOC_ARM_SHIFT_IMM:
10809       newval = md_chars_to_number (buf, INSN_SIZE);
10810       if (((unsigned long) value) > 32
10811           || (value == 32
10812               && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
10813         {
10814           as_bad_where (fixP->fx_file, fixP->fx_line,
10815                         _("shift expression is too large"));
10816           break;
10817         }
10818
10819       if (value == 0)
10820         /* Shifts of zero must be done as lsl.  */
10821         newval &= ~0x60;
10822       else if (value == 32)
10823         value = 0;
10824       newval &= 0xfffff07f;
10825       newval |= (value & 0x1f) << 7;
10826       md_number_to_chars (buf, newval, INSN_SIZE);
10827       break;
10828
10829     case BFD_RELOC_ARM_SWI:
10830       if (arm_data->thumb_mode)
10831         {
10832           if (((unsigned long) value) > 0xff)
10833             as_bad_where (fixP->fx_file, fixP->fx_line,
10834                           _("invalid swi expression"));
10835           newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
10836           newval |= value;
10837           md_number_to_chars (buf, newval, THUMB_SIZE);
10838         }
10839       else
10840         {
10841           if (((unsigned long) value) > 0x00ffffff)
10842             as_bad_where (fixP->fx_file, fixP->fx_line,
10843                           _("invalid swi expression"));
10844           newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
10845           newval |= value;
10846           md_number_to_chars (buf, newval, INSN_SIZE);
10847         }
10848       break;
10849
10850     case BFD_RELOC_ARM_MULTI:
10851       if (((unsigned long) value) > 0xffff)
10852         as_bad_where (fixP->fx_file, fixP->fx_line,
10853                       _("invalid expression in load/store multiple"));
10854       newval = value | md_chars_to_number (buf, INSN_SIZE);
10855       md_number_to_chars (buf, newval, INSN_SIZE);
10856       break;
10857
10858     case BFD_RELOC_ARM_PCREL_BRANCH:
10859       newval = md_chars_to_number (buf, INSN_SIZE);
10860
10861       /* Sign-extend a 24-bit number.  */
10862 #define SEXT24(x)       ((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
10863
10864 #ifdef OBJ_ELF
10865       if (! target_oabi)
10866         value = fixP->fx_offset;
10867 #endif
10868
10869       /* We are going to store value (shifted right by two) in the
10870          instruction, in a 24 bit, signed field.  Thus we need to check
10871          that none of the top 8 bits of the shifted value (top 7 bits of
10872          the unshifted, unsigned value) are set, or that they are all set.  */
10873       if ((value & ~ ((offsetT) 0x1ffffff)) != 0
10874           && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
10875         {
10876 #ifdef OBJ_ELF
10877           /* Normally we would be stuck at this point, since we cannot store
10878              the absolute address that is the destination of the branch in the
10879              24 bits of the branch instruction.  If however, we happen to know
10880              that the destination of the branch is in the same section as the
10881              branch instruciton itself, then we can compute the relocation for
10882              ourselves and not have to bother the linker with it.
10883
10884              FIXME: The tests for OBJ_ELF and ! target_oabi are only here
10885              because I have not worked out how to do this for OBJ_COFF or
10886              target_oabi.  */
10887           if (! target_oabi
10888               && fixP->fx_addsy != NULL
10889               && S_IS_DEFINED (fixP->fx_addsy)
10890               && S_GET_SEGMENT (fixP->fx_addsy) == seg)
10891             {
10892               /* Get pc relative value to go into the branch.  */
10893               value = * valP;
10894
10895               /* Permit a backward branch provided that enough bits
10896                  are set.  Allow a forwards branch, provided that
10897                  enough bits are clear.  */
10898               if (   (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
10899                   || (value & ~ ((offsetT) 0x1ffffff)) == 0)
10900                 fixP->fx_done = 1;
10901             }
10902
10903           if (! fixP->fx_done)
10904 #endif
10905             as_bad_where (fixP->fx_file, fixP->fx_line,
10906                           _("GAS can't handle same-section branch dest >= 0x04000000"));
10907         }
10908
10909       value >>= 2;
10910       value += SEXT24 (newval);
10911
10912       if (    (value & ~ ((offsetT) 0xffffff)) != 0
10913           && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
10914         as_bad_where (fixP->fx_file, fixP->fx_line,
10915                       _("out of range branch"));
10916
10917       newval = (value & 0x00ffffff) | (newval & 0xff000000);
10918       md_number_to_chars (buf, newval, INSN_SIZE);
10919       break;
10920
10921     case BFD_RELOC_ARM_PCREL_BLX:
10922       {
10923         offsetT hbit;
10924         newval = md_chars_to_number (buf, INSN_SIZE);
10925
10926 #ifdef OBJ_ELF
10927         if (! target_oabi)
10928           value = fixP->fx_offset;
10929 #endif
10930         hbit   = (value >> 1) & 1;
10931         value  = (value >> 2) & 0x00ffffff;
10932         value  = (value + (newval & 0x00ffffff)) & 0x00ffffff;
10933         newval = value | (newval & 0xfe000000) | (hbit << 24);
10934         md_number_to_chars (buf, newval, INSN_SIZE);
10935       }
10936       break;
10937
10938     case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch.  */
10939       newval = md_chars_to_number (buf, THUMB_SIZE);
10940       {
10941         addressT diff = (newval & 0xff) << 1;
10942         if (diff & 0x100)
10943           diff |= ~0xff;
10944
10945         value += diff;
10946         if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
10947           as_bad_where (fixP->fx_file, fixP->fx_line,
10948                         _("branch out of range"));
10949         newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
10950       }
10951       md_number_to_chars (buf, newval, THUMB_SIZE);
10952       break;
10953
10954     case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch.  */
10955       newval = md_chars_to_number (buf, THUMB_SIZE);
10956       {
10957         addressT diff = (newval & 0x7ff) << 1;
10958         if (diff & 0x800)
10959           diff |= ~0x7ff;
10960
10961         value += diff;
10962         if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
10963           as_bad_where (fixP->fx_file, fixP->fx_line,
10964                         _("branch out of range"));
10965         newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
10966       }
10967       md_number_to_chars (buf, newval, THUMB_SIZE);
10968       break;
10969
10970     case BFD_RELOC_THUMB_PCREL_BLX:
10971     case BFD_RELOC_THUMB_PCREL_BRANCH23:
10972       {
10973         offsetT newval2;
10974         addressT diff;
10975
10976         newval  = md_chars_to_number (buf, THUMB_SIZE);
10977         newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
10978         diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
10979         if (diff & 0x400000)
10980           diff |= ~0x3fffff;
10981 #ifdef OBJ_ELF
10982         value = fixP->fx_offset;
10983 #endif
10984         value += diff;
10985
10986         if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
10987           as_bad_where (fixP->fx_file, fixP->fx_line,
10988                         _("branch with link out of range"));
10989
10990         newval  = (newval  & 0xf800) | ((value & 0x7fffff) >> 12);
10991         newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
10992         if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
10993           /* For a BLX instruction, make sure that the relocation is rounded up
10994              to a word boundary.  This follows the semantics of the instruction
10995              which specifies that bit 1 of the target address will come from bit
10996              1 of the base address.  */
10997           newval2 = (newval2 + 1) & ~ 1;
10998         md_number_to_chars (buf, newval, THUMB_SIZE);
10999         md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
11000       }
11001       break;
11002
11003     case BFD_RELOC_8:
11004       if (fixP->fx_done || fixP->fx_pcrel)
11005         md_number_to_chars (buf, value, 1);
11006 #ifdef OBJ_ELF
11007       else if (!target_oabi)
11008         {
11009           value = fixP->fx_offset;
11010           md_number_to_chars (buf, value, 1);
11011         }
11012 #endif
11013       break;
11014
11015     case BFD_RELOC_16:
11016       if (fixP->fx_done || fixP->fx_pcrel)
11017         md_number_to_chars (buf, value, 2);
11018 #ifdef OBJ_ELF
11019       else if (!target_oabi)
11020         {
11021           value = fixP->fx_offset;
11022           md_number_to_chars (buf, value, 2);
11023         }
11024 #endif
11025       break;
11026
11027 #ifdef OBJ_ELF
11028     case BFD_RELOC_ARM_GOT32:
11029     case BFD_RELOC_ARM_GOTOFF:
11030       md_number_to_chars (buf, 0, 4);
11031       break;
11032 #endif
11033
11034     case BFD_RELOC_RVA:
11035     case BFD_RELOC_32:
11036       if (fixP->fx_done || fixP->fx_pcrel)
11037         md_number_to_chars (buf, value, 4);
11038 #ifdef OBJ_ELF
11039       else if (!target_oabi)
11040         {
11041           value = fixP->fx_offset;
11042           md_number_to_chars (buf, value, 4);
11043         }
11044 #endif
11045       break;
11046
11047 #ifdef OBJ_ELF
11048     case BFD_RELOC_ARM_PLT32:
11049       /* It appears the instruction is fully prepared at this point.  */
11050       break;
11051 #endif
11052
11053     case BFD_RELOC_ARM_CP_OFF_IMM:
11054       sign = value >= 0;
11055       if (value < -1023 || value > 1023 || (value & 3))
11056         as_bad_where (fixP->fx_file, fixP->fx_line,
11057                       _("illegal value for co-processor offset"));
11058       if (value < 0)
11059         value = -value;
11060       newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11061       newval |= (value >> 2) | (sign ? INDEX_UP : 0);
11062       md_number_to_chars (buf, newval, INSN_SIZE);
11063       break;
11064
11065     case BFD_RELOC_ARM_CP_OFF_IMM_S2:
11066       sign = value >= 0;
11067       if (value < -255 || value > 255)
11068         as_bad_where (fixP->fx_file, fixP->fx_line,
11069                       _("Illegal value for co-processor offset"));
11070       if (value < 0)
11071         value = -value;
11072       newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
11073       newval |= value | (sign ?  INDEX_UP : 0);
11074       md_number_to_chars (buf, newval , INSN_SIZE);
11075       break;
11076
11077     case BFD_RELOC_ARM_THUMB_OFFSET:
11078       newval = md_chars_to_number (buf, THUMB_SIZE);
11079       /* Exactly what ranges, and where the offset is inserted depends
11080          on the type of instruction, we can establish this from the
11081          top 4 bits.  */
11082       switch (newval >> 12)
11083         {
11084         case 4: /* PC load.  */
11085           /* Thumb PC loads are somewhat odd, bit 1 of the PC is
11086              forced to zero for these loads, so we will need to round
11087              up the offset if the instruction address is not word
11088              aligned (since the final address produced must be, and
11089              we can only describe word-aligned immediate offsets).  */
11090
11091           if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
11092             as_bad_where (fixP->fx_file, fixP->fx_line,
11093                           _("invalid offset, target not word aligned (0x%08X)"),
11094                           (unsigned int) (fixP->fx_frag->fr_address
11095                                           + fixP->fx_where + value));
11096
11097           if ((value + 2) & ~0x3fe)
11098             as_bad_where (fixP->fx_file, fixP->fx_line,
11099                           _("invalid offset, value too big (0x%08lX)"),
11100                           (long) value);
11101
11102           /* Round up, since pc will be rounded down.  */
11103           newval |= (value + 2) >> 2;
11104           break;
11105
11106         case 9: /* SP load/store.  */
11107           if (value & ~0x3fc)
11108             as_bad_where (fixP->fx_file, fixP->fx_line,
11109                           _("invalid offset, value too big (0x%08lX)"),
11110                           (long) value);
11111           newval |= value >> 2;
11112           break;
11113
11114         case 6: /* Word load/store.  */
11115           if (value & ~0x7c)
11116             as_bad_where (fixP->fx_file, fixP->fx_line,
11117                           _("invalid offset, value too big (0x%08lX)"),
11118                           (long) value);
11119           newval |= value << 4; /* 6 - 2.  */
11120           break;
11121
11122         case 7: /* Byte load/store.  */
11123           if (value & ~0x1f)
11124             as_bad_where (fixP->fx_file, fixP->fx_line,
11125                           _("invalid offset, value too big (0x%08lX)"),
11126                           (long) value);
11127           newval |= value << 6;
11128           break;
11129
11130         case 8: /* Halfword load/store.  */
11131           if (value & ~0x3e)
11132             as_bad_where (fixP->fx_file, fixP->fx_line,
11133                           _("invalid offset, value too big (0x%08lX)"),
11134                           (long) value);
11135           newval |= value << 5; /* 6 - 1.  */
11136           break;
11137
11138         default:
11139           as_bad_where (fixP->fx_file, fixP->fx_line,
11140                         "Unable to process relocation for thumb opcode: %lx",
11141                         (unsigned long) newval);
11142           break;
11143         }
11144       md_number_to_chars (buf, newval, THUMB_SIZE);
11145       break;
11146
11147     case BFD_RELOC_ARM_THUMB_ADD:
11148       /* This is a complicated relocation, since we use it for all of
11149          the following immediate relocations:
11150
11151             3bit ADD/SUB
11152             8bit ADD/SUB
11153             9bit ADD/SUB SP word-aligned
11154            10bit ADD PC/SP word-aligned
11155
11156          The type of instruction being processed is encoded in the
11157          instruction field:
11158
11159            0x8000  SUB
11160            0x00F0  Rd
11161            0x000F  Rs
11162       */
11163       newval = md_chars_to_number (buf, THUMB_SIZE);
11164       {
11165         int rd = (newval >> 4) & 0xf;
11166         int rs = newval & 0xf;
11167         int subtract = newval & 0x8000;
11168
11169         if (rd == REG_SP)
11170           {
11171             if (value & ~0x1fc)
11172               as_bad_where (fixP->fx_file, fixP->fx_line,
11173                             _("invalid immediate for stack address calculation"));
11174             newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
11175             newval |= value >> 2;
11176           }
11177         else if (rs == REG_PC || rs == REG_SP)
11178           {
11179             if (subtract ||
11180                 value & ~0x3fc)
11181               as_bad_where (fixP->fx_file, fixP->fx_line,
11182                             _("invalid immediate for address calculation (value = 0x%08lX)"),
11183                             (unsigned long) value);
11184             newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
11185             newval |= rd << 8;
11186             newval |= value >> 2;
11187           }
11188         else if (rs == rd)
11189           {
11190             if (value & ~0xff)
11191               as_bad_where (fixP->fx_file, fixP->fx_line,
11192                             _("invalid 8bit immediate"));
11193             newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
11194             newval |= (rd << 8) | value;
11195           }
11196         else
11197           {
11198             if (value & ~0x7)
11199               as_bad_where (fixP->fx_file, fixP->fx_line,
11200                             _("invalid 3bit immediate"));
11201             newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
11202             newval |= rd | (rs << 3) | (value << 6);
11203           }
11204       }
11205       md_number_to_chars (buf, newval, THUMB_SIZE);
11206       break;
11207
11208     case BFD_RELOC_ARM_THUMB_IMM:
11209       newval = md_chars_to_number (buf, THUMB_SIZE);
11210       switch (newval >> 11)
11211         {
11212         case 0x04: /* 8bit immediate MOV.  */
11213         case 0x05: /* 8bit immediate CMP.  */
11214           if (value < 0 || value > 255)
11215             as_bad_where (fixP->fx_file, fixP->fx_line,
11216                           _("invalid immediate: %ld is too large"),
11217                           (long) value);
11218           newval |= value;
11219           break;
11220
11221         default:
11222           abort ();
11223         }
11224       md_number_to_chars (buf, newval, THUMB_SIZE);
11225       break;
11226
11227     case BFD_RELOC_ARM_THUMB_SHIFT:
11228       /* 5bit shift value (0..31).  */
11229       if (value < 0 || value > 31)
11230         as_bad_where (fixP->fx_file, fixP->fx_line,
11231                       _("illegal Thumb shift value: %ld"), (long) value);
11232       newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
11233       newval |= value << 6;
11234       md_number_to_chars (buf, newval, THUMB_SIZE);
11235       break;
11236
11237     case BFD_RELOC_VTABLE_INHERIT:
11238     case BFD_RELOC_VTABLE_ENTRY:
11239       fixP->fx_done = 0;
11240       return;
11241
11242     case BFD_RELOC_NONE:
11243     default:
11244       as_bad_where (fixP->fx_file, fixP->fx_line,
11245                     _("bad relocation fixup type (%d)"), fixP->fx_r_type);
11246     }
11247 }
11248
11249 /* Translate internal representation of relocation info to BFD target
11250    format.  */
11251
11252 arelent *
11253 tc_gen_reloc (section, fixp)
11254      asection * section ATTRIBUTE_UNUSED;
11255      fixS * fixp;
11256 {
11257   arelent * reloc;
11258   bfd_reloc_code_real_type code;
11259
11260   reloc = (arelent *) xmalloc (sizeof (arelent));
11261
11262   reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
11263   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
11264   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
11265
11266   /* @@ Why fx_addnumber sometimes and fx_offset other times?  */
11267 #ifndef OBJ_ELF
11268   if (fixp->fx_pcrel == 0)
11269     reloc->addend = fixp->fx_offset;
11270   else
11271     reloc->addend = fixp->fx_offset = reloc->address;
11272 #else  /* OBJ_ELF */
11273   reloc->addend = fixp->fx_offset;
11274 #endif
11275
11276   switch (fixp->fx_r_type)
11277     {
11278     case BFD_RELOC_8:
11279       if (fixp->fx_pcrel)
11280         {
11281           code = BFD_RELOC_8_PCREL;
11282           break;
11283         }
11284
11285     case BFD_RELOC_16:
11286       if (fixp->fx_pcrel)
11287         {
11288           code = BFD_RELOC_16_PCREL;
11289           break;
11290         }
11291
11292     case BFD_RELOC_32:
11293       if (fixp->fx_pcrel)
11294         {
11295           code = BFD_RELOC_32_PCREL;
11296           break;
11297         }
11298
11299     case BFD_RELOC_ARM_PCREL_BRANCH:
11300     case BFD_RELOC_ARM_PCREL_BLX:
11301     case BFD_RELOC_RVA:
11302     case BFD_RELOC_THUMB_PCREL_BRANCH9:
11303     case BFD_RELOC_THUMB_PCREL_BRANCH12:
11304     case BFD_RELOC_THUMB_PCREL_BRANCH23:
11305     case BFD_RELOC_THUMB_PCREL_BLX:
11306     case BFD_RELOC_VTABLE_ENTRY:
11307     case BFD_RELOC_VTABLE_INHERIT:
11308       code = fixp->fx_r_type;
11309       break;
11310
11311     case BFD_RELOC_ARM_LITERAL:
11312     case BFD_RELOC_ARM_HWLITERAL:
11313       /* If this is called then the a literal has
11314          been referenced across a section boundary.  */
11315       as_bad_where (fixp->fx_file, fixp->fx_line,
11316                     _("literal referenced across section boundary"));
11317       return NULL;
11318
11319 #ifdef OBJ_ELF
11320     case BFD_RELOC_ARM_GOT32:
11321     case BFD_RELOC_ARM_GOTOFF:
11322     case BFD_RELOC_ARM_PLT32:
11323       code = fixp->fx_r_type;
11324       break;
11325 #endif
11326
11327     case BFD_RELOC_ARM_IMMEDIATE:
11328       as_bad_where (fixp->fx_file, fixp->fx_line,
11329                     _("internal relocation (type: IMMEDIATE) not fixed up"));
11330       return NULL;
11331
11332     case BFD_RELOC_ARM_ADRL_IMMEDIATE:
11333       as_bad_where (fixp->fx_file, fixp->fx_line,
11334                     _("ADRL used for a symbol not defined in the same file"));
11335       return NULL;
11336
11337     case BFD_RELOC_ARM_OFFSET_IMM:
11338       as_bad_where (fixp->fx_file, fixp->fx_line,
11339                     _("internal_relocation (type: OFFSET_IMM) not fixed up"));
11340       return NULL;
11341
11342     default:
11343       {
11344         char * type;
11345
11346         switch (fixp->fx_r_type)
11347           {
11348           case BFD_RELOC_ARM_OFFSET_IMM8:  type = "OFFSET_IMM8";  break;
11349           case BFD_RELOC_ARM_SHIFT_IMM:    type = "SHIFT_IMM";    break;
11350           case BFD_RELOC_ARM_SWI:          type = "SWI";          break;
11351           case BFD_RELOC_ARM_MULTI:        type = "MULTI";        break;
11352           case BFD_RELOC_ARM_CP_OFF_IMM:   type = "CP_OFF_IMM";   break;
11353           case BFD_RELOC_ARM_THUMB_ADD:    type = "THUMB_ADD";    break;
11354           case BFD_RELOC_ARM_THUMB_SHIFT:  type = "THUMB_SHIFT";  break;
11355           case BFD_RELOC_ARM_THUMB_IMM:    type = "THUMB_IMM";    break;
11356           case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
11357           default:                         type = _("<unknown>"); break;
11358           }
11359         as_bad_where (fixp->fx_file, fixp->fx_line,
11360                       _("cannot represent %s relocation in this object file format"),
11361                       type);
11362         return NULL;
11363       }
11364     }
11365
11366 #ifdef OBJ_ELF
11367   if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
11368       && GOT_symbol
11369       && fixp->fx_addsy == GOT_symbol)
11370     {
11371       code = BFD_RELOC_ARM_GOTPC;
11372       reloc->addend = fixp->fx_offset = reloc->address;
11373     }
11374 #endif
11375
11376   reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
11377
11378   if (reloc->howto == NULL)
11379     {
11380       as_bad_where (fixp->fx_file, fixp->fx_line,
11381                     _("cannot represent %s relocation in this object file format"),
11382                     bfd_get_reloc_code_name (code));
11383       return NULL;
11384     }
11385
11386   /* HACK: Since arm ELF uses Rel instead of Rela, encode the
11387      vtable entry to be used in the relocation's section offset.  */
11388   if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
11389     reloc->address = fixp->fx_offset;
11390
11391   return reloc;
11392 }
11393
11394 int
11395 md_estimate_size_before_relax (fragP, segtype)
11396      fragS * fragP ATTRIBUTE_UNUSED;
11397      segT    segtype ATTRIBUTE_UNUSED;
11398 {
11399   as_fatal (_("md_estimate_size_before_relax\n"));
11400   return 1;
11401 }
11402
11403 static void
11404 output_inst (str)
11405      const char *str;
11406 {
11407   char * to = NULL;
11408
11409   if (inst.error)
11410     {
11411       as_bad ("%s -- `%s'", inst.error, str);
11412       return;
11413     }
11414
11415   to = frag_more (inst.size);
11416
11417   if (thumb_mode && (inst.size > THUMB_SIZE))
11418     {
11419       assert (inst.size == (2 * THUMB_SIZE));
11420       md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
11421       md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
11422     }
11423   else if (inst.size > INSN_SIZE)
11424     {
11425       assert (inst.size == (2 * INSN_SIZE));
11426       md_number_to_chars (to, inst.instruction, INSN_SIZE);
11427       md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
11428     }
11429   else
11430     md_number_to_chars (to, inst.instruction, inst.size);
11431
11432   if (inst.reloc.type != BFD_RELOC_NONE)
11433     fix_new_arm (frag_now, to - frag_now->fr_literal,
11434                  inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
11435                  inst.reloc.type);
11436
11437 #ifdef OBJ_ELF
11438   dwarf2_emit_insn (inst.size);
11439 #endif
11440 }
11441
11442 void
11443 md_assemble (str)
11444      char * str;
11445 {
11446   char  c;
11447   char *p;
11448   char *start;
11449
11450   /* Align the instruction.
11451      This may not be the right thing to do but ...  */
11452 #if 0
11453   arm_align (2, 0);
11454 #endif
11455
11456   /* Align the previous label if needed.  */
11457   if (last_label_seen != NULL)
11458     {
11459       symbol_set_frag (last_label_seen, frag_now);
11460       S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
11461       S_SET_SEGMENT (last_label_seen, now_seg);
11462     }
11463
11464   memset (&inst, '\0', sizeof (inst));
11465   inst.reloc.type = BFD_RELOC_NONE;
11466
11467   skip_whitespace (str);
11468
11469   /* Scan up to the end of the op-code, which must end in white space or
11470      end of string.  */
11471   for (start = p = str; *p != '\0'; p++)
11472     if (*p == ' ')
11473       break;
11474
11475   if (p == str)
11476     {
11477       as_bad (_("no operator -- statement `%s'\n"), str);
11478       return;
11479     }
11480
11481   if (thumb_mode)
11482     {
11483       const struct thumb_opcode * opcode;
11484
11485       c = *p;
11486       *p = '\0';
11487       opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
11488       *p = c;
11489
11490       if (opcode)
11491         {
11492           /* Check that this instruction is supported for this CPU.  */
11493           if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
11494             {
11495               as_bad (_("selected processor does not support `%s'"), str);
11496               return;
11497             }
11498
11499           inst.instruction = opcode->value;
11500           inst.size = opcode->size;
11501           (*opcode->parms) (p);
11502           output_inst (str);
11503           return;
11504         }
11505     }
11506   else
11507     {
11508       const struct asm_opcode * opcode;
11509
11510       c = *p;
11511       *p = '\0';
11512       opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
11513       *p = c;
11514
11515       if (opcode)
11516         {
11517           /* Check that this instruction is supported for this CPU.  */
11518           if ((opcode->variant & cpu_variant) == 0)
11519             {
11520               as_bad (_("selected processor does not support `%s'"), str);
11521               return;
11522             }
11523
11524           inst.instruction = opcode->value;
11525           inst.size = INSN_SIZE;
11526           (*opcode->parms) (p);
11527           output_inst (str);
11528           return;
11529         }
11530     }
11531
11532   /* It wasn't an instruction, but it might be a register alias of the form
11533      alias .req reg.  */
11534   if (create_register_alias (str, p))
11535     return;
11536
11537   as_bad (_("bad instruction `%s'"), start);
11538 }
11539
11540 /* md_parse_option
11541       Invocation line includes a switch not recognized by the base assembler.
11542       See if it's a processor-specific option.
11543
11544       This routine is somewhat complicated by the need for backwards
11545       compatibility (since older releases of gcc can't be changed).
11546       The new options try to make the interface as compatible as
11547       possible with GCC.
11548
11549       New options (supported) are:
11550
11551               -mcpu=<cpu name>           Assemble for selected processor
11552               -march=<architecture name> Assemble for selected architecture
11553               -mfpu=<fpu architecture>   Assemble for selected FPU.
11554               -EB/-mbig-endian           Big-endian
11555               -EL/-mlittle-endian        Little-endian
11556               -k                         Generate PIC code
11557               -mthumb                    Start in Thumb mode
11558               -mthumb-interwork          Code supports ARM/Thumb interworking
11559
11560       For now we will also provide support for:
11561
11562               -mapcs-32                  32-bit Program counter
11563               -mapcs-26                  26-bit Program counter
11564               -macps-float               Floats passed in FP registers
11565               -mapcs-reentrant           Reentrant code
11566               -matpcs
11567       (sometime these will probably be replaced with -mapcs=<list of options>
11568       and -matpcs=<list of options>)
11569
11570       The remaining options are only supported for back-wards compatibility.
11571       Cpu variants, the arm part is optional:
11572               -m[arm]1                Currently not supported.
11573               -m[arm]2, -m[arm]250    Arm 2 and Arm 250 processor
11574               -m[arm]3                Arm 3 processor
11575               -m[arm]6[xx],           Arm 6 processors
11576               -m[arm]7[xx][t][[d]m]   Arm 7 processors
11577               -m[arm]8[10]            Arm 8 processors
11578               -m[arm]9[20][tdmi]      Arm 9 processors
11579               -mstrongarm[110[0]]     StrongARM processors
11580               -mxscale                XScale processors
11581               -m[arm]v[2345[t[e]]]    Arm architectures
11582               -mall                   All (except the ARM1)
11583       FP variants:
11584               -mfpa10, -mfpa11        FPA10 and 11 co-processor instructions
11585               -mfpe-old               (No float load/store multiples)
11586               -mvfpxd                 VFP Single precision
11587               -mvfp                   All VFP
11588               -mno-fpu                Disable all floating point instructions
11589
11590       The following CPU names are recognized:
11591               arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
11592               arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
11593               arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
11594               arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
11595               arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
11596               arm10t arm10e, arm1020t, arm1020e, arm10200e,
11597               strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
11598
11599       */
11600
11601 const char * md_shortopts = "m:k";
11602
11603 #ifdef ARM_BI_ENDIAN
11604 #define OPTION_EB (OPTION_MD_BASE + 0)
11605 #define OPTION_EL (OPTION_MD_BASE + 1)
11606 #else
11607 #if TARGET_BYTES_BIG_ENDIAN
11608 #define OPTION_EB (OPTION_MD_BASE + 0)
11609 #else
11610 #define OPTION_EL (OPTION_MD_BASE + 1)
11611 #endif
11612 #endif
11613
11614 struct option md_longopts[] =
11615 {
11616 #ifdef OPTION_EB
11617   {"EB", no_argument, NULL, OPTION_EB},
11618 #endif
11619 #ifdef OPTION_EL
11620   {"EL", no_argument, NULL, OPTION_EL},
11621 #endif
11622   {NULL, no_argument, NULL, 0}
11623 };
11624
11625 size_t md_longopts_size = sizeof (md_longopts);
11626
11627 struct arm_option_table
11628 {
11629   char *option;         /* Option name to match.  */
11630   char *help;           /* Help information.  */
11631   int  *var;            /* Variable to change.  */
11632   int   value;          /* What to change it to.  */
11633   char *deprecated;     /* If non-null, print this message.  */
11634 };
11635
11636 struct arm_option_table arm_opts[] =
11637 {
11638   {"k",      N_("generate PIC code"),      &pic_code,    1, NULL},
11639   {"mthumb", N_("assemble Thumb code"),    &thumb_mode,  1, NULL},
11640   {"mthumb-interwork", N_("support ARM/Thumb interworking"),
11641    &support_interwork, 1, NULL},
11642   {"moabi",  N_("use old ABI (ELF only)"), &target_oabi, 1, NULL},
11643   {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
11644   {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
11645   {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
11646    1, NULL},
11647   {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
11648   {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
11649   {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
11650   {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
11651    NULL},
11652
11653   /* These are recognized by the assembler, but have no affect on code.  */
11654   {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
11655   {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
11656
11657   /* DON'T add any new processors to this list -- we want the whole list
11658      to go away...  Add them to the processors table instead.  */
11659   {"marm1",      NULL, &legacy_cpu, ARM_ARCH_V1,  N_("use -mcpu=arm1")},
11660   {"m1",         NULL, &legacy_cpu, ARM_ARCH_V1,  N_("use -mcpu=arm1")},
11661   {"marm2",      NULL, &legacy_cpu, ARM_ARCH_V2,  N_("use -mcpu=arm2")},
11662   {"m2",         NULL, &legacy_cpu, ARM_ARCH_V2,  N_("use -mcpu=arm2")},
11663   {"marm250",    NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
11664   {"m250",       NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
11665   {"marm3",      NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
11666   {"m3",         NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
11667   {"marm6",      NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm6")},
11668   {"m6",         NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm6")},
11669   {"marm600",    NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm600")},
11670   {"m600",       NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm600")},
11671   {"marm610",    NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm610")},
11672   {"m610",       NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm610")},
11673   {"marm620",    NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm620")},
11674   {"m620",       NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm620")},
11675   {"marm7",      NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7")},
11676   {"m7",         NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7")},
11677   {"marm70",     NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm70")},
11678   {"m70",        NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm70")},
11679   {"marm700",    NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm700")},
11680   {"m700",       NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm700")},
11681   {"marm700i",   NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm700i")},
11682   {"m700i",      NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm700i")},
11683   {"marm710",    NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm710")},
11684   {"m710",       NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm710")},
11685   {"marm710c",   NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm710c")},
11686   {"m710c",      NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm710c")},
11687   {"marm720",    NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm720")},
11688   {"m720",       NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm720")},
11689   {"marm7d",     NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7d")},
11690   {"m7d",        NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7d")},
11691   {"marm7di",    NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7di")},
11692   {"m7di",       NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7di")},
11693   {"marm7m",     NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
11694   {"m7m",        NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
11695   {"marm7dm",    NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
11696   {"m7dm",       NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
11697   {"marm7dmi",   NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
11698   {"m7dmi",      NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
11699   {"marm7100",   NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7100")},
11700   {"m7100",      NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7100")},
11701   {"marm7500",   NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7500")},
11702   {"m7500",      NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7500")},
11703   {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7500fe")},
11704   {"m7500fe",    NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7500fe")},
11705   {"marm7t",     NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
11706   {"m7t",        NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
11707   {"marm7tdmi",  NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
11708   {"m7tdmi",     NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
11709   {"marm710t",   NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
11710   {"m710t",      NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
11711   {"marm720t",   NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
11712   {"m720t",      NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
11713   {"marm740t",   NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
11714   {"m740t",      NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
11715   {"marm8",      NULL, &legacy_cpu, ARM_ARCH_V4,  N_("use -mcpu=arm8")},
11716   {"m8",         NULL, &legacy_cpu, ARM_ARCH_V4,  N_("use -mcpu=arm8")},
11717   {"marm810",    NULL, &legacy_cpu, ARM_ARCH_V4,  N_("use -mcpu=arm810")},
11718   {"m810",       NULL, &legacy_cpu, ARM_ARCH_V4,  N_("use -mcpu=arm810")},
11719   {"marm9",      NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
11720   {"m9",         NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
11721   {"marm9tdmi",  NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
11722   {"m9tdmi",     NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
11723   {"marm920",    NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
11724   {"m920",       NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
11725   {"marm940",    NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
11726   {"m940",       NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
11727   {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4,  N_("use -mcpu=strongarm")},
11728   {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
11729    N_("use -mcpu=strongarm110")},
11730   {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
11731    N_("use -mcpu=strongarm1100")},
11732   {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
11733    N_("use -mcpu=strongarm1110")},
11734   {"mxscale",    NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
11735   {"miwmmxt",    NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
11736   {"mall",       NULL, &legacy_cpu, ARM_ANY,      N_("use -mcpu=all")},
11737
11738   /* Architecture variants -- don't add any more to this list either.  */
11739   {"mv2",        NULL, &legacy_cpu, ARM_ARCH_V2,  N_("use -march=armv2")},
11740   {"marmv2",     NULL, &legacy_cpu, ARM_ARCH_V2,  N_("use -march=armv2")},
11741   {"mv2a",       NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
11742   {"marmv2a",    NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
11743   {"mv3",        NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -march=armv3")},
11744   {"marmv3",     NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -march=armv3")},
11745   {"mv3m",       NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
11746   {"marmv3m",    NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
11747   {"mv4",        NULL, &legacy_cpu, ARM_ARCH_V4,  N_("use -march=armv4")},
11748   {"marmv4",     NULL, &legacy_cpu, ARM_ARCH_V4,  N_("use -march=armv4")},
11749   {"mv4t",       NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
11750   {"marmv4t",    NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
11751   {"mv5",        NULL, &legacy_cpu, ARM_ARCH_V5,  N_("use -march=armv5")},
11752   {"marmv5",     NULL, &legacy_cpu, ARM_ARCH_V5,  N_("use -march=armv5")},
11753   {"mv5t",       NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
11754   {"marmv5t",    NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
11755   {"mv5e",       NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
11756   {"marmv5e",    NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
11757
11758   /* Floating point variants -- don't add any more to this list either.  */
11759   {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
11760   {"mfpa10",   NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
11761   {"mfpa11",   NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
11762   {"mno-fpu",  NULL, &legacy_fpu, 0,
11763    N_("use either -mfpu=softfpa or -mfpu=softvfp")},
11764
11765   {NULL, NULL, NULL, 0, NULL}
11766 };
11767
11768 struct arm_cpu_option_table
11769 {
11770   char *name;
11771   int   value;
11772   /* For some CPUs we assume an FPU unless the user explicitly sets
11773      -mfpu=...  */
11774   int   default_fpu;
11775 };
11776
11777 /* This list should, at a minimum, contain all the cpu names
11778    recognized by GCC.  */
11779 static struct arm_cpu_option_table arm_cpus[] =
11780 {
11781   {"all",               ARM_ANY,         FPU_ARCH_FPA},
11782   {"arm1",              ARM_ARCH_V1,     FPU_ARCH_FPA},
11783   {"arm2",              ARM_ARCH_V2,     FPU_ARCH_FPA},
11784   {"arm250",            ARM_ARCH_V2S,    FPU_ARCH_FPA},
11785   {"arm3",              ARM_ARCH_V2S,    FPU_ARCH_FPA},
11786   {"arm6",              ARM_ARCH_V3,     FPU_ARCH_FPA},
11787   {"arm60",             ARM_ARCH_V3,     FPU_ARCH_FPA},
11788   {"arm600",            ARM_ARCH_V3,     FPU_ARCH_FPA},
11789   {"arm610",            ARM_ARCH_V3,     FPU_ARCH_FPA},
11790   {"arm620",            ARM_ARCH_V3,     FPU_ARCH_FPA},
11791   {"arm7",              ARM_ARCH_V3,     FPU_ARCH_FPA},
11792   {"arm7m",             ARM_ARCH_V3M,    FPU_ARCH_FPA},
11793   {"arm7d",             ARM_ARCH_V3,     FPU_ARCH_FPA},
11794   {"arm7dm",            ARM_ARCH_V3M,    FPU_ARCH_FPA},
11795   {"arm7di",            ARM_ARCH_V3,     FPU_ARCH_FPA},
11796   {"arm7dmi",           ARM_ARCH_V3M,    FPU_ARCH_FPA},
11797   {"arm70",             ARM_ARCH_V3,     FPU_ARCH_FPA},
11798   {"arm700",            ARM_ARCH_V3,     FPU_ARCH_FPA},
11799   {"arm700i",           ARM_ARCH_V3,     FPU_ARCH_FPA},
11800   {"arm710",            ARM_ARCH_V3,     FPU_ARCH_FPA},
11801   {"arm710t",           ARM_ARCH_V4T,    FPU_ARCH_FPA},
11802   {"arm720",            ARM_ARCH_V3,     FPU_ARCH_FPA},
11803   {"arm720t",           ARM_ARCH_V4T,    FPU_ARCH_FPA},
11804   {"arm740t",           ARM_ARCH_V4T,    FPU_ARCH_FPA},
11805   {"arm710c",           ARM_ARCH_V3,     FPU_ARCH_FPA},
11806   {"arm7100",           ARM_ARCH_V3,     FPU_ARCH_FPA},
11807   {"arm7500",           ARM_ARCH_V3,     FPU_ARCH_FPA},
11808   {"arm7500fe",         ARM_ARCH_V3,     FPU_ARCH_FPA},
11809   {"arm7t",             ARM_ARCH_V4T,    FPU_ARCH_FPA},
11810   {"arm7tdmi",          ARM_ARCH_V4T,    FPU_ARCH_FPA},
11811   {"arm8",              ARM_ARCH_V4,     FPU_ARCH_FPA},
11812   {"arm810",            ARM_ARCH_V4,     FPU_ARCH_FPA},
11813   {"strongarm",         ARM_ARCH_V4,     FPU_ARCH_FPA},
11814   {"strongarm1",        ARM_ARCH_V4,     FPU_ARCH_FPA},
11815   {"strongarm110",      ARM_ARCH_V4,     FPU_ARCH_FPA},
11816   {"strongarm1100",     ARM_ARCH_V4,     FPU_ARCH_FPA},
11817   {"strongarm1110",     ARM_ARCH_V4,     FPU_ARCH_FPA},
11818   {"arm9",              ARM_ARCH_V4T,    FPU_ARCH_FPA},
11819   {"arm920",            ARM_ARCH_V4T,    FPU_ARCH_FPA},
11820   {"arm920t",           ARM_ARCH_V4T,    FPU_ARCH_FPA},
11821   {"arm922t",           ARM_ARCH_V4T,    FPU_ARCH_FPA},
11822   {"arm940t",           ARM_ARCH_V4T,    FPU_ARCH_FPA},
11823   {"arm9tdmi",          ARM_ARCH_V4T,    FPU_ARCH_FPA},
11824   /* For V5 or later processors we default to using VFP; but the user
11825      should really set the FPU type explicitly.  */
11826   {"arm9e-r0",          ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
11827   {"arm9e",             ARM_ARCH_V5TE,   FPU_ARCH_VFP_V2},
11828   {"arm926ej",          ARM_ARCH_V5TEJ,  FPU_ARCH_VFP_V2},
11829   {"arm946e-r0",        ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
11830   {"arm946e",           ARM_ARCH_V5TE,   FPU_ARCH_VFP_V2},
11831   {"arm966e-r0",        ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
11832   {"arm966e",           ARM_ARCH_V5TE,   FPU_ARCH_VFP_V2},
11833   {"arm10t",            ARM_ARCH_V5T,    FPU_ARCH_VFP_V1},
11834   {"arm10e",            ARM_ARCH_V5TE,   FPU_ARCH_VFP_V2},
11835   {"arm1020",           ARM_ARCH_V5TE,   FPU_ARCH_VFP_V2},
11836   {"arm1020t",          ARM_ARCH_V5T,    FPU_ARCH_VFP_V1},
11837   {"arm1020e",          ARM_ARCH_V5TE,   FPU_ARCH_VFP_V2},
11838   /* ??? XSCALE is really an architecture.  */
11839   {"xscale",            ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
11840   /* ??? iwmmxt is not a processor.  */
11841   {"iwmmxt",            ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
11842   {"i80200",            ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
11843   /* Maverick */
11844   {"ep9312",            ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_NONE},
11845   {NULL, 0, 0}
11846 };
11847
11848 struct arm_arch_option_table
11849 {
11850   char *name;
11851   int   value;
11852   int   default_fpu;
11853 };
11854
11855 /* This list should, at a minimum, contain all the architecture names
11856    recognized by GCC.  */
11857 static struct arm_arch_option_table arm_archs[] =
11858 {
11859   {"all",               ARM_ANY,         FPU_ARCH_FPA},
11860   {"armv1",             ARM_ARCH_V1,     FPU_ARCH_FPA},
11861   {"armv2",             ARM_ARCH_V2,     FPU_ARCH_FPA},
11862   {"armv2a",            ARM_ARCH_V2S,    FPU_ARCH_FPA},
11863   {"armv2s",            ARM_ARCH_V2S,    FPU_ARCH_FPA},
11864   {"armv3",             ARM_ARCH_V3,     FPU_ARCH_FPA},
11865   {"armv3m",            ARM_ARCH_V3M,    FPU_ARCH_FPA},
11866   {"armv4",             ARM_ARCH_V4,     FPU_ARCH_FPA},
11867   {"armv4xm",           ARM_ARCH_V4xM,   FPU_ARCH_FPA},
11868   {"armv4t",            ARM_ARCH_V4T,    FPU_ARCH_FPA},
11869   {"armv4txm",          ARM_ARCH_V4TxM,  FPU_ARCH_FPA},
11870   {"armv5",             ARM_ARCH_V5,     FPU_ARCH_VFP},
11871   {"armv5t",            ARM_ARCH_V5T,    FPU_ARCH_VFP},
11872   {"armv5txm",          ARM_ARCH_V5TxM,  FPU_ARCH_VFP},
11873   {"armv5te",           ARM_ARCH_V5TE,   FPU_ARCH_VFP},
11874   {"armv5texp",         ARM_ARCH_V5TExP, FPU_ARCH_VFP},
11875   {"armv5tej",          ARM_ARCH_V5TEJ,  FPU_ARCH_VFP},
11876   {"xscale",            ARM_ARCH_XSCALE, FPU_ARCH_VFP},
11877   {NULL, 0, 0}
11878 };
11879
11880 /* ISA extensions in the co-processor space.  */
11881 struct arm_arch_extension_table
11882 {
11883   char *name;
11884   int value;
11885 };
11886
11887 static struct arm_arch_extension_table arm_extensions[] =
11888 {
11889   {"maverick",          ARM_CEXT_MAVERICK},
11890   {"xscale",            ARM_CEXT_XSCALE},
11891   {"iwmmxt",            ARM_CEXT_IWMMXT},
11892   {NULL,                0}
11893 };
11894
11895 struct arm_fpu_option_table
11896 {
11897   char *name;
11898   int   value;
11899 };
11900
11901 /* This list should, at a minimum, contain all the fpu names
11902    recognized by GCC.  */
11903 static struct arm_fpu_option_table arm_fpus[] =
11904 {
11905   {"softfpa",           FPU_NONE},
11906   {"fpe",               FPU_ARCH_FPE},
11907   {"fpe2",              FPU_ARCH_FPE},
11908   {"fpe3",              FPU_ARCH_FPA},  /* Third release supports LFM/SFM.  */
11909   {"fpa",               FPU_ARCH_FPA},
11910   {"fpa10",             FPU_ARCH_FPA},
11911   {"fpa11",             FPU_ARCH_FPA},
11912   {"arm7500fe",         FPU_ARCH_FPA},
11913   {"softvfp",           FPU_ARCH_VFP},
11914   {"softvfp+vfp",       FPU_ARCH_VFP_V2},
11915   {"vfp",               FPU_ARCH_VFP_V2},
11916   {"vfp9",              FPU_ARCH_VFP_V2},
11917   {"vfp10",             FPU_ARCH_VFP_V2},
11918   {"vfp10-r0",          FPU_ARCH_VFP_V1},
11919   {"vfpxd",             FPU_ARCH_VFP_V1xD},
11920   {"arm1020t",          FPU_ARCH_VFP_V1},
11921   {"arm1020e",          FPU_ARCH_VFP_V2},
11922   {NULL, 0}
11923 };
11924
11925 struct arm_long_option_table
11926 {
11927   char *option;         /* Substring to match.  */
11928   char *help;           /* Help information.  */
11929   int (*func) PARAMS ((char *subopt));  /* Function to decode sub-option.  */
11930   char *deprecated;     /* If non-null, print this message.  */
11931 };
11932
11933 static int
11934 arm_parse_extension (str, opt_p)
11935      char *str;
11936      int *opt_p;
11937 {
11938   while (str != NULL && *str != 0)
11939     {
11940       struct arm_arch_extension_table *opt;
11941       char *ext;
11942       int optlen;
11943
11944       if (*str != '+')
11945         {
11946           as_bad (_("invalid architectural extension"));
11947           return 0;
11948         }
11949
11950       str++;
11951       ext = strchr (str, '+');
11952
11953       if (ext != NULL)
11954         optlen = ext - str;
11955       else
11956         optlen = strlen (str);
11957
11958       if (optlen == 0)
11959         {
11960           as_bad (_("missing architectural extension"));
11961           return 0;
11962         }
11963
11964       for (opt = arm_extensions; opt->name != NULL; opt++)
11965         if (strncmp (opt->name, str, optlen) == 0)
11966           {
11967             *opt_p |= opt->value;
11968             break;
11969           }
11970
11971       if (opt->name == NULL)
11972         {
11973           as_bad (_("unknown architectural extnsion `%s'"), str);
11974           return 0;
11975         }
11976
11977       str = ext;
11978     };
11979
11980   return 1;
11981 }
11982
11983 static int
11984 arm_parse_cpu (str)
11985      char *str;
11986 {
11987   struct arm_cpu_option_table *opt;
11988   char *ext = strchr (str, '+');
11989   int optlen;
11990
11991   if (ext != NULL)
11992     optlen = ext - str;
11993   else
11994     optlen = strlen (str);
11995
11996   if (optlen == 0)
11997     {
11998       as_bad (_("missing cpu name `%s'"), str);
11999       return 0;
12000     }
12001
12002   for (opt = arm_cpus; opt->name != NULL; opt++)
12003     if (strncmp (opt->name, str, optlen) == 0)
12004       {
12005         mcpu_cpu_opt = opt->value;
12006         mcpu_fpu_opt = opt->default_fpu;
12007
12008         if (ext != NULL)
12009           return arm_parse_extension (ext, &mcpu_cpu_opt);
12010
12011         return 1;
12012       }
12013
12014   as_bad (_("unknown cpu `%s'"), str);
12015   return 0;
12016 }
12017
12018 static int
12019 arm_parse_arch (str)
12020      char *str;
12021 {
12022   struct arm_arch_option_table *opt;
12023   char *ext = strchr (str, '+');
12024   int optlen;
12025
12026   if (ext != NULL)
12027     optlen = ext - str;
12028   else
12029     optlen = strlen (str);
12030
12031   if (optlen == 0)
12032     {
12033       as_bad (_("missing architecture name `%s'"), str);
12034       return 0;
12035     }
12036
12037
12038   for (opt = arm_archs; opt->name != NULL; opt++)
12039     if (strcmp (opt->name, str) == 0)
12040       {
12041         march_cpu_opt = opt->value;
12042         march_fpu_opt = opt->default_fpu;
12043
12044         if (ext != NULL)
12045           return arm_parse_extension (ext, &march_cpu_opt);
12046
12047         return 1;
12048       }
12049
12050   as_bad (_("unknown architecture `%s'\n"), str);
12051   return 0;
12052 }
12053
12054 static int
12055 arm_parse_fpu (str)
12056      char *str;
12057 {
12058   struct arm_fpu_option_table *opt;
12059
12060   for (opt = arm_fpus; opt->name != NULL; opt++)
12061     if (strcmp (opt->name, str) == 0)
12062       {
12063         mfpu_opt = opt->value;
12064         return 1;
12065       }
12066
12067   as_bad (_("unknown floating point format `%s'\n"), str);
12068   return 0;
12069 }
12070
12071 struct arm_long_option_table arm_long_opts[] =
12072 {
12073   {"mcpu=", N_("<cpu name>\t  assemble for CPU <cpu name>"),
12074    arm_parse_cpu, NULL},
12075   {"march=", N_("<arch name>\t  assemble for architecture <arch name>"),
12076    arm_parse_arch, NULL},
12077   {"mfpu=", N_("<fpu name>\t  assemble for FPU architecture <fpu name>"),
12078    arm_parse_fpu, NULL},
12079   {NULL, NULL, 0, NULL}
12080 };
12081
12082 int
12083 md_parse_option (c, arg)
12084      int    c;
12085      char * arg;
12086 {
12087   struct arm_option_table *opt;
12088   struct arm_long_option_table *lopt;
12089
12090   switch (c)
12091     {
12092 #ifdef OPTION_EB
12093     case OPTION_EB:
12094       target_big_endian = 1;
12095       break;
12096 #endif
12097
12098 #ifdef OPTION_EL
12099     case OPTION_EL:
12100       target_big_endian = 0;
12101       break;
12102 #endif
12103
12104     case 'a':
12105       /* Listing option.  Just ignore these, we don't support additional
12106          ones.  */
12107       return 0;
12108
12109     default:
12110       for (opt = arm_opts; opt->option != NULL; opt++)
12111         {
12112           if (c == opt->option[0]
12113               && ((arg == NULL && opt->option[1] == 0)
12114                   || strcmp (arg, opt->option + 1) == 0))
12115             {
12116 #if WARN_DEPRECATED
12117               /* If the option is deprecated, tell the user.  */
12118               if (opt->deprecated != NULL)
12119                 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
12120                            arg ? arg : "", _(opt->deprecated));
12121 #endif
12122
12123               if (opt->var != NULL)
12124                 *opt->var = opt->value;
12125
12126               return 1;
12127             }
12128         }
12129
12130       for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
12131         {
12132           /* These options are expected to have an argument.  */
12133           if (c == lopt->option[0]
12134               && arg != NULL
12135               && strncmp (arg, lopt->option + 1,
12136                           strlen (lopt->option + 1)) == 0)
12137             {
12138 #if WARN_DEPRECATED
12139               /* If the option is deprecated, tell the user.  */
12140               if (lopt->deprecated != NULL)
12141                 as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
12142                            _(lopt->deprecated));
12143 #endif
12144
12145               /* Call the sup-option parser.  */
12146               return (*lopt->func)(arg + strlen (lopt->option) - 1);
12147             }
12148         }
12149
12150       as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : "");
12151       return 0;
12152     }
12153
12154   return 1;
12155 }
12156
12157 void
12158 md_show_usage (fp)
12159      FILE * fp;
12160 {
12161   struct arm_option_table *opt;
12162   struct arm_long_option_table *lopt;
12163
12164   fprintf (fp, _(" ARM-specific assembler options:\n"));
12165
12166   for (opt = arm_opts; opt->option != NULL; opt++)
12167     if (opt->help != NULL)
12168       fprintf (fp, "  -%-23s%s\n", opt->option, _(opt->help));
12169
12170   for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
12171     if (lopt->help != NULL)
12172       fprintf (fp, "  -%s%s\n", lopt->option, _(lopt->help));
12173
12174 #ifdef OPTION_EB
12175   fprintf (fp, _("\
12176   -EB                     assemble code for a big-endian cpu\n"));
12177 #endif
12178
12179 #ifdef OPTION_EL
12180   fprintf (fp, _("\
12181   -EL                     assemble code for a little-endian cpu\n"));
12182 #endif
12183 }
12184
12185 /* We need to be able to fix up arbitrary expressions in some statements.
12186    This is so that we can handle symbols that are an arbitrary distance from
12187    the pc.  The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
12188    which returns part of an address in a form which will be valid for
12189    a data instruction.  We do this by pushing the expression into a symbol
12190    in the expr_section, and creating a fix for that.  */
12191
12192 static void
12193 fix_new_arm (frag, where, size, exp, pc_rel, reloc)
12194      fragS *       frag;
12195      int           where;
12196      short int     size;
12197      expressionS * exp;
12198      int           pc_rel;
12199      int           reloc;
12200 {
12201   fixS *           new_fix;
12202   arm_fix_data *   arm_data;
12203
12204   switch (exp->X_op)
12205     {
12206     case O_constant:
12207     case O_symbol:
12208     case O_add:
12209     case O_subtract:
12210       new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
12211       break;
12212
12213     default:
12214       new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
12215                          pc_rel, reloc);
12216       break;
12217     }
12218
12219   /* Mark whether the fix is to a THUMB instruction, or an ARM
12220      instruction.  */
12221   arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
12222   new_fix->tc_fix_data = (PTR) arm_data;
12223   arm_data->thumb_mode = thumb_mode;
12224
12225   return;
12226 }
12227
12228 /* This fix_new is called by cons via TC_CONS_FIX_NEW.  */
12229
12230 void
12231 cons_fix_new_arm (frag, where, size, exp)
12232      fragS *       frag;
12233      int           where;
12234      int           size;
12235      expressionS * exp;
12236 {
12237   bfd_reloc_code_real_type type;
12238   int pcrel = 0;
12239
12240   /* Pick a reloc.
12241      FIXME: @@ Should look at CPU word size.  */
12242   switch (size)
12243     {
12244     case 1:
12245       type = BFD_RELOC_8;
12246       break;
12247     case 2:
12248       type = BFD_RELOC_16;
12249       break;
12250     case 4:
12251     default:
12252       type = BFD_RELOC_32;
12253       break;
12254     case 8:
12255       type = BFD_RELOC_64;
12256       break;
12257     }
12258
12259   fix_new_exp (frag, where, (int) size, exp, pcrel, type);
12260 }
12261
12262 /* A good place to do this, although this was probably not intended
12263    for this kind of use.  We need to dump the literal pool before
12264    references are made to a null symbol pointer.  */
12265
12266 void
12267 arm_cleanup ()
12268 {
12269   literal_pool * pool;
12270
12271   for (pool = list_of_pools; pool; pool = pool->next)
12272     {
12273       /* Put it at the end of the relevent section.  */
12274       subseg_set (pool->section, pool->sub_section);
12275       s_ltorg (0);
12276     }
12277 }
12278
12279 void
12280 arm_start_line_hook ()
12281 {
12282   last_label_seen = NULL;
12283 }
12284
12285 void
12286 arm_frob_label (sym)
12287      symbolS * sym;
12288 {
12289   last_label_seen = sym;
12290
12291   ARM_SET_THUMB (sym, thumb_mode);
12292
12293 #if defined OBJ_COFF || defined OBJ_ELF
12294   ARM_SET_INTERWORK (sym, support_interwork);
12295 #endif
12296
12297   /* Note - do not allow local symbols (.Lxxx) to be labeled
12298      as Thumb functions.  This is because these labels, whilst
12299      they exist inside Thumb code, are not the entry points for
12300      possible ARM->Thumb calls.  Also, these labels can be used
12301      as part of a computed goto or switch statement.  eg gcc
12302      can generate code that looks like this:
12303
12304                 ldr  r2, [pc, .Laaa]
12305                 lsl  r3, r3, #2
12306                 ldr  r2, [r3, r2]
12307                 mov  pc, r2
12308
12309        .Lbbb:  .word .Lxxx
12310        .Lccc:  .word .Lyyy
12311        ..etc...
12312        .Laaa:   .word Lbbb
12313
12314      The first instruction loads the address of the jump table.
12315      The second instruction converts a table index into a byte offset.
12316      The third instruction gets the jump address out of the table.
12317      The fourth instruction performs the jump.
12318
12319      If the address stored at .Laaa is that of a symbol which has the
12320      Thumb_Func bit set, then the linker will arrange for this address
12321      to have the bottom bit set, which in turn would mean that the
12322      address computation performed by the third instruction would end
12323      up with the bottom bit set.  Since the ARM is capable of unaligned
12324      word loads, the instruction would then load the incorrect address
12325      out of the jump table, and chaos would ensue.  */
12326   if (label_is_thumb_function_name
12327       && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
12328       && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
12329     {
12330       /* When the address of a Thumb function is taken the bottom
12331          bit of that address should be set.  This will allow
12332          interworking between Arm and Thumb functions to work
12333          correctly.  */
12334
12335       THUMB_SET_FUNC (sym, 1);
12336
12337       label_is_thumb_function_name = FALSE;
12338     }
12339 }
12340
12341 /* Adjust the symbol table.  This marks Thumb symbols as distinct from
12342    ARM ones.  */
12343
12344 void
12345 arm_adjust_symtab ()
12346 {
12347 #ifdef OBJ_COFF
12348   symbolS * sym;
12349
12350   for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
12351     {
12352       if (ARM_IS_THUMB (sym))
12353         {
12354           if (THUMB_IS_FUNC (sym))
12355             {
12356               /* Mark the symbol as a Thumb function.  */
12357               if (   S_GET_STORAGE_CLASS (sym) == C_STAT
12358                   || S_GET_STORAGE_CLASS (sym) == C_LABEL)  /* This can happen!  */
12359                 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
12360
12361               else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
12362                 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
12363               else
12364                 as_bad (_("%s: unexpected function type: %d"),
12365                         S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
12366             }
12367           else switch (S_GET_STORAGE_CLASS (sym))
12368             {
12369             case C_EXT:
12370               S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
12371               break;
12372             case C_STAT:
12373               S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
12374               break;
12375             case C_LABEL:
12376               S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
12377               break;
12378             default:
12379               /* Do nothing.  */
12380               break;
12381             }
12382         }
12383
12384       if (ARM_IS_INTERWORK (sym))
12385         coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
12386     }
12387 #endif
12388 #ifdef OBJ_ELF
12389   symbolS * sym;
12390   char      bind;
12391
12392   for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
12393     {
12394       if (ARM_IS_THUMB (sym))
12395         {
12396           elf_symbol_type * elf_sym;
12397
12398           elf_sym = elf_symbol (symbol_get_bfdsym (sym));
12399           bind = ELF_ST_BIND (elf_sym);
12400
12401           /* If it's a .thumb_func, declare it as so,
12402              otherwise tag label as .code 16.  */
12403           if (THUMB_IS_FUNC (sym))
12404             elf_sym->internal_elf_sym.st_info =
12405               ELF_ST_INFO (bind, STT_ARM_TFUNC);
12406           else
12407             elf_sym->internal_elf_sym.st_info =
12408               ELF_ST_INFO (bind, STT_ARM_16BIT);
12409         }
12410     }
12411 #endif
12412 }
12413
12414 int
12415 arm_data_in_code ()
12416 {
12417   if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
12418     {
12419       *input_line_pointer = '/';
12420       input_line_pointer += 5;
12421       *input_line_pointer = 0;
12422       return 1;
12423     }
12424
12425   return 0;
12426 }
12427
12428 char *
12429 arm_canonicalize_symbol_name (name)
12430      char * name;
12431 {
12432   int len;
12433
12434   if (thumb_mode && (len = strlen (name)) > 5
12435       && streq (name + len - 5, "/data"))
12436     *(name + len - 5) = 0;
12437
12438   return name;
12439 }
12440
12441 #if defined OBJ_COFF || defined OBJ_ELF
12442 void
12443 arm_validate_fix (fixP)
12444      fixS * fixP;
12445 {
12446   /* If the destination of the branch is a defined symbol which does not have
12447      the THUMB_FUNC attribute, then we must be calling a function which has
12448      the (interfacearm) attribute.  We look for the Thumb entry point to that
12449      function and change the branch to refer to that function instead.  */
12450   if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
12451       && fixP->fx_addsy != NULL
12452       && S_IS_DEFINED (fixP->fx_addsy)
12453       && ! THUMB_IS_FUNC (fixP->fx_addsy))
12454     {
12455       fixP->fx_addsy = find_real_start (fixP->fx_addsy);
12456     }
12457 }
12458 #endif
12459
12460 int
12461 arm_force_relocation (fixp)
12462      struct fix * fixp;
12463 {
12464 #if defined (OBJ_COFF) && defined (TE_PE)
12465   if (fixp->fx_r_type == BFD_RELOC_RVA)
12466     return 1;
12467 #endif
12468 #ifdef OBJ_ELF
12469   if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
12470       || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
12471       || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
12472       || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
12473     return 1;
12474 #endif
12475
12476   /* Resolve these relocations even if the symbol is extern or weak.  */
12477   if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
12478       || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
12479     return 0;
12480
12481   return generic_force_reloc (fixp);
12482 }
12483
12484 #ifdef OBJ_COFF
12485 /* This is a little hack to help the gas/arm/adrl.s test.  It prevents
12486    local labels from being added to the output symbol table when they
12487    are used with the ADRL pseudo op.  The ADRL relocation should always
12488    be resolved before the binbary is emitted, so it is safe to say that
12489    it is adjustable.  */
12490
12491 bfd_boolean
12492 arm_fix_adjustable (fixP)
12493    fixS * fixP;
12494 {
12495   if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
12496     return 1;
12497   return 0;
12498 }
12499 #endif
12500
12501 #ifdef OBJ_ELF
12502 /* Relocations against Thumb function names must be left unadjusted,
12503    so that the linker can use this information to correctly set the
12504    bottom bit of their addresses.  The MIPS version of this function
12505    also prevents relocations that are mips-16 specific, but I do not
12506    know why it does this.
12507
12508    FIXME:
12509    There is one other problem that ought to be addressed here, but
12510    which currently is not:  Taking the address of a label (rather
12511    than a function) and then later jumping to that address.  Such
12512    addresses also ought to have their bottom bit set (assuming that
12513    they reside in Thumb code), but at the moment they will not.  */
12514
12515 bfd_boolean
12516 arm_fix_adjustable (fixP)
12517    fixS * fixP;
12518 {
12519   if (fixP->fx_addsy == NULL)
12520     return 1;
12521
12522   if (THUMB_IS_FUNC (fixP->fx_addsy)
12523       && fixP->fx_subsy == NULL)
12524     return 0;
12525
12526   /* We need the symbol name for the VTABLE entries.  */
12527   if (   fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
12528       || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12529     return 0;
12530
12531   /* Don't allow symbols to be discarded on GOT related relocs.  */
12532   if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
12533       || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
12534       || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF)
12535     return 0;
12536
12537   return 1;
12538 }
12539
12540 const char *
12541 elf32_arm_target_format ()
12542 {
12543   if (target_big_endian)
12544     {
12545       if (target_oabi)
12546         return "elf32-bigarm-oabi";
12547       else
12548         return "elf32-bigarm";
12549     }
12550   else
12551     {
12552       if (target_oabi)
12553         return "elf32-littlearm-oabi";
12554       else
12555         return "elf32-littlearm";
12556     }
12557 }
12558
12559 void
12560 armelf_frob_symbol (symp, puntp)
12561      symbolS * symp;
12562      int *     puntp;
12563 {
12564   elf_frob_symbol (symp, puntp);
12565 }
12566
12567 static bfd_reloc_code_real_type
12568 arm_parse_reloc ()
12569 {
12570   char         id [16];
12571   char *       ip;
12572   unsigned int i;
12573   static struct
12574   {
12575     char * str;
12576     int    len;
12577     bfd_reloc_code_real_type reloc;
12578   }
12579   reloc_map[] =
12580   {
12581 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
12582     MAP ("(got)",    BFD_RELOC_ARM_GOT32),
12583     MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
12584     /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
12585        branch instructions generated by GCC for PLT relocs.  */
12586     MAP ("(plt)",    BFD_RELOC_ARM_PLT32),
12587     { NULL, 0,         BFD_RELOC_UNUSED }
12588 #undef MAP
12589   };
12590
12591   for (i = 0, ip = input_line_pointer;
12592        i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
12593        i++, ip++)
12594     id[i] = TOLOWER (*ip);
12595
12596   for (i = 0; reloc_map[i].str; i++)
12597     if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
12598       break;
12599
12600   input_line_pointer += reloc_map[i].len;
12601
12602   return reloc_map[i].reloc;
12603 }
12604
12605 static void
12606 s_arm_elf_cons (nbytes)
12607      int nbytes;
12608 {
12609   expressionS exp;
12610
12611 #ifdef md_flush_pending_output
12612   md_flush_pending_output ();
12613 #endif
12614
12615   if (is_it_end_of_statement ())
12616     {
12617       demand_empty_rest_of_line ();
12618       return;
12619     }
12620
12621 #ifdef md_cons_align
12622   md_cons_align (nbytes);
12623 #endif
12624
12625   do
12626     {
12627       bfd_reloc_code_real_type reloc;
12628
12629       expression (& exp);
12630
12631       if (exp.X_op == O_symbol
12632           && * input_line_pointer == '('
12633           && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
12634         {
12635           reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
12636           int size = bfd_get_reloc_size (howto);
12637
12638           if (size > nbytes)
12639             as_bad ("%s relocations do not fit in %d bytes",
12640                     howto->name, nbytes);
12641           else
12642             {
12643               register char *p = frag_more ((int) nbytes);
12644               int offset = nbytes - size;
12645
12646               fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
12647                            &exp, 0, reloc);
12648             }
12649         }
12650       else
12651         emit_expr (&exp, (unsigned int) nbytes);
12652     }
12653   while (*input_line_pointer++ == ',');
12654
12655   /* Put terminator back into stream.  */
12656   input_line_pointer --;
12657   demand_empty_rest_of_line ();
12658 }
12659
12660 #endif /* OBJ_ELF */
12661
12662 /* This is called from HANDLE_ALIGN in write.c.  Fill in the contents
12663    of an rs_align_code fragment.  */
12664
12665 void
12666 arm_handle_align (fragP)
12667      fragS *fragP;
12668 {
12669   static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
12670   static char const thumb_noop[2] = { 0xc0, 0x46 };
12671   static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
12672   static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
12673
12674   int bytes, fix, noop_size;
12675   char * p;
12676   const char * noop;
12677
12678   if (fragP->fr_type != rs_align_code)
12679     return;
12680
12681   bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
12682   p = fragP->fr_literal + fragP->fr_fix;
12683   fix = 0;
12684
12685   if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
12686     bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
12687
12688   if (fragP->tc_frag_data)
12689     {
12690       if (target_big_endian)
12691         noop = thumb_bigend_noop;
12692       else
12693         noop = thumb_noop;
12694       noop_size = sizeof (thumb_noop);
12695     }
12696   else
12697     {
12698       if (target_big_endian)
12699         noop = arm_bigend_noop;
12700       else
12701         noop = arm_noop;
12702       noop_size = sizeof (arm_noop);
12703     }
12704
12705   if (bytes & (noop_size - 1))
12706     {
12707       fix = bytes & (noop_size - 1);
12708       memset (p, 0, fix);
12709       p += fix;
12710       bytes -= fix;
12711     }
12712
12713   while (bytes >= noop_size)
12714     {
12715       memcpy (p, noop, noop_size);
12716       p += noop_size;
12717       bytes -= noop_size;
12718       fix += noop_size;
12719     }
12720
12721   fragP->fr_fix += fix;
12722   fragP->fr_var = noop_size;
12723 }
12724
12725 /* Called from md_do_align.  Used to create an alignment
12726    frag in a code section.  */
12727
12728 void
12729 arm_frag_align_code (n, max)
12730      int n;
12731      int max;
12732 {
12733   char * p;
12734
12735   /* We assume that there will never be a requirment
12736      to support alignments greater than 32 bytes.  */
12737   if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
12738     as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
12739
12740   p = frag_var (rs_align_code,
12741                 MAX_MEM_FOR_RS_ALIGN_CODE,
12742                 1,
12743                 (relax_substateT) max,
12744                 (symbolS *) NULL,
12745                 (offsetT) n,
12746                 (char *) NULL);
12747   *p = 0;
12748
12749 }
12750
12751 /* Perform target specific initialisation of a frag.  */
12752
12753 void
12754 arm_init_frag (fragP)
12755      fragS *fragP;
12756 {
12757   /* Record whether this frag is in an ARM or a THUMB area.  */
12758   fragP->tc_frag_data = thumb_mode;
12759 }