* xcofflink.c: More improvements, mostly to fix handling of
[deliverable/binutils-gdb.git] / gas / config / tc-arm.c
CommitLineData
338a7060
DE
1/* tc-arm.c All the arm specific stuff in one convenient, huge,
2 slow to compile, easy to find file.
3 Contributed by Richard Earnshaw (rwe@pegasus.esprit.ec.org)
4 Modified by David Taylor (dtaylor@armltd.co.uk)
5
6 Copyright (C) 1994, 1995 Free Software Foundation, Inc.
7
8 This file is part of GAS, the GNU Assembler.
9
10 GAS is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2, or (at your option)
13 any later version.
14
15 GAS is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with GAS; see the file COPYING. If not, write to
22 the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
23
24#include <ctype.h>
25#include <string.h>
26#define NO_RELOC 0
27#include "as.h"
28
29/* need TARGET_CPU */
30#include "config.h"
31#include "subsegs.h"
32#include "obstack.h"
33#include "symbols.h"
34#include "listing.h"
35
36/* ??? This is currently unused. */
37#ifdef __STDC__
38#define internalError() \
39 as_fatal ("ARM Internal Error, line %d, %s", __LINE__, __FILE__)
40#else
41#define internalError() as_fatal ("ARM Internal Error")
42#endif
43
44/* Types of processor to assemble for. */
45#define ARM_1 0x00000001
46#define ARM_2 0x00000002
47#define ARM_250 0x00000002 /* Checkme, should this be = ARM_3? */
48#define ARM_3 0x00000004
49#define ARM_6 0x00000008
50#define ARM_7 0x00000008
51#define ARM_7DM 0x00000010
52
53/* Some useful combinations: */
54#define ARM_ANY 0x00ffffff
55#define ARM_2UP 0x00fffffe
56#define ARM_ALL ARM_2UP /* Not arm1 only */
57#define ARM_3UP 0x00fffffc
58#define ARM_6UP 0x00fffff8
59#define ARM_LONGMUL 0x00000010 /* Don't know which will have this. */
60
61#define FPU_CORE 0x80000000
62#define FPU_FPA10 0x40000000
63#define FPU_FPA11 0x40000000
64#define FPU_NONE 0
65
66/* Some useful combinations */
67#define FPU_ALL 0xff000000 /* Note this is ~ARM_ANY */
68#define FPU_MEMMULTI 0x7f000000 /* Not fpu_core */
69
70#ifndef CPU_DEFAULT
71#define CPU_DEFAULT ARM_ALL
72#endif
73
74#ifndef FPU_DEFAULT
75#define FPU_DEFAULT FPU_ALL
76#endif
77
78unsigned long cpu_variant = CPU_DEFAULT | FPU_DEFAULT;
79
80/* This array holds the chars that always start a comment. If the
81 pre-processor is disabled, these aren't very useful */
82CONST char comment_chars[] = "@";
83
84/* This array holds the chars that only start a comment at the beginning of
85 a line. If the line seems to have the form '# 123 filename'
86 .line and .file directives will appear in the pre-processed output */
87/* Note that input_file.c hand checks for '#' at the beginning of the
88 first line of the input file. This is because the compiler outputs
89 #NO_APP at the beginning of its output. */
90/* Also note that comments like this one will always work. */
91CONST char line_comment_chars[] = "#";
92
93CONST char line_separator_chars[] = "";
94
95/* Chars that can be used to separate mant from exp in floating point nums */
96CONST char EXP_CHARS[] = "eE";
97
98/* Chars that mean this number is a floating point constant */
99/* As in 0f12.456 */
100/* or 0d1.2345e12 */
101
102CONST char FLT_CHARS[] = "rRsSfFdDxXeEpP";
103
104const int md_reloc_size = 8; /* Size of relocation record */
105
106struct arm_it
107{
108 CONST char *error;
109 unsigned long instruction;
110 int suffix;
111 struct
112 {
113 bfd_reloc_code_real_type type;
114 expressionS exp;
115 int pc_rel;
116 } reloc;
117};
118
119struct arm_it inst;
120
121struct asm_shift
122{
123 CONST char *template;
124 unsigned long value;
125};
126
127static CONST struct asm_shift shift[] =
128{
129 {"asl", 0},
130 {"lsl", 0},
131 {"lsr", 0x00000020},
132 {"asr", 0x00000040},
133 {"ror", 0x00000060},
134 {"rrx", 0x00000060},
135 {"ASL", 0},
136 {"LSL", 0},
137 {"LSR", 0x00000020},
138 {"ASR", 0x00000040},
139 {"ROR", 0x00000060},
140 {"RRX", 0x00000060}
141};
142
143#define NO_SHIFT_RESTRICT 1
144#define SHIFT_RESTRICT 0
145
146#define NUM_FLOAT_VALS 8
147
148CONST char *fp_const[] =
149{
150 "0.0", "1.0", "2.0", "3.0", "4.0", "5.0", "0.5", "10.0", 0
151};
152
153/* Number of littlenums required to hold an extended precision number */
154#define MAX_LITTLENUMS 6
155
156LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
157
158#define FAIL (-1)
159#define SUCCESS (0)
160
161#define SUFF_S 1
162#define SUFF_D 2
163#define SUFF_E 3
164#define SUFF_P 4
165
166#define CP_T_X 0x00008000
167#define CP_T_Y 0x00400000
168#define CP_T_Pre 0x01000000
169#define CP_T_UD 0x00800000
170#define CP_T_WB 0x00200000
171
172#define TRANS_BIT (0x00200000)
173
174struct asm_cond
175{
176 CONST char *template;
177 unsigned long value;
178};
179
180/* This is to save a hash look-up in the common case */
181#define COND_ALWAYS 0xe0000000
182
183static CONST struct asm_cond conds[] =
184{
185 {"eq", 0x00000000},
186 {"ne", 0x10000000},
187 {"cs", 0x20000000}, {"hs", 0x20000000},
188 {"cc", 0x30000000}, {"ul", 0x30000000}, {"lo", 0x30000000},
189 {"mi", 0x40000000},
190 {"pl", 0x50000000},
191 {"vs", 0x60000000},
192 {"vc", 0x70000000},
193 {"hi", 0x80000000},
194 {"ls", 0x90000000},
195 {"ge", 0xa0000000},
196 {"lt", 0xb0000000},
197 {"gt", 0xc0000000},
198 {"le", 0xd0000000},
199 {"al", 0xe0000000},
200 {"nv", 0xf0000000}
201};
202
203
204struct asm_flg
205{
206 CONST char *template; /* Basic flag string */
207 unsigned long set_bits; /* Bits to set */
208};
209
210static CONST struct asm_flg s_flag[] =
211{
212 {"s", 0x00100000},
213 {NULL, 0}
214};
215
216static CONST struct asm_flg ldst_flags[] =
217{
218 {"b", 0x00400000},
219 {"t", TRANS_BIT},
220 {"bt", 0x00400000 | TRANS_BIT},
221 {NULL, 0}
222};
223
224static CONST struct asm_flg byte_flag[] =
225{
226 {"b", 0x00400000},
227 {NULL, 0}
228};
229
230static CONST struct asm_flg cmp_flags[] =
231{
232 {"s", 0x00100000},
233 {"p", 0x0010f000},
234 {NULL, 0}
235};
236
237static CONST struct asm_flg ldm_flags[] =
238{
239 {"ed", 0x01800000},
240 {"fd", 0x00800000},
241 {"ea", 0x01000000},
242 {"fa", 0x08000000},
243 {"ib", 0x01800000},
244 {"ia", 0x00800000},
245 {"db", 0x01000000},
246 {"da", 0x08000000},
247 {NULL, 0}
248};
249
250static CONST struct asm_flg stm_flags[] =
251{
252 {"ed", 0x08000000},
253 {"fd", 0x01000000},
254 {"ea", 0x00800000},
255 {"fa", 0x01800000},
256 {"ib", 0x01800000},
257 {"ia", 0x00800000},
258 {"db", 0x01000000},
259 {"da", 0x08000000},
260 {NULL, 0}
261};
262
263static CONST struct asm_flg lfm_flags[] =
264{
265 {"fd", 0x00800000},
266 {"ea", 0x01000000},
267 {NULL, 0}
268};
269
270static CONST struct asm_flg sfm_flags[] =
271{
272 {"fd", 0x01000000},
273 {"ea", 0x00800000},
274 {NULL, 0}
275};
276
277static CONST struct asm_flg round_flags[] =
278{
279 {"p", 0x00000020},
280 {"m", 0x00000040},
281 {"z", 0x00000060},
282 {NULL, 0}
283};
284
285static CONST struct asm_flg except_flag[] =
286{
287 {"e", 0x00400000},
288 {NULL, 0}
289};
290
291static CONST struct asm_flg cplong_flag[] =
292{
293 {"l", 0x00400000},
294 {NULL, 0}
295};
296
297struct asm_psr
298{
299 CONST char *template;
300 unsigned long number;
301};
302
303#define PSR_ALL 0x00010000
304
305static CONST struct asm_psr psrs[] =
306{
307 /* Valid <psr>'s */
308 {"cpsr", 0},
309 {"cpsr_all", 0},
310 {"spsr", 1},
311 {"spsr_all", 1},
312
313 /* Valid <psrf>'s */
314 {"cpsr_flg", 2},
315 {"spsr_flg", 3}
316};
317
318/* Functions called by parser */
319/* ARM instructions */
320static void do_arit PARAMS ((char *operands, unsigned long flags));
321static void do_cmp PARAMS ((char *operands, unsigned long flags));
322static void do_mov PARAMS ((char *operands, unsigned long flags));
323static void do_ldst PARAMS ((char *operands, unsigned long flags));
324static void do_ldmstm PARAMS ((char *operands, unsigned long flags));
325static void do_branch PARAMS ((char *operands, unsigned long flags));
326static void do_swi PARAMS ((char *operands, unsigned long flags));
327/* Pseudo Op codes */
328static void do_adr PARAMS ((char *operands, unsigned long flags));
329static void do_nop PARAMS ((char *operands, unsigned long flags));
330/* ARM 2 */
331static void do_mul PARAMS ((char *operands, unsigned long flags));
332static void do_mla PARAMS ((char *operands, unsigned long flags));
333/* ARM 3 */
334static void do_swap PARAMS ((char *operands, unsigned long flags));
335/* ARM 6 */
336static void do_msr PARAMS ((char *operands, unsigned long flags));
337static void do_mrs PARAMS ((char *operands, unsigned long flags));
338/* ARM 7DM */
339static void do_mull PARAMS ((char *operands, unsigned long flags));
340/* Coprocessor Instructions */
341static void do_cdp PARAMS ((char *operands, unsigned long flags));
342static void do_lstc PARAMS ((char *operands, unsigned long flags));
343static void do_co_reg PARAMS ((char *operands, unsigned long flags));
344static void do_fp_ctrl PARAMS ((char *operands, unsigned long flags));
345static void do_fp_ldst PARAMS ((char *operands, unsigned long flags));
346static void do_fp_ldmstm PARAMS ((char *operands, unsigned long flags));
347static void do_fp_dyadic PARAMS ((char *operands, unsigned long flags));
348static void do_fp_monadic PARAMS ((char *operands, unsigned long flags));
349static void do_fp_cmp PARAMS ((char *operands, unsigned long flags));
350static void do_fp_from_reg PARAMS ((char *operands, unsigned long flags));
351static void do_fp_to_reg PARAMS ((char *operands, unsigned long flags));
352
353static void fix_new_arm PARAMS ((fragS *frag, int where,
354 short int size, expressionS *exp,
355 int pc_rel, int reloc));
356static int arm_reg_parse PARAMS ((char **ccp));
357static int arm_psr_parse PARAMS ((char **ccp));
358
359/* All instructions take 4 bytes in the object file */
360
361#define INSN_SIZE 4
362
363/* LONGEST_INST is the longest basic instruction name without conditions or
364 * flags.
365 * ARM7DM has 4 of length 5
366 */
367
368#define LONGEST_INST 5
369
370struct asm_opcode
371{
372 CONST char *template; /* Basic string to match */
373 unsigned long value; /* Basic instruction code */
374 CONST char *comp_suffix; /* Compulsory suffix that must follow conds */
375 CONST struct asm_flg *flags; /* Bits to toggle if flag 'n' set */
376 unsigned long variants; /* Which CPU variants this exists for */
377 void (*parms)(); /* Function to call to parse args */
378};
379
380static CONST struct asm_opcode insns[] =
381{
382/* ARM Instructions */
383 {"and", 0x00000000, NULL, s_flag, ARM_ANY, do_arit},
384 {"eor", 0x00200000, NULL, s_flag, ARM_ANY, do_arit},
385 {"sub", 0x00400000, NULL, s_flag, ARM_ANY, do_arit},
386 {"rsb", 0x00600000, NULL, s_flag, ARM_ANY, do_arit},
387 {"add", 0x00800000, NULL, s_flag, ARM_ANY, do_arit},
388 {"adc", 0x00a00000, NULL, s_flag, ARM_ANY, do_arit},
389 {"sbc", 0x00c00000, NULL, s_flag, ARM_ANY, do_arit},
390 {"rsc", 0x00e00000, NULL, s_flag, ARM_ANY, do_arit},
391 {"orr", 0x01800000, NULL, s_flag, ARM_ANY, do_arit},
392 {"bic", 0x01c00000, NULL, s_flag, ARM_ANY, do_arit},
393 {"tst", 0x01000000, NULL, cmp_flags, ARM_ANY, do_cmp},
394 {"teq", 0x01200000, NULL, cmp_flags, ARM_ANY, do_cmp},
395 {"cmp", 0x01400000, NULL, cmp_flags, ARM_ANY, do_cmp},
396 {"cmn", 0x01600000, NULL, cmp_flags, ARM_ANY, do_cmp},
397 {"mov", 0x01a00000, NULL, s_flag, ARM_ANY, do_mov},
398 {"mvn", 0x01e00000, NULL, s_flag, ARM_ANY, do_mov},
399 {"str", 0x04000000, NULL, ldst_flags, ARM_ANY, do_ldst},
400 {"ldr", 0x04100000, NULL, ldst_flags, ARM_ANY, do_ldst},
401 {"stm", 0x08000000, NULL, stm_flags, ARM_ANY, do_ldmstm},
402 {"ldm", 0x08100000, NULL, ldm_flags, ARM_ANY, do_ldmstm},
403 {"swi", 0x0f000000, NULL, NULL, ARM_ANY, do_swi},
404 {"bl", 0x0b000000, NULL, NULL, ARM_ANY, do_branch},
405 {"b", 0x0a000000, NULL, NULL, ARM_ANY, do_branch},
406
407/* Pseudo ops */
408 {"adr", 0x028f0000, NULL, NULL, ARM_ANY, do_adr},
409 {"nop", 0x01a00000, NULL, NULL, ARM_ANY, do_nop},
410
411/* ARM 2 multiplies */
412 {"mul", 0x00000090, NULL, s_flag, ARM_2UP, do_mul},
413 {"mla", 0x00200090, NULL, s_flag, ARM_2UP, do_mla},
414
415/* ARM 3 - swp instructions */
416 {"swp", 0x01000090, NULL, byte_flag, ARM_3UP, do_swap},
417
418/* ARM 6 Coprocessor instructions */
419 {"mrs", 0x010f0000, NULL, NULL, ARM_6UP, do_mrs},
420 {"msr", 0x0128f000, NULL, NULL, ARM_6UP, do_msr},
421
422/* ARM 7DM long multiplies - need signed/unsigned flags! */
423 {"smull", 0x00c00090, NULL, s_flag, ARM_LONGMUL, do_mull},
424 {"umull", 0x00800090, NULL, s_flag, ARM_LONGMUL, do_mull},
425 {"smlal", 0x00e00090, NULL, s_flag, ARM_LONGMUL, do_mull},
426 {"umlal", 0x00a00090, NULL, s_flag, ARM_LONGMUL, do_mull},
427
428/* Floating point instructions */
429 {"wfs", 0x0e200110, NULL, NULL, FPU_ALL, do_fp_ctrl},
430 {"rfs", 0x0e300110, NULL, NULL, FPU_ALL, do_fp_ctrl},
431 {"wfc", 0x0e400110, NULL, NULL, FPU_ALL, do_fp_ctrl},
432 {"rfc", 0x0e500110, NULL, NULL, FPU_ALL, do_fp_ctrl},
433 {"ldf", 0x0c100100, "sdep", NULL, FPU_ALL, do_fp_ldst},
434 {"stf", 0x0c000100, "sdep", NULL, FPU_ALL, do_fp_ldst},
435 {"lfm", 0x0c100200, NULL, lfm_flags, FPU_MEMMULTI, do_fp_ldmstm},
436 {"sfm", 0x0c000200, NULL, sfm_flags, FPU_MEMMULTI, do_fp_ldmstm},
437 {"mvf", 0x0e008100, "sde", round_flags, FPU_ALL, do_fp_monadic},
438 {"mnf", 0x0e108100, "sde", round_flags, FPU_ALL, do_fp_monadic},
439 {"abs", 0x0e208100, "sde", round_flags, FPU_ALL, do_fp_monadic},
440 {"rnd", 0x0e308100, "sde", round_flags, FPU_ALL, do_fp_monadic},
441 {"sqt", 0x0e408100, "sde", round_flags, FPU_ALL, do_fp_monadic},
442 {"log", 0x0e508100, "sde", round_flags, FPU_ALL, do_fp_monadic},
443 {"lgn", 0x0e608100, "sde", round_flags, FPU_ALL, do_fp_monadic},
444 {"exp", 0x0e708100, "sde", round_flags, FPU_ALL, do_fp_monadic},
445 {"sin", 0x0e808100, "sde", round_flags, FPU_ALL, do_fp_monadic},
446 {"cos", 0x0e908100, "sde", round_flags, FPU_ALL, do_fp_monadic},
447 {"tan", 0x0ea08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
448 {"asn", 0x0eb08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
449 {"acs", 0x0ec08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
450 {"atn", 0x0ed08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
451 {"urd", 0x0ee08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
452 {"nrm", 0x0ef08100, "sde", round_flags, FPU_ALL, do_fp_monadic},
453 {"adf", 0x0e000100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
454 {"suf", 0x0e200100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
455 {"rsf", 0x0e300100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
456 {"muf", 0x0e100100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
457 {"dvf", 0x0e400100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
458 {"rdf", 0x0e500100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
459 {"pow", 0x0e600100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
460 {"rpw", 0x0e700100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
461 {"rmf", 0x0e800100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
462 {"fml", 0x0e900100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
463 {"fdv", 0x0ea00100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
464 {"frd", 0x0eb00100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
465 {"pol", 0x0ec00100, "sde", round_flags, FPU_ALL, do_fp_dyadic},
466 {"cmf", 0x0e90f110, NULL, except_flag, FPU_ALL, do_fp_cmp},
467 {"cnf", 0x0eb0f110, NULL, except_flag, FPU_ALL, do_fp_cmp},
468/* The FPA10 data sheet suggests that the 'E' of cmfe/cnfe should not
469 be an optional suffix, but part of the instruction. To be compatible,
470 we accept either. */
471 {"cmfe", 0x0ed0f110, NULL, NULL, FPU_ALL, do_fp_cmp},
472 {"cnfe", 0x0ef0f110, NULL, NULL, FPU_ALL, do_fp_cmp},
473 {"flt", 0x0e000110, "sde", round_flags, FPU_ALL, do_fp_from_reg},
474 {"fix", 0x0e100110, NULL, round_flags, FPU_ALL, do_fp_to_reg},
475
476/* Generic copressor instructions */
477 {"cdp", 0x0e000000, NULL, NULL, ARM_ANY, do_cdp},
478 {"ldc", 0x0c100000, NULL, cplong_flag, ARM_ANY, do_lstc},
479 {"stc", 0x0c000000, NULL, cplong_flag, ARM_ANY, do_lstc},
480 {"mcr", 0x0e000010, NULL, NULL, ARM_ANY, do_co_reg},
481 {"mrc", 0x0e100010, NULL, NULL, ARM_ANY, do_co_reg},
482};
483
484/* defines for various bits that we will want to toggle */
485
486#define INST_IMMEDIATE 0x02000000
487#define OFFSET_REG 0x02000000
488#define SHIFT_BY_REG 0x00000010
489#define PRE_INDEX 0x01000000
490#define INDEX_UP 0x00800000
491#define WRITE_BACK 0x00200000
492#define MULTI_SET_PSR 0x00400000
493
494#define LITERAL_MASK 0xf000f000
495#define COND_MASK 0xf0000000
496#define OPCODE_MASK 0xfe1fffff
497#define DATA_OP_SHIFT 21
498
499/* Codes to distinguish the arithmetic instructions */
500
501#define OPCODE_AND 0
502#define OPCODE_EOR 1
503#define OPCODE_SUB 2
504#define OPCODE_RSB 3
505#define OPCODE_ADD 4
506#define OPCODE_ADC 5
507#define OPCODE_SBC 6
508#define OPCODE_RSC 7
509#define OPCODE_TST 8
510#define OPCODE_TEQ 9
511#define OPCODE_CMP 10
512#define OPCODE_CMN 11
513#define OPCODE_ORR 12
514#define OPCODE_MOV 13
515#define OPCODE_BIC 14
516#define OPCODE_MVN 15
517
518struct reg_entry
519{
520 CONST char *name;
521 int number;
522};
523
524#define int_register(reg) ((reg) >= 0 && (reg) <= 15)
525#define cp_register(reg) ((reg) >= 32 && (reg) <= 47)
526#define fp_register(reg) ((reg) >= 16 && (reg) <= 23)
527
528#define REG_PC 15
529
530/* These are the standard names; Users can add aliases with .req */
531static CONST struct reg_entry reg_table[] =
532{
533 /* Processor Register Numbers */
534 {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
535 {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
536 {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
537 {"r12", 12}, {"r13", 13}, {"r14", 14}, {"r15", REG_PC},
538 /* APCS conventions */
539 {"a1", 0}, {"a2", 1}, {"a3", 2}, {"a4", 3},
540 {"v1", 4}, {"v2", 5}, {"v3", 6}, {"v4", 7}, {"v5", 8},
541 {"v6", 9}, {"sb", 9}, {"v7", 10}, {"sl", 10},
542 {"fp", 11}, {"ip", 12}, {"sp", 13}, {"lr", 14}, {"pc", REG_PC},
543 /* FP Registers */
544 {"f0", 16}, {"f1", 17}, {"f2", 18}, {"f3", 19},
545 {"f4", 20}, {"f5", 21}, {"f6", 22}, {"f7", 23},
546 {"c0", 32}, {"c1", 33}, {"c2", 34}, {"c3", 35},
547 {"c4", 36}, {"c5", 37}, {"c6", 38}, {"c7", 39},
548 {"c8", 40}, {"c9", 41}, {"c10", 42}, {"c11", 43},
549 {"c12", 44}, {"c13", 45}, {"c14", 46}, {"c15", 47},
550 {"cr0", 32}, {"cr1", 33}, {"cr2", 34}, {"cr3", 35},
551 {"cr4", 36}, {"cr5", 37}, {"cr6", 38}, {"cr7", 39},
552 {"cr8", 40}, {"cr9", 41}, {"cr10", 42}, {"cr11", 43},
553 {"cr12", 44}, {"cr13", 45}, {"cr14", 46}, {"cr15", 47},
554 {NULL, 0}
555};
556
557static CONST char *bad_args = "Bad arguments to instruction";
558static CONST char *bad_pc = "r15 not allowed here";
559
560static struct hash_control *arm_ops_hsh = NULL;
561static struct hash_control *arm_cond_hsh = NULL;
562static struct hash_control *arm_shift_hsh = NULL;
563static struct hash_control *arm_reg_hsh = NULL;
564static struct hash_control *arm_psr_hsh = NULL;
565
566/* This table describes all the machine specific pseudo-ops the assembler
567 has to support. The fields are:
568 pseudo-op name without dot
569 function to call to execute this pseudo-op
570 Integer arg to pass to the function
571 */
572
573static void s_req PARAMS ((int));
574static void s_align PARAMS ((int));
575static void s_bss PARAMS ((int));
576static void s_even PARAMS ((int));
577static void s_ltorg PARAMS ((int));
578
579static int my_get_expression PARAMS ((expressionS *, char **));
580
581CONST pseudo_typeS md_pseudo_table[] =
582{
583 {"req", s_req, 0}, /* Never called becasue '.req' does not start line */
584 {"bss", s_bss, 0},
585 {"align", s_align, 0},
586 {"even", s_even, 0},
587 {"ltorg", s_ltorg, 0},
588 {"pool", s_ltorg, 0},
589 {"word", cons, 4},
590 {"extend", float_cons, 'x'},
591 {"ldouble", float_cons, 'x'},
592 {"packed", float_cons, 'p'},
593 {0, 0, 0}
594};
595
596/* Stuff needed to resolve the label ambiguity
597 As:
598 ...
599 label: <insn>
600 may differ from:
601 ...
602 label:
603 <insn>
604*/
605
606symbolS *last_label_seen;
607
608/* Literal stuff */
609
610#define MAX_LITERAL_POOL_SIZE 1024
611
612typedef struct literalS
613{
614 struct expressionS exp;
615 struct arm_it *inst;
616} literalT;
617
618literalT literals[MAX_LITERAL_POOL_SIZE];
619int next_literal_pool_place = 0; /* Next free entry in the pool */
620int lit_pool_num = 1; /* Next literal pool number */
621symbolS *current_poolP = NULL;
622symbolS *symbol_make_empty ();
623
624static int
625add_to_lit_pool ()
626{
627 if (current_poolP == NULL)
628 current_poolP = symbol_make_empty();
629
630 if (next_literal_pool_place > MAX_LITERAL_POOL_SIZE)
631 {
632 inst.error = "Literal Pool Overflow\n";
633 return FAIL;
634 }
635
636 literals[next_literal_pool_place].exp = inst.reloc.exp;
637 inst.reloc.exp.X_op = O_symbol;
638 inst.reloc.exp.X_add_number = (next_literal_pool_place++)*4-8;
639 inst.reloc.exp.X_add_symbol = current_poolP;
640
641 return SUCCESS;
642}
643
644/* Can't use symbol_new here, so have to create a symbol and them at
645 a later datete assign iot a value. Thats what these functions do */
646static void
647symbol_locate (symbolP, name, segment, valu, frag)
648 symbolS *symbolP;
649 CONST char *name; /* It is copied, the caller can modify */
650 segT segment; /* Segment identifier (SEG_<something>) */
651 valueT valu; /* Symbol value */
652 fragS *frag; /* Associated fragment */
653{
654 unsigned int name_length;
655 char *preserved_copy_of_name;
656
657 name_length = strlen (name) + 1; /* +1 for \0 */
658 obstack_grow (&notes, name, name_length);
659 preserved_copy_of_name = obstack_finish (&notes);
660#ifdef STRIP_UNDERSCORE
661 if (preserved_copy_of_name[0] == '_')
662 preserved_copy_of_name++;
663#endif
664
665#ifdef tc_canonicalize_symbol_name
666 preserved_copy_of_name =
667 tc_canonicalize_symbol_name (preserved_copy_of_name);
668#endif
669
670 S_SET_NAME (symbolP, preserved_copy_of_name);
671
672 S_SET_SEGMENT (symbolP, segment);
673 S_SET_VALUE (symbolP, valu);
674 symbol_clear_list_pointers(symbolP);
675
676 symbolP->sy_frag = frag;
677
678 /*
679 * Link to end of symbol chain.
680 */
681 {
682 extern int symbol_table_frozen;
683 if (symbol_table_frozen)
684 abort ();
685 }
686
687 symbol_append (symbolP, symbol_lastP, &symbol_rootP, &symbol_lastP);
688
689 obj_symbol_new_hook (symbolP);
690
691#ifdef tc_symbol_new_hook
692 tc_symbol_new_hook (symbolP);
693#endif
694
695#ifdef DEBUG_SYMS
696 verify_symbol_chain(symbol_rootP, symbol_lastP);
697#endif /* DEBUG_SYMS */
698}
699
700symbolS *
701symbol_make_empty ()
702{
703 symbolS *symbolP;
704
705 symbolP = (symbolS *) obstack_alloc (&notes, sizeof (symbolS));
706
707 /* symbol must be born in some fixed state. This seems as good as any. */
708 memset (symbolP, 0, sizeof (symbolS));
709
710#ifdef BFD_ASSEMBLER
711 symbolP->bsym = bfd_make_empty_symbol (stdoutput);
712 assert (symbolP->bsym != 0);
713 symbolP->bsym->udata.p = (PTR) symbolP;
714#endif
715
716 return symbolP;
717}
718
719/* Check that an immediate is valid, and if so, convert it to the right format
720 */
721
722/* OH, for a rotate instruction in C! */
723
724static int
725validate_immediate (val)
726 int val;
727{
728 unsigned int a = (unsigned int) val;
729 int i;
730
731 /* Do the easy (and most common ones) quickly */
732 for (i = 0; i <= 24; i += 2)
733 {
734 if ((a & (0xff << i)) == a)
735 return (int) (((32 - i) & 0x1e) << 7) | ((a >> i) & 0xff);
736 }
737
738 /* Now do the harder ones */
739 for (; i < 32; i += 2)
740 {
741 if ((a & ((0xff << i) | (0xff >> (32 - i)))) == a)
742 {
743 a = ((a >> i) & 0xff) | ((a << (32 - i)) & 0xff);
744 return (int) a | (((32 - i) >> 1) << 8);
745 }
746 }
747 return FAIL;
748}
749
750static int
751validate_offset_imm (val)
752 int val;
753{
754 if (val < -4095 || val > 4095)
755 as_bad ("bad immediate value for offset (%d)", val);
756 return val;
757}
758
759
760static void
761s_req (a)
762 int a;
763{
764 as_bad ("Invalid syntax for .req directive.");
765}
766
767static void
768s_bss (ignore)
769 int ignore;
770{
771 /* We don't support putting frags in the BSS segment, we fake it by
772 marking in_bss, then looking at s_skip for clues?.. */
773 subseg_set (bss_section, 0);
774 demand_empty_rest_of_line ();
775}
776
777static void
778s_even (ignore)
779 int ignore;
780{
781 if (!need_pass_2) /* Never make frag if expect extra pass. */
782 frag_align (1, 0);
783 record_alignment (now_seg, 1);
784 demand_empty_rest_of_line ();
785}
786
787static void
788s_ltorg (internal)
789 int internal;
790{
791 int lit_count = 0;
792 char sym_name[20];
793
794 if (current_poolP == NULL)
795 {
796 /* Nothing to do */
797 if (!internal)
798 as_tsktsk ("Nothing to put in the pool\n");
799 return;
800 }
801
802 /* Align pool as you have word accesses */
803 /* Only make a frag if we have to ... */
804 if (!need_pass_2)
805 frag_align (2, 0);
806
807 record_alignment (now_seg, 2);
808
809 if (internal)
810 as_tsktsk ("Inserting implicit pool at change of section");
811
812 sprintf (sym_name, "$$lit_\002%x", lit_pool_num++);
813
814 symbol_locate (current_poolP, sym_name, now_seg,
815 (valueT) ((char *)obstack_next_free (&frags)
816 - frag_now->fr_literal), frag_now);
817 symbol_table_insert (current_poolP);
818
819 while (lit_count < next_literal_pool_place)
820 /* First output the expression in the instruction to the pool */
821 emit_expr (&(literals[lit_count++].exp), 4); /* .word */
822
823 next_literal_pool_place = 0;
824 current_poolP = NULL;
825}
826
827static void
828arm_align (power, fill)
829 int power;
830 int fill;
831{
832 /* Only make a frag if we HAVE to ... */
833 if (power && !need_pass_2)
834 frag_align (power, fill);
835
836 record_alignment (now_seg, power);
837}
838
839static void
840s_align (unused) /* Same as s_align_ptwo but align 0 => align 2 */
841 int unused;
842{
843 register int temp;
844 register long temp_fill;
845 long max_alignment = 15;
846
847 temp = get_absolute_expression ();
848 if (temp > max_alignment)
849 as_bad ("Alignment too large: %d. assumed.", temp = max_alignment);
850 else if (temp < 0)
851 {
852 as_bad ("Alignment negative. 0 assumed.");
853 temp = 0;
854 }
855
856 if (*input_line_pointer == ',')
857 {
858 input_line_pointer++;
859 temp_fill = get_absolute_expression ();
860 }
861 else
862 temp_fill = 0;
863
864 if (!temp)
865 temp = 2;
866
867 /* Only make a frag if we HAVE to. . . */
868 if (temp && !need_pass_2)
869 frag_align (temp, (int) temp_fill);
870 demand_empty_rest_of_line ();
871
872 record_alignment (now_seg, temp);
873}
874
875static void
876end_of_line (str)
877 char *str;
878{
879 while (*str == ' ')
880 str++;
881
882 if (*str != '\0')
883 inst.error = "Garbage following instruction";
884}
885
886static int
887skip_past_comma (str)
888 char **str;
889{
890 char *p = *str, c;
891 int comma = 0;
892
893 while ((c = *p) == ' ' || c == ',')
894 {
895 p++;
896 if (c == ',' && comma++)
897 return FAIL;
898 }
899
900 if (c == '\0')
901 return FAIL;
902
903 *str = p;
904 return comma ? SUCCESS : FAIL;
905}
906
907/* A standard register must be given at this point. Shift is the place to
908 put it in the instruction. */
909
910static int
911reg_required_here (str, shift)
912 char **str;
913 int shift;
914{
915 int reg;
916 char *start = *str;
917
918 if ((reg = arm_reg_parse (str)) != FAIL && int_register (reg))
919 {
920 inst.instruction |= reg << shift;
921 return reg;
922 }
923
924 /* In the few cases where we might be able to accept something else
925 this error can be overridden */
926 inst.error = "Register expected";
927
928 /* Restore the start point, we may have got a reg of the wrong class. */
929 *str = start;
930 return FAIL;
931}
932
933static int
934psr_required_here (str, shift)
935 char **str;
936 int shift;
937{
938 int psr;
939 char *start = *str;
940
941 if ((psr = arm_psr_parse (str)) != FAIL && psr < 2)
942 {
943 if (psr == 1)
944 inst.instruction |= 1 << shift; /* Should be bit 22 */
945 return psr;
946 }
947
948 /* In the few cases where we might be able to accept something else
949 this error can be overridden */
950 inst.error = "<psr> expected";
951
952 /* Restore the start point. */
953 *str = start;
954 return FAIL;
955}
956
957static int
958psrf_required_here (str, shift)
959 char **str;
960 int shift;
961{
962 int psrf;
963 char *start = *str;
964
965 if ((psrf = arm_psr_parse (str)) != FAIL && psrf > 1)
966 {
967 if (psrf == 1 || psrf == 3)
968 inst.instruction |= 1 << shift; /* Should be bit 22 */
969 return psrf;
970 }
971
972 /* In the few cases where we might be able to accept something else
973 this error can be overridden */
974 inst.error = "<psrf> expected";
975
976 /* Restore the start point. */
977 *str = start;
978 return FAIL;
979}
980
981static int
982co_proc_number (str)
983 char **str;
984{
985 int processor, pchar;
986
987 while (**str == ' ')
988 (*str)++;
989
990 /* The data sheet seems to imply that just a number on its own is valid
991 here, but the RISC iX assembler seems to accept a prefix 'p'. We will
992 accept either. */
993 if (**str == 'p' || **str == 'P')
994 (*str)++;
995
996 pchar = *(*str)++;
997 if (pchar >= '0' && pchar <= '9')
998 {
999 processor = pchar - '0';
1000 if (**str >= '0' && **str <= '9')
1001 {
1002 processor = processor * 10 + *(*str)++ - '0';
1003 if (processor > 15)
1004 {
1005 inst.error = "Illegal co-processor number";
1006 return FAIL;
1007 }
1008 }
1009 }
1010 else
1011 {
1012 inst.error = "Bad or missing co-processor number";
1013 return FAIL;
1014 }
1015
1016 inst.instruction |= processor << 8;
1017 return SUCCESS;
1018}
1019
1020static int
1021cp_opc_expr (str, where, length)
1022 char **str;
1023 int where;
1024 int length;
1025{
1026 expressionS expr;
1027
1028 while (**str == ' ')
1029 (*str)++;
1030
1031 memset (&expr, '\0', sizeof (expr));
1032
1033 if (my_get_expression (&expr, str))
1034 return FAIL;
1035 if (expr.X_op != O_constant)
1036 {
1037 inst.error = "bad or missing expression";
1038 return FAIL;
1039 }
1040
1041 if ((expr.X_add_number & ((1 << length) - 1)) != expr.X_add_number)
1042 {
1043 inst.error = "immediate co-processor expression too large";
1044 return FAIL;
1045 }
1046
1047 inst.instruction |= expr.X_add_number << where;
1048 return SUCCESS;
1049}
1050
1051static int
1052cp_reg_required_here (str, where)
1053 char **str;
1054 int where;
1055{
1056 int reg;
1057 char *start = *str;
1058
1059 if ((reg = arm_reg_parse (str)) != FAIL && cp_register (reg))
1060 {
1061 reg &= 15;
1062 inst.instruction |= reg << where;
1063 return reg;
1064 }
1065
1066 /* In the few cases where we might be able to accept something else
1067 this error can be overridden */
1068 inst.error = "Co-processor register expected";
1069
1070 /* Restore the start point */
1071 *str = start;
1072 return FAIL;
1073}
1074
1075static int
1076fp_reg_required_here (str, where)
1077 char **str;
1078 int where;
1079{
1080 int reg;
1081 char *start = *str;
1082
1083 if ((reg = arm_reg_parse (str)) != FAIL && fp_register (reg))
1084 {
1085 reg &= 7;
1086 inst.instruction |= reg << where;
1087 return reg;
1088 }
1089
1090 /* In the few cases where we might be able to accept something else
1091 this error can be overridden */
1092 inst.error = "Floating point register expected";
1093
1094 /* Restore the start point */
1095 *str = start;
1096 return FAIL;
1097}
1098
1099static int
1100cp_address_offset (str)
1101 char **str;
1102{
1103 int offset;
1104
1105 while (**str == ' ')
1106 (*str)++;
1107
1108 if (**str != '#')
1109 {
1110 inst.error = "immediate expression expected";
1111 return FAIL;
1112 }
1113
1114 (*str)++;
1115 if (my_get_expression (&inst.reloc.exp, str))
1116 return FAIL;
1117 if (inst.reloc.exp.X_op == O_constant)
1118 {
1119 offset = inst.reloc.exp.X_add_number;
1120 if (offset & 3)
1121 {
1122 inst.error = "co-processor address must be word aligned";
1123 return FAIL;
1124 }
1125
1126 if (offset > 1023 || offset < -1023)
1127 {
1128 inst.error = "offset too large";
1129 return FAIL;
1130 }
1131
1132 if (offset >= 0)
1133 inst.instruction |= INDEX_UP;
1134 else
1135 offset = -offset;
1136
1137 inst.instruction |= offset >> 2;
1138 }
1139 else
1140 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
1141
1142 return SUCCESS;
1143}
1144
1145static int
1146cp_address_required_here (str)
1147 char **str;
1148{
1149 char *p = *str;
1150 int pre_inc = 0;
1151 int write_back = 0;
1152
1153 if (*p == '[')
1154 {
1155 int reg;
1156
1157 p++;
1158 while (*p == ' ')
1159 p++;
1160
1161 if ((reg = reg_required_here (&p, 16)) == FAIL)
1162 {
1163 inst.error = "Register required";
1164 return FAIL;
1165 }
1166
1167 while (*p == ' ')
1168 p++;
1169
1170 if (*p == ']')
1171 {
1172 p++;
1173 if (skip_past_comma (&p) == SUCCESS)
1174 {
1175 /* [Rn], #expr */
1176 write_back = WRITE_BACK;
1177 if (reg == REG_PC)
1178 {
1179 inst.error = "pc may not be used in post-increment";
1180 return FAIL;
1181 }
1182
1183 if (cp_address_offset (&p) == FAIL)
1184 return FAIL;
1185 }
1186 else
1187 pre_inc = PRE_INDEX | INDEX_UP;
1188 }
1189 else
1190 {
1191 /* '['Rn, #expr']'[!] */
1192
1193 if (skip_past_comma (&p) == FAIL)
1194 {
1195 inst.error = "pre-indexed expression expected";
1196 return FAIL;
1197 }
1198
1199 pre_inc = PRE_INDEX;
1200 if (cp_address_offset (&p) == FAIL)
1201 return FAIL;
1202
1203 while (*p == ' ')
1204 p++;
1205
1206 if (*p++ != ']')
1207 {
1208 inst.error = "missing ]";
1209 return FAIL;
1210 }
1211
1212 while (*p == ' ')
1213 p++;
1214
1215 if (*p == '!')
1216 {
1217 if (reg == REG_PC)
1218 {
1219 inst.error = "pc may not be used with write-back";
1220 return FAIL;
1221 }
1222
1223 p++;
1224 write_back = WRITE_BACK;
1225 }
1226 }
1227 }
1228 else
1229 {
1230 if (my_get_expression (&inst.reloc.exp, &p))
1231 return FAIL;
1232
1233 inst.reloc.type = BFD_RELOC_ARM_CP_OFF_IMM;
1234 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust */
1235 inst.reloc.pc_rel = 1;
1236 inst.instruction |= (REG_PC << 16);
1237 }
1238
1239 inst.instruction |= write_back | pre_inc;
1240 *str = p;
1241 return SUCCESS;
1242}
1243
1244static void
1245do_nop (str, flags)
1246 char *str;
1247 unsigned long flags;
1248{
1249 /* Do nothing really */
1250 inst.instruction |= flags; /* This is pointless */
1251 end_of_line (str);
1252 return;
1253}
1254
1255static void
1256do_mrs (str, flags)
1257 char *str;
1258 unsigned long flags;
1259{
1260 /* Only one syntax */
1261 while (*str == ' ')
1262 str++;
1263
1264 if (reg_required_here (&str, 12) == FAIL)
1265 {
1266 inst.error = bad_args;
1267 return;
1268 }
1269
1270 if (skip_past_comma (&str) == FAIL
1271 || psr_required_here (&str, 22) == FAIL)
1272 {
1273 inst.error = "<psr> expected";
1274 return;
1275 }
1276
1277 inst.instruction |= flags;
1278 end_of_line (str);
1279 return;
1280}
1281
1282static void
1283do_msr (str, flags)
1284 char *str;
1285 unsigned long flags;
1286{
1287 int psr, psrf, reg;
1288 /* Three possible forms: "<psr>, Rm", "<psrf>, Rm", "<psrf>, #expression" */
1289
1290 while (*str == ' ')
1291 str++;
1292
1293 if ((psr = psr_required_here (&str, 22)) != FAIL)
1294 {
1295 inst.instruction |= PSR_ALL;
1296 /* Sytax should be "<psr>, Rm" */
1297 if (skip_past_comma (&str) == FAIL
1298 || (reg = reg_required_here (&str, 0)) == FAIL)
1299 {
1300 inst.error = bad_args;
1301 return;
1302 }
1303 }
1304 else if ((psrf = psrf_required_here (&str, 22)) != FAIL)
1305 /* Syntax could be "<psrf>, rm", "<psrf>, #expression" */
1306 {
1307 if (skip_past_comma (&str) == FAIL)
1308 {
1309 inst.error = bad_args;
1310 return;
1311 }
1312 if ((reg = reg_required_here (&str, 0)) != FAIL)
1313 ;
1314 /* Immediate expression */
1315 else if (*(str++) == '#')
1316 {
1317 inst.error = NULL;
1318 if (my_get_expression (&inst.reloc.exp, &str))
1319 {
1320 inst.error = "Register or shift expression expected";
1321 return;
1322 }
1323
1324 if (inst.reloc.exp.X_add_symbol)
1325 {
1326 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
1327 inst.reloc.pc_rel = 0;
1328 }
1329 else
1330 {
1331 int value = validate_immediate (inst.reloc.exp.X_add_number);
1332 if (value == FAIL)
1333 {
1334 inst.error = "Invalid constant";
1335 return;
1336 }
1337
1338 inst.instruction |= value;
1339 }
1340
1341 flags |= INST_IMMEDIATE;
1342 }
1343 else
1344 {
1345 inst.error = "Error: the other";
1346 return;
1347 }
1348 }
1349 else
1350 {
1351 inst.error = bad_args;
1352 return;
1353 }
1354
1355 inst.error = NULL;
1356 inst.instruction |= flags;
1357 end_of_line (str);
1358 return;
1359}
1360
1361/* Long Multiply Parser
1362 UMULL RdLo, RdHi, Rm, Rs
1363 SMULL RdLo, RdHi, Rm, Rs
1364 UMLAL RdLo, RdHi, Rm, Rs
1365 SMLAL RdLo, RdHi, Rm, Rs
1366*/
1367static void
1368do_mull (str, flags)
1369 char *str;
1370 unsigned long flags;
1371{
1372 int rdlo, rdhi, rm, rs;
1373
1374 /* only one format "rdlo, rdhi, rm, rs" */
1375 while (*str == ' ')
1376 str++;
1377
1378 if ((rdlo = reg_required_here (&str, 12)) == FAIL)
1379 {
1380 inst.error = bad_args;
1381 return;
1382 }
1383
1384 if (skip_past_comma (&str) == FAIL
1385 || (rdhi = reg_required_here (&str, 16)) == FAIL)
1386 {
1387 inst.error = bad_args;
1388 return;
1389 }
1390
1391 if (skip_past_comma (&str) == FAIL
1392 || (rm = reg_required_here (&str, 0)) == FAIL)
1393 {
1394 inst.error = bad_args;
1395 return;
1396 }
1397
1398 /* rdhi, rdlo and rm must all be different */
1399 if (rdlo == rdhi || rdlo == rm || rdhi == rm)
1400 as_tsktsk ("rdhi, rdlo and rm must all be different");
1401
1402 if (skip_past_comma (&str) == FAIL
1403 || (rs = reg_required_here (&str, 8)) == FAIL)
1404 {
1405 inst.error = bad_args;
1406 return;
1407 }
1408
1409 if (rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC || rdhi == REG_PC)
1410 {
1411 inst.error = bad_pc;
1412 return;
1413 }
1414
1415 inst.instruction |= flags;
1416 end_of_line (str);
1417 return;
1418}
1419
1420static void
1421do_mul (str, flags)
1422 char *str;
1423 unsigned long flags;
1424{
1425 int rd, rm;
1426
1427 /* only one format "rd, rm, rs" */
1428 while (*str == ' ')
1429 str++;
1430
1431 if ((rd = reg_required_here (&str, 16)) == FAIL)
1432 {
1433 inst.error = bad_args;
1434 return;
1435 }
1436
1437 if (rd == REG_PC)
1438 {
1439 inst.error = bad_pc;
1440 return;
1441 }
1442
1443 if (skip_past_comma (&str) == FAIL
1444 || (rm = reg_required_here (&str, 0)) == FAIL)
1445 {
1446 inst.error = bad_args;
1447 return;
1448 }
1449
1450 if (rm == REG_PC)
1451 {
1452 inst.error = bad_pc;
1453 return;
1454 }
1455
1456 if (rm == rd)
1457 as_tsktsk ("rd and rm should be different in mul");
1458
1459 if (skip_past_comma (&str) == FAIL
1460 || (rm = reg_required_here (&str, 8)) == FAIL)
1461 {
1462 inst.error = bad_args;
1463 return;
1464 }
1465
1466 if (rm == REG_PC)
1467 {
1468 inst.error = bad_pc;
1469 return;
1470 }
1471
1472 inst.instruction |= flags;
1473 end_of_line (str);
1474 return;
1475}
1476
1477static void
1478do_mla (str, flags)
1479 char *str;
1480 unsigned long flags;
1481{
1482 int rd, rm;
1483
1484 /* only one format "rd, rm, rs, rn" */
1485 while (*str == ' ')
1486 str++;
1487
1488 if ((rd = reg_required_here (&str, 16)) == FAIL)
1489 {
1490 inst.error = bad_args;
1491 return;
1492 }
1493
1494 if (rd == REG_PC)
1495 {
1496 inst.error = bad_pc;
1497 return;
1498 }
1499
1500 if (skip_past_comma (&str) == FAIL
1501 || (rm = reg_required_here (&str, 0)) == FAIL)
1502 {
1503 inst.error = bad_args;
1504 return;
1505 }
1506
1507 if (rm == REG_PC)
1508 {
1509 inst.error = bad_pc;
1510 return;
1511 }
1512
1513 if (rm == rd)
1514 as_tsktsk ("rd and rm should be different in mla");
1515
1516 if (skip_past_comma (&str) == FAIL
1517 || (rd = reg_required_here (&str, 8)) == FAIL
1518 || skip_past_comma (&str) == FAIL
1519 || (rm = reg_required_here (&str, 12)) == FAIL)
1520 {
1521 inst.error = bad_args;
1522 return;
1523 }
1524
1525 if (rd == REG_PC || rm == REG_PC)
1526 {
1527 inst.error = bad_pc;
1528 return;
1529 }
1530
1531 inst.instruction |= flags;
1532 end_of_line (str);
1533 return;
1534}
1535
1536/* Returns the index into fp_values of a floating point number, or -1 if
1537 not in the table. */
1538static int
1539my_get_float_expression (str)
1540 char **str;
1541{
1542 LITTLENUM_TYPE words[MAX_LITTLENUMS];
1543 char *save_in;
1544 expressionS exp;
1545 int i, j;
1546
1547 memset (words, 0, MAX_LITTLENUMS * sizeof (LITTLENUM_TYPE));
1548 /* Look for a raw floating point number */
1549 if ((save_in = atof_ieee (*str, 'x', words)) != NULL
1550 && (is_end_of_line [(int)(*save_in)] || *save_in == '\0'))
1551 {
1552 for (i = 0; i < NUM_FLOAT_VALS; i++)
1553 {
1554 for (j = 0; j < MAX_LITTLENUMS; j++)
1555 {
1556 if (words[j] != fp_values[i][j])
1557 break;
1558 }
1559
1560 if (j == MAX_LITTLENUMS)
1561 {
1562 *str = save_in;
1563 return i;
1564 }
1565 }
1566 }
1567
1568 /* Try and parse a more complex expression, this will probably fail
1569 unless the code uses a floating point prefix (eg "0f") */
1570 save_in = input_line_pointer;
1571 input_line_pointer = *str;
1572 if (expression (&exp) == absolute_section
1573 && exp.X_op == O_big
1574 && exp.X_add_number < 0)
1575 {
1576 if (gen_to_words (words, 6, (long)15) == 0)
1577 {
1578 for (i = 0; i < NUM_FLOAT_VALS; i++)
1579 {
1580 for (j = 0; j < MAX_LITTLENUMS; j++)
1581 {
1582 if (words[j] != fp_values[i][j])
1583 break;
1584 }
1585
1586 if (j == MAX_LITTLENUMS)
1587 {
1588 *str = input_line_pointer;
1589 input_line_pointer = save_in;
1590 return i;
1591 }
1592 }
1593 }
1594 }
1595
1596 *str = input_line_pointer;
1597 input_line_pointer = save_in;
1598 return -1;
1599}
1600
1601/* Return true if anything in the expression is a bignum */
1602static int
1603walk_no_bignums (sp)
1604 symbolS *sp;
1605{
1606 if (sp->sy_value.X_op == O_big)
1607 return 1;
1608
1609 if (sp->sy_value.X_add_symbol)
1610 {
1611 return (walk_no_bignums (sp->sy_value.X_add_symbol)
1612 || (sp->sy_value.X_op_symbol
1613 && walk_no_bignums (sp->sy_value.X_op_symbol)));
1614 }
1615
1616 return 0;
1617}
1618
1619static int
1620my_get_expression (ep, str)
1621 expressionS *ep;
1622 char **str;
1623{
1624 char *save_in;
1625 segT seg;
1626
1627 save_in = input_line_pointer;
1628 input_line_pointer = *str;
1629 seg = expression (ep);
1630 if (seg != absolute_section
1631 && seg != text_section
1632 && seg != data_section
1633 && seg != bss_section
1634 && seg != undefined_section)
1635 {
1636 inst.error = "bad_segment";
1637 *str = input_line_pointer;
1638 input_line_pointer = save_in;
1639 return 1;
1640 }
1641
1642 /* Get rid of any bignums now, so that we don't generate an error for which
1643 we can't establish a line number later on. Big numbers are never valid
1644 in instructions, which is where is routine is always called. */
1645 if (ep->X_op == O_big
1646 || (ep->X_add_symbol
1647 && (walk_no_bignums (ep->X_add_symbol)
1648 || (ep->X_op_symbol
1649 && walk_no_bignums (ep->X_op_symbol)))))
1650 {
1651 inst.error = "Invalid constant";
1652 *str = input_line_pointer;
1653 input_line_pointer = save_in;
1654 return 1;
1655 }
1656
1657 *str = input_line_pointer;
1658 input_line_pointer = save_in;
1659 return 0;
1660}
1661
1662/* unrestrict should be one if <shift> <register> is permitted for this
1663 instruction */
1664
1665static int
1666decode_shift (str, unrestrict)
1667 char **str;
1668 int unrestrict;
1669{
1670 struct asm_shift *shft;
1671 char *p;
1672 char c;
1673
1674 while (**str == ' ')
1675 (*str)++;
1676
1677 for (p = *str; isalpha (*p); p++)
1678 ;
1679
1680 if (p == *str)
1681 {
1682 inst.error = "Shift expression expected";
1683 return FAIL;
1684 }
1685
1686 c = *p;
1687 *p = '\0';
1688 shft = (struct asm_shift *) hash_find (arm_shift_hsh, *str);
1689 *p = c;
1690 if (shft)
1691 {
1692 if (!strcmp (*str, "rrx"))
1693 {
1694 *str = p;
1695 inst.instruction |= shft->value;
1696 return SUCCESS;
1697 }
1698
1699 while (*p == ' ')
1700 p++;
1701
1702 if (unrestrict && reg_required_here (&p, 8) != FAIL)
1703 {
1704 inst.instruction |= shft->value | SHIFT_BY_REG;
1705 *str = p;
1706 return SUCCESS;
1707 }
1708 else if (*p == '#')
1709 {
1710 inst.error = NULL;
1711 p++;
1712 if (my_get_expression (&inst.reloc.exp, &p))
1713 return FAIL;
1714
1715 /* Validate some simple #expressions */
1716 if (! inst.reloc.exp.X_add_symbol)
1717 {
1718 int num = inst.reloc.exp.X_add_number;
1719 if (num < 0 || num > 32
1720 || (num == 32
1721 && (shft->value == 0 || shft->value == 0x60)))
1722 {
1723 inst.error = "Invalid immediate shift";
1724 return FAIL;
1725 }
1726
1727 /* Shifts of zero should be converted to lsl (which is zero)*/
1728 if (num == 0)
1729 {
1730 *str = p;
1731 return SUCCESS;
1732 }
1733
1734 /* Shifts of 32 are encoded as 0, for those shifts that
1735 support it. */
1736 if (num == 32)
1737 num = 0;
1738
1739 inst.instruction |= (num << 7) | shft->value;
1740 *str = p;
1741 return SUCCESS;
1742 }
1743
1744 inst.reloc.type = BFD_RELOC_ARM_SHIFT_IMM;
1745 inst.reloc.pc_rel = 0;
1746 inst.instruction |= shft->value;
1747 *str = p;
1748 return SUCCESS;
1749 }
1750 else
1751 {
1752 inst.error = unrestrict ? "shift requires register or #expression"
1753 : "shift requires #expression";
1754 *str = p;
1755 return FAIL;
1756 }
1757 }
1758
1759 inst.error = "Shift expression expected";
1760 return FAIL;
1761}
1762
1763/* Do those data_ops which can take a negative immediate constant */
1764/* by altering the instuction. A bit of a hack really */
1765/* MOV <-> MVN
1766 AND <-> BIC
1767 ADC <-> SBC
1768 by inverting the second operand, and
1769 ADD <-> SUB
1770 CMP <-> CMN
1771 by negating the second operand.
1772*/
1773static int
1774negate_data_op (instruction, value)
1775 unsigned long *instruction;
1776 unsigned long value;
1777{
1778 int op, new_inst;
1779 unsigned long negated, inverted;
1780
1781 negated = validate_immediate (-value);
1782 inverted = validate_immediate (~value);
1783
1784 op = (*instruction >> DATA_OP_SHIFT) & 0xf;
1785 switch (op)
1786 {
1787 /* First negates */
1788 case OPCODE_SUB: /* ADD <-> SUB */
1789 new_inst = OPCODE_ADD;
1790 value = negated;
1791 break;
1792
1793 case OPCODE_ADD:
1794 new_inst = OPCODE_SUB;
1795 value = negated;
1796 break;
1797
1798 case OPCODE_CMP: /* CMP <-> CMN */
1799 new_inst = OPCODE_CMN;
1800 value = negated;
1801 break;
1802
1803 case OPCODE_CMN:
1804 new_inst = OPCODE_CMP;
1805 value = negated;
1806 break;
1807
1808 /* Now Inverted ops */
1809 case OPCODE_MOV: /* MOV <-> MVN */
1810 new_inst = OPCODE_MVN;
1811 value = inverted;
1812 break;
1813
1814 case OPCODE_MVN:
1815 new_inst = OPCODE_MOV;
1816 value = inverted;
1817 break;
1818
1819 case OPCODE_AND: /* AND <-> BIC */
1820 new_inst = OPCODE_BIC;
1821 value = inverted;
1822 break;
1823
1824 case OPCODE_BIC:
1825 new_inst = OPCODE_AND;
1826 value = inverted;
1827 break;
1828
1829 case OPCODE_ADC: /* ADC <-> SBC */
1830 new_inst = OPCODE_SBC;
1831 value = inverted;
1832 break;
1833
1834 case OPCODE_SBC:
1835 new_inst = OPCODE_ADC;
1836 value = inverted;
1837 break;
1838
1839 /* We cannot do anything */
1840 default:
1841 return FAIL;
1842 }
1843
1844 if (value == FAIL)
1845 return FAIL;
1846
1847 *instruction &= OPCODE_MASK;
1848 *instruction |= new_inst << DATA_OP_SHIFT;
1849 return value;
1850}
1851
1852static int
1853data_op2 (str)
1854 char **str;
1855{
1856 int value;
1857 expressionS expr;
1858
1859 while (**str == ' ')
1860 (*str)++;
1861
1862 if (reg_required_here (str, 0) != FAIL)
1863 {
1864 if (skip_past_comma (str) == SUCCESS)
1865 {
1866 /* Shift operation on register */
1867 return decode_shift (str, NO_SHIFT_RESTRICT);
1868 }
1869 return SUCCESS;
1870 }
1871 else
1872 {
1873 /* Immediate expression */
1874 if (*((*str)++) == '#')
1875 {
1876 inst.error = NULL;
1877 if (my_get_expression (&inst.reloc.exp, str))
1878 return FAIL;
1879
1880 if (inst.reloc.exp.X_add_symbol)
1881 {
1882 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
1883 inst.reloc.pc_rel = 0;
1884 }
1885 else
1886 {
1887 if (skip_past_comma (str) == SUCCESS)
1888 {
1889 /* #x, y -- ie explicit rotation by Y */
1890 if (my_get_expression (&expr, str))
1891 return FAIL;
1892
1893 if (expr.X_op != O_constant)
1894 {
1895 inst.error = "Constant expression expected";
1896 return FAIL;
1897 }
1898
1899 /* Rotate must be a multiple of 2 */
1900 if (((unsigned) expr.X_add_number) > 30
1901 || (expr.X_add_number & 1) != 0
1902 || ((unsigned) inst.reloc.exp.X_add_number) > 255)
1903 {
1904 inst.error = "Invalid constant";
1905 return FAIL;
1906 }
1907 inst.instruction |= INST_IMMEDIATE;
1908 inst.instruction |= inst.reloc.exp.X_add_number;
1909 inst.instruction |= expr.X_add_number << 7;
1910 return SUCCESS;
1911 }
1912
1913 /* Implicit rotation, select a suitable one */
1914 value = validate_immediate (inst.reloc.exp.X_add_number);
1915
1916 if (value == FAIL)
1917 {
1918 /* Can't be done, perhaps the code reads something like
1919 "add Rd, Rn, #-n", where "sub Rd, Rn, #n" would be ok */
1920 if ((value = negate_data_op (&inst.instruction,
1921 inst.reloc.exp.X_add_number))
1922 == FAIL)
1923 {
1924 inst.error = "Invalid constant";
1925 return FAIL;
1926 }
1927 }
1928
1929 inst.instruction |= value;
1930 }
1931
1932 inst.instruction |= INST_IMMEDIATE;
1933 return SUCCESS;
1934 }
1935
1936 inst.error = "Register or shift expression expected";
1937 return FAIL;
1938 }
1939}
1940
1941static int
1942fp_op2 (str, flags)
1943 char **str;
1944 unsigned long flags;
1945{
1946 while (**str == ' ')
1947 (*str)++;
1948
1949 if (fp_reg_required_here (str, 0) != FAIL)
1950 return SUCCESS;
1951 else
1952 {
1953 /* Immediate expression */
1954 if (*((*str)++) == '#')
1955 {
1956 int i;
1957
1958 inst.error = NULL;
1959 while (**str == ' ')
1960 (*str)++;
1961
1962 /* First try and match exact strings, this is to guarantee that
1963 some formats will work even for cross assembly */
1964
1965 for (i = 0; fp_const[i]; i++)
1966 {
1967 if (strncmp (*str, fp_const[i], strlen (fp_const[i])) == 0)
1968 {
1969 char *start = *str;
1970
1971 *str += strlen (fp_const[i]);
1972 if (is_end_of_line[(int)**str] || **str == '\0')
1973 {
1974 inst.instruction |= i + 8;
1975 return SUCCESS;
1976 }
1977 *str = start;
1978 }
1979 }
1980
1981 /* Just because we didn't get a match doesn't mean that the
1982 constant isn't valid, just that it is in a format that we
1983 don't automatically recognize. Try parsing it with
1984 the standard expression routines. */
1985 if ((i = my_get_float_expression (str)) >= 0)
1986 {
1987 inst.instruction |= i + 8;
1988 return SUCCESS;
1989 }
1990
1991 inst.error = "Invalid floating point immediate expression";
1992 return FAIL;
1993 }
1994 inst.error = "Floating point register or immediate expression expected";
1995 return FAIL;
1996 }
1997}
1998
1999static void
2000do_arit (str, flags)
2001 char *str;
2002 unsigned long flags;
2003{
2004 while (*str == ' ')
2005 str++;
2006
2007 if (reg_required_here (&str, 12) == FAIL
2008 || skip_past_comma (&str) == FAIL
2009 || reg_required_here (&str, 16) == FAIL
2010 || skip_past_comma (&str) == FAIL
2011 || data_op2 (&str) == FAIL)
2012 {
2013 if (!inst.error)
2014 inst.error = bad_args;
2015 return;
2016 }
2017
2018 inst.instruction |= flags;
2019 end_of_line (str);
2020 return;
2021}
2022
2023static void
2024do_adr (str, flags)
2025 char *str;
2026 unsigned long flags;
2027{
2028 /* This is a pseudo-op of the form "adr rd, label" to be converted into
2029 a relative address of the form add rd, pc, #label-.-8 */
2030
2031 while (*str == ' ')
2032 str++;
2033
2034 if (reg_required_here (&str, 12) == FAIL
2035 || skip_past_comma (&str) == FAIL
2036 || my_get_expression (&inst.reloc.exp, &str))
2037 {
2038 if (!inst.error)
2039 inst.error = bad_args;
2040 return;
2041 }
2042 /* Frag hacking will turn this into a sub instruction if the offset turns
2043 out to be negative. */
2044 inst.reloc.type = BFD_RELOC_ARM_IMMEDIATE;
2045 inst.reloc.exp.X_add_number -= 8; /* PC relative adjust */
2046 inst.reloc.pc_rel = 1;
2047 inst.instruction |= flags;
2048 end_of_line (str);
2049 return;
2050}
2051
2052static void
2053do_cmp (str, flags)
2054 char *str;
2055 unsigned long flags;
2056{
2057 while (*str == ' ')
2058 str++;
2059
2060 if (reg_required_here (&str, 16) == FAIL)
2061 {
2062 if (!inst.error)
2063 inst.error = bad_args;
2064 return;
2065 }
2066
2067 if (skip_past_comma (&str) == FAIL
2068 || data_op2 (&str) == FAIL)
2069 {
2070 if (!inst.error)
2071 inst.error = bad_args;
2072 return;
2073 }
2074
2075 inst.instruction |= flags;
2076 if ((flags & 0x0000f000) == 0)
2077 inst.instruction |= 0x00100000;
2078
2079 end_of_line (str);
2080 return;
2081}
2082
2083static void
2084do_mov (str, flags)
2085 char *str;
2086 unsigned long flags;
2087{
2088 while (*str == ' ')
2089 str++;
2090
2091 if (reg_required_here (&str, 12) == FAIL)
2092 {
2093 if (!inst.error)
2094 inst.error = bad_args;
2095 return;
2096 }
2097
2098 if (skip_past_comma (&str) == FAIL
2099 || data_op2 (&str) == FAIL)
2100 {
2101 if (!inst.error)
2102 inst.error = bad_args;
2103 return;
2104 }
2105
2106 inst.instruction |= flags;
2107 end_of_line (str);
2108 return;
2109}
2110
2111static int
2112ldst_extend (str)
2113 char **str;
2114{
2115 int add = INDEX_UP;
2116
2117 switch (**str)
2118 {
2119 case '#':
2120 (*str)++;
2121 if (my_get_expression (&inst.reloc.exp, str))
2122 return FAIL;
2123
2124 if (inst.reloc.exp.X_op == O_constant)
2125 {
2126 int value = inst.reloc.exp.X_add_number;
2127
2128 if (value < -4095 || value > 4095)
2129 {
2130 inst.error = "address offset too large";
2131 return FAIL;
2132 }
2133
2134 if (value < 0)
2135 {
2136 value = -value;
2137 add = 0;
2138 }
2139
2140 inst.instruction |= add | value;
2141 }
2142 else
2143 {
2144 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
2145 inst.reloc.pc_rel = 0;
2146 }
2147 return SUCCESS;
2148
2149 case '-':
2150 add = 0; /* and fall through */
2151 case '+':
2152 (*str)++; /* and fall through */
2153 default:
2154 if (reg_required_here (str, 0) == FAIL)
2155 {
2156 inst.error = "Register expected";
2157 return FAIL;
2158 }
2159 inst.instruction |= add | OFFSET_REG;
2160 if (skip_past_comma (str) == SUCCESS)
2161 return decode_shift (str, SHIFT_RESTRICT);
2162 return SUCCESS;
2163 }
2164}
2165
2166static void
2167do_ldst (str, flags)
2168 char *str;
2169 unsigned long flags;
2170{
2171 int pre_inc = 0;
2172 int conflict_reg;
2173 int value;
2174
2175 while (*str == ' ')
2176 str++;
2177
2178 if ((conflict_reg = reg_required_here (&str, 12)) == FAIL)
2179 {
2180 if (!inst.error)
2181 inst.error = bad_args;
2182 return;
2183 }
2184
2185 if (skip_past_comma (&str) == FAIL)
2186 {
2187 inst.error = "Address expected";
2188 return;
2189 }
2190
2191 if (*str == '[')
2192 {
2193 int reg;
2194
2195 str++;
2196 while (*str == ' ')
2197 str++;
2198
2199 if ((reg = reg_required_here (&str, 16)) == FAIL)
2200 {
2201 inst.error = "Register required";
2202 return;
2203 }
2204
2205 conflict_reg = (((conflict_reg == reg)
2206 && (inst.instruction & 0x00100000))
2207 ? 1 : 0);
2208
2209 while (*str == ' ')
2210 str++;
2211
2212 if (*str == ']')
2213 {
2214 str++;
2215 if (skip_past_comma (&str) == SUCCESS)
2216 {
2217 /* [Rn],... (post inc) */
2218 if (ldst_extend (&str) == FAIL)
2219 return;
2220 if (conflict_reg)
2221 as_warn ("destination register same as write-back base\n");
2222 }
2223 else
2224 {
2225 /* [Rn] */
2226 flags |= INDEX_UP;
2227 }
2228 }
2229 else
2230 {
2231 /* [Rn,...] */
2232 if (skip_past_comma (&str) == FAIL)
2233 {
2234 inst.error = "pre-indexed expression expected";
2235 return;
2236 }
2237
2238 pre_inc = 1;
2239 if (ldst_extend (&str) == FAIL)
2240 return;
2241
2242 while (*str == ' ')
2243 str++;
2244
2245 if (*str++ != ']')
2246 {
2247 inst.error = "missing ]";
2248 return;
2249 }
2250
2251 while (*str == ' ')
2252 str++;
2253
2254 if (*str == '!')
2255 {
2256 if (conflict_reg)
2257 as_warn ("destination register same as write-back base\n");
2258 str++;
2259 inst.instruction |= WRITE_BACK;
2260 }
2261 }
2262 }
2263 else if (*str == '=')
2264 {
2265 /* Parse an "ldr Rd, =expr" instruction; this is another pseudo op */
2266 str++;
2267
2268 while (*str == ' ')
2269 str++;
2270
2271 if (my_get_expression (&inst.reloc.exp, &str))
2272 return;
2273
2274 if (inst.reloc.exp.X_op != O_constant
2275 && inst.reloc.exp.X_op != O_symbol)
2276 {
2277 inst.error = "Constant expression expected";
2278 return;
2279 }
2280
2281 if (inst.reloc.exp.X_op == O_constant
2282 && (value = validate_immediate(inst.reloc.exp.X_add_number)) != FAIL)
2283 {
2284 /* This can be done with a mov instruction */
2285 inst.instruction &= LITERAL_MASK;
2286 inst.instruction |= INST_IMMEDIATE | (OPCODE_MOV << DATA_OP_SHIFT);
2287 inst.instruction |= (flags & COND_MASK) | (value & 0xfff);
2288 end_of_line(str);
2289 return;
2290 }
2291 else
2292 {
2293 /* Insert into literal pool */
2294 if (add_to_lit_pool () == FAIL)
2295 {
2296 if (!inst.error)
2297 inst.error = "literal pool insertion failed\n";
2298 return;
2299 }
2300
2301 /* Change the instruction exp to point to the pool */
2302 inst.reloc.type = BFD_RELOC_ARM_LITERAL;
2303 inst.reloc.pc_rel = 1;
2304 inst.instruction |= (REG_PC << 16);
2305 pre_inc = 1;
2306 }
2307 }
2308 else
2309 {
2310 if (my_get_expression (&inst.reloc.exp, &str))
2311 return;
2312
2313 inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
2314 inst.reloc.exp.X_add_number -= 8; /* PC rel adjust */
2315 inst.reloc.pc_rel = 1;
2316 inst.instruction |= (REG_PC << 16);
2317 pre_inc = 1;
2318 }
2319
2320 if (pre_inc && (flags & TRANS_BIT))
2321 inst.error = "Pre-increment instruction with translate";
2322
2323 inst.instruction |= flags | (pre_inc ? PRE_INDEX : 0);
2324 end_of_line (str);
2325 return;
2326}
2327
2328static void
2329do_ldmstm (str, flags)
2330 char *str;
2331 unsigned long flags;
2332{
2333 int base_reg;
2334
2335 while (*str == ' ')
2336 str++;
2337
2338 if ((base_reg = reg_required_here (&str, 16)) == FAIL)
2339 {
2340 if (!inst.error)
2341 inst.error = bad_args;
2342 return;
2343 }
2344
2345 if (base_reg == REG_PC)
2346 {
2347 inst.error = "r15 not allowed as base register";
2348 return;
2349 }
2350
2351 while (*str == ' ')
2352 str++;
2353 if (*str == '!')
2354 {
2355 flags |= WRITE_BACK;
2356 str++;
2357 }
2358
2359 if (skip_past_comma (&str) == FAIL)
2360 {
2361 inst.error = bad_args;
2362 return;
2363 }
2364
2365 /* We come back here if we get ranges concatenated by '+' or '|' */
2366 another_range:
2367 if (*str == '{')
2368 {
2369 int in_range = 0;
2370 int cur_reg = -1;
2371
2372 str++;
2373 do
2374 {
2375 int reg;
2376
2377 while (*str == ' ')
2378 str++;
2379
2380 if ((reg = arm_reg_parse (&str)) == FAIL || !int_register (reg))
2381 {
2382 inst.error = "Register expected";
2383 return;
2384 }
2385
2386 if (in_range)
2387 {
2388 int i;
2389
2390 if (reg <= cur_reg)
2391 {
2392 inst.error = "Bad range in register list";
2393 return;
2394 }
2395
2396 for (i = cur_reg + 1; i < reg; i++)
2397 {
2398 if (flags & (1 << i))
2399 as_tsktsk
2400 ("Warning: Duplicated register (r%d) in register list",
2401 i);
2402 else
2403 flags |= 1 << i;
2404 }
2405 in_range = 0;
2406 }
2407
2408 if (flags & (1 << reg))
2409 as_tsktsk ("Warning: Duplicated register (r%d) in register list",
2410 reg);
2411 else if (reg <= cur_reg)
2412 as_tsktsk ("Warning: Register range not in ascending order");
2413
2414 flags |= 1 << reg;
2415 cur_reg = reg;
2416 } while (skip_past_comma (&str) != FAIL
2417 || (in_range = 1, *str++ == '-'));
2418 str--;
2419 while (*str == ' ')
2420 str++;
2421
2422 if (*str++ != '}')
2423 {
2424 inst.error = "Missing `}'";
2425 return;
2426 }
2427 }
2428 else
2429 {
2430 expressionS expr;
2431
2432 if (my_get_expression (&expr, &str))
2433 return;
2434
2435 if (expr.X_op == O_constant)
2436 {
2437 if (expr.X_add_number
2438 != (expr.X_add_number & 0x0000ffff))
2439 {
2440 inst.error = "invalid register mask";
2441 return;
2442 }
2443
2444 if ((flags & expr.X_add_number) != 0)
2445 {
2446 int regno = flags & expr.X_add_number;
2447
2448 regno &= -regno;
2449 regno = (1 << regno) - 1;
2450 as_tsktsk ("Warning: Duplicated register (r%d) in register list",
2451 regno);
2452 }
2453
2454 flags |= expr.X_add_number;
2455 }
2456 else
2457 {
2458 if (inst.reloc.type != 0)
2459 {
2460 inst.error = "expression too complex";
2461 return;
2462 }
2463
2464 memcpy (&inst.reloc.exp, &expr, sizeof (expressionS));
2465 inst.reloc.type = BFD_RELOC_ARM_MULTI;
2466 inst.reloc.pc_rel = 0;
2467 }
2468 }
2469
2470 while (*str == ' ')
2471 str++;
2472
2473 if (*str == '|' || *str == '+')
2474 {
2475 str++;
2476 goto another_range;
2477 }
2478
2479 if (*str == '^')
2480 {
2481 str++;
2482 flags |= MULTI_SET_PSR;
2483 }
2484 inst.instruction |= flags;
2485 end_of_line (str);
2486 return;
2487}
2488
2489static void
2490do_swi (str, flags)
2491 char *str;
2492 unsigned long flags;
2493{
2494 /* Allow optional leading '#'. */
2495 while (*str == ' ')
2496 str++;
2497 if (*str == '#')
2498 str++;
2499
2500 if (my_get_expression (&inst.reloc.exp, &str))
2501 return;
2502
2503 inst.reloc.type = BFD_RELOC_ARM_SWI;
2504 inst.reloc.pc_rel = 0;
2505 inst.instruction |= flags;
2506 end_of_line (str);
2507 return;
2508}
2509
2510static void
2511do_swap (str, flags)
2512 char *str;
2513 unsigned long flags;
2514{
2515 int reg;
2516
2517 while (*str == ' ')
2518 str++;
2519
2520 if ((reg = reg_required_here (&str, 12)) == FAIL)
2521 return;
2522
2523 if (reg == REG_PC)
2524 {
2525 inst.error = "r15 not allowed in swap";
2526 return;
2527 }
2528
2529 if (skip_past_comma (&str) == FAIL
2530 || (reg = reg_required_here (&str, 0)) == FAIL)
2531 {
2532 if (!inst.error)
2533 inst.error = bad_args;
2534 return;
2535 }
2536
2537 if (reg == REG_PC)
2538 {
2539 inst.error = "r15 not allowed in swap";
2540 return;
2541 }
2542
2543 if (skip_past_comma (&str) == FAIL
2544 || *str++ != '[')
2545 {
2546 inst.error = bad_args;
2547 return;
2548 }
2549
2550 while (*str == ' ')
2551 str++;
2552
2553 if ((reg = reg_required_here (&str, 16)) == FAIL)
2554 return;
2555
2556 if (reg == REG_PC)
2557 {
2558 inst.error = bad_pc;
2559 return;
2560 }
2561
2562 while (*str == ' ')
2563 str++;
2564
2565 if (*str++ != ']')
2566 {
2567 inst.error = "missing ]";
2568 return;
2569 }
2570
2571 inst.instruction |= flags;
2572 end_of_line (str);
2573 return;
2574}
2575
2576static void
2577do_branch (str, flags)
2578 char *str;
2579 unsigned long flags;
2580{
2581 if (my_get_expression (&inst.reloc.exp, &str))
2582 return;
2583 inst.reloc.type = BFD_RELOC_ARM_PCREL_BRANCH;
2584 inst.reloc.pc_rel = 1;
2585 inst.instruction |= flags | 0x00fffffe; /* PC-rel adjust */
2586 end_of_line (str);
2587 return;
2588}
2589
2590static void
2591do_cdp (str, flags)
2592 char *str;
2593 unsigned long flags;
2594{
2595 /* Co-processor data operation.
2596 Format: CDP{cond} CP#,<expr>,CRd,CRn,CRm{,<expr>} */
2597 while (*str == ' ')
2598 str++;
2599
2600 if (co_proc_number (&str) == FAIL)
2601 {
2602 if (!inst.error)
2603 inst.error = bad_args;
2604 return;
2605 }
2606
2607 if (skip_past_comma (&str) == FAIL
2608 || cp_opc_expr (&str, 20,4) == FAIL)
2609 {
2610 if (!inst.error)
2611 inst.error = bad_args;
2612 return;
2613 }
2614
2615 if (skip_past_comma (&str) == FAIL
2616 || cp_reg_required_here (&str, 12) == FAIL)
2617 {
2618 if (!inst.error)
2619 inst.error = bad_args;
2620 return;
2621 }
2622
2623 if (skip_past_comma (&str) == FAIL
2624 || cp_reg_required_here (&str, 16) == FAIL)
2625 {
2626 if (!inst.error)
2627 inst.error = bad_args;
2628 return;
2629 }
2630
2631 if (skip_past_comma (&str) == FAIL
2632 || cp_reg_required_here (&str, 0) == FAIL)
2633 {
2634 if (!inst.error)
2635 inst.error = bad_args;
2636 return;
2637 }
2638
2639 if (skip_past_comma (&str) == SUCCESS)
2640 {
2641 if (cp_opc_expr (&str, 5, 3) == FAIL)
2642 {
2643 if (!inst.error)
2644 inst.error = bad_args;
2645 return;
2646 }
2647 }
2648
2649 end_of_line (str);
2650 return;
2651}
2652
2653static void
2654do_lstc (str, flags)
2655 char *str;
2656 unsigned long flags;
2657{
2658 /* Co-processor register load/store.
2659 Format: <LDC|STC{cond}[L] CP#,CRd,<address> */
2660
2661 while (*str == ' ')
2662 str++;
2663
2664 if (co_proc_number (&str) == FAIL)
2665 {
2666 if (!inst.error)
2667 inst.error = bad_args;
2668 return;
2669 }
2670
2671 if (skip_past_comma (&str) == FAIL
2672 || cp_reg_required_here (&str, 12) == FAIL)
2673 {
2674 if (!inst.error)
2675 inst.error = bad_args;
2676 return;
2677 }
2678
2679 if (skip_past_comma (&str) == FAIL
2680 || cp_address_required_here (&str) == FAIL)
2681 {
2682 if (! inst.error)
2683 inst.error = bad_args;
2684 return;
2685 }
2686
2687 inst.instruction |= flags;
2688 end_of_line (str);
2689 return;
2690}
2691
2692static void
2693do_co_reg (str, flags)
2694 char *str;
2695 unsigned long flags;
2696{
2697 /* Co-processor register transfer.
2698 Format: <MCR|MRC>{cond} CP#,<expr1>,Rd,CRn,CRm{,<expr2>} */
2699
2700 while (*str == ' ')
2701 str++;
2702
2703 if (co_proc_number (&str) == FAIL)
2704 {
2705 if (!inst.error)
2706 inst.error = bad_args;
2707 return;
2708 }
2709
2710 if (skip_past_comma (&str) == FAIL
2711 || cp_opc_expr (&str, 21, 3) == FAIL)
2712 {
2713 if (!inst.error)
2714 inst.error = bad_args;
2715 return;
2716 }
2717
2718 if (skip_past_comma (&str) == FAIL
2719 || reg_required_here (&str, 12) == FAIL)
2720 {
2721 if (!inst.error)
2722 inst.error = bad_args;
2723 return;
2724 }
2725
2726 if (skip_past_comma (&str) == FAIL
2727 || cp_reg_required_here (&str, 16) == FAIL)
2728 {
2729 if (!inst.error)
2730 inst.error = bad_args;
2731 return;
2732 }
2733
2734 if (skip_past_comma (&str) == FAIL
2735 || cp_reg_required_here (&str, 0) == FAIL)
2736 {
2737 if (!inst.error)
2738 inst.error = bad_args;
2739 return;
2740 }
2741
2742 if (skip_past_comma (&str) == SUCCESS)
2743 {
2744 if (cp_opc_expr (&str, 5, 3) == FAIL)
2745 {
2746 if (!inst.error)
2747 inst.error = bad_args;
2748 return;
2749 }
2750 }
2751
2752 end_of_line (str);
2753 return;
2754}
2755
2756static void
2757do_fp_ctrl (str, flags)
2758 char *str;
2759 unsigned long flags;
2760{
2761 /* FP control registers.
2762 Format: <WFS|RFS|WFC|RFC>{cond} Rn */
2763
2764 while (*str == ' ')
2765 str++;
2766
2767 if (reg_required_here (&str, 12) == FAIL)
2768 {
2769 if (!inst.error)
2770 inst.error = bad_args;
2771 return;
2772 }
2773
2774 end_of_line (str);
2775 return;
2776}
2777
2778static void
2779do_fp_ldst (str, flags)
2780 char *str;
2781 unsigned long flags;
2782{
2783 while (*str == ' ')
2784 str++;
2785
2786 switch (inst.suffix)
2787 {
2788 case SUFF_S:
2789 break;
2790 case SUFF_D:
2791 inst.instruction |= CP_T_X;
2792 break;
2793 case SUFF_E:
2794 inst.instruction |= CP_T_Y;
2795 break;
2796 case SUFF_P:
2797 inst.instruction |= CP_T_X | CP_T_Y;
2798 break;
2799 default:
2800 abort ();
2801 }
2802
2803 if (fp_reg_required_here (&str, 12) == FAIL)
2804 {
2805 if (!inst.error)
2806 inst.error = bad_args;
2807 return;
2808 }
2809
2810 if (skip_past_comma (&str) == FAIL
2811 || cp_address_required_here (&str) == FAIL)
2812 {
2813 if (!inst.error)
2814 inst.error = bad_args;
2815 return;
2816 }
2817
2818 end_of_line (str);
2819}
2820
2821static void
2822do_fp_ldmstm (str, flags)
2823 char *str;
2824 unsigned long flags;
2825{
2826 int num_regs;
2827
2828 while (*str == ' ')
2829 str++;
2830
2831 if (fp_reg_required_here (&str, 12) == FAIL)
2832 {
2833 if (! inst.error)
2834 inst.error = bad_args;
2835 return;
2836 }
2837
2838 /* Get Number of registers to transfer */
2839 if (skip_past_comma (&str) == FAIL
2840 || my_get_expression (&inst.reloc.exp, &str))
2841 {
2842 if (! inst.error)
2843 inst.error = "constant expression expected";
2844 return;
2845 }
2846
2847 if (inst.reloc.exp.X_op != O_constant)
2848 {
2849 inst.error = "Constant value required for number of registers";
2850 return;
2851 }
2852
2853 num_regs = inst.reloc.exp.X_add_number;
2854
2855 if (num_regs < 1 || num_regs > 4)
2856 {
2857 inst.error = "number of registers must be in the range [1:4]";
2858 return;
2859 }
2860
2861 switch (num_regs)
2862 {
2863 case 1:
2864 inst.instruction |= CP_T_X;
2865 break;
2866 case 2:
2867 inst.instruction |= CP_T_Y;
2868 break;
2869 case 3:
2870 inst.instruction |= CP_T_Y | CP_T_X;
2871 break;
2872 case 4:
2873 break;
2874 default:
2875 abort ();
2876 }
2877
2878 if (flags)
2879 {
2880 int reg;
2881 int write_back;
2882 int offset;
2883
2884 /* The instruction specified "ea" or "fd", so we can only accept
2885 [Rn]{!}. The instruction does not really support stacking or
2886 unstacking, so we have to emulate these by setting appropriate
2887 bits and offsets. */
2888 if (skip_past_comma (&str) == FAIL
2889 || *str != '[')
2890 {
2891 if (! inst.error)
2892 inst.error = bad_args;
2893 return;
2894 }
2895
2896 str++;
2897 while (*str == ' ')
2898 str++;
2899
2900 if ((reg = reg_required_here (&str, 16)) == FAIL)
2901 {
2902 inst.error = "Register required";
2903 return;
2904 }
2905
2906 while (*str == ' ')
2907 str++;
2908
2909 if (*str != ']')
2910 {
2911 inst.error = bad_args;
2912 return;
2913 }
2914
2915 str++;
2916 if (*str == '!')
2917 {
2918 write_back = 1;
2919 str++;
2920 if (reg == REG_PC)
2921 {
2922 inst.error = "R15 not allowed as base register with write-back";
2923 return;
2924 }
2925 }
2926 else
2927 write_back = 0;
2928
2929 if (flags & CP_T_Pre)
2930 {
2931 /* Pre-decrement */
2932 offset = 3 * num_regs;
2933 if (write_back)
2934 flags |= CP_T_WB;
2935 }
2936 else
2937 {
2938 /* Post-increment */
2939 if (write_back)
2940 {
2941 flags |= CP_T_WB;
2942 offset = 3 * num_regs;
2943 }
2944 else
2945 {
2946 /* No write-back, so convert this into a standard pre-increment
2947 instruction -- aesthetically more pleasing. */
2948 flags = CP_T_Pre | CP_T_UD;
2949 offset = 0;
2950 }
2951 }
2952
2953 inst.instruction |= flags | offset;
2954 }
2955 else if (skip_past_comma (&str) == FAIL
2956 || cp_address_required_here (&str) == FAIL)
2957 {
2958 if (! inst.error)
2959 inst.error = bad_args;
2960 return;
2961 }
2962
2963 end_of_line (str);
2964}
2965
2966static void
2967do_fp_dyadic (str, flags)
2968 char *str;
2969 unsigned long flags;
2970{
2971 while (*str == ' ')
2972 str++;
2973
2974 switch (inst.suffix)
2975 {
2976 case SUFF_S:
2977 break;
2978 case SUFF_D:
2979 inst.instruction |= 0x00000080;
2980 break;
2981 case SUFF_E:
2982 inst.instruction |= 0x00080000;
2983 break;
2984 default:
2985 abort ();
2986 }
2987
2988 if (fp_reg_required_here (&str, 12) == FAIL)
2989 {
2990 if (! inst.error)
2991 inst.error = bad_args;
2992 return;
2993 }
2994
2995 if (skip_past_comma (&str) == FAIL
2996 || fp_reg_required_here (&str, 16) == FAIL)
2997 {
2998 if (! inst.error)
2999 inst.error = bad_args;
3000 return;
3001 }
3002
3003 if (skip_past_comma (&str) == FAIL
3004 || fp_op2 (&str) == FAIL)
3005 {
3006 if (! inst.error)
3007 inst.error = bad_args;
3008 return;
3009 }
3010
3011 inst.instruction |= flags;
3012 end_of_line (str);
3013 return;
3014}
3015
3016static void
3017do_fp_monadic (str, flags)
3018 char *str;
3019 unsigned long flags;
3020{
3021 while (*str == ' ')
3022 str++;
3023
3024 switch (inst.suffix)
3025 {
3026 case SUFF_S:
3027 break;
3028 case SUFF_D:
3029 inst.instruction |= 0x00000080;
3030 break;
3031 case SUFF_E:
3032 inst.instruction |= 0x00080000;
3033 break;
3034 default:
3035 abort ();
3036 }
3037
3038 if (fp_reg_required_here (&str, 12) == FAIL)
3039 {
3040 if (! inst.error)
3041 inst.error = bad_args;
3042 return;
3043 }
3044
3045 if (skip_past_comma (&str) == FAIL
3046 || fp_op2 (&str) == FAIL)
3047 {
3048 if (! inst.error)
3049 inst.error = bad_args;
3050 return;
3051 }
3052
3053 inst.instruction |= flags;
3054 end_of_line (str);
3055 return;
3056}
3057
3058static void
3059do_fp_cmp (str, flags)
3060 char *str;
3061 unsigned long flags;
3062{
3063 while (*str == ' ')
3064 str++;
3065
3066 if (fp_reg_required_here (&str, 16) == FAIL)
3067 {
3068 if (! inst.error)
3069 inst.error = bad_args;
3070 return;
3071 }
3072
3073 if (skip_past_comma (&str) == FAIL
3074 || fp_op2 (&str) == FAIL)
3075 {
3076 if (! inst.error)
3077 inst.error = bad_args;
3078 return;
3079 }
3080
3081 inst.instruction |= flags;
3082 end_of_line (str);
3083 return;
3084}
3085
3086static void
3087do_fp_from_reg (str, flags)
3088 char *str;
3089 unsigned long flags;
3090{
3091 while (*str == ' ')
3092 str++;
3093
3094 switch (inst.suffix)
3095 {
3096 case SUFF_S:
3097 break;
3098 case SUFF_D:
3099 inst.instruction |= 0x00000080;
3100 break;
3101 case SUFF_E:
3102 inst.instruction |= 0x00080000;
3103 break;
3104 default:
3105 abort ();
3106 }
3107
3108 if (fp_reg_required_here (&str, 16) == FAIL)
3109 {
3110 if (! inst.error)
3111 inst.error = bad_args;
3112 return;
3113 }
3114
3115 if (skip_past_comma (&str) == FAIL
3116 || reg_required_here (&str, 12) == FAIL)
3117 {
3118 if (! inst.error)
3119 inst.error = bad_args;
3120 return;
3121 }
3122
3123 inst.instruction |= flags;
3124 end_of_line (str);
3125 return;
3126}
3127
3128static void
3129do_fp_to_reg (str, flags)
3130 char *str;
3131 unsigned long flags;
3132{
3133 while (*str == ' ')
3134 str++;
3135
3136 if (reg_required_here (&str, 12) == FAIL)
3137 {
3138 if (! inst.error)
3139 inst.error = bad_args;
3140 return;
3141 }
3142
3143 if (skip_past_comma (&str) == FAIL
3144 || fp_reg_required_here (&str, 0) == FAIL)
3145 {
3146 if (! inst.error)
3147 inst.error = bad_args;
3148 return;
3149 }
3150
3151 inst.instruction |= flags;
3152 end_of_line (str);
3153 return;
3154}
3155
3156static void
3157insert_reg (entry)
3158 int entry;
3159{
3160 int len = strlen (reg_table[entry].name) + 2;
3161 char *buf = (char *) xmalloc (len);
3162 char *buf2 = (char *) xmalloc (len);
3163 int i = 0;
3164
3165#ifdef REGISTER_PREFIX
3166 buf[i++] = REGISTER_PREFIX;
3167#endif
3168
3169 strcpy (buf + i, reg_table[entry].name);
3170
3171 for (i = 0; buf[i]; i++)
3172 buf2[i] = islower (buf[i]) ? toupper (buf[i]) : buf[i];
3173
3174 buf2[i] = '\0';
3175
3176 hash_insert (arm_reg_hsh, buf, (PTR) &reg_table[entry]);
3177 hash_insert (arm_reg_hsh, buf2, (PTR) &reg_table[entry]);
3178}
3179
3180static void
3181insert_reg_alias (str, regnum)
3182 char *str;
3183 int regnum;
3184{
3185 struct reg_entry *new =
3186 (struct reg_entry *)xmalloc (sizeof (struct reg_entry));
3187 char *name = xmalloc (strlen (str) + 1);
3188 strcpy (name, str);
3189
3190 new->name = name;
3191 new->number = regnum;
3192
3193 hash_insert (arm_reg_hsh, name, (PTR) new);
3194}
3195
3196static void
3197set_constant_flonums ()
3198{
3199 int i;
3200
3201 for (i = 0; i < NUM_FLOAT_VALS; i++)
3202 if (atof_ieee ((char *)fp_const[i], 'x', fp_values[i]) == NULL)
3203 abort ();
3204}
3205
3206void
3207md_begin ()
3208{
3209 int i;
3210
3211 if ((arm_ops_hsh = hash_new ()) == NULL
3212 || (arm_cond_hsh = hash_new ()) == NULL
3213 || (arm_shift_hsh = hash_new ()) == NULL
3214 || (arm_reg_hsh = hash_new ()) == NULL
3215 || (arm_psr_hsh = hash_new ()) == NULL)
3216 as_fatal ("Virtual memory exhausted");
3217
3218 for (i = 0; i < sizeof (insns) / sizeof (struct asm_opcode); i++)
3219 hash_insert (arm_ops_hsh, insns[i].template, (PTR) (insns + i));
3220 for (i = 0; i < sizeof (conds) / sizeof (struct asm_cond); i++)
3221 hash_insert (arm_cond_hsh, conds[i].template, (PTR) (conds + i));
3222 for (i = 0; i < sizeof (shift) / sizeof (struct asm_shift); i++)
3223 hash_insert (arm_shift_hsh, shift[i].template, (PTR) (shift + i));
3224 for (i = 0; i < sizeof (psrs) / sizeof (struct asm_psr); i++)
3225 hash_insert (arm_psr_hsh, psrs[i].template, (PTR) (psrs + i));
3226
3227 for (i = 0; reg_table[i].name; i++)
3228 insert_reg (i);
3229
3230 set_constant_flonums ();
3231}
3232
3233/* This funciton is called once, before the assembler exits. It is
3234 supposed to do any final cleanup for this part of the assembler.
3235 */
3236void
3237md_end ()
3238{
3239}
3240
3241/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
3242 for use in the a.out file, and stores them in the array pointed to by buf.
3243 This knows about the endian-ness of the target machine and does
3244 THE RIGHT THING, whatever it is. Possible values for n are 1 (byte)
3245 2 (short) and 4 (long) Floating numbers are put out as a series of
3246 LITTLENUMS (shorts, here at least)
3247 */
3248void
3249md_number_to_chars (buf, val, n)
3250 char *buf;
3251 valueT val;
3252 int n;
3253{
3254 if (target_big_endian)
3255 number_to_chars_bigendian (buf, val, n);
3256 else
3257 number_to_chars_littleendian (buf, val, n);
3258}
3259
3260static valueT
3261md_chars_to_number (buf, n)
3262 char *buf;
3263 int n;
3264{
3265 valueT result = 0;
3266 unsigned char *where = (unsigned char *) buf;
3267
3268 if (target_big_endian)
3269 {
3270 while (n--)
3271 {
3272 result <<= 8;
3273 result |= (*where++ & 255);
3274 }
3275 }
3276 else
3277 {
3278 while (n--)
3279 {
3280 result <<= 8;
3281 result |= (where[n] & 255);
3282 }
3283 }
3284
3285 return result;
3286}
3287
3288/*
3289 This is identical to the md_atof in m68k.c. I think this is right,
3290 but I'm not sure.
3291
3292 Turn a string in input_line_pointer into a floating point constant of type
3293 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
3294 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
3295 */
3296char *
3297md_atof (type, litP, sizeP)
3298 char type;
3299 char *litP;
3300 int *sizeP;
3301{
3302 int prec;
3303 LITTLENUM_TYPE words[MAX_LITTLENUMS];
3304 LITTLENUM_TYPE *wordP;
3305 char *t;
3306 char *atof_ieee ();
3307
3308 switch (type)
3309 {
3310
3311 case 'f':
3312 case 'F':
3313 case 's':
3314 case 'S':
3315 prec = 2;
3316 break;
3317
3318 case 'd':
3319 case 'D':
3320 case 'r':
3321 case 'R':
3322 prec = 4;
3323 break;
3324
3325 case 'x':
3326 case 'X':
3327 prec = 6;
3328 break;
3329
3330 case 'p':
3331 case 'P':
3332 prec = 6;
3333 break;
3334
3335 default:
3336 *sizeP = 0;
3337 return "Bad call to MD_ATOF()";
3338 }
3339 t = atof_ieee (input_line_pointer, type, words);
3340 if (t)
3341 input_line_pointer = t;
3342 *sizeP = prec * sizeof (LITTLENUM_TYPE);
3343 for (wordP = words; prec--;)
3344 {
3345 fprintf (stderr, "%02x 02x ", ((*wordP) >> 8) & 255, (*wordP) & 255);
3346 md_number_to_chars (litP, (valueT) (*wordP++), sizeof (LITTLENUM_TYPE));
3347 litP += sizeof (LITTLENUM_TYPE);
3348 }
3349 fprintf (stderr, "\n");
3350 return 0;
3351}
3352
3353/* We have already put the pipeline compensation in the instruction */
3354
3355long
3356md_pcrel_from (fixP)
3357 fixS *fixP;
3358{
3359 if (fixP->fx_addsy && S_GET_SEGMENT (fixP->fx_addsy) == undefined_section
3360 && fixP->fx_subsy == NULL)
3361 return 0; /* HACK */
3362
3363 return fixP->fx_where + fixP->fx_frag->fr_address;
3364}
3365
3366/* Round up a section size to the appropriate boundary. */
3367valueT
3368md_section_align (segment, size)
3369 segT segment;
3370 valueT size;
3371{
3372 /* Round all sects to multiple of 4 */
3373 return (size + 3) & ~3;
3374}
3375
3376/* We have no need to default values of symbols. */
3377
3378/* ARGSUSED */
3379symbolS *
3380md_undefined_symbol (name)
3381 char *name;
3382{
3383 return 0;
3384}
3385
3386/* arm_reg_parse () := if it looks like a register, return its token and
3387 advance the pointer. */
3388
3389static int
3390arm_reg_parse (ccp)
3391 register char **ccp;
3392{
3393 char *start = *ccp;
3394 char c;
3395 char *p;
3396 struct reg_entry *reg;
3397
3398#ifdef REGISTER_PREFIX
3399 if (*start != REGISTER_PREFIX)
3400 return FAIL;
3401 p = start + 1;
3402#else
3403 p = start;
3404#ifdef OPTIONAL_REGISTER_PREFIX
3405 if (*p == OPTIONAL_REGISTER_PREFIX)
3406 p++, start++;
3407#endif
3408#endif
3409 if (!isalpha (*p) || !is_name_beginner (*p))
3410 return FAIL;
3411
3412 c = *p++;
3413 while (isalpha (c) || isdigit (c) || c == '_')
3414 c = *p++;
3415
3416 *--p = 0;
3417 reg = (struct reg_entry *) hash_find (arm_reg_hsh, start);
3418 *p = c;
3419
3420 if (reg)
3421 {
3422 *ccp = p;
3423 return reg->number;
3424 }
3425
3426 return FAIL;
3427}
3428
3429static int
3430arm_psr_parse (ccp)
3431 register char **ccp;
3432{
3433 char *start = *ccp;
3434 char c, *p;
3435 CONST struct asm_psr *psr;
3436
3437 p = start;
3438 c = *p++;
3439 while (isalpha (c) || c == '_')
3440 c = *p++;
3441
3442 *--p = 0;
3443 psr = (CONST struct asm_psr *) hash_find (arm_psr_hsh, start);
3444 *p = c;
3445
3446 if (psr)
3447 {
3448 *ccp = p;
3449 return psr->number;
3450 }
3451
3452 return FAIL;
3453}
3454
3455int
3456md_apply_fix (fixP, val)
3457 fixS *fixP;
3458 valueT *val;
3459{
3460 offsetT value = *val;
3461 offsetT newval, temp;
3462 int sign;
3463 char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
3464
3465 assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
3466
3467 fixP->fx_addnumber = value; /* Remember value for emit_reloc */
3468
3469 /* Note whether this will delete the relocation. */
3470 if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
3471 fixP->fx_done = 1;
3472
3473 switch (fixP->fx_r_type)
3474 {
3475 case BFD_RELOC_ARM_IMMEDIATE:
3476 newval = validate_immediate (value);
3477 temp = md_chars_to_number (buf, INSN_SIZE);
3478
3479 /* If the instruction will fail, see if we can fix things up by
3480 changing the opcode. */
3481 if (newval == FAIL
3482 && (newval = negate_data_op (&temp, value)) == FAIL)
3483 {
3484 as_bad_where (fixP->fx_file, fixP->fx_line,
3485 "invalid constant after fixup\n");
3486 break;
3487 }
3488
3489 newval |= (temp & 0xfffff000);
3490 md_number_to_chars (buf, newval, INSN_SIZE);
3491 break;
3492
3493 case BFD_RELOC_ARM_OFFSET_IMM:
3494 sign = value >= 0;
3495 value = validate_offset_imm (value); /* Should be OK ... but .... */
3496 if (value < 0)
3497 value = -value;
3498
3499 newval = md_chars_to_number (buf, INSN_SIZE);
3500 newval &= 0xff7ff000;
3501 newval |= value | (sign ? 0x00800000 : 0);
3502 md_number_to_chars (buf, newval, INSN_SIZE);
3503 break;
3504
3505 case BFD_RELOC_ARM_LITERAL:
3506 sign = value >= 0;
3507 if (value < 0)
3508 value = -value;
3509
3510 if ((value = validate_immediate (value)) == FAIL)
3511 {
3512 as_bad_where (fixP->fx_file, fixP->fx_line,
3513 "invalid literal constant: pool needs to be closer\n");
3514 break;
3515 }
3516
3517 newval = md_chars_to_number (buf, INSN_SIZE);
3518 newval &= 0xff7ff000;
3519 newval |= value | (sign ? 0x00800000 : 0);
3520 md_number_to_chars (buf, newval, INSN_SIZE);
3521 break;
3522
3523 case BFD_RELOC_ARM_SHIFT_IMM:
3524 newval = md_chars_to_number (buf, INSN_SIZE);
3525 if (((unsigned long) value) > 32
3526 || (value == 32
3527 && (((newval & 0x60) == 0) || (newval & 0x60) == 0x60)))
3528 {
3529 as_bad_where (fixP->fx_file, fixP->fx_line,
3530 "shift expression is too large");
3531 break;
3532 }
3533
3534 if (value == 0)
3535 newval &= ~0x60; /* Shifts of zero must be done as lsl */
3536 else if (value == 32)
3537 value = 0;
3538 newval &= 0xfffff07f;
3539 newval |= (value & 0x1f) << 7;
3540 md_number_to_chars (buf, newval , INSN_SIZE);
3541 break;
3542
3543 case BFD_RELOC_ARM_SWI:
3544 if (((unsigned long) value) > 0x00ffffff)
3545 as_bad_where (fixP->fx_file, fixP->fx_line, "Invalid swi expression");
3546 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff000000;
3547 newval |= value;
3548 md_number_to_chars (buf, newval , INSN_SIZE);
3549 break;
3550
3551 case BFD_RELOC_ARM_MULTI:
3552 if (((unsigned long) value) > 0xffff)
3553 as_bad_where (fixP->fx_file, fixP->fx_line,
3554 "Invalid expression in load/store multiple");
3555 newval = value | md_chars_to_number (buf, INSN_SIZE);
3556 md_number_to_chars (buf, newval, INSN_SIZE);
3557 break;
3558
3559 case BFD_RELOC_ARM_PCREL_BRANCH:
3560 value = (value >> 2) & 0x00ffffff;
3561 newval = md_chars_to_number (buf, INSN_SIZE);
3562 value = (value + (newval & 0x00ffffff)) & 0x00ffffff;
3563 newval = value | (newval & 0xff000000);
3564 md_number_to_chars (buf, newval, INSN_SIZE);
3565 break;
3566
3567 case BFD_RELOC_8:
3568 if (fixP->fx_done || fixP->fx_pcrel)
3569 md_number_to_chars (buf, value, 1);
3570 break;
3571
3572 case BFD_RELOC_16:
3573 if (fixP->fx_done || fixP->fx_pcrel)
3574 md_number_to_chars (buf, value, 2);
3575 break;
3576
3577 case BFD_RELOC_32:
3578 if (fixP->fx_done || fixP->fx_pcrel)
3579 md_number_to_chars (buf, value, 4);
3580 break;
3581
3582 case BFD_RELOC_ARM_CP_OFF_IMM:
3583 sign = value >= 0;
3584 if (value < -1023 || value > 1023 || (value & 3))
3585 as_bad_where (fixP->fx_file, fixP->fx_line,
3586 "Illegal value for co-processor offset");
3587 if (value < 0)
3588 value = -value;
3589 newval = md_chars_to_number (buf, INSN_SIZE) & 0xff7fff00;
3590 newval |= (value >> 2) | (sign ? 0x00800000 : 0);
3591 md_number_to_chars (buf, newval , INSN_SIZE);
3592 break;
3593
3594 case BFD_RELOC_NONE:
3595 default:
3596 as_bad_where (fixP->fx_file, fixP->fx_line,
3597 "Bad relocation fixup type (%d)\n", fixP->fx_r_type);
3598 }
3599
3600 return 1;
3601}
3602
3603/* Translate internal representation of relocation info to BFD target
3604 format. */
3605arelent *
3606tc_gen_reloc (section, fixp)
3607 asection *section;
3608 fixS *fixp;
3609{
3610 arelent *reloc;
3611 bfd_reloc_code_real_type code;
3612
3613 reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
3614 assert (reloc != 0);
3615
3616 reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
3617 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
3618
3619 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
3620 if (fixp->fx_pcrel == 0)
3621 reloc->addend = fixp->fx_offset;
3622 else
3623 reloc->addend = fixp->fx_offset = reloc->address;
3624
3625 /* @@ Why fx_addnumber sometimes and fx_offset other times? */
3626 if (fixp->fx_pcrel == 0)
3627 reloc->addend = fixp->fx_offset;
3628 else
3629 reloc->addend = fixp->fx_offset = reloc->address;
3630
3631 switch (fixp->fx_r_type)
3632 {
3633 case BFD_RELOC_8:
3634 if (fixp->fx_pcrel)
3635 {
3636 code = BFD_RELOC_8_PCREL;
3637 break;
3638 }
3639
3640 case BFD_RELOC_16:
3641 if (fixp->fx_pcrel)
3642 {
3643 code = BFD_RELOC_16_PCREL;
3644 break;
3645 }
3646
3647 case BFD_RELOC_32:
3648 if (fixp->fx_pcrel)
3649 {
3650 code = BFD_RELOC_32_PCREL;
3651 break;
3652 }
3653
3654 case BFD_RELOC_ARM_PCREL_BRANCH:
3655 code = fixp->fx_r_type;
3656 break;
3657
3658 case BFD_RELOC_ARM_LITERAL:
3659 /* If this is called then the a literal has been referenced across
3660 a section boundry - possibly due to an implicit dump */
3661 as_bad ("Literal referenced across section boundry (Implicit dump?)");
3662 return NULL;
3663
3664 case BFD_RELOC_ARM_IMMEDIATE:
3665 as_bad ("Internal_relocation (type %d) not fixed up (IMMEDIATE)"
3666 , fixp->fx_r_type);
3667 return NULL;
3668
3669 case BFD_RELOC_ARM_OFFSET_IMM:
3670 as_bad ("Internal_relocation (type %d) not fixed up (OFFSET_IMM)"
3671 , fixp->fx_r_type);
3672 return NULL;
3673
3674 case BFD_RELOC_ARM_SHIFT_IMM:
3675 as_bad ("Internal_relocation (type %d) not fixed up (SHIFT_IMM)"
3676 , fixp->fx_r_type);
3677 return NULL;
3678
3679 case BFD_RELOC_ARM_SWI:
3680 as_bad ("Internal_relocation (type %d) not fixed up (SWI)"
3681 , fixp->fx_r_type);
3682 return NULL;
3683
3684 case BFD_RELOC_ARM_MULTI:
3685 as_bad ("Internal_relocation (type %d) not fixed up (MULTI)"
3686 , fixp->fx_r_type);
3687 return NULL;
3688
3689 case BFD_RELOC_ARM_CP_OFF_IMM:
3690 as_bad ("Internal_relocation (type %d) not fixed up (CP_OFF_IMM)"
3691 , fixp->fx_r_type);
3692 return NULL;
3693
3694 default:
3695 abort ();
3696 }
3697
3698 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
3699 assert (reloc->howto != 0);
3700
3701 return reloc;
3702}
3703
3704CONST int md_short_jump_size = 4;
3705CONST int md_long_jump_size = 4;
3706
3707/* These should never be called on the arm */
3708void
3709md_create_long_jump (ptr, from_addr, to_addr, frag, to_symbol)
3710 char *ptr;
3711 addressT from_addr, to_addr;
3712 fragS *frag;
3713 symbolS *to_symbol;
3714{
3715 as_fatal ("md_create_long_jump\n");
3716}
3717
3718void
3719md_create_short_jump (ptr, from_addr, to_addr, frag, to_symbol)
3720 char *ptr;
3721 addressT from_addr, to_addr;
3722 fragS *frag;
3723 symbolS *to_symbol;
3724{
3725 as_fatal ("md_create_short_jump\n");
3726}
3727
3728int
3729md_estimate_size_before_relax (fragP, segtype)
3730 fragS *fragP;
3731 segT segtype;
3732{
3733 as_fatal ("md_estimate_size_before_relax\n");
3734 return (1);
3735}
3736
3737void
3738output_inst (str)
3739 char *str;
3740{
3741 char *to = NULL;
3742
3743 if (inst.error)
3744 {
3745 as_bad ("%s -- statement `%s'\n", inst.error, str);
3746 return;
3747 }
3748
3749 to = frag_more (INSN_SIZE);
3750 md_number_to_chars (to, inst.instruction, INSN_SIZE);
3751
3752 if (inst.reloc.type != BFD_RELOC_NONE)
3753 fix_new_arm (frag_now, to - frag_now->fr_literal,
3754 4, &inst.reloc.exp, inst.reloc.pc_rel,
3755 inst.reloc.type);
3756
3757 return;
3758}
3759
3760void
3761md_assemble (str)
3762 char *str;
3763{
3764 char c;
3765 CONST struct asm_opcode *opcode;
3766 char *p, *q, *start;
3767
3768 /* Align the instruction */
3769 /* this may not be the right thing to do but ... */
3770 /* arm_align (2, 0); */
3771 listing_prev_line (); /* Defined in listing.h */
3772
3773 /* Align the previous label if needed */
3774 if (last_label_seen != NULL)
3775 {
3776 last_label_seen->sy_frag = frag_now;
3777 S_SET_VALUE (last_label_seen,
3778 (valueT) ((char *) obstack_next_free (&frags)
3779 - frag_now->fr_literal));
3780 S_SET_SEGMENT (last_label_seen, now_seg);
3781 }
3782
3783 memset (&inst, '\0', sizeof (inst));
3784 inst.reloc.type = BFD_RELOC_NONE;
3785
3786 if (*str == ' ')
3787 str++; /* Skip leading white space */
3788
3789 /* scan up to the end of the op-code, which must end in white space or
3790 end of string */
3791 for (start = p = str; *p != '\0'; p++)
3792 if (*p == ' ')
3793 break;
3794
3795 if (p == str)
3796 {
3797 as_bad ("No operator -- statement `%s'\n", str);
3798 return;
3799 }
3800
3801 /* p now points to the end of the opcode, probably white space, but we have
3802 to break the opcode up in case it contains condionals and flags;
3803 keep trying with progressively smaller basic instructions until one
3804 matches, or we run out of opcode. */
3805 q = (p - str > LONGEST_INST) ? str + LONGEST_INST : p;
3806 for (; q != str; q--)
3807 {
3808 c = *q;
3809 *q = '\0';
3810 opcode = (CONST struct asm_opcode *) hash_find (arm_ops_hsh, str);
3811 *q = c;
3812 if (opcode && opcode->template)
3813 {
3814 unsigned long flag_bits = 0;
3815 char *r;
3816
3817 /* Check that this instruction is supported for this CPU */
3818 if ((opcode->variants & cpu_variant) == 0)
3819 goto try_shorter;
3820
3821 inst.instruction = opcode->value;
3822 if (q == p) /* Just a simple opcode */
3823 {
3824 if (opcode->comp_suffix != 0)
3825 as_bad ("Opcode `%s' must have suffix from <%s>\n", str,
3826 opcode->comp_suffix);
3827 else
3828 {
3829 inst.instruction |= COND_ALWAYS;
3830 (*opcode->parms)(q, 0);
3831 }
3832 output_inst (start);
3833 return;
3834 }
3835
3836 /* Now check for a conditional */
3837 r = q;
3838 if (p - r >= 2)
3839 {
3840 CONST struct asm_cond *cond;
3841 char d = *(r + 2);
3842
3843 *(r + 2) = '\0';
3844 cond = (CONST struct asm_cond *) hash_find (arm_cond_hsh, r);
3845 *(r + 2) = d;
3846 if (cond)
3847 {
3848 if (cond->value == 0xf0000000)
3849 as_tsktsk
3850 ("Warning: Use of the 'nv' conditional is deprecated\n");
3851
3852 inst.instruction |= cond->value;
3853 r += 2;
3854 }
3855 else
3856 inst.instruction |= COND_ALWAYS;
3857 }
3858 else
3859 inst.instruction |= COND_ALWAYS;
3860
3861 /* if there is a compulsory suffix, it should come here, before
3862 any optional flags. */
3863 if (opcode->comp_suffix)
3864 {
3865 CONST char *s = opcode->comp_suffix;
3866
3867 while (*s)
3868 {
3869 inst.suffix++;
3870 if (*r == *s)
3871 break;
3872 s++;
3873 }
3874
3875 if (*s == '\0')
3876 {
3877 as_bad ("Opcode `%s' must have suffix from <%s>\n", str,
3878 opcode->comp_suffix);
3879 return;
3880 }
3881
3882 r++;
3883 }
3884
3885 /* The remainder, if any should now be flags for the instruction;
3886 Scan these checking each one found with the opcode. */
3887 if (r != p)
3888 {
3889 char d;
3890 CONST struct asm_flg *flag = opcode->flags;
3891
3892 if (flag)
3893 {
3894 int flagno;
3895
3896 d = *p;
3897 *p = '\0';
3898
3899 for (flagno = 0; flag[flagno].template; flagno++)
3900 {
3901 if (! strcmp (r, flag[flagno].template))
3902 {
3903 flag_bits |= flag[flagno].set_bits;
3904 break;
3905 }
3906 }
3907
3908 *p = d;
3909 if (! flag[flagno].template)
3910 goto try_shorter;
3911 }
3912 else
3913 goto try_shorter;
3914 }
3915
3916 (*opcode->parms) (p, flag_bits);
3917 output_inst (start);
3918 return;
3919 }
3920
3921 try_shorter:
3922 ;
3923 }
3924 /* It wasn't an instruction, but it might be a register alias of the form
3925 alias .req reg
3926 */
3927 q = p;
3928 while (*q == ' ')
3929 q++;
3930
3931 c = *p;
3932 *p = '\0';
3933
3934 if (*q && !strncmp (q, ".req ", 4))
3935 {
3936 int reg;
3937 if ((reg = arm_reg_parse (&str)) == FAIL)
3938 {
3939 char *r;
3940
3941 q += 4;
3942 while (*q == ' ')
3943 q++;
3944
3945 for (r = q; *r != '\0'; r++)
3946 if (*r == ' ')
3947 break;
3948
3949 if (r != q)
3950 {
3951 int regnum;
3952 char d = *r;
3953
3954 *r = '\0';
3955 regnum = arm_reg_parse (&q);
3956 *r = d;
3957 if (regnum != FAIL)
3958 {
3959 insert_reg_alias (str, regnum);
3960 *p = c;
3961 return;
3962 }
3963 }
3964 }
3965 else
3966 {
3967 *p = c;
3968 return;
3969 }
3970 }
3971
3972 *p = c;
3973 as_bad ("bad instruction `%s'", start);
3974}
3975
3976/*
3977 * md_parse_option
3978 * Invocation line includes a switch not recognized by the base assembler.
3979 * See if it's a processor-specific option. These are:
3980 * Cpu variants, the arm part is optional:
3981 * -m[arm]1 Currently not supported.
3982 * -m[arm]2, -m[arm]250 Arm 2 and Arm 250 processor
3983 * -m[arm]3 Arm 3 processor
3984 * -m[arm]6, -m[arm]7 Arm 6 and 7 processors
3985 * -m[arm]7dm Arm 7dm processors
3986 * -mall All (except the ARM1)
3987 * FP variants:
3988 * -mfpa10, -mfpa11 FPA10 and 11 co-processor instructions
3989 * -mfpe-old (No float load/store multiples)
3990 * -mno-fpu Disable all floating point instructions
3991 * Run-time endian selection:
3992 * -EB big endian cpu
3993 * -EL little endian cpu
3994 */
3995
3996CONST char *md_shortopts = "m:";
3997struct option md_longopts[] = {
3998#ifdef ARM_BI_ENDIAN
3999#define OPTION_EB (OPTION_MD_BASE + 0)
4000 {"EB", no_argument, NULL, OPTION_EB},
4001#define OPTION_EL (OPTION_MD_BASE + 1)
4002 {"EL", no_argument, NULL, OPTION_EL},
4003#endif
4004 {NULL, no_argument, NULL, 0}
4005};
4006size_t md_longopts_size = sizeof(md_longopts);
4007
4008int
4009md_parse_option (c, arg)
4010 int c;
4011 char *arg;
4012{
4013 char *str = arg;
4014
4015 switch (c)
4016 {
4017#ifdef ARM_BI_ENDIAN
4018 case OPTION_EB:
4019 target_big_endian = 1;
4020 break;
4021 case OPTION_EL:
4022 target_big_endian = 0;
4023 break;
4024#endif
4025
4026 case 'm':
4027 switch (*str)
4028 {
4029 case 'f':
4030 if (! strcmp (str, "fpa10"))
4031 cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_FPA10;
4032 else if (! strcmp (str, "fpa11"))
4033 cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_FPA11;
4034 else if (! strcmp (str, "fpe-old"))
4035 cpu_variant = (cpu_variant & ~FPU_ALL) | FPU_CORE;
4036 else
4037 goto bad;
4038 break;
4039
4040 case 'n':
4041 if (! strcmp (str, "no-fpu"))
4042 cpu_variant &= ~FPU_ALL;
4043 break;
4044
4045 default:
4046 if (! strcmp (str, "all"))
4047 {
4048 cpu_variant = ARM_ALL | FPU_ALL;
4049 return 1;
4050 }
4051
4052 /* Strip off optional "arm" */
4053 if (! strncmp (str, "arm", 3))
4054 str += 3;
4055
4056 switch (*str)
4057 {
4058 case '1':
4059 if (! strcmp (str, "1"))
4060 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_1;
4061 else
4062 goto bad;
4063 break;
4064
4065 case '2':
4066 if (! strcmp (str, "2"))
4067 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_2;
4068 else if (! strcmp (str, "250"))
4069 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_250;
4070 else
4071 goto bad;
4072 break;
4073
4074 case '3':
4075 if (! strcmp (str, "3"))
4076 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_3;
4077 else
4078 goto bad;
4079 break;
4080
4081 case '6':
4082 if (! strcmp (str, "6"))
4083 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_6;
4084 else
4085 goto bad;
4086 break;
4087
4088 case '7':
4089 if (! strcmp (str, "7"))
4090 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7;
4091 else if (! strcmp (str, "7dm"))
4092 cpu_variant = (cpu_variant & ~ARM_ANY) | ARM_7DM;
4093 else
4094 goto bad;
4095 break;
4096
4097 default:
4098 bad:
4099 as_bad ("Invalid architecture -m%s", arg);
4100 return 0;
4101 }
4102 }
4103 break;
4104
4105 default:
4106 return 0;
4107 }
4108
4109 return 1;
4110}
4111
4112void
4113md_show_usage (fp)
4114 FILE *fp;
4115{
4116 fprintf (fp,
4117"-m[arm]1, -m[arm]2, -m[arm]250,\n-m[arm]3, -m[arm]6, -m[arm]7, -m[arm]7dm\n\
4118\t\t\tselect processor architecture\n\
4119-mall\t\t\tallow any instruction\n\
4120-mfpa10, -mfpa11\tselect floating point architecture\n\
4121-mfpe-old\t\tdon't allow floating-point multiple instructions\n\
4122-mno-fpu\t\tdon't allow any floating-point instructions.\n");
4123#ifdef ARM_BI_ENDIAN
4124 fprintf (fp,
4125"-EB\t\t\tassemble code for a big endian cpu\n\
4126-EL\t\t\tassemble code for a little endian cpu\n");
4127#endif
4128}
4129
4130/* We need to be able to fix up arbitrary expressions in some statements.
4131 This is so that we can handle symbols that are an arbitrary distance from
4132 the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
4133 which returns part of an address in a form which will be valid for
4134 a data instruction. We do this by pushing the expression into a symbol
4135 in the expr_section, and creating a fix for that. */
4136
4137static void
4138fix_new_arm (frag, where, size, exp, pc_rel, reloc)
4139 fragS *frag;
4140 int where;
4141 short int size;
4142 expressionS *exp;
4143 int pc_rel;
4144 int reloc;
4145{
4146 fixS *new_fix;
4147
4148 switch (exp->X_op)
4149 {
4150 case O_constant:
4151 case O_symbol:
4152 case O_add:
4153 case O_subtract:
4154 new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
4155 break;
4156
4157 default:
4158 {
4159 const char *fake;
4160 symbolS *symbolP;
4161
4162 /* FIXME: This should be something which decode_local_label_name
4163 will handle. */
4164 fake = FAKE_LABEL_NAME;
4165
4166 /* Putting constant symbols in absolute_section rather than
4167 expr_section is convenient for the old a.out code, for which
4168 S_GET_SEGMENT does not always retrieve the value put in by
4169 S_SET_SEGMENT. */
4170 symbolP = symbol_new (fake, expr_section, 0, &zero_address_frag);
4171 symbolP->sy_value = *exp;
4172 new_fix = fix_new (frag, where, size, symbolP, 0, pc_rel, reloc);
4173 }
4174 break;
4175 }
4176
4177 return;
4178}
4179
4180/* A good place to do this, although this was probably not intended
4181 * for this kind of use. We need to dump the literal pool before
4182 * references are made to a null symbol pointer. */
4183void
4184arm_after_pass_hook (ignore)
4185 asection *ignore;
4186{
4187 if (current_poolP != NULL)
4188 {
4189 subseg_set (text_section, 0); /* Put it at the end of text section */
4190 s_ltorg (0);
4191 listing_prev_line ();
4192 }
4193}
4194
4195void
4196arm_start_line_hook ()
4197{
4198 last_label_seen = NULL;
4199}
4200
4201void
4202arm_frob_label (sym)
4203 symbolS *sym;
4204{
4205 last_label_seen = sym;
4206}
This page took 0.175198 seconds and 4 git commands to generate.