tc-arc.c revision 1.1.1.2 1 /* tc-arc.c -- Assembler for the ARC
2 Copyright (C) 1994-2015 Free Software Foundation, Inc.
3
4 Contributor: Claudiu Zissulescu <claziss (at) synopsys.com>
5
6 This file is part of GAS, the GNU Assembler.
7
8 GAS is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
11 any later version.
12
13 GAS is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GAS; see the file COPYING. If not, write to the Free
20 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
21 02110-1301, USA. */
22
23 #include "as.h"
24 #include "subsegs.h"
25 #include "struc-symbol.h"
26 #include "dwarf2dbg.h"
27 #include "safe-ctype.h"
28
29 #include "opcode/arc.h"
30 #include "elf/arc.h"
31
32 /* Defines section. */
33
34 #define MAX_FLAG_NAME_LENGHT 3
35 #define MAX_INSN_FIXUPS 2
36 #define MAX_CONSTR_STR 20
37
38 #ifdef DEBUG
39 # define pr_debug(fmt, args...) fprintf (stderr, fmt, ##args)
40 #else
41 # define pr_debug(fmt, args...)
42 #endif
43
44 #define MAJOR_OPCODE(x) (((x) & 0xF8000000) >> 27)
45 #define SUB_OPCODE(x) (((x) & 0x003F0000) >> 16)
46 #define LP_INSN(x) ((MAJOR_OPCODE (x) == 0x4) && \
47 (SUB_OPCODE (x) == 0x28))
48
49 /* Equal to MAX_PRECISION in atof-ieee.c. */
50 #define MAX_LITTLENUMS 6
51
52 /* Macros section. */
53
54 #define regno(x) ((x) & 0x3F)
55 #define is_ir_num(x) (((x) & ~0x3F) == 0)
56 #define is_code_density_p(op) (((op)->subclass == CD1 || (op)->subclass == CD2))
57 #define is_br_jmp_insn_p(op) (((op)->class == BRANCH || (op)->class == JUMP))
58 #define is_kernel_insn_p(op) (((op)->class == KERNEL))
59
60 /* Generic assembler global variables which must be defined by all
61 targets. */
62
63 /* Characters which always start a comment. */
64 const char comment_chars[] = "#;";
65
66 /* Characters which start a comment at the beginning of a line. */
67 const char line_comment_chars[] = "#";
68
69 /* Characters which may be used to separate multiple commands on a
70 single line. */
71 const char line_separator_chars[] = "`";
72
73 /* Characters which are used to indicate an exponent in a floating
74 point number. */
75 const char EXP_CHARS[] = "eE";
76
77 /* Chars that mean this number is a floating point constant
78 As in 0f12.456 or 0d1.2345e12. */
79 const char FLT_CHARS[] = "rRsSfFdD";
80
81 /* Byte order. */
82 extern int target_big_endian;
83 const char *arc_target_format = DEFAULT_TARGET_FORMAT;
84 static int byte_order = DEFAULT_BYTE_ORDER;
85
86 extern int arc_get_mach (char *);
87
88 /* Forward declaration. */
89 static void arc_lcomm (int);
90 static void arc_option (int);
91 static void arc_extra_reloc (int);
92
93 const pseudo_typeS md_pseudo_table[] =
94 {
95 /* Make sure that .word is 32 bits. */
96 { "word", cons, 4 },
97
98 { "align", s_align_bytes, 0 }, /* Defaulting is invalid (0). */
99 { "lcomm", arc_lcomm, 0 },
100 { "lcommon", arc_lcomm, 0 },
101 { "cpu", arc_option, 0 },
102
103 { "tls_gd_ld", arc_extra_reloc, BFD_RELOC_ARC_TLS_GD_LD },
104 { "tls_gd_call", arc_extra_reloc, BFD_RELOC_ARC_TLS_GD_CALL },
105
106 { NULL, NULL, 0 }
107 };
108
109 const char *md_shortopts = "";
110
111 enum options
112 {
113 OPTION_EB = OPTION_MD_BASE,
114 OPTION_EL,
115
116 OPTION_ARC600,
117 OPTION_ARC601,
118 OPTION_ARC700,
119 OPTION_ARCEM,
120 OPTION_ARCHS,
121
122 OPTION_MCPU,
123 OPTION_CD,
124
125 /* The following options are deprecated and provided here only for
126 compatibility reasons. */
127 OPTION_USER_MODE,
128 OPTION_LD_EXT_MASK,
129 OPTION_SWAP,
130 OPTION_NORM,
131 OPTION_BARREL_SHIFT,
132 OPTION_MIN_MAX,
133 OPTION_NO_MPY,
134 OPTION_EA,
135 OPTION_MUL64,
136 OPTION_SIMD,
137 OPTION_SPFP,
138 OPTION_DPFP,
139 OPTION_XMAC_D16,
140 OPTION_XMAC_24,
141 OPTION_DSP_PACKA,
142 OPTION_CRC,
143 OPTION_DVBF,
144 OPTION_TELEPHONY,
145 OPTION_XYMEMORY,
146 OPTION_LOCK,
147 OPTION_SWAPE,
148 OPTION_RTSC,
149 OPTION_FPUDA
150 };
151
152 struct option md_longopts[] =
153 {
154 { "EB", no_argument, NULL, OPTION_EB },
155 { "EL", no_argument, NULL, OPTION_EL },
156 { "mcpu", required_argument, NULL, OPTION_MCPU },
157 { "mA6", no_argument, NULL, OPTION_ARC600 },
158 { "mARC600", no_argument, NULL, OPTION_ARC600 },
159 { "mARC601", no_argument, NULL, OPTION_ARC601 },
160 { "mARC700", no_argument, NULL, OPTION_ARC700 },
161 { "mA7", no_argument, NULL, OPTION_ARC700 },
162 { "mEM", no_argument, NULL, OPTION_ARCEM },
163 { "mHS", no_argument, NULL, OPTION_ARCHS },
164 { "mcode-density", no_argument, NULL, OPTION_CD },
165
166 /* The following options are deprecated and provided here only for
167 compatibility reasons. */
168 { "mav2em", no_argument, NULL, OPTION_ARCEM },
169 { "mav2hs", no_argument, NULL, OPTION_ARCHS },
170 { "muser-mode-only", no_argument, NULL, OPTION_USER_MODE },
171 { "mld-extension-reg-mask", required_argument, NULL, OPTION_LD_EXT_MASK },
172 { "mswap", no_argument, NULL, OPTION_SWAP },
173 { "mnorm", no_argument, NULL, OPTION_NORM },
174 { "mbarrel-shifter", no_argument, NULL, OPTION_BARREL_SHIFT },
175 { "mbarrel_shifter", no_argument, NULL, OPTION_BARREL_SHIFT },
176 { "mmin-max", no_argument, NULL, OPTION_MIN_MAX },
177 { "mmin_max", no_argument, NULL, OPTION_MIN_MAX },
178 { "mno-mpy", no_argument, NULL, OPTION_NO_MPY },
179 { "mea", no_argument, NULL, OPTION_EA },
180 { "mEA", no_argument, NULL, OPTION_EA },
181 { "mmul64", no_argument, NULL, OPTION_MUL64 },
182 { "msimd", no_argument, NULL, OPTION_SIMD},
183 { "mspfp", no_argument, NULL, OPTION_SPFP},
184 { "mspfp-compact", no_argument, NULL, OPTION_SPFP},
185 { "mspfp_compact", no_argument, NULL, OPTION_SPFP},
186 { "mspfp-fast", no_argument, NULL, OPTION_SPFP},
187 { "mspfp_fast", no_argument, NULL, OPTION_SPFP},
188 { "mdpfp", no_argument, NULL, OPTION_DPFP},
189 { "mdpfp-compact", no_argument, NULL, OPTION_DPFP},
190 { "mdpfp_compact", no_argument, NULL, OPTION_DPFP},
191 { "mdpfp-fast", no_argument, NULL, OPTION_DPFP},
192 { "mdpfp_fast", no_argument, NULL, OPTION_DPFP},
193 { "mmac-d16", no_argument, NULL, OPTION_XMAC_D16},
194 { "mmac_d16", no_argument, NULL, OPTION_XMAC_D16},
195 { "mmac-24", no_argument, NULL, OPTION_XMAC_24},
196 { "mmac_24", no_argument, NULL, OPTION_XMAC_24},
197 { "mdsp-packa", no_argument, NULL, OPTION_DSP_PACKA},
198 { "mdsp_packa", no_argument, NULL, OPTION_DSP_PACKA},
199 { "mcrc", no_argument, NULL, OPTION_CRC},
200 { "mdvbf", no_argument, NULL, OPTION_DVBF},
201 { "mtelephony", no_argument, NULL, OPTION_TELEPHONY},
202 { "mxy", no_argument, NULL, OPTION_XYMEMORY},
203 { "mlock", no_argument, NULL, OPTION_LOCK},
204 { "mswape", no_argument, NULL, OPTION_SWAPE},
205 { "mrtsc", no_argument, NULL, OPTION_RTSC},
206 { "mfpuda", no_argument, NULL, OPTION_FPUDA},
207
208 { NULL, no_argument, NULL, 0 }
209 };
210
211 size_t md_longopts_size = sizeof (md_longopts);
212
213 /* Local data and data types. */
214
215 /* Used since new relocation types are introduced in this
216 file (DUMMY_RELOC_LITUSE_*). */
217 typedef int extended_bfd_reloc_code_real_type;
218
219 struct arc_fixup
220 {
221 expressionS exp;
222
223 extended_bfd_reloc_code_real_type reloc;
224
225 /* index into arc_operands. */
226 unsigned int opindex;
227
228 /* PC-relative, used by internals fixups. */
229 unsigned char pcrel;
230
231 /* TRUE if this fixup is for LIMM operand. */
232 bfd_boolean islong;
233 };
234
235 struct arc_insn
236 {
237 unsigned int insn;
238 int nfixups;
239 struct arc_fixup fixups[MAX_INSN_FIXUPS];
240 long limm;
241 bfd_boolean short_insn; /* Boolean value: TRUE if current insn is
242 short. */
243 bfd_boolean has_limm; /* Boolean value: TRUE if limm field is
244 valid. */
245 };
246
247 /* Structure to hold any last two instructions. */
248 static struct arc_last_insn
249 {
250 /* Saved instruction opcode. */
251 const struct arc_opcode *opcode;
252
253 /* Boolean value: TRUE if current insn is short. */
254 bfd_boolean has_limm;
255
256 /* Boolean value: TRUE if current insn has delay slot. */
257 bfd_boolean has_delay_slot;
258 } arc_last_insns[2];
259
260 /* The cpu for which we are generating code. */
261 static unsigned arc_target = ARC_OPCODE_BASE;
262 static const char *arc_target_name = "<all>";
263 static unsigned arc_features = 0x00;
264
265 /* The default architecture. */
266 static int arc_mach_type = bfd_mach_arc_arcv2;
267
268 /* Non-zero if the cpu type has been explicitly specified. */
269 static int mach_type_specified_p = 0;
270
271 /* The hash table of instruction opcodes. */
272 static struct hash_control *arc_opcode_hash;
273
274 /* The hash table of register symbols. */
275 static struct hash_control *arc_reg_hash;
276
277 /* A table of CPU names and opcode sets. */
278 static const struct cpu_type
279 {
280 const char *name;
281 unsigned flags;
282 int mach;
283 unsigned eflags;
284 unsigned features;
285 }
286 cpu_types[] =
287 {
288 { "arc600", ARC_OPCODE_ARC600, bfd_mach_arc_arc600,
289 E_ARC_MACH_ARC600, 0x00},
290 { "arc700", ARC_OPCODE_ARC700, bfd_mach_arc_arc700,
291 E_ARC_MACH_ARC700, 0x00},
292 { "arcem", ARC_OPCODE_ARCv2EM, bfd_mach_arc_arcv2,
293 EF_ARC_CPU_ARCV2EM, 0x00},
294 { "archs", ARC_OPCODE_ARCv2HS, bfd_mach_arc_arcv2,
295 EF_ARC_CPU_ARCV2HS, ARC_CD},
296 { "all", ARC_OPCODE_BASE, bfd_mach_arc_arcv2,
297 0x00, 0x00 },
298 { 0, 0, 0, 0, 0 }
299 };
300
301 struct arc_flags
302 {
303 /* Name of the parsed flag. */
304 char name[MAX_FLAG_NAME_LENGHT+1];
305
306 /* The code of the parsed flag. Valid when is not zero. */
307 unsigned char code;
308 };
309
310 /* Used by the arc_reloc_op table. Order is important. */
311 #define O_gotoff O_md1 /* @gotoff relocation. */
312 #define O_gotpc O_md2 /* @gotpc relocation. */
313 #define O_plt O_md3 /* @plt relocation. */
314 #define O_sda O_md4 /* @sda relocation. */
315 #define O_pcl O_md5 /* @pcl relocation. */
316 #define O_tlsgd O_md6 /* @tlsgd relocation. */
317 #define O_tlsie O_md7 /* @tlsie relocation. */
318 #define O_tpoff9 O_md8 /* @tpoff9 relocation. */
319 #define O_tpoff O_md9 /* @tpoff relocation. */
320 #define O_dtpoff9 O_md10 /* @dtpoff9 relocation. */
321 #define O_dtpoff O_md11 /* @dtpoff relocation. */
322 #define O_last O_dtpoff
323
324 /* Used to define a bracket as operand in tokens. */
325 #define O_bracket O_md32
326
327 /* Dummy relocation, to be sorted out. */
328 #define DUMMY_RELOC_ARC_ENTRY (BFD_RELOC_UNUSED + 1)
329
330 #define USER_RELOC_P(R) ((R) >= O_gotoff && (R) <= O_last)
331
332 /* A table to map the spelling of a relocation operand into an appropriate
333 bfd_reloc_code_real_type type. The table is assumed to be ordered such
334 that op-O_literal indexes into it. */
335 #define ARC_RELOC_TABLE(op) \
336 (&arc_reloc_op[ ((!USER_RELOC_P (op)) \
337 ? (abort (), 0) \
338 : (int) (op) - (int) O_gotoff) ])
339
340 #define DEF(NAME, RELOC, REQ) \
341 { #NAME, sizeof (#NAME)-1, O_##NAME, RELOC, REQ}
342
343 static const struct arc_reloc_op_tag
344 {
345 /* String to lookup. */
346 const char *name;
347 /* Size of the string. */
348 size_t length;
349 /* Which operator to use. */
350 operatorT op;
351 extended_bfd_reloc_code_real_type reloc;
352 /* Allows complex relocation expression like identifier@reloc +
353 const. */
354 unsigned int complex_expr : 1;
355 }
356 arc_reloc_op[] =
357 {
358 DEF (gotoff, BFD_RELOC_ARC_GOTOFF, 1),
359 DEF (gotpc, BFD_RELOC_ARC_GOTPC32, 0),
360 DEF (plt, BFD_RELOC_ARC_PLT32, 0),
361 DEF (sda, DUMMY_RELOC_ARC_ENTRY, 1),
362 DEF (pcl, BFD_RELOC_ARC_PC32, 1),
363 DEF (tlsgd, BFD_RELOC_ARC_TLS_GD_GOT, 0),
364 DEF (tlsie, BFD_RELOC_ARC_TLS_IE_GOT, 0),
365 DEF (tpoff9, BFD_RELOC_ARC_TLS_LE_S9, 0),
366 DEF (tpoff, BFD_RELOC_ARC_TLS_LE_32, 0),
367 DEF (dtpoff9, BFD_RELOC_ARC_TLS_DTPOFF_S9, 0),
368 DEF (dtpoff, BFD_RELOC_ARC_TLS_DTPOFF, 0),
369 };
370
371 static const int arc_num_reloc_op
372 = sizeof (arc_reloc_op) / sizeof (*arc_reloc_op);
373
374 /* Flags to set in the elf header. */
375 static flagword arc_eflag = 0x00;
376
377 /* Pre-defined "_GLOBAL_OFFSET_TABLE_". */
378 symbolS * GOT_symbol = 0;
379
380 /* Set to TRUE when we assemble instructions. */
381 static bfd_boolean assembling_insn = FALSE;
382
383 /* Functions declaration. */
384
385 static void assemble_tokens (const char *, expressionS *, int,
386 struct arc_flags *, int);
387 static const struct arc_opcode *find_opcode_match (const struct arc_opcode *,
388 expressionS *, int *,
389 struct arc_flags *,
390 int, int *);
391 static void assemble_insn (const struct arc_opcode *, const expressionS *,
392 int, const struct arc_flags *, int,
393 struct arc_insn *);
394 static void emit_insn (struct arc_insn *);
395 static unsigned insert_operand (unsigned, const struct arc_operand *,
396 offsetT, char *, unsigned);
397 static const struct arc_opcode *find_special_case_flag (const char *,
398 int *,
399 struct arc_flags *);
400 static const struct arc_opcode *find_special_case (const char *,
401 int *,
402 struct arc_flags *,
403 expressionS *, int *);
404 static const struct arc_opcode *find_special_case_pseudo (const char *,
405 int *,
406 expressionS *,
407 int *,
408 struct arc_flags *);
409
410 /* Functions implementation. */
411
412 /* Like md_number_to_chars but used for limms. The 4-byte limm value,
413 is encoded as 'middle-endian' for a little-endian target. FIXME!
414 this function is used for regular 4 byte instructions as well. */
415
416 static void
417 md_number_to_chars_midend (char *buf, valueT val, int n)
418 {
419 if (n == 4)
420 {
421 md_number_to_chars (buf, (val & 0xffff0000) >> 16, 2);
422 md_number_to_chars (buf + 2, (val & 0xffff), 2);
423 }
424 else
425 {
426 md_number_to_chars (buf, val, n);
427 }
428 }
429
430 /* Here ends all the ARCompact extension instruction assembling
431 stuff. */
432
433 static void
434 arc_extra_reloc (int r_type)
435 {
436 char *sym_name, c;
437 symbolS *sym, *lab = NULL;
438
439 if (*input_line_pointer == '@')
440 input_line_pointer++;
441 c = get_symbol_name (&sym_name);
442 sym = symbol_find_or_make (sym_name);
443 restore_line_pointer (c);
444 if (c == ',' && r_type == BFD_RELOC_ARC_TLS_GD_LD)
445 {
446 ++input_line_pointer;
447 char *lab_name;
448 c = get_symbol_name (&lab_name);
449 lab = symbol_find_or_make (lab_name);
450 restore_line_pointer (c);
451 }
452 fixS *fixP
453 = fix_new (frag_now, /* Which frag? */
454 frag_now_fix (), /* Where in that frag? */
455 2, /* size: 1, 2, or 4 usually. */
456 sym, /* X_add_symbol. */
457 0, /* X_add_number. */
458 FALSE, /* TRUE if PC-relative relocation. */
459 r_type /* Relocation type. */);
460 fixP->fx_subsy = lab;
461 }
462
463 static symbolS *
464 arc_lcomm_internal (int ignore ATTRIBUTE_UNUSED,
465 symbolS *symbolP, addressT size)
466 {
467 addressT align = 0;
468 SKIP_WHITESPACE ();
469
470 if (*input_line_pointer == ',')
471 {
472 align = parse_align (1);
473
474 if (align == (addressT) -1)
475 return NULL;
476 }
477 else
478 {
479 if (size >= 8)
480 align = 3;
481 else if (size >= 4)
482 align = 2;
483 else if (size >= 2)
484 align = 1;
485 else
486 align = 0;
487 }
488
489 bss_alloc (symbolP, size, align);
490 S_CLEAR_EXTERNAL (symbolP);
491
492 return symbolP;
493 }
494
495 static void
496 arc_lcomm (int ignore)
497 {
498 symbolS *symbolP = s_comm_internal (ignore, arc_lcomm_internal);
499
500 if (symbolP)
501 symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
502 }
503
504 /* Select the cpu we're assembling for. */
505
506 static void
507 arc_option (int ignore ATTRIBUTE_UNUSED)
508 {
509 int mach = -1;
510 char c;
511 char *cpu;
512
513 c = get_symbol_name (&cpu);
514 mach = arc_get_mach (cpu);
515 restore_line_pointer (c);
516
517 if (mach == -1)
518 goto bad_cpu;
519
520 if (!mach_type_specified_p)
521 {
522 arc_mach_type = mach;
523 if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, mach))
524 as_fatal ("could not set architecture and machine");
525
526 mach_type_specified_p = 1;
527 }
528 else
529 if (arc_mach_type != mach)
530 as_warn ("Command-line value overrides \".cpu\" directive");
531
532 demand_empty_rest_of_line ();
533
534 return;
535
536 bad_cpu:
537 as_bad ("invalid identifier for \".cpu\"");
538 ignore_rest_of_line ();
539 }
540
541 /* Smartly print an expression. */
542
543 static void
544 debug_exp (expressionS *t)
545 {
546 const char *name ATTRIBUTE_UNUSED;
547 const char *namemd ATTRIBUTE_UNUSED;
548
549 pr_debug ("debug_exp: ");
550
551 switch (t->X_op)
552 {
553 default: name = "unknown"; break;
554 case O_illegal: name = "O_illegal"; break;
555 case O_absent: name = "O_absent"; break;
556 case O_constant: name = "O_constant"; break;
557 case O_symbol: name = "O_symbol"; break;
558 case O_symbol_rva: name = "O_symbol_rva"; break;
559 case O_register: name = "O_register"; break;
560 case O_big: name = "O_big"; break;
561 case O_uminus: name = "O_uminus"; break;
562 case O_bit_not: name = "O_bit_not"; break;
563 case O_logical_not: name = "O_logical_not"; break;
564 case O_multiply: name = "O_multiply"; break;
565 case O_divide: name = "O_divide"; break;
566 case O_modulus: name = "O_modulus"; break;
567 case O_left_shift: name = "O_left_shift"; break;
568 case O_right_shift: name = "O_right_shift"; break;
569 case O_bit_inclusive_or: name = "O_bit_inclusive_or"; break;
570 case O_bit_or_not: name = "O_bit_or_not"; break;
571 case O_bit_exclusive_or: name = "O_bit_exclusive_or"; break;
572 case O_bit_and: name = "O_bit_and"; break;
573 case O_add: name = "O_add"; break;
574 case O_subtract: name = "O_subtract"; break;
575 case O_eq: name = "O_eq"; break;
576 case O_ne: name = "O_ne"; break;
577 case O_lt: name = "O_lt"; break;
578 case O_le: name = "O_le"; break;
579 case O_ge: name = "O_ge"; break;
580 case O_gt: name = "O_gt"; break;
581 case O_logical_and: name = "O_logical_and"; break;
582 case O_logical_or: name = "O_logical_or"; break;
583 case O_index: name = "O_index"; break;
584 case O_bracket: name = "O_bracket"; break;
585 }
586
587 switch (t->X_md)
588 {
589 default: namemd = "unknown"; break;
590 case O_gotoff: namemd = "O_gotoff"; break;
591 case O_gotpc: namemd = "O_gotpc"; break;
592 case O_plt: namemd = "O_plt"; break;
593 case O_sda: namemd = "O_sda"; break;
594 case O_pcl: namemd = "O_pcl"; break;
595 case O_tlsgd: namemd = "O_tlsgd"; break;
596 case O_tlsie: namemd = "O_tlsie"; break;
597 case O_tpoff9: namemd = "O_tpoff9"; break;
598 case O_tpoff: namemd = "O_tpoff"; break;
599 case O_dtpoff9: namemd = "O_dtpoff9"; break;
600 case O_dtpoff: namemd = "O_dtpoff"; break;
601 }
602
603 pr_debug ("%s (%s, %s, %d, %s)", name,
604 (t->X_add_symbol) ? S_GET_NAME (t->X_add_symbol) : "--",
605 (t->X_op_symbol) ? S_GET_NAME (t->X_op_symbol) : "--",
606 (int) t->X_add_number,
607 (t->X_md) ? namemd : "--");
608 pr_debug ("\n");
609 fflush (stderr);
610 }
611
612 /* Parse the arguments to an opcode. */
613
614 static int
615 tokenize_arguments (char *str,
616 expressionS *tok,
617 int ntok)
618 {
619 char *old_input_line_pointer;
620 bfd_boolean saw_comma = FALSE;
621 bfd_boolean saw_arg = FALSE;
622 int brk_lvl = 0;
623 int num_args = 0;
624 int i;
625 size_t len;
626 const struct arc_reloc_op_tag *r;
627 expressionS tmpE;
628 char *reloc_name, c;
629
630 memset (tok, 0, sizeof (*tok) * ntok);
631
632 /* Save and restore input_line_pointer around this function. */
633 old_input_line_pointer = input_line_pointer;
634 input_line_pointer = str;
635
636 while (*input_line_pointer)
637 {
638 SKIP_WHITESPACE ();
639 switch (*input_line_pointer)
640 {
641 case '\0':
642 goto fini;
643
644 case ',':
645 input_line_pointer++;
646 if (saw_comma || !saw_arg)
647 goto err;
648 saw_comma = TRUE;
649 break;
650
651 case '}':
652 case ']':
653 ++input_line_pointer;
654 --brk_lvl;
655 if (!saw_arg)
656 goto err;
657 tok->X_op = O_bracket;
658 ++tok;
659 ++num_args;
660 break;
661
662 case '{':
663 case '[':
664 input_line_pointer++;
665 if (brk_lvl)
666 goto err;
667 ++brk_lvl;
668 tok->X_op = O_bracket;
669 ++tok;
670 ++num_args;
671 break;
672
673 case '@':
674 /* We have labels, function names and relocations, all
675 starting with @ symbol. Sort them out. */
676 if (saw_arg && !saw_comma)
677 goto err;
678
679 /* Parse @label. */
680 tok->X_op = O_symbol;
681 tok->X_md = O_absent;
682 expression (tok);
683 if (*input_line_pointer != '@')
684 goto normalsymbol; /* This is not a relocation. */
685
686 relocationsym:
687
688 /* A relocation opernad has the following form
689 @identifier@relocation_type. The identifier is already
690 in tok! */
691 if (tok->X_op != O_symbol)
692 {
693 as_bad (_("No valid label relocation operand"));
694 goto err;
695 }
696
697 /* Parse @relocation_type. */
698 input_line_pointer++;
699 c = get_symbol_name (&reloc_name);
700 len = input_line_pointer - reloc_name;
701 if (len == 0)
702 {
703 as_bad (_("No relocation operand"));
704 goto err;
705 }
706
707 /* Go through known relocation and try to find a match. */
708 r = &arc_reloc_op[0];
709 for (i = arc_num_reloc_op - 1; i >= 0; i--, r++)
710 if (len == r->length
711 && memcmp (reloc_name, r->name, len) == 0)
712 break;
713 if (i < 0)
714 {
715 as_bad (_("Unknown relocation operand: @%s"), reloc_name);
716 goto err;
717 }
718
719 *input_line_pointer = c;
720 SKIP_WHITESPACE_AFTER_NAME ();
721 /* Extra check for TLS: base. */
722 if (*input_line_pointer == '@')
723 {
724 symbolS *base;
725 if (tok->X_op_symbol != NULL
726 || tok->X_op != O_symbol)
727 {
728 as_bad (_("Unable to parse TLS base: %s"),
729 input_line_pointer);
730 goto err;
731 }
732 input_line_pointer++;
733 char *sym_name;
734 c = get_symbol_name (&sym_name);
735 base = symbol_find_or_make (sym_name);
736 tok->X_op = O_subtract;
737 tok->X_op_symbol = base;
738 restore_line_pointer (c);
739 tmpE.X_add_number = 0;
740 }
741 else if ((*input_line_pointer != '+')
742 && (*input_line_pointer != '-'))
743 {
744 tmpE.X_add_number = 0;
745 }
746 else
747 {
748 /* Parse the constant of a complex relocation expression
749 like @identifier@reloc +/- const. */
750 if (! r->complex_expr)
751 {
752 as_bad (_("@%s is not a complex relocation."), r->name);
753 goto err;
754 }
755 expression (&tmpE);
756 if (tmpE.X_op != O_constant)
757 {
758 as_bad (_("Bad expression: @%s + %s."),
759 r->name, input_line_pointer);
760 goto err;
761 }
762 }
763
764 tok->X_md = r->op;
765 tok->X_add_number = tmpE.X_add_number;
766
767 debug_exp (tok);
768
769 saw_comma = FALSE;
770 saw_arg = TRUE;
771 tok++;
772 num_args++;
773 break;
774
775 case '%':
776 /* Can be a register. */
777 ++input_line_pointer;
778 /* Fall through. */
779 default:
780
781 if (saw_arg && !saw_comma)
782 goto err;
783
784 tok->X_op = O_absent;
785 tok->X_md = O_absent;
786 expression (tok);
787
788 /* Legacy: There are cases when we have
789 identifier@relocation_type, if it is the case parse the
790 relocation type as well. */
791 if (*input_line_pointer == '@')
792 goto relocationsym;
793
794 normalsymbol:
795 debug_exp (tok);
796
797 if (tok->X_op == O_illegal || tok->X_op == O_absent)
798 goto err;
799
800 saw_comma = FALSE;
801 saw_arg = TRUE;
802 tok++;
803 num_args++;
804 break;
805 }
806 }
807
808 fini:
809 if (saw_comma || brk_lvl)
810 goto err;
811 input_line_pointer = old_input_line_pointer;
812
813 return num_args;
814
815 err:
816 if (brk_lvl)
817 as_bad (_("Brackets in operand field incorrect"));
818 else if (saw_comma)
819 as_bad (_("extra comma"));
820 else if (!saw_arg)
821 as_bad (_("missing argument"));
822 else
823 as_bad (_("missing comma or colon"));
824 input_line_pointer = old_input_line_pointer;
825 return -1;
826 }
827
828 /* Parse the flags to a structure. */
829
830 static int
831 tokenize_flags (const char *str,
832 struct arc_flags flags[],
833 int nflg)
834 {
835 char *old_input_line_pointer;
836 bfd_boolean saw_flg = FALSE;
837 bfd_boolean saw_dot = FALSE;
838 int num_flags = 0;
839 size_t flgnamelen;
840
841 memset (flags, 0, sizeof (*flags) * nflg);
842
843 /* Save and restore input_line_pointer around this function. */
844 old_input_line_pointer = input_line_pointer;
845 input_line_pointer = (char *) str;
846
847 while (*input_line_pointer)
848 {
849 switch (*input_line_pointer)
850 {
851 case ' ':
852 case '\0':
853 goto fini;
854
855 case '.':
856 input_line_pointer++;
857 if (saw_dot)
858 goto err;
859 saw_dot = TRUE;
860 saw_flg = FALSE;
861 break;
862
863 default:
864 if (saw_flg && !saw_dot)
865 goto err;
866
867 if (num_flags >= nflg)
868 goto err;
869
870 flgnamelen = strspn (input_line_pointer, "abcdefghilmnopqrstvwxz");
871 if (flgnamelen > MAX_FLAG_NAME_LENGHT)
872 goto err;
873
874 memcpy (flags->name, input_line_pointer, flgnamelen);
875
876 input_line_pointer += flgnamelen;
877 flags++;
878 saw_dot = FALSE;
879 saw_flg = TRUE;
880 num_flags++;
881 break;
882 }
883 }
884
885 fini:
886 input_line_pointer = old_input_line_pointer;
887 return num_flags;
888
889 err:
890 if (saw_dot)
891 as_bad (_("extra dot"));
892 else if (!saw_flg)
893 as_bad (_("unrecognized flag"));
894 else
895 as_bad (_("failed to parse flags"));
896 input_line_pointer = old_input_line_pointer;
897 return -1;
898 }
899
900 /* The public interface to the instruction assembler. */
901
902 void
903 md_assemble (char *str)
904 {
905 char *opname;
906 expressionS tok[MAX_INSN_ARGS];
907 int ntok, nflg;
908 size_t opnamelen;
909 struct arc_flags flags[MAX_INSN_FLGS];
910
911 /* Split off the opcode. */
912 opnamelen = strspn (str, "abcdefghijklmnopqrstuvwxyz_0123468");
913 opname = xmalloc (opnamelen + 1);
914 memcpy (opname, str, opnamelen);
915 opname[opnamelen] = '\0';
916
917 /* Signalize we are assmbling the instructions. */
918 assembling_insn = TRUE;
919
920 /* Tokenize the flags. */
921 if ((nflg = tokenize_flags (str + opnamelen, flags, MAX_INSN_FLGS)) == -1)
922 {
923 as_bad (_("syntax error"));
924 return;
925 }
926
927 /* Scan up to the end of the mnemonic which must end in space or end
928 of string. */
929 str += opnamelen;
930 for (; *str != '\0'; str++)
931 if (*str == ' ')
932 break;
933
934 /* Tokenize the rest of the line. */
935 if ((ntok = tokenize_arguments (str, tok, MAX_INSN_ARGS)) < 0)
936 {
937 as_bad (_("syntax error"));
938 return;
939 }
940
941 /* Finish it off. */
942 assemble_tokens (opname, tok, ntok, flags, nflg);
943 assembling_insn = FALSE;
944 }
945
946 /* Callback to insert a register into the hash table. */
947
948 static void
949 declare_register (char *name, int number)
950 {
951 const char *err;
952 symbolS *regS = symbol_create (name, reg_section,
953 number, &zero_address_frag);
954
955 err = hash_insert (arc_reg_hash, S_GET_NAME (regS), (void *) regS);
956 if (err)
957 as_fatal ("Inserting \"%s\" into register table failed: %s",
958 name, err);
959 }
960
961 /* Construct symbols for each of the general registers. */
962
963 static void
964 declare_register_set (void)
965 {
966 int i;
967 for (i = 0; i < 32; ++i)
968 {
969 char name[7];
970
971 sprintf (name, "r%d", i);
972 declare_register (name, i);
973 if ((i & 0x01) == 0)
974 {
975 sprintf (name, "r%dr%d", i, i+1);
976 declare_register (name, i);
977 }
978 }
979 }
980
981 /* Port-specific assembler initialization. This function is called
982 once, at assembler startup time. */
983
984 void
985 md_begin (void)
986 {
987 unsigned int i;
988
989 /* The endianness can be chosen "at the factory". */
990 target_big_endian = byte_order == BIG_ENDIAN;
991
992 if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, arc_mach_type))
993 as_warn (_("could not set architecture and machine"));
994
995 /* Set elf header flags. */
996 bfd_set_private_flags (stdoutput, arc_eflag);
997
998 /* Set up a hash table for the instructions. */
999 arc_opcode_hash = hash_new ();
1000 if (arc_opcode_hash == NULL)
1001 as_fatal (_("Virtual memory exhausted"));
1002
1003 /* Initialize the hash table with the insns. */
1004 for (i = 0; i < arc_num_opcodes;)
1005 {
1006 const char *name, *retval;
1007
1008 name = arc_opcodes[i].name;
1009 retval = hash_insert (arc_opcode_hash, name, (void *) &arc_opcodes[i]);
1010 if (retval)
1011 as_fatal (_("internal error: can't hash opcode '%s': %s"),
1012 name, retval);
1013
1014 while (++i < arc_num_opcodes
1015 && (arc_opcodes[i].name == name
1016 || !strcmp (arc_opcodes[i].name, name)))
1017 continue;
1018 }
1019
1020 /* Register declaration. */
1021 arc_reg_hash = hash_new ();
1022 if (arc_reg_hash == NULL)
1023 as_fatal (_("Virtual memory exhausted"));
1024
1025 declare_register_set ();
1026 declare_register ("gp", 26);
1027 declare_register ("fp", 27);
1028 declare_register ("sp", 28);
1029 declare_register ("ilink", 29);
1030 declare_register ("ilink1", 29);
1031 declare_register ("ilink2", 30);
1032 declare_register ("blink", 31);
1033
1034 declare_register ("mlo", 57);
1035 declare_register ("mmid", 58);
1036 declare_register ("mhi", 59);
1037
1038 declare_register ("acc1", 56);
1039 declare_register ("acc2", 57);
1040
1041 declare_register ("lp_count", 60);
1042 declare_register ("pcl", 63);
1043
1044 /* Initialize the last instructions. */
1045 memset (&arc_last_insns[0], 0, sizeof (arc_last_insns));
1046 }
1047
1048 /* Write a value out to the object file, using the appropriate
1049 endianness. */
1050
1051 void
1052 md_number_to_chars (char *buf,
1053 valueT val,
1054 int n)
1055 {
1056 if (target_big_endian)
1057 number_to_chars_bigendian (buf, val, n);
1058 else
1059 number_to_chars_littleendian (buf, val, n);
1060 }
1061
1062 /* Round up a section size to the appropriate boundary. */
1063
1064 valueT
1065 md_section_align (segT segment,
1066 valueT size)
1067 {
1068 int align = bfd_get_section_alignment (stdoutput, segment);
1069
1070 return ((size + (1 << align) - 1) & -(1 << align));
1071 }
1072
1073 /* The location from which a PC relative jump should be calculated,
1074 given a PC relative reloc. */
1075
1076 long
1077 md_pcrel_from_section (fixS *fixP,
1078 segT sec)
1079 {
1080 offsetT base = fixP->fx_where + fixP->fx_frag->fr_address;
1081
1082 pr_debug ("pcrel_from_section, fx_offset = %d\n", (int) fixP->fx_offset);
1083
1084 if (fixP->fx_addsy != (symbolS *) NULL
1085 && (!S_IS_DEFINED (fixP->fx_addsy)
1086 || S_GET_SEGMENT (fixP->fx_addsy) != sec))
1087 {
1088 pr_debug ("Unknown pcrel symbol: %s\n", S_GET_NAME (fixP->fx_addsy));
1089
1090 /* The symbol is undefined (or is defined but not in this section).
1091 Let the linker figure it out. */
1092 return 0;
1093 }
1094
1095 if ((int) fixP->fx_r_type < 0)
1096 {
1097 /* These are the "internal" relocations. Align them to
1098 32 bit boundary (PCL), for the moment. */
1099 base &= ~3;
1100 }
1101 else
1102 {
1103 switch (fixP->fx_r_type)
1104 {
1105 case BFD_RELOC_ARC_PC32:
1106 /* The hardware calculates relative to the start of the
1107 insn, but this relocation is relative to location of the
1108 LIMM, compensate. TIP: the base always needs to be
1109 substracted by 4 as we do not support this type of PCrel
1110 relocation for short instructions. */
1111 base -= fixP->fx_where - fixP->fx_dot_value;
1112 gas_assert ((fixP->fx_where - fixP->fx_dot_value) == 4);
1113 /* Fall through. */
1114 case BFD_RELOC_ARC_PLT32:
1115 case BFD_RELOC_ARC_S25H_PCREL_PLT:
1116 case BFD_RELOC_ARC_S21H_PCREL_PLT:
1117 case BFD_RELOC_ARC_S25W_PCREL_PLT:
1118 case BFD_RELOC_ARC_S21W_PCREL_PLT:
1119
1120 case BFD_RELOC_ARC_S21H_PCREL:
1121 case BFD_RELOC_ARC_S25H_PCREL:
1122 case BFD_RELOC_ARC_S13_PCREL:
1123 case BFD_RELOC_ARC_S21W_PCREL:
1124 case BFD_RELOC_ARC_S25W_PCREL:
1125 base &= ~3;
1126 break;
1127 default:
1128 as_bad_where (fixP->fx_file, fixP->fx_line,
1129 _("unhandled reloc %s in md_pcrel_from_section"),
1130 bfd_get_reloc_code_name (fixP->fx_r_type));
1131 break;
1132 }
1133 }
1134
1135 pr_debug ("pcrel from %x + %lx = %x, symbol: %s (%x)\n",
1136 fixP->fx_frag->fr_address, fixP->fx_where, base,
1137 fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : "(null)",
1138 fixP->fx_addsy ? S_GET_VALUE (fixP->fx_addsy) : 0);
1139
1140 return base;
1141 }
1142
1143 /* Given a BFD relocation find the coresponding operand. */
1144
1145 static const struct arc_operand *
1146 find_operand_for_reloc (extended_bfd_reloc_code_real_type reloc)
1147 {
1148 unsigned i;
1149
1150 for (i = 0; i < arc_num_operands; i++)
1151 if (arc_operands[i].default_reloc == reloc)
1152 return &arc_operands[i];
1153 return NULL;
1154 }
1155
1156 /* Apply a fixup to the object code. At this point all symbol values
1157 should be fully resolved, and we attempt to completely resolve the
1158 reloc. If we can not do that, we determine the correct reloc code
1159 and put it back in the fixup. To indicate that a fixup has been
1160 eliminated, set fixP->fx_done. */
1161
1162 void
1163 md_apply_fix (fixS *fixP,
1164 valueT *valP,
1165 segT seg)
1166 {
1167 char * const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where;
1168 valueT value = *valP;
1169 unsigned insn = 0;
1170 symbolS *fx_addsy, *fx_subsy;
1171 offsetT fx_offset;
1172 segT add_symbol_segment = absolute_section;
1173 segT sub_symbol_segment = absolute_section;
1174 const struct arc_operand *operand = NULL;
1175 extended_bfd_reloc_code_real_type reloc;
1176
1177 pr_debug ("%s:%u: apply_fix: r_type=%d (%s) value=0x%lX offset=0x%lX\n",
1178 fixP->fx_file, fixP->fx_line, fixP->fx_r_type,
1179 ((int) fixP->fx_r_type < 0) ? "Internal":
1180 bfd_get_reloc_code_name (fixP->fx_r_type), value,
1181 fixP->fx_offset);
1182
1183 fx_addsy = fixP->fx_addsy;
1184 fx_subsy = fixP->fx_subsy;
1185 fx_offset = 0;
1186
1187 if (fx_addsy)
1188 {
1189 add_symbol_segment = S_GET_SEGMENT (fx_addsy);
1190 }
1191
1192 if (fx_subsy
1193 && fixP->fx_r_type != BFD_RELOC_ARC_TLS_DTPOFF
1194 && fixP->fx_r_type != BFD_RELOC_ARC_TLS_DTPOFF_S9
1195 && fixP->fx_r_type != BFD_RELOC_ARC_TLS_GD_LD)
1196 {
1197 resolve_symbol_value (fx_subsy);
1198 sub_symbol_segment = S_GET_SEGMENT (fx_subsy);
1199
1200 if (sub_symbol_segment == absolute_section)
1201 {
1202 /* The symbol is really a constant. */
1203 fx_offset -= S_GET_VALUE (fx_subsy);
1204 fx_subsy = NULL;
1205 }
1206 else
1207 {
1208 as_bad_where (fixP->fx_file, fixP->fx_line,
1209 _("can't resolve `%s' {%s section} - `%s' {%s section}"),
1210 fx_addsy ? S_GET_NAME (fx_addsy) : "0",
1211 segment_name (add_symbol_segment),
1212 S_GET_NAME (fx_subsy),
1213 segment_name (sub_symbol_segment));
1214 return;
1215 }
1216 }
1217
1218 if (fx_addsy
1219 && !S_IS_WEAK (fx_addsy))
1220 {
1221 if (add_symbol_segment == seg
1222 && fixP->fx_pcrel)
1223 {
1224 value += S_GET_VALUE (fx_addsy);
1225 value -= md_pcrel_from_section (fixP, seg);
1226 fx_addsy = NULL;
1227 fixP->fx_pcrel = FALSE;
1228 }
1229 else if (add_symbol_segment == absolute_section)
1230 {
1231 value = fixP->fx_offset;
1232 fx_offset += S_GET_VALUE (fixP->fx_addsy);
1233 fx_addsy = NULL;
1234 fixP->fx_pcrel = FALSE;
1235 }
1236 }
1237
1238 if (!fx_addsy)
1239 fixP->fx_done = TRUE;
1240
1241 if (fixP->fx_pcrel)
1242 {
1243 if (fx_addsy
1244 && ((S_IS_DEFINED (fx_addsy)
1245 && S_GET_SEGMENT (fx_addsy) != seg)
1246 || S_IS_WEAK (fx_addsy)))
1247 value += md_pcrel_from_section (fixP, seg);
1248
1249 switch (fixP->fx_r_type)
1250 {
1251 case BFD_RELOC_ARC_32_ME:
1252 /* This is a pc-relative value in a LIMM. Adjust it to the
1253 address of the instruction not to the address of the
1254 LIMM. Note: it is not anylonger valid this afirmation as
1255 the linker consider ARC_PC32 a fixup to entire 64 bit
1256 insn. */
1257 fixP->fx_offset += fixP->fx_frag->fr_address;
1258 /* Fall through. */
1259 case BFD_RELOC_32:
1260 fixP->fx_r_type = BFD_RELOC_ARC_PC32;
1261 /* Fall through. */
1262 case BFD_RELOC_ARC_PC32:
1263 /* fixP->fx_offset += fixP->fx_where - fixP->fx_dot_value; */
1264 break;
1265 default:
1266 if ((int) fixP->fx_r_type < 0)
1267 as_fatal (_("PC relative relocation not allowed for (internal) type %d"),
1268 fixP->fx_r_type);
1269 break;
1270 }
1271 }
1272
1273 pr_debug ("%s:%u: apply_fix: r_type=%d (%s) value=0x%lX offset=0x%lX\n",
1274 fixP->fx_file, fixP->fx_line, fixP->fx_r_type,
1275 ((int) fixP->fx_r_type < 0) ? "Internal":
1276 bfd_get_reloc_code_name (fixP->fx_r_type), value,
1277 fixP->fx_offset);
1278
1279
1280 /* Now check for TLS relocations. */
1281 reloc = fixP->fx_r_type;
1282 switch (reloc)
1283 {
1284 case BFD_RELOC_ARC_TLS_DTPOFF:
1285 case BFD_RELOC_ARC_TLS_LE_32:
1286 fixP->fx_offset = 0;
1287 /* Fall through. */
1288 case BFD_RELOC_ARC_TLS_GD_GOT:
1289 case BFD_RELOC_ARC_TLS_IE_GOT:
1290 S_SET_THREAD_LOCAL (fixP->fx_addsy);
1291 break;
1292
1293 case BFD_RELOC_ARC_TLS_GD_LD:
1294 gas_assert (!fixP->fx_offset);
1295 if (fixP->fx_subsy)
1296 fixP->fx_offset
1297 = (S_GET_VALUE (fixP->fx_subsy)
1298 - fixP->fx_frag->fr_address- fixP->fx_where);
1299 fixP->fx_subsy = NULL;
1300 /* Fall through. */
1301 case BFD_RELOC_ARC_TLS_GD_CALL:
1302 /* These two relocs are there just to allow ld to change the tls
1303 model for this symbol, by patching the code. The offset -
1304 and scale, if any - will be installed by the linker. */
1305 S_SET_THREAD_LOCAL (fixP->fx_addsy);
1306 break;
1307
1308 case BFD_RELOC_ARC_TLS_LE_S9:
1309 case BFD_RELOC_ARC_TLS_DTPOFF_S9:
1310 as_bad (_("TLS_*_S9 relocs are not supported yet"));
1311 break;
1312
1313 default:
1314 break;
1315 }
1316
1317 if (!fixP->fx_done)
1318 {
1319 return;
1320 }
1321
1322 /* Addjust the value if we have a constant. */
1323 value += fx_offset;
1324
1325 /* For hosts with longs bigger than 32-bits make sure that the top
1326 bits of a 32-bit negative value read in by the parser are set,
1327 so that the correct comparisons are made. */
1328 if (value & 0x80000000)
1329 value |= (-1L << 31);
1330
1331 reloc = fixP->fx_r_type;
1332 switch (reloc)
1333 {
1334 case BFD_RELOC_8:
1335 case BFD_RELOC_16:
1336 case BFD_RELOC_24:
1337 case BFD_RELOC_32:
1338 case BFD_RELOC_64:
1339 case BFD_RELOC_ARC_32_PCREL:
1340 md_number_to_chars (fixpos, value, fixP->fx_size);
1341 return;
1342
1343 case BFD_RELOC_ARC_GOTPC32:
1344 /* I cannot fix an GOTPC relocation because I need to relax it
1345 from ld rx,[pcl,@sym@gotpc] to add rx,pcl,@sym@gotpc. */
1346 as_bad (_("Unsupported operation on reloc"));
1347 return;
1348 case BFD_RELOC_ARC_GOTOFF:
1349 case BFD_RELOC_ARC_32_ME:
1350 case BFD_RELOC_ARC_PC32:
1351 md_number_to_chars_midend (fixpos, value, fixP->fx_size);
1352 return;
1353
1354 case BFD_RELOC_ARC_PLT32:
1355 md_number_to_chars_midend (fixpos, value, fixP->fx_size);
1356 return;
1357
1358 case BFD_RELOC_ARC_S25H_PCREL_PLT:
1359 reloc = BFD_RELOC_ARC_S25W_PCREL;
1360 goto solve_plt;
1361
1362 case BFD_RELOC_ARC_S21H_PCREL_PLT:
1363 reloc = BFD_RELOC_ARC_S21H_PCREL;
1364 goto solve_plt;
1365
1366 case BFD_RELOC_ARC_S25W_PCREL_PLT:
1367 reloc = BFD_RELOC_ARC_S25W_PCREL;
1368 goto solve_plt;
1369
1370 case BFD_RELOC_ARC_S21W_PCREL_PLT:
1371 reloc = BFD_RELOC_ARC_S21W_PCREL;
1372
1373 case BFD_RELOC_ARC_S25W_PCREL:
1374 case BFD_RELOC_ARC_S21W_PCREL:
1375 case BFD_RELOC_ARC_S21H_PCREL:
1376 case BFD_RELOC_ARC_S25H_PCREL:
1377 case BFD_RELOC_ARC_S13_PCREL:
1378 solve_plt:
1379 operand = find_operand_for_reloc (reloc);
1380 gas_assert (operand);
1381 break;
1382
1383 default:
1384 {
1385 if ((int) fixP->fx_r_type >= 0)
1386 as_fatal (_("unhandled relocation type %s"),
1387 bfd_get_reloc_code_name (fixP->fx_r_type));
1388
1389 /* The rest of these fixups needs to be completely resolved as
1390 constants. */
1391 if (fixP->fx_addsy != 0
1392 && S_GET_SEGMENT (fixP->fx_addsy) != absolute_section)
1393 as_bad_where (fixP->fx_file, fixP->fx_line,
1394 _("non-absolute expression in constant field"));
1395
1396 gas_assert (-(int) fixP->fx_r_type < (int) arc_num_operands);
1397 operand = &arc_operands[-(int) fixP->fx_r_type];
1398 break;
1399 }
1400 }
1401
1402 if (target_big_endian)
1403 {
1404 switch (fixP->fx_size)
1405 {
1406 case 4:
1407 insn = bfd_getb32 (fixpos);
1408 break;
1409 case 2:
1410 insn = bfd_getb16 (fixpos);
1411 break;
1412 default:
1413 as_bad_where (fixP->fx_file, fixP->fx_line,
1414 _("unknown fixup size"));
1415 }
1416 }
1417 else
1418 {
1419 insn = 0;
1420 switch (fixP->fx_size)
1421 {
1422 case 4:
1423 insn = bfd_getl16 (fixpos) << 16 | bfd_getl16 (fixpos + 2);
1424 break;
1425 case 2:
1426 insn = bfd_getl16 (fixpos);
1427 break;
1428 default:
1429 as_bad_where (fixP->fx_file, fixP->fx_line,
1430 _("unknown fixup size"));
1431 }
1432 }
1433
1434 insn = insert_operand (insn, operand, (offsetT) value,
1435 fixP->fx_file, fixP->fx_line);
1436
1437 md_number_to_chars_midend (fixpos, insn, fixP->fx_size);
1438 }
1439
1440 /* Prepare machine-dependent frags for relaxation.
1441
1442 Called just before relaxation starts. Any symbol that is now undefined
1443 will not become defined.
1444
1445 Return the correct fr_subtype in the frag.
1446
1447 Return the initial "guess for fr_var" to caller. The guess for fr_var
1448 is *actually* the growth beyond fr_fix. Whatever we do to grow fr_fix
1449 or fr_var contributes to our returned value.
1450
1451 Although it may not be explicit in the frag, pretend
1452 fr_var starts with a value. */
1453
1454 int
1455 md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED,
1456 segT segment ATTRIBUTE_UNUSED)
1457 {
1458 int growth = 4;
1459
1460 fragP->fr_var = 4;
1461 pr_debug ("%s:%d: md_estimate_size_before_relax: %d\n",
1462 fragP->fr_file, fragP->fr_line, growth);
1463
1464 as_fatal (_("md_estimate_size_before_relax\n"));
1465 return growth;
1466 }
1467
1468 /* Translate internal representation of relocation info to BFD target
1469 format. */
1470
1471 arelent *
1472 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED,
1473 fixS *fixP)
1474 {
1475 arelent *reloc;
1476 bfd_reloc_code_real_type code;
1477
1478 reloc = (arelent *) xmalloc (sizeof (* reloc));
1479 reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
1480 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
1481 reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
1482
1483 /* Make sure none of our internal relocations make it this far.
1484 They'd better have been fully resolved by this point. */
1485 gas_assert ((int) fixP->fx_r_type > 0);
1486
1487 code = fixP->fx_r_type;
1488
1489 /* if we have something like add gp, pcl,
1490 _GLOBAL_OFFSET_TABLE_@gotpc. */
1491 if (code == BFD_RELOC_ARC_GOTPC32
1492 && GOT_symbol
1493 && fixP->fx_addsy == GOT_symbol)
1494 code = BFD_RELOC_ARC_GOTPC;
1495
1496 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
1497 if (reloc->howto == NULL)
1498 {
1499 as_bad_where (fixP->fx_file, fixP->fx_line,
1500 _("cannot represent `%s' relocation in object file"),
1501 bfd_get_reloc_code_name (code));
1502 return NULL;
1503 }
1504
1505 if (!fixP->fx_pcrel != !reloc->howto->pc_relative)
1506 as_fatal (_("internal error? cannot generate `%s' relocation"),
1507 bfd_get_reloc_code_name (code));
1508
1509 gas_assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
1510
1511 if (code == BFD_RELOC_ARC_TLS_DTPOFF
1512 || code == BFD_RELOC_ARC_TLS_DTPOFF_S9)
1513 {
1514 asymbol *sym
1515 = fixP->fx_subsy ? symbol_get_bfdsym (fixP->fx_subsy) : NULL;
1516 /* We just want to store a 24 bit index, but we have to wait
1517 till after write_contents has been called via
1518 bfd_map_over_sections before we can get the index from
1519 _bfd_elf_symbol_from_bfd_symbol. Thus, the write_relocs
1520 function is elf32-arc.c has to pick up the slack.
1521 Unfortunately, this leads to problems with hosts that have
1522 pointers wider than long (bfd_vma). There would be various
1523 ways to handle this, all error-prone :-( */
1524 reloc->addend = (bfd_vma) sym;
1525 if ((asymbol *) reloc->addend != sym)
1526 {
1527 as_bad ("Can't store pointer\n");
1528 return NULL;
1529 }
1530 }
1531 else
1532 reloc->addend = fixP->fx_offset;
1533
1534 return reloc;
1535 }
1536
1537 /* Perform post-processing of machine-dependent frags after relaxation.
1538 Called after relaxation is finished.
1539 In: Address of frag.
1540 fr_type == rs_machine_dependent.
1541 fr_subtype is what the address relaxed to.
1542
1543 Out: Any fixS:s and constants are set up. */
1544
1545 void
1546 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
1547 segT segment ATTRIBUTE_UNUSED,
1548 fragS *fragP ATTRIBUTE_UNUSED)
1549 {
1550 pr_debug ("%s:%d: md_convert_frag, subtype: %d, fix: %d, var: %d\n",
1551 fragP->fr_file, fragP->fr_line,
1552 fragP->fr_subtype, fragP->fr_fix, fragP->fr_var);
1553 abort ();
1554 }
1555
1556 /* We have no need to default values of symbols. We could catch
1557 register names here, but that is handled by inserting them all in
1558 the symbol table to begin with. */
1559
1560 symbolS *
1561 md_undefined_symbol (char *name)
1562 {
1563 /* The arc abi demands that a GOT[0] should be referencible as
1564 [pc+_DYNAMIC@gotpc]. Hence we convert a _DYNAMIC@gotpc to a
1565 GOTPC reference to _GLOBAL_OFFSET_TABLE_. */
1566 if (((*name == '_')
1567 && (*(name+1) == 'G')
1568 && (strcmp (name, GLOBAL_OFFSET_TABLE_NAME) == 0))
1569 || ((*name == '_')
1570 && (*(name+1) == 'D')
1571 && (strcmp (name, DYNAMIC_STRUCT_NAME) == 0)))
1572 {
1573 if (!GOT_symbol)
1574 {
1575 if (symbol_find (name))
1576 as_bad ("GOT already in symbol table");
1577
1578 GOT_symbol = symbol_new (GLOBAL_OFFSET_TABLE_NAME, undefined_section,
1579 (valueT) 0, &zero_address_frag);
1580 };
1581 return GOT_symbol;
1582 }
1583 return NULL;
1584 }
1585
1586 /* Turn a string in input_line_pointer into a floating point constant
1587 of type type, and store the appropriate bytes in *litP. The number
1588 of LITTLENUMS emitted is stored in *sizeP. An error message is
1589 returned, or NULL on OK. */
1590
1591 char *
1592 md_atof (int type, char *litP, int *sizeP)
1593 {
1594 return ieee_md_atof (type, litP, sizeP, target_big_endian);
1595 }
1596
1597 /* Called for any expression that can not be recognized. When the
1598 function is called, `input_line_pointer' will point to the start of
1599 the expression. */
1600
1601 void
1602 md_operand (expressionS *expressionP ATTRIBUTE_UNUSED)
1603 {
1604 char *p = input_line_pointer;
1605 if (*p == '@')
1606 {
1607 input_line_pointer++;
1608 expressionP->X_op = O_symbol;
1609 expression (expressionP);
1610 }
1611 }
1612
1613 /* This function is called from the function 'expression', it attempts
1614 to parse special names (in our case register names). It fills in
1615 the expression with the identified register. It returns TRUE if
1616 it is a register and FALSE otherwise. */
1617
1618 bfd_boolean
1619 arc_parse_name (const char *name,
1620 struct expressionS *e)
1621 {
1622 struct symbol *sym;
1623
1624 if (!assembling_insn)
1625 return FALSE;
1626
1627 /* Handle only registers. */
1628 if (e->X_op != O_absent)
1629 return FALSE;
1630
1631 sym = hash_find (arc_reg_hash, name);
1632 if (sym)
1633 {
1634 e->X_op = O_register;
1635 e->X_add_number = S_GET_VALUE (sym);
1636 return TRUE;
1637 }
1638 return FALSE;
1639 }
1640
1641 /* md_parse_option
1642 Invocation line includes a switch not recognized by the base assembler.
1643 See if it's a processor-specific option.
1644
1645 New options (supported) are:
1646
1647 -mcpu=<cpu name> Assemble for selected processor
1648 -EB/-mbig-endian Big-endian
1649 -EL/-mlittle-endian Little-endian
1650
1651 The following CPU names are recognized:
1652 arc700, av2em, av2hs. */
1653
1654 int
1655 md_parse_option (int c, char *arg ATTRIBUTE_UNUSED)
1656 {
1657 int cpu_flags = EF_ARC_CPU_GENERIC;
1658
1659 switch (c)
1660 {
1661 case OPTION_ARC600:
1662 case OPTION_ARC601:
1663 return md_parse_option (OPTION_MCPU, "arc600");
1664
1665 case OPTION_ARC700:
1666 return md_parse_option (OPTION_MCPU, "arc700");
1667
1668 case OPTION_ARCEM:
1669 return md_parse_option (OPTION_MCPU, "arcem");
1670
1671 case OPTION_ARCHS:
1672 return md_parse_option (OPTION_MCPU, "archs");
1673
1674 case OPTION_MCPU:
1675 {
1676 int i;
1677 char *s = alloca (strlen (arg) + 1);
1678
1679 {
1680 char *t = s;
1681 char *arg1 = arg;
1682
1683 do
1684 *t = TOLOWER (*arg1++);
1685 while (*t++);
1686 }
1687
1688 for (i = 0; cpu_types[i].name; ++i)
1689 {
1690 if (!strcmp (cpu_types[i].name, s))
1691 {
1692 arc_target = cpu_types[i].flags;
1693 arc_target_name = cpu_types[i].name;
1694 arc_features = cpu_types[i].features;
1695 arc_mach_type = cpu_types[i].mach;
1696 cpu_flags = cpu_types[i].eflags;
1697
1698 mach_type_specified_p = 1;
1699 break;
1700 }
1701 }
1702
1703 if (!cpu_types[i].name)
1704 {
1705 as_fatal (_("unknown architecture: %s\n"), arg);
1706 }
1707 break;
1708 }
1709
1710 case OPTION_EB:
1711 arc_target_format = "elf32-bigarc";
1712 byte_order = BIG_ENDIAN;
1713 break;
1714
1715 case OPTION_EL:
1716 arc_target_format = "elf32-littlearc";
1717 byte_order = LITTLE_ENDIAN;
1718 break;
1719
1720 case OPTION_CD:
1721 /* This option has an effect only on ARC EM. */
1722 if (arc_target & ARC_OPCODE_ARCv2EM)
1723 arc_features |= ARC_CD;
1724 break;
1725
1726 case OPTION_USER_MODE:
1727 case OPTION_LD_EXT_MASK:
1728 case OPTION_SWAP:
1729 case OPTION_NORM:
1730 case OPTION_BARREL_SHIFT:
1731 case OPTION_MIN_MAX:
1732 case OPTION_NO_MPY:
1733 case OPTION_EA:
1734 case OPTION_MUL64:
1735 case OPTION_SIMD:
1736 case OPTION_SPFP:
1737 case OPTION_DPFP:
1738 case OPTION_XMAC_D16:
1739 case OPTION_XMAC_24:
1740 case OPTION_DSP_PACKA:
1741 case OPTION_CRC:
1742 case OPTION_DVBF:
1743 case OPTION_TELEPHONY:
1744 case OPTION_XYMEMORY:
1745 case OPTION_LOCK:
1746 case OPTION_SWAPE:
1747 case OPTION_RTSC:
1748 case OPTION_FPUDA:
1749 /* Dummy options. */
1750 break;
1751
1752 default:
1753 return 0;
1754 }
1755
1756 if (cpu_flags != EF_ARC_CPU_GENERIC)
1757 arc_eflag = (arc_eflag & ~EF_ARC_MACH_MSK) | cpu_flags;
1758
1759 return 1;
1760 }
1761
1762 void
1763 md_show_usage (FILE *stream)
1764 {
1765 fprintf (stream, _("ARC-specific assembler options:\n"));
1766
1767 fprintf (stream, " -mcpu=<cpu name>\t assemble for CPU <cpu name>\n");
1768 fprintf (stream,
1769 " -mcode-density\t enable code density option for ARC EM\n");
1770
1771 fprintf (stream, _("\
1772 -EB assemble code for a big-endian cpu\n"));
1773 fprintf (stream, _("\
1774 -EL assemble code for a little-endian cpu\n"));
1775 }
1776
1777 static void
1778 preprocess_operands (const struct arc_opcode *opcode,
1779 expressionS *tok,
1780 int ntok)
1781 {
1782 int i;
1783 size_t len;
1784 const char *p;
1785 unsigned j;
1786 const struct arc_aux_reg *auxr;
1787
1788 for (i = 0; i < ntok; i++)
1789 {
1790 switch (tok[i].X_op)
1791 {
1792 case O_illegal:
1793 case O_absent:
1794 break; /* Throw and error. */
1795
1796 case O_symbol:
1797 if (opcode->class != AUXREG)
1798 break;
1799 /* Convert the symbol to a constant if possible. */
1800 p = S_GET_NAME (tok[i].X_add_symbol);
1801 len = strlen (p);
1802
1803 auxr = &arc_aux_regs[0];
1804 for (j = 0; j < arc_num_aux_regs; j++, auxr++)
1805 if (len == auxr->length
1806 && strcasecmp (auxr->name, p) == 0)
1807 {
1808 tok[i].X_op = O_constant;
1809 tok[i].X_add_number = auxr->address;
1810 break;
1811 }
1812 break;
1813 default:
1814 break;
1815 }
1816 }
1817 }
1818
1819 /* Given an opcode name, pre-tockenized set of argumenst and the
1820 opcode flags, take it all the way through emission. */
1821
1822 static void
1823 assemble_tokens (const char *opname,
1824 expressionS *tok,
1825 int ntok,
1826 struct arc_flags *pflags,
1827 int nflgs)
1828 {
1829 bfd_boolean found_something = FALSE;
1830 const struct arc_opcode *opcode;
1831 int cpumatch = 1;
1832
1833 /* Search opcodes. */
1834 opcode = (const struct arc_opcode *) hash_find (arc_opcode_hash, opname);
1835
1836 /* Couldn't find opcode conventional way, try special cases. */
1837 if (!opcode)
1838 opcode = find_special_case (opname, &nflgs, pflags, tok, &ntok);
1839
1840 if (opcode)
1841 {
1842 pr_debug ("%s:%d: assemble_tokens: %s trying opcode 0x%08X\n",
1843 frag_now->fr_file, frag_now->fr_line, opcode->name,
1844 opcode->opcode);
1845
1846 preprocess_operands (opcode, tok, ntok);
1847
1848 found_something = TRUE;
1849 opcode = find_opcode_match (opcode, tok, &ntok, pflags, nflgs, &cpumatch);
1850 if (opcode)
1851 {
1852 struct arc_insn insn;
1853 assemble_insn (opcode, tok, ntok, pflags, nflgs, &insn);
1854 emit_insn (&insn);
1855 return;
1856 }
1857 }
1858
1859 if (found_something)
1860 {
1861 if (cpumatch)
1862 as_bad (_("inappropriate arguments for opcode '%s'"), opname);
1863 else
1864 as_bad (_("opcode '%s' not supported for target %s"), opname,
1865 arc_target_name);
1866 }
1867 else
1868 as_bad (_("unknown opcode '%s'"), opname);
1869 }
1870
1871 /* Used to find special case opcode. */
1872
1873 static const struct arc_opcode *
1874 find_special_case (const char *opname,
1875 int *nflgs,
1876 struct arc_flags *pflags,
1877 expressionS *tok,
1878 int *ntok)
1879 {
1880 const struct arc_opcode *opcode;
1881
1882 opcode = find_special_case_pseudo (opname, ntok, tok, nflgs, pflags);
1883
1884 if (opcode == NULL)
1885 opcode = find_special_case_flag (opname, nflgs, pflags);
1886
1887 return opcode;
1888 }
1889
1890 /* Swap operand tokens. */
1891
1892 static void
1893 swap_operand (expressionS *operand_array,
1894 unsigned source,
1895 unsigned destination)
1896 {
1897 expressionS cpy_operand;
1898 expressionS *src_operand;
1899 expressionS *dst_operand;
1900 size_t size;
1901
1902 if (source == destination)
1903 return;
1904
1905 src_operand = &operand_array[source];
1906 dst_operand = &operand_array[destination];
1907 size = sizeof (expressionS);
1908
1909 /* Make copy of operand to swap with and swap. */
1910 memcpy (&cpy_operand, dst_operand, size);
1911 memcpy (dst_operand, src_operand, size);
1912 memcpy (src_operand, &cpy_operand, size);
1913 }
1914
1915 /* Check if *op matches *tok type.
1916 Returns FALSE if they don't match, TRUE if they match. */
1917
1918 static bfd_boolean
1919 pseudo_operand_match (const expressionS *tok,
1920 const struct arc_operand_operation *op)
1921 {
1922 offsetT min, max, val;
1923 bfd_boolean ret;
1924 const struct arc_operand *operand_real = &arc_operands[op->operand_idx];
1925
1926 ret = FALSE;
1927 switch (tok->X_op)
1928 {
1929 case O_constant:
1930 if (operand_real->bits == 32 && (operand_real->flags & ARC_OPERAND_LIMM))
1931 ret = 1;
1932 else if (!(operand_real->flags & ARC_OPERAND_IR))
1933 {
1934 val = tok->X_add_number;
1935 if (operand_real->flags & ARC_OPERAND_SIGNED)
1936 {
1937 max = (1 << (operand_real->bits - 1)) - 1;
1938 min = -(1 << (operand_real->bits - 1));
1939 }
1940 else
1941 {
1942 max = (1 << operand_real->bits) - 1;
1943 min = 0;
1944 }
1945 if (min <= val && val <= max)
1946 ret = TRUE;
1947 }
1948 break;
1949
1950 case O_symbol:
1951 /* Handle all symbols as long immediates or signed 9. */
1952 if (operand_real->flags & ARC_OPERAND_LIMM ||
1953 ((operand_real->flags & ARC_OPERAND_SIGNED) && operand_real->bits == 9))
1954 ret = TRUE;
1955 break;
1956
1957 case O_register:
1958 if (operand_real->flags & ARC_OPERAND_IR)
1959 ret = TRUE;
1960 break;
1961
1962 case O_bracket:
1963 if (operand_real->flags & ARC_OPERAND_BRAKET)
1964 ret = TRUE;
1965 break;
1966
1967 default:
1968 /* Unknown. */
1969 break;
1970 }
1971 return ret;
1972 }
1973
1974 /* Find pseudo instruction in array. */
1975
1976 static const struct arc_pseudo_insn *
1977 find_pseudo_insn (const char *opname,
1978 int ntok,
1979 const expressionS *tok)
1980 {
1981 const struct arc_pseudo_insn *pseudo_insn = NULL;
1982 const struct arc_operand_operation *op;
1983 unsigned int i;
1984 int j;
1985
1986 for (i = 0; i < arc_num_pseudo_insn; ++i)
1987 {
1988 pseudo_insn = &arc_pseudo_insns[i];
1989 if (strcmp (pseudo_insn->mnemonic_p, opname) == 0)
1990 {
1991 op = pseudo_insn->operand;
1992 for (j = 0; j < ntok; ++j)
1993 if (!pseudo_operand_match (&tok[j], &op[j]))
1994 break;
1995
1996 /* Found the right instruction. */
1997 if (j == ntok)
1998 return pseudo_insn;
1999 }
2000 }
2001 return NULL;
2002 }
2003
2004 /* Assumes the expressionS *tok is of sufficient size. */
2005
2006 static const struct arc_opcode *
2007 find_special_case_pseudo (const char *opname,
2008 int *ntok,
2009 expressionS *tok,
2010 int *nflgs,
2011 struct arc_flags *pflags)
2012 {
2013 const struct arc_pseudo_insn *pseudo_insn = NULL;
2014 const struct arc_operand_operation *operand_pseudo;
2015 const struct arc_operand *operand_real;
2016 unsigned i;
2017 char construct_operand[MAX_CONSTR_STR];
2018
2019 /* Find whether opname is in pseudo instruction array. */
2020 pseudo_insn = find_pseudo_insn (opname, *ntok, tok);
2021
2022 if (pseudo_insn == NULL)
2023 return NULL;
2024
2025 /* Handle flag, Limited to one flag at the moment. */
2026 if (pseudo_insn->flag_r != NULL)
2027 *nflgs += tokenize_flags (pseudo_insn->flag_r, &pflags[*nflgs],
2028 MAX_INSN_FLGS - *nflgs);
2029
2030 /* Handle operand operations. */
2031 for (i = 0; i < pseudo_insn->operand_cnt; ++i)
2032 {
2033 operand_pseudo = &pseudo_insn->operand[i];
2034 operand_real = &arc_operands[operand_pseudo->operand_idx];
2035
2036 if (operand_real->flags & ARC_OPERAND_BRAKET &&
2037 !operand_pseudo->needs_insert)
2038 continue;
2039
2040 /* Has to be inserted (i.e. this token does not exist yet). */
2041 if (operand_pseudo->needs_insert)
2042 {
2043 if (operand_real->flags & ARC_OPERAND_BRAKET)
2044 {
2045 tok[i].X_op = O_bracket;
2046 ++(*ntok);
2047 continue;
2048 }
2049
2050 /* Check if operand is a register or constant and handle it
2051 by type. */
2052 if (operand_real->flags & ARC_OPERAND_IR)
2053 snprintf (construct_operand, MAX_CONSTR_STR, "r%d",
2054 operand_pseudo->count);
2055 else
2056 snprintf (construct_operand, MAX_CONSTR_STR, "%d",
2057 operand_pseudo->count);
2058
2059 tokenize_arguments (construct_operand, &tok[i], 1);
2060 ++(*ntok);
2061 }
2062
2063 else if (operand_pseudo->count)
2064 {
2065 /* Operand number has to be adjusted accordingly (by operand
2066 type). */
2067 switch (tok[i].X_op)
2068 {
2069 case O_constant:
2070 tok[i].X_add_number += operand_pseudo->count;
2071 break;
2072
2073 case O_symbol:
2074 break;
2075
2076 default:
2077 /* Ignored. */
2078 break;
2079 }
2080 }
2081 }
2082
2083 /* Swap operands if necessary. Only supports one swap at the
2084 moment. */
2085 for (i = 0; i < pseudo_insn->operand_cnt; ++i)
2086 {
2087 operand_pseudo = &pseudo_insn->operand[i];
2088
2089 if (operand_pseudo->swap_operand_idx == i)
2090 continue;
2091
2092 swap_operand (tok, i, operand_pseudo->swap_operand_idx);
2093
2094 /* Prevent a swap back later by breaking out. */
2095 break;
2096 }
2097
2098 return (const struct arc_opcode *)
2099 hash_find (arc_opcode_hash, pseudo_insn->mnemonic_r);
2100 }
2101
2102 static const struct arc_opcode *
2103 find_special_case_flag (const char *opname,
2104 int *nflgs,
2105 struct arc_flags *pflags)
2106 {
2107 unsigned int i;
2108 const char *flagnm;
2109 unsigned flag_idx, flag_arr_idx;
2110 size_t flaglen, oplen;
2111 const struct arc_flag_special *arc_flag_special_opcode;
2112 const struct arc_opcode *opcode;
2113
2114 /* Search for special case instruction. */
2115 for (i = 0; i < arc_num_flag_special; i++)
2116 {
2117 arc_flag_special_opcode = &arc_flag_special_cases[i];
2118 oplen = strlen (arc_flag_special_opcode->name);
2119
2120 if (strncmp (opname, arc_flag_special_opcode->name, oplen) != 0)
2121 continue;
2122
2123 /* Found a potential special case instruction, now test for
2124 flags. */
2125 for (flag_arr_idx = 0;; ++flag_arr_idx)
2126 {
2127 flag_idx = arc_flag_special_opcode->flags[flag_arr_idx];
2128 if (flag_idx == 0)
2129 break; /* End of array, nothing found. */
2130
2131 flagnm = arc_flag_operands[flag_idx].name;
2132 flaglen = strlen (flagnm);
2133 if (strcmp (opname + oplen, flagnm) == 0)
2134 {
2135 opcode = (const struct arc_opcode *)
2136 hash_find (arc_opcode_hash,
2137 arc_flag_special_opcode->name);
2138
2139 if (*nflgs + 1 > MAX_INSN_FLGS)
2140 break;
2141 memcpy (pflags[*nflgs].name, flagnm, flaglen);
2142 pflags[*nflgs].name[flaglen] = '\0';
2143 (*nflgs)++;
2144 return opcode;
2145 }
2146 }
2147 }
2148 return NULL;
2149 }
2150
2151 /* Check whether a symbol involves a register. */
2152
2153 static int
2154 contains_register (symbolS *sym)
2155 {
2156 if (sym)
2157 {
2158 expressionS *ex = symbol_get_value_expression (sym);
2159 return ((O_register == ex->X_op)
2160 && !contains_register (ex->X_add_symbol)
2161 && !contains_register (ex->X_op_symbol));
2162 }
2163 else
2164 return 0;
2165 }
2166
2167 /* Returns the register number within a symbol. */
2168
2169 static int
2170 get_register (symbolS *sym)
2171 {
2172 if (!contains_register (sym))
2173 return -1;
2174
2175 expressionS *ex = symbol_get_value_expression (sym);
2176 return regno (ex->X_add_number);
2177 }
2178
2179 /* Allocates a tok entry. */
2180
2181 static int
2182 allocate_tok (expressionS *tok, int ntok, int cidx)
2183 {
2184 if (ntok > MAX_INSN_ARGS - 2)
2185 return 0; /* No space left. */
2186
2187 if (cidx > ntok)
2188 return 0; /* Incorect args. */
2189
2190 memcpy (&tok[ntok+1], &tok[ntok], sizeof (*tok));
2191
2192 if (cidx == ntok)
2193 return 1; /* Success. */
2194 return allocate_tok (tok, ntok - 1, cidx);
2195 }
2196
2197 /* Return true if a RELOC is generic. A generic reloc is PC-rel of a
2198 simple ME relocation (e.g. RELOC_ARC_32_ME, BFD_RELOC_ARC_PC32. */
2199
2200 static bfd_boolean
2201 generic_reloc_p (extended_bfd_reloc_code_real_type reloc)
2202 {
2203 if (!reloc)
2204 return FALSE;
2205
2206 switch (reloc)
2207 {
2208 case BFD_RELOC_ARC_SDA_LDST:
2209 case BFD_RELOC_ARC_SDA_LDST1:
2210 case BFD_RELOC_ARC_SDA_LDST2:
2211 case BFD_RELOC_ARC_SDA16_LD:
2212 case BFD_RELOC_ARC_SDA16_LD1:
2213 case BFD_RELOC_ARC_SDA16_LD2:
2214 case BFD_RELOC_ARC_SDA16_ST2:
2215 case BFD_RELOC_ARC_SDA32_ME:
2216 return FALSE;
2217 default:
2218 break;
2219 }
2220 return TRUE;
2221 }
2222
2223 /* Search forward through all variants of an opcode looking for a
2224 syntax match. */
2225
2226 static const struct arc_opcode *
2227 find_opcode_match (const struct arc_opcode *first_opcode,
2228 expressionS *tok,
2229 int *pntok,
2230 struct arc_flags *first_pflag,
2231 int nflgs,
2232 int *pcpumatch)
2233 {
2234 const struct arc_opcode *opcode = first_opcode;
2235 int ntok = *pntok;
2236 int got_cpu_match = 0;
2237 expressionS bktok[MAX_INSN_ARGS];
2238 int bkntok;
2239 expressionS emptyE;
2240
2241 memset (&emptyE, 0, sizeof (emptyE));
2242 memcpy (bktok, tok, MAX_INSN_ARGS * sizeof (*tok));
2243 bkntok = ntok;
2244
2245 do
2246 {
2247 const unsigned char *opidx;
2248 const unsigned char *flgidx;
2249 int tokidx = 0;
2250 const expressionS *t = &emptyE;
2251
2252 pr_debug ("%s:%d: find_opcode_match: trying opcode 0x%08X ",
2253 frag_now->fr_file, frag_now->fr_line, opcode->opcode);
2254
2255 /* Don't match opcodes that don't exist on this
2256 architecture. */
2257 if (!(opcode->cpu & arc_target))
2258 goto match_failed;
2259
2260 if (is_code_density_p (opcode) && !(arc_features & ARC_CD))
2261 goto match_failed;
2262
2263 got_cpu_match = 1;
2264 pr_debug ("cpu ");
2265
2266 /* Check the operands. */
2267 for (opidx = opcode->operands; *opidx; ++opidx)
2268 {
2269 const struct arc_operand *operand = &arc_operands[*opidx];
2270
2271 /* Only take input from real operands. */
2272 if ((operand->flags & ARC_OPERAND_FAKE)
2273 && !(operand->flags & ARC_OPERAND_BRAKET))
2274 continue;
2275
2276 /* When we expect input, make sure we have it. */
2277 if (tokidx >= ntok)
2278 goto match_failed;
2279
2280 /* Match operand type with expression type. */
2281 switch (operand->flags & ARC_OPERAND_TYPECHECK_MASK)
2282 {
2283 case ARC_OPERAND_IR:
2284 /* Check to be a register. */
2285 if ((tok[tokidx].X_op != O_register
2286 || !is_ir_num (tok[tokidx].X_add_number))
2287 && !(operand->flags & ARC_OPERAND_IGNORE))
2288 goto match_failed;
2289
2290 /* If expect duplicate, make sure it is duplicate. */
2291 if (operand->flags & ARC_OPERAND_DUPLICATE)
2292 {
2293 /* Check for duplicate. */
2294 if (t->X_op != O_register
2295 || !is_ir_num (t->X_add_number)
2296 || (regno (t->X_add_number) !=
2297 regno (tok[tokidx].X_add_number)))
2298 goto match_failed;
2299 }
2300
2301 /* Special handling? */
2302 if (operand->insert)
2303 {
2304 const char *errmsg = NULL;
2305 (*operand->insert)(0,
2306 regno (tok[tokidx].X_add_number),
2307 &errmsg);
2308 if (errmsg)
2309 {
2310 if (operand->flags & ARC_OPERAND_IGNORE)
2311 {
2312 /* Missing argument, create one. */
2313 if (!allocate_tok (tok, ntok - 1, tokidx))
2314 goto match_failed;
2315
2316 tok[tokidx].X_op = O_absent;
2317 ++ntok;
2318 }
2319 else
2320 goto match_failed;
2321 }
2322 }
2323
2324 t = &tok[tokidx];
2325 break;
2326
2327 case ARC_OPERAND_BRAKET:
2328 /* Check if bracket is also in opcode table as
2329 operand. */
2330 if (tok[tokidx].X_op != O_bracket)
2331 goto match_failed;
2332 break;
2333
2334 case ARC_OPERAND_LIMM:
2335 case ARC_OPERAND_SIGNED:
2336 case ARC_OPERAND_UNSIGNED:
2337 switch (tok[tokidx].X_op)
2338 {
2339 case O_illegal:
2340 case O_absent:
2341 case O_register:
2342 goto match_failed;
2343
2344 case O_bracket:
2345 /* Got an (too) early bracket, check if it is an
2346 ignored operand. N.B. This procedure works only
2347 when bracket is the last operand! */
2348 if (!(operand->flags & ARC_OPERAND_IGNORE))
2349 goto match_failed;
2350 /* Insert the missing operand. */
2351 if (!allocate_tok (tok, ntok - 1, tokidx))
2352 goto match_failed;
2353
2354 tok[tokidx].X_op = O_absent;
2355 ++ntok;
2356 break;
2357
2358 case O_constant:
2359 /* Check the range. */
2360 if (operand->bits != 32
2361 && !(operand->flags & ARC_OPERAND_NCHK))
2362 {
2363 offsetT min, max, val;
2364 val = tok[tokidx].X_add_number;
2365
2366 if (operand->flags & ARC_OPERAND_SIGNED)
2367 {
2368 max = (1 << (operand->bits - 1)) - 1;
2369 min = -(1 << (operand->bits - 1));
2370 }
2371 else
2372 {
2373 max = (1 << operand->bits) - 1;
2374 min = 0;
2375 }
2376
2377 if (val < min || val > max)
2378 goto match_failed;
2379
2380 /* Check alignmets. */
2381 if ((operand->flags & ARC_OPERAND_ALIGNED32)
2382 && (val & 0x03))
2383 goto match_failed;
2384
2385 if ((operand->flags & ARC_OPERAND_ALIGNED16)
2386 && (val & 0x01))
2387 goto match_failed;
2388 }
2389 else if (operand->flags & ARC_OPERAND_NCHK)
2390 {
2391 if (operand->insert)
2392 {
2393 const char *errmsg = NULL;
2394 (*operand->insert)(0,
2395 tok[tokidx].X_add_number,
2396 &errmsg);
2397 if (errmsg)
2398 goto match_failed;
2399 }
2400 else
2401 goto match_failed;
2402 }
2403 break;
2404
2405 case O_subtract:
2406 /* Check if it is register range. */
2407 if ((tok[tokidx].X_add_number == 0)
2408 && contains_register (tok[tokidx].X_add_symbol)
2409 && contains_register (tok[tokidx].X_op_symbol))
2410 {
2411 int regs;
2412
2413 regs = get_register (tok[tokidx].X_add_symbol);
2414 regs <<= 16;
2415 regs |= get_register (tok[tokidx].X_op_symbol);
2416 if (operand->insert)
2417 {
2418 const char *errmsg = NULL;
2419 (*operand->insert)(0,
2420 regs,
2421 &errmsg);
2422 if (errmsg)
2423 goto match_failed;
2424 }
2425 else
2426 goto match_failed;
2427 break;
2428 }
2429 default:
2430 if (operand->default_reloc == 0)
2431 goto match_failed; /* The operand needs relocation. */
2432
2433 /* Relocs requiring long immediate. FIXME! make it
2434 generic and move it to a function. */
2435 switch (tok[tokidx].X_md)
2436 {
2437 case O_gotoff:
2438 case O_gotpc:
2439 case O_pcl:
2440 case O_tpoff:
2441 case O_dtpoff:
2442 case O_tlsgd:
2443 case O_tlsie:
2444 if (!(operand->flags & ARC_OPERAND_LIMM))
2445 goto match_failed;
2446 case O_absent:
2447 if (!generic_reloc_p (operand->default_reloc))
2448 goto match_failed;
2449 default:
2450 break;
2451 }
2452 break;
2453 }
2454 /* If expect duplicate, make sure it is duplicate. */
2455 if (operand->flags & ARC_OPERAND_DUPLICATE)
2456 {
2457 if (t->X_op == O_illegal
2458 || t->X_op == O_absent
2459 || t->X_op == O_register
2460 || (t->X_add_number != tok[tokidx].X_add_number))
2461 goto match_failed;
2462 }
2463 t = &tok[tokidx];
2464 break;
2465
2466 default:
2467 /* Everything else should have been fake. */
2468 abort ();
2469 }
2470
2471 ++tokidx;
2472 }
2473 pr_debug ("opr ");
2474
2475 /* Check the flags. Iterate over the valid flag classes. */
2476 int lnflg = nflgs;
2477
2478 for (flgidx = opcode->flags; *flgidx && lnflg; ++flgidx)
2479 {
2480 /* Get a valid flag class. */
2481 const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
2482 const unsigned *flgopridx;
2483
2484 for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
2485 {
2486 const struct arc_flag_operand *flg_operand;
2487 struct arc_flags *pflag = first_pflag;
2488 int i;
2489
2490 flg_operand = &arc_flag_operands[*flgopridx];
2491 for (i = 0; i < nflgs; i++, pflag++)
2492 {
2493 /* Match against the parsed flags. */
2494 if (!strcmp (flg_operand->name, pflag->name))
2495 {
2496 /*TODO: Check if it is duplicated. */
2497 pflag->code = *flgopridx;
2498 lnflg--;
2499 break; /* goto next flag class and parsed flag. */
2500 }
2501 }
2502 }
2503 }
2504 /* Did I check all the parsed flags? */
2505 if (lnflg)
2506 goto match_failed;
2507
2508 pr_debug ("flg");
2509 /* Possible match -- did we use all of our input? */
2510 if (tokidx == ntok)
2511 {
2512 *pntok = ntok;
2513 pr_debug ("\n");
2514 return opcode;
2515 }
2516
2517 match_failed:;
2518 pr_debug ("\n");
2519 /* Restore the original parameters. */
2520 memcpy (tok, bktok, MAX_INSN_ARGS * sizeof (*tok));
2521 ntok = bkntok;
2522 }
2523 while (++opcode - arc_opcodes < (int) arc_num_opcodes
2524 && !strcmp (opcode->name, first_opcode->name));
2525
2526 if (*pcpumatch)
2527 *pcpumatch = got_cpu_match;
2528
2529 return NULL;
2530 }
2531
2532 /* Find the proper relocation for the given opcode. */
2533
2534 static extended_bfd_reloc_code_real_type
2535 find_reloc (const char *name,
2536 const char *opcodename,
2537 const struct arc_flags *pflags,
2538 int nflg,
2539 extended_bfd_reloc_code_real_type reloc)
2540 {
2541 unsigned int i;
2542 int j;
2543 bfd_boolean found_flag;
2544 extended_bfd_reloc_code_real_type ret = BFD_RELOC_UNUSED;
2545
2546 for (i = 0; i < arc_num_equiv_tab; i++)
2547 {
2548 const struct arc_reloc_equiv_tab *r = &arc_reloc_equiv[i];
2549
2550 /* Find the entry. */
2551 if (strcmp (name, r->name))
2552 continue;
2553 if (r->mnemonic && (strcmp (r->mnemonic, opcodename)))
2554 continue;
2555 if (r->flagcode)
2556 {
2557 if (!nflg)
2558 continue;
2559 found_flag = FALSE;
2560 for (j = 0; j < nflg; j++)
2561 if (pflags[i].code == r->flagcode)
2562 {
2563 found_flag = TRUE;
2564 break;
2565 }
2566 if (!found_flag)
2567 continue;
2568 }
2569
2570 if (reloc != r->oldreloc)
2571 continue;
2572 /* Found it. */
2573 ret = r->newreloc;
2574 break;
2575 }
2576
2577 if (ret == BFD_RELOC_UNUSED)
2578 as_bad (_("Unable to find %s relocation for instruction %s"),
2579 name, opcodename);
2580 return ret;
2581 }
2582
2583 /* Turn an opcode description and a set of arguments into
2584 an instruction and a fixup. */
2585
2586 static void
2587 assemble_insn (const struct arc_opcode *opcode,
2588 const expressionS *tok,
2589 int ntok,
2590 const struct arc_flags *pflags,
2591 int nflg,
2592 struct arc_insn *insn)
2593 {
2594 const expressionS *reloc_exp = NULL;
2595 unsigned image;
2596 const unsigned char *argidx;
2597 int i;
2598 int tokidx = 0;
2599 unsigned char pcrel = 0;
2600 bfd_boolean needGOTSymbol;
2601 bfd_boolean has_delay_slot = FALSE;
2602 extended_bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
2603
2604 memset (insn, 0, sizeof (*insn));
2605 image = opcode->opcode;
2606
2607 pr_debug ("%s:%d: assemble_insn: %s using opcode %x\n",
2608 frag_now->fr_file, frag_now->fr_line, opcode->name,
2609 opcode->opcode);
2610
2611 /* Handle operands. */
2612 for (argidx = opcode->operands; *argidx; ++argidx)
2613 {
2614 const struct arc_operand *operand = &arc_operands[*argidx];
2615 const expressionS *t = (const expressionS *) 0;
2616
2617 if ((operand->flags & ARC_OPERAND_FAKE)
2618 && !(operand->flags & ARC_OPERAND_BRAKET))
2619 continue;
2620
2621 if (operand->flags & ARC_OPERAND_DUPLICATE)
2622 {
2623 /* Duplicate operand, already inserted. */
2624 tokidx ++;
2625 continue;
2626 }
2627
2628 if (tokidx >= ntok)
2629 {
2630 abort ();
2631 }
2632 else
2633 t = &tok[tokidx++];
2634
2635 /* Regardless if we have a reloc or not mark the instruction
2636 limm if it is the case. */
2637 if (operand->flags & ARC_OPERAND_LIMM)
2638 insn->has_limm = TRUE;
2639
2640 switch (t->X_op)
2641 {
2642 case O_register:
2643 image = insert_operand (image, operand, regno (t->X_add_number),
2644 NULL, 0);
2645 break;
2646
2647 case O_constant:
2648 image = insert_operand (image, operand, t->X_add_number, NULL, 0);
2649 reloc_exp = t;
2650 if (operand->flags & ARC_OPERAND_LIMM)
2651 insn->limm = t->X_add_number;
2652 break;
2653
2654 case O_bracket:
2655 /* Ignore brackets. */
2656 break;
2657
2658 case O_absent:
2659 gas_assert (operand->flags & ARC_OPERAND_IGNORE);
2660 break;
2661
2662 case O_subtract:
2663 /* Maybe register range. */
2664 if ((t->X_add_number == 0)
2665 && contains_register (t->X_add_symbol)
2666 && contains_register (t->X_op_symbol))
2667 {
2668 int regs;
2669
2670 regs = get_register (t->X_add_symbol);
2671 regs <<= 16;
2672 regs |= get_register (t->X_op_symbol);
2673 image = insert_operand (image, operand, regs, NULL, 0);
2674 break;
2675 }
2676
2677 default:
2678 /* This operand needs a relocation. */
2679 needGOTSymbol = FALSE;
2680
2681 switch (t->X_md)
2682 {
2683 case O_plt:
2684 needGOTSymbol = TRUE;
2685 reloc = find_reloc ("plt", opcode->name,
2686 pflags, nflg,
2687 operand->default_reloc);
2688 break;
2689
2690 case O_gotoff:
2691 case O_gotpc:
2692 needGOTSymbol = TRUE;
2693 reloc = ARC_RELOC_TABLE (t->X_md)->reloc;
2694 break;
2695 case O_pcl:
2696 reloc = ARC_RELOC_TABLE (t->X_md)->reloc;
2697 if (ARC_SHORT (opcode->mask))
2698 as_bad_where (frag_now->fr_file, frag_now->fr_line,
2699 _("Unable to use @pcl relocation for insn %s"),
2700 opcode->name);
2701 break;
2702 case O_sda:
2703 reloc = find_reloc ("sda", opcode->name,
2704 pflags, nflg,
2705 operand->default_reloc);
2706 break;
2707 case O_tlsgd:
2708 case O_tlsie:
2709 needGOTSymbol = TRUE;
2710 /* Fall-through. */
2711
2712 case O_tpoff:
2713 case O_dtpoff:
2714 reloc = ARC_RELOC_TABLE (t->X_md)->reloc;
2715 break;
2716
2717 case O_tpoff9: /*FIXME! Check for the conditionality of
2718 the insn. */
2719 case O_dtpoff9: /*FIXME! Check for the conditionality of
2720 the insn. */
2721 as_bad (_("TLS_*_S9 relocs are not supported yet"));
2722 break;
2723
2724 default:
2725 /* Just consider the default relocation. */
2726 reloc = operand->default_reloc;
2727 break;
2728 }
2729
2730 if (needGOTSymbol && (GOT_symbol == NULL))
2731 GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME);
2732
2733 reloc_exp = t;
2734
2735 #if 0
2736 if (reloc > 0)
2737 {
2738 /* sanity checks. */
2739 reloc_howto_type *reloc_howto
2740 = bfd_reloc_type_lookup (stdoutput,
2741 (bfd_reloc_code_real_type) reloc);
2742 unsigned reloc_bitsize = reloc_howto->bitsize;
2743 if (reloc_howto->rightshift)
2744 reloc_bitsize -= reloc_howto->rightshift;
2745 if (reloc_bitsize != operand->bits)
2746 {
2747 as_bad (_("invalid relocation %s for field"),
2748 bfd_get_reloc_code_name (reloc));
2749 return;
2750 }
2751 }
2752 #endif
2753 if (insn->nfixups >= MAX_INSN_FIXUPS)
2754 as_fatal (_("too many fixups"));
2755
2756 struct arc_fixup *fixup;
2757 fixup = &insn->fixups[insn->nfixups++];
2758 fixup->exp = *t;
2759 fixup->reloc = reloc;
2760 pcrel = (operand->flags & ARC_OPERAND_PCREL) ? 1 : 0;
2761 fixup->pcrel = pcrel;
2762 fixup->islong = (operand->flags & ARC_OPERAND_LIMM) ?
2763 TRUE : FALSE;
2764 break;
2765 }
2766 }
2767
2768 /* Handle flags. */
2769 for (i = 0; i < nflg; i++)
2770 {
2771 const struct arc_flag_operand *flg_operand =
2772 &arc_flag_operands[pflags[i].code];
2773
2774 /* Check if the instruction has a delay slot. */
2775 if (!strcmp (flg_operand->name, "d"))
2776 has_delay_slot = TRUE;
2777
2778 /* There is an exceptional case when we cannot insert a flag
2779 just as it is. The .T flag must be handled in relation with
2780 the relative address. */
2781 if (!strcmp (flg_operand->name, "t")
2782 || !strcmp (flg_operand->name, "nt"))
2783 {
2784 unsigned bitYoperand = 0;
2785 /* FIXME! move selection bbit/brcc in arc-opc.c. */
2786 if (!strcmp (flg_operand->name, "t"))
2787 if (!strcmp (opcode->name, "bbit0")
2788 || !strcmp (opcode->name, "bbit1"))
2789 bitYoperand = arc_NToperand;
2790 else
2791 bitYoperand = arc_Toperand;
2792 else
2793 if (!strcmp (opcode->name, "bbit0")
2794 || !strcmp (opcode->name, "bbit1"))
2795 bitYoperand = arc_Toperand;
2796 else
2797 bitYoperand = arc_NToperand;
2798
2799 gas_assert (reloc_exp != NULL);
2800 if (reloc_exp->X_op == O_constant)
2801 {
2802 /* Check if we have a constant and solved it
2803 immediately. */
2804 offsetT val = reloc_exp->X_add_number;
2805 image |= insert_operand (image, &arc_operands[bitYoperand],
2806 val, NULL, 0);
2807 }
2808 else
2809 {
2810 struct arc_fixup *fixup;
2811
2812 if (insn->nfixups >= MAX_INSN_FIXUPS)
2813 as_fatal (_("too many fixups"));
2814
2815 fixup = &insn->fixups[insn->nfixups++];
2816 fixup->exp = *reloc_exp;
2817 fixup->reloc = -bitYoperand;
2818 fixup->pcrel = pcrel;
2819 fixup->islong = FALSE;
2820 }
2821 }
2822 else
2823 image |= (flg_operand->code & ((1 << flg_operand->bits) - 1))
2824 << flg_operand->shift;
2825 }
2826
2827 /* Short instruction? */
2828 insn->short_insn = ARC_SHORT (opcode->mask) ? TRUE : FALSE;
2829
2830 insn->insn = image;
2831
2832 /* Update last insn status. */
2833 arc_last_insns[1] = arc_last_insns[0];
2834 arc_last_insns[0].opcode = opcode;
2835 arc_last_insns[0].has_limm = insn->has_limm;
2836 arc_last_insns[0].has_delay_slot = has_delay_slot;
2837
2838 /* Check if the current instruction is legally used. */
2839 if (arc_last_insns[1].has_delay_slot
2840 && is_br_jmp_insn_p (arc_last_insns[0].opcode))
2841 as_bad_where (frag_now->fr_file, frag_now->fr_line,
2842 _("A jump/branch instruction in delay slot."));
2843 }
2844
2845 /* Actually output an instruction with its fixup. */
2846
2847 static void
2848 emit_insn (struct arc_insn *insn)
2849 {
2850 char *f;
2851 int i;
2852
2853 pr_debug ("Emit insn : 0x%x\n", insn->insn);
2854 pr_debug ("\tShort : 0x%d\n", insn->short_insn);
2855 pr_debug ("\tLong imm: 0x%lx\n", insn->limm);
2856
2857 /* Write out the instruction. */
2858 if (insn->short_insn)
2859 {
2860 if (insn->has_limm)
2861 {
2862 f = frag_more (6);
2863 md_number_to_chars (f, insn->insn, 2);
2864 md_number_to_chars_midend (f + 2, insn->limm, 4);
2865 dwarf2_emit_insn (6);
2866 }
2867 else
2868 {
2869 f = frag_more (2);
2870 md_number_to_chars (f, insn->insn, 2);
2871 dwarf2_emit_insn (2);
2872 }
2873 }
2874 else
2875 {
2876 if (insn->has_limm)
2877 {
2878 f = frag_more (8);
2879 md_number_to_chars_midend (f, insn->insn, 4);
2880 md_number_to_chars_midend (f + 4, insn->limm, 4);
2881 dwarf2_emit_insn (8);
2882 }
2883 else
2884 {
2885 f = frag_more (4);
2886 md_number_to_chars_midend (f, insn->insn, 4);
2887 dwarf2_emit_insn (4);
2888 }
2889 }
2890
2891 /* Apply the fixups in order. */
2892 for (i = 0; i < insn->nfixups; i++)
2893 {
2894 struct arc_fixup *fixup = &insn->fixups[i];
2895 int size, pcrel, offset = 0;
2896
2897 /*FIXME! the reloc size is wrong in the BFD file. When it will
2898 be fixed please delete me. */
2899 size = (insn->short_insn && !fixup->islong) ? 2 : 4;
2900
2901 if (fixup->islong)
2902 offset = (insn->short_insn) ? 2 : 4;
2903
2904 /* Some fixups are only used internally, thus no howto. */
2905 if ((int) fixup->reloc < 0)
2906 {
2907 /*FIXME! the reloc size is wrong in the BFD file. When it
2908 will be fixed please enable me.
2909 size = (insn->short_insn && !fixup->islong) ? 2 : 4; */
2910 pcrel = fixup->pcrel;
2911 }
2912 else
2913 {
2914 reloc_howto_type *reloc_howto =
2915 bfd_reloc_type_lookup (stdoutput,
2916 (bfd_reloc_code_real_type) fixup->reloc);
2917 gas_assert (reloc_howto);
2918 /*FIXME! the reloc size is wrong in the BFD file. When it
2919 will be fixed please enable me.
2920 size = bfd_get_reloc_size (reloc_howto); */
2921 pcrel = reloc_howto->pc_relative;
2922 }
2923
2924 pr_debug ("%s:%d: emit_insn: new %s fixup (PCrel:%s) of size %d @ offset %d\n",
2925 frag_now->fr_file, frag_now->fr_line,
2926 (fixup->reloc < 0) ? "Internal" :
2927 bfd_get_reloc_code_name (fixup->reloc),
2928 pcrel ? "Y" : "N",
2929 size, offset);
2930 fix_new_exp (frag_now, f - frag_now->fr_literal + offset,
2931 size, &fixup->exp, pcrel, fixup->reloc);
2932
2933 /* Check for ZOLs, and update symbol info if any. */
2934 if (LP_INSN (insn->insn))
2935 {
2936 gas_assert (fixup->exp.X_add_symbol);
2937 ARC_SET_FLAG (fixup->exp.X_add_symbol, ARC_FLAG_ZOL);
2938 }
2939 }
2940 }
2941
2942 /* Insert an operand value into an instruction. */
2943
2944 static unsigned
2945 insert_operand (unsigned insn,
2946 const struct arc_operand *operand,
2947 offsetT val,
2948 char *file,
2949 unsigned line)
2950 {
2951 offsetT min = 0, max = 0;
2952
2953 if (operand->bits != 32
2954 && !(operand->flags & ARC_OPERAND_NCHK)
2955 && !(operand->flags & ARC_OPERAND_FAKE))
2956 {
2957 if (operand->flags & ARC_OPERAND_SIGNED)
2958 {
2959 max = (1 << (operand->bits - 1)) - 1;
2960 min = -(1 << (operand->bits - 1));
2961 }
2962 else
2963 {
2964 max = (1 << operand->bits) - 1;
2965 min = 0;
2966 }
2967
2968 if (val < min || val > max)
2969 as_bad_value_out_of_range (_("operand"),
2970 val, min, max, file, line);
2971 }
2972
2973 pr_debug ("insert field: %ld <= %ld <= %ld in 0x%08x\n",
2974 min, val, max, insn);
2975
2976 if ((operand->flags & ARC_OPERAND_ALIGNED32)
2977 && (val & 0x03))
2978 as_bad_where (file, line,
2979 _("Unaligned operand. Needs to be 32bit aligned"));
2980
2981 if ((operand->flags & ARC_OPERAND_ALIGNED16)
2982 && (val & 0x01))
2983 as_bad_where (file, line,
2984 _("Unaligned operand. Needs to be 16bit aligned"));
2985
2986 if (operand->insert)
2987 {
2988 const char *errmsg = NULL;
2989
2990 insn = (*operand->insert) (insn, val, &errmsg);
2991 if (errmsg)
2992 as_warn_where (file, line, "%s", errmsg);
2993 }
2994 else
2995 {
2996 if (operand->flags & ARC_OPERAND_TRUNCATE)
2997 {
2998 if (operand->flags & ARC_OPERAND_ALIGNED32)
2999 val >>= 2;
3000 if (operand->flags & ARC_OPERAND_ALIGNED16)
3001 val >>= 1;
3002 }
3003 insn |= ((val & ((1 << operand->bits) - 1)) << operand->shift);
3004 }
3005 return insn;
3006 }
3007
3008 void
3009 arc_handle_align (fragS* fragP)
3010 {
3011 if ((fragP)->fr_type == rs_align_code)
3012 {
3013 char *dest = (fragP)->fr_literal + (fragP)->fr_fix;
3014 valueT count = ((fragP)->fr_next->fr_address
3015 - (fragP)->fr_address - (fragP)->fr_fix);
3016
3017 (fragP)->fr_var = 2;
3018
3019 if (count & 1)/* Padding in the gap till the next 2-byte
3020 boundary with 0s. */
3021 {
3022 (fragP)->fr_fix++;
3023 *dest++ = 0;
3024 }
3025 /* Writing nop_s. */
3026 md_number_to_chars (dest, NOP_OPCODE_S, 2);
3027 }
3028 }
3029
3030 /* Here we decide which fixups can be adjusted to make them relative
3031 to the beginning of the section instead of the symbol. Basically
3032 we need to make sure that the dynamic relocations are done
3033 correctly, so in some cases we force the original symbol to be
3034 used. */
3035
3036 int
3037 tc_arc_fix_adjustable (fixS *fixP)
3038 {
3039
3040 /* Prevent all adjustments to global symbols. */
3041 if (S_IS_EXTERNAL (fixP->fx_addsy))
3042 return 0;
3043 if (S_IS_WEAK (fixP->fx_addsy))
3044 return 0;
3045
3046 /* Adjust_reloc_syms doesn't know about the GOT. */
3047 switch (fixP->fx_r_type)
3048 {
3049 case BFD_RELOC_ARC_GOTPC32:
3050 case BFD_RELOC_ARC_PLT32:
3051 case BFD_RELOC_ARC_S25H_PCREL_PLT:
3052 case BFD_RELOC_ARC_S21H_PCREL_PLT:
3053 case BFD_RELOC_ARC_S25W_PCREL_PLT:
3054 case BFD_RELOC_ARC_S21W_PCREL_PLT:
3055 return 0;
3056
3057 default:
3058 break;
3059 }
3060
3061 return 0; /* FIXME! return 1, fix it in the linker. */
3062 }
3063
3064 /* Compute the reloc type of an expression EXP. */
3065
3066 static void
3067 arc_check_reloc (expressionS *exp,
3068 bfd_reloc_code_real_type *r_type_p)
3069 {
3070 if (*r_type_p == BFD_RELOC_32
3071 && exp->X_op == O_subtract
3072 && exp->X_op_symbol != NULL
3073 && exp->X_op_symbol->bsym->section == now_seg)
3074 *r_type_p = BFD_RELOC_ARC_32_PCREL;
3075 }
3076
3077
3078 /* Add expression EXP of SIZE bytes to offset OFF of fragment FRAG. */
3079
3080 void
3081 arc_cons_fix_new (fragS *frag,
3082 int off,
3083 int size,
3084 expressionS *exp,
3085 bfd_reloc_code_real_type r_type)
3086 {
3087 r_type = BFD_RELOC_UNUSED;
3088
3089 switch (size)
3090 {
3091 case 1:
3092 r_type = BFD_RELOC_8;
3093 break;
3094
3095 case 2:
3096 r_type = BFD_RELOC_16;
3097 break;
3098
3099 case 3:
3100 r_type = BFD_RELOC_24;
3101 break;
3102
3103 case 4:
3104 r_type = BFD_RELOC_32;
3105 arc_check_reloc (exp, &r_type);
3106 break;
3107
3108 case 8:
3109 r_type = BFD_RELOC_64;
3110 break;
3111
3112 default:
3113 as_bad (_("unsupported BFD relocation size %u"), size);
3114 r_type = BFD_RELOC_UNUSED;
3115 }
3116
3117 fix_new_exp (frag, off, size, exp, 0, r_type);
3118 }
3119
3120 /* The actual routine that checks the ZOL conditions. */
3121
3122 static void
3123 check_zol (symbolS *s)
3124 {
3125 switch (arc_mach_type)
3126 {
3127 case bfd_mach_arc_arcv2:
3128 if (arc_target & ARC_OPCODE_ARCv2EM)
3129 return;
3130
3131 if (is_br_jmp_insn_p (arc_last_insns[0].opcode)
3132 || arc_last_insns[1].has_delay_slot)
3133 as_bad (_("Jump/Branch instruction detected at the end of the ZOL label @%s"),
3134 S_GET_NAME (s));
3135
3136 break;
3137 case bfd_mach_arc_arc600:
3138
3139 if (is_kernel_insn_p (arc_last_insns[0].opcode))
3140 as_bad (_("Kernel instruction detected at the end of the ZOL label @%s"),
3141 S_GET_NAME (s));
3142
3143 if (arc_last_insns[0].has_limm
3144 && is_br_jmp_insn_p (arc_last_insns[0].opcode))
3145 as_bad (_("A jump instruction with long immediate detected at the \
3146 end of the ZOL label @%s"), S_GET_NAME (s));
3147
3148 /* Fall through. */
3149 case bfd_mach_arc_arc700:
3150 if (arc_last_insns[0].has_delay_slot)
3151 as_bad (_("An illegal use of delay slot detected at the end of the ZOL label @%s"),
3152 S_GET_NAME (s));
3153
3154 break;
3155 default:
3156 break;
3157 }
3158 }
3159
3160 /* If ZOL end check the last two instruction for illegals. */
3161 void
3162 arc_frob_label (symbolS * sym)
3163 {
3164 if (ARC_GET_FLAG (sym) & ARC_FLAG_ZOL)
3165 check_zol (sym);
3166
3167 dwarf2_emit_label (sym);
3168 }
3169