xref: /openbsd/gnu/usr.bin/binutils/gas/config/tc-arm.c (revision 007c2a45)
1 /* tc-arm.c -- Assemble for the ARM
2    Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
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 	Cirrus coprocessor fixes by Petko Manolov (petkan@nucleusys.com)
8 	Cirrus coprocessor fixes by Vladimir Ivanov (vladitx@nucleusys.com)
9 
10    This file is part of GAS, the GNU Assembler.
11 
12    GAS is free software; you can redistribute it and/or modify
13    it under the terms of the GNU General Public License as published by
14    the Free Software Foundation; either version 2, or (at your option)
15    any later version.
16 
17    GAS is distributed in the hope that it will be useful,
18    but WITHOUT ANY WARRANTY; without even the implied warranty of
19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20    GNU General Public License for more details.
21 
22    You should have received a copy of the GNU General Public License
23    along with GAS; see the file COPYING.  If not, write to the Free
24    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
25    02111-1307, USA.  */
26 
27 #include <string.h>
28 #define  NO_RELOC 0
29 #include "as.h"
30 #include "safe-ctype.h"
31 
32 /* Need TARGET_CPU.  */
33 #include "config.h"
34 #include "subsegs.h"
35 #include "obstack.h"
36 #include "symbols.h"
37 #include "listing.h"
38 
39 #ifdef OBJ_ELF
40 #include "elf/arm.h"
41 #include "dwarf2dbg.h"
42 #endif
43 
44 /* XXX Set this to 1 after the next binutils release */
45 #define WARN_DEPRECATED 0
46 
47 /* The following bitmasks control CPU extensions:  */
48 #define ARM_EXT_V1	 0x00000001	/* All processors (core set).  */
49 #define ARM_EXT_V2	 0x00000002	/* Multiply instructions.  */
50 #define ARM_EXT_V2S	 0x00000004	/* SWP instructions.       */
51 #define ARM_EXT_V3	 0x00000008	/* MSR MRS.                */
52 #define ARM_EXT_V3M	 0x00000010	/* Allow long multiplies.  */
53 #define ARM_EXT_V4	 0x00000020	/* Allow half word loads.  */
54 #define ARM_EXT_V4T	 0x00000040	/* Thumb v1.               */
55 #define ARM_EXT_V5	 0x00000080	/* Allow CLZ, etc.         */
56 #define ARM_EXT_V5T	 0x00000100	/* Thumb v2.               */
57 #define ARM_EXT_V5ExP	 0x00000200	/* DSP core set.           */
58 #define ARM_EXT_V5E	 0x00000400	/* DSP Double transfers.   */
59 #define ARM_EXT_V5J	 0x00000800	/* Jazelle extension.	   */
60 #define ARM_EXT_V6       0x00001000     /* ARM V6.                 */
61 
62 /* Co-processor space extensions.  */
63 #define ARM_CEXT_XSCALE   0x00800000	/* Allow MIA etc.          */
64 #define ARM_CEXT_MAVERICK 0x00400000	/* Use Cirrus/DSP coprocessor.  */
65 #define ARM_CEXT_IWMMXT   0x00200000    /* Intel Wireless MMX technology coprocessor.   */
66 
67 /* Architectures are the sum of the base and extensions.  The ARM ARM (rev E)
68    defines the following: ARMv3, ARMv3M, ARMv4xM, ARMv4, ARMv4TxM, ARMv4T,
69    ARMv5xM, ARMv5, ARMv5TxM, ARMv5T, ARMv5TExP, ARMv5TE.  To these we add
70    three more to cover cores prior to ARM6.  Finally, there are cores which
71    implement further extensions in the co-processor space.  */
72 #define ARM_ARCH_V1			  ARM_EXT_V1
73 #define ARM_ARCH_V2	(ARM_ARCH_V1	| ARM_EXT_V2)
74 #define ARM_ARCH_V2S	(ARM_ARCH_V2	| ARM_EXT_V2S)
75 #define ARM_ARCH_V3	(ARM_ARCH_V2S	| ARM_EXT_V3)
76 #define ARM_ARCH_V3M	(ARM_ARCH_V3	| ARM_EXT_V3M)
77 #define ARM_ARCH_V4xM	(ARM_ARCH_V3	| ARM_EXT_V4)
78 #define ARM_ARCH_V4	(ARM_ARCH_V3M	| ARM_EXT_V4)
79 #define ARM_ARCH_V4TxM	(ARM_ARCH_V4xM	| ARM_EXT_V4T)
80 #define ARM_ARCH_V4T	(ARM_ARCH_V4	| ARM_EXT_V4T)
81 #define ARM_ARCH_V5xM	(ARM_ARCH_V4xM	| ARM_EXT_V5)
82 #define ARM_ARCH_V5	(ARM_ARCH_V4	| ARM_EXT_V5)
83 #define ARM_ARCH_V5TxM	(ARM_ARCH_V5xM	| ARM_EXT_V4T | ARM_EXT_V5T)
84 #define ARM_ARCH_V5T	(ARM_ARCH_V5	| ARM_EXT_V4T | ARM_EXT_V5T)
85 #define ARM_ARCH_V5TExP	(ARM_ARCH_V5T	| ARM_EXT_V5ExP)
86 #define ARM_ARCH_V5TE	(ARM_ARCH_V5TExP | ARM_EXT_V5E)
87 #define ARM_ARCH_V5TEJ	(ARM_ARCH_V5TE	| ARM_EXT_V5J)
88 #define ARM_ARCH_V6     (ARM_ARCH_V5TEJ | ARM_EXT_V6)
89 
90 /* Processors with specific extensions in the co-processor space.  */
91 #define ARM_ARCH_XSCALE	(ARM_ARCH_V5TE	| ARM_CEXT_XSCALE)
92 #define ARM_ARCH_IWMMXT	(ARM_ARCH_XSCALE | ARM_CEXT_IWMMXT)
93 
94 /* Some useful combinations:  */
95 #define ARM_ANY		0x0000ffff	/* Any basic core.  */
96 #define ARM_ALL		0x00ffffff	/* Any core + co-processor */
97 #define CPROC_ANY	0x00ff0000	/* Any co-processor */
98 #define FPU_ANY		0xff000000	/* Note this is ~ARM_ALL.  */
99 
100 
101 #define FPU_FPA_EXT_V1	 0x80000000	/* Base FPA instruction set.  */
102 #define FPU_FPA_EXT_V2	 0x40000000	/* LFM/SFM.		      */
103 #define FPU_VFP_EXT_NONE 0x20000000	/* Use VFP word-ordering.     */
104 #define FPU_VFP_EXT_V1xD 0x10000000	/* Base VFP instruction set.  */
105 #define FPU_VFP_EXT_V1	 0x08000000	/* Double-precision insns.    */
106 #define FPU_VFP_EXT_V2	 0x04000000	/* ARM10E VFPr1.	      */
107 #define FPU_MAVERICK	 0x02000000	/* Cirrus Maverick.	      */
108 #define FPU_NONE	 0
109 
110 #define FPU_ARCH_FPE	 FPU_FPA_EXT_V1
111 #define FPU_ARCH_FPA	(FPU_ARCH_FPE | FPU_FPA_EXT_V2)
112 
113 #define FPU_ARCH_VFP       FPU_VFP_EXT_NONE
114 #define FPU_ARCH_VFP_V1xD (FPU_VFP_EXT_V1xD | FPU_VFP_EXT_NONE)
115 #define FPU_ARCH_VFP_V1   (FPU_ARCH_VFP_V1xD | FPU_VFP_EXT_V1)
116 #define FPU_ARCH_VFP_V2	  (FPU_ARCH_VFP_V1 | FPU_VFP_EXT_V2)
117 
118 #define FPU_ARCH_MAVERICK  FPU_MAVERICK
119 
120 enum arm_float_abi
121 {
122   ARM_FLOAT_ABI_HARD,
123   ARM_FLOAT_ABI_SOFTFP,
124   ARM_FLOAT_ABI_SOFT
125 };
126 
127 /* Types of processor to assemble for.  */
128 #define ARM_1		ARM_ARCH_V1
129 #define ARM_2		ARM_ARCH_V2
130 #define ARM_3		ARM_ARCH_V2S
131 #define ARM_250		ARM_ARCH_V2S
132 #define ARM_6		ARM_ARCH_V3
133 #define ARM_7		ARM_ARCH_V3
134 #define ARM_8		ARM_ARCH_V4
135 #define ARM_9		ARM_ARCH_V4T
136 #define ARM_STRONG	ARM_ARCH_V4
137 #define ARM_CPU_MASK	0x0000000f              /* XXX? */
138 
139 #ifndef CPU_DEFAULT
140 #if defined __XSCALE__
141 #define CPU_DEFAULT	(ARM_ARCH_XSCALE)
142 #else
143 #if defined __thumb__
144 #define CPU_DEFAULT 	(ARM_ARCH_V5T)
145 #else
146 #define CPU_DEFAULT 	ARM_ANY
147 #endif
148 #endif
149 #endif
150 
151 #ifdef TE_LINUX
152 #define FPU_DEFAULT FPU_ARCH_FPA
153 #endif
154 
155 #if defined(TE_NetBSD) || defined(TE_OpenBSD)
156 #ifdef OBJ_ELF
157 #define FPU_DEFAULT FPU_ARCH_VFP	/* Soft-float, but VFP order.  */
158 #else
159 /* Legacy a.out format.  */
160 #define FPU_DEFAULT FPU_ARCH_FPA	/* Soft-float, but FPA order.  */
161 #endif
162 #endif
163 
164 /* For backwards compatibility we default to the FPA.  */
165 #ifndef FPU_DEFAULT
166 #define FPU_DEFAULT FPU_ARCH_FPA
167 #endif
168 
169 #define streq(a, b)           (strcmp (a, b) == 0)
170 #define skip_whitespace(str)  while (*(str) == ' ') ++(str)
171 
172 static unsigned long cpu_variant;
173 static int target_oabi = 0;
174 
175 /* Flags stored in private area of BFD structure.  */
176 static int uses_apcs_26      = FALSE;
177 static int atpcs             = FALSE;
178 static int support_interwork = FALSE;
179 static int uses_apcs_float   = FALSE;
180 static int pic_code          = FALSE;
181 
182 /* Variables that we set while parsing command-line options.  Once all
183    options have been read we re-process these values to set the real
184    assembly flags.  */
185 static int legacy_cpu = -1;
186 static int legacy_fpu = -1;
187 
188 static int mcpu_cpu_opt = -1;
189 static int mcpu_fpu_opt = -1;
190 static int march_cpu_opt = -1;
191 static int march_fpu_opt = -1;
192 static int mfpu_opt = -1;
193 static int mfloat_abi_opt = -1;
194 
195 /* This array holds the chars that always start a comment.  If the
196    pre-processor is disabled, these aren't very useful.  */
197 const char comment_chars[] = "@";
198 
199 /* This array holds the chars that only start a comment at the beginning of
200    a line.  If the line seems to have the form '# 123 filename'
201    .line and .file directives will appear in the pre-processed output.  */
202 /* Note that input_file.c hand checks for '#' at the beginning of the
203    first line of the input file.  This is because the compiler outputs
204    #NO_APP at the beginning of its output.  */
205 /* Also note that comments like this one will always work.  */
206 const char line_comment_chars[] = "#";
207 
208 const char line_separator_chars[] = ";";
209 
210 /* Chars that can be used to separate mant
211    from exp in floating point numbers.  */
212 const char EXP_CHARS[] = "eE";
213 
214 /* Chars that mean this number is a floating point constant.  */
215 /* As in 0f12.456  */
216 /* or    0d1.2345e12  */
217 
218 const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
219 
220 /* Prefix characters that indicate the start of an immediate
221    value.  */
222 #define is_immediate_prefix(C) ((C) == '#' || (C) == '$')
223 
224 #ifdef OBJ_ELF
225 /* Pre-defined "_GLOBAL_OFFSET_TABLE_"  */
226 symbolS * GOT_symbol;
227 #endif
228 
229 /* Size of relocation record.  */
230 const int md_reloc_size = 8;
231 
232 /* 0: assemble for ARM,
233    1: assemble for Thumb,
234    2: assemble for Thumb even though target CPU does not support thumb
235       instructions.  */
236 static int thumb_mode = 0;
237 
238 typedef struct arm_fix
239 {
240   int thumb_mode;
241 } arm_fix_data;
242 
243 struct arm_it
244 {
245   const char *  error;
246   unsigned long instruction;
247   int           size;
248   struct
249   {
250     bfd_reloc_code_real_type type;
251     expressionS              exp;
252     int                      pc_rel;
253   } reloc;
254 };
255 
256 struct arm_it inst;
257 
258 enum asm_shift_index
259 {
260   SHIFT_LSL = 0,
261   SHIFT_LSR,
262   SHIFT_ASR,
263   SHIFT_ROR,
264   SHIFT_RRX
265 };
266 
267 struct asm_shift_properties
268 {
269   enum asm_shift_index index;
270   unsigned long        bit_field;
271   unsigned int         allows_0  : 1;
272   unsigned int         allows_32 : 1;
273 };
274 
275 static const struct asm_shift_properties shift_properties [] =
276 {
277   { SHIFT_LSL, 0,    1, 0},
278   { SHIFT_LSR, 0x20, 0, 1},
279   { SHIFT_ASR, 0x40, 0, 1},
280   { SHIFT_ROR, 0x60, 0, 0},
281   { SHIFT_RRX, 0x60, 0, 0}
282 };
283 
284 struct asm_shift_name
285 {
286   const char *                        name;
287   const struct asm_shift_properties * properties;
288 };
289 
290 static const struct asm_shift_name shift_names [] =
291 {
292   { "asl", shift_properties + SHIFT_LSL },
293   { "lsl", shift_properties + SHIFT_LSL },
294   { "lsr", shift_properties + SHIFT_LSR },
295   { "asr", shift_properties + SHIFT_ASR },
296   { "ror", shift_properties + SHIFT_ROR },
297   { "rrx", shift_properties + SHIFT_RRX },
298   { "ASL", shift_properties + SHIFT_LSL },
299   { "LSL", shift_properties + SHIFT_LSL },
300   { "LSR", shift_properties + SHIFT_LSR },
301   { "ASR", shift_properties + SHIFT_ASR },
302   { "ROR", shift_properties + SHIFT_ROR },
303   { "RRX", shift_properties + SHIFT_RRX }
304 };
305 
306 /* Any kind of shift is accepted.  */
307 #define NO_SHIFT_RESTRICT 1
308 /* The shift operand must be an immediate value, not a register.  */
309 #define SHIFT_IMMEDIATE	  0
310 /* The shift must be LSL or ASR and the operand must be an immediate.  */
311 #define SHIFT_LSL_OR_ASR_IMMEDIATE 2
312 /* The shift must be ASR and the operand must be an immediate.  */
313 #define SHIFT_ASR_IMMEDIATE 3
314 /* The shift must be LSL and the operand must be an immediate.  */
315 #define SHIFT_LSL_IMMEDIATE 4
316 
317 #define NUM_FLOAT_VALS 8
318 
319 const char * fp_const[] =
320 {
321   "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
322 };
323 
324 /* Number of littlenums required to hold an extended precision number.  */
325 #define MAX_LITTLENUMS 6
326 
327 LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
328 
329 #define FAIL	(-1)
330 #define SUCCESS (0)
331 
332 /* Whether a Co-processor load/store operation accepts write-back forms.  */
333 #define CP_WB_OK 1
334 #define CP_NO_WB 0
335 
336 #define SUFF_S 1
337 #define SUFF_D 2
338 #define SUFF_E 3
339 #define SUFF_P 4
340 
341 #define CP_T_X   0x00008000
342 #define CP_T_Y   0x00400000
343 #define CP_T_Pre 0x01000000
344 #define CP_T_UD  0x00800000
345 #define CP_T_WB  0x00200000
346 
347 #define CONDS_BIT        0x00100000
348 #define LOAD_BIT         0x00100000
349 
350 #define DOUBLE_LOAD_FLAG 0x00000001
351 
352 struct asm_cond
353 {
354   const char *  template;
355   unsigned long value;
356 };
357 
358 #define COND_ALWAYS 0xe0000000
359 #define COND_MASK   0xf0000000
360 
361 static const struct asm_cond conds[] =
362 {
363   {"eq", 0x00000000},
364   {"ne", 0x10000000},
365   {"cs", 0x20000000}, {"hs", 0x20000000},
366   {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
367   {"mi", 0x40000000},
368   {"pl", 0x50000000},
369   {"vs", 0x60000000},
370   {"vc", 0x70000000},
371   {"hi", 0x80000000},
372   {"ls", 0x90000000},
373   {"ge", 0xa0000000},
374   {"lt", 0xb0000000},
375   {"gt", 0xc0000000},
376   {"le", 0xd0000000},
377   {"al", 0xe0000000},
378   {"nv", 0xf0000000}
379 };
380 
381 struct asm_psr
382 {
383   const char *template;
384   bfd_boolean cpsr;
385   unsigned long field;
386 };
387 
388 /* The bit that distinguishes CPSR and SPSR.  */
389 #define SPSR_BIT   (1 << 22)
390 
391 /* How many bits to shift the PSR_xxx bits up by.  */
392 #define PSR_SHIFT  16
393 
394 #define PSR_c   (1 << 0)
395 #define PSR_x   (1 << 1)
396 #define PSR_s   (1 << 2)
397 #define PSR_f   (1 << 3)
398 
399 static const struct asm_psr psrs[] =
400 {
401   {"CPSR",	TRUE,  PSR_c | PSR_f},
402   {"CPSR_all",	TRUE,  PSR_c | PSR_f},
403   {"SPSR",	FALSE, PSR_c | PSR_f},
404   {"SPSR_all",	FALSE, PSR_c | PSR_f},
405   {"CPSR_flg",	TRUE,  PSR_f},
406   {"CPSR_f",    TRUE,  PSR_f},
407   {"SPSR_flg",	FALSE, PSR_f},
408   {"SPSR_f",    FALSE, PSR_f},
409   {"CPSR_c",	TRUE,  PSR_c},
410   {"CPSR_ctl",	TRUE,  PSR_c},
411   {"SPSR_c",	FALSE, PSR_c},
412   {"SPSR_ctl",	FALSE, PSR_c},
413   {"CPSR_x",    TRUE,  PSR_x},
414   {"CPSR_s",    TRUE,  PSR_s},
415   {"SPSR_x",    FALSE, PSR_x},
416   {"SPSR_s",    FALSE, PSR_s},
417   /* Combinations of flags.  */
418   {"CPSR_fs",	TRUE, PSR_f | PSR_s},
419   {"CPSR_fx",	TRUE, PSR_f | PSR_x},
420   {"CPSR_fc",	TRUE, PSR_f | PSR_c},
421   {"CPSR_sf",	TRUE, PSR_s | PSR_f},
422   {"CPSR_sx",	TRUE, PSR_s | PSR_x},
423   {"CPSR_sc",	TRUE, PSR_s | PSR_c},
424   {"CPSR_xf",	TRUE, PSR_x | PSR_f},
425   {"CPSR_xs",	TRUE, PSR_x | PSR_s},
426   {"CPSR_xc",	TRUE, PSR_x | PSR_c},
427   {"CPSR_cf",	TRUE, PSR_c | PSR_f},
428   {"CPSR_cs",	TRUE, PSR_c | PSR_s},
429   {"CPSR_cx",	TRUE, PSR_c | PSR_x},
430   {"CPSR_fsx",	TRUE, PSR_f | PSR_s | PSR_x},
431   {"CPSR_fsc",	TRUE, PSR_f | PSR_s | PSR_c},
432   {"CPSR_fxs",	TRUE, PSR_f | PSR_x | PSR_s},
433   {"CPSR_fxc",	TRUE, PSR_f | PSR_x | PSR_c},
434   {"CPSR_fcs",	TRUE, PSR_f | PSR_c | PSR_s},
435   {"CPSR_fcx",	TRUE, PSR_f | PSR_c | PSR_x},
436   {"CPSR_sfx",	TRUE, PSR_s | PSR_f | PSR_x},
437   {"CPSR_sfc",	TRUE, PSR_s | PSR_f | PSR_c},
438   {"CPSR_sxf",	TRUE, PSR_s | PSR_x | PSR_f},
439   {"CPSR_sxc",	TRUE, PSR_s | PSR_x | PSR_c},
440   {"CPSR_scf",	TRUE, PSR_s | PSR_c | PSR_f},
441   {"CPSR_scx",	TRUE, PSR_s | PSR_c | PSR_x},
442   {"CPSR_xfs",	TRUE, PSR_x | PSR_f | PSR_s},
443   {"CPSR_xfc",	TRUE, PSR_x | PSR_f | PSR_c},
444   {"CPSR_xsf",	TRUE, PSR_x | PSR_s | PSR_f},
445   {"CPSR_xsc",	TRUE, PSR_x | PSR_s | PSR_c},
446   {"CPSR_xcf",	TRUE, PSR_x | PSR_c | PSR_f},
447   {"CPSR_xcs",	TRUE, PSR_x | PSR_c | PSR_s},
448   {"CPSR_cfs",	TRUE, PSR_c | PSR_f | PSR_s},
449   {"CPSR_cfx",	TRUE, PSR_c | PSR_f | PSR_x},
450   {"CPSR_csf",	TRUE, PSR_c | PSR_s | PSR_f},
451   {"CPSR_csx",	TRUE, PSR_c | PSR_s | PSR_x},
452   {"CPSR_cxf",	TRUE, PSR_c | PSR_x | PSR_f},
453   {"CPSR_cxs",	TRUE, PSR_c | PSR_x | PSR_s},
454   {"CPSR_fsxc",	TRUE, PSR_f | PSR_s | PSR_x | PSR_c},
455   {"CPSR_fscx",	TRUE, PSR_f | PSR_s | PSR_c | PSR_x},
456   {"CPSR_fxsc",	TRUE, PSR_f | PSR_x | PSR_s | PSR_c},
457   {"CPSR_fxcs",	TRUE, PSR_f | PSR_x | PSR_c | PSR_s},
458   {"CPSR_fcsx",	TRUE, PSR_f | PSR_c | PSR_s | PSR_x},
459   {"CPSR_fcxs",	TRUE, PSR_f | PSR_c | PSR_x | PSR_s},
460   {"CPSR_sfxc",	TRUE, PSR_s | PSR_f | PSR_x | PSR_c},
461   {"CPSR_sfcx",	TRUE, PSR_s | PSR_f | PSR_c | PSR_x},
462   {"CPSR_sxfc",	TRUE, PSR_s | PSR_x | PSR_f | PSR_c},
463   {"CPSR_sxcf",	TRUE, PSR_s | PSR_x | PSR_c | PSR_f},
464   {"CPSR_scfx",	TRUE, PSR_s | PSR_c | PSR_f | PSR_x},
465   {"CPSR_scxf",	TRUE, PSR_s | PSR_c | PSR_x | PSR_f},
466   {"CPSR_xfsc",	TRUE, PSR_x | PSR_f | PSR_s | PSR_c},
467   {"CPSR_xfcs",	TRUE, PSR_x | PSR_f | PSR_c | PSR_s},
468   {"CPSR_xsfc",	TRUE, PSR_x | PSR_s | PSR_f | PSR_c},
469   {"CPSR_xscf",	TRUE, PSR_x | PSR_s | PSR_c | PSR_f},
470   {"CPSR_xcfs",	TRUE, PSR_x | PSR_c | PSR_f | PSR_s},
471   {"CPSR_xcsf",	TRUE, PSR_x | PSR_c | PSR_s | PSR_f},
472   {"CPSR_cfsx",	TRUE, PSR_c | PSR_f | PSR_s | PSR_x},
473   {"CPSR_cfxs",	TRUE, PSR_c | PSR_f | PSR_x | PSR_s},
474   {"CPSR_csfx",	TRUE, PSR_c | PSR_s | PSR_f | PSR_x},
475   {"CPSR_csxf",	TRUE, PSR_c | PSR_s | PSR_x | PSR_f},
476   {"CPSR_cxfs",	TRUE, PSR_c | PSR_x | PSR_f | PSR_s},
477   {"CPSR_cxsf",	TRUE, PSR_c | PSR_x | PSR_s | PSR_f},
478   {"SPSR_fs",	FALSE, PSR_f | PSR_s},
479   {"SPSR_fx",	FALSE, PSR_f | PSR_x},
480   {"SPSR_fc",	FALSE, PSR_f | PSR_c},
481   {"SPSR_sf",	FALSE, PSR_s | PSR_f},
482   {"SPSR_sx",	FALSE, PSR_s | PSR_x},
483   {"SPSR_sc",	FALSE, PSR_s | PSR_c},
484   {"SPSR_xf",	FALSE, PSR_x | PSR_f},
485   {"SPSR_xs",	FALSE, PSR_x | PSR_s},
486   {"SPSR_xc",	FALSE, PSR_x | PSR_c},
487   {"SPSR_cf",	FALSE, PSR_c | PSR_f},
488   {"SPSR_cs",	FALSE, PSR_c | PSR_s},
489   {"SPSR_cx",	FALSE, PSR_c | PSR_x},
490   {"SPSR_fsx",	FALSE, PSR_f | PSR_s | PSR_x},
491   {"SPSR_fsc",	FALSE, PSR_f | PSR_s | PSR_c},
492   {"SPSR_fxs",	FALSE, PSR_f | PSR_x | PSR_s},
493   {"SPSR_fxc",	FALSE, PSR_f | PSR_x | PSR_c},
494   {"SPSR_fcs",	FALSE, PSR_f | PSR_c | PSR_s},
495   {"SPSR_fcx",	FALSE, PSR_f | PSR_c | PSR_x},
496   {"SPSR_sfx",	FALSE, PSR_s | PSR_f | PSR_x},
497   {"SPSR_sfc",	FALSE, PSR_s | PSR_f | PSR_c},
498   {"SPSR_sxf",	FALSE, PSR_s | PSR_x | PSR_f},
499   {"SPSR_sxc",	FALSE, PSR_s | PSR_x | PSR_c},
500   {"SPSR_scf",	FALSE, PSR_s | PSR_c | PSR_f},
501   {"SPSR_scx",	FALSE, PSR_s | PSR_c | PSR_x},
502   {"SPSR_xfs",	FALSE, PSR_x | PSR_f | PSR_s},
503   {"SPSR_xfc",	FALSE, PSR_x | PSR_f | PSR_c},
504   {"SPSR_xsf",	FALSE, PSR_x | PSR_s | PSR_f},
505   {"SPSR_xsc",	FALSE, PSR_x | PSR_s | PSR_c},
506   {"SPSR_xcf",	FALSE, PSR_x | PSR_c | PSR_f},
507   {"SPSR_xcs",	FALSE, PSR_x | PSR_c | PSR_s},
508   {"SPSR_cfs",	FALSE, PSR_c | PSR_f | PSR_s},
509   {"SPSR_cfx",	FALSE, PSR_c | PSR_f | PSR_x},
510   {"SPSR_csf",	FALSE, PSR_c | PSR_s | PSR_f},
511   {"SPSR_csx",	FALSE, PSR_c | PSR_s | PSR_x},
512   {"SPSR_cxf",	FALSE, PSR_c | PSR_x | PSR_f},
513   {"SPSR_cxs",	FALSE, PSR_c | PSR_x | PSR_s},
514   {"SPSR_fsxc",	FALSE, PSR_f | PSR_s | PSR_x | PSR_c},
515   {"SPSR_fscx",	FALSE, PSR_f | PSR_s | PSR_c | PSR_x},
516   {"SPSR_fxsc",	FALSE, PSR_f | PSR_x | PSR_s | PSR_c},
517   {"SPSR_fxcs",	FALSE, PSR_f | PSR_x | PSR_c | PSR_s},
518   {"SPSR_fcsx",	FALSE, PSR_f | PSR_c | PSR_s | PSR_x},
519   {"SPSR_fcxs",	FALSE, PSR_f | PSR_c | PSR_x | PSR_s},
520   {"SPSR_sfxc",	FALSE, PSR_s | PSR_f | PSR_x | PSR_c},
521   {"SPSR_sfcx",	FALSE, PSR_s | PSR_f | PSR_c | PSR_x},
522   {"SPSR_sxfc",	FALSE, PSR_s | PSR_x | PSR_f | PSR_c},
523   {"SPSR_sxcf",	FALSE, PSR_s | PSR_x | PSR_c | PSR_f},
524   {"SPSR_scfx",	FALSE, PSR_s | PSR_c | PSR_f | PSR_x},
525   {"SPSR_scxf",	FALSE, PSR_s | PSR_c | PSR_x | PSR_f},
526   {"SPSR_xfsc",	FALSE, PSR_x | PSR_f | PSR_s | PSR_c},
527   {"SPSR_xfcs",	FALSE, PSR_x | PSR_f | PSR_c | PSR_s},
528   {"SPSR_xsfc",	FALSE, PSR_x | PSR_s | PSR_f | PSR_c},
529   {"SPSR_xscf",	FALSE, PSR_x | PSR_s | PSR_c | PSR_f},
530   {"SPSR_xcfs",	FALSE, PSR_x | PSR_c | PSR_f | PSR_s},
531   {"SPSR_xcsf",	FALSE, PSR_x | PSR_c | PSR_s | PSR_f},
532   {"SPSR_cfsx",	FALSE, PSR_c | PSR_f | PSR_s | PSR_x},
533   {"SPSR_cfxs",	FALSE, PSR_c | PSR_f | PSR_x | PSR_s},
534   {"SPSR_csfx",	FALSE, PSR_c | PSR_s | PSR_f | PSR_x},
535   {"SPSR_csxf",	FALSE, PSR_c | PSR_s | PSR_x | PSR_f},
536   {"SPSR_cxfs",	FALSE, PSR_c | PSR_x | PSR_f | PSR_s},
537   {"SPSR_cxsf",	FALSE, PSR_c | PSR_x | PSR_s | PSR_f},
538 };
539 
540 enum wreg_type
541   {
542     IWMMXT_REG_WR = 0,
543     IWMMXT_REG_WC = 1,
544     IWMMXT_REG_WR_OR_WC = 2,
545     IWMMXT_REG_WCG
546   };
547 
548 enum iwmmxt_insn_type
549 {
550   check_rd,
551   check_wr,
552   check_wrwr,
553   check_wrwrwr,
554   check_wrwrwcg,
555   check_tbcst,
556   check_tmovmsk,
557   check_tmia,
558   check_tmcrr,
559   check_tmrrc,
560   check_tmcr,
561   check_tmrc,
562   check_tinsr,
563   check_textrc,
564   check_waligni,
565   check_textrm,
566   check_wshufh
567 };
568 
569 enum vfp_dp_reg_pos
570 {
571   VFP_REG_Dd, VFP_REG_Dm, VFP_REG_Dn
572 };
573 
574 enum vfp_sp_reg_pos
575 {
576   VFP_REG_Sd, VFP_REG_Sm, VFP_REG_Sn
577 };
578 
579 enum vfp_ldstm_type
580 {
581   VFP_LDSTMIA, VFP_LDSTMDB, VFP_LDSTMIAX, VFP_LDSTMDBX
582 };
583 
584 /* VFP system registers.  */
585 struct vfp_reg
586 {
587   const char *name;
588   unsigned long regno;
589 };
590 
591 static const struct vfp_reg vfp_regs[] =
592 {
593   {"fpsid", 0x00000000},
594   {"FPSID", 0x00000000},
595   {"fpscr", 0x00010000},
596   {"FPSCR", 0x00010000},
597   {"fpexc", 0x00080000},
598   {"FPEXC", 0x00080000}
599 };
600 
601 /* Structure for a hash table entry for a register.  */
602 struct reg_entry
603 {
604   const char * name;
605   int          number;
606   bfd_boolean  builtin;
607 };
608 
609 /* Some well known registers that we refer to directly elsewhere.  */
610 #define REG_SP  13
611 #define REG_LR  14
612 #define REG_PC	15
613 
614 #define wr_register(reg)  ((reg ^ WR_PREFIX) >= 0 && (reg ^ WR_PREFIX) <= 15)
615 #define wc_register(reg)  ((reg ^ WC_PREFIX) >= 0 && (reg ^ WC_PREFIX) <= 15)
616 #define wcg_register(reg) ((reg ^ WC_PREFIX) >= 8 && (reg ^ WC_PREFIX) <= 11)
617 
618 /* These are the standard names.  Users can add aliases with .req.
619    and delete them with .unreq.  */
620 
621 /* Integer Register Numbers.  */
622 static const struct reg_entry rn_table[] =
623 {
624   {"r0",  0, TRUE},  {"r1",  1, TRUE},      {"r2",  2, TRUE},      {"r3",  3, TRUE},
625   {"r4",  4, TRUE},  {"r5",  5, TRUE},      {"r6",  6, TRUE},      {"r7",  7, TRUE},
626   {"r8",  8, TRUE},  {"r9",  9, TRUE},      {"r10", 10, TRUE},     {"r11", 11, TRUE},
627   {"r12", 12, TRUE}, {"r13", REG_SP, TRUE}, {"r14", REG_LR, TRUE}, {"r15", REG_PC, TRUE},
628   /* ATPCS Synonyms.  */
629   {"a1",  0, TRUE},  {"a2",  1, TRUE},      {"a3",  2, TRUE},      {"a4",  3, TRUE},
630   {"v1",  4, TRUE},  {"v2",  5, TRUE},      {"v3",  6, TRUE},      {"v4",  7, TRUE},
631   {"v5",  8, TRUE},  {"v6",  9, TRUE},      {"v7",  10, TRUE},     {"v8",  11, TRUE},
632   /* Well-known aliases.  */
633   {"wr",  7, TRUE},  {"sb",  9, TRUE},      {"sl",  10, TRUE},     {"fp",  11, TRUE},
634   {"ip",  12, TRUE}, {"sp",  REG_SP, TRUE}, {"lr",  REG_LR, TRUE}, {"pc",  REG_PC, TRUE},
635   {NULL, 0, TRUE}
636 };
637 
638 #define WR_PREFIX 0x200
639 #define WC_PREFIX 0x400
640 
641 static const struct reg_entry iwmmxt_table[] =
642 {
643   /* Intel Wireless MMX technology register names.  */
644   {  "wr0", 0x0 | WR_PREFIX, TRUE},   {"wr1", 0x1 | WR_PREFIX, TRUE},
645   {  "wr2", 0x2 | WR_PREFIX, TRUE},   {"wr3", 0x3 | WR_PREFIX, TRUE},
646   {  "wr4", 0x4 | WR_PREFIX, TRUE},   {"wr5", 0x5 | WR_PREFIX, TRUE},
647   {  "wr6", 0x6 | WR_PREFIX, TRUE},   {"wr7", 0x7 | WR_PREFIX, TRUE},
648   {  "wr8", 0x8 | WR_PREFIX, TRUE},   {"wr9", 0x9 | WR_PREFIX, TRUE},
649   { "wr10", 0xa | WR_PREFIX, TRUE},  {"wr11", 0xb | WR_PREFIX, TRUE},
650   { "wr12", 0xc | WR_PREFIX, TRUE},  {"wr13", 0xd | WR_PREFIX, TRUE},
651   { "wr14", 0xe | WR_PREFIX, TRUE},  {"wr15", 0xf | WR_PREFIX, TRUE},
652   { "wcid", 0x0 | WC_PREFIX, TRUE},  {"wcon", 0x1 | WC_PREFIX, TRUE},
653   {"wcssf", 0x2 | WC_PREFIX, TRUE}, {"wcasf", 0x3 | WC_PREFIX, TRUE},
654   {"wcgr0", 0x8 | WC_PREFIX, TRUE}, {"wcgr1", 0x9 | WC_PREFIX, TRUE},
655   {"wcgr2", 0xa | WC_PREFIX, TRUE}, {"wcgr3", 0xb | WC_PREFIX, TRUE},
656 
657   {  "wR0", 0x0 | WR_PREFIX, TRUE},   {"wR1", 0x1 | WR_PREFIX, TRUE},
658   {  "wR2", 0x2 | WR_PREFIX, TRUE},   {"wR3", 0x3 | WR_PREFIX, TRUE},
659   {  "wR4", 0x4 | WR_PREFIX, TRUE},   {"wR5", 0x5 | WR_PREFIX, TRUE},
660   {  "wR6", 0x6 | WR_PREFIX, TRUE},   {"wR7", 0x7 | WR_PREFIX, TRUE},
661   {  "wR8", 0x8 | WR_PREFIX, TRUE},   {"wR9", 0x9 | WR_PREFIX, TRUE},
662   { "wR10", 0xa | WR_PREFIX, TRUE},  {"wR11", 0xb | WR_PREFIX, TRUE},
663   { "wR12", 0xc | WR_PREFIX, TRUE},  {"wR13", 0xd | WR_PREFIX, TRUE},
664   { "wR14", 0xe | WR_PREFIX, TRUE},  {"wR15", 0xf | WR_PREFIX, TRUE},
665   { "wCID", 0x0 | WC_PREFIX, TRUE},  {"wCon", 0x1 | WC_PREFIX, TRUE},
666   {"wCSSF", 0x2 | WC_PREFIX, TRUE}, {"wCASF", 0x3 | WC_PREFIX, TRUE},
667   {"wCGR0", 0x8 | WC_PREFIX, TRUE}, {"wCGR1", 0x9 | WC_PREFIX, TRUE},
668   {"wCGR2", 0xa | WC_PREFIX, TRUE}, {"wCGR3", 0xb | WC_PREFIX, TRUE},
669   {NULL, 0, TRUE}
670 };
671 
672 /* Co-processor Numbers.  */
673 static const struct reg_entry cp_table[] =
674 {
675   {"p0",  0, TRUE},  {"p1",  1, TRUE},  {"p2",  2, TRUE},  {"p3", 3, TRUE},
676   {"p4",  4, TRUE},  {"p5",  5, TRUE},  {"p6",  6, TRUE},  {"p7", 7, TRUE},
677   {"p8",  8, TRUE},  {"p9",  9, TRUE},  {"p10", 10, TRUE}, {"p11", 11, TRUE},
678   {"p12", 12, TRUE}, {"p13", 13, TRUE}, {"p14", 14, TRUE}, {"p15", 15, TRUE},
679   {NULL, 0, TRUE}
680 };
681 
682 /* Co-processor Register Numbers.  */
683 static const struct reg_entry cn_table[] =
684 {
685   {"c0",   0, TRUE},  {"c1",   1, TRUE},  {"c2",   2, TRUE},  {"c3",   3, TRUE},
686   {"c4",   4, TRUE},  {"c5",   5, TRUE},  {"c6",   6, TRUE},  {"c7",   7, TRUE},
687   {"c8",   8, TRUE},  {"c9",   9, TRUE},  {"c10",  10, TRUE}, {"c11",  11, TRUE},
688   {"c12",  12, TRUE}, {"c13",  13, TRUE}, {"c14",  14, TRUE}, {"c15",  15, TRUE},
689   /* Not really valid, but kept for back-wards compatibility.  */
690   {"cr0",  0, TRUE},  {"cr1",  1, TRUE},  {"cr2",  2, TRUE},  {"cr3",  3, TRUE},
691   {"cr4",  4, TRUE},  {"cr5",  5, TRUE},  {"cr6",  6, TRUE},  {"cr7",  7, TRUE},
692   {"cr8",  8, TRUE},  {"cr9",  9, TRUE},  {"cr10", 10, TRUE}, {"cr11", 11, TRUE},
693   {"cr12", 12, TRUE}, {"cr13", 13, TRUE}, {"cr14", 14, TRUE}, {"cr15", 15, TRUE},
694   {NULL, 0, TRUE}
695 };
696 
697 /* FPA Registers.  */
698 static const struct reg_entry fn_table[] =
699 {
700   {"f0", 0, TRUE},   {"f1", 1, TRUE},   {"f2", 2, TRUE},   {"f3", 3, TRUE},
701   {"f4", 4, TRUE},   {"f5", 5, TRUE},   {"f6", 6, TRUE},   {"f7", 7, TRUE},
702   {NULL, 0, TRUE}
703 };
704 
705 /* VFP SP Registers.  */
706 static const struct reg_entry sn_table[] =
707 {
708   {"s0",  0, TRUE},  {"s1",  1, TRUE},  {"s2",  2, TRUE},  {"s3", 3, TRUE},
709   {"s4",  4, TRUE},  {"s5",  5, TRUE},  {"s6",  6, TRUE},  {"s7", 7, TRUE},
710   {"s8",  8, TRUE},  {"s9",  9, TRUE},  {"s10", 10, TRUE}, {"s11", 11, TRUE},
711   {"s12", 12, TRUE}, {"s13", 13, TRUE}, {"s14", 14, TRUE}, {"s15", 15, TRUE},
712   {"s16", 16, TRUE}, {"s17", 17, TRUE}, {"s18", 18, TRUE}, {"s19", 19, TRUE},
713   {"s20", 20, TRUE}, {"s21", 21, TRUE}, {"s22", 22, TRUE}, {"s23", 23, TRUE},
714   {"s24", 24, TRUE}, {"s25", 25, TRUE}, {"s26", 26, TRUE}, {"s27", 27, TRUE},
715   {"s28", 28, TRUE}, {"s29", 29, TRUE}, {"s30", 30, TRUE}, {"s31", 31, TRUE},
716   {NULL, 0, TRUE}
717 };
718 
719 /* VFP DP Registers.  */
720 static const struct reg_entry dn_table[] =
721 {
722   {"d0",  0, TRUE},  {"d1",  1, TRUE},  {"d2",  2, TRUE},  {"d3", 3, TRUE},
723   {"d4",  4, TRUE},  {"d5",  5, TRUE},  {"d6",  6, TRUE},  {"d7", 7, TRUE},
724   {"d8",  8, TRUE},  {"d9",  9, TRUE},  {"d10", 10, TRUE}, {"d11", 11, TRUE},
725   {"d12", 12, TRUE}, {"d13", 13, TRUE}, {"d14", 14, TRUE}, {"d15", 15, TRUE},
726   {NULL, 0, TRUE}
727 };
728 
729 /* Maverick DSP coprocessor registers.  */
730 static const struct reg_entry mav_mvf_table[] =
731 {
732   {"mvf0",  0, TRUE},  {"mvf1",  1, TRUE},  {"mvf2",  2, TRUE},  {"mvf3",  3, TRUE},
733   {"mvf4",  4, TRUE},  {"mvf5",  5, TRUE},  {"mvf6",  6, TRUE},  {"mvf7",  7, TRUE},
734   {"mvf8",  8, TRUE},  {"mvf9",  9, TRUE},  {"mvf10", 10, TRUE}, {"mvf11", 11, TRUE},
735   {"mvf12", 12, TRUE}, {"mvf13", 13, TRUE}, {"mvf14", 14, TRUE}, {"mvf15", 15, TRUE},
736   {NULL, 0, TRUE}
737 };
738 
739 static const struct reg_entry mav_mvd_table[] =
740 {
741   {"mvd0",  0, TRUE},  {"mvd1",  1, TRUE},  {"mvd2",  2, TRUE},  {"mvd3",  3, TRUE},
742   {"mvd4",  4, TRUE},  {"mvd5",  5, TRUE},  {"mvd6",  6, TRUE},  {"mvd7",  7, TRUE},
743   {"mvd8",  8, TRUE},  {"mvd9",  9, TRUE},  {"mvd10", 10, TRUE}, {"mvd11", 11, TRUE},
744   {"mvd12", 12, TRUE}, {"mvd13", 13, TRUE}, {"mvd14", 14, TRUE}, {"mvd15", 15, TRUE},
745   {NULL, 0, TRUE}
746 };
747 
748 static const struct reg_entry mav_mvfx_table[] =
749 {
750   {"mvfx0",  0, TRUE},  {"mvfx1",  1, TRUE},  {"mvfx2",  2, TRUE},  {"mvfx3",  3, TRUE},
751   {"mvfx4",  4, TRUE},  {"mvfx5",  5, TRUE},  {"mvfx6",  6, TRUE},  {"mvfx7",  7, TRUE},
752   {"mvfx8",  8, TRUE},  {"mvfx9",  9, TRUE},  {"mvfx10", 10, TRUE}, {"mvfx11", 11, TRUE},
753   {"mvfx12", 12, TRUE}, {"mvfx13", 13, TRUE}, {"mvfx14", 14, TRUE}, {"mvfx15", 15, TRUE},
754   {NULL, 0, TRUE}
755 };
756 
757 static const struct reg_entry mav_mvdx_table[] =
758 {
759   {"mvdx0",  0, TRUE},  {"mvdx1",  1, TRUE},  {"mvdx2",  2, TRUE},  {"mvdx3",  3, TRUE},
760   {"mvdx4",  4, TRUE},  {"mvdx5",  5, TRUE},  {"mvdx6",  6, TRUE},  {"mvdx7",  7, TRUE},
761   {"mvdx8",  8, TRUE},  {"mvdx9",  9, TRUE},  {"mvdx10", 10, TRUE}, {"mvdx11", 11, TRUE},
762   {"mvdx12", 12, TRUE}, {"mvdx13", 13, TRUE}, {"mvdx14", 14, TRUE}, {"mvdx15", 15, TRUE},
763   {NULL, 0, TRUE}
764 };
765 
766 static const struct reg_entry mav_mvax_table[] =
767 {
768   {"mvax0", 0, TRUE}, {"mvax1", 1, TRUE}, {"mvax2", 2, TRUE}, {"mvax3", 3, TRUE},
769   {NULL, 0, TRUE}
770 };
771 
772 static const struct reg_entry mav_dspsc_table[] =
773 {
774   {"dspsc", 0, TRUE},
775   {NULL, 0, TRUE}
776 };
777 
778 struct reg_map
779 {
780   const struct reg_entry *names;
781   int max_regno;
782   struct hash_control *htab;
783   const char *expected;
784 };
785 
786 struct reg_map all_reg_maps[] =
787 {
788   {rn_table,        15, NULL, N_("ARM register expected")},
789   {cp_table,        15, NULL, N_("bad or missing co-processor number")},
790   {cn_table,        15, NULL, N_("co-processor register expected")},
791   {fn_table,         7, NULL, N_("FPA register expected")},
792   {sn_table,	    31, NULL, N_("VFP single precision register expected")},
793   {dn_table,	    15, NULL, N_("VFP double precision register expected")},
794   {mav_mvf_table,   15, NULL, N_("Maverick MVF register expected")},
795   {mav_mvd_table,   15, NULL, N_("Maverick MVD register expected")},
796   {mav_mvfx_table,  15, NULL, N_("Maverick MVFX register expected")},
797   {mav_mvdx_table,  15, NULL, N_("Maverick MVDX register expected")},
798   {mav_mvax_table,   3, NULL, N_("Maverick MVAX register expected")},
799   {mav_dspsc_table,  0, NULL, N_("Maverick DSPSC register expected")},
800   {iwmmxt_table,    23, NULL, N_("Intel Wireless MMX technology register expected")},
801 };
802 
803 /* Enumeration matching entries in table above.  */
804 enum arm_reg_type
805 {
806   REG_TYPE_RN = 0,
807 #define REG_TYPE_FIRST REG_TYPE_RN
808   REG_TYPE_CP = 1,
809   REG_TYPE_CN = 2,
810   REG_TYPE_FN = 3,
811   REG_TYPE_SN = 4,
812   REG_TYPE_DN = 5,
813   REG_TYPE_MVF = 6,
814   REG_TYPE_MVD = 7,
815   REG_TYPE_MVFX = 8,
816   REG_TYPE_MVDX = 9,
817   REG_TYPE_MVAX = 10,
818   REG_TYPE_DSPSC = 11,
819   REG_TYPE_IWMMXT = 12,
820 
821   REG_TYPE_MAX = 13
822 };
823 
824 /* Functions called by parser.  */
825 /* ARM instructions.  */
826 static void do_arit		PARAMS ((char *));
827 static void do_cmp		PARAMS ((char *));
828 static void do_mov		PARAMS ((char *));
829 static void do_ldst		PARAMS ((char *));
830 static void do_ldstt		PARAMS ((char *));
831 static void do_ldmstm		PARAMS ((char *));
832 static void do_branch		PARAMS ((char *));
833 static void do_swi		PARAMS ((char *));
834 
835 /* Pseudo Op codes.  */
836 static void do_adr		PARAMS ((char *));
837 static void do_adrl		PARAMS ((char *));
838 static void do_empty		PARAMS ((char *));
839 
840 /* ARM v2.  */
841 static void do_mul		PARAMS ((char *));
842 static void do_mla		PARAMS ((char *));
843 
844 /* ARM v2S.  */
845 static void do_swap		PARAMS ((char *));
846 
847 /* ARM v3.  */
848 static void do_msr		PARAMS ((char *));
849 static void do_mrs		PARAMS ((char *));
850 
851 /* ARM v3M.  */
852 static void do_mull		PARAMS ((char *));
853 
854 /* ARM v4.  */
855 static void do_ldstv4		PARAMS ((char *));
856 
857 /* ARM v4T.  */
858 static void do_bx               PARAMS ((char *));
859 
860 /* ARM v5T.  */
861 static void do_blx		PARAMS ((char *));
862 static void do_bkpt		PARAMS ((char *));
863 static void do_clz		PARAMS ((char *));
864 static void do_lstc2		PARAMS ((char *));
865 static void do_cdp2		PARAMS ((char *));
866 static void do_co_reg2		PARAMS ((char *));
867 
868 /* ARM v5TExP.  */
869 static void do_smla		PARAMS ((char *));
870 static void do_smlal		PARAMS ((char *));
871 static void do_smul		PARAMS ((char *));
872 static void do_qadd		PARAMS ((char *));
873 
874 /* ARM v5TE.  */
875 static void do_pld		PARAMS ((char *));
876 static void do_ldrd		PARAMS ((char *));
877 static void do_co_reg2c		PARAMS ((char *));
878 
879 /* ARM v5TEJ.  */
880 static void do_bxj		PARAMS ((char *));
881 
882 /* ARM V6. */
883 static void do_cps              PARAMS ((char *));
884 static void do_cpsi             PARAMS ((char *));
885 static void do_ldrex            PARAMS ((char *));
886 static void do_pkhbt            PARAMS ((char *));
887 static void do_pkhtb            PARAMS ((char *));
888 static void do_qadd16           PARAMS ((char *));
889 static void do_rev              PARAMS ((char *));
890 static void do_rfe              PARAMS ((char *));
891 static void do_sxtah            PARAMS ((char *));
892 static void do_sxth             PARAMS ((char *));
893 static void do_setend           PARAMS ((char *));
894 static void do_smlad            PARAMS ((char *));
895 static void do_smlald           PARAMS ((char *));
896 static void do_smmul            PARAMS ((char *));
897 static void do_ssat             PARAMS ((char *));
898 static void do_usat             PARAMS ((char *));
899 static void do_srs              PARAMS ((char *));
900 static void do_ssat16           PARAMS ((char *));
901 static void do_usat16           PARAMS ((char *));
902 static void do_strex            PARAMS ((char *));
903 static void do_umaal            PARAMS ((char *));
904 
905 static void do_cps_mode         PARAMS ((char **));
906 static void do_cps_flags        PARAMS ((char **, int));
907 static int do_endian_specifier  PARAMS ((char *));
908 static void do_pkh_core         PARAMS ((char *, int));
909 static void do_sat              PARAMS ((char **, int));
910 static void do_sat16            PARAMS ((char **, int));
911 
912 /* Coprocessor Instructions.  */
913 static void do_cdp		PARAMS ((char *));
914 static void do_lstc		PARAMS ((char *));
915 static void do_co_reg		PARAMS ((char *));
916 
917 /* FPA instructions.  */
918 static void do_fpa_ctrl		PARAMS ((char *));
919 static void do_fpa_ldst		PARAMS ((char *));
920 static void do_fpa_ldmstm	PARAMS ((char *));
921 static void do_fpa_dyadic	PARAMS ((char *));
922 static void do_fpa_monadic	PARAMS ((char *));
923 static void do_fpa_cmp		PARAMS ((char *));
924 static void do_fpa_from_reg	PARAMS ((char *));
925 static void do_fpa_to_reg	PARAMS ((char *));
926 
927 /* VFP instructions.  */
928 static void do_vfp_sp_monadic	PARAMS ((char *));
929 static void do_vfp_dp_monadic	PARAMS ((char *));
930 static void do_vfp_sp_dyadic	PARAMS ((char *));
931 static void do_vfp_dp_dyadic	PARAMS ((char *));
932 static void do_vfp_reg_from_sp  PARAMS ((char *));
933 static void do_vfp_sp_from_reg  PARAMS ((char *));
934 static void do_vfp_reg2_from_sp2 PARAMS ((char *));
935 static void do_vfp_sp2_from_reg2 PARAMS ((char *));
936 static void do_vfp_reg_from_dp  PARAMS ((char *));
937 static void do_vfp_reg2_from_dp PARAMS ((char *));
938 static void do_vfp_dp_from_reg  PARAMS ((char *));
939 static void do_vfp_dp_from_reg2 PARAMS ((char *));
940 static void do_vfp_reg_from_ctrl PARAMS ((char *));
941 static void do_vfp_ctrl_from_reg PARAMS ((char *));
942 static void do_vfp_sp_ldst	PARAMS ((char *));
943 static void do_vfp_dp_ldst	PARAMS ((char *));
944 static void do_vfp_sp_ldstmia	PARAMS ((char *));
945 static void do_vfp_sp_ldstmdb	PARAMS ((char *));
946 static void do_vfp_dp_ldstmia	PARAMS ((char *));
947 static void do_vfp_dp_ldstmdb	PARAMS ((char *));
948 static void do_vfp_xp_ldstmia	PARAMS ((char *));
949 static void do_vfp_xp_ldstmdb	PARAMS ((char *));
950 static void do_vfp_sp_compare_z	PARAMS ((char *));
951 static void do_vfp_dp_compare_z	PARAMS ((char *));
952 static void do_vfp_dp_sp_cvt	PARAMS ((char *));
953 static void do_vfp_sp_dp_cvt	PARAMS ((char *));
954 
955 /* XScale.  */
956 static void do_xsc_mia		PARAMS ((char *));
957 static void do_xsc_mar		PARAMS ((char *));
958 static void do_xsc_mra		PARAMS ((char *));
959 
960 /* Maverick.  */
961 static void do_mav_binops	PARAMS ((char *, int, enum arm_reg_type,
962 					 enum arm_reg_type));
963 static void do_mav_binops_1a	PARAMS ((char *));
964 static void do_mav_binops_1b	PARAMS ((char *));
965 static void do_mav_binops_1c	PARAMS ((char *));
966 static void do_mav_binops_1d	PARAMS ((char *));
967 static void do_mav_binops_1e	PARAMS ((char *));
968 static void do_mav_binops_1f	PARAMS ((char *));
969 static void do_mav_binops_1g	PARAMS ((char *));
970 static void do_mav_binops_1h	PARAMS ((char *));
971 static void do_mav_binops_1i	PARAMS ((char *));
972 static void do_mav_binops_1j	PARAMS ((char *));
973 static void do_mav_binops_1k	PARAMS ((char *));
974 static void do_mav_binops_1l	PARAMS ((char *));
975 static void do_mav_binops_1m	PARAMS ((char *));
976 static void do_mav_binops_1n	PARAMS ((char *));
977 static void do_mav_binops_1o	PARAMS ((char *));
978 static void do_mav_binops_2a	PARAMS ((char *));
979 static void do_mav_binops_2b	PARAMS ((char *));
980 static void do_mav_binops_2c	PARAMS ((char *));
981 static void do_mav_binops_3a	PARAMS ((char *));
982 static void do_mav_binops_3b	PARAMS ((char *));
983 static void do_mav_binops_3c	PARAMS ((char *));
984 static void do_mav_binops_3d	PARAMS ((char *));
985 static void do_mav_triple	PARAMS ((char *, int, enum arm_reg_type,
986 					 enum arm_reg_type,
987 					 enum arm_reg_type));
988 static void do_mav_triple_4a	PARAMS ((char *));
989 static void do_mav_triple_4b	PARAMS ((char *));
990 static void do_mav_triple_5a	PARAMS ((char *));
991 static void do_mav_triple_5b	PARAMS ((char *));
992 static void do_mav_triple_5c	PARAMS ((char *));
993 static void do_mav_triple_5d	PARAMS ((char *));
994 static void do_mav_triple_5e	PARAMS ((char *));
995 static void do_mav_triple_5f	PARAMS ((char *));
996 static void do_mav_triple_5g	PARAMS ((char *));
997 static void do_mav_triple_5h	PARAMS ((char *));
998 static void do_mav_quad		PARAMS ((char *, int, enum arm_reg_type,
999 					 enum arm_reg_type,
1000 					 enum arm_reg_type,
1001 					 enum arm_reg_type));
1002 static void do_mav_quad_6a	PARAMS ((char *));
1003 static void do_mav_quad_6b	PARAMS ((char *));
1004 static void do_mav_dspsc_1	PARAMS ((char *));
1005 static void do_mav_dspsc_2	PARAMS ((char *));
1006 static void do_mav_shift	PARAMS ((char *, enum arm_reg_type,
1007 					 enum arm_reg_type));
1008 static void do_mav_shift_1	PARAMS ((char *));
1009 static void do_mav_shift_2	PARAMS ((char *));
1010 static void do_mav_ldst		PARAMS ((char *, enum arm_reg_type));
1011 static void do_mav_ldst_1	PARAMS ((char *));
1012 static void do_mav_ldst_2	PARAMS ((char *));
1013 static void do_mav_ldst_3	PARAMS ((char *));
1014 static void do_mav_ldst_4	PARAMS ((char *));
1015 
1016 static int mav_reg_required_here	PARAMS ((char **, int,
1017 						 enum arm_reg_type));
1018 static int mav_parse_offset	PARAMS ((char **, int *));
1019 
1020 static void fix_new_arm		PARAMS ((fragS *, int, short, expressionS *,
1021 					 int, int));
1022 static int arm_reg_parse	PARAMS ((char **, struct hash_control *));
1023 static enum arm_reg_type arm_reg_parse_any PARAMS ((char *));
1024 static const struct asm_psr * arm_psr_parse PARAMS ((char **));
1025 static void symbol_locate	PARAMS ((symbolS *, const char *, segT, valueT,
1026 					 fragS *));
1027 static int add_to_lit_pool	PARAMS ((void));
1028 static unsigned validate_immediate PARAMS ((unsigned));
1029 static unsigned validate_immediate_twopart PARAMS ((unsigned int,
1030 						    unsigned int *));
1031 static int validate_offset_imm	PARAMS ((unsigned int, int));
1032 static void opcode_select	PARAMS ((int));
1033 static void end_of_line		PARAMS ((char *));
1034 static int reg_required_here	PARAMS ((char **, int));
1035 static int psr_required_here	PARAMS ((char **));
1036 static int co_proc_number	PARAMS ((char **));
1037 static int cp_opc_expr		PARAMS ((char **, int, int));
1038 static int cp_reg_required_here	PARAMS ((char **, int));
1039 static int fp_reg_required_here	PARAMS ((char **, int));
1040 static int vfp_sp_reg_required_here PARAMS ((char **, enum vfp_sp_reg_pos));
1041 static int vfp_dp_reg_required_here PARAMS ((char **, enum vfp_dp_reg_pos));
1042 static void vfp_sp_ldstm	PARAMS ((char *, enum vfp_ldstm_type));
1043 static void vfp_dp_ldstm	PARAMS ((char *, enum vfp_ldstm_type));
1044 static long vfp_sp_reg_list	PARAMS ((char **, enum vfp_sp_reg_pos));
1045 static long vfp_dp_reg_list	PARAMS ((char **));
1046 static int vfp_psr_required_here PARAMS ((char **str));
1047 static const struct vfp_reg *vfp_psr_parse PARAMS ((char **str));
1048 static int cp_address_offset	PARAMS ((char **));
1049 static int cp_address_required_here	PARAMS ((char **, int));
1050 static int my_get_float_expression	PARAMS ((char **));
1051 static int skip_past_comma	PARAMS ((char **));
1052 static int walk_no_bignums	PARAMS ((symbolS *));
1053 static int negate_data_op	PARAMS ((unsigned long *, unsigned long));
1054 static int data_op2		PARAMS ((char **));
1055 static int fp_op2		PARAMS ((char **));
1056 static long reg_list		PARAMS ((char **));
1057 static void thumb_load_store	PARAMS ((char *, int, int));
1058 static int decode_shift		PARAMS ((char **, int));
1059 static int ldst_extend		PARAMS ((char **));
1060 static int ldst_extend_v4		PARAMS ((char **));
1061 static void thumb_add_sub	PARAMS ((char *, int));
1062 static void insert_reg		PARAMS ((const struct reg_entry *,
1063 					 struct hash_control *));
1064 static void thumb_shift		PARAMS ((char *, int));
1065 static void thumb_mov_compare	PARAMS ((char *, int));
1066 static void build_arm_ops_hsh	PARAMS ((void));
1067 static void set_constant_flonums	PARAMS ((void));
1068 static valueT md_chars_to_number	PARAMS ((char *, int));
1069 static void build_reg_hsh	PARAMS ((struct reg_map *));
1070 static void insert_reg_alias	PARAMS ((char *, int, struct hash_control *));
1071 static int create_register_alias	PARAMS ((char *, char *));
1072 static void output_inst		PARAMS ((const char *));
1073 static int accum0_required_here PARAMS ((char **));
1074 static int ld_mode_required_here PARAMS ((char **));
1075 static void do_branch25         PARAMS ((char *));
1076 static symbolS * find_real_start PARAMS ((symbolS *));
1077 #ifdef OBJ_ELF
1078 static bfd_reloc_code_real_type	arm_parse_reloc PARAMS ((void));
1079 #endif
1080 
1081 static int wreg_required_here   PARAMS ((char **, int, enum wreg_type));
1082 static void do_iwmmxt_byte_addr PARAMS ((char *));
1083 static void do_iwmmxt_tandc     PARAMS ((char *));
1084 static void do_iwmmxt_tbcst     PARAMS ((char *));
1085 static void do_iwmmxt_textrc    PARAMS ((char *));
1086 static void do_iwmmxt_textrm    PARAMS ((char *));
1087 static void do_iwmmxt_tinsr     PARAMS ((char *));
1088 static void do_iwmmxt_tmcr      PARAMS ((char *));
1089 static void do_iwmmxt_tmcrr     PARAMS ((char *));
1090 static void do_iwmmxt_tmia      PARAMS ((char *));
1091 static void do_iwmmxt_tmovmsk   PARAMS ((char *));
1092 static void do_iwmmxt_tmrc      PARAMS ((char *));
1093 static void do_iwmmxt_tmrrc     PARAMS ((char *));
1094 static void do_iwmmxt_torc      PARAMS ((char *));
1095 static void do_iwmmxt_waligni   PARAMS ((char *));
1096 static void do_iwmmxt_wmov      PARAMS ((char *));
1097 static void do_iwmmxt_word_addr PARAMS ((char *));
1098 static void do_iwmmxt_wrwr      PARAMS ((char *));
1099 static void do_iwmmxt_wrwrwcg   PARAMS ((char *));
1100 static void do_iwmmxt_wrwrwr    PARAMS ((char *));
1101 static void do_iwmmxt_wshufh    PARAMS ((char *));
1102 static void do_iwmmxt_wzero     PARAMS ((char *));
1103 static int cp_byte_address_offset         PARAMS ((char **));
1104 static int cp_byte_address_required_here  PARAMS ((char **));
1105 
1106 /* ARM instructions take 4bytes in the object file, Thumb instructions
1107    take 2:  */
1108 #define INSN_SIZE       4
1109 
1110 /* "INSN<cond> X,Y" where X:bit12, Y:bit16.  */
1111 #define MAV_MODE1	0x100c
1112 
1113 /* "INSN<cond> X,Y" where X:bit16, Y:bit12.  */
1114 #define MAV_MODE2	0x0c10
1115 
1116 /* "INSN<cond> X,Y" where X:bit12, Y:bit16.  */
1117 #define MAV_MODE3	0x100c
1118 
1119 /* "INSN<cond> X,Y,Z" where X:16, Y:0, Z:12.  */
1120 #define MAV_MODE4	0x0c0010
1121 
1122 /* "INSN<cond> X,Y,Z" where X:12, Y:16, Z:0.  */
1123 #define MAV_MODE5	0x00100c
1124 
1125 /* "INSN<cond> W,X,Y,Z" where W:5, X:12, Y:16, Z:0.  */
1126 #define MAV_MODE6	0x00100c05
1127 
1128 struct asm_opcode
1129 {
1130   /* Basic string to match.  */
1131   const char * template;
1132 
1133   /* Basic instruction code.  */
1134   unsigned long value;
1135 
1136   /* Offset into the template where the condition code (if any) will be.
1137      If zero, then the instruction is never conditional.  */
1138   unsigned cond_offset;
1139 
1140   /* Which architecture variant provides this instruction.  */
1141   unsigned long variant;
1142 
1143   /* Function to call to parse args.  */
1144   void (* parms) PARAMS ((char *));
1145 };
1146 
1147 static const struct asm_opcode insns[] =
1148 {
1149   /* Core ARM Instructions.  */
1150   {"and",        0xe0000000, 3,  ARM_EXT_V1,       do_arit},
1151   {"ands",       0xe0100000, 3,  ARM_EXT_V1,       do_arit},
1152   {"eor",        0xe0200000, 3,  ARM_EXT_V1,       do_arit},
1153   {"eors",       0xe0300000, 3,  ARM_EXT_V1,       do_arit},
1154   {"sub",        0xe0400000, 3,  ARM_EXT_V1,       do_arit},
1155   {"subs",       0xe0500000, 3,  ARM_EXT_V1,       do_arit},
1156   {"rsb",        0xe0600000, 3,  ARM_EXT_V1,       do_arit},
1157   {"rsbs",       0xe0700000, 3,  ARM_EXT_V1,       do_arit},
1158   {"add",        0xe0800000, 3,  ARM_EXT_V1,       do_arit},
1159   {"adds",       0xe0900000, 3,  ARM_EXT_V1,       do_arit},
1160   {"adc",        0xe0a00000, 3,  ARM_EXT_V1,       do_arit},
1161   {"adcs",       0xe0b00000, 3,  ARM_EXT_V1,       do_arit},
1162   {"sbc",        0xe0c00000, 3,  ARM_EXT_V1,       do_arit},
1163   {"sbcs",       0xe0d00000, 3,  ARM_EXT_V1,       do_arit},
1164   {"rsc",        0xe0e00000, 3,  ARM_EXT_V1,       do_arit},
1165   {"rscs",       0xe0f00000, 3,  ARM_EXT_V1,       do_arit},
1166   {"orr",        0xe1800000, 3,  ARM_EXT_V1,       do_arit},
1167   {"orrs",       0xe1900000, 3,  ARM_EXT_V1,       do_arit},
1168   {"bic",        0xe1c00000, 3,  ARM_EXT_V1,       do_arit},
1169   {"bics",       0xe1d00000, 3,  ARM_EXT_V1,       do_arit},
1170 
1171   {"tst",        0xe1100000, 3,  ARM_EXT_V1,       do_cmp},
1172   {"tsts",       0xe1100000, 3,  ARM_EXT_V1,       do_cmp},
1173   {"tstp",       0xe110f000, 3,  ARM_EXT_V1,       do_cmp},
1174   {"teq",        0xe1300000, 3,  ARM_EXT_V1,       do_cmp},
1175   {"teqs",       0xe1300000, 3,  ARM_EXT_V1,       do_cmp},
1176   {"teqp",       0xe130f000, 3,  ARM_EXT_V1,       do_cmp},
1177   {"cmp",        0xe1500000, 3,  ARM_EXT_V1,       do_cmp},
1178   {"cmps",       0xe1500000, 3,  ARM_EXT_V1,       do_cmp},
1179   {"cmpp",       0xe150f000, 3,  ARM_EXT_V1,       do_cmp},
1180   {"cmn",        0xe1700000, 3,  ARM_EXT_V1,       do_cmp},
1181   {"cmns",       0xe1700000, 3,  ARM_EXT_V1,       do_cmp},
1182   {"cmnp",       0xe170f000, 3,  ARM_EXT_V1,       do_cmp},
1183 
1184   {"mov",        0xe1a00000, 3,  ARM_EXT_V1,       do_mov},
1185   {"movs",       0xe1b00000, 3,  ARM_EXT_V1,       do_mov},
1186   {"mvn",        0xe1e00000, 3,  ARM_EXT_V1,       do_mov},
1187   {"mvns",       0xe1f00000, 3,  ARM_EXT_V1,       do_mov},
1188 
1189   {"ldr",        0xe4100000, 3,  ARM_EXT_V1,       do_ldst},
1190   {"ldrb",       0xe4500000, 3,  ARM_EXT_V1,       do_ldst},
1191   {"ldrt",       0xe4300000, 3,  ARM_EXT_V1,       do_ldstt},
1192   {"ldrbt",      0xe4700000, 3,  ARM_EXT_V1,       do_ldstt},
1193   {"str",        0xe4000000, 3,  ARM_EXT_V1,       do_ldst},
1194   {"strb",       0xe4400000, 3,  ARM_EXT_V1,       do_ldst},
1195   {"strt",       0xe4200000, 3,  ARM_EXT_V1,       do_ldstt},
1196   {"strbt",      0xe4600000, 3,  ARM_EXT_V1,       do_ldstt},
1197 
1198   {"stmia",      0xe8800000, 3,  ARM_EXT_V1,       do_ldmstm},
1199   {"stmib",      0xe9800000, 3,  ARM_EXT_V1,       do_ldmstm},
1200   {"stmda",      0xe8000000, 3,  ARM_EXT_V1,       do_ldmstm},
1201   {"stmdb",      0xe9000000, 3,  ARM_EXT_V1,       do_ldmstm},
1202   {"stmfd",      0xe9000000, 3,  ARM_EXT_V1,       do_ldmstm},
1203   {"stmfa",      0xe9800000, 3,  ARM_EXT_V1,       do_ldmstm},
1204   {"stmea",      0xe8800000, 3,  ARM_EXT_V1,       do_ldmstm},
1205   {"stmed",      0xe8000000, 3,  ARM_EXT_V1,       do_ldmstm},
1206 
1207   {"ldmia",      0xe8900000, 3,  ARM_EXT_V1,       do_ldmstm},
1208   {"ldmib",      0xe9900000, 3,  ARM_EXT_V1,       do_ldmstm},
1209   {"ldmda",      0xe8100000, 3,  ARM_EXT_V1,       do_ldmstm},
1210   {"ldmdb",      0xe9100000, 3,  ARM_EXT_V1,       do_ldmstm},
1211   {"ldmfd",      0xe8900000, 3,  ARM_EXT_V1,       do_ldmstm},
1212   {"ldmfa",      0xe8100000, 3,  ARM_EXT_V1,       do_ldmstm},
1213   {"ldmea",      0xe9100000, 3,  ARM_EXT_V1,       do_ldmstm},
1214   {"ldmed",      0xe9900000, 3,  ARM_EXT_V1,       do_ldmstm},
1215 
1216   {"swi",        0xef000000, 3,  ARM_EXT_V1,       do_swi},
1217 #ifdef TE_WINCE
1218   /* XXX This is the wrong place to do this.  Think multi-arch.  */
1219   {"bl",         0xeb000000, 2,  ARM_EXT_V1,       do_branch},
1220   {"b",          0xea000000, 1,  ARM_EXT_V1,       do_branch},
1221 #else
1222   {"bl",         0xebfffffe, 2,  ARM_EXT_V1,       do_branch},
1223   {"b",          0xeafffffe, 1,  ARM_EXT_V1,       do_branch},
1224 #endif
1225 
1226   /* Pseudo ops.  */
1227   {"adr",        0xe28f0000, 3,  ARM_EXT_V1,       do_adr},
1228   {"adrl",       0xe28f0000, 3,  ARM_EXT_V1,       do_adrl},
1229   {"nop",        0xe1a00000, 3,  ARM_EXT_V1,       do_empty},
1230 
1231   /* ARM 2 multiplies.  */
1232   {"mul",        0xe0000090, 3,  ARM_EXT_V2,       do_mul},
1233   {"muls",       0xe0100090, 3,  ARM_EXT_V2,       do_mul},
1234   {"mla",        0xe0200090, 3,  ARM_EXT_V2,       do_mla},
1235   {"mlas",       0xe0300090, 3,  ARM_EXT_V2,       do_mla},
1236 
1237   /* Generic coprocessor instructions.  */
1238   {"cdp",        0xee000000, 3,  ARM_EXT_V2,       do_cdp},
1239   {"ldc",        0xec100000, 3,  ARM_EXT_V2,       do_lstc},
1240   {"ldcl",       0xec500000, 3,  ARM_EXT_V2,       do_lstc},
1241   {"stc",        0xec000000, 3,  ARM_EXT_V2,       do_lstc},
1242   {"stcl",       0xec400000, 3,  ARM_EXT_V2,       do_lstc},
1243   {"mcr",        0xee000010, 3,  ARM_EXT_V2,       do_co_reg},
1244   {"mrc",        0xee100010, 3,  ARM_EXT_V2,       do_co_reg},
1245 
1246   /* ARM 3 - swp instructions.  */
1247   {"swp",        0xe1000090, 3,  ARM_EXT_V2S,      do_swap},
1248   {"swpb",       0xe1400090, 3,  ARM_EXT_V2S,      do_swap},
1249 
1250   /* ARM 6 Status register instructions.  */
1251   {"mrs",        0xe10f0000, 3,  ARM_EXT_V3,       do_mrs},
1252   {"msr",        0xe120f000, 3,  ARM_EXT_V3,       do_msr},
1253   /* ScottB: our code uses     0xe128f000 for msr.
1254      NickC:  but this is wrong because the bits 16 through 19 are
1255              handled by the PSR_xxx defines above.  */
1256 
1257   /* ARM 7M long multiplies.  */
1258   {"smull",      0xe0c00090, 5,  ARM_EXT_V3M,      do_mull},
1259   {"smulls",     0xe0d00090, 5,  ARM_EXT_V3M,      do_mull},
1260   {"umull",      0xe0800090, 5,  ARM_EXT_V3M,      do_mull},
1261   {"umulls",     0xe0900090, 5,  ARM_EXT_V3M,      do_mull},
1262   {"smlal",      0xe0e00090, 5,  ARM_EXT_V3M,      do_mull},
1263   {"smlals",     0xe0f00090, 5,  ARM_EXT_V3M,      do_mull},
1264   {"umlal",      0xe0a00090, 5,  ARM_EXT_V3M,      do_mull},
1265   {"umlals",     0xe0b00090, 5,  ARM_EXT_V3M,      do_mull},
1266 
1267   /* ARM Architecture 4.  */
1268   {"ldrh",       0xe01000b0, 3,  ARM_EXT_V4,       do_ldstv4},
1269   {"ldrsh",      0xe01000f0, 3,  ARM_EXT_V4,       do_ldstv4},
1270   {"ldrsb",      0xe01000d0, 3,  ARM_EXT_V4,       do_ldstv4},
1271   {"strh",       0xe00000b0, 3,  ARM_EXT_V4,       do_ldstv4},
1272 
1273   /* ARM Architecture 4T.  */
1274   /* Note: bx (and blx) are required on V5, even if the processor does
1275      not support Thumb.  */
1276   {"bx",         0xe12fff10, 2,  ARM_EXT_V4T | ARM_EXT_V5, do_bx},
1277 
1278   /*  ARM Architecture 5T.  */
1279   /* Note: blx has 2 variants, so the .value is set dynamically.
1280      Only one of the variants has conditional execution.  */
1281   {"blx",        0xe0000000, 3,  ARM_EXT_V5,       do_blx},
1282   {"clz",        0xe16f0f10, 3,  ARM_EXT_V5,       do_clz},
1283   {"bkpt",       0xe1200070, 0,  ARM_EXT_V5,       do_bkpt},
1284   {"ldc2",       0xfc100000, 0,  ARM_EXT_V5,       do_lstc2},
1285   {"ldc2l",      0xfc500000, 0,  ARM_EXT_V5,       do_lstc2},
1286   {"stc2",       0xfc000000, 0,  ARM_EXT_V5,       do_lstc2},
1287   {"stc2l",      0xfc400000, 0,  ARM_EXT_V5,       do_lstc2},
1288   {"cdp2",       0xfe000000, 0,  ARM_EXT_V5,       do_cdp2},
1289   {"mcr2",       0xfe000010, 0,  ARM_EXT_V5,       do_co_reg2},
1290   {"mrc2",       0xfe100010, 0,  ARM_EXT_V5,       do_co_reg2},
1291 
1292   /*  ARM Architecture 5TExP.  */
1293   {"smlabb",     0xe1000080, 6,  ARM_EXT_V5ExP,    do_smla},
1294   {"smlatb",     0xe10000a0, 6,  ARM_EXT_V5ExP,    do_smla},
1295   {"smlabt",     0xe10000c0, 6,  ARM_EXT_V5ExP,    do_smla},
1296   {"smlatt",     0xe10000e0, 6,  ARM_EXT_V5ExP,    do_smla},
1297 
1298   {"smlawb",     0xe1200080, 6,  ARM_EXT_V5ExP,    do_smla},
1299   {"smlawt",     0xe12000c0, 6,  ARM_EXT_V5ExP,    do_smla},
1300 
1301   {"smlalbb",    0xe1400080, 7,  ARM_EXT_V5ExP,    do_smlal},
1302   {"smlaltb",    0xe14000a0, 7,  ARM_EXT_V5ExP,    do_smlal},
1303   {"smlalbt",    0xe14000c0, 7,  ARM_EXT_V5ExP,    do_smlal},
1304   {"smlaltt",    0xe14000e0, 7,  ARM_EXT_V5ExP,    do_smlal},
1305 
1306   {"smulbb",     0xe1600080, 6,  ARM_EXT_V5ExP,    do_smul},
1307   {"smultb",     0xe16000a0, 6,  ARM_EXT_V5ExP,    do_smul},
1308   {"smulbt",     0xe16000c0, 6,  ARM_EXT_V5ExP,    do_smul},
1309   {"smultt",     0xe16000e0, 6,  ARM_EXT_V5ExP,    do_smul},
1310 
1311   {"smulwb",     0xe12000a0, 6,  ARM_EXT_V5ExP,    do_smul},
1312   {"smulwt",     0xe12000e0, 6,  ARM_EXT_V5ExP,    do_smul},
1313 
1314   {"qadd",       0xe1000050, 4,  ARM_EXT_V5ExP,    do_qadd},
1315   {"qdadd",      0xe1400050, 5,  ARM_EXT_V5ExP,    do_qadd},
1316   {"qsub",       0xe1200050, 4,  ARM_EXT_V5ExP,    do_qadd},
1317   {"qdsub",      0xe1600050, 5,  ARM_EXT_V5ExP,    do_qadd},
1318 
1319   /*  ARM Architecture 5TE.  */
1320   {"pld",        0xf450f000, 0,  ARM_EXT_V5E,      do_pld},
1321   {"ldrd",       0xe00000d0, 3,  ARM_EXT_V5E,      do_ldrd},
1322   {"strd",       0xe00000f0, 3,  ARM_EXT_V5E,      do_ldrd},
1323 
1324   {"mcrr",       0xec400000, 4,  ARM_EXT_V5E,      do_co_reg2c},
1325   {"mrrc",       0xec500000, 4,  ARM_EXT_V5E,      do_co_reg2c},
1326 
1327   /*  ARM Architecture 5TEJ.  */
1328   {"bxj",	 0xe12fff20, 3,  ARM_EXT_V5J,	   do_bxj},
1329 
1330   /*  ARM V6.  */
1331   { "cps",       0xf1020000, 0,  ARM_EXT_V6,       do_cps},
1332   { "cpsie",     0xf1080000, 0,  ARM_EXT_V6,       do_cpsi},
1333   { "cpsid",     0xf10C0000, 0,  ARM_EXT_V6,       do_cpsi},
1334   { "ldrex",     0xe1900f9f, 5,  ARM_EXT_V6,       do_ldrex},
1335   { "mcrr2",     0xfc400000, 0,  ARM_EXT_V6,       do_co_reg2c},
1336   { "mrrc2",     0xfc500000, 0,  ARM_EXT_V6,       do_co_reg2c},
1337   { "pkhbt",     0xe6800010, 5,  ARM_EXT_V6,       do_pkhbt},
1338   { "pkhtb",     0xe6800050, 5,  ARM_EXT_V6,       do_pkhtb},
1339   { "qadd16",    0xe6200f10, 6,  ARM_EXT_V6,       do_qadd16},
1340   { "qadd8",     0xe6200f90, 5,  ARM_EXT_V6,       do_qadd16},
1341   { "qaddsubx",  0xe6200f30, 8,  ARM_EXT_V6,       do_qadd16},
1342   { "qsub16",    0xe6200f70, 6,  ARM_EXT_V6,       do_qadd16},
1343   { "qsub8",     0xe6200ff0, 5,  ARM_EXT_V6,       do_qadd16},
1344   { "qsubaddx",  0xe6200f50, 8,  ARM_EXT_V6,       do_qadd16},
1345   { "sadd16",    0xe6100f10, 6,  ARM_EXT_V6,       do_qadd16},
1346   { "sadd8",     0xe6100f90, 5,  ARM_EXT_V6,       do_qadd16},
1347   { "saddsubx",  0xe6100f30, 8,  ARM_EXT_V6,       do_qadd16},
1348   { "shadd16",   0xe6300f10, 7,  ARM_EXT_V6,       do_qadd16},
1349   { "shadd8",    0xe6300f90, 6,  ARM_EXT_V6,       do_qadd16},
1350   { "shaddsubx", 0xe6300f30, 9,  ARM_EXT_V6,       do_qadd16},
1351   { "shsub16",   0xe6300f70, 7,  ARM_EXT_V6,       do_qadd16},
1352   { "shsub8",    0xe6300ff0, 6,  ARM_EXT_V6,       do_qadd16},
1353   { "shsubaddx", 0xe6300f50, 9,  ARM_EXT_V6,       do_qadd16},
1354   { "ssub16",    0xe6100f70, 6,  ARM_EXT_V6,       do_qadd16},
1355   { "ssub8",     0xe6100ff0, 5,  ARM_EXT_V6,       do_qadd16},
1356   { "ssubaddx",  0xe6100f50, 8,  ARM_EXT_V6,       do_qadd16},
1357   { "uadd16",    0xe6500f10, 6,  ARM_EXT_V6,       do_qadd16},
1358   { "uadd8",     0xe6500f90, 5,  ARM_EXT_V6,       do_qadd16},
1359   { "uaddsubx",  0xe6500f30, 8,  ARM_EXT_V6,       do_qadd16},
1360   { "uhadd16",   0xe6700f10, 7,  ARM_EXT_V6,       do_qadd16},
1361   { "uhadd8",    0xe6700f90, 6,  ARM_EXT_V6,       do_qadd16},
1362   { "uhaddsubx", 0xe6700f30, 9,  ARM_EXT_V6,       do_qadd16},
1363   { "uhsub16",   0xe6700f70, 7,  ARM_EXT_V6,       do_qadd16},
1364   { "uhsub8",    0xe6700ff0, 6,  ARM_EXT_V6,       do_qadd16},
1365   { "uhsubaddx", 0xe6700f50, 9,  ARM_EXT_V6,       do_qadd16},
1366   { "uqadd16",   0xe6600f10, 7,  ARM_EXT_V6,       do_qadd16},
1367   { "uqadd8",    0xe6600f90, 6,  ARM_EXT_V6,       do_qadd16},
1368   { "uqaddsubx", 0xe6600f30, 9,  ARM_EXT_V6,       do_qadd16},
1369   { "uqsub16",   0xe6600f70, 7,  ARM_EXT_V6,       do_qadd16},
1370   { "uqsub8",    0xe6600ff0, 6,  ARM_EXT_V6,       do_qadd16},
1371   { "uqsubaddx", 0xe6600f50, 9,  ARM_EXT_V6,       do_qadd16},
1372   { "usub16",    0xe6500f70, 6,  ARM_EXT_V6,       do_qadd16},
1373   { "usub8",     0xe6500ff0, 5,  ARM_EXT_V6,       do_qadd16},
1374   { "usubaddx",  0xe6500f50, 8,  ARM_EXT_V6,       do_qadd16},
1375   { "rev",       0xe6bf0f30, 3,  ARM_EXT_V6,       do_rev},
1376   { "rev16",     0xe6bf0fb0, 5,  ARM_EXT_V6,       do_rev},
1377   { "revsh",     0xe6ff0fb0, 5,  ARM_EXT_V6,       do_rev},
1378   { "rfeia",     0xf8900a00, 0,  ARM_EXT_V6,       do_rfe},
1379   { "rfeib",     0xf9900a00, 0,  ARM_EXT_V6,       do_rfe},
1380   { "rfeda",     0xf8100a00, 0,  ARM_EXT_V6,       do_rfe},
1381   { "rfedb",     0xf9100a00, 0,  ARM_EXT_V6,       do_rfe},
1382   { "rfefd",     0xf8900a00, 0,  ARM_EXT_V6,       do_rfe},
1383   { "rfefa",     0xf9900a00, 0,  ARM_EXT_V6,       do_rfe},
1384   { "rfeea",     0xf8100a00, 0,  ARM_EXT_V6,       do_rfe},
1385   { "rfeed",     0xf9100a00, 0,  ARM_EXT_V6,       do_rfe},
1386   { "sxtah",     0xe6b00070, 5,  ARM_EXT_V6,       do_sxtah},
1387   { "sxtab16",   0xe6800070, 7,  ARM_EXT_V6,       do_sxtah},
1388   { "sxtab",     0xe6a00070, 5,  ARM_EXT_V6,       do_sxtah},
1389   { "sxth",      0xe6bf0070, 4,  ARM_EXT_V6,       do_sxth},
1390   { "sxtb16",    0xe68f0070, 6,  ARM_EXT_V6,       do_sxth},
1391   { "sxtb",      0xe6af0070, 4,  ARM_EXT_V6,       do_sxth},
1392   { "uxtah",     0xe6f00070, 5,  ARM_EXT_V6,       do_sxtah},
1393   { "uxtab16",   0xe6c00070, 7,  ARM_EXT_V6,       do_sxtah},
1394   { "uxtab",     0xe6e00070, 5,  ARM_EXT_V6,       do_sxtah},
1395   { "uxth",      0xe6ff0070, 4,  ARM_EXT_V6,       do_sxth},
1396   { "uxtb16",    0xe6cf0070, 6,  ARM_EXT_V6,       do_sxth},
1397   { "uxtb",      0xe6ef0070, 4,  ARM_EXT_V6,       do_sxth},
1398   { "sel",       0xe68000b0, 3,  ARM_EXT_V6,       do_qadd16},
1399   { "setend",    0xf1010000, 0,  ARM_EXT_V6,       do_setend},
1400   { "smlad",     0xe7000010, 5,  ARM_EXT_V6,       do_smlad},
1401   { "smladx",    0xe7000030, 6,  ARM_EXT_V6,       do_smlad},
1402   { "smlald",    0xe7400010, 6,  ARM_EXT_V6,       do_smlald},
1403   { "smlaldx",   0xe7400030, 7,  ARM_EXT_V6,       do_smlald},
1404   { "smlsd",     0xe7000050, 5,  ARM_EXT_V6,       do_smlad},
1405   { "smlsdx",    0xe7000070, 6,  ARM_EXT_V6,       do_smlad},
1406   { "smlsld",    0xe7400050, 6,  ARM_EXT_V6,       do_smlald},
1407   { "smlsldx",   0xe7400070, 7,  ARM_EXT_V6,       do_smlald},
1408   { "smmla",     0xe7500010, 5,  ARM_EXT_V6,       do_smlad},
1409   { "smmlar",    0xe7500030, 6,  ARM_EXT_V6,       do_smlad},
1410   { "smmls",     0xe75000d0, 5,  ARM_EXT_V6,       do_smlad},
1411   { "smmlsr",    0xe75000f0, 6,  ARM_EXT_V6,       do_smlad},
1412   { "smmul",     0xe750f010, 5,  ARM_EXT_V6,       do_smmul},
1413   { "smmulr",    0xe750f030, 6,  ARM_EXT_V6,       do_smmul},
1414   { "smuad",     0xe700f010, 5,  ARM_EXT_V6,       do_smmul},
1415   { "smuadx",    0xe700f030, 6,  ARM_EXT_V6,       do_smmul},
1416   { "smusd",     0xe700f050, 5,  ARM_EXT_V6,       do_smmul},
1417   { "smusdx",    0xe700f070, 6,  ARM_EXT_V6,       do_smmul},
1418   { "srsia",     0xf8cd0500, 0,  ARM_EXT_V6,       do_srs},
1419   { "srsib",     0xf9cd0500, 0,  ARM_EXT_V6,       do_srs},
1420   { "srsda",     0xf84d0500, 0,  ARM_EXT_V6,       do_srs},
1421   { "srsdb",     0xf94d0500, 0,  ARM_EXT_V6,       do_srs},
1422   { "ssat",      0xe6a00010, 4,  ARM_EXT_V6,       do_ssat},
1423   { "ssat16",    0xe6a00f30, 6,  ARM_EXT_V6,       do_ssat16},
1424   { "strex",     0xe1800f90, 5,  ARM_EXT_V6,       do_strex},
1425   { "umaal",     0xe0400090, 5,  ARM_EXT_V6,       do_umaal},
1426   { "usad8",     0xe780f010, 5,  ARM_EXT_V6,       do_smmul},
1427   { "usada8",    0xe7800010, 6,  ARM_EXT_V6,       do_smlad},
1428   { "usat",      0xe6e00010, 4,  ARM_EXT_V6,       do_usat},
1429   { "usat16",    0xe6e00f30, 6,  ARM_EXT_V6,       do_usat16},
1430 
1431   /* Core FPA instruction set (V1).  */
1432   {"wfs",        0xee200110, 3,  FPU_FPA_EXT_V1,   do_fpa_ctrl},
1433   {"rfs",        0xee300110, 3,  FPU_FPA_EXT_V1,   do_fpa_ctrl},
1434   {"wfc",        0xee400110, 3,  FPU_FPA_EXT_V1,   do_fpa_ctrl},
1435   {"rfc",        0xee500110, 3,  FPU_FPA_EXT_V1,   do_fpa_ctrl},
1436 
1437   {"ldfs",       0xec100100, 3,  FPU_FPA_EXT_V1,   do_fpa_ldst},
1438   {"ldfd",       0xec108100, 3,  FPU_FPA_EXT_V1,   do_fpa_ldst},
1439   {"ldfe",       0xec500100, 3,  FPU_FPA_EXT_V1,   do_fpa_ldst},
1440   {"ldfp",       0xec508100, 3,  FPU_FPA_EXT_V1,   do_fpa_ldst},
1441 
1442   {"stfs",       0xec000100, 3,  FPU_FPA_EXT_V1,   do_fpa_ldst},
1443   {"stfd",       0xec008100, 3,  FPU_FPA_EXT_V1,   do_fpa_ldst},
1444   {"stfe",       0xec400100, 3,  FPU_FPA_EXT_V1,   do_fpa_ldst},
1445   {"stfp",       0xec408100, 3,  FPU_FPA_EXT_V1,   do_fpa_ldst},
1446 
1447   {"mvfs",       0xee008100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1448   {"mvfsp",      0xee008120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1449   {"mvfsm",      0xee008140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1450   {"mvfsz",      0xee008160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1451   {"mvfd",       0xee008180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1452   {"mvfdp",      0xee0081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1453   {"mvfdm",      0xee0081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1454   {"mvfdz",      0xee0081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1455   {"mvfe",       0xee088100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1456   {"mvfep",      0xee088120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1457   {"mvfem",      0xee088140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1458   {"mvfez",      0xee088160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1459 
1460   {"mnfs",       0xee108100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1461   {"mnfsp",      0xee108120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1462   {"mnfsm",      0xee108140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1463   {"mnfsz",      0xee108160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1464   {"mnfd",       0xee108180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1465   {"mnfdp",      0xee1081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1466   {"mnfdm",      0xee1081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1467   {"mnfdz",      0xee1081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1468   {"mnfe",       0xee188100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1469   {"mnfep",      0xee188120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1470   {"mnfem",      0xee188140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1471   {"mnfez",      0xee188160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1472 
1473   {"abss",       0xee208100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1474   {"abssp",      0xee208120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1475   {"abssm",      0xee208140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1476   {"abssz",      0xee208160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1477   {"absd",       0xee208180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1478   {"absdp",      0xee2081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1479   {"absdm",      0xee2081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1480   {"absdz",      0xee2081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1481   {"abse",       0xee288100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1482   {"absep",      0xee288120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1483   {"absem",      0xee288140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1484   {"absez",      0xee288160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1485 
1486   {"rnds",       0xee308100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1487   {"rndsp",      0xee308120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1488   {"rndsm",      0xee308140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1489   {"rndsz",      0xee308160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1490   {"rndd",       0xee308180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1491   {"rnddp",      0xee3081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1492   {"rnddm",      0xee3081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1493   {"rnddz",      0xee3081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1494   {"rnde",       0xee388100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1495   {"rndep",      0xee388120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1496   {"rndem",      0xee388140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1497   {"rndez",      0xee388160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1498 
1499   {"sqts",       0xee408100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1500   {"sqtsp",      0xee408120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1501   {"sqtsm",      0xee408140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1502   {"sqtsz",      0xee408160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1503   {"sqtd",       0xee408180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1504   {"sqtdp",      0xee4081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1505   {"sqtdm",      0xee4081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1506   {"sqtdz",      0xee4081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1507   {"sqte",       0xee488100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1508   {"sqtep",      0xee488120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1509   {"sqtem",      0xee488140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1510   {"sqtez",      0xee488160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1511 
1512   {"logs",       0xee508100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1513   {"logsp",      0xee508120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1514   {"logsm",      0xee508140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1515   {"logsz",      0xee508160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1516   {"logd",       0xee508180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1517   {"logdp",      0xee5081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1518   {"logdm",      0xee5081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1519   {"logdz",      0xee5081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1520   {"loge",       0xee588100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1521   {"logep",      0xee588120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1522   {"logem",      0xee588140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1523   {"logez",      0xee588160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1524 
1525   {"lgns",       0xee608100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1526   {"lgnsp",      0xee608120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1527   {"lgnsm",      0xee608140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1528   {"lgnsz",      0xee608160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1529   {"lgnd",       0xee608180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1530   {"lgndp",      0xee6081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1531   {"lgndm",      0xee6081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1532   {"lgndz",      0xee6081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1533   {"lgne",       0xee688100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1534   {"lgnep",      0xee688120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1535   {"lgnem",      0xee688140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1536   {"lgnez",      0xee688160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1537 
1538   {"exps",       0xee708100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1539   {"expsp",      0xee708120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1540   {"expsm",      0xee708140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1541   {"expsz",      0xee708160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1542   {"expd",       0xee708180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1543   {"expdp",      0xee7081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1544   {"expdm",      0xee7081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1545   {"expdz",      0xee7081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1546   {"expe",       0xee788100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1547   {"expep",      0xee788120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1548   {"expem",      0xee788140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1549   {"expdz",      0xee788160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1550 
1551   {"sins",       0xee808100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1552   {"sinsp",      0xee808120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1553   {"sinsm",      0xee808140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1554   {"sinsz",      0xee808160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1555   {"sind",       0xee808180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1556   {"sindp",      0xee8081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1557   {"sindm",      0xee8081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1558   {"sindz",      0xee8081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1559   {"sine",       0xee888100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1560   {"sinep",      0xee888120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1561   {"sinem",      0xee888140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1562   {"sinez",      0xee888160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1563 
1564   {"coss",       0xee908100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1565   {"cossp",      0xee908120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1566   {"cossm",      0xee908140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1567   {"cossz",      0xee908160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1568   {"cosd",       0xee908180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1569   {"cosdp",      0xee9081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1570   {"cosdm",      0xee9081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1571   {"cosdz",      0xee9081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1572   {"cose",       0xee988100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1573   {"cosep",      0xee988120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1574   {"cosem",      0xee988140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1575   {"cosez",      0xee988160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1576 
1577   {"tans",       0xeea08100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1578   {"tansp",      0xeea08120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1579   {"tansm",      0xeea08140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1580   {"tansz",      0xeea08160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1581   {"tand",       0xeea08180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1582   {"tandp",      0xeea081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1583   {"tandm",      0xeea081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1584   {"tandz",      0xeea081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1585   {"tane",       0xeea88100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1586   {"tanep",      0xeea88120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1587   {"tanem",      0xeea88140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1588   {"tanez",      0xeea88160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1589 
1590   {"asns",       0xeeb08100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1591   {"asnsp",      0xeeb08120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1592   {"asnsm",      0xeeb08140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1593   {"asnsz",      0xeeb08160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1594   {"asnd",       0xeeb08180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1595   {"asndp",      0xeeb081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1596   {"asndm",      0xeeb081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1597   {"asndz",      0xeeb081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1598   {"asne",       0xeeb88100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1599   {"asnep",      0xeeb88120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1600   {"asnem",      0xeeb88140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1601   {"asnez",      0xeeb88160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1602 
1603   {"acss",       0xeec08100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1604   {"acssp",      0xeec08120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1605   {"acssm",      0xeec08140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1606   {"acssz",      0xeec08160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1607   {"acsd",       0xeec08180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1608   {"acsdp",      0xeec081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1609   {"acsdm",      0xeec081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1610   {"acsdz",      0xeec081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1611   {"acse",       0xeec88100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1612   {"acsep",      0xeec88120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1613   {"acsem",      0xeec88140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1614   {"acsez",      0xeec88160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1615 
1616   {"atns",       0xeed08100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1617   {"atnsp",      0xeed08120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1618   {"atnsm",      0xeed08140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1619   {"atnsz",      0xeed08160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1620   {"atnd",       0xeed08180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1621   {"atndp",      0xeed081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1622   {"atndm",      0xeed081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1623   {"atndz",      0xeed081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1624   {"atne",       0xeed88100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1625   {"atnep",      0xeed88120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1626   {"atnem",      0xeed88140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1627   {"atnez",      0xeed88160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1628 
1629   {"urds",       0xeee08100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1630   {"urdsp",      0xeee08120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1631   {"urdsm",      0xeee08140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1632   {"urdsz",      0xeee08160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1633   {"urdd",       0xeee08180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1634   {"urddp",      0xeee081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1635   {"urddm",      0xeee081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1636   {"urddz",      0xeee081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1637   {"urde",       0xeee88100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1638   {"urdep",      0xeee88120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1639   {"urdem",      0xeee88140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1640   {"urdez",      0xeee88160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1641 
1642   {"nrms",       0xeef08100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1643   {"nrmsp",      0xeef08120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1644   {"nrmsm",      0xeef08140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1645   {"nrmsz",      0xeef08160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1646   {"nrmd",       0xeef08180, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1647   {"nrmdp",      0xeef081a0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1648   {"nrmdm",      0xeef081c0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1649   {"nrmdz",      0xeef081e0, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1650   {"nrme",       0xeef88100, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1651   {"nrmep",      0xeef88120, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1652   {"nrmem",      0xeef88140, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1653   {"nrmez",      0xeef88160, 3,  FPU_FPA_EXT_V1,   do_fpa_monadic},
1654 
1655   {"adfs",       0xee000100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1656   {"adfsp",      0xee000120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1657   {"adfsm",      0xee000140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1658   {"adfsz",      0xee000160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1659   {"adfd",       0xee000180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1660   {"adfdp",      0xee0001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1661   {"adfdm",      0xee0001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1662   {"adfdz",      0xee0001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1663   {"adfe",       0xee080100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1664   {"adfep",      0xee080120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1665   {"adfem",      0xee080140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1666   {"adfez",      0xee080160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1667 
1668   {"sufs",       0xee200100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1669   {"sufsp",      0xee200120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1670   {"sufsm",      0xee200140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1671   {"sufsz",      0xee200160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1672   {"sufd",       0xee200180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1673   {"sufdp",      0xee2001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1674   {"sufdm",      0xee2001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1675   {"sufdz",      0xee2001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1676   {"sufe",       0xee280100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1677   {"sufep",      0xee280120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1678   {"sufem",      0xee280140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1679   {"sufez",      0xee280160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1680 
1681   {"rsfs",       0xee300100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1682   {"rsfsp",      0xee300120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1683   {"rsfsm",      0xee300140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1684   {"rsfsz",      0xee300160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1685   {"rsfd",       0xee300180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1686   {"rsfdp",      0xee3001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1687   {"rsfdm",      0xee3001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1688   {"rsfdz",      0xee3001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1689   {"rsfe",       0xee380100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1690   {"rsfep",      0xee380120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1691   {"rsfem",      0xee380140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1692   {"rsfez",      0xee380160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1693 
1694   {"mufs",       0xee100100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1695   {"mufsp",      0xee100120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1696   {"mufsm",      0xee100140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1697   {"mufsz",      0xee100160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1698   {"mufd",       0xee100180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1699   {"mufdp",      0xee1001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1700   {"mufdm",      0xee1001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1701   {"mufdz",      0xee1001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1702   {"mufe",       0xee180100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1703   {"mufep",      0xee180120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1704   {"mufem",      0xee180140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1705   {"mufez",      0xee180160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1706 
1707   {"dvfs",       0xee400100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1708   {"dvfsp",      0xee400120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1709   {"dvfsm",      0xee400140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1710   {"dvfsz",      0xee400160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1711   {"dvfd",       0xee400180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1712   {"dvfdp",      0xee4001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1713   {"dvfdm",      0xee4001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1714   {"dvfdz",      0xee4001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1715   {"dvfe",       0xee480100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1716   {"dvfep",      0xee480120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1717   {"dvfem",      0xee480140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1718   {"dvfez",      0xee480160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1719 
1720   {"rdfs",       0xee500100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1721   {"rdfsp",      0xee500120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1722   {"rdfsm",      0xee500140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1723   {"rdfsz",      0xee500160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1724   {"rdfd",       0xee500180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1725   {"rdfdp",      0xee5001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1726   {"rdfdm",      0xee5001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1727   {"rdfdz",      0xee5001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1728   {"rdfe",       0xee580100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1729   {"rdfep",      0xee580120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1730   {"rdfem",      0xee580140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1731   {"rdfez",      0xee580160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1732 
1733   {"pows",       0xee600100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1734   {"powsp",      0xee600120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1735   {"powsm",      0xee600140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1736   {"powsz",      0xee600160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1737   {"powd",       0xee600180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1738   {"powdp",      0xee6001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1739   {"powdm",      0xee6001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1740   {"powdz",      0xee6001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1741   {"powe",       0xee680100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1742   {"powep",      0xee680120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1743   {"powem",      0xee680140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1744   {"powez",      0xee680160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1745 
1746   {"rpws",       0xee700100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1747   {"rpwsp",      0xee700120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1748   {"rpwsm",      0xee700140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1749   {"rpwsz",      0xee700160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1750   {"rpwd",       0xee700180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1751   {"rpwdp",      0xee7001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1752   {"rpwdm",      0xee7001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1753   {"rpwdz",      0xee7001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1754   {"rpwe",       0xee780100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1755   {"rpwep",      0xee780120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1756   {"rpwem",      0xee780140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1757   {"rpwez",      0xee780160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1758 
1759   {"rmfs",       0xee800100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1760   {"rmfsp",      0xee800120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1761   {"rmfsm",      0xee800140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1762   {"rmfsz",      0xee800160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1763   {"rmfd",       0xee800180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1764   {"rmfdp",      0xee8001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1765   {"rmfdm",      0xee8001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1766   {"rmfdz",      0xee8001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1767   {"rmfe",       0xee880100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1768   {"rmfep",      0xee880120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1769   {"rmfem",      0xee880140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1770   {"rmfez",      0xee880160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1771 
1772   {"fmls",       0xee900100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1773   {"fmlsp",      0xee900120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1774   {"fmlsm",      0xee900140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1775   {"fmlsz",      0xee900160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1776   {"fmld",       0xee900180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1777   {"fmldp",      0xee9001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1778   {"fmldm",      0xee9001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1779   {"fmldz",      0xee9001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1780   {"fmle",       0xee980100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1781   {"fmlep",      0xee980120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1782   {"fmlem",      0xee980140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1783   {"fmlez",      0xee980160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1784 
1785   {"fdvs",       0xeea00100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1786   {"fdvsp",      0xeea00120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1787   {"fdvsm",      0xeea00140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1788   {"fdvsz",      0xeea00160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1789   {"fdvd",       0xeea00180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1790   {"fdvdp",      0xeea001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1791   {"fdvdm",      0xeea001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1792   {"fdvdz",      0xeea001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1793   {"fdve",       0xeea80100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1794   {"fdvep",      0xeea80120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1795   {"fdvem",      0xeea80140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1796   {"fdvez",      0xeea80160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1797 
1798   {"frds",       0xeeb00100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1799   {"frdsp",      0xeeb00120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1800   {"frdsm",      0xeeb00140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1801   {"frdsz",      0xeeb00160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1802   {"frdd",       0xeeb00180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1803   {"frddp",      0xeeb001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1804   {"frddm",      0xeeb001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1805   {"frddz",      0xeeb001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1806   {"frde",       0xeeb80100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1807   {"frdep",      0xeeb80120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1808   {"frdem",      0xeeb80140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1809   {"frdez",      0xeeb80160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1810 
1811   {"pols",       0xeec00100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1812   {"polsp",      0xeec00120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1813   {"polsm",      0xeec00140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1814   {"polsz",      0xeec00160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1815   {"pold",       0xeec00180, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1816   {"poldp",      0xeec001a0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1817   {"poldm",      0xeec001c0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1818   {"poldz",      0xeec001e0, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1819   {"pole",       0xeec80100, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1820   {"polep",      0xeec80120, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1821   {"polem",      0xeec80140, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1822   {"polez",      0xeec80160, 3,  FPU_FPA_EXT_V1,   do_fpa_dyadic},
1823 
1824   {"cmf",        0xee90f110, 3,  FPU_FPA_EXT_V1,   do_fpa_cmp},
1825   {"cmfe",       0xeed0f110, 3,  FPU_FPA_EXT_V1,   do_fpa_cmp},
1826   {"cnf",        0xeeb0f110, 3,  FPU_FPA_EXT_V1,   do_fpa_cmp},
1827   {"cnfe",       0xeef0f110, 3,  FPU_FPA_EXT_V1,   do_fpa_cmp},
1828   /* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should
1829      not be an optional suffix, but part of the instruction.  To be
1830      compatible, we accept either.  */
1831   {"cmfe",       0xeed0f110, 4,  FPU_FPA_EXT_V1,   do_fpa_cmp},
1832   {"cnfe",       0xeef0f110, 4,  FPU_FPA_EXT_V1,   do_fpa_cmp},
1833 
1834   {"flts",       0xee000110, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
1835   {"fltsp",      0xee000130, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
1836   {"fltsm",      0xee000150, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
1837   {"fltsz",      0xee000170, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
1838   {"fltd",       0xee000190, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
1839   {"fltdp",      0xee0001b0, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
1840   {"fltdm",      0xee0001d0, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
1841   {"fltdz",      0xee0001f0, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
1842   {"flte",       0xee080110, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
1843   {"fltep",      0xee080130, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
1844   {"fltem",      0xee080150, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
1845   {"fltez",      0xee080170, 3,  FPU_FPA_EXT_V1,   do_fpa_from_reg},
1846 
1847   /* The implementation of the FIX instruction is broken on some
1848      assemblers, in that it accepts a precision specifier as well as a
1849      rounding specifier, despite the fact that this is meaningless.
1850      To be more compatible, we accept it as well, though of course it
1851      does not set any bits.  */
1852   {"fix",        0xee100110, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
1853   {"fixp",       0xee100130, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
1854   {"fixm",       0xee100150, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
1855   {"fixz",       0xee100170, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
1856   {"fixsp",      0xee100130, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
1857   {"fixsm",      0xee100150, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
1858   {"fixsz",      0xee100170, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
1859   {"fixdp",      0xee100130, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
1860   {"fixdm",      0xee100150, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
1861   {"fixdz",      0xee100170, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
1862   {"fixep",      0xee100130, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
1863   {"fixem",      0xee100150, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
1864   {"fixez",      0xee100170, 3,  FPU_FPA_EXT_V1,   do_fpa_to_reg},
1865 
1866   /* Instructions that were new with the real FPA, call them V2.  */
1867   {"lfm",        0xec100200, 3,  FPU_FPA_EXT_V2,   do_fpa_ldmstm},
1868   {"lfmfd",      0xec900200, 3,  FPU_FPA_EXT_V2,   do_fpa_ldmstm},
1869   {"lfmea",      0xed100200, 3,  FPU_FPA_EXT_V2,   do_fpa_ldmstm},
1870   {"sfm",        0xec000200, 3,  FPU_FPA_EXT_V2,   do_fpa_ldmstm},
1871   {"sfmfd",      0xed000200, 3,  FPU_FPA_EXT_V2,   do_fpa_ldmstm},
1872   {"sfmea",      0xec800200, 3,  FPU_FPA_EXT_V2,   do_fpa_ldmstm},
1873 
1874   /* VFP V1xD (single precision).  */
1875   /* Moves and type conversions.  */
1876   {"fcpys",   0xeeb00a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1877   {"fmrs",    0xee100a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_sp},
1878   {"fmsr",    0xee000a10, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_from_reg},
1879   {"fmstat",  0xeef1fa10, 6, FPU_VFP_EXT_V1xD, do_empty},
1880   {"fsitos",  0xeeb80ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1881   {"fuitos",  0xeeb80a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1882   {"ftosis",  0xeebd0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1883   {"ftosizs", 0xeebd0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1884   {"ftouis",  0xeebc0a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1885   {"ftouizs", 0xeebc0ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1886   {"fmrx",    0xeef00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_reg_from_ctrl},
1887   {"fmxr",    0xeee00a10, 4, FPU_VFP_EXT_V1xD, do_vfp_ctrl_from_reg},
1888 
1889   /* Memory operations.  */
1890   {"flds",    0xed100a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1891   {"fsts",    0xed000a00, 4, FPU_VFP_EXT_V1xD, do_vfp_sp_ldst},
1892   {"fldmias", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1893   {"fldmfds", 0xec900a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1894   {"fldmdbs", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1895   {"fldmeas", 0xed300a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1896   {"fldmiax", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1897   {"fldmfdx", 0xec900b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1898   {"fldmdbx", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1899   {"fldmeax", 0xed300b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1900   {"fstmias", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1901   {"fstmeas", 0xec800a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmia},
1902   {"fstmdbs", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1903   {"fstmfds", 0xed200a00, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_ldstmdb},
1904   {"fstmiax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1905   {"fstmeax", 0xec800b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmia},
1906   {"fstmdbx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1907   {"fstmfdx", 0xed200b00, 7, FPU_VFP_EXT_V1xD, do_vfp_xp_ldstmdb},
1908 
1909   /* Monadic operations.  */
1910   {"fabss",   0xeeb00ac0, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1911   {"fnegs",   0xeeb10a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1912   {"fsqrts",  0xeeb10ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1913 
1914   /* Dyadic operations.  */
1915   {"fadds",   0xee300a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1916   {"fsubs",   0xee300a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1917   {"fmuls",   0xee200a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1918   {"fdivs",   0xee800a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1919   {"fmacs",   0xee000a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1920   {"fmscs",   0xee100a00, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1921   {"fnmuls",  0xee200a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1922   {"fnmacs",  0xee000a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1923   {"fnmscs",  0xee100a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_dyadic},
1924 
1925   /* Comparisons.  */
1926   {"fcmps",   0xeeb40a40, 5, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1927   {"fcmpzs",  0xeeb50a40, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1928   {"fcmpes",  0xeeb40ac0, 6, FPU_VFP_EXT_V1xD, do_vfp_sp_monadic},
1929   {"fcmpezs", 0xeeb50ac0, 7, FPU_VFP_EXT_V1xD, do_vfp_sp_compare_z},
1930 
1931   /* VFP V1 (Double precision).  */
1932   /* Moves and type conversions.  */
1933   {"fcpyd",   0xeeb00b40, 5, FPU_VFP_EXT_V1,   do_vfp_dp_monadic},
1934   {"fcvtds",  0xeeb70ac0, 6, FPU_VFP_EXT_V1,   do_vfp_dp_sp_cvt},
1935   {"fcvtsd",  0xeeb70bc0, 6, FPU_VFP_EXT_V1,   do_vfp_sp_dp_cvt},
1936   {"fmdhr",   0xee200b10, 5, FPU_VFP_EXT_V1,   do_vfp_dp_from_reg},
1937   {"fmdlr",   0xee000b10, 5, FPU_VFP_EXT_V1,   do_vfp_dp_from_reg},
1938   {"fmrdh",   0xee300b10, 5, FPU_VFP_EXT_V1,   do_vfp_reg_from_dp},
1939   {"fmrdl",   0xee100b10, 5, FPU_VFP_EXT_V1,   do_vfp_reg_from_dp},
1940   {"fsitod",  0xeeb80bc0, 6, FPU_VFP_EXT_V1,   do_vfp_dp_sp_cvt},
1941   {"fuitod",  0xeeb80b40, 6, FPU_VFP_EXT_V1,   do_vfp_dp_sp_cvt},
1942   {"ftosid",  0xeebd0b40, 6, FPU_VFP_EXT_V1,   do_vfp_sp_dp_cvt},
1943   {"ftosizd", 0xeebd0bc0, 7, FPU_VFP_EXT_V1,   do_vfp_sp_dp_cvt},
1944   {"ftouid",  0xeebc0b40, 6, FPU_VFP_EXT_V1,   do_vfp_sp_dp_cvt},
1945   {"ftouizd", 0xeebc0bc0, 7, FPU_VFP_EXT_V1,   do_vfp_sp_dp_cvt},
1946 
1947   /* Memory operations.  */
1948   {"fldd",    0xed100b00, 4, FPU_VFP_EXT_V1,   do_vfp_dp_ldst},
1949   {"fstd",    0xed000b00, 4, FPU_VFP_EXT_V1,   do_vfp_dp_ldst},
1950   {"fldmiad", 0xec900b00, 7, FPU_VFP_EXT_V1,   do_vfp_dp_ldstmia},
1951   {"fldmfdd", 0xec900b00, 7, FPU_VFP_EXT_V1,   do_vfp_dp_ldstmia},
1952   {"fldmdbd", 0xed300b00, 7, FPU_VFP_EXT_V1,   do_vfp_dp_ldstmdb},
1953   {"fldmead", 0xed300b00, 7, FPU_VFP_EXT_V1,   do_vfp_dp_ldstmdb},
1954   {"fstmiad", 0xec800b00, 7, FPU_VFP_EXT_V1,   do_vfp_dp_ldstmia},
1955   {"fstmead", 0xec800b00, 7, FPU_VFP_EXT_V1,   do_vfp_dp_ldstmia},
1956   {"fstmdbd", 0xed200b00, 7, FPU_VFP_EXT_V1,   do_vfp_dp_ldstmdb},
1957   {"fstmfdd", 0xed200b00, 7, FPU_VFP_EXT_V1,   do_vfp_dp_ldstmdb},
1958 
1959   /* Monadic operations.  */
1960   {"fabsd",   0xeeb00bc0, 5, FPU_VFP_EXT_V1,   do_vfp_dp_monadic},
1961   {"fnegd",   0xeeb10b40, 5, FPU_VFP_EXT_V1,   do_vfp_dp_monadic},
1962   {"fsqrtd",  0xeeb10bc0, 6, FPU_VFP_EXT_V1,   do_vfp_dp_monadic},
1963 
1964   /* Dyadic operations.  */
1965   {"faddd",   0xee300b00, 5, FPU_VFP_EXT_V1,   do_vfp_dp_dyadic},
1966   {"fsubd",   0xee300b40, 5, FPU_VFP_EXT_V1,   do_vfp_dp_dyadic},
1967   {"fmuld",   0xee200b00, 5, FPU_VFP_EXT_V1,   do_vfp_dp_dyadic},
1968   {"fdivd",   0xee800b00, 5, FPU_VFP_EXT_V1,   do_vfp_dp_dyadic},
1969   {"fmacd",   0xee000b00, 5, FPU_VFP_EXT_V1,   do_vfp_dp_dyadic},
1970   {"fmscd",   0xee100b00, 5, FPU_VFP_EXT_V1,   do_vfp_dp_dyadic},
1971   {"fnmuld",  0xee200b40, 6, FPU_VFP_EXT_V1,   do_vfp_dp_dyadic},
1972   {"fnmacd",  0xee000b40, 6, FPU_VFP_EXT_V1,   do_vfp_dp_dyadic},
1973   {"fnmscd",  0xee100b40, 6, FPU_VFP_EXT_V1,   do_vfp_dp_dyadic},
1974 
1975   /* Comparisons.  */
1976   {"fcmpd",   0xeeb40b40, 5, FPU_VFP_EXT_V1,   do_vfp_dp_monadic},
1977   {"fcmpzd",  0xeeb50b40, 6, FPU_VFP_EXT_V1,   do_vfp_dp_compare_z},
1978   {"fcmped",  0xeeb40bc0, 6, FPU_VFP_EXT_V1,   do_vfp_dp_monadic},
1979   {"fcmpezd", 0xeeb50bc0, 7, FPU_VFP_EXT_V1,   do_vfp_dp_compare_z},
1980 
1981   /* VFP V2.  */
1982   {"fmsrr",   0xec400a10, 5, FPU_VFP_EXT_V2,   do_vfp_sp2_from_reg2},
1983   {"fmrrs",   0xec500a10, 5, FPU_VFP_EXT_V2,   do_vfp_reg2_from_sp2},
1984   {"fmdrr",   0xec400b10, 5, FPU_VFP_EXT_V2,   do_vfp_dp_from_reg2},
1985   {"fmrrd",   0xec500b10, 5, FPU_VFP_EXT_V2,   do_vfp_reg2_from_dp},
1986 
1987   /* Intel XScale extensions to ARM V5 ISA.  (All use CP0).  */
1988   {"mia",        0xee200010, 3,  ARM_CEXT_XSCALE,   do_xsc_mia},
1989   {"miaph",      0xee280010, 5,  ARM_CEXT_XSCALE,   do_xsc_mia},
1990   {"miabb",      0xee2c0010, 5,  ARM_CEXT_XSCALE,   do_xsc_mia},
1991   {"miabt",      0xee2d0010, 5,  ARM_CEXT_XSCALE,   do_xsc_mia},
1992   {"miatb",      0xee2e0010, 5,  ARM_CEXT_XSCALE,   do_xsc_mia},
1993   {"miatt",      0xee2f0010, 5,  ARM_CEXT_XSCALE,   do_xsc_mia},
1994   {"mar",        0xec400000, 3,  ARM_CEXT_XSCALE,   do_xsc_mar},
1995   {"mra",        0xec500000, 3,  ARM_CEXT_XSCALE,   do_xsc_mra},
1996 
1997   /* Intel Wireless MMX technology instructions.  */
1998   {"tandcb",     0xee130130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
1999   {"tandch",     0xee530130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
2000   {"tandcw",     0xee930130, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tandc},
2001   {"tbcstb",     0xee400010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2002   {"tbcsth",     0xee400050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2003   {"tbcstw",     0xee400090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tbcst},
2004   {"textrcb",    0xee130170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2005   {"textrch",    0xee530170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2006   {"textrcw",    0xee930170, 7, ARM_CEXT_IWMMXT, do_iwmmxt_textrc},
2007   {"textrmub",   0xee100070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2008   {"textrmuh",   0xee500070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2009   {"textrmuw",   0xee900070, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2010   {"textrmsb",   0xee100078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2011   {"textrmsh",   0xee500078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2012   {"textrmsw",   0xee900078, 8, ARM_CEXT_IWMMXT, do_iwmmxt_textrm},
2013   {"tinsrb",     0xee600010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2014   {"tinsrh",     0xee600050, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2015   {"tinsrw",     0xee600090, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tinsr},
2016   {"tmcr",       0xee000110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmcr},
2017   {"tmcrr",      0xec400000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmcrr},
2018   {"tmia",       0xee200010, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2019   {"tmiaph",     0xee280010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2020   {"tmiabb",     0xee2c0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2021   {"tmiabt",     0xee2d0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2022   {"tmiatb",     0xee2e0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2023   {"tmiatt",     0xee2f0010, 6, ARM_CEXT_IWMMXT, do_iwmmxt_tmia},
2024   {"tmovmskb",   0xee100030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2025   {"tmovmskh",   0xee500030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2026   {"tmovmskw",   0xee900030, 8, ARM_CEXT_IWMMXT, do_iwmmxt_tmovmsk},
2027   {"tmrc",       0xee100110, 4, ARM_CEXT_IWMMXT, do_iwmmxt_tmrc},
2028   {"tmrrc",      0xec500000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_tmrrc},
2029   {"torcb",      0xee130150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2030   {"torch",      0xee530150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2031   {"torcw",      0xee930150, 5, ARM_CEXT_IWMMXT, do_iwmmxt_torc},
2032   {"waccb",      0xee0001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2033   {"wacch",      0xee4001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2034   {"waccw",      0xee8001c0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2035   {"waddbss",    0xee300180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2036   {"waddb",      0xee000180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2037   {"waddbus",    0xee100180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2038   {"waddhss",    0xee700180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2039   {"waddh",      0xee400180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2040   {"waddhus",    0xee500180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2041   {"waddwss",    0xeeb00180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2042   {"waddw",      0xee800180, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2043   {"waddwus",    0xee900180, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2044   {"waligni",    0xee000020, 7, ARM_CEXT_IWMMXT, do_iwmmxt_waligni},
2045   {"walignr0",   0xee800020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2046   {"walignr1",   0xee900020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2047   {"walignr2",   0xeea00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2048   {"walignr3",   0xeeb00020, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2049   {"wand",       0xee200000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2050   {"wandn",      0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2051   {"wavg2b",     0xee800000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2052   {"wavg2br",    0xee900000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2053   {"wavg2h",     0xeec00000, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2054   {"wavg2hr",    0xeed00000, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2055   {"wcmpeqb",    0xee000060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2056   {"wcmpeqh",    0xee400060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2057   {"wcmpeqw",    0xee800060, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2058   {"wcmpgtub",   0xee100060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2059   {"wcmpgtuh",   0xee500060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2060   {"wcmpgtuw",   0xee900060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2061   {"wcmpgtsb",   0xee300060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2062   {"wcmpgtsh",   0xee700060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2063   {"wcmpgtsw",   0xeeb00060, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2064   {"wldrb",      0xec100000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2065   {"wldrh",      0xec100100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2066   {"wldrw",      0xec100200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2067   {"wldrd",      0xec100300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2068   {"wmacs",      0xee600100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2069   {"wmacsz",     0xee700100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2070   {"wmacu",      0xee400100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2071   {"wmacuz",     0xee500100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2072   {"wmadds",     0xeea00100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2073   {"wmaddu",     0xee800100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2074   {"wmaxsb",     0xee200160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2075   {"wmaxsh",     0xee600160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2076   {"wmaxsw",     0xeea00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2077   {"wmaxub",     0xee000160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2078   {"wmaxuh",     0xee400160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2079   {"wmaxuw",     0xee800160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2080   {"wminsb",     0xee300160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2081   {"wminsh",     0xee700160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2082   {"wminsw",     0xeeb00160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2083   {"wminub",     0xee100160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2084   {"wminuh",     0xee500160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2085   {"wminuw",     0xee900160, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2086   {"wmov",       0xee000000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wmov},
2087   {"wmulsm",     0xee300100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2088   {"wmulsl",     0xee200100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2089   {"wmulum",     0xee100100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2090   {"wmulul",     0xee000100, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2091   {"wor",        0xee000000, 3, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2092   {"wpackhss",   0xee700080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2093   {"wpackhus",   0xee500080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2094   {"wpackwss",   0xeeb00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2095   {"wpackwus",   0xee900080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2096   {"wpackdss",   0xeef00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2097   {"wpackdus",   0xeed00080, 8, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2098   {"wrorh",      0xee700040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2099   {"wrorhg",     0xee700148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2100   {"wrorw",      0xeeb00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2101   {"wrorwg",     0xeeb00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2102   {"wrord",      0xeef00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2103   {"wrordg",     0xeef00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2104   {"wsadb",      0xee000120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2105   {"wsadbz",     0xee100120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2106   {"wsadh",      0xee400120, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2107   {"wsadhz",     0xee500120, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2108   {"wshufh",     0xee0001e0, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wshufh},
2109   {"wsllh",      0xee500040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2110   {"wsllhg",     0xee500148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2111   {"wsllw",      0xee900040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2112   {"wsllwg",     0xee900148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2113   {"wslld",      0xeed00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2114   {"wslldg",     0xeed00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2115   {"wsrah",      0xee400040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2116   {"wsrahg",     0xee400148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2117   {"wsraw",      0xee800040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2118   {"wsrawg",     0xee800148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2119   {"wsrad",      0xeec00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2120   {"wsradg",     0xeec00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2121   {"wsrlh",      0xee600040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2122   {"wsrlhg",     0xee600148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2123   {"wsrlw",      0xeea00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2124   {"wsrlwg",     0xeea00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2125   {"wsrld",      0xeee00040, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2126   {"wsrldg",     0xeee00148, 6, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwcg},
2127   {"wstrb",      0xec000000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2128   {"wstrh",      0xec000100, 5, ARM_CEXT_IWMMXT, do_iwmmxt_byte_addr},
2129   {"wstrw",      0xec000200, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2130   {"wstrd",      0xec000300, 5, ARM_CEXT_IWMMXT, do_iwmmxt_word_addr},
2131   {"wsubbss",    0xee3001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2132   {"wsubb",      0xee0001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2133   {"wsubbus",    0xee1001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2134   {"wsubhss",    0xee7001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2135   {"wsubh",      0xee4001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2136   {"wsubhus",    0xee5001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2137   {"wsubwss",    0xeeb001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2138   {"wsubw",      0xee8001a0, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2139   {"wsubwus",    0xee9001a0, 7, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2140   {"wunpckehub", 0xee0000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2141   {"wunpckehuh", 0xee4000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2142   {"wunpckehuw", 0xee8000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2143   {"wunpckehsb", 0xee2000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2144   {"wunpckehsh", 0xee6000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2145   {"wunpckehsw", 0xeea000c0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2146   {"wunpckihb",  0xee1000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2147   {"wunpckihh",  0xee5000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2148   {"wunpckihw",  0xee9000c0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2149   {"wunpckelub", 0xee0000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2150   {"wunpckeluh", 0xee4000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2151   {"wunpckeluw", 0xee8000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2152   {"wunpckelsb", 0xee2000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2153   {"wunpckelsh", 0xee6000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2154   {"wunpckelsw", 0xeea000e0, 10, ARM_CEXT_IWMMXT, do_iwmmxt_wrwr},
2155   {"wunpckilb",  0xee1000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2156   {"wunpckilh",  0xee5000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2157   {"wunpckilw",  0xee9000e0, 9, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2158   {"wxor",       0xee100000, 4, ARM_CEXT_IWMMXT, do_iwmmxt_wrwrwr},
2159   {"wzero",      0xee300000, 5, ARM_CEXT_IWMMXT, do_iwmmxt_wzero},
2160 
2161   /* Cirrus Maverick instructions.  */
2162   {"cfldrs",     0xec100400, 6,  ARM_CEXT_MAVERICK, do_mav_ldst_1},
2163   {"cfldrd",     0xec500400, 6,  ARM_CEXT_MAVERICK, do_mav_ldst_2},
2164   {"cfldr32",    0xec100500, 7,  ARM_CEXT_MAVERICK, do_mav_ldst_3},
2165   {"cfldr64",    0xec500500, 7,  ARM_CEXT_MAVERICK, do_mav_ldst_4},
2166   {"cfstrs",     0xec000400, 6,  ARM_CEXT_MAVERICK, do_mav_ldst_1},
2167   {"cfstrd",     0xec400400, 6,  ARM_CEXT_MAVERICK, do_mav_ldst_2},
2168   {"cfstr32",    0xec000500, 7,  ARM_CEXT_MAVERICK, do_mav_ldst_3},
2169   {"cfstr64",    0xec400500, 7,  ARM_CEXT_MAVERICK, do_mav_ldst_4},
2170   {"cfmvsr",     0xee000450, 6,  ARM_CEXT_MAVERICK, do_mav_binops_2a},
2171   {"cfmvrs",     0xee100450, 6,  ARM_CEXT_MAVERICK, do_mav_binops_1a},
2172   {"cfmvdlr",    0xee000410, 7,  ARM_CEXT_MAVERICK, do_mav_binops_2b},
2173   {"cfmvrdl",    0xee100410, 7,  ARM_CEXT_MAVERICK, do_mav_binops_1b},
2174   {"cfmvdhr",    0xee000430, 7,  ARM_CEXT_MAVERICK, do_mav_binops_2b},
2175   {"cfmvrdh",    0xee100430, 7,  ARM_CEXT_MAVERICK, do_mav_binops_1b},
2176   {"cfmv64lr",   0xee000510, 8,  ARM_CEXT_MAVERICK, do_mav_binops_2c},
2177   {"cfmvr64l",   0xee100510, 8,  ARM_CEXT_MAVERICK, do_mav_binops_1c},
2178   {"cfmv64hr",   0xee000530, 8,  ARM_CEXT_MAVERICK, do_mav_binops_2c},
2179   {"cfmvr64h",   0xee100530, 8,  ARM_CEXT_MAVERICK, do_mav_binops_1c},
2180   {"cfmval32",   0xee200440, 8,  ARM_CEXT_MAVERICK, do_mav_binops_3a},
2181   {"cfmv32al",   0xee100440, 8,  ARM_CEXT_MAVERICK, do_mav_binops_3b},
2182   {"cfmvam32",   0xee200460, 8,  ARM_CEXT_MAVERICK, do_mav_binops_3a},
2183   {"cfmv32am",   0xee100460, 8,  ARM_CEXT_MAVERICK, do_mav_binops_3b},
2184   {"cfmvah32",   0xee200480, 8,  ARM_CEXT_MAVERICK, do_mav_binops_3a},
2185   {"cfmv32ah",   0xee100480, 8,  ARM_CEXT_MAVERICK, do_mav_binops_3b},
2186   {"cfmva32",    0xee2004a0, 7,  ARM_CEXT_MAVERICK, do_mav_binops_3a},
2187   {"cfmv32a",    0xee1004a0, 7,  ARM_CEXT_MAVERICK, do_mav_binops_3b},
2188   {"cfmva64",    0xee2004c0, 7,  ARM_CEXT_MAVERICK, do_mav_binops_3c},
2189   {"cfmv64a",    0xee1004c0, 7,  ARM_CEXT_MAVERICK, do_mav_binops_3d},
2190   {"cfmvsc32",   0xee2004e0, 8,  ARM_CEXT_MAVERICK, do_mav_dspsc_1},
2191   {"cfmv32sc",   0xee1004e0, 8,  ARM_CEXT_MAVERICK, do_mav_dspsc_2},
2192   {"cfcpys",     0xee000400, 6,  ARM_CEXT_MAVERICK, do_mav_binops_1d},
2193   {"cfcpyd",     0xee000420, 6,  ARM_CEXT_MAVERICK, do_mav_binops_1e},
2194   {"cfcvtsd",    0xee000460, 7,  ARM_CEXT_MAVERICK, do_mav_binops_1f},
2195   {"cfcvtds",    0xee000440, 7,  ARM_CEXT_MAVERICK, do_mav_binops_1g},
2196   {"cfcvt32s",   0xee000480, 8,  ARM_CEXT_MAVERICK, do_mav_binops_1h},
2197   {"cfcvt32d",   0xee0004a0, 8,  ARM_CEXT_MAVERICK, do_mav_binops_1i},
2198   {"cfcvt64s",   0xee0004c0, 8,  ARM_CEXT_MAVERICK, do_mav_binops_1j},
2199   {"cfcvt64d",   0xee0004e0, 8,  ARM_CEXT_MAVERICK, do_mav_binops_1k},
2200   {"cfcvts32",   0xee100580, 8,  ARM_CEXT_MAVERICK, do_mav_binops_1l},
2201   {"cfcvtd32",   0xee1005a0, 8,  ARM_CEXT_MAVERICK, do_mav_binops_1m},
2202   {"cftruncs32", 0xee1005c0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1l},
2203   {"cftruncd32", 0xee1005e0, 10, ARM_CEXT_MAVERICK, do_mav_binops_1m},
2204   {"cfrshl32",   0xee000550, 8,  ARM_CEXT_MAVERICK, do_mav_triple_4a},
2205   {"cfrshl64",   0xee000570, 8,  ARM_CEXT_MAVERICK, do_mav_triple_4b},
2206   {"cfsh32",     0xee000500, 6,  ARM_CEXT_MAVERICK, do_mav_shift_1},
2207   {"cfsh64",     0xee200500, 6,  ARM_CEXT_MAVERICK, do_mav_shift_2},
2208   {"cfcmps",     0xee100490, 6,  ARM_CEXT_MAVERICK, do_mav_triple_5a},
2209   {"cfcmpd",     0xee1004b0, 6,  ARM_CEXT_MAVERICK, do_mav_triple_5b},
2210   {"cfcmp32",    0xee100590, 7,  ARM_CEXT_MAVERICK, do_mav_triple_5c},
2211   {"cfcmp64",    0xee1005b0, 7,  ARM_CEXT_MAVERICK, do_mav_triple_5d},
2212   {"cfabss",     0xee300400, 6,  ARM_CEXT_MAVERICK, do_mav_binops_1d},
2213   {"cfabsd",     0xee300420, 6,  ARM_CEXT_MAVERICK, do_mav_binops_1e},
2214   {"cfnegs",     0xee300440, 6,  ARM_CEXT_MAVERICK, do_mav_binops_1d},
2215   {"cfnegd",     0xee300460, 6,  ARM_CEXT_MAVERICK, do_mav_binops_1e},
2216   {"cfadds",     0xee300480, 6,  ARM_CEXT_MAVERICK, do_mav_triple_5e},
2217   {"cfaddd",     0xee3004a0, 6,  ARM_CEXT_MAVERICK, do_mav_triple_5f},
2218   {"cfsubs",     0xee3004c0, 6,  ARM_CEXT_MAVERICK, do_mav_triple_5e},
2219   {"cfsubd",     0xee3004e0, 6,  ARM_CEXT_MAVERICK, do_mav_triple_5f},
2220   {"cfmuls",     0xee100400, 6,  ARM_CEXT_MAVERICK, do_mav_triple_5e},
2221   {"cfmuld",     0xee100420, 6,  ARM_CEXT_MAVERICK, do_mav_triple_5f},
2222   {"cfabs32",    0xee300500, 7,  ARM_CEXT_MAVERICK, do_mav_binops_1n},
2223   {"cfabs64",    0xee300520, 7,  ARM_CEXT_MAVERICK, do_mav_binops_1o},
2224   {"cfneg32",    0xee300540, 7,  ARM_CEXT_MAVERICK, do_mav_binops_1n},
2225   {"cfneg64",    0xee300560, 7,  ARM_CEXT_MAVERICK, do_mav_binops_1o},
2226   {"cfadd32",    0xee300580, 7,  ARM_CEXT_MAVERICK, do_mav_triple_5g},
2227   {"cfadd64",    0xee3005a0, 7,  ARM_CEXT_MAVERICK, do_mav_triple_5h},
2228   {"cfsub32",    0xee3005c0, 7,  ARM_CEXT_MAVERICK, do_mav_triple_5g},
2229   {"cfsub64",    0xee3005e0, 7,  ARM_CEXT_MAVERICK, do_mav_triple_5h},
2230   {"cfmul32",    0xee100500, 7,  ARM_CEXT_MAVERICK, do_mav_triple_5g},
2231   {"cfmul64",    0xee100520, 7,  ARM_CEXT_MAVERICK, do_mav_triple_5h},
2232   {"cfmac32",    0xee100540, 7,  ARM_CEXT_MAVERICK, do_mav_triple_5g},
2233   {"cfmsc32",    0xee100560, 7,  ARM_CEXT_MAVERICK, do_mav_triple_5g},
2234   {"cfmadd32",   0xee000600, 8,  ARM_CEXT_MAVERICK, do_mav_quad_6a},
2235   {"cfmsub32",   0xee100600, 8,  ARM_CEXT_MAVERICK, do_mav_quad_6a},
2236   {"cfmadda32",  0xee200600, 9,  ARM_CEXT_MAVERICK, do_mav_quad_6b},
2237   {"cfmsuba32",  0xee300600, 9,  ARM_CEXT_MAVERICK, do_mav_quad_6b},
2238 };
2239 
2240 /* Defines for various bits that we will want to toggle.  */
2241 #define INST_IMMEDIATE	0x02000000
2242 #define OFFSET_REG	0x02000000
2243 #define HWOFFSET_IMM    0x00400000
2244 #define SHIFT_BY_REG	0x00000010
2245 #define PRE_INDEX	0x01000000
2246 #define INDEX_UP	0x00800000
2247 #define WRITE_BACK	0x00200000
2248 #define LDM_TYPE_2_OR_3	0x00400000
2249 
2250 #define LITERAL_MASK	0xf000f000
2251 #define OPCODE_MASK	0xfe1fffff
2252 #define V4_STR_BIT	0x00000020
2253 
2254 #define DATA_OP_SHIFT	21
2255 
2256 /* Codes to distinguish the arithmetic instructions.  */
2257 #define OPCODE_AND	0
2258 #define OPCODE_EOR	1
2259 #define OPCODE_SUB	2
2260 #define OPCODE_RSB	3
2261 #define OPCODE_ADD	4
2262 #define OPCODE_ADC	5
2263 #define OPCODE_SBC	6
2264 #define OPCODE_RSC	7
2265 #define OPCODE_TST	8
2266 #define OPCODE_TEQ	9
2267 #define OPCODE_CMP	10
2268 #define OPCODE_CMN	11
2269 #define OPCODE_ORR	12
2270 #define OPCODE_MOV	13
2271 #define OPCODE_BIC	14
2272 #define OPCODE_MVN	15
2273 
2274 /* Thumb v1 (ARMv4T).  */
2275 static void do_t_nop		PARAMS ((char *));
2276 static void do_t_arit		PARAMS ((char *));
2277 static void do_t_add		PARAMS ((char *));
2278 static void do_t_asr		PARAMS ((char *));
2279 static void do_t_branch9	PARAMS ((char *));
2280 static void do_t_branch12	PARAMS ((char *));
2281 static void do_t_branch23	PARAMS ((char *));
2282 static void do_t_bx		PARAMS ((char *));
2283 static void do_t_compare	PARAMS ((char *));
2284 static void do_t_ldmstm		PARAMS ((char *));
2285 static void do_t_ldr		PARAMS ((char *));
2286 static void do_t_ldrb		PARAMS ((char *));
2287 static void do_t_ldrh		PARAMS ((char *));
2288 static void do_t_lds		PARAMS ((char *));
2289 static void do_t_lsl		PARAMS ((char *));
2290 static void do_t_lsr		PARAMS ((char *));
2291 static void do_t_mov		PARAMS ((char *));
2292 static void do_t_push_pop	PARAMS ((char *));
2293 static void do_t_str		PARAMS ((char *));
2294 static void do_t_strb		PARAMS ((char *));
2295 static void do_t_strh		PARAMS ((char *));
2296 static void do_t_sub		PARAMS ((char *));
2297 static void do_t_swi		PARAMS ((char *));
2298 static void do_t_adr		PARAMS ((char *));
2299 
2300 /* Thumb v2 (ARMv5T).  */
2301 static void do_t_blx		PARAMS ((char *));
2302 static void do_t_bkpt		PARAMS ((char *));
2303 
2304 /* ARM V6.  */
2305 static void do_t_cps            PARAMS ((char *));
2306 static void do_t_cpy            PARAMS ((char *));
2307 static void do_t_setend         PARAMS ((char *));;
2308 
2309 #define T_OPCODE_MUL 0x4340
2310 #define T_OPCODE_TST 0x4200
2311 #define T_OPCODE_CMN 0x42c0
2312 #define T_OPCODE_NEG 0x4240
2313 #define T_OPCODE_MVN 0x43c0
2314 
2315 #define T_OPCODE_ADD_R3	0x1800
2316 #define T_OPCODE_SUB_R3 0x1a00
2317 #define T_OPCODE_ADD_HI 0x4400
2318 #define T_OPCODE_ADD_ST 0xb000
2319 #define T_OPCODE_SUB_ST 0xb080
2320 #define T_OPCODE_ADD_SP 0xa800
2321 #define T_OPCODE_ADD_PC 0xa000
2322 #define T_OPCODE_ADD_I8 0x3000
2323 #define T_OPCODE_SUB_I8 0x3800
2324 #define T_OPCODE_ADD_I3 0x1c00
2325 #define T_OPCODE_SUB_I3 0x1e00
2326 
2327 #define T_OPCODE_ASR_R	0x4100
2328 #define T_OPCODE_LSL_R	0x4080
2329 #define T_OPCODE_LSR_R  0x40c0
2330 #define T_OPCODE_ASR_I	0x1000
2331 #define T_OPCODE_LSL_I	0x0000
2332 #define T_OPCODE_LSR_I	0x0800
2333 
2334 #define T_OPCODE_MOV_I8	0x2000
2335 #define T_OPCODE_CMP_I8 0x2800
2336 #define T_OPCODE_CMP_LR 0x4280
2337 #define T_OPCODE_MOV_HR 0x4600
2338 #define T_OPCODE_CMP_HR 0x4500
2339 
2340 #define T_OPCODE_LDR_PC 0x4800
2341 #define T_OPCODE_LDR_SP 0x9800
2342 #define T_OPCODE_STR_SP 0x9000
2343 #define T_OPCODE_LDR_IW 0x6800
2344 #define T_OPCODE_STR_IW 0x6000
2345 #define T_OPCODE_LDR_IH 0x8800
2346 #define T_OPCODE_STR_IH 0x8000
2347 #define T_OPCODE_LDR_IB 0x7800
2348 #define T_OPCODE_STR_IB 0x7000
2349 #define T_OPCODE_LDR_RW 0x5800
2350 #define T_OPCODE_STR_RW 0x5000
2351 #define T_OPCODE_LDR_RH 0x5a00
2352 #define T_OPCODE_STR_RH 0x5200
2353 #define T_OPCODE_LDR_RB 0x5c00
2354 #define T_OPCODE_STR_RB 0x5400
2355 
2356 #define T_OPCODE_PUSH	0xb400
2357 #define T_OPCODE_POP	0xbc00
2358 
2359 #define T_OPCODE_BRANCH 0xe7fe
2360 
2361 static int thumb_reg		PARAMS ((char ** str, int hi_lo));
2362 
2363 #define THUMB_SIZE	2	/* Size of thumb instruction.  */
2364 #define THUMB_REG_LO	0x1
2365 #define THUMB_REG_HI	0x2
2366 #define THUMB_REG_ANY	0x3
2367 
2368 #define THUMB_H1	0x0080
2369 #define THUMB_H2	0x0040
2370 
2371 #define THUMB_ASR 0
2372 #define THUMB_LSL 1
2373 #define THUMB_LSR 2
2374 
2375 #define THUMB_MOVE 0
2376 #define THUMB_COMPARE 1
2377 #define THUMB_CPY 2
2378 
2379 #define THUMB_LOAD 0
2380 #define THUMB_STORE 1
2381 
2382 #define THUMB_PP_PC_LR 0x0100
2383 
2384 /* These three are used for immediate shifts, do not alter.  */
2385 #define THUMB_WORD 2
2386 #define THUMB_HALFWORD 1
2387 #define THUMB_BYTE 0
2388 
2389 struct thumb_opcode
2390 {
2391   /* Basic string to match.  */
2392   const char * template;
2393 
2394   /* Basic instruction code.  */
2395   unsigned long value;
2396 
2397   int size;
2398 
2399   /* Which CPU variants this exists for.  */
2400   unsigned long variant;
2401 
2402   /* Function to call to parse args.  */
2403   void (* parms) PARAMS ((char *));
2404 };
2405 
2406 static const struct thumb_opcode tinsns[] =
2407 {
2408   /* Thumb v1 (ARMv4T).  */
2409   {"adc",	0x4140,		2,	ARM_EXT_V4T, do_t_arit},
2410   {"add",	0x0000,		2,	ARM_EXT_V4T, do_t_add},
2411   {"and",	0x4000,		2,	ARM_EXT_V4T, do_t_arit},
2412   {"asr",	0x0000,		2,	ARM_EXT_V4T, do_t_asr},
2413   {"b",		T_OPCODE_BRANCH, 2,	ARM_EXT_V4T, do_t_branch12},
2414   {"beq",	0xd0fe,		2,	ARM_EXT_V4T, do_t_branch9},
2415   {"bne",	0xd1fe,		2,	ARM_EXT_V4T, do_t_branch9},
2416   {"bcs",	0xd2fe,		2,	ARM_EXT_V4T, do_t_branch9},
2417   {"bhs",	0xd2fe,		2,	ARM_EXT_V4T, do_t_branch9},
2418   {"bcc",	0xd3fe,		2,	ARM_EXT_V4T, do_t_branch9},
2419   {"bul",	0xd3fe,		2,	ARM_EXT_V4T, do_t_branch9},
2420   {"blo",	0xd3fe,		2,	ARM_EXT_V4T, do_t_branch9},
2421   {"bmi",	0xd4fe,		2,	ARM_EXT_V4T, do_t_branch9},
2422   {"bpl",	0xd5fe,		2,	ARM_EXT_V4T, do_t_branch9},
2423   {"bvs",	0xd6fe,		2,	ARM_EXT_V4T, do_t_branch9},
2424   {"bvc",	0xd7fe,		2,	ARM_EXT_V4T, do_t_branch9},
2425   {"bhi",	0xd8fe,		2,	ARM_EXT_V4T, do_t_branch9},
2426   {"bls",	0xd9fe,		2,	ARM_EXT_V4T, do_t_branch9},
2427   {"bge",	0xdafe,		2,	ARM_EXT_V4T, do_t_branch9},
2428   {"blt",	0xdbfe,		2,	ARM_EXT_V4T, do_t_branch9},
2429   {"bgt",	0xdcfe,		2,	ARM_EXT_V4T, do_t_branch9},
2430   {"ble",	0xddfe,		2,	ARM_EXT_V4T, do_t_branch9},
2431   {"bal",	0xdefe,		2,	ARM_EXT_V4T, do_t_branch9},
2432   {"bic",	0x4380,		2,	ARM_EXT_V4T, do_t_arit},
2433   {"bl",	0xf7fffffe,	4,	ARM_EXT_V4T, do_t_branch23},
2434   {"bx",	0x4700,		2,	ARM_EXT_V4T, do_t_bx},
2435   {"cmn",	T_OPCODE_CMN,	2,	ARM_EXT_V4T, do_t_arit},
2436   {"cmp",	0x0000,		2,	ARM_EXT_V4T, do_t_compare},
2437   {"eor",	0x4040,		2,	ARM_EXT_V4T, do_t_arit},
2438   {"ldmia",	0xc800,		2,	ARM_EXT_V4T, do_t_ldmstm},
2439   {"ldr",	0x0000,		2,	ARM_EXT_V4T, do_t_ldr},
2440   {"ldrb",	0x0000,		2,	ARM_EXT_V4T, do_t_ldrb},
2441   {"ldrh",	0x0000,		2,	ARM_EXT_V4T, do_t_ldrh},
2442   {"ldrsb",	0x5600,		2,	ARM_EXT_V4T, do_t_lds},
2443   {"ldrsh",	0x5e00,		2,	ARM_EXT_V4T, do_t_lds},
2444   {"ldsb",	0x5600,		2,	ARM_EXT_V4T, do_t_lds},
2445   {"ldsh",	0x5e00,		2,	ARM_EXT_V4T, do_t_lds},
2446   {"lsl",	0x0000,		2,	ARM_EXT_V4T, do_t_lsl},
2447   {"lsr",	0x0000,		2,	ARM_EXT_V4T, do_t_lsr},
2448   {"mov",	0x0000,		2,	ARM_EXT_V4T, do_t_mov},
2449   {"mul",	T_OPCODE_MUL,	2,	ARM_EXT_V4T, do_t_arit},
2450   {"mvn",	T_OPCODE_MVN,	2,	ARM_EXT_V4T, do_t_arit},
2451   {"neg",	T_OPCODE_NEG,	2,	ARM_EXT_V4T, do_t_arit},
2452   {"orr",	0x4300,		2,	ARM_EXT_V4T, do_t_arit},
2453   {"pop",	0xbc00,		2,	ARM_EXT_V4T, do_t_push_pop},
2454   {"push",	0xb400,		2,	ARM_EXT_V4T, do_t_push_pop},
2455   {"ror",	0x41c0,		2,	ARM_EXT_V4T, do_t_arit},
2456   {"sbc",	0x4180,		2,	ARM_EXT_V4T, do_t_arit},
2457   {"stmia",	0xc000,		2,	ARM_EXT_V4T, do_t_ldmstm},
2458   {"str",	0x0000,		2,	ARM_EXT_V4T, do_t_str},
2459   {"strb",	0x0000,		2,	ARM_EXT_V4T, do_t_strb},
2460   {"strh",	0x0000,		2,	ARM_EXT_V4T, do_t_strh},
2461   {"swi",	0xdf00,		2,	ARM_EXT_V4T, do_t_swi},
2462   {"sub",	0x0000,		2,	ARM_EXT_V4T, do_t_sub},
2463   {"tst",	T_OPCODE_TST,	2,	ARM_EXT_V4T, do_t_arit},
2464   /* Pseudo ops:  */
2465   {"adr",       0x0000,         2,      ARM_EXT_V4T, do_t_adr},
2466   {"nop",       0x46C0,         2,      ARM_EXT_V4T, do_t_nop},      /* mov r8,r8  */
2467   /* Thumb v2 (ARMv5T).  */
2468   {"blx",	0,		0,	ARM_EXT_V5T, do_t_blx},
2469   {"bkpt",	0xbe00,		2,	ARM_EXT_V5T, do_t_bkpt},
2470 
2471   /* ARM V6.  */
2472   {"cpsie",	0xb660,		2,	ARM_EXT_V6,  do_t_cps},
2473   {"cpsid",     0xb670,		2,	ARM_EXT_V6,  do_t_cps},
2474   {"cpy",	0x4600,		2,	ARM_EXT_V6,  do_t_cpy},
2475   {"rev",	0xba00,		2,	ARM_EXT_V6,  do_t_arit},
2476   {"rev16",	0xba40,		2,	ARM_EXT_V6,  do_t_arit},
2477   {"revsh",	0xbac0,		2,	ARM_EXT_V6,  do_t_arit},
2478   {"setend",	0xb650,		2,	ARM_EXT_V6,  do_t_setend},
2479   {"sxth",	0xb200,		2,	ARM_EXT_V6,  do_t_arit},
2480   {"sxtb",	0xb240,		2,	ARM_EXT_V6,  do_t_arit},
2481   {"uxth",	0xb280,		2,	ARM_EXT_V6,  do_t_arit},
2482   {"uxtb",	0xb2c0,		2,	ARM_EXT_V6,  do_t_arit},
2483 };
2484 
2485 #define BAD_ARGS 	_("bad arguments to instruction")
2486 #define BAD_PC 		_("r15 not allowed here")
2487 #define BAD_COND 	_("instruction is not conditional")
2488 #define ERR_NO_ACCUM	_("acc0 expected")
2489 
2490 static struct hash_control * arm_ops_hsh   = NULL;
2491 static struct hash_control * arm_tops_hsh  = NULL;
2492 static struct hash_control * arm_cond_hsh  = NULL;
2493 static struct hash_control * arm_shift_hsh = NULL;
2494 static struct hash_control * arm_psr_hsh   = NULL;
2495 
2496 /* This table describes all the machine specific pseudo-ops the assembler
2497    has to support.  The fields are:
2498      pseudo-op name without dot
2499      function to call to execute this pseudo-op
2500      Integer arg to pass to the function.  */
2501 
2502 static void s_req PARAMS ((int));
2503 static void s_unreq PARAMS ((int));
2504 static void s_align PARAMS ((int));
2505 static void s_bss PARAMS ((int));
2506 static void s_even PARAMS ((int));
2507 static void s_ltorg PARAMS ((int));
2508 static void s_arm PARAMS ((int));
2509 static void s_thumb PARAMS ((int));
2510 static void s_code PARAMS ((int));
2511 static void s_force_thumb PARAMS ((int));
2512 static void s_thumb_func PARAMS ((int));
2513 static void s_thumb_set PARAMS ((int));
2514 #ifdef OBJ_ELF
2515 static void s_arm_elf_cons PARAMS ((int));
2516 #endif
2517 
2518 static int my_get_expression PARAMS ((expressionS *, char **));
2519 
2520 const pseudo_typeS md_pseudo_table[] =
2521 {
2522   /* Never called because '.req' does not start a line.  */
2523   { "req",         s_req,         0 },
2524   { "unreq",       s_unreq,       0 },
2525   { "bss",         s_bss,         0 },
2526   { "align",       s_align,       0 },
2527   { "arm",         s_arm,         0 },
2528   { "thumb",       s_thumb,       0 },
2529   { "code",        s_code,        0 },
2530   { "force_thumb", s_force_thumb, 0 },
2531   { "thumb_func",  s_thumb_func,  0 },
2532   { "thumb_set",   s_thumb_set,   0 },
2533   { "even",        s_even,        0 },
2534   { "ltorg",       s_ltorg,       0 },
2535   { "pool",        s_ltorg,       0 },
2536 #ifdef OBJ_ELF
2537   { "word",        s_arm_elf_cons, 4 },
2538   { "long",        s_arm_elf_cons, 4 },
2539 #else
2540   { "word",        cons, 4},
2541 #endif
2542   { "extend",      float_cons, 'x' },
2543   { "ldouble",     float_cons, 'x' },
2544   { "packed",      float_cons, 'p' },
2545   { 0, 0, 0 }
2546 };
2547 
2548 /* Other internal functions.  */
2549 static int arm_parse_extension PARAMS ((char *, int *));
2550 static int arm_parse_cpu PARAMS ((char *));
2551 static int arm_parse_arch PARAMS ((char *));
2552 static int arm_parse_fpu PARAMS ((char *));
2553 static int arm_parse_float_abi PARAMS ((char *));
2554 #if 0 /* Suppressed - for now.  */
2555 #if defined OBJ_COFF || defined OBJ_ELF
2556 static void arm_add_note PARAMS ((const char *, const char *, unsigned int));
2557 #endif
2558 #endif
2559 
2560 /* Stuff needed to resolve the label ambiguity
2561    As:
2562      ...
2563      label:   <insn>
2564    may differ from:
2565      ...
2566      label:
2567               <insn>
2568 */
2569 
2570 symbolS *  last_label_seen;
2571 static int label_is_thumb_function_name = FALSE;
2572 
2573 /* Literal Pool stuff.  */
2574 
2575 #define MAX_LITERAL_POOL_SIZE 1024
2576 
2577 /* Literal pool structure.  Held on a per-section
2578    and per-sub-section basis.  */
2579 typedef struct literal_pool
2580 {
2581   expressionS    literals [MAX_LITERAL_POOL_SIZE];
2582   unsigned int   next_free_entry;
2583   unsigned int   id;
2584   symbolS *      symbol;
2585   segT           section;
2586   subsegT        sub_section;
2587   struct literal_pool * next;
2588 } literal_pool;
2589 
2590 /* Pointer to a linked list of literal pools.  */
2591 literal_pool * list_of_pools = NULL;
2592 
2593 static literal_pool * find_literal_pool PARAMS ((void));
2594 static literal_pool * find_or_make_literal_pool PARAMS ((void));
2595 
2596 static literal_pool *
find_literal_pool()2597 find_literal_pool ()
2598 {
2599   literal_pool * pool;
2600 
2601   for (pool = list_of_pools; pool != NULL; pool = pool->next)
2602     {
2603       if (pool->section == now_seg
2604 	  && pool->sub_section == now_subseg)
2605 	break;
2606     }
2607 
2608   return pool;
2609 }
2610 
2611 static literal_pool *
find_or_make_literal_pool()2612 find_or_make_literal_pool ()
2613 {
2614   /* Next literal pool ID number.  */
2615   static unsigned int latest_pool_num = 1;
2616   literal_pool *      pool;
2617 
2618   pool = find_literal_pool ();
2619 
2620   if (pool == NULL)
2621     {
2622       /* Create a new pool.  */
2623       pool = (literal_pool *) xmalloc (sizeof (* pool));
2624       if (! pool)
2625 	return NULL;
2626 
2627       pool->next_free_entry = 0;
2628       pool->section         = now_seg;
2629       pool->sub_section     = now_subseg;
2630       pool->next            = list_of_pools;
2631       pool->symbol          = NULL;
2632 
2633       /* Add it to the list.  */
2634       list_of_pools = pool;
2635     }
2636 
2637   /* New pools, and emptied pools, will have a NULL symbol.  */
2638   if (pool->symbol == NULL)
2639     {
2640       pool->symbol = symbol_create (FAKE_LABEL_NAME, undefined_section,
2641 				    (valueT) 0, &zero_address_frag);
2642       pool->id = latest_pool_num ++;
2643     }
2644 
2645   /* Done.  */
2646   return pool;
2647 }
2648 
2649 /* Add the literal in the global 'inst'
2650    structure to the relevent literal pool.  */
2651 static int
add_to_lit_pool()2652 add_to_lit_pool ()
2653 {
2654   literal_pool * pool;
2655   unsigned int entry;
2656 
2657   pool = find_or_make_literal_pool ();
2658 
2659   /* Check if this literal value is already in the pool.  */
2660   for (entry = 0; entry < pool->next_free_entry; entry ++)
2661     {
2662       if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2663 	  && (inst.reloc.exp.X_op == O_constant)
2664 	  && (pool->literals[entry].X_add_number
2665 	      == inst.reloc.exp.X_add_number)
2666 	  && (pool->literals[entry].X_unsigned
2667 	      == inst.reloc.exp.X_unsigned))
2668 	break;
2669 
2670       if ((pool->literals[entry].X_op == inst.reloc.exp.X_op)
2671           && (inst.reloc.exp.X_op == O_symbol)
2672           && (pool->literals[entry].X_add_number
2673 	      == inst.reloc.exp.X_add_number)
2674           && (pool->literals[entry].X_add_symbol
2675 	      == inst.reloc.exp.X_add_symbol)
2676           && (pool->literals[entry].X_op_symbol
2677 	      == inst.reloc.exp.X_op_symbol))
2678         break;
2679     }
2680 
2681   /* Do we need to create a new entry?  */
2682   if (entry == pool->next_free_entry)
2683     {
2684       if (entry >= MAX_LITERAL_POOL_SIZE)
2685 	{
2686 	  inst.error = _("literal pool overflow");
2687 	  return FAIL;
2688 	}
2689 
2690       pool->literals[entry] = inst.reloc.exp;
2691       pool->next_free_entry += 1;
2692     }
2693 
2694   inst.reloc.exp.X_op         = O_symbol;
2695   inst.reloc.exp.X_add_number = ((int) entry) * 4 - 8;
2696   inst.reloc.exp.X_add_symbol = pool->symbol;
2697 
2698   return SUCCESS;
2699 }
2700 
2701 /* Can't use symbol_new here, so have to create a symbol and then at
2702    a later date assign it a value. Thats what these functions do.  */
2703 
2704 static void
symbol_locate(symbolP,name,segment,valu,frag)2705 symbol_locate (symbolP, name, segment, valu, frag)
2706      symbolS *    symbolP;
2707      const char * name;		/* It is copied, the caller can modify.  */
2708      segT         segment;	/* Segment identifier (SEG_<something>).  */
2709      valueT       valu;		/* Symbol value.  */
2710      fragS *      frag;		/* Associated fragment.  */
2711 {
2712   unsigned int name_length;
2713   char * preserved_copy_of_name;
2714 
2715   name_length = strlen (name) + 1;   /* +1 for \0.  */
2716   obstack_grow (&notes, name, name_length);
2717   preserved_copy_of_name = obstack_finish (&notes);
2718 #ifdef STRIP_UNDERSCORE
2719   if (preserved_copy_of_name[0] == '_')
2720     preserved_copy_of_name++;
2721 #endif
2722 
2723 #ifdef tc_canonicalize_symbol_name
2724   preserved_copy_of_name =
2725     tc_canonicalize_symbol_name (preserved_copy_of_name);
2726 #endif
2727 
2728   S_SET_NAME (symbolP, preserved_copy_of_name);
2729 
2730   S_SET_SEGMENT (symbolP, segment);
2731   S_SET_VALUE (symbolP, valu);
2732   symbol_clear_list_pointers (symbolP);
2733 
2734   symbol_set_frag (symbolP, frag);
2735 
2736   /* Link to end of symbol chain.  */
2737   {
2738     extern int symbol_table_frozen;
2739     if (symbol_table_frozen)
2740       abort ();
2741   }
2742 
2743   symbol_append (symbolP, symbol_lastP, & symbol_rootP, & symbol_lastP);
2744 
2745   obj_symbol_new_hook (symbolP);
2746 
2747 #ifdef tc_symbol_new_hook
2748   tc_symbol_new_hook (symbolP);
2749 #endif
2750 
2751 #ifdef DEBUG_SYMS
2752   verify_symbol_chain (symbol_rootP, symbol_lastP);
2753 #endif /* DEBUG_SYMS  */
2754 }
2755 
2756 /* Check that an immediate is valid.
2757    If so, convert it to the right format.  */
2758 
2759 static unsigned int
validate_immediate(val)2760 validate_immediate (val)
2761      unsigned int val;
2762 {
2763   unsigned int a;
2764   unsigned int i;
2765 
2766 #define rotate_left(v, n) (v << n | v >> (32 - n))
2767 
2768   for (i = 0; i < 32; i += 2)
2769     if ((a = rotate_left (val, i)) <= 0xff)
2770       return a | (i << 7); /* 12-bit pack: [shift-cnt,const].  */
2771 
2772   return FAIL;
2773 }
2774 
2775 /* Check to see if an immediate can be computed as two separate immediate
2776    values, added together.  We already know that this value cannot be
2777    computed by just one ARM instruction.  */
2778 
2779 static unsigned int
validate_immediate_twopart(val,highpart)2780 validate_immediate_twopart (val, highpart)
2781      unsigned int   val;
2782      unsigned int * highpart;
2783 {
2784   unsigned int a;
2785   unsigned int i;
2786 
2787   for (i = 0; i < 32; i += 2)
2788     if (((a = rotate_left (val, i)) & 0xff) != 0)
2789       {
2790 	if (a & 0xff00)
2791 	  {
2792 	    if (a & ~ 0xffff)
2793 	      continue;
2794 	    * highpart = (a  >> 8) | ((i + 24) << 7);
2795 	  }
2796 	else if (a & 0xff0000)
2797 	  {
2798 	    if (a & 0xff000000)
2799 	      continue;
2800 	    * highpart = (a >> 16) | ((i + 16) << 7);
2801 	  }
2802 	else
2803 	  {
2804 	    assert (a & 0xff000000);
2805 	    * highpart = (a >> 24) | ((i + 8) << 7);
2806 	  }
2807 
2808 	return (a & 0xff) | (i << 7);
2809       }
2810 
2811   return FAIL;
2812 }
2813 
2814 static int
validate_offset_imm(val,hwse)2815 validate_offset_imm (val, hwse)
2816      unsigned int val;
2817      int hwse;
2818 {
2819   if ((hwse && val > 255) || val > 4095)
2820     return FAIL;
2821   return val;
2822 }
2823 
2824 
2825 #ifdef OBJ_ELF
2826 /* This code is to handle mapping symbols as defined in the ARM ELF spec.
2827    (This text is taken from version B-02 of the spec):
2828 
2829       4.4.7 Mapping and tagging symbols
2830 
2831       A section of an ARM ELF file can contain a mixture of ARM code,
2832       Thumb code, and data.  There are inline transitions between code
2833       and data at literal pool boundaries. There can also be inline
2834       transitions between ARM code and Thumb code, for example in
2835       ARM-Thumb inter-working veneers.  Linkers, machine-level
2836       debuggers, profiling tools, and disassembly tools need to map
2837       images accurately. For example, setting an ARM breakpoint on a
2838       Thumb location, or in a literal pool, can crash the program
2839       being debugged, ruining the debugging session.
2840 
2841       ARM ELF entities are mapped (see section 4.4.7.1 below) and
2842       tagged (see section 4.4.7.2 below) using local symbols (with
2843       binding STB_LOCAL).  To assist consumers, mapping and tagging
2844       symbols should be collated first in the symbol table, before
2845       other symbols with binding STB_LOCAL.
2846 
2847       To allow properly collated mapping and tagging symbols to be
2848       skipped by consumers that have no interest in them, the first
2849       such symbol should have the name $m and its st_value field equal
2850       to the total number of mapping and tagging symbols (including
2851       the $m) in the symbol table.
2852 
2853       4.4.7.1 Mapping symbols
2854 
2855       $a    Labels the first byte of a sequence of ARM instructions.
2856             Its type is STT_FUNC.
2857 
2858       $d    Labels the first byte of a sequence of data items.
2859             Its type is STT_OBJECT.
2860 
2861       $t    Labels the first byte of a sequence of Thumb instructions.
2862             Its type is STT_FUNC.
2863 
2864       This list of mapping symbols may be extended in the future.
2865 
2866       Section-relative mapping symbols
2867 
2868       Mapping symbols defined in a section define a sequence of
2869       half-open address intervals that cover the address range of the
2870       section. Each interval starts at the address defined by a
2871       mapping symbol, and continues up to, but not including, the
2872       address defined by the next (in address order) mapping symbol or
2873       the end of the section. A corollary is that there must be a
2874       mapping symbol defined at the beginning of each section.
2875       Consumers can ignore the size of a section-relative mapping
2876       symbol. Producers can set it to 0.
2877 
2878       Absolute mapping symbols
2879 
2880       Because of the need to crystallize a Thumb address with the
2881       Thumb-bit set, absolute symbol of type STT_FUNC (symbols of type
2882       STT_FUNC defined in section SHN_ABS) need to be mapped with $a
2883       or $t.
2884 
2885       The extent of a mapping symbol defined in SHN_ABS is [st_value,
2886       st_value + st_size), or [st_value, st_value + 1) if st_size = 0,
2887       where [x, y) denotes the half-open address range from x,
2888       inclusive, to y, exclusive.
2889 
2890       In the absence of a mapping symbol, a consumer can interpret a
2891       function symbol with an odd value as the Thumb code address
2892       obtained by clearing the least significant bit of the
2893       value. This interpretation is deprecated, and it may not work in
2894       the future.
2895 
2896    Note - the Tagging symbols ($b, $f, $p $m) have been dropped from
2897    the EABI (which is still under development), so they are not
2898    implemented here.  */
2899 
2900 static enum mstate mapstate = MAP_UNDEFINED;
2901 
2902 static void
mapping_state(enum mstate state)2903 mapping_state (enum mstate state)
2904 {
2905   symbolS * symbolP;
2906   const char * symname;
2907   int type;
2908 
2909   if (mapstate == state)
2910     /* The mapping symbol has already been emitted.
2911        There is nothing else to do.  */
2912     return;
2913 
2914   mapstate = state;
2915 
2916   switch (state)
2917     {
2918     case MAP_DATA:
2919       symname = "$d";
2920       type = BSF_OBJECT;
2921       break;
2922     case MAP_ARM:
2923       symname = "$a";
2924       type = BSF_FUNCTION;
2925       break;
2926     case MAP_THUMB:
2927       symname = "$t";
2928       type = BSF_FUNCTION;
2929       break;
2930     case MAP_UNDEFINED:
2931       return;
2932     default:
2933       abort ();
2934     }
2935 
2936   seg_info (now_seg)->tc_segment_info_data = state;
2937 
2938   symbolP = symbol_new (symname, now_seg, (valueT) frag_now_fix (), frag_now);
2939   symbol_table_insert (symbolP);
2940   symbol_get_bfdsym (symbolP)->flags |= type | BSF_LOCAL;
2941 
2942   switch (state)
2943     {
2944     case MAP_ARM:
2945       THUMB_SET_FUNC (symbolP, 0);
2946       ARM_SET_THUMB (symbolP, 0);
2947       ARM_SET_INTERWORK (symbolP, support_interwork);
2948       break;
2949 
2950     case MAP_THUMB:
2951       THUMB_SET_FUNC (symbolP, 1);
2952       ARM_SET_THUMB (symbolP, 1);
2953       ARM_SET_INTERWORK (symbolP, support_interwork);
2954       break;
2955 
2956     case MAP_DATA:
2957     default:
2958       return;
2959     }
2960 }
2961 
2962 /* When we change sections we need to issue a new mapping symbol.  */
2963 
2964 void
arm_elf_change_section(void)2965 arm_elf_change_section (void)
2966 {
2967   flagword flags;
2968 
2969   if (!SEG_NORMAL (now_seg))
2970     return;
2971 
2972   flags = bfd_get_section_flags (stdoutput, now_seg);
2973 
2974   /* We can ignore sections that only contain debug info.  */
2975   if ((flags & SEC_ALLOC) == 0)
2976     return;
2977 
2978   mapstate = seg_info (now_seg)->tc_segment_info_data;
2979 }
2980 #else
2981 #define mapping_state(a)
2982 #endif /* OBJ_ELF */
2983 
2984 
2985 static void
s_req(a)2986 s_req (a)
2987      int a ATTRIBUTE_UNUSED;
2988 {
2989   as_bad (_("invalid syntax for .req directive"));
2990 }
2991 
2992 /* The .unreq directive deletes an alias which was previously defined
2993    by .req.  For example:
2994 
2995        my_alias .req r11
2996        .unreq my_alias    */
2997 
2998 static void
s_unreq(int a ATTRIBUTE_UNUSED)2999 s_unreq (int a ATTRIBUTE_UNUSED)
3000 {
3001   char *name;
3002   char saved_char;
3003 
3004   skip_whitespace (input_line_pointer);
3005   name = input_line_pointer;
3006 
3007   while (*input_line_pointer != 0
3008 	 && *input_line_pointer != ' '
3009 	 && *input_line_pointer != '\n')
3010     ++input_line_pointer;
3011 
3012   saved_char = *input_line_pointer;
3013   *input_line_pointer = 0;
3014 
3015   if (*name)
3016     {
3017       enum arm_reg_type req_type = arm_reg_parse_any (name);
3018 
3019       if (req_type != REG_TYPE_MAX)
3020 	{
3021 	  char *temp_name = name;
3022 	  int req_no = arm_reg_parse (&temp_name, all_reg_maps[req_type].htab);
3023 
3024 	  if (req_no != FAIL)
3025 	    {
3026 	      struct reg_entry *req_entry;
3027 
3028 	      /* Check to see if this alias is a builtin one.  */
3029 	      req_entry = hash_delete (all_reg_maps[req_type].htab, name);
3030 
3031 	      if (!req_entry)
3032 		as_bad (_("unreq: missing hash entry for \"%s\""), name);
3033 	      else if (req_entry->builtin)
3034 		/* FIXME: We are deleting a built in register alias which
3035 		   points to a const data structure, so we only need to
3036 		   free up the memory used by the key in the hash table.
3037 		   Unfortunately we have not recorded this value, so this
3038 		   is a memory leak.  */
3039 		  /* FIXME: Should we issue a warning message ?  */
3040 		;
3041 	      else
3042 		{
3043 		  /* Deleting a user defined alias.  We need to free the
3044 		     key and the value, but fortunately the key is the same
3045 		     as the value->name field.  */
3046 		  free ((char *) req_entry->name);
3047 		  free (req_entry);
3048 		}
3049 	    }
3050           else
3051             as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
3052 	}
3053       else
3054         as_bad (_(".unreq: unrecognized symbol \"%s\""), name);
3055     }
3056   else
3057     as_bad (_("invalid syntax for .unreq directive"));
3058 
3059   *input_line_pointer = saved_char;
3060   demand_empty_rest_of_line ();
3061 }
3062 
3063 static void
s_bss(ignore)3064 s_bss (ignore)
3065      int ignore ATTRIBUTE_UNUSED;
3066 {
3067   /* We don't support putting frags in the BSS segment, we fake it by
3068      marking in_bss, then looking at s_skip for clues.  */
3069   subseg_set (bss_section, 0);
3070   demand_empty_rest_of_line ();
3071   mapping_state (MAP_DATA);
3072 }
3073 
3074 static void
s_even(ignore)3075 s_even (ignore)
3076      int ignore ATTRIBUTE_UNUSED;
3077 {
3078   /* Never make frag if expect extra pass.  */
3079   if (!need_pass_2)
3080     frag_align (1, 0, 0);
3081 
3082   record_alignment (now_seg, 1);
3083 
3084   demand_empty_rest_of_line ();
3085 }
3086 
3087 static void
s_ltorg(ignored)3088 s_ltorg (ignored)
3089      int ignored ATTRIBUTE_UNUSED;
3090 {
3091   unsigned int entry;
3092   literal_pool * pool;
3093   char sym_name[20];
3094 
3095   pool = find_literal_pool ();
3096   if (pool == NULL
3097       || pool->symbol == NULL
3098       || pool->next_free_entry == 0)
3099     return;
3100 
3101   mapping_state (MAP_DATA);
3102 
3103   /* Align pool as you have word accesses.
3104      Only make a frag if we have to.  */
3105   if (!need_pass_2)
3106     frag_align (2, 0, 0);
3107 
3108   record_alignment (now_seg, 2);
3109 
3110   sprintf (sym_name, "$$lit_\002%x", pool->id);
3111 
3112   symbol_locate (pool->symbol, sym_name, now_seg,
3113 		 (valueT) frag_now_fix (), frag_now);
3114   symbol_table_insert (pool->symbol);
3115 
3116   ARM_SET_THUMB (pool->symbol, thumb_mode);
3117 
3118 #if defined OBJ_COFF || defined OBJ_ELF
3119   ARM_SET_INTERWORK (pool->symbol, support_interwork);
3120 #endif
3121 
3122   for (entry = 0; entry < pool->next_free_entry; entry ++)
3123     /* First output the expression in the instruction to the pool.  */
3124     emit_expr (&(pool->literals[entry]), 4); /* .word  */
3125 
3126   /* Mark the pool as empty.  */
3127   pool->next_free_entry = 0;
3128   pool->symbol = NULL;
3129 }
3130 
3131 /* Same as s_align_ptwo but align 0 => align 2.  */
3132 
3133 static void
s_align(unused)3134 s_align (unused)
3135      int unused ATTRIBUTE_UNUSED;
3136 {
3137   register int temp;
3138   register long temp_fill;
3139   long max_alignment = 15;
3140 
3141   temp = get_absolute_expression ();
3142   if (temp > max_alignment)
3143     as_bad (_("alignment too large: %d assumed"), temp = max_alignment);
3144   else if (temp < 0)
3145     {
3146       as_bad (_("alignment negative. 0 assumed."));
3147       temp = 0;
3148     }
3149 
3150   if (*input_line_pointer == ',')
3151     {
3152       input_line_pointer++;
3153       temp_fill = get_absolute_expression ();
3154     }
3155   else
3156     temp_fill = 0;
3157 
3158   if (!temp)
3159     temp = 2;
3160 
3161   /* Only make a frag if we HAVE to.  */
3162   if (temp && !need_pass_2)
3163     frag_align (temp, (int) temp_fill, 0);
3164   demand_empty_rest_of_line ();
3165 
3166   record_alignment (now_seg, temp);
3167 }
3168 
3169 static void
s_force_thumb(ignore)3170 s_force_thumb (ignore)
3171      int ignore ATTRIBUTE_UNUSED;
3172 {
3173   /* If we are not already in thumb mode go into it, EVEN if
3174      the target processor does not support thumb instructions.
3175      This is used by gcc/config/arm/lib1funcs.asm for example
3176      to compile interworking support functions even if the
3177      target processor should not support interworking.  */
3178   if (! thumb_mode)
3179     {
3180       thumb_mode = 2;
3181 
3182       record_alignment (now_seg, 1);
3183     }
3184 
3185   demand_empty_rest_of_line ();
3186 }
3187 
3188 static void
s_thumb_func(ignore)3189 s_thumb_func (ignore)
3190      int ignore ATTRIBUTE_UNUSED;
3191 {
3192   if (! thumb_mode)
3193     opcode_select (16);
3194 
3195   /* The following label is the name/address of the start of a Thumb function.
3196      We need to know this for the interworking support.  */
3197   label_is_thumb_function_name = TRUE;
3198 
3199   demand_empty_rest_of_line ();
3200 }
3201 
3202 /* Perform a .set directive, but also mark the alias as
3203    being a thumb function.  */
3204 
3205 static void
s_thumb_set(equiv)3206 s_thumb_set (equiv)
3207      int equiv;
3208 {
3209   /* XXX the following is a duplicate of the code for s_set() in read.c
3210      We cannot just call that code as we need to get at the symbol that
3211      is created.  */
3212   register char *    name;
3213   register char      delim;
3214   register char *    end_name;
3215   register symbolS * symbolP;
3216 
3217   /* Especial apologies for the random logic:
3218      This just grew, and could be parsed much more simply!
3219      Dean - in haste.  */
3220   name      = input_line_pointer;
3221   delim     = get_symbol_end ();
3222   end_name  = input_line_pointer;
3223   *end_name = delim;
3224 
3225   SKIP_WHITESPACE ();
3226 
3227   if (*input_line_pointer != ',')
3228     {
3229       *end_name = 0;
3230       as_bad (_("expected comma after name \"%s\""), name);
3231       *end_name = delim;
3232       ignore_rest_of_line ();
3233       return;
3234     }
3235 
3236   input_line_pointer++;
3237   *end_name = 0;
3238 
3239   if (name[0] == '.' && name[1] == '\0')
3240     {
3241       /* XXX - this should not happen to .thumb_set.  */
3242       abort ();
3243     }
3244 
3245   if ((symbolP = symbol_find (name)) == NULL
3246       && (symbolP = md_undefined_symbol (name)) == NULL)
3247     {
3248 #ifndef NO_LISTING
3249       /* When doing symbol listings, play games with dummy fragments living
3250 	 outside the normal fragment chain to record the file and line info
3251          for this symbol.  */
3252       if (listing & LISTING_SYMBOLS)
3253 	{
3254 	  extern struct list_info_struct * listing_tail;
3255 	  fragS * dummy_frag = (fragS *) xmalloc (sizeof (fragS));
3256 
3257 	  memset (dummy_frag, 0, sizeof (fragS));
3258 	  dummy_frag->fr_type = rs_fill;
3259 	  dummy_frag->line = listing_tail;
3260 	  symbolP = symbol_new (name, undefined_section, 0, dummy_frag);
3261 	  dummy_frag->fr_symbol = symbolP;
3262 	}
3263       else
3264 #endif
3265 	symbolP = symbol_new (name, undefined_section, 0, &zero_address_frag);
3266 
3267 #ifdef OBJ_COFF
3268       /* "set" symbols are local unless otherwise specified.  */
3269       SF_SET_LOCAL (symbolP);
3270 #endif /* OBJ_COFF  */
3271     }				/* Make a new symbol.  */
3272 
3273   symbol_table_insert (symbolP);
3274 
3275   * end_name = delim;
3276 
3277   if (equiv
3278       && S_IS_DEFINED (symbolP)
3279       && S_GET_SEGMENT (symbolP) != reg_section)
3280     as_bad (_("symbol `%s' already defined"), S_GET_NAME (symbolP));
3281 
3282   pseudo_set (symbolP);
3283 
3284   demand_empty_rest_of_line ();
3285 
3286   /* XXX Now we come to the Thumb specific bit of code.  */
3287 
3288   THUMB_SET_FUNC (symbolP, 1);
3289   ARM_SET_THUMB (symbolP, 1);
3290 #if defined OBJ_ELF || defined OBJ_COFF
3291   ARM_SET_INTERWORK (symbolP, support_interwork);
3292 #endif
3293 }
3294 
3295 static void
opcode_select(width)3296 opcode_select (width)
3297      int width;
3298 {
3299   switch (width)
3300     {
3301     case 16:
3302       if (! thumb_mode)
3303 	{
3304 	  if (! (cpu_variant & ARM_EXT_V4T))
3305 	    as_bad (_("selected processor does not support THUMB opcodes"));
3306 
3307 	  thumb_mode = 1;
3308 	  /* No need to force the alignment, since we will have been
3309              coming from ARM mode, which is word-aligned.  */
3310 	  record_alignment (now_seg, 1);
3311 	}
3312       mapping_state (MAP_THUMB);
3313       break;
3314 
3315     case 32:
3316       if (thumb_mode)
3317 	{
3318 	  if ((cpu_variant & ARM_ALL) == ARM_EXT_V4T)
3319 	    as_bad (_("selected processor does not support ARM opcodes"));
3320 
3321 	  thumb_mode = 0;
3322 
3323 	  if (!need_pass_2)
3324 	    frag_align (2, 0, 0);
3325 
3326 	  record_alignment (now_seg, 1);
3327 	}
3328       mapping_state (MAP_ARM);
3329       break;
3330 
3331     default:
3332       as_bad (_("invalid instruction size selected (%d)"), width);
3333     }
3334 }
3335 
3336 static void
s_arm(ignore)3337 s_arm (ignore)
3338      int ignore ATTRIBUTE_UNUSED;
3339 {
3340   opcode_select (32);
3341   demand_empty_rest_of_line ();
3342 }
3343 
3344 static void
s_thumb(ignore)3345 s_thumb (ignore)
3346      int ignore ATTRIBUTE_UNUSED;
3347 {
3348   opcode_select (16);
3349   demand_empty_rest_of_line ();
3350 }
3351 
3352 static void
s_code(unused)3353 s_code (unused)
3354      int unused ATTRIBUTE_UNUSED;
3355 {
3356   register int temp;
3357 
3358   temp = get_absolute_expression ();
3359   switch (temp)
3360     {
3361     case 16:
3362     case 32:
3363       opcode_select (temp);
3364       break;
3365 
3366     default:
3367       as_bad (_("invalid operand to .code directive (%d) (expecting 16 or 32)"), temp);
3368     }
3369 }
3370 
3371 static void
end_of_line(str)3372 end_of_line (str)
3373      char *str;
3374 {
3375   skip_whitespace (str);
3376 
3377   if (*str != '\0' && !inst.error)
3378     inst.error = _("garbage following instruction");
3379 }
3380 
3381 static int
skip_past_comma(str)3382 skip_past_comma (str)
3383      char ** str;
3384 {
3385   char * p = * str, c;
3386   int comma = 0;
3387 
3388   while ((c = *p) == ' ' || c == ',')
3389     {
3390       p++;
3391       if (c == ',' && comma++)
3392 	return FAIL;
3393     }
3394 
3395   if (c == '\0')
3396     return FAIL;
3397 
3398   *str = p;
3399   return comma ? SUCCESS : FAIL;
3400 }
3401 
3402 /* A standard register must be given at this point.
3403    SHIFT is the place to put it in inst.instruction.
3404    Restores input start point on error.
3405    Returns the reg#, or FAIL.  */
3406 
3407 static int
reg_required_here(str,shift)3408 reg_required_here (str, shift)
3409      char ** str;
3410      int     shift;
3411 {
3412   static char buff [128]; /* XXX  */
3413   int         reg;
3414   char *      start = * str;
3415 
3416   if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_RN].htab)) != FAIL)
3417     {
3418       if (shift >= 0)
3419 	inst.instruction |= reg << shift;
3420       return reg;
3421     }
3422 
3423   /* Restore the start point, we may have got a reg of the wrong class.  */
3424   *str = start;
3425 
3426   /* In the few cases where we might be able to accept something else
3427      this error can be overridden.  */
3428   sprintf (buff, _("register expected, not '%.100s'"), start);
3429   inst.error = buff;
3430 
3431   return FAIL;
3432 }
3433 
3434 /* A Intel Wireless MMX technology register
3435    must be given at this point.
3436    Shift is the place to put it in inst.instruction.
3437    Restores input start point on err.
3438    Returns the reg#, or FAIL.  */
3439 
3440 static int
wreg_required_here(str,shift,reg_type)3441 wreg_required_here (str, shift, reg_type)
3442      char ** str;
3443      int     shift;
3444      enum wreg_type reg_type;
3445 {
3446   static char buff [128];
3447   int    reg;
3448   char * start = *str;
3449 
3450   if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_IWMMXT].htab)) != FAIL)
3451     {
3452       if (wr_register (reg)
3453 	  && (reg_type == IWMMXT_REG_WR || reg_type == IWMMXT_REG_WR_OR_WC))
3454         {
3455           if (shift >= 0)
3456             inst.instruction |= (reg ^ WR_PREFIX) << shift;
3457           return reg;
3458         }
3459       else if (wc_register (reg)
3460 	       && (reg_type == IWMMXT_REG_WC || reg_type == IWMMXT_REG_WR_OR_WC))
3461         {
3462           if (shift >= 0)
3463             inst.instruction |= (reg ^ WC_PREFIX) << shift;
3464           return reg;
3465         }
3466       else if ((wcg_register (reg) && reg_type == IWMMXT_REG_WCG))
3467         {
3468           if (shift >= 0)
3469             inst.instruction |= ((reg ^ WC_PREFIX) - 8) << shift;
3470           return reg;
3471         }
3472     }
3473 
3474   /* Restore the start point, we may have got a reg of the wrong class.  */
3475   *str = start;
3476 
3477   /* In the few cases where we might be able to accept
3478      something else this error can be overridden.  */
3479   sprintf (buff, _("Intel Wireless MMX technology register expected, not '%.100s'"), start);
3480   inst.error = buff;
3481 
3482   return FAIL;
3483 }
3484 
3485 static const struct asm_psr *
arm_psr_parse(ccp)3486 arm_psr_parse (ccp)
3487      register char ** ccp;
3488 {
3489   char * start = * ccp;
3490   char   c;
3491   char * p;
3492   const struct asm_psr * psr;
3493 
3494   p = start;
3495 
3496   /* Skip to the end of the next word in the input stream.  */
3497   do
3498     {
3499       c = *p++;
3500     }
3501   while (ISALPHA (c) || c == '_');
3502 
3503   /* Terminate the word.  */
3504   *--p = 0;
3505 
3506   /* CPSR's and SPSR's can now be lowercase.  This is just a convenience
3507      feature for ease of use and backwards compatibility.  */
3508   if (!strncmp (start, "cpsr", 4))
3509     strncpy (start, "CPSR", 4);
3510   else if (!strncmp (start, "spsr", 4))
3511     strncpy (start, "SPSR", 4);
3512 
3513   /* Now locate the word in the psr hash table.  */
3514   psr = (const struct asm_psr *) hash_find (arm_psr_hsh, start);
3515 
3516   /* Restore the input stream.  */
3517   *p = c;
3518 
3519   /* If we found a valid match, advance the
3520      stream pointer past the end of the word.  */
3521   *ccp = p;
3522 
3523   return psr;
3524 }
3525 
3526 /* Parse the input looking for a PSR flag.  */
3527 
3528 static int
psr_required_here(str)3529 psr_required_here (str)
3530      char ** str;
3531 {
3532   char * start = * str;
3533   const struct asm_psr * psr;
3534 
3535   psr = arm_psr_parse (str);
3536 
3537   if (psr)
3538     {
3539       /* If this is the SPSR that is being modified, set the R bit.  */
3540       if (! psr->cpsr)
3541 	inst.instruction |= SPSR_BIT;
3542 
3543       /* Set the psr flags in the MSR instruction.  */
3544       inst.instruction |= psr->field << PSR_SHIFT;
3545 
3546       return SUCCESS;
3547     }
3548 
3549   /* In the few cases where we might be able to accept
3550      something else this error can be overridden.  */
3551   inst.error = _("flag for {c}psr instruction expected");
3552 
3553   /* Restore the start point.  */
3554   *str = start;
3555   return FAIL;
3556 }
3557 
3558 static int
co_proc_number(str)3559 co_proc_number (str)
3560      char **str;
3561 {
3562   int processor, pchar;
3563   char *start;
3564 
3565   skip_whitespace (*str);
3566   start = *str;
3567 
3568   /* The data sheet seems to imply that just a number on its own is valid
3569      here, but the RISC iX assembler seems to accept a prefix 'p'.  We will
3570      accept either.  */
3571   if ((processor = arm_reg_parse (str, all_reg_maps[REG_TYPE_CP].htab))
3572       == FAIL)
3573     {
3574       *str = start;
3575 
3576       pchar = *(*str)++;
3577       if (pchar >= '0' && pchar <= '9')
3578 	{
3579 	  processor = pchar - '0';
3580 	  if (**str >= '0' && **str <= '9')
3581 	    {
3582 	      processor = processor * 10 + *(*str)++ - '0';
3583 	      if (processor > 15)
3584 		{
3585 		  inst.error = _("illegal co-processor number");
3586 		  return FAIL;
3587 		}
3588 	    }
3589 	}
3590       else
3591 	{
3592 	  inst.error = _("bad or missing co-processor number");
3593 	  return FAIL;
3594 	}
3595     }
3596 
3597   inst.instruction |= processor << 8;
3598   return SUCCESS;
3599 }
3600 
3601 static int
cp_opc_expr(str,where,length)3602 cp_opc_expr (str, where, length)
3603      char ** str;
3604      int where;
3605      int length;
3606 {
3607   expressionS expr;
3608 
3609   skip_whitespace (* str);
3610 
3611   memset (&expr, '\0', sizeof (expr));
3612 
3613   if (my_get_expression (&expr, str))
3614     return FAIL;
3615   if (expr.X_op != O_constant)
3616     {
3617       inst.error = _("bad or missing expression");
3618       return FAIL;
3619     }
3620 
3621   if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
3622     {
3623       inst.error = _("immediate co-processor expression too large");
3624       return FAIL;
3625     }
3626 
3627   inst.instruction |= expr.X_add_number << where;
3628   return SUCCESS;
3629 }
3630 
3631 static int
cp_reg_required_here(str,where)3632 cp_reg_required_here (str, where)
3633      char ** str;
3634      int     where;
3635 {
3636   int    reg;
3637   char * start = *str;
3638 
3639   if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_CN].htab)) != FAIL)
3640     {
3641       inst.instruction |= reg << where;
3642       return reg;
3643     }
3644 
3645   /* In the few cases where we might be able to accept something else
3646      this error can be overridden.  */
3647   inst.error = _("co-processor register expected");
3648 
3649   /* Restore the start point.  */
3650   *str = start;
3651   return FAIL;
3652 }
3653 
3654 static int
fp_reg_required_here(str,where)3655 fp_reg_required_here (str, where)
3656      char ** str;
3657      int     where;
3658 {
3659   int    reg;
3660   char * start = * str;
3661 
3662   if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_FN].htab)) != FAIL)
3663     {
3664       inst.instruction |= reg << where;
3665       return reg;
3666     }
3667 
3668   /* In the few cases where we might be able to accept something else
3669      this error can be overridden.  */
3670   inst.error = _("floating point register expected");
3671 
3672   /* Restore the start point.  */
3673   *str = start;
3674   return FAIL;
3675 }
3676 
3677 static int
cp_address_offset(str)3678 cp_address_offset (str)
3679      char ** str;
3680 {
3681   int offset;
3682 
3683   skip_whitespace (* str);
3684 
3685   if (! is_immediate_prefix (**str))
3686     {
3687       inst.error = _("immediate expression expected");
3688       return FAIL;
3689     }
3690 
3691   (*str)++;
3692 
3693   if (my_get_expression (& inst.reloc.exp, str))
3694     return FAIL;
3695 
3696   if (inst.reloc.exp.X_op == O_constant)
3697     {
3698       offset = inst.reloc.exp.X_add_number;
3699 
3700       if (offset & 3)
3701 	{
3702 	  inst.error = _("co-processor address must be word aligned");
3703 	  return FAIL;
3704 	}
3705 
3706       if (offset > 1023 || offset < -1023)
3707 	{
3708 	  inst.error = _("offset too large");
3709 	  return FAIL;
3710 	}
3711 
3712       if (offset >= 0)
3713 	inst.instruction |= INDEX_UP;
3714       else
3715 	offset = -offset;
3716 
3717       inst.instruction |= offset >> 2;
3718     }
3719   else
3720     inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3721 
3722   return SUCCESS;
3723 }
3724 
3725 static int
cp_address_required_here(str,wb_ok)3726 cp_address_required_here (str, wb_ok)
3727      char ** str;
3728      int wb_ok;
3729 {
3730   char * p = * str;
3731   int    pre_inc = 0;
3732   int    write_back = 0;
3733 
3734   if (*p == '[')
3735     {
3736       int reg;
3737 
3738       p++;
3739       skip_whitespace (p);
3740 
3741       if ((reg = reg_required_here (& p, 16)) == FAIL)
3742 	return FAIL;
3743 
3744       skip_whitespace (p);
3745 
3746       if (*p == ']')
3747 	{
3748 	  p++;
3749 
3750 	  skip_whitespace (p);
3751 
3752 	  if (*p == '\0')
3753 	    {
3754 	      /* As an extension to the official ARM syntax we allow:
3755 
3756 		   [Rn]
3757 
3758 	         as a short hand for:
3759 
3760 		   [Rn,#0]  */
3761 	      inst.instruction |= PRE_INDEX | INDEX_UP;
3762 	      *str = p;
3763 	      return SUCCESS;
3764 	    }
3765 
3766 	  if (skip_past_comma (& p) == FAIL)
3767 	    {
3768 	      inst.error = _("comma expected after closing square bracket");
3769 	      return FAIL;
3770 	    }
3771 
3772 	  skip_whitespace (p);
3773 
3774 	  if (*p == '#')
3775 	    {
3776 	      if (wb_ok)
3777 		{
3778 		  /* [Rn], #expr  */
3779 		  write_back = WRITE_BACK;
3780 
3781 		  if (reg == REG_PC)
3782 		    {
3783 		      inst.error = _("pc may not be used in post-increment");
3784 		      return FAIL;
3785 		    }
3786 
3787 		  if (cp_address_offset (& p) == FAIL)
3788 		    return FAIL;
3789 		}
3790 	      else
3791 		pre_inc = PRE_INDEX | INDEX_UP;
3792 	    }
3793 	  else if (*p == '{')
3794 	    {
3795 	      int option;
3796 
3797 	      /* [Rn], {<expr>}  */
3798 	      p++;
3799 
3800 	      skip_whitespace (p);
3801 
3802 	      if (my_get_expression (& inst.reloc.exp, & p))
3803 		return FAIL;
3804 
3805 	      if (inst.reloc.exp.X_op == O_constant)
3806 		{
3807 		  option = inst.reloc.exp.X_add_number;
3808 
3809 		  if (option > 255 || option < 0)
3810 		    {
3811 		      inst.error = _("'option' field too large");
3812 		      return FAIL;
3813 		    }
3814 
3815 		  skip_whitespace (p);
3816 
3817 		  if (*p != '}')
3818 		    {
3819 		      inst.error = _("'}' expected at end of 'option' field");
3820 		      return FAIL;
3821 		    }
3822 		  else
3823 		    {
3824 		      p++;
3825 		      inst.instruction |= option;
3826 		      inst.instruction |= INDEX_UP;
3827 		    }
3828 		}
3829 	      else
3830 		{
3831 		  inst.error = _("non-constant expressions for 'option' field not supported");
3832 		  return FAIL;
3833 		}
3834 	    }
3835 	  else
3836 	    {
3837 	      inst.error = _("# or { expected after comma");
3838 	      return FAIL;
3839 	    }
3840 	}
3841       else
3842 	{
3843 	  /* '['Rn, #expr']'[!]  */
3844 
3845 	  if (skip_past_comma (& p) == FAIL)
3846 	    {
3847 	      inst.error = _("pre-indexed expression expected");
3848 	      return FAIL;
3849 	    }
3850 
3851 	  pre_inc = PRE_INDEX;
3852 
3853 	  if (cp_address_offset (& p) == FAIL)
3854 	    return FAIL;
3855 
3856 	  skip_whitespace (p);
3857 
3858 	  if (*p++ != ']')
3859 	    {
3860 	      inst.error = _("missing ]");
3861 	      return FAIL;
3862 	    }
3863 
3864 	  skip_whitespace (p);
3865 
3866 	  if (wb_ok && *p == '!')
3867 	    {
3868 	      if (reg == REG_PC)
3869 		{
3870 		  inst.error = _("pc may not be used with write-back");
3871 		  return FAIL;
3872 		}
3873 
3874 	      p++;
3875 	      write_back = WRITE_BACK;
3876 	    }
3877 	}
3878     }
3879   else
3880     {
3881       if (my_get_expression (&inst.reloc.exp, &p))
3882 	return FAIL;
3883 
3884       inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
3885       inst.reloc.exp.X_add_number -= 8;  /* PC rel adjust.  */
3886       inst.reloc.pc_rel = 1;
3887       inst.instruction |= (REG_PC << 16);
3888       pre_inc = PRE_INDEX;
3889     }
3890 
3891   inst.instruction |= write_back | pre_inc;
3892   *str = p;
3893   return SUCCESS;
3894 }
3895 
3896 static int
cp_byte_address_offset(str)3897 cp_byte_address_offset (str)
3898      char ** str;
3899 {
3900   int offset;
3901 
3902   skip_whitespace (* str);
3903 
3904   if (! is_immediate_prefix (**str))
3905     {
3906       inst.error = _("immediate expression expected");
3907       return FAIL;
3908     }
3909 
3910   (*str)++;
3911 
3912   if (my_get_expression (& inst.reloc.exp, str))
3913     return FAIL;
3914 
3915   if (inst.reloc.exp.X_op == O_constant)
3916     {
3917       offset = inst.reloc.exp.X_add_number;
3918 
3919       if (offset > 255 || offset < -255)
3920         {
3921           inst.error = _("offset too large");
3922           return FAIL;
3923         }
3924 
3925       if (offset >= 0)
3926         inst.instruction |= INDEX_UP;
3927       else
3928         offset = -offset;
3929 
3930       inst.instruction |= offset;
3931     }
3932   else
3933     inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
3934 
3935   return SUCCESS;
3936 }
3937 
3938 static int
cp_byte_address_required_here(str)3939 cp_byte_address_required_here (str)
3940      char ** str;
3941 {
3942   char * p = * str;
3943   int    pre_inc = 0;
3944   int    write_back = 0;
3945 
3946   if (*p == '[')
3947     {
3948       int reg;
3949 
3950       p++;
3951       skip_whitespace (p);
3952 
3953       if ((reg = reg_required_here (& p, 16)) == FAIL)
3954         return FAIL;
3955 
3956       skip_whitespace (p);
3957 
3958       if (*p == ']')
3959         {
3960           p++;
3961 
3962           if (skip_past_comma (& p) == SUCCESS)
3963             {
3964               /* [Rn], #expr */
3965               write_back = WRITE_BACK;
3966 
3967               if (reg == REG_PC)
3968                 {
3969                   inst.error = _("pc may not be used in post-increment");
3970                   return FAIL;
3971                 }
3972 
3973               if (cp_byte_address_offset (& p) == FAIL)
3974                 return FAIL;
3975             }
3976           else
3977             pre_inc = PRE_INDEX | INDEX_UP;
3978         }
3979       else
3980         {
3981           /* '['Rn, #expr']'[!] */
3982 
3983           if (skip_past_comma (& p) == FAIL)
3984             {
3985               inst.error = _("pre-indexed expression expected");
3986               return FAIL;
3987             }
3988 
3989           pre_inc = PRE_INDEX;
3990 
3991           if (cp_byte_address_offset (& p) == FAIL)
3992             return FAIL;
3993 
3994           skip_whitespace (p);
3995 
3996           if (*p++ != ']')
3997             {
3998               inst.error = _("missing ]");
3999               return FAIL;
4000             }
4001 
4002           skip_whitespace (p);
4003 
4004           if (*p == '!')
4005             {
4006               if (reg == REG_PC)
4007                 {
4008                   inst.error = _("pc may not be used with write-back");
4009                   return FAIL;
4010                 }
4011 
4012               p++;
4013               write_back = WRITE_BACK;
4014             }
4015         }
4016     }
4017   else
4018     {
4019       if (my_get_expression (&inst.reloc.exp, &p))
4020         return FAIL;
4021 
4022       inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM_S2;
4023       inst.reloc.exp.X_add_number -= 8;  /* PC rel adjust.  */
4024       inst.reloc.pc_rel = 1;
4025       inst.instruction |= (REG_PC << 16);
4026       pre_inc = PRE_INDEX;
4027     }
4028 
4029   inst.instruction |= write_back | pre_inc;
4030   *str = p;
4031   return SUCCESS;
4032 }
4033 
4034 static void
do_empty(str)4035 do_empty (str)
4036      char * str;
4037 {
4038   /* Do nothing really.  */
4039   end_of_line (str);
4040 }
4041 
4042 static void
do_mrs(str)4043 do_mrs (str)
4044      char *str;
4045 {
4046   int skip = 0;
4047 
4048   /* Only one syntax.  */
4049   skip_whitespace (str);
4050 
4051   if (reg_required_here (&str, 12) == FAIL)
4052     {
4053       inst.error = BAD_ARGS;
4054       return;
4055     }
4056 
4057   if (skip_past_comma (&str) == FAIL)
4058     {
4059       inst.error = _("comma expected after register name");
4060       return;
4061     }
4062 
4063   skip_whitespace (str);
4064 
4065   if (   strcmp (str, "CPSR") == 0
4066       || strcmp (str, "SPSR") == 0
4067 	 /* Lower case versions for backwards compatibility.  */
4068       || strcmp (str, "cpsr") == 0
4069       || strcmp (str, "spsr") == 0)
4070     skip = 4;
4071 
4072   /* This is for backwards compatibility with older toolchains.  */
4073   else if (   strcmp (str, "cpsr_all") == 0
4074 	   || strcmp (str, "spsr_all") == 0)
4075     skip = 8;
4076   else
4077     {
4078       inst.error = _("CPSR or SPSR expected");
4079       return;
4080     }
4081 
4082   if (* str == 's' || * str == 'S')
4083     inst.instruction |= SPSR_BIT;
4084   str += skip;
4085 
4086   end_of_line (str);
4087 }
4088 
4089 /* Two possible forms:
4090       "{C|S}PSR_<field>, Rm",
4091       "{C|S}PSR_f, #expression".  */
4092 
4093 static void
do_msr(str)4094 do_msr (str)
4095      char * str;
4096 {
4097   skip_whitespace (str);
4098 
4099   if (psr_required_here (& str) == FAIL)
4100     return;
4101 
4102   if (skip_past_comma (& str) == FAIL)
4103     {
4104       inst.error = _("comma missing after psr flags");
4105       return;
4106     }
4107 
4108   skip_whitespace (str);
4109 
4110   if (reg_required_here (& str, 0) != FAIL)
4111     {
4112       inst.error = NULL;
4113       end_of_line (str);
4114       return;
4115     }
4116 
4117   if (! is_immediate_prefix (* str))
4118     {
4119       inst.error =
4120 	_("only a register or immediate value can follow a psr flag");
4121       return;
4122     }
4123 
4124   str ++;
4125   inst.error = NULL;
4126 
4127   if (my_get_expression (& inst.reloc.exp, & str))
4128     {
4129       inst.error =
4130 	_("only a register or immediate value can follow a psr flag");
4131       return;
4132     }
4133 
4134 #if 0  /* The first edition of the ARM architecture manual stated that
4135 	  writing anything other than the flags with an immediate operation
4136 	  had UNPREDICTABLE effects.  This constraint was removed in the
4137 	  second edition of the specification.  */
4138   if ((cpu_variant & ARM_EXT_V5) != ARM_EXT_V5
4139       && inst.instruction & ((PSR_c | PSR_x | PSR_s) << PSR_SHIFT))
4140     {
4141       inst.error = _("immediate value cannot be used to set this field");
4142       return;
4143     }
4144 #endif
4145 
4146   inst.instruction |= INST_IMMEDIATE;
4147 
4148   if (inst.reloc.exp.X_add_symbol)
4149     {
4150       inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
4151       inst.reloc.pc_rel = 0;
4152     }
4153   else
4154     {
4155       unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
4156 
4157       if (value == (unsigned) FAIL)
4158 	{
4159 	  inst.error = _("invalid constant");
4160 	  return;
4161 	}
4162 
4163       inst.instruction |= value;
4164     }
4165 
4166   inst.error = NULL;
4167   end_of_line (str);
4168 }
4169 
4170 /* Long Multiply Parser
4171    UMULL RdLo, RdHi, Rm, Rs
4172    SMULL RdLo, RdHi, Rm, Rs
4173    UMLAL RdLo, RdHi, Rm, Rs
4174    SMLAL RdLo, RdHi, Rm, Rs.  */
4175 
4176 static void
do_mull(str)4177 do_mull (str)
4178      char * str;
4179 {
4180   int rdlo, rdhi, rm, rs;
4181 
4182   /* Only one format "rdlo, rdhi, rm, rs".  */
4183   skip_whitespace (str);
4184 
4185   if ((rdlo = reg_required_here (&str, 12)) == FAIL)
4186     {
4187       inst.error = BAD_ARGS;
4188       return;
4189     }
4190 
4191   if (skip_past_comma (&str) == FAIL
4192       || (rdhi = reg_required_here (&str, 16)) == FAIL)
4193     {
4194       inst.error = BAD_ARGS;
4195       return;
4196     }
4197 
4198   if (skip_past_comma (&str) == FAIL
4199       || (rm = reg_required_here (&str, 0)) == FAIL)
4200     {
4201       inst.error = BAD_ARGS;
4202       return;
4203     }
4204 
4205   /* rdhi, rdlo and rm must all be different.  */
4206   if (rdlo == rdhi || rdlo == rm || rdhi == rm)
4207     as_tsktsk (_("rdhi, rdlo and rm must all be different"));
4208 
4209   if (skip_past_comma (&str) == FAIL
4210       || (rs = reg_required_here (&str, 8)) == FAIL)
4211     {
4212       inst.error = BAD_ARGS;
4213       return;
4214     }
4215 
4216   if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
4217     {
4218       inst.error = BAD_PC;
4219       return;
4220     }
4221 
4222   end_of_line (str);
4223 }
4224 
4225 static void
do_mul(str)4226 do_mul (str)
4227      char * str;
4228 {
4229   int rd, rm;
4230 
4231   /* Only one format "rd, rm, rs".  */
4232   skip_whitespace (str);
4233 
4234   if ((rd = reg_required_here (&str, 16)) == FAIL)
4235     {
4236       inst.error = BAD_ARGS;
4237       return;
4238     }
4239 
4240   if (rd == REG_PC)
4241     {
4242       inst.error = BAD_PC;
4243       return;
4244     }
4245 
4246   if (skip_past_comma (&str) == FAIL
4247       || (rm = reg_required_here (&str, 0)) == FAIL)
4248     {
4249       inst.error = BAD_ARGS;
4250       return;
4251     }
4252 
4253   if (rm == REG_PC)
4254     {
4255       inst.error = BAD_PC;
4256       return;
4257     }
4258 
4259   if (rm == rd)
4260     as_tsktsk (_("rd and rm should be different in mul"));
4261 
4262   if (skip_past_comma (&str) == FAIL
4263       || (rm = reg_required_here (&str, 8)) == FAIL)
4264     {
4265       inst.error = BAD_ARGS;
4266       return;
4267     }
4268 
4269   if (rm == REG_PC)
4270     {
4271       inst.error = BAD_PC;
4272       return;
4273     }
4274 
4275   end_of_line (str);
4276 }
4277 
4278 static void
do_mla(str)4279 do_mla (str)
4280      char * str;
4281 {
4282   int rd, rm;
4283 
4284   /* Only one format "rd, rm, rs, rn".  */
4285   skip_whitespace (str);
4286 
4287   if ((rd = reg_required_here (&str, 16)) == FAIL)
4288     {
4289       inst.error = BAD_ARGS;
4290       return;
4291     }
4292 
4293   if (rd == REG_PC)
4294     {
4295       inst.error = BAD_PC;
4296       return;
4297     }
4298 
4299   if (skip_past_comma (&str) == FAIL
4300       || (rm = reg_required_here (&str, 0)) == FAIL)
4301     {
4302       inst.error = BAD_ARGS;
4303       return;
4304     }
4305 
4306   if (rm == REG_PC)
4307     {
4308       inst.error = BAD_PC;
4309       return;
4310     }
4311 
4312   if (rm == rd)
4313     as_tsktsk (_("rd and rm should be different in mla"));
4314 
4315   if (skip_past_comma (&str) == FAIL
4316       || (rd = reg_required_here (&str, 8)) == FAIL
4317       || skip_past_comma (&str) == FAIL
4318       || (rm = reg_required_here (&str, 12)) == FAIL)
4319     {
4320       inst.error = BAD_ARGS;
4321       return;
4322     }
4323 
4324   if (rd == REG_PC || rm == REG_PC)
4325     {
4326       inst.error = BAD_PC;
4327       return;
4328     }
4329 
4330   end_of_line (str);
4331 }
4332 
4333 /* Expects *str -> the characters "acc0", possibly with leading blanks.
4334    Advances *str to the next non-alphanumeric.
4335    Returns 0, or else FAIL (in which case sets inst.error).
4336 
4337   (In a future XScale, there may be accumulators other than zero.
4338   At that time this routine and its callers can be upgraded to suit.)  */
4339 
4340 static int
accum0_required_here(str)4341 accum0_required_here (str)
4342      char ** str;
4343 {
4344   static char buff [128];	/* Note the address is taken.  Hence, static.  */
4345   char * p = * str;
4346   char   c;
4347   int result = 0;		/* The accum number.  */
4348 
4349   skip_whitespace (p);
4350 
4351   *str = p;			/* Advance caller's string pointer too.  */
4352   c = *p++;
4353   while (ISALNUM (c))
4354     c = *p++;
4355 
4356   *--p = 0;			/* Aap nul into input buffer at non-alnum.  */
4357 
4358   if (! ( streq (*str, "acc0") || streq (*str, "ACC0")))
4359     {
4360       sprintf (buff, _("acc0 expected, not '%.100s'"), *str);
4361       inst.error = buff;
4362       result = FAIL;
4363     }
4364 
4365   *p = c;			/* Unzap.  */
4366   *str = p;			/* Caller's string pointer to after match.  */
4367   return result;
4368 }
4369 
4370 /* Expects **str -> after a comma. May be leading blanks.
4371    Advances *str, recognizing a load  mode, and setting inst.instruction.
4372    Returns rn, or else FAIL (in which case may set inst.error
4373    and not advance str)
4374 
4375    Note: doesn't know Rd, so no err checks that require such knowledge.  */
4376 
4377 static int
ld_mode_required_here(string)4378 ld_mode_required_here (string)
4379      char ** string;
4380 {
4381   char * str = * string;
4382   int    rn;
4383   int    pre_inc = 0;
4384 
4385   skip_whitespace (str);
4386 
4387   if (* str == '[')
4388     {
4389       str++;
4390 
4391       skip_whitespace (str);
4392 
4393       if ((rn = reg_required_here (& str, 16)) == FAIL)
4394 	return FAIL;
4395 
4396       skip_whitespace (str);
4397 
4398       if (* str == ']')
4399 	{
4400 	  str ++;
4401 
4402 	  if (skip_past_comma (& str) == SUCCESS)
4403 	    {
4404 	      /* [Rn],... (post inc) */
4405 	      if (ldst_extend_v4 (&str) == FAIL)
4406 		return FAIL;
4407 	    }
4408 	  else 	      /* [Rn] */
4409 	    {
4410 	      skip_whitespace (str);
4411 
4412 	      if (* str == '!')
4413 		{
4414 		  str ++;
4415 		  inst.instruction |= WRITE_BACK;
4416 		}
4417 
4418 	      inst.instruction |= INDEX_UP | HWOFFSET_IMM;
4419 	      pre_inc = 1;
4420 	    }
4421 	}
4422       else	  /* [Rn,...] */
4423 	{
4424 	  if (skip_past_comma (& str) == FAIL)
4425 	    {
4426 	      inst.error = _("pre-indexed expression expected");
4427 	      return FAIL;
4428 	    }
4429 
4430 	  pre_inc = 1;
4431 
4432 	  if (ldst_extend_v4 (&str) == FAIL)
4433 	    return FAIL;
4434 
4435 	  skip_whitespace (str);
4436 
4437 	  if (* str ++ != ']')
4438 	    {
4439 	      inst.error = _("missing ]");
4440 	      return FAIL;
4441 	    }
4442 
4443 	  skip_whitespace (str);
4444 
4445 	  if (* str == '!')
4446 	    {
4447 	      str ++;
4448 	      inst.instruction |= WRITE_BACK;
4449 	    }
4450 	}
4451     }
4452   else if (* str == '=')	/* ldr's "r,=label" syntax */
4453     /* We should never reach here, because <text> = <expression> is
4454        caught gas/read.c read_a_source_file() as a .set operation.  */
4455     return FAIL;
4456   else				/* PC +- 8 bit immediate offset.  */
4457     {
4458       if (my_get_expression (& inst.reloc.exp, & str))
4459 	return FAIL;
4460 
4461       inst.instruction            |= HWOFFSET_IMM;	/* The I bit.  */
4462       inst.reloc.type              = BFD_RELOC_ARM_OFFSET_IMM8;
4463       inst.reloc.exp.X_add_number -= 8;  		/* PC rel adjust.  */
4464       inst.reloc.pc_rel            = 1;
4465       inst.instruction            |= (REG_PC << 16);
4466 
4467       rn = REG_PC;
4468       pre_inc = 1;
4469     }
4470 
4471   inst.instruction |= (pre_inc ? PRE_INDEX : 0);
4472   * string = str;
4473 
4474   return rn;
4475 }
4476 
4477 /* ARM V5E (El Segundo) signed-multiply-accumulate (argument parse)
4478    SMLAxy{cond} Rd,Rm,Rs,Rn
4479    SMLAWy{cond} Rd,Rm,Rs,Rn
4480    Error if any register is R15.  */
4481 
4482 static void
do_smla(str)4483 do_smla (str)
4484      char *        str;
4485 {
4486   int rd, rm, rs, rn;
4487 
4488   skip_whitespace (str);
4489 
4490   if ((rd = reg_required_here (& str, 16)) == FAIL
4491       || skip_past_comma (& str) == FAIL
4492       || (rm = reg_required_here (& str, 0)) == FAIL
4493       || skip_past_comma (& str) == FAIL
4494       || (rs = reg_required_here (& str, 8)) == FAIL
4495       || skip_past_comma (& str) == FAIL
4496       || (rn = reg_required_here (& str, 12)) == FAIL)
4497     inst.error = BAD_ARGS;
4498 
4499   else if (rd == REG_PC || rm == REG_PC || rs == REG_PC || rn == REG_PC)
4500     inst.error = BAD_PC;
4501 
4502   else
4503     end_of_line (str);
4504 }
4505 
4506 /* ARM V5E (El Segundo) signed-multiply-accumulate-long (argument parse)
4507    SMLALxy{cond} Rdlo,Rdhi,Rm,Rs
4508    Error if any register is R15.
4509    Warning if Rdlo == Rdhi.  */
4510 
4511 static void
do_smlal(str)4512 do_smlal (str)
4513      char *        str;
4514 {
4515   int rdlo, rdhi, rm, rs;
4516 
4517   skip_whitespace (str);
4518 
4519   if ((rdlo = reg_required_here (& str, 12)) == FAIL
4520       || skip_past_comma (& str) == FAIL
4521       || (rdhi = reg_required_here (& str, 16)) == FAIL
4522       || skip_past_comma (& str) == FAIL
4523       || (rm = reg_required_here (& str, 0)) == FAIL
4524       || skip_past_comma (& str) == FAIL
4525       || (rs = reg_required_here (& str, 8)) == FAIL)
4526     {
4527       inst.error = BAD_ARGS;
4528       return;
4529     }
4530 
4531   if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4532     {
4533       inst.error = BAD_PC;
4534       return;
4535     }
4536 
4537   if (rdlo == rdhi)
4538     as_tsktsk (_("rdhi and rdlo must be different"));
4539 
4540   end_of_line (str);
4541 }
4542 
4543 /* ARM V5E (El Segundo) signed-multiply (argument parse)
4544    SMULxy{cond} Rd,Rm,Rs
4545    Error if any register is R15.  */
4546 
4547 static void
do_smul(str)4548 do_smul (str)
4549      char *        str;
4550 {
4551   int rd, rm, rs;
4552 
4553   skip_whitespace (str);
4554 
4555   if ((rd = reg_required_here (& str, 16)) == FAIL
4556       || skip_past_comma (& str) == FAIL
4557       || (rm = reg_required_here (& str, 0)) == FAIL
4558       || skip_past_comma (& str) == FAIL
4559       || (rs = reg_required_here (& str, 8)) == FAIL)
4560     inst.error = BAD_ARGS;
4561 
4562   else if (rd == REG_PC || rm == REG_PC || rs == REG_PC)
4563     inst.error = BAD_PC;
4564 
4565   else
4566     end_of_line (str);
4567 }
4568 
4569 /* ARM V5E (El Segundo) saturating-add/subtract (argument parse)
4570    Q[D]{ADD,SUB}{cond} Rd,Rm,Rn
4571    Error if any register is R15.  */
4572 
4573 static void
do_qadd(str)4574 do_qadd (str)
4575      char *        str;
4576 {
4577   int rd, rm, rn;
4578 
4579   skip_whitespace (str);
4580 
4581   if ((rd = reg_required_here (& str, 12)) == FAIL
4582       || skip_past_comma (& str) == FAIL
4583       || (rm = reg_required_here (& str, 0)) == FAIL
4584       || skip_past_comma (& str) == FAIL
4585       || (rn = reg_required_here (& str, 16)) == FAIL)
4586     inst.error = BAD_ARGS;
4587 
4588   else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
4589     inst.error = BAD_PC;
4590 
4591   else
4592     end_of_line (str);
4593 }
4594 
4595 /* ARM V5E (el Segundo)
4596    MCRRcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4597    MRRCcc <coproc>, <opcode>, <Rd>, <Rn>, <CRm>.
4598 
4599    These are equivalent to the XScale instructions MAR and MRA,
4600    respectively, when coproc == 0, opcode == 0, and CRm == 0.
4601 
4602    Result unpredicatable if Rd or Rn is R15.  */
4603 
4604 static void
do_co_reg2c(str)4605 do_co_reg2c (str)
4606      char *        str;
4607 {
4608   int rd, rn;
4609 
4610   skip_whitespace (str);
4611 
4612   if (co_proc_number (& str) == FAIL)
4613     {
4614       if (!inst.error)
4615 	inst.error = BAD_ARGS;
4616       return;
4617     }
4618 
4619   if (skip_past_comma (& str) == FAIL
4620       || cp_opc_expr (& str, 4, 4) == FAIL)
4621     {
4622       if (!inst.error)
4623 	inst.error = BAD_ARGS;
4624       return;
4625     }
4626 
4627   if (skip_past_comma (& str) == FAIL
4628       || (rd = reg_required_here (& str, 12)) == FAIL)
4629     {
4630       if (!inst.error)
4631 	inst.error = BAD_ARGS;
4632       return;
4633     }
4634 
4635   if (skip_past_comma (& str) == FAIL
4636       || (rn = reg_required_here (& str, 16)) == FAIL)
4637     {
4638       if (!inst.error)
4639 	inst.error = BAD_ARGS;
4640       return;
4641     }
4642 
4643   /* Unpredictable result if rd or rn is R15.  */
4644   if (rd == REG_PC || rn == REG_PC)
4645     as_tsktsk
4646       (_("Warning: instruction unpredictable when using r15"));
4647 
4648   if (skip_past_comma (& str) == FAIL
4649       || cp_reg_required_here (& str, 0) == FAIL)
4650     {
4651       if (!inst.error)
4652 	inst.error = BAD_ARGS;
4653       return;
4654     }
4655 
4656   end_of_line (str);
4657 }
4658 
4659 /* ARM V5 count-leading-zeroes instruction (argument parse)
4660      CLZ{<cond>} <Rd>, <Rm>
4661      Condition defaults to COND_ALWAYS.
4662      Error if Rd or Rm are R15.  */
4663 
4664 static void
do_clz(str)4665 do_clz (str)
4666      char *        str;
4667 {
4668   int rd, rm;
4669 
4670   skip_whitespace (str);
4671 
4672   if (((rd = reg_required_here (& str, 12)) == FAIL)
4673       || (skip_past_comma (& str) == FAIL)
4674       || ((rm = reg_required_here (& str, 0)) == FAIL))
4675     inst.error = BAD_ARGS;
4676 
4677   else if (rd == REG_PC || rm == REG_PC )
4678     inst.error = BAD_PC;
4679 
4680   else
4681     end_of_line (str);
4682 }
4683 
4684 /* ARM V5 (argument parse)
4685      LDC2{L} <coproc>, <CRd>, <addressing mode>
4686      STC2{L} <coproc>, <CRd>, <addressing mode>
4687      Instruction is not conditional, and has 0xf in the condition field.
4688      Otherwise, it's the same as LDC/STC.  */
4689 
4690 static void
do_lstc2(str)4691 do_lstc2 (str)
4692      char *        str;
4693 {
4694   skip_whitespace (str);
4695 
4696   if (co_proc_number (& str) == FAIL)
4697     {
4698       if (!inst.error)
4699 	inst.error = BAD_ARGS;
4700     }
4701   else if (skip_past_comma (& str) == FAIL
4702 	   || cp_reg_required_here (& str, 12) == FAIL)
4703     {
4704       if (!inst.error)
4705 	inst.error = BAD_ARGS;
4706     }
4707   else if (skip_past_comma (& str) == FAIL
4708 	   || cp_address_required_here (&str, CP_WB_OK) == FAIL)
4709     {
4710       if (! inst.error)
4711 	inst.error = BAD_ARGS;
4712     }
4713   else
4714     end_of_line (str);
4715 }
4716 
4717 /* ARM V5 (argument parse)
4718      CDP2 <coproc>, <opcode_1>, <CRd>, <CRn>, <CRm>, <opcode_2>
4719      Instruction is not conditional, and has 0xf in the condition field.
4720      Otherwise, it's the same as CDP.  */
4721 
4722 static void
do_cdp2(str)4723 do_cdp2 (str)
4724      char *        str;
4725 {
4726   skip_whitespace (str);
4727 
4728   if (co_proc_number (& str) == FAIL)
4729     {
4730       if (!inst.error)
4731 	inst.error = BAD_ARGS;
4732       return;
4733     }
4734 
4735   if (skip_past_comma (& str) == FAIL
4736       || cp_opc_expr (& str, 20,4) == FAIL)
4737     {
4738       if (!inst.error)
4739 	inst.error = BAD_ARGS;
4740       return;
4741     }
4742 
4743   if (skip_past_comma (& str) == FAIL
4744       || cp_reg_required_here (& str, 12) == FAIL)
4745     {
4746       if (!inst.error)
4747 	inst.error = BAD_ARGS;
4748       return;
4749     }
4750 
4751   if (skip_past_comma (& str) == FAIL
4752       || cp_reg_required_here (& str, 16) == FAIL)
4753     {
4754       if (!inst.error)
4755 	inst.error = BAD_ARGS;
4756       return;
4757     }
4758 
4759   if (skip_past_comma (& str) == FAIL
4760       || cp_reg_required_here (& str, 0) == FAIL)
4761     {
4762       if (!inst.error)
4763 	inst.error = BAD_ARGS;
4764       return;
4765     }
4766 
4767   if (skip_past_comma (& str) == SUCCESS)
4768     {
4769       if (cp_opc_expr (& str, 5, 3) == FAIL)
4770 	{
4771 	  if (!inst.error)
4772 	    inst.error = BAD_ARGS;
4773 	  return;
4774 	}
4775     }
4776 
4777   end_of_line (str);
4778 }
4779 
4780 /* ARM V5 (argument parse)
4781      MCR2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4782      MRC2 <coproc>, <opcode_1>, <Rd>, <CRn>, <CRm>, <opcode_2>
4783      Instruction is not conditional, and has 0xf in the condition field.
4784      Otherwise, it's the same as MCR/MRC.  */
4785 
4786 static void
do_co_reg2(str)4787 do_co_reg2 (str)
4788      char *        str;
4789 {
4790   skip_whitespace (str);
4791 
4792   if (co_proc_number (& str) == FAIL)
4793     {
4794       if (!inst.error)
4795 	inst.error = BAD_ARGS;
4796       return;
4797     }
4798 
4799   if (skip_past_comma (& str) == FAIL
4800       || cp_opc_expr (& str, 21, 3) == FAIL)
4801     {
4802       if (!inst.error)
4803 	inst.error = BAD_ARGS;
4804       return;
4805     }
4806 
4807   if (skip_past_comma (& str) == FAIL
4808       || reg_required_here (& str, 12) == FAIL)
4809     {
4810       if (!inst.error)
4811 	inst.error = BAD_ARGS;
4812       return;
4813     }
4814 
4815   if (skip_past_comma (& str) == FAIL
4816       || cp_reg_required_here (& str, 16) == FAIL)
4817     {
4818       if (!inst.error)
4819 	inst.error = BAD_ARGS;
4820       return;
4821     }
4822 
4823   if (skip_past_comma (& str) == FAIL
4824       || cp_reg_required_here (& str, 0) == FAIL)
4825     {
4826       if (!inst.error)
4827 	inst.error = BAD_ARGS;
4828       return;
4829     }
4830 
4831   if (skip_past_comma (& str) == SUCCESS)
4832     {
4833       if (cp_opc_expr (& str, 5, 3) == FAIL)
4834 	{
4835 	  if (!inst.error)
4836 	    inst.error = BAD_ARGS;
4837 	  return;
4838 	}
4839     }
4840 
4841   end_of_line (str);
4842 }
4843 
4844 /* ARM v5TEJ.  Jump to Jazelle code.  */
4845 static void
do_bxj(str)4846 do_bxj (str)
4847      char * str;
4848 {
4849   int reg;
4850 
4851   skip_whitespace (str);
4852 
4853   if ((reg = reg_required_here (&str, 0)) == FAIL)
4854     {
4855       inst.error = BAD_ARGS;
4856       return;
4857     }
4858 
4859   /* Note - it is not illegal to do a "bxj pc".  Useless, but not illegal.  */
4860   if (reg == REG_PC)
4861     as_tsktsk (_("use of r15 in bxj is not really useful"));
4862 
4863   end_of_line (str);
4864 }
4865 
4866 /* ARM V6 umaal (argument parse). */
4867 
4868 static void
do_umaal(str)4869 do_umaal (str)
4870      char *str;
4871 {
4872 
4873   int rdlo, rdhi, rm, rs;
4874 
4875   skip_whitespace (str);
4876   if ((rdlo = reg_required_here (& str, 12)) == FAIL
4877       || skip_past_comma (& str) == FAIL
4878       || (rdhi = reg_required_here (& str, 16)) == FAIL
4879       || skip_past_comma (& str) == FAIL
4880       || (rm = reg_required_here (& str, 0)) == FAIL
4881       || skip_past_comma (& str) == FAIL
4882       || (rs = reg_required_here (& str, 8)) == FAIL)
4883     {
4884       inst.error = BAD_ARGS;
4885       return;
4886     }
4887 
4888   if (rdlo == REG_PC || rdhi == REG_PC || rm == REG_PC || rs == REG_PC)
4889     {
4890       inst.error = BAD_PC;
4891       return;
4892     }
4893 
4894   end_of_line (str);
4895 }
4896 
4897 /* ARM V6 strex (argument parse). */
4898 
4899 static void
do_strex(str)4900 do_strex (str)
4901      char *str;
4902 {
4903   int rd, rm, rn;
4904 
4905   /* Parse Rd, Rm,. */
4906   skip_whitespace (str);
4907   if ((rd = reg_required_here (& str, 12)) == FAIL
4908       || skip_past_comma (& str) == FAIL
4909       || (rm = reg_required_here (& str, 0)) == FAIL
4910       || skip_past_comma (& str) == FAIL)
4911     {
4912       inst.error = BAD_ARGS;
4913       return;
4914     }
4915   if (rd == REG_PC || rm == REG_PC)
4916     {
4917       inst.error = BAD_PC;
4918       return;
4919     }
4920   if (rd == rm)
4921     {
4922       inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4923       return;
4924     }
4925 
4926   /* Skip past '['. */
4927   if ((strlen (str) >= 1)
4928       && strncmp (str, "[", 1) == 0)
4929     str+=1;
4930   skip_whitespace (str);
4931 
4932   /* Parse Rn. */
4933   if ((rn = reg_required_here (& str, 16)) == FAIL)
4934     {
4935       inst.error = BAD_ARGS;
4936       return;
4937     }
4938   else if (rn == REG_PC)
4939     {
4940       inst.error = BAD_PC;
4941       return;
4942     }
4943   if (rd == rn)
4944     {
4945       inst.error = _("Rd equal to Rm or Rn yields unpredictable results");
4946       return;
4947     }
4948   skip_whitespace (str);
4949 
4950   /* Skip past ']'. */
4951   if ((strlen (str) >= 1)
4952       && strncmp (str, "]", 1) == 0)
4953     str+=1;
4954 
4955   end_of_line (str);
4956 }
4957 
4958 /* ARM V6 ssat (argument parse). */
4959 
4960 static void
do_ssat(str)4961 do_ssat (str)
4962      char* str;
4963 {
4964   do_sat (&str, /*bias=*/-1);
4965   end_of_line (str);
4966 }
4967 
4968 /* ARM V6 usat (argument parse). */
4969 
4970 static void
do_usat(str)4971 do_usat (str)
4972      char* str;
4973 {
4974   do_sat (&str, /*bias=*/0);
4975   end_of_line (str);
4976 }
4977 
4978 static void
do_sat(str,bias)4979 do_sat (str, bias)
4980      char **str;
4981      int    bias;
4982 {
4983   int rd, rm;
4984   expressionS expr;
4985 
4986   skip_whitespace (*str);
4987 
4988   /* Parse <Rd>, field. */
4989   if ((rd = reg_required_here (str, 12)) == FAIL
4990       || skip_past_comma (str) == FAIL)
4991     {
4992       inst.error = BAD_ARGS;
4993       return;
4994     }
4995   if (rd == REG_PC)
4996     {
4997       inst.error = BAD_PC;
4998       return;
4999     }
5000 
5001   /* Parse #<immed>,  field. */
5002   if (is_immediate_prefix (**str))
5003     (*str)++;
5004   else
5005     {
5006       inst.error = _("immediate expression expected");
5007       return;
5008     }
5009   if (my_get_expression (&expr, str))
5010     {
5011       inst.error = _("bad expression");
5012       return;
5013     }
5014   if (expr.X_op != O_constant)
5015     {
5016       inst.error = _("constant expression expected");
5017       return;
5018     }
5019   if (expr.X_add_number + bias < 0
5020       || expr.X_add_number + bias > 31)
5021     {
5022       inst.error = _("immediate value out of range");
5023       return;
5024     }
5025   inst.instruction |= (expr.X_add_number + bias) << 16;
5026   if (skip_past_comma (str) == FAIL)
5027     {
5028       inst.error = BAD_ARGS;
5029       return;
5030     }
5031 
5032   /* Parse <Rm> field. */
5033   if ((rm = reg_required_here (str, 0)) == FAIL)
5034     {
5035       inst.error = BAD_ARGS;
5036       return;
5037     }
5038   if (rm == REG_PC)
5039     {
5040       inst.error = BAD_PC;
5041       return;
5042     }
5043 
5044   if (skip_past_comma (str) == SUCCESS)
5045     decode_shift (str, SHIFT_LSL_OR_ASR_IMMEDIATE);
5046 }
5047 
5048 /* ARM V6 ssat16 (argument parse). */
5049 
5050 static void
do_ssat16(str)5051 do_ssat16 (str)
5052      char *str;
5053 {
5054   do_sat16 (&str, /*bias=*/-1);
5055   end_of_line (str);
5056 }
5057 
5058 static void
do_usat16(str)5059 do_usat16 (str)
5060      char *str;
5061 {
5062   do_sat16 (&str, /*bias=*/0);
5063   end_of_line (str);
5064 }
5065 
5066 static void
do_sat16(str,bias)5067 do_sat16 (str, bias)
5068      char **str;
5069      int bias;
5070 {
5071   int rd, rm;
5072   expressionS expr;
5073 
5074   skip_whitespace (*str);
5075 
5076   /* Parse the <Rd> field. */
5077   if ((rd = reg_required_here (str, 12)) == FAIL
5078       || skip_past_comma (str) == FAIL)
5079     {
5080       inst.error = BAD_ARGS;
5081       return;
5082     }
5083   if (rd == REG_PC)
5084     {
5085       inst.error = BAD_PC;
5086       return;
5087     }
5088 
5089   /* Parse #<immed>, field. */
5090   if (is_immediate_prefix (**str))
5091     (*str)++;
5092   else
5093     {
5094       inst.error = _("immediate expression expected");
5095       return;
5096     }
5097   if (my_get_expression (&expr, str))
5098     {
5099       inst.error = _("bad expression");
5100       return;
5101     }
5102   if (expr.X_op != O_constant)
5103     {
5104       inst.error = _("constant expression expected");
5105       return;
5106     }
5107   if (expr.X_add_number + bias < 0
5108       || expr.X_add_number + bias > 15)
5109     {
5110       inst.error = _("immediate value out of range");
5111       return;
5112     }
5113   inst.instruction |= (expr.X_add_number + bias) << 16;
5114   if (skip_past_comma (str) == FAIL)
5115     {
5116       inst.error = BAD_ARGS;
5117       return;
5118     }
5119 
5120   /* Parse <Rm> field. */
5121   if ((rm = reg_required_here (str, 0)) == FAIL)
5122     {
5123       inst.error = BAD_ARGS;
5124       return;
5125     }
5126   if (rm == REG_PC)
5127     {
5128       inst.error = BAD_PC;
5129       return;
5130     }
5131 }
5132 
5133 /* ARM V6 srs (argument parse). */
5134 
5135 static void
do_srs(str)5136 do_srs (str)
5137      char* str;
5138 {
5139   char *exclam;
5140   skip_whitespace (str);
5141   exclam = strchr (str, '!');
5142   if (exclam)
5143     *exclam = '\0';
5144   do_cps_mode (&str);
5145   if (exclam)
5146     *exclam = '!';
5147   if (*str == '!')
5148     {
5149       inst.instruction |= WRITE_BACK;
5150       str++;
5151     }
5152   end_of_line (str);
5153 }
5154 
5155 /* ARM V6 SMMUL (argument parse). */
5156 
5157 static void
do_smmul(str)5158 do_smmul (str)
5159      char* str;
5160 {
5161   int rd, rm, rs;
5162 
5163   skip_whitespace (str);
5164   if ((rd = reg_required_here (&str, 16)) == FAIL
5165       || skip_past_comma (&str) == FAIL
5166       || (rm = reg_required_here (&str, 0)) == FAIL
5167       || skip_past_comma (&str) == FAIL
5168       || (rs = reg_required_here (&str, 8)) == FAIL)
5169     {
5170       inst.error = BAD_ARGS;
5171       return;
5172     }
5173 
5174   if (rd == REG_PC
5175       || rm == REG_PC
5176       || rs == REG_PC)
5177     {
5178       inst.error = BAD_PC;
5179       return;
5180     }
5181 
5182   end_of_line (str);
5183 
5184 }
5185 
5186 /* ARM V6 SMLALD (argument parse). */
5187 
5188 static void
do_smlald(str)5189 do_smlald (str)
5190     char* str;
5191 {
5192   int rdlo, rdhi, rm, rs;
5193   skip_whitespace (str);
5194   if ((rdlo = reg_required_here (&str, 12)) == FAIL
5195       || skip_past_comma (&str) == FAIL
5196       || (rdhi = reg_required_here (&str, 16)) == FAIL
5197       || skip_past_comma (&str) == FAIL
5198       || (rm = reg_required_here (&str, 0)) == FAIL
5199       || skip_past_comma (&str) == FAIL
5200       || (rs = reg_required_here (&str, 8)) == FAIL)
5201     {
5202       inst.error = BAD_ARGS;
5203       return;
5204     }
5205 
5206   if (rdlo == REG_PC
5207       || rdhi == REG_PC
5208       || rm == REG_PC
5209       || rs == REG_PC)
5210     {
5211       inst.error = BAD_PC;
5212       return;
5213     }
5214 
5215   end_of_line (str);
5216 }
5217 
5218 /* ARM V6 SMLAD (argument parse).  Signed multiply accumulate dual.
5219    smlad{x}{<cond>} Rd, Rm, Rs, Rn */
5220 
5221 static void
do_smlad(str)5222 do_smlad (str)
5223      char *str;
5224 {
5225   int rd, rm, rs, rn;
5226 
5227   skip_whitespace (str);
5228   if ((rd = reg_required_here (&str, 16)) == FAIL
5229       || skip_past_comma (&str) == FAIL
5230       || (rm = reg_required_here (&str, 0)) == FAIL
5231       || skip_past_comma (&str) == FAIL
5232       || (rs = reg_required_here (&str, 8)) == FAIL
5233       || skip_past_comma (&str) == FAIL
5234       || (rn = reg_required_here (&str, 12)) == FAIL)
5235     {
5236       inst.error = BAD_ARGS;
5237       return;
5238     }
5239 
5240   if (rd == REG_PC
5241       || rn == REG_PC
5242       || rs == REG_PC
5243       || rm == REG_PC)
5244     {
5245       inst.error = BAD_PC;
5246       return;
5247     }
5248 
5249   end_of_line (str);
5250 }
5251 
5252 /* ARM V6 SETEND (argument parse).  Sets the E bit in the CPSR while
5253    preserving the other bits.
5254 
5255    setend <endian_specifier>, where <endian_specifier> is either
5256    BE or LE. */
5257 
5258 static void
do_setend(str)5259 do_setend (str)
5260      char *str;
5261 {
5262   if (do_endian_specifier (str))
5263     inst.instruction |= 0x200;
5264 }
5265 
5266 /* Returns true if the endian-specifier indicates big-endianness.  */
5267 
5268 static int
do_endian_specifier(str)5269 do_endian_specifier (str)
5270      char *str;
5271 {
5272   int big_endian = 0;
5273 
5274   skip_whitespace (str);
5275   if (strlen (str) < 2)
5276     inst.error = _("missing endian specifier");
5277   else if (strncasecmp (str, "BE", 2) == 0)
5278     {
5279       str += 2;
5280       big_endian = 1;
5281     }
5282   else if (strncasecmp (str, "LE", 2) == 0)
5283     str += 2;
5284   else
5285     inst.error = _("valid endian specifiers are be or le");
5286 
5287   end_of_line (str);
5288 
5289   return big_endian;
5290 }
5291 
5292 /* ARM V6 SXTH.
5293 
5294    SXTH {<cond>} <Rd>, <Rm>{, <rotation>}
5295    Condition defaults to COND_ALWAYS.
5296    Error if any register uses R15. */
5297 
5298 static void
do_sxth(str)5299 do_sxth (str)
5300      char *str;
5301 {
5302   int rd, rm;
5303   expressionS expr;
5304   int rotation_clear_mask = 0xfffff3ff;
5305   int rotation_eight_mask = 0x00000400;
5306   int rotation_sixteen_mask = 0x00000800;
5307   int rotation_twenty_four_mask = 0x00000c00;
5308 
5309   skip_whitespace (str);
5310   if ((rd = reg_required_here (&str, 12)) == FAIL
5311       || skip_past_comma (&str) == FAIL
5312       || (rm = reg_required_here (&str, 0)) == FAIL)
5313     {
5314       inst.error = BAD_ARGS;
5315       return;
5316     }
5317 
5318   else if (rd == REG_PC || rm == REG_PC)
5319     {
5320       inst.error = BAD_PC;
5321       return;
5322     }
5323 
5324   /* Zero out the rotation field. */
5325   inst.instruction &= rotation_clear_mask;
5326 
5327   /* Check for lack of optional rotation field. */
5328   if (skip_past_comma (&str) == FAIL)
5329     {
5330       end_of_line (str);
5331       return;
5332     }
5333 
5334   /* Move past 'ROR'. */
5335   skip_whitespace (str);
5336   if (strncasecmp (str, "ROR", 3) == 0)
5337     str+=3;
5338   else
5339     {
5340       inst.error = _("missing rotation field after comma");
5341       return;
5342     }
5343 
5344   /* Get the immediate constant. */
5345   skip_whitespace (str);
5346   if (is_immediate_prefix (* str))
5347     str++;
5348   else
5349     {
5350       inst.error = _("immediate expression expected");
5351       return;
5352     }
5353 
5354   if (my_get_expression (&expr, &str))
5355     {
5356       inst.error = _("bad expression");
5357       return;
5358     }
5359 
5360   if (expr.X_op != O_constant)
5361     {
5362       inst.error = _("constant expression expected");
5363       return;
5364     }
5365 
5366   switch (expr.X_add_number)
5367     {
5368     case 0:
5369       /* Rotation field has already been zeroed. */
5370       break;
5371     case 8:
5372       inst.instruction |= rotation_eight_mask;
5373       break;
5374 
5375     case 16:
5376       inst.instruction |= rotation_sixteen_mask;
5377       break;
5378 
5379     case 24:
5380       inst.instruction |= rotation_twenty_four_mask;
5381       break;
5382 
5383     default:
5384       inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5385       break;
5386     }
5387 
5388   end_of_line (str);
5389 
5390 }
5391 
5392 /* ARM V6 SXTAH extracts a 16-bit value from a register, sign
5393    extends it to 32-bits, and adds the result to a value in another
5394    register.  You can specify a rotation by 0, 8, 16, or 24 bits
5395    before extracting the 16-bit value.
5396    SXTAH{<cond>} <Rd>, <Rn>, <Rm>{, <rotation>}
5397    Condition defaults to COND_ALWAYS.
5398    Error if any register uses R15. */
5399 
5400 static void
do_sxtah(str)5401 do_sxtah (str)
5402      char *str;
5403 {
5404   int rd, rn, rm;
5405   expressionS expr;
5406   int rotation_clear_mask = 0xfffff3ff;
5407   int rotation_eight_mask = 0x00000400;
5408   int rotation_sixteen_mask = 0x00000800;
5409   int rotation_twenty_four_mask = 0x00000c00;
5410 
5411   skip_whitespace (str);
5412   if ((rd = reg_required_here (&str, 12)) == FAIL
5413       || skip_past_comma (&str) == FAIL
5414       || (rn = reg_required_here (&str, 16)) == FAIL
5415       || skip_past_comma (&str) == FAIL
5416       || (rm = reg_required_here (&str, 0)) == FAIL)
5417     {
5418       inst.error = BAD_ARGS;
5419       return;
5420     }
5421 
5422   else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
5423     {
5424       inst.error = BAD_PC;
5425       return;
5426     }
5427 
5428   /* Zero out the rotation field. */
5429   inst.instruction &= rotation_clear_mask;
5430 
5431   /* Check for lack of optional rotation field. */
5432   if (skip_past_comma (&str) == FAIL)
5433     {
5434       end_of_line (str);
5435       return;
5436     }
5437 
5438   /* Move past 'ROR'. */
5439   skip_whitespace (str);
5440   if (strncasecmp (str, "ROR", 3) == 0)
5441     str+=3;
5442   else
5443     {
5444       inst.error = _("missing rotation field after comma");
5445       return;
5446     }
5447 
5448   /* Get the immediate constant. */
5449   skip_whitespace (str);
5450   if (is_immediate_prefix (* str))
5451     str++;
5452   else
5453     {
5454       inst.error = _("immediate expression expected");
5455       return;
5456     }
5457 
5458   if (my_get_expression (&expr, &str))
5459     {
5460       inst.error = _("bad expression");
5461       return;
5462     }
5463 
5464   if (expr.X_op != O_constant)
5465     {
5466       inst.error = _("constant expression expected");
5467       return;
5468     }
5469 
5470   switch (expr.X_add_number)
5471     {
5472     case 0:
5473       /* Rotation field has already been zeroed. */
5474       break;
5475 
5476     case 8:
5477       inst.instruction |= rotation_eight_mask;
5478       break;
5479 
5480     case 16:
5481       inst.instruction |= rotation_sixteen_mask;
5482       break;
5483 
5484     case 24:
5485       inst.instruction |= rotation_twenty_four_mask;
5486       break;
5487 
5488     default:
5489       inst.error = _("rotation can be 8, 16, 24 or 0 when field is ommited");
5490       break;
5491     }
5492 
5493   end_of_line (str);
5494 
5495 }
5496 
5497 
5498 /* ARM V6 RFE (Return from Exception) loads the PC and CPSR from the
5499    word at the specified address and the following word
5500    respectively.
5501    Unconditionally executed.
5502    Error if Rn is R15.
5503 */
5504 
5505 static void
do_rfe(str)5506 do_rfe (str)
5507      char *str;
5508 {
5509   int rn;
5510 
5511   skip_whitespace (str);
5512 
5513   if ((rn = reg_required_here (&str, 16)) == FAIL)
5514     return;
5515 
5516   if (rn == REG_PC)
5517     {
5518       inst.error = BAD_PC;
5519       return;
5520     }
5521 
5522   skip_whitespace (str);
5523 
5524   if (*str == '!')
5525     {
5526       inst.instruction |= WRITE_BACK;
5527       str++;
5528     }
5529   end_of_line (str);
5530 }
5531 
5532 /* ARM V6 REV (Byte Reverse Word) reverses the byte order in a 32-bit
5533    register (argument parse).
5534    REV{<cond>} Rd, Rm.
5535    Condition defaults to COND_ALWAYS.
5536    Error if Rd or Rm are R15. */
5537 
5538 static void
do_rev(str)5539 do_rev (str)
5540      char* str;
5541 {
5542   int rd, rm;
5543 
5544   skip_whitespace (str);
5545 
5546   if ((rd = reg_required_here (&str, 12)) == FAIL
5547       || skip_past_comma (&str) == FAIL
5548       || (rm = reg_required_here (&str, 0)) == FAIL)
5549     inst.error = BAD_ARGS;
5550 
5551   else if (rd == REG_PC || rm == REG_PC)
5552     inst.error = BAD_PC;
5553 
5554   else
5555     end_of_line (str);
5556 }
5557 
5558 /* ARM V6 Perform Two Sixteen Bit Integer Additions. (argument parse).
5559    QADD16{<cond>} <Rd>, <Rn>, <Rm>
5560    Condition defaults to COND_ALWAYS.
5561    Error if Rd, Rn or Rm are R15.  */
5562 
5563 static void
do_qadd16(str)5564 do_qadd16 (str)
5565      char* str;
5566 {
5567   int rd, rm, rn;
5568 
5569   skip_whitespace (str);
5570 
5571   if ((rd = reg_required_here (&str, 12)) == FAIL
5572       || skip_past_comma (&str) == FAIL
5573       || (rn = reg_required_here (&str, 16)) == FAIL
5574       || skip_past_comma (&str) == FAIL
5575       || (rm = reg_required_here (&str, 0)) == FAIL)
5576     inst.error = BAD_ARGS;
5577 
5578   else if (rd == REG_PC || rm == REG_PC || rn == REG_PC)
5579     inst.error = BAD_PC;
5580 
5581   else
5582     end_of_line (str);
5583 }
5584 
5585 /* ARM V6 Pack Halfword Bottom Top instruction (argument parse).
5586    PKHBT {<cond>} <Rd>, <Rn>, <Rm> {, LSL #<shift_imm>}
5587    Condition defaults to COND_ALWAYS.
5588    Error if Rd, Rn or Rm are R15.  */
5589 
5590 static void
do_pkhbt(str)5591 do_pkhbt (str)
5592      char* str;
5593 {
5594   do_pkh_core (str, SHIFT_LSL_IMMEDIATE);
5595 }
5596 
5597 /* ARM V6 PKHTB (Argument Parse). */
5598 
5599 static void
do_pkhtb(str)5600 do_pkhtb (str)
5601      char* str;
5602 {
5603   do_pkh_core (str, SHIFT_ASR_IMMEDIATE);
5604 }
5605 
5606 static void
do_pkh_core(str,shift)5607 do_pkh_core (str, shift)
5608      char* str;
5609      int shift;
5610 {
5611   int rd, rn, rm;
5612 
5613   skip_whitespace (str);
5614   if (((rd = reg_required_here (&str, 12)) == FAIL)
5615       || (skip_past_comma (&str) == FAIL)
5616       || ((rn = reg_required_here (&str, 16)) == FAIL)
5617       || (skip_past_comma (&str) == FAIL)
5618       || ((rm = reg_required_here (&str, 0)) == FAIL))
5619     {
5620       inst.error = BAD_ARGS;
5621       return;
5622     }
5623 
5624   else if (rd == REG_PC || rn == REG_PC || rm == REG_PC)
5625     {
5626       inst.error = BAD_PC;
5627       return;
5628     }
5629 
5630   /* Check for optional shift immediate constant. */
5631   if (skip_past_comma (&str) == FAIL)
5632     {
5633       if (shift == SHIFT_ASR_IMMEDIATE)
5634 	{
5635 	  /* If the shift specifier is ommited, turn the instruction
5636 	     into pkhbt rd, rm, rn.  First, switch the instruction
5637 	     code, and clear the rn and rm fields.  */
5638 	  inst.instruction &= 0xfff0f010;
5639 	  /* Now, re-encode the registers.  */
5640 	  inst.instruction |= (rm << 16) | rn;
5641 	}
5642       return;
5643     }
5644 
5645   decode_shift (&str, shift);
5646 }
5647 
5648 /* ARM V6 Load Register Exclusive instruction (argument parse).
5649    LDREX{<cond>} <Rd, [<Rn>]
5650    Condition defaults to COND_ALWAYS.
5651    Error if Rd or Rn are R15.
5652    See ARMARMv6 A4.1.27: LDREX. */
5653 
5654 
5655 static void
do_ldrex(str)5656 do_ldrex (str)
5657      char * str;
5658 {
5659   int rd, rn;
5660 
5661   skip_whitespace (str);
5662 
5663   /* Parse Rd. */
5664   if (((rd = reg_required_here (&str, 12)) == FAIL)
5665       || (skip_past_comma (&str) == FAIL))
5666     {
5667       inst.error = BAD_ARGS;
5668       return;
5669     }
5670   else if (rd == REG_PC)
5671     {
5672       inst.error = BAD_PC;
5673       return;
5674     }
5675   skip_whitespace (str);
5676 
5677   /* Skip past '['. */
5678   if ((strlen (str) >= 1)
5679       &&strncmp (str, "[", 1) == 0)
5680     str+=1;
5681   skip_whitespace (str);
5682 
5683   /* Parse Rn. */
5684   if ((rn = reg_required_here (&str, 16)) == FAIL)
5685     {
5686       inst.error = BAD_ARGS;
5687       return;
5688     }
5689   else if (rn == REG_PC)
5690     {
5691       inst.error = BAD_PC;
5692       return;
5693     }
5694   skip_whitespace (str);
5695 
5696   /* Skip past ']'. */
5697   if ((strlen (str) >= 1)
5698       && strncmp (str, "]", 1) == 0)
5699     str+=1;
5700 
5701   end_of_line (str);
5702 }
5703 
5704 /* ARM V6 change processor state instruction (argument parse)
5705       CPS, CPSIE, CSPID . */
5706 
5707 static void
do_cps(str)5708 do_cps (str)
5709      char * str;
5710 {
5711   do_cps_mode (&str);
5712   end_of_line (str);
5713 }
5714 
5715 static void
do_cpsi(str)5716 do_cpsi (str)
5717      char * str;
5718 {
5719   do_cps_flags (&str, /*thumb_p=*/0);
5720 
5721   if (skip_past_comma (&str) == SUCCESS)
5722     {
5723       skip_whitespace (str);
5724       do_cps_mode (&str);
5725     }
5726   end_of_line (str);
5727 }
5728 
5729 static void
do_cps_mode(str)5730 do_cps_mode (str)
5731      char **str;
5732 {
5733   expressionS expr;
5734 
5735   skip_whitespace (*str);
5736 
5737   if (! is_immediate_prefix (**str))
5738     {
5739       inst.error = _("immediate expression expected");
5740       return;
5741     }
5742 
5743   (*str)++; /* Strip off the immediate signifier. */
5744   if (my_get_expression (&expr, str))
5745     {
5746       inst.error = _("bad expression");
5747       return;
5748     }
5749 
5750   if (expr.X_op != O_constant)
5751     {
5752       inst.error = _("constant expression expected");
5753       return;
5754     }
5755 
5756   /* The mode is a 5 bit field.  Valid values are 0-31. */
5757   if (((unsigned) expr.X_add_number) > 31
5758       || (inst.reloc.exp.X_add_number) < 0)
5759     {
5760       inst.error = _("invalid constant");
5761       return;
5762     }
5763 
5764   inst.instruction |= expr.X_add_number;
5765 }
5766 
5767 static void
do_cps_flags(str,thumb_p)5768 do_cps_flags (str, thumb_p)
5769      char **str;
5770      int    thumb_p;
5771 {
5772   struct cps_flag {
5773     char character;
5774     unsigned long arm_value;
5775     unsigned long thumb_value;
5776   };
5777   static struct cps_flag flag_table[] = {
5778     {'a', 0x100, 0x4 },
5779     {'i', 0x080, 0x2 },
5780     {'f', 0x040, 0x1 }
5781   };
5782 
5783   int saw_a_flag = 0;
5784 
5785   skip_whitespace (*str);
5786 
5787   /* Get the a, f and i flags. */
5788   while (**str && **str != ',')
5789     {
5790       struct cps_flag *p;
5791       struct cps_flag *q = flag_table + sizeof (flag_table)/sizeof (*p);
5792       for (p = flag_table; p < q; ++p)
5793 	if (strncasecmp (*str, &p->character, 1) == 0)
5794 	  {
5795 	    inst.instruction |= (thumb_p ? p->thumb_value : p->arm_value);
5796 	    saw_a_flag = 1;
5797 	    break;
5798 	  }
5799       if (p == q)
5800 	{
5801 	  inst.error = _("unrecognized flag");
5802 	  return;
5803 	}
5804       (*str)++;
5805     }
5806   if (!saw_a_flag)
5807     inst.error = _("no 'a', 'i', or 'f' flags for 'cps'");
5808 }
5809 
5810 /* THUMB V5 breakpoint instruction (argument parse)
5811 	BKPT <immed_8>.  */
5812 
5813 static void
do_t_bkpt(str)5814 do_t_bkpt (str)
5815      char * str;
5816 {
5817   expressionS expr;
5818   unsigned long number;
5819 
5820   skip_whitespace (str);
5821 
5822   /* Allow optional leading '#'.  */
5823   if (is_immediate_prefix (*str))
5824     str ++;
5825 
5826   memset (& expr, '\0', sizeof (expr));
5827   if (my_get_expression (& expr, & str)
5828       || (expr.X_op != O_constant
5829 	  /* As a convenience we allow 'bkpt' without an operand.  */
5830 	  && expr.X_op != O_absent))
5831     {
5832       inst.error = _("bad expression");
5833       return;
5834     }
5835 
5836   number = expr.X_add_number;
5837 
5838   /* Check it fits an 8 bit unsigned.  */
5839   if (number != (number & 0xff))
5840     {
5841       inst.error = _("immediate value out of range");
5842       return;
5843     }
5844 
5845   inst.instruction |= number;
5846 
5847   end_of_line (str);
5848 }
5849 
5850 /* ARM V5 branch-link-exchange (argument parse) for BLX(1) only.
5851    Expects inst.instruction is set for BLX(1).
5852    Note: this is cloned from do_branch, and the reloc changed to be a
5853 	new one that can cope with setting one extra bit (the H bit).  */
5854 
5855 static void
do_branch25(str)5856 do_branch25 (str)
5857      char *        str;
5858 {
5859   if (my_get_expression (& inst.reloc.exp, & str))
5860     return;
5861 
5862 #ifdef OBJ_ELF
5863   {
5864     char * save_in;
5865 
5866     /* ScottB: February 5, 1998 */
5867     /* Check to see of PLT32 reloc required for the instruction.  */
5868 
5869     /* arm_parse_reloc() works on input_line_pointer.
5870        We actually want to parse the operands to the branch instruction
5871        passed in 'str'.  Save the input pointer and restore it later.  */
5872     save_in = input_line_pointer;
5873     input_line_pointer = str;
5874 
5875     if (inst.reloc.exp.X_op == O_symbol
5876 	&& *str == '('
5877 	&& arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
5878       {
5879 	inst.reloc.type   = BFD_RELOC_ARM_PLT32;
5880 	inst.reloc.pc_rel = 0;
5881 	/* Modify str to point to after parsed operands, otherwise
5882 	   end_of_line() will complain about the (PLT) left in str.  */
5883 	str = input_line_pointer;
5884       }
5885     else
5886       {
5887 	inst.reloc.type   = BFD_RELOC_ARM_PCREL_BLX;
5888 	inst.reloc.pc_rel = 1;
5889       }
5890 
5891     input_line_pointer = save_in;
5892   }
5893 #else
5894   inst.reloc.type   = BFD_RELOC_ARM_PCREL_BLX;
5895   inst.reloc.pc_rel = 1;
5896 #endif /* OBJ_ELF */
5897 
5898   end_of_line (str);
5899 }
5900 
5901 /* ARM V5 branch-link-exchange instruction (argument parse)
5902      BLX <target_addr>		ie BLX(1)
5903      BLX{<condition>} <Rm>	ie BLX(2)
5904    Unfortunately, there are two different opcodes for this mnemonic.
5905    So, the insns[].value is not used, and the code here zaps values
5906 	into inst.instruction.
5907    Also, the <target_addr> can be 25 bits, hence has its own reloc.  */
5908 
5909 static void
do_blx(str)5910 do_blx (str)
5911      char *        str;
5912 {
5913   char * mystr = str;
5914   int rm;
5915 
5916   skip_whitespace (mystr);
5917   rm = reg_required_here (& mystr, 0);
5918 
5919   /* The above may set inst.error.  Ignore his opinion.  */
5920   inst.error = 0;
5921 
5922   if (rm != FAIL)
5923     {
5924       /* Arg is a register.
5925 	 Use the condition code our caller put in inst.instruction.
5926 	 Pass ourselves off as a BX with a funny opcode.  */
5927       inst.instruction |= 0x012fff30;
5928       do_bx (str);
5929     }
5930   else
5931     {
5932       /* This must be is BLX <target address>, no condition allowed.  */
5933       if (inst.instruction != COND_ALWAYS)
5934 	{
5935 	  inst.error = BAD_COND;
5936 	  return;
5937 	}
5938 
5939       inst.instruction = 0xfafffffe;
5940 
5941       /* Process like a B/BL, but with a different reloc.
5942 	 Note that B/BL expecte fffffe, not 0, offset in the opcode table.  */
5943       do_branch25 (str);
5944     }
5945 }
5946 
5947 /* ARM V5 Thumb BLX (argument parse)
5948 	BLX <target_addr>	which is BLX(1)
5949 	BLX <Rm>		which is BLX(2)
5950    Unfortunately, there are two different opcodes for this mnemonic.
5951    So, the tinsns[].value is not used, and the code here zaps values
5952 	into inst.instruction.	*/
5953 
5954 static void
do_t_blx(str)5955 do_t_blx (str)
5956      char * str;
5957 {
5958   char * mystr = str;
5959   int rm;
5960 
5961   skip_whitespace (mystr);
5962   inst.instruction = 0x4780;
5963 
5964   /* Note that this call is to the ARM register recognizer.  BLX(2)
5965      uses the ARM register space, not the Thumb one, so a call to
5966      thumb_reg() would be wrong.  */
5967   rm = reg_required_here (& mystr, 3);
5968   inst.error = 0;
5969 
5970   if (rm != FAIL)
5971     {
5972       /* It's BLX(2).  The .instruction was zapped with rm & is final.  */
5973       inst.size = 2;
5974     }
5975   else
5976     {
5977       /* No ARM register.  This must be BLX(1).  Change the .instruction.  */
5978       inst.instruction = 0xf7ffeffe;
5979       inst.size = 4;
5980 
5981       if (my_get_expression (& inst.reloc.exp, & mystr))
5982 	return;
5983 
5984       inst.reloc.type   = BFD_RELOC_THUMB_PCREL_BLX;
5985       inst.reloc.pc_rel = 1;
5986     }
5987 
5988   end_of_line (mystr);
5989 }
5990 
5991 /* ARM V5 breakpoint instruction (argument parse)
5992      BKPT <16 bit unsigned immediate>
5993      Instruction is not conditional.
5994 	The bit pattern given in insns[] has the COND_ALWAYS condition,
5995 	and it is an error if the caller tried to override that.  */
5996 
5997 static void
do_bkpt(str)5998 do_bkpt (str)
5999      char *        str;
6000 {
6001   expressionS expr;
6002   unsigned long number;
6003 
6004   skip_whitespace (str);
6005 
6006   /* Allow optional leading '#'.  */
6007   if (is_immediate_prefix (* str))
6008     str++;
6009 
6010   memset (& expr, '\0', sizeof (expr));
6011 
6012   if (my_get_expression (& expr, & str)
6013       || (expr.X_op != O_constant
6014 	  /* As a convenience we allow 'bkpt' without an operand.  */
6015 	  && expr.X_op != O_absent))
6016     {
6017       inst.error = _("bad expression");
6018       return;
6019     }
6020 
6021   number = expr.X_add_number;
6022 
6023   /* Check it fits a 16 bit unsigned.  */
6024   if (number != (number & 0xffff))
6025     {
6026       inst.error = _("immediate value out of range");
6027       return;
6028     }
6029 
6030   /* Top 12 of 16 bits to bits 19:8.  */
6031   inst.instruction |= (number & 0xfff0) << 4;
6032 
6033   /* Bottom 4 of 16 bits to bits 3:0.  */
6034   inst.instruction |= number & 0xf;
6035 
6036   end_of_line (str);
6037 }
6038 
6039 /* THUMB CPS instruction (argument parse).  */
6040 
6041 static void
do_t_cps(str)6042 do_t_cps (str)
6043      char *str;
6044 {
6045   do_cps_flags (&str, /*thumb_p=*/1);
6046   end_of_line (str);
6047 }
6048 
6049 /* THUMB CPY instruction (argument parse).  */
6050 
6051 static void
do_t_cpy(str)6052 do_t_cpy (str)
6053      char *str;
6054 {
6055   thumb_mov_compare (str, THUMB_CPY);
6056 }
6057 
6058 /* THUMB SETEND instruction (argument parse).  */
6059 
6060 static void
do_t_setend(str)6061 do_t_setend (str)
6062      char *str;
6063 {
6064   if (do_endian_specifier (str))
6065     inst.instruction |= 0x8;
6066 }
6067 
6068 static unsigned long check_iwmmxt_insn PARAMS ((char *, enum iwmmxt_insn_type, int));
6069 
6070 /* Parse INSN_TYPE insn STR having a possible IMMEDIATE_SIZE immediate.  */
6071 
6072 static unsigned long
check_iwmmxt_insn(str,insn_type,immediate_size)6073 check_iwmmxt_insn (str, insn_type, immediate_size)
6074      char * str;
6075      enum iwmmxt_insn_type insn_type;
6076      int immediate_size;
6077 {
6078   int reg = 0;
6079   const char *  inst_error;
6080   expressionS expr;
6081   unsigned long number;
6082 
6083   inst_error = inst.error;
6084   if (!inst.error)
6085     inst.error = BAD_ARGS;
6086   skip_whitespace (str);
6087 
6088   switch (insn_type)
6089     {
6090     case check_rd:
6091       if ((reg = reg_required_here (&str, 12)) == FAIL)
6092 	return FAIL;
6093       break;
6094 
6095     case check_wr:
6096        if ((wreg_required_here (&str, 0, IWMMXT_REG_WR)) == FAIL)
6097 	 return FAIL;
6098        break;
6099 
6100     case check_wrwr:
6101       if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6102 	   || skip_past_comma (&str) == FAIL
6103 	   || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6104 	return FAIL;
6105       break;
6106 
6107     case check_wrwrwr:
6108       if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6109 	   || skip_past_comma (&str) == FAIL
6110 	   || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6111 	   || skip_past_comma (&str) == FAIL
6112 	   || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6113 	return FAIL;
6114       break;
6115 
6116     case check_wrwrwcg:
6117       if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6118 	   || skip_past_comma (&str) == FAIL
6119 	   || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6120 	   || skip_past_comma (&str) == FAIL
6121 	   || wreg_required_here (&str, 0, IWMMXT_REG_WCG) == FAIL))
6122 	return FAIL;
6123       break;
6124 
6125     case check_tbcst:
6126       if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6127 	   || skip_past_comma (&str) == FAIL
6128 	   || reg_required_here (&str, 12) == FAIL))
6129 	return FAIL;
6130       break;
6131 
6132     case check_tmovmsk:
6133       if ((reg_required_here (&str, 12) == FAIL
6134 	   || skip_past_comma (&str) == FAIL
6135 	   || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL))
6136 	return FAIL;
6137       break;
6138 
6139     case check_tmia:
6140       if ((wreg_required_here (&str, 5, IWMMXT_REG_WR) == FAIL
6141 	   || skip_past_comma (&str) == FAIL
6142 	   || reg_required_here (&str, 0) == FAIL
6143 	   || skip_past_comma (&str) == FAIL
6144 	   || reg_required_here (&str, 12) == FAIL))
6145 	return FAIL;
6146       break;
6147 
6148     case check_tmcrr:
6149       if ((wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6150 	   || skip_past_comma (&str) == FAIL
6151 	   || reg_required_here (&str, 12) == FAIL
6152 	   || skip_past_comma (&str) == FAIL
6153 	   || reg_required_here (&str, 16) == FAIL))
6154 	return FAIL;
6155       break;
6156 
6157     case check_tmrrc:
6158       if ((reg_required_here (&str, 12) == FAIL
6159 	   || skip_past_comma (&str) == FAIL
6160 	   || reg_required_here (&str, 16) == FAIL
6161 	   || skip_past_comma (&str) == FAIL
6162 	   || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL))
6163 	return FAIL;
6164       break;
6165 
6166     case check_tmcr:
6167       if ((wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL
6168 	   || skip_past_comma (&str) == FAIL
6169 	   || reg_required_here (&str, 12) == FAIL))
6170 	return FAIL;
6171       break;
6172 
6173     case check_tmrc:
6174       if ((reg_required_here (&str, 12) == FAIL
6175 	   || skip_past_comma (&str) == FAIL
6176 	   || wreg_required_here (&str, 16, IWMMXT_REG_WC) == FAIL))
6177 	return FAIL;
6178       break;
6179 
6180     case check_tinsr:
6181       if ((wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6182 	   || skip_past_comma (&str) == FAIL
6183 	   || reg_required_here (&str, 12) == FAIL
6184 	   || skip_past_comma (&str) == FAIL))
6185 	return FAIL;
6186       break;
6187 
6188     case check_textrc:
6189       if ((reg_required_here (&str, 12) == FAIL
6190 	   || skip_past_comma (&str) == FAIL))
6191 	return FAIL;
6192       break;
6193 
6194     case check_waligni:
6195       if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6196 	   || skip_past_comma (&str) == FAIL
6197 	   || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6198 	   || skip_past_comma (&str) == FAIL
6199 	   || wreg_required_here (&str, 0, IWMMXT_REG_WR) == FAIL
6200 	   || skip_past_comma (&str) == FAIL))
6201 	return FAIL;
6202       break;
6203 
6204     case check_textrm:
6205       if ((reg_required_here (&str, 12) == FAIL
6206 	   || skip_past_comma (&str) == FAIL
6207 	   || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6208 	   || skip_past_comma (&str) == FAIL))
6209 	return FAIL;
6210       break;
6211 
6212     case check_wshufh:
6213       if ((wreg_required_here (&str, 12, IWMMXT_REG_WR) == FAIL
6214 	   || skip_past_comma (&str) == FAIL
6215 	   || wreg_required_here (&str, 16, IWMMXT_REG_WR) == FAIL
6216 	   || skip_past_comma (&str) == FAIL))
6217 	return FAIL;
6218       break;
6219     }
6220 
6221   if (immediate_size == 0)
6222     {
6223       end_of_line (str);
6224       inst.error = inst_error;
6225       return reg;
6226     }
6227   else
6228     {
6229       skip_whitespace (str);
6230 
6231       /* Allow optional leading '#'. */
6232       if (is_immediate_prefix (* str))
6233         str++;
6234 
6235       memset (& expr, '\0', sizeof (expr));
6236 
6237       if (my_get_expression (& expr, & str) || (expr.X_op != O_constant))
6238         {
6239           inst.error = _("bad or missing expression");
6240           return FAIL;
6241         }
6242 
6243       number = expr.X_add_number;
6244 
6245       if (number != (number & immediate_size))
6246         {
6247           inst.error = _("immediate value out of range");
6248           return FAIL;
6249         }
6250       end_of_line (str);
6251       inst.error = inst_error;
6252       return number;
6253     }
6254 }
6255 
6256 static void
do_iwmmxt_byte_addr(str)6257 do_iwmmxt_byte_addr (str)
6258      char * str;
6259 {
6260   int op = (inst.instruction & 0x300) >> 8;
6261   int reg;
6262 
6263   inst.instruction &= ~0x300;
6264   inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6265 
6266   skip_whitespace (str);
6267 
6268   if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6269       || skip_past_comma (& str) == FAIL
6270       || cp_byte_address_required_here (&str) == FAIL)
6271     {
6272       if (! inst.error)
6273         inst.error = BAD_ARGS;
6274     }
6275   else
6276     end_of_line (str);
6277 
6278   if (wc_register (reg))
6279     {
6280       as_bad (_("non-word size not supported with control register"));
6281       inst.instruction |=  0xf0000100;
6282       inst.instruction &= ~0x00400000;
6283     }
6284 }
6285 
6286 static void
do_iwmmxt_tandc(str)6287 do_iwmmxt_tandc (str)
6288      char * str;
6289 {
6290   int reg;
6291 
6292   reg = check_iwmmxt_insn (str, check_rd, 0);
6293 
6294   if (reg != REG_PC && !inst.error)
6295     inst.error = _("only r15 allowed here");
6296 }
6297 
6298 static void
do_iwmmxt_tbcst(str)6299 do_iwmmxt_tbcst (str)
6300      char * str;
6301 {
6302   check_iwmmxt_insn (str, check_tbcst, 0);
6303 }
6304 
6305 static void
do_iwmmxt_textrc(str)6306 do_iwmmxt_textrc (str)
6307      char * str;
6308 {
6309   unsigned long number;
6310 
6311   if ((number = check_iwmmxt_insn (str, check_textrc, 7)) == (unsigned long) FAIL)
6312     return;
6313 
6314   inst.instruction |= number & 0x7;
6315 }
6316 
6317 static void
do_iwmmxt_textrm(str)6318 do_iwmmxt_textrm (str)
6319      char * str;
6320 {
6321   unsigned long number;
6322 
6323   if ((number = check_iwmmxt_insn (str, check_textrm, 7)) == (unsigned long) FAIL)
6324     return;
6325 
6326   inst.instruction |= number & 0x7;
6327 }
6328 
6329 static void
do_iwmmxt_tinsr(str)6330 do_iwmmxt_tinsr (str)
6331      char * str;
6332 {
6333   unsigned long number;
6334 
6335   if ((number = check_iwmmxt_insn (str, check_tinsr, 7)) == (unsigned long) FAIL)
6336     return;
6337 
6338   inst.instruction |= number & 0x7;
6339 }
6340 
6341 static void
do_iwmmxt_tmcr(str)6342 do_iwmmxt_tmcr (str)
6343      char * str;
6344 {
6345   check_iwmmxt_insn (str, check_tmcr, 0);
6346 }
6347 
6348 static void
do_iwmmxt_tmcrr(str)6349 do_iwmmxt_tmcrr (str)
6350      char * str;
6351 {
6352   check_iwmmxt_insn (str, check_tmcrr, 0);
6353 }
6354 
6355 static void
do_iwmmxt_tmia(str)6356 do_iwmmxt_tmia (str)
6357      char * str;
6358 {
6359   check_iwmmxt_insn (str, check_tmia, 0);
6360 }
6361 
6362 static void
do_iwmmxt_tmovmsk(str)6363 do_iwmmxt_tmovmsk (str)
6364      char * str;
6365 {
6366   check_iwmmxt_insn (str, check_tmovmsk, 0);
6367 }
6368 
6369 static void
do_iwmmxt_tmrc(str)6370 do_iwmmxt_tmrc (str)
6371      char * str;
6372 {
6373   check_iwmmxt_insn (str, check_tmrc, 0);
6374 }
6375 
6376 static void
do_iwmmxt_tmrrc(str)6377 do_iwmmxt_tmrrc (str)
6378      char * str;
6379 {
6380   check_iwmmxt_insn (str, check_tmrrc, 0);
6381 }
6382 
6383 static void
do_iwmmxt_torc(str)6384 do_iwmmxt_torc (str)
6385      char * str;
6386 {
6387   check_iwmmxt_insn (str, check_rd, 0);
6388 }
6389 
6390 static void
do_iwmmxt_waligni(str)6391 do_iwmmxt_waligni (str)
6392      char * str;
6393 {
6394   unsigned long number;
6395 
6396   if ((number = check_iwmmxt_insn (str, check_waligni, 7)) == (unsigned long) FAIL)
6397     return;
6398 
6399   inst.instruction |= ((number & 0x7) << 20);
6400 }
6401 
6402 static void
do_iwmmxt_wmov(str)6403 do_iwmmxt_wmov (str)
6404      char * str;
6405 {
6406   if (check_iwmmxt_insn (str, check_wrwr, 0) == (unsigned long) FAIL)
6407     return;
6408 
6409   inst.instruction |= ((inst.instruction >> 16) & 0xf);
6410 }
6411 
6412 static void
do_iwmmxt_word_addr(str)6413 do_iwmmxt_word_addr (str)
6414      char * str;
6415 {
6416   int op = (inst.instruction & 0x300) >> 8;
6417   int reg;
6418 
6419   inst.instruction &= ~0x300;
6420   inst.instruction |= (op & 1) << 22 | (op & 2) << 7;
6421 
6422   skip_whitespace (str);
6423 
6424   if ((reg = wreg_required_here (&str, 12, IWMMXT_REG_WR_OR_WC)) == FAIL
6425       || skip_past_comma (& str) == FAIL
6426       || cp_address_required_here (& str, CP_WB_OK) == FAIL)
6427     {
6428       if (! inst.error)
6429         inst.error = BAD_ARGS;
6430     }
6431   else
6432     end_of_line (str);
6433 
6434   if (wc_register (reg))
6435     {
6436       if ((inst.instruction & COND_MASK) != COND_ALWAYS)
6437 	as_bad (_("conditional execution not supported with control register"));
6438       if (op != 2)
6439 	as_bad (_("non-word size not supported with control register"));
6440       inst.instruction |=  0xf0000100;
6441       inst.instruction &= ~0x00400000;
6442     }
6443 }
6444 
6445 static void
do_iwmmxt_wrwr(str)6446 do_iwmmxt_wrwr (str)
6447      char * str;
6448 {
6449   check_iwmmxt_insn (str, check_wrwr, 0);
6450 }
6451 
6452 static void
do_iwmmxt_wrwrwcg(str)6453 do_iwmmxt_wrwrwcg (str)
6454      char * str;
6455 {
6456   check_iwmmxt_insn (str, check_wrwrwcg, 0);
6457 }
6458 
6459 static void
do_iwmmxt_wrwrwr(str)6460 do_iwmmxt_wrwrwr (str)
6461      char * str;
6462 {
6463   check_iwmmxt_insn (str, check_wrwrwr, 0);
6464 }
6465 
6466 static void
do_iwmmxt_wshufh(str)6467 do_iwmmxt_wshufh (str)
6468      char * str;
6469 {
6470   unsigned long number;
6471 
6472   if ((number = check_iwmmxt_insn (str, check_wshufh, 0xff)) == (unsigned long) FAIL)
6473     return;
6474 
6475   inst.instruction |= ((number & 0xf0) << 16) | (number & 0xf);
6476 }
6477 
6478 static void
do_iwmmxt_wzero(str)6479 do_iwmmxt_wzero (str)
6480      char * str;
6481 {
6482   if (check_iwmmxt_insn (str, check_wr, 0) == (unsigned long) FAIL)
6483     return;
6484 
6485   inst.instruction |= ((inst.instruction & 0xf) << 12) | ((inst.instruction & 0xf) << 16);
6486 }
6487 
6488 /* Xscale multiply-accumulate (argument parse)
6489      MIAcc   acc0,Rm,Rs
6490      MIAPHcc acc0,Rm,Rs
6491      MIAxycc acc0,Rm,Rs.  */
6492 
6493 static void
do_xsc_mia(str)6494 do_xsc_mia (str)
6495      char * str;
6496 {
6497   int rs;
6498   int rm;
6499 
6500   if (accum0_required_here (& str) == FAIL)
6501     inst.error = ERR_NO_ACCUM;
6502 
6503   else if (skip_past_comma (& str) == FAIL
6504 	   || (rm = reg_required_here (& str, 0)) == FAIL)
6505     inst.error = BAD_ARGS;
6506 
6507   else if (skip_past_comma (& str) == FAIL
6508 	   || (rs = reg_required_here (& str, 12)) == FAIL)
6509     inst.error = BAD_ARGS;
6510 
6511   /* inst.instruction has now been zapped with both rm and rs.  */
6512   else if (rm == REG_PC || rs == REG_PC)
6513     inst.error = BAD_PC;	/* Undefined result if rm or rs is R15.  */
6514 
6515   else
6516     end_of_line (str);
6517 }
6518 
6519 /* Xscale move-accumulator-register (argument parse)
6520 
6521      MARcc   acc0,RdLo,RdHi.  */
6522 
6523 static void
do_xsc_mar(str)6524 do_xsc_mar (str)
6525      char * str;
6526 {
6527   int rdlo, rdhi;
6528 
6529   if (accum0_required_here (& str) == FAIL)
6530     inst.error = ERR_NO_ACCUM;
6531 
6532   else if (skip_past_comma (& str) == FAIL
6533 	   || (rdlo = reg_required_here (& str, 12)) == FAIL)
6534     inst.error = BAD_ARGS;
6535 
6536   else if (skip_past_comma (& str) == FAIL
6537 	   || (rdhi = reg_required_here (& str, 16)) == FAIL)
6538     inst.error = BAD_ARGS;
6539 
6540   /* inst.instruction has now been zapped with both rdlo and rdhi.  */
6541   else if (rdlo == REG_PC || rdhi == REG_PC)
6542     inst.error = BAD_PC;	/* Undefined result if rdlo or rdhi is R15.  */
6543 
6544   else
6545     end_of_line (str);
6546 }
6547 
6548 /* Xscale move-register-accumulator (argument parse)
6549 
6550      MRAcc   RdLo,RdHi,acc0.  */
6551 
6552 static void
do_xsc_mra(str)6553 do_xsc_mra (str)
6554      char * str;
6555 {
6556   int rdlo;
6557   int rdhi;
6558 
6559   skip_whitespace (str);
6560 
6561   if ((rdlo = reg_required_here (& str, 12)) == FAIL)
6562     inst.error = BAD_ARGS;
6563 
6564   else if (skip_past_comma (& str) == FAIL
6565 	   || (rdhi = reg_required_here (& str, 16)) == FAIL)
6566     inst.error = BAD_ARGS;
6567 
6568   else if  (skip_past_comma (& str) == FAIL
6569 	    || accum0_required_here (& str) == FAIL)
6570     inst.error = ERR_NO_ACCUM;
6571 
6572   /* inst.instruction has now been zapped with both rdlo and rdhi.  */
6573   else if (rdlo == rdhi)
6574     inst.error = BAD_ARGS;	/* Undefined result if 2 writes to same reg.  */
6575 
6576   else if (rdlo == REG_PC || rdhi == REG_PC)
6577     inst.error = BAD_PC;	/* Undefined result if rdlo or rdhi is R15.  */
6578   else
6579     end_of_line (str);
6580 }
6581 
6582 /* ARMv5TE: Preload-Cache
6583 
6584     PLD <addr_mode>
6585 
6586   Syntactically, like LDR with B=1, W=0, L=1.  */
6587 
6588 static void
do_pld(str)6589 do_pld (str)
6590      char * str;
6591 {
6592   int rd;
6593 
6594   skip_whitespace (str);
6595 
6596   if (* str != '[')
6597     {
6598       inst.error = _("'[' expected after PLD mnemonic");
6599       return;
6600     }
6601 
6602   ++str;
6603   skip_whitespace (str);
6604 
6605   if ((rd = reg_required_here (& str, 16)) == FAIL)
6606     return;
6607 
6608   skip_whitespace (str);
6609 
6610   if (*str == ']')
6611     {
6612       /* [Rn], ... ?  */
6613       ++str;
6614       skip_whitespace (str);
6615 
6616       /* Post-indexed addressing is not allowed with PLD.  */
6617       if (skip_past_comma (&str) == SUCCESS)
6618 	{
6619 	  inst.error
6620 	    = _("post-indexed expression used in preload instruction");
6621 	  return;
6622 	}
6623       else if (*str == '!') /* [Rn]! */
6624 	{
6625 	  inst.error = _("writeback used in preload instruction");
6626 	  ++str;
6627 	}
6628       else /* [Rn] */
6629 	inst.instruction |= INDEX_UP | PRE_INDEX;
6630     }
6631   else /* [Rn, ...] */
6632     {
6633       if (skip_past_comma (& str) == FAIL)
6634 	{
6635 	  inst.error = _("pre-indexed expression expected");
6636 	  return;
6637 	}
6638 
6639       if (ldst_extend (&str) == FAIL)
6640 	return;
6641 
6642       skip_whitespace (str);
6643 
6644       if (* str != ']')
6645 	{
6646 	  inst.error = _("missing ]");
6647 	  return;
6648 	}
6649 
6650       ++ str;
6651       skip_whitespace (str);
6652 
6653       if (* str == '!') /* [Rn]! */
6654 	{
6655 	  inst.error = _("writeback used in preload instruction");
6656 	  ++ str;
6657 	}
6658 
6659       inst.instruction |= PRE_INDEX;
6660     }
6661 
6662   end_of_line (str);
6663 }
6664 
6665 /* ARMv5TE load-consecutive (argument parse)
6666    Mode is like LDRH.
6667 
6668      LDRccD R, mode
6669      STRccD R, mode.  */
6670 
6671 static void
do_ldrd(str)6672 do_ldrd (str)
6673      char * str;
6674 {
6675   int rd;
6676   int rn;
6677 
6678   skip_whitespace (str);
6679 
6680   if ((rd = reg_required_here (& str, 12)) == FAIL)
6681     {
6682       inst.error = BAD_ARGS;
6683       return;
6684     }
6685 
6686   if (skip_past_comma (& str) == FAIL
6687       || (rn = ld_mode_required_here (& str)) == FAIL)
6688     {
6689       if (!inst.error)
6690 	inst.error = BAD_ARGS;
6691       return;
6692     }
6693 
6694   /* inst.instruction has now been zapped with Rd and the addressing mode.  */
6695   if (rd & 1)		/* Unpredictable result if Rd is odd.  */
6696     {
6697       inst.error = _("destination register must be even");
6698       return;
6699     }
6700 
6701   if (rd == REG_LR)
6702     {
6703       inst.error = _("r14 not allowed here");
6704       return;
6705     }
6706 
6707   if (((rd == rn) || (rd + 1 == rn))
6708       && ((inst.instruction & WRITE_BACK)
6709 	  || (!(inst.instruction & PRE_INDEX))))
6710     as_warn (_("pre/post-indexing used when modified address register is destination"));
6711 
6712   /* For an index-register load, the index register must not overlap the
6713      destination (even if not write-back).  */
6714   if ((inst.instruction & V4_STR_BIT) == 0
6715       && (inst.instruction & HWOFFSET_IMM) == 0)
6716     {
6717       int rm = inst.instruction & 0x0000000f;
6718 
6719       if (rm == rd || (rm == rd + 1))
6720 	as_warn (_("ldrd destination registers must not overlap index register"));
6721     }
6722 
6723   end_of_line (str);
6724 }
6725 
6726 /* Returns the index into fp_values of a floating point number,
6727    or -1 if not in the table.  */
6728 
6729 static int
my_get_float_expression(str)6730 my_get_float_expression (str)
6731      char ** str;
6732 {
6733   LITTLENUM_TYPE words[MAX_LITTLENUMS];
6734   char *         save_in;
6735   expressionS    exp;
6736   int            i;
6737   int            j;
6738 
6739   memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
6740 
6741   /* Look for a raw floating point number.  */
6742   if ((save_in = atof_ieee (*str, 'x', words)) != NULL
6743       && is_end_of_line[(unsigned char) *save_in])
6744     {
6745       for (i = 0; i < NUM_FLOAT_VALS; i++)
6746 	{
6747 	  for (j = 0; j < MAX_LITTLENUMS; j++)
6748 	    {
6749 	      if (words[j] != fp_values[i][j])
6750 		break;
6751 	    }
6752 
6753 	  if (j == MAX_LITTLENUMS)
6754 	    {
6755 	      *str = save_in;
6756 	      return i;
6757 	    }
6758 	}
6759     }
6760 
6761   /* Try and parse a more complex expression, this will probably fail
6762      unless the code uses a floating point prefix (eg "0f").  */
6763   save_in = input_line_pointer;
6764   input_line_pointer = *str;
6765   if (expression (&exp) == absolute_section
6766       && exp.X_op == O_big
6767       && exp.X_add_number < 0)
6768     {
6769       /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
6770 	 Ditto for 15.  */
6771       if (gen_to_words (words, 5, (long) 15) == 0)
6772 	{
6773 	  for (i = 0; i < NUM_FLOAT_VALS; i++)
6774 	    {
6775 	      for (j = 0; j < MAX_LITTLENUMS; j++)
6776 		{
6777 		  if (words[j] != fp_values[i][j])
6778 		    break;
6779 		}
6780 
6781 	      if (j == MAX_LITTLENUMS)
6782 		{
6783 		  *str = input_line_pointer;
6784 		  input_line_pointer = save_in;
6785 		  return i;
6786 		}
6787 	    }
6788 	}
6789     }
6790 
6791   *str = input_line_pointer;
6792   input_line_pointer = save_in;
6793   return -1;
6794 }
6795 
6796 /* Return TRUE if anything in the expression is a bignum.  */
6797 
6798 static int
walk_no_bignums(sp)6799 walk_no_bignums (sp)
6800      symbolS * sp;
6801 {
6802   if (symbol_get_value_expression (sp)->X_op == O_big)
6803     return 1;
6804 
6805   if (symbol_get_value_expression (sp)->X_add_symbol)
6806     {
6807       return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
6808 	      || (symbol_get_value_expression (sp)->X_op_symbol
6809 		  && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
6810     }
6811 
6812   return 0;
6813 }
6814 
6815 static int in_my_get_expression = 0;
6816 
6817 static int
my_get_expression(ep,str)6818 my_get_expression (ep, str)
6819      expressionS * ep;
6820      char ** str;
6821 {
6822   char * save_in;
6823   segT   seg;
6824 
6825   save_in = input_line_pointer;
6826   input_line_pointer = *str;
6827   in_my_get_expression = 1;
6828   seg = expression (ep);
6829   in_my_get_expression = 0;
6830 
6831   if (ep->X_op == O_illegal)
6832     {
6833       /* We found a bad expression in md_operand().  */
6834       *str = input_line_pointer;
6835       input_line_pointer = save_in;
6836       return 1;
6837     }
6838 
6839 #ifdef OBJ_AOUT
6840   if (seg != absolute_section
6841       && seg != text_section
6842       && seg != data_section
6843       && seg != bss_section
6844       && seg != undefined_section)
6845     {
6846       inst.error = _("bad_segment");
6847       *str = input_line_pointer;
6848       input_line_pointer = save_in;
6849       return 1;
6850     }
6851 #endif
6852 
6853   /* Get rid of any bignums now, so that we don't generate an error for which
6854      we can't establish a line number later on.  Big numbers are never valid
6855      in instructions, which is where this routine is always called.  */
6856   if (ep->X_op == O_big
6857       || (ep->X_add_symbol
6858 	  && (walk_no_bignums (ep->X_add_symbol)
6859 	      || (ep->X_op_symbol
6860 		  && walk_no_bignums (ep->X_op_symbol)))))
6861     {
6862       inst.error = _("invalid constant");
6863       *str = input_line_pointer;
6864       input_line_pointer = save_in;
6865       return 1;
6866     }
6867 
6868   *str = input_line_pointer;
6869   input_line_pointer = save_in;
6870   return 0;
6871 }
6872 
6873 /* We handle all bad expressions here, so that we can report the faulty
6874    instruction in the error message.  */
6875 void
md_operand(expr)6876 md_operand (expr)
6877      expressionS *expr;
6878 {
6879   if (in_my_get_expression)
6880     {
6881       expr->X_op = O_illegal;
6882       if (inst.error == NULL)
6883 	inst.error = _("bad expression");
6884     }
6885 }
6886 
6887 /* KIND indicates what kind of shifts are accepted.  */
6888 
6889 static int
decode_shift(str,kind)6890 decode_shift (str, kind)
6891      char ** str;
6892      int     kind;
6893 {
6894   const struct asm_shift_name * shift;
6895   char * p;
6896   char   c;
6897 
6898   skip_whitespace (* str);
6899 
6900   for (p = * str; ISALPHA (* p); p ++)
6901     ;
6902 
6903   if (p == * str)
6904     {
6905       inst.error = _("shift expression expected");
6906       return FAIL;
6907     }
6908 
6909   c = * p;
6910   * p = '\0';
6911   shift = (const struct asm_shift_name *) hash_find (arm_shift_hsh, * str);
6912   * p = c;
6913 
6914   if (shift == NULL)
6915     {
6916       inst.error = _("shift expression expected");
6917       return FAIL;
6918     }
6919 
6920   assert (shift->properties->index == shift_properties[shift->properties->index].index);
6921 
6922   if (kind == SHIFT_LSL_OR_ASR_IMMEDIATE
6923       && shift->properties->index != SHIFT_LSL
6924       && shift->properties->index != SHIFT_ASR)
6925     {
6926       inst.error = _("'LSL' or 'ASR' required");
6927       return FAIL;
6928     }
6929   else if (kind == SHIFT_LSL_IMMEDIATE
6930 	   && shift->properties->index != SHIFT_LSL)
6931     {
6932       inst.error = _("'LSL' required");
6933       return FAIL;
6934     }
6935   else if (kind == SHIFT_ASR_IMMEDIATE
6936 	   && shift->properties->index != SHIFT_ASR)
6937     {
6938       inst.error = _("'ASR' required");
6939       return FAIL;
6940     }
6941 
6942   if (shift->properties->index == SHIFT_RRX)
6943     {
6944       * str = p;
6945       inst.instruction |= shift->properties->bit_field;
6946       return SUCCESS;
6947     }
6948 
6949   skip_whitespace (p);
6950 
6951   if (kind == NO_SHIFT_RESTRICT && reg_required_here (& p, 8) != FAIL)
6952     {
6953       inst.instruction |= shift->properties->bit_field | SHIFT_BY_REG;
6954       * str = p;
6955       return SUCCESS;
6956     }
6957   else if (! is_immediate_prefix (* p))
6958     {
6959       inst.error = (NO_SHIFT_RESTRICT
6960 		    ? _("shift requires register or #expression")
6961 		    : _("shift requires #expression"));
6962       * str = p;
6963       return FAIL;
6964     }
6965 
6966   inst.error = NULL;
6967   p ++;
6968 
6969   if (my_get_expression (& inst.reloc.exp, & p))
6970     return FAIL;
6971 
6972   /* Validate some simple #expressions.  */
6973   if (inst.reloc.exp.X_op == O_constant)
6974     {
6975       unsigned num = inst.reloc.exp.X_add_number;
6976 
6977       /* Reject operations greater than 32.  */
6978       if (num > 32
6979 	  /* Reject a shift of 0 unless the mode allows it.  */
6980 	  || (num == 0 && shift->properties->allows_0 == 0)
6981 	  /* Reject a shift of 32 unless the mode allows it.  */
6982 	  || (num == 32 && shift->properties->allows_32 == 0)
6983 	  )
6984 	{
6985 	  /* As a special case we allow a shift of zero for
6986 	     modes that do not support it to be recoded as an
6987 	     logical shift left of zero (ie nothing).  We warn
6988 	     about this though.  */
6989 	  if (num == 0)
6990 	    {
6991 	      as_warn (_("shift of 0 ignored."));
6992 	      shift = & shift_names[0];
6993 	      assert (shift->properties->index == SHIFT_LSL);
6994 	    }
6995 	  else
6996 	    {
6997 	      inst.error = _("invalid immediate shift");
6998 	      return FAIL;
6999 	    }
7000 	}
7001 
7002       /* Shifts of 32 are encoded as 0, for those shifts that
7003 	 support it.  */
7004       if (num == 32)
7005 	num = 0;
7006 
7007       inst.instruction |= (num << 7) | shift->properties->bit_field;
7008     }
7009   else
7010     {
7011       inst.reloc.type   = BFD_RELOC_ARM_SHIFT_IMM;
7012       inst.reloc.pc_rel = 0;
7013       inst.instruction |= shift->properties->bit_field;
7014     }
7015 
7016   * str = p;
7017   return SUCCESS;
7018 }
7019 
7020 /* Do those data_ops which can take a negative immediate constant
7021    by altering the instruction.  A bit of a hack really.
7022         MOV <-> MVN
7023         AND <-> BIC
7024         ADC <-> SBC
7025         by inverting the second operand, and
7026         ADD <-> SUB
7027         CMP <-> CMN
7028         by negating the second operand.  */
7029 
7030 static int
negate_data_op(instruction,value)7031 negate_data_op (instruction, value)
7032      unsigned long * instruction;
7033      unsigned long   value;
7034 {
7035   int op, new_inst;
7036   unsigned long negated, inverted;
7037 
7038   negated = validate_immediate (-value);
7039   inverted = validate_immediate (~value);
7040 
7041   op = (*instruction >> DATA_OP_SHIFT) & 0xf;
7042   switch (op)
7043     {
7044       /* First negates.  */
7045     case OPCODE_SUB:             /* ADD <-> SUB  */
7046       new_inst = OPCODE_ADD;
7047       value = negated;
7048       break;
7049 
7050     case OPCODE_ADD:
7051       new_inst = OPCODE_SUB;
7052       value = negated;
7053       break;
7054 
7055     case OPCODE_CMP:             /* CMP <-> CMN  */
7056       new_inst = OPCODE_CMN;
7057       value = negated;
7058       break;
7059 
7060     case OPCODE_CMN:
7061       new_inst = OPCODE_CMP;
7062       value = negated;
7063       break;
7064 
7065       /* Now Inverted ops.  */
7066     case OPCODE_MOV:             /* MOV <-> MVN  */
7067       new_inst = OPCODE_MVN;
7068       value = inverted;
7069       break;
7070 
7071     case OPCODE_MVN:
7072       new_inst = OPCODE_MOV;
7073       value = inverted;
7074       break;
7075 
7076     case OPCODE_AND:             /* AND <-> BIC  */
7077       new_inst = OPCODE_BIC;
7078       value = inverted;
7079       break;
7080 
7081     case OPCODE_BIC:
7082       new_inst = OPCODE_AND;
7083       value = inverted;
7084       break;
7085 
7086     case OPCODE_ADC:              /* ADC <-> SBC  */
7087       new_inst = OPCODE_SBC;
7088       value = inverted;
7089       break;
7090 
7091     case OPCODE_SBC:
7092       new_inst = OPCODE_ADC;
7093       value = inverted;
7094       break;
7095 
7096       /* We cannot do anything.  */
7097     default:
7098       return FAIL;
7099     }
7100 
7101   if (value == (unsigned) FAIL)
7102     return FAIL;
7103 
7104   *instruction &= OPCODE_MASK;
7105   *instruction |= new_inst << DATA_OP_SHIFT;
7106   return value;
7107 }
7108 
7109 static int
data_op2(str)7110 data_op2 (str)
7111      char ** str;
7112 {
7113   int value;
7114   expressionS expr;
7115 
7116   skip_whitespace (* str);
7117 
7118   if (reg_required_here (str, 0) != FAIL)
7119     {
7120       if (skip_past_comma (str) == SUCCESS)
7121 	/* Shift operation on register.  */
7122 	return decode_shift (str, NO_SHIFT_RESTRICT);
7123 
7124       return SUCCESS;
7125     }
7126   else
7127     {
7128       /* Immediate expression.  */
7129       if (is_immediate_prefix (**str))
7130 	{
7131 	  (*str)++;
7132 	  inst.error = NULL;
7133 
7134 	  if (my_get_expression (&inst.reloc.exp, str))
7135 	    return FAIL;
7136 
7137 	  if (inst.reloc.exp.X_add_symbol)
7138 	    {
7139 	      inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
7140 	      inst.reloc.pc_rel = 0;
7141 	    }
7142 	  else
7143 	    {
7144 	      if (skip_past_comma (str) == SUCCESS)
7145 		{
7146 		  /* #x, y -- ie explicit rotation by Y.  */
7147 		  if (my_get_expression (&expr, str))
7148 		    return FAIL;
7149 
7150 		  if (expr.X_op != O_constant)
7151 		    {
7152 		      inst.error = _("constant expression expected");
7153 		      return FAIL;
7154 		    }
7155 
7156 		  /* Rotate must be a multiple of 2.  */
7157 		  if (((unsigned) expr.X_add_number) > 30
7158 		      || (expr.X_add_number & 1) != 0
7159 		      || ((unsigned) inst.reloc.exp.X_add_number) > 255)
7160 		    {
7161 		      inst.error = _("invalid constant");
7162 		      return FAIL;
7163 		    }
7164 		  inst.instruction |= INST_IMMEDIATE;
7165 		  inst.instruction |= inst.reloc.exp.X_add_number;
7166 		  inst.instruction |= expr.X_add_number << 7;
7167 		  return SUCCESS;
7168 		}
7169 
7170 	      /* Implicit rotation, select a suitable one.  */
7171 	      value = validate_immediate (inst.reloc.exp.X_add_number);
7172 
7173 	      if (value == FAIL)
7174 		{
7175 		  /* Can't be done.  Perhaps the code reads something like
7176 		     "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be OK.  */
7177 		  if ((value = negate_data_op (&inst.instruction,
7178 					       inst.reloc.exp.X_add_number))
7179 		      == FAIL)
7180 		    {
7181 		      inst.error = _("invalid constant");
7182 		      return FAIL;
7183 		    }
7184 		}
7185 
7186 	      inst.instruction |= value;
7187 	    }
7188 
7189 	  inst.instruction |= INST_IMMEDIATE;
7190 	  return SUCCESS;
7191 	}
7192 
7193       (*str)++;
7194       inst.error = _("register or shift expression expected");
7195       return FAIL;
7196     }
7197 }
7198 
7199 static int
fp_op2(str)7200 fp_op2 (str)
7201      char ** str;
7202 {
7203   skip_whitespace (* str);
7204 
7205   if (fp_reg_required_here (str, 0) != FAIL)
7206     return SUCCESS;
7207   else
7208     {
7209       /* Immediate expression.  */
7210       if (*((*str)++) == '#')
7211 	{
7212 	  int i;
7213 
7214 	  inst.error = NULL;
7215 
7216 	  skip_whitespace (* str);
7217 
7218 	  /* First try and match exact strings, this is to guarantee
7219 	     that some formats will work even for cross assembly.  */
7220 
7221 	  for (i = 0; fp_const[i]; i++)
7222 	    {
7223 	      if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
7224 		{
7225 		  char *start = *str;
7226 
7227 		  *str += strlen (fp_const[i]);
7228 		  if (is_end_of_line[(unsigned char) **str])
7229 		    {
7230 		      inst.instruction |= i + 8;
7231 		      return SUCCESS;
7232 		    }
7233 		  *str = start;
7234 		}
7235 	    }
7236 
7237 	  /* Just because we didn't get a match doesn't mean that the
7238 	     constant isn't valid, just that it is in a format that we
7239 	     don't automatically recognize.  Try parsing it with
7240 	     the standard expression routines.  */
7241 	  if ((i = my_get_float_expression (str)) >= 0)
7242 	    {
7243 	      inst.instruction |= i + 8;
7244 	      return SUCCESS;
7245 	    }
7246 
7247 	  inst.error = _("invalid floating point immediate expression");
7248 	  return FAIL;
7249 	}
7250       inst.error =
7251 	_("floating point register or immediate expression expected");
7252       return FAIL;
7253     }
7254 }
7255 
7256 static void
do_arit(str)7257 do_arit (str)
7258      char * str;
7259 {
7260   skip_whitespace (str);
7261 
7262   if (reg_required_here (&str, 12) == FAIL
7263       || skip_past_comma (&str) == FAIL
7264       || reg_required_here (&str, 16) == FAIL
7265       || skip_past_comma (&str) == FAIL
7266       || data_op2 (&str) == FAIL)
7267     {
7268       if (!inst.error)
7269 	inst.error = BAD_ARGS;
7270       return;
7271     }
7272 
7273   end_of_line (str);
7274 }
7275 
7276 static void
do_adr(str)7277 do_adr (str)
7278      char * str;
7279 {
7280   /* This is a pseudo-op of the form "adr rd, label" to be converted
7281      into a relative address of the form "add rd, pc, #label-.-8".  */
7282   skip_whitespace (str);
7283 
7284   if (reg_required_here (&str, 12) == FAIL
7285       || skip_past_comma (&str) == FAIL
7286       || my_get_expression (&inst.reloc.exp, &str))
7287     {
7288       if (!inst.error)
7289 	inst.error = BAD_ARGS;
7290       return;
7291     }
7292 
7293   /* Frag hacking will turn this into a sub instruction if the offset turns
7294      out to be negative.  */
7295   inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
7296 #ifndef TE_WINCE
7297   inst.reloc.exp.X_add_number -= 8; /* PC relative adjust.  */
7298 #endif
7299   inst.reloc.pc_rel = 1;
7300 
7301   end_of_line (str);
7302 }
7303 
7304 static void
do_adrl(str)7305 do_adrl (str)
7306      char * str;
7307 {
7308   /* This is a pseudo-op of the form "adrl rd, label" to be converted
7309      into a relative address of the form:
7310      add rd, pc, #low(label-.-8)"
7311      add rd, rd, #high(label-.-8)"  */
7312 
7313   skip_whitespace (str);
7314 
7315   if (reg_required_here (&str, 12) == FAIL
7316       || skip_past_comma (&str) == FAIL
7317       || my_get_expression (&inst.reloc.exp, &str))
7318     {
7319       if (!inst.error)
7320 	inst.error = BAD_ARGS;
7321 
7322       return;
7323     }
7324 
7325   end_of_line (str);
7326   /* Frag hacking will turn this into a sub instruction if the offset turns
7327      out to be negative.  */
7328   inst.reloc.type              = BFD_RELOC_ARM_ADRL_IMMEDIATE;
7329 #ifndef TE_WINCE
7330   inst.reloc.exp.X_add_number -= 8; /* PC relative adjust  */
7331 #endif
7332   inst.reloc.pc_rel            = 1;
7333   inst.size                    = INSN_SIZE * 2;
7334 }
7335 
7336 static void
do_cmp(str)7337 do_cmp (str)
7338      char * str;
7339 {
7340   skip_whitespace (str);
7341 
7342   if (reg_required_here (&str, 16) == FAIL)
7343     {
7344       if (!inst.error)
7345 	inst.error = BAD_ARGS;
7346       return;
7347     }
7348 
7349   if (skip_past_comma (&str) == FAIL
7350       || data_op2 (&str) == FAIL)
7351     {
7352       if (!inst.error)
7353 	inst.error = BAD_ARGS;
7354       return;
7355     }
7356 
7357   end_of_line (str);
7358 }
7359 
7360 static void
do_mov(str)7361 do_mov (str)
7362      char * str;
7363 {
7364   skip_whitespace (str);
7365 
7366   if (reg_required_here (&str, 12) == FAIL)
7367     {
7368       if (!inst.error)
7369 	inst.error = BAD_ARGS;
7370       return;
7371     }
7372 
7373   if (skip_past_comma (&str) == FAIL
7374       || data_op2 (&str) == FAIL)
7375     {
7376       if (!inst.error)
7377 	inst.error = BAD_ARGS;
7378       return;
7379     }
7380 
7381   end_of_line (str);
7382 }
7383 
7384 static int
ldst_extend(str)7385 ldst_extend (str)
7386      char ** str;
7387 {
7388   int add = INDEX_UP;
7389 
7390   switch (**str)
7391     {
7392     case '#':
7393     case '$':
7394       (*str)++;
7395       if (my_get_expression (& inst.reloc.exp, str))
7396 	return FAIL;
7397 
7398       if (inst.reloc.exp.X_op == O_constant)
7399 	{
7400 	  int value = inst.reloc.exp.X_add_number;
7401 
7402 	  if (value < -4095 || value > 4095)
7403 	    {
7404 	      inst.error = _("address offset too large");
7405 	      return FAIL;
7406 	    }
7407 
7408 	  if (value < 0)
7409 	    {
7410 	      value = -value;
7411 	      add = 0;
7412 	    }
7413 
7414 	  inst.instruction |= add | value;
7415 	}
7416       else
7417 	{
7418 	  inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7419 	  inst.reloc.pc_rel = 0;
7420 	}
7421       return SUCCESS;
7422 
7423     case '-':
7424       add = 0;
7425       /* Fall through.  */
7426 
7427     case '+':
7428       (*str)++;
7429       /* Fall through.  */
7430 
7431     default:
7432       if (reg_required_here (str, 0) == FAIL)
7433 	return FAIL;
7434 
7435       inst.instruction |= add | OFFSET_REG;
7436       if (skip_past_comma (str) == SUCCESS)
7437 	return decode_shift (str, SHIFT_IMMEDIATE);
7438 
7439       return SUCCESS;
7440     }
7441 }
7442 
7443 static void
do_ldst(str)7444 do_ldst (str)
7445      char *        str;
7446 {
7447   int pre_inc = 0;
7448   int conflict_reg;
7449   int value;
7450 
7451   skip_whitespace (str);
7452 
7453   if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
7454     {
7455       if (!inst.error)
7456 	inst.error = BAD_ARGS;
7457       return;
7458     }
7459 
7460   if (skip_past_comma (&str) == FAIL)
7461     {
7462       inst.error = _("address expected");
7463       return;
7464     }
7465 
7466   if (*str == '[')
7467     {
7468       int reg;
7469 
7470       str++;
7471 
7472       skip_whitespace (str);
7473 
7474       if ((reg = reg_required_here (&str, 16)) == FAIL)
7475 	return;
7476 
7477       /* Conflicts can occur on stores as well as loads.  */
7478       conflict_reg = (conflict_reg == reg);
7479 
7480       skip_whitespace (str);
7481 
7482       if (*str == ']')
7483 	{
7484 	  str ++;
7485 
7486 	  if (skip_past_comma (&str) == SUCCESS)
7487 	    {
7488 	      /* [Rn],... (post inc)  */
7489 	      if (ldst_extend (&str) == FAIL)
7490 		return;
7491 	      if (conflict_reg)
7492 		as_warn (_("%s register same as write-back base"),
7493 			 ((inst.instruction & LOAD_BIT)
7494 			  ? _("destination") : _("source")));
7495 	    }
7496 	  else
7497 	    {
7498 	      /* [Rn]  */
7499 	      skip_whitespace (str);
7500 
7501 	      if (*str == '!')
7502 		{
7503 		  if (conflict_reg)
7504 		    as_warn (_("%s register same as write-back base"),
7505 			     ((inst.instruction & LOAD_BIT)
7506 			      ? _("destination") : _("source")));
7507 		  str++;
7508 		  inst.instruction |= WRITE_BACK;
7509 		}
7510 
7511 	      inst.instruction |= INDEX_UP;
7512 	      pre_inc = 1;
7513 	    }
7514 	}
7515       else
7516 	{
7517 	  /* [Rn,...]  */
7518 	  if (skip_past_comma (&str) == FAIL)
7519 	    {
7520 	      inst.error = _("pre-indexed expression expected");
7521 	      return;
7522 	    }
7523 
7524 	  pre_inc = 1;
7525 	  if (ldst_extend (&str) == FAIL)
7526 	    return;
7527 
7528 	  skip_whitespace (str);
7529 
7530 	  if (*str++ != ']')
7531 	    {
7532 	      inst.error = _("missing ]");
7533 	      return;
7534 	    }
7535 
7536 	  skip_whitespace (str);
7537 
7538 	  if (*str == '!')
7539 	    {
7540 	      if (conflict_reg)
7541 		as_warn (_("%s register same as write-back base"),
7542 			 ((inst.instruction & LOAD_BIT)
7543 			  ? _("destination") : _("source")));
7544 	      str++;
7545 	      inst.instruction |= WRITE_BACK;
7546 	    }
7547 	}
7548     }
7549   else if (*str == '=')
7550     {
7551       if ((inst.instruction & LOAD_BIT) == 0)
7552 	{
7553 	  inst.error = _("invalid pseudo operation");
7554 	  return;
7555 	}
7556 
7557       /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op.  */
7558       str++;
7559 
7560       skip_whitespace (str);
7561 
7562       if (my_get_expression (&inst.reloc.exp, &str))
7563 	return;
7564 
7565       if (inst.reloc.exp.X_op != O_constant
7566 	  && inst.reloc.exp.X_op != O_symbol)
7567 	{
7568 	  inst.error = _("constant expression expected");
7569 	  return;
7570 	}
7571 
7572       if (inst.reloc.exp.X_op == O_constant)
7573 	{
7574 	  value = validate_immediate (inst.reloc.exp.X_add_number);
7575 
7576 	  if (value != FAIL)
7577 	    {
7578 	      /* This can be done with a mov instruction.  */
7579 	      inst.instruction &= LITERAL_MASK;
7580 	      inst.instruction |= (INST_IMMEDIATE
7581 				   | (OPCODE_MOV << DATA_OP_SHIFT));
7582 	      inst.instruction |= value & 0xfff;
7583 	      end_of_line (str);
7584 	      return;
7585 	    }
7586 
7587 	  value = validate_immediate (~inst.reloc.exp.X_add_number);
7588 
7589 	  if (value != FAIL)
7590 	    {
7591 	      /* This can be done with a mvn instruction.  */
7592 	      inst.instruction &= LITERAL_MASK;
7593 	      inst.instruction |= (INST_IMMEDIATE
7594 				   | (OPCODE_MVN << DATA_OP_SHIFT));
7595 	      inst.instruction |= value & 0xfff;
7596 	      end_of_line (str);
7597 	      return;
7598 	    }
7599 	}
7600 
7601       /* Insert into literal pool.  */
7602       if (add_to_lit_pool () == FAIL)
7603 	{
7604 	  if (!inst.error)
7605 	    inst.error = _("literal pool insertion failed");
7606 	  return;
7607 	}
7608 
7609       /* Change the instruction exp to point to the pool.  */
7610       inst.reloc.type = BFD_RELOC_ARM_LITERAL;
7611       inst.reloc.pc_rel = 1;
7612       inst.instruction |= (REG_PC << 16);
7613       pre_inc = 1;
7614     }
7615   else
7616     {
7617       if (my_get_expression (&inst.reloc.exp, &str))
7618 	return;
7619 
7620       inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
7621 #ifndef TE_WINCE
7622       /* PC rel adjust.  */
7623       inst.reloc.exp.X_add_number -= 8;
7624 #endif
7625       inst.reloc.pc_rel = 1;
7626       inst.instruction |= (REG_PC << 16);
7627       pre_inc = 1;
7628     }
7629 
7630   inst.instruction |= (pre_inc ? PRE_INDEX : 0);
7631   end_of_line (str);
7632 }
7633 
7634 static void
do_ldstt(str)7635 do_ldstt (str)
7636      char *        str;
7637 {
7638   int conflict_reg;
7639 
7640   skip_whitespace (str);
7641 
7642   if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
7643     {
7644       if (!inst.error)
7645 	inst.error = BAD_ARGS;
7646       return;
7647     }
7648 
7649   if (skip_past_comma (& str) == FAIL)
7650     {
7651       inst.error = _("address expected");
7652       return;
7653     }
7654 
7655   if (*str == '[')
7656     {
7657       int reg;
7658 
7659       str++;
7660 
7661       skip_whitespace (str);
7662 
7663       if ((reg = reg_required_here (&str, 16)) == FAIL)
7664 	return;
7665 
7666       /* ldrt/strt always use post-indexed addressing, so if the base is
7667 	 the same as Rd, we warn.  */
7668       if (conflict_reg == reg)
7669 	as_warn (_("%s register same as write-back base"),
7670 		 ((inst.instruction & LOAD_BIT)
7671 		  ? _("destination") : _("source")));
7672 
7673       skip_whitespace (str);
7674 
7675       if (*str == ']')
7676 	{
7677 	  str ++;
7678 
7679 	  if (skip_past_comma (&str) == SUCCESS)
7680 	    {
7681 	      /* [Rn],... (post inc)  */
7682 	      if (ldst_extend (&str) == FAIL)
7683 		return;
7684 	    }
7685 	  else
7686 	    {
7687 	      /* [Rn]  */
7688 	      skip_whitespace (str);
7689 
7690 	      /* Skip a write-back '!'.  */
7691 	      if (*str == '!')
7692 		str++;
7693 
7694 	      inst.instruction |= INDEX_UP;
7695 	    }
7696 	}
7697       else
7698 	{
7699 	  inst.error = _("post-indexed expression expected");
7700 	  return;
7701 	}
7702     }
7703   else
7704     {
7705       inst.error = _("post-indexed expression expected");
7706       return;
7707     }
7708 
7709   end_of_line (str);
7710 }
7711 
7712 static int
ldst_extend_v4(str)7713 ldst_extend_v4 (str)
7714      char ** str;
7715 {
7716   int add = INDEX_UP;
7717 
7718   switch (**str)
7719     {
7720     case '#':
7721     case '$':
7722       (*str)++;
7723       if (my_get_expression (& inst.reloc.exp, str))
7724 	return FAIL;
7725 
7726       if (inst.reloc.exp.X_op == O_constant)
7727 	{
7728 	  int value = inst.reloc.exp.X_add_number;
7729 
7730 	  if (value < -255 || value > 255)
7731 	    {
7732 	      inst.error = _("address offset too large");
7733 	      return FAIL;
7734 	    }
7735 
7736 	  if (value < 0)
7737 	    {
7738 	      value = -value;
7739 	      add = 0;
7740 	    }
7741 
7742 	  /* Halfword and signextension instructions have the
7743              immediate value split across bits 11..8 and bits 3..0.  */
7744 	  inst.instruction |= (add | HWOFFSET_IMM
7745 			       | ((value >> 4) << 8) | (value & 0xF));
7746 	}
7747       else
7748 	{
7749 	  inst.instruction |= HWOFFSET_IMM;
7750 	  inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
7751 	  inst.reloc.pc_rel = 0;
7752 	}
7753       return SUCCESS;
7754 
7755     case '-':
7756       add = 0;
7757       /* Fall through.  */
7758 
7759     case '+':
7760       (*str)++;
7761       /* Fall through.  */
7762 
7763     default:
7764       if (reg_required_here (str, 0) == FAIL)
7765 	return FAIL;
7766 
7767       inst.instruction |= add;
7768       return SUCCESS;
7769     }
7770 }
7771 
7772 /* Halfword and signed-byte load/store operations.  */
7773 static void
do_ldstv4(str)7774 do_ldstv4 (str)
7775      char *        str;
7776 {
7777   int pre_inc = 0;
7778   int conflict_reg;
7779   int value;
7780 
7781   skip_whitespace (str);
7782 
7783   if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
7784     {
7785       if (!inst.error)
7786 	inst.error = BAD_ARGS;
7787       return;
7788     }
7789 
7790   if (skip_past_comma (& str) == FAIL)
7791     {
7792       inst.error = _("address expected");
7793       return;
7794     }
7795 
7796   if (*str == '[')
7797     {
7798       int reg;
7799 
7800       str++;
7801 
7802       skip_whitespace (str);
7803 
7804       if ((reg = reg_required_here (&str, 16)) == FAIL)
7805 	return;
7806 
7807       /* Conflicts can occur on stores as well as loads.  */
7808       conflict_reg = (conflict_reg == reg);
7809 
7810       skip_whitespace (str);
7811 
7812       if (*str == ']')
7813 	{
7814 	  str ++;
7815 
7816 	  if (skip_past_comma (&str) == SUCCESS)
7817 	    {
7818 	      /* [Rn],... (post inc)  */
7819 	      if (ldst_extend_v4 (&str) == FAIL)
7820 		return;
7821 	      if (conflict_reg)
7822 		as_warn (_("%s register same as write-back base"),
7823 			 ((inst.instruction & LOAD_BIT)
7824 			  ? _("destination") : _("source")));
7825 	    }
7826 	  else
7827 	    {
7828 	      /* [Rn]  */
7829 	      inst.instruction |= HWOFFSET_IMM;
7830 
7831 	      skip_whitespace (str);
7832 
7833 	      if (*str == '!')
7834 		{
7835 		  if (conflict_reg)
7836 		    as_warn (_("%s register same as write-back base"),
7837 			     ((inst.instruction & LOAD_BIT)
7838 			      ? _("destination") : _("source")));
7839 		  str++;
7840 		  inst.instruction |= WRITE_BACK;
7841 		}
7842 
7843 	      inst.instruction |= INDEX_UP;
7844 	      pre_inc = 1;
7845 	    }
7846 	}
7847       else
7848 	{
7849 	  /* [Rn,...]  */
7850 	  if (skip_past_comma (&str) == FAIL)
7851 	    {
7852 	      inst.error = _("pre-indexed expression expected");
7853 	      return;
7854 	    }
7855 
7856 	  pre_inc = 1;
7857 	  if (ldst_extend_v4 (&str) == FAIL)
7858 	    return;
7859 
7860 	  skip_whitespace (str);
7861 
7862 	  if (*str++ != ']')
7863 	    {
7864 	      inst.error = _("missing ]");
7865 	      return;
7866 	    }
7867 
7868 	  skip_whitespace (str);
7869 
7870 	  if (*str == '!')
7871 	    {
7872 	      if (conflict_reg)
7873 		as_warn (_("%s register same as write-back base"),
7874 			 ((inst.instruction & LOAD_BIT)
7875 			  ? _("destination") : _("source")));
7876 	      str++;
7877 	      inst.instruction |= WRITE_BACK;
7878 	    }
7879 	}
7880     }
7881   else if (*str == '=')
7882     {
7883       if ((inst.instruction & LOAD_BIT) == 0)
7884 	{
7885 	  inst.error = _("invalid pseudo operation");
7886 	  return;
7887 	}
7888 
7889       /* XXX Does this work correctly for half-word/byte ops?  */
7890       /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op.  */
7891       str++;
7892 
7893       skip_whitespace (str);
7894 
7895       if (my_get_expression (&inst.reloc.exp, &str))
7896 	return;
7897 
7898       if (inst.reloc.exp.X_op != O_constant
7899 	  && inst.reloc.exp.X_op != O_symbol)
7900 	{
7901 	  inst.error = _("constant expression expected");
7902 	  return;
7903 	}
7904 
7905       if (inst.reloc.exp.X_op == O_constant)
7906 	{
7907 	  value = validate_immediate (inst.reloc.exp.X_add_number);
7908 
7909 	  if (value != FAIL)
7910 	    {
7911 	      /* This can be done with a mov instruction.  */
7912 	      inst.instruction &= LITERAL_MASK;
7913 	      inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
7914 	      inst.instruction |= value & 0xfff;
7915 	      end_of_line (str);
7916 	      return;
7917 	    }
7918 
7919 	  value = validate_immediate (~ inst.reloc.exp.X_add_number);
7920 
7921 	  if (value != FAIL)
7922 	    {
7923 	      /* This can be done with a mvn instruction.  */
7924 	      inst.instruction &= LITERAL_MASK;
7925 	      inst.instruction |= INST_IMMEDIATE | (OPCODE_MVN << DATA_OP_SHIFT);
7926 	      inst.instruction |= value & 0xfff;
7927 	      end_of_line (str);
7928 	      return;
7929 	    }
7930 	}
7931 
7932       /* Insert into literal pool.  */
7933       if (add_to_lit_pool () == FAIL)
7934 	{
7935 	  if (!inst.error)
7936 	    inst.error = _("literal pool insertion failed");
7937 	  return;
7938 	}
7939 
7940       /* Change the instruction exp to point to the pool.  */
7941       inst.instruction |= HWOFFSET_IMM;
7942       inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
7943       inst.reloc.pc_rel = 1;
7944       inst.instruction |= (REG_PC << 16);
7945       pre_inc = 1;
7946     }
7947   else
7948     {
7949       if (my_get_expression (&inst.reloc.exp, &str))
7950 	return;
7951 
7952       inst.instruction |= HWOFFSET_IMM;
7953       inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
7954 #ifndef TE_WINCE
7955       /* PC rel adjust.  */
7956       inst.reloc.exp.X_add_number -= 8;
7957 #endif
7958       inst.reloc.pc_rel = 1;
7959       inst.instruction |= (REG_PC << 16);
7960       pre_inc = 1;
7961     }
7962 
7963   inst.instruction |= (pre_inc ? PRE_INDEX : 0);
7964   end_of_line (str);
7965 }
7966 
7967 static long
reg_list(strp)7968 reg_list (strp)
7969      char ** strp;
7970 {
7971   char * str = * strp;
7972   long   range = 0;
7973   int    another_range;
7974 
7975   /* We come back here if we get ranges concatenated by '+' or '|'.  */
7976   do
7977     {
7978       another_range = 0;
7979 
7980       if (*str == '{')
7981 	{
7982 	  int in_range = 0;
7983 	  int cur_reg = -1;
7984 
7985 	  str++;
7986 	  do
7987 	    {
7988 	      int reg;
7989 
7990 	      skip_whitespace (str);
7991 
7992 	      if ((reg = reg_required_here (& str, -1)) == FAIL)
7993 		return FAIL;
7994 
7995 	      if (in_range)
7996 		{
7997 		  int i;
7998 
7999 		  if (reg <= cur_reg)
8000 		    {
8001 		      inst.error = _("bad range in register list");
8002 		      return FAIL;
8003 		    }
8004 
8005 		  for (i = cur_reg + 1; i < reg; i++)
8006 		    {
8007 		      if (range & (1 << i))
8008 			as_tsktsk
8009 			  (_("Warning: duplicated register (r%d) in register list"),
8010 			   i);
8011 		      else
8012 			range |= 1 << i;
8013 		    }
8014 		  in_range = 0;
8015 		}
8016 
8017 	      if (range & (1 << reg))
8018 		as_tsktsk (_("Warning: duplicated register (r%d) in register list"),
8019 			   reg);
8020 	      else if (reg <= cur_reg)
8021 		as_tsktsk (_("Warning: register range not in ascending order"));
8022 
8023 	      range |= 1 << reg;
8024 	      cur_reg = reg;
8025 	    }
8026 	  while (skip_past_comma (&str) != FAIL
8027 		 || (in_range = 1, *str++ == '-'));
8028 	  str--;
8029 	  skip_whitespace (str);
8030 
8031 	  if (*str++ != '}')
8032 	    {
8033 	      inst.error = _("missing `}'");
8034 	      return FAIL;
8035 	    }
8036 	}
8037       else
8038 	{
8039 	  expressionS expr;
8040 
8041 	  if (my_get_expression (&expr, &str))
8042 	    return FAIL;
8043 
8044 	  if (expr.X_op == O_constant)
8045 	    {
8046 	      if (expr.X_add_number
8047 		  != (expr.X_add_number & 0x0000ffff))
8048 		{
8049 		  inst.error = _("invalid register mask");
8050 		  return FAIL;
8051 		}
8052 
8053 	      if ((range & expr.X_add_number) != 0)
8054 		{
8055 		  int regno = range & expr.X_add_number;
8056 
8057 		  regno &= -regno;
8058 		  regno = (1 << regno) - 1;
8059 		  as_tsktsk
8060 		    (_("Warning: duplicated register (r%d) in register list"),
8061 		     regno);
8062 		}
8063 
8064 	      range |= expr.X_add_number;
8065 	    }
8066 	  else
8067 	    {
8068 	      if (inst.reloc.type != 0)
8069 		{
8070 		  inst.error = _("expression too complex");
8071 		  return FAIL;
8072 		}
8073 
8074 	      memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
8075 	      inst.reloc.type = BFD_RELOC_ARM_MULTI;
8076 	      inst.reloc.pc_rel = 0;
8077 	    }
8078 	}
8079 
8080       skip_whitespace (str);
8081 
8082       if (*str == '|' || *str == '+')
8083 	{
8084 	  str++;
8085 	  another_range = 1;
8086 	}
8087     }
8088   while (another_range);
8089 
8090   *strp = str;
8091   return range;
8092 }
8093 
8094 static void
do_ldmstm(str)8095 do_ldmstm (str)
8096      char * str;
8097 {
8098   int base_reg;
8099   long range;
8100 
8101   skip_whitespace (str);
8102 
8103   if ((base_reg = reg_required_here (&str, 16)) == FAIL)
8104     return;
8105 
8106   if (base_reg == REG_PC)
8107     {
8108       inst.error = _("r15 not allowed as base register");
8109       return;
8110     }
8111 
8112   skip_whitespace (str);
8113 
8114   if (*str == '!')
8115     {
8116       inst.instruction |= WRITE_BACK;
8117       str++;
8118     }
8119 
8120   if (skip_past_comma (&str) == FAIL
8121       || (range = reg_list (&str)) == FAIL)
8122     {
8123       if (! inst.error)
8124 	inst.error = BAD_ARGS;
8125       return;
8126     }
8127 
8128   if (*str == '^')
8129     {
8130       str++;
8131       inst.instruction |= LDM_TYPE_2_OR_3;
8132     }
8133 
8134   if (inst.instruction & WRITE_BACK)
8135     {
8136       /* Check for unpredictable uses of writeback.  */
8137       if (inst.instruction & LOAD_BIT)
8138 	{
8139 	  /* Not allowed in LDM type 2.  */
8140 	  if ((inst.instruction & LDM_TYPE_2_OR_3)
8141 	      && ((range & (1 << REG_PC)) == 0))
8142 	    as_warn (_("writeback of base register is UNPREDICTABLE"));
8143 	  /* Only allowed if base reg not in list for other types.  */
8144 	  else if (range & (1 << base_reg))
8145 	    as_warn (_("writeback of base register when in register list is UNPREDICTABLE"));
8146 	}
8147       else /* STM.  */
8148 	{
8149 	  /* Not allowed for type 2.  */
8150 	  if (inst.instruction & LDM_TYPE_2_OR_3)
8151 	    as_warn (_("writeback of base register is UNPREDICTABLE"));
8152 	  /* Only allowed if base reg not in list, or first in list.  */
8153 	  else if ((range & (1 << base_reg))
8154 		   && (range & ((1 << base_reg) - 1)))
8155 	    as_warn (_("if writeback register is in list, it must be the lowest reg in the list"));
8156 	}
8157     }
8158 
8159   inst.instruction |= range;
8160   end_of_line (str);
8161 }
8162 
8163 static void
do_swi(str)8164 do_swi (str)
8165      char * str;
8166 {
8167   skip_whitespace (str);
8168 
8169   /* Allow optional leading '#'.  */
8170   if (is_immediate_prefix (*str))
8171     str++;
8172 
8173   if (my_get_expression (& inst.reloc.exp, & str))
8174     return;
8175 
8176   inst.reloc.type = BFD_RELOC_ARM_SWI;
8177   inst.reloc.pc_rel = 0;
8178   end_of_line (str);
8179 }
8180 
8181 static void
do_swap(str)8182 do_swap (str)
8183      char * str;
8184 {
8185   int reg;
8186 
8187   skip_whitespace (str);
8188 
8189   if ((reg = reg_required_here (&str, 12)) == FAIL)
8190     return;
8191 
8192   if (reg == REG_PC)
8193     {
8194       inst.error = _("r15 not allowed in swap");
8195       return;
8196     }
8197 
8198   if (skip_past_comma (&str) == FAIL
8199       || (reg = reg_required_here (&str, 0)) == FAIL)
8200     {
8201       if (!inst.error)
8202 	inst.error = BAD_ARGS;
8203       return;
8204     }
8205 
8206   if (reg == REG_PC)
8207     {
8208       inst.error = _("r15 not allowed in swap");
8209       return;
8210     }
8211 
8212   if (skip_past_comma (&str) == FAIL
8213       || *str++ != '[')
8214     {
8215       inst.error = BAD_ARGS;
8216       return;
8217     }
8218 
8219   skip_whitespace (str);
8220 
8221   if ((reg = reg_required_here (&str, 16)) == FAIL)
8222     return;
8223 
8224   if (reg == REG_PC)
8225     {
8226       inst.error = BAD_PC;
8227       return;
8228     }
8229 
8230   skip_whitespace (str);
8231 
8232   if (*str++ != ']')
8233     {
8234       inst.error = _("missing ]");
8235       return;
8236     }
8237 
8238   end_of_line (str);
8239 }
8240 
8241 static void
do_branch(str)8242 do_branch (str)
8243      char * str;
8244 {
8245   if (my_get_expression (&inst.reloc.exp, &str))
8246     return;
8247 
8248 #ifdef OBJ_ELF
8249   {
8250     char * save_in;
8251 
8252     /* ScottB: February 5, 1998 - Check to see of PLT32 reloc
8253        required for the instruction.  */
8254 
8255     /* arm_parse_reloc () works on input_line_pointer.
8256        We actually want to parse the operands to the branch instruction
8257        passed in 'str'.  Save the input pointer and restore it later.  */
8258     save_in = input_line_pointer;
8259     input_line_pointer = str;
8260     if (inst.reloc.exp.X_op == O_symbol
8261 	&& *str == '('
8262 	&& arm_parse_reloc () == BFD_RELOC_ARM_PLT32)
8263       {
8264 	inst.reloc.type   = BFD_RELOC_ARM_PLT32;
8265 	inst.reloc.pc_rel = 0;
8266 	/* Modify str to point to after parsed operands, otherwise
8267 	   end_of_line() will complain about the (PLT) left in str.  */
8268 	str = input_line_pointer;
8269       }
8270     else
8271       {
8272 	inst.reloc.type   = BFD_RELOC_ARM_PCREL_BRANCH;
8273 	inst.reloc.pc_rel = 1;
8274       }
8275     input_line_pointer = save_in;
8276   }
8277 #else
8278   inst.reloc.type   = BFD_RELOC_ARM_PCREL_BRANCH;
8279   inst.reloc.pc_rel = 1;
8280 #endif /* OBJ_ELF  */
8281 
8282   end_of_line (str);
8283 }
8284 
8285 static void
do_bx(str)8286 do_bx (str)
8287      char * str;
8288 {
8289   int reg;
8290 
8291   skip_whitespace (str);
8292 
8293   if ((reg = reg_required_here (&str, 0)) == FAIL)
8294     {
8295       inst.error = BAD_ARGS;
8296       return;
8297     }
8298 
8299   /* Note - it is not illegal to do a "bx pc".  Useless, but not illegal.  */
8300   if (reg == REG_PC)
8301     as_tsktsk (_("use of r15 in bx in ARM mode is not really useful"));
8302 
8303   end_of_line (str);
8304 }
8305 
8306 static void
do_cdp(str)8307 do_cdp (str)
8308      char * str;
8309 {
8310   /* Co-processor data operation.
8311      Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>}  */
8312   skip_whitespace (str);
8313 
8314   if (co_proc_number (&str) == FAIL)
8315     {
8316       if (!inst.error)
8317 	inst.error = BAD_ARGS;
8318       return;
8319     }
8320 
8321   if (skip_past_comma (&str) == FAIL
8322       || cp_opc_expr (&str, 20,4) == FAIL)
8323     {
8324       if (!inst.error)
8325 	inst.error = BAD_ARGS;
8326       return;
8327     }
8328 
8329   if (skip_past_comma (&str) == FAIL
8330       || cp_reg_required_here (&str, 12) == FAIL)
8331     {
8332       if (!inst.error)
8333 	inst.error = BAD_ARGS;
8334       return;
8335     }
8336 
8337   if (skip_past_comma (&str) == FAIL
8338       || cp_reg_required_here (&str, 16) == FAIL)
8339     {
8340       if (!inst.error)
8341 	inst.error = BAD_ARGS;
8342       return;
8343     }
8344 
8345   if (skip_past_comma (&str) == FAIL
8346       || cp_reg_required_here (&str, 0) == FAIL)
8347     {
8348       if (!inst.error)
8349 	inst.error = BAD_ARGS;
8350       return;
8351     }
8352 
8353   if (skip_past_comma (&str) == SUCCESS)
8354     {
8355       if (cp_opc_expr (&str, 5, 3) == FAIL)
8356 	{
8357 	  if (!inst.error)
8358 	    inst.error = BAD_ARGS;
8359 	  return;
8360 	}
8361     }
8362 
8363   end_of_line (str);
8364 }
8365 
8366 static void
do_lstc(str)8367 do_lstc (str)
8368      char * str;
8369 {
8370   /* Co-processor register load/store.
8371      Format: <LDC|STC{cond}[L] CP#,CRd,<address>  */
8372 
8373   skip_whitespace (str);
8374 
8375   if (co_proc_number (&str) == FAIL)
8376     {
8377       if (!inst.error)
8378 	inst.error = BAD_ARGS;
8379       return;
8380     }
8381 
8382   if (skip_past_comma (&str) == FAIL
8383       || cp_reg_required_here (&str, 12) == FAIL)
8384     {
8385       if (!inst.error)
8386 	inst.error = BAD_ARGS;
8387       return;
8388     }
8389 
8390   if (skip_past_comma (&str) == FAIL
8391       || cp_address_required_here (&str, CP_WB_OK) == FAIL)
8392     {
8393       if (! inst.error)
8394 	inst.error = BAD_ARGS;
8395       return;
8396     }
8397 
8398   end_of_line (str);
8399 }
8400 
8401 static void
do_co_reg(str)8402 do_co_reg (str)
8403      char * str;
8404 {
8405   /* Co-processor register transfer.
8406      Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>}  */
8407 
8408   skip_whitespace (str);
8409 
8410   if (co_proc_number (&str) == FAIL)
8411     {
8412       if (!inst.error)
8413 	inst.error = BAD_ARGS;
8414       return;
8415     }
8416 
8417   if (skip_past_comma (&str) == FAIL
8418       || cp_opc_expr (&str, 21, 3) == FAIL)
8419     {
8420       if (!inst.error)
8421 	inst.error = BAD_ARGS;
8422       return;
8423     }
8424 
8425   if (skip_past_comma (&str) == FAIL
8426       || reg_required_here (&str, 12) == FAIL)
8427     {
8428       if (!inst.error)
8429 	inst.error = BAD_ARGS;
8430       return;
8431     }
8432 
8433   if (skip_past_comma (&str) == FAIL
8434       || cp_reg_required_here (&str, 16) == FAIL)
8435     {
8436       if (!inst.error)
8437 	inst.error = BAD_ARGS;
8438       return;
8439     }
8440 
8441   if (skip_past_comma (&str) == FAIL
8442       || cp_reg_required_here (&str, 0) == FAIL)
8443     {
8444       if (!inst.error)
8445 	inst.error = BAD_ARGS;
8446       return;
8447     }
8448 
8449   if (skip_past_comma (&str) == SUCCESS)
8450     {
8451       if (cp_opc_expr (&str, 5, 3) == FAIL)
8452 	{
8453 	  if (!inst.error)
8454 	    inst.error = BAD_ARGS;
8455 	  return;
8456 	}
8457     }
8458 
8459   end_of_line (str);
8460 }
8461 
8462 static void
do_fpa_ctrl(str)8463 do_fpa_ctrl (str)
8464      char * str;
8465 {
8466   /* FP control registers.
8467      Format: <WFS|RFS|WFC|RFC>{cond} Rn  */
8468 
8469   skip_whitespace (str);
8470 
8471   if (reg_required_here (&str, 12) == FAIL)
8472     {
8473       if (!inst.error)
8474 	inst.error = BAD_ARGS;
8475       return;
8476     }
8477 
8478   end_of_line (str);
8479 }
8480 
8481 static void
do_fpa_ldst(str)8482 do_fpa_ldst (str)
8483      char * str;
8484 {
8485   skip_whitespace (str);
8486 
8487   if (fp_reg_required_here (&str, 12) == FAIL)
8488     {
8489       if (!inst.error)
8490 	inst.error = BAD_ARGS;
8491       return;
8492     }
8493 
8494   if (skip_past_comma (&str) == FAIL
8495       || cp_address_required_here (&str, CP_WB_OK) == FAIL)
8496     {
8497       if (!inst.error)
8498 	inst.error = BAD_ARGS;
8499       return;
8500     }
8501 
8502   end_of_line (str);
8503 }
8504 
8505 static void
do_fpa_ldmstm(str)8506 do_fpa_ldmstm (str)
8507      char * str;
8508 {
8509   int num_regs;
8510 
8511   skip_whitespace (str);
8512 
8513   if (fp_reg_required_here (&str, 12) == FAIL)
8514     {
8515       if (! inst.error)
8516 	inst.error = BAD_ARGS;
8517       return;
8518     }
8519 
8520   /* Get Number of registers to transfer.  */
8521   if (skip_past_comma (&str) == FAIL
8522       || my_get_expression (&inst.reloc.exp, &str))
8523     {
8524       if (! inst.error)
8525 	inst.error = _("constant expression expected");
8526       return;
8527     }
8528 
8529   if (inst.reloc.exp.X_op != O_constant)
8530     {
8531       inst.error = _("constant value required for number of registers");
8532       return;
8533     }
8534 
8535   num_regs = inst.reloc.exp.X_add_number;
8536 
8537   if (num_regs < 1 || num_regs > 4)
8538     {
8539       inst.error = _("number of registers must be in the range [1:4]");
8540       return;
8541     }
8542 
8543   switch (num_regs)
8544     {
8545     case 1:
8546       inst.instruction |= CP_T_X;
8547       break;
8548     case 2:
8549       inst.instruction |= CP_T_Y;
8550       break;
8551     case 3:
8552       inst.instruction |= CP_T_Y | CP_T_X;
8553       break;
8554     case 4:
8555       break;
8556     default:
8557       abort ();
8558     }
8559 
8560   if (inst.instruction & (CP_T_Pre | CP_T_UD)) /* ea/fd format.  */
8561     {
8562       int reg;
8563       int write_back;
8564       int offset;
8565 
8566       /* The instruction specified "ea" or "fd", so we can only accept
8567 	 [Rn]{!}.  The instruction does not really support stacking or
8568 	 unstacking, so we have to emulate these by setting appropriate
8569 	 bits and offsets.  */
8570       if (skip_past_comma (&str) == FAIL
8571 	  || *str != '[')
8572 	{
8573 	  if (! inst.error)
8574 	    inst.error = BAD_ARGS;
8575 	  return;
8576 	}
8577 
8578       str++;
8579       skip_whitespace (str);
8580 
8581       if ((reg = reg_required_here (&str, 16)) == FAIL)
8582 	return;
8583 
8584       skip_whitespace (str);
8585 
8586       if (*str != ']')
8587 	{
8588 	  inst.error = BAD_ARGS;
8589 	  return;
8590 	}
8591 
8592       str++;
8593       if (*str == '!')
8594 	{
8595 	  write_back = 1;
8596 	  str++;
8597 	  if (reg == REG_PC)
8598 	    {
8599 	      inst.error =
8600 		_("r15 not allowed as base register with write-back");
8601 	      return;
8602 	    }
8603 	}
8604       else
8605 	write_back = 0;
8606 
8607       if (inst.instruction & CP_T_Pre)
8608 	{
8609 	  /* Pre-decrement.  */
8610 	  offset = 3 * num_regs;
8611 	  if (write_back)
8612 	    inst.instruction |= CP_T_WB;
8613 	}
8614       else
8615 	{
8616 	  /* Post-increment.  */
8617 	  if (write_back)
8618 	    {
8619 	      inst.instruction |= CP_T_WB;
8620 	      offset = 3 * num_regs;
8621 	    }
8622 	  else
8623 	    {
8624 	      /* No write-back, so convert this into a standard pre-increment
8625 		 instruction -- aesthetically more pleasing.  */
8626 	      inst.instruction |= CP_T_Pre | CP_T_UD;
8627 	      offset = 0;
8628 	    }
8629 	}
8630 
8631       inst.instruction |= offset;
8632     }
8633   else if (skip_past_comma (&str) == FAIL
8634 	   || cp_address_required_here (&str, CP_WB_OK) == FAIL)
8635     {
8636       if (! inst.error)
8637 	inst.error = BAD_ARGS;
8638       return;
8639     }
8640 
8641   end_of_line (str);
8642 }
8643 
8644 static void
do_fpa_dyadic(str)8645 do_fpa_dyadic (str)
8646      char * str;
8647 {
8648   skip_whitespace (str);
8649 
8650   if (fp_reg_required_here (&str, 12) == FAIL)
8651     {
8652       if (! inst.error)
8653 	inst.error = BAD_ARGS;
8654       return;
8655     }
8656 
8657   if (skip_past_comma (&str) == FAIL
8658       || fp_reg_required_here (&str, 16) == FAIL)
8659     {
8660       if (! inst.error)
8661 	inst.error = BAD_ARGS;
8662       return;
8663     }
8664 
8665   if (skip_past_comma (&str) == FAIL
8666       || fp_op2 (&str) == FAIL)
8667     {
8668       if (! inst.error)
8669 	inst.error = BAD_ARGS;
8670       return;
8671     }
8672 
8673   end_of_line (str);
8674 }
8675 
8676 static void
do_fpa_monadic(str)8677 do_fpa_monadic (str)
8678      char * str;
8679 {
8680   skip_whitespace (str);
8681 
8682   if (fp_reg_required_here (&str, 12) == FAIL)
8683     {
8684       if (! inst.error)
8685 	inst.error = BAD_ARGS;
8686       return;
8687     }
8688 
8689   if (skip_past_comma (&str) == FAIL
8690       || fp_op2 (&str) == FAIL)
8691     {
8692       if (! inst.error)
8693 	inst.error = BAD_ARGS;
8694       return;
8695     }
8696 
8697   end_of_line (str);
8698 }
8699 
8700 static void
do_fpa_cmp(str)8701 do_fpa_cmp (str)
8702      char * str;
8703 {
8704   skip_whitespace (str);
8705 
8706   if (fp_reg_required_here (&str, 16) == FAIL)
8707     {
8708       if (! inst.error)
8709 	inst.error = BAD_ARGS;
8710       return;
8711     }
8712 
8713   if (skip_past_comma (&str) == FAIL
8714       || fp_op2 (&str) == FAIL)
8715     {
8716       if (! inst.error)
8717 	inst.error = BAD_ARGS;
8718       return;
8719     }
8720 
8721   end_of_line (str);
8722 }
8723 
8724 static void
do_fpa_from_reg(str)8725 do_fpa_from_reg (str)
8726      char * str;
8727 {
8728   skip_whitespace (str);
8729 
8730   if (fp_reg_required_here (&str, 16) == FAIL)
8731     {
8732       if (! inst.error)
8733 	inst.error = BAD_ARGS;
8734       return;
8735     }
8736 
8737   if (skip_past_comma (&str) == FAIL
8738       || reg_required_here (&str, 12) == FAIL)
8739     {
8740       if (! inst.error)
8741 	inst.error = BAD_ARGS;
8742       return;
8743     }
8744 
8745   end_of_line (str);
8746 }
8747 
8748 static void
do_fpa_to_reg(str)8749 do_fpa_to_reg (str)
8750      char * str;
8751 {
8752   skip_whitespace (str);
8753 
8754   if (reg_required_here (&str, 12) == FAIL)
8755     return;
8756 
8757   if (skip_past_comma (&str) == FAIL
8758       || fp_reg_required_here (&str, 0) == FAIL)
8759     {
8760       if (! inst.error)
8761 	inst.error = BAD_ARGS;
8762       return;
8763     }
8764 
8765   end_of_line (str);
8766 }
8767 
8768 static int
vfp_sp_reg_required_here(str,pos)8769 vfp_sp_reg_required_here (str, pos)
8770      char **str;
8771      enum vfp_sp_reg_pos pos;
8772 {
8773   int    reg;
8774   char *start = *str;
8775 
8776   if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab)) != FAIL)
8777     {
8778       switch (pos)
8779 	{
8780 	case VFP_REG_Sd:
8781 	  inst.instruction |= ((reg >> 1) << 12) | ((reg & 1) << 22);
8782 	  break;
8783 
8784 	case VFP_REG_Sn:
8785 	  inst.instruction |= ((reg >> 1) << 16) | ((reg & 1) << 7);
8786 	  break;
8787 
8788 	case VFP_REG_Sm:
8789 	  inst.instruction |= ((reg >> 1) << 0) | ((reg & 1) << 5);
8790 	  break;
8791 
8792 	default:
8793 	  abort ();
8794 	}
8795       return reg;
8796     }
8797 
8798   /* In the few cases where we might be able to accept something else
8799      this error can be overridden.  */
8800   inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
8801 
8802   /* Restore the start point.  */
8803   *str = start;
8804   return FAIL;
8805 }
8806 
8807 static int
vfp_dp_reg_required_here(str,pos)8808 vfp_dp_reg_required_here (str, pos)
8809      char **str;
8810      enum vfp_dp_reg_pos pos;
8811 {
8812   int   reg;
8813   char *start = *str;
8814 
8815   if ((reg = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab)) != FAIL)
8816     {
8817       switch (pos)
8818 	{
8819 	case VFP_REG_Dd:
8820 	  inst.instruction |= reg << 12;
8821 	  break;
8822 
8823 	case VFP_REG_Dn:
8824 	  inst.instruction |= reg << 16;
8825 	  break;
8826 
8827 	case VFP_REG_Dm:
8828 	  inst.instruction |= reg << 0;
8829 	  break;
8830 
8831 	default:
8832 	  abort ();
8833 	}
8834       return reg;
8835     }
8836 
8837   /* In the few cases where we might be able to accept something else
8838      this error can be overridden.  */
8839   inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
8840 
8841   /* Restore the start point.  */
8842   *str = start;
8843   return FAIL;
8844 }
8845 
8846 static void
do_vfp_sp_monadic(str)8847 do_vfp_sp_monadic (str)
8848      char *str;
8849 {
8850   skip_whitespace (str);
8851 
8852   if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8853     return;
8854 
8855   if (skip_past_comma (&str) == FAIL
8856       || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8857     {
8858       if (! inst.error)
8859 	inst.error = BAD_ARGS;
8860       return;
8861     }
8862 
8863   end_of_line (str);
8864 }
8865 
8866 static void
do_vfp_dp_monadic(str)8867 do_vfp_dp_monadic (str)
8868      char *str;
8869 {
8870   skip_whitespace (str);
8871 
8872   if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8873     return;
8874 
8875   if (skip_past_comma (&str) == FAIL
8876       || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8877     {
8878       if (! inst.error)
8879 	inst.error = BAD_ARGS;
8880       return;
8881     }
8882 
8883   end_of_line (str);
8884 }
8885 
8886 static void
do_vfp_sp_dyadic(str)8887 do_vfp_sp_dyadic (str)
8888      char *str;
8889 {
8890   skip_whitespace (str);
8891 
8892   if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
8893     return;
8894 
8895   if (skip_past_comma (&str) == FAIL
8896       || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL
8897       || skip_past_comma (&str) == FAIL
8898       || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
8899     {
8900       if (! inst.error)
8901 	inst.error = BAD_ARGS;
8902       return;
8903     }
8904 
8905   end_of_line (str);
8906 }
8907 
8908 static void
do_vfp_dp_dyadic(str)8909 do_vfp_dp_dyadic (str)
8910      char *str;
8911 {
8912   skip_whitespace (str);
8913 
8914   if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
8915     return;
8916 
8917   if (skip_past_comma (&str) == FAIL
8918       || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL
8919       || skip_past_comma (&str) == FAIL
8920       || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
8921     {
8922       if (! inst.error)
8923 	inst.error = BAD_ARGS;
8924       return;
8925     }
8926 
8927   end_of_line (str);
8928 }
8929 
8930 static void
do_vfp_reg_from_sp(str)8931 do_vfp_reg_from_sp (str)
8932      char *str;
8933 {
8934   skip_whitespace (str);
8935 
8936   if (reg_required_here (&str, 12) == FAIL)
8937     return;
8938 
8939   if (skip_past_comma (&str) == FAIL
8940       || vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8941     {
8942       if (! inst.error)
8943 	inst.error = BAD_ARGS;
8944       return;
8945     }
8946 
8947   end_of_line (str);
8948 }
8949 
8950 static void
do_vfp_reg2_from_sp2(str)8951 do_vfp_reg2_from_sp2 (str)
8952      char *str;
8953 {
8954   skip_whitespace (str);
8955 
8956   if (reg_required_here (&str, 12) == FAIL
8957       || skip_past_comma (&str) == FAIL
8958       || reg_required_here (&str, 16) == FAIL
8959       || skip_past_comma (&str) == FAIL)
8960     {
8961       if (! inst.error)
8962 	inst.error = BAD_ARGS;
8963       return;
8964     }
8965 
8966   /* We require exactly two consecutive SP registers.  */
8967   if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
8968     {
8969       if (! inst.error)
8970 	inst.error = _("only two consecutive VFP SP registers allowed here");
8971     }
8972 
8973   end_of_line (str);
8974 }
8975 
8976 static void
do_vfp_sp_from_reg(str)8977 do_vfp_sp_from_reg (str)
8978      char *str;
8979 {
8980   skip_whitespace (str);
8981 
8982   if (vfp_sp_reg_required_here (&str, VFP_REG_Sn) == FAIL)
8983     return;
8984 
8985   if (skip_past_comma (&str) == FAIL
8986       || reg_required_here (&str, 12) == FAIL)
8987     {
8988       if (! inst.error)
8989 	inst.error = BAD_ARGS;
8990       return;
8991     }
8992 
8993   end_of_line (str);
8994 }
8995 
8996 static void
do_vfp_sp2_from_reg2(str)8997 do_vfp_sp2_from_reg2 (str)
8998      char *str;
8999 {
9000   skip_whitespace (str);
9001 
9002   /* We require exactly two consecutive SP registers.  */
9003   if (vfp_sp_reg_list (&str, VFP_REG_Sm) != 2)
9004     {
9005       if (! inst.error)
9006 	inst.error = _("only two consecutive VFP SP registers allowed here");
9007     }
9008 
9009   if (skip_past_comma (&str) == FAIL
9010       || reg_required_here (&str, 12) == FAIL
9011       || skip_past_comma (&str) == FAIL
9012       || reg_required_here (&str, 16) == FAIL)
9013     {
9014       if (! inst.error)
9015 	inst.error = BAD_ARGS;
9016       return;
9017     }
9018 
9019   end_of_line (str);
9020 }
9021 
9022 static void
do_vfp_reg_from_dp(str)9023 do_vfp_reg_from_dp (str)
9024      char *str;
9025 {
9026   skip_whitespace (str);
9027 
9028   if (reg_required_here (&str, 12) == FAIL)
9029     return;
9030 
9031   if (skip_past_comma (&str) == FAIL
9032       || vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
9033     {
9034       if (! inst.error)
9035 	inst.error = BAD_ARGS;
9036       return;
9037     }
9038 
9039   end_of_line (str);
9040 }
9041 
9042 static void
do_vfp_reg2_from_dp(str)9043 do_vfp_reg2_from_dp (str)
9044      char *str;
9045 {
9046   skip_whitespace (str);
9047 
9048   if (reg_required_here (&str, 12) == FAIL)
9049     return;
9050 
9051   if (skip_past_comma (&str) == FAIL
9052       || reg_required_here (&str, 16) == FAIL
9053       || skip_past_comma (&str) == FAIL
9054       || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9055     {
9056       if (! inst.error)
9057 	inst.error = BAD_ARGS;
9058       return;
9059     }
9060 
9061   end_of_line (str);
9062 }
9063 
9064 static void
do_vfp_dp_from_reg(str)9065 do_vfp_dp_from_reg (str)
9066      char *str;
9067 {
9068   skip_whitespace (str);
9069 
9070   if (vfp_dp_reg_required_here (&str, VFP_REG_Dn) == FAIL)
9071     return;
9072 
9073   if (skip_past_comma (&str) == FAIL
9074       || reg_required_here (&str, 12) == FAIL)
9075     {
9076       if (! inst.error)
9077 	inst.error = BAD_ARGS;
9078       return;
9079     }
9080 
9081   end_of_line (str);
9082 }
9083 
9084 static void
do_vfp_dp_from_reg2(str)9085 do_vfp_dp_from_reg2 (str)
9086      char *str;
9087 {
9088   skip_whitespace (str);
9089 
9090   if (vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9091     return;
9092 
9093   if (skip_past_comma (&str) == FAIL
9094       || reg_required_here (&str, 12) == FAIL
9095       || skip_past_comma (&str) == FAIL
9096       || reg_required_here (&str, 16) == FAIL)
9097     {
9098       if (! inst.error)
9099 	inst.error = BAD_ARGS;
9100       return;
9101     }
9102 
9103   end_of_line (str);
9104 }
9105 
9106 static const struct vfp_reg *
vfp_psr_parse(str)9107 vfp_psr_parse (str)
9108      char **str;
9109 {
9110   char *start = *str;
9111   char  c;
9112   char *p;
9113   const struct vfp_reg *vreg;
9114 
9115   p = start;
9116 
9117   /* Find the end of the current token.  */
9118   do
9119     {
9120       c = *p++;
9121     }
9122   while (ISALPHA (c));
9123 
9124   /* Mark it.  */
9125   *--p = 0;
9126 
9127   for (vreg = vfp_regs + 0;
9128        vreg < vfp_regs + sizeof (vfp_regs) / sizeof (struct vfp_reg);
9129        vreg++)
9130     {
9131       if (strcmp (start, vreg->name) == 0)
9132 	{
9133 	  *p = c;
9134 	  *str = p;
9135 	  return vreg;
9136 	}
9137     }
9138 
9139   *p = c;
9140   return NULL;
9141 }
9142 
9143 static int
vfp_psr_required_here(str)9144 vfp_psr_required_here (str)
9145      char **str;
9146 {
9147   char *start = *str;
9148   const struct vfp_reg *vreg;
9149 
9150   vreg = vfp_psr_parse (str);
9151 
9152   if (vreg)
9153     {
9154       inst.instruction |= vreg->regno;
9155       return SUCCESS;
9156     }
9157 
9158   inst.error = _("VFP system register expected");
9159 
9160   *str = start;
9161   return FAIL;
9162 }
9163 
9164 static void
do_vfp_reg_from_ctrl(str)9165 do_vfp_reg_from_ctrl (str)
9166      char *str;
9167 {
9168   skip_whitespace (str);
9169 
9170   if (reg_required_here (&str, 12) == FAIL)
9171     return;
9172 
9173   if (skip_past_comma (&str) == FAIL
9174       || vfp_psr_required_here (&str) == FAIL)
9175     {
9176       if (! inst.error)
9177 	inst.error = BAD_ARGS;
9178       return;
9179     }
9180 
9181   end_of_line (str);
9182 }
9183 
9184 static void
do_vfp_ctrl_from_reg(str)9185 do_vfp_ctrl_from_reg (str)
9186      char *str;
9187 {
9188   skip_whitespace (str);
9189 
9190   if (vfp_psr_required_here (&str) == FAIL)
9191     return;
9192 
9193   if (skip_past_comma (&str) == FAIL
9194       || reg_required_here (&str, 12) == FAIL)
9195     {
9196       if (! inst.error)
9197 	inst.error = BAD_ARGS;
9198       return;
9199     }
9200 
9201   end_of_line (str);
9202 }
9203 
9204 static void
do_vfp_sp_ldst(str)9205 do_vfp_sp_ldst (str)
9206      char *str;
9207 {
9208   skip_whitespace (str);
9209 
9210   if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9211     {
9212       if (!inst.error)
9213 	inst.error = BAD_ARGS;
9214       return;
9215     }
9216 
9217   if (skip_past_comma (&str) == FAIL
9218       || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9219     {
9220       if (!inst.error)
9221 	inst.error = BAD_ARGS;
9222       return;
9223     }
9224 
9225   end_of_line (str);
9226 }
9227 
9228 static void
do_vfp_dp_ldst(str)9229 do_vfp_dp_ldst (str)
9230      char *str;
9231 {
9232   skip_whitespace (str);
9233 
9234   if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9235     {
9236       if (!inst.error)
9237 	inst.error = BAD_ARGS;
9238       return;
9239     }
9240 
9241   if (skip_past_comma (&str) == FAIL
9242       || cp_address_required_here (&str, CP_NO_WB) == FAIL)
9243     {
9244       if (!inst.error)
9245 	inst.error = BAD_ARGS;
9246       return;
9247     }
9248 
9249   end_of_line (str);
9250 }
9251 
9252 /* Parse and encode a VFP SP register list, storing the initial
9253    register in position POS and returning the range as the result.  If
9254    the string is invalid return FAIL (an invalid range).  */
9255 static long
vfp_sp_reg_list(str,pos)9256 vfp_sp_reg_list (str, pos)
9257      char **str;
9258      enum vfp_sp_reg_pos pos;
9259 {
9260   long range = 0;
9261   int base_reg = 0;
9262   int new_base;
9263   long base_bits = 0;
9264   int count = 0;
9265   long tempinst;
9266   unsigned long mask = 0;
9267   int warned = 0;
9268 
9269   if (**str != '{')
9270     return FAIL;
9271 
9272   (*str)++;
9273   skip_whitespace (*str);
9274 
9275   tempinst = inst.instruction;
9276 
9277   do
9278     {
9279       inst.instruction = 0;
9280 
9281       if ((new_base = vfp_sp_reg_required_here (str, pos)) == FAIL)
9282 	return FAIL;
9283 
9284       if (count == 0 || base_reg > new_base)
9285 	{
9286 	  base_reg = new_base;
9287 	  base_bits = inst.instruction;
9288 	}
9289 
9290       if (mask & (1 << new_base))
9291 	{
9292 	  inst.error = _("invalid register list");
9293 	  return FAIL;
9294 	}
9295 
9296       if ((mask >> new_base) != 0 && ! warned)
9297 	{
9298 	  as_tsktsk (_("register list not in ascending order"));
9299 	  warned = 1;
9300 	}
9301 
9302       mask |= 1 << new_base;
9303       count++;
9304 
9305       skip_whitespace (*str);
9306 
9307       if (**str == '-') /* We have the start of a range expression */
9308 	{
9309 	  int high_range;
9310 
9311 	  (*str)++;
9312 
9313 	  if ((high_range
9314 	       = arm_reg_parse (str, all_reg_maps[REG_TYPE_SN].htab))
9315 	      == FAIL)
9316 	    {
9317 	      inst.error = _(all_reg_maps[REG_TYPE_SN].expected);
9318 	      return FAIL;
9319 	    }
9320 
9321 	  if (high_range <= new_base)
9322 	    {
9323 	      inst.error = _("register range not in ascending order");
9324 	      return FAIL;
9325 	    }
9326 
9327 	  for (new_base++; new_base <= high_range; new_base++)
9328 	    {
9329 	      if (mask & (1 << new_base))
9330 		{
9331 		  inst.error = _("invalid register list");
9332 		  return FAIL;
9333 		}
9334 
9335 	      mask |= 1 << new_base;
9336 	      count++;
9337 	    }
9338 	}
9339     }
9340   while (skip_past_comma (str) != FAIL);
9341 
9342   if (**str != '}')
9343     {
9344       inst.error = _("invalid register list");
9345       return FAIL;
9346     }
9347 
9348   (*str)++;
9349 
9350   range = count;
9351 
9352   /* Sanity check -- should have raised a parse error above.  */
9353   if (count == 0 || count > 32)
9354     abort ();
9355 
9356   /* Final test -- the registers must be consecutive.  */
9357   while (count--)
9358     {
9359       if ((mask & (1 << base_reg++)) == 0)
9360 	{
9361 	  inst.error = _("non-contiguous register range");
9362 	  return FAIL;
9363 	}
9364     }
9365 
9366   inst.instruction = tempinst | base_bits;
9367   return range;
9368 }
9369 
9370 static long
vfp_dp_reg_list(str)9371 vfp_dp_reg_list (str)
9372      char **str;
9373 {
9374   long range = 0;
9375   int base_reg = 0;
9376   int new_base;
9377   int count = 0;
9378   long tempinst;
9379   unsigned long mask = 0;
9380   int warned = 0;
9381 
9382   if (**str != '{')
9383     return FAIL;
9384 
9385   (*str)++;
9386   skip_whitespace (*str);
9387 
9388   tempinst = inst.instruction;
9389 
9390   do
9391     {
9392       inst.instruction = 0;
9393 
9394       if ((new_base = vfp_dp_reg_required_here (str, VFP_REG_Dd)) == FAIL)
9395 	return FAIL;
9396 
9397       if (count == 0 || base_reg > new_base)
9398 	{
9399 	  base_reg = new_base;
9400 	  range = inst.instruction;
9401 	}
9402 
9403       if (mask & (1 << new_base))
9404 	{
9405 	  inst.error = _("invalid register list");
9406 	  return FAIL;
9407 	}
9408 
9409       if ((mask >> new_base) != 0 && ! warned)
9410 	{
9411 	  as_tsktsk (_("register list not in ascending order"));
9412 	  warned = 1;
9413 	}
9414 
9415       mask |= 1 << new_base;
9416       count++;
9417 
9418       skip_whitespace (*str);
9419 
9420       if (**str == '-') /* We have the start of a range expression */
9421 	{
9422 	  int high_range;
9423 
9424 	  (*str)++;
9425 
9426 	  if ((high_range
9427 	       = arm_reg_parse (str, all_reg_maps[REG_TYPE_DN].htab))
9428 	      == FAIL)
9429 	    {
9430 	      inst.error = _(all_reg_maps[REG_TYPE_DN].expected);
9431 	      return FAIL;
9432 	    }
9433 
9434 	  if (high_range <= new_base)
9435 	    {
9436 	      inst.error = _("register range not in ascending order");
9437 	      return FAIL;
9438 	    }
9439 
9440 	  for (new_base++; new_base <= high_range; new_base++)
9441 	    {
9442 	      if (mask & (1 << new_base))
9443 		{
9444 		  inst.error = _("invalid register list");
9445 		  return FAIL;
9446 		}
9447 
9448 	      mask |= 1 << new_base;
9449 	      count++;
9450 	    }
9451 	}
9452     }
9453   while (skip_past_comma (str) != FAIL);
9454 
9455   if (**str != '}')
9456     {
9457       inst.error = _("invalid register list");
9458       return FAIL;
9459     }
9460 
9461   (*str)++;
9462 
9463   range |= 2 * count;
9464 
9465   /* Sanity check -- should have raised a parse error above.  */
9466   if (count == 0 || count > 16)
9467     abort ();
9468 
9469   /* Final test -- the registers must be consecutive.  */
9470   while (count--)
9471     {
9472       if ((mask & (1 << base_reg++)) == 0)
9473 	{
9474 	  inst.error = _("non-contiguous register range");
9475 	  return FAIL;
9476 	}
9477     }
9478 
9479   inst.instruction = tempinst;
9480   return range;
9481 }
9482 
9483 static void
vfp_sp_ldstm(str,ldstm_type)9484 vfp_sp_ldstm (str, ldstm_type)
9485      char *str;
9486      enum vfp_ldstm_type ldstm_type;
9487 {
9488   long range;
9489 
9490   skip_whitespace (str);
9491 
9492   if (reg_required_here (&str, 16) == FAIL)
9493     return;
9494 
9495   skip_whitespace (str);
9496 
9497   if (*str == '!')
9498     {
9499       inst.instruction |= WRITE_BACK;
9500       str++;
9501     }
9502   else if (ldstm_type != VFP_LDSTMIA)
9503     {
9504       inst.error = _("this addressing mode requires base-register writeback");
9505       return;
9506     }
9507 
9508   if (skip_past_comma (&str) == FAIL
9509       || (range = vfp_sp_reg_list (&str, VFP_REG_Sd)) == FAIL)
9510     {
9511       if (!inst.error)
9512 	inst.error = BAD_ARGS;
9513       return;
9514     }
9515 
9516   inst.instruction |= range;
9517   end_of_line (str);
9518 }
9519 
9520 static void
vfp_dp_ldstm(str,ldstm_type)9521 vfp_dp_ldstm (str, ldstm_type)
9522      char *str;
9523      enum vfp_ldstm_type ldstm_type;
9524 {
9525   long range;
9526 
9527   skip_whitespace (str);
9528 
9529   if (reg_required_here (&str, 16) == FAIL)
9530     return;
9531 
9532   skip_whitespace (str);
9533 
9534   if (*str == '!')
9535     {
9536       inst.instruction |= WRITE_BACK;
9537       str++;
9538     }
9539   else if (ldstm_type != VFP_LDSTMIA && ldstm_type != VFP_LDSTMIAX)
9540     {
9541       inst.error = _("this addressing mode requires base-register writeback");
9542       return;
9543     }
9544 
9545   if (skip_past_comma (&str) == FAIL
9546       || (range = vfp_dp_reg_list (&str)) == FAIL)
9547     {
9548       if (!inst.error)
9549 	inst.error = BAD_ARGS;
9550       return;
9551     }
9552 
9553   if (ldstm_type == VFP_LDSTMIAX || ldstm_type == VFP_LDSTMDBX)
9554     range += 1;
9555 
9556   inst.instruction |= range;
9557   end_of_line (str);
9558 }
9559 
9560 static void
do_vfp_sp_ldstmia(str)9561 do_vfp_sp_ldstmia (str)
9562      char *str;
9563 {
9564   vfp_sp_ldstm (str, VFP_LDSTMIA);
9565 }
9566 
9567 static void
do_vfp_sp_ldstmdb(str)9568 do_vfp_sp_ldstmdb (str)
9569      char *str;
9570 {
9571   vfp_sp_ldstm (str, VFP_LDSTMDB);
9572 }
9573 
9574 static void
do_vfp_dp_ldstmia(str)9575 do_vfp_dp_ldstmia (str)
9576      char *str;
9577 {
9578   vfp_dp_ldstm (str, VFP_LDSTMIA);
9579 }
9580 
9581 static void
do_vfp_dp_ldstmdb(str)9582 do_vfp_dp_ldstmdb (str)
9583      char *str;
9584 {
9585   vfp_dp_ldstm (str, VFP_LDSTMDB);
9586 }
9587 
9588 static void
do_vfp_xp_ldstmia(str)9589 do_vfp_xp_ldstmia (str)
9590      char *str;
9591 {
9592   vfp_dp_ldstm (str, VFP_LDSTMIAX);
9593 }
9594 
9595 static void
do_vfp_xp_ldstmdb(str)9596 do_vfp_xp_ldstmdb (str)
9597      char *str;
9598 {
9599   vfp_dp_ldstm (str, VFP_LDSTMDBX);
9600 }
9601 
9602 static void
do_vfp_sp_compare_z(str)9603 do_vfp_sp_compare_z (str)
9604      char *str;
9605 {
9606   skip_whitespace (str);
9607 
9608   if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9609     {
9610       if (!inst.error)
9611 	inst.error = BAD_ARGS;
9612       return;
9613     }
9614 
9615   end_of_line (str);
9616 }
9617 
9618 static void
do_vfp_dp_compare_z(str)9619 do_vfp_dp_compare_z (str)
9620      char *str;
9621 {
9622   skip_whitespace (str);
9623 
9624   if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9625     {
9626       if (!inst.error)
9627 	inst.error = BAD_ARGS;
9628       return;
9629     }
9630 
9631   end_of_line (str);
9632 }
9633 
9634 static void
do_vfp_dp_sp_cvt(str)9635 do_vfp_dp_sp_cvt (str)
9636      char *str;
9637 {
9638   skip_whitespace (str);
9639 
9640   if (vfp_dp_reg_required_here (&str, VFP_REG_Dd) == FAIL)
9641     return;
9642 
9643   if (skip_past_comma (&str) == FAIL
9644       || vfp_sp_reg_required_here (&str, VFP_REG_Sm) == FAIL)
9645     {
9646       if (! inst.error)
9647 	inst.error = BAD_ARGS;
9648       return;
9649     }
9650 
9651   end_of_line (str);
9652 }
9653 
9654 static void
do_vfp_sp_dp_cvt(str)9655 do_vfp_sp_dp_cvt (str)
9656      char *str;
9657 {
9658   skip_whitespace (str);
9659 
9660   if (vfp_sp_reg_required_here (&str, VFP_REG_Sd) == FAIL)
9661     return;
9662 
9663   if (skip_past_comma (&str) == FAIL
9664       || vfp_dp_reg_required_here (&str, VFP_REG_Dm) == FAIL)
9665     {
9666       if (! inst.error)
9667 	inst.error = BAD_ARGS;
9668       return;
9669     }
9670 
9671   end_of_line (str);
9672 }
9673 
9674 /* Thumb specific routines.  */
9675 
9676 /* Parse and validate that a register is of the right form, this saves
9677    repeated checking of this information in many similar cases.
9678    Unlike the 32-bit case we do not insert the register into the opcode
9679    here, since the position is often unknown until the full instruction
9680    has been parsed.  */
9681 
9682 static int
thumb_reg(strp,hi_lo)9683 thumb_reg (strp, hi_lo)
9684      char ** strp;
9685      int     hi_lo;
9686 {
9687   int reg;
9688 
9689   if ((reg = reg_required_here (strp, -1)) == FAIL)
9690     return FAIL;
9691 
9692   switch (hi_lo)
9693     {
9694     case THUMB_REG_LO:
9695       if (reg > 7)
9696 	{
9697 	  inst.error = _("lo register required");
9698 	  return FAIL;
9699 	}
9700       break;
9701 
9702     case THUMB_REG_HI:
9703       if (reg < 8)
9704 	{
9705 	  inst.error = _("hi register required");
9706 	  return FAIL;
9707 	}
9708       break;
9709 
9710     default:
9711       break;
9712     }
9713 
9714   return reg;
9715 }
9716 
9717 /* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
9718    was SUB.  */
9719 
9720 static void
thumb_add_sub(str,subtract)9721 thumb_add_sub (str, subtract)
9722      char * str;
9723      int    subtract;
9724 {
9725   int Rd, Rs, Rn = FAIL;
9726 
9727   skip_whitespace (str);
9728 
9729   if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
9730       || skip_past_comma (&str) == FAIL)
9731     {
9732       if (! inst.error)
9733 	inst.error = BAD_ARGS;
9734       return;
9735     }
9736 
9737   if (is_immediate_prefix (*str))
9738     {
9739       Rs = Rd;
9740       str++;
9741       if (my_get_expression (&inst.reloc.exp, &str))
9742 	return;
9743     }
9744   else
9745     {
9746       if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9747 	return;
9748 
9749       if (skip_past_comma (&str) == FAIL)
9750 	{
9751 	  /* Two operand format, shuffle the registers
9752 	     and pretend there are 3.  */
9753 	  Rn = Rs;
9754 	  Rs = Rd;
9755 	}
9756       else if (is_immediate_prefix (*str))
9757 	{
9758 	  str++;
9759 	  if (my_get_expression (&inst.reloc.exp, &str))
9760 	    return;
9761 	}
9762       else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
9763 	return;
9764     }
9765 
9766   /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9767      for the latter case, EXPR contains the immediate that was found.  */
9768   if (Rn != FAIL)
9769     {
9770       /* All register format.  */
9771       if (Rd > 7 || Rs > 7 || Rn > 7)
9772 	{
9773 	  if (Rs != Rd)
9774 	    {
9775 	      inst.error = _("dest and source1 must be the same register");
9776 	      return;
9777 	    }
9778 
9779 	  /* Can't do this for SUB.  */
9780 	  if (subtract)
9781 	    {
9782 	      inst.error = _("subtract valid only on lo regs");
9783 	      return;
9784 	    }
9785 
9786 	  inst.instruction = (T_OPCODE_ADD_HI
9787 			      | (Rd > 7 ? THUMB_H1 : 0)
9788 			      | (Rn > 7 ? THUMB_H2 : 0));
9789 	  inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
9790 	}
9791       else
9792 	{
9793 	  inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
9794 	  inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
9795 	}
9796     }
9797   else
9798     {
9799       /* Immediate expression, now things start to get nasty.  */
9800 
9801       /* First deal with HI regs, only very restricted cases allowed:
9802 	 Adjusting SP, and using PC or SP to get an address.  */
9803       if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
9804 	  || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
9805 	{
9806 	  inst.error = _("invalid Hi register with immediate");
9807 	  return;
9808 	}
9809 
9810       if (inst.reloc.exp.X_op != O_constant)
9811 	{
9812 	  /* Value isn't known yet, all we can do is store all the fragments
9813 	     we know about in the instruction and let the reloc hacking
9814 	     work it all out.  */
9815 	  inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
9816 	  inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
9817 	}
9818       else
9819 	{
9820 	  int offset = inst.reloc.exp.X_add_number;
9821 
9822 	  if (subtract)
9823 	    offset = - offset;
9824 
9825 	  if (offset < 0)
9826 	    {
9827 	      offset = - offset;
9828 	      subtract = 1;
9829 
9830 	      /* Quick check, in case offset is MIN_INT.  */
9831 	      if (offset < 0)
9832 		{
9833 		  inst.error = _("immediate value out of range");
9834 		  return;
9835 		}
9836 	    }
9837 	  /* Note - you cannot convert a subtract of 0 into an
9838 	     add of 0 because the carry flag is set differently.  */
9839 	  else if (offset > 0)
9840 	    subtract = 0;
9841 
9842 	  if (Rd == REG_SP)
9843 	    {
9844 	      if (offset & ~0x1fc)
9845 		{
9846 		  inst.error = _("invalid immediate value for stack adjust");
9847 		  return;
9848 		}
9849 	      inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
9850 	      inst.instruction |= offset >> 2;
9851 	    }
9852 	  else if (Rs == REG_PC || Rs == REG_SP)
9853 	    {
9854 	      if (subtract
9855 		  || (offset & ~0x3fc))
9856 		{
9857 		  inst.error = _("invalid immediate for address calculation");
9858 		  return;
9859 		}
9860 	      inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
9861 				  : T_OPCODE_ADD_SP);
9862 	      inst.instruction |= (Rd << 8) | (offset >> 2);
9863 	    }
9864 	  else if (Rs == Rd)
9865 	    {
9866 	      if (offset & ~0xff)
9867 		{
9868 		  inst.error = _("immediate value out of range");
9869 		  return;
9870 		}
9871 	      inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
9872 	      inst.instruction |= (Rd << 8) | offset;
9873 	    }
9874 	  else
9875 	    {
9876 	      if (offset & ~0x7)
9877 		{
9878 		  inst.error = _("immediate value out of range");
9879 		  return;
9880 		}
9881 	      inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
9882 	      inst.instruction |= Rd | (Rs << 3) | (offset << 6);
9883 	    }
9884 	}
9885     }
9886 
9887   end_of_line (str);
9888 }
9889 
9890 static void
thumb_shift(str,shift)9891 thumb_shift (str, shift)
9892      char * str;
9893      int    shift;
9894 {
9895   int Rd, Rs, Rn = FAIL;
9896 
9897   skip_whitespace (str);
9898 
9899   if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
9900       || skip_past_comma (&str) == FAIL)
9901     {
9902       if (! inst.error)
9903 	inst.error = BAD_ARGS;
9904       return;
9905     }
9906 
9907   if (is_immediate_prefix (*str))
9908     {
9909       /* Two operand immediate format, set Rs to Rd.  */
9910       Rs = Rd;
9911       str ++;
9912       if (my_get_expression (&inst.reloc.exp, &str))
9913 	return;
9914     }
9915   else
9916     {
9917       if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9918 	return;
9919 
9920       if (skip_past_comma (&str) == FAIL)
9921 	{
9922 	  /* Two operand format, shuffle the registers
9923 	     and pretend there are 3.  */
9924 	  Rn = Rs;
9925 	  Rs = Rd;
9926 	}
9927       else if (is_immediate_prefix (*str))
9928 	{
9929 	  str++;
9930 	  if (my_get_expression (&inst.reloc.exp, &str))
9931 	    return;
9932 	}
9933       else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
9934 	return;
9935     }
9936 
9937   /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
9938      for the latter case, EXPR contains the immediate that was found.  */
9939 
9940   if (Rn != FAIL)
9941     {
9942       if (Rs != Rd)
9943 	{
9944 	  inst.error = _("source1 and dest must be same register");
9945 	  return;
9946 	}
9947 
9948       switch (shift)
9949 	{
9950 	case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
9951 	case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
9952 	case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
9953 	}
9954 
9955       inst.instruction |= Rd | (Rn << 3);
9956     }
9957   else
9958     {
9959       switch (shift)
9960 	{
9961 	case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
9962 	case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
9963 	case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
9964 	}
9965 
9966       if (inst.reloc.exp.X_op != O_constant)
9967 	{
9968 	  /* Value isn't known yet, create a dummy reloc and let reloc
9969 	     hacking fix it up.  */
9970 	  inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
9971 	}
9972       else
9973 	{
9974 	  unsigned shift_value = inst.reloc.exp.X_add_number;
9975 
9976 	  if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
9977 	    {
9978 	      inst.error = _("invalid immediate for shift");
9979 	      return;
9980 	    }
9981 
9982 	  /* Shifts of zero are handled by converting to LSL.  */
9983 	  if (shift_value == 0)
9984 	    inst.instruction = T_OPCODE_LSL_I;
9985 
9986 	  /* Shifts of 32 are encoded as a shift of zero.  */
9987 	  if (shift_value == 32)
9988 	    shift_value = 0;
9989 
9990 	  inst.instruction |= shift_value << 6;
9991 	}
9992 
9993       inst.instruction |= Rd | (Rs << 3);
9994     }
9995 
9996   end_of_line (str);
9997 }
9998 
9999 static void
thumb_mov_compare(str,move)10000 thumb_mov_compare (str, move)
10001      char * str;
10002      int    move;
10003 {
10004   int Rd, Rs = FAIL;
10005 
10006   skip_whitespace (str);
10007 
10008   if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
10009       || skip_past_comma (&str) == FAIL)
10010     {
10011       if (! inst.error)
10012 	inst.error = BAD_ARGS;
10013       return;
10014     }
10015 
10016   if (move != THUMB_CPY && is_immediate_prefix (*str))
10017     {
10018       str++;
10019       if (my_get_expression (&inst.reloc.exp, &str))
10020 	return;
10021     }
10022   else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10023     return;
10024 
10025   if (Rs != FAIL)
10026     {
10027       if (move != THUMB_CPY && Rs < 8 && Rd < 8)
10028 	{
10029 	  if (move == THUMB_MOVE)
10030 	    /* A move of two lowregs is encoded as ADD Rd, Rs, #0
10031 	       since a MOV instruction produces unpredictable results.  */
10032 	    inst.instruction = T_OPCODE_ADD_I3;
10033 	  else
10034 	    inst.instruction = T_OPCODE_CMP_LR;
10035 	  inst.instruction |= Rd | (Rs << 3);
10036 	}
10037       else
10038 	{
10039 	  if (move == THUMB_MOVE)
10040 	    inst.instruction = T_OPCODE_MOV_HR;
10041 	  else if (move != THUMB_CPY)
10042 	    inst.instruction = T_OPCODE_CMP_HR;
10043 
10044 	  if (Rd > 7)
10045 	    inst.instruction |= THUMB_H1;
10046 
10047 	  if (Rs > 7)
10048 	    inst.instruction |= THUMB_H2;
10049 
10050 	  inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
10051 	}
10052     }
10053   else
10054     {
10055       if (Rd > 7)
10056 	{
10057 	  inst.error = _("only lo regs allowed with immediate");
10058 	  return;
10059 	}
10060 
10061       if (move == THUMB_MOVE)
10062 	inst.instruction = T_OPCODE_MOV_I8;
10063       else
10064 	inst.instruction = T_OPCODE_CMP_I8;
10065 
10066       inst.instruction |= Rd << 8;
10067 
10068       if (inst.reloc.exp.X_op != O_constant)
10069 	inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
10070       else
10071 	{
10072 	  unsigned value = inst.reloc.exp.X_add_number;
10073 
10074 	  if (value > 255)
10075 	    {
10076 	      inst.error = _("invalid immediate");
10077 	      return;
10078 	    }
10079 
10080 	  inst.instruction |= value;
10081 	}
10082     }
10083 
10084   end_of_line (str);
10085 }
10086 
10087 static void
thumb_load_store(str,load_store,size)10088 thumb_load_store (str, load_store, size)
10089      char * str;
10090      int    load_store;
10091      int    size;
10092 {
10093   int Rd, Rb, Ro = FAIL;
10094 
10095   skip_whitespace (str);
10096 
10097   if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10098       || skip_past_comma (&str) == FAIL)
10099     {
10100       if (! inst.error)
10101 	inst.error = BAD_ARGS;
10102       return;
10103     }
10104 
10105   if (*str == '[')
10106     {
10107       str++;
10108       if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
10109 	return;
10110 
10111       if (skip_past_comma (&str) != FAIL)
10112 	{
10113 	  if (is_immediate_prefix (*str))
10114 	    {
10115 	      str++;
10116 	      if (my_get_expression (&inst.reloc.exp, &str))
10117 		return;
10118 	    }
10119 	  else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10120 	    return;
10121 	}
10122       else
10123 	{
10124 	  inst.reloc.exp.X_op = O_constant;
10125 	  inst.reloc.exp.X_add_number = 0;
10126 	}
10127 
10128       if (*str != ']')
10129 	{
10130 	  inst.error = _("expected ']'");
10131 	  return;
10132 	}
10133       str++;
10134     }
10135   else if (*str == '=')
10136     {
10137       if (load_store != THUMB_LOAD)
10138 	{
10139 	  inst.error = _("invalid pseudo operation");
10140 	  return;
10141 	}
10142 
10143       /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op.  */
10144       str++;
10145 
10146       skip_whitespace (str);
10147 
10148       if (my_get_expression (& inst.reloc.exp, & str))
10149 	return;
10150 
10151       end_of_line (str);
10152 
10153       if (   inst.reloc.exp.X_op != O_constant
10154 	  && inst.reloc.exp.X_op != O_symbol)
10155 	{
10156 	  inst.error = "Constant expression expected";
10157 	  return;
10158 	}
10159 
10160       if (inst.reloc.exp.X_op == O_constant
10161 	  && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
10162 	{
10163 	  /* This can be done with a mov instruction.  */
10164 
10165 	  inst.instruction  = T_OPCODE_MOV_I8 | (Rd << 8);
10166 	  inst.instruction |= inst.reloc.exp.X_add_number;
10167 	  return;
10168 	}
10169 
10170       /* Insert into literal pool.  */
10171       if (add_to_lit_pool () == FAIL)
10172 	{
10173 	  if (!inst.error)
10174 	    inst.error = "literal pool insertion failed";
10175 	  return;
10176 	}
10177 
10178       inst.reloc.type   = BFD_RELOC_ARM_THUMB_OFFSET;
10179       inst.reloc.pc_rel = 1;
10180       inst.instruction  = T_OPCODE_LDR_PC | (Rd << 8);
10181       /* Adjust ARM pipeline offset to Thumb.  */
10182       inst.reloc.exp.X_add_number += 4;
10183 
10184       return;
10185     }
10186   else
10187     {
10188       if (my_get_expression (&inst.reloc.exp, &str))
10189 	return;
10190 
10191       inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
10192       inst.reloc.pc_rel = 1;
10193       inst.reloc.exp.X_add_number -= 4; /* Pipeline offset.  */
10194       inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10195       end_of_line (str);
10196       return;
10197     }
10198 
10199   if (Rb == REG_PC || Rb == REG_SP)
10200     {
10201       if (size != THUMB_WORD)
10202 	{
10203 	  inst.error = _("byte or halfword not valid for base register");
10204 	  return;
10205 	}
10206       else if (Rb == REG_PC && load_store != THUMB_LOAD)
10207 	{
10208 	  inst.error = _("r15 based store not allowed");
10209 	  return;
10210 	}
10211       else if (Ro != FAIL)
10212 	{
10213 	  inst.error = _("invalid base register for register offset");
10214 	  return;
10215 	}
10216 
10217       if (Rb == REG_PC)
10218 	inst.instruction = T_OPCODE_LDR_PC;
10219       else if (load_store == THUMB_LOAD)
10220 	inst.instruction = T_OPCODE_LDR_SP;
10221       else
10222 	inst.instruction = T_OPCODE_STR_SP;
10223 
10224       inst.instruction |= Rd << 8;
10225       if (inst.reloc.exp.X_op == O_constant)
10226 	{
10227 	  unsigned offset = inst.reloc.exp.X_add_number;
10228 
10229 	  if (offset & ~0x3fc)
10230 	    {
10231 	      inst.error = _("invalid offset");
10232 	      return;
10233 	    }
10234 
10235 	  inst.instruction |= offset >> 2;
10236 	}
10237       else
10238 	inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10239     }
10240   else if (Rb > 7)
10241     {
10242       inst.error = _("invalid base register in load/store");
10243       return;
10244     }
10245   else if (Ro == FAIL)
10246     {
10247       /* Immediate offset.  */
10248       if (size == THUMB_WORD)
10249 	inst.instruction = (load_store == THUMB_LOAD
10250 			    ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
10251       else if (size == THUMB_HALFWORD)
10252 	inst.instruction = (load_store == THUMB_LOAD
10253 			    ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
10254       else
10255 	inst.instruction = (load_store == THUMB_LOAD
10256 			    ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
10257 
10258       inst.instruction |= Rd | (Rb << 3);
10259 
10260       if (inst.reloc.exp.X_op == O_constant)
10261 	{
10262 	  unsigned offset = inst.reloc.exp.X_add_number;
10263 
10264 	  if (offset & ~(0x1f << size))
10265 	    {
10266 	      inst.error = _("invalid offset");
10267 	      return;
10268 	    }
10269 	  inst.instruction |= (offset >> size) << 6;
10270 	}
10271       else
10272 	inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
10273     }
10274   else
10275     {
10276       /* Register offset.  */
10277       if (size == THUMB_WORD)
10278 	inst.instruction = (load_store == THUMB_LOAD
10279 			    ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
10280       else if (size == THUMB_HALFWORD)
10281 	inst.instruction = (load_store == THUMB_LOAD
10282 			    ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
10283       else
10284 	inst.instruction = (load_store == THUMB_LOAD
10285 			    ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
10286 
10287       inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
10288     }
10289 
10290   end_of_line (str);
10291 }
10292 
10293 /* A register must be given at this point.
10294 
10295    Shift is the place to put it in inst.instruction.
10296 
10297    Restores input start point on err.
10298    Returns the reg#, or FAIL.  */
10299 
10300 static int
mav_reg_required_here(str,shift,regtype)10301 mav_reg_required_here (str, shift, regtype)
10302      char ** str;
10303      int shift;
10304      enum arm_reg_type regtype;
10305 {
10306   int   reg;
10307   char *start = *str;
10308 
10309   if ((reg = arm_reg_parse (str, all_reg_maps[regtype].htab)) != FAIL)
10310     {
10311       if (shift >= 0)
10312 	inst.instruction |= reg << shift;
10313 
10314       return reg;
10315     }
10316 
10317   /* Restore the start point.  */
10318   *str = start;
10319 
10320   /* In the few cases where we might be able to accept something else
10321      this error can be overridden.  */
10322   inst.error = _(all_reg_maps[regtype].expected);
10323 
10324   return FAIL;
10325 }
10326 
10327 /* Cirrus Maverick Instructions.  */
10328 
10329 /* Wrapper functions.  */
10330 
10331 static void
do_mav_binops_1a(str)10332 do_mav_binops_1a (str)
10333      char * str;
10334 {
10335   do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVF);
10336 }
10337 
10338 static void
do_mav_binops_1b(str)10339 do_mav_binops_1b (str)
10340      char * str;
10341 {
10342   do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVD);
10343 }
10344 
10345 static void
do_mav_binops_1c(str)10346 do_mav_binops_1c (str)
10347      char * str;
10348 {
10349   do_mav_binops (str, MAV_MODE1, REG_TYPE_RN, REG_TYPE_MVDX);
10350 }
10351 
10352 static void
do_mav_binops_1d(str)10353 do_mav_binops_1d (str)
10354      char * str;
10355 {
10356   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVF);
10357 }
10358 
10359 static void
do_mav_binops_1e(str)10360 do_mav_binops_1e (str)
10361      char * str;
10362 {
10363   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVD);
10364 }
10365 
10366 static void
do_mav_binops_1f(str)10367 do_mav_binops_1f (str)
10368      char * str;
10369 {
10370   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVF);
10371 }
10372 
10373 static void
do_mav_binops_1g(str)10374 do_mav_binops_1g (str)
10375      char * str;
10376 {
10377   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVD);
10378 }
10379 
10380 static void
do_mav_binops_1h(str)10381 do_mav_binops_1h (str)
10382      char * str;
10383 {
10384   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVFX);
10385 }
10386 
10387 static void
do_mav_binops_1i(str)10388 do_mav_binops_1i (str)
10389      char * str;
10390 {
10391   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVFX);
10392 }
10393 
10394 static void
do_mav_binops_1j(str)10395 do_mav_binops_1j (str)
10396      char * str;
10397 {
10398   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVF, REG_TYPE_MVDX);
10399 }
10400 
10401 static void
do_mav_binops_1k(str)10402 do_mav_binops_1k (str)
10403      char * str;
10404 {
10405   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVD, REG_TYPE_MVDX);
10406 }
10407 
10408 static void
do_mav_binops_1l(str)10409 do_mav_binops_1l (str)
10410      char * str;
10411 {
10412   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVF);
10413 }
10414 
10415 static void
do_mav_binops_1m(str)10416 do_mav_binops_1m (str)
10417      char * str;
10418 {
10419   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVD);
10420 }
10421 
10422 static void
do_mav_binops_1n(str)10423 do_mav_binops_1n (str)
10424      char * str;
10425 {
10426   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVFX, REG_TYPE_MVFX);
10427 }
10428 
10429 static void
do_mav_binops_1o(str)10430 do_mav_binops_1o (str)
10431      char * str;
10432 {
10433   do_mav_binops (str, MAV_MODE1, REG_TYPE_MVDX, REG_TYPE_MVDX);
10434 }
10435 
10436 static void
do_mav_binops_2a(str)10437 do_mav_binops_2a (str)
10438      char * str;
10439 {
10440   do_mav_binops (str, MAV_MODE2, REG_TYPE_MVF, REG_TYPE_RN);
10441 }
10442 
10443 static void
do_mav_binops_2b(str)10444 do_mav_binops_2b (str)
10445      char * str;
10446 {
10447   do_mav_binops (str, MAV_MODE2, REG_TYPE_MVD, REG_TYPE_RN);
10448 }
10449 
10450 static void
do_mav_binops_2c(str)10451 do_mav_binops_2c (str)
10452      char * str;
10453 {
10454   do_mav_binops (str, MAV_MODE2, REG_TYPE_MVDX, REG_TYPE_RN);
10455 }
10456 
10457 static void
do_mav_binops_3a(str)10458 do_mav_binops_3a (str)
10459      char * str;
10460 {
10461   do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVFX);
10462 }
10463 
10464 static void
do_mav_binops_3b(str)10465 do_mav_binops_3b (str)
10466      char * str;
10467 {
10468   do_mav_binops (str, MAV_MODE3, REG_TYPE_MVFX, REG_TYPE_MVAX);
10469 }
10470 
10471 static void
do_mav_binops_3c(str)10472 do_mav_binops_3c (str)
10473      char * str;
10474 {
10475   do_mav_binops (str, MAV_MODE3, REG_TYPE_MVAX, REG_TYPE_MVDX);
10476 }
10477 
10478 static void
do_mav_binops_3d(str)10479 do_mav_binops_3d (str)
10480      char * str;
10481 {
10482   do_mav_binops (str, MAV_MODE3, REG_TYPE_MVDX, REG_TYPE_MVAX);
10483 }
10484 
10485 static void
do_mav_triple_4a(str)10486 do_mav_triple_4a (str)
10487      char * str;
10488 {
10489   do_mav_triple (str, MAV_MODE4, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_RN);
10490 }
10491 
10492 static void
do_mav_triple_4b(str)10493 do_mav_triple_4b (str)
10494      char * str;
10495 {
10496   do_mav_triple (str, MAV_MODE4, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_RN);
10497 }
10498 
10499 static void
do_mav_triple_5a(str)10500 do_mav_triple_5a (str)
10501      char * str;
10502 {
10503   do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVF, REG_TYPE_MVF);
10504 }
10505 
10506 static void
do_mav_triple_5b(str)10507 do_mav_triple_5b (str)
10508      char * str;
10509 {
10510   do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVD, REG_TYPE_MVD);
10511 }
10512 
10513 static void
do_mav_triple_5c(str)10514 do_mav_triple_5c (str)
10515      char * str;
10516 {
10517   do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVFX, REG_TYPE_MVFX);
10518 }
10519 
10520 static void
do_mav_triple_5d(str)10521 do_mav_triple_5d (str)
10522      char * str;
10523 {
10524   do_mav_triple (str, MAV_MODE5, REG_TYPE_RN, REG_TYPE_MVDX, REG_TYPE_MVDX);
10525 }
10526 
10527 static void
do_mav_triple_5e(str)10528 do_mav_triple_5e (str)
10529      char * str;
10530 {
10531   do_mav_triple (str, MAV_MODE5, REG_TYPE_MVF, REG_TYPE_MVF, REG_TYPE_MVF);
10532 }
10533 
10534 static void
do_mav_triple_5f(str)10535 do_mav_triple_5f (str)
10536      char * str;
10537 {
10538   do_mav_triple (str, MAV_MODE5, REG_TYPE_MVD, REG_TYPE_MVD, REG_TYPE_MVD);
10539 }
10540 
10541 static void
do_mav_triple_5g(str)10542 do_mav_triple_5g (str)
10543      char * str;
10544 {
10545   do_mav_triple (str, MAV_MODE5, REG_TYPE_MVFX, REG_TYPE_MVFX, REG_TYPE_MVFX);
10546 }
10547 
10548 static void
do_mav_triple_5h(str)10549 do_mav_triple_5h (str)
10550      char * str;
10551 {
10552   do_mav_triple (str, MAV_MODE5, REG_TYPE_MVDX, REG_TYPE_MVDX, REG_TYPE_MVDX);
10553 }
10554 
10555 static void
do_mav_quad_6a(str)10556 do_mav_quad_6a (str)
10557      char * str;
10558 {
10559   do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVFX, REG_TYPE_MVFX,
10560 	     REG_TYPE_MVFX);
10561 }
10562 
10563 static void
do_mav_quad_6b(str)10564 do_mav_quad_6b (str)
10565      char * str;
10566 {
10567   do_mav_quad (str, MAV_MODE6, REG_TYPE_MVAX, REG_TYPE_MVAX, REG_TYPE_MVFX,
10568 	     REG_TYPE_MVFX);
10569 }
10570 
10571 /* cfmvsc32<cond> DSPSC,MVDX[15:0].  */
10572 static void
do_mav_dspsc_1(str)10573 do_mav_dspsc_1 (str)
10574      char * str;
10575 {
10576   skip_whitespace (str);
10577 
10578   /* cfmvsc32.  */
10579   if (mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL
10580       || skip_past_comma (&str) == FAIL
10581       || mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL)
10582     {
10583       if (!inst.error)
10584 	inst.error = BAD_ARGS;
10585 
10586       return;
10587     }
10588 
10589   end_of_line (str);
10590 }
10591 
10592 /* cfmv32sc<cond> MVDX[15:0],DSPSC.  */
10593 static void
do_mav_dspsc_2(str)10594 do_mav_dspsc_2 (str)
10595      char * str;
10596 {
10597   skip_whitespace (str);
10598 
10599   /* cfmv32sc.  */
10600   if (mav_reg_required_here (&str, 12, REG_TYPE_MVDX) == FAIL
10601       || skip_past_comma (&str) == FAIL
10602       || mav_reg_required_here (&str, -1, REG_TYPE_DSPSC) == FAIL)
10603     {
10604       if (!inst.error)
10605 	inst.error = BAD_ARGS;
10606 
10607       return;
10608     }
10609 
10610   end_of_line (str);
10611 }
10612 
10613 static void
do_mav_shift_1(str)10614 do_mav_shift_1 (str)
10615      char * str;
10616 {
10617   do_mav_shift (str, REG_TYPE_MVFX, REG_TYPE_MVFX);
10618 }
10619 
10620 static void
do_mav_shift_2(str)10621 do_mav_shift_2 (str)
10622      char * str;
10623 {
10624   do_mav_shift (str, REG_TYPE_MVDX, REG_TYPE_MVDX);
10625 }
10626 
10627 static void
do_mav_ldst_1(str)10628 do_mav_ldst_1 (str)
10629      char * str;
10630 {
10631   do_mav_ldst (str, REG_TYPE_MVF);
10632 }
10633 
10634 static void
do_mav_ldst_2(str)10635 do_mav_ldst_2 (str)
10636      char * str;
10637 {
10638   do_mav_ldst (str, REG_TYPE_MVD);
10639 }
10640 
10641 static void
do_mav_ldst_3(str)10642 do_mav_ldst_3 (str)
10643      char * str;
10644 {
10645   do_mav_ldst (str, REG_TYPE_MVFX);
10646 }
10647 
10648 static void
do_mav_ldst_4(str)10649 do_mav_ldst_4 (str)
10650      char * str;
10651 {
10652   do_mav_ldst (str, REG_TYPE_MVDX);
10653 }
10654 
10655 /* Isnsn like "foo X,Y".  */
10656 
10657 static void
do_mav_binops(str,mode,reg0,reg1)10658 do_mav_binops (str, mode, reg0, reg1)
10659      char * str;
10660      int mode;
10661      enum arm_reg_type reg0;
10662      enum arm_reg_type reg1;
10663 {
10664   int shift0, shift1;
10665 
10666   shift0 = mode & 0xff;
10667   shift1 = (mode >> 8) & 0xff;
10668 
10669   skip_whitespace (str);
10670 
10671   if (mav_reg_required_here (&str, shift0, reg0) == FAIL
10672       || skip_past_comma (&str) == FAIL
10673       || mav_reg_required_here (&str, shift1, reg1) == FAIL)
10674     {
10675       if (!inst.error)
10676 	inst.error = BAD_ARGS;
10677     }
10678   else
10679     end_of_line (str);
10680 }
10681 
10682 /* Isnsn like "foo X,Y,Z".  */
10683 
10684 static void
do_mav_triple(str,mode,reg0,reg1,reg2)10685 do_mav_triple (str, mode, reg0, reg1, reg2)
10686      char * str;
10687      int mode;
10688      enum arm_reg_type reg0;
10689      enum arm_reg_type reg1;
10690      enum arm_reg_type reg2;
10691 {
10692   int shift0, shift1, shift2;
10693 
10694   shift0 = mode & 0xff;
10695   shift1 = (mode >> 8) & 0xff;
10696   shift2 = (mode >> 16) & 0xff;
10697 
10698   skip_whitespace (str);
10699 
10700   if (mav_reg_required_here (&str, shift0, reg0) == FAIL
10701       || skip_past_comma (&str) == FAIL
10702       || mav_reg_required_here (&str, shift1, reg1) == FAIL
10703       || skip_past_comma (&str) == FAIL
10704       || mav_reg_required_here (&str, shift2, reg2) == FAIL)
10705     {
10706       if (!inst.error)
10707 	inst.error = BAD_ARGS;
10708     }
10709   else
10710     end_of_line (str);
10711 }
10712 
10713 /* Isnsn like "foo W,X,Y,Z".
10714     where W=MVAX[0:3] and X,Y,Z=MVFX[0:15].  */
10715 
10716 static void
do_mav_quad(str,mode,reg0,reg1,reg2,reg3)10717 do_mav_quad (str, mode, reg0, reg1, reg2, reg3)
10718      char * str;
10719      int mode;
10720      enum arm_reg_type reg0;
10721      enum arm_reg_type reg1;
10722      enum arm_reg_type reg2;
10723      enum arm_reg_type reg3;
10724 {
10725   int shift0, shift1, shift2, shift3;
10726 
10727   shift0= mode & 0xff;
10728   shift1 = (mode >> 8) & 0xff;
10729   shift2 = (mode >> 16) & 0xff;
10730   shift3 = (mode >> 24) & 0xff;
10731 
10732   skip_whitespace (str);
10733 
10734   if (mav_reg_required_here (&str, shift0, reg0) == FAIL
10735       || skip_past_comma (&str) == FAIL
10736       || mav_reg_required_here (&str, shift1, reg1) == FAIL
10737       || skip_past_comma (&str) == FAIL
10738       || mav_reg_required_here (&str, shift2, reg2) == FAIL
10739       || skip_past_comma (&str) == FAIL
10740       || mav_reg_required_here (&str, shift3, reg3) == FAIL)
10741     {
10742       if (!inst.error)
10743 	inst.error = BAD_ARGS;
10744     }
10745   else
10746     end_of_line (str);
10747 }
10748 
10749 /* Maverick shift immediate instructions.
10750    cfsh32<cond> MVFX[15:0],MVFX[15:0],Shift[6:0].
10751    cfsh64<cond> MVDX[15:0],MVDX[15:0],Shift[6:0].  */
10752 
10753 static void
do_mav_shift(str,reg0,reg1)10754 do_mav_shift (str, reg0, reg1)
10755      char * str;
10756      enum arm_reg_type reg0;
10757      enum arm_reg_type reg1;
10758 {
10759   int error;
10760   int imm, neg = 0;
10761 
10762   skip_whitespace (str);
10763 
10764   error = 0;
10765 
10766   if (mav_reg_required_here (&str, 12, reg0) == FAIL
10767       || skip_past_comma (&str) == FAIL
10768       || mav_reg_required_here (&str, 16, reg1) == FAIL
10769       || skip_past_comma  (&str) == FAIL)
10770     {
10771       if (!inst.error)
10772 	inst.error = BAD_ARGS;
10773       return;
10774     }
10775 
10776   /* Calculate the immediate operand.
10777      The operand is a 7bit signed number.  */
10778   skip_whitespace (str);
10779 
10780   if (*str == '#')
10781     ++str;
10782 
10783   if (!ISDIGIT (*str) && *str != '-')
10784     {
10785       inst.error = _("expecting immediate, 7bit operand");
10786       return;
10787     }
10788 
10789   if (*str == '-')
10790     {
10791       neg = 1;
10792       ++str;
10793     }
10794 
10795   for (imm = 0; *str && ISDIGIT (*str); ++str)
10796     imm = imm * 10 + *str - '0';
10797 
10798   if (imm > 64)
10799     {
10800       inst.error = _("immediate out of range");
10801       return;
10802     }
10803 
10804   /* Make negative imm's into 7bit signed numbers.  */
10805   if (neg)
10806     {
10807       imm = -imm;
10808       imm &= 0x0000007f;
10809     }
10810 
10811   /* Bits 0-3 of the insn should have bits 0-3 of the immediate.
10812      Bits 5-7 of the insn should have bits 4-6 of the immediate.
10813      Bit 4 should be 0.  */
10814   imm = (imm & 0xf) | ((imm & 0x70) << 1);
10815 
10816   inst.instruction |= imm;
10817   end_of_line (str);
10818 }
10819 
10820 static int
mav_parse_offset(str,negative)10821 mav_parse_offset (str, negative)
10822      char ** str;
10823      int *negative;
10824 {
10825   char * p = *str;
10826   int offset;
10827 
10828   *negative = 0;
10829 
10830   skip_whitespace (p);
10831 
10832   if (*p == '#')
10833     ++p;
10834 
10835   if (*p == '-')
10836     {
10837       *negative = 1;
10838       ++p;
10839     }
10840 
10841   if (!ISDIGIT (*p))
10842     {
10843       inst.error = _("offset expected");
10844       return 0;
10845     }
10846 
10847   for (offset = 0; *p && ISDIGIT (*p); ++p)
10848     offset = offset * 10 + *p - '0';
10849 
10850   if (offset > 0xff)
10851     {
10852       inst.error = _("offset out of range");
10853       return 0;
10854     }
10855 
10856   *str = p;
10857 
10858   return *negative ? -offset : offset;
10859 }
10860 
10861 /* Maverick load/store instructions.
10862   <insn><cond> CRd,[Rn,<offset>]{!}.
10863   <insn><cond> CRd,[Rn],<offset>.  */
10864 
10865 static void
do_mav_ldst(str,reg0)10866 do_mav_ldst (str, reg0)
10867      char * str;
10868      enum arm_reg_type reg0;
10869 {
10870   int offset, negative;
10871 
10872   skip_whitespace (str);
10873 
10874   if (mav_reg_required_here (&str, 12, reg0) == FAIL
10875       || skip_past_comma (&str) == FAIL
10876       || *str++ != '['
10877       || reg_required_here (&str, 16) == FAIL)
10878     goto fail_ldst;
10879 
10880   if (skip_past_comma (&str) == SUCCESS)
10881     {
10882       /* You are here: "<offset>]{!}".  */
10883       inst.instruction |= PRE_INDEX;
10884 
10885       offset = mav_parse_offset (&str, &negative);
10886 
10887       if (inst.error)
10888 	return;
10889 
10890       if (*str++ != ']')
10891 	{
10892 	  inst.error = _("missing ]");
10893 	  return;
10894 	}
10895 
10896       if (*str == '!')
10897 	{
10898 	  inst.instruction |= WRITE_BACK;
10899 	  ++str;
10900 	}
10901     }
10902   else
10903     {
10904       /* You are here: "], <offset>".  */
10905       if (*str++ != ']')
10906 	{
10907 	  inst.error = _("missing ]");
10908 	  return;
10909 	}
10910 
10911       if (skip_past_comma (&str) == FAIL
10912 	  || (offset = mav_parse_offset (&str, &negative), inst.error))
10913 	goto fail_ldst;
10914 
10915       inst.instruction |= CP_T_WB; /* Post indexed, set bit W.  */
10916     }
10917 
10918   if (negative)
10919     offset = -offset;
10920   else
10921     inst.instruction |= CP_T_UD; /* Positive, so set bit U.  */
10922 
10923   inst.instruction |= offset >> 2;
10924   end_of_line (str);
10925   return;
10926 
10927 fail_ldst:
10928   if (!inst.error)
10929      inst.error = BAD_ARGS;
10930 }
10931 
10932 static void
do_t_nop(str)10933 do_t_nop (str)
10934      char * str;
10935 {
10936   /* Do nothing.  */
10937   end_of_line (str);
10938 }
10939 
10940 /* Handle the Format 4 instructions that do not have equivalents in other
10941    formats.  That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
10942    BIC and MVN.  */
10943 
10944 static void
do_t_arit(str)10945 do_t_arit (str)
10946      char * str;
10947 {
10948   int Rd, Rs, Rn;
10949 
10950   skip_whitespace (str);
10951 
10952   if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
10953       || skip_past_comma (&str) == FAIL
10954       || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10955     {
10956       inst.error = BAD_ARGS;
10957       return;
10958     }
10959 
10960   if (skip_past_comma (&str) != FAIL)
10961     {
10962       /* Three operand format not allowed for TST, CMN, NEG and MVN.
10963 	 (It isn't allowed for CMP either, but that isn't handled by this
10964 	 function.)  */
10965       if (inst.instruction == T_OPCODE_TST
10966 	  || inst.instruction == T_OPCODE_CMN
10967 	  || inst.instruction == T_OPCODE_NEG
10968 	  || inst.instruction == T_OPCODE_MVN)
10969 	{
10970 	  inst.error = BAD_ARGS;
10971 	  return;
10972 	}
10973 
10974       if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
10975 	return;
10976 
10977       if (Rs != Rd)
10978 	{
10979 	  inst.error = _("dest and source1 must be the same register");
10980 	  return;
10981 	}
10982       Rs = Rn;
10983     }
10984 
10985   if (inst.instruction == T_OPCODE_MUL
10986       && Rs == Rd)
10987     as_tsktsk (_("Rs and Rd must be different in MUL"));
10988 
10989   inst.instruction |= Rd | (Rs << 3);
10990   end_of_line (str);
10991 }
10992 
10993 static void
do_t_add(str)10994 do_t_add (str)
10995      char * str;
10996 {
10997   thumb_add_sub (str, 0);
10998 }
10999 
11000 static void
do_t_asr(str)11001 do_t_asr (str)
11002      char * str;
11003 {
11004   thumb_shift (str, THUMB_ASR);
11005 }
11006 
11007 static void
do_t_branch9(str)11008 do_t_branch9 (str)
11009      char * str;
11010 {
11011   if (my_get_expression (&inst.reloc.exp, &str))
11012     return;
11013   inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
11014   inst.reloc.pc_rel = 1;
11015   end_of_line (str);
11016 }
11017 
11018 static void
do_t_branch12(str)11019 do_t_branch12 (str)
11020      char * str;
11021 {
11022   if (my_get_expression (&inst.reloc.exp, &str))
11023     return;
11024   inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
11025   inst.reloc.pc_rel = 1;
11026   end_of_line (str);
11027 }
11028 
11029 /* Find the real, Thumb encoded start of a Thumb function.  */
11030 
11031 static symbolS *
find_real_start(symbolP)11032 find_real_start (symbolP)
11033      symbolS * symbolP;
11034 {
11035   char *       real_start;
11036   const char * name = S_GET_NAME (symbolP);
11037   symbolS *    new_target;
11038 
11039   /* This definition must agree with the one in gcc/config/arm/thumb.c.  */
11040 #define STUB_NAME ".real_start_of"
11041 
11042   if (name == NULL)
11043     abort ();
11044 
11045   /* Names that start with '.' are local labels, not function entry points.
11046      The compiler may generate BL instructions to these labels because it
11047      needs to perform a branch to a far away location.  */
11048   if (name[0] == '.')
11049     return symbolP;
11050 
11051   real_start = malloc (strlen (name) + strlen (STUB_NAME) + 1);
11052   sprintf (real_start, "%s%s", STUB_NAME, name);
11053 
11054   new_target = symbol_find (real_start);
11055 
11056   if (new_target == NULL)
11057     {
11058       as_warn ("Failed to find real start of function: %s\n", name);
11059       new_target = symbolP;
11060     }
11061 
11062   free (real_start);
11063 
11064   return new_target;
11065 }
11066 
11067 static void
do_t_branch23(str)11068 do_t_branch23 (str)
11069      char * str;
11070 {
11071   if (my_get_expression (& inst.reloc.exp, & str))
11072     return;
11073 
11074   inst.reloc.type   = BFD_RELOC_THUMB_PCREL_BRANCH23;
11075   inst.reloc.pc_rel = 1;
11076   end_of_line (str);
11077 
11078   /* If the destination of the branch is a defined symbol which does not have
11079      the THUMB_FUNC attribute, then we must be calling a function which has
11080      the (interfacearm) attribute.  We look for the Thumb entry point to that
11081      function and change the branch to refer to that function instead.  */
11082   if (   inst.reloc.exp.X_op == O_symbol
11083       && inst.reloc.exp.X_add_symbol != NULL
11084       && S_IS_DEFINED (inst.reloc.exp.X_add_symbol)
11085       && ! THUMB_IS_FUNC (inst.reloc.exp.X_add_symbol))
11086     inst.reloc.exp.X_add_symbol =
11087       find_real_start (inst.reloc.exp.X_add_symbol);
11088 }
11089 
11090 static void
do_t_bx(str)11091 do_t_bx (str)
11092      char * str;
11093 {
11094   int reg;
11095 
11096   skip_whitespace (str);
11097 
11098   if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
11099     return;
11100 
11101   /* This sets THUMB_H2 from the top bit of reg.  */
11102   inst.instruction |= reg << 3;
11103 
11104   /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC.  The reloc
11105      should cause the alignment to be checked once it is known.  This is
11106      because BX PC only works if the instruction is word aligned.  */
11107 
11108   end_of_line (str);
11109 }
11110 
11111 static void
do_t_compare(str)11112 do_t_compare (str)
11113      char * str;
11114 {
11115   thumb_mov_compare (str, THUMB_COMPARE);
11116 }
11117 
11118 static void
do_t_ldmstm(str)11119 do_t_ldmstm (str)
11120      char * str;
11121 {
11122   int Rb;
11123   long range;
11124 
11125   skip_whitespace (str);
11126 
11127   if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
11128     return;
11129 
11130   if (*str != '!')
11131     as_warn (_("inserted missing '!': load/store multiple always writes back base register"));
11132   else
11133     str++;
11134 
11135   if (skip_past_comma (&str) == FAIL
11136       || (range = reg_list (&str)) == FAIL)
11137     {
11138       if (! inst.error)
11139 	inst.error = BAD_ARGS;
11140       return;
11141     }
11142 
11143   if (inst.reloc.type != BFD_RELOC_NONE)
11144     {
11145       /* This really doesn't seem worth it.  */
11146       inst.reloc.type = BFD_RELOC_NONE;
11147       inst.error = _("expression too complex");
11148       return;
11149     }
11150 
11151   if (range & ~0xff)
11152     {
11153       inst.error = _("only lo-regs valid in load/store multiple");
11154       return;
11155     }
11156 
11157   inst.instruction |= (Rb << 8) | range;
11158   end_of_line (str);
11159 }
11160 
11161 static void
do_t_ldr(str)11162 do_t_ldr (str)
11163      char * str;
11164 {
11165   thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
11166 }
11167 
11168 static void
do_t_ldrb(str)11169 do_t_ldrb (str)
11170      char * str;
11171 {
11172   thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
11173 }
11174 
11175 static void
do_t_ldrh(str)11176 do_t_ldrh (str)
11177      char * str;
11178 {
11179   thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
11180 }
11181 
11182 static void
do_t_lds(str)11183 do_t_lds (str)
11184      char * str;
11185 {
11186   int Rd, Rb, Ro;
11187 
11188   skip_whitespace (str);
11189 
11190   if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11191       || skip_past_comma (&str) == FAIL
11192       || *str++ != '['
11193       || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11194       || skip_past_comma (&str) == FAIL
11195       || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
11196       || *str++ != ']')
11197     {
11198       if (! inst.error)
11199 	inst.error = _("syntax: ldrs[b] Rd, [Rb, Ro]");
11200       return;
11201     }
11202 
11203   inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
11204   end_of_line (str);
11205 }
11206 
11207 static void
do_t_lsl(str)11208 do_t_lsl (str)
11209      char * str;
11210 {
11211   thumb_shift (str, THUMB_LSL);
11212 }
11213 
11214 static void
do_t_lsr(str)11215 do_t_lsr (str)
11216      char * str;
11217 {
11218   thumb_shift (str, THUMB_LSR);
11219 }
11220 
11221 static void
do_t_mov(str)11222 do_t_mov (str)
11223      char * str;
11224 {
11225   thumb_mov_compare (str, THUMB_MOVE);
11226 }
11227 
11228 static void
do_t_push_pop(str)11229 do_t_push_pop (str)
11230      char * str;
11231 {
11232   long range;
11233 
11234   skip_whitespace (str);
11235 
11236   if ((range = reg_list (&str)) == FAIL)
11237     {
11238       if (! inst.error)
11239 	inst.error = BAD_ARGS;
11240       return;
11241     }
11242 
11243   if (inst.reloc.type != BFD_RELOC_NONE)
11244     {
11245       /* This really doesn't seem worth it.  */
11246       inst.reloc.type = BFD_RELOC_NONE;
11247       inst.error = _("expression too complex");
11248       return;
11249     }
11250 
11251   if (range & ~0xff)
11252     {
11253       if ((inst.instruction == T_OPCODE_PUSH
11254 	   && (range & ~0xff) == 1 << REG_LR)
11255 	  || (inst.instruction == T_OPCODE_POP
11256 	      && (range & ~0xff) == 1 << REG_PC))
11257 	{
11258 	  inst.instruction |= THUMB_PP_PC_LR;
11259 	  range &= 0xff;
11260 	}
11261       else
11262 	{
11263 	  inst.error = _("invalid register list to push/pop instruction");
11264 	  return;
11265 	}
11266     }
11267 
11268   inst.instruction |= range;
11269   end_of_line (str);
11270 }
11271 
11272 static void
do_t_str(str)11273 do_t_str (str)
11274      char * str;
11275 {
11276   thumb_load_store (str, THUMB_STORE, THUMB_WORD);
11277 }
11278 
11279 static void
do_t_strb(str)11280 do_t_strb (str)
11281      char * str;
11282 {
11283   thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
11284 }
11285 
11286 static void
do_t_strh(str)11287 do_t_strh (str)
11288      char * str;
11289 {
11290   thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
11291 }
11292 
11293 static void
do_t_sub(str)11294 do_t_sub (str)
11295      char * str;
11296 {
11297   thumb_add_sub (str, 1);
11298 }
11299 
11300 static void
do_t_swi(str)11301 do_t_swi (str)
11302      char * str;
11303 {
11304   skip_whitespace (str);
11305 
11306   if (my_get_expression (&inst.reloc.exp, &str))
11307     return;
11308 
11309   inst.reloc.type = BFD_RELOC_ARM_SWI;
11310   end_of_line (str);
11311 }
11312 
11313 static void
do_t_adr(str)11314 do_t_adr (str)
11315      char * str;
11316 {
11317   int reg;
11318 
11319   /* This is a pseudo-op of the form "adr rd, label" to be converted
11320      into a relative address of the form "add rd, pc, #label-.-4".  */
11321   skip_whitespace (str);
11322 
11323   /* Store Rd in temporary location inside instruction.  */
11324   if ((reg = reg_required_here (&str, 4)) == FAIL
11325       || (reg > 7)  /* For Thumb reg must be r0..r7.  */
11326       || skip_past_comma (&str) == FAIL
11327       || my_get_expression (&inst.reloc.exp, &str))
11328     {
11329       if (!inst.error)
11330 	inst.error = BAD_ARGS;
11331       return;
11332     }
11333 
11334   inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
11335   inst.reloc.exp.X_add_number -= 4; /* PC relative adjust.  */
11336   inst.reloc.pc_rel = 1;
11337   inst.instruction |= REG_PC; /* Rd is already placed into the instruction.  */
11338 
11339   end_of_line (str);
11340 }
11341 
11342 static void
insert_reg(r,htab)11343 insert_reg (r, htab)
11344      const struct reg_entry *r;
11345      struct hash_control *htab;
11346 {
11347   int    len  = strlen (r->name) + 2;
11348   char * buf  = (char *) xmalloc (len);
11349   char * buf2 = (char *) xmalloc (len);
11350   int    i    = 0;
11351 
11352 #ifdef REGISTER_PREFIX
11353   buf[i++] = REGISTER_PREFIX;
11354 #endif
11355 
11356   strcpy (buf + i, r->name);
11357 
11358   for (i = 0; buf[i]; i++)
11359     buf2[i] = TOUPPER (buf[i]);
11360 
11361   buf2[i] = '\0';
11362 
11363   hash_insert (htab, buf,  (PTR) r);
11364   hash_insert (htab, buf2, (PTR) r);
11365 }
11366 
11367 static void
build_reg_hsh(map)11368 build_reg_hsh (map)
11369      struct reg_map *map;
11370 {
11371   const struct reg_entry *r;
11372 
11373   if ((map->htab = hash_new ()) == NULL)
11374     as_fatal (_("virtual memory exhausted"));
11375 
11376   for (r = map->names; r->name != NULL; r++)
11377     insert_reg (r, map->htab);
11378 }
11379 
11380 static void
insert_reg_alias(str,regnum,htab)11381 insert_reg_alias (str, regnum, htab)
11382      char *str;
11383      int regnum;
11384      struct hash_control *htab;
11385 {
11386   const char *error;
11387   struct reg_entry *new = xmalloc (sizeof (struct reg_entry));
11388   const char *name = xmalloc (strlen (str) + 1);
11389 
11390   strcpy ((char *) name, str);
11391 
11392   new->name = name;
11393   new->number = regnum;
11394   new->builtin = FALSE;
11395 
11396   error = hash_insert (htab, name, (PTR) new);
11397   if (error)
11398     {
11399       as_bad (_("failed to create an alias for %s, reason: %s"),
11400 	    str, error);
11401       free ((char *) name);
11402       free (new);
11403     }
11404 }
11405 
11406 /* Look for the .req directive.  This is of the form:
11407 
11408    	new_register_name .req existing_register_name
11409 
11410    If we find one, or if it looks sufficiently like one that we want to
11411    handle any error here, return non-zero.  Otherwise return zero.  */
11412 static int
create_register_alias(newname,p)11413 create_register_alias (newname, p)
11414      char *newname;
11415      char *p;
11416 {
11417   char *q;
11418   char c;
11419 
11420   q = p;
11421   skip_whitespace (q);
11422 
11423   c = *p;
11424   *p = '\0';
11425 
11426   if (*q && !strncmp (q, ".req ", 5))
11427     {
11428       char *copy_of_str;
11429       char *r;
11430 
11431 #ifdef IGNORE_OPCODE_CASE
11432       newname = original_case_string;
11433 #endif
11434       copy_of_str = newname;
11435 
11436       q += 4;
11437       skip_whitespace (q);
11438 
11439       for (r = q; *r != '\0'; r++)
11440 	if (*r == ' ')
11441 	  break;
11442 
11443       if (r != q)
11444 	{
11445 	  enum arm_reg_type new_type, old_type;
11446 	  int old_regno;
11447 	  char d = *r;
11448 
11449 	  *r = '\0';
11450 	  old_type = arm_reg_parse_any (q);
11451 	  *r = d;
11452 
11453 	  new_type = arm_reg_parse_any (newname);
11454 
11455 	  if (new_type == REG_TYPE_MAX)
11456 	    {
11457 	      if (old_type != REG_TYPE_MAX)
11458 		{
11459 		  old_regno = arm_reg_parse (&q, all_reg_maps[old_type].htab);
11460 		  insert_reg_alias (newname, old_regno,
11461 				    all_reg_maps[old_type].htab);
11462 		}
11463 	      else
11464 		as_warn (_("register '%s' does not exist\n"), q);
11465 	    }
11466 	  else if (old_type == REG_TYPE_MAX)
11467 	    {
11468 	      as_warn (_("ignoring redefinition of register alias '%s' to non-existant register '%s'"),
11469 		       copy_of_str, q);
11470 	    }
11471 	  else
11472 	    {
11473 	      /* Do not warn about redefinitions to the same alias.  */
11474 	      if (new_type != old_type
11475 		  || (arm_reg_parse (&q, all_reg_maps[old_type].htab)
11476 		      != arm_reg_parse (&q, all_reg_maps[new_type].htab)))
11477 		as_warn (_("ignoring redefinition of register alias '%s'"),
11478 			 copy_of_str);
11479 
11480 	    }
11481 	}
11482       else
11483 	as_warn (_("ignoring incomplete .req pseuso op"));
11484 
11485       *p = c;
11486       return 1;
11487     }
11488 
11489   *p = c;
11490   return 0;
11491 }
11492 
11493 static void
set_constant_flonums()11494 set_constant_flonums ()
11495 {
11496   int i;
11497 
11498   for (i = 0; i < NUM_FLOAT_VALS; i++)
11499     if (atof_ieee ((char *) fp_const[i], 'x', fp_values[i]) == NULL)
11500       abort ();
11501 }
11502 
11503 /* Iterate over the base tables to create the instruction patterns.  */
11504 static void
build_arm_ops_hsh()11505 build_arm_ops_hsh ()
11506 {
11507   unsigned int i;
11508   unsigned int j;
11509   static struct obstack insn_obstack;
11510 
11511   obstack_begin (&insn_obstack, 4000);
11512 
11513   for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
11514     {
11515       const struct asm_opcode *insn = insns + i;
11516 
11517       if (insn->cond_offset != 0)
11518 	{
11519 	  /* Insn supports conditional execution.  Build the varaints
11520 	     and insert them in the hash table.  */
11521 	  for (j = 0; j < sizeof (conds) / sizeof (struct asm_cond); j++)
11522 	    {
11523 	      unsigned len = strlen (insn->template);
11524 	      struct asm_opcode *new;
11525 	      char *template;
11526 
11527 	      new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
11528 	      /* All condition codes are two characters.  */
11529 	      template = obstack_alloc (&insn_obstack, len + 3);
11530 
11531 	      strncpy (template, insn->template, insn->cond_offset);
11532 	      strcpy (template + insn->cond_offset, conds[j].template);
11533 	      if (len > insn->cond_offset)
11534 		strcpy (template + insn->cond_offset + 2,
11535 			insn->template + insn->cond_offset);
11536 	      new->template = template;
11537 	      new->cond_offset = 0;
11538 	      new->variant = insn->variant;
11539 	      new->parms = insn->parms;
11540 	      new->value = (insn->value & ~COND_MASK) | conds[j].value;
11541 
11542 	      hash_insert (arm_ops_hsh, new->template, (PTR) new);
11543 	    }
11544 	}
11545       /* Finally, insert the unconditional insn in the table directly;
11546 	 no need to build a copy.  */
11547       hash_insert (arm_ops_hsh, insn->template, (PTR) insn);
11548     }
11549 }
11550 
11551 #if 0 /* Suppressed - for now.  */
11552 #if defined OBJ_ELF || defined OBJ_COFF
11553 
11554 #ifdef OBJ_ELF
11555 #define arm_Note Elf_External_Note
11556 #else
11557 typedef struct
11558 {
11559   unsigned char	namesz[4];	/* Size of entry's owner string.  */
11560   unsigned char	descsz[4];	/* Size of the note descriptor.  */
11561   unsigned char	type[4];	/* Interpretation of the descriptor.  */
11562   char		name[1];	/* Start of the name+desc data.  */
11563 } arm_Note;
11564 #endif
11565 
11566 /* The description is kept to a fix sized in order to make updating
11567    it and merging it easier.  */
11568 #define ARM_NOTE_DESCRIPTION_LENGTH	8
11569 
11570 static void
11571 arm_add_note (name, description, type)
11572      const char * name;
11573      const char * description;
11574      unsigned int type;
11575 {
11576   arm_Note     note ATTRIBUTE_UNUSED;
11577   char *       p;
11578   unsigned int name_len;
11579 
11580   name_len = (strlen (name) + 1 + 3) & ~3;
11581 
11582   p = frag_more (sizeof (note.namesz));
11583   md_number_to_chars (p, (valueT) name_len, sizeof (note.namesz));
11584 
11585   p = frag_more (sizeof (note.descsz));
11586   md_number_to_chars (p, (valueT) ARM_NOTE_DESCRIPTION_LENGTH, sizeof (note.descsz));
11587 
11588   p = frag_more (sizeof (note.type));
11589   md_number_to_chars (p, (valueT) type, sizeof (note.type));
11590 
11591   p = frag_more (name_len);
11592   strcpy (p, name);
11593 
11594   p = frag_more (ARM_NOTE_DESCRIPTION_LENGTH);
11595   strncpy (p, description, ARM_NOTE_DESCRIPTION_LENGTH);
11596   frag_align (2, 0, 0);
11597 }
11598 #endif
11599 #endif
11600 
11601 void
md_begin()11602 md_begin ()
11603 {
11604   unsigned mach;
11605   unsigned int i;
11606 
11607   if (   (arm_ops_hsh = hash_new ()) == NULL
11608       || (arm_tops_hsh = hash_new ()) == NULL
11609       || (arm_cond_hsh = hash_new ()) == NULL
11610       || (arm_shift_hsh = hash_new ()) == NULL
11611       || (arm_psr_hsh = hash_new ()) == NULL)
11612     as_fatal (_("virtual memory exhausted"));
11613 
11614   build_arm_ops_hsh ();
11615   for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
11616     hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
11617   for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
11618     hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
11619   for (i = 0; i < sizeof (shift_names) / sizeof (struct asm_shift_name); i++)
11620     hash_insert (arm_shift_hsh, shift_names[i].name, (PTR) (shift_names + i));
11621   for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
11622     hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
11623 
11624   for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
11625     build_reg_hsh (all_reg_maps + i);
11626 
11627   set_constant_flonums ();
11628 
11629   /* Set the cpu variant based on the command-line options.  We prefer
11630      -mcpu= over -march= if both are set (as for GCC); and we prefer
11631      -mfpu= over any other way of setting the floating point unit.
11632      Use of legacy options with new options are faulted.  */
11633   if (legacy_cpu != -1)
11634     {
11635       if (mcpu_cpu_opt != -1 || march_cpu_opt != -1)
11636 	as_bad (_("use of old and new-style options to set CPU type"));
11637 
11638       mcpu_cpu_opt = legacy_cpu;
11639     }
11640   else if (mcpu_cpu_opt == -1)
11641     mcpu_cpu_opt = march_cpu_opt;
11642 
11643   if (legacy_fpu != -1)
11644     {
11645       if (mfpu_opt != -1)
11646 	as_bad (_("use of old and new-style options to set FPU type"));
11647 
11648       mfpu_opt = legacy_fpu;
11649     }
11650   else if (mfpu_opt == -1)
11651     {
11652 #if !(defined (TE_LINUX) || defined (TE_NetBSD) || defined(TE_OpenBSD))
11653       /* Some environments specify a default FPU.  If they don't, infer it
11654 	 from the processor.  */
11655       if (mcpu_fpu_opt != -1)
11656 	mfpu_opt = mcpu_fpu_opt;
11657       else
11658 	mfpu_opt = march_fpu_opt;
11659 #else
11660       mfpu_opt = FPU_DEFAULT;
11661 #endif
11662     }
11663 
11664   if (mfpu_opt == -1)
11665     {
11666       if (mcpu_cpu_opt == -1)
11667 	mfpu_opt = FPU_DEFAULT;
11668       else if (mcpu_cpu_opt & ARM_EXT_V5)
11669 	mfpu_opt = FPU_ARCH_VFP_V2;
11670       else
11671 	mfpu_opt = FPU_ARCH_FPA;
11672     }
11673 
11674   if (mcpu_cpu_opt == -1)
11675     mcpu_cpu_opt = CPU_DEFAULT;
11676 
11677   cpu_variant = mcpu_cpu_opt | mfpu_opt;
11678 
11679 #if defined OBJ_COFF || defined OBJ_ELF
11680   {
11681     unsigned int flags = 0;
11682 
11683     /* Set the flags in the private structure.  */
11684     if (uses_apcs_26)      flags |= F_APCS26;
11685     if (support_interwork) flags |= F_INTERWORK;
11686     if (uses_apcs_float)   flags |= F_APCS_FLOAT;
11687     if (pic_code)          flags |= F_PIC;
11688     if ((cpu_variant & FPU_ANY) == FPU_NONE
11689 	 || (cpu_variant & FPU_ANY) == FPU_ARCH_VFP) /* VFP layout only.  */
11690       {
11691 	flags |= F_SOFT_FLOAT;
11692       }
11693     switch (mfloat_abi_opt)
11694       {
11695       case ARM_FLOAT_ABI_SOFT:
11696       case ARM_FLOAT_ABI_SOFTFP:
11697 	flags |= F_SOFT_FLOAT;
11698 	break;
11699 
11700       case ARM_FLOAT_ABI_HARD:
11701 	if (flags & F_SOFT_FLOAT)
11702 	  as_bad (_("hard-float conflicts with specified fpu"));
11703 	break;
11704       }
11705     /* Using VFP conventions (even if soft-float).  */
11706     if (cpu_variant & FPU_VFP_EXT_NONE) flags |= F_VFP_FLOAT;
11707 
11708 #if defined OBJ_ELF
11709     if (cpu_variant & FPU_ARCH_MAVERICK)
11710 	flags |= EF_ARM_MAVERICK_FLOAT;
11711 #endif
11712 
11713     bfd_set_private_flags (stdoutput, flags);
11714 
11715     /* We have run out flags in the COFF header to encode the
11716        status of ATPCS support, so instead we create a dummy,
11717        empty, debug section called .arm.atpcs.  */
11718     if (atpcs)
11719       {
11720 	asection * sec;
11721 
11722 	sec = bfd_make_section (stdoutput, ".arm.atpcs");
11723 
11724 	if (sec != NULL)
11725 	  {
11726 	    bfd_set_section_flags
11727 	      (stdoutput, sec, SEC_READONLY | SEC_DEBUGGING /* | SEC_HAS_CONTENTS */);
11728 	    bfd_set_section_size (stdoutput, sec, 0);
11729 	    bfd_set_section_contents (stdoutput, sec, NULL, 0, 0);
11730 	  }
11731       }
11732   }
11733 #endif
11734 
11735   /* Record the CPU type as well.  */
11736   switch (cpu_variant & ARM_CPU_MASK)
11737     {
11738     case ARM_2:
11739       mach = bfd_mach_arm_2;
11740       break;
11741 
11742     case ARM_3: 		/* Also ARM_250.  */
11743       mach = bfd_mach_arm_2a;
11744       break;
11745 
11746     case ARM_6:			/* Also ARM_7.  */
11747       mach = bfd_mach_arm_3;
11748       break;
11749 
11750     default:
11751       mach = bfd_mach_arm_unknown;
11752       break;
11753     }
11754 
11755   /* Catch special cases.  */
11756   if (cpu_variant & ARM_CEXT_IWMMXT)
11757     mach = bfd_mach_arm_iWMMXt;
11758   else if (cpu_variant & ARM_CEXT_XSCALE)
11759     mach = bfd_mach_arm_XScale;
11760   else if (cpu_variant & ARM_CEXT_MAVERICK)
11761     mach = bfd_mach_arm_ep9312;
11762   else if (cpu_variant & ARM_EXT_V5E)
11763     mach = bfd_mach_arm_5TE;
11764   else if (cpu_variant & ARM_EXT_V5)
11765     {
11766       if (cpu_variant & ARM_EXT_V4T)
11767 	mach = bfd_mach_arm_5T;
11768       else
11769 	mach = bfd_mach_arm_5;
11770     }
11771   else if (cpu_variant & ARM_EXT_V4)
11772     {
11773       if (cpu_variant & ARM_EXT_V4T)
11774 	mach = bfd_mach_arm_4T;
11775       else
11776 	mach = bfd_mach_arm_4;
11777     }
11778   else if (cpu_variant & ARM_EXT_V3M)
11779     mach = bfd_mach_arm_3M;
11780 
11781 #if 0 /* Suppressed - for now.  */
11782 #if defined (OBJ_ELF) || defined (OBJ_COFF)
11783 
11784   /* Create a .note section to fully identify this arm binary.  */
11785 
11786 #define NOTE_ARCH_STRING 	"arch: "
11787 
11788 #if defined OBJ_COFF && ! defined NT_VERSION
11789 #define NT_VERSION  1
11790 #define NT_ARCH     2
11791 #endif
11792 
11793   {
11794     segT current_seg = now_seg;
11795     subsegT current_subseg = now_subseg;
11796     asection * arm_arch;
11797     const char * arch_string;
11798 
11799     arm_arch = bfd_make_section_old_way (stdoutput, ARM_NOTE_SECTION);
11800 
11801 #ifdef OBJ_COFF
11802     bfd_set_section_flags (stdoutput, arm_arch,
11803 			   SEC_DATA | SEC_ALLOC | SEC_LOAD | SEC_LINK_ONCE \
11804 			   | SEC_HAS_CONTENTS);
11805 #else
11806     bfd_set_section_flags (stdoutput, arm_arch,
11807 			   SEC_READONLY | SEC_HAS_CONTENTS);
11808 #endif
11809     arm_arch->output_section = arm_arch;
11810     subseg_set (arm_arch, 0);
11811 
11812     switch (mach)
11813       {
11814       default:
11815       case bfd_mach_arm_unknown: arch_string = "unknown"; break;
11816       case bfd_mach_arm_2:       arch_string = "armv2"; break;
11817       case bfd_mach_arm_2a:      arch_string = "armv2a"; break;
11818       case bfd_mach_arm_3:       arch_string = "armv3"; break;
11819       case bfd_mach_arm_3M:      arch_string = "armv3M"; break;
11820       case bfd_mach_arm_4:       arch_string = "armv4"; break;
11821       case bfd_mach_arm_4T:      arch_string = "armv4t"; break;
11822       case bfd_mach_arm_5:       arch_string = "armv5"; break;
11823       case bfd_mach_arm_5T:      arch_string = "armv5t"; break;
11824       case bfd_mach_arm_5TE:     arch_string = "armv5te"; break;
11825       case bfd_mach_arm_XScale:  arch_string = "XScale"; break;
11826       case bfd_mach_arm_ep9312:  arch_string = "ep9312"; break;
11827       case bfd_mach_arm_iWMMXt:  arch_string = "iWMMXt"; break;
11828       }
11829 
11830     arm_add_note (NOTE_ARCH_STRING, arch_string, NT_ARCH);
11831 
11832     subseg_set (current_seg, current_subseg);
11833   }
11834 #endif
11835 #endif /* Suppressed code.  */
11836 
11837   bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
11838 }
11839 
11840 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
11841    for use in the a.out file, and stores them in the array pointed to by buf.
11842    This knows about the endian-ness of the target machine and does
11843    THE RIGHT THING, whatever it is.  Possible values for n are 1 (byte)
11844    2 (short) and 4 (long)  Floating numbers are put out as a series of
11845    LITTLENUMS (shorts, here at least).  */
11846 
11847 void
md_number_to_chars(buf,val,n)11848 md_number_to_chars (buf, val, n)
11849      char * buf;
11850      valueT val;
11851      int    n;
11852 {
11853   if (target_big_endian)
11854     number_to_chars_bigendian (buf, val, n);
11855   else
11856     number_to_chars_littleendian (buf, val, n);
11857 }
11858 
11859 static valueT
md_chars_to_number(buf,n)11860 md_chars_to_number (buf, n)
11861      char * buf;
11862      int    n;
11863 {
11864   valueT result = 0;
11865   unsigned char * where = (unsigned char *) buf;
11866 
11867   if (target_big_endian)
11868     {
11869       while (n--)
11870 	{
11871 	  result <<= 8;
11872 	  result |= (*where++ & 255);
11873 	}
11874     }
11875   else
11876     {
11877       while (n--)
11878 	{
11879 	  result <<= 8;
11880 	  result |= (where[n] & 255);
11881 	}
11882     }
11883 
11884   return result;
11885 }
11886 
11887 /* Turn a string in input_line_pointer into a floating point constant
11888    of type TYPE, and store the appropriate bytes in *LITP.  The number
11889    of LITTLENUMS emitted is stored in *SIZEP.  An error message is
11890    returned, or NULL on OK.
11891 
11892    Note that fp constants aren't represent in the normal way on the ARM.
11893    In big endian mode, things are as expected.  However, in little endian
11894    mode fp constants are big-endian word-wise, and little-endian byte-wise
11895    within the words.  For example, (double) 1.1 in big endian mode is
11896    the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
11897    the byte sequence 99 99 f1 3f 9a 99 99 99.
11898 
11899    ??? The format of 12 byte floats is uncertain according to gcc's arm.h.  */
11900 
11901 char *
md_atof(type,litP,sizeP)11902 md_atof (type, litP, sizeP)
11903      char   type;
11904      char * litP;
11905      int *  sizeP;
11906 {
11907   int prec;
11908   LITTLENUM_TYPE words[MAX_LITTLENUMS];
11909   char *t;
11910   int i;
11911 
11912   switch (type)
11913     {
11914     case 'f':
11915     case 'F':
11916     case 's':
11917     case 'S':
11918       prec = 2;
11919       break;
11920 
11921     case 'd':
11922     case 'D':
11923     case 'r':
11924     case 'R':
11925       prec = 4;
11926       break;
11927 
11928     case 'x':
11929     case 'X':
11930       prec = 6;
11931       break;
11932 
11933     case 'p':
11934     case 'P':
11935       prec = 6;
11936       break;
11937 
11938     default:
11939       *sizeP = 0;
11940       return _("bad call to MD_ATOF()");
11941     }
11942 
11943   t = atof_ieee (input_line_pointer, type, words);
11944   if (t)
11945     input_line_pointer = t;
11946   *sizeP = prec * 2;
11947 
11948   if (target_big_endian)
11949     {
11950       for (i = 0; i < prec; i++)
11951 	{
11952 	  md_number_to_chars (litP, (valueT) words[i], 2);
11953 	  litP += 2;
11954 	}
11955     }
11956   else
11957     {
11958       if (cpu_variant & FPU_ARCH_VFP)
11959 	for (i = prec - 1; i >= 0; i--)
11960 	  {
11961 	    md_number_to_chars (litP, (valueT) words[i], 2);
11962 	    litP += 2;
11963 	  }
11964       else
11965 	/* For a 4 byte float the order of elements in `words' is 1 0.
11966 	   For an 8 byte float the order is 1 0 3 2.  */
11967 	for (i = 0; i < prec; i += 2)
11968 	  {
11969 	    md_number_to_chars (litP, (valueT) words[i + 1], 2);
11970 	    md_number_to_chars (litP + 2, (valueT) words[i], 2);
11971 	    litP += 4;
11972 	  }
11973     }
11974 
11975   return 0;
11976 }
11977 
11978 /* The knowledge of the PC's pipeline offset is built into the insns
11979    themselves.  */
11980 
11981 long
md_pcrel_from(fixP)11982 md_pcrel_from (fixP)
11983      fixS * fixP;
11984 {
11985   if (fixP->fx_addsy
11986       && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
11987       && fixP->fx_subsy == NULL)
11988     return 0;
11989 
11990   if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
11991     {
11992       /* PC relative addressing on the Thumb is slightly odd
11993 	 as the bottom two bits of the PC are forced to zero
11994 	 for the calculation.  */
11995       return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
11996     }
11997 
11998 #ifdef TE_WINCE
11999   /* The pattern was adjusted to accommodate CE's off-by-one fixups,
12000      so we un-adjust here to compensate for the accommodation.  */
12001   return fixP->fx_where + fixP->fx_frag->fr_address + 8;
12002 #else
12003   return fixP->fx_where + fixP->fx_frag->fr_address;
12004 #endif
12005 }
12006 
12007 /* Round up a section size to the appropriate boundary.  */
12008 
12009 valueT
md_section_align(segment,size)12010 md_section_align (segment, size)
12011      segT   segment ATTRIBUTE_UNUSED;
12012      valueT size;
12013 {
12014 #ifdef OBJ_ELF
12015   return size;
12016 #else
12017   /* Round all sects to multiple of 4.  */
12018   return (size + 3) & ~3;
12019 #endif
12020 }
12021 
12022 /* Under ELF we need to default _GLOBAL_OFFSET_TABLE.
12023    Otherwise we have no need to default values of symbols.  */
12024 
12025 symbolS *
md_undefined_symbol(name)12026 md_undefined_symbol (name)
12027      char * name ATTRIBUTE_UNUSED;
12028 {
12029 #ifdef OBJ_ELF
12030   if (name[0] == '_' && name[1] == 'G'
12031       && streq (name, GLOBAL_OFFSET_TABLE_NAME))
12032     {
12033       if (!GOT_symbol)
12034 	{
12035 	  if (symbol_find (name))
12036 	    as_bad ("GOT already in the symbol table");
12037 
12038 	  GOT_symbol = symbol_new (name, undefined_section,
12039 				   (valueT) 0, & zero_address_frag);
12040 	}
12041 
12042       return GOT_symbol;
12043     }
12044 #endif
12045 
12046   return 0;
12047 }
12048 
12049 /* arm_reg_parse () := if it looks like a register, return its token and
12050    advance the pointer.  */
12051 
12052 static int
arm_reg_parse(ccp,htab)12053 arm_reg_parse (ccp, htab)
12054      register char ** ccp;
12055      struct hash_control *htab;
12056 {
12057   char * start = * ccp;
12058   char   c;
12059   char * p;
12060   struct reg_entry * reg;
12061 
12062 #ifdef REGISTER_PREFIX
12063   if (*start != REGISTER_PREFIX)
12064     return FAIL;
12065   p = start + 1;
12066 #else
12067   p = start;
12068 #ifdef OPTIONAL_REGISTER_PREFIX
12069   if (*p == OPTIONAL_REGISTER_PREFIX)
12070     p++, start++;
12071 #endif
12072 #endif
12073   if (!ISALPHA (*p) || !is_name_beginner (*p))
12074     return FAIL;
12075 
12076   c = *p++;
12077   while (ISALPHA (c) || ISDIGIT (c) || c == '_')
12078     c = *p++;
12079 
12080   *--p = 0;
12081   reg = (struct reg_entry *) hash_find (htab, start);
12082   *p = c;
12083 
12084   if (reg)
12085     {
12086       *ccp = p;
12087       return reg->number;
12088     }
12089 
12090   return FAIL;
12091 }
12092 
12093 /* Search for the following register name in each of the possible reg name
12094    tables.  Return the classification if found, or REG_TYPE_MAX if not
12095    present.  */
12096 static enum arm_reg_type
arm_reg_parse_any(cp)12097 arm_reg_parse_any (cp)
12098      char *cp;
12099 {
12100   int i;
12101 
12102   for (i = (int) REG_TYPE_FIRST; i < (int) REG_TYPE_MAX; i++)
12103     if (arm_reg_parse (&cp, all_reg_maps[i].htab) != FAIL)
12104       return (enum arm_reg_type) i;
12105 
12106   return REG_TYPE_MAX;
12107 }
12108 
12109 void
md_apply_fix3(fixP,valP,seg)12110 md_apply_fix3 (fixP, valP, seg)
12111      fixS *   fixP;
12112      valueT * valP;
12113      segT     seg;
12114 {
12115   offsetT        value = * valP;
12116   offsetT        newval;
12117   unsigned int   newimm;
12118   unsigned long  temp;
12119   int            sign;
12120   char *         buf = fixP->fx_where + fixP->fx_frag->fr_literal;
12121   arm_fix_data * arm_data = (arm_fix_data *) fixP->tc_fix_data;
12122 
12123   assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
12124 
12125   /* Note whether this will delete the relocation.  */
12126 #if 0
12127   /* Patch from REarnshaw to JDavis (disabled for the moment, since it
12128      doesn't work fully.)  */
12129   if ((fixP->fx_addsy == 0 || symbol_constant_p (fixP->fx_addsy))
12130       && !fixP->fx_pcrel)
12131 #else
12132   if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
12133 #endif
12134     fixP->fx_done = 1;
12135 
12136   /* If this symbol is in a different section then we need to leave it for
12137      the linker to deal with.  Unfortunately, md_pcrel_from can't tell,
12138      so we have to undo it's effects here.  */
12139   if (fixP->fx_pcrel)
12140     {
12141       if (fixP->fx_addsy != NULL
12142 	  && S_IS_DEFINED (fixP->fx_addsy)
12143 	  && S_GET_SEGMENT (fixP->fx_addsy) != seg)
12144 	{
12145 	  if (target_oabi
12146 	      && (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
12147 		  || fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
12148 		  ))
12149 	    value = 0;
12150 	  else
12151 	    value += md_pcrel_from (fixP);
12152 	}
12153     }
12154 
12155   /* Remember value for emit_reloc.  */
12156   fixP->fx_addnumber = value;
12157 
12158   switch (fixP->fx_r_type)
12159     {
12160     case BFD_RELOC_ARM_IMMEDIATE:
12161       newimm = validate_immediate (value);
12162       temp = md_chars_to_number (buf, INSN_SIZE);
12163 
12164       /* If the instruction will fail, see if we can fix things up by
12165 	 changing the opcode.  */
12166       if (newimm == (unsigned int) FAIL
12167 	  && (newimm = negate_data_op (&temp, value)) == (unsigned int) FAIL)
12168 	{
12169 	  as_bad_where (fixP->fx_file, fixP->fx_line,
12170 			_("invalid constant (%lx) after fixup"),
12171 			(unsigned long) value);
12172 	  break;
12173 	}
12174 
12175       newimm |= (temp & 0xfffff000);
12176       md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
12177       fixP->fx_done = 1;
12178       break;
12179 
12180     case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12181       {
12182 	unsigned int highpart = 0;
12183 	unsigned int newinsn  = 0xe1a00000; /* nop.  */
12184 
12185 	newimm = validate_immediate (value);
12186 	temp = md_chars_to_number (buf, INSN_SIZE);
12187 
12188 	/* If the instruction will fail, see if we can fix things up by
12189 	   changing the opcode.  */
12190 	if (newimm == (unsigned int) FAIL
12191 	    && (newimm = negate_data_op (& temp, value)) == (unsigned int) FAIL)
12192 	  {
12193 	    /* No ?  OK - try using two ADD instructions to generate
12194                the value.  */
12195 	    newimm = validate_immediate_twopart (value, & highpart);
12196 
12197 	    /* Yes - then make sure that the second instruction is
12198                also an add.  */
12199 	    if (newimm != (unsigned int) FAIL)
12200 	      newinsn = temp;
12201 	    /* Still No ?  Try using a negated value.  */
12202 	    else if ((newimm = validate_immediate_twopart (- value, & highpart)) != (unsigned int) FAIL)
12203 	      temp = newinsn = (temp & OPCODE_MASK) | OPCODE_SUB << DATA_OP_SHIFT;
12204 	    /* Otherwise - give up.  */
12205 	    else
12206 	      {
12207 		as_bad_where (fixP->fx_file, fixP->fx_line,
12208 			      _("unable to compute ADRL instructions for PC offset of 0x%lx"),
12209 			      (long) value);
12210 		break;
12211 	      }
12212 
12213 	    /* Replace the first operand in the 2nd instruction (which
12214 	       is the PC) with the destination register.  We have
12215 	       already added in the PC in the first instruction and we
12216 	       do not want to do it again.  */
12217 	    newinsn &= ~ 0xf0000;
12218 	    newinsn |= ((newinsn & 0x0f000) << 4);
12219 	  }
12220 
12221 	newimm |= (temp & 0xfffff000);
12222 	md_number_to_chars (buf, (valueT) newimm, INSN_SIZE);
12223 
12224 	highpart |= (newinsn & 0xfffff000);
12225 	md_number_to_chars (buf + INSN_SIZE, (valueT) highpart, INSN_SIZE);
12226       }
12227       break;
12228 
12229     case BFD_RELOC_ARM_OFFSET_IMM:
12230       sign = value >= 0;
12231 
12232       if (value < 0)
12233 	value = - value;
12234 
12235       if (validate_offset_imm (value, 0) == FAIL)
12236 	{
12237 	  as_bad_where (fixP->fx_file, fixP->fx_line,
12238 			_("bad immediate value for offset (%ld)"),
12239 			(long) value);
12240 	  break;
12241 	}
12242 
12243       newval = md_chars_to_number (buf, INSN_SIZE);
12244       newval &= 0xff7ff000;
12245       newval |= value | (sign ? INDEX_UP : 0);
12246       md_number_to_chars (buf, newval, INSN_SIZE);
12247       break;
12248 
12249     case BFD_RELOC_ARM_OFFSET_IMM8:
12250     case BFD_RELOC_ARM_HWLITERAL:
12251       sign = value >= 0;
12252 
12253       if (value < 0)
12254 	value = - value;
12255 
12256       if (validate_offset_imm (value, 1) == FAIL)
12257 	{
12258 	  if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
12259 	    as_bad_where (fixP->fx_file, fixP->fx_line,
12260 			  _("invalid literal constant: pool needs to be closer"));
12261 	  else
12262 	    as_bad (_("bad immediate value for half-word offset (%ld)"),
12263 		    (long) value);
12264 	  break;
12265 	}
12266 
12267       newval = md_chars_to_number (buf, INSN_SIZE);
12268       newval &= 0xff7ff0f0;
12269       newval |= ((value >> 4) << 8) | (value & 0xf) | (sign ? INDEX_UP : 0);
12270       md_number_to_chars (buf, newval, INSN_SIZE);
12271       break;
12272 
12273     case BFD_RELOC_ARM_LITERAL:
12274       sign = value >= 0;
12275 
12276       if (value < 0)
12277 	value = - value;
12278 
12279       if (validate_offset_imm (value, 0) == FAIL)
12280 	{
12281 	  as_bad_where (fixP->fx_file, fixP->fx_line,
12282 			_("invalid literal constant: pool needs to be closer"));
12283 	  break;
12284 	}
12285 
12286       newval = md_chars_to_number (buf, INSN_SIZE);
12287       newval &= 0xff7ff000;
12288       newval |= value | (sign ? INDEX_UP : 0);
12289       md_number_to_chars (buf, newval, INSN_SIZE);
12290       break;
12291 
12292     case BFD_RELOC_ARM_SHIFT_IMM:
12293       newval = md_chars_to_number (buf, INSN_SIZE);
12294       if (((unsigned long) value) > 32
12295 	  || (value == 32
12296 	      && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
12297 	{
12298 	  as_bad_where (fixP->fx_file, fixP->fx_line,
12299 			_("shift expression is too large"));
12300 	  break;
12301 	}
12302 
12303       if (value == 0)
12304 	/* Shifts of zero must be done as lsl.  */
12305 	newval &= ~0x60;
12306       else if (value == 32)
12307 	value = 0;
12308       newval &= 0xfffff07f;
12309       newval |= (value & 0x1f) << 7;
12310       md_number_to_chars (buf, newval, INSN_SIZE);
12311       break;
12312 
12313     case BFD_RELOC_ARM_SWI:
12314       if (arm_data->thumb_mode)
12315 	{
12316 	  if (((unsigned long) value) > 0xff)
12317 	    as_bad_where (fixP->fx_file, fixP->fx_line,
12318 			  _("invalid swi expression"));
12319 	  newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
12320 	  newval |= value;
12321 	  md_number_to_chars (buf, newval, THUMB_SIZE);
12322 	}
12323       else
12324 	{
12325 	  if (((unsigned long) value) > 0x00ffffff)
12326 	    as_bad_where (fixP->fx_file, fixP->fx_line,
12327 			  _("invalid swi expression"));
12328 	  newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
12329 	  newval |= value;
12330 	  md_number_to_chars (buf, newval, INSN_SIZE);
12331 	}
12332       break;
12333 
12334     case BFD_RELOC_ARM_MULTI:
12335       if (((unsigned long) value) > 0xffff)
12336 	as_bad_where (fixP->fx_file, fixP->fx_line,
12337 		      _("invalid expression in load/store multiple"));
12338       newval = value | md_chars_to_number (buf, INSN_SIZE);
12339       md_number_to_chars (buf, newval, INSN_SIZE);
12340       break;
12341 
12342     case BFD_RELOC_ARM_PCREL_BRANCH:
12343       newval = md_chars_to_number (buf, INSN_SIZE);
12344 
12345       /* Sign-extend a 24-bit number.  */
12346 #define SEXT24(x)	((((x) & 0xffffff) ^ (~ 0x7fffff)) + 0x800000)
12347 
12348 #ifdef OBJ_ELF
12349       if (! target_oabi)
12350 	value = fixP->fx_offset;
12351 #endif
12352 
12353       /* We are going to store value (shifted right by two) in the
12354 	 instruction, in a 24 bit, signed field.  Thus we need to check
12355 	 that none of the top 8 bits of the shifted value (top 7 bits of
12356          the unshifted, unsigned value) are set, or that they are all set.  */
12357       if ((value & ~ ((offsetT) 0x1ffffff)) != 0
12358 	  && ((value & ~ ((offsetT) 0x1ffffff)) != ~ ((offsetT) 0x1ffffff)))
12359 	{
12360 #ifdef OBJ_ELF
12361 	  /* Normally we would be stuck at this point, since we cannot store
12362 	     the absolute address that is the destination of the branch in the
12363 	     24 bits of the branch instruction.  If however, we happen to know
12364 	     that the destination of the branch is in the same section as the
12365 	     branch instruction itself, then we can compute the relocation for
12366 	     ourselves and not have to bother the linker with it.
12367 
12368 	     FIXME: The tests for OBJ_ELF and ! target_oabi are only here
12369 	     because I have not worked out how to do this for OBJ_COFF or
12370 	     target_oabi.  */
12371 	  if (! target_oabi
12372 	      && fixP->fx_addsy != NULL
12373 	      && S_IS_DEFINED (fixP->fx_addsy)
12374 	      && S_GET_SEGMENT (fixP->fx_addsy) == seg)
12375 	    {
12376 	      /* Get pc relative value to go into the branch.  */
12377 	      value = * valP;
12378 
12379 	      /* Permit a backward branch provided that enough bits
12380 		 are set.  Allow a forwards branch, provided that
12381 		 enough bits are clear.  */
12382 	      if (   (value & ~ ((offsetT) 0x1ffffff)) == ~ ((offsetT) 0x1ffffff)
12383 		  || (value & ~ ((offsetT) 0x1ffffff)) == 0)
12384 		fixP->fx_done = 1;
12385 	    }
12386 
12387 	  if (! fixP->fx_done)
12388 #endif
12389 	    as_bad_where (fixP->fx_file, fixP->fx_line,
12390 			  _("GAS can't handle same-section branch dest >= 0x04000000"));
12391 	}
12392 
12393       value >>= 2;
12394       value += SEXT24 (newval);
12395 
12396       if (    (value & ~ ((offsetT) 0xffffff)) != 0
12397 	  && ((value & ~ ((offsetT) 0xffffff)) != ~ ((offsetT) 0xffffff)))
12398 	as_bad_where (fixP->fx_file, fixP->fx_line,
12399 		      _("out of range branch"));
12400 
12401       newval = (value & 0x00ffffff) | (newval & 0xff000000);
12402       md_number_to_chars (buf, newval, INSN_SIZE);
12403       break;
12404 
12405     case BFD_RELOC_ARM_PCREL_BLX:
12406       {
12407 	offsetT hbit;
12408 	newval = md_chars_to_number (buf, INSN_SIZE);
12409 
12410 #ifdef OBJ_ELF
12411 	if (! target_oabi)
12412 	  value = fixP->fx_offset;
12413 #endif
12414 	hbit   = (value >> 1) & 1;
12415 	value  = (value >> 2) & 0x00ffffff;
12416 	value  = (value + (newval & 0x00ffffff)) & 0x00ffffff;
12417 	newval = value | (newval & 0xfe000000) | (hbit << 24);
12418 	md_number_to_chars (buf, newval, INSN_SIZE);
12419       }
12420       break;
12421 
12422     case BFD_RELOC_THUMB_PCREL_BRANCH9: /* Conditional branch.  */
12423       newval = md_chars_to_number (buf, THUMB_SIZE);
12424       {
12425 	addressT diff = (newval & 0xff) << 1;
12426 	if (diff & 0x100)
12427 	  diff |= ~0xff;
12428 
12429 	value += diff;
12430 	if ((value & ~0xff) && ((value & ~0xff) != ~0xff))
12431 	  as_bad_where (fixP->fx_file, fixP->fx_line,
12432 			_("branch out of range"));
12433 	newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
12434       }
12435       md_number_to_chars (buf, newval, THUMB_SIZE);
12436       break;
12437 
12438     case BFD_RELOC_THUMB_PCREL_BRANCH12: /* Unconditional branch.  */
12439       newval = md_chars_to_number (buf, THUMB_SIZE);
12440       {
12441 	addressT diff = (newval & 0x7ff) << 1;
12442 	if (diff & 0x800)
12443 	  diff |= ~0x7ff;
12444 
12445 	value += diff;
12446 	if ((value & ~0x7ff) && ((value & ~0x7ff) != ~0x7ff))
12447 	  as_bad_where (fixP->fx_file, fixP->fx_line,
12448 			_("branch out of range"));
12449 	newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
12450       }
12451       md_number_to_chars (buf, newval, THUMB_SIZE);
12452       break;
12453 
12454     case BFD_RELOC_THUMB_PCREL_BLX:
12455     case BFD_RELOC_THUMB_PCREL_BRANCH23:
12456       {
12457 	offsetT newval2;
12458 	addressT diff;
12459 
12460 	newval  = md_chars_to_number (buf, THUMB_SIZE);
12461 	newval2 = md_chars_to_number (buf + THUMB_SIZE, THUMB_SIZE);
12462 	diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
12463 	if (diff & 0x400000)
12464 	  diff |= ~0x3fffff;
12465 #ifdef OBJ_ELF
12466 	value = fixP->fx_offset;
12467 #endif
12468 	value += diff;
12469 
12470 	if ((value & ~0x3fffff) && ((value & ~0x3fffff) != ~0x3fffff))
12471 	  as_bad_where (fixP->fx_file, fixP->fx_line,
12472 			_("branch with link out of range"));
12473 
12474 	newval  = (newval  & 0xf800) | ((value & 0x7fffff) >> 12);
12475 	newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
12476 	if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX)
12477 	  /* For a BLX instruction, make sure that the relocation is rounded up
12478 	     to a word boundary.  This follows the semantics of the instruction
12479 	     which specifies that bit 1 of the target address will come from bit
12480 	     1 of the base address.  */
12481 	  newval2 = (newval2 + 1) & ~ 1;
12482 	md_number_to_chars (buf, newval, THUMB_SIZE);
12483 	md_number_to_chars (buf + THUMB_SIZE, newval2, THUMB_SIZE);
12484       }
12485       break;
12486 
12487     case BFD_RELOC_8:
12488       if (fixP->fx_done || fixP->fx_pcrel)
12489 	md_number_to_chars (buf, value, 1);
12490 #ifdef OBJ_ELF
12491       else if (!target_oabi)
12492 	{
12493 	  value = fixP->fx_offset;
12494 	  md_number_to_chars (buf, value, 1);
12495 	}
12496 #endif
12497       break;
12498 
12499     case BFD_RELOC_16:
12500       if (fixP->fx_done || fixP->fx_pcrel)
12501 	md_number_to_chars (buf, value, 2);
12502 #ifdef OBJ_ELF
12503       else if (!target_oabi)
12504 	{
12505 	  value = fixP->fx_offset;
12506 	  md_number_to_chars (buf, value, 2);
12507 	}
12508 #endif
12509       break;
12510 
12511 #ifdef OBJ_ELF
12512     case BFD_RELOC_ARM_GOT32:
12513     case BFD_RELOC_ARM_GOTOFF:
12514       md_number_to_chars (buf, 0, 4);
12515       break;
12516 #endif
12517 
12518     case BFD_RELOC_RVA:
12519     case BFD_RELOC_32:
12520       if (fixP->fx_done || fixP->fx_pcrel)
12521 	md_number_to_chars (buf, value, 4);
12522 #ifdef OBJ_ELF
12523       else if (!target_oabi)
12524 	{
12525 	  value = fixP->fx_offset;
12526 	  md_number_to_chars (buf, value, 4);
12527 	}
12528 #endif
12529       break;
12530 
12531 #ifdef OBJ_ELF
12532     case BFD_RELOC_ARM_PLT32:
12533       /* It appears the instruction is fully prepared at this point.  */
12534       break;
12535 #endif
12536 
12537     case BFD_RELOC_ARM_CP_OFF_IMM:
12538       sign = value >= 0;
12539       if (value < -1023 || value > 1023 || (value & 3))
12540 	as_bad_where (fixP->fx_file, fixP->fx_line,
12541 		      _("illegal value for co-processor offset"));
12542       if (value < 0)
12543 	value = -value;
12544       newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12545       newval |= (value >> 2) | (sign ? INDEX_UP : 0);
12546       md_number_to_chars (buf, newval, INSN_SIZE);
12547       break;
12548 
12549     case BFD_RELOC_ARM_CP_OFF_IMM_S2:
12550       sign = value >= 0;
12551       if (value < -255 || value > 255)
12552         as_bad_where (fixP->fx_file, fixP->fx_line,
12553                       _("Illegal value for co-processor offset"));
12554       if (value < 0)
12555         value = -value;
12556       newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
12557       newval |= value | (sign ?  INDEX_UP : 0);
12558       md_number_to_chars (buf, newval , INSN_SIZE);
12559       break;
12560 
12561     case BFD_RELOC_ARM_THUMB_OFFSET:
12562       newval = md_chars_to_number (buf, THUMB_SIZE);
12563       /* Exactly what ranges, and where the offset is inserted depends
12564 	 on the type of instruction, we can establish this from the
12565 	 top 4 bits.  */
12566       switch (newval >> 12)
12567 	{
12568 	case 4: /* PC load.  */
12569 	  /* Thumb PC loads are somewhat odd, bit 1 of the PC is
12570 	     forced to zero for these loads, so we will need to round
12571 	     up the offset if the instruction address is not word
12572 	     aligned (since the final address produced must be, and
12573 	     we can only describe word-aligned immediate offsets).  */
12574 
12575 	  if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
12576 	    as_bad_where (fixP->fx_file, fixP->fx_line,
12577 			  _("invalid offset, target not word aligned (0x%08X)"),
12578 			  (unsigned int) (fixP->fx_frag->fr_address
12579 					  + fixP->fx_where + value));
12580 
12581 	  if ((value + 2) & ~0x3fe)
12582 	    as_bad_where (fixP->fx_file, fixP->fx_line,
12583 			  _("invalid offset, value too big (0x%08lX)"),
12584 			  (long) value);
12585 
12586 	  /* Round up, since pc will be rounded down.  */
12587 	  newval |= (value + 2) >> 2;
12588 	  break;
12589 
12590 	case 9: /* SP load/store.  */
12591 	  if (value & ~0x3fc)
12592 	    as_bad_where (fixP->fx_file, fixP->fx_line,
12593 			  _("invalid offset, value too big (0x%08lX)"),
12594 			  (long) value);
12595 	  newval |= value >> 2;
12596 	  break;
12597 
12598 	case 6: /* Word load/store.  */
12599 	  if (value & ~0x7c)
12600 	    as_bad_where (fixP->fx_file, fixP->fx_line,
12601 			  _("invalid offset, value too big (0x%08lX)"),
12602 			  (long) value);
12603 	  newval |= value << 4; /* 6 - 2.  */
12604 	  break;
12605 
12606 	case 7: /* Byte load/store.  */
12607 	  if (value & ~0x1f)
12608 	    as_bad_where (fixP->fx_file, fixP->fx_line,
12609 			  _("invalid offset, value too big (0x%08lX)"),
12610 			  (long) value);
12611 	  newval |= value << 6;
12612 	  break;
12613 
12614 	case 8: /* Halfword load/store.  */
12615 	  if (value & ~0x3e)
12616 	    as_bad_where (fixP->fx_file, fixP->fx_line,
12617 			  _("invalid offset, value too big (0x%08lX)"),
12618 			  (long) value);
12619 	  newval |= value << 5; /* 6 - 1.  */
12620 	  break;
12621 
12622 	default:
12623 	  as_bad_where (fixP->fx_file, fixP->fx_line,
12624 			"Unable to process relocation for thumb opcode: %lx",
12625 			(unsigned long) newval);
12626 	  break;
12627 	}
12628       md_number_to_chars (buf, newval, THUMB_SIZE);
12629       break;
12630 
12631     case BFD_RELOC_ARM_THUMB_ADD:
12632       /* This is a complicated relocation, since we use it for all of
12633          the following immediate relocations:
12634 
12635 	    3bit ADD/SUB
12636 	    8bit ADD/SUB
12637 	    9bit ADD/SUB SP word-aligned
12638 	   10bit ADD PC/SP word-aligned
12639 
12640          The type of instruction being processed is encoded in the
12641          instruction field:
12642 
12643 	   0x8000  SUB
12644 	   0x00F0  Rd
12645 	   0x000F  Rs
12646       */
12647       newval = md_chars_to_number (buf, THUMB_SIZE);
12648       {
12649 	int rd = (newval >> 4) & 0xf;
12650 	int rs = newval & 0xf;
12651 	int subtract = newval & 0x8000;
12652 
12653 	if (rd == REG_SP)
12654 	  {
12655 	    if (value & ~0x1fc)
12656 	      as_bad_where (fixP->fx_file, fixP->fx_line,
12657 			    _("invalid immediate for stack address calculation"));
12658 	    newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
12659 	    newval |= value >> 2;
12660 	  }
12661 	else if (rs == REG_PC || rs == REG_SP)
12662 	  {
12663 	    if (subtract ||
12664 		value & ~0x3fc)
12665 	      as_bad_where (fixP->fx_file, fixP->fx_line,
12666 			    _("invalid immediate for address calculation (value = 0x%08lX)"),
12667 			    (unsigned long) value);
12668 	    newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
12669 	    newval |= rd << 8;
12670 	    newval |= value >> 2;
12671 	  }
12672 	else if (rs == rd)
12673 	  {
12674 	    if (value & ~0xff)
12675 	      as_bad_where (fixP->fx_file, fixP->fx_line,
12676 			    _("invalid 8bit immediate"));
12677 	    newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
12678 	    newval |= (rd << 8) | value;
12679 	  }
12680 	else
12681 	  {
12682 	    if (value & ~0x7)
12683 	      as_bad_where (fixP->fx_file, fixP->fx_line,
12684 			    _("invalid 3bit immediate"));
12685 	    newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
12686 	    newval |= rd | (rs << 3) | (value << 6);
12687 	  }
12688       }
12689       md_number_to_chars (buf, newval, THUMB_SIZE);
12690       break;
12691 
12692     case BFD_RELOC_ARM_THUMB_IMM:
12693       newval = md_chars_to_number (buf, THUMB_SIZE);
12694       switch (newval >> 11)
12695 	{
12696 	case 0x04: /* 8bit immediate MOV.  */
12697 	case 0x05: /* 8bit immediate CMP.  */
12698 	  if (value < 0 || value > 255)
12699 	    as_bad_where (fixP->fx_file, fixP->fx_line,
12700 			  _("invalid immediate: %ld is too large"),
12701 			  (long) value);
12702 	  newval |= value;
12703 	  break;
12704 
12705 	default:
12706 	  abort ();
12707 	}
12708       md_number_to_chars (buf, newval, THUMB_SIZE);
12709       break;
12710 
12711     case BFD_RELOC_ARM_THUMB_SHIFT:
12712       /* 5bit shift value (0..31).  */
12713       if (value < 0 || value > 31)
12714 	as_bad_where (fixP->fx_file, fixP->fx_line,
12715 		      _("illegal Thumb shift value: %ld"), (long) value);
12716       newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
12717       newval |= value << 6;
12718       md_number_to_chars (buf, newval, THUMB_SIZE);
12719       break;
12720 
12721     case BFD_RELOC_VTABLE_INHERIT:
12722     case BFD_RELOC_VTABLE_ENTRY:
12723       fixP->fx_done = 0;
12724       return;
12725 
12726     case BFD_RELOC_NONE:
12727     default:
12728       as_bad_where (fixP->fx_file, fixP->fx_line,
12729 		    _("bad relocation fixup type (%d)"), fixP->fx_r_type);
12730     }
12731 }
12732 
12733 /* Translate internal representation of relocation info to BFD target
12734    format.  */
12735 
12736 arelent *
tc_gen_reloc(section,fixp)12737 tc_gen_reloc (section, fixp)
12738      asection * section ATTRIBUTE_UNUSED;
12739      fixS * fixp;
12740 {
12741   arelent * reloc;
12742   bfd_reloc_code_real_type code;
12743 
12744   reloc = (arelent *) xmalloc (sizeof (arelent));
12745 
12746   reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
12747   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
12748   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
12749 
12750   /* @@ Why fx_addnumber sometimes and fx_offset other times?  */
12751 #ifndef OBJ_ELF
12752   if (fixp->fx_pcrel == 0)
12753     reloc->addend = fixp->fx_offset;
12754   else
12755     reloc->addend = fixp->fx_offset = reloc->address;
12756 #else  /* OBJ_ELF */
12757   reloc->addend = fixp->fx_offset;
12758 #endif
12759 
12760   switch (fixp->fx_r_type)
12761     {
12762     case BFD_RELOC_8:
12763       if (fixp->fx_pcrel)
12764 	{
12765 	  code = BFD_RELOC_8_PCREL;
12766 	  break;
12767 	}
12768 
12769     case BFD_RELOC_16:
12770       if (fixp->fx_pcrel)
12771 	{
12772 	  code = BFD_RELOC_16_PCREL;
12773 	  break;
12774 	}
12775 
12776     case BFD_RELOC_32:
12777       if (fixp->fx_pcrel)
12778 	{
12779 	  code = BFD_RELOC_32_PCREL;
12780 	  break;
12781 	}
12782 
12783     case BFD_RELOC_ARM_PCREL_BRANCH:
12784     case BFD_RELOC_ARM_PCREL_BLX:
12785     case BFD_RELOC_RVA:
12786     case BFD_RELOC_THUMB_PCREL_BRANCH9:
12787     case BFD_RELOC_THUMB_PCREL_BRANCH12:
12788     case BFD_RELOC_THUMB_PCREL_BRANCH23:
12789     case BFD_RELOC_THUMB_PCREL_BLX:
12790     case BFD_RELOC_VTABLE_ENTRY:
12791     case BFD_RELOC_VTABLE_INHERIT:
12792       code = fixp->fx_r_type;
12793       break;
12794 
12795     case BFD_RELOC_ARM_LITERAL:
12796     case BFD_RELOC_ARM_HWLITERAL:
12797       /* If this is called then the a literal has
12798 	 been referenced across a section boundary.  */
12799       as_bad_where (fixp->fx_file, fixp->fx_line,
12800 		    _("literal referenced across section boundary"));
12801       return NULL;
12802 
12803 #ifdef OBJ_ELF
12804     case BFD_RELOC_ARM_GOT32:
12805     case BFD_RELOC_ARM_GOTOFF:
12806     case BFD_RELOC_ARM_PLT32:
12807       code = fixp->fx_r_type;
12808       break;
12809 #endif
12810 
12811     case BFD_RELOC_ARM_IMMEDIATE:
12812       as_bad_where (fixp->fx_file, fixp->fx_line,
12813 		    _("internal relocation (type: IMMEDIATE) not fixed up"));
12814       return NULL;
12815 
12816     case BFD_RELOC_ARM_ADRL_IMMEDIATE:
12817       as_bad_where (fixp->fx_file, fixp->fx_line,
12818 		    _("ADRL used for a symbol not defined in the same file"));
12819       return NULL;
12820 
12821     case BFD_RELOC_ARM_OFFSET_IMM:
12822       if (fixp->fx_addsy != NULL
12823 	  && !S_IS_DEFINED (fixp->fx_addsy)
12824 	  && S_IS_LOCAL (fixp->fx_addsy))
12825 	{
12826 	  as_bad_where (fixp->fx_file, fixp->fx_line,
12827 			_("undefined local label `%s'"),
12828 			S_GET_NAME (fixp->fx_addsy));
12829 	  return NULL;
12830 	}
12831 
12832       as_bad_where (fixp->fx_file, fixp->fx_line,
12833 		    _("internal_relocation (type: OFFSET_IMM) not fixed up"));
12834       return NULL;
12835 
12836     default:
12837       {
12838 	char * type;
12839 
12840 	switch (fixp->fx_r_type)
12841 	  {
12842 	  case BFD_RELOC_ARM_OFFSET_IMM8:  type = "OFFSET_IMM8";  break;
12843 	  case BFD_RELOC_ARM_SHIFT_IMM:    type = "SHIFT_IMM";    break;
12844 	  case BFD_RELOC_ARM_SWI:          type = "SWI";          break;
12845 	  case BFD_RELOC_ARM_MULTI:        type = "MULTI";        break;
12846 	  case BFD_RELOC_ARM_CP_OFF_IMM:   type = "CP_OFF_IMM";   break;
12847 	  case BFD_RELOC_ARM_THUMB_ADD:    type = "THUMB_ADD";    break;
12848 	  case BFD_RELOC_ARM_THUMB_SHIFT:  type = "THUMB_SHIFT";  break;
12849 	  case BFD_RELOC_ARM_THUMB_IMM:    type = "THUMB_IMM";    break;
12850 	  case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
12851 	  default:                         type = _("<unknown>"); break;
12852 	  }
12853 	as_bad_where (fixp->fx_file, fixp->fx_line,
12854 		      _("cannot represent %s relocation in this object file format"),
12855 		      type);
12856 	return NULL;
12857       }
12858     }
12859 
12860 #ifdef OBJ_ELF
12861   if ((code == BFD_RELOC_32_PCREL || code == BFD_RELOC_32)
12862       && GOT_symbol
12863       && fixp->fx_addsy == GOT_symbol)
12864     {
12865       code = BFD_RELOC_ARM_GOTPC;
12866       reloc->addend = fixp->fx_offset = reloc->address;
12867     }
12868 #endif
12869 
12870   reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
12871 
12872   if (reloc->howto == NULL)
12873     {
12874       as_bad_where (fixp->fx_file, fixp->fx_line,
12875 		    _("cannot represent %s relocation in this object file format"),
12876 		    bfd_get_reloc_code_name (code));
12877       return NULL;
12878     }
12879 
12880   /* HACK: Since arm ELF uses Rel instead of Rela, encode the
12881      vtable entry to be used in the relocation's section offset.  */
12882   if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
12883     reloc->address = fixp->fx_offset;
12884 
12885   return reloc;
12886 }
12887 
12888 int
md_estimate_size_before_relax(fragP,segtype)12889 md_estimate_size_before_relax (fragP, segtype)
12890      fragS * fragP ATTRIBUTE_UNUSED;
12891      segT    segtype ATTRIBUTE_UNUSED;
12892 {
12893   as_fatal (_("md_estimate_size_before_relax\n"));
12894   return 1;
12895 }
12896 
12897 static void
output_inst(str)12898 output_inst (str)
12899      const char *str;
12900 {
12901   char * to = NULL;
12902 
12903   if (inst.error)
12904     {
12905       as_bad ("%s -- `%s'", inst.error, str);
12906       return;
12907     }
12908 
12909   to = frag_more (inst.size);
12910 
12911   if (thumb_mode && (inst.size > THUMB_SIZE))
12912     {
12913       assert (inst.size == (2 * THUMB_SIZE));
12914       md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
12915       md_number_to_chars (to + THUMB_SIZE, inst.instruction, THUMB_SIZE);
12916     }
12917   else if (inst.size > INSN_SIZE)
12918     {
12919       assert (inst.size == (2 * INSN_SIZE));
12920       md_number_to_chars (to, inst.instruction, INSN_SIZE);
12921       md_number_to_chars (to + INSN_SIZE, inst.instruction, INSN_SIZE);
12922     }
12923   else
12924     md_number_to_chars (to, inst.instruction, inst.size);
12925 
12926   if (inst.reloc.type != BFD_RELOC_NONE)
12927     fix_new_arm (frag_now, to - frag_now->fr_literal,
12928 		 inst.size, & inst.reloc.exp, inst.reloc.pc_rel,
12929 		 inst.reloc.type);
12930 
12931 #ifdef OBJ_ELF
12932   dwarf2_emit_insn (inst.size);
12933 #endif
12934 }
12935 
12936 void
md_assemble(str)12937 md_assemble (str)
12938      char * str;
12939 {
12940   char  c;
12941   char *p;
12942   char *start;
12943 
12944   /* Align the instruction.
12945      This may not be the right thing to do but ...  */
12946 #if 0
12947   arm_align (2, 0);
12948 #endif
12949 
12950   /* Align the previous label if needed.  */
12951   if (last_label_seen != NULL)
12952     {
12953       symbol_set_frag (last_label_seen, frag_now);
12954       S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
12955       S_SET_SEGMENT (last_label_seen, now_seg);
12956     }
12957 
12958   memset (&inst, '\0', sizeof (inst));
12959   inst.reloc.type = BFD_RELOC_NONE;
12960 
12961   skip_whitespace (str);
12962 
12963   /* Scan up to the end of the op-code, which must end in white space or
12964      end of string.  */
12965   for (start = p = str; *p != '\0'; p++)
12966     if (*p == ' ')
12967       break;
12968 
12969   if (p == str)
12970     {
12971       as_bad (_("no operator -- statement `%s'\n"), str);
12972       return;
12973     }
12974 
12975   if (thumb_mode)
12976     {
12977       const struct thumb_opcode * opcode;
12978 
12979       c = *p;
12980       *p = '\0';
12981       opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
12982       *p = c;
12983 
12984       if (opcode)
12985 	{
12986 	  /* Check that this instruction is supported for this CPU.  */
12987 	  if (thumb_mode == 1 && (opcode->variant & cpu_variant) == 0)
12988 	    {
12989 	      as_bad (_("selected processor does not support `%s'"), str);
12990 	      return;
12991 	    }
12992 
12993 	  mapping_state (MAP_THUMB);
12994 	  inst.instruction = opcode->value;
12995 	  inst.size = opcode->size;
12996 	  (*opcode->parms) (p);
12997 	  output_inst (str);
12998 	  return;
12999 	}
13000     }
13001   else
13002     {
13003       const struct asm_opcode * opcode;
13004 
13005       c = *p;
13006       *p = '\0';
13007       opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
13008       *p = c;
13009 
13010       if (opcode)
13011 	{
13012 	  /* Check that this instruction is supported for this CPU.  */
13013 	  if ((opcode->variant & cpu_variant) == 0)
13014 	    {
13015 	      as_bad (_("selected processor does not support `%s'"), str);
13016 	      return;
13017 	    }
13018 
13019           mapping_state (MAP_ARM);
13020 	  inst.instruction = opcode->value;
13021 	  inst.size = INSN_SIZE;
13022 	  (*opcode->parms) (p);
13023 	  output_inst (str);
13024 	  return;
13025 	}
13026     }
13027 
13028   /* It wasn't an instruction, but it might be a register alias of the form
13029      alias .req reg.  */
13030   if (create_register_alias (str, p))
13031     return;
13032 
13033   as_bad (_("bad instruction `%s'"), start);
13034 }
13035 
13036 /* md_parse_option
13037       Invocation line includes a switch not recognized by the base assembler.
13038       See if it's a processor-specific option.
13039 
13040       This routine is somewhat complicated by the need for backwards
13041       compatibility (since older releases of gcc can't be changed).
13042       The new options try to make the interface as compatible as
13043       possible with GCC.
13044 
13045       New options (supported) are:
13046 
13047 	      -mcpu=<cpu name>		 Assemble for selected processor
13048 	      -march=<architecture name> Assemble for selected architecture
13049 	      -mfpu=<fpu architecture>	 Assemble for selected FPU.
13050 	      -EB/-mbig-endian		 Big-endian
13051 	      -EL/-mlittle-endian	 Little-endian
13052 	      -k			 Generate PIC code
13053 	      -mthumb			 Start in Thumb mode
13054 	      -mthumb-interwork		 Code supports ARM/Thumb interworking
13055 
13056       For now we will also provide support for:
13057 
13058 	      -mapcs-32			 32-bit Program counter
13059 	      -mapcs-26			 26-bit Program counter
13060 	      -macps-float		 Floats passed in FP registers
13061 	      -mapcs-reentrant		 Reentrant code
13062 	      -matpcs
13063       (sometime these will probably be replaced with -mapcs=<list of options>
13064       and -matpcs=<list of options>)
13065 
13066       The remaining options are only supported for back-wards compatibility.
13067       Cpu variants, the arm part is optional:
13068               -m[arm]1                Currently not supported.
13069               -m[arm]2, -m[arm]250    Arm 2 and Arm 250 processor
13070               -m[arm]3                Arm 3 processor
13071               -m[arm]6[xx],           Arm 6 processors
13072               -m[arm]7[xx][t][[d]m]   Arm 7 processors
13073               -m[arm]8[10]            Arm 8 processors
13074               -m[arm]9[20][tdmi]      Arm 9 processors
13075               -mstrongarm[110[0]]     StrongARM processors
13076               -mxscale                XScale processors
13077               -m[arm]v[2345[t[e]]]    Arm architectures
13078               -mall                   All (except the ARM1)
13079       FP variants:
13080               -mfpa10, -mfpa11        FPA10 and 11 co-processor instructions
13081               -mfpe-old               (No float load/store multiples)
13082 	      -mvfpxd		      VFP Single precision
13083 	      -mvfp		      All VFP
13084               -mno-fpu                Disable all floating point instructions
13085 
13086       The following CPU names are recognized:
13087 	      arm1, arm2, arm250, arm3, arm6, arm600, arm610, arm620,
13088 	      arm7, arm7m, arm7d, arm7dm, arm7di, arm7dmi, arm70, arm700,
13089 	      arm700i, arm710 arm710t, arm720, arm720t, arm740t, arm710c,
13090 	      arm7100, arm7500, arm7500fe, arm7tdmi, arm8, arm810, arm9,
13091 	      arm920, arm920t, arm940t, arm946, arm966, arm9tdmi, arm9e,
13092 	      arm10t arm10e, arm1020t, arm1020e, arm10200e,
13093 	      strongarm, strongarm110, strongarm1100, strongarm1110, xscale.
13094 
13095       */
13096 
13097 const char * md_shortopts = "m:k";
13098 
13099 #ifdef ARM_BI_ENDIAN
13100 #define OPTION_EB (OPTION_MD_BASE + 0)
13101 #define OPTION_EL (OPTION_MD_BASE + 1)
13102 #else
13103 #if TARGET_BYTES_BIG_ENDIAN
13104 #define OPTION_EB (OPTION_MD_BASE + 0)
13105 #else
13106 #define OPTION_EL (OPTION_MD_BASE + 1)
13107 #endif
13108 #endif
13109 
13110 struct option md_longopts[] =
13111 {
13112 #ifdef OPTION_EB
13113   {"EB", no_argument, NULL, OPTION_EB},
13114 #endif
13115 #ifdef OPTION_EL
13116   {"EL", no_argument, NULL, OPTION_EL},
13117 #endif
13118   {NULL, no_argument, NULL, 0}
13119 };
13120 
13121 size_t md_longopts_size = sizeof (md_longopts);
13122 
13123 struct arm_option_table
13124 {
13125   char *option;		/* Option name to match.  */
13126   char *help;		/* Help information.  */
13127   int  *var;		/* Variable to change.  */
13128   int   value;		/* What to change it to.  */
13129   char *deprecated;	/* If non-null, print this message.  */
13130 };
13131 
13132 struct arm_option_table arm_opts[] =
13133 {
13134   {"k",      N_("generate PIC code"),      &pic_code,    1, NULL},
13135   {"mthumb", N_("assemble Thumb code"),    &thumb_mode,  1, NULL},
13136   {"mthumb-interwork", N_("support ARM/Thumb interworking"),
13137    &support_interwork, 1, NULL},
13138   {"moabi",  N_("use old ABI (ELF only)"), &target_oabi, 1, NULL},
13139   {"mapcs-32", N_("code uses 32-bit program counter"), &uses_apcs_26, 0, NULL},
13140   {"mapcs-26", N_("code uses 26-bit program counter"), &uses_apcs_26, 1, NULL},
13141   {"mapcs-float", N_("floating point args are in fp regs"), &uses_apcs_float,
13142    1, NULL},
13143   {"mapcs-reentrant", N_("re-entrant code"), &pic_code, 1, NULL},
13144   {"matpcs", N_("code is ATPCS conformant"), &atpcs, 1, NULL},
13145   {"mbig-endian", N_("assemble for big-endian"), &target_big_endian, 1, NULL},
13146   {"mlittle-endian", N_("assemble for little-endian"), &target_big_endian, 1,
13147    NULL},
13148 
13149   /* These are recognized by the assembler, but have no affect on code.  */
13150   {"mapcs-frame", N_("use frame pointer"), NULL, 0, NULL},
13151   {"mapcs-stack-check", N_("use stack size checking"), NULL, 0, NULL},
13152 
13153   /* DON'T add any new processors to this list -- we want the whole list
13154      to go away...  Add them to the processors table instead.  */
13155   {"marm1",	 NULL, &legacy_cpu, ARM_ARCH_V1,  N_("use -mcpu=arm1")},
13156   {"m1",	 NULL, &legacy_cpu, ARM_ARCH_V1,  N_("use -mcpu=arm1")},
13157   {"marm2",	 NULL, &legacy_cpu, ARM_ARCH_V2,  N_("use -mcpu=arm2")},
13158   {"m2",	 NULL, &legacy_cpu, ARM_ARCH_V2,  N_("use -mcpu=arm2")},
13159   {"marm250",	 NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13160   {"m250",	 NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm250")},
13161   {"marm3",	 NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13162   {"m3",	 NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -mcpu=arm3")},
13163   {"marm6",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm6")},
13164   {"m6",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm6")},
13165   {"marm600",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm600")},
13166   {"m600",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm600")},
13167   {"marm610",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm610")},
13168   {"m610",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm610")},
13169   {"marm620",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm620")},
13170   {"m620",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm620")},
13171   {"marm7",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7")},
13172   {"m7",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7")},
13173   {"marm70",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm70")},
13174   {"m70",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm70")},
13175   {"marm700",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm700")},
13176   {"m700",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm700")},
13177   {"marm700i",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm700i")},
13178   {"m700i",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm700i")},
13179   {"marm710",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm710")},
13180   {"m710",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm710")},
13181   {"marm710c",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm710c")},
13182   {"m710c",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm710c")},
13183   {"marm720",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm720")},
13184   {"m720",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm720")},
13185   {"marm7d",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7d")},
13186   {"m7d",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7d")},
13187   {"marm7di",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7di")},
13188   {"m7di",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7di")},
13189   {"marm7m",	 NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13190   {"m7m",	 NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7m")},
13191   {"marm7dm",	 NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13192   {"m7dm",	 NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dm")},
13193   {"marm7dmi",	 NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13194   {"m7dmi",	 NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -mcpu=arm7dmi")},
13195   {"marm7100",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7100")},
13196   {"m7100",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7100")},
13197   {"marm7500",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7500")},
13198   {"m7500",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7500")},
13199   {"marm7500fe", NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7500fe")},
13200   {"m7500fe",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -mcpu=arm7500fe")},
13201   {"marm7t",	 NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13202   {"m7t",	 NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13203   {"marm7tdmi",	 NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13204   {"m7tdmi",	 NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm7tdmi")},
13205   {"marm710t",	 NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13206   {"m710t",	 NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm710t")},
13207   {"marm720t",	 NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13208   {"m720t",	 NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm720t")},
13209   {"marm740t",	 NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13210   {"m740t",	 NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm740t")},
13211   {"marm8",	 NULL, &legacy_cpu, ARM_ARCH_V4,  N_("use -mcpu=arm8")},
13212   {"m8",	 NULL, &legacy_cpu, ARM_ARCH_V4,  N_("use -mcpu=arm8")},
13213   {"marm810",	 NULL, &legacy_cpu, ARM_ARCH_V4,  N_("use -mcpu=arm810")},
13214   {"m810",	 NULL, &legacy_cpu, ARM_ARCH_V4,  N_("use -mcpu=arm810")},
13215   {"marm9",	 NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13216   {"m9",	 NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9")},
13217   {"marm9tdmi",	 NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13218   {"m9tdmi",	 NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm9tdmi")},
13219   {"marm920",	 NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13220   {"m920",	 NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm920")},
13221   {"marm940",	 NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13222   {"m940",	 NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -mcpu=arm940")},
13223   {"mstrongarm", NULL, &legacy_cpu, ARM_ARCH_V4,  N_("use -mcpu=strongarm")},
13224   {"mstrongarm110", NULL, &legacy_cpu, ARM_ARCH_V4,
13225    N_("use -mcpu=strongarm110")},
13226   {"mstrongarm1100", NULL, &legacy_cpu, ARM_ARCH_V4,
13227    N_("use -mcpu=strongarm1100")},
13228   {"mstrongarm1110", NULL, &legacy_cpu, ARM_ARCH_V4,
13229    N_("use -mcpu=strongarm1110")},
13230   {"mxscale",	 NULL, &legacy_cpu, ARM_ARCH_XSCALE, N_("use -mcpu=xscale")},
13231   {"miwmmxt",	 NULL, &legacy_cpu, ARM_ARCH_IWMMXT, N_("use -mcpu=iwmmxt")},
13232   {"mall",	 NULL, &legacy_cpu, ARM_ANY,      N_("use -mcpu=all")},
13233 
13234   /* Architecture variants -- don't add any more to this list either.  */
13235   {"mv2",	 NULL, &legacy_cpu, ARM_ARCH_V2,  N_("use -march=armv2")},
13236   {"marmv2",	 NULL, &legacy_cpu, ARM_ARCH_V2,  N_("use -march=armv2")},
13237   {"mv2a",	 NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13238   {"marmv2a",	 NULL, &legacy_cpu, ARM_ARCH_V2S, N_("use -march=armv2a")},
13239   {"mv3",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -march=armv3")},
13240   {"marmv3",	 NULL, &legacy_cpu, ARM_ARCH_V3,  N_("use -march=armv3")},
13241   {"mv3m",	 NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13242   {"marmv3m",	 NULL, &legacy_cpu, ARM_ARCH_V3M, N_("use -march=armv3m")},
13243   {"mv4",	 NULL, &legacy_cpu, ARM_ARCH_V4,  N_("use -march=armv4")},
13244   {"marmv4",	 NULL, &legacy_cpu, ARM_ARCH_V4,  N_("use -march=armv4")},
13245   {"mv4t",	 NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13246   {"marmv4t",	 NULL, &legacy_cpu, ARM_ARCH_V4T, N_("use -march=armv4t")},
13247   {"mv5",	 NULL, &legacy_cpu, ARM_ARCH_V5,  N_("use -march=armv5")},
13248   {"marmv5",	 NULL, &legacy_cpu, ARM_ARCH_V5,  N_("use -march=armv5")},
13249   {"mv5t",	 NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13250   {"marmv5t",	 NULL, &legacy_cpu, ARM_ARCH_V5T, N_("use -march=armv5t")},
13251   {"mv5e",	 NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13252   {"marmv5e",	 NULL, &legacy_cpu, ARM_ARCH_V5TE, N_("use -march=armv5te")},
13253 
13254   /* Floating point variants -- don't add any more to this list either.  */
13255   {"mfpe-old", NULL, &legacy_fpu, FPU_ARCH_FPE, N_("use -mfpu=fpe")},
13256   {"mfpa10",   NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa10")},
13257   {"mfpa11",   NULL, &legacy_fpu, FPU_ARCH_FPA, N_("use -mfpu=fpa11")},
13258   {"mno-fpu",  NULL, &legacy_fpu, 0,
13259    N_("use either -mfpu=softfpa or -mfpu=softvfp")},
13260 
13261   {NULL, NULL, NULL, 0, NULL}
13262 };
13263 
13264 struct arm_cpu_option_table
13265 {
13266   char *name;
13267   int   value;
13268   /* For some CPUs we assume an FPU unless the user explicitly sets
13269      -mfpu=...  */
13270   int   default_fpu;
13271 };
13272 
13273 /* This list should, at a minimum, contain all the cpu names
13274    recognized by GCC.  */
13275 static struct arm_cpu_option_table arm_cpus[] =
13276 {
13277   {"all",		ARM_ANY,	 FPU_ARCH_FPA},
13278   {"arm1",		ARM_ARCH_V1,	 FPU_ARCH_FPA},
13279   {"arm2",		ARM_ARCH_V2,	 FPU_ARCH_FPA},
13280   {"arm250",		ARM_ARCH_V2S,	 FPU_ARCH_FPA},
13281   {"arm3",		ARM_ARCH_V2S,	 FPU_ARCH_FPA},
13282   {"arm6",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
13283   {"arm60",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
13284   {"arm600",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
13285   {"arm610",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
13286   {"arm620",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
13287   {"arm7",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
13288   {"arm7m",		ARM_ARCH_V3M,	 FPU_ARCH_FPA},
13289   {"arm7d",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
13290   {"arm7dm",		ARM_ARCH_V3M,	 FPU_ARCH_FPA},
13291   {"arm7di",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
13292   {"arm7dmi",		ARM_ARCH_V3M,	 FPU_ARCH_FPA},
13293   {"arm70",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
13294   {"arm700",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
13295   {"arm700i",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
13296   {"arm710",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
13297   {"arm710t",		ARM_ARCH_V4T,	 FPU_ARCH_FPA},
13298   {"arm720",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
13299   {"arm720t",		ARM_ARCH_V4T,	 FPU_ARCH_FPA},
13300   {"arm740t",		ARM_ARCH_V4T,	 FPU_ARCH_FPA},
13301   {"arm710c",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
13302   {"arm7100",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
13303   {"arm7500",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
13304   {"arm7500fe",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
13305   {"arm7t",		ARM_ARCH_V4T,	 FPU_ARCH_FPA},
13306   {"arm7tdmi",		ARM_ARCH_V4T,	 FPU_ARCH_FPA},
13307   {"arm8",		ARM_ARCH_V4,	 FPU_ARCH_FPA},
13308   {"arm810",		ARM_ARCH_V4,	 FPU_ARCH_FPA},
13309   {"strongarm",		ARM_ARCH_V4,	 FPU_ARCH_FPA},
13310   {"strongarm1",	ARM_ARCH_V4,	 FPU_ARCH_FPA},
13311   {"strongarm110",	ARM_ARCH_V4,	 FPU_ARCH_FPA},
13312   {"strongarm1100",	ARM_ARCH_V4,	 FPU_ARCH_FPA},
13313   {"strongarm1110",	ARM_ARCH_V4,	 FPU_ARCH_FPA},
13314   {"arm9",		ARM_ARCH_V4T,	 FPU_ARCH_FPA},
13315   {"arm920",		ARM_ARCH_V4T,	 FPU_ARCH_FPA},
13316   {"arm920t",		ARM_ARCH_V4T,	 FPU_ARCH_FPA},
13317   {"arm922t",		ARM_ARCH_V4T,	 FPU_ARCH_FPA},
13318   {"arm940t",		ARM_ARCH_V4T,	 FPU_ARCH_FPA},
13319   {"arm9tdmi",		ARM_ARCH_V4T,	 FPU_ARCH_FPA},
13320   /* For V5 or later processors we default to using VFP; but the user
13321      should really set the FPU type explicitly.  */
13322   {"arm9e-r0",		ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13323   {"arm9e",		ARM_ARCH_V5TE,   FPU_ARCH_VFP_V2},
13324   {"arm926ej",		ARM_ARCH_V5TEJ,	 FPU_ARCH_VFP_V2},
13325   {"arm926ejs",		ARM_ARCH_V5TEJ,	 FPU_ARCH_VFP_V2},
13326   {"arm946e-r0",	ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13327   {"arm946e",		ARM_ARCH_V5TE,   FPU_ARCH_VFP_V2},
13328   {"arm966e-r0",	ARM_ARCH_V5TExP, FPU_ARCH_VFP_V2},
13329   {"arm966e",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2},
13330   {"arm10t",		ARM_ARCH_V5T,	 FPU_ARCH_VFP_V1},
13331   {"arm10e",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2},
13332   {"arm1020",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2},
13333   {"arm1020t",		ARM_ARCH_V5T,	 FPU_ARCH_VFP_V1},
13334   {"arm1020e",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2},
13335   {"arm1026ejs",	ARM_ARCH_V5TE,	 FPU_ARCH_VFP_V2},
13336   {"arm1136js",		ARM_ARCH_V6,     FPU_NONE},
13337   {"arm1136jfs",	ARM_ARCH_V6,     FPU_ARCH_VFP_V2},
13338   /* ??? XSCALE is really an architecture.  */
13339   {"xscale",		ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13340   /* ??? iwmmxt is not a processor.  */
13341   {"iwmmxt",		ARM_ARCH_IWMMXT, FPU_ARCH_VFP_V2},
13342   {"i80200",		ARM_ARCH_XSCALE, FPU_ARCH_VFP_V2},
13343   /* Maverick */
13344   {"ep9312",		ARM_ARCH_V4T | ARM_CEXT_MAVERICK, FPU_ARCH_MAVERICK},
13345   {NULL, 0, 0}
13346 };
13347 
13348 struct arm_arch_option_table
13349 {
13350   char *name;
13351   int   value;
13352   int   default_fpu;
13353 };
13354 
13355 /* This list should, at a minimum, contain all the architecture names
13356    recognized by GCC.  */
13357 static struct arm_arch_option_table arm_archs[] =
13358 {
13359   {"all",		ARM_ANY,	 FPU_ARCH_FPA},
13360   {"armv1",		ARM_ARCH_V1,	 FPU_ARCH_FPA},
13361   {"armv2",		ARM_ARCH_V2,	 FPU_ARCH_FPA},
13362   {"armv2a",		ARM_ARCH_V2S,	 FPU_ARCH_FPA},
13363   {"armv2s",		ARM_ARCH_V2S,	 FPU_ARCH_FPA},
13364   {"armv3",		ARM_ARCH_V3,	 FPU_ARCH_FPA},
13365   {"armv3m",		ARM_ARCH_V3M,	 FPU_ARCH_FPA},
13366   {"armv4",		ARM_ARCH_V4,	 FPU_ARCH_FPA},
13367   {"armv4xm",		ARM_ARCH_V4xM,	 FPU_ARCH_FPA},
13368   {"armv4t",		ARM_ARCH_V4T,	 FPU_ARCH_FPA},
13369   {"armv4txm",		ARM_ARCH_V4TxM,	 FPU_ARCH_FPA},
13370   {"armv5",		ARM_ARCH_V5,	 FPU_ARCH_VFP},
13371   {"armv5t",		ARM_ARCH_V5T,	 FPU_ARCH_VFP},
13372   {"armv5txm",		ARM_ARCH_V5TxM,	 FPU_ARCH_VFP},
13373   {"armv5te",		ARM_ARCH_V5TE,	 FPU_ARCH_VFP},
13374   {"armv5texp",		ARM_ARCH_V5TExP, FPU_ARCH_VFP},
13375   {"armv5tej",		ARM_ARCH_V5TEJ,  FPU_ARCH_VFP},
13376   {"armv6",             ARM_ARCH_V6,     FPU_ARCH_VFP},
13377   {"armv6j",            ARM_ARCH_V6,     FPU_ARCH_VFP},
13378   {"xscale",		ARM_ARCH_XSCALE, FPU_ARCH_VFP},
13379   {"iwmmxt",		ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
13380   {NULL, 0, 0}
13381 };
13382 
13383 /* ISA extensions in the co-processor space.  */
13384 struct arm_arch_extension_table
13385 {
13386   char *name;
13387   int value;
13388 };
13389 
13390 static struct arm_arch_extension_table arm_extensions[] =
13391 {
13392   {"maverick",		ARM_CEXT_MAVERICK},
13393   {"xscale",		ARM_CEXT_XSCALE},
13394   {"iwmmxt",		ARM_CEXT_IWMMXT},
13395   {NULL,		0}
13396 };
13397 
13398 struct arm_fpu_option_table
13399 {
13400   char *name;
13401   int   value;
13402 };
13403 
13404 /* This list should, at a minimum, contain all the fpu names
13405    recognized by GCC.  */
13406 static struct arm_fpu_option_table arm_fpus[] =
13407 {
13408   {"softfpa",		FPU_NONE},
13409   {"fpe",		FPU_ARCH_FPE},
13410   {"fpe2",		FPU_ARCH_FPE},
13411   {"fpe3",		FPU_ARCH_FPA},	/* Third release supports LFM/SFM.  */
13412   {"fpa",		FPU_ARCH_FPA},
13413   {"fpa10",		FPU_ARCH_FPA},
13414   {"fpa11",		FPU_ARCH_FPA},
13415   {"arm7500fe",		FPU_ARCH_FPA},
13416   {"softvfp",		FPU_ARCH_VFP},
13417   {"softvfp+vfp",	FPU_ARCH_VFP_V2},
13418   {"vfp",		FPU_ARCH_VFP_V2},
13419   {"vfp9",		FPU_ARCH_VFP_V2},
13420   {"vfp10",		FPU_ARCH_VFP_V2},
13421   {"vfp10-r0",		FPU_ARCH_VFP_V1},
13422   {"vfpxd",		FPU_ARCH_VFP_V1xD},
13423   {"arm1020t",		FPU_ARCH_VFP_V1},
13424   {"arm1020e",		FPU_ARCH_VFP_V2},
13425   {"arm1136jfs",	FPU_ARCH_VFP_V2},
13426   {"maverick",		FPU_ARCH_MAVERICK},
13427   {NULL, 0}
13428 };
13429 
13430 struct arm_float_abi_option_table
13431 {
13432   char *name;
13433   int value;
13434 };
13435 
13436 static struct arm_float_abi_option_table arm_float_abis[] =
13437 {
13438   {"hard",	ARM_FLOAT_ABI_HARD},
13439   {"softfp",	ARM_FLOAT_ABI_SOFTFP},
13440   {"soft",	ARM_FLOAT_ABI_SOFT},
13441   {NULL, 0}
13442 };
13443 
13444 struct arm_long_option_table
13445 {
13446   char *option;		/* Substring to match.  */
13447   char *help;		/* Help information.  */
13448   int (*func) PARAMS ((char *subopt));	/* Function to decode sub-option.  */
13449   char *deprecated;	/* If non-null, print this message.  */
13450 };
13451 
13452 static int
arm_parse_extension(str,opt_p)13453 arm_parse_extension (str, opt_p)
13454      char *str;
13455      int *opt_p;
13456 {
13457   while (str != NULL && *str != 0)
13458     {
13459       struct arm_arch_extension_table *opt;
13460       char *ext;
13461       int optlen;
13462 
13463       if (*str != '+')
13464 	{
13465 	  as_bad (_("invalid architectural extension"));
13466 	  return 0;
13467 	}
13468 
13469       str++;
13470       ext = strchr (str, '+');
13471 
13472       if (ext != NULL)
13473 	optlen = ext - str;
13474       else
13475 	optlen = strlen (str);
13476 
13477       if (optlen == 0)
13478 	{
13479 	  as_bad (_("missing architectural extension"));
13480 	  return 0;
13481 	}
13482 
13483       for (opt = arm_extensions; opt->name != NULL; opt++)
13484 	if (strncmp (opt->name, str, optlen) == 0)
13485 	  {
13486 	    *opt_p |= opt->value;
13487 	    break;
13488 	  }
13489 
13490       if (opt->name == NULL)
13491 	{
13492 	  as_bad (_("unknown architectural extnsion `%s'"), str);
13493 	  return 0;
13494 	}
13495 
13496       str = ext;
13497     };
13498 
13499   return 1;
13500 }
13501 
13502 static int
arm_parse_cpu(str)13503 arm_parse_cpu (str)
13504      char *str;
13505 {
13506   struct arm_cpu_option_table *opt;
13507   char *ext = strchr (str, '+');
13508   int optlen;
13509 
13510   if (ext != NULL)
13511     optlen = ext - str;
13512   else
13513     optlen = strlen (str);
13514 
13515   if (optlen == 0)
13516     {
13517       as_bad (_("missing cpu name `%s'"), str);
13518       return 0;
13519     }
13520 
13521   for (opt = arm_cpus; opt->name != NULL; opt++)
13522     if (strncmp (opt->name, str, optlen) == 0)
13523       {
13524 	mcpu_cpu_opt = opt->value;
13525 	mcpu_fpu_opt = opt->default_fpu;
13526 
13527 	if (ext != NULL)
13528 	  return arm_parse_extension (ext, &mcpu_cpu_opt);
13529 
13530 	return 1;
13531       }
13532 
13533   as_bad (_("unknown cpu `%s'"), str);
13534   return 0;
13535 }
13536 
13537 static int
arm_parse_arch(str)13538 arm_parse_arch (str)
13539      char *str;
13540 {
13541   struct arm_arch_option_table *opt;
13542   char *ext = strchr (str, '+');
13543   int optlen;
13544 
13545   if (ext != NULL)
13546     optlen = ext - str;
13547   else
13548     optlen = strlen (str);
13549 
13550   if (optlen == 0)
13551     {
13552       as_bad (_("missing architecture name `%s'"), str);
13553       return 0;
13554     }
13555 
13556 
13557   for (opt = arm_archs; opt->name != NULL; opt++)
13558     if (strcmp (opt->name, str) == 0)
13559       {
13560 	march_cpu_opt = opt->value;
13561 	march_fpu_opt = opt->default_fpu;
13562 
13563 	if (ext != NULL)
13564 	  return arm_parse_extension (ext, &march_cpu_opt);
13565 
13566 	return 1;
13567       }
13568 
13569   as_bad (_("unknown architecture `%s'\n"), str);
13570   return 0;
13571 }
13572 
13573 static int
arm_parse_fpu(str)13574 arm_parse_fpu (str)
13575      char *str;
13576 {
13577   struct arm_fpu_option_table *opt;
13578 
13579   for (opt = arm_fpus; opt->name != NULL; opt++)
13580     if (strcmp (opt->name, str) == 0)
13581       {
13582 	mfpu_opt = opt->value;
13583 	return 1;
13584       }
13585 
13586   as_bad (_("unknown floating point format `%s'\n"), str);
13587   return 0;
13588 }
13589 
13590 static int
arm_parse_float_abi(str)13591 arm_parse_float_abi (str)
13592      char * str;
13593 {
13594   struct arm_float_abi_option_table *opt;
13595 
13596   for (opt = arm_float_abis; opt->name != NULL; opt++)
13597     if (strcmp (opt->name, str) == 0)
13598       {
13599 	mfloat_abi_opt = opt->value;
13600 	return 1;
13601       }
13602 
13603   as_bad (_("unknown floating point abi `%s'\n"), str);
13604   return 0;
13605 }
13606 
13607 struct arm_long_option_table arm_long_opts[] =
13608 {
13609   {"mcpu=", N_("<cpu name>\t  assemble for CPU <cpu name>"),
13610    arm_parse_cpu, NULL},
13611   {"march=", N_("<arch name>\t  assemble for architecture <arch name>"),
13612    arm_parse_arch, NULL},
13613   {"mfpu=", N_("<fpu name>\t  assemble for FPU architecture <fpu name>"),
13614    arm_parse_fpu, NULL},
13615   {"mfloat-abi=", N_("<abi>\t  assemble for floating point ABI <abi>"),
13616    arm_parse_float_abi, NULL},
13617   {NULL, NULL, 0, NULL}
13618 };
13619 
13620 int
md_parse_option(c,arg)13621 md_parse_option (c, arg)
13622      int    c;
13623      char * arg;
13624 {
13625   struct arm_option_table *opt;
13626   struct arm_long_option_table *lopt;
13627 
13628   switch (c)
13629     {
13630 #ifdef OPTION_EB
13631     case OPTION_EB:
13632       target_big_endian = 1;
13633       break;
13634 #endif
13635 
13636 #ifdef OPTION_EL
13637     case OPTION_EL:
13638       target_big_endian = 0;
13639       break;
13640 #endif
13641 
13642     case 'a':
13643       /* Listing option.  Just ignore these, we don't support additional
13644 	 ones.  */
13645       return 0;
13646 
13647     default:
13648       for (opt = arm_opts; opt->option != NULL; opt++)
13649 	{
13650 	  if (c == opt->option[0]
13651 	      && ((arg == NULL && opt->option[1] == 0)
13652 		  || strcmp (arg, opt->option + 1) == 0))
13653 	    {
13654 #if WARN_DEPRECATED
13655 	      /* If the option is deprecated, tell the user.  */
13656 	      if (opt->deprecated != NULL)
13657 		as_tsktsk (_("option `-%c%s' is deprecated: %s"), c,
13658 			   arg ? arg : "", _(opt->deprecated));
13659 #endif
13660 
13661 	      if (opt->var != NULL)
13662 		*opt->var = opt->value;
13663 
13664 	      return 1;
13665 	    }
13666 	}
13667 
13668       for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13669 	{
13670 	  /* These options are expected to have an argument.  */
13671 	  if (c == lopt->option[0]
13672 	      && arg != NULL
13673 	      && strncmp (arg, lopt->option + 1,
13674 			  strlen (lopt->option + 1)) == 0)
13675 	    {
13676 #if WARN_DEPRECATED
13677 	      /* If the option is deprecated, tell the user.  */
13678 	      if (lopt->deprecated != NULL)
13679 		as_tsktsk (_("option `-%c%s' is deprecated: %s"), c, arg,
13680 			   _(lopt->deprecated));
13681 #endif
13682 
13683 	      /* Call the sup-option parser.  */
13684 	      return (*lopt->func)(arg + strlen (lopt->option) - 1);
13685 	    }
13686 	}
13687 
13688       as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : "");
13689       return 0;
13690     }
13691 
13692   return 1;
13693 }
13694 
13695 void
md_show_usage(fp)13696 md_show_usage (fp)
13697      FILE * fp;
13698 {
13699   struct arm_option_table *opt;
13700   struct arm_long_option_table *lopt;
13701 
13702   fprintf (fp, _(" ARM-specific assembler options:\n"));
13703 
13704   for (opt = arm_opts; opt->option != NULL; opt++)
13705     if (opt->help != NULL)
13706       fprintf (fp, "  -%-23s%s\n", opt->option, _(opt->help));
13707 
13708   for (lopt = arm_long_opts; lopt->option != NULL; lopt++)
13709     if (lopt->help != NULL)
13710       fprintf (fp, "  -%s%s\n", lopt->option, _(lopt->help));
13711 
13712 #ifdef OPTION_EB
13713   fprintf (fp, _("\
13714   -EB                     assemble code for a big-endian cpu\n"));
13715 #endif
13716 
13717 #ifdef OPTION_EL
13718   fprintf (fp, _("\
13719   -EL                     assemble code for a little-endian cpu\n"));
13720 #endif
13721 }
13722 
13723 /* We need to be able to fix up arbitrary expressions in some statements.
13724    This is so that we can handle symbols that are an arbitrary distance from
13725    the pc.  The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
13726    which returns part of an address in a form which will be valid for
13727    a data instruction.  We do this by pushing the expression into a symbol
13728    in the expr_section, and creating a fix for that.  */
13729 
13730 static void
fix_new_arm(frag,where,size,exp,pc_rel,reloc)13731 fix_new_arm (frag, where, size, exp, pc_rel, reloc)
13732      fragS *       frag;
13733      int           where;
13734      short int     size;
13735      expressionS * exp;
13736      int           pc_rel;
13737      int           reloc;
13738 {
13739   fixS *           new_fix;
13740   arm_fix_data *   arm_data;
13741 
13742   switch (exp->X_op)
13743     {
13744     case O_constant:
13745     case O_symbol:
13746     case O_add:
13747     case O_subtract:
13748       new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
13749       break;
13750 
13751     default:
13752       new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
13753 			 pc_rel, reloc);
13754       break;
13755     }
13756 
13757   /* Mark whether the fix is to a THUMB instruction, or an ARM
13758      instruction.  */
13759   arm_data = (arm_fix_data *) obstack_alloc (& notes, sizeof (arm_fix_data));
13760   new_fix->tc_fix_data = (PTR) arm_data;
13761   arm_data->thumb_mode = thumb_mode;
13762 }
13763 
13764 /* This fix_new is called by cons via TC_CONS_FIX_NEW.  */
13765 
13766 void
cons_fix_new_arm(frag,where,size,exp)13767 cons_fix_new_arm (frag, where, size, exp)
13768      fragS *       frag;
13769      int           where;
13770      int           size;
13771      expressionS * exp;
13772 {
13773   bfd_reloc_code_real_type type;
13774   int pcrel = 0;
13775 
13776   /* Pick a reloc.
13777      FIXME: @@ Should look at CPU word size.  */
13778   switch (size)
13779     {
13780     case 1:
13781       type = BFD_RELOC_8;
13782       break;
13783     case 2:
13784       type = BFD_RELOC_16;
13785       break;
13786     case 4:
13787     default:
13788       type = BFD_RELOC_32;
13789       break;
13790     case 8:
13791       type = BFD_RELOC_64;
13792       break;
13793     }
13794 
13795   fix_new_exp (frag, where, (int) size, exp, pcrel, type);
13796 }
13797 
13798 /* A good place to do this, although this was probably not intended
13799    for this kind of use.  We need to dump the literal pool before
13800    references are made to a null symbol pointer.  */
13801 
13802 void
arm_cleanup()13803 arm_cleanup ()
13804 {
13805   literal_pool * pool;
13806 
13807   for (pool = list_of_pools; pool; pool = pool->next)
13808     {
13809       /* Put it at the end of the relevent section.  */
13810       subseg_set (pool->section, pool->sub_section);
13811 #ifdef OBJ_ELF
13812       arm_elf_change_section ();
13813 #endif
13814       s_ltorg (0);
13815     }
13816 }
13817 
13818 void
arm_start_line_hook()13819 arm_start_line_hook ()
13820 {
13821   last_label_seen = NULL;
13822 }
13823 
13824 void
arm_frob_label(sym)13825 arm_frob_label (sym)
13826      symbolS * sym;
13827 {
13828   last_label_seen = sym;
13829 
13830   ARM_SET_THUMB (sym, thumb_mode);
13831 
13832 #if defined OBJ_COFF || defined OBJ_ELF
13833   ARM_SET_INTERWORK (sym, support_interwork);
13834 #endif
13835 
13836   /* Note - do not allow local symbols (.Lxxx) to be labeled
13837      as Thumb functions.  This is because these labels, whilst
13838      they exist inside Thumb code, are not the entry points for
13839      possible ARM->Thumb calls.  Also, these labels can be used
13840      as part of a computed goto or switch statement.  eg gcc
13841      can generate code that looks like this:
13842 
13843                 ldr  r2, [pc, .Laaa]
13844                 lsl  r3, r3, #2
13845                 ldr  r2, [r3, r2]
13846                 mov  pc, r2
13847 
13848        .Lbbb:  .word .Lxxx
13849        .Lccc:  .word .Lyyy
13850        ..etc...
13851        .Laaa:   .word Lbbb
13852 
13853      The first instruction loads the address of the jump table.
13854      The second instruction converts a table index into a byte offset.
13855      The third instruction gets the jump address out of the table.
13856      The fourth instruction performs the jump.
13857 
13858      If the address stored at .Laaa is that of a symbol which has the
13859      Thumb_Func bit set, then the linker will arrange for this address
13860      to have the bottom bit set, which in turn would mean that the
13861      address computation performed by the third instruction would end
13862      up with the bottom bit set.  Since the ARM is capable of unaligned
13863      word loads, the instruction would then load the incorrect address
13864      out of the jump table, and chaos would ensue.  */
13865   if (label_is_thumb_function_name
13866       && (S_GET_NAME (sym)[0] != '.' || S_GET_NAME (sym)[1] != 'L')
13867       && (bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
13868     {
13869       /* When the address of a Thumb function is taken the bottom
13870 	 bit of that address should be set.  This will allow
13871 	 interworking between Arm and Thumb functions to work
13872 	 correctly.  */
13873 
13874       THUMB_SET_FUNC (sym, 1);
13875 
13876       label_is_thumb_function_name = FALSE;
13877     }
13878 }
13879 
13880 /* Adjust the symbol table.  This marks Thumb symbols as distinct from
13881    ARM ones.  */
13882 
13883 void
arm_adjust_symtab()13884 arm_adjust_symtab ()
13885 {
13886 #ifdef OBJ_COFF
13887   symbolS * sym;
13888 
13889   for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13890     {
13891       if (ARM_IS_THUMB (sym))
13892 	{
13893 	  if (THUMB_IS_FUNC (sym))
13894 	    {
13895 	      /* Mark the symbol as a Thumb function.  */
13896 	      if (   S_GET_STORAGE_CLASS (sym) == C_STAT
13897 		  || S_GET_STORAGE_CLASS (sym) == C_LABEL)  /* This can happen!  */
13898 		S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
13899 
13900 	      else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
13901 		S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
13902 	      else
13903 		as_bad (_("%s: unexpected function type: %d"),
13904 			S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
13905 	    }
13906 	  else switch (S_GET_STORAGE_CLASS (sym))
13907 	    {
13908 	    case C_EXT:
13909 	      S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
13910 	      break;
13911 	    case C_STAT:
13912 	      S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
13913 	      break;
13914 	    case C_LABEL:
13915 	      S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
13916 	      break;
13917 	    default:
13918 	      /* Do nothing.  */
13919 	      break;
13920 	    }
13921 	}
13922 
13923       if (ARM_IS_INTERWORK (sym))
13924 	coffsymbol (symbol_get_bfdsym (sym))->native->u.syment.n_flags = 0xFF;
13925     }
13926 #endif
13927 #ifdef OBJ_ELF
13928   symbolS * sym;
13929   char      bind;
13930 
13931   for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
13932     {
13933       if (ARM_IS_THUMB (sym))
13934 	{
13935 	  elf_symbol_type * elf_sym;
13936 
13937 	  elf_sym = elf_symbol (symbol_get_bfdsym (sym));
13938 	  bind = ELF_ST_BIND (elf_sym);
13939 
13940 	  /* If it's a .thumb_func, declare it as so,
13941 	     otherwise tag label as .code 16.  */
13942 	  if (THUMB_IS_FUNC (sym))
13943 	    elf_sym->internal_elf_sym.st_info =
13944 	      ELF_ST_INFO (bind, STT_ARM_TFUNC);
13945 	  else
13946 	    elf_sym->internal_elf_sym.st_info =
13947 	      ELF_ST_INFO (bind, STT_ARM_16BIT);
13948 	}
13949     }
13950 #endif
13951 }
13952 
13953 int
arm_data_in_code()13954 arm_data_in_code ()
13955 {
13956   if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
13957     {
13958       *input_line_pointer = '/';
13959       input_line_pointer += 5;
13960       *input_line_pointer = 0;
13961       return 1;
13962     }
13963 
13964   return 0;
13965 }
13966 
13967 char *
arm_canonicalize_symbol_name(name)13968 arm_canonicalize_symbol_name (name)
13969      char * name;
13970 {
13971   int len;
13972 
13973   if (thumb_mode && (len = strlen (name)) > 5
13974       && streq (name + len - 5, "/data"))
13975     *(name + len - 5) = 0;
13976 
13977   return name;
13978 }
13979 
13980 #if defined OBJ_COFF || defined OBJ_ELF
13981 void
arm_validate_fix(fixP)13982 arm_validate_fix (fixP)
13983      fixS * fixP;
13984 {
13985   /* If the destination of the branch is a defined symbol which does not have
13986      the THUMB_FUNC attribute, then we must be calling a function which has
13987      the (interfacearm) attribute.  We look for the Thumb entry point to that
13988      function and change the branch to refer to that function instead.  */
13989   if (fixP->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23
13990       && fixP->fx_addsy != NULL
13991       && S_IS_DEFINED (fixP->fx_addsy)
13992       && ! THUMB_IS_FUNC (fixP->fx_addsy))
13993     {
13994       fixP->fx_addsy = find_real_start (fixP->fx_addsy);
13995     }
13996 }
13997 #endif
13998 
13999 int
arm_force_relocation(fixp)14000 arm_force_relocation (fixp)
14001      struct fix * fixp;
14002 {
14003 #if defined (OBJ_COFF) && defined (TE_PE)
14004   if (fixp->fx_r_type == BFD_RELOC_RVA)
14005     return 1;
14006 #endif
14007 #ifdef OBJ_ELF
14008   if (fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH
14009       || fixp->fx_r_type == BFD_RELOC_ARM_PCREL_BLX
14010       || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BLX
14011       || fixp->fx_r_type == BFD_RELOC_THUMB_PCREL_BRANCH23)
14012     return 1;
14013 #endif
14014 
14015   /* Resolve these relocations even if the symbol is extern or weak.  */
14016   if (fixp->fx_r_type == BFD_RELOC_ARM_IMMEDIATE
14017       || fixp->fx_r_type == BFD_RELOC_ARM_OFFSET_IMM
14018       || fixp->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
14019     return 0;
14020 
14021   return generic_force_reloc (fixp);
14022 }
14023 
14024 #ifdef OBJ_COFF
14025 /* This is a little hack to help the gas/arm/adrl.s test.  It prevents
14026    local labels from being added to the output symbol table when they
14027    are used with the ADRL pseudo op.  The ADRL relocation should always
14028    be resolved before the binbary is emitted, so it is safe to say that
14029    it is adjustable.  */
14030 
14031 bfd_boolean
arm_fix_adjustable(fixP)14032 arm_fix_adjustable (fixP)
14033    fixS * fixP;
14034 {
14035   if (fixP->fx_r_type == BFD_RELOC_ARM_ADRL_IMMEDIATE)
14036     return 1;
14037   return 0;
14038 }
14039 #endif
14040 
14041 #ifdef OBJ_ELF
14042 /* Relocations against Thumb function names must be left unadjusted,
14043    so that the linker can use this information to correctly set the
14044    bottom bit of their addresses.  The MIPS version of this function
14045    also prevents relocations that are mips-16 specific, but I do not
14046    know why it does this.
14047 
14048    FIXME:
14049    There is one other problem that ought to be addressed here, but
14050    which currently is not:  Taking the address of a label (rather
14051    than a function) and then later jumping to that address.  Such
14052    addresses also ought to have their bottom bit set (assuming that
14053    they reside in Thumb code), but at the moment they will not.  */
14054 
14055 bfd_boolean
arm_fix_adjustable(fixP)14056 arm_fix_adjustable (fixP)
14057    fixS * fixP;
14058 {
14059   if (fixP->fx_addsy == NULL)
14060     return 1;
14061 
14062   if (THUMB_IS_FUNC (fixP->fx_addsy)
14063       && fixP->fx_subsy == NULL)
14064     return 0;
14065 
14066   /* We need the symbol name for the VTABLE entries.  */
14067   if (   fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
14068       || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
14069     return 0;
14070 
14071   /* Don't allow symbols to be discarded on GOT related relocs.  */
14072   if (fixP->fx_r_type == BFD_RELOC_ARM_PLT32
14073       || fixP->fx_r_type == BFD_RELOC_ARM_GOT32
14074       || fixP->fx_r_type == BFD_RELOC_ARM_GOTOFF)
14075     return 0;
14076 
14077   return 1;
14078 }
14079 
14080 const char *
elf32_arm_target_format()14081 elf32_arm_target_format ()
14082 {
14083   if (target_big_endian)
14084     {
14085       if (target_oabi)
14086 	return "elf32-bigarm-oabi";
14087       else
14088 	return "elf32-bigarm";
14089     }
14090   else
14091     {
14092       if (target_oabi)
14093 	return "elf32-littlearm-oabi";
14094       else
14095 	return "elf32-littlearm";
14096     }
14097 }
14098 
14099 void
armelf_frob_symbol(symp,puntp)14100 armelf_frob_symbol (symp, puntp)
14101      symbolS * symp;
14102      int *     puntp;
14103 {
14104   elf_frob_symbol (symp, puntp);
14105 }
14106 
14107 static bfd_reloc_code_real_type
arm_parse_reloc()14108 arm_parse_reloc ()
14109 {
14110   char         id [16];
14111   char *       ip;
14112   unsigned int i;
14113   static struct
14114   {
14115     char * str;
14116     int    len;
14117     bfd_reloc_code_real_type reloc;
14118   }
14119   reloc_map[] =
14120   {
14121 #define MAP(str,reloc) { str, sizeof (str) - 1, reloc }
14122     MAP ("(got)",    BFD_RELOC_ARM_GOT32),
14123     MAP ("(gotoff)", BFD_RELOC_ARM_GOTOFF),
14124     /* ScottB: Jan 30, 1998 - Added support for parsing "var(PLT)"
14125        branch instructions generated by GCC for PLT relocs.  */
14126     MAP ("(plt)",    BFD_RELOC_ARM_PLT32),
14127     { NULL, 0,         BFD_RELOC_UNUSED }
14128 #undef MAP
14129   };
14130 
14131   for (i = 0, ip = input_line_pointer;
14132        i < sizeof (id) && (ISALNUM (*ip) || ISPUNCT (*ip));
14133        i++, ip++)
14134     id[i] = TOLOWER (*ip);
14135 
14136   for (i = 0; reloc_map[i].str; i++)
14137     if (strncmp (id, reloc_map[i].str, reloc_map[i].len) == 0)
14138       break;
14139 
14140   input_line_pointer += reloc_map[i].len;
14141 
14142   return reloc_map[i].reloc;
14143 }
14144 
14145 static void
s_arm_elf_cons(nbytes)14146 s_arm_elf_cons (nbytes)
14147      int nbytes;
14148 {
14149   expressionS exp;
14150 
14151 #ifdef md_flush_pending_output
14152   md_flush_pending_output ();
14153 #endif
14154 
14155   if (is_it_end_of_statement ())
14156     {
14157       demand_empty_rest_of_line ();
14158       return;
14159     }
14160 
14161 #ifdef md_cons_align
14162   md_cons_align (nbytes);
14163 #endif
14164 
14165   mapping_state (MAP_DATA);
14166   do
14167     {
14168       bfd_reloc_code_real_type reloc;
14169 
14170       expression (& exp);
14171 
14172       if (exp.X_op == O_symbol
14173 	  && * input_line_pointer == '('
14174 	  && (reloc = arm_parse_reloc ()) != BFD_RELOC_UNUSED)
14175 	{
14176 	  reloc_howto_type *howto = bfd_reloc_type_lookup (stdoutput, reloc);
14177 	  int size = bfd_get_reloc_size (howto);
14178 
14179 	  if (size > nbytes)
14180 	    as_bad ("%s relocations do not fit in %d bytes",
14181 		    howto->name, nbytes);
14182 	  else
14183 	    {
14184 	      register char *p = frag_more ((int) nbytes);
14185 	      int offset = nbytes - size;
14186 
14187 	      fix_new_exp (frag_now, p - frag_now->fr_literal + offset, size,
14188 			   &exp, 0, reloc);
14189 	    }
14190 	}
14191       else
14192 	emit_expr (&exp, (unsigned int) nbytes);
14193     }
14194   while (*input_line_pointer++ == ',');
14195 
14196   /* Put terminator back into stream.  */
14197   input_line_pointer --;
14198   demand_empty_rest_of_line ();
14199 }
14200 
14201 #endif /* OBJ_ELF */
14202 
14203 /* This is called from HANDLE_ALIGN in write.c.  Fill in the contents
14204    of an rs_align_code fragment.  */
14205 
14206 void
arm_handle_align(fragP)14207 arm_handle_align (fragP)
14208      fragS *fragP;
14209 {
14210   static char const arm_noop[4] = { 0x00, 0x00, 0xa0, 0xe1 };
14211   static char const thumb_noop[2] = { 0xc0, 0x46 };
14212   static char const arm_bigend_noop[4] = { 0xe1, 0xa0, 0x00, 0x00 };
14213   static char const thumb_bigend_noop[2] = { 0x46, 0xc0 };
14214 
14215   int bytes, fix, noop_size;
14216   char * p;
14217   const char * noop;
14218 
14219   if (fragP->fr_type != rs_align_code)
14220     return;
14221 
14222   bytes = fragP->fr_next->fr_address - fragP->fr_address - fragP->fr_fix;
14223   p = fragP->fr_literal + fragP->fr_fix;
14224   fix = 0;
14225 
14226   if (bytes > MAX_MEM_FOR_RS_ALIGN_CODE)
14227     bytes &= MAX_MEM_FOR_RS_ALIGN_CODE;
14228 
14229   if (fragP->tc_frag_data)
14230     {
14231       if (target_big_endian)
14232 	noop = thumb_bigend_noop;
14233       else
14234 	noop = thumb_noop;
14235       noop_size = sizeof (thumb_noop);
14236     }
14237   else
14238     {
14239       if (target_big_endian)
14240 	noop = arm_bigend_noop;
14241       else
14242 	noop = arm_noop;
14243       noop_size = sizeof (arm_noop);
14244     }
14245 
14246   if (bytes & (noop_size - 1))
14247     {
14248       fix = bytes & (noop_size - 1);
14249       memset (p, 0, fix);
14250       p += fix;
14251       bytes -= fix;
14252     }
14253 
14254   while (bytes >= noop_size)
14255     {
14256       memcpy (p, noop, noop_size);
14257       p += noop_size;
14258       bytes -= noop_size;
14259       fix += noop_size;
14260     }
14261 
14262   fragP->fr_fix += fix;
14263   fragP->fr_var = noop_size;
14264 }
14265 
14266 /* Called from md_do_align.  Used to create an alignment
14267    frag in a code section.  */
14268 
14269 void
arm_frag_align_code(n,max)14270 arm_frag_align_code (n, max)
14271      int n;
14272      int max;
14273 {
14274   char * p;
14275 
14276   /* We assume that there will never be a requirement
14277      to support alignments greater than 32 bytes.  */
14278   if (max > MAX_MEM_FOR_RS_ALIGN_CODE)
14279     as_fatal (_("alignments greater than 32 bytes not supported in .text sections."));
14280 
14281   p = frag_var (rs_align_code,
14282 		MAX_MEM_FOR_RS_ALIGN_CODE,
14283 		1,
14284 		(relax_substateT) max,
14285 		(symbolS *) NULL,
14286 		(offsetT) n,
14287 		(char *) NULL);
14288   *p = 0;
14289 
14290 }
14291 
14292 /* Perform target specific initialisation of a frag.  */
14293 
14294 void
arm_init_frag(fragP)14295 arm_init_frag (fragP)
14296      fragS *fragP;
14297 {
14298   /* Record whether this frag is in an ARM or a THUMB area.  */
14299   fragP->tc_frag_data = thumb_mode;
14300 }
14301