Add support for more ARM processor names.
[deliverable/binutils-gdb.git] / gas / config / tc-arm.c
CommitLineData
590c50d8
ILT
1/* tc-arm.c -- Assemble for the ARM
2 Copyright (C) 1994, 95, 96, 1997 Free Software Foundation, Inc.
338a7060
DE
3 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
4 Modified by David Taylor (dtaylor@armltd.co.uk)
5
338a7060
DE
6 This file is part of GAS, the GNU Assembler.
7
8 GAS is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 GAS is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
590c50d8
ILT
19 along with GAS; see the file COPYING. If not, write to the Free
20 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
21 02111-1307, USA. */
338a7060
DE
22
23#include <ctype.h>
24#include <string.h>
25#define NO_RELOC 0
26#include "as.h"
27
28/* need TARGET_CPU */
29#include "config.h"
30#include "subsegs.h"
31#include "obstack.h"
32#include "symbols.h"
33#include "listing.h"
34
35/* ??? This is currently unused. */
36#ifdef __STDC__
37#define internalError() \
38 as_fatal ("ARM Internal Error, line %d, %s", __LINE__, __FILE__)
39#else
40#define internalError() as_fatal ("ARM Internal Error")
41#endif
42
43/* Types of processor to assemble for. */
44#define ARM_1 0x00000001
45#define ARM_2 0x00000002
338a7060 46#define ARM_3 0x00000004
590c50d8 47#define ARM_250 ARM_3
338a7060 48#define ARM_6 0x00000008
590c50d8 49#define ARM_7 ARM_6 /* same core instruction set */
46686c78 50#define ARM_CPU_MASK 0x0000000f
c479fc62
JSC
51
52/* The following bitmasks control CPU extensions (ARM7 onwards): */
53#define ARM_LONGMUL 0x00000010 /* allow long multiplies */
f520aaee
NC
54#define ARM_HALFWORD 0x00000020 /* allow half word loads */
55#define ARM_THUMB 0x00000040 /* allow BX instruction */
56
57#define ARM_ARCHv4 (ARM_7 | ARM_LONGMUL | ARM_HALFWORD)
338a7060
DE
58
59/* Some useful combinations: */
60#define ARM_ANY 0x00ffffff
61#define ARM_2UP 0x00fffffe
62#define ARM_ALL ARM_2UP /* Not arm1 only */
63#define ARM_3UP 0x00fffffc
c479fc62 64#define ARM_6UP 0x00fffff8 /* Includes ARM7 */
338a7060
DE
65
66#define FPU_CORE 0x80000000
67#define FPU_FPA10 0x40000000
68#define FPU_FPA11 0x40000000
69#define FPU_NONE 0
70
71/* Some useful combinations */
72#define FPU_ALL 0xff000000 /* Note this is ~ARM_ANY */
73#define FPU_MEMMULTI 0x7f000000 /* Not fpu_core */
74
ccc30467 75
338a7060 76#ifndef CPU_DEFAULT
ccc30467 77#if defined __thumb__
f520aaee 78#define CPU_DEFAULT (ARM_ARCHv4 | ARM_THUMB)
ccc30467 79#else
338a7060
DE
80#define CPU_DEFAULT ARM_ALL
81#endif
ccc30467 82#endif
338a7060
DE
83
84#ifndef FPU_DEFAULT
85#define FPU_DEFAULT FPU_ALL
86#endif
87
46686c78
NC
88static unsigned long cpu_variant = CPU_DEFAULT | FPU_DEFAULT;
89
ccc30467 90#ifdef OBJ_COFF
46686c78
NC
91/* Flags stored in private area of BFD COFF structure */
92static boolean uses_apcs_26 = false;
f520aaee
NC
93static boolean support_interwork = false;
94static boolean uses_apcs_float = false;
95static boolean pic_code = false;
ccc30467 96#endif
338a7060
DE
97
98/* This array holds the chars that always start a comment. If the
99 pre-processor is disabled, these aren't very useful */
100CONST char comment_chars[] = "@";
101
102/* This array holds the chars that only start a comment at the beginning of
103 a line. If the line seems to have the form '# 123 filename'
104 .line and .file directives will appear in the pre-processed output */
105/* Note that input_file.c hand checks for '#' at the beginning of the
106 first line of the input file. This is because the compiler outputs
107 #NO_APP at the beginning of its output. */
108/* Also note that comments like this one will always work. */
109CONST char line_comment_chars[] = "#";
110
111CONST char line_separator_chars[] = "";
112
113/* Chars that can be used to separate mant from exp in floating point nums */
114CONST char EXP_CHARS[] = "eE";
115
116/* Chars that mean this number is a floating point constant */
117/* As in 0f12.456 */
118/* or 0d1.2345e12 */
119
120CONST char FLT_CHARS[] = "rRsSfFdDxXeEpP";
121
590c50d8
ILT
122CONST int md_reloc_size = 8; /* Size of relocation record */
123
124static int thumb_mode = 0; /* non-zero if assembling thumb instructions */
125
126typedef struct arm_fix
127{
128 int thumb_mode;
129} arm_fix_data;
338a7060
DE
130
131struct arm_it
132{
133 CONST char *error;
134 unsigned long instruction;
135 int suffix;
590c50d8 136 int size;
338a7060
DE
137 struct
138 {
139 bfd_reloc_code_real_type type;
140 expressionS exp;
141 int pc_rel;
142 } reloc;
143};
144
145struct arm_it inst;
146
147struct asm_shift
148{
149 CONST char *template;
150 unsigned long value;
151};
152
153static CONST struct asm_shift shift[] =
154{
155 {"asl", 0},
156 {"lsl", 0},
157 {"lsr", 0x00000020},
158 {"asr", 0x00000040},
159 {"ror", 0x00000060},
160 {"rrx", 0x00000060},
161 {"ASL", 0},
162 {"LSL", 0},
163 {"LSR", 0x00000020},
164 {"ASR", 0x00000040},
165 {"ROR", 0x00000060},
166 {"RRX", 0x00000060}
167};
168
169#define NO_SHIFT_RESTRICT 1
170#define SHIFT_RESTRICT 0
171
172#define NUM_FLOAT_VALS 8
173
174CONST char *fp_const[] =
175{
176 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
177};
178
179/* Number of littlenums required to hold an extended precision number */
180#define MAX_LITTLENUMS 6
181
182LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
183
184#define FAIL (-1)
185#define SUCCESS (0)
186
187#define SUFF_S 1
188#define SUFF_D 2
189#define SUFF_E 3
190#define SUFF_P 4
191
192#define CP_T_X 0x00008000
193#define CP_T_Y 0x00400000
194#define CP_T_Pre 0x01000000
195#define CP_T_UD 0x00800000
196#define CP_T_WB 0x00200000
197
590c50d8
ILT
198#define CONDS_BIT (0x00100000)
199#define LOAD_BIT (0x00100000)
338a7060
DE
200#define TRANS_BIT (0x00200000)
201
202struct asm_cond
203{
204 CONST char *template;
205 unsigned long value;
206};
207
208/* This is to save a hash look-up in the common case */
209#define COND_ALWAYS 0xe0000000
210
211static CONST struct asm_cond conds[] =
212{
213 {"eq", 0x00000000},
214 {"ne", 0x10000000},
215 {"cs", 0x20000000}, {"hs", 0x20000000},
216 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
217 {"mi", 0x40000000},
218 {"pl", 0x50000000},
219 {"vs", 0x60000000},
220 {"vc", 0x70000000},
221 {"hi", 0x80000000},
222 {"ls", 0x90000000},
223 {"ge", 0xa0000000},
224 {"lt", 0xb0000000},
225 {"gt", 0xc0000000},
226 {"le", 0xd0000000},
227 {"al", 0xe0000000},
228 {"nv", 0xf0000000}
229};
230
590c50d8
ILT
231/* Warning: If the top bit of the set_bits is set, then the standard
232 instruction bitmask is ignored, and the new bitmask is taken from
233 the set_bits: */
338a7060
DE
234struct asm_flg
235{
236 CONST char *template; /* Basic flag string */
237 unsigned long set_bits; /* Bits to set */
238};
239
240static CONST struct asm_flg s_flag[] =
241{
590c50d8
ILT
242 {"s", CONDS_BIT},
243 {NULL, 0}
244};
245
246static CONST struct asm_flg ldr_flags[] =
247{
248 {"b", 0x00400000},
249 {"t", TRANS_BIT},
250 {"bt", 0x00400000 | TRANS_BIT},
251 {"h", 0x801000b0},
252 {"sh", 0x801000f0},
253 {"sb", 0x801000d0},
254 {NULL, 0}
338a7060
DE
255};
256
590c50d8 257static CONST struct asm_flg str_flags[] =
338a7060 258{
590c50d8
ILT
259 {"b", 0x00400000},
260 {"t", TRANS_BIT},
261 {"bt", 0x00400000 | TRANS_BIT},
262 {"h", 0x800000b0},
263 {NULL, 0}
338a7060
DE
264};
265
266static CONST struct asm_flg byte_flag[] =
267{
590c50d8
ILT
268 {"b", 0x00400000},
269 {NULL, 0}
338a7060
DE
270};
271
272static CONST struct asm_flg cmp_flags[] =
273{
590c50d8
ILT
274 {"s", CONDS_BIT},
275 {"p", 0x0010f000},
276 {NULL, 0}
338a7060
DE
277};
278
279static CONST struct asm_flg ldm_flags[] =
280{
590c50d8
ILT
281 {"ed", 0x01800000},
282 {"fd", 0x00800000},
283 {"ea", 0x01000000},
284 {"fa", 0x08000000},
285 {"ib", 0x01800000},
286 {"ia", 0x00800000},
287 {"db", 0x01000000},
288 {"da", 0x08000000},
289 {NULL, 0}
338a7060
DE
290};
291
292static CONST struct asm_flg stm_flags[] =
293{
590c50d8
ILT
294 {"ed", 0x08000000},
295 {"fd", 0x01000000},
296 {"ea", 0x00800000},
297 {"fa", 0x01800000},
298 {"ib", 0x01800000},
299 {"ia", 0x00800000},
300 {"db", 0x01000000},
301 {"da", 0x08000000},
302 {NULL, 0}
338a7060
DE
303};
304
305static CONST struct asm_flg lfm_flags[] =
306{
590c50d8
ILT
307 {"fd", 0x00800000},
308 {"ea", 0x01000000},
309 {NULL, 0}
338a7060
DE
310};
311
312static CONST struct asm_flg sfm_flags[] =
313{
590c50d8
ILT
314 {"fd", 0x01000000},
315 {"ea", 0x00800000},
316 {NULL, 0}
338a7060
DE
317};
318
319static CONST struct asm_flg round_flags[] =
320{
590c50d8
ILT
321 {"p", 0x00000020},
322 {"m", 0x00000040},
323 {"z", 0x00000060},
324 {NULL, 0}
325};
326
327/* The implementation of the FIX instruction is broken on some assemblers,
328 in that it accepts a precision specifier as well as a rounding specifier,
329 despite the fact that this is meaningless. To be more compatible, we
330 accept it as well, though of course it does not set any bits. */
331static CONST struct asm_flg fix_flags[] =
332{
333 {"p", 0x00000020},
334 {"m", 0x00000040},
335 {"z", 0x00000060},
336 {"sp", 0x00000020},
337 {"sm", 0x00000040},
338 {"sz", 0x00000060},
339 {"dp", 0x00000020},
340 {"dm", 0x00000040},
341 {"dz", 0x00000060},
342 {"ep", 0x00000020},
343 {"em", 0x00000040},
344 {"ez", 0x00000060},
345 {NULL, 0}
338a7060
DE
346};
347
348static CONST struct asm_flg except_flag[] =
349{
590c50d8
ILT
350 {"e", 0x00400000},
351 {NULL, 0}
338a7060
DE
352};
353
354static CONST struct asm_flg cplong_flag[] =
355{
590c50d8
ILT
356 {"l", 0x00400000},
357 {NULL, 0}
338a7060
DE
358};
359
360struct asm_psr
361{
362 CONST char *template;
363 unsigned long number;
364};
365
366#define PSR_ALL 0x00010000
367
368static CONST struct asm_psr psrs[] =
369{
370 /* Valid <psr>'s */
371 {"cpsr", 0},
372 {"cpsr_all", 0},
373 {"spsr", 1},
374 {"spsr_all", 1},
375
376 /* Valid <psrf>'s */
377 {"cpsr_flg", 2},
378 {"spsr_flg", 3}
379};
380
381/* Functions called by parser */
382/* ARM instructions */
383static void do_arit PARAMS ((char *operands, unsigned long flags));
384static void do_cmp PARAMS ((char *operands, unsigned long flags));
385static void do_mov PARAMS ((char *operands, unsigned long flags));
386static void do_ldst PARAMS ((char *operands, unsigned long flags));
387static void do_ldmstm PARAMS ((char *operands, unsigned long flags));
388static void do_branch PARAMS ((char *operands, unsigned long flags));
389static void do_swi PARAMS ((char *operands, unsigned long flags));
390/* Pseudo Op codes */
391static void do_adr PARAMS ((char *operands, unsigned long flags));
392static void do_nop PARAMS ((char *operands, unsigned long flags));
393/* ARM 2 */
394static void do_mul PARAMS ((char *operands, unsigned long flags));
395static void do_mla PARAMS ((char *operands, unsigned long flags));
396/* ARM 3 */
397static void do_swap PARAMS ((char *operands, unsigned long flags));
398/* ARM 6 */
399static void do_msr PARAMS ((char *operands, unsigned long flags));
400static void do_mrs PARAMS ((char *operands, unsigned long flags));
c479fc62 401/* ARM 7M */
338a7060 402static void do_mull PARAMS ((char *operands, unsigned long flags));
590c50d8
ILT
403/* ARM THUMB */
404static void do_bx PARAMS ((char *operands, unsigned long flags));
c479fc62 405
338a7060
DE
406/* Coprocessor Instructions */
407static void do_cdp PARAMS ((char *operands, unsigned long flags));
408static void do_lstc PARAMS ((char *operands, unsigned long flags));
409static void do_co_reg PARAMS ((char *operands, unsigned long flags));
410static void do_fp_ctrl PARAMS ((char *operands, unsigned long flags));
411static void do_fp_ldst PARAMS ((char *operands, unsigned long flags));
412static void do_fp_ldmstm PARAMS ((char *operands, unsigned long flags));
413static void do_fp_dyadic PARAMS ((char *operands, unsigned long flags));
414static void do_fp_monadic PARAMS ((char *operands, unsigned long flags));
415static void do_fp_cmp PARAMS ((char *operands, unsigned long flags));
416static void do_fp_from_reg PARAMS ((char *operands, unsigned long flags));
417static void do_fp_to_reg PARAMS ((char *operands, unsigned long flags));
418
419static void fix_new_arm PARAMS ((fragS *frag, int where,
420 short int size, expressionS *exp,
421 int pc_rel, int reloc));
422static int arm_reg_parse PARAMS ((char **ccp));
423static int arm_psr_parse PARAMS ((char **ccp));
ccc30467
ILT
424static void symbol_locate PARAMS ((symbolS *, CONST char *, segT,
425 valueT, fragS *));
426static int add_to_lit_pool PARAMS ((void));
f520aaee 427static unsigned validate_immediate PARAMS ((unsigned));
ccc30467
ILT
428static int validate_offset_imm PARAMS ((int, int));
429static void opcode_select PARAMS ((int));
430static void end_of_line PARAMS ((char *));
431static int reg_required_here PARAMS ((char **, int));
432static int psr_required_here PARAMS ((char **, int));
433static int psrf_required_here PARAMS ((char **, int));
434static int co_proc_number PARAMS ((char **));
435static int cp_opc_expr PARAMS ((char **, int, int));
436static int cp_reg_required_here PARAMS ((char **, int));
437static int fp_reg_required_here PARAMS ((char **, int));
438static int cp_address_offset PARAMS ((char **));
439static int cp_address_required_here PARAMS ((char **));
440static int my_get_float_expression PARAMS ((char **));
441static int skip_past_comma PARAMS ((char **));
442static int walk_no_bignums PARAMS ((symbolS *));
443static int negate_data_op PARAMS ((unsigned long *,
444 unsigned long));
445static int data_op2 PARAMS ((char **));
446static int fp_op2 PARAMS ((char **));
447static long reg_list PARAMS ((char **));
448static void thumb_load_store PARAMS ((char *, int, int));
449static int decode_shift PARAMS ((char **, int));
450static int ldst_extend PARAMS ((char **, int));
451static void thumb_add_sub PARAMS ((char *, int));
452static void insert_reg PARAMS ((int));
453static void thumb_shift PARAMS ((char *, int));
454static void thumb_mov_compare PARAMS ((char *, int));
455static void set_constant_flonums PARAMS ((void));
456static valueT md_chars_to_number PARAMS ((char *, int));
457static void insert_reg_alias PARAMS ((char *, int));
458static void output_inst PARAMS ((char *));
338a7060 459
c479fc62 460/* ARM instructions take 4bytes in the object file, Thumb instructions
590c50d8
ILT
461 take 2: */
462#define INSN_SIZE 4
338a7060
DE
463
464/* LONGEST_INST is the longest basic instruction name without conditions or
465 * flags.
590c50d8 466 * ARM7M has 4 of length 5
338a7060
DE
467 */
468
469#define LONGEST_INST 5
470
471struct asm_opcode
472{
473 CONST char *template; /* Basic string to match */
474 unsigned long value; /* Basic instruction code */
475 CONST char *comp_suffix; /* Compulsory suffix that must follow conds */
476 CONST struct asm_flg *flags; /* Bits to toggle if flag 'n' set */
477 unsigned long variants; /* Which CPU variants this exists for */
ccc30467
ILT
478 /* Function to call to parse args */
479 void (*parms) PARAMS ((char *, unsigned long));
338a7060
DE
480};
481
482static CONST struct asm_opcode insns[] =
483{
484/* ARM Instructions */
485 {"and", 0x00000000, NULL, s_flag, ARM_ANY, do_arit},
486 {"eor", 0x00200000, NULL, s_flag, ARM_ANY, do_arit},
487 {"sub", 0x00400000, NULL, s_flag, ARM_ANY, do_arit},
488 {"rsb", 0x00600000, NULL, s_flag, ARM_ANY, do_arit},
489 {"add", 0x00800000, NULL, s_flag, ARM_ANY, do_arit},
490 {"adc", 0x00a00000, NULL, s_flag, ARM_ANY, do_arit},
491 {"sbc", 0x00c00000, NULL, s_flag, ARM_ANY, do_arit},
492 {"rsc", 0x00e00000, NULL, s_flag, ARM_ANY, do_arit},
493 {"orr", 0x01800000, NULL, s_flag, ARM_ANY, do_arit},
494 {"bic", 0x01c00000, NULL, s_flag, ARM_ANY, do_arit},
495 {"tst", 0x01000000, NULL, cmp_flags, ARM_ANY, do_cmp},
496 {"teq", 0x01200000, NULL, cmp_flags, ARM_ANY, do_cmp},
497 {"cmp", 0x01400000, NULL, cmp_flags, ARM_ANY, do_cmp},
498 {"cmn", 0x01600000, NULL, cmp_flags, ARM_ANY, do_cmp},
499 {"mov", 0x01a00000, NULL, s_flag, ARM_ANY, do_mov},
500 {"mvn", 0x01e00000, NULL, s_flag, ARM_ANY, do_mov},
590c50d8
ILT
501 {"str", 0x04000000, NULL, str_flags, ARM_ANY, do_ldst},
502 {"ldr", 0x04100000, NULL, ldr_flags, ARM_ANY, do_ldst},
338a7060
DE
503 {"stm", 0x08000000, NULL, stm_flags, ARM_ANY, do_ldmstm},
504 {"ldm", 0x08100000, NULL, ldm_flags, ARM_ANY, do_ldmstm},
505 {"swi", 0x0f000000, NULL, NULL, ARM_ANY, do_swi},
590c50d8
ILT
506 {"bl", 0x0bfffffe, NULL, NULL, ARM_ANY, do_branch},
507 {"b", 0x0afffffe, NULL, NULL, ARM_ANY, do_branch},
338a7060
DE
508
509/* Pseudo ops */
510 {"adr", 0x028f0000, NULL, NULL, ARM_ANY, do_adr},
511 {"nop", 0x01a00000, NULL, NULL, ARM_ANY, do_nop},
512
513/* ARM 2 multiplies */
514 {"mul", 0x00000090, NULL, s_flag, ARM_2UP, do_mul},
515 {"mla", 0x00200090, NULL, s_flag, ARM_2UP, do_mla},
516
517/* ARM 3 - swp instructions */
518 {"swp", 0x01000090, NULL, byte_flag, ARM_3UP, do_swap},
519
520/* ARM 6 Coprocessor instructions */
521 {"mrs", 0x010f0000, NULL, NULL, ARM_6UP, do_mrs},
522 {"msr", 0x0128f000, NULL, NULL, ARM_6UP, do_msr},
523
c479fc62 524/* ARM 7M long multiplies - need signed/unsigned flags! */
338a7060
DE
525 {"smull", 0x00c00090, NULL, s_flag, ARM_LONGMUL, do_mull},
526 {"umull", 0x00800090, NULL, s_flag, ARM_LONGMUL, do_mull},
527 {"smlal", 0x00e00090, NULL, s_flag, ARM_LONGMUL, do_mull},
528 {"umlal", 0x00a00090, NULL, s_flag, ARM_LONGMUL, do_mull},
529
590c50d8
ILT
530/* ARM THUMB interworking */
531 {"bx", 0x012fff10, NULL, NULL, ARM_THUMB, do_bx},
532
338a7060
DE
533/* Floating point instructions */
534 {"wfs", 0x0e200110, NULL, NULL, FPU_ALL, do_fp_ctrl},
535 {"rfs", 0x0e300110, NULL, NULL, FPU_ALL, do_fp_ctrl},
536 {"wfc", 0x0e400110, NULL, NULL, FPU_ALL, do_fp_ctrl},
537 {"rfc", 0x0e500110, NULL, NULL, FPU_ALL, do_fp_ctrl},
538 {"ldf", 0x0c100100, "sdep", NULL, FPU_ALL, do_fp_ldst},
539 {"stf", 0x0c000100, "sdep", NULL, FPU_ALL, do_fp_ldst},
540 {"lfm", 0x0c100200, NULL, lfm_flags, FPU_MEMMULTI, do_fp_ldmstm},
541 {"sfm", 0x0c000200, NULL, sfm_flags, FPU_MEMMULTI, do_fp_ldmstm},
542 {"mvf", 0x0e008100, "sde", round_flags, FPU_ALL, do_fp_monadic},
543 {"mnf", 0x0e108100, "sde", round_flags, FPU_ALL, do_fp_monadic},
544 {"abs", 0x0e208100, "sde", round_flags, FPU_ALL, do_fp_monadic},
545 {"rnd", 0x0e308100, "sde", round_flags, FPU_ALL, do_fp_monadic},
546 {"sqt", 0x0e408100, "sde", round_flags, FPU_ALL, do_fp_monadic},
547 {"log", 0x0e508100, "sde", round_flags, FPU_ALL, do_fp_monadic},
548 {"lgn", 0x0e608100, "sde", round_flags, FPU_ALL, do_fp_monadic},
549 {"exp", 0x0e708100, "sde", round_flags, FPU_ALL, do_fp_monadic},
550 {"sin", 0x0e808100, "sde", round_flags, FPU_ALL, do_fp_monadic},
551 {"cos", 0x0e908100, "sde", round_flags, FPU_ALL, do_fp_monadic},
552 {"tan", 0x0ea08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
553 {"asn", 0x0eb08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
554 {"acs", 0x0ec08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
555 {"atn", 0x0ed08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
556 {"urd", 0x0ee08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
557 {"nrm", 0x0ef08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
558 {"adf", 0x0e000100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
559 {"suf", 0x0e200100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
560 {"rsf", 0x0e300100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
561 {"muf", 0x0e100100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
562 {"dvf", 0x0e400100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
563 {"rdf", 0x0e500100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
564 {"pow", 0x0e600100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
565 {"rpw", 0x0e700100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
566 {"rmf", 0x0e800100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
567 {"fml", 0x0e900100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
568 {"fdv", 0x0ea00100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
569 {"frd", 0x0eb00100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
570 {"pol", 0x0ec00100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
571 {"cmf", 0x0e90f110, NULL, except_flag, FPU_ALL, do_fp_cmp},
572 {"cnf", 0x0eb0f110, NULL, except_flag, FPU_ALL, do_fp_cmp},
573/* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should not
574 be an optional suffix, but part of the instruction. To be compatible,
575 we accept either. */
576 {"cmfe", 0x0ed0f110, NULL, NULL, FPU_ALL, do_fp_cmp},
577 {"cnfe", 0x0ef0f110, NULL, NULL, FPU_ALL, do_fp_cmp},
578 {"flt", 0x0e000110, "sde", round_flags, FPU_ALL, do_fp_from_reg},
590c50d8 579 {"fix", 0x0e100110, NULL, fix_flags, FPU_ALL, do_fp_to_reg},
338a7060
DE
580
581/* Generic copressor instructions */
c479fc62
JSC
582 {"cdp", 0x0e000000, NULL, NULL, ARM_2UP, do_cdp},
583 {"ldc", 0x0c100000, NULL, cplong_flag, ARM_2UP, do_lstc},
584 {"stc", 0x0c000000, NULL, cplong_flag, ARM_2UP, do_lstc},
585 {"mcr", 0x0e000010, NULL, NULL, ARM_2UP, do_co_reg},
586 {"mrc", 0x0e100010, NULL, NULL, ARM_2UP, do_co_reg},
338a7060
DE
587};
588
589/* defines for various bits that we will want to toggle */
590
591#define INST_IMMEDIATE 0x02000000
592#define OFFSET_REG 0x02000000
c479fc62 593#define HWOFFSET_IMM 0x00400000
338a7060
DE
594#define SHIFT_BY_REG 0x00000010
595#define PRE_INDEX 0x01000000
596#define INDEX_UP 0x00800000
597#define WRITE_BACK 0x00200000
598#define MULTI_SET_PSR 0x00400000
599
600#define LITERAL_MASK 0xf000f000
601#define COND_MASK 0xf0000000
602#define OPCODE_MASK 0xfe1fffff
603#define DATA_OP_SHIFT 21
604
605/* Codes to distinguish the arithmetic instructions */
606
607#define OPCODE_AND 0
608#define OPCODE_EOR 1
609#define OPCODE_SUB 2
610#define OPCODE_RSB 3
611#define OPCODE_ADD 4
612#define OPCODE_ADC 5
613#define OPCODE_SBC 6
614#define OPCODE_RSC 7
615#define OPCODE_TST 8
616#define OPCODE_TEQ 9
617#define OPCODE_CMP 10
618#define OPCODE_CMN 11
619#define OPCODE_ORR 12
620#define OPCODE_MOV 13
621#define OPCODE_BIC 14
622#define OPCODE_MVN 15
623
ccc30467 624static void do_t_nop PARAMS ((char *operands));
590c50d8
ILT
625static void do_t_arit PARAMS ((char *operands));
626static void do_t_add PARAMS ((char *operands));
627static void do_t_asr PARAMS ((char *operands));
ccc30467
ILT
628static void do_t_branch9 PARAMS ((char *operands));
629static void do_t_branch12 PARAMS ((char *operands));
630static void do_t_branch23 PARAMS ((char *operands));
590c50d8
ILT
631static void do_t_bx PARAMS ((char *operands));
632static void do_t_compare PARAMS ((char *operands));
633static void do_t_ldmstm PARAMS ((char *operands));
634static void do_t_ldr PARAMS ((char *operands));
635static void do_t_ldrb PARAMS ((char *operands));
636static void do_t_ldrh PARAMS ((char *operands));
637static void do_t_lds PARAMS ((char *operands));
638static void do_t_lsl PARAMS ((char *operands));
639static void do_t_lsr PARAMS ((char *operands));
640static void do_t_mov PARAMS ((char *operands));
641static void do_t_push_pop PARAMS ((char *operands));
642static void do_t_str PARAMS ((char *operands));
643static void do_t_strb PARAMS ((char *operands));
644static void do_t_strh PARAMS ((char *operands));
645static void do_t_sub PARAMS ((char *operands));
646static void do_t_swi PARAMS ((char *operands));
647static void do_t_adr PARAMS ((char *operands));
648
649#define T_OPCODE_MUL 0x4340
650#define T_OPCODE_TST 0x4200
651#define T_OPCODE_CMN 0x42c0
652#define T_OPCODE_NEG 0x4240
653#define T_OPCODE_MVN 0x43c0
654
655#define T_OPCODE_ADD_R3 0x1800
656#define T_OPCODE_SUB_R3 0x1a00
657#define T_OPCODE_ADD_HI 0x4400
658#define T_OPCODE_ADD_ST 0xb000
659#define T_OPCODE_SUB_ST 0xb080
660#define T_OPCODE_ADD_SP 0xa800
661#define T_OPCODE_ADD_PC 0xa000
662#define T_OPCODE_ADD_I8 0x3000
663#define T_OPCODE_SUB_I8 0x3800
664#define T_OPCODE_ADD_I3 0x1c00
665#define T_OPCODE_SUB_I3 0x1e00
666
667#define T_OPCODE_ASR_R 0x4100
668#define T_OPCODE_LSL_R 0x4080
669#define T_OPCODE_LSR_R 0x40c0
670#define T_OPCODE_ASR_I 0x1000
671#define T_OPCODE_LSL_I 0x0000
672#define T_OPCODE_LSR_I 0x0800
673
674#define T_OPCODE_MOV_I8 0x2000
675#define T_OPCODE_CMP_I8 0x2800
676#define T_OPCODE_CMP_LR 0x4280
677#define T_OPCODE_MOV_HR 0x4600
678#define T_OPCODE_CMP_HR 0x4500
679
680#define T_OPCODE_LDR_PC 0x4800
681#define T_OPCODE_LDR_SP 0x9800
682#define T_OPCODE_STR_SP 0x9000
683#define T_OPCODE_LDR_IW 0x6800
684#define T_OPCODE_STR_IW 0x6000
685#define T_OPCODE_LDR_IH 0x8800
686#define T_OPCODE_STR_IH 0x8000
687#define T_OPCODE_LDR_IB 0x7800
688#define T_OPCODE_STR_IB 0x7000
689#define T_OPCODE_LDR_RW 0x5800
690#define T_OPCODE_STR_RW 0x5000
691#define T_OPCODE_LDR_RH 0x5a00
692#define T_OPCODE_STR_RH 0x5200
693#define T_OPCODE_LDR_RB 0x5c00
694#define T_OPCODE_STR_RB 0x5400
695
696#define T_OPCODE_PUSH 0xb400
697#define T_OPCODE_POP 0xbc00
698
699#define T_OPCODE_BRANCH 0xe7fe
700
701static int thumb_reg PARAMS ((char **str, int hi_lo));
702
703#define THUMB_SIZE 2 /* Size of thumb instruction */
704#define THUMB_REG_LO 0x1
705#define THUMB_REG_HI 0x2
706#define THUMB_REG_ANY 0x3
707
708#define THUMB_H1 0x0080
709#define THUMB_H2 0x0040
710
711#define THUMB_ASR 0
712#define THUMB_LSL 1
713#define THUMB_LSR 2
714
715#define THUMB_MOVE 0
716#define THUMB_COMPARE 1
717
718#define THUMB_LOAD 0
719#define THUMB_STORE 1
720
721#define THUMB_PP_PC_LR 0x0100
722
723/* These three are used for immediate shifts, do not alter */
724#define THUMB_WORD 2
725#define THUMB_HALFWORD 1
726#define THUMB_BYTE 0
727
728struct thumb_opcode
729{
730 CONST char *template; /* Basic string to match */
731 unsigned long value; /* Basic instruction code */
732 int size;
ccc30467
ILT
733 /* Function to call to parse args */
734 void (*parms) PARAMS ((char *));
590c50d8
ILT
735};
736
737static CONST struct thumb_opcode tinsns[] =
738{
739 {"adc", 0x4140, 2, do_t_arit},
740 {"add", 0x0000, 2, do_t_add},
741 {"and", 0x4000, 2, do_t_arit},
742 {"asr", 0x0000, 2, do_t_asr},
ccc30467
ILT
743 {"b", T_OPCODE_BRANCH, 2, do_t_branch12},
744 {"beq", 0xd0fe, 2, do_t_branch9},
745 {"bne", 0xd1fe, 2, do_t_branch9},
746 {"bcs", 0xd2fe, 2, do_t_branch9},
747 {"bhs", 0xd2fe, 2, do_t_branch9},
748 {"bcc", 0xd3fe, 2, do_t_branch9},
749 {"bul", 0xd3fe, 2, do_t_branch9},
750 {"blo", 0xd3fe, 2, do_t_branch9},
751 {"bmi", 0xd4fe, 2, do_t_branch9},
752 {"bpl", 0xd5fe, 2, do_t_branch9},
753 {"bvs", 0xd6fe, 2, do_t_branch9},
754 {"bvc", 0xd7fe, 2, do_t_branch9},
755 {"bhi", 0xd8fe, 2, do_t_branch9},
756 {"bls", 0xd9fe, 2, do_t_branch9},
757 {"bge", 0xdafe, 2, do_t_branch9},
758 {"blt", 0xdbfe, 2, do_t_branch9},
759 {"bgt", 0xdcfe, 2, do_t_branch9},
760 {"ble", 0xddfe, 2, do_t_branch9},
590c50d8 761 {"bic", 0x4380, 2, do_t_arit},
ccc30467 762 {"bl", 0xf7fffffe, 4, do_t_branch23},
590c50d8
ILT
763 {"bx", 0x4700, 2, do_t_bx},
764 {"cmn", T_OPCODE_CMN, 2, do_t_arit},
765 {"cmp", 0x0000, 2, do_t_compare},
766 {"eor", 0x4040, 2, do_t_arit},
767 {"ldmia", 0xc800, 2, do_t_ldmstm},
768 {"ldr", 0x0000, 2, do_t_ldr},
769 {"ldrb", 0x0000, 2, do_t_ldrb},
770 {"ldrh", 0x0000, 2, do_t_ldrh},
771 {"ldrsb", 0x5600, 2, do_t_lds},
772 {"ldrsh", 0x5e00, 2, do_t_lds},
773 {"ldsb", 0x5600, 2, do_t_lds},
774 {"ldsh", 0x5e00, 2, do_t_lds},
775 {"lsl", 0x0000, 2, do_t_lsl},
776 {"lsr", 0x0000, 2, do_t_lsr},
777 {"mov", 0x0000, 2, do_t_mov},
778 {"mul", T_OPCODE_MUL, 2, do_t_arit},
779 {"mvn", T_OPCODE_MVN, 2, do_t_arit},
780 {"neg", T_OPCODE_NEG, 2, do_t_arit},
781 {"orr", 0x4300, 2, do_t_arit},
782 {"pop", 0xbc00, 2, do_t_push_pop},
783 {"push", 0xb400, 2, do_t_push_pop},
784 {"ror", 0x41c0, 2, do_t_arit},
785 {"sbc", 0x4180, 2, do_t_arit},
786 {"stmia", 0xc000, 2, do_t_ldmstm},
787 {"str", 0x0000, 2, do_t_str},
788 {"strb", 0x0000, 2, do_t_strb},
789 {"strh", 0x0000, 2, do_t_strh},
790 {"swi", 0xdf00, 2, do_t_swi},
791 {"sub", 0x0000, 2, do_t_sub},
792 {"tst", T_OPCODE_TST, 2, do_t_arit},
793 /* Pseudo ops: */
794 {"adr", 0x0000, 2, do_t_adr},
ccc30467 795 {"nop", 0x46C0, 2, do_t_nop}, /* mov r8,r8 */
590c50d8
ILT
796};
797
338a7060
DE
798struct reg_entry
799{
800 CONST char *name;
801 int number;
802};
803
804#define int_register(reg) ((reg) >= 0 && (reg) <= 15)
805#define cp_register(reg) ((reg) >= 32 && (reg) <= 47)
806#define fp_register(reg) ((reg) >= 16 && (reg) <= 23)
807
808#define REG_PC 15
590c50d8
ILT
809#define REG_LR 14
810#define REG_SP 13
338a7060
DE
811
812/* These are the standard names; Users can add aliases with .req */
813static CONST struct reg_entry reg_table[] =
814{
815 /* Processor Register Numbers */
590c50d8
ILT
816 {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
817 {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
818 {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
819 {"r12", 12}, {"r13", REG_SP},{"r14", REG_LR},{"r15", REG_PC},
338a7060 820 /* APCS conventions */
590c50d8
ILT
821 {"a1", 0}, {"a2", 1}, {"a3", 2}, {"a4", 3},
822 {"v1", 4}, {"v2", 5}, {"v3", 6}, {"v4", 7}, {"v5", 8},
823 {"v6", 9}, {"sb", 9}, {"v7", 10}, {"sl", 10},
824 {"fp", 11}, {"ip", 12}, {"sp", REG_SP},{"lr", REG_LR},{"pc", REG_PC},
338a7060
DE
825 /* FP Registers */
826 {"f0", 16}, {"f1", 17}, {"f2", 18}, {"f3", 19},
827 {"f4", 20}, {"f5", 21}, {"f6", 22}, {"f7", 23},
828 {"c0", 32}, {"c1", 33}, {"c2", 34}, {"c3", 35},
829 {"c4", 36}, {"c5", 37}, {"c6", 38}, {"c7", 39},
830 {"c8", 40}, {"c9", 41}, {"c10", 42}, {"c11", 43},
831 {"c12", 44}, {"c13", 45}, {"c14", 46}, {"c15", 47},
832 {"cr0", 32}, {"cr1", 33}, {"cr2", 34}, {"cr3", 35},
833 {"cr4", 36}, {"cr5", 37}, {"cr6", 38}, {"cr7", 39},
834 {"cr8", 40}, {"cr9", 41}, {"cr10", 42}, {"cr11", 43},
835 {"cr12", 44}, {"cr13", 45}, {"cr14", 46}, {"cr15", 47},
836 {NULL, 0}
837};
838
839static CONST char *bad_args = "Bad arguments to instruction";
840static CONST char *bad_pc = "r15 not allowed here";
841
842static struct hash_control *arm_ops_hsh = NULL;
590c50d8 843static struct hash_control *arm_tops_hsh = NULL;
338a7060
DE
844static struct hash_control *arm_cond_hsh = NULL;
845static struct hash_control *arm_shift_hsh = NULL;
846static struct hash_control *arm_reg_hsh = NULL;
847static struct hash_control *arm_psr_hsh = NULL;
848
849/* This table describes all the machine specific pseudo-ops the assembler
850 has to support. The fields are:
851 pseudo-op name without dot
852 function to call to execute this pseudo-op
853 Integer arg to pass to the function
854 */
855
856static void s_req PARAMS ((int));
857static void s_align PARAMS ((int));
858static void s_bss PARAMS ((int));
859static void s_even PARAMS ((int));
860static void s_ltorg PARAMS ((int));
590c50d8
ILT
861static void s_arm PARAMS ((int));
862static void s_thumb PARAMS ((int));
863static void s_code PARAMS ((int));
f520aaee
NC
864static void s_force_thumb PARAMS ((int));
865static void s_thumb_func PARAMS ((int));
338a7060
DE
866
867static int my_get_expression PARAMS ((expressionS *, char **));
868
869CONST pseudo_typeS md_pseudo_table[] =
870{
871 {"req", s_req, 0}, /* Never called becasue '.req' does not start line */
872 {"bss", s_bss, 0},
873 {"align", s_align, 0},
590c50d8
ILT
874 {"arm", s_arm, 0},
875 {"thumb", s_thumb, 0},
876 {"code", s_code, 0},
f520aaee
NC
877 {"force_thumb", s_force_thumb, 0},
878 {"thumb_func", s_thumb_func, 0},
338a7060
DE
879 {"even", s_even, 0},
880 {"ltorg", s_ltorg, 0},
881 {"pool", s_ltorg, 0},
882 {"word", cons, 4},
883 {"extend", float_cons, 'x'},
884 {"ldouble", float_cons, 'x'},
885 {"packed", float_cons, 'p'},
886 {0, 0, 0}
887};
888
889/* Stuff needed to resolve the label ambiguity
890 As:
891 ...
892 label: <insn>
893 may differ from:
894 ...
895 label:
896 <insn>
897*/
898
f520aaee
NC
899symbolS * last_label_seen;
900static int label_is_thumb_function_name = false;
338a7060
DE
901
902/* Literal stuff */
903
904#define MAX_LITERAL_POOL_SIZE 1024
905
906typedef struct literalS
907{
908 struct expressionS exp;
909 struct arm_it *inst;
910} literalT;
911
912literalT literals[MAX_LITERAL_POOL_SIZE];
913int next_literal_pool_place = 0; /* Next free entry in the pool */
914int lit_pool_num = 1; /* Next literal pool number */
915symbolS *current_poolP = NULL;
ccc30467 916symbolS *symbol_make_empty PARAMS ((void));
338a7060
DE
917
918static int
919add_to_lit_pool ()
920{
c479fc62
JSC
921 int lit_count = 0;
922
338a7060
DE
923 if (current_poolP == NULL)
924 current_poolP = symbol_make_empty();
925
c479fc62
JSC
926 /* Check if this literal value is already in the pool: */
927 while (lit_count < next_literal_pool_place)
338a7060 928 {
c479fc62
JSC
929 if (literals[lit_count].exp.X_op == inst.reloc.exp.X_op
930 && inst.reloc.exp.X_op == O_constant
931 && literals[lit_count].exp.X_add_number == inst.reloc.exp.X_add_number
932 && literals[lit_count].exp.X_unsigned == inst.reloc.exp.X_unsigned)
933 break;
934 lit_count++;
935 }
936
937 if (lit_count == next_literal_pool_place) /* new entry */
938 {
939 if (next_literal_pool_place > MAX_LITERAL_POOL_SIZE)
940 {
f520aaee 941 inst.error = "Literal Pool Overflow";
c479fc62
JSC
942 return FAIL;
943 }
944
945 literals[next_literal_pool_place].exp = inst.reloc.exp;
946 lit_count = next_literal_pool_place++;
338a7060
DE
947 }
948
338a7060 949 inst.reloc.exp.X_op = O_symbol;
c479fc62 950 inst.reloc.exp.X_add_number = (lit_count)*4-8;
338a7060
DE
951 inst.reloc.exp.X_add_symbol = current_poolP;
952
953 return SUCCESS;
954}
955
ccc30467 956/* Can't use symbol_new here, so have to create a symbol and then at
590c50d8 957 a later date assign it a value. Thats what these functions do */
338a7060
DE
958static void
959symbol_locate (symbolP, name, segment, valu, frag)
960 symbolS *symbolP;
961 CONST char *name; /* It is copied, the caller can modify */
962 segT segment; /* Segment identifier (SEG_<something>) */
963 valueT valu; /* Symbol value */
964 fragS *frag; /* Associated fragment */
965{
966 unsigned int name_length;
967 char *preserved_copy_of_name;
968
969 name_length = strlen (name) + 1; /* +1 for \0 */
970 obstack_grow (&notes, name, name_length);
971 preserved_copy_of_name = obstack_finish (&notes);
972#ifdef STRIP_UNDERSCORE
973 if (preserved_copy_of_name[0] == '_')
974 preserved_copy_of_name++;
975#endif
976
977#ifdef tc_canonicalize_symbol_name
978 preserved_copy_of_name =
979 tc_canonicalize_symbol_name (preserved_copy_of_name);
980#endif
981
982 S_SET_NAME (symbolP, preserved_copy_of_name);
983
984 S_SET_SEGMENT (symbolP, segment);
985 S_SET_VALUE (symbolP, valu);
986 symbol_clear_list_pointers(symbolP);
987
988 symbolP->sy_frag = frag;
989
990 /*
991 * Link to end of symbol chain.
992 */
993 {
994 extern int symbol_table_frozen;
995 if (symbol_table_frozen)
996 abort ();
997 }
998
999 symbol_append (symbolP, symbol_lastP, &symbol_rootP, &symbol_lastP);
1000
1001 obj_symbol_new_hook (symbolP);
1002
1003#ifdef tc_symbol_new_hook
1004 tc_symbol_new_hook (symbolP);
1005#endif
1006
1007#ifdef DEBUG_SYMS
1008 verify_symbol_chain(symbol_rootP, symbol_lastP);
1009#endif /* DEBUG_SYMS */
1010}
1011
1012symbolS *
1013symbol_make_empty ()
1014{
1015 symbolS *symbolP;
1016
1017 symbolP = (symbolS *) obstack_alloc (&notes, sizeof (symbolS));
1018
1019 /* symbol must be born in some fixed state. This seems as good as any. */
1020 memset (symbolP, 0, sizeof (symbolS));
1021
338a7060
DE
1022 symbolP->bsym = bfd_make_empty_symbol (stdoutput);
1023 assert (symbolP->bsym != 0);
1024 symbolP->bsym->udata.p = (PTR) symbolP;
338a7060
DE
1025
1026 return symbolP;
1027}
ccc30467 1028
f520aaee 1029/* Check that an immediate is valid, and if so, convert it to the right format. */
338a7060 1030
f520aaee 1031static unsigned int
338a7060 1032validate_immediate (val)
f520aaee 1033 unsigned int val;
338a7060 1034{
f520aaee
NC
1035 unsigned int a;
1036 unsigned int i;
338a7060 1037
f520aaee
NC
1038#define rotate_left(v, n) (v << n | v >> (32 - n))
1039
1040 for (i = 0; i < 32; i += 2)
1041 if ((a = rotate_left (val, i)) <= 0xff)
1042 return a | (i << 7); /* 12-bit pack: [shift-cnt,const] */
1043 return FAIL;
338a7060
DE
1044}
1045
1046static int
c479fc62 1047validate_offset_imm (val, hwse)
338a7060 1048 int val;
c479fc62 1049 int hwse;
338a7060 1050{
c479fc62
JSC
1051 if ((hwse && (val < -255 || val > 255))
1052 || (val < -4095 || val > 4095))
1053 return FAIL;
338a7060
DE
1054 return val;
1055}
1056
1057
1058static void
1059s_req (a)
1060 int a;
1061{
1062 as_bad ("Invalid syntax for .req directive.");
1063}
1064
1065static void
1066s_bss (ignore)
1067 int ignore;
1068{
1069 /* We don't support putting frags in the BSS segment, we fake it by
1070 marking in_bss, then looking at s_skip for clues?.. */
1071 subseg_set (bss_section, 0);
1072 demand_empty_rest_of_line ();
1073}
1074
1075static void
1076s_even (ignore)
1077 int ignore;
1078{
1079 if (!need_pass_2) /* Never make frag if expect extra pass. */
590c50d8 1080 frag_align (1, 0, 0);
338a7060
DE
1081 record_alignment (now_seg, 1);
1082 demand_empty_rest_of_line ();
1083}
1084
1085static void
1086s_ltorg (internal)
1087 int internal;
1088{
1089 int lit_count = 0;
1090 char sym_name[20];
1091
1092 if (current_poolP == NULL)
1093 {
1094 /* Nothing to do */
1095 if (!internal)
1096 as_tsktsk ("Nothing to put in the pool\n");
1097 return;
1098 }
1099
1100 /* Align pool as you have word accesses */
1101 /* Only make a frag if we have to ... */
1102 if (!need_pass_2)
590c50d8 1103 frag_align (2, 0, 0);
338a7060
DE
1104
1105 record_alignment (now_seg, 2);
1106
1107 if (internal)
1108 as_tsktsk ("Inserting implicit pool at change of section");
1109
1110 sprintf (sym_name, "$$lit_\002%x", lit_pool_num++);
1111
1112 symbol_locate (current_poolP, sym_name, now_seg,
c479fc62 1113 (valueT) frag_now_fix (), frag_now);
338a7060
DE
1114 symbol_table_insert (current_poolP);
1115
f520aaee
NC
1116 ARM_SET_THUMB (current_poolP, thumb_mode);
1117 ARM_SET_INTERWORK (current_poolP, support_interwork);
1118
338a7060
DE
1119 while (lit_count < next_literal_pool_place)
1120 /* First output the expression in the instruction to the pool */
1121 emit_expr (&(literals[lit_count++].exp), 4); /* .word */
1122
1123 next_literal_pool_place = 0;
1124 current_poolP = NULL;
1125}
1126
c479fc62 1127#if 0 /* not used */
338a7060
DE
1128static void
1129arm_align (power, fill)
1130 int power;
1131 int fill;
1132{
1133 /* Only make a frag if we HAVE to ... */
1134 if (power && !need_pass_2)
590c50d8 1135 frag_align (power, fill, 0);
338a7060
DE
1136
1137 record_alignment (now_seg, power);
1138}
c479fc62 1139#endif
338a7060
DE
1140
1141static void
1142s_align (unused) /* Same as s_align_ptwo but align 0 => align 2 */
1143 int unused;
1144{
1145 register int temp;
1146 register long temp_fill;
1147 long max_alignment = 15;
1148
1149 temp = get_absolute_expression ();
1150 if (temp > max_alignment)
1151 as_bad ("Alignment too large: %d. assumed.", temp = max_alignment);
1152 else if (temp < 0)
1153 {
1154 as_bad ("Alignment negative. 0 assumed.");
1155 temp = 0;
1156 }
1157
1158 if (*input_line_pointer == ',')
1159 {
1160 input_line_pointer++;
1161 temp_fill = get_absolute_expression ();
1162 }
1163 else
1164 temp_fill = 0;
1165
1166 if (!temp)
1167 temp = 2;
1168
1169 /* Only make a frag if we HAVE to. . . */
1170 if (temp && !need_pass_2)
590c50d8 1171 frag_align (temp, (int) temp_fill, 0);
338a7060
DE
1172 demand_empty_rest_of_line ();
1173
1174 record_alignment (now_seg, temp);
1175}
1176
f520aaee
NC
1177static void
1178s_force_thumb (ignore)
1179 int ignore;
1180{
1181 /* If we are not already in thumb mode go into it, EVEN if
1182 the target processor does not support thumb instructions.
1183 This is used by gcc/config/arm/lib1funcs.asm for example
1184 to compile interworking support functions even if the
1185 target processor should not support interworking. */
1186
1187 if (! thumb_mode)
1188 {
1189 thumb_mode = 1;
1190
1191 record_alignment (now_seg, 1);
1192 }
1193
1194 demand_empty_rest_of_line ();
1195}
1196
1197static void
1198s_thumb_func (ignore)
1199 int ignore;
1200{
1201 /* The following label is the name/address of the start of a Thumb function.
1202 We need to know this for the interworking support. */
1203
1204 label_is_thumb_function_name = true;
1205
1206 demand_empty_rest_of_line();
1207}
1208
590c50d8
ILT
1209static void
1210opcode_select (width)
1211 int width;
1212{
1213 switch (width)
1214 {
1215 case 16:
1216 if (! thumb_mode)
1217 {
1218 if (! (cpu_variant & ARM_THUMB))
1219 as_bad ("selected processor does not support THUMB opcodes");
1220 thumb_mode = 1;
1221 /* No need to force the alignment, since we will have been
1222 coming from ARM mode, which is word-aligned. */
1223 record_alignment (now_seg, 1);
1224 }
1225 break;
1226
1227 case 32:
1228 if (thumb_mode)
1229 {
1230 if ((cpu_variant & ARM_ANY) == ARM_THUMB)
1231 as_bad ("selected processor does not support ARM opcodes");
1232 thumb_mode = 0;
1233 if (!need_pass_2)
1234 frag_align (2, 0, 0);
1235 record_alignment (now_seg, 1);
1236 }
1237 break;
1238
1239 default:
1240 as_bad ("invalid instruction size selected (%d)", width);
1241 }
1242}
1243
1244static void
1245s_arm (ignore)
1246 int ignore;
1247{
1248 opcode_select (32);
1249 demand_empty_rest_of_line ();
1250}
1251
1252static void
1253s_thumb (ignore)
1254 int ignore;
1255{
1256 opcode_select (16);
1257 demand_empty_rest_of_line ();
1258}
1259
1260static void
1261s_code (unused)
1262 int unused;
1263{
1264 register int temp;
1265
1266 temp = get_absolute_expression ();
1267 switch (temp)
1268 {
1269 case 16:
1270 case 32:
1271 opcode_select(temp);
1272 break;
1273
1274 default:
ccc30467 1275 as_bad ("invalid operand to .code directive (%d) (expecting 16 or 32)", temp);
590c50d8
ILT
1276 }
1277}
1278
338a7060
DE
1279static void
1280end_of_line (str)
1281 char *str;
1282{
1283 while (*str == ' ')
1284 str++;
1285
1286 if (*str != '\0')
1287 inst.error = "Garbage following instruction";
1288}
1289
1290static int
1291skip_past_comma (str)
1292 char **str;
1293{
1294 char *p = *str, c;
1295 int comma = 0;
1296
1297 while ((c = *p) == ' ' || c == ',')
1298 {
1299 p++;
1300 if (c == ',' && comma++)
1301 return FAIL;
1302 }
1303
1304 if (c == '\0')
1305 return FAIL;
1306
1307 *str = p;
1308 return comma ? SUCCESS : FAIL;
1309}
1310
1311/* A standard register must be given at this point. Shift is the place to
1312 put it in the instruction. */
1313
1314static int
1315reg_required_here (str, shift)
1316 char **str;
1317 int shift;
1318{
1319 int reg;
1320 char *start = *str;
1321
1322 if ((reg = arm_reg_parse (str)) != FAIL && int_register (reg))
1323 {
1324 inst.instruction |= reg << shift;
1325 return reg;
1326 }
1327
1328 /* In the few cases where we might be able to accept something else
1329 this error can be overridden */
1330 inst.error = "Register expected";
1331
1332 /* Restore the start point, we may have got a reg of the wrong class. */
1333 *str = start;
1334 return FAIL;
1335}
1336
1337static int
1338psr_required_here (str, shift)
1339 char **str;
1340 int shift;
1341{
1342 int psr;
1343 char *start = *str;
1344
1345 if ((psr = arm_psr_parse (str)) != FAIL && psr < 2)
1346 {
1347 if (psr == 1)
1348 inst.instruction |= 1 << shift; /* Should be bit 22 */
1349 return psr;
1350 }
1351
1352 /* In the few cases where we might be able to accept something else
1353 this error can be overridden */
1354 inst.error = "<psr> expected";
1355
1356 /* Restore the start point. */
1357 *str = start;
1358 return FAIL;
1359}
1360
1361static int
1362psrf_required_here (str, shift)
1363 char **str;
1364 int shift;
1365{
1366 int psrf;
1367 char *start = *str;
1368
1369 if ((psrf = arm_psr_parse (str)) != FAIL && psrf > 1)
1370 {
1371 if (psrf == 1 || psrf == 3)
1372 inst.instruction |= 1 << shift; /* Should be bit 22 */
1373 return psrf;
1374 }
1375
1376 /* In the few cases where we might be able to accept something else
1377 this error can be overridden */
1378 inst.error = "<psrf> expected";
1379
1380 /* Restore the start point. */
1381 *str = start;
1382 return FAIL;
1383}
1384
1385static int
1386co_proc_number (str)
1387 char **str;
1388{
1389 int processor, pchar;
1390
1391 while (**str == ' ')
1392 (*str)++;
1393
1394 /* The data sheet seems to imply that just a number on its own is valid
1395 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
1396 accept either. */
1397 if (**str == 'p' || **str == 'P')
1398 (*str)++;
1399
1400 pchar = *(*str)++;
1401 if (pchar >= '0' && pchar <= '9')
1402 {
1403 processor = pchar - '0';
1404 if (**str >= '0' && **str <= '9')
1405 {
1406 processor = processor * 10 + *(*str)++ - '0';
1407 if (processor > 15)
1408 {
1409 inst.error = "Illegal co-processor number";
1410 return FAIL;
1411 }
1412 }
1413 }
1414 else
1415 {
1416 inst.error = "Bad or missing co-processor number";
1417 return FAIL;
1418 }
1419
1420 inst.instruction |= processor << 8;
1421 return SUCCESS;
1422}
1423
1424static int
1425cp_opc_expr (str, where, length)
1426 char **str;
1427 int where;
1428 int length;
1429{
1430 expressionS expr;
1431
1432 while (**str == ' ')
1433 (*str)++;
1434
1435 memset (&expr, '\0', sizeof (expr));
1436
1437 if (my_get_expression (&expr, str))
1438 return FAIL;
1439 if (expr.X_op != O_constant)
1440 {
1441 inst.error = "bad or missing expression";
1442 return FAIL;
1443 }
1444
1445 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
1446 {
1447 inst.error = "immediate co-processor expression too large";
1448 return FAIL;
1449 }
1450
1451 inst.instruction |= expr.X_add_number << where;
1452 return SUCCESS;
1453}
1454
1455static int
1456cp_reg_required_here (str, where)
1457 char **str;
1458 int where;
1459{
1460 int reg;
1461 char *start = *str;
1462
1463 if ((reg = arm_reg_parse (str)) != FAIL && cp_register (reg))
1464 {
1465 reg &= 15;
1466 inst.instruction |= reg << where;
1467 return reg;
1468 }
1469
1470 /* In the few cases where we might be able to accept something else
1471 this error can be overridden */
1472 inst.error = "Co-processor register expected";
1473
1474 /* Restore the start point */
1475 *str = start;
1476 return FAIL;
1477}
1478
1479static int
1480fp_reg_required_here (str, where)
1481 char **str;
1482 int where;
1483{
1484 int reg;
1485 char *start = *str;
1486
1487 if ((reg = arm_reg_parse (str)) != FAIL && fp_register (reg))
1488 {
1489 reg &= 7;
1490 inst.instruction |= reg << where;
1491 return reg;
1492 }
1493
1494 /* In the few cases where we might be able to accept something else
1495 this error can be overridden */
1496 inst.error = "Floating point register expected";
1497
1498 /* Restore the start point */
1499 *str = start;
1500 return FAIL;
1501}
1502
1503static int
1504cp_address_offset (str)
1505 char **str;
1506{
1507 int offset;
1508
1509 while (**str == ' ')
1510 (*str)++;
1511
1512 if (**str != '#')
1513 {
1514 inst.error = "immediate expression expected";
1515 return FAIL;
1516 }
1517
1518 (*str)++;
1519 if (my_get_expression (&inst.reloc.exp, str))
1520 return FAIL;
1521 if (inst.reloc.exp.X_op == O_constant)
1522 {
1523 offset = inst.reloc.exp.X_add_number;
1524 if (offset & 3)
1525 {
1526 inst.error = "co-processor address must be word aligned";
1527 return FAIL;
1528 }
1529
1530 if (offset > 1023 || offset < -1023)
1531 {
1532 inst.error = "offset too large";
1533 return FAIL;
1534 }
1535
1536 if (offset >= 0)
1537 inst.instruction |= INDEX_UP;
1538 else
1539 offset = -offset;
1540
1541 inst.instruction |= offset >> 2;
1542 }
1543 else
1544 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
1545
1546 return SUCCESS;
1547}
1548
1549static int
1550cp_address_required_here (str)
1551 char **str;
1552{
1553 char *p = *str;
1554 int pre_inc = 0;
1555 int write_back = 0;
1556
1557 if (*p == '[')
1558 {
1559 int reg;
1560
1561 p++;
1562 while (*p == ' ')
1563 p++;
1564
1565 if ((reg = reg_required_here (&p, 16)) == FAIL)
1566 {
1567 inst.error = "Register required";
1568 return FAIL;
1569 }
1570
1571 while (*p == ' ')
1572 p++;
1573
1574 if (*p == ']')
1575 {
1576 p++;
1577 if (skip_past_comma (&p) == SUCCESS)
1578 {
1579 /* [Rn], #expr */
1580 write_back = WRITE_BACK;
1581 if (reg == REG_PC)
1582 {
1583 inst.error = "pc may not be used in post-increment";
1584 return FAIL;
1585 }
1586
1587 if (cp_address_offset (&p) == FAIL)
1588 return FAIL;
1589 }
1590 else
1591 pre_inc = PRE_INDEX | INDEX_UP;
1592 }
1593 else
1594 {
1595 /* '['Rn, #expr']'[!] */
1596
1597 if (skip_past_comma (&p) == FAIL)
1598 {
1599 inst.error = "pre-indexed expression expected";
1600 return FAIL;
1601 }
1602
1603 pre_inc = PRE_INDEX;
1604 if (cp_address_offset (&p) == FAIL)
1605 return FAIL;
1606
1607 while (*p == ' ')
1608 p++;
1609
1610 if (*p++ != ']')
1611 {
1612 inst.error = "missing ]";
1613 return FAIL;
1614 }
1615
1616 while (*p == ' ')
1617 p++;
1618
1619 if (*p == '!')
1620 {
1621 if (reg == REG_PC)
1622 {
1623 inst.error = "pc may not be used with write-back";
1624 return FAIL;
1625 }
1626
1627 p++;
1628 write_back = WRITE_BACK;
1629 }
1630 }
1631 }
1632 else
1633 {
1634 if (my_get_expression (&inst.reloc.exp, &p))
1635 return FAIL;
1636
1637 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
1638 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust */
1639 inst.reloc.pc_rel = 1;
1640 inst.instruction |= (REG_PC << 16);
c479fc62 1641 pre_inc = PRE_INDEX;
338a7060
DE
1642 }
1643
1644 inst.instruction |= write_back | pre_inc;
1645 *str = p;
1646 return SUCCESS;
1647}
1648
1649static void
1650do_nop (str, flags)
1651 char *str;
1652 unsigned long flags;
1653{
1654 /* Do nothing really */
1655 inst.instruction |= flags; /* This is pointless */
1656 end_of_line (str);
1657 return;
1658}
1659
1660static void
1661do_mrs (str, flags)
1662 char *str;
1663 unsigned long flags;
1664{
1665 /* Only one syntax */
1666 while (*str == ' ')
1667 str++;
1668
1669 if (reg_required_here (&str, 12) == FAIL)
1670 {
1671 inst.error = bad_args;
1672 return;
1673 }
1674
1675 if (skip_past_comma (&str) == FAIL
1676 || psr_required_here (&str, 22) == FAIL)
1677 {
1678 inst.error = "<psr> expected";
1679 return;
1680 }
1681
1682 inst.instruction |= flags;
1683 end_of_line (str);
1684 return;
1685}
1686
1687static void
1688do_msr (str, flags)
1689 char *str;
1690 unsigned long flags;
1691{
1692 int psr, psrf, reg;
1693 /* Three possible forms: "<psr>, Rm", "<psrf>, Rm", "<psrf>, #expression" */
1694
1695 while (*str == ' ')
1696 str++;
1697
1698 if ((psr = psr_required_here (&str, 22)) != FAIL)
1699 {
1700 inst.instruction |= PSR_ALL;
1701 /* Sytax should be "<psr>, Rm" */
1702 if (skip_past_comma (&str) == FAIL
1703 || (reg = reg_required_here (&str, 0)) == FAIL)
1704 {
1705 inst.error = bad_args;
1706 return;
1707 }
1708 }
1709 else if ((psrf = psrf_required_here (&str, 22)) != FAIL)
1710 /* Syntax could be "<psrf>, rm", "<psrf>, #expression" */
1711 {
1712 if (skip_past_comma (&str) == FAIL)
1713 {
1714 inst.error = bad_args;
1715 return;
1716 }
1717 if ((reg = reg_required_here (&str, 0)) != FAIL)
1718 ;
1719 /* Immediate expression */
1720 else if (*(str++) == '#')
1721 {
1722 inst.error = NULL;
1723 if (my_get_expression (&inst.reloc.exp, &str))
1724 {
1725 inst.error = "Register or shift expression expected";
1726 return;
1727 }
1728
1729 if (inst.reloc.exp.X_add_symbol)
1730 {
1731 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
1732 inst.reloc.pc_rel = 0;
1733 }
1734 else
1735 {
f520aaee 1736 unsigned value = validate_immediate (inst.reloc.exp.X_add_number);
338a7060
DE
1737 if (value == FAIL)
1738 {
1739 inst.error = "Invalid constant";
1740 return;
1741 }
1742
1743 inst.instruction |= value;
1744 }
1745
1746 flags |= INST_IMMEDIATE;
1747 }
1748 else
1749 {
1750 inst.error = "Error: the other";
1751 return;
1752 }
1753 }
1754 else
1755 {
1756 inst.error = bad_args;
1757 return;
1758 }
1759
1760 inst.error = NULL;
1761 inst.instruction |= flags;
1762 end_of_line (str);
1763 return;
1764}
1765
1766/* Long Multiply Parser
1767 UMULL RdLo, RdHi, Rm, Rs
1768 SMULL RdLo, RdHi, Rm, Rs
1769 UMLAL RdLo, RdHi, Rm, Rs
1770 SMLAL RdLo, RdHi, Rm, Rs
1771*/
1772static void
1773do_mull (str, flags)
1774 char *str;
1775 unsigned long flags;
1776{
1777 int rdlo, rdhi, rm, rs;
1778
1779 /* only one format "rdlo, rdhi, rm, rs" */
1780 while (*str == ' ')
1781 str++;
1782
1783 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
1784 {
1785 inst.error = bad_args;
1786 return;
1787 }
1788
1789 if (skip_past_comma (&str) == FAIL
1790 || (rdhi = reg_required_here (&str, 16)) == FAIL)
1791 {
1792 inst.error = bad_args;
1793 return;
1794 }
1795
1796 if (skip_past_comma (&str) == FAIL
1797 || (rm = reg_required_here (&str, 0)) == FAIL)
1798 {
1799 inst.error = bad_args;
1800 return;
1801 }
1802
1803 /* rdhi, rdlo and rm must all be different */
1804 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
1805 as_tsktsk ("rdhi, rdlo and rm must all be different");
1806
1807 if (skip_past_comma (&str) == FAIL
1808 || (rs = reg_required_here (&str, 8)) == FAIL)
1809 {
1810 inst.error = bad_args;
1811 return;
1812 }
1813
1814 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
1815 {
1816 inst.error = bad_pc;
1817 return;
1818 }
1819
1820 inst.instruction |= flags;
1821 end_of_line (str);
1822 return;
1823}
1824
1825static void
1826do_mul (str, flags)
1827 char *str;
1828 unsigned long flags;
1829{
1830 int rd, rm;
1831
1832 /* only one format "rd, rm, rs" */
1833 while (*str == ' ')
1834 str++;
1835
1836 if ((rd = reg_required_here (&str, 16)) == FAIL)
1837 {
1838 inst.error = bad_args;
1839 return;
1840 }
1841
1842 if (rd == REG_PC)
1843 {
1844 inst.error = bad_pc;
1845 return;
1846 }
1847
1848 if (skip_past_comma (&str) == FAIL
1849 || (rm = reg_required_here (&str, 0)) == FAIL)
1850 {
1851 inst.error = bad_args;
1852 return;
1853 }
1854
1855 if (rm == REG_PC)
1856 {
1857 inst.error = bad_pc;
1858 return;
1859 }
1860
1861 if (rm == rd)
1862 as_tsktsk ("rd and rm should be different in mul");
1863
1864 if (skip_past_comma (&str) == FAIL
1865 || (rm = reg_required_here (&str, 8)) == FAIL)
1866 {
1867 inst.error = bad_args;
1868 return;
1869 }
1870
1871 if (rm == REG_PC)
1872 {
1873 inst.error = bad_pc;
1874 return;
1875 }
1876
1877 inst.instruction |= flags;
1878 end_of_line (str);
1879 return;
1880}
1881
1882static void
1883do_mla (str, flags)
1884 char *str;
1885 unsigned long flags;
1886{
1887 int rd, rm;
1888
1889 /* only one format "rd, rm, rs, rn" */
1890 while (*str == ' ')
1891 str++;
1892
1893 if ((rd = reg_required_here (&str, 16)) == FAIL)
1894 {
1895 inst.error = bad_args;
1896 return;
1897 }
1898
1899 if (rd == REG_PC)
1900 {
1901 inst.error = bad_pc;
1902 return;
1903 }
1904
1905 if (skip_past_comma (&str) == FAIL
1906 || (rm = reg_required_here (&str, 0)) == FAIL)
1907 {
1908 inst.error = bad_args;
1909 return;
1910 }
1911
1912 if (rm == REG_PC)
1913 {
1914 inst.error = bad_pc;
1915 return;
1916 }
1917
1918 if (rm == rd)
1919 as_tsktsk ("rd and rm should be different in mla");
1920
1921 if (skip_past_comma (&str) == FAIL
1922 || (rd = reg_required_here (&str, 8)) == FAIL
1923 || skip_past_comma (&str) == FAIL
1924 || (rm = reg_required_here (&str, 12)) == FAIL)
1925 {
1926 inst.error = bad_args;
1927 return;
1928 }
1929
1930 if (rd == REG_PC || rm == REG_PC)
1931 {
1932 inst.error = bad_pc;
1933 return;
1934 }
1935
1936 inst.instruction |= flags;
1937 end_of_line (str);
1938 return;
1939}
1940
1941/* Returns the index into fp_values of a floating point number, or -1 if
1942 not in the table. */
1943static int
1944my_get_float_expression (str)
1945 char **str;
1946{
1947 LITTLENUM_TYPE words[MAX_LITTLENUMS];
1948 char *save_in;
1949 expressionS exp;
1950 int i, j;
1951
1952 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
1953 /* Look for a raw floating point number */
1954 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
1955 && (is_end_of_line [(int)(*save_in)] || *save_in == '\0'))
1956 {
1957 for (i = 0; i < NUM_FLOAT_VALS; i++)
1958 {
1959 for (j = 0; j < MAX_LITTLENUMS; j++)
1960 {
1961 if (words[j] != fp_values[i][j])
1962 break;
1963 }
1964
1965 if (j == MAX_LITTLENUMS)
1966 {
1967 *str = save_in;
1968 return i;
1969 }
1970 }
1971 }
1972
1973 /* Try and parse a more complex expression, this will probably fail
1974 unless the code uses a floating point prefix (eg "0f") */
1975 save_in = input_line_pointer;
1976 input_line_pointer = *str;
1977 if (expression (&exp) == absolute_section
1978 && exp.X_op == O_big
1979 && exp.X_add_number < 0)
1980 {
c479fc62
JSC
1981 /* FIXME: 5 = X_PRECISION, should be #define'd where we can use it.
1982 Ditto for 15. */
1983 if (gen_to_words (words, 5, (long)15) == 0)
338a7060
DE
1984 {
1985 for (i = 0; i < NUM_FLOAT_VALS; i++)
1986 {
1987 for (j = 0; j < MAX_LITTLENUMS; j++)
1988 {
1989 if (words[j] != fp_values[i][j])
1990 break;
1991 }
1992
1993 if (j == MAX_LITTLENUMS)
1994 {
1995 *str = input_line_pointer;
1996 input_line_pointer = save_in;
1997 return i;
1998 }
1999 }
2000 }
2001 }
2002
2003 *str = input_line_pointer;
2004 input_line_pointer = save_in;
2005 return -1;
2006}
2007
2008/* Return true if anything in the expression is a bignum */
2009static int
2010walk_no_bignums (sp)
2011 symbolS *sp;
2012{
2013 if (sp->sy_value.X_op == O_big)
2014 return 1;
2015
2016 if (sp->sy_value.X_add_symbol)
2017 {
2018 return (walk_no_bignums (sp->sy_value.X_add_symbol)
2019 || (sp->sy_value.X_op_symbol
2020 && walk_no_bignums (sp->sy_value.X_op_symbol)));
2021 }
2022
2023 return 0;
2024}
2025
2026static int
2027my_get_expression (ep, str)
2028 expressionS *ep;
2029 char **str;
2030{
2031 char *save_in;
2032 segT seg;
2033
2034 save_in = input_line_pointer;
2035 input_line_pointer = *str;
2036 seg = expression (ep);
c479fc62
JSC
2037
2038#ifdef OBJ_AOUT
338a7060
DE
2039 if (seg != absolute_section
2040 && seg != text_section
2041 && seg != data_section
2042 && seg != bss_section
2043 && seg != undefined_section)
2044 {
2045 inst.error = "bad_segment";
2046 *str = input_line_pointer;
2047 input_line_pointer = save_in;
2048 return 1;
2049 }
c479fc62 2050#endif
338a7060
DE
2051
2052 /* Get rid of any bignums now, so that we don't generate an error for which
2053 we can't establish a line number later on. Big numbers are never valid
c479fc62 2054 in instructions, which is where this routine is always called. */
338a7060
DE
2055 if (ep->X_op == O_big
2056 || (ep->X_add_symbol
2057 && (walk_no_bignums (ep->X_add_symbol)
2058 || (ep->X_op_symbol
2059 && walk_no_bignums (ep->X_op_symbol)))))
2060 {
2061 inst.error = "Invalid constant";
2062 *str = input_line_pointer;
2063 input_line_pointer = save_in;
2064 return 1;
2065 }
2066
2067 *str = input_line_pointer;
2068 input_line_pointer = save_in;
2069 return 0;
2070}
2071
2072/* unrestrict should be one if <shift> <register> is permitted for this
2073 instruction */
2074
2075static int
2076decode_shift (str, unrestrict)
2077 char **str;
2078 int unrestrict;
2079{
2080 struct asm_shift *shft;
2081 char *p;
2082 char c;
2083
2084 while (**str == ' ')
2085 (*str)++;
2086
2087 for (p = *str; isalpha (*p); p++)
2088 ;
2089
2090 if (p == *str)
2091 {
2092 inst.error = "Shift expression expected";
2093 return FAIL;
2094 }
2095
2096 c = *p;
2097 *p = '\0';
2098 shft = (struct asm_shift *) hash_find (arm_shift_hsh, *str);
2099 *p = c;
2100 if (shft)
2101 {
590c50d8
ILT
2102 if (!strcmp (*str, "rrx")
2103 || !strcmp (*str, "RRX"))
338a7060
DE
2104 {
2105 *str = p;
2106 inst.instruction |= shft->value;
2107 return SUCCESS;
2108 }
2109
2110 while (*p == ' ')
2111 p++;
2112
2113 if (unrestrict && reg_required_here (&p, 8) != FAIL)
2114 {
2115 inst.instruction |= shft->value | SHIFT_BY_REG;
2116 *str = p;
2117 return SUCCESS;
2118 }
2119 else if (*p == '#')
2120 {
2121 inst.error = NULL;
2122 p++;
2123 if (my_get_expression (&inst.reloc.exp, &p))
2124 return FAIL;
2125
2126 /* Validate some simple #expressions */
590c50d8 2127 if (inst.reloc.exp.X_op == O_constant)
338a7060 2128 {
590c50d8
ILT
2129 unsigned num = inst.reloc.exp.X_add_number;
2130
2131 /* Reject operations greater than 32, or lsl #32 */
2132 if (num > 32 || (num == 32 && shft->value == 0))
338a7060
DE
2133 {
2134 inst.error = "Invalid immediate shift";
2135 return FAIL;
2136 }
2137
2138 /* Shifts of zero should be converted to lsl (which is zero)*/
2139 if (num == 0)
2140 {
2141 *str = p;
2142 return SUCCESS;
2143 }
2144
2145 /* Shifts of 32 are encoded as 0, for those shifts that
2146 support it. */
2147 if (num == 32)
2148 num = 0;
2149
2150 inst.instruction |= (num << 7) | shft->value;
2151 *str = p;
2152 return SUCCESS;
2153 }
2154
2155 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
2156 inst.reloc.pc_rel = 0;
2157 inst.instruction |= shft->value;
2158 *str = p;
2159 return SUCCESS;
2160 }
2161 else
2162 {
2163 inst.error = unrestrict ? "shift requires register or #expression"
2164 : "shift requires #expression";
2165 *str = p;
2166 return FAIL;
2167 }
2168 }
2169
2170 inst.error = "Shift expression expected";
2171 return FAIL;
2172}
2173
2174/* Do those data_ops which can take a negative immediate constant */
2175/* by altering the instuction. A bit of a hack really */
2176/* MOV <-> MVN
2177 AND <-> BIC
2178 ADC <-> SBC
2179 by inverting the second operand, and
2180 ADD <-> SUB
2181 CMP <-> CMN
2182 by negating the second operand.
2183*/
2184static int
2185negate_data_op (instruction, value)
2186 unsigned long *instruction;
2187 unsigned long value;
2188{
2189 int op, new_inst;
2190 unsigned long negated, inverted;
2191
2192 negated = validate_immediate (-value);
2193 inverted = validate_immediate (~value);
2194
2195 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
2196 switch (op)
2197 {
2198 /* First negates */
2199 case OPCODE_SUB: /* ADD <-> SUB */
2200 new_inst = OPCODE_ADD;
2201 value = negated;
2202 break;
2203
2204 case OPCODE_ADD:
2205 new_inst = OPCODE_SUB;
2206 value = negated;
2207 break;
2208
2209 case OPCODE_CMP: /* CMP <-> CMN */
2210 new_inst = OPCODE_CMN;
2211 value = negated;
2212 break;
2213
2214 case OPCODE_CMN:
2215 new_inst = OPCODE_CMP;
2216 value = negated;
2217 break;
2218
2219 /* Now Inverted ops */
2220 case OPCODE_MOV: /* MOV <-> MVN */
2221 new_inst = OPCODE_MVN;
2222 value = inverted;
2223 break;
2224
2225 case OPCODE_MVN:
2226 new_inst = OPCODE_MOV;
2227 value = inverted;
2228 break;
2229
2230 case OPCODE_AND: /* AND <-> BIC */
2231 new_inst = OPCODE_BIC;
2232 value = inverted;
2233 break;
2234
2235 case OPCODE_BIC:
2236 new_inst = OPCODE_AND;
2237 value = inverted;
2238 break;
2239
2240 case OPCODE_ADC: /* ADC <-> SBC */
2241 new_inst = OPCODE_SBC;
2242 value = inverted;
2243 break;
2244
2245 case OPCODE_SBC:
2246 new_inst = OPCODE_ADC;
2247 value = inverted;
2248 break;
2249
2250 /* We cannot do anything */
2251 default:
2252 return FAIL;
2253 }
2254
2255 if (value == FAIL)
2256 return FAIL;
2257
2258 *instruction &= OPCODE_MASK;
2259 *instruction |= new_inst << DATA_OP_SHIFT;
2260 return value;
2261}
2262
2263static int
2264data_op2 (str)
2265 char **str;
2266{
2267 int value;
2268 expressionS expr;
2269
2270 while (**str == ' ')
2271 (*str)++;
2272
2273 if (reg_required_here (str, 0) != FAIL)
2274 {
2275 if (skip_past_comma (str) == SUCCESS)
2276 {
2277 /* Shift operation on register */
2278 return decode_shift (str, NO_SHIFT_RESTRICT);
2279 }
2280 return SUCCESS;
2281 }
2282 else
2283 {
2284 /* Immediate expression */
2285 if (*((*str)++) == '#')
2286 {
2287 inst.error = NULL;
2288 if (my_get_expression (&inst.reloc.exp, str))
2289 return FAIL;
2290
2291 if (inst.reloc.exp.X_add_symbol)
2292 {
2293 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
2294 inst.reloc.pc_rel = 0;
2295 }
2296 else
2297 {
2298 if (skip_past_comma (str) == SUCCESS)
2299 {
2300 /* #x, y -- ie explicit rotation by Y */
2301 if (my_get_expression (&expr, str))
2302 return FAIL;
2303
2304 if (expr.X_op != O_constant)
2305 {
2306 inst.error = "Constant expression expected";
2307 return FAIL;
2308 }
2309
2310 /* Rotate must be a multiple of 2 */
2311 if (((unsigned) expr.X_add_number) > 30
2312 || (expr.X_add_number & 1) != 0
2313 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
2314 {
2315 inst.error = "Invalid constant";
2316 return FAIL;
2317 }
2318 inst.instruction |= INST_IMMEDIATE;
2319 inst.instruction |= inst.reloc.exp.X_add_number;
2320 inst.instruction |= expr.X_add_number << 7;
2321 return SUCCESS;
2322 }
2323
2324 /* Implicit rotation, select a suitable one */
2325 value = validate_immediate (inst.reloc.exp.X_add_number);
2326
2327 if (value == FAIL)
2328 {
2329 /* Can't be done, perhaps the code reads something like
2330 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be ok */
2331 if ((value = negate_data_op (&inst.instruction,
2332 inst.reloc.exp.X_add_number))
2333 == FAIL)
2334 {
2335 inst.error = "Invalid constant";
2336 return FAIL;
2337 }
2338 }
2339
2340 inst.instruction |= value;
2341 }
2342
2343 inst.instruction |= INST_IMMEDIATE;
2344 return SUCCESS;
2345 }
2346
2347 inst.error = "Register or shift expression expected";
2348 return FAIL;
2349 }
2350}
2351
2352static int
ccc30467 2353fp_op2 (str)
338a7060 2354 char **str;
338a7060
DE
2355{
2356 while (**str == ' ')
2357 (*str)++;
2358
2359 if (fp_reg_required_here (str, 0) != FAIL)
2360 return SUCCESS;
2361 else
2362 {
2363 /* Immediate expression */
2364 if (*((*str)++) == '#')
2365 {
2366 int i;
2367
2368 inst.error = NULL;
2369 while (**str == ' ')
2370 (*str)++;
2371
2372 /* First try and match exact strings, this is to guarantee that
2373 some formats will work even for cross assembly */
2374
2375 for (i = 0; fp_const[i]; i++)
2376 {
2377 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
2378 {
2379 char *start = *str;
2380
2381 *str += strlen (fp_const[i]);
2382 if (is_end_of_line[(int)**str] || **str == '\0')
2383 {
2384 inst.instruction |= i + 8;
2385 return SUCCESS;
2386 }
2387 *str = start;
2388 }
2389 }
2390
2391 /* Just because we didn't get a match doesn't mean that the
2392 constant isn't valid, just that it is in a format that we
2393 don't automatically recognize. Try parsing it with
2394 the standard expression routines. */
2395 if ((i = my_get_float_expression (str)) >= 0)
2396 {
2397 inst.instruction |= i + 8;
2398 return SUCCESS;
2399 }
2400
2401 inst.error = "Invalid floating point immediate expression";
2402 return FAIL;
2403 }
2404 inst.error = "Floating point register or immediate expression expected";
2405 return FAIL;
2406 }
2407}
2408
2409static void
2410do_arit (str, flags)
2411 char *str;
2412 unsigned long flags;
2413{
2414 while (*str == ' ')
2415 str++;
2416
2417 if (reg_required_here (&str, 12) == FAIL
2418 || skip_past_comma (&str) == FAIL
2419 || reg_required_here (&str, 16) == FAIL
2420 || skip_past_comma (&str) == FAIL
2421 || data_op2 (&str) == FAIL)
2422 {
2423 if (!inst.error)
2424 inst.error = bad_args;
2425 return;
2426 }
2427
2428 inst.instruction |= flags;
2429 end_of_line (str);
2430 return;
2431}
2432
2433static void
2434do_adr (str, flags)
2435 char *str;
2436 unsigned long flags;
2437{
590c50d8
ILT
2438 /* This is a pseudo-op of the form "adr rd, label" to be converted
2439 into a relative address of the form "add rd, pc, #label-.-8" */
338a7060
DE
2440
2441 while (*str == ' ')
2442 str++;
2443
2444 if (reg_required_here (&str, 12) == FAIL
2445 || skip_past_comma (&str) == FAIL
2446 || my_get_expression (&inst.reloc.exp, &str))
2447 {
2448 if (!inst.error)
2449 inst.error = bad_args;
2450 return;
2451 }
2452 /* Frag hacking will turn this into a sub instruction if the offset turns
2453 out to be negative. */
2454 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
2455 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
2456 inst.reloc.pc_rel = 1;
2457 inst.instruction |= flags;
2458 end_of_line (str);
2459 return;
2460}
2461
2462static void
2463do_cmp (str, flags)
2464 char *str;
2465 unsigned long flags;
2466{
2467 while (*str == ' ')
2468 str++;
2469
2470 if (reg_required_here (&str, 16) == FAIL)
2471 {
2472 if (!inst.error)
2473 inst.error = bad_args;
2474 return;
2475 }
2476
2477 if (skip_past_comma (&str) == FAIL
2478 || data_op2 (&str) == FAIL)
2479 {
2480 if (!inst.error)
2481 inst.error = bad_args;
2482 return;
2483 }
2484
2485 inst.instruction |= flags;
2486 if ((flags & 0x0000f000) == 0)
590c50d8 2487 inst.instruction |= CONDS_BIT;
338a7060
DE
2488
2489 end_of_line (str);
2490 return;
2491}
2492
2493static void
2494do_mov (str, flags)
2495 char *str;
2496 unsigned long flags;
2497{
2498 while (*str == ' ')
2499 str++;
2500
2501 if (reg_required_here (&str, 12) == FAIL)
2502 {
2503 if (!inst.error)
2504 inst.error = bad_args;
2505 return;
2506 }
2507
2508 if (skip_past_comma (&str) == FAIL
2509 || data_op2 (&str) == FAIL)
2510 {
2511 if (!inst.error)
2512 inst.error = bad_args;
2513 return;
2514 }
2515
2516 inst.instruction |= flags;
2517 end_of_line (str);
2518 return;
2519}
2520
2521static int
c479fc62 2522ldst_extend (str, hwse)
338a7060 2523 char **str;
c479fc62 2524 int hwse;
338a7060
DE
2525{
2526 int add = INDEX_UP;
2527
2528 switch (**str)
2529 {
2530 case '#':
2531 (*str)++;
2532 if (my_get_expression (&inst.reloc.exp, str))
2533 return FAIL;
2534
2535 if (inst.reloc.exp.X_op == O_constant)
2536 {
2537 int value = inst.reloc.exp.X_add_number;
2538
c479fc62
JSC
2539 if ((hwse && (value < -255 || value > 255))
2540 || (value < -4095 || value > 4095))
338a7060
DE
2541 {
2542 inst.error = "address offset too large";
2543 return FAIL;
2544 }
2545
2546 if (value < 0)
2547 {
2548 value = -value;
2549 add = 0;
2550 }
2551
c479fc62
JSC
2552 /* Halfword and signextension instructions have the
2553 immediate value split across bits 11..8 and bits 3..0 */
2554 if (hwse)
2555 inst.instruction |= add | HWOFFSET_IMM | (value >> 4) << 8 | value & 0xF;
2556 else
2557 inst.instruction |= add | value;
338a7060
DE
2558 }
2559 else
2560 {
c479fc62
JSC
2561 if (hwse)
2562 {
2563 inst.instruction |= HWOFFSET_IMM;
2564 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
2565 }
2566 else
2567 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
338a7060
DE
2568 inst.reloc.pc_rel = 0;
2569 }
2570 return SUCCESS;
2571
2572 case '-':
2573 add = 0; /* and fall through */
2574 case '+':
2575 (*str)++; /* and fall through */
2576 default:
2577 if (reg_required_here (str, 0) == FAIL)
2578 {
2579 inst.error = "Register expected";
2580 return FAIL;
2581 }
c479fc62
JSC
2582
2583 if (hwse)
2584 inst.instruction |= add;
2585 else
590c50d8
ILT
2586 {
2587 inst.instruction |= add | OFFSET_REG;
2588 if (skip_past_comma (str) == SUCCESS)
2589 return decode_shift (str, SHIFT_RESTRICT);
2590 }
c479fc62 2591
338a7060
DE
2592 return SUCCESS;
2593 }
2594}
2595
2596static void
2597do_ldst (str, flags)
2598 char *str;
2599 unsigned long flags;
2600{
c479fc62 2601 int halfword = 0;
338a7060
DE
2602 int pre_inc = 0;
2603 int conflict_reg;
2604 int value;
2605
c479fc62 2606 /* This is not ideal, but it is the simplest way of dealing with the
590c50d8 2607 ARM7T halfword instructions (since they use a different
c479fc62 2608 encoding, but the same mnemonic): */
590c50d8 2609 if (halfword = ((flags & 0x80000000) != 0))
c479fc62
JSC
2610 {
2611 /* This is actually a load/store of a halfword, or a
2612 signed-extension load */
f520aaee 2613 if ((cpu_variant & ARM_HALFWORD) == 0)
c479fc62 2614 {
590c50d8 2615 inst.error
f520aaee 2616 = "Processor does not support halfwords or signed bytes";
590c50d8 2617 return;
c479fc62 2618 }
590c50d8
ILT
2619
2620 inst.instruction = (inst.instruction & COND_MASK)
2621 | (flags & ~COND_MASK);
2622
2623 flags = 0;
c479fc62
JSC
2624 }
2625
338a7060
DE
2626 while (*str == ' ')
2627 str++;
2628
2629 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
2630 {
2631 if (!inst.error)
2632 inst.error = bad_args;
2633 return;
2634 }
2635
2636 if (skip_past_comma (&str) == FAIL)
2637 {
2638 inst.error = "Address expected";
2639 return;
2640 }
2641
2642 if (*str == '[')
2643 {
2644 int reg;
2645
2646 str++;
2647 while (*str == ' ')
2648 str++;
2649
2650 if ((reg = reg_required_here (&str, 16)) == FAIL)
2651 {
2652 inst.error = "Register required";
2653 return;
2654 }
2655
2656 conflict_reg = (((conflict_reg == reg)
590c50d8 2657 && (inst.instruction & LOAD_BIT))
338a7060
DE
2658 ? 1 : 0);
2659
2660 while (*str == ' ')
2661 str++;
2662
2663 if (*str == ']')
2664 {
2665 str++;
2666 if (skip_past_comma (&str) == SUCCESS)
2667 {
2668 /* [Rn],... (post inc) */
590c50d8 2669 if (ldst_extend (&str, halfword) == FAIL)
338a7060
DE
2670 return;
2671 if (conflict_reg)
2672 as_warn ("destination register same as write-back base\n");
2673 }
2674 else
2675 {
2676 /* [Rn] */
590c50d8 2677 if (halfword)
c479fc62
JSC
2678 inst.instruction |= HWOFFSET_IMM;
2679
2680 while (*str == ' ')
2681 str++;
2682
2683 if (*str == '!')
2684 {
2685 if (conflict_reg)
2686 as_warn ("destination register same as write-back base\n");
2687 str++;
2688 inst.instruction |= WRITE_BACK;
2689 }
2690
338a7060 2691 flags |= INDEX_UP;
c479fc62
JSC
2692 if (! (flags & TRANS_BIT))
2693 pre_inc = 1;
338a7060
DE
2694 }
2695 }
2696 else
2697 {
2698 /* [Rn,...] */
2699 if (skip_past_comma (&str) == FAIL)
2700 {
2701 inst.error = "pre-indexed expression expected";
2702 return;
2703 }
2704
2705 pre_inc = 1;
590c50d8 2706 if (ldst_extend (&str, halfword) == FAIL)
338a7060
DE
2707 return;
2708
2709 while (*str == ' ')
2710 str++;
2711
2712 if (*str++ != ']')
2713 {
2714 inst.error = "missing ]";
2715 return;
2716 }
2717
2718 while (*str == ' ')
2719 str++;
2720
2721 if (*str == '!')
2722 {
2723 if (conflict_reg)
590c50d8 2724 as_tsktsk ("destination register same as write-back base\n");
338a7060
DE
2725 str++;
2726 inst.instruction |= WRITE_BACK;
2727 }
2728 }
2729 }
2730 else if (*str == '=')
2731 {
2732 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op */
2733 str++;
2734
2735 while (*str == ' ')
2736 str++;
2737
2738 if (my_get_expression (&inst.reloc.exp, &str))
2739 return;
2740
2741 if (inst.reloc.exp.X_op != O_constant
2742 && inst.reloc.exp.X_op != O_symbol)
2743 {
2744 inst.error = "Constant expression expected";
2745 return;
2746 }
2747
2748 if (inst.reloc.exp.X_op == O_constant
2749 && (value = validate_immediate(inst.reloc.exp.X_add_number)) != FAIL)
2750 {
2751 /* This can be done with a mov instruction */
2752 inst.instruction &= LITERAL_MASK;
2753 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
2754 inst.instruction |= (flags & COND_MASK) | (value & 0xfff);
2755 end_of_line(str);
2756 return;
2757 }
2758 else
2759 {
2760 /* Insert into literal pool */
2761 if (add_to_lit_pool () == FAIL)
2762 {
2763 if (!inst.error)
f520aaee 2764 inst.error = "literal pool insertion failed";
338a7060
DE
2765 return;
2766 }
2767
2768 /* Change the instruction exp to point to the pool */
590c50d8 2769 if (halfword)
c479fc62
JSC
2770 {
2771 inst.instruction |= HWOFFSET_IMM;
2772 inst.reloc.type = BFD_RELOC_ARM_HWLITERAL;
2773 }
2774 else
2775 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
338a7060
DE
2776 inst.reloc.pc_rel = 1;
2777 inst.instruction |= (REG_PC << 16);
2778 pre_inc = 1;
2779 }
2780 }
2781 else
2782 {
2783 if (my_get_expression (&inst.reloc.exp, &str))
2784 return;
2785
590c50d8 2786 if (halfword)
c479fc62
JSC
2787 {
2788 inst.instruction |= HWOFFSET_IMM;
2789 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
2790 }
2791 else
2792 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
338a7060
DE
2793 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust */
2794 inst.reloc.pc_rel = 1;
2795 inst.instruction |= (REG_PC << 16);
2796 pre_inc = 1;
2797 }
2798
2799 if (pre_inc && (flags & TRANS_BIT))
2800 inst.error = "Pre-increment instruction with translate";
2801
2802 inst.instruction |= flags | (pre_inc ? PRE_INDEX : 0);
2803 end_of_line (str);
2804 return;
2805}
2806
590c50d8
ILT
2807static long
2808reg_list (strp)
2809 char **strp;
338a7060 2810{
590c50d8
ILT
2811 char *str = *strp;
2812 long range = 0;
2813 int another_range;
338a7060 2814
590c50d8
ILT
2815 /* We come back here if we get ranges concatenated by '+' or '|' */
2816 do
338a7060 2817 {
590c50d8 2818 another_range = 0;
338a7060 2819
590c50d8
ILT
2820 if (*str == '{')
2821 {
2822 int in_range = 0;
2823 int cur_reg = -1;
2824
2825 str++;
2826 do
2827 {
2828 int reg;
2829
2830 while (*str == ' ')
2831 str++;
338a7060 2832
590c50d8
ILT
2833 if ((reg = arm_reg_parse (&str)) == FAIL || !int_register (reg))
2834 {
2835 inst.error = "Register expected";
2836 return FAIL;
2837 }
338a7060 2838
590c50d8
ILT
2839 if (in_range)
2840 {
2841 int i;
2842
2843 if (reg <= cur_reg)
2844 {
2845 inst.error = "Bad range in register list";
2846 return FAIL;
2847 }
338a7060 2848
590c50d8
ILT
2849 for (i = cur_reg + 1; i < reg; i++)
2850 {
2851 if (range & (1 << i))
2852 as_tsktsk
2853 ("Warning: Duplicated register (r%d) in register list",
2854 i);
2855 else
2856 range |= 1 << i;
2857 }
2858 in_range = 0;
2859 }
2860
2861 if (range & (1 << reg))
2862 as_tsktsk ("Warning: Duplicated register (r%d) in register list",
2863 reg);
2864 else if (reg <= cur_reg)
2865 as_tsktsk ("Warning: Register range not in ascending order");
2866
2867 range |= 1 << reg;
2868 cur_reg = reg;
2869 } while (skip_past_comma (&str) != FAIL
2870 || (in_range = 1, *str++ == '-'));
2871 str--;
338a7060
DE
2872 while (*str == ' ')
2873 str++;
2874
590c50d8 2875 if (*str++ != '}')
338a7060 2876 {
590c50d8
ILT
2877 inst.error = "Missing `}'";
2878 return FAIL;
338a7060 2879 }
590c50d8
ILT
2880 }
2881 else
2882 {
2883 expressionS expr;
2884
2885 if (my_get_expression (&expr, &str))
2886 return FAIL;
338a7060 2887
590c50d8 2888 if (expr.X_op == O_constant)
338a7060 2889 {
590c50d8
ILT
2890 if (expr.X_add_number
2891 != (expr.X_add_number & 0x0000ffff))
338a7060 2892 {
590c50d8
ILT
2893 inst.error = "invalid register mask";
2894 return FAIL;
338a7060
DE
2895 }
2896
590c50d8 2897 if ((range & expr.X_add_number) != 0)
338a7060 2898 {
590c50d8
ILT
2899 int regno = range & expr.X_add_number;
2900
2901 regno &= -regno;
2902 regno = (1 << regno) - 1;
2903 as_tsktsk
2904 ("Warning: Duplicated register (r%d) in register list",
2905 regno);
2906 }
2907
2908 range |= expr.X_add_number;
2909 }
2910 else
2911 {
2912 if (inst.reloc.type != 0)
2913 {
2914 inst.error = "expression too complex";
2915 return FAIL;
338a7060 2916 }
590c50d8
ILT
2917
2918 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
2919 inst.reloc.type = BFD_RELOC_ARM_MULTI;
2920 inst.reloc.pc_rel = 0;
338a7060 2921 }
590c50d8 2922 }
338a7060 2923
338a7060
DE
2924 while (*str == ' ')
2925 str++;
2926
590c50d8 2927 if (*str == '|' || *str == '+')
338a7060 2928 {
590c50d8
ILT
2929 str++;
2930 another_range = 1;
338a7060 2931 }
590c50d8 2932 } while (another_range);
338a7060 2933
590c50d8
ILT
2934 *strp = str;
2935 return range;
2936}
338a7060 2937
590c50d8
ILT
2938static void
2939do_ldmstm (str, flags)
2940 char *str;
2941 unsigned long flags;
2942{
2943 int base_reg;
2944 long range;
338a7060 2945
590c50d8
ILT
2946 while (*str == ' ')
2947 str++;
338a7060 2948
590c50d8
ILT
2949 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
2950 {
2951 if (!inst.error)
2952 inst.error = bad_args;
2953 return;
2954 }
338a7060 2955
590c50d8
ILT
2956 if (base_reg == REG_PC)
2957 {
2958 inst.error = "r15 not allowed as base register";
2959 return;
338a7060
DE
2960 }
2961
2962 while (*str == ' ')
2963 str++;
590c50d8 2964 if (*str == '!')
338a7060 2965 {
590c50d8 2966 flags |= WRITE_BACK;
338a7060 2967 str++;
590c50d8
ILT
2968 }
2969
2970 if (skip_past_comma (&str) == FAIL
2971 || (range = reg_list (&str)) == FAIL)
2972 {
2973 if (! inst.error)
2974 inst.error = bad_args;
2975 return;
338a7060
DE
2976 }
2977
2978 if (*str == '^')
2979 {
2980 str++;
2981 flags |= MULTI_SET_PSR;
2982 }
590c50d8
ILT
2983
2984 inst.instruction |= flags | range;
338a7060
DE
2985 end_of_line (str);
2986 return;
2987}
2988
2989static void
2990do_swi (str, flags)
2991 char *str;
2992 unsigned long flags;
2993{
2994 /* Allow optional leading '#'. */
2995 while (*str == ' ')
2996 str++;
2997 if (*str == '#')
2998 str++;
2999
3000 if (my_get_expression (&inst.reloc.exp, &str))
3001 return;
3002
3003 inst.reloc.type = BFD_RELOC_ARM_SWI;
3004 inst.reloc.pc_rel = 0;
3005 inst.instruction |= flags;
3006 end_of_line (str);
3007 return;
3008}
3009
3010static void
3011do_swap (str, flags)
3012 char *str;
3013 unsigned long flags;
3014{
3015 int reg;
3016
3017 while (*str == ' ')
3018 str++;
3019
3020 if ((reg = reg_required_here (&str, 12)) == FAIL)
3021 return;
3022
3023 if (reg == REG_PC)
3024 {
3025 inst.error = "r15 not allowed in swap";
3026 return;
3027 }
3028
3029 if (skip_past_comma (&str) == FAIL
3030 || (reg = reg_required_here (&str, 0)) == FAIL)
3031 {
3032 if (!inst.error)
3033 inst.error = bad_args;
3034 return;
3035 }
3036
3037 if (reg == REG_PC)
3038 {
3039 inst.error = "r15 not allowed in swap";
3040 return;
3041 }
3042
3043 if (skip_past_comma (&str) == FAIL
3044 || *str++ != '[')
3045 {
3046 inst.error = bad_args;
3047 return;
3048 }
3049
3050 while (*str == ' ')
3051 str++;
3052
3053 if ((reg = reg_required_here (&str, 16)) == FAIL)
3054 return;
3055
3056 if (reg == REG_PC)
3057 {
3058 inst.error = bad_pc;
3059 return;
3060 }
3061
3062 while (*str == ' ')
3063 str++;
3064
3065 if (*str++ != ']')
3066 {
3067 inst.error = "missing ]";
3068 return;
3069 }
3070
3071 inst.instruction |= flags;
3072 end_of_line (str);
3073 return;
3074}
3075
3076static void
3077do_branch (str, flags)
3078 char *str;
3079 unsigned long flags;
3080{
3081 if (my_get_expression (&inst.reloc.exp, &str))
3082 return;
3083 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
3084 inst.reloc.pc_rel = 1;
590c50d8
ILT
3085 end_of_line (str);
3086 return;
3087}
3088
3089static void
3090do_bx (str, flags)
3091 char *str;
3092 unsigned long flags;
3093{
3094 int reg;
3095
3096 while (*str == ' ')
3097 str++;
3098
3099 if ((reg = reg_required_here (&str, 0)) == FAIL)
3100 return;
3101
3102 if (reg == REG_PC)
3103 as_tsktsk ("Use of r15 in bx has undefined behaviour");
3104
338a7060
DE
3105 end_of_line (str);
3106 return;
3107}
3108
3109static void
3110do_cdp (str, flags)
3111 char *str;
3112 unsigned long flags;
3113{
3114 /* Co-processor data operation.
3115 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
3116 while (*str == ' ')
3117 str++;
3118
3119 if (co_proc_number (&str) == FAIL)
3120 {
3121 if (!inst.error)
3122 inst.error = bad_args;
3123 return;
3124 }
3125
3126 if (skip_past_comma (&str) == FAIL
3127 || cp_opc_expr (&str, 20,4) == FAIL)
3128 {
3129 if (!inst.error)
3130 inst.error = bad_args;
3131 return;
3132 }
3133
3134 if (skip_past_comma (&str) == FAIL
3135 || cp_reg_required_here (&str, 12) == FAIL)
3136 {
3137 if (!inst.error)
3138 inst.error = bad_args;
3139 return;
3140 }
3141
3142 if (skip_past_comma (&str) == FAIL
3143 || cp_reg_required_here (&str, 16) == FAIL)
3144 {
3145 if (!inst.error)
3146 inst.error = bad_args;
3147 return;
3148 }
3149
3150 if (skip_past_comma (&str) == FAIL
3151 || cp_reg_required_here (&str, 0) == FAIL)
3152 {
3153 if (!inst.error)
3154 inst.error = bad_args;
3155 return;
3156 }
3157
3158 if (skip_past_comma (&str) == SUCCESS)
3159 {
3160 if (cp_opc_expr (&str, 5, 3) == FAIL)
3161 {
3162 if (!inst.error)
3163 inst.error = bad_args;
3164 return;
3165 }
3166 }
3167
3168 end_of_line (str);
3169 return;
3170}
3171
3172static void
3173do_lstc (str, flags)
3174 char *str;
3175 unsigned long flags;
3176{
3177 /* Co-processor register load/store.
3178 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
3179
3180 while (*str == ' ')
3181 str++;
3182
3183 if (co_proc_number (&str) == FAIL)
3184 {
3185 if (!inst.error)
3186 inst.error = bad_args;
3187 return;
3188 }
3189
3190 if (skip_past_comma (&str) == FAIL
3191 || cp_reg_required_here (&str, 12) == FAIL)
3192 {
3193 if (!inst.error)
3194 inst.error = bad_args;
3195 return;
3196 }
3197
3198 if (skip_past_comma (&str) == FAIL
3199 || cp_address_required_here (&str) == FAIL)
3200 {
3201 if (! inst.error)
3202 inst.error = bad_args;
3203 return;
3204 }
3205
3206 inst.instruction |= flags;
3207 end_of_line (str);
3208 return;
3209}
3210
3211static void
3212do_co_reg (str, flags)
3213 char *str;
3214 unsigned long flags;
3215{
3216 /* Co-processor register transfer.
3217 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
3218
3219 while (*str == ' ')
3220 str++;
3221
3222 if (co_proc_number (&str) == FAIL)
3223 {
3224 if (!inst.error)
3225 inst.error = bad_args;
3226 return;
3227 }
3228
3229 if (skip_past_comma (&str) == FAIL
3230 || cp_opc_expr (&str, 21, 3) == FAIL)
3231 {
3232 if (!inst.error)
3233 inst.error = bad_args;
3234 return;
3235 }
3236
3237 if (skip_past_comma (&str) == FAIL
3238 || reg_required_here (&str, 12) == FAIL)
3239 {
3240 if (!inst.error)
3241 inst.error = bad_args;
3242 return;
3243 }
3244
3245 if (skip_past_comma (&str) == FAIL
3246 || cp_reg_required_here (&str, 16) == FAIL)
3247 {
3248 if (!inst.error)
3249 inst.error = bad_args;
3250 return;
3251 }
3252
3253 if (skip_past_comma (&str) == FAIL
3254 || cp_reg_required_here (&str, 0) == FAIL)
3255 {
3256 if (!inst.error)
3257 inst.error = bad_args;
3258 return;
3259 }
3260
3261 if (skip_past_comma (&str) == SUCCESS)
3262 {
3263 if (cp_opc_expr (&str, 5, 3) == FAIL)
3264 {
3265 if (!inst.error)
3266 inst.error = bad_args;
3267 return;
3268 }
3269 }
3270
3271 end_of_line (str);
3272 return;
3273}
3274
3275static void
3276do_fp_ctrl (str, flags)
3277 char *str;
3278 unsigned long flags;
3279{
3280 /* FP control registers.
3281 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
3282
3283 while (*str == ' ')
3284 str++;
3285
3286 if (reg_required_here (&str, 12) == FAIL)
3287 {
3288 if (!inst.error)
3289 inst.error = bad_args;
3290 return;
3291 }
3292
3293 end_of_line (str);
3294 return;
3295}
3296
3297static void
3298do_fp_ldst (str, flags)
3299 char *str;
3300 unsigned long flags;
3301{
3302 while (*str == ' ')
3303 str++;
3304
3305 switch (inst.suffix)
3306 {
3307 case SUFF_S:
3308 break;
3309 case SUFF_D:
3310 inst.instruction |= CP_T_X;
3311 break;
3312 case SUFF_E:
3313 inst.instruction |= CP_T_Y;
3314 break;
3315 case SUFF_P:
3316 inst.instruction |= CP_T_X | CP_T_Y;
3317 break;
3318 default:
3319 abort ();
3320 }
3321
3322 if (fp_reg_required_here (&str, 12) == FAIL)
3323 {
3324 if (!inst.error)
3325 inst.error = bad_args;
3326 return;
3327 }
3328
3329 if (skip_past_comma (&str) == FAIL
3330 || cp_address_required_here (&str) == FAIL)
3331 {
3332 if (!inst.error)
3333 inst.error = bad_args;
3334 return;
3335 }
3336
3337 end_of_line (str);
3338}
3339
3340static void
3341do_fp_ldmstm (str, flags)
3342 char *str;
3343 unsigned long flags;
3344{
3345 int num_regs;
3346
3347 while (*str == ' ')
3348 str++;
3349
3350 if (fp_reg_required_here (&str, 12) == FAIL)
3351 {
3352 if (! inst.error)
3353 inst.error = bad_args;
3354 return;
3355 }
3356
3357 /* Get Number of registers to transfer */
3358 if (skip_past_comma (&str) == FAIL
3359 || my_get_expression (&inst.reloc.exp, &str))
3360 {
3361 if (! inst.error)
3362 inst.error = "constant expression expected";
3363 return;
3364 }
3365
3366 if (inst.reloc.exp.X_op != O_constant)
3367 {
3368 inst.error = "Constant value required for number of registers";
3369 return;
3370 }
3371
3372 num_regs = inst.reloc.exp.X_add_number;
3373
3374 if (num_regs < 1 || num_regs > 4)
3375 {
3376 inst.error = "number of registers must be in the range [1:4]";
3377 return;
3378 }
3379
3380 switch (num_regs)
3381 {
3382 case 1:
3383 inst.instruction |= CP_T_X;
3384 break;
3385 case 2:
3386 inst.instruction |= CP_T_Y;
3387 break;
3388 case 3:
3389 inst.instruction |= CP_T_Y | CP_T_X;
3390 break;
3391 case 4:
3392 break;
3393 default:
3394 abort ();
3395 }
3396
3397 if (flags)
3398 {
3399 int reg;
3400 int write_back;
3401 int offset;
3402
3403 /* The instruction specified "ea" or "fd", so we can only accept
3404 [Rn]{!}. The instruction does not really support stacking or
3405 unstacking, so we have to emulate these by setting appropriate
3406 bits and offsets. */
3407 if (skip_past_comma (&str) == FAIL
3408 || *str != '[')
3409 {
3410 if (! inst.error)
3411 inst.error = bad_args;
3412 return;
3413 }
3414
3415 str++;
3416 while (*str == ' ')
3417 str++;
3418
3419 if ((reg = reg_required_here (&str, 16)) == FAIL)
3420 {
3421 inst.error = "Register required";
3422 return;
3423 }
3424
3425 while (*str == ' ')
3426 str++;
3427
3428 if (*str != ']')
3429 {
3430 inst.error = bad_args;
3431 return;
3432 }
3433
3434 str++;
3435 if (*str == '!')
3436 {
3437 write_back = 1;
3438 str++;
3439 if (reg == REG_PC)
3440 {
3441 inst.error = "R15 not allowed as base register with write-back";
3442 return;
3443 }
3444 }
3445 else
3446 write_back = 0;
3447
3448 if (flags & CP_T_Pre)
3449 {
3450 /* Pre-decrement */
3451 offset = 3 * num_regs;
3452 if (write_back)
3453 flags |= CP_T_WB;
3454 }
3455 else
3456 {
3457 /* Post-increment */
3458 if (write_back)
3459 {
3460 flags |= CP_T_WB;
3461 offset = 3 * num_regs;
3462 }
3463 else
3464 {
3465 /* No write-back, so convert this into a standard pre-increment
3466 instruction -- aesthetically more pleasing. */
3467 flags = CP_T_Pre | CP_T_UD;
3468 offset = 0;
3469 }
3470 }
3471
3472 inst.instruction |= flags | offset;
3473 }
3474 else if (skip_past_comma (&str) == FAIL
3475 || cp_address_required_here (&str) == FAIL)
3476 {
3477 if (! inst.error)
3478 inst.error = bad_args;
3479 return;
3480 }
3481
3482 end_of_line (str);
3483}
3484
3485static void
3486do_fp_dyadic (str, flags)
3487 char *str;
3488 unsigned long flags;
3489{
3490 while (*str == ' ')
3491 str++;
3492
3493 switch (inst.suffix)
3494 {
3495 case SUFF_S:
3496 break;
3497 case SUFF_D:
3498 inst.instruction |= 0x00000080;
3499 break;
3500 case SUFF_E:
3501 inst.instruction |= 0x00080000;
3502 break;
3503 default:
3504 abort ();
3505 }
3506
3507 if (fp_reg_required_here (&str, 12) == FAIL)
3508 {
3509 if (! inst.error)
3510 inst.error = bad_args;
3511 return;
3512 }
3513
3514 if (skip_past_comma (&str) == FAIL
3515 || fp_reg_required_here (&str, 16) == FAIL)
3516 {
3517 if (! inst.error)
3518 inst.error = bad_args;
3519 return;
3520 }
3521
3522 if (skip_past_comma (&str) == FAIL
3523 || fp_op2 (&str) == FAIL)
3524 {
3525 if (! inst.error)
3526 inst.error = bad_args;
3527 return;
3528 }
3529
3530 inst.instruction |= flags;
3531 end_of_line (str);
3532 return;
3533}
3534
3535static void
3536do_fp_monadic (str, flags)
3537 char *str;
3538 unsigned long flags;
3539{
3540 while (*str == ' ')
3541 str++;
3542
3543 switch (inst.suffix)
3544 {
3545 case SUFF_S:
3546 break;
3547 case SUFF_D:
3548 inst.instruction |= 0x00000080;
3549 break;
3550 case SUFF_E:
3551 inst.instruction |= 0x00080000;
3552 break;
3553 default:
3554 abort ();
3555 }
3556
3557 if (fp_reg_required_here (&str, 12) == FAIL)
3558 {
3559 if (! inst.error)
3560 inst.error = bad_args;
3561 return;
3562 }
3563
3564 if (skip_past_comma (&str) == FAIL
3565 || fp_op2 (&str) == FAIL)
3566 {
3567 if (! inst.error)
3568 inst.error = bad_args;
3569 return;
3570 }
3571
3572 inst.instruction |= flags;
3573 end_of_line (str);
3574 return;
3575}
3576
3577static void
3578do_fp_cmp (str, flags)
3579 char *str;
3580 unsigned long flags;
3581{
3582 while (*str == ' ')
3583 str++;
3584
3585 if (fp_reg_required_here (&str, 16) == FAIL)
3586 {
3587 if (! inst.error)
3588 inst.error = bad_args;
3589 return;
3590 }
3591
3592 if (skip_past_comma (&str) == FAIL
3593 || fp_op2 (&str) == FAIL)
3594 {
3595 if (! inst.error)
3596 inst.error = bad_args;
3597 return;
3598 }
3599
3600 inst.instruction |= flags;
3601 end_of_line (str);
3602 return;
3603}
3604
3605static void
3606do_fp_from_reg (str, flags)
3607 char *str;
3608 unsigned long flags;
3609{
3610 while (*str == ' ')
3611 str++;
3612
3613 switch (inst.suffix)
3614 {
3615 case SUFF_S:
3616 break;
3617 case SUFF_D:
3618 inst.instruction |= 0x00000080;
3619 break;
3620 case SUFF_E:
3621 inst.instruction |= 0x00080000;
3622 break;
3623 default:
3624 abort ();
3625 }
3626
3627 if (fp_reg_required_here (&str, 16) == FAIL)
3628 {
3629 if (! inst.error)
3630 inst.error = bad_args;
3631 return;
3632 }
3633
3634 if (skip_past_comma (&str) == FAIL
3635 || reg_required_here (&str, 12) == FAIL)
3636 {
3637 if (! inst.error)
3638 inst.error = bad_args;
3639 return;
3640 }
3641
3642 inst.instruction |= flags;
3643 end_of_line (str);
3644 return;
3645}
3646
3647static void
3648do_fp_to_reg (str, flags)
3649 char *str;
3650 unsigned long flags;
3651{
3652 while (*str == ' ')
3653 str++;
3654
3655 if (reg_required_here (&str, 12) == FAIL)
3656 {
3657 if (! inst.error)
3658 inst.error = bad_args;
3659 return;
3660 }
3661
3662 if (skip_past_comma (&str) == FAIL
3663 || fp_reg_required_here (&str, 0) == FAIL)
3664 {
3665 if (! inst.error)
3666 inst.error = bad_args;
3667 return;
3668 }
3669
3670 inst.instruction |= flags;
3671 end_of_line (str);
3672 return;
3673}
3674
590c50d8
ILT
3675/* Thumb specific routines */
3676
3677/* Parse and validate that a register is of the right form, this saves
3678 repeated checking of this information in many similar cases.
3679 Unlike the 32-bit case we do not insert the register into the opcode
3680 here, since the position is often unknown until the full instruction
3681 has been parsed. */
3682static int
3683thumb_reg (strp, hi_lo)
3684 char **strp;
3685 int hi_lo;
338a7060 3686{
590c50d8 3687 int reg;
338a7060 3688
590c50d8
ILT
3689 if ((reg = arm_reg_parse (strp)) == FAIL || ! int_register (reg))
3690 {
3691 inst.error = "Register expected";
3692 return FAIL;
3693 }
338a7060 3694
590c50d8
ILT
3695 switch (hi_lo)
3696 {
3697 case THUMB_REG_LO:
3698 if (reg > 7)
3699 {
3700 inst.error = "lo register required";
3701 return FAIL;
3702 }
3703 break;
338a7060 3704
590c50d8
ILT
3705 case THUMB_REG_HI:
3706 if (reg < 8)
3707 {
3708 inst.error = "hi register required";
3709 return FAIL;
3710 }
3711 break;
3712
3713 default:
3714 break;
3715 }
3716
3717 return reg;
3718}
3719
3720/* Parse an add or subtract instruction, SUBTRACT is non-zero if the opcode
3721 was SUB. */
3722static void
3723thumb_add_sub (str, subtract)
3724 char *str;
3725 int subtract;
3726{
3727 int Rd, Rs, Rn = FAIL;
3728
3729 while (*str == ' ')
3730 str++;
3731
3732 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
3733 || skip_past_comma (&str) == FAIL)
3734 {
3735 if (! inst.error)
3736 inst.error = bad_args;
3737 return;
3738 }
3739
3740 if (*str == '#')
3741 {
3742 Rs = Rd;
3743 str++;
3744 if (my_get_expression (&inst.reloc.exp, &str))
3745 return;
3746 }
3747 else
3748 {
3749 if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
3750 return;
3751
3752 if (skip_past_comma (&str) == FAIL)
3753 {
3754 /* Two operand format, shuffle the registers and pretend there
3755 are 3 */
3756 Rn = Rs;
3757 Rs = Rd;
3758 }
3759 else if (*str == '#')
3760 {
3761 str++;
3762 if (my_get_expression (&inst.reloc.exp, &str))
3763 return;
3764 }
3765 else if ((Rn = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
3766 return;
3767 }
3768
3769 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
3770 for the latter case, EXPR contains the immediate that was found. */
3771 if (Rn != FAIL)
3772 {
3773 /* All register format. */
ccc30467 3774 if (Rd > 7 || Rs > 7 || Rn > 7)
590c50d8
ILT
3775 {
3776 if (Rs != Rd)
3777 {
3778 inst.error = "dest and source1 must be the same register";
3779 return;
3780 }
3781
3782 /* Can't do this for SUB */
3783 if (subtract)
3784 {
3785 inst.error = "subtract valid only on lo regs";
3786 return;
3787 }
3788
3789 inst.instruction = (T_OPCODE_ADD_HI
3790 | (Rd > 7 ? THUMB_H1 : 0)
3791 | (Rn > 7 ? THUMB_H2 : 0));
3792 inst.instruction |= (Rd & 7) | ((Rn & 7) << 3);
3793 }
3794 else
3795 {
3796 inst.instruction = subtract ? T_OPCODE_SUB_R3 : T_OPCODE_ADD_R3;
3797 inst.instruction |= Rd | (Rs << 3) | (Rn << 6);
3798 }
3799 }
3800 else
3801 {
3802 /* Immediate expression, now things start to get nasty. */
3803
3804 /* First deal with HI regs, only very restricted cases allowed:
3805 Adjusting SP, and using PC or SP to get an address. */
3806 if ((Rd > 7 && (Rd != REG_SP || Rs != REG_SP))
3807 || (Rs > 7 && Rs != REG_SP && Rs != REG_PC))
3808 {
3809 inst.error = "invalid Hi register with immediate";
3810 return;
3811 }
3812
3813 if (inst.reloc.exp.X_op != O_constant)
3814 {
3815 /* Value isn't known yet, all we can do is store all the fragments
3816 we know about in the instruction and let the reloc hacking
3817 work it all out. */
3818 inst.instruction = (subtract ? 0x8000 : 0) | (Rd << 4) | Rs;
3819 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
3820 }
3821 else
3822 {
3823 int offset = inst.reloc.exp.X_add_number;
3824
3825 if (subtract)
3826 offset = -offset;
3827
3828 if (offset < 0)
3829 {
3830 offset = -offset;
3831 subtract = 1;
3832
3833 /* Quick check, in case offset is MIN_INT */
3834 if (offset < 0)
3835 {
3836 inst.error = "immediate value out of range";
3837 return;
3838 }
3839 }
3840 else
3841 subtract = 0;
3842
3843 if (Rd == REG_SP)
3844 {
3845 if (offset & ~0x1fc)
3846 {
3847 inst.error = "invalid immediate value for stack adjust";
3848 return;
3849 }
3850 inst.instruction = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
3851 inst.instruction |= offset >> 2;
3852 }
3853 else if (Rs == REG_PC || Rs == REG_SP)
3854 {
3855 if (subtract
3856 || (offset & ~0x3fc))
3857 {
3858 inst.error = "invalid immediate for address calculation";
3859 return;
3860 }
3861 inst.instruction = (Rs == REG_PC ? T_OPCODE_ADD_PC
3862 : T_OPCODE_ADD_SP);
3863 inst.instruction |= (Rd << 8) | (offset >> 2);
3864 }
3865 else if (Rs == Rd)
3866 {
3867 if (offset & ~0xff)
3868 {
3869 inst.error = "immediate value out of range";
3870 return;
3871 }
3872 inst.instruction = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
3873 inst.instruction |= (Rd << 8) | offset;
3874 }
3875 else
3876 {
3877 if (offset & ~0x7)
3878 {
3879 inst.error = "immediate value out of range";
3880 return;
3881 }
3882 inst.instruction = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
3883 inst.instruction |= Rd | (Rs << 3) | (offset << 6);
3884 }
3885 }
3886 }
3887 end_of_line (str);
3888}
3889
3890static void
3891thumb_shift (str, shift)
3892 char *str;
3893 int shift;
3894{
3895 int Rd, Rs, Rn = FAIL;
3896
3897 while (*str == ' ')
3898 str++;
3899
3900 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
3901 || skip_past_comma (&str) == FAIL)
3902 {
3903 if (! inst.error)
3904 inst.error = bad_args;
3905 return;
3906 }
3907
3908 if (*str == '#')
3909 {
3910 /* Two operand immediate format, set Rs to Rd. */
3911 Rs = Rd;
3912 str++;
3913 if (my_get_expression (&inst.reloc.exp, &str))
3914 return;
3915 }
3916 else
3917 {
3918 if ((Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
3919 return;
3920
3921 if (skip_past_comma (&str) == FAIL)
3922 {
3923 /* Two operand format, shuffle the registers and pretend there
3924 are 3 */
3925 Rn = Rs;
3926 Rs = Rd;
3927 }
3928 else if (*str == '#')
3929 {
3930 str++;
3931 if (my_get_expression (&inst.reloc.exp, &str))
3932 return;
3933 }
3934 else if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
3935 return;
3936 }
3937
3938 /* We now have Rd and Rs set to registers, and Rn set to a register or FAIL;
3939 for the latter case, EXPR contains the immediate that was found. */
3940
3941 if (Rn != FAIL)
3942 {
3943 if (Rs != Rd)
3944 {
3945 inst.error = "source1 and dest must be same register";
3946 return;
3947 }
3948
3949 switch (shift)
3950 {
3951 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_R; break;
3952 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_R; break;
3953 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_R; break;
3954 }
3955
3956 inst.instruction |= Rd | (Rn << 3);
3957 }
3958 else
3959 {
3960 switch (shift)
3961 {
3962 case THUMB_ASR: inst.instruction = T_OPCODE_ASR_I; break;
3963 case THUMB_LSL: inst.instruction = T_OPCODE_LSL_I; break;
3964 case THUMB_LSR: inst.instruction = T_OPCODE_LSR_I; break;
3965 }
3966
3967 if (inst.reloc.exp.X_op != O_constant)
3968 {
3969 /* Value isn't known yet, create a dummy reloc and let reloc
3970 hacking fix it up */
3971
3972 inst.reloc.type = BFD_RELOC_ARM_THUMB_SHIFT;
3973 }
3974 else
3975 {
3976 unsigned shift_value = inst.reloc.exp.X_add_number;
3977
3978 if (shift_value > 32 || (shift_value == 32 && shift == THUMB_LSL))
3979 {
3980 inst.error = "Invalid immediate for shift";
3981 return;
3982 }
3983
3984 /* Shifts of zero are handled by converting to LSL */
3985 if (shift_value == 0)
3986 inst.instruction = T_OPCODE_LSL_I;
3987
3988 /* Shifts of 32 are encoded as a shift of zero */
3989 if (shift_value == 32)
3990 shift_value = 0;
3991
3992 inst.instruction |= shift_value << 6;
3993 }
3994
3995 inst.instruction |= Rd | (Rs << 3);
3996 }
3997 end_of_line (str);
3998}
3999
4000static void
4001thumb_mov_compare (str, move)
4002 char *str;
4003 int move;
4004{
4005 int Rd, Rs = FAIL;
4006
4007 while (*str == ' ')
4008 str++;
4009
4010 if ((Rd = thumb_reg (&str, THUMB_REG_ANY)) == FAIL
4011 || skip_past_comma (&str) == FAIL)
4012 {
4013 if (! inst.error)
4014 inst.error = bad_args;
4015 return;
4016 }
4017
4018 if (*str == '#')
4019 {
4020 str++;
4021 if (my_get_expression (&inst.reloc.exp, &str))
4022 return;
4023 }
4024 else if ((Rs = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
4025 return;
4026
4027 if (Rs != FAIL)
4028 {
4029 if (Rs < 8 && Rd < 8)
4030 {
4031 if (move == THUMB_MOVE)
f520aaee
NC
4032 /* A move of two lowregs is encoded as ADD Rd, Rs, #0
4033 since a MOV instruction produces unpredictable results */
590c50d8
ILT
4034 inst.instruction = T_OPCODE_ADD_I3;
4035 else
4036 inst.instruction = T_OPCODE_CMP_LR;
4037 inst.instruction |= Rd | (Rs << 3);
4038 }
4039 else
4040 {
4041 if (move == THUMB_MOVE)
4042 inst.instruction = T_OPCODE_MOV_HR;
4043 else
4044 inst.instruction = T_OPCODE_CMP_HR;
4045
4046 if (Rd > 7)
4047 inst.instruction |= THUMB_H1;
4048
4049 if (Rs > 7)
4050 inst.instruction |= THUMB_H2;
4051
4052 inst.instruction |= (Rd & 7) | ((Rs & 7) << 3);
4053 }
4054 }
4055 else
4056 {
4057 if (Rd > 7)
4058 {
4059 inst.error = "only lo regs allowed with immediate";
4060 return;
4061 }
4062
4063 if (move == THUMB_MOVE)
4064 inst.instruction = T_OPCODE_MOV_I8;
4065 else
4066 inst.instruction = T_OPCODE_CMP_I8;
4067
4068 inst.instruction |= Rd << 8;
4069
4070 if (inst.reloc.exp.X_op != O_constant)
4071 inst.reloc.type = BFD_RELOC_ARM_THUMB_IMM;
4072 else
4073 {
4074 unsigned value = inst.reloc.exp.X_add_number;
4075
4076 if (value > 255)
4077 {
4078 inst.error = "invalid immediate";
4079 return;
4080 }
4081
4082 inst.instruction |= value;
4083 }
4084 }
4085
4086 end_of_line (str);
4087}
4088
4089static void
4090thumb_load_store (str, load_store, size)
4091 char *str;
4092 int load_store;
4093 int size;
4094{
4095 int Rd, Rb, Ro = FAIL;
4096
4097 while (*str == ' ')
4098 str++;
4099
4100 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
4101 || skip_past_comma (&str) == FAIL)
4102 {
4103 if (! inst.error)
4104 inst.error = bad_args;
4105 return;
4106 }
4107
4108 if (*str == '[')
4109 {
4110 str++;
4111 if ((Rb = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
4112 return;
4113
4114 if (skip_past_comma (&str) != FAIL)
4115 {
4116 if (*str == '#')
4117 {
4118 str++;
4119 if (my_get_expression (&inst.reloc.exp, &str))
4120 return;
4121 }
4122 else if ((Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
4123 return;
4124 }
4125 else
4126 {
4127 inst.reloc.exp.X_op = O_constant;
4128 inst.reloc.exp.X_add_number = 0;
4129 }
4130
4131 if (*str != ']')
4132 {
4133 inst.error = "expected ']'";
4134 return;
4135 }
4136 str++;
4137 }
4138 else if (*str == '=')
4139 {
f520aaee
NC
4140 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op */
4141 str++;
4142
4143 while (*str == ' ')
4144 str++;
4145
4146 if (my_get_expression (& inst.reloc.exp, & str))
4147 return;
4148
4149 end_of_line (str);
4150
4151 if ( inst.reloc.exp.X_op != O_constant
4152 && inst.reloc.exp.X_op != O_symbol)
4153 {
4154 inst.error = "Constant expression expected";
4155 return;
4156 }
4157
4158 if (inst.reloc.exp.X_op == O_constant
4159 && ((inst.reloc.exp.X_add_number & ~0xFF) == 0))
4160 {
4161 /* This can be done with a mov instruction */
4162
4163 inst.instruction = T_OPCODE_MOV_I8 | (Rd << 8);
4164 inst.instruction |= inst.reloc.exp.X_add_number;
4165 return;
4166 }
4167
4168 /* Insert into literal pool */
4169 if (add_to_lit_pool () == FAIL)
4170 {
4171 if (!inst.error)
4172 inst.error = "literal pool insertion failed";
4173 return;
4174 }
4175
4176 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
4177 inst.reloc.pc_rel = 1;
4178 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
4179 inst.reloc.exp.X_add_number += 4; /* Adjust ARM pipeline offset to Thumb */
4180
4181 return;
590c50d8
ILT
4182 }
4183 else
4184 {
4185 if (my_get_expression (&inst.reloc.exp, &str))
4186 return;
4187
4188 inst.instruction = T_OPCODE_LDR_PC | (Rd << 8);
4189 inst.reloc.pc_rel = 1;
4190 inst.reloc.exp.X_add_number -= 4; /* Pipeline offset */
4191 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
4192 end_of_line (str);
4193 return;
4194 }
4195
4196 if (Rb == REG_PC || Rb == REG_SP)
4197 {
4198 if (size != THUMB_WORD)
4199 {
4200 inst.error = "byte or halfword not valid for base register";
4201 return;
4202 }
4203 else if (Rb == REG_PC && load_store != THUMB_LOAD)
4204 {
4205 inst.error = "R15 based store not allowed";
4206 return;
4207 }
4208 else if (Ro != FAIL)
4209 {
4210 inst.error = "Invalid base register for register offset";
4211 return;
4212 }
4213
4214 if (Rb == REG_PC)
4215 inst.instruction = T_OPCODE_LDR_PC;
4216 else if (load_store == THUMB_LOAD)
4217 inst.instruction = T_OPCODE_LDR_SP;
4218 else
4219 inst.instruction = T_OPCODE_STR_SP;
4220
4221 inst.instruction |= Rd << 8;
4222 if (inst.reloc.exp.X_op == O_constant)
4223 {
4224 unsigned offset = inst.reloc.exp.X_add_number;
4225
4226 if (offset & ~0x3fc)
4227 {
4228 inst.error = "invalid offset";
4229 return;
4230 }
4231
4232 inst.instruction |= offset >> 2;
4233 }
4234 else
4235 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
4236 }
4237 else if (Rb > 7)
4238 {
4239 inst.error = "invalid base register in load/store";
4240 return;
4241 }
4242 else if (Ro == FAIL)
4243 {
4244 /* Immediate offset */
4245 if (size == THUMB_WORD)
4246 inst.instruction = (load_store == THUMB_LOAD
4247 ? T_OPCODE_LDR_IW : T_OPCODE_STR_IW);
4248 else if (size == THUMB_HALFWORD)
4249 inst.instruction = (load_store == THUMB_LOAD
4250 ? T_OPCODE_LDR_IH : T_OPCODE_STR_IH);
4251 else
4252 inst.instruction = (load_store == THUMB_LOAD
4253 ? T_OPCODE_LDR_IB : T_OPCODE_STR_IB);
4254
4255 inst.instruction |= Rd | (Rb << 3);
4256
4257 if (inst.reloc.exp.X_op == O_constant)
4258 {
4259 unsigned offset = inst.reloc.exp.X_add_number;
4260
4261 if (offset & ~(0x1f << size))
4262 {
4263 inst.error = "Invalid offset";
4264 return;
4265 }
ccc30467 4266 inst.instruction |= (offset >> size) << 6;
590c50d8
ILT
4267 }
4268 else
4269 inst.reloc.type = BFD_RELOC_ARM_THUMB_OFFSET;
4270 }
4271 else
4272 {
4273 /* Register offset */
4274 if (size == THUMB_WORD)
4275 inst.instruction = (load_store == THUMB_LOAD
4276 ? T_OPCODE_LDR_RW : T_OPCODE_STR_RW);
4277 else if (size == THUMB_HALFWORD)
4278 inst.instruction = (load_store == THUMB_LOAD
4279 ? T_OPCODE_LDR_RH : T_OPCODE_STR_RH);
4280 else
4281 inst.instruction = (load_store == THUMB_LOAD
4282 ? T_OPCODE_LDR_RB : T_OPCODE_STR_RB);
4283
4284 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
4285 }
4286
4287 end_of_line (str);
4288}
4289
ccc30467
ILT
4290static void
4291do_t_nop (str)
4292 char *str;
4293{
4294 /* Do nothing */
4295 end_of_line (str);
4296 return;
4297}
4298
590c50d8
ILT
4299/* Handle the Format 4 instructions that do not have equivalents in other
4300 formats. That is, ADC, AND, EOR, SBC, ROR, TST, NEG, CMN, ORR, MUL,
4301 BIC and MVN. */
4302static void
4303do_t_arit (str)
4304 char *str;
4305{
4306 int Rd, Rs, Rn;
4307
4308 while (*str == ' ')
4309 str++;
4310
4311 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
4312 return;
4313
4314 if (skip_past_comma (&str) == FAIL
4315 || (Rs = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
4316 {
4317 if (! inst.error)
4318 inst.error = bad_args;
4319 return;
4320 }
4321
4322 if (skip_past_comma (&str) != FAIL)
4323 {
4324 /* Three operand format not allowed for TST, CMN, NEG and MVN.
4325 (It isn't allowed for CMP either, but that isn't handled by this
4326 function.) */
4327 if (inst.instruction == T_OPCODE_TST
4328 || inst.instruction == T_OPCODE_CMN
4329 || inst.instruction == T_OPCODE_NEG
4330 || inst.instruction == T_OPCODE_MVN)
4331 {
4332 inst.error = bad_args;
4333 return;
4334 }
4335
4336 if ((Rn = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
4337 return;
4338
4339 if (Rs != Rd)
4340 {
4341 inst.error = "dest and source1 one must be the same register";
4342 return;
4343 }
4344 Rs = Rn;
4345 }
4346
4347 if (inst.instruction == T_OPCODE_MUL
4348 && Rs == Rd)
4349 as_tsktsk ("Rs and Rd must be different in MUL");
4350
4351 inst.instruction |= Rd | (Rs << 3);
4352 end_of_line (str);
4353}
4354
4355static void
4356do_t_add (str)
4357 char *str;
4358{
4359 thumb_add_sub (str, 0);
4360}
4361
4362static void
4363do_t_asr (str)
4364 char *str;
4365{
4366 thumb_shift (str, THUMB_ASR);
4367}
4368
4369static void
ccc30467 4370do_t_branch9 (str)
590c50d8
ILT
4371 char *str;
4372{
4373 if (my_get_expression (&inst.reloc.exp, &str))
4374 return;
ccc30467
ILT
4375 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH9;
4376 inst.reloc.pc_rel = 1;
4377 end_of_line (str);
4378}
4379
4380static void
4381do_t_branch12 (str)
4382 char *str;
4383{
4384 if (my_get_expression (&inst.reloc.exp, &str))
4385 return;
4386 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH12;
4387 inst.reloc.pc_rel = 1;
4388 end_of_line (str);
4389}
4390
4391static void
4392do_t_branch23 (str)
4393 char *str;
4394{
4395 if (my_get_expression (&inst.reloc.exp, &str))
4396 return;
4397 inst.reloc.type = BFD_RELOC_THUMB_PCREL_BRANCH23;
590c50d8
ILT
4398 inst.reloc.pc_rel = 1;
4399 end_of_line (str);
4400}
4401
4402static void
4403do_t_bx (str)
4404 char *str;
4405{
4406 int reg;
4407
4408 while (*str == ' ')
4409 str++;
4410
4411 if ((reg = thumb_reg (&str, THUMB_REG_ANY)) == FAIL)
4412 return;
4413
4414 /* This sets THUMB_H2 from the top bit of reg. */
4415 inst.instruction |= reg << 3;
4416
4417 /* ??? FIXME: Should add a hacky reloc here if reg is REG_PC. The reloc
4418 should cause the alignment to be checked once it is known. This is
4419 because BX PC only works if the instruction is word aligned. */
4420
4421 end_of_line (str);
4422}
4423
4424static void
4425do_t_compare (str)
4426 char *str;
4427{
4428 thumb_mov_compare (str, THUMB_COMPARE);
4429}
4430
4431static void
4432do_t_ldmstm (str)
4433 char *str;
4434{
4435 int Rb;
4436 long range;
4437
4438 while (*str == ' ')
4439 str++;
4440
4441 if ((Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL)
4442 return;
4443
4444 if (*str != '!')
4445 as_warn ("Inserted missing '!': load/store multiple always writes back base register");
4446 else
4447 str++;
4448
4449 if (skip_past_comma (&str) == FAIL
4450 || (range = reg_list (&str)) == FAIL)
4451 {
4452 if (! inst.error)
4453 inst.error = bad_args;
4454 return;
4455 }
4456
4457 if (inst.reloc.type != BFD_RELOC_NONE)
4458 {
4459 /* This really doesn't seem worth it. */
4460 inst.reloc.type = BFD_RELOC_NONE;
4461 inst.error = "Expression too complex";
4462 return;
4463 }
4464
4465 if (range & ~0xff)
4466 {
4467 inst.error = "only lo-regs valid in load/store multiple";
4468 return;
4469 }
4470
4471 inst.instruction |= (Rb << 8) | range;
4472 end_of_line (str);
4473}
4474
4475static void
4476do_t_ldr (str)
4477 char *str;
4478{
4479 thumb_load_store (str, THUMB_LOAD, THUMB_WORD);
4480}
4481
4482static void
4483do_t_ldrb (str)
4484 char *str;
4485{
4486 thumb_load_store (str, THUMB_LOAD, THUMB_BYTE);
4487}
4488
4489static void
4490do_t_ldrh (str)
4491 char *str;
4492{
4493 thumb_load_store (str, THUMB_LOAD, THUMB_HALFWORD);
4494}
4495
4496static void
4497do_t_lds (str)
4498 char *str;
4499{
4500 int Rd, Rb, Ro;
4501
4502 while (*str == ' ')
4503 str++;
4504
4505 if ((Rd = thumb_reg (&str, THUMB_REG_LO)) == FAIL
4506 || skip_past_comma (&str) == FAIL
4507 || *str++ != '['
4508 || (Rb = thumb_reg (&str, THUMB_REG_LO)) == FAIL
4509 || skip_past_comma (&str) == FAIL
4510 || (Ro = thumb_reg (&str, THUMB_REG_LO)) == FAIL
4511 || *str++ != ']')
4512 {
4513 if (! inst.error)
4514 inst.error = "Syntax: ldrs[b] Rd, [Rb, Ro]";
4515 return;
4516 }
4517
4518 inst.instruction |= Rd | (Rb << 3) | (Ro << 6);
4519 end_of_line (str);
4520}
4521
4522static void
4523do_t_lsl (str)
4524 char *str;
4525{
4526 thumb_shift (str, THUMB_LSL);
4527}
4528
4529static void
4530do_t_lsr (str)
4531 char *str;
4532{
4533 thumb_shift (str, THUMB_LSR);
4534}
4535
4536static void
4537do_t_mov (str)
4538 char *str;
4539{
4540 thumb_mov_compare (str, THUMB_MOVE);
4541}
4542
4543static void
4544do_t_push_pop (str)
4545 char *str;
4546{
4547 long range;
4548
4549 while (*str == ' ')
4550 str++;
4551
4552 if ((range = reg_list (&str)) == FAIL)
4553 {
4554 if (! inst.error)
4555 inst.error = bad_args;
4556 return;
4557 }
4558
4559 if (inst.reloc.type != BFD_RELOC_NONE)
4560 {
4561 /* This really doesn't seem worth it. */
4562 inst.reloc.type = BFD_RELOC_NONE;
4563 inst.error = "Expression too complex";
4564 return;
4565 }
4566
4567 if (range & ~0xff)
4568 {
4569 if ((inst.instruction == T_OPCODE_PUSH
4570 && (range & ~0xff) == 1 << REG_LR)
4571 || (inst.instruction == T_OPCODE_POP
4572 && (range & ~0xff) == 1 << REG_PC))
4573 {
4574 inst.instruction |= THUMB_PP_PC_LR;
4575 range &= 0xff;
4576 }
4577 else
4578 {
4579 inst.error = "invalid register list to push/pop instruction";
4580 return;
4581 }
4582 }
4583
4584 inst.instruction |= range;
4585 end_of_line (str);
4586}
4587
4588static void
4589do_t_str (str)
4590 char *str;
4591{
4592 thumb_load_store (str, THUMB_STORE, THUMB_WORD);
4593}
4594
4595static void
4596do_t_strb (str)
4597 char *str;
4598{
4599 thumb_load_store (str, THUMB_STORE, THUMB_BYTE);
4600}
4601
4602static void
4603do_t_strh (str)
4604 char *str;
4605{
4606 thumb_load_store (str, THUMB_STORE, THUMB_HALFWORD);
4607}
4608
4609static void
4610do_t_sub (str)
4611 char *str;
4612{
4613 thumb_add_sub (str, 1);
4614}
4615
4616static void
4617do_t_swi (str)
4618 char *str;
4619{
4620 while (*str == ' ')
4621 str++;
4622
4623 if (my_get_expression (&inst.reloc.exp, &str))
4624 return;
4625
4626 inst.reloc.type = BFD_RELOC_ARM_SWI;
4627 end_of_line (str);
4628 return;
4629}
4630
4631static void
4632do_t_adr (str)
4633 char *str;
4634{
4635 /* This is a pseudo-op of the form "adr rd, label" to be converted
ccc30467 4636 into a relative address of the form "add rd, pc, #label-.-4" */
590c50d8
ILT
4637 while (*str == ' ')
4638 str++;
4639
f520aaee 4640 if (reg_required_here (&str, 4) == FAIL /* Store Rd in temporary location inside instruction. */
590c50d8
ILT
4641 || skip_past_comma (&str) == FAIL
4642 || my_get_expression (&inst.reloc.exp, &str))
4643 {
4644 if (!inst.error)
4645 inst.error = bad_args;
4646 return;
4647 }
4648
4649 inst.reloc.type = BFD_RELOC_ARM_THUMB_ADD;
ccc30467 4650 inst.reloc.exp.X_add_number -= 4; /* PC relative adjust */
590c50d8
ILT
4651 inst.reloc.pc_rel = 1;
4652 inst.instruction |= REG_PC; /* Rd is already placed into the instruction */
4653 end_of_line (str);
4654}
4655
4656static void
4657insert_reg (entry)
4658 int entry;
4659{
4660 int len = strlen (reg_table[entry].name) + 2;
4661 char *buf = (char *) xmalloc (len);
4662 char *buf2 = (char *) xmalloc (len);
4663 int i = 0;
4664
4665#ifdef REGISTER_PREFIX
4666 buf[i++] = REGISTER_PREFIX;
4667#endif
4668
4669 strcpy (buf + i, reg_table[entry].name);
4670
4671 for (i = 0; buf[i]; i++)
4672 buf2[i] = islower (buf[i]) ? toupper (buf[i]) : buf[i];
338a7060
DE
4673
4674 buf2[i] = '\0';
4675
4676 hash_insert (arm_reg_hsh, buf, (PTR) &reg_table[entry]);
4677 hash_insert (arm_reg_hsh, buf2, (PTR) &reg_table[entry]);
4678}
4679
4680static void
4681insert_reg_alias (str, regnum)
4682 char *str;
4683 int regnum;
4684{
4685 struct reg_entry *new =
4686 (struct reg_entry *)xmalloc (sizeof (struct reg_entry));
4687 char *name = xmalloc (strlen (str) + 1);
4688 strcpy (name, str);
4689
4690 new->name = name;
4691 new->number = regnum;
4692
4693 hash_insert (arm_reg_hsh, name, (PTR) new);
4694}
4695
4696static void
4697set_constant_flonums ()
4698{
4699 int i;
4700
4701 for (i = 0; i < NUM_FLOAT_VALS; i++)
4702 if (atof_ieee ((char *)fp_const[i], 'x', fp_values[i]) == NULL)
4703 abort ();
4704}
4705
4706void
4707md_begin ()
4708{
4709 int i;
f520aaee 4710
338a7060 4711 if ((arm_ops_hsh = hash_new ()) == NULL
590c50d8 4712 || (arm_tops_hsh = hash_new ()) == NULL
338a7060
DE
4713 || (arm_cond_hsh = hash_new ()) == NULL
4714 || (arm_shift_hsh = hash_new ()) == NULL
4715 || (arm_reg_hsh = hash_new ()) == NULL
4716 || (arm_psr_hsh = hash_new ()) == NULL)
4717 as_fatal ("Virtual memory exhausted");
4718
4719 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
4720 hash_insert (arm_ops_hsh, insns[i].template, (PTR) (insns + i));
590c50d8
ILT
4721 for (i = 0; i < sizeof (tinsns) / sizeof (struct thumb_opcode); i++)
4722 hash_insert (arm_tops_hsh, tinsns[i].template, (PTR) (tinsns + i));
338a7060
DE
4723 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
4724 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
4725 for (i = 0; i < sizeof (shift) / sizeof (struct asm_shift); i++)
4726 hash_insert (arm_shift_hsh, shift[i].template, (PTR) (shift + i));
4727 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
4728 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
4729
4730 for (i = 0; reg_table[i].name; i++)
4731 insert_reg (i);
4732
4733 set_constant_flonums ();
46686c78
NC
4734
4735#ifdef OBJ_COFF
f520aaee
NC
4736 {
4737 unsigned int flags = 0;
4738
4739 /* Set the flags in the private structure */
4740 if (uses_apcs_26) flags |= F_APCS26;
4741 if (support_interwork) flags |= F_INTERWORK;
4742 if (uses_apcs_float) flags |= F_APCS_FLOAT;
4743 if (pic_code) flags |= F_PIC;
4744
4745 bfd_set_private_flags (stdoutput, flags);
4746 }
46686c78
NC
4747#endif
4748
4749 {
4750 unsigned mach;
4751
4752 /* Record the CPU type as well */
4753 switch (cpu_variant & ARM_CPU_MASK)
4754 {
4755 case ARM_2:
4756 mach = bfd_mach_arm_2;
4757 break;
4758
4759 case ARM_3: /* also ARM_250 */
4760 mach = bfd_mach_arm_2a;
4761 break;
4762
4763 default:
4764 case ARM_6 | ARM_3 | ARM_2: /* Actually no CPU type defined */
ccc30467
ILT
4765 mach = bfd_mach_arm_4;
4766 break;
4767
46686c78
NC
4768 case ARM_7: /* also ARM_6 */
4769 mach = bfd_mach_arm_3;
4770 break;
4771 }
4772
4773 /* Catch special cases */
ccc30467
ILT
4774 if (cpu_variant != (FPU_DEFAULT | CPU_DEFAULT))
4775 {
4776 if (cpu_variant & ARM_THUMB)
4777 mach = bfd_mach_arm_4T;
f520aaee 4778 else if ((cpu_variant & ARM_ARCHv4) == ARM_ARCHv4)
ccc30467
ILT
4779 mach = bfd_mach_arm_4;
4780 else if (cpu_variant & ARM_LONGMUL)
4781 mach = bfd_mach_arm_3M;
4782 }
46686c78
NC
4783
4784 bfd_set_arch_mach (stdoutput, TARGET_ARCH, mach);
4785 }
338a7060
DE
4786}
4787
338a7060
DE
4788/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
4789 for use in the a.out file, and stores them in the array pointed to by buf.
4790 This knows about the endian-ness of the target machine and does
4791 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
4792 2 (short) and 4 (long) Floating numbers are put out as a series of
4793 LITTLENUMS (shorts, here at least)
4794 */
4795void
4796md_number_to_chars (buf, val, n)
4797 char *buf;
4798 valueT val;
4799 int n;
4800{
4801 if (target_big_endian)
4802 number_to_chars_bigendian (buf, val, n);
4803 else
4804 number_to_chars_littleendian (buf, val, n);
4805}
4806
4807static valueT
4808md_chars_to_number (buf, n)
4809 char *buf;
4810 int n;
4811{
4812 valueT result = 0;
4813 unsigned char *where = (unsigned char *) buf;
4814
4815 if (target_big_endian)
4816 {
4817 while (n--)
4818 {
4819 result <<= 8;
4820 result |= (*where++ & 255);
4821 }
4822 }
4823 else
4824 {
4825 while (n--)
4826 {
4827 result <<= 8;
4828 result |= (where[n] & 255);
4829 }
4830 }
4831
4832 return result;
4833}
4834
c479fc62
JSC
4835/* Turn a string in input_line_pointer into a floating point constant
4836 of type TYPE, and store the appropriate bytes in *litP. The number
4837 of LITTLENUMS emitted is stored in *sizeP . An error message is
4838 returned, or NULL on OK.
4839
4840 Note that fp constants aren't represent in the normal way on the ARM.
4841 In big endian mode, things are as expected. However, in little endian
4842 mode fp constants are big-endian word-wise, and little-endian byte-wise
4843 within the words. For example, (double) 1.1 in big endian mode is
4844 the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
4845 the byte sequence 99 99 f1 3f 9a 99 99 99.
4846
4847 ??? The format of 12 byte floats is uncertain according to gcc's arm.h. */
338a7060 4848
338a7060
DE
4849char *
4850md_atof (type, litP, sizeP)
4851 char type;
4852 char *litP;
4853 int *sizeP;
4854{
4855 int prec;
4856 LITTLENUM_TYPE words[MAX_LITTLENUMS];
338a7060 4857 char *t;
c479fc62 4858 int i;
338a7060
DE
4859
4860 switch (type)
4861 {
338a7060
DE
4862 case 'f':
4863 case 'F':
4864 case 's':
4865 case 'S':
4866 prec = 2;
4867 break;
4868
4869 case 'd':
4870 case 'D':
4871 case 'r':
4872 case 'R':
4873 prec = 4;
4874 break;
4875
4876 case 'x':
4877 case 'X':
4878 prec = 6;
4879 break;
4880
4881 case 'p':
4882 case 'P':
4883 prec = 6;
4884 break;
4885
4886 default:
4887 *sizeP = 0;
4888 return "Bad call to MD_ATOF()";
4889 }
c479fc62 4890
338a7060
DE
4891 t = atof_ieee (input_line_pointer, type, words);
4892 if (t)
4893 input_line_pointer = t;
c479fc62
JSC
4894 *sizeP = prec * 2;
4895
4896 if (target_big_endian)
338a7060 4897 {
c479fc62
JSC
4898 for (i = 0; i < prec; i++)
4899 {
4900 md_number_to_chars (litP, (valueT) words[i], 2);
4901 litP += 2;
4902 }
338a7060 4903 }
c479fc62
JSC
4904 else
4905 {
4906 /* For a 4 byte float the order of elements in `words' is 1 0. For an
4907 8 byte float the order is 1 0 3 2. */
4908 for (i = 0; i < prec; i += 2)
4909 {
4910 md_number_to_chars (litP, (valueT) words[i + 1], 2);
4911 md_number_to_chars (litP + 2, (valueT) words[i], 2);
4912 litP += 4;
4913 }
4914 }
4915
338a7060
DE
4916 return 0;
4917}
4918
4919/* We have already put the pipeline compensation in the instruction */
4920
4921long
4922md_pcrel_from (fixP)
4923 fixS *fixP;
4924{
4925 if (fixP->fx_addsy && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
4926 && fixP->fx_subsy == NULL)
4927 return 0; /* HACK */
4928
f520aaee
NC
4929 if (fixP->fx_pcrel && (fixP->fx_r_type == BFD_RELOC_ARM_THUMB_ADD))
4930 {
4931 /* PC relative addressing on the Thumb is slightly odd
4932 as the bottom two bits of the PC are forced to zero
4933 for the calculation */
4934 return (fixP->fx_where + fixP->fx_frag->fr_address) & ~3;
4935 }
4936
338a7060
DE
4937 return fixP->fx_where + fixP->fx_frag->fr_address;
4938}
4939
4940/* Round up a section size to the appropriate boundary. */
4941valueT
4942md_section_align (segment, size)
4943 segT segment;
4944 valueT size;
4945{
4946 /* Round all sects to multiple of 4 */
4947 return (size + 3) & ~3;
4948}
4949
4950/* We have no need to default values of symbols. */
4951
4952/* ARGSUSED */
4953symbolS *
4954md_undefined_symbol (name)
4955 char *name;
4956{
4957 return 0;
4958}
4959
4960/* arm_reg_parse () := if it looks like a register, return its token and
4961 advance the pointer. */
4962
4963static int
4964arm_reg_parse (ccp)
4965 register char **ccp;
4966{
4967 char *start = *ccp;
4968 char c;
4969 char *p;
4970 struct reg_entry *reg;
4971
4972#ifdef REGISTER_PREFIX
4973 if (*start != REGISTER_PREFIX)
4974 return FAIL;
4975 p = start + 1;
4976#else
4977 p = start;
4978#ifdef OPTIONAL_REGISTER_PREFIX
4979 if (*p == OPTIONAL_REGISTER_PREFIX)
4980 p++, start++;
4981#endif
4982#endif
4983 if (!isalpha (*p) || !is_name_beginner (*p))
4984 return FAIL;
4985
4986 c = *p++;
4987 while (isalpha (c) || isdigit (c) || c == '_')
4988 c = *p++;
4989
4990 *--p = 0;
4991 reg = (struct reg_entry *) hash_find (arm_reg_hsh, start);
4992 *p = c;
4993
4994 if (reg)
4995 {
4996 *ccp = p;
4997 return reg->number;
4998 }
4999
5000 return FAIL;
5001}
5002
5003static int
5004arm_psr_parse (ccp)
5005 register char **ccp;
5006{
5007 char *start = *ccp;
5008 char c, *p;
5009 CONST struct asm_psr *psr;
5010
5011 p = start;
5012 c = *p++;
5013 while (isalpha (c) || c == '_')
5014 c = *p++;
5015
5016 *--p = 0;
5017 psr = (CONST struct asm_psr *) hash_find (arm_psr_hsh, start);
5018 *p = c;
5019
5020 if (psr)
5021 {
5022 *ccp = p;
5023 return psr->number;
5024 }
5025
5026 return FAIL;
5027}
5028
5029int
c479fc62 5030md_apply_fix3 (fixP, val, seg)
338a7060
DE
5031 fixS *fixP;
5032 valueT *val;
c479fc62 5033 segT seg;
338a7060
DE
5034{
5035 offsetT value = *val;
6e3fcdf0
NC
5036 offsetT newval;
5037 unsigned long temp;
338a7060
DE
5038 int sign;
5039 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
590c50d8 5040 arm_fix_data *arm_data = (arm_fix_data *) fixP->tc_fix_data;
338a7060
DE
5041
5042 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
5043
338a7060 5044 /* Note whether this will delete the relocation. */
ccc30467
ILT
5045#if 0 /* patch from REarnshaw to JDavis (disabled for the moment, since it doesn't work fully) */
5046 if ((fixP->fx_addsy == 0 || fixP->fx_addsy->sy_value.X_op == O_constant)
5047 && !fixP->fx_pcrel)
5048#else
338a7060 5049 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
ccc30467 5050#endif
338a7060
DE
5051 fixP->fx_done = 1;
5052
c479fc62
JSC
5053 /* If this symbol is in a different section then we need to leave it for
5054 the linker to deal with. Unfortunately, md_pcrel_from can't tell,
5055 so we have to undo it's effects here. */
5056 if (fixP->fx_pcrel)
5057 {
5058 if (S_IS_DEFINED (fixP->fx_addsy)
5059 && S_GET_SEGMENT (fixP->fx_addsy) != seg)
f520aaee
NC
5060 {
5061 if (fixP->fx_r_type == BFD_RELOC_ARM_PCREL_BRANCH)
5062 value = 0;
5063 else
5064 value += md_pcrel_from (fixP);
5065 }
c479fc62
JSC
5066 }
5067
5068 fixP->fx_addnumber = value; /* Remember value for emit_reloc */
5069
338a7060
DE
5070 switch (fixP->fx_r_type)
5071 {
5072 case BFD_RELOC_ARM_IMMEDIATE:
5073 newval = validate_immediate (value);
590c50d8 5074 temp = md_chars_to_number (buf, INSN_SIZE);
338a7060
DE
5075
5076 /* If the instruction will fail, see if we can fix things up by
5077 changing the opcode. */
5078 if (newval == FAIL
5079 && (newval = negate_data_op (&temp, value)) == FAIL)
5080 {
5081 as_bad_where (fixP->fx_file, fixP->fx_line,
5082 "invalid constant after fixup\n");
5083 break;
5084 }
5085
5086 newval |= (temp & 0xfffff000);
590c50d8 5087 md_number_to_chars (buf, newval, INSN_SIZE);
338a7060
DE
5088 break;
5089
c479fc62 5090 case BFD_RELOC_ARM_OFFSET_IMM:
338a7060 5091 sign = value >= 0;
c479fc62
JSC
5092 if ((value = validate_offset_imm (value, 0)) == FAIL)
5093 {
5094 as_bad ("bad immediate value for offset (%d)", val);
5095 break;
5096 }
338a7060
DE
5097 if (value < 0)
5098 value = -value;
5099
590c50d8 5100 newval = md_chars_to_number (buf, INSN_SIZE);
338a7060 5101 newval &= 0xff7ff000;
590c50d8
ILT
5102 newval |= value | (sign ? INDEX_UP : 0);
5103 md_number_to_chars (buf, newval, INSN_SIZE);
c479fc62
JSC
5104 break;
5105
5106 case BFD_RELOC_ARM_OFFSET_IMM8:
5107 case BFD_RELOC_ARM_HWLITERAL:
5108 sign = value >= 0;
5109 if ((value = validate_offset_imm (value, 1)) == FAIL)
5110 {
5111 if (fixP->fx_r_type == BFD_RELOC_ARM_HWLITERAL)
5112 as_bad_where (fixP->fx_file, fixP->fx_line,
5113 "invalid literal constant: pool needs to be closer\n");
5114 else
5115 as_bad ("bad immediate value for offset (%d)", value);
5116 break;
5117 }
5118
5119 if (value < 0)
5120 value = -value;
5121
590c50d8 5122 newval = md_chars_to_number (buf, INSN_SIZE);
c479fc62 5123 newval &= 0xff7ff0f0;
590c50d8
ILT
5124 newval |= ((value >> 4) << 8) | value & 0xf | (sign ? INDEX_UP : 0);
5125 md_number_to_chars (buf, newval, INSN_SIZE);
338a7060
DE
5126 break;
5127
5128 case BFD_RELOC_ARM_LITERAL:
5129 sign = value >= 0;
5130 if (value < 0)
5131 value = -value;
5132
c479fc62 5133 if ((value = validate_offset_imm (value, 0)) == FAIL)
338a7060
DE
5134 {
5135 as_bad_where (fixP->fx_file, fixP->fx_line,
5136 "invalid literal constant: pool needs to be closer\n");
5137 break;
5138 }
5139
590c50d8 5140 newval = md_chars_to_number (buf, INSN_SIZE);
338a7060 5141 newval &= 0xff7ff000;
590c50d8
ILT
5142 newval |= value | (sign ? INDEX_UP : 0);
5143 md_number_to_chars (buf, newval, INSN_SIZE);
338a7060
DE
5144 break;
5145
5146 case BFD_RELOC_ARM_SHIFT_IMM:
590c50d8 5147 newval = md_chars_to_number (buf, INSN_SIZE);
338a7060
DE
5148 if (((unsigned long) value) > 32
5149 || (value == 32
5150 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
5151 {
5152 as_bad_where (fixP->fx_file, fixP->fx_line,
5153 "shift expression is too large");
5154 break;
5155 }
5156
5157 if (value == 0)
5158 newval &= ~0x60; /* Shifts of zero must be done as lsl */
5159 else if (value == 32)
5160 value = 0;
5161 newval &= 0xfffff07f;
5162 newval |= (value & 0x1f) << 7;
590c50d8 5163 md_number_to_chars (buf, newval , INSN_SIZE);
338a7060
DE
5164 break;
5165
5166 case BFD_RELOC_ARM_SWI:
590c50d8
ILT
5167 if (arm_data->thumb_mode)
5168 {
5169 if (((unsigned long) value) > 0xff)
5170 as_bad_where (fixP->fx_file, fixP->fx_line,
5171 "Invalid swi expression");
5172 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xff00;
5173 newval |= value;
5174 md_number_to_chars (buf, newval, THUMB_SIZE);
5175 }
5176 else
5177 {
5178 if (((unsigned long) value) > 0x00ffffff)
5179 as_bad_where (fixP->fx_file, fixP->fx_line,
5180 "Invalid swi expression");
5181 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
5182 newval |= value;
5183 md_number_to_chars (buf, newval , INSN_SIZE);
5184 }
338a7060
DE
5185 break;
5186
5187 case BFD_RELOC_ARM_MULTI:
5188 if (((unsigned long) value) > 0xffff)
5189 as_bad_where (fixP->fx_file, fixP->fx_line,
5190 "Invalid expression in load/store multiple");
590c50d8
ILT
5191 newval = value | md_chars_to_number (buf, INSN_SIZE);
5192 md_number_to_chars (buf, newval, INSN_SIZE);
338a7060
DE
5193 break;
5194
5195 case BFD_RELOC_ARM_PCREL_BRANCH:
ccc30467
ILT
5196 value = (value >> 2) & 0x00ffffff;
5197 newval = md_chars_to_number (buf, INSN_SIZE);
5198 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
5199 newval = value | (newval & 0xff000000);
5200 md_number_to_chars (buf, newval, INSN_SIZE);
5201 break;
5202
5203 case BFD_RELOC_THUMB_PCREL_BRANCH9: /* conditional branch */
5204 newval = md_chars_to_number (buf, THUMB_SIZE);
5205 {
5206 addressT diff = (newval & 0xff) << 1;
5207 if (diff & 0x100)
5208 diff |= ~0xff;
5209
5210 value += diff;
5211 if ((value & 0x100) && ((value & ~0xff) != ~0xff))
5212 as_bad_where (fixP->fx_file, fixP->fx_line,
5213 "Branch out of range");
5214 newval = (newval & 0xff00) | ((value & 0x1ff) >> 1);
5215 }
5216 md_number_to_chars (buf, newval, THUMB_SIZE);
5217 break;
5218
5219 case BFD_RELOC_THUMB_PCREL_BRANCH12: /* unconditional branch */
5220 newval = md_chars_to_number (buf, THUMB_SIZE);
5221 {
5222 addressT diff = (newval & 0x7ff) << 1;
5223 if (diff & 0x800)
5224 diff |= ~0x7ff;
5225
5226 value += diff;
5227 if ((value & 0x800) && ((value & ~0x7ff) != ~0x7ff))
5228 as_bad_where (fixP->fx_file, fixP->fx_line,
5229 "Branch out of range");
5230 newval = (newval & 0xf800) | ((value & 0xfff) >> 1);
5231 }
5232 md_number_to_chars (buf, newval, THUMB_SIZE);
5233 break;
5234
5235 case BFD_RELOC_THUMB_PCREL_BRANCH23:
5236 newval = md_chars_to_number (buf, THUMB_SIZE);
5237 {
5238 offsetT newval2;
5239 addressT diff;
5240
5241 newval2 = md_chars_to_number (buf + 2, THUMB_SIZE);
5242 diff = ((newval & 0x7ff) << 12) | ((newval2 & 0x7ff) << 1);
5243 if (diff & 0x400000)
5244 diff |= ~0x3fffff;
5245 value += diff;
5246 if ((value & 0x400000) && ((value & ~0x3fffff) != ~0x3fffff))
5247 as_bad_where (fixP->fx_file, fixP->fx_line,
5248 "Branch with link out of range");
5249
5250 newval = (newval & 0xf800) | ((value & 0x7fffff) >> 12);
5251 newval2 = (newval2 & 0xf800) | ((value & 0xfff) >> 1);
5252 md_number_to_chars (buf, newval, THUMB_SIZE);
5253 md_number_to_chars (buf + 2, newval2, THUMB_SIZE);
5254 }
338a7060
DE
5255 break;
5256
5257 case BFD_RELOC_8:
5258 if (fixP->fx_done || fixP->fx_pcrel)
5259 md_number_to_chars (buf, value, 1);
5260 break;
5261
5262 case BFD_RELOC_16:
5263 if (fixP->fx_done || fixP->fx_pcrel)
5264 md_number_to_chars (buf, value, 2);
5265 break;
5266
c479fc62 5267 case BFD_RELOC_RVA:
338a7060
DE
5268 case BFD_RELOC_32:
5269 if (fixP->fx_done || fixP->fx_pcrel)
5270 md_number_to_chars (buf, value, 4);
5271 break;
5272
5273 case BFD_RELOC_ARM_CP_OFF_IMM:
5274 sign = value >= 0;
5275 if (value < -1023 || value > 1023 || (value & 3))
5276 as_bad_where (fixP->fx_file, fixP->fx_line,
5277 "Illegal value for co-processor offset");
5278 if (value < 0)
5279 value = -value;
590c50d8
ILT
5280 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
5281 newval |= (value >> 2) | (sign ? INDEX_UP : 0);
5282 md_number_to_chars (buf, newval , INSN_SIZE);
5283 break;
5284
5285 case BFD_RELOC_ARM_THUMB_OFFSET:
5286 newval = md_chars_to_number (buf, THUMB_SIZE);
5287 /* Exactly what ranges, and where the offset is inserted depends on
5288 the type of instruction, we can establish this from the top 4 bits */
5289 switch (newval >> 12)
5290 {
5291 case 4: /* PC load */
ccc30467
ILT
5292 /* Thumb PC loads are somewhat odd, bit 1 of the PC is
5293 forced to zero for these loads, so we will need to round
5294 up the offset if the instruction address is not word
5295 aligned (since the final address produced must be, and
5296 we can only describe word-aligned immediate offsets). */
590c50d8
ILT
5297
5298 if ((fixP->fx_frag->fr_address + fixP->fx_where + value) & 3)
5299 as_bad_where (fixP->fx_file, fixP->fx_line,
ccc30467
ILT
5300 "Invalid offset, target not word aligned (0x%08X)",
5301 (unsigned int)(fixP->fx_frag->fr_address + fixP->fx_where + value));
590c50d8
ILT
5302
5303 if ((value + 2) & ~0x3fe)
5304 as_bad_where (fixP->fx_file, fixP->fx_line,
5305 "Invalid offset");
ccc30467
ILT
5306
5307 /* Round up, since pc will be rounded down. */
590c50d8
ILT
5308 newval |= (value + 2) >> 2;
5309 break;
5310
5311 case 9: /* SP load/store */
5312 if (value & ~0x3fc)
5313 as_bad_where (fixP->fx_file, fixP->fx_line,
5314 "Invalid offset");
5315 newval |= value >> 2;
5316 break;
5317
5318 case 6: /* Word load/store */
5319 if (value & ~0x7c)
5320 as_bad_where (fixP->fx_file, fixP->fx_line,
5321 "Invalid offset");
5322 newval |= value << 4; /* 6 - 2 */
5323 break;
5324
5325 case 7: /* Byte load/store */
5326 if (value & ~0x1f)
5327 as_bad_where (fixP->fx_file, fixP->fx_line,
5328 "Invalid offset");
5329 newval |= value << 6;
5330 break;
5331
5332 case 8: /* Halfword load/store */
5333 if (value & ~0x3e)
5334 as_bad_where (fixP->fx_file, fixP->fx_line,
5335 "Invalid offset");
5336 newval |= value << 5; /* 6 - 1 */
5337 break;
5338
5339 default:
f520aaee
NC
5340 as_bad_where (fixP->fx_file, fixP->fx_line,
5341 "Unable to process relocation for thumb opcode: %x", newval);
5342 break;
590c50d8
ILT
5343 }
5344 md_number_to_chars (buf, newval, THUMB_SIZE);
5345 break;
5346
5347 case BFD_RELOC_ARM_THUMB_ADD:
5348 /* This is a complicated relocation, since we use it for all of
5349 the following immediate relocations:
5350 3bit ADD/SUB
5351 8bit ADD/SUB
5352 9bit ADD/SUB SP word-aligned
5353 10bit ADD PC/SP word-aligned
5354
5355 The type of instruction being processed is encoded in the
5356 instruction field:
5357 0x8000 SUB
5358 0x00F0 Rd
5359 0x000F Rs
5360 */
5361 newval = md_chars_to_number (buf, THUMB_SIZE);
5362 {
5363 int rd = (newval >> 4) & 0xf;
5364 int rs = newval & 0xf;
5365 int subtract = newval & 0x8000;
5366
5367 if (rd == REG_SP)
5368 {
5369 if (value & ~0x1fc)
5370 as_bad_where (fixP->fx_file, fixP->fx_line,
5371 "Invalid immediate for stack address calculation");
5372 newval = subtract ? T_OPCODE_SUB_ST : T_OPCODE_ADD_ST;
5373 newval |= value >> 2;
5374 }
5375 else if (rs == REG_PC || rs == REG_SP)
5376 {
5377 if (subtract ||
5378 value & ~0x3fc)
5379 as_bad_where (fixP->fx_file, fixP->fx_line,
5380 "Invalid immediate for address calculation (value = 0x%08X)", value);
5381 newval = (rs == REG_PC ? T_OPCODE_ADD_PC : T_OPCODE_ADD_SP);
6e3fcdf0 5382 newval |= rd << 8;
590c50d8
ILT
5383 newval |= value >> 2;
5384 }
5385 else if (rs == rd)
5386 {
5387 if (value & ~0xff)
5388 as_bad_where (fixP->fx_file, fixP->fx_line,
5389 "Invalid 8bit immediate");
5390 newval = subtract ? T_OPCODE_SUB_I8 : T_OPCODE_ADD_I8;
5391 newval |= (rd << 8) | value;
5392 }
5393 else
5394 {
5395 if (value & ~0x7)
5396 as_bad_where (fixP->fx_file, fixP->fx_line,
5397 "Invalid 3bit immediate");
5398 newval = subtract ? T_OPCODE_SUB_I3 : T_OPCODE_ADD_I3;
5399 newval |= rd | (rs << 3) | (value << 6);
5400 }
5401 }
5402 md_number_to_chars (buf, newval , THUMB_SIZE);
5403 break;
5404
5405 case BFD_RELOC_ARM_THUMB_IMM:
5406 newval = md_chars_to_number (buf, THUMB_SIZE);
5407 switch (newval >> 11)
5408 {
5409 case 0x04: /* 8bit immediate MOV */
5410 case 0x05: /* 8bit immediate CMP */
5411 if (value < 0 || value > 255)
5412 as_bad_where (fixP->fx_file, fixP->fx_line,
5413 "Invalid immediate: %d is too large", value);
5414 newval |= value;
5415 break;
5416
5417 default:
5418 abort ();
5419 }
5420 md_number_to_chars (buf, newval , THUMB_SIZE);
5421 break;
5422
5423 case BFD_RELOC_ARM_THUMB_SHIFT:
5424 /* 5bit shift value (0..31) */
5425 if (value < 0 || value > 31)
5426 as_bad_where (fixP->fx_file, fixP->fx_line,
5427 "Illegal Thumb shift value: %d", value);
5428 newval = md_chars_to_number (buf, THUMB_SIZE) & 0xf03f;
5429 newval |= value << 6;
5430 md_number_to_chars (buf, newval , THUMB_SIZE);
338a7060
DE
5431 break;
5432
5433 case BFD_RELOC_NONE:
5434 default:
5435 as_bad_where (fixP->fx_file, fixP->fx_line,
5436 "Bad relocation fixup type (%d)\n", fixP->fx_r_type);
5437 }
5438
5439 return 1;
5440}
5441
5442/* Translate internal representation of relocation info to BFD target
5443 format. */
5444arelent *
5445tc_gen_reloc (section, fixp)
5446 asection *section;
5447 fixS *fixp;
5448{
5449 arelent *reloc;
5450 bfd_reloc_code_real_type code;
5451
590c50d8 5452 reloc = (arelent *) xmalloc (sizeof (arelent));
338a7060
DE
5453
5454 reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
5455 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
5456
338a7060
DE
5457 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
5458 if (fixp->fx_pcrel == 0)
5459 reloc->addend = fixp->fx_offset;
5460 else
5461 reloc->addend = fixp->fx_offset = reloc->address;
5462
5463 switch (fixp->fx_r_type)
5464 {
5465 case BFD_RELOC_8:
5466 if (fixp->fx_pcrel)
5467 {
5468 code = BFD_RELOC_8_PCREL;
5469 break;
5470 }
5471
5472 case BFD_RELOC_16:
5473 if (fixp->fx_pcrel)
5474 {
5475 code = BFD_RELOC_16_PCREL;
5476 break;
5477 }
5478
5479 case BFD_RELOC_32:
5480 if (fixp->fx_pcrel)
5481 {
5482 code = BFD_RELOC_32_PCREL;
5483 break;
5484 }
5485
5486 case BFD_RELOC_ARM_PCREL_BRANCH:
c479fc62 5487 case BFD_RELOC_RVA:
ccc30467
ILT
5488 case BFD_RELOC_THUMB_PCREL_BRANCH9:
5489 case BFD_RELOC_THUMB_PCREL_BRANCH12:
5490 case BFD_RELOC_THUMB_PCREL_BRANCH23:
338a7060
DE
5491 code = fixp->fx_r_type;
5492 break;
5493
5494 case BFD_RELOC_ARM_LITERAL:
c479fc62 5495 case BFD_RELOC_ARM_HWLITERAL:
338a7060
DE
5496 /* If this is called then the a literal has been referenced across
5497 a section boundry - possibly due to an implicit dump */
ccc30467
ILT
5498 as_bad_where (fixp->fx_file, fixp->fx_line,
5499 "Literal referenced across section boundry (Implicit dump?)");
338a7060
DE
5500 return NULL;
5501
f520aaee
NC
5502 default:
5503 {
5504 char * type;
5505 switch (fixp->fx_r_type)
5506 {
5507 case BFD_RELOC_ARM_IMMEDIATE: type = "IMMEDIATE"; break;
5508 case BFD_RELOC_ARM_OFFSET_IMM: type = "OFFSET_IMM"; break;
5509 case BFD_RELOC_ARM_OFFSET_IMM8: type = "OFFSET_IMM8"; break;
5510 case BFD_RELOC_ARM_SHIFT_IMM: type = "SHIFT_IMM"; break;
5511 case BFD_RELOC_ARM_SWI: type = "SWI"; break;
5512 case BFD_RELOC_ARM_MULTI: type = "MULTI"; break;
5513 case BFD_RELOC_ARM_CP_OFF_IMM: type = "CP_OFF_IMM"; break;
5514 case BFD_RELOC_ARM_THUMB_ADD: type = "THUMB_ADD"; break;
5515 case BFD_RELOC_ARM_THUMB_SHIFT: type = "THUMB_SHIFT"; break;
5516 case BFD_RELOC_ARM_THUMB_IMM: type = "THUMB_IMM"; break;
5517 case BFD_RELOC_ARM_THUMB_OFFSET: type = "THUMB_OFFSET"; break;
5518 default: type = "<unknown>"; break;
5519 }
5520 as_bad_where (fixp->fx_file, fixp->fx_line,
5521 "Can not represent %s relocation in this object file format (%d)",
5522 type, fixp->fx_pcrel);
5523 return NULL;
5524 }
5525 }
338a7060 5526
f520aaee 5527 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
338a7060 5528
f520aaee
NC
5529 if (reloc->howto == NULL)
5530 {
ccc30467 5531 as_bad_where (fixp->fx_file, fixp->fx_line,
f520aaee
NC
5532 "Can not represent %s relocation in this object file format",
5533 bfd_get_reloc_code_name (code));
590c50d8 5534 return NULL;
338a7060
DE
5535 }
5536
338a7060
DE
5537 return reloc;
5538}
5539
5540CONST int md_short_jump_size = 4;
5541CONST int md_long_jump_size = 4;
5542
5543/* These should never be called on the arm */
5544void
5545md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
5546 char *ptr;
5547 addressT from_addr, to_addr;
5548 fragS *frag;
5549 symbolS *to_symbol;
5550{
5551 as_fatal ("md_create_long_jump\n");
5552}
5553
5554void
5555md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
5556 char *ptr;
5557 addressT from_addr, to_addr;
5558 fragS *frag;
5559 symbolS *to_symbol;
5560{
5561 as_fatal ("md_create_short_jump\n");
5562}
5563
5564int
5565md_estimate_size_before_relax (fragP, segtype)
5566 fragS *fragP;
5567 segT segtype;
5568{
5569 as_fatal ("md_estimate_size_before_relax\n");
5570 return (1);
5571}
5572
ccc30467 5573static void
338a7060
DE
5574output_inst (str)
5575 char *str;
5576{
5577 char *to = NULL;
5578
5579 if (inst.error)
5580 {
f520aaee 5581 as_bad (inst.error);
338a7060
DE
5582 return;
5583 }
5584
590c50d8 5585 to = frag_more (inst.size);
ccc30467 5586 if (thumb_mode && (inst.size > THUMB_SIZE))
590c50d8 5587 {
ccc30467
ILT
5588 assert (inst.size == (2 * THUMB_SIZE));
5589 md_number_to_chars (to, inst.instruction >> 16, THUMB_SIZE);
5590 md_number_to_chars (to + 2, inst.instruction, THUMB_SIZE);
590c50d8 5591 }
ccc30467
ILT
5592 else
5593 md_number_to_chars (to, inst.instruction, inst.size);
338a7060
DE
5594
5595 if (inst.reloc.type != BFD_RELOC_NONE)
5596 fix_new_arm (frag_now, to - frag_now->fr_literal,
590c50d8 5597 inst.size, &inst.reloc.exp, inst.reloc.pc_rel,
338a7060
DE
5598 inst.reloc.type);
5599
5600 return;
5601}
5602
5603void
5604md_assemble (str)
5605 char *str;
5606{
5607 char c;
338a7060
DE
5608 char *p, *q, *start;
5609
5610 /* Align the instruction */
5611 /* this may not be the right thing to do but ... */
5612 /* arm_align (2, 0); */
5613 listing_prev_line (); /* Defined in listing.h */
5614
5615 /* Align the previous label if needed */
5616 if (last_label_seen != NULL)
5617 {
5618 last_label_seen->sy_frag = frag_now;
c479fc62 5619 S_SET_VALUE (last_label_seen, (valueT) frag_now_fix ());
338a7060
DE
5620 S_SET_SEGMENT (last_label_seen, now_seg);
5621 }
5622
5623 memset (&inst, '\0', sizeof (inst));
5624 inst.reloc.type = BFD_RELOC_NONE;
5625
5626 if (*str == ' ')
5627 str++; /* Skip leading white space */
5628
5629 /* scan up to the end of the op-code, which must end in white space or
5630 end of string */
5631 for (start = p = str; *p != '\0'; p++)
5632 if (*p == ' ')
5633 break;
5634
5635 if (p == str)
5636 {
5637 as_bad ("No operator -- statement `%s'\n", str);
5638 return;
5639 }
5640
590c50d8 5641 if (thumb_mode)
338a7060 5642 {
590c50d8 5643 CONST struct thumb_opcode *opcode;
338a7060 5644
590c50d8
ILT
5645 c = *p;
5646 *p = '\0';
5647 opcode = (CONST struct thumb_opcode *) hash_find (arm_tops_hsh, str);
5648 *p = c;
5649 if (opcode)
5650 {
338a7060 5651 inst.instruction = opcode->value;
590c50d8
ILT
5652 inst.size = opcode->size;
5653 (*opcode->parms)(p);
5654 output_inst (start);
5655 return;
5656 }
5657 }
5658 else
5659 {
5660 CONST struct asm_opcode *opcode;
5661
5662 inst.size = INSN_SIZE;
5663 /* p now points to the end of the opcode, probably white space, but we
5664 have to break the opcode up in case it contains condionals and flags;
5665 keep trying with progressively smaller basic instructions until one
5666 matches, or we run out of opcode. */
5667 q = (p - str > LONGEST_INST) ? str + LONGEST_INST : p;
5668 for (; q != str; q--)
5669 {
5670 c = *q;
5671 *q = '\0';
5672 opcode = (CONST struct asm_opcode *) hash_find (arm_ops_hsh, str);
5673 *q = c;
5674 if (opcode && opcode->template)
338a7060 5675 {
590c50d8
ILT
5676 unsigned long flag_bits = 0;
5677 char *r;
5678
5679 /* Check that this instruction is supported for this CPU */
5680 if ((opcode->variants & cpu_variant) == 0)
5681 goto try_shorter;
5682
5683 inst.instruction = opcode->value;
5684 if (q == p) /* Just a simple opcode */
338a7060 5685 {
590c50d8
ILT
5686 if (opcode->comp_suffix != 0)
5687 as_bad ("Opcode `%s' must have suffix from <%s>\n", str,
5688 opcode->comp_suffix);
5689 else
5690 {
5691 inst.instruction |= COND_ALWAYS;
5692 (*opcode->parms)(q, 0);
5693 }
5694 output_inst (start);
5695 return;
338a7060 5696 }
338a7060 5697
590c50d8
ILT
5698 /* Now check for a conditional */
5699 r = q;
5700 if (p - r >= 2)
338a7060 5701 {
590c50d8
ILT
5702 CONST struct asm_cond *cond;
5703 char d = *(r + 2);
5704
5705 *(r + 2) = '\0';
5706 cond = (CONST struct asm_cond *) hash_find (arm_cond_hsh, r);
5707 *(r + 2) = d;
5708 if (cond)
5709 {
5710 if (cond->value == 0xf0000000)
5711 as_tsktsk (
5712"Warning: Use of the 'nv' conditional is deprecated\n");
338a7060 5713
590c50d8
ILT
5714 inst.instruction |= cond->value;
5715 r += 2;
5716 }
5717 else
5718 inst.instruction |= COND_ALWAYS;
338a7060
DE
5719 }
5720 else
5721 inst.instruction |= COND_ALWAYS;
338a7060 5722
590c50d8
ILT
5723 /* if there is a compulsory suffix, it should come here, before
5724 any optional flags. */
5725 if (opcode->comp_suffix)
338a7060 5726 {
590c50d8 5727 CONST char *s = opcode->comp_suffix;
338a7060 5728
590c50d8
ILT
5729 while (*s)
5730 {
5731 inst.suffix++;
5732 if (*r == *s)
5733 break;
5734 s++;
5735 }
338a7060 5736
590c50d8
ILT
5737 if (*s == '\0')
5738 {
5739 as_bad ("Opcode `%s' must have suffix from <%s>\n", str,
5740 opcode->comp_suffix);
5741 return;
5742 }
338a7060 5743
590c50d8
ILT
5744 r++;
5745 }
5746
5747 /* The remainder, if any should now be flags for the instruction;
5748 Scan these checking each one found with the opcode. */
5749 if (r != p)
5750 {
5751 char d;
5752 CONST struct asm_flg *flag = opcode->flags;
338a7060 5753
590c50d8 5754 if (flag)
338a7060 5755 {
590c50d8
ILT
5756 int flagno;
5757
5758 d = *p;
5759 *p = '\0';
5760
5761 for (flagno = 0; flag[flagno].template; flagno++)
338a7060 5762 {
590c50d8
ILT
5763 if (! strcmp (r, flag[flagno].template))
5764 {
5765 flag_bits |= flag[flagno].set_bits;
5766 break;
5767 }
338a7060 5768 }
338a7060 5769
590c50d8
ILT
5770 *p = d;
5771 if (! flag[flagno].template)
5772 goto try_shorter;
5773 }
5774 else
338a7060
DE
5775 goto try_shorter;
5776 }
590c50d8
ILT
5777
5778 (*opcode->parms) (p, flag_bits);
5779 output_inst (start);
5780 return;
338a7060
DE
5781 }
5782
590c50d8
ILT
5783 try_shorter:
5784 ;
338a7060 5785 }
338a7060 5786 }
590c50d8 5787
338a7060
DE
5788 /* It wasn't an instruction, but it might be a register alias of the form
5789 alias .req reg
5790 */
5791 q = p;
5792 while (*q == ' ')
5793 q++;
5794
5795 c = *p;
5796 *p = '\0';
5797
5798 if (*q && !strncmp (q, ".req ", 4))
5799 {
f520aaee
NC
5800 int reg;
5801 char * copy_of_str = str;
5802 char * r;
338a7060 5803
f520aaee
NC
5804 q += 4;
5805 while (*q == ' ')
5806 q++;
338a7060 5807
f520aaee
NC
5808 for (r = q; *r != '\0'; r++)
5809 if (*r == ' ')
5810 break;
5811
5812 if (r != q)
5813 {
5814 int regnum;
5815 char d = *r;
338a7060 5816
f520aaee
NC
5817 *r = '\0';
5818 regnum = arm_reg_parse (& q);
5819 *r = d;
338a7060 5820
f520aaee
NC
5821 reg = arm_reg_parse (& str);
5822
5823 if (reg == FAIL)
5824 {
338a7060
DE
5825 if (regnum != FAIL)
5826 {
5827 insert_reg_alias (str, regnum);
f520aaee
NC
5828 }
5829 else
5830 {
5831 as_warn ("register '%s' does not exist\n", q);
338a7060
DE
5832 }
5833 }
f520aaee
NC
5834 else if (regnum != FAIL)
5835 {
5836 if (reg != regnum)
5837 as_warn ("ignoring redefinition of register alias '%s'", copy_of_str );
5838
5839 /* Do not warn abpout redefinitions to the same alias. */
5840 }
5841 else
5842 as_warn ("ignoring redefinition of register alias '%s' to non-existant register '%s'",
5843 copy_of_str, q);
338a7060
DE
5844 }
5845 else
f520aaee
NC
5846 as_warn ("ignoring incomplete .req pseuso op");
5847
5848 *p = c;
5849 return;
338a7060
DE
5850 }
5851
5852 *p = c;
5853 as_bad ("bad instruction `%s'", start);
5854}
5855
5856/*
5857 * md_parse_option
5858 * Invocation line includes a switch not recognized by the base assembler.
5859 * See if it's a processor-specific option. These are:
5860 * Cpu variants, the arm part is optional:
5861 * -m[arm]1 Currently not supported.
5862 * -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
5863 * -m[arm]3 Arm 3 processor
c479fc62
JSC
5864 * -m[arm]6, Arm 6 processors
5865 * -m[arm]7[t][[d]m] Arm 7 processors
338a7060
DE
5866 * -mall All (except the ARM1)
5867 * FP variants:
5868 * -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
5869 * -mfpe-old (No float load/store multiples)
5870 * -mno-fpu Disable all floating point instructions
5871 * Run-time endian selection:
5872 * -EB big endian cpu
5873 * -EL little endian cpu
46686c78
NC
5874 * ARM Procedure Calling Standard:
5875 * -mapcs-32 32 bit APCS
5876 * -mapcs-26 26 bit APCS
f520aaee
NC
5877 * -mapcs-float Pass floats in float regs
5878 * -mapcs-reentrant Position independent code
5879 * -mthumb-interwork Code supports Arm/Thumb interworking
338a7060
DE
5880 */
5881
5882CONST char *md_shortopts = "m:";
46686c78
NC
5883struct option md_longopts[] =
5884{
338a7060
DE
5885#ifdef ARM_BI_ENDIAN
5886#define OPTION_EB (OPTION_MD_BASE + 0)
5887 {"EB", no_argument, NULL, OPTION_EB},
5888#define OPTION_EL (OPTION_MD_BASE + 1)
5889 {"EL", no_argument, NULL, OPTION_EL},
5890#endif
5891 {NULL, no_argument, NULL, 0}
5892};
590c50d8 5893size_t md_longopts_size = sizeof (md_longopts);
338a7060
DE
5894
5895int
5896md_parse_option (c, arg)
5897 int c;
5898 char *arg;
5899{
5900 char *str = arg;
5901
5902 switch (c)
5903 {
5904#ifdef ARM_BI_ENDIAN
5905 case OPTION_EB:
5906 target_big_endian = 1;
5907 break;
5908 case OPTION_EL:
5909 target_big_endian = 0;
5910 break;
5911#endif
5912
5913 case 'm':
5914 switch (*str)
5915 {
5916 case 'f':
5917 if (! strcmp (str, "fpa10"))
5918 cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_FPA10;
5919 else if (! strcmp (str, "fpa11"))
5920 cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_FPA11;
5921 else if (! strcmp (str, "fpe-old"))
5922 cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_CORE;
5923 else
5924 goto bad;
5925 break;
5926
5927 case 'n':
5928 if (! strcmp (str, "no-fpu"))
5929 cpu_variant &= ~FPU_ALL;
5930 break;
5931
590c50d8
ILT
5932 case 't':
5933 /* Limit assembler to generating only Thumb instructions: */
5934 if (! strcmp (str, "thumb"))
5935 {
5936 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_THUMB;
5937 cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_NONE;
5938 thumb_mode = 1;
5939 }
f520aaee
NC
5940 else if (! strcmp (str, "thumb-interwork"))
5941 {
5942 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_THUMB | ARM_ARCHv4;
5943#ifdef OBJ_COFF
5944 support_interwork = true;
5945#endif
5946 }
590c50d8
ILT
5947 else
5948 goto bad;
5949 break;
5950
338a7060
DE
5951 default:
5952 if (! strcmp (str, "all"))
5953 {
5954 cpu_variant = ARM_ALL | FPU_ALL;
5955 return 1;
5956 }
ccc30467 5957#ifdef OBJ_COFF
f520aaee 5958 if (! strncmp (str, "apcs-", 5))
46686c78 5959 {
f520aaee
NC
5960 /* GCC passes on all command line options starting "-mapcs-..."
5961 to us, so we must parse them here. */
5962
5963 str += 5;
5964
5965 if (! strcmp (str, "32"))
5966 {
5967 uses_apcs_26 = false;
5968 return 1;
5969 }
5970 else if (! strcmp (str, "26"))
5971 {
5972 uses_apcs_26 = true;
5973 return 1;
5974 }
5975 else if (! strcmp (str, "frame"))
5976 {
5977 /* Stack frames are being generated - does not affect
5978 linkage of code. */
5979 return 1;
5980 }
5981 else if (! strcmp (str, "stack-check"))
5982 {
5983 /* Stack checking is being performed - does not affect
5984 linkage, but does require that the functions
5985 __rt_stkovf_split_small and __rt_stkovf_split_big be
5986 present in the final link. */
5987
5988 return 1;
5989 }
5990 else if (! strcmp (str, "float"))
5991 {
5992 /* Floating point arguments are being passed in the floating
5993 point registers. This does affect linking, since this
5994 version of the APCS is incompatible with the version that
5995 passes floating points in the integer registers. */
5996
5997 uses_apcs_float = true;
5998 return 1;
5999 }
6000 else if (! strcmp (str, "reentrant"))
6001 {
6002 /* Reentrant code has been generated. This does affect
6003 linking, since there is no point in linking reentrant/
6004 position independent code with absolute position code. */
6005 pic_code = true;
6006 return 1;
6007 }
6008
6009 as_bad ("Unrecognised APCS switch -m%s", arg);
6010 return 0;
6011 }
ccc30467 6012#endif
338a7060
DE
6013 /* Strip off optional "arm" */
6014 if (! strncmp (str, "arm", 3))
6015 str += 3;
6016
6017 switch (*str)
6018 {
6019 case '1':
6020 if (! strcmp (str, "1"))
6021 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_1;
6022 else
6023 goto bad;
6024 break;
6025
6026 case '2':
6027 if (! strcmp (str, "2"))
6028 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_2;
6029 else if (! strcmp (str, "250"))
6030 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_250;
6031 else
6032 goto bad;
6033 break;
6034
6035 case '3':
6036 if (! strcmp (str, "3"))
6037 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_3;
6038 else
6039 goto bad;
6040 break;
6041
f520aaee
NC
6042 case 's':
6043 if (streq (str, "strongarm") || streq (str, "strongarm110"))
6044 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7 | ARM_ARCHv4 | ARM_LONGMUL;
6045 else
6046 goto bad;
6047 break;
6048
6049 case '8':
6050 if (streq (str, "8"))
6051 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7 | ARM_ARCHv4 | ARM_LONGMUL;
6052 else
6053 goto bad;
6054 break;
6055
338a7060
DE
6056 case '6':
6057 if (! strcmp (str, "6"))
6058 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_6;
6059 else
6060 goto bad;
6061 break;
6062
6063 case '7':
c479fc62
JSC
6064 str++; /* eat the '7' */
6065 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7;
6066 for (; *str; str++)
6067 {
f520aaee 6068 switch (* str)
c479fc62
JSC
6069 {
6070 case 't':
f520aaee 6071 cpu_variant |= (ARM_THUMB | ARM_ARCHv4);
c479fc62
JSC
6072 break;
6073
6074 case 'm':
6075 cpu_variant |= ARM_LONGMUL;
6076 break;
6077
f520aaee
NC
6078 case 'f': /* fe => fp enabled cpu. */
6079 if (str[1] == 'e')
6080 ++ str;
6081 else
6082 goto bad;
6083
6084 case 'c': /* Unknown */
c479fc62
JSC
6085 case 'd': /* debug */
6086 case 'i': /* embedded ice */
f520aaee 6087 /* Included for completeness in ARM processor naming. */
c479fc62
JSC
6088 break;
6089
6090 default:
6091 goto bad;
6092 }
6093 }
338a7060
DE
6094 break;
6095
46686c78
NC
6096 case 'v':
6097 /* Select variant based on architecture rather than processor */
6098 switch (*++str)
6099 {
6100 case '2':
6101 switch (*++str)
6102 {
6103 case 'a': cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_3; break;
6104 case 0: cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_2; break;
ccc30467 6105 default: as_bad ("Invalid architecture variant -m%s", arg); break;
46686c78
NC
6106 }
6107 break;
6108
6109 case '3':
6110 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7;
6111
6112 switch (*++str)
6113 {
6114 case 'm': cpu_variant |= ARM_LONGMUL; break;
6115 case 0: break;
ccc30467 6116 default: as_bad ("Invalid architecture variant -m%s", arg); break;
46686c78
NC
6117 }
6118 break;
6119
6120 case '4':
f520aaee 6121 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_ARCHv4;
46686c78
NC
6122
6123 switch (*++str)
6124 {
6125 case 't': cpu_variant |= ARM_THUMB; break;
6126 case 0: break;
ccc30467 6127 default: as_bad ("Invalid architecture variant -m%s", arg); break;
46686c78
NC
6128 }
6129 break;
6130
6131 default:
ccc30467 6132 as_bad ("Invalid architecture variant -m%s", arg);
46686c78
NC
6133 break;
6134 }
6135 break;
6136
338a7060
DE
6137 default:
6138 bad:
46686c78 6139 as_bad ("Invalid processor variant -m%s", arg);
338a7060
DE
6140 return 0;
6141 }
6142 }
6143 break;
6144
6145 default:
6146 return 0;
6147 }
6148
6149 return 1;
6150}
6151
6152void
6153md_show_usage (fp)
6154 FILE *fp;
6155{
6156 fprintf (fp,
f520aaee 6157"-m[arm][<processor name>] select processor variant\n\
46686c78
NC
6158-m[arm]v[2|2a|3|3m|4|4t] select architecture variant\n\
6159-mthumb\t\t\tonly allow Thumb instructions\n\
f520aaee 6160-mthumb-interwork\tmark the assembled code as supporting interworking\n\
338a7060
DE
6161-mall\t\t\tallow any instruction\n\
6162-mfpa10, -mfpa11\tselect floating point architecture\n\
6163-mfpe-old\t\tdon't allow floating-point multiple instructions\n\
ccc30467
ILT
6164-mno-fpu\t\tdon't allow any floating-point instructions.\n");
6165#ifdef OBJ_COFF
6166 fprintf (fp,
6167"-mapcs-32, -mapcs-26\tspecify which ARM Procedure Calling Standard is in use\n");
f520aaee
NC
6168 fprintf (fp,
6169"-mapcs-float\t\tfloating point args are passed in floating point regs\n");
6170 fprintf (fp,
6171"-mapcs-reentrant\tposition independent/reentrant code has been generated\n");
ccc30467 6172#endif
338a7060
DE
6173#ifdef ARM_BI_ENDIAN
6174 fprintf (fp,
6175"-EB\t\t\tassemble code for a big endian cpu\n\
6176-EL\t\t\tassemble code for a little endian cpu\n");
6177#endif
6178}
6179
6180/* We need to be able to fix up arbitrary expressions in some statements.
6181 This is so that we can handle symbols that are an arbitrary distance from
6182 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
6183 which returns part of an address in a form which will be valid for
6184 a data instruction. We do this by pushing the expression into a symbol
6185 in the expr_section, and creating a fix for that. */
6186
6187static void
6188fix_new_arm (frag, where, size, exp, pc_rel, reloc)
6189 fragS *frag;
6190 int where;
6191 short int size;
6192 expressionS *exp;
6193 int pc_rel;
6194 int reloc;
6195{
6196 fixS *new_fix;
590c50d8 6197 arm_fix_data *arm_data;
338a7060
DE
6198
6199 switch (exp->X_op)
6200 {
6201 case O_constant:
6202 case O_symbol:
6203 case O_add:
6204 case O_subtract:
6205 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
6206 break;
6207
6208 default:
590c50d8
ILT
6209 new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0,
6210 pc_rel, reloc);
338a7060
DE
6211 break;
6212 }
6213
590c50d8
ILT
6214 /* Mark whether the fix is to a THUMB instruction, or an ARM instruction */
6215 arm_data = (arm_fix_data *) obstack_alloc (&notes, sizeof (arm_fix_data));
6216 new_fix->tc_fix_data = (PTR) arm_data;
6217 arm_data->thumb_mode = thumb_mode;
6218
338a7060
DE
6219 return;
6220}
6221
6222/* A good place to do this, although this was probably not intended
6223 * for this kind of use. We need to dump the literal pool before
6224 * references are made to a null symbol pointer. */
6225void
ccc30467 6226arm_after_pass_hook ()
338a7060
DE
6227{
6228 if (current_poolP != NULL)
6229 {
6230 subseg_set (text_section, 0); /* Put it at the end of text section */
6231 s_ltorg (0);
6232 listing_prev_line ();
6233 }
6234}
6235
6236void
6237arm_start_line_hook ()
6238{
6239 last_label_seen = NULL;
6240}
6241
6242void
6243arm_frob_label (sym)
6244 symbolS *sym;
6245{
6246 last_label_seen = sym;
f520aaee
NC
6247 ARM_SET_THUMB (sym, thumb_mode);
6248 ARM_SET_INTERWORK (sym, support_interwork);
6249
6250 if (label_is_thumb_function_name)
6251 {
6252 /* When the address of a Thumb function is taken the bottom
6253 bit of that address should be set. This will allow
6254 interworking between Arm and Thumb functions to work
6255 correctly. */
6256
6257 THUMB_SET_FUNC (sym, 1);
6258
6259 label_is_thumb_function_name = false;
6260 }
ccc30467
ILT
6261}
6262
6263/* Adjust the symbol table. This marks Thumb symbols as distinct from
6264 ARM ones. */
6265
6266void
6267arm_adjust_symtab ()
6268{
7436e4de 6269#ifdef OBJ_COFF
ccc30467
ILT
6270 symbolS *sym;
6271
6272 for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
6273 {
f520aaee 6274 if (ARM_IS_THUMB (sym))
ccc30467 6275 {
f520aaee
NC
6276 if (THUMB_IS_FUNC (sym))
6277 {
6278 /* Mark the symbol as a Thumb function. */
6279 if ( S_GET_STORAGE_CLASS (sym) == C_STAT
6280 || S_GET_STORAGE_CLASS (sym) == C_LABEL) /* This can happen! */
6281 S_SET_STORAGE_CLASS (sym, C_THUMBSTATFUNC);
6282 else if (S_GET_STORAGE_CLASS (sym) == C_EXT)
6283 S_SET_STORAGE_CLASS (sym, C_THUMBEXTFUNC);
6284 else
6285 as_bad ("%s: unexpected function type: %d", S_GET_NAME (sym), S_GET_STORAGE_CLASS (sym));
6286 }
6287 else switch (S_GET_STORAGE_CLASS (sym))
ccc30467
ILT
6288 {
6289 case C_EXT:
6290 S_SET_STORAGE_CLASS (sym, C_THUMBEXT);
6291 break;
6292 case C_STAT:
6293 S_SET_STORAGE_CLASS (sym, C_THUMBSTAT);
6294 break;
6295 case C_LABEL:
6296 S_SET_STORAGE_CLASS (sym, C_THUMBLABEL);
6297 break;
6298 default: /* do nothing */
6299 break;
6300 }
6301 }
f520aaee
NC
6302
6303 if (ARM_IS_INTERWORK (sym))
6304 {
6305 coffsymbol(sym->bsym)->native->u.syment.n_flags = 0xFF;
6306 }
ccc30467 6307 }
7436e4de 6308#endif
338a7060 6309}
590c50d8
ILT
6310
6311int
6312arm_data_in_code ()
6313{
6314 if (thumb_mode && ! strncmp (input_line_pointer + 1, "data:", 5))
6315 {
6316 *input_line_pointer = '/';
6317 input_line_pointer += 5;
6318 *input_line_pointer = 0;
6319 return 1;
6320 }
6321 return 0;
6322}
6323
6324char *
6325arm_canonicalize_symbol_name (name)
6326 char *name;
6327{
6328 int len;
6329
6330 if (thumb_mode && (len = strlen (name)) > 5
6331 && ! strcmp (name + len - 5, "/data"))
6332 {
6333 *(name + len - 5) = 0;
6334 }
6335
6336 return name;
6337}
This page took 0.360164 seconds and 4 git commands to generate.