1 /* tc-nds32.c -- Assemble for the nds32
2 Copyright (C) 2012-2018 Free Software Foundation, Inc.
3 Contributed by Andes Technology Corporation.
5 This file is part of GAS, the GNU Assembler.
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to the Free
19 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
23 #include "safe-ctype.h"
26 #include "dwarf2dbg.h"
27 #include "dw2gencfi.h"
28 #include "opcodes/nds32-asm.h"
29 #include "elf/nds32.h"
30 #include "bfd/elf32-nds32.h"
34 #include "struc-symbol.h"
35 #include "opcode/nds32.h"
41 /* GAS definitions. */
43 /* Characters which start a comment. */
44 const char comment_chars[] = "!";
45 /* Characters which start a comment when they appear at the start of a line. */
46 const char line_comment_chars[] = "#!";
47 /* Characters which separate lines (null and newline are by default). */
48 const char line_separator_chars[] = ";";
49 /* Characters which may be used as the exponent character
50 in a floating point number. */
51 const char EXP_CHARS[] = "eE";
52 /* Characters which may be used to indicate a floating point constant. */
53 const char FLT_CHARS[] = "dDfF";
55 static int enable_16bit = 1;
56 /* Save for md_assemble to distinguish if this instruction is
57 expanded from the pseudo instruction. */
58 static bfd_boolean pseudo_opcode = FALSE;
59 static struct nds32_relocs_pattern *relocs_list = NULL;
60 /* Save instruction relation to inserting relaxation relocation. */
61 struct nds32_relocs_pattern
68 struct nds32_opcode *opcode;
70 struct nds32_relocs_pattern *next;
71 /* Assembled instruction bytes. */
75 /* Suffix name and relocation. */
79 short unsigned int reloc;
81 static int vec_size = 0;
82 /* If the assembly code is generated by compiler, it is supposed to have
83 ".flag verbatim" at beginning of the content. We have
84 'nds32_flag' to parse it and set this field to be non-zero. */
85 static int verbatim = 0;
86 static struct hash_control *nds32_gprs_hash;
87 static struct hash_control *nds32_hint_hash;
88 #define TLS_REG "$r27"
89 #define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
91 /* Generate relocation for relax or not, and the default is true. */
92 static int enable_relax_relocs = 1;
93 /* Save option -O for performance. */
94 static int optimize = 0;
95 /* Save option -Os for code size. */
96 static int optimize_for_space = 0;
97 /* Flag to save label exist. */
98 static int label_exist = 0;
99 /* Flag to save state in omit_fp region. */
100 static int in_omit_fp = 0;
101 extern struct nds32_keyword keyword_gpr[];
102 /* Tag there is relax relocation having to link. */
103 static bfd_boolean relaxing = FALSE;
110 static enum ict_option ict_flag = ICT_NONE;
113 static struct hash_control *nds32_relax_info_hash;
115 /* Branch patterns. */
116 static relax_info_t relax_table[] =
120 .br_range = BR_RANGE_S16M,
125 .relax_code_seq[BR_RANGE_S256] =
127 INSN_JAL /* jal label */
129 .relax_code_size[BR_RANGE_S256] = 4,
130 .relax_branch_isize[BR_RANGE_S256] = 4,
131 .relax_fixup[BR_RANGE_S256] =
133 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
137 .relax_code_seq[BR_RANGE_S16K] =
139 INSN_JAL /* jal label */
141 .relax_code_size[BR_RANGE_S16K] = 4,
142 .relax_branch_isize[BR_RANGE_S16K] = 4,
143 .relax_fixup[BR_RANGE_S16K] =
145 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
149 .relax_code_seq[BR_RANGE_S64K] =
151 INSN_JAL /* jal label */
153 .relax_code_size[BR_RANGE_S64K] = 4,
154 .relax_branch_isize[BR_RANGE_S64K] = 4,
155 .relax_fixup[BR_RANGE_S64K] =
157 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
161 .relax_code_seq[BR_RANGE_S16M] =
163 INSN_JAL /* jal label */
165 .relax_code_size[BR_RANGE_S16M] = 4,
166 .relax_branch_isize[BR_RANGE_S16M] = 4,
167 .relax_fixup[BR_RANGE_S16M] =
169 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
173 .relax_code_seq[BR_RANGE_U4G] =
175 INSN_SETHI_TA, /* sethi $ta, label */
176 INSN_ORI_TA, /* ori $ta, $ta, label */
177 INSN_JRAL_TA /* jral $ta */
179 .relax_code_size[BR_RANGE_U4G] = 12,
180 .relax_branch_isize[BR_RANGE_U4G] = 4,
181 .relax_fixup[BR_RANGE_U4G] =
183 {0, 4, 0, BFD_RELOC_NDS32_HI20},
184 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL4},
185 {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI},
186 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
187 {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
188 {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
189 {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
195 .br_range = BR_RANGE_S64K,
198 {0, 20, 0x1F, FALSE},
201 .relax_code_seq[BR_RANGE_S256] =
203 INSN_BGEZAL /* bgezal $rt, label */
205 .relax_code_condition[BR_RANGE_S256] =
207 {0, 20, 0x1F, FALSE},
210 .relax_code_size[BR_RANGE_S256] = 4,
211 .relax_branch_isize[BR_RANGE_S256] = 4,
212 .relax_fixup[BR_RANGE_S256] =
214 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
218 .relax_code_seq[BR_RANGE_S16K] =
220 INSN_BGEZAL /* bgezal $rt, label */
222 .relax_code_condition[BR_RANGE_S16K] =
224 {0, 20, 0x1F, FALSE},
227 .relax_code_size[BR_RANGE_S16K] = 4,
228 .relax_branch_isize[BR_RANGE_S16K] = 4,
229 .relax_fixup[BR_RANGE_S16K] =
231 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
235 .relax_code_seq[BR_RANGE_S64K] =
237 INSN_BGEZAL /* bgezal $rt, label */
239 .relax_code_condition[BR_RANGE_S64K] =
241 {0, 20, 0x1F, FALSE},
244 .relax_code_size[BR_RANGE_S64K] = 4,
245 .relax_branch_isize[BR_RANGE_S64K] = 4,
246 .relax_fixup[BR_RANGE_S64K] =
248 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
252 .relax_code_seq[BR_RANGE_S16M] =
254 INSN_BLTZ, /* bltz $rt, $1 */
255 INSN_JAL /* jal label */
257 .relax_code_condition[BR_RANGE_S16M] =
259 {0, 20, 0x1F, FALSE},
262 .relax_code_size[BR_RANGE_S16M] = 8,
263 .relax_branch_isize[BR_RANGE_S16M] = 4,
264 .relax_fixup[BR_RANGE_S16M] =
266 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
267 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL5},
268 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
272 .relax_code_seq[BR_RANGE_U4G] =
274 INSN_BLTZ, /* bltz $rt, $1 */
275 INSN_SETHI_TA, /* sethi $ta, label */
276 INSN_ORI_TA, /* ori $ta, $ta, label */
277 INSN_JRAL_TA /* jral $ta */
279 .relax_code_condition[BR_RANGE_U4G] =
281 {0, 20, 0x1F, FALSE},
284 .relax_code_size[BR_RANGE_U4G] = 16,
285 .relax_branch_isize[BR_RANGE_U4G] = 4,
286 .relax_fixup[BR_RANGE_U4G] =
288 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
289 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL6},
290 {4, 4, 0, BFD_RELOC_NDS32_HI20},
291 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
292 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
293 {8, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
294 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
295 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
296 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
302 .br_range = BR_RANGE_S64K,
305 {0, 20, 0x1F, FALSE},
308 .relax_code_seq[BR_RANGE_S256] =
310 INSN_BLTZAL /* bltzal $rt, label */
312 .relax_code_condition[BR_RANGE_S256] =
314 {0, 20, 0x1F, FALSE},
317 .relax_code_size[BR_RANGE_S256] = 4,
318 .relax_branch_isize[BR_RANGE_S256] = 4,
319 .relax_fixup[BR_RANGE_S256] =
321 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
325 .relax_code_seq[BR_RANGE_S16K] =
327 INSN_BLTZAL /* bltzal $rt, label */
329 .relax_code_condition[BR_RANGE_S16K] =
331 {0, 20, 0x1F, FALSE},
334 .relax_code_size[BR_RANGE_S16K] = 4,
335 .relax_branch_isize[BR_RANGE_S16K] = 4,
336 .relax_fixup[BR_RANGE_S16K] =
338 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
342 .relax_code_seq[BR_RANGE_S64K] =
344 INSN_BLTZAL /* bltzal $rt, label */
346 .relax_code_condition[BR_RANGE_S64K] =
348 {0, 20, 0x1F, FALSE},
351 .relax_code_size[BR_RANGE_S64K] = 4,
352 .relax_branch_isize[BR_RANGE_S64K] = 4,
353 .relax_fixup[BR_RANGE_S64K] =
355 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
359 .relax_code_seq[BR_RANGE_S16M] =
361 INSN_BGEZ, /* bgez $rt, $1 */
362 INSN_JAL /* jal label */
364 .relax_code_condition[BR_RANGE_S16M] =
366 {0, 20, 0x1F, FALSE},
369 .relax_code_size[BR_RANGE_S16M] = 8,
370 .relax_branch_isize[BR_RANGE_S16M] = 4,
371 .relax_fixup[BR_RANGE_S16M] =
373 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
374 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL5},
375 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
379 .relax_code_seq[BR_RANGE_U4G] =
381 INSN_BGEZ, /* bgez $rt, $1 */
382 INSN_SETHI_TA, /* sethi $ta, label */
383 INSN_ORI_TA, /* ori $ta, $ta, label */
384 INSN_JRAL_TA /* jral $ta */
386 .relax_code_condition[BR_RANGE_U4G] =
388 {0, 20, 0x1F, FALSE},
391 .relax_code_size[BR_RANGE_U4G] = 16,
392 .relax_branch_isize[BR_RANGE_U4G] = 4,
393 .relax_fixup[BR_RANGE_U4G] =
395 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
396 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL6},
397 {4, 4, 0, BFD_RELOC_NDS32_HI20},
398 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
399 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
400 {8, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
401 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
402 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
403 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
409 .br_range = BR_RANGE_S16M,
414 .relax_code_seq[BR_RANGE_S256] =
416 (INSN_J8 << 16) /* j8 label */
418 .relax_code_size[BR_RANGE_S256] = 2,
419 .relax_branch_isize[BR_RANGE_S256] = 2,
420 .relax_fixup[BR_RANGE_S256] =
422 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
426 .relax_code_seq[BR_RANGE_S16K] =
430 . relax_code_size[BR_RANGE_S16K] = 4,
431 .relax_branch_isize[BR_RANGE_S16K] = 4,
432 .relax_fixup[BR_RANGE_S16K] =
434 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
438 .relax_code_seq[BR_RANGE_S64K] =
442 .relax_code_size[BR_RANGE_S64K] = 4,
443 .relax_branch_isize[BR_RANGE_S64K] = 4,
444 .relax_fixup[BR_RANGE_S64K] =
446 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
450 .relax_code_seq[BR_RANGE_S16M] =
454 .relax_code_size[BR_RANGE_S16M] = 4,
455 .relax_branch_isize[BR_RANGE_S16M] = 4,
456 .relax_fixup[BR_RANGE_S16M] =
458 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
462 .relax_code_seq[BR_RANGE_U4G] =
464 INSN_SETHI_TA, /* sethi $ta, label */
465 INSN_ORI_TA, /* ori $ta, $ta, label */
466 INSN_JR_TA /* jr $ta */
468 .relax_code_size[BR_RANGE_U4G] = 12,
469 .relax_branch_isize[BR_RANGE_U4G] = 4,
470 .relax_fixup[BR_RANGE_U4G] =
472 {0, 4, 0, BFD_RELOC_NDS32_HI20},
473 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP4},
474 {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI},
475 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
476 {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
477 {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
478 {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
484 .br_range = BR_RANGE_S256,
489 .relax_code_seq[BR_RANGE_S256] =
491 (INSN_J8 << 16) /* j8 label */
493 .relax_code_size[BR_RANGE_S256] = 2,
494 .relax_branch_isize[BR_RANGE_S256] = 2,
495 .relax_fixup[BR_RANGE_S256] =
497 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
501 .relax_code_seq[BR_RANGE_S16K] =
505 .relax_code_size[BR_RANGE_S16K] = 4,
506 .relax_branch_isize[BR_RANGE_S16K] = 4,
507 .relax_fixup[BR_RANGE_S16K] =
509 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
513 .relax_code_seq[BR_RANGE_S64K] =
517 .relax_code_size[BR_RANGE_S64K] = 4,
518 .relax_branch_isize[BR_RANGE_S64K] = 4,
519 .relax_fixup[BR_RANGE_S64K] =
521 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
525 .relax_code_seq[BR_RANGE_S16M] =
529 .relax_code_size[BR_RANGE_S16M] = 4,
530 .relax_branch_isize[BR_RANGE_S16M] = 4,
531 .relax_fixup[BR_RANGE_S16M] =
533 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
537 .relax_code_seq[BR_RANGE_U4G] =
539 INSN_SETHI_TA, /* sethi $ta, label */
540 INSN_ORI_TA, /* ori $ta, $ta, label */
541 INSN_JR_TA /* jr $ta */
543 .relax_code_size[BR_RANGE_U4G] = 12,
544 .relax_branch_isize[BR_RANGE_U4G] = 4,
545 .relax_fixup[BR_RANGE_U4G] =
547 {0, 4, 0, BFD_RELOC_NDS32_HI20},
548 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP4},
549 {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI},
550 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
551 {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
552 {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
553 {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
559 .br_range = BR_RANGE_S64K,
562 {0, 20, 0x1F, FALSE},
565 /* We do not use beqz38 and beqzs8 here directly because we
566 don't want to check register number for specail condition. */
567 .relax_code_seq[BR_RANGE_S256] =
569 INSN_BEQZ /* beqz $rt, label */
571 .relax_code_condition[BR_RANGE_S256] =
573 {0, 20, 0x1F, FALSE},
576 .relax_code_size[BR_RANGE_S256] = 4,
577 .relax_branch_isize[BR_RANGE_S256] = 4,
578 .relax_fixup[BR_RANGE_S256] =
580 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
581 {0, 4, NDS32_INSN16 , BFD_RELOC_NDS32_INSN16},
585 .relax_code_seq[BR_RANGE_S16K] =
587 INSN_BEQZ /* beqz $rt, label */
589 .relax_code_condition[BR_RANGE_S16K] =
591 {0, 20, 0x1F, FALSE},
594 .relax_code_size[BR_RANGE_S16K] = 4,
595 .relax_branch_isize[BR_RANGE_S16K] = 4,
596 .relax_fixup[BR_RANGE_S16K] =
598 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
602 .relax_code_seq[BR_RANGE_S64K] =
604 INSN_BEQZ /* beqz $rt, label */
606 .relax_code_condition[BR_RANGE_S64K] =
608 {0, 20, 0x1F, FALSE},
611 .relax_code_size[BR_RANGE_S64K] = 4,
612 .relax_branch_isize[BR_RANGE_S64K] = 4,
613 .relax_fixup[BR_RANGE_S64K] =
615 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
619 .relax_code_seq[BR_RANGE_S16M] =
621 INSN_BNEZ, /* bnez $rt, $1 */
624 .relax_code_condition[BR_RANGE_S16M] =
626 {0, 20, 0x1F, FALSE},
629 .relax_code_size[BR_RANGE_S16M] = 8,
630 .relax_branch_isize[BR_RANGE_S16M] = 4,
631 .relax_fixup[BR_RANGE_S16M] =
633 /* bnez range is 17 pcrel, but it use 15 pcrel here since link time
634 relaxtion. If 17 pcrel can reach, it do not have to use S16M.
635 Therefore, 15 pcrel is just for linker to distinguish LONGJUMP5
637 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
638 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
639 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
640 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
641 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
645 .relax_code_seq[BR_RANGE_U4G] =
647 INSN_BNEZ, /* bnez $rt, $1 */
648 INSN_SETHI_TA, /* sethi $ta, label */
649 INSN_ORI_TA, /* ori $ta, $ta, label */
650 INSN_JR_TA /* jr $ta */
652 .relax_code_condition[BR_RANGE_U4G] =
654 {0, 20, 0x1F, FALSE},
657 .relax_code_size[BR_RANGE_U4G] = 16,
658 .relax_branch_isize[BR_RANGE_U4G] = 4,
659 .relax_fixup[BR_RANGE_U4G] =
661 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
662 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
663 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
664 {4, 4, 0, BFD_RELOC_NDS32_HI20},
665 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
666 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
667 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
668 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
669 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
670 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
676 .br_range = BR_RANGE_S64K,
679 {0, 20, 0x1F, FALSE},
682 .relax_code_seq[BR_RANGE_S256] =
684 INSN_BGEZ /* bgez $rt, label */
686 .relax_code_condition[BR_RANGE_S256] =
688 {0, 20, 0x1F, FALSE},
691 .relax_code_size[BR_RANGE_S256] = 4,
692 .relax_branch_isize[BR_RANGE_S256] = 4,
693 .relax_fixup[BR_RANGE_S256] =
695 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
699 .relax_code_seq[BR_RANGE_S16K] =
701 INSN_BGEZ /* bgez $rt, label */
703 .relax_code_condition[BR_RANGE_S16K] =
705 {0, 20, 0x1F, FALSE},
708 .relax_code_size[BR_RANGE_S16K] = 4,
709 .relax_branch_isize[BR_RANGE_S16K] = 4,
710 .relax_fixup[BR_RANGE_S16K] =
712 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
716 .relax_code_seq[BR_RANGE_S64K] =
718 INSN_BGEZ /* bgez $rt, label */
720 .relax_code_condition[BR_RANGE_S64K] =
722 {0, 20, 0x1F, FALSE},
725 .relax_code_size[BR_RANGE_S64K] = 4,
726 .relax_branch_isize[BR_RANGE_S64K] = 4,
727 .relax_fixup[BR_RANGE_S64K] =
729 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
733 .relax_code_seq[BR_RANGE_S16M] =
735 INSN_BLTZ, /* bltz $rt, $1 */
738 .relax_code_condition[BR_RANGE_S16M] =
740 {0, 20, 0x1F, FALSE},
743 .relax_code_size[BR_RANGE_S16M] = 8,
744 .relax_branch_isize[BR_RANGE_S16M] = 4,
745 .relax_fixup[BR_RANGE_S16M] =
747 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
748 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
749 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
752 .relax_code_seq[BR_RANGE_U4G] =
754 INSN_BLTZ, /* bltz $rt, $1 */
755 INSN_SETHI_TA, /* sethi $ta, label */
756 INSN_ORI_TA, /* ori $ta, $ta, label */
757 INSN_JR_TA /* jr $ta */
759 .relax_code_condition[BR_RANGE_U4G] =
761 {0, 20, 0x1F, FALSE},
764 .relax_code_size[BR_RANGE_U4G] = 16,
765 .relax_branch_isize[BR_RANGE_U4G] = 4,
766 .relax_fixup[BR_RANGE_U4G] =
768 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
769 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
770 {4, 4, 0, BFD_RELOC_NDS32_HI20},
771 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
772 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
773 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
774 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
775 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
776 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
782 .br_range = BR_RANGE_S64K,
785 {0, 20, 0x1F, FALSE},
788 .relax_code_seq[BR_RANGE_S256] =
790 INSN_BNEZ /* bnez $rt, label */
792 .relax_code_condition[BR_RANGE_S256] =
794 {0, 20, 0x1F, FALSE},
797 .relax_code_size[BR_RANGE_S256] = 4,
798 .relax_branch_isize[BR_RANGE_S256] = 4,
799 .relax_fixup[BR_RANGE_S256] =
801 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
802 {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
806 .relax_code_seq[BR_RANGE_S16K] =
808 INSN_BNEZ /* bnez $rt, label */
810 .relax_code_condition[BR_RANGE_S16K] =
812 {0, 20, 0x1F, FALSE},
815 .relax_code_size[BR_RANGE_S16K] = 4,
816 .relax_branch_isize[BR_RANGE_S16K] = 4,
817 .relax_fixup[BR_RANGE_S16K] =
819 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
823 .relax_code_seq[BR_RANGE_S64K] =
825 INSN_BNEZ /* bnez $rt, label */
827 .relax_code_condition[BR_RANGE_S64K] =
829 {0, 20, 0x1F, FALSE},
832 .relax_code_size[BR_RANGE_S64K] = 4,
833 .relax_branch_isize[BR_RANGE_S64K] = 4,
834 .relax_fixup[BR_RANGE_S64K] =
836 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
840 .relax_code_seq[BR_RANGE_S16M] =
842 INSN_BEQZ, /* beqz $rt, $1 */
845 .relax_code_condition[BR_RANGE_S16M] =
847 {0, 20, 0x1F, FALSE},
850 .relax_code_size[BR_RANGE_S16M] = 8,
851 .relax_branch_isize[BR_RANGE_S16M] = 4,
852 .relax_fixup[BR_RANGE_S16M] =
854 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
855 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
856 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
857 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
858 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
862 .relax_code_seq[BR_RANGE_U4G] =
864 INSN_BEQZ, /* beqz $rt, $1 */
865 INSN_SETHI_TA, /* sethi $ta, label */
866 INSN_ORI_TA, /* ori $ta, $ta, label */
867 INSN_JR_TA /* jr $ta */
869 .relax_code_condition[BR_RANGE_U4G] =
871 {0, 20, 0x1F, FALSE},
874 .relax_code_size[BR_RANGE_U4G] = 16,
875 .relax_branch_isize[BR_RANGE_U4G] = 4,
876 .relax_fixup[BR_RANGE_U4G] =
878 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
879 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
880 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
881 {4, 4, 0, BFD_RELOC_NDS32_HI20},
882 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
883 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
884 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
885 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
886 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
887 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
893 .br_range = BR_RANGE_S64K,
896 {0, 20, 0x1F, FALSE},
899 .relax_code_seq[BR_RANGE_S256] =
901 INSN_BGTZ /* bgtz $rt, label */
903 .relax_code_condition[BR_RANGE_S256] =
905 {0, 20, 0x1F, FALSE},
908 .relax_code_size[BR_RANGE_S256] = 4,
909 .relax_branch_isize[BR_RANGE_S256] = 4,
910 .relax_fixup[BR_RANGE_S256] =
912 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
916 .relax_code_seq[BR_RANGE_S16K] =
918 INSN_BGTZ /* bgtz $rt, label */
920 .relax_code_condition[BR_RANGE_S16K] =
922 {0, 20, 0x1F, FALSE},
925 .relax_code_size[BR_RANGE_S16K] = 4,
926 .relax_branch_isize[BR_RANGE_S16K] = 4,
927 .relax_fixup[BR_RANGE_S16K] =
929 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
933 .relax_code_seq[BR_RANGE_S64K] =
935 INSN_BGTZ /* bgtz $rt, label */
937 .relax_code_condition[BR_RANGE_S64K] =
939 {0, 20, 0x1F, FALSE},
942 .relax_code_size[BR_RANGE_S64K] = 4,
943 .relax_branch_isize[BR_RANGE_S64K] = 4,
944 .relax_fixup[BR_RANGE_S64K] =
946 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
950 .relax_code_seq[BR_RANGE_S16M] =
952 INSN_BLEZ, /* blez $rt, $1 */
955 .relax_code_condition[BR_RANGE_S16M] =
957 {0, 20, 0x1F, FALSE},
960 .relax_code_size[BR_RANGE_S16M] = 8,
961 .relax_branch_isize[BR_RANGE_S16M] = 4,
962 .relax_fixup[BR_RANGE_S16M] =
964 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
965 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
966 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
970 .relax_code_seq[BR_RANGE_U4G] =
972 INSN_BLEZ, /* blez $rt, $1 */
973 INSN_SETHI_TA, /* sethi $ta, label */
974 INSN_ORI_TA, /* ori $ta, $ta, label */
975 INSN_JR_TA /* jr $ta */
977 .relax_code_condition[BR_RANGE_U4G] =
979 {0, 20, 0x1F, FALSE},
982 .relax_code_size[BR_RANGE_U4G] = 16,
983 .relax_branch_isize[BR_RANGE_U4G] = 4,
984 .relax_fixup[BR_RANGE_U4G] =
986 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
987 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
988 {4, 4, 0, BFD_RELOC_NDS32_HI20},
989 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
990 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
991 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
992 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
993 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
994 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1000 .br_range = BR_RANGE_S64K,
1003 {0, 20, 0x1F, FALSE},
1006 .relax_code_seq[BR_RANGE_S256] =
1008 INSN_BLEZ /* blez $rt, label */
1010 .relax_code_condition[BR_RANGE_S256] =
1012 {0, 20, 0x1F, FALSE},
1015 .relax_code_size[BR_RANGE_S256] = 4,
1016 .relax_branch_isize[BR_RANGE_S256] = 4,
1017 .relax_fixup[BR_RANGE_S256] =
1019 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1023 .relax_code_seq[BR_RANGE_S16K] =
1025 INSN_BLEZ /* blez $rt, label */
1027 .relax_code_condition[BR_RANGE_S16K] =
1029 {0, 20, 0x1F, FALSE},
1032 .relax_code_size[BR_RANGE_S16K] = 4,
1033 .relax_branch_isize[BR_RANGE_S16K] = 4,
1034 .relax_fixup[BR_RANGE_S16K] =
1036 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1040 .relax_code_seq[BR_RANGE_S64K] =
1042 INSN_BLEZ /* blez $rt, label */
1044 .relax_code_condition[BR_RANGE_S64K] =
1046 {0, 20, 0x1F, FALSE},
1049 .relax_code_size[BR_RANGE_S64K] = 4,
1050 .relax_branch_isize[BR_RANGE_S64K] = 4,
1051 .relax_fixup[BR_RANGE_S64K] =
1053 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1057 .relax_code_seq[BR_RANGE_S16M] =
1059 INSN_BGTZ, /* bgtz $rt, $1 */
1060 INSN_J /* j label */
1062 .relax_code_condition[BR_RANGE_S16M] =
1064 {0, 20, 0x1F, FALSE},
1067 .relax_code_size[BR_RANGE_S16M] = 8,
1068 .relax_branch_isize[BR_RANGE_S16M] = 4,
1069 .relax_fixup[BR_RANGE_S16M] =
1071 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1072 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1073 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1077 .relax_code_seq[BR_RANGE_U4G] =
1079 INSN_BGTZ, /* bgtz $rt, $1 */
1080 INSN_SETHI_TA, /* sethi $ta, label */
1081 INSN_ORI_TA, /* ori $ta, $ta, label */
1082 INSN_JR_TA /* jr $ta */
1084 .relax_code_condition[BR_RANGE_U4G] =
1086 {0, 20, 0x1F, FALSE},
1089 .relax_code_size[BR_RANGE_U4G] = 16,
1090 .relax_branch_isize[BR_RANGE_U4G] = 4,
1091 .relax_fixup[BR_RANGE_U4G] =
1093 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1094 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1095 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1096 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1097 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1098 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1099 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1100 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1101 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1107 .br_range = BR_RANGE_S64K,
1110 {0, 20, 0x1F, FALSE},
1113 .relax_code_seq[BR_RANGE_S256] =
1115 INSN_BLTZ /* bltz $rt, label */
1117 .relax_code_condition[BR_RANGE_S256] =
1119 {0, 20, 0x1F, FALSE},
1122 .relax_code_size[BR_RANGE_S256] = 4,
1123 .relax_branch_isize[BR_RANGE_S256] = 4,
1124 .relax_fixup[BR_RANGE_S256] =
1126 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1130 .relax_code_seq[BR_RANGE_S16K] =
1132 INSN_BLTZ /* bltz $rt, label */
1134 .relax_code_condition[BR_RANGE_S16K] =
1136 {0, 20, 0x1F, FALSE},
1139 .relax_code_size[BR_RANGE_S16K] = 4,
1140 .relax_branch_isize[BR_RANGE_S16K] = 4,
1141 .relax_fixup[BR_RANGE_S16K] =
1143 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1147 .relax_code_seq[BR_RANGE_S64K] =
1149 INSN_BLTZ /* bltz $rt, label */
1151 .relax_code_condition[BR_RANGE_S64K] =
1153 {0, 20, 0x1F, FALSE},
1156 .relax_code_size[BR_RANGE_S64K] = 4,
1157 .relax_branch_isize[BR_RANGE_S64K] = 4,
1158 .relax_fixup[BR_RANGE_S64K] =
1160 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1164 .relax_code_seq[BR_RANGE_S16M] =
1166 INSN_BGEZ, /* bgez $rt, $1 */
1167 INSN_J /* j label */
1169 .relax_code_condition[BR_RANGE_S16M] =
1171 {0, 20, 0x1F, FALSE},
1174 .relax_code_size[BR_RANGE_S16M] = 8,
1175 .relax_branch_isize[BR_RANGE_S16M] = 4,
1176 .relax_fixup[BR_RANGE_S16M] =
1178 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1179 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1180 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1184 .relax_code_seq[BR_RANGE_U4G] =
1186 INSN_BGEZ, /* bgez $rt, $1 */
1187 INSN_SETHI_TA, /* sethi $ta, label */
1188 INSN_ORI_TA, /* ori $ta, $ta, label */
1189 INSN_JR_TA /* jr $ta */
1191 .relax_code_condition[BR_RANGE_U4G] =
1193 {0, 20, 0x1F, FALSE},
1196 .relax_code_size[BR_RANGE_U4G] = 16,
1197 .relax_branch_isize[BR_RANGE_U4G] = 4,
1198 .relax_fixup[BR_RANGE_U4G] =
1200 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1201 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1202 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1203 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1204 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1205 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1206 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1207 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1208 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1214 .br_range = BR_RANGE_S16K,
1217 {0, 20, 0x1F, FALSE},
1218 {0, 15, 0x1F, FALSE},
1221 .relax_code_seq[BR_RANGE_S256] =
1223 INSN_BEQ /* beq $rt, $ra, label */
1225 .relax_code_condition[BR_RANGE_S256] =
1227 {0, 20, 0x1F, FALSE},
1228 {0, 15, 0x1F, FALSE},
1231 .relax_code_size[BR_RANGE_S256] = 4,
1232 .relax_branch_isize[BR_RANGE_S256] = 4,
1233 .relax_fixup[BR_RANGE_S256] =
1235 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1236 {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
1240 .relax_code_seq[BR_RANGE_S16K] =
1242 INSN_BEQ /* beq $rt, $ra, label */
1244 .relax_code_condition[BR_RANGE_S16K] =
1246 {0, 20, 0x1F, FALSE},
1247 {0, 15, 0x1F, FALSE},
1250 .relax_code_size[BR_RANGE_S16K] = 4,
1251 .relax_branch_isize[BR_RANGE_S16K] = 4,
1252 .relax_fixup[BR_RANGE_S16K] =
1254 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1258 .relax_code_seq[BR_RANGE_S64K] =
1260 INSN_BNE, /* bne $rt, $ra, $1 */
1261 INSN_J /* j label */
1263 .relax_code_condition[BR_RANGE_S64K] =
1265 {0, 20, 0x1F, FALSE},
1266 {0, 15, 0x1F, FALSE},
1269 .relax_code_size[BR_RANGE_S64K] = 8,
1270 .relax_branch_isize[BR_RANGE_S64K] = 4,
1271 .relax_fixup[BR_RANGE_S64K] =
1273 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1274 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1275 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1276 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1277 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1281 .relax_code_seq[BR_RANGE_S16M] =
1283 INSN_BNE, /* bne $rt, $ra, $1 */
1284 INSN_J /* j label */
1286 .relax_code_condition[BR_RANGE_S16M] =
1288 {0, 20, 0x1F, FALSE},
1289 {0, 15, 0x1F, FALSE},
1292 .relax_code_size[BR_RANGE_S16M] = 8,
1293 .relax_branch_isize[BR_RANGE_S16M] = 4,
1294 .relax_fixup[BR_RANGE_S16M] =
1296 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1297 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1298 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1299 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1300 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1304 .relax_code_seq[BR_RANGE_U4G] =
1306 INSN_BNE, /* bne $rt, $ra, $1 */
1307 INSN_SETHI_TA, /* sethi $ta, label */
1308 INSN_ORI_TA, /* ori $ta, $ta, label */
1309 INSN_JR_TA /* jr $ta */
1311 .relax_code_condition[BR_RANGE_U4G] =
1313 {0, 20, 0x1F, FALSE},
1314 {0, 15, 0x1F, FALSE},
1317 .relax_code_size[BR_RANGE_U4G] = 16,
1318 .relax_branch_isize[BR_RANGE_U4G] = 4,
1319 .relax_fixup[BR_RANGE_U4G] =
1321 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1322 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1323 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1324 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1325 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1326 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1327 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1328 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1329 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1330 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1336 .br_range = BR_RANGE_S16K,
1339 {0, 20, 0x1F, FALSE},
1340 {0, 15, 0x1F, FALSE},
1343 .relax_code_seq[BR_RANGE_S256] =
1345 INSN_BNE /* bne $rt, $ra, label */
1347 .relax_code_condition[BR_RANGE_S256] =
1349 {0, 20, 0x1F, FALSE},
1350 {0, 15, 0x1F, FALSE},
1353 .relax_code_size[BR_RANGE_S256] = 4,
1354 .relax_branch_isize[BR_RANGE_S256] = 4,
1355 .relax_fixup[BR_RANGE_S256] =
1357 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1358 {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
1362 .relax_code_seq[BR_RANGE_S16K] =
1364 INSN_BNE /* bne $rt, $ra, label */
1366 .relax_code_condition[BR_RANGE_S16K] =
1368 {0, 20, 0x1F, FALSE},
1369 {0, 15, 0x1F, FALSE},
1372 .relax_code_size[BR_RANGE_S16K] = 4,
1373 .relax_branch_isize[BR_RANGE_S16K] = 4,
1374 .relax_fixup[BR_RANGE_S16K] =
1376 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1380 .relax_code_seq[BR_RANGE_S64K] =
1382 INSN_BEQ, /* beq $rt, $ra, $1 */
1383 INSN_J /* j label */
1385 .relax_code_condition[BR_RANGE_S64K] =
1387 {0, 20, 0x1F, FALSE},
1388 {0, 15, 0x1F, FALSE},
1391 .relax_code_size[BR_RANGE_S64K] = 8,
1392 .relax_branch_isize[BR_RANGE_S64K] = 4,
1393 .relax_fixup[BR_RANGE_S64K] =
1395 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1396 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1397 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1398 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1399 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1403 .relax_code_seq[BR_RANGE_S16M] =
1405 INSN_BEQ, /* beq $rt, $ra, $1 */
1406 INSN_J /* j label */
1408 .relax_code_condition[BR_RANGE_S16M] =
1410 {0, 20, 0x1F, FALSE},
1411 {0, 15, 0x1F, FALSE},
1414 .relax_code_size[BR_RANGE_S16M] = 8,
1415 .relax_branch_isize[BR_RANGE_S16M] = 4,
1416 .relax_fixup[BR_RANGE_S16M] =
1418 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1419 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1420 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1421 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1422 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1426 .relax_code_seq[BR_RANGE_U4G] =
1428 INSN_BEQ, /* beq $rt, $ra, $1 */
1429 INSN_SETHI_TA, /* sethi $ta, label */
1430 INSN_ORI_TA, /* ori $ta, $ta, label */
1431 INSN_JR_TA /* jr $ta */
1433 .relax_code_condition[BR_RANGE_U4G] =
1435 {0, 20, 0x1F, FALSE},
1436 {0, 15, 0x1F, FALSE},
1439 .relax_code_size[BR_RANGE_U4G] = 16,
1440 .relax_branch_isize[BR_RANGE_U4G] = 4,
1441 .relax_fixup[BR_RANGE_U4G] =
1443 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1444 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1445 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1446 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1447 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1448 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1449 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1450 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1451 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1452 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1458 .br_range = BR_RANGE_S256,
1464 .relax_code_seq[BR_RANGE_S256] =
1466 INSN_BEQZ38 << 16 /* beqz $rt, label */
1468 .relax_code_condition[BR_RANGE_S256] =
1473 .relax_code_size[BR_RANGE_S256] = 2,
1474 .relax_branch_isize[BR_RANGE_S256] = 2,
1475 .relax_fixup[BR_RANGE_S256] =
1477 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
1481 .relax_code_seq[BR_RANGE_S16K] =
1483 INSN_BEQZ /* beqz $rt, label */
1485 .relax_code_condition[BR_RANGE_S16K] =
1487 {0, 20, 0x1F, FALSE},
1490 .relax_code_size[BR_RANGE_S16K] = 4,
1491 .relax_branch_isize[BR_RANGE_S16K] = 4,
1492 .relax_fixup[BR_RANGE_S16K] =
1494 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1498 .relax_code_seq[BR_RANGE_S64K] =
1500 INSN_BEQZ /* beqz $rt, label */
1502 .relax_code_condition[BR_RANGE_S64K] =
1504 {0, 20, 0x1F, FALSE},
1507 .relax_code_size[BR_RANGE_S64K] = 4,
1508 .relax_branch_isize[BR_RANGE_S64K] = 4,
1509 .relax_fixup[BR_RANGE_S64K] =
1511 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1515 .relax_code_seq[BR_RANGE_S16M] =
1517 INSN_BNEZ, /* bnez $rt, $1 */
1518 INSN_J /* j label */
1520 .relax_code_condition[BR_RANGE_S16M] =
1522 {0, 20, 0x1F, FALSE},
1525 .relax_code_size[BR_RANGE_S16M] = 8,
1526 .relax_branch_isize[BR_RANGE_S16M] = 4,
1527 .relax_fixup[BR_RANGE_S16M] =
1529 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1530 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1531 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1532 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1533 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1537 .relax_code_seq[BR_RANGE_U4G] =
1539 INSN_BNEZ, /* bnez $rt, $1 */
1540 INSN_SETHI_TA, /* sethi $ta, label */
1541 INSN_ORI_TA, /* ori $ta, $ta, label */
1542 INSN_JR_TA /* jr $ta */
1544 .relax_code_condition[BR_RANGE_U4G] =
1546 {0, 20, 0x1F, FALSE},
1549 .relax_code_size[BR_RANGE_U4G] = 16,
1550 .relax_branch_isize[BR_RANGE_U4G] = 4,
1551 .relax_fixup[BR_RANGE_U4G] =
1553 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1554 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1555 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1556 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1557 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1558 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1559 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1560 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1561 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1562 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1568 .br_range = BR_RANGE_S256,
1574 .relax_code_seq[BR_RANGE_S256] =
1576 INSN_BNEZ38 << 16 /* bnez $rt, label */
1578 .relax_code_condition[BR_RANGE_S256] =
1583 .relax_code_size[BR_RANGE_S256] = 2,
1584 .relax_branch_isize[BR_RANGE_S256] = 2,
1585 .relax_fixup[BR_RANGE_S256] =
1587 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
1591 .relax_code_seq[BR_RANGE_S16K] =
1593 INSN_BNEZ /* bnez $rt, label */
1595 .relax_code_condition[BR_RANGE_S16K] =
1597 {0, 20, 0x1F, FALSE},
1600 .relax_code_size[BR_RANGE_S16K] = 4,
1601 .relax_branch_isize[BR_RANGE_S16K] = 4,
1602 .relax_fixup[BR_RANGE_S16K] =
1604 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1608 .relax_code_seq[BR_RANGE_S64K] =
1610 INSN_BNEZ /* bnez $rt, label */
1612 .relax_code_condition[BR_RANGE_S64K] =
1614 {0, 20, 0x1F, FALSE},
1617 .relax_code_size[BR_RANGE_S64K] = 4,
1618 .relax_branch_isize[BR_RANGE_S64K] = 4,
1619 .relax_fixup[BR_RANGE_S64K] =
1621 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1625 .relax_code_seq[BR_RANGE_S16M] =
1627 INSN_BEQZ, /* beqz $rt, $1 */
1628 INSN_J /* j label */
1630 .relax_code_condition[BR_RANGE_S16M] =
1632 {0, 20, 0x1F, FALSE},
1635 .relax_code_size[BR_RANGE_S16M] = 8,
1636 .relax_branch_isize[BR_RANGE_S16M] = 4,
1637 .relax_fixup[BR_RANGE_S16M] =
1639 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1640 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1641 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1642 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1643 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1647 .relax_code_seq[BR_RANGE_U4G] =
1649 INSN_BEQZ, /* beqz $rt, $1 */
1650 INSN_SETHI_TA, /* sethi $ta, label */
1651 INSN_ORI_TA, /* ori $ta, $ta, label */
1652 INSN_JR_TA /* jr $ta */
1654 .relax_code_condition[BR_RANGE_U4G] =
1656 {0, 20, 0x1F, FALSE},
1659 .relax_code_size[BR_RANGE_U4G] = 16,
1660 .relax_branch_isize[BR_RANGE_U4G] = 4,
1661 .relax_fixup[BR_RANGE_U4G] =
1663 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1664 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1665 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1666 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1667 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1668 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1669 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1670 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1671 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1672 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1678 .br_range = BR_RANGE_S256,
1683 .relax_code_seq[BR_RANGE_S256] =
1685 INSN_BEQZS8 << 16 /* beqz $r15, label */
1687 .relax_code_size[BR_RANGE_S256] = 2,
1688 .relax_branch_isize[BR_RANGE_S256] = 2,
1689 .relax_fixup[BR_RANGE_S256] =
1691 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
1695 .relax_code_seq[BR_RANGE_S16K] =
1697 INSN_BEQZ_TA /* beqz $r15, label */
1699 .relax_code_size[BR_RANGE_S16K] = 4,
1700 .relax_branch_isize[BR_RANGE_S16K] = 4,
1701 .relax_fixup[BR_RANGE_S16K] =
1703 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1707 .relax_code_seq[BR_RANGE_S64K] =
1709 INSN_BEQZ_TA /* beqz $r15, label */
1711 .relax_code_size[BR_RANGE_S64K] = 4,
1712 .relax_branch_isize[BR_RANGE_S64K] = 4,
1713 .relax_fixup[BR_RANGE_S64K] =
1715 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1719 .relax_code_seq[BR_RANGE_S16M] =
1721 INSN_BNEZ_TA, /* bnez $r15, $1 */
1722 INSN_J /* j label */
1724 .relax_code_size[BR_RANGE_S16M] = 8,
1725 .relax_branch_isize[BR_RANGE_S16M] = 4,
1726 .relax_fixup[BR_RANGE_S16M] =
1728 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1729 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1730 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1731 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1732 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1736 .relax_code_seq[BR_RANGE_U4G] =
1738 INSN_BNEZ_TA, /* bnez $r15, $1 */
1739 INSN_SETHI_TA, /* sethi $ta, label */
1740 INSN_ORI_TA, /* ori $ta, $ta, label */
1741 INSN_JR_TA /* jr $ta */
1743 .relax_code_size[BR_RANGE_U4G] = 16,
1744 .relax_branch_isize[BR_RANGE_U4G] = 4,
1745 .relax_fixup[BR_RANGE_U4G] =
1747 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1748 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1749 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1750 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1751 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1752 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1753 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1754 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1755 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1756 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1762 .br_range = BR_RANGE_S256,
1767 .relax_code_seq[BR_RANGE_S256] =
1769 INSN_BNEZS8 << 16 /* bnez $r15, label */
1771 .relax_code_size[BR_RANGE_S256] = 2,
1772 .relax_branch_isize[BR_RANGE_S256] = 2,
1773 .relax_fixup[BR_RANGE_S256] =
1775 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
1779 .relax_code_seq[BR_RANGE_S16K] =
1781 INSN_BNEZ_TA /* bnez $r15, label */
1783 .relax_code_size[BR_RANGE_S16K] = 4,
1784 .relax_branch_isize[BR_RANGE_S16K] = 4,
1785 .relax_fixup[BR_RANGE_S16K] =
1787 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1791 .relax_code_seq[BR_RANGE_S64K] =
1793 INSN_BNEZ_TA /* bnez $r15, label */
1795 .relax_code_size[BR_RANGE_S64K] = 4,
1796 .relax_branch_isize[BR_RANGE_S64K] = 4,
1797 .relax_fixup[BR_RANGE_S64K] =
1799 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1803 .relax_code_seq[BR_RANGE_S16M] =
1805 INSN_BEQZ_TA, /* beqz $r15, $1 */
1806 INSN_J /* j label */
1808 .relax_code_size[BR_RANGE_S16M] = 8,
1809 .relax_branch_isize[BR_RANGE_S16M] = 4,
1810 .relax_fixup[BR_RANGE_S16M] =
1812 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1813 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1814 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1815 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1816 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1820 .relax_code_seq[BR_RANGE_U4G] =
1822 INSN_BEQZ_TA, /* beqz $r15, $1 */
1823 INSN_SETHI_TA, /* sethi $ta, label */
1824 INSN_ORI_TA, /* ori $ta, $ta, label */
1825 INSN_JR_TA /* jr $ta */
1827 .relax_code_size[BR_RANGE_U4G] = 16,
1828 .relax_branch_isize[BR_RANGE_U4G] = 4,
1829 .relax_fixup[BR_RANGE_U4G] =
1831 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1832 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1833 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1834 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1835 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1836 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1837 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1838 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1839 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1840 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1846 .br_range = BR_RANGE_S256,
1852 .relax_code_seq[BR_RANGE_S256] =
1854 INSN_BNES38 << 16 /* bne $rt, $r5, label */
1856 .relax_code_condition[BR_RANGE_S256] =
1861 .relax_code_size[BR_RANGE_S256] = 2,
1862 .relax_branch_isize[BR_RANGE_S256] = 2,
1863 .relax_fixup[BR_RANGE_S256] =
1865 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
1869 .relax_code_seq[BR_RANGE_S16K] =
1871 INSN_BNE_R5 /* bne $rt, $r5, label */
1873 .relax_code_condition[BR_RANGE_S16K] =
1875 {0, 20, 0x1F, FALSE},
1878 .relax_code_size[BR_RANGE_S16K] = 4,
1879 .relax_branch_isize[BR_RANGE_S16K] = 4,
1880 .relax_fixup[BR_RANGE_S16K] =
1882 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1886 .relax_code_seq[BR_RANGE_S64K] =
1888 INSN_BEQ_R5, /* beq $rt, $r5, $1 */
1889 INSN_J /* j label */
1891 .relax_code_condition[BR_RANGE_S64K] =
1893 {0, 20, 0x1F, FALSE},
1896 .relax_code_size[BR_RANGE_S64K] = 8,
1897 .relax_branch_isize[BR_RANGE_S64K] = 4,
1898 .relax_fixup[BR_RANGE_S64K] =
1900 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1901 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1902 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1903 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1904 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1908 .relax_code_seq[BR_RANGE_S16M] =
1910 INSN_BEQ_R5, /* beq $rt, $r5, $1 */
1911 INSN_J /* j label */
1913 .relax_code_condition[BR_RANGE_S16M] =
1915 {0, 20, 0x1F, FALSE},
1918 .relax_code_size[BR_RANGE_S16M] = 8,
1919 .relax_branch_isize[BR_RANGE_S16M] = 4,
1920 .relax_fixup[BR_RANGE_S16M] =
1922 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1923 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1924 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1925 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1926 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1930 .relax_code_seq[BR_RANGE_U4G] =
1932 INSN_BEQ_R5, /* beq $rt, $r5, $1 */
1933 INSN_SETHI_TA, /* sethi $ta, label */
1934 INSN_ORI_TA, /* ori $ta, $ta, label */
1935 INSN_JR_TA /* jr $ta */
1937 .relax_code_condition[BR_RANGE_U4G] =
1939 {0, 20, 0x1F, FALSE},
1942 .relax_code_size[BR_RANGE_U4G] = 16,
1943 .relax_branch_isize[BR_RANGE_U4G] = 4,
1944 .relax_fixup[BR_RANGE_U4G] =
1946 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1947 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1948 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1949 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1950 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1951 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1952 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1953 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1954 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1955 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1961 .br_range = BR_RANGE_S256,
1967 .relax_code_seq[BR_RANGE_S256] =
1969 INSN_BEQS38 << 16 /* beq $rt, $r5, label */
1971 .relax_code_condition[BR_RANGE_S256] =
1976 .relax_code_size[BR_RANGE_S256] = 2,
1977 .relax_branch_isize[BR_RANGE_S256] = 2,
1978 .relax_fixup[BR_RANGE_S256] =
1980 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
1984 .relax_code_seq[BR_RANGE_S16K] =
1986 INSN_BEQ_R5 /* beq $rt, $r5, label */
1988 .relax_code_condition[BR_RANGE_S16K] =
1990 {0, 20, 0x1F, FALSE},
1993 .relax_code_size[BR_RANGE_S16K] = 4,
1994 .relax_branch_isize[BR_RANGE_S16K] = 4,
1995 .relax_fixup[BR_RANGE_S16K] =
1997 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
2001 .relax_code_seq[BR_RANGE_S64K] =
2003 INSN_BNE_R5, /* bne $rt, $r5, $1 */
2004 INSN_J /* j label */
2006 .relax_code_condition[BR_RANGE_S64K] =
2008 {0, 20, 0x1F, FALSE},
2011 .relax_code_size[BR_RANGE_S64K] = 8,
2012 .relax_branch_isize[BR_RANGE_S64K] = 4,
2013 .relax_fixup[BR_RANGE_S64K] =
2015 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
2016 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
2017 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
2018 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
2019 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
2023 .relax_code_seq[BR_RANGE_S16M] =
2025 INSN_BNE_R5, /* bne $rt, $r5, $1 */
2026 INSN_J /* j label */
2028 .relax_code_condition[BR_RANGE_S16M] =
2030 {0, 20, 0x1F, FALSE},
2033 .relax_code_size[BR_RANGE_S16M] = 8,
2034 .relax_branch_isize[BR_RANGE_S16M] = 4,
2035 .relax_fixup[BR_RANGE_S16M] =
2037 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
2038 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
2039 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
2040 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
2041 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
2045 .relax_code_seq[BR_RANGE_U4G] =
2047 INSN_BNE_R5, /* bne $rt, $r5, $1 */
2048 INSN_SETHI_TA, /* sethi $ta, label */
2049 INSN_ORI_TA, /* ori $ta, $ta, label */
2050 INSN_JR_TA /* jr $ta */
2052 .relax_code_condition[BR_RANGE_U4G] =
2054 {0, 20, 0x1F, FALSE},
2057 .relax_code_size[BR_RANGE_U4G] = 16,
2058 .relax_branch_isize[BR_RANGE_U4G] = 4,
2059 .relax_fixup[BR_RANGE_U4G] =
2061 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
2062 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
2063 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
2064 {4, 4, 0, BFD_RELOC_NDS32_HI20},
2065 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
2066 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
2067 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
2068 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
2069 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
2070 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
2076 .br_range = BR_RANGE_S256,
2079 {0, 8, 0x7FF, TRUE},
2080 {0, 20, 0x1F, FALSE},
2083 .relax_code_seq[BR_RANGE_S256] =
2085 INSN_BEQC /* beqc $rt, imm11s, label */
2087 .relax_code_condition[BR_RANGE_S256] =
2089 {0, 8, 0x7FF, FALSE},
2090 {0, 20, 0x1F, FALSE},
2093 .relax_code_size[BR_RANGE_S256] = 4,
2094 .relax_branch_isize[BR_RANGE_S256] = 4,
2095 .relax_fixup[BR_RANGE_S256] =
2097 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
2101 .relax_code_seq[BR_RANGE_S16K] =
2103 INSN_MOVI_TA, /* movi $ta, imm11s */
2104 INSN_BEQ_TA /* beq $rt, $ta, label */
2106 .relax_code_condition[BR_RANGE_S16K] =
2108 {0, 0, 0xFFFFF, FALSE},
2109 {4, 20, 0x1F, FALSE},
2112 .relax_code_size[BR_RANGE_S16K] = 8,
2113 .relax_branch_isize[BR_RANGE_S16K] = 4,
2114 .relax_fixup[BR_RANGE_S16K] =
2116 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
2117 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP7},
2118 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
2122 .relax_code_seq[BR_RANGE_S64K] =
2124 INSN_BNEC, /* bnec $rt, imm11s, $1 */
2125 INSN_J /* j label */
2127 .relax_code_condition[BR_RANGE_S64K] =
2129 {0, 8, 0x7FF, FALSE},
2130 {0, 20, 0x1F, FALSE},
2133 .relax_code_size[BR_RANGE_S64K] = 8,
2134 .relax_branch_isize[BR_RANGE_S64K] = 4,
2135 .relax_fixup[BR_RANGE_S64K] =
2137 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
2138 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
2142 .relax_code_seq[BR_RANGE_S16M] =
2144 INSN_BNEC, /* bnec $rt, imm11s, $1 */
2145 INSN_J /* j label */
2147 .relax_code_condition[BR_RANGE_S16M] =
2149 {0, 8, 0x7FF, FALSE},
2150 {0, 20, 0x1F, FALSE},
2153 .relax_code_size[BR_RANGE_S16M] = 8,
2154 .relax_branch_isize[BR_RANGE_S16M] = 4,
2155 .relax_fixup[BR_RANGE_S16M] =
2157 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
2158 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
2162 .relax_code_seq[BR_RANGE_U4G] =
2164 INSN_BNEC, /* bnec $rt, imm11s, $1 */
2165 INSN_SETHI_TA, /* sethi $ta, label */
2166 INSN_ORI_TA, /* ori $ta, $ta, label */
2167 INSN_JR_TA /* jr $ta */
2169 .relax_code_condition[BR_RANGE_U4G] =
2171 {0, 8, 0x7FF, FALSE},
2172 {0, 20, 0x1F, FALSE},
2175 .relax_code_size[BR_RANGE_U4G] = 16,
2176 .relax_branch_isize[BR_RANGE_U4G] = 4,
2177 .relax_fixup[BR_RANGE_U4G] =
2179 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
2180 {4, 4, 0, BFD_RELOC_NDS32_HI20},
2181 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
2182 {12, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
2188 .br_range = BR_RANGE_S256,
2191 {0, 8, 0x7FF, TRUE},
2192 {0, 20, 0x1F, FALSE},
2195 .relax_code_seq[BR_RANGE_S256] =
2197 INSN_BNEC /* bnec $rt, imm11s, label */
2199 .relax_code_condition[BR_RANGE_S256] =
2201 {0, 8, 0x7FF, FALSE},
2202 {0, 20, 0x1F, FALSE},
2205 .relax_code_size[BR_RANGE_S256] = 4,
2206 .relax_branch_isize[BR_RANGE_S256] = 4,
2207 .relax_fixup[BR_RANGE_S256] =
2209 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
2213 .relax_code_seq[BR_RANGE_S16K] =
2215 INSN_MOVI_TA, /* movi $ta, imm11s */
2216 INSN_BNE_TA /* bne $rt, $ta, label */
2218 .relax_code_condition[BR_RANGE_S16K] =
2220 {0, 0, 0xFFFFF, FALSE},
2221 {4, 20, 0x1F, FALSE},
2224 .relax_code_size[BR_RANGE_S16K] = 8,
2225 .relax_branch_isize[BR_RANGE_S16K] = 4,
2226 .relax_fixup[BR_RANGE_S16K] =
2228 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
2229 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP7},
2230 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
2234 .relax_code_seq[BR_RANGE_S64K] =
2236 INSN_BEQC, /* beqc $rt, imm11s, $1 */
2237 INSN_J /* j label */
2239 .relax_code_condition[BR_RANGE_S64K] =
2241 {0, 8, 0x7FF, FALSE},
2242 {0, 20, 0x1F, FALSE},
2245 .relax_code_size[BR_RANGE_S64K] = 8,
2246 .relax_branch_isize[BR_RANGE_S64K] = 4,
2247 .relax_fixup[BR_RANGE_S64K] =
2249 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
2250 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
2254 .relax_code_seq[BR_RANGE_S16M] =
2256 INSN_BEQC, /* beqc $rt, imm11s, $1 */
2257 INSN_J /* j label */
2259 .relax_code_condition[BR_RANGE_S16M] =
2261 {0, 8, 0x7FF, FALSE},
2262 {0, 20, 0x1F, FALSE},
2265 .relax_code_size[BR_RANGE_S16M] = 8,
2266 .relax_branch_isize[BR_RANGE_S16M] = 4,
2267 .relax_fixup[BR_RANGE_S16M] =
2269 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
2270 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
2274 .relax_code_seq[BR_RANGE_U4G] =
2276 INSN_BEQC, /* beqc $rt, imm11s, $1 */
2277 INSN_SETHI_TA, /* sethi $ta, label */
2278 INSN_ORI_TA, /* ori $ta, $ta, label */
2279 INSN_JR_TA /* jr $ta */
2281 .relax_code_condition[BR_RANGE_U4G] =
2283 {0, 8, 0x7FF, FALSE},
2284 {0, 20, 0x1F, FALSE},
2287 .relax_code_size[BR_RANGE_U4G] = 16,
2288 .relax_branch_isize[BR_RANGE_U4G] = 4,
2289 .relax_fixup[BR_RANGE_U4G] =
2291 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
2292 {4, 4, 0, BFD_RELOC_NDS32_HI20},
2293 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
2294 {12, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
2304 /* GAS definitions for command-line options. */
2307 OPTION_BIG = OPTION_MD_BASE,
2311 OPTION_RELAX_FP_AS_GP_OFF,
2312 OPTION_RELAX_B2BB_ON,
2313 OPTION_RELAX_ALL_OFF,
2315 OPTION_OPTIMIZE_SPACE
2318 const char *md_shortopts = "m:O:";
2319 struct option md_longopts[] =
2321 {"O1", no_argument, NULL, OPTION_OPTIMIZE},
2322 {"Os", no_argument, NULL, OPTION_OPTIMIZE_SPACE},
2323 {"big", no_argument, NULL, OPTION_BIG},
2324 {"little", no_argument, NULL, OPTION_LITTLE},
2325 {"EB", no_argument, NULL, OPTION_BIG},
2326 {"EL", no_argument, NULL, OPTION_LITTLE},
2327 {"meb", no_argument, NULL, OPTION_BIG},
2328 {"mel", no_argument, NULL, OPTION_LITTLE},
2329 {"mall-ext", no_argument, NULL, OPTION_TURBO},
2330 {"mext-all", no_argument, NULL, OPTION_TURBO},
2331 {"mpic", no_argument, NULL, OPTION_PIC},
2332 /* Relaxation related options. */
2333 {"mno-fp-as-gp-relax", no_argument, NULL, OPTION_RELAX_FP_AS_GP_OFF},
2334 {"mb2bb", no_argument, NULL, OPTION_RELAX_B2BB_ON},
2335 {"mno-all-relax", no_argument, NULL, OPTION_RELAX_ALL_OFF},
2336 {NULL, no_argument, NULL, 0}
2339 size_t md_longopts_size = sizeof (md_longopts);
2341 struct nds32_parse_option_table
2343 const char *name; /* Option string. */
2344 const char *help; /* Help description. */
2345 int (*func) (const char *arg); /* How to parse it. */
2349 /* The value `-1' represents this option has *NOT* been set. */
2350 #ifdef NDS32_DEFAULT_ARCH_NAME
2351 static const char* nds32_arch_name = NDS32_DEFAULT_ARCH_NAME;
2353 static const char* nds32_arch_name = "v3";
2355 static int nds32_baseline = -1;
2356 static int nds32_gpr16 = -1;
2357 static int nds32_fpu_sp_ext = -1;
2358 static int nds32_fpu_dp_ext = -1;
2359 static int nds32_freg = -1;
2360 static int nds32_abi = -1;
2362 /* Record ELF flags */
2363 static int nds32_elf_flags = 0;
2364 static int nds32_fpu_com = 0;
2366 static int nds32_parse_arch (const char *str);
2367 static int nds32_parse_baseline (const char *str);
2368 static int nds32_parse_freg (const char *str);
2369 static int nds32_parse_abi (const char *str);
2370 static void add_mapping_symbol (enum mstate state,
2371 unsigned int padding_byte,
2372 unsigned int align);
2374 static struct nds32_parse_option_table parse_opts [] =
2376 {"arch=", N_("<arch name>\t Assemble for architecture <arch name>\n\
2377 <arch name> could be\n\
2378 v3, v3j, v3m, v3f, v3s, "\
2379 "v2, v2j, v2f, v2s"), nds32_parse_arch},
2380 {"baseline=", N_("<baseline>\t Assemble for baseline <baseline>\n\
2381 <baseline> could be v2, v3, v3m"),
2382 nds32_parse_baseline},
2383 {"fpu-freg=", N_("<freg>\t Specify a FPU configuration\n\
2385 0: 8 SP / 4 DP registers\n\
2386 1: 16 SP / 8 DP registers\n\
2387 2: 32 SP / 16 DP registers\n\
2388 3: 32 SP / 32 DP registers"), nds32_parse_freg},
2389 {"abi=", N_("<abi>\t Specify a abi version\n\
2390 <abi> could be v1, v2, v2fp, v2fpp"), nds32_parse_abi},
2394 static int nds32_mac = 1;
2395 static int nds32_div = 1;
2396 static int nds32_16bit_ext = 1;
2397 static int nds32_dx_regs = NDS32_DEFAULT_DX_REGS;
2398 static int nds32_perf_ext = NDS32_DEFAULT_PERF_EXT;
2399 static int nds32_perf_ext2 = NDS32_DEFAULT_PERF_EXT2;
2400 static int nds32_string_ext = NDS32_DEFAULT_STRING_EXT;
2401 static int nds32_audio_ext = NDS32_DEFAULT_AUDIO_EXT;
2402 static int nds32_dsp_ext = NDS32_DEFAULT_DSP_EXT;
2403 static int nds32_zol_ext = NDS32_DEFAULT_ZOL_EXT;
2404 static int nds32_fpu_fma = 0;
2405 static int nds32_pic = 0;
2406 static int nds32_relax_fp_as_gp = 1;
2407 static int nds32_relax_b2bb = 0;
2408 static int nds32_relax_all = 1;
2409 struct nds32_set_option_table
2411 const char *name; /* Option string. */
2412 const char *help; /* Help description. */
2413 int *var; /* Variable to be set. */
2414 int value; /* Value to set. */
2417 /* The option in this group has both Enable/Disable settings.
2418 Just list on here. */
2420 static struct nds32_set_option_table toggle_opts [] =
2422 {"mac", N_("Multiply instructions support"), &nds32_mac, 1},
2423 {"div", N_("Divide instructions support"), &nds32_div, 1},
2424 {"16bit-ext", N_("16-bit extension"), &nds32_16bit_ext, 1},
2425 {"dx-regs", N_("d0/d1 registers"), &nds32_dx_regs, 1},
2426 {"perf-ext", N_("Performance extension"), &nds32_perf_ext, 1},
2427 {"perf2-ext", N_("Performance extension 2"), &nds32_perf_ext2, 1},
2428 {"string-ext", N_("String extension"), &nds32_string_ext, 1},
2429 {"reduced-regs", N_("Reduced Register configuration (GPR16) option"), &nds32_gpr16, 1},
2430 {"audio-isa-ext", N_("AUDIO ISA extension"), &nds32_audio_ext, 1},
2431 {"fpu-sp-ext", N_("FPU SP extension"), &nds32_fpu_sp_ext, 1},
2432 {"fpu-dp-ext", N_("FPU DP extension"), &nds32_fpu_dp_ext, 1},
2433 {"fpu-fma", N_("FPU fused-multiply-add instructions"), &nds32_fpu_fma, 1},
2434 {"dsp-ext", N_("DSP extension"), &nds32_dsp_ext, 1},
2435 {"zol-ext", N_("hardware loop extension"), &nds32_zol_ext, 1},
2436 {NULL, NULL, NULL, 0}
2440 /* GAS declarations. */
2442 /* This is the callback for nds32-asm.c to parse operands. */
2444 nds32_asm_parse_operand (struct nds32_asm_desc *pdesc,
2445 struct nds32_asm_insn *pinsn,
2446 char **pstr, int64_t *value);
2449 static struct nds32_asm_desc asm_desc;
2451 /* md_after_parse_args ()
2453 GAS will call md_after_parse_args whenever it is defined.
2454 This function checks any conflicting options specified. */
2457 nds32_after_parse_args (void)
2459 /* If -march option is not used in command-line, set the value of option
2460 variable according to NDS32_DEFAULT_ARCH_NAME. */
2461 nds32_parse_arch (nds32_arch_name);
2464 /* This function is called when printing usage message (--help). */
2467 md_show_usage (FILE *stream)
2469 struct nds32_parse_option_table *coarse_tune;
2470 struct nds32_set_option_table *fine_tune;
2472 fprintf (stream, _("\n NDS32-specific assembler options:\n"));
2473 fprintf (stream, _("\
2474 -O1, Optimize for performance\n\
2475 -Os Optimize for space\n"));
2476 fprintf (stream, _("\
2477 -EL, -mel or -little Produce little endian output\n\
2478 -EB, -meb or -big Produce big endian output\n\
2479 -mpic Generate PIC\n\
2480 -mno-fp-as-gp-relax Suppress fp-as-gp relaxation for this file\n\
2481 -mb2bb-relax Back-to-back branch optimization\n\
2482 -mno-all-relax Suppress all relaxation for this file\n"));
2484 for (coarse_tune = parse_opts; coarse_tune->name != NULL; coarse_tune++)
2486 if (coarse_tune->help != NULL)
2487 fprintf (stream, _(" -m%s%s\n"),
2488 coarse_tune->name, _(coarse_tune->help));
2491 for (fine_tune = toggle_opts; fine_tune->name != NULL; fine_tune++)
2493 if (fine_tune->help != NULL)
2494 fprintf (stream, _(" -m[no-]%-17sEnable/Disable %s\n"),
2495 fine_tune->name, _(fine_tune->help));
2498 fprintf (stream, _("\
2499 -mall-ext Turn on all extensions and instructions support\n"));
2503 nds32_frag_init (fragS *fragp)
2505 fragp->tc_frag_data.flag = 0;
2506 fragp->tc_frag_data.opcode = NULL;
2507 fragp->tc_frag_data.fixup = NULL;
2512 /* This function reads an expression from a C string and returns a pointer past
2513 the end of the expression. */
2516 parse_expression (char *str, expressionS *exp)
2521 tmp = input_line_pointer; /* Save line pointer. */
2522 input_line_pointer = str;
2524 s = input_line_pointer;
2525 input_line_pointer = tmp; /* Restore line pointer. */
2527 return s; /* Return pointer to where parsing stopped. */
2531 nds32_start_line_hook (void)
2539 typedef void (*nds32_pseudo_opcode_func) (int argc, char *argv[], unsigned int pv);
2540 struct nds32_pseudo_opcode
2544 nds32_pseudo_opcode_func proc;
2545 unsigned int pseudo_val;
2547 /* Some instructions are not pseudo opcode, but they might still be
2548 expanded or changed with other instruction combination for some
2549 conditions. We also apply this structure to assist such work.
2551 For example, if the distance of branch target '.L0' is larger than
2558 will be transformed into:
2564 However, sometimes we do not want assembler to do such changes
2565 because compiler knows how to generate corresponding instruction sequence.
2566 Use this field to indicate that this opcode is also a physical instruction.
2567 If the flag 'verbatim' is nozero and this opcode
2568 is a physical instruction, we should not expand it. */
2571 #define PV_DONT_CARE 0
2573 static struct hash_control *nds32_pseudo_opcode_hash = NULL;
2576 builtin_isreg (const char *s, const char *x ATTRIBUTE_UNUSED)
2578 if (s [0] == '$' && hash_find (nds32_gprs_hash, (s + 1)))
2584 builtin_regnum (const char *s, const char *x ATTRIBUTE_UNUSED)
2586 struct nds32_keyword *k;
2590 k = hash_find (nds32_gprs_hash, s);
2599 builtin_addend (const char *s, char *x ATTRIBUTE_UNUSED)
2601 const char *ptr = s;
2603 while (*ptr != '+' && *ptr != '-' && *ptr)
2609 return strtol (ptr, NULL, 0);
2613 md_assemblef (const char *format, ...)
2615 /* FIXME: hope this is long enough. */
2620 va_start (ap, format);
2621 r = vsnprintf (line, sizeof (line), format, ap);
2624 gas_assert (r < sizeof (line));
2627 /* Some prototypes here, since some op may use another op. */
2628 static void do_pseudo_li_internal (const char *rt, int imm32s);
2629 static void do_pseudo_move_reg_internal (char *dst, char *src);
2632 do_pseudo_b (int argc ATTRIBUTE_UNUSED, char *argv[],
2633 unsigned int pv ATTRIBUTE_UNUSED)
2635 char *arg_label = argv[0];
2640 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2641 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2642 md_assemble ((char *) "add $ta,$ta,$gp");
2643 md_assemble ((char *) "jr $ta");
2647 md_assemblef ("j %s", arg_label);
2653 do_pseudo_bal (int argc ATTRIBUTE_UNUSED, char *argv[],
2654 unsigned int pv ATTRIBUTE_UNUSED)
2656 char *arg_label = argv[0];
2658 /* bal|call label */
2661 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2662 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2663 md_assemble ((char *) "add $ta,$ta,$gp");
2664 md_assemble ((char *) "jral $ta");
2668 md_assemblef ("jal %s", arg_label);
2674 do_pseudo_bge (int argc ATTRIBUTE_UNUSED, char *argv[],
2675 unsigned int pv ATTRIBUTE_UNUSED)
2677 /* rt5, ra5, label */
2678 md_assemblef ("slt $ta,%s,%s", argv[0], argv[1]);
2679 md_assemblef ("beqz $ta,%s", argv[2]);
2683 do_pseudo_bges (int argc ATTRIBUTE_UNUSED, char *argv[],
2684 unsigned int pv ATTRIBUTE_UNUSED)
2686 /* rt5, ra5, label */
2687 md_assemblef ("slts $ta,%s,%s", argv[0], argv[1]);
2688 md_assemblef ("beqz $ta,%s", argv[2]);
2692 do_pseudo_bgt (int argc ATTRIBUTE_UNUSED, char *argv[],
2693 unsigned int pv ATTRIBUTE_UNUSED)
2695 /* bgt rt5, ra5, label */
2696 md_assemblef ("slt $ta,%s,%s", argv[1], argv[0]);
2697 md_assemblef ("bnez $ta,%s", argv[2]);
2701 do_pseudo_bgts (int argc ATTRIBUTE_UNUSED, char *argv[],
2702 unsigned int pv ATTRIBUTE_UNUSED)
2704 /* bgt rt5, ra5, label */
2705 md_assemblef ("slts $ta,%s,%s", argv[1], argv[0]);
2706 md_assemblef ("bnez $ta,%s", argv[2]);
2710 do_pseudo_ble (int argc ATTRIBUTE_UNUSED, char *argv[],
2711 unsigned int pv ATTRIBUTE_UNUSED)
2713 /* bgt rt5, ra5, label */
2714 md_assemblef ("slt $ta,%s,%s", argv[1], argv[0]);
2715 md_assemblef ("beqz $ta,%s", argv[2]);
2719 do_pseudo_bles (int argc ATTRIBUTE_UNUSED, char *argv[],
2720 unsigned int pv ATTRIBUTE_UNUSED)
2722 /* bgt rt5, ra5, label */
2723 md_assemblef ("slts $ta,%s,%s", argv[1], argv[0]);
2724 md_assemblef ("beqz $ta,%s", argv[2]);
2728 do_pseudo_blt (int argc ATTRIBUTE_UNUSED, char *argv[],
2729 unsigned int pv ATTRIBUTE_UNUSED)
2731 /* rt5, ra5, label */
2732 md_assemblef ("slt $ta,%s,%s", argv[0], argv[1]);
2733 md_assemblef ("bnez $ta,%s", argv[2]);
2737 do_pseudo_blts (int argc ATTRIBUTE_UNUSED, char *argv[],
2738 unsigned int pv ATTRIBUTE_UNUSED)
2740 /* rt5, ra5, label */
2741 md_assemblef ("slts $ta,%s,%s", argv[0], argv[1]);
2742 md_assemblef ("bnez $ta,%s", argv[2]);
2746 do_pseudo_br (int argc ATTRIBUTE_UNUSED, char *argv[],
2747 unsigned int pv ATTRIBUTE_UNUSED)
2749 md_assemblef ("jr %s", argv[0]);
2753 do_pseudo_bral (int argc, char *argv[],
2754 unsigned int pv ATTRIBUTE_UNUSED)
2757 md_assemblef ("jral $lp,%s", argv[0]);
2759 md_assemblef ("jral %s,%s", argv[0], argv[1]);
2763 do_pseudo_la_internal (const char *arg_reg, char *arg_label,
2768 parse_expression (arg_label, &exp);
2769 if (exp.X_op != O_symbol)
2771 as_bad (_("la must use with symbol. '%s'"), line);
2777 if (!nds32_pic && !strstr (arg_label, "@"))
2779 md_assemblef ("sethi %s,hi20(%s)", arg_reg, arg_label);
2780 md_assemblef ("ori %s,%s,lo12(%s)", arg_reg, arg_reg, arg_label);
2782 else if (strstr (arg_label, "@TPOFF"))
2784 /* la $rt, sym@TPOFF */
2785 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2786 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2787 md_assemblef ("add %s,$ta,%s", arg_reg, TLS_REG);
2789 else if (strstr(arg_label, "@GOTTPOFF"))
2791 /* la $rt, sym@GOTTPOFF*/
2792 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2793 md_assemblef ("lwi $ta,[$ta+lo12(%s)]", arg_label);
2794 md_assemblef ("add %s,$ta,%s", arg_reg, TLS_REG);
2796 else if (nds32_pic && ((strstr (arg_label, "@PLT")
2797 || strstr (arg_label, "@GOTOFF"))))
2799 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2800 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2801 md_assemblef ("add %s,$ta,$gp", arg_reg);
2803 else if (nds32_pic && strstr (arg_label, "@GOT"))
2805 long addend = builtin_addend (arg_label, NULL);
2807 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2808 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2809 md_assemblef ("lw %s,[$gp+$ta]", arg_reg);
2812 if (addend < 0x4000 && addend >= -0x4000)
2814 md_assemblef ("addi %s,%s,%d", arg_reg, arg_reg, addend);
2818 do_pseudo_li_internal ("$ta", addend);
2819 md_assemblef ("add %s,$ta,%s", arg_reg, arg_reg);
2824 as_bad (_("need PIC qualifier with symbol. '%s'"), line);
2829 do_pseudo_la (int argc ATTRIBUTE_UNUSED, char *argv[],
2830 unsigned int pv ATTRIBUTE_UNUSED)
2832 do_pseudo_la_internal (argv[0], argv[1], argv[argc]);
2836 do_pseudo_li_internal (const char *rt, int imm32s)
2838 if (enable_16bit && imm32s <= 0xf && imm32s >= -0x10)
2839 md_assemblef ("movi55 %s,%d", rt, imm32s);
2840 else if (imm32s <= 0x7ffff && imm32s >= -0x80000)
2841 md_assemblef ("movi %s,%d", rt, imm32s);
2842 else if ((imm32s & 0xfff) == 0)
2843 md_assemblef ("sethi %s,hi20(%d)", rt, imm32s);
2846 md_assemblef ("sethi %s,hi20(%d)", rt, imm32s);
2847 md_assemblef ("ori %s,%s,lo12(%d)", rt, rt, imm32s);
2852 do_pseudo_li (int argc ATTRIBUTE_UNUSED, char *argv[],
2853 unsigned int pv ATTRIBUTE_UNUSED)
2855 /* Validate argv[1] for constant expression. */
2858 parse_expression (argv[1], &exp);
2859 if (exp.X_op != O_constant)
2861 as_bad (_("Operand is not a constant. `%s'"), argv[argc]);
2865 do_pseudo_li_internal (argv[0], exp.X_add_number);
2869 do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED, char *argv[],
2874 const char *sign = "";
2876 /* Prepare arguments for various load/store. */
2877 sign = (pv & 0x10) ? "s" : "";
2878 ls = (pv & 0x80000000) ? 's' : 'l';
2881 case 0: size = 'b'; break;
2882 case 1: size = 'h'; break;
2883 case 2: size = 'w'; break;
2886 if (ls == 's' || size == 'w')
2889 if (builtin_isreg (argv[1], NULL))
2892 md_assemblef ("%c%ci %s,[%s]", ls, size, argv[0], argv[1]);
2894 else if (!nds32_pic)
2897 if (strstr (argv[1], "@TPOFF"))
2899 /* ls.w $rt, sym@TPOFF */
2900 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2901 md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
2902 md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], TLS_REG);
2904 else if (strstr (argv[1], "@GOTTPOFF"))
2906 /* ls.w $rt, sym@GOTTPOFF */
2907 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2908 md_assemblef ("lwi $ta,[$ta+lo12(%s)]", argv[1]);
2909 md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], TLS_REG);
2914 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2915 md_assemblef ("%c%c%si %s,[$ta+lo12(%s)]", ls, size, sign, argv[0], argv[1]);
2923 if (strstr (argv[1], "@GOTOFF"))
2926 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2927 md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
2928 md_assemblef ("%c%c%s %s,[$ta+$gp]", ls, size, sign, argv[0]);
2930 else if (strstr (argv[1], "@GOT"))
2932 long addend = builtin_addend (argv[1], NULL);
2934 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2935 md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
2936 md_assemble ((char *) "lw $ta,[$gp+$ta]"); /* Load address word. */
2937 if (addend < 0x10000 && addend >= -0x10000)
2939 md_assemblef ("%c%c%si %s,[$ta+(%d)]", ls, size, sign, argv[0], addend);
2944 do_pseudo_li_internal (argv[0], addend);
2945 md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], argv[0]);
2950 as_bad (_("needs @GOT or @GOTOFF. %s"), argv[argc]);
2957 do_pseudo_ls_bhwp (int argc ATTRIBUTE_UNUSED, char *argv[],
2960 char *arg_rt = argv[0];
2961 char *arg_label = argv[1];
2962 char *arg_inc = argv[2];
2965 const char *sign = "";
2967 /* Prepare arguments for various load/store. */
2968 sign = (pv & 0x10) ? "s" : "";
2969 ls = (pv & 0x80000000) ? 's' : 'l';
2972 case 0: size = 'b'; break;
2973 case 1: size = 'h'; break;
2974 case 2: size = 'w'; break;
2977 if (ls == 's' || size == 'w')
2980 do_pseudo_la_internal ("$ta", arg_label, argv[argc]);
2981 md_assemblef ("%c%c%si.bi %s,[$ta],%s", ls, size, sign, arg_rt, arg_inc);
2985 do_pseudo_ls_bhwpc (int argc ATTRIBUTE_UNUSED, char *argv[],
2988 char *arg_rt = argv[0];
2989 char *arg_inc = argv[1];
2992 const char *sign = "";
2994 /* Prepare arguments for various load/store. */
2995 sign = (pv & 0x10) ? "s" : "";
2996 ls = (pv & 0x80000000) ? 's' : 'l';
2999 case 0: size = 'b'; break;
3000 case 1: size = 'h'; break;
3001 case 2: size = 'w'; break;
3004 if (ls == 's' || size == 'w')
3007 md_assemblef ("%c%c%si.bi %s,[$ta],%s", ls, size, sign, arg_rt, arg_inc);
3011 do_pseudo_ls_bhwi (int argc ATTRIBUTE_UNUSED, char *argv[],
3016 const char *sign = "";
3018 /* Prepare arguments for various load/store. */
3019 sign = (pv & 0x10) ? "s" : "";
3020 ls = (pv & 0x80000000) ? 's' : 'l';
3023 case 0: size = 'b'; break;
3024 case 1: size = 'h'; break;
3025 case 2: size = 'w'; break;
3028 if (ls == 's' || size == 'w')
3031 md_assemblef ("%c%c%si.bi %s,%s,%s",
3032 ls, size, sign, argv[0], argv[1], argv[2]);
3036 do_pseudo_move_reg_internal (char *dst, char *src)
3039 md_assemblef ("mov55 %s,%s", dst, src);
3041 md_assemblef ("ori %s,%s,0", dst, src);
3045 do_pseudo_move (int argc ATTRIBUTE_UNUSED, char *argv[],
3046 unsigned int pv ATTRIBUTE_UNUSED)
3050 if (builtin_isreg (argv[1], NULL))
3051 do_pseudo_move_reg_internal (argv[0], argv[1]);
3054 parse_expression (argv[1], &exp);
3055 if (exp.X_op == O_constant)
3056 /* move $rt, imm -> li $rt, imm */
3057 do_pseudo_li_internal (argv[0], exp.X_add_number);
3059 /* l.w $rt, var -> l.w $rt, var */
3060 do_pseudo_ls_bhw (argc, argv, 2);
3065 do_pseudo_neg (int argc ATTRIBUTE_UNUSED, char *argv[],
3066 unsigned int pv ATTRIBUTE_UNUSED)
3068 /* Instead of "subri". */
3069 md_assemblef ("subri %s,%s,0", argv[0], argv[1]);
3073 do_pseudo_not (int argc ATTRIBUTE_UNUSED, char *argv[],
3074 unsigned int pv ATTRIBUTE_UNUSED)
3076 md_assemblef ("nor %s,%s,%s", argv[0], argv[1], argv[1]);
3080 do_pseudo_pushpopm (int argc, char *argv[],
3081 unsigned int pv ATTRIBUTE_UNUSED)
3083 /* posh/pop $ra, $rb */
3084 /* SMW.{b | a}{i | d}{m?} Rb, [Ra], Re, Enable4 */
3085 int rb, re, ra, en4;
3087 const char *opc = "pushpopm";
3090 as_bad ("'pushm/popm $ra5, $rb5, $label' is deprecated. "
3091 "Only 'pushm/popm $ra5' is supported now. %s", argv[argc]);
3093 as_bad ("'pushm/popm $ra5, $rb5'. %s\n", argv[argc]);
3095 if (strstr (argv[argc], "pop") == argv[argc])
3097 else if (strstr (argv[argc], "push") == argv[argc])
3100 as_fatal ("nds32-as internal error. %s", argv[argc]);
3102 rb = builtin_regnum (argv[0], NULL);
3103 re = builtin_regnum (argv[1], NULL);
3107 as_warn ("$rb should not be smaller than $ra. %s", argv[argc]);
3108 /* Swap to right order. */
3114 /* Build enable4 mask. */
3116 if (re >= 28 || rb >= 28)
3118 for (i = (rb >= 28? rb: 28); i <= re; i++)
3119 en4 |= 1 << (3 - (i - 28));
3122 /* Adjust $re, $rb. */
3125 else if (nds32_gpr16 != 1 && re >= 28)
3128 /* Reduce register. */
3129 if (nds32_gpr16 && re > 10 && !(rb == 31 && re == 31))
3131 if (re >= 15 && strstr (opc, "smw") != NULL)
3132 md_assemblef ("%s $r15,[$sp],$r15,%d", opc, en4);
3134 md_assemblef ("%s $r%d,[$sp],$r10, 0x0", opc, rb);
3135 if (re >= 15 && strstr (opc, "lmw") != NULL)
3136 md_assemblef ("%s $r15,[$sp],$r15,%d", opc, en4);
3139 md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc, rb, re, en4);
3143 do_pseudo_pushpop (int argc, char *argv[],
3144 unsigned int pv ATTRIBUTE_UNUSED)
3146 /* push/pop $ra5, $label=$sp */
3150 as_bad ("'push/pop $ra5, rb5' is deprecated. "
3151 "Only 'push/pop $ra5' is supported now. %s", argv[argc]);
3155 argvm[2] = argv[argc];
3156 do_pseudo_pushpopm (2, argvm, PV_DONT_CARE);
3160 do_pseudo_v3push (int argc ATTRIBUTE_UNUSED, char *argv[],
3161 unsigned int pv ATTRIBUTE_UNUSED)
3163 md_assemblef ("push25 %s,%s", argv[0], argv[1]);
3167 do_pseudo_v3pop (int argc ATTRIBUTE_UNUSED, char *argv[],
3168 unsigned int pv ATTRIBUTE_UNUSED)
3170 md_assemblef ("pop25 %s,%s", argv[0], argv[1]);
3173 /* pv == 0, parsing "push.s" pseudo instruction operands.
3174 pv != 0, parsing "pop.s" pseudo instruction operands. */
3177 do_pseudo_pushpop_stack (int argc, char *argv[],
3180 /* push.s Rb,Re,{$fp $gp $lp $sp} ==> smw.adm Rb,[$sp],Re,Eable4 */
3181 /* pop.s Rb,Re,{$fp $gp $lp $sp} ==> lmw.bim Rb,[$sp],Re,Eable4 */
3186 const char *opc = (pv == 0) ? "smw.adm" : "lmw.bim";
3192 /* argc=1, operands pattern: { $fp $gp $lp $sp } */
3194 /* Set register number Rb = Re = $sp = $r31. */
3197 else if (argc == 2 || argc == 3)
3199 /* argc=2, operands pattern: Rb, Re */
3200 /* argc=3, operands pattern: Rb, Re, { $fp $gp $lp $sp } */
3202 /* Get register number in integer. */
3203 rb = builtin_regnum (argv[0], NULL);
3204 re = builtin_regnum (argv[1], NULL);
3206 /* Rb should be equal/less than Re. */
3208 as_bad ("The first operand (%s) should be equal to or smaller than "
3209 "second operand (%s).", argv[0], argv[1]);
3211 /* forbid using $fp|$gp|$lp|$sp in Rb or Re
3214 as_bad ("Cannot use $fp, $gp, $lp, or $sp at first operand !!");
3216 as_bad ("Cannot use $fp, $gp, $lp, or $sp at second operand !!");
3220 as_bad ("Invalid operands pattern !!");
3223 /* Build Enable4 mask. */
3224 /* Using last_arg_index for argc=1|2|3 is safe, because $fp, $gp, $lp,
3225 and $sp only appear in argc=1 or argc=3 if argc=2, en4 remains 0,
3226 which is also valid for code generation. */
3228 last_arg_index = argc - 1;
3229 if (strstr (argv[last_arg_index], "$fp"))
3231 if (strstr (argv[last_arg_index], "$gp"))
3233 if (strstr (argv[last_arg_index], "$lp"))
3235 if (strstr (argv[last_arg_index], "$sp"))
3238 md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc, rb, re, en4);
3242 do_pseudo_push_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[],
3243 unsigned int pv ATTRIBUTE_UNUSED)
3246 /* If users omit push location, use $sp as default value. */
3247 char location[8] = "$sp"; /* 8 is enough for register name. */
3251 case 0: size = 'b'; break;
3252 case 1: size = 'h'; break;
3253 case 2: size = 'w'; break;
3254 case 3: size = 'w'; break;
3259 strncpy (location, argv[1], 8);
3263 md_assemblef ("l.%c $ta,%s", size, argv[0]);
3264 md_assemblef ("smw.adm $ta,[%s],$ta", location);
3266 if ((pv & 0x3) == 0x3) /* double-word */
3268 md_assemblef ("l.w $ta,%s+4", argv[0]);
3269 md_assemblef ("smw.adm $ta,[%s],$ta", location);
3274 do_pseudo_pop_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[],
3275 unsigned int pv ATTRIBUTE_UNUSED)
3278 /* If users omit pop location, use $sp as default value. */
3279 char location[8] = "$sp"; /* 8 is enough for register name. */
3283 case 0: size = 'b'; break;
3284 case 1: size = 'h'; break;
3285 case 2: size = 'w'; break;
3286 case 3: size = 'w'; break;
3291 strncpy (location, argv[2], 8);
3295 if ((pv & 0x3) == 0x3) /* double-word */
3297 md_assemblef ("lmw.bim %s,[%s],%s", argv[1], location, argv[1]);
3298 md_assemblef ("s.w %s,%s+4", argv[1], argv[0]);
3301 md_assemblef ("lmw.bim %s,[%s],%s", argv[1], location, argv[1]);
3302 md_assemblef ("s.%c %s,%s", size, argv[1], argv[0]);
3306 do_pseudo_pusha (int argc ATTRIBUTE_UNUSED, char *argv[],
3307 unsigned int pv ATTRIBUTE_UNUSED)
3309 /* If users omit push location, use $sp as default value. */
3310 char location[8] = "$sp"; /* 8 is enough for register name. */
3314 strncpy (location, argv[1], 8);
3318 md_assemblef ("la $ta,%s", argv[0]);
3319 md_assemblef ("smw.adm $ta,[%s],$ta", location);
3323 do_pseudo_pushi (int argc ATTRIBUTE_UNUSED, char *argv[],
3324 unsigned int pv ATTRIBUTE_UNUSED)
3326 /* If users omit push location, use $sp as default value. */
3327 char location[8] = "$sp"; /* 8 is enough for register name. */
3331 strncpy (location, argv[1], 8);
3335 md_assemblef ("li $ta,%s", argv[0]);
3336 md_assemblef ("smw.adm $ta,[%s],$ta", location);
3339 static struct nds32_pseudo_opcode nds32_pseudo_opcode_table[] =
3341 {"b", 1, do_pseudo_b, 0, 0},
3342 {"bal", 1, do_pseudo_bal, 0, 0},
3344 {"bge", 3, do_pseudo_bge, 0, 0},
3345 {"bges", 3, do_pseudo_bges, 0, 0},
3347 {"bgt", 3, do_pseudo_bgt, 0, 0},
3348 {"bgts", 3, do_pseudo_bgts, 0, 0},
3350 {"ble", 3, do_pseudo_ble, 0, 0},
3351 {"bles", 3, do_pseudo_bles, 0, 0},
3353 {"blt", 3, do_pseudo_blt, 0, 0},
3354 {"blts", 3, do_pseudo_blts, 0, 0},
3356 {"br", 1, do_pseudo_br, 0, 0},
3357 {"bral", 1, do_pseudo_bral, 0, 0},
3359 {"call", 1, do_pseudo_bal, 0, 0},
3361 {"la", 2, do_pseudo_la, 0, 0},
3362 {"li", 2, do_pseudo_li, 0, 0},
3364 {"l.b", 2, do_pseudo_ls_bhw, 0, 0},
3365 {"l.h", 2, do_pseudo_ls_bhw, 1, 0},
3366 {"l.w", 2, do_pseudo_ls_bhw, 2, 0},
3367 {"l.bs", 2, do_pseudo_ls_bhw, 0 | 0x10, 0},
3368 {"l.hs", 2, do_pseudo_ls_bhw, 1 | 0x10, 0},
3369 {"s.b", 2, do_pseudo_ls_bhw, 0 | 0x80000000, 0},
3370 {"s.h", 2, do_pseudo_ls_bhw, 1 | 0x80000000, 0},
3371 {"s.w", 2, do_pseudo_ls_bhw, 2 | 0x80000000, 0},
3373 {"l.bp", 3, do_pseudo_ls_bhwp, 0, 0},
3374 {"l.bpc", 3, do_pseudo_ls_bhwpc, 0, 0},
3375 {"l.hp", 3, do_pseudo_ls_bhwp, 1, 0},
3376 {"l.hpc", 3, do_pseudo_ls_bhwpc, 1, 0},
3377 {"l.wp", 3, do_pseudo_ls_bhwp, 2, 0},
3378 {"l.wpc", 3, do_pseudo_ls_bhwpc, 2, 0},
3379 {"l.bsp", 3, do_pseudo_ls_bhwp, 0 | 0x10, 0},
3380 {"l.bspc", 3, do_pseudo_ls_bhwpc, 0 | 0x10, 0},
3381 {"l.hsp", 3, do_pseudo_ls_bhwp, 1 | 0x10, 0},
3382 {"l.hspc", 3, do_pseudo_ls_bhwpc, 1 | 0x10, 0},
3383 {"s.bp", 3, do_pseudo_ls_bhwp, 0 | 0x80000000, 0},
3384 {"s.bpc", 3, do_pseudo_ls_bhwpc, 0 | 0x80000000, 0},
3385 {"s.hp", 3, do_pseudo_ls_bhwp, 1 | 0x80000000, 0},
3386 {"s.hpc", 3, do_pseudo_ls_bhwpc, 1 | 0x80000000, 0},
3387 {"s.wp", 3, do_pseudo_ls_bhwp, 2 | 0x80000000, 0},
3388 {"s.wpc", 3, do_pseudo_ls_bhwpc, 2 | 0x80000000, 0},
3389 {"s.bsp", 3, do_pseudo_ls_bhwp, 0 | 0x80000000 | 0x10, 0},
3390 {"s.hsp", 3, do_pseudo_ls_bhwp, 1 | 0x80000000 | 0x10, 0},
3392 {"lbi.p", 3, do_pseudo_ls_bhwi, 0, 0},
3393 {"lhi.p", 3, do_pseudo_ls_bhwi, 1, 0},
3394 {"lwi.p", 3, do_pseudo_ls_bhwi, 2, 0},
3395 {"sbi.p", 3, do_pseudo_ls_bhwi, 0 | 0x80000000, 0},
3396 {"shi.p", 3, do_pseudo_ls_bhwi, 1 | 0x80000000, 0},
3397 {"swi.p", 3, do_pseudo_ls_bhwi, 2 | 0x80000000, 0},
3398 {"lbsi.p", 3, do_pseudo_ls_bhwi, 0 | 0x10, 0},
3399 {"lhsi.p", 3, do_pseudo_ls_bhwi, 1 | 0x10, 0},
3400 {"lwsi.p", 3, do_pseudo_ls_bhwi, 2 | 0x10, 0},
3402 {"move", 2, do_pseudo_move, 0, 0},
3403 {"neg", 2, do_pseudo_neg, 0, 0},
3404 {"not", 2, do_pseudo_not, 0, 0},
3406 {"pop", 2, do_pseudo_pushpop, 0, 0},
3407 {"push", 2, do_pseudo_pushpop, 0, 0},
3408 {"popm", 2, do_pseudo_pushpopm, 0, 0},
3409 {"pushm", 3, do_pseudo_pushpopm, 0, 0},
3411 {"v3push", 2, do_pseudo_v3push, 0, 0},
3412 {"v3pop", 2, do_pseudo_v3pop, 0, 0},
3414 /* Support pseudo instructions of pushing/poping registers into/from stack
3415 push.s Rb, Re, { $fp $gp $lp $sp } ==> smw.adm Rb,[$sp],Re,Enable4
3416 pop.s Rb, Re, { $fp $gp $lp $sp } ==> lmw.bim Rb,[$sp],Re,Enable4 */
3417 { "push.s", 3, do_pseudo_pushpop_stack, 0, 0 },
3418 { "pop.s", 3, do_pseudo_pushpop_stack, 1, 0 },
3419 { "push.b", 2, do_pseudo_push_bhwd, 0, 0 },
3420 { "push.h", 2, do_pseudo_push_bhwd, 1, 0 },
3421 { "push.w", 2, do_pseudo_push_bhwd, 2, 0 },
3422 { "push.d", 2, do_pseudo_push_bhwd, 3, 0 },
3423 { "pop.b", 3, do_pseudo_pop_bhwd, 0, 0 },
3424 { "pop.h", 3, do_pseudo_pop_bhwd, 1, 0 },
3425 { "pop.w", 3, do_pseudo_pop_bhwd, 2, 0 },
3426 { "pop.d", 3, do_pseudo_pop_bhwd, 3, 0 },
3427 { "pusha", 2, do_pseudo_pusha, 0, 0 },
3428 { "pushi", 2, do_pseudo_pushi, 0, 0 },
3430 {NULL, 0, NULL, 0, 0}
3434 nds32_init_nds32_pseudo_opcodes (void)
3436 struct nds32_pseudo_opcode *opcode = nds32_pseudo_opcode_table;
3438 nds32_pseudo_opcode_hash = hash_new ();
3439 for ( ; opcode->opcode; opcode++)
3443 op = hash_find (nds32_pseudo_opcode_hash, opcode->opcode);
3446 as_warn (_("Duplicated pseudo-opcode %s."), opcode->opcode);
3449 hash_insert (nds32_pseudo_opcode_hash, opcode->opcode, opcode);
3453 static struct nds32_pseudo_opcode *
3454 nds32_lookup_pseudo_opcode (const char *str)
3456 struct nds32_pseudo_opcode *result;
3459 /* (*op) is the first word of current source line (*str) */
3460 int maxlen = strlen (str);
3461 char *op = xmalloc (maxlen + 1);
3463 for (i = 0; i < maxlen; i++)
3465 if (ISSPACE (op[i] = str[i]))
3470 result = hash_find (nds32_pseudo_opcode_hash, op);
3476 nds32_pseudo_opcode_wrapper (char *line, struct nds32_pseudo_opcode *opcode)
3479 char *argv[8] = {NULL};
3481 char *str = xstrdup (line);
3483 /* Parse arguments for opcode. */
3484 s = str + strlen (opcode->opcode);
3489 /* Dummy comma to ease separate arguments as below. */
3495 if (argc >= opcode->argc
3496 || (argc >= (int)ARRAY_SIZE (argv) - 1))
3497 as_bad (_("Too many argument. `%s'"), line);
3504 } while (s[0] != '\0');
3506 /* Put the origin line for debugging. */
3508 opcode->proc (argc, argv, opcode->pseudo_val);
3512 /* This function will be invoked from function `nds32_after_parse_args'.
3513 Thus, if the value of option has been set, keep the value the way it is. */
3516 nds32_parse_arch (const char *str)
3518 static const struct nds32_arch
3529 {"v3m", ISA_V3M, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3530 {"v3j", ISA_V3, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3531 {"v3s", ISA_V3, 0, 1, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3532 {"v3f", ISA_V3, 0, 1, 1, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3533 {"v3", ISA_V3, 0, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3534 {"v2j", ISA_V2, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3535 {"v2s", ISA_V2, 0, 1, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3536 {"v2f", ISA_V2, 0, 1, 1, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3537 {"v2", ISA_V2, 0, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3541 for (i = 0; i < ARRAY_SIZE (archs); i++)
3543 if (strcmp (str, archs[i].name) != 0)
3546 /* The value `-1' represents this option has *NOT* been set. */
3547 nds32_baseline = (-1 != nds32_baseline) ? nds32_baseline : archs[i].baseline;
3548 nds32_gpr16 = (-1 != nds32_gpr16) ? nds32_gpr16 : archs[i].reduced_reg;
3549 nds32_fpu_sp_ext = (-1 != nds32_fpu_sp_ext) ? nds32_fpu_sp_ext : archs[i].fpu_sp_ext;
3550 nds32_fpu_dp_ext = (-1 != nds32_fpu_dp_ext) ? nds32_fpu_dp_ext : archs[i].fpu_dp_ext;
3551 nds32_freg = (-1 != nds32_freg) ? nds32_freg : archs[i].fpu_freg;
3552 nds32_abi = (-1 != nds32_abi) ? nds32_abi : archs[i].abi;
3557 /* Logic here rejects the input arch name. */
3558 as_bad (_("unknown arch name `%s'\n"), str);
3563 /* This function parses "baseline" specified. */
3566 nds32_parse_baseline (const char *str)
3568 if (strcmp (str, "v3") == 0)
3569 nds32_baseline = ISA_V3;
3570 else if (strcmp (str, "v3m") == 0)
3571 nds32_baseline = ISA_V3M;
3572 else if (strcmp (str, "v2") == 0)
3573 nds32_baseline = ISA_V2;
3576 /* Logic here rejects the input baseline. */
3577 as_bad (_("unknown baseline `%s'\n"), str);
3584 /* This function parses "fpu-freg" specified. */
3587 nds32_parse_freg (const char *str)
3589 if (strcmp (str, "2") == 0)
3590 nds32_freg = E_NDS32_FPU_REG_32SP_16DP;
3591 else if (strcmp (str, "3") == 0)
3592 nds32_freg = E_NDS32_FPU_REG_32SP_32DP;
3593 else if (strcmp (str, "1") == 0)
3594 nds32_freg = E_NDS32_FPU_REG_16SP_8DP;
3595 else if (strcmp (str, "0") == 0)
3596 nds32_freg = E_NDS32_FPU_REG_8SP_4DP;
3599 /* Logic here rejects the input FPU configuration. */
3600 as_bad (_("unknown FPU configuration `%s'\n"), str);
3607 /* This function parse "abi=" specified. */
3610 nds32_parse_abi (const char *str)
3612 if (strcmp (str, "v2") == 0)
3613 nds32_abi = E_NDS_ABI_AABI;
3615 else if (strcmp (str, "v2fp") == 0)
3616 nds32_abi = E_NDS_ABI_V2FP;
3617 else if (strcmp (str, "v1") == 0)
3618 nds32_abi = E_NDS_ABI_V1;
3619 else if (strcmp (str,"v2fpp") == 0)
3620 nds32_abi = E_NDS_ABI_V2FP_PLUS;
3623 /* Logic here rejects the input abi version. */
3624 as_bad (_("unknown ABI version`%s'\n"), str);
3631 /* This function turn on all extensions and instructions support. */
3634 nds32_all_ext (void)
3639 nds32_16bit_ext = 1;
3641 nds32_perf_ext2 = 1;
3642 nds32_string_ext = 1;
3643 nds32_audio_ext = 1;
3645 nds32_fpu_sp_ext = 1;
3646 nds32_fpu_dp_ext = 1;
3649 /* Turn off reduced register. */
3655 /* GAS will call md_parse_option whenever getopt returns an unrecognized code,
3656 presumably indicating a special code value which appears in md_longopts.
3657 This function should return non-zero if it handled the option and zero
3658 otherwise. There is no need to print a message about an option not being
3659 recognized. This will be handled by the generic code. */
3662 nds32_parse_option (int c, const char *arg)
3664 struct nds32_parse_option_table *coarse_tune;
3665 struct nds32_set_option_table *fine_tune;
3666 const char *ptr_arg = NULL;
3670 case OPTION_OPTIMIZE:
3672 optimize_for_space = 0;
3674 case OPTION_OPTIMIZE_SPACE:
3676 optimize_for_space = 1;
3679 target_big_endian = 1;
3682 target_big_endian = 0;
3690 case OPTION_RELAX_FP_AS_GP_OFF:
3691 nds32_relax_fp_as_gp = 0;
3693 case OPTION_RELAX_B2BB_ON:
3694 nds32_relax_b2bb = 1;
3696 case OPTION_RELAX_ALL_OFF:
3697 nds32_relax_all = 0;
3700 /* Determination of which option table to search for to save time. */
3704 ptr_arg = strchr (arg, '=');
3708 /* Find the value after '='. */
3709 if (ptr_arg != NULL)
3711 for (coarse_tune = parse_opts; coarse_tune->name != NULL; coarse_tune++)
3713 if (strncmp (arg, coarse_tune->name, (ptr_arg - arg)) == 0)
3715 coarse_tune->func (ptr_arg);
3724 /* Filter out the Disable option first. */
3725 if (strncmp (arg, "no-", 3) == 0)
3731 for (fine_tune = toggle_opts; fine_tune->name != NULL; fine_tune++)
3733 if (strcmp (arg, fine_tune->name) == 0)
3735 if (fine_tune->var != NULL)
3736 *fine_tune->var = (disable) ? 0 : 1;
3741 /* Nothing match. */
3748 /* tc_check_label */
3751 nds32_check_label (symbolS *label ATTRIBUTE_UNUSED)
3753 /* The code used to create BB is move to frob_label.
3754 They should go there. */
3758 set_endian_little (int on)
3760 target_big_endian = !on;
3763 /* These functions toggles the generation of 16-bit. First encounter signals
3764 the beginning of not generating 16-bit instructions and next encounter
3765 signals the restoring back to default behavior. */
3768 trigger_16bit (int trigger)
3770 enable_16bit = trigger;
3773 static int backup_16bit_mode;
3775 restore_16bit (int no_use ATTRIBUTE_UNUSED)
3777 enable_16bit = backup_16bit_mode;
3781 off_16bit (int no_use ATTRIBUTE_UNUSED)
3783 backup_16bit_mode = enable_16bit;
3787 /* Built-in segments for small object. */
3788 typedef struct nds32_seg_entryT
3795 nds32_seg_entry nds32_seg_table[] =
3797 {NULL, ".sdata_f", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3798 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3799 {NULL, ".sdata_b", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3800 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3801 {NULL, ".sdata_h", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3802 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3803 {NULL, ".sdata_w", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3804 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3805 {NULL, ".sdata_d", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3806 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3807 {NULL, ".sbss_f", SEC_ALLOC | SEC_SMALL_DATA},
3808 {NULL, ".sbss_b", SEC_ALLOC | SEC_SMALL_DATA},
3809 {NULL, ".sbss_h", SEC_ALLOC | SEC_SMALL_DATA},
3810 {NULL, ".sbss_w", SEC_ALLOC | SEC_SMALL_DATA},
3811 {NULL, ".sbss_d", SEC_ALLOC | SEC_SMALL_DATA}
3814 /* Indexes to nds32_seg_table[]. */
3815 enum NDS32_SECTIONS_ENUM
3817 SDATA_F_SECTION = 0,
3818 SDATA_B_SECTION = 1,
3819 SDATA_H_SECTION = 2,
3820 SDATA_W_SECTION = 3,
3821 SDATA_D_SECTION = 4,
3829 /* The following code is borrowed from v850_seg. Revise this is needed. */
3832 do_nds32_seg (int i, subsegT sub)
3834 nds32_seg_entry *seg = nds32_seg_table + i;
3836 obj_elf_section_change_hook ();
3839 subseg_set (seg->s, sub);
3842 seg->s = subseg_new (seg->name, sub);
3843 if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
3845 bfd_set_section_flags (stdoutput, seg->s, seg->flags);
3846 if ((seg->flags & SEC_LOAD) == 0)
3847 seg_info (seg->s)->bss = 1;
3855 subsegT sub = get_absolute_expression ();
3857 do_nds32_seg (i, sub);
3858 demand_empty_rest_of_line ();
3861 /* Set if label adjustment is needed. I should not adjust .xbyte in dwarf. */
3862 static symbolS *nds32_last_label; /* Last label for alignment. */
3865 add_mapping_symbol_for_align (int shift, valueT addr, int is_data_align)
3867 if ((shift > 1) && (addr & 1))
3869 int n = (1 << shift) - 1;
3871 add_mapping_symbol (MAP_CODE, 1, 0);
3872 else if ((int) (addr & n) != n)
3873 add_mapping_symbol (MAP_CODE, 1, 0);
3875 else if ((shift > 1) && ((int) (addr & 1) == 0))
3876 add_mapping_symbol (MAP_CODE, 0, 0);
3879 /* This code is referred from D30V for adjust label to be with pending
3880 alignment. For example,
3884 Without this, the above label will not attach to incoming data. */
3887 nds32_adjust_label (int n)
3889 /* FIXME: I think adjust label and alignment is
3890 the programmer's obligation. Sadly, VLSI team doesn't
3891 properly use .align for their test cases.
3892 So I re-implement cons_align and auto adjust labels, again.
3894 I think d30v's implementation is simple and good enough. */
3896 symbolS *label = nds32_last_label;
3897 nds32_last_label = NULL;
3899 /* SEC_ALLOC is used to eliminate .debug_ sections.
3900 SEC_CODE is used to include section for ILM. */
3901 if (((now_seg->flags & SEC_ALLOC) == 0 && (now_seg->flags & SEC_CODE) == 0)
3902 || strcmp (now_seg->name, ".eh_frame") == 0
3903 || strcmp (now_seg->name, ".gcc_except_table") == 0)
3906 /* Only frag by alignment when needed.
3907 Otherwise, it will fail to optimize labels on 4-byte boundary. (bug8454)
3908 See md_convert_frag () and RELAX_SET_RELAXABLE (frag) for details. */
3909 if (frag_now_fix () & ((1 << n) -1 ))
3911 if (subseg_text_p (now_seg))
3913 add_mapping_symbol_for_align (n, frag_now_fix (), 1);
3914 frag_align_code (n, 0);
3917 frag_align (n, 0, 0);
3919 /* Record the minimum alignment for this segment. */
3920 record_alignment (now_seg, n - OCTETS_PER_BYTE_POWER);
3926 int label_seen = FALSE;
3927 struct frag *old_frag;
3928 valueT old_value, new_value;
3930 gas_assert (S_GET_SEGMENT (label) == now_seg);
3932 old_frag = symbol_get_frag (label);
3933 old_value = S_GET_VALUE (label);
3934 new_value = (valueT) frag_now_fix ();
3936 /* Multiple labels may be on the same address. And the last symbol
3937 may not be a label at all, e.g., register name, external function names,
3938 so I have to track the last label in tc_frob_label instead of
3939 just using symbol_lastP. */
3940 for (sym = symbol_lastP; sym != NULL; sym = symbol_previous (sym))
3942 if (symbol_get_frag (sym) == old_frag
3943 && S_GET_VALUE (sym) == old_value)
3947 symbol_set_frag (sym, frag_now);
3948 S_SET_VALUE (sym, new_value);
3950 else if (label_seen && symbol_get_frag (sym) != old_frag)
3957 nds32_cons_align (int size ATTRIBUTE_UNUSED)
3960 This is called before `md_flush_pending_output' is called by `cons'.
3962 There are two things should be done for auto-adjust-label.
3963 1. Align data/instructions and adjust label to be attached to them.
3964 2. Clear auto-adjust state, so incoming data/instructions will not
3972 in this case, '.word 0x2' will adjust the label, .L0, but '.word 0x3' should not.
3974 I think `md_flush_pending_output' is a good place to clear the auto-adjust state,
3975 but it is also called by `cons' before this function.
3976 To simplify the code, instead of overriding .zero, .fill, .space, etc,
3977 I think we should just adjust label in `nds32_aligned_X_cons' instead of here. */
3981 make_mapping_symbol (enum mstate state, valueT value, fragS * frag, unsigned int align)
3983 symbolS *symbol_p = NULL;
3984 const char *symbol_name = NULL;
3989 symbol_name = "$d0";
3990 else if (align == 1)
3991 symbol_name = "$d1";
3992 else if (align == 2)
3993 symbol_name = "$d2";
3994 else if (align == 3)
3995 symbol_name = "$d3";
3996 else if (align == 4)
3997 symbol_name = "$d4";
4006 symbol_p = symbol_new (symbol_name, now_seg, value, frag);
4007 /* local scope attribute */
4008 symbol_get_bfdsym (symbol_p)->flags |= BSF_NO_FLAGS | BSF_LOCAL;
4012 add_mapping_symbol (enum mstate state, unsigned int padding_byte,
4015 enum mstate current_mapping_state =
4016 seg_info (now_seg)->tc_segment_info_data.mapstate;
4018 if (state == MAP_CODE
4019 && current_mapping_state == state)
4022 if (!SEG_NORMAL (now_seg)
4023 || !subseg_text_p (now_seg))
4026 /* start adding mapping symbol */
4027 seg_info (now_seg)->tc_segment_info_data.mapstate = state;
4028 make_mapping_symbol (state, (valueT) frag_now_fix () + padding_byte,
4033 nds32_aligned_cons (int idx)
4035 nds32_adjust_label (idx);
4036 add_mapping_symbol (MAP_DATA, 0, idx);
4037 /* Call default handler. */
4039 if (now_seg->flags & SEC_CODE
4040 && now_seg->flags & SEC_ALLOC && now_seg->flags & SEC_RELOC)
4042 /* Use BFD_RELOC_NDS32_DATA to avoid linker
4043 optimization replacing data. */
4046 exp.X_add_number = 0;
4047 exp.X_op = O_constant;
4048 fix_new_exp (frag_now, frag_now_fix () - (1 << idx), 1 << idx,
4049 &exp, 0, BFD_RELOC_NDS32_DATA);
4053 /* `.double' directive. */
4056 nds32_aligned_float_cons (int type)
4064 nds32_adjust_label (2);
4070 nds32_adjust_label (4);
4073 as_bad ("Unrecognized float type, %c\n", (char)type);
4075 /* Call default handler. */
4080 nds32_enable_pic (int ignore ATTRIBUTE_UNUSED)
4082 /* Another way to do -mpic.
4083 This is for GCC internal use and should always be first line
4084 of code, otherwise, the effect is not determined. */
4089 nds32_set_abi (int ver)
4094 /* Relax directive to set relocation R_NDS32_RELAX_ENTRY value. */
4097 nds32_relax_relocs (int relax)
4102 const char *subtype_relax[] =
4105 name = input_line_pointer;
4106 while (*input_line_pointer && !ISSPACE (*input_line_pointer))
4107 input_line_pointer++;
4108 saved_char = *input_line_pointer;
4109 *input_line_pointer = 0;
4111 for (i = 0; i < (int) ARRAY_SIZE (subtype_relax); i++)
4113 if (strcmp (name, subtype_relax[i]) == 0)
4119 enable_relax_relocs = relax & enable_relax_relocs;
4127 *input_line_pointer = saved_char;
4128 ignore_rest_of_line ();
4131 /* Record which arguments register($r0 ~ $r5) is not used in callee.
4135 nds32_set_hint_func_args (int ignore ATTRIBUTE_UNUSED)
4137 ignore_rest_of_line ();
4140 /* Insert relocations to mark the begin and end of a fp-omitted function,
4141 for further relaxation use.
4145 nds32_omit_fp_begin (int mode)
4149 if (nds32_relax_fp_as_gp == 0)
4151 exp.X_op = O_symbol;
4152 exp.X_add_symbol = abs_section_sym;
4156 exp.X_add_number = R_NDS32_RELAX_REGION_OMIT_FP_FLAG;
4157 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
4158 BFD_RELOC_NDS32_RELAX_REGION_BEGIN);
4163 exp.X_add_number = R_NDS32_RELAX_REGION_OMIT_FP_FLAG;
4164 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
4165 BFD_RELOC_NDS32_RELAX_REGION_END);
4170 nds32_loop_begin (int mode)
4172 /* Insert loop region relocation here. */
4175 exp.X_op = O_symbol;
4176 exp.X_add_symbol = abs_section_sym;
4179 exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG;
4180 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
4181 BFD_RELOC_NDS32_RELAX_REGION_BEGIN);
4185 exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG;
4186 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
4187 BFD_RELOC_NDS32_RELAX_REGION_END);
4191 struct nds32_relocs_group
4193 struct nds32_relocs_pattern *pattern;
4194 struct nds32_relocs_group *next;
4197 static struct nds32_relocs_group *nds32_relax_hint_current = NULL;
4198 /* Used to reorder the id for ".relax_hint id". */
4199 static int relax_hint_bias = 0;
4200 /* Record current relax hint id. */
4201 static int relax_hint_id_current = -1;
4203 /* If ".relax_hint begin" is triggered? */
4204 int relax_hint_begin = 0;
4206 /* Record the reordered relax hint id. */
4208 struct relax_hint_id
4212 struct relax_hint_id *next;
4215 /* FIXME: Need to find somewhere to free the list. */
4216 struct relax_hint_id *record_id_head = NULL;
4218 /* Is the buffer large enough? */
4219 #define MAX_BUFFER 12
4221 static char *nds_itoa (int n);
4226 char *buf = xmalloc (MAX_BUFFER * sizeof (char));
4227 snprintf (buf, MAX_BUFFER, "%d", n);
4231 /* Insert a relax hint. */
4234 nds32_relax_hint (int mode ATTRIBUTE_UNUSED)
4238 struct nds32_relocs_pattern *relocs = NULL;
4239 struct nds32_relocs_group *group, *new;
4240 struct relax_hint_id *record_id;
4242 name = input_line_pointer;
4243 while (*input_line_pointer && !ISSPACE (*input_line_pointer))
4244 input_line_pointer++;
4245 saved_char = *input_line_pointer;
4246 *input_line_pointer = 0;
4247 name = strdup (name);
4249 if (name && strcmp (name, "begin") == 0)
4251 if (relax_hint_id_current == -1)
4254 relax_hint_id_current++;
4255 relax_hint_begin = 1;
4258 /* Original case ".relax_hint id". It's id may need to be reordered. */
4259 if (!relax_hint_begin)
4261 int tmp = strtol (name, NULL, 10);
4262 record_id = record_id_head;
4265 if (record_id->old_id == tmp)
4267 name = nds_itoa (record_id->new_id);
4270 record_id = record_id->next;
4274 relax_hint_bias = relax_hint_id_current - atoi (name) + 1;
4277 relax_hint_id_current = tmp + relax_hint_bias;
4279 /* Insert the element to the head of the link list. */
4280 struct relax_hint_id *tmp_id = malloc (sizeof (struct relax_hint_id));
4281 tmp_id->old_id = tmp;
4282 tmp_id->new_id = relax_hint_id_current;
4283 tmp_id->next = record_id_head;
4284 record_id_head = tmp_id;
4287 if (name && strcmp (name, "end") == 0)
4288 relax_hint_begin = 0;
4289 name = nds_itoa (relax_hint_id_current);
4293 /* Find relax hint entry for next instruction, and all member will be
4294 initialized at that time. */
4295 relocs = hash_find (nds32_hint_hash, name);
4298 relocs = XNEW (struct nds32_relocs_pattern);
4299 memset (relocs, 0, sizeof (struct nds32_relocs_pattern));
4300 hash_insert (nds32_hint_hash, name, relocs);
4304 while (relocs->next)
4305 relocs=relocs->next;
4306 relocs->next = XNEW (struct nds32_relocs_pattern);
4307 relocs = relocs->next;
4308 memset (relocs, 0, sizeof (struct nds32_relocs_pattern));
4311 relocs->next = NULL;
4312 *input_line_pointer = saved_char;
4313 ignore_rest_of_line ();
4315 /* Get the final one of relax hint series. */
4317 /* It has to build this list because there are maybe more than one
4318 instructions relative to the same instruction. It to connect to
4319 next instruction after md_assemble. */
4320 new = XNEW (struct nds32_relocs_group);
4321 memset (new, 0, sizeof (struct nds32_relocs_group));
4322 new->pattern = relocs;
4324 group = nds32_relax_hint_current;
4326 nds32_relax_hint_current = new;
4329 while (group->next != NULL)
4330 group = group->next;
4336 /* Decide the size of vector entries, only accepts 4 or 16 now. */
4339 nds32_vec_size (int ignore ATTRIBUTE_UNUSED)
4345 if (exp.X_op == O_constant)
4347 if (exp.X_add_number == 4 || exp.X_add_number == 16)
4350 vec_size = exp.X_add_number;
4351 else if (vec_size != exp.X_add_number)
4352 as_warn (_("Different arguments of .vec_size are found, "
4353 "previous %d, current %d"),
4354 (int) vec_size, (int) exp.X_add_number);
4357 as_warn (_("Argument of .vec_size is expected 4 or 16, actual: %d."),
4358 (int) exp.X_add_number);
4361 as_warn (_("Argument of .vec_size is not a constant."));
4364 /* The behavior of ".flag" directive varies depending on the target.
4365 In nds32 target, we use it to recognize whether this assembly content is
4366 generated by compiler. Other features can also be added in this function
4370 nds32_flag (int ignore ATTRIBUTE_UNUSED)
4375 const char *possible_flags[] = { "verbatim" };
4377 /* Skip whitespaces. */
4378 name = input_line_pointer;
4379 while (*input_line_pointer && !ISSPACE (*input_line_pointer))
4380 input_line_pointer++;
4381 saved_char = *input_line_pointer;
4382 *input_line_pointer = 0;
4384 for (i = 0; i < (int) ARRAY_SIZE (possible_flags); i++)
4386 if (strcmp (name, possible_flags[i]) == 0)
4391 /* flag: verbatim */
4397 /* Already found the flag, no need to continue next loop. */
4402 *input_line_pointer = saved_char;
4403 ignore_rest_of_line ();
4407 ict_model (int ignore ATTRIBUTE_UNUSED)
4412 const char *possible_flags[] = { "small", "large" };
4414 /* Skip whitespaces. */
4415 name = input_line_pointer;
4416 while (*input_line_pointer && !ISSPACE (*input_line_pointer))
4417 input_line_pointer++;
4418 saved_char = *input_line_pointer;
4419 *input_line_pointer = 0;
4421 for (i = 0; i < (int) ARRAY_SIZE (possible_flags); i++)
4423 if (strcmp (name, possible_flags[i]) == 0)
4428 /* flag: verbatim */
4429 ict_flag = ICT_SMALL;
4432 ict_flag = ICT_LARGE;
4437 /* Already found the flag, no need to continue next loop. */
4442 *input_line_pointer = saved_char;
4443 ignore_rest_of_line ();
4447 nds32_n12hc (int ignore ATTRIBUTE_UNUSED)
4449 /* N1213HC core is used. */
4453 /* The target specific pseudo-ops which we support. */
4454 const pseudo_typeS md_pseudo_table[] =
4456 /* Forced alignment if declared these ways. */
4457 {"ascii", stringer, 8 + 0},
4458 {"asciz", stringer, 8 + 1},
4459 {"double", nds32_aligned_float_cons, 'd'},
4460 {"dword", nds32_aligned_cons, 3},
4461 {"float", nds32_aligned_float_cons, 'f'},
4462 {"half", nds32_aligned_cons, 1},
4463 {"hword", nds32_aligned_cons, 1},
4464 {"int", nds32_aligned_cons, 2},
4465 {"long", nds32_aligned_cons, 2},
4466 {"octa", nds32_aligned_cons, 4},
4467 {"quad", nds32_aligned_cons, 3},
4468 {"qword", nds32_aligned_cons, 4},
4469 {"short", nds32_aligned_cons, 1},
4470 {"byte", nds32_aligned_cons, 0},
4471 {"single", nds32_aligned_float_cons, 'f'},
4472 {"string", stringer, 8 + 1},
4473 {"word", nds32_aligned_cons, 2},
4475 {"little", set_endian_little, 1},
4476 {"big", set_endian_little, 0},
4477 {"16bit_on", trigger_16bit, 1},
4478 {"16bit_off", trigger_16bit, 0},
4479 {"restore_16bit", restore_16bit, 0},
4480 {"off_16bit", off_16bit, 0},
4482 {"sdata_d", nds32_seg, SDATA_D_SECTION},
4483 {"sdata_w", nds32_seg, SDATA_W_SECTION},
4484 {"sdata_h", nds32_seg, SDATA_H_SECTION},
4485 {"sdata_b", nds32_seg, SDATA_B_SECTION},
4486 {"sdata_f", nds32_seg, SDATA_F_SECTION},
4488 {"sbss_d", nds32_seg, SBSS_D_SECTION},
4489 {"sbss_w", nds32_seg, SBSS_W_SECTION},
4490 {"sbss_h", nds32_seg, SBSS_H_SECTION},
4491 {"sbss_b", nds32_seg, SBSS_B_SECTION},
4492 {"sbss_f", nds32_seg, SBSS_F_SECTION},
4494 {"pic", nds32_enable_pic, 0},
4495 {"n12_hc", nds32_n12hc, 0},
4496 {"abi_1", nds32_set_abi, E_NDS_ABI_V1},
4497 {"abi_2", nds32_set_abi, E_NDS_ABI_AABI},
4499 {"abi_2fp", nds32_set_abi, E_NDS_ABI_V2FP},
4500 {"abi_2fp_plus", nds32_set_abi, E_NDS_ABI_V2FP_PLUS},
4501 {"relax", nds32_relax_relocs, 1},
4502 {"no_relax", nds32_relax_relocs, 0},
4503 {"hint_func_args", nds32_set_hint_func_args, 0}, /* Abandon?? */
4504 {"omit_fp_begin", nds32_omit_fp_begin, 1},
4505 {"omit_fp_end", nds32_omit_fp_begin, 0},
4506 {"vec_size", nds32_vec_size, 0},
4507 {"flag", nds32_flag, 0},
4508 {"innermost_loop_begin", nds32_loop_begin, 1},
4509 {"innermost_loop_end", nds32_loop_begin, 0},
4510 {"relax_hint", nds32_relax_hint, 0},
4511 {"ict_model", ict_model, 0},
4516 nds32_pre_do_align (int n, char *fill, int len, int max)
4518 /* Only make a frag if we HAVE to... */
4520 if (n != 0 && !need_pass_2)
4524 if (subseg_text_p (now_seg))
4526 dwarf2_emit_insn (0);
4528 add_mapping_symbol_for_align (n, frag_now_fix (), 0);
4529 frag_align_code (n, max);
4531 /* Tag this alignment when there is a label before it. */
4534 fragP->tc_frag_data.flag = NDS32_FRAG_LABEL;
4539 frag_align (n, 0, max);
4542 frag_align (n, *fill, max);
4544 frag_align_pattern (n, fill, len, max);
4549 nds32_do_align (int n)
4551 /* Optimize for space and label exists. */
4554 /* FIXME:I think this will break debug info sections and except_table. */
4555 if (!enable_relax_relocs || !subseg_text_p (now_seg))
4558 /* Create and attach a BFD_RELOC_NDS32_LABEL fixup
4559 the size of instruction may not be correct because
4560 it could be relaxable. */
4561 exp.X_op = O_symbol;
4562 exp.X_add_symbol = section_symbol (now_seg);
4563 exp.X_add_number = n;
4564 fix_new_exp (frag_now,
4565 frag_now_fix (), 0, &exp, 0, BFD_RELOC_NDS32_LABEL);
4568 /* Supported Andes machines. */
4571 enum bfd_architecture bfd_mach;
4575 /* This is the callback for nds32-asm.c to parse operands. */
4578 nds32_asm_parse_operand (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED,
4579 struct nds32_asm_insn *pinsn,
4580 char **pstr, int64_t *value)
4583 expressionS *pexp = pinsn->info;
4585 hold = input_line_pointer;
4586 input_line_pointer = *pstr;
4588 *pstr = input_line_pointer;
4589 input_line_pointer = hold;
4595 return NASM_R_SYMBOL;
4597 *value = pexp->X_add_number;
4598 return NASM_R_CONST;
4603 return NASM_R_ILLEGAL;
4607 /* GAS will call this function at the start of the assembly, after the command
4608 line arguments have been parsed and all the machine independent
4609 initializations have been completed. */
4614 struct nds32_keyword *k;
4615 relax_info_t *relax_info;
4618 bfd_set_arch_mach (stdoutput, TARGET_ARCH, nds32_baseline);
4620 nds32_init_nds32_pseudo_opcodes ();
4621 asm_desc.parse_operand = nds32_asm_parse_operand;
4623 flags |= NASM_OPEN_REDUCED_REG;
4624 nds32_asm_init (&asm_desc, flags);
4626 /* Initial general purpose registers hash table. */
4627 nds32_gprs_hash = hash_new ();
4628 for (k = keyword_gpr; k->name; k++)
4629 hash_insert (nds32_gprs_hash, k->name, k);
4631 /* Initial branch hash table. */
4632 nds32_relax_info_hash = hash_new ();
4633 for (relax_info = relax_table; relax_info->opcode; relax_info++)
4634 hash_insert (nds32_relax_info_hash, relax_info->opcode, relax_info);
4636 /* Initial relax hint hash table. */
4637 nds32_hint_hash = hash_new ();
4638 enable_16bit = nds32_16bit_ext;
4641 /* HANDLE_ALIGN in write.c. */
4644 nds32_handle_align (fragS *fragp)
4646 static const unsigned char nop16[] = { 0x92, 0x00 };
4647 static const unsigned char nop32[] = { 0x40, 0x00, 0x00, 0x09 };
4651 if (fragp->fr_type != rs_align_code)
4654 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
4655 p = fragp->fr_literal + fragp->fr_fix;
4666 exp_t.X_op = O_symbol;
4667 exp_t.X_add_symbol = abs_section_sym;
4668 exp_t.X_add_number = R_NDS32_INSN16_CONVERT_FLAG;
4669 fix_new_exp (fragp, fragp->fr_fix, 2, &exp_t, 0,
4670 BFD_RELOC_NDS32_INSN16);
4671 memcpy (p, nop16, 2);
4678 memcpy (p, nop32, 4);
4683 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
4684 fragp->fr_fix += bytes;
4687 /* md_flush_pending_output */
4690 nds32_flush_pending_output (void)
4692 nds32_last_label = NULL;
4696 nds32_frob_label (symbolS *label)
4698 dwarf2_emit_label (label);
4701 /* TC_START_LABEL */
4704 nds32_start_label (int asmdone ATTRIBUTE_UNUSED, int secdone ATTRIBUTE_UNUSED)
4706 if (optimize && subseg_text_p (now_seg))
4714 nds32_target_format (void)
4717 if (target_big_endian)
4718 return "elf32-nds32be-linux";
4720 return "elf32-nds32le-linux";
4722 if (target_big_endian)
4723 return "elf32-nds32be";
4725 return "elf32-nds32le";
4729 static enum nds32_br_range
4730 get_range_type (const struct nds32_field *field)
4732 gas_assert (field != NULL);
4734 if (field->bitpos != 0)
4735 return BR_RANGE_U4G;
4737 if (field->bitsize == 24 && field->shift == 1)
4738 return BR_RANGE_S16M;
4739 else if (field->bitsize == 16 && field->shift == 1)
4740 return BR_RANGE_S64K;
4741 else if (field->bitsize == 14 && field->shift == 1)
4742 return BR_RANGE_S16K;
4743 else if (field->bitsize == 8 && field->shift == 1)
4744 return BR_RANGE_S256;
4746 return BR_RANGE_U4G;
4749 /* Save pseudo instruction relocation list. */
4751 static struct nds32_relocs_pattern*
4752 nds32_elf_save_pseudo_pattern (fixS* fixP, struct nds32_asm_insn *insn,
4753 char *out, symbolS *sym,
4754 struct nds32_relocs_pattern *reloc_ptr,
4757 struct nds32_opcode *opcode = insn->opcode;
4759 reloc_ptr = XNEW (struct nds32_relocs_pattern);
4760 reloc_ptr->seg = now_seg;
4761 reloc_ptr->sym = sym;
4762 reloc_ptr->frag = fragP;
4763 reloc_ptr->frchain = frchain_now;
4764 reloc_ptr->fixP = fixP;
4765 reloc_ptr->opcode = opcode;
4766 reloc_ptr->where = out;
4767 reloc_ptr->insn = insn->insn;
4768 reloc_ptr->next = NULL;
4772 /* Check X_md to transform relocation. */
4775 nds32_elf_record_fixup_exp (fragS *fragP, const char *str,
4776 const struct nds32_field *fld,
4777 expressionS *pexp, char* out,
4778 struct nds32_asm_insn *insn)
4784 /* Handle instruction relocation. */
4785 if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_HI20))
4787 /* Relocation for hi20 modifier. */
4790 case BFD_RELOC_NDS32_GOTOFF: /* @GOTOFF */
4791 reloc = BFD_RELOC_NDS32_GOTOFF_HI20;
4793 case BFD_RELOC_NDS32_GOT20: /* @GOT */
4794 reloc = BFD_RELOC_NDS32_GOT_HI20;
4796 case BFD_RELOC_NDS32_25_PLTREL: /* @PLT */
4798 as_bad (_("Invalid PIC expression."));
4800 reloc = BFD_RELOC_NDS32_PLT_GOTREL_HI20;
4802 case BFD_RELOC_NDS32_GOTPC20: /* _GLOBAL_OFFSET_TABLE_ */
4803 reloc = BFD_RELOC_NDS32_GOTPC_HI20;
4805 case BFD_RELOC_NDS32_TPOFF: /* @TPOFF */
4806 reloc = BFD_RELOC_NDS32_TLS_LE_HI20;
4808 case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */
4809 reloc = nds32_pic ? BFD_RELOC_NDS32_TLS_IEGP_HI20 : BFD_RELOC_NDS32_TLS_IE_HI20;
4811 case BFD_RELOC_NDS32_TLS_DESC: /* @TLSDESC */
4812 reloc = BFD_RELOC_NDS32_TLS_DESC_HI20;
4814 default: /* No suffix */
4816 /* When the file is pic, the address must be offset to gp.
4817 It may define another relocation or use GOTOFF. */
4818 reloc = BFD_RELOC_NDS32_PLT_GOTREL_HI20;
4820 reloc = BFD_RELOC_NDS32_HI20;
4823 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4824 insn->info, 0 /* pcrel */, reloc);
4826 else if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_LO12))
4828 /* Relocation for lo12 modifier. */
4829 if (fld->bitsize == 15 && fld->shift == 0)
4834 case BFD_RELOC_NDS32_GOTOFF: /* @GOTOFF */
4835 reloc = BFD_RELOC_NDS32_GOTOFF_LO12;
4837 case BFD_RELOC_NDS32_GOT20: /* @GOT */
4838 reloc = BFD_RELOC_NDS32_GOT_LO12;
4840 case BFD_RELOC_NDS32_25_PLTREL: /* @PLT */
4842 as_bad (_("Invalid PIC expression."));
4844 reloc = BFD_RELOC_NDS32_PLT_GOTREL_LO12;
4846 case BFD_RELOC_NDS32_GOTPC20: /* _GLOBAL_OFFSET_TABLE_ */
4847 reloc = BFD_RELOC_NDS32_GOTPC_LO12;
4849 case BFD_RELOC_NDS32_TPOFF: /* @TPOFF */
4850 reloc = BFD_RELOC_NDS32_TLS_LE_LO12;
4852 case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */
4853 reloc = nds32_pic ? BFD_RELOC_NDS32_TLS_IEGP_LO12 : BFD_RELOC_NDS32_TLS_IE_LO12;
4855 case BFD_RELOC_NDS32_TLS_DESC: /* @TLSDESC */
4856 reloc = BFD_RELOC_NDS32_TLS_DESC_LO12;
4858 default: /* No suffix */
4860 /* When the file is pic, the address must be offset to gp.
4861 It may define another relocation or use GOTOFF. */
4862 reloc = BFD_RELOC_NDS32_PLT_GOTREL_LO12;
4864 reloc = BFD_RELOC_NDS32_LO12S0;
4868 else if (fld->bitsize == 15 && fld->shift == 1)
4869 reloc = BFD_RELOC_NDS32_LO12S1; /* [ls]hi */
4870 else if (fld->bitsize == 15 && fld->shift == 2)
4875 case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */
4876 reloc = nds32_pic ? BFD_RELOC_NDS32_TLS_IEGP_LO12S2 : BFD_RELOC_NDS32_TLS_IE_LO12S2;
4878 default: /* No suffix */
4879 reloc = BFD_RELOC_NDS32_LO12S2;
4883 else if (fld->bitsize == 15 && fld->shift == 3)
4884 reloc = BFD_RELOC_NDS32_LO12S3; /* [ls]di */
4885 else if (fld->bitsize == 12 && fld->shift == 2)
4886 reloc = BFD_RELOC_NDS32_LO12S2_SP; /* f[ls][sd]i */
4888 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4889 insn->info, 0 /* pcrel */, reloc);
4891 else if (fld && fld->bitpos == 0 && insn->opcode->isize == 4
4892 && (insn->attr & NASM_ATTR_PCREL))
4894 /* Relocation for 32-bit branch instructions. */
4895 if (fld->bitsize == 24 && fld->shift == 1)
4896 reloc = BFD_RELOC_NDS32_25_PCREL;
4897 else if (fld->bitsize == 16 && fld->shift == 1)
4898 reloc = BFD_RELOC_NDS32_17_PCREL;
4899 else if (fld->bitsize == 14 && fld->shift == 1)
4900 reloc = BFD_RELOC_NDS32_15_PCREL;
4901 else if (fld->bitsize == 8 && fld->shift == 1)
4902 reloc = BFD_RELOC_NDS32_WORD_9_PCREL;
4906 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4907 insn->info, 1 /* pcrel */, reloc);
4909 else if (fld && fld->bitpos == 0 && insn->opcode->isize == 4
4910 && (insn->attr & NASM_ATTR_GPREL))
4912 /* Relocation for 32-bit gp-relative instructions. */
4913 if (fld->bitsize == 19 && fld->shift == 0)
4914 reloc = BFD_RELOC_NDS32_SDA19S0;
4915 else if (fld->bitsize == 18 && fld->shift == 1)
4916 reloc = BFD_RELOC_NDS32_SDA18S1;
4917 else if (fld->bitsize == 17 && fld->shift == 2)
4918 reloc = BFD_RELOC_NDS32_SDA17S2;
4922 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4923 insn->info, 0 /* pcrel */, reloc);
4924 /* Insert INSN16 for converting fp_as_gp. */
4925 exp.X_op = O_symbol;
4926 exp.X_add_symbol = abs_section_sym;
4927 exp.X_add_number = 0;
4928 if (in_omit_fp && reloc == BFD_RELOC_NDS32_SDA17S2)
4929 fix_new_exp (fragP, out - fragP->fr_literal,
4930 insn->opcode->isize, &exp, 0 /* pcrel */,
4931 BFD_RELOC_NDS32_INSN16);
4933 else if (fld && fld->bitpos == 0 && insn->opcode->isize == 2
4934 && (insn->attr & NASM_ATTR_PCREL))
4936 /* Relocation for 16-bit branch instructions. */
4937 if (fld->bitsize == 8 && fld->shift == 1)
4938 reloc = BFD_RELOC_NDS32_9_PCREL;
4942 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4943 insn->info, 1 /* pcrel */, reloc);
4946 as_bad (_("Don't know how to handle this field. %s"), str);
4951 /* Build instruction pattern to relax. There are two type group pattern
4952 including pseudo instruction and relax hint. */
4955 nds32_elf_build_relax_relation (fixS *fixP, expressionS *pexp, char* out,
4956 struct nds32_asm_insn *insn, fragS *fragP,
4957 const struct nds32_field *fld,
4958 bfd_boolean pseudo_hint)
4960 struct nds32_relocs_pattern *reloc_ptr;
4961 struct nds32_relocs_group *group;
4962 symbolS *sym = NULL;
4964 /* The expression may be used uninitialized. */
4966 sym = pexp->X_add_symbol;
4970 /* We cannot know how many instructions will be expanded for
4971 the pseudo instruction here. The first expanded instruction fills
4972 the memory created by relax_hint. The follower will created and link
4974 group = nds32_relax_hint_current;
4977 if (group->pattern->opcode == NULL)
4978 nds32_elf_save_pseudo_pattern (fixP, insn, out, sym,
4979 group->pattern, fragP);
4982 group->pattern->next =
4983 nds32_elf_save_pseudo_pattern (fixP, insn, out, sym,
4985 group->pattern = group->pattern->next;
4987 group = group->next;
4990 else if (pseudo_opcode)
4992 /* Save instruction relation for pseudo instruction expanding pattern. */
4993 reloc_ptr = nds32_elf_save_pseudo_pattern (fixP, insn, out, sym,
4996 relocs_list = reloc_ptr;
4999 struct nds32_relocs_pattern *temp = relocs_list;
5002 temp->next = reloc_ptr;
5005 else if (nds32_relax_hint_current)
5007 /* Save instruction relation by relax hint. */
5008 group = nds32_relax_hint_current;
5011 nds32_elf_save_pseudo_pattern (fixP, insn, out, sym,
5012 group->pattern, fragP);
5013 group = group->next;
5014 free (nds32_relax_hint_current);
5015 nds32_relax_hint_current = group;
5019 /* Set relaxing false only for relax_hint trigger it. */
5024 #define N32_MEM_EXT(insn) ((N32_OP6_MEM << 25) | insn)
5026 /* Relax pattern for link time relaxation. */
5027 /* Relaxation types only! relocation types are not necessary. */
5028 /* Refer to nds32_elf_record_fixup_exp (). */
5030 static struct nds32_relax_hint_table relax_ls_table[] =
5033 /* LA and Floating LSI. */
5034 .main_type = NDS32_RELAX_HINT_LA_FLSI,
5035 .relax_code_size = 12,
5044 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5045 {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
5046 {4, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5047 {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_LSI},
5048 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5049 {8, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5054 /* Load Address / Load-Store (LALS). */
5055 .main_type = NDS32_RELAX_HINT_LALS,
5056 .relax_code_size = 12,
5065 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5066 {4, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5067 {8, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5072 /* B(AL) symbol@PLT */
5073 .main_type = NDS32_RELAX_HINT_LA_PLT,
5074 .relax_code_size = 16,
5084 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5085 {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
5086 {8, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
5087 {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PLT_GOT_SUFF},
5088 {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5089 {12, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5095 .main_type = NDS32_RELAX_HINT_LA_GOT,
5096 .relax_code_size = 12,
5105 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5106 {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
5107 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5108 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_GOT_SUFF},
5114 .main_type = NDS32_RELAX_HINT_LA_GOTOFF,
5115 .relax_code_size = 16,
5125 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5126 {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
5127 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5128 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_GOTOFF_SUFF},
5129 {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5130 {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_GOTOFF_SUFF},
5136 .main_type = NDS32_RELAX_HINT_TLS_LE_LS,
5137 .relax_code_size = 16,
5147 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5148 {4, 4, NDS32_HINT | NDS32_PTR_MULTIPLE, BFD_RELOC_NDS32_PTR},
5149 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5150 {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_LE_LS},
5151 {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5152 {12, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_LE_ADD},
5158 .main_type = NDS32_RELAX_HINT_TLS_IE_LA,
5159 .relax_code_size = 8,
5167 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5168 {4, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5174 .main_type = NDS32_RELAX_HINT_TLS_IEGP_LA,
5175 .relax_code_size = 12,
5184 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5185 {4, 4, NDS32_HINT | NDS32_PTR_PATTERN, BFD_RELOC_NDS32_PTR},
5186 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5187 {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_IEGP_LW},
5193 .main_type = NDS32_RELAX_HINT_TLS_DESC_LS,
5194 .relax_code_size = 24,
5200 OP6 (LBI), /* load argument */
5202 OP6 (MEM), /* load/store variable or load argument */
5206 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5207 {4, 4, NDS32_HINT | NDS32_PTR_PATTERN, BFD_RELOC_NDS32_PTR},
5208 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5209 {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_DESC_ADD},
5210 {12, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_DESC_FUNC},
5211 {16, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_DESC_CALL},
5212 {20, 4, NDS32_HINT | NDS32_SYM_DESC_MEM, BFD_RELOC_NDS32_TLS_DESC_MEM},
5218 .relax_code_seq = {0},
5219 .relax_fixup = {{0, 0 , 0, 0}}
5223 /* Since sethi loadstore relocation has to using next instruction to determine
5224 elimination itself or not, we have to return the next instruction range. */
5227 nds32_elf_sethi_range (struct nds32_relocs_pattern *pattern)
5232 switch (pattern->opcode->value)
5237 case N32_MEM_EXT (N32_MEM_LB):
5238 case N32_MEM_EXT (N32_MEM_LBS):
5239 case N32_MEM_EXT (N32_MEM_SB):
5240 range = NDS32_LOADSTORE_BYTE;
5245 case N32_MEM_EXT (N32_MEM_LH):
5246 case N32_MEM_EXT (N32_MEM_LHS):
5247 case N32_MEM_EXT (N32_MEM_SH):
5248 range = NDS32_LOADSTORE_HALF;
5252 case N32_MEM_EXT (N32_MEM_LW):
5253 case N32_MEM_EXT (N32_MEM_SW):
5254 range = NDS32_LOADSTORE_WORD;
5258 range = NDS32_LOADSTORE_FLOAT_S;
5262 range = NDS32_LOADSTORE_FLOAT_D;
5265 range = NDS32_LOADSTORE_IMM;
5268 range = NDS32_LOADSTORE_NONE;
5271 if (range != NDS32_LOADSTORE_NONE)
5273 pattern = pattern->next;
5278 /* The args means: instruction size, the 1st instruction is converted to 16 or
5279 not, optimize option, 16 bit instruction is enable. */
5281 #define SET_ADDEND(size, convertible, optimize, insn16_on) \
5282 (((size) & 0xff) | ((convertible) ? 1 << 31 : 0) \
5283 | ((optimize) ? 1<< 30 : 0) | (insn16_on ? 1 << 29 : 0))
5284 #define MAC_COMBO (E_NDS32_HAS_FPU_MAC_INST|E_NDS32_HAS_MAC_DX_INST)
5287 nds32_set_elf_flags_by_insn (struct nds32_asm_insn * insn)
5289 static int skip_flags = NASM_ATTR_FPU_FMA
5290 | NASM_ATTR_BRANCH | NASM_ATTR_SATURATION_EXT
5291 | NASM_ATTR_GPREL | NASM_ATTR_DXREG
5292 | NASM_ATTR_ISA_V1 | NASM_ATTR_ISA_V2
5293 | NASM_ATTR_ISA_V3 | NASM_ATTR_ISA_V3M
5296 int new_flags = insn->opcode->attr & ~skip_flags;
5299 int next = 1 << (ffs (new_flags) - 1);
5303 case NASM_ATTR_PERF_EXT:
5307 nds32_elf_flags |= E_NDS32_HAS_EXT_INST;
5308 skip_flags |= NASM_ATTR_PERF_EXT;
5311 as_bad (_("instruction %s requires enabling performance "
5312 "extension"), insn->opcode->opcode);
5315 case NASM_ATTR_PERF2_EXT:
5317 if (nds32_perf_ext2)
5319 nds32_elf_flags |= E_NDS32_HAS_EXT2_INST;
5320 skip_flags |= NASM_ATTR_PERF2_EXT;
5323 as_bad (_("instruction %s requires enabling performance "
5324 "extension II"), insn->opcode->opcode);
5327 case NASM_ATTR_AUDIO_ISAEXT:
5329 if (nds32_audio_ext)
5331 nds32_elf_flags |= E_NDS32_HAS_AUDIO_INST;
5332 skip_flags |= NASM_ATTR_AUDIO_ISAEXT;
5335 as_bad (_("instruction %s requires enabling AUDIO extension"),
5336 insn->opcode->opcode);
5339 case NASM_ATTR_STR_EXT:
5341 if (nds32_string_ext)
5343 nds32_elf_flags |= E_NDS32_HAS_STRING_INST;
5344 skip_flags |= NASM_ATTR_STR_EXT;
5347 as_bad (_("instruction %s requires enabling STRING extension"),
5348 insn->opcode->opcode);
5353 if (insn->opcode->attr & NASM_ATTR_DXREG)
5355 if (nds32_div && nds32_dx_regs)
5357 nds32_elf_flags |= E_NDS32_HAS_DIV_DX_INST;
5358 skip_flags |= NASM_ATTR_DIV;
5361 as_bad (_("instruction %s requires enabling DIV & DX_REGS "
5362 "extension"), insn->opcode->opcode);
5368 if (nds32_fpu_sp_ext || nds32_fpu_dp_ext)
5370 if (!(nds32_elf_flags
5371 & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST)))
5373 skip_flags |= NASM_ATTR_FPU;
5376 as_bad (_("instruction %s requires enabling FPU extension"),
5377 insn->opcode->opcode);
5380 case NASM_ATTR_FPU_SP_EXT:
5382 if (nds32_fpu_sp_ext)
5384 nds32_elf_flags |= E_NDS32_HAS_FPU_INST;
5385 skip_flags |= NASM_ATTR_FPU_SP_EXT;
5388 as_bad (_("instruction %s requires enabling FPU_SP extension"),
5389 insn->opcode->opcode);
5392 case NASM_ATTR_FPU_DP_EXT:
5394 if (nds32_fpu_dp_ext)
5396 nds32_elf_flags |= E_NDS32_HAS_FPU_DP_INST;
5397 skip_flags |= NASM_ATTR_FPU_DP_EXT;
5400 as_bad (_("instruction %s requires enabling FPU_DP extension"),
5401 insn->opcode->opcode);
5406 if (insn->opcode->attr & NASM_ATTR_FPU_SP_EXT)
5408 if (nds32_fpu_sp_ext && nds32_mac)
5409 nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST;
5411 as_bad (_("instruction %s requires enabling FPU_MAC "
5412 "extension"), insn->opcode->opcode);
5414 else if (insn->opcode->attr & NASM_ATTR_FPU_DP_EXT)
5416 if (nds32_fpu_dp_ext && nds32_mac)
5417 nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST;
5419 as_bad (_("instruction %s requires enabling FPU_MAC "
5420 "extension"), insn->opcode->opcode);
5422 else if (insn->opcode->attr & NASM_ATTR_DXREG)
5424 if (nds32_dx_regs && nds32_mac)
5425 nds32_elf_flags |= E_NDS32_HAS_MAC_DX_INST;
5427 as_bad (_("instruction %s requires enabling DX_REGS "
5428 "extension"), insn->opcode->opcode);
5431 if (MAC_COMBO == (MAC_COMBO & nds32_elf_flags))
5432 skip_flags |= NASM_ATTR_MAC;
5435 case NASM_ATTR_DSP_ISAEXT:
5439 nds32_elf_flags |= E_NDS32_HAS_DSP_INST;
5440 skip_flags |= NASM_ATTR_DSP_ISAEXT;
5443 as_bad (_("instruction %s requires enabling dsp extension"),
5444 insn->opcode->opcode);
5451 nds32_elf_flags |= E_NDS32_HAS_ZOL;
5452 skip_flags |= NASM_ATTR_ZOL;
5455 as_bad (_("instruction %s requires enabling zol extension"),
5456 insn->opcode->opcode);
5460 as_bad (_("internal error: unknown instruction attribute: 0x%08x"),
5466 /* Flag for analysis relaxation type. */
5468 enum nds32_insn_type
5470 N32_RELAX_SETHI = 1,
5471 N32_RELAX_BR = (1 << 1),
5472 N32_RELAX_LSI = (1 << 2),
5473 N32_RELAX_JUMP = (1 << 3),
5474 N32_RELAX_CALL = (1 << 4),
5475 N32_RELAX_ORI = (1 << 5),
5476 N32_RELAX_MEM = (1 << 6),
5477 N32_RELAX_MOVI = (1 << 7),
5478 N32_RELAX_ALU1 = (1 << 8),
5479 N32_RELAX_16BIT = (1 << 9),
5482 struct nds32_hint_map
5484 /* the preamble relocation */
5485 bfd_reloc_code_real_type hi_type;
5488 /* relax pattern ID */
5489 enum nds32_relax_hint_type hint_type;
5491 enum nds32_br_range range;
5492 /* pattern character flags */
5493 enum nds32_insn_type insn_list;
5494 /* optional pattern character flags */
5495 enum nds32_insn_type option_list;
5498 /* Table to match instructions with hint and relax pattern. */
5500 static struct nds32_hint_map hint_map [] =
5504 BFD_RELOC_NDS32_HI20,
5506 NDS32_RELAX_HINT_NONE,
5508 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL,
5513 _dummy_first_bfd_reloc_code_real,
5515 NDS32_RELAX_HINT_NONE,
5517 N32_RELAX_BR | N32_RELAX_CALL,
5522 BFD_RELOC_NDS32_HI20,
5524 NDS32_RELAX_HINT_NONE,
5526 N32_RELAX_BR | N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL,
5531 BFD_RELOC_NDS32_HI20,
5533 NDS32_RELAX_HINT_NONE,
5535 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_JUMP,
5540 /* There is two kinds of variation of LONGJUMP5. One of them
5541 generate EMPTY relocation for converted INSN16 if needed.
5542 But we don't distinguish them here. */
5543 _dummy_first_bfd_reloc_code_real,
5545 NDS32_RELAX_HINT_NONE,
5547 N32_RELAX_BR | N32_RELAX_JUMP,
5552 BFD_RELOC_NDS32_HI20,
5554 NDS32_RELAX_HINT_NONE,
5556 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_BR | N32_RELAX_JUMP,
5561 _dummy_first_bfd_reloc_code_real,
5563 NDS32_RELAX_HINT_NONE,
5565 N32_RELAX_MOVI | N32_RELAX_BR,
5569 /* LONGCALL (BAL|JR|LA symbol@PLT). */
5570 BFD_RELOC_NDS32_PLT_GOTREL_HI20,
5572 NDS32_RELAX_HINT_LA_PLT,
5574 N32_RELAX_SETHI | N32_RELAX_ORI,
5575 N32_RELAX_ALU1 | N32_RELAX_CALL | N32_RELAX_JUMP,
5577 /* relative issue: #12566 */
5579 /* LA and Floating LSI. */
5580 BFD_RELOC_NDS32_HI20,
5582 NDS32_RELAX_HINT_LA_FLSI,
5584 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_LSI,
5587 /* relative issue: #11685 #11602 */
5589 /* load address / load-store (LALS). */
5590 BFD_RELOC_NDS32_HI20,
5592 NDS32_RELAX_HINT_LALS,
5595 N32_RELAX_ORI | N32_RELAX_LSI,
5598 /* setup $GP (_GLOBAL_OFFSET_TABLE_) */
5599 BFD_RELOC_NDS32_GOTPC_HI20,
5601 NDS32_RELAX_HINT_LALS,
5603 N32_RELAX_SETHI | N32_RELAX_ORI,
5607 /* GOT LA/LS (symbol@GOT) */
5608 BFD_RELOC_NDS32_GOT_HI20,
5610 NDS32_RELAX_HINT_LA_GOT,
5612 N32_RELAX_SETHI | N32_RELAX_ORI,
5616 /* GOTOFF LA/LS (symbol@GOTOFF) */
5617 BFD_RELOC_NDS32_GOTOFF_HI20,
5619 NDS32_RELAX_HINT_LA_GOTOFF,
5621 N32_RELAX_SETHI | N32_RELAX_ORI,
5622 N32_RELAX_ALU1 | N32_RELAX_MEM, /* | N32_RELAX_LSI, */
5625 /* TLS LE LA|LS (@TPOFF) */
5626 BFD_RELOC_NDS32_TLS_LE_HI20,
5628 NDS32_RELAX_HINT_TLS_LE_LS,
5630 N32_RELAX_SETHI | N32_RELAX_ORI,
5631 N32_RELAX_ALU1 | N32_RELAX_MEM,
5635 BFD_RELOC_NDS32_TLS_IE_HI20,
5637 NDS32_RELAX_HINT_TLS_IE_LA,
5639 N32_RELAX_SETHI | N32_RELAX_LSI,
5644 BFD_RELOC_NDS32_TLS_IE_HI20,
5646 NDS32_RELAX_HINT_TLS_IE_LS,
5648 N32_RELAX_SETHI | N32_RELAX_LSI | N32_RELAX_MEM,
5653 BFD_RELOC_NDS32_TLS_IEGP_HI20,
5655 NDS32_RELAX_HINT_TLS_IEGP_LA,
5657 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_MEM,
5662 BFD_RELOC_NDS32_TLS_DESC_HI20,
5664 NDS32_RELAX_HINT_TLS_DESC_LS,
5666 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_ALU1 | N32_RELAX_CALL,
5667 N32_RELAX_LSI | N32_RELAX_MEM,
5670 {0, NULL, 0, 0 ,0, 0}
5673 /* Find the relaxation pattern according to instructions. */
5676 nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern,
5677 struct nds32_relax_hint_table *hint_info)
5679 unsigned int opcode, seq_size;
5680 enum nds32_br_range range;
5681 struct nds32_relocs_pattern *pattern, *hi_pattern = NULL;
5682 const char *opc = NULL;
5683 relax_info_t *relax_info = NULL;
5684 nds32_relax_fixup_info_t *fixup_info, *hint_fixup;
5685 enum nds32_relax_hint_type hint_type = NDS32_RELAX_HINT_NONE;
5686 struct nds32_relax_hint_table *table_ptr;
5687 uint32_t *code_seq, *hint_code;
5688 enum nds32_insn_type relax_type = 0;
5689 struct nds32_hint_map *map_ptr = hint_map;
5691 const char *check_insn[] =
5692 { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8" };
5694 /* TODO: PLT GOT. */
5695 /* Traverse all pattern instruction and set flag. */
5696 pattern = relocs_pattern;
5699 if (pattern->opcode->isize == 4)
5701 /* 4 byte instruction. */
5702 opcode = N32_OP6 (pattern->opcode->value);
5706 hi_pattern = pattern;
5707 relax_type |= N32_RELAX_SETHI;
5710 relax_type |= N32_RELAX_MEM;
5713 relax_type |= N32_RELAX_ALU1;
5716 relax_type |= N32_RELAX_ORI;
5721 relax_type |= N32_RELAX_BR;
5724 relax_type |= N32_RELAX_MOVI;
5738 relax_type |= N32_RELAX_LSI;
5741 if (__GF (pattern->opcode->value, 0, 1) == 1)
5742 relax_type |= N32_RELAX_CALL;
5744 relax_type |= N32_RELAX_JUMP;
5747 if (__GF (pattern->opcode->value, 24, 1) == 1)
5748 relax_type |= N32_RELAX_CALL;
5750 relax_type |= N32_RELAX_JUMP;
5753 as_warn (_("relax hint unrecognized instruction: line %d."),
5754 pattern->frag->fr_line);
5760 /* 2 byte instruction. Compare by opcode name because
5761 the opcode of 2byte instruction is not regular. */
5763 for (i = 0; i < ARRAY_SIZE (check_insn); i++)
5765 if (strcmp (pattern->opcode->opcode, check_insn[i]) == 0)
5767 relax_type |= N32_RELAX_BR;
5773 relax_type |= N32_RELAX_16BIT;
5775 pattern = pattern->next;
5778 /* Analysis instruction flag to choose relaxation table. */
5779 while (map_ptr->insn_list != 0)
5781 struct nds32_hint_map *hint = map_ptr++;
5782 enum nds32_insn_type must = hint->insn_list;
5783 enum nds32_insn_type optional = hint->option_list;
5784 enum nds32_insn_type extra;
5786 if (must != (must & relax_type))
5789 extra = relax_type ^ must;
5790 if (extra != (extra & optional))
5794 || (hi_pattern->fixP
5795 && hi_pattern->fixP->fx_r_type == hint->hi_type))
5798 hint_type = hint->hint_type;
5799 range = hint->range;
5805 if (map_ptr->insn_list == 0)
5808 as_warn (_("Can not find match relax hint. Line: %d"),
5809 relocs_pattern->frag->fr_line);
5813 /* Get the match table. */
5816 /* Branch relax pattern. */
5817 relax_info = hash_find (nds32_relax_info_hash, opc);
5820 fixup_info = relax_info->relax_fixup[range];
5821 code_seq = relax_info->relax_code_seq[range];
5822 seq_size = relax_info->relax_code_size[range];
5826 /* Load-store relax pattern. */
5827 table_ptr = relax_ls_table;
5828 while (table_ptr->main_type != 0)
5830 if (table_ptr->main_type == hint_type)
5832 fixup_info = table_ptr->relax_fixup;
5833 code_seq = table_ptr->relax_code_seq;
5834 seq_size = table_ptr->relax_code_size;
5839 if (table_ptr->main_type == 0)
5845 hint_fixup = hint_info->relax_fixup;
5846 hint_code = hint_info->relax_code_seq;
5847 hint_info->relax_code_size = seq_size;
5849 while (fixup_info->size != 0)
5851 if (fixup_info->ramp & NDS32_HINT)
5853 memcpy (hint_fixup, fixup_info, sizeof (nds32_relax_fixup_info_t));
5858 /* Clear final relocation. */
5859 memset (hint_fixup, 0, sizeof (nds32_relax_fixup_info_t));
5860 /* Copy code sequence. */
5861 memcpy (hint_code, code_seq, seq_size);
5865 /* Because there are a lot of variant of load-store, check
5866 all these type here. */
5868 #define CLEAN_REG(insn) ((insn) & 0xfe0003ff)
5869 #define GET_OPCODE(insn) ((insn) & 0xfe000000)
5872 nds32_match_hint_insn (struct nds32_opcode *opcode, uint32_t seq)
5874 const char *check_insn[] =
5875 { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8", "jral5" };
5876 uint32_t insn = opcode->value;
5879 insn = CLEAN_REG (opcode->value);
5886 /* In relocation_table, it regards instruction LBI as representation
5887 of all the NDS32_RELAX_HINT_LS pattern. */
5888 if (insn == OP6 (LBI) || insn == OP6 (SBI) || insn == OP6 (LBSI)
5889 || insn == OP6 (LHI) || insn == OP6 (SHI) || insn == OP6 (LHSI)
5890 || insn == OP6 (LWI) || insn == OP6 (SWI)
5891 || insn == OP6 (LWC) || insn == OP6 (SWC)
5892 || insn == OP6 (LDC) || insn == OP6 (SDC))
5896 /* This is for LONGCALL5 and LONGCALL6. */
5897 if (insn == OP6 (BR2))
5901 /* This is for LONGJUMP5 and LONGJUMP6. */
5902 if (opcode->isize == 4
5903 && (insn == OP6 (BR1) || insn == OP6 (BR2) || insn == OP6 (BR3)))
5905 else if (opcode->isize == 2)
5907 for (i = 0; i < ARRAY_SIZE (check_insn); i++)
5908 if (strcmp (opcode->opcode, check_insn[i]) == 0)
5913 /* This is for LONGJUMP7. */
5914 if (opcode->isize == 2 && strcmp (opcode->opcode, "movi55") == 0)
5918 if (OP6 (MEM) == GET_OPCODE (insn))
5922 /* bit 24: N32_JI_JAL */ /* feed me! */
5923 if ((insn & ~(N32_BIT (24))) == JREG (JRAL))
5927 if (opcode->isize == 2)
5929 for (i = 0; i < ARRAY_SIZE (check_insn); i++)
5930 if (strcmp (opcode->opcode, check_insn[i]) == 0)
5933 if ((strcmp (opcode->opcode, "add5.pc") == 0) ||
5934 (strcmp (opcode->opcode, "add45") == 0))
5941 /* Append relax relocation for link time relaxing. */
5944 nds32_elf_append_relax_relocs (const char *key, void *value)
5946 struct nds32_relocs_pattern *relocs_pattern =
5947 (struct nds32_relocs_pattern *) value;
5948 struct nds32_relocs_pattern *pattern_temp, *pattern_now;
5949 symbolS *sym, *hi_sym = NULL;
5952 segT seg_bak = now_seg;
5953 frchainS *frchain_bak = frchain_now;
5954 struct nds32_relax_hint_table hint_info;
5955 nds32_relax_fixup_info_t *hint_fixup, *fixup_now;
5957 offsetT branch_offset, hi_branch_offset = 0;
5960 unsigned int ptr_offset, hint_count, relax_code_size, count = 0;
5961 uint32_t *code_seq, code_insn;
5965 if (!relocs_pattern)
5968 if (!nds32_find_reloc_table (relocs_pattern, &hint_info))
5971 /* Save symbol for some EMPTY relocation using. */
5972 pattern_now = relocs_pattern;
5975 if (pattern_now->opcode->value == OP6 (SETHI))
5977 hi_sym = pattern_now->sym;
5978 hi_branch_offset = pattern_now->fixP->fx_offset;
5981 pattern_now = pattern_now->next;
5984 /* Inserting fix up must specify now_seg or frchain_now. */
5985 now_seg = relocs_pattern->seg;
5986 frchain_now = relocs_pattern->frchain;
5987 fragP = relocs_pattern->frag;
5988 branch_offset = fragP->fr_offset;
5990 hint_fixup = hint_info.relax_fixup;
5991 code_seq = hint_info.relax_code_seq;
5992 relax_code_size = hint_info.relax_code_size;
5993 pattern_now = relocs_pattern;
5995 #ifdef NDS32_LINUX_TOOLCHAIN
5996 /* prepare group relocation ID (number). */
6000 /* convert .relax_hint key to number */
6002 group_id = strtol (key, NULL, 10);
6003 if ((errno == ERANGE && (group_id == LONG_MAX || group_id == LONG_MIN))
6004 || (errno != 0 && group_id == 0))
6006 as_bad (_("Internal error: .relax_hint KEY is not a number!"));
6012 /* Insert relaxation. */
6013 exp.X_op = O_symbol;
6015 /* For each instruction in the hint group. */
6018 if (count >= relax_code_size / 4)
6021 /* Choose the match fixup by instruction. */
6022 code_insn = CLEAN_REG (*(code_seq + count));
6023 if (!nds32_match_hint_insn (pattern_now->opcode, code_insn))
6025 /* Try search from head again */
6027 code_insn = CLEAN_REG (*(code_seq + count));
6029 while (!nds32_match_hint_insn (pattern_now->opcode, code_insn))
6032 if (count >= relax_code_size / 4)
6034 as_bad (_("Internal error: Relax hint (%s) error. %s: %s (%x)"),
6037 pattern_now->opcode->opcode,
6038 pattern_now->opcode->value);
6041 code_insn = CLEAN_REG (*(code_seq + count));
6044 fragP = pattern_now->frag;
6045 sym = pattern_now->sym;
6046 branch_offset = fragP->fr_offset;
6048 where = pattern_now->where;
6049 /* Find the instruction map fix. */
6050 fixup_now = hint_fixup;
6051 while (fixup_now->offset != offset)
6054 if (fixup_now->size == 0)
6057 /* This element is without relaxation relocation. */
6058 if (fixup_now->size == 0)
6060 pattern_now = pattern_now->next;
6063 fixup_size = fixup_now->size;
6065 /* Insert all fixup. */
6066 while (fixup_size != 0 && fixup_now->offset == offset)
6068 /* Set the real instruction size in element. */
6069 fixup_size = pattern_now->opcode->isize;
6070 pcrel = ((fixup_now->ramp & NDS32_PCREL) != 0) ? 1 : 0;
6071 if (fixup_now->ramp & NDS32_FIX)
6073 /* Convert original relocation. */
6074 pattern_now->fixP->fx_r_type = fixup_now->r_type ;
6077 else if ((fixup_now->ramp & NDS32_PTR) != 0)
6079 /* This relocation has to point to another instruction. Make
6080 sure each resolved relocation has to be pointed. */
6081 pattern_temp = relocs_pattern;
6082 /* All instruction in relax_table should be 32-bit. */
6083 hint_count = hint_info.relax_code_size / 4;
6084 code_insn = CLEAN_REG (*(code_seq + hint_count - 1));
6085 while (pattern_temp)
6087 /* Point to every resolved relocation. */
6088 if (nds32_match_hint_insn (pattern_temp->opcode, code_insn))
6091 pattern_temp->where - pattern_temp->frag->fr_literal;
6092 exp.X_add_symbol = symbol_temp_new (now_seg, ptr_offset,
6093 pattern_temp->frag);
6094 exp.X_add_number = 0;
6096 fix_new_exp (fragP, where - fragP->fr_literal,
6097 fixup_size, &exp, 0, fixup_now->r_type);
6098 fixP->fx_addnumber = fixP->fx_offset;
6100 pattern_temp = pattern_temp->next;
6104 else if (fixup_now->ramp & NDS32_ADDEND)
6106 range = nds32_elf_sethi_range (relocs_pattern);
6107 if (range == NDS32_LOADSTORE_NONE)
6109 as_bad (_("Internal error: Range error. %s"), now_seg->name);
6112 exp.X_add_symbol = abs_section_sym;
6113 exp.X_add_number = SET_ADDEND (4, 0, optimize, enable_16bit);
6114 exp.X_add_number |= ((range & 0x3f) << 8);
6116 else if ((fixup_now->ramp & NDS32_ABS) != 0)
6118 /* This is a tag relocation. */
6119 exp.X_add_symbol = abs_section_sym;
6120 exp.X_add_number = 0;
6122 else if ((fixup_now->ramp & NDS32_INSN16) != 0)
6126 /* This is a tag relocation. */
6127 exp.X_add_symbol = abs_section_sym;
6128 exp.X_add_number = 0;
6130 else if ((fixup_now->ramp & NDS32_SYM) != 0)
6132 /* For EMPTY relocation save the true symbol. */
6133 exp.X_add_symbol = hi_sym;
6134 exp.X_add_number = hi_branch_offset;
6136 else if (NDS32_SYM_DESC_MEM & fixup_now->ramp)
6138 /* Do the same as NDS32_SYM. */
6139 exp.X_add_symbol = hi_sym;
6140 exp.X_add_number = hi_branch_offset;
6142 /* Extra to NDS32_SYM. */
6143 /* Detect if DESC_FUNC relax type do apply. */
6144 if ((REG_GP == N32_RA5 (pattern_now->insn))
6145 || (REG_GP == N32_RB5 (pattern_now->insn)))
6147 fixP = fix_new_exp (fragP, where - fragP->fr_literal,
6148 fixup_size, &exp, pcrel,
6149 BFD_RELOC_NDS32_TLS_DESC_FUNC);
6150 fixP->fx_addnumber = fixP->fx_offset;
6154 /* Else do as usual. */
6156 else if (fixup_now->ramp & NDS32_PTR_PATTERN)
6158 /* Find out PTR_RESOLVED code pattern. */
6159 nds32_relax_fixup_info_t *next_fixup = fixup_now + 1;
6160 uint32_t resolved_pattern = 0;
6161 while (next_fixup->offset)
6163 if (next_fixup->r_type == BFD_RELOC_NDS32_PTR_RESOLVED)
6165 uint32_t new_pattern = code_seq[next_fixup->offset >> 2];
6166 if (!resolved_pattern)
6167 resolved_pattern = new_pattern;
6168 else if (new_pattern != resolved_pattern)
6170 as_warn (_("Multiple BFD_RELOC_NDS32_PTR_RESOLVED "
6171 "patterns are not supported yet!"));
6178 /* Find matched code and insert fix-ups. */
6179 struct nds32_relocs_pattern *next_pattern = pattern_now->next;
6180 /* This relocation has to point to another instruction.
6181 Make sure each resolved relocation has to be pointed. */
6182 /* All instruction in relax_table should be 32-bit. */
6183 while (next_pattern)
6185 uint32_t cur_pattern = GET_OPCODE (next_pattern->opcode->value);
6186 if (cur_pattern == resolved_pattern)
6188 ptr_offset = next_pattern->where
6189 - next_pattern->frag->fr_literal;
6190 exp.X_add_symbol = symbol_temp_new (now_seg, ptr_offset,
6191 next_pattern->frag);
6192 exp.X_add_number = 0;
6193 fixP = fix_new_exp (fragP, where - fragP->fr_literal,
6194 fixup_size, &exp, 0,
6196 fixP->fx_addnumber = fixP->fx_offset;
6198 next_pattern = next_pattern->next;
6203 else if (fixup_now->ramp & NDS32_PTR_MULTIPLE)
6205 /* Find each PTR_RESOLVED pattern after PTR. */
6206 nds32_relax_fixup_info_t *next_fixup = fixup_now + 1;
6207 while (next_fixup->offset)
6209 if (next_fixup->r_type == BFD_RELOC_NDS32_PTR_RESOLVED)
6211 uint32_t pattern = code_seq[next_fixup->offset >> 2];
6212 /* Find matched code to insert fix-ups. */
6213 struct nds32_relocs_pattern *next_insn = pattern_now->next;
6216 uint32_t insn_pattern = GET_OPCODE (next_insn->opcode->value);
6217 if (insn_pattern == pattern)
6219 ptr_offset = next_insn->where
6220 - next_insn->frag->fr_literal;
6221 exp.X_add_symbol = symbol_temp_new (now_seg,
6224 exp.X_add_number = 0;
6225 fixP = fix_new_exp (fragP,
6226 where - fragP->fr_literal,
6227 fixup_size, &exp, 0,
6229 fixP->fx_addnumber = fixP->fx_offset;
6231 next_insn = next_insn->next;
6240 exp.X_add_symbol = sym;
6241 exp.X_add_number = branch_offset;
6244 if (fixup_size != 0)
6246 fixP = fix_new_exp (fragP, where - fragP->fr_literal, fixup_size,
6247 &exp, pcrel, fixup_now->r_type);
6248 fixP->fx_addnumber = fixP->fx_offset;
6251 fixup_size = fixup_now->size;
6254 #ifdef NDS32_LINUX_TOOLCHAIN
6255 /* Insert group relocation for each relax hint. */
6258 exp.X_add_symbol = hi_sym; /* for eyes only */
6259 exp.X_add_number = group_id;
6260 fixP = fix_new_exp (fragP, where - fragP->fr_literal, fixup_size,
6261 &exp, pcrel, BFD_RELOC_NDS32_GROUP);
6262 fixP->fx_addnumber = fixP->fx_offset;
6266 if (count < relax_code_size / 4)
6268 pattern_now = pattern_now->next;
6273 frchain_now = frchain_bak;
6277 nds32_str_tolower (const char *src, char *dest)
6279 unsigned int i, len;
6283 for (i = 0; i < len; i++)
6284 *(dest + i) = TOLOWER (*(src + i));
6289 /* Check instruction if it can be used for the baseline. */
6292 nds32_check_insn_available (struct nds32_asm_insn insn, const char *str)
6294 int attr = insn.attr & ATTR_ALL;
6295 static int baseline_isa = 0;
6298 s = xmalloc (strlen (str) + 1);
6299 nds32_str_tolower (str, s);
6301 && (((insn.opcode->value == ALU2 (MTUSR)
6302 || insn.opcode->value == ALU2 (MFUSR))
6303 && (strstr (s, "lc")
6305 || strstr (s, "lb")))
6306 || (insn.attr & NASM_ATTR_ZOL)))
6308 as_bad (_("Not support instruction %s in verbatim."), str);
6313 if (!enable_16bit && insn.opcode->isize == 2)
6315 as_bad (_("16-bit instruction is disabled: %s."), str);
6319 /* No isa setting or all isa can use. */
6320 if (attr == 0 || attr == ATTR_ALL)
6323 if (baseline_isa == 0)
6325 /* Map option baseline and instruction attribute. */
6326 switch (nds32_baseline)
6329 baseline_isa = ATTR (ISA_V2);
6332 baseline_isa = ATTR (ISA_V3);
6335 baseline_isa = ATTR (ISA_V3M);
6340 if ((baseline_isa & attr) == 0)
6342 as_bad (_("Instruction %s not supported in the baseline."), str);
6348 /* Stub of machine dependent. */
6351 md_assemble (char *str)
6353 struct nds32_asm_insn insn;
6355 struct nds32_pseudo_opcode *popcode;
6356 const struct nds32_field *fld = NULL;
6359 struct nds32_relocs_pattern *relocs_temp;
6360 struct nds32_relocs_group *group_temp;
6362 int label = label_exist;
6363 static bfd_boolean pseudo_hint = FALSE;
6365 popcode = nds32_lookup_pseudo_opcode (str);
6366 /* Note that we need to check 'verbatim' and
6367 'opcode->physical_op'. If the assembly content is generated by
6368 compiler and this opcode is a physical instruction, there is no
6369 need to perform pseudo instruction expansion/transformation. */
6370 if (popcode && !(verbatim && popcode->physical_op))
6372 /* Pseudo instruction is with relax_hint. */
6375 pseudo_opcode = TRUE;
6376 nds32_pseudo_opcode_wrapper (str, popcode);
6377 pseudo_opcode = FALSE;
6378 pseudo_hint = FALSE;
6379 nds32_elf_append_relax_relocs (NULL, relocs_list);
6381 /* Free relax_hint group list. */
6382 while (nds32_relax_hint_current)
6384 group_temp = nds32_relax_hint_current->next;
6385 free (nds32_relax_hint_current);
6386 nds32_relax_hint_current = group_temp;
6389 /* Free pseudo list. */
6390 relocs_temp = relocs_list;
6393 relocs_list = relocs_list->next;
6395 relocs_temp = relocs_list;
6402 insn.info = XNEW (expressionS);
6403 asm_desc.result = NASM_OK;
6404 nds32_assemble (&asm_desc, &insn, str);
6406 switch (asm_desc.result)
6408 case NASM_ERR_UNKNOWN_OP:
6409 as_bad (_("Unrecognized opcode, %s."), str);
6411 case NASM_ERR_SYNTAX:
6412 as_bad (_("Incorrect syntax, %s."), str);
6414 case NASM_ERR_OPERAND:
6415 as_bad (_("Unrecognized operand/register, %s."), str);
6417 case NASM_ERR_OUT_OF_RANGE:
6418 as_bad (_("Operand out of range, %s."), str);
6420 case NASM_ERR_REG_REDUCED:
6421 as_bad (_("Prohibited register used for reduced-register, %s."), str);
6423 case NASM_ERR_JUNK_EOL:
6424 as_bad (_("Junk at end of line, %s."), str);
6428 gas_assert (insn.opcode);
6430 nds32_set_elf_flags_by_insn (&insn);
6432 gas_assert (insn.opcode->isize == 4 || insn.opcode->isize == 2);
6434 if (!nds32_check_insn_available (insn, str))
6437 /* Make sure the beginning of text being 2-byte align. */
6438 nds32_adjust_label (1);
6439 add_mapping_symbol (MAP_CODE, 0, 0);
6441 /* Try to allocate the max size to guarantee relaxable same branch
6442 instructions in the same fragment. */
6443 frag_grow (NDS32_MAXCHAR);
6446 if (fld && (insn.attr & NASM_ATTR_BRANCH)
6447 && (pseudo_opcode || (insn.opcode->value != INSN_JAL
6448 && insn.opcode->value != INSN_J))
6449 && (!verbatim || pseudo_opcode))
6451 /* User assembly code branch relax for it. */
6452 /* If fld is not NULL, it is a symbol. */
6453 /* Branch must relax to proper pattern in user assembly code exclude
6454 J and JAL. Keep these two in original type for users which wants
6455 to keep their size be fixed. In general, assembler does not convert
6456 instruction generated by compiler. But jump instruction may be
6457 truncated in text virtual model. For workaround, compiler generate
6458 pseudo jump to fix this issue currently. */
6460 /* Get branch range type. */
6461 dwarf2_emit_insn (0);
6462 enum nds32_br_range range_type;
6463 expressionS *pexp = insn.info;
6465 range_type = get_range_type (fld);
6467 out = frag_var (rs_machine_dependent, NDS32_MAXCHAR,
6468 0, /* VAR is un-used. */
6469 range_type, /* SUBTYPE is used as range type. */
6470 pexp->X_add_symbol, pexp->X_add_number, 0);
6472 fragP->fr_fix += insn.opcode->isize;
6473 fragP->tc_frag_data.opcode = insn.opcode;
6474 fragP->tc_frag_data.insn = insn.insn;
6475 if (insn.opcode->isize == 4)
6476 bfd_putb32 (insn.insn, out);
6477 else if (insn.opcode->isize == 2)
6478 bfd_putb16 (insn.insn, out);
6479 fragP->tc_frag_data.flag |= NDS32_FRAG_BRANCH;
6483 /* md_convert_frag will insert relocations. */
6485 else if (!relaxing && enable_16bit && (optimize || optimize_for_space)
6486 && ((!fld && !verbatim && insn.opcode->isize == 4
6487 && nds32_convert_32_to_16 (stdoutput, insn.insn, &insn_16, NULL))
6488 || (insn.opcode->isize == 2
6489 && nds32_convert_16_to_32 (stdoutput, insn.insn, NULL))))
6491 /* Record this one is relaxable. */
6492 expressionS *pexp = insn.info;
6493 dwarf2_emit_insn (0);
6496 out = frag_var (rs_machine_dependent,
6497 4, /* Max size is 32-bit instruction. */
6498 0, /* VAR is un-used. */
6499 0, pexp->X_add_symbol, pexp->X_add_number, 0);
6500 fragP->tc_frag_data.flag |= NDS32_FRAG_RELAXABLE_BRANCH;
6503 out = frag_var (rs_machine_dependent,
6504 4, /* Max size is 32-bit instruction. */
6505 0, /* VAR is un-used. */
6507 fragP->tc_frag_data.flag |= NDS32_FRAG_RELAXABLE;
6508 fragP->tc_frag_data.opcode = insn.opcode;
6509 fragP->tc_frag_data.insn = insn.insn;
6512 /* In original, we don't relax the instruction with label on it,
6513 but this may cause some redundant nop16. Therefore, tag this
6514 relaxable instruction and relax it carefully. */
6516 fragP->tc_frag_data.flag |= NDS32_FRAG_LABEL;
6518 if (insn.opcode->isize == 4)
6519 bfd_putb16 (insn_16, out);
6520 else if (insn.opcode->isize == 2)
6521 bfd_putb16 (insn.insn, out);
6526 else if ((verbatim || !relaxing) && optimize && label)
6528 /* This instruction is with label. */
6530 out = frag_var (rs_machine_dependent, insn.opcode->isize,
6531 0, 0, NULL, 0, NULL);
6532 /* If this instruction is branch target, it is not relaxable. */
6533 fragP->tc_frag_data.flag = NDS32_FRAG_LABEL;
6534 fragP->tc_frag_data.opcode = insn.opcode;
6535 fragP->tc_frag_data.insn = insn.insn;
6536 fragP->fr_fix += insn.opcode->isize;
6537 if (insn.opcode->isize == 4)
6539 exp.X_op = O_symbol;
6540 exp.X_add_symbol = abs_section_sym;
6541 exp.X_add_number = 0;
6542 fixP = fix_new_exp (fragP, fragP->fr_fix - 4, 0, &exp,
6543 0, BFD_RELOC_NDS32_LABEL);
6545 fragP->tc_frag_data.flag = NDS32_FRAG_ALIGN;
6549 out = frag_more (insn.opcode->isize);
6551 if (insn.opcode->isize == 4)
6552 bfd_putb32 (insn.insn, out);
6553 else if (insn.opcode->isize == 2)
6554 bfd_putb16 (insn.insn, out);
6556 dwarf2_emit_insn (insn.opcode->isize);
6558 /* Compiler generating code and user assembly pseudo load-store, insert
6560 expressionS *pexp = insn.info;
6561 fixP = nds32_elf_record_fixup_exp (fragP, str, fld, pexp, out, &insn);
6562 /* Build relaxation pattern when relaxing is enable. */
6564 nds32_elf_build_relax_relation (fixP, pexp, out, &insn, fragP, fld,
6570 /* md_macro_start */
6573 nds32_macro_start (void)
6580 nds32_macro_info (void *info ATTRIBUTE_UNUSED)
6587 nds32_macro_end (void)
6591 /* GAS will call this function with one argument, an expressionS pointer, for
6592 any expression that can not be recognized. When the function is called,
6593 input_line_pointer will point to the start of the expression. */
6596 md_operand (expressionS *expressionP)
6598 if (*input_line_pointer == '#')
6600 input_line_pointer++;
6601 expression (expressionP);
6605 /* GAS will call this function for each section at the end of the assembly, to
6606 permit the CPU back end to adjust the alignment of a section. The function
6607 must take two arguments, a segT for the section and a valueT for the size of
6608 the section, and return a valueT for the rounded size. */
6611 md_section_align (segT segment, valueT size)
6613 int align = bfd_get_section_alignment (stdoutput, segment);
6615 return ((size + (1 << align) - 1) & ((valueT) -1 << align));
6618 /* GAS will call this function when a symbol table lookup fails, before it
6619 creates a new symbol. Typically this would be used to supply symbols whose
6620 name or value changes dynamically, possibly in a context sensitive way.
6621 Predefined symbols with fixed values, such as register names or condition
6622 codes, are typically entered directly into the symbol table when md_begin
6623 is called. One argument is passed, a char * for the symbol. */
6626 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
6632 nds32_calc_branch_offset (segT segment, fragS *fragP,
6633 long stretch ATTRIBUTE_UNUSED,
6634 relax_info_t *relax_info,
6635 enum nds32_br_range branch_range_type)
6637 struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
6638 symbolS *branch_symbol = fragP->fr_symbol;
6639 offsetT branch_offset = fragP->fr_offset;
6640 offsetT branch_target_address;
6641 offsetT branch_insn_address;
6644 if ((S_GET_SEGMENT (branch_symbol) != segment)
6645 || S_IS_WEAK (branch_symbol))
6647 /* The symbol is not in the SEGMENT. It could be far far away. */
6648 offset = 0x80000000;
6652 /* Calculate symbol-to-instruction offset. */
6653 branch_target_address = S_GET_VALUE (branch_symbol) + branch_offset;
6654 /* If the destination symbol is beyond current frag address,
6655 STRETCH will take effect to symbol's position. */
6656 if (S_GET_VALUE (branch_symbol) > fragP->fr_address)
6657 branch_target_address += stretch;
6659 branch_insn_address = fragP->fr_address + fragP->fr_fix;
6660 branch_insn_address -= opcode->isize;
6662 /* Update BRANCH_INSN_ADDRESS to relaxed position. */
6663 branch_insn_address += (relax_info->relax_code_size[branch_range_type]
6664 - relax_info->relax_branch_isize[branch_range_type]);
6666 offset = branch_target_address - branch_insn_address;
6672 static enum nds32_br_range
6673 nds32_convert_to_range_type (long offset)
6675 enum nds32_br_range range_type;
6677 if (-(0x100) <= offset && offset < 0x100) /* 256 bytes */
6678 range_type = BR_RANGE_S256;
6679 else if (-(0x4000) <= offset && offset < 0x4000) /* 16K bytes */
6680 range_type = BR_RANGE_S16K;
6681 else if (-(0x10000) <= offset && offset < 0x10000) /* 64K bytes */
6682 range_type = BR_RANGE_S64K;
6683 else if (-(0x1000000) <= offset && offset < 0x1000000) /* 16M bytes */
6684 range_type = BR_RANGE_S16M;
6686 range_type = BR_RANGE_U4G;
6691 /* Set instruction register mask. */
6694 nds32_elf_get_set_cond (relax_info_t *relax_info, int offset, uint32_t *insn,
6695 uint32_t ori_insn, int range)
6697 nds32_cond_field_t *cond_fields = relax_info->cond_field;
6698 nds32_cond_field_t *code_seq_cond = relax_info->relax_code_condition[range];
6702 /* The instruction has conditions. Collect condition values. */
6703 while (code_seq_cond[i].bitmask != 0)
6705 if (offset == code_seq_cond[i].offset)
6707 mask = (ori_insn >> cond_fields[i].bitpos) & cond_fields[i].bitmask;
6709 if (cond_fields[i].signed_extend)
6710 mask = (mask ^ ((cond_fields[i].bitmask + 1) >> 1)) -
6711 ((cond_fields[i].bitmask + 1) >> 1);
6712 *insn |= (mask & code_seq_cond[i].bitmask) << code_seq_cond[i].bitpos;
6719 nds32_relax_branch_instructions (segT segment, fragS *fragP,
6720 long stretch ATTRIBUTE_UNUSED,
6723 enum nds32_br_range branch_range_type;
6724 struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
6726 enum nds32_br_range real_range_type;
6728 relax_info_t *relax_info;
6735 int code_seq_offset;
6737 /* Replace with gas_assert (fragP->fr_symbol != NULL); */
6738 if (fragP->fr_symbol == NULL)
6741 /* If frag_var is not enough room, the previous frag is fr_full and with
6742 opcode. The new one is rs_dependent but without opcode. */
6746 /* Use U4G mode for b and bal in verbatim mode because lto may combine
6747 functions into a file. And order the file in the last when linking.
6748 Once there is multiple definition, the same function will be kicked.
6749 This may cause relocation truncated error. */
6750 if (verbatim && !nds32_pic
6751 && (strcmp (opcode->opcode, "j") == 0
6752 || strcmp (opcode->opcode, "jal") == 0))
6754 fragP->fr_subtype = BR_RANGE_U4G;
6761 relax_info = hash_find (nds32_relax_info_hash, opcode->opcode);
6763 if (relax_info == NULL)
6768 branch_range_type = relax_info->br_range;
6773 branch_range_type = fragP->fr_subtype;
6774 i = branch_range_type;
6777 offset = nds32_calc_branch_offset (segment, fragP, stretch,
6778 relax_info, branch_range_type);
6780 real_range_type = nds32_convert_to_range_type (offset);
6782 /* If actual range is equal to instruction jump range, do nothing. */
6783 if (real_range_type == branch_range_type)
6785 fragP->fr_subtype = real_range_type;
6789 /* Find out proper relaxation code sequence. */
6790 for (; i < BR_RANGE_NUM; i++)
6792 if (real_range_type <= (unsigned int) i)
6795 diff = relax_info->relax_code_size[i] - opcode->isize;
6796 else if (real_range_type < (unsigned int) i)
6797 diff = relax_info->relax_code_size[real_range_type]
6798 - relax_info->relax_code_size[branch_range_type];
6800 diff = relax_info->relax_code_size[i]
6801 - relax_info->relax_code_size[branch_range_type];
6803 /* If the instruction could be converted to 16-bits,
6804 minus the difference. */
6805 code_seq_offset = 0;
6808 code_seq_size = relax_info->relax_code_size[i];
6809 code_seq = relax_info->relax_code_seq[i];
6810 while (code_seq_offset < code_seq_size)
6813 if (insn & 0x80000000) /* 16-bits instruction. */
6817 else /* 32-bits instruction. */
6821 while (relax_info->relax_fixup[i][k].size !=0
6822 && relax_info->relax_fixup[i][k].offset < code_seq_offset)
6826 code_seq_offset += insn_size;
6830 /* Update fr_subtype to new NDS32_BR_RANGE. */
6831 fragP->fr_subtype = real_range_type;
6836 return diff + adjust;
6839 /* Adjust relaxable frag till current frag. */
6842 nds32_adjust_relaxable_frag (fragS *startP, fragS *fragP)
6845 if (startP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
6850 startP->tc_frag_data.flag ^= NDS32_FRAG_RELAXED;
6854 startP = startP->fr_next;
6857 startP->fr_address += adj;
6858 if (startP == fragP)
6866 nds32_get_align (addressT address, int align)
6868 addressT mask, new_address;
6870 mask = ~((addressT) (~0) << align);
6871 new_address = (address + mask) & (~mask);
6872 return (new_address - address);
6875 /* Check the prev_frag is legal. */
6877 invalid_prev_frag (fragS * fragP, fragS **prev_frag, bfd_boolean relax)
6880 fragS *frag_start = *prev_frag;
6882 if (!frag_start || !relax)
6885 if (frag_start->last_fr_address >= fragP->last_fr_address)
6891 fragS *frag_t = *prev_frag;
6892 while (frag_t != fragP)
6894 if (frag_t->fr_type == rs_align
6895 || frag_t->fr_type == rs_align_code
6896 || frag_t->fr_type == rs_align_test)
6898 /* Relax instruction can not walk across label. */
6899 if (frag_t->tc_frag_data.flag & NDS32_FRAG_LABEL)
6904 /* Relax previous relaxable to align rs_align frag. */
6905 address = frag_t->fr_address + frag_t->fr_fix;
6906 addressT offset = nds32_get_align (address, (int) frag_t->fr_offset);
6909 /* If there is label on the prev_frag, check if it is aligned. */
6910 if (!((*prev_frag)->tc_frag_data.flag & NDS32_FRAG_LABEL)
6911 || (((*prev_frag)->fr_address + (*prev_frag)->fr_fix - 2 )
6913 nds32_adjust_relaxable_frag (*prev_frag, frag_t);
6918 frag_t = frag_t->fr_next;
6921 if (fragP->tc_frag_data.flag & NDS32_FRAG_ALIGN)
6923 address = fragP->fr_address;
6924 addressT offset = nds32_get_align (address, 2);
6927 /* If there is label on the prev_frag, check if it is aligned. */
6928 if (!((*prev_frag)->tc_frag_data.flag & NDS32_FRAG_LABEL)
6929 || (((*prev_frag)->fr_address + (*prev_frag)->fr_fix - 2 )
6931 nds32_adjust_relaxable_frag (*prev_frag, fragP);
6941 nds32_relax_frag (segT segment, fragS *fragP, long stretch ATTRIBUTE_UNUSED)
6943 /* Currently, there are two kinds of relaxation in nds32 assembler.
6945 2. relax for 32-bits to 16-bits */
6947 static fragS *prev_frag = NULL;
6950 invalid_prev_frag (fragP, &prev_frag, TRUE);
6952 if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
6953 adjust = nds32_relax_branch_instructions (segment, fragP, stretch, 0);
6954 if (fragP->tc_frag_data.flag & NDS32_FRAG_LABEL)
6956 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE
6957 && (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED) == 0)
6958 /* Here is considered relaxed case originally. But it may cause
6959 an endless loop when relaxing. Once the instruction is relaxed,
6960 it can not be undone. */
6966 /* This function returns an initial guess of the length by which a fragment
6967 must grow to hold a branch to reach its destination. Also updates
6968 fr_type/fr_subtype as necessary.
6970 It is called just before doing relaxation. Any symbol that is now undefined
6971 will not become defined. The guess for fr_var is ACTUALLY the growth beyond
6972 fr_fix. Whatever we do to grow fr_fix or fr_var contributes to our returned
6973 value. Although it may not be explicit in the frag, pretend fr_var starts
6977 md_estimate_size_before_relax (fragS *fragP, segT segment)
6979 /* Currently, there are two kinds of relaxation in nds32 assembler.
6981 2. relax for 32-bits to 16-bits */
6983 /* Save previous relaxable frag. */
6984 static fragS *prev_frag = NULL;
6987 invalid_prev_frag (fragP, &prev_frag, FALSE);
6989 if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
6990 adjust = nds32_relax_branch_instructions (segment, fragP, 0, 1);
6991 if (fragP->tc_frag_data.flag & NDS32_FRAG_LABEL)
6993 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
6995 else if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE)
7001 /* GAS will call this for each rs_machine_dependent fragment. The instruction
7002 is completed using the data from the relaxation pass. It may also create any
7003 necessary relocations.
7005 *FRAGP has been relaxed to its final size, and now needs to have the bytes
7006 inside it modified to conform to the new size. It is called after relaxation
7009 fragP->fr_type == rs_machine_dependent.
7010 fragP->fr_subtype is the subtype of what the address relaxed to. */
7013 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP)
7015 /* Convert branch relaxation instructions. */
7016 symbolS *branch_symbol = fragP->fr_symbol;
7017 offsetT branch_offset = fragP->fr_offset;
7018 enum nds32_br_range branch_range_type = fragP->fr_subtype;
7019 struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
7020 uint32_t origin_insn = fragP->tc_frag_data.insn;
7021 relax_info_t *relax_info;
7024 int addend ATTRIBUTE_UNUSED;
7025 offsetT branch_target_address, branch_insn_address;
7030 int code_size, insn_size, offset, fixup_size;
7031 int buf_offset, pcrel;
7034 nds32_relax_fixup_info_t fixup_info[MAX_RELAX_FIX];
7035 /* Save the 1st instruction is converted to 16 bit or not. */
7036 unsigned int branch_size;
7037 enum bfd_reloc_code_real final_r_type;
7039 /* Replace with gas_assert (branch_symbol != NULL); */
7040 if (branch_symbol == NULL && !(fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED))
7043 /* If frag_var is not enough room, the previous frag is fr_full and with
7044 opcode. The new one is rs_dependent but without opcode. */
7048 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE_BRANCH)
7050 relax_info = hash_find (nds32_relax_info_hash, opcode->opcode);
7052 if (relax_info == NULL)
7056 while (i < BR_RANGE_NUM
7057 && relax_info->relax_code_size[i]
7058 != (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED ? 4 : 2))
7061 if (i >= BR_RANGE_NUM)
7062 as_bad ("Internal error: Cannot find relocation of"
7063 "relaxable branch.");
7065 exp.X_op = O_symbol;
7066 exp.X_add_symbol = branch_symbol;
7067 exp.X_add_number = branch_offset;
7068 pcrel = ((relax_info->relax_fixup[i][0].ramp & NDS32_PCREL) != 0) ? 1 : 0;
7069 fr_where = fragP->fr_fix - 2;
7070 fixP = fix_new_exp (fragP, fr_where, relax_info->relax_fixup[i][0].size,
7071 &exp, pcrel, relax_info->relax_fixup[i][0].r_type);
7072 fixP->fx_addnumber = fixP->fx_offset;
7074 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
7076 insn_16 = fragP->tc_frag_data.insn;
7077 nds32_convert_16_to_32 (stdoutput, insn_16, &insn);
7078 fr_buffer = fragP->fr_literal + fr_where;
7080 exp.X_op = O_symbol;
7081 exp.X_add_symbol = abs_section_sym;
7082 exp.X_add_number = 0;
7083 fix_new_exp (fragP, fr_where, 4,
7084 &exp, 0, BFD_RELOC_NDS32_INSN16);
7085 number_to_chars_bigendian (fr_buffer, insn, 4);
7088 else if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
7090 if (fragP->tc_frag_data.opcode->isize == 2)
7092 insn_16 = fragP->tc_frag_data.insn;
7093 nds32_convert_16_to_32 (stdoutput, insn_16, &insn);
7096 insn = fragP->tc_frag_data.insn;
7098 fr_where = fragP->fr_fix - 4;
7099 fr_buffer = fragP->fr_literal + fr_where;
7100 exp.X_op = O_symbol;
7101 exp.X_add_symbol = abs_section_sym;
7102 exp.X_add_number = 0;
7103 fix_new_exp (fragP, fr_where, 4, &exp, 0,
7104 BFD_RELOC_NDS32_INSN16);
7105 number_to_chars_bigendian (fr_buffer, insn, 4);
7107 else if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
7109 /* Branch instruction adjust and append relocations. */
7110 relax_info = hash_find (nds32_relax_info_hash, opcode->opcode);
7112 if (relax_info == NULL)
7115 fr_where = fragP->fr_fix - opcode->isize;
7116 fr_buffer = fragP->fr_literal + fr_where;
7118 if ((S_GET_SEGMENT (branch_symbol) != sec)
7119 || S_IS_WEAK (branch_symbol))
7121 if (fragP->fr_offset & 3)
7122 as_warn (_("Addend to unresolved symbol is not on word boundary."));
7127 /* Calculate symbol-to-instruction offset. */
7128 branch_target_address = S_GET_VALUE (branch_symbol) + branch_offset;
7129 branch_insn_address = fragP->fr_address + fr_where;
7130 addend = (branch_target_address - branch_insn_address) >> 1;
7133 code_size = relax_info->relax_code_size[branch_range_type];
7134 code_seq = relax_info->relax_code_seq[branch_range_type];
7136 memcpy (fixup_info, relax_info->relax_fixup[branch_range_type],
7137 sizeof (fixup_info));
7142 offset = 0; /* code_seq offset */
7143 buf_offset = 0; /* fr_buffer offset */
7144 while (offset < code_size)
7147 if (insn & 0x80000000) /* 16-bits instruction. */
7149 insn = (insn >> 16) & 0xFFFF;
7152 else /* 32-bits instruction. */
7157 nds32_elf_get_set_cond (relax_info, offset, &insn,
7158 origin_insn, branch_range_type);
7160 /* Try to convert to 16-bits instruction. Currently, only the first
7161 instruction in pattern can be converted. EX: bnez sethi ori jr,
7162 only bnez can be converted to 16 bit and ori can't. */
7164 while (fixup_info[k].size != 0
7165 && relax_info->relax_fixup[branch_range_type][k].offset < offset)
7168 number_to_chars_bigendian (fr_buffer + buf_offset, insn, insn_size);
7169 buf_offset += insn_size;
7171 offset += insn_size;
7176 exp.X_op = O_symbol;
7178 for (i = 0; fixup_info[i].size != 0; i++)
7180 fixup_size = fixup_info[i].size;
7181 pcrel = ((fixup_info[i].ramp & NDS32_PCREL) != 0) ? 1 : 0;
7183 if ((fixup_info[i].ramp & NDS32_CREATE_LABEL) != 0)
7185 /* This is a reverse branch. */
7186 exp.X_add_symbol = symbol_temp_new (sec, 0, fragP->fr_next);
7187 exp.X_add_number = 0;
7189 else if ((fixup_info[i].ramp & NDS32_PTR) != 0)
7191 /* This relocation has to point to another instruction. */
7192 branch_size = fr_where + code_size - 4;
7193 exp.X_add_symbol = symbol_temp_new (sec, branch_size, fragP);
7194 exp.X_add_number = 0;
7196 else if ((fixup_info[i].ramp & NDS32_ABS) != 0)
7198 /* This is a tag relocation. */
7199 exp.X_add_symbol = abs_section_sym;
7200 exp.X_add_number = 0;
7202 else if ((fixup_info[i].ramp & NDS32_INSN16) != 0)
7206 /* This is a tag relocation. */
7207 exp.X_add_symbol = abs_section_sym;
7208 exp.X_add_number = 0;
7212 exp.X_add_symbol = branch_symbol;
7213 exp.X_add_number = branch_offset;
7216 if (fixup_info[i].r_type != 0)
7218 final_r_type = fixup_info[i].r_type;
7219 fixP = fix_new_exp (fragP, fr_where + fixup_info[i].offset,
7220 fixup_size, &exp, pcrel,
7222 fixP->fx_addnumber = fixP->fx_offset;
7226 fragP->fr_fix = fr_where + buf_offset;
7230 /* tc_frob_file_before_fix */
7233 nds32_frob_file_before_fix (void)
7238 nds32_relaxable_section (asection *sec)
7240 return ((sec->flags & SEC_DEBUGGING) == 0
7241 && strcmp (sec->name, ".eh_frame") != 0);
7244 /* TC_FORCE_RELOCATION */
7246 nds32_force_relocation (fixS * fix)
7248 switch (fix->fx_r_type)
7250 case BFD_RELOC_NDS32_INSN16:
7251 case BFD_RELOC_NDS32_LABEL:
7252 case BFD_RELOC_NDS32_LONGCALL1:
7253 case BFD_RELOC_NDS32_LONGCALL2:
7254 case BFD_RELOC_NDS32_LONGCALL3:
7255 case BFD_RELOC_NDS32_LONGJUMP1:
7256 case BFD_RELOC_NDS32_LONGJUMP2:
7257 case BFD_RELOC_NDS32_LONGJUMP3:
7258 case BFD_RELOC_NDS32_LOADSTORE:
7259 case BFD_RELOC_NDS32_9_FIXED:
7260 case BFD_RELOC_NDS32_15_FIXED:
7261 case BFD_RELOC_NDS32_17_FIXED:
7262 case BFD_RELOC_NDS32_25_FIXED:
7263 case BFD_RELOC_NDS32_9_PCREL:
7264 case BFD_RELOC_NDS32_15_PCREL:
7265 case BFD_RELOC_NDS32_17_PCREL:
7266 case BFD_RELOC_NDS32_WORD_9_PCREL:
7267 case BFD_RELOC_NDS32_10_UPCREL:
7268 case BFD_RELOC_NDS32_25_PCREL:
7269 case BFD_RELOC_NDS32_MINUEND:
7270 case BFD_RELOC_NDS32_SUBTRAHEND:
7276 case BFD_RELOC_NDS32_DIFF_ULEB128:
7277 /* Linker should handle difference between two symbol. */
7278 return fix->fx_subsy != NULL
7279 && nds32_relaxable_section (S_GET_SEGMENT (fix->fx_addsy));
7282 as_bad ("Double word for difference between two symbols "
7283 "is not supported across relaxation.");
7288 if (generic_force_reloc (fix))
7291 return fix->fx_pcrel;
7294 /* TC_VALIDATE_FIX_SUB */
7297 nds32_validate_fix_sub (fixS *fix, segT add_symbol_segment)
7299 segT sub_symbol_segment;
7301 /* This code is referred from Xtensa. Check their implementation for
7304 /* Make sure both symbols are in the same segment, and that segment is
7305 "normal" and relaxable. */
7306 sub_symbol_segment = S_GET_SEGMENT (fix->fx_subsy);
7307 return (sub_symbol_segment == add_symbol_segment
7308 && add_symbol_segment != undefined_section);
7312 md_number_to_chars (char *buf, valueT val, int n)
7314 if (target_big_endian)
7315 number_to_chars_bigendian (buf, val, n);
7317 number_to_chars_littleendian (buf, val, n);
7320 /* Equal to MAX_PRECISION in atof-ieee.c. */
7321 #define MAX_LITTLENUMS 6
7323 /* This function is called to convert an ASCII string into a floating point
7324 value in format used by the CPU. */
7327 md_atof (int type, char *litP, int *sizeP)
7331 LITTLENUM_TYPE words[MAX_LITTLENUMS];
7350 return _("Bad call to md_atof()");
7353 t = atof_ieee (input_line_pointer, type, words);
7355 input_line_pointer = t;
7356 *sizeP = prec * sizeof (LITTLENUM_TYPE);
7358 if (target_big_endian)
7360 for (i = 0; i < prec; i++)
7362 md_number_to_chars (litP, (valueT) words[i],
7363 sizeof (LITTLENUM_TYPE));
7364 litP += sizeof (LITTLENUM_TYPE);
7369 for (i = prec - 1; i >= 0; i--)
7371 md_number_to_chars (litP, (valueT) words[i],
7372 sizeof (LITTLENUM_TYPE));
7373 litP += sizeof (LITTLENUM_TYPE);
7380 /* md_elf_section_change_hook */
7383 nds32_elf_section_change_hook (void)
7390 nds32_cleanup (void)
7394 /* This function is used to scan leb128 subtraction expressions,
7395 and insert fixups for them.
7397 e.g., .leb128 .L1 - .L0
7399 These expressions are heavily used in debug information or
7400 exception tables. Because relaxation will change code size,
7401 we must resolve them in link time. */
7404 nds32_insert_leb128_fixes (bfd *abfd ATTRIBUTE_UNUSED,
7405 asection *sec, void *xxx ATTRIBUTE_UNUSED)
7407 segment_info_type *seginfo = seg_info (sec);
7410 subseg_set (sec, 0);
7412 for (fragP = seginfo->frchainP->frch_root;
7413 fragP; fragP = fragP->fr_next)
7417 /* Only unsigned leb128 can be handle. */
7418 if (fragP->fr_type != rs_leb128 || fragP->fr_subtype != 0
7419 || fragP->fr_symbol == NULL)
7422 exp = symbol_get_value_expression (fragP->fr_symbol);
7424 if (exp->X_op != O_subtract)
7427 fix_new_exp (fragP, fragP->fr_fix, 0,
7428 exp, 0, BFD_RELOC_NDS32_DIFF_ULEB128);
7433 nds32_insert_relax_entry (bfd *abfd ATTRIBUTE_UNUSED, asection *sec,
7434 void *xxx ATTRIBUTE_UNUSED)
7436 segment_info_type *seginfo;
7442 seginfo = seg_info (sec);
7443 if (!seginfo || !symbol_rootP || !subseg_text_p (sec) || sec->size == 0)
7446 for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
7450 if (!fixp && !verbatim && ict_flag == ICT_NONE)
7453 subseg_change (sec, 0);
7455 /* Set RELAX_ENTRY flags for linker. */
7456 fragP = seginfo->frchainP->frch_root;
7457 exp.X_op = O_symbol;
7458 exp.X_add_symbol = abs_section_sym;
7459 exp.X_add_number = 0;
7460 if (!enable_relax_relocs)
7461 exp.X_add_number |= R_NDS32_RELAX_ENTRY_DISABLE_RELAX_FLAG;
7464 /* These flags are only enabled when global relax is enabled.
7465 Maybe we can check DISABLE_RELAX_FLAG at link-time,
7466 so we set them anyway. */
7468 exp.X_add_number |= R_NDS32_RELAX_ENTRY_VERBATIM_FLAG;
7469 if (ict_flag == ICT_SMALL)
7470 exp.X_add_number |= R_NDS32_RELAX_ENTRY_ICT_SMALL;
7471 else if (ict_flag == ICT_LARGE)
7472 exp.X_add_number |= R_NDS32_RELAX_ENTRY_ICT_LARGE;
7475 exp.X_add_number |= R_NDS32_RELAX_ENTRY_OPTIMIZE_FLAG;
7476 if (optimize_for_space)
7477 exp.X_add_number |= R_NDS32_RELAX_ENTRY_OPTIMIZE_FOR_SPACE_FLAG;
7479 fixP = fix_new_exp (fragP, 0, 0, &exp, 0, BFD_RELOC_NDS32_RELAX_ENTRY);
7480 fixP->fx_no_overflow = 1;
7483 /* Analysis relax hint and insert suitable relocation pattern. */
7486 nds32_elf_analysis_relax_hint (void)
7488 hash_traverse (nds32_hint_hash, nds32_elf_append_relax_relocs);
7492 nds32_elf_insert_final_frag (void)
7494 struct frchain *frchainP;
7501 for (s = stdoutput->sections; s; s = s->next)
7503 segment_info_type *seginfo = seg_info (s);
7507 for (frchainP = seginfo->frchainP; frchainP != NULL;
7508 frchainP = frchainP->frch_next)
7510 subseg_set (s, frchainP->frch_subseg);
7512 if (subseg_text_p (now_seg))
7515 frag_var (rs_machine_dependent, 2, /* Max size. */
7516 0, /* VAR is un-used. */ 0, NULL, 0, NULL);
7517 fragP->tc_frag_data.flag |= NDS32_FRAG_FINAL;
7526 nds32_elf_insert_final_frag ();
7527 nds32_elf_analysis_relax_hint ();
7528 bfd_map_over_sections (stdoutput, nds32_insert_leb128_fixes, NULL);
7531 /* Implement md_allow_local_subtract. */
7534 nds32_allow_local_subtract (expressionS *expr_l ATTRIBUTE_UNUSED,
7535 expressionS *expr_r ATTRIBUTE_UNUSED,
7536 segT sec ATTRIBUTE_UNUSED)
7538 /* Don't allow any subtraction, because relax may change the code. */
7542 /* Sort relocation by address.
7544 We didn't use qsort () in stdlib, because quick-sort is not a stable
7545 sorting algorithm. Relocations at the same address (r_offset) must keep
7546 their relative order. For example, RELAX_ENTRY must be the very first
7549 Currently, this function implements insertion-sort. */
7552 compar_relent (const void *lhs, const void *rhs)
7554 const arelent **l = (const arelent **) lhs;
7555 const arelent **r = (const arelent **) rhs;
7557 if ((*l)->address > (*r)->address)
7559 else if ((*l)->address == (*r)->address)
7565 /* SET_SECTION_RELOCS ()
7567 Although this macro is originally used to set a relocation for each section,
7568 we use it to sort relocations in the same section by the address of the
7572 nds32_set_section_relocs (asection *sec, arelent ** relocs ATTRIBUTE_UNUSED,
7573 unsigned int n ATTRIBUTE_UNUSED)
7575 bfd *abfd ATTRIBUTE_UNUSED = sec->owner;
7576 if (bfd_get_section_flags (abfd, sec) & (flagword) SEC_RELOC)
7577 nds32_insertion_sort (sec->orelocation, sec->reloc_count,
7578 sizeof (arelent**), compar_relent);
7582 nds32_pcrel_from_section (fixS *fixP, segT sec ATTRIBUTE_UNUSED)
7584 if (fixP->fx_addsy == NULL || !S_IS_DEFINED (fixP->fx_addsy)
7585 || S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy))
7587 /* Let linker resolve undefined symbols. */
7591 return fixP->fx_frag->fr_address + fixP->fx_where;
7594 /* md_post_relax_hook ()
7595 Insert relax entry relocation into sections. */
7598 nds32_post_relax_hook (void)
7600 bfd_map_over_sections (stdoutput, nds32_insert_relax_entry, NULL);
7603 /* tc_fix_adjustable ()
7605 Return whether this symbol (fixup) can be replaced with
7609 nds32_fix_adjustable (fixS *fixP)
7611 switch (fixP->fx_r_type)
7613 case BFD_RELOC_NDS32_WORD_9_PCREL:
7614 case BFD_RELOC_NDS32_9_PCREL:
7615 case BFD_RELOC_NDS32_15_PCREL:
7616 case BFD_RELOC_NDS32_17_PCREL:
7617 case BFD_RELOC_NDS32_25_PCREL:
7618 case BFD_RELOC_NDS32_HI20:
7619 case BFD_RELOC_NDS32_LO12S0:
7623 case BFD_RELOC_NDS32_PTR:
7624 case BFD_RELOC_NDS32_LONGCALL4:
7625 case BFD_RELOC_NDS32_LONGCALL5:
7626 case BFD_RELOC_NDS32_LONGCALL6:
7627 case BFD_RELOC_NDS32_LONGJUMP4:
7628 case BFD_RELOC_NDS32_LONGJUMP5:
7629 case BFD_RELOC_NDS32_LONGJUMP6:
7630 case BFD_RELOC_NDS32_LONGJUMP7:
7637 /* elf_tc_final_processing */
7640 elf_nds32_final_processing (void)
7642 /* An FPU_COM instruction is found without previous non-FPU_COM
7645 && !(nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST)))
7647 /* Since only FPU_COM instructions are used and no other FPU instructions
7648 are used. The nds32_elf_flags will be decided by the enabled options
7649 by command line or default configuration. */
7650 if (nds32_fpu_dp_ext || nds32_fpu_sp_ext)
7652 nds32_elf_flags |= nds32_fpu_dp_ext ? E_NDS32_HAS_FPU_DP_INST : 0;
7653 nds32_elf_flags |= nds32_fpu_sp_ext ? E_NDS32_HAS_FPU_INST : 0;
7657 /* Should never here. */
7658 as_bad (_("Used FPU instructions requires enabling FPU extension"));
7662 if (nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST))
7664 /* Single/double FPU has been used, set FPU register config. */
7665 /* We did not check the actual number of register used. We may
7666 want to do it while assemble. */
7667 nds32_elf_flags &= ~E_NDS32_FPU_REG_CONF;
7668 nds32_elf_flags |= (nds32_freg << E_NDS32_FPU_REG_CONF_SHIFT);
7672 nds32_elf_flags |= E_NDS32_HAS_PIC;
7675 nds32_elf_flags |= E_NDS32_HAS_REDUCED_REGS;
7677 nds32_elf_flags |= (E_NDS32_ELF_VER_1_4 | nds32_abi);
7678 elf_elfheader (stdoutput)->e_flags |= nds32_elf_flags;
7681 /* Implement md_apply_fix. Apply the fix-up or transform the fix-up for
7682 later relocation generation. */
7685 nds32_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
7687 char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
7688 bfd_vma value = *valP;
7690 if (fixP->fx_r_type < BFD_RELOC_UNUSED
7691 && fixP->fx_r_type > BFD_RELOC_NONE
7692 && fixP->fx_r_type != BFD_RELOC_NDS32_DIFF_ULEB128)
7694 /* In our old nds32 binutils, it must convert relocations which is
7695 generated by CGEN. However, it does not have to consider this anymore.
7696 In current, it only deal with data relocations which enum
7697 is smaller than BFD_RELOC_NONE and BFD_RELOC_NDS32_DIFF_ULEB128.
7698 It is believed that we can construct a better mechanism to
7699 deal with the whole relocation issue in nds32 target
7700 without using CGEN. */
7701 fixP->fx_addnumber = value;
7702 fixP->tc_fix_data = NULL;
7704 /* Transform specific relocations here for later relocation generation.
7705 Tag tls data for linker. */
7706 switch (fixP->fx_r_type)
7708 case BFD_RELOC_NDS32_DATA:
7709 /* This reloc is obselete, we do not need it so far. */
7712 case BFD_RELOC_NDS32_TPOFF:
7713 case BFD_RELOC_NDS32_TLS_LE_HI20:
7714 case BFD_RELOC_NDS32_TLS_LE_LO12:
7715 case BFD_RELOC_NDS32_TLS_LE_ADD:
7716 case BFD_RELOC_NDS32_TLS_LE_LS:
7717 case BFD_RELOC_NDS32_GOTTPOFF:
7718 case BFD_RELOC_NDS32_TLS_IE_HI20:
7719 case BFD_RELOC_NDS32_TLS_IE_LO12S2:
7720 case BFD_RELOC_NDS32_TLS_DESC_HI20:
7721 case BFD_RELOC_NDS32_TLS_DESC_LO12:
7722 case BFD_RELOC_NDS32_TLS_IE_LO12:
7723 case BFD_RELOC_NDS32_TLS_IEGP_HI20:
7724 case BFD_RELOC_NDS32_TLS_IEGP_LO12:
7725 case BFD_RELOC_NDS32_TLS_IEGP_LO12S2:
7726 S_SET_THREAD_LOCAL (fixP->fx_addsy);
7734 if (fixP->fx_addsy == (symbolS *) NULL)
7737 if (fixP->fx_subsy != (symbolS *) NULL)
7739 /* HOW DIFF RELOCATION WORKS.
7741 First of all, this relocation is used to calculate the distance
7742 between two symbols in the SAME section. It is used for jump-
7743 table, debug information, exception table, et al. Therefore,
7744 it is a unsigned positive value. It is NOT used for general-
7747 Consider this example, the distance between .LEND and .LBEGIN
7748 is stored at the address of foo.
7750 ---- >8 ---- >8 ---- >8 ---- >8 ----
7753 .word .LBEGIN - .LEND
7763 ---- 8< ---- 8< ---- 8< ---- 8< ----
7765 We use a single relocation entry for this expression.
7766 * The initial distance value is stored directly in that location
7767 specified by r_offset (i.e., foo in this example.)
7768 * The begin of the region, i.e., .LBEGIN, is specified by
7769 r_info/R_SYM and r_addend, e.g., .text + 0x32.
7770 * The end of region, i.e., .LEND, is represented by
7771 .LBEGIN + distance instead of .LEND, so we only need
7772 a single relocation entry instead of two.
7774 When an instruction is relaxed, we adjust the relocation entry
7775 depending on where the instruction locates. There are three
7776 cases, before, after and between the region.
7777 * between: Distance value is read from r_offset, adjusted and
7778 written back into r_offset.
7779 * before: Only r_addend is adjust.
7780 * after: We don't care about it.
7782 Hereby, there are some limitation.
7784 `(.LEND - 1) - .LBEGIN' and `(.LEND - .LBEGIN) - 1'
7785 are semantically different, and we cannot handle latter case
7788 The latter expression means subtracting 1 from the distance
7789 between .LEND and .LBEGIN. And the former expression means
7790 the distance between (.LEND - 1) and .LBEGIN.
7792 The nuance affects whether to adjust distance value when relax
7793 an instruction. In another words, whether the instruction
7794 locates in the region. Because we use a single relocation entry,
7795 there is no field left for .LEND and the subtrahend.
7797 Since GCC-4.5, GCC may produce debug information in such expression
7799 in order to describe register clobbering during an function-call.
7804 Check http://gcc.gnu.org/ml/gcc-patches/2009-06/msg01317.html
7807 value -= S_GET_VALUE (fixP->fx_subsy);
7809 fixP->fx_subsy = NULL;
7810 fixP->fx_offset -= value;
7812 switch (fixP->fx_r_type)
7815 fixP->fx_r_type = BFD_RELOC_NDS32_DIFF8;
7816 md_number_to_chars (where, value, 1);
7819 fixP->fx_r_type = BFD_RELOC_NDS32_DIFF16;
7820 md_number_to_chars (where, value, 2);
7823 fixP->fx_r_type = BFD_RELOC_NDS32_DIFF32;
7824 md_number_to_chars (where, value, 4);
7826 case BFD_RELOC_NDS32_DIFF_ULEB128:
7827 /* cvt_frag_to_fill () has called output_leb128 () for us. */
7830 as_bad_where (fixP->fx_file, fixP->fx_line,
7831 _("expression too complex"));
7835 else if (fixP->fx_done)
7837 /* We're finished with this fixup. Install it because
7838 bfd_install_relocation won't be called to do it. */
7839 switch (fixP->fx_r_type)
7842 md_number_to_chars (where, value, 1);
7845 md_number_to_chars (where, value, 2);
7848 md_number_to_chars (where, value, 4);
7851 md_number_to_chars (where, value, 8);
7854 as_bad_where (fixP->fx_file, fixP->fx_line,
7855 _("Internal error: Unknown fixup type %d (`%s')"),
7857 bfd_get_reloc_code_name (fixP->fx_r_type));
7863 /* Implement tc_gen_reloc. Generate ELF relocation for a fix-up. */
7866 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
7869 bfd_reloc_code_real_type code;
7871 reloc = XNEW (arelent);
7873 reloc->sym_ptr_ptr = XNEW (asymbol *);
7874 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
7875 reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
7877 code = fixP->fx_r_type;
7879 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
7880 if (reloc->howto == (reloc_howto_type *) NULL)
7882 as_bad_where (fixP->fx_file, fixP->fx_line,
7883 _("internal error: can't export reloc type %d (`%s')"),
7884 fixP->fx_r_type, bfd_get_reloc_code_name (code));
7888 /* Add relocation handling here. */
7890 switch (fixP->fx_r_type)
7893 /* In general, addend of a relocation is the offset to the
7894 associated symbol. */
7895 reloc->addend = fixP->fx_offset;
7898 case BFD_RELOC_NDS32_DATA:
7899 /* Prevent linker from optimizing data in text sections.
7900 For example, jump table. */
7901 reloc->addend = fixP->fx_size;
7908 static struct suffix_name suffix_table[] =
7910 {"GOTOFF", BFD_RELOC_NDS32_GOTOFF},
7911 {"GOT", BFD_RELOC_NDS32_GOT20},
7912 {"TPOFF", BFD_RELOC_NDS32_TPOFF},
7913 {"PLT", BFD_RELOC_NDS32_25_PLTREL},
7914 {"GOTTPOFF", BFD_RELOC_NDS32_GOTTPOFF},
7915 {"TLSDESC", BFD_RELOC_NDS32_TLS_DESC},
7918 /* Implement md_parse_name. */
7921 nds32_parse_name (char const *name, expressionS *exprP,
7922 enum expr_mode mode ATTRIBUTE_UNUSED,
7923 char *nextcharP ATTRIBUTE_UNUSED)
7927 exprP->X_op_symbol = NULL;
7928 exprP->X_md = BFD_RELOC_UNUSED;
7930 exprP->X_add_symbol = symbol_find_or_make (name);
7931 exprP->X_op = O_symbol;
7932 exprP->X_add_number = 0;
7934 /* Check the special name if a symbol. */
7935 segment = S_GET_SEGMENT (exprP->X_add_symbol);
7936 if ((segment != undefined_section) && (*nextcharP != '@'))
7939 if (strcmp (name, GOT_NAME) == 0 && *nextcharP != '@')
7941 /* Set for _GOT_OFFSET_TABLE_. */
7942 exprP->X_md = BFD_RELOC_NDS32_GOTPC20;
7944 else if (*nextcharP == '@')
7948 for (i = 0; i < ARRAY_SIZE (suffix_table); i++)
7950 next = input_line_pointer + 1 + strlen (suffix_table[i].suffix);
7951 if (strncasecmp (input_line_pointer + 1, suffix_table[i].suffix,
7952 strlen (suffix_table[i].suffix)) == 0
7953 && !is_part_of_name (*next))
7955 exprP->X_md = suffix_table[i].reloc;
7956 *input_line_pointer = *nextcharP;
7957 input_line_pointer = next;
7958 *nextcharP = *input_line_pointer;
7959 *input_line_pointer = '\0';
7968 /* Implement tc_regname_to_dw2regnum. */
7971 tc_nds32_regname_to_dw2regnum (char *regname)
7973 struct nds32_keyword *sym = hash_find (nds32_gprs_hash, regname);
7982 tc_nds32_frame_initial_instructions (void)
7985 /* Default cfa is register-31/sp. */
7986 cfi_add_CFA_def_cfa (31, 0);