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