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