1 /* tc-nds32.c -- Assemble for the nds32
2 Copyright (C) 2012-2016 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"
39 /* GAS definitions. */
41 /* Characters which start a comment. */
42 const char comment_chars[] = "!";
43 /* Characters which start a comment when they appear at the start of a line. */
44 const char line_comment_chars[] = "#!";
45 /* Characters which separate lines (null and newline are by default). */
46 const char line_separator_chars[] = ";";
47 /* Characters which may be used as the exponent character
48 in a floating point number. */
49 const char EXP_CHARS[] = "eE";
50 /* Characters which may be used to indicate a floating point constant. */
51 const char FLT_CHARS[] = "dDfF";
53 static int enable_16bit = 1;
54 /* Save for md_assemble to distinguish if this instruction is
55 expanded from the pseudo instruction. */
56 static bfd_boolean pseudo_opcode = FALSE;
57 static struct nds32_relocs_pattern *relocs_list = NULL;
58 /* Save instruction relation to inserting relaxation relocation. */
59 struct nds32_relocs_pattern
66 struct nds32_opcode *opcode;
68 struct nds32_relocs_pattern *next;
71 /* Suffix name and relocation. */
75 short unsigned int reloc;
78 static int vec_size = 0;
79 /* If the assembly code is generated by compiler, it is supposed to have
80 ".flag verbatim" at beginning of the content. We have
81 'nds32_flag' to parse it and set this field to be non-zero. */
82 static int verbatim = 0;
83 static struct hash_control *nds32_gprs_hash;
84 static struct hash_control *nds32_hint_hash;
85 #define TLS_REG "$r27"
86 #define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
88 /* Generate relocation for relax or not, and the default is true. */
89 static int enable_relax_relocs = 1;
90 /* The value will be used in RELAX_ENTRY. */
91 static int enable_relax_ex9 = 0;
92 /* The value will be used in RELAX_ENTRY. */
93 static int enable_relax_ifc = 0;
94 /* Save option -O for perfomance. */
95 static int optimize = 0;
96 /* Save option -Os for code size. */
97 static int optimize_for_space = 0;
98 /* Flag to save label exist. */
99 static int label_exist = 0;
100 /* Flag to save state in omit_fp region. */
101 static int in_omit_fp = 0;
102 extern struct nds32_keyword keyword_gpr[];
103 /* Tag there is relax relocation having to link. */
104 static bfd_boolean relaxing = FALSE;
106 static struct hash_control *nds32_relax_info_hash;
107 static relax_info_t relax_table[] =
111 BR_RANGE_S16M, /* br_range */
112 {{0, 0, 0, FALSE}}, /* cond_field */
115 INSN_JAL /* jal label */
116 }, /* BR_RANGE_S256 */
118 INSN_JAL /* jal label */
119 }, /* BR_RANGE_S16K */
121 INSN_JAL /* jal label */
122 }, /* BR_RANGE_S64K */
124 INSN_JAL /* jal label */
125 }, /* BR_RANGE_S16M */
127 INSN_SETHI_TA, /* sethi $ta, label */
128 INSN_ORI_TA, /* ori $ta, $ta, label */
130 }, /* BR_RANGE_U4G */
131 }, /* relax_code_seq */
133 {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */
134 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */
135 {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */
136 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */
137 {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */
138 }, /* relax_code_condition */
139 {4, 4, 4, 4, 12}, /* relax_code_size */
140 {4, 4, 4, 4, 4}, /* relax_branch_isize */
143 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
145 }, /* BR_RANGE_S256 */
147 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
149 }, /* BR_RANGE_S16K */
151 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
153 }, /* BR_RANGE_S64K */
155 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
157 }, /* BR_RANGE_S16M */
159 {0, 4, 0, BFD_RELOC_NDS32_HI20},
160 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL4},
161 {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI},
162 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
163 {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
164 {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
165 {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
171 "bltzal", /* opcode */
172 BR_RANGE_S64K, /* br_range */
174 {0, 20, 0x1F, FALSE},
179 INSN_BLTZAL /* bltzal $rt, label */
180 }, /* BR_RANGE_S256 */
182 INSN_BLTZAL /* bltzal $rt, label */
183 }, /* BR_RANGE_S16K */
185 INSN_BLTZAL /* bltzal $rt, label */
186 }, /* BR_RANGE_S64K */
188 INSN_BGEZ, /* bgez $rt, $1 */
189 INSN_JAL /* jal label */
190 }, /* BR_RANGE_S16M */
192 INSN_BGEZ, /* bgez $rt, $1 */
193 INSN_SETHI_TA, /* sethi $ta, label */
194 INSN_ORI_TA, /* ori $ta, $ta, label */
195 INSN_JRAL_TA /* jral $ta */
197 }, /* relax_code_seq */
200 {0, 20, 0x1F, FALSE},
202 }, /* BR_RANGE_S256 */
204 {0, 20, 0x1F, FALSE},
206 }, /* BR_RANGE_S16K */
208 {0, 20, 0x1F, FALSE},
210 }, /* BR_RANGE_S64K */
212 {0, 20, 0x1F, FALSE},
214 }, /* BR_RANGE_S16M */
216 {0, 20, 0x1F, FALSE},
219 }, /* relax_code_condition */
220 {4, 4, 4, 8, 16}, /* relax_code_size */
221 {4, 4, 4, 4, 4}, /* relax_branch_isize */
224 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
226 }, /* BR_RANGE_S256 */
228 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
230 }, /* BR_RANGE_S16K */
232 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
234 }, /* BR_RANGE_S64K */
236 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
237 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL5},
238 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
240 }, /* BR_RANGE_S16M */
242 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
243 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL6},
244 {4, 4, 0, BFD_RELOC_NDS32_HI20},
245 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
246 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
247 {8, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
248 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
249 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
250 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
256 "bgezal", /* opcode */
257 BR_RANGE_S64K, /* br_range */
259 {0, 20, 0x1F, FALSE},
264 INSN_BGEZAL /* bgezal $rt, label */
265 }, /* BR_RANGE_S256 */
267 INSN_BGEZAL /* bgezal $rt, label */
268 }, /* BR_RANGE_S16K */
270 INSN_BGEZAL /* bgezal $rt, label */
271 }, /* BR_RANGE_S64K */
273 INSN_BLTZ, /* bltz $rt, $1 */
274 INSN_JAL /* jal label */
275 }, /* BR_RANGE_S16M */
277 INSN_BLTZ, /* bltz $rt, $1 */
278 INSN_SETHI_TA, /* sethi $ta, label */
279 INSN_ORI_TA, /* ori $ta, $ta, label */
280 INSN_JRAL_TA /* jral $ta */
282 }, /* relax_code_seq */
285 {0, 20, 0x1F, FALSE},
287 }, /* BR_RANGE_S256 */
289 {0, 20, 0x1F, FALSE},
291 }, /* BR_RANGE_S16K */
293 {0, 20, 0x1F, FALSE},
295 }, /* BR_RANGE_S64K */
297 {0, 20, 0x1F, FALSE},
299 }, /* BR_RANGE_S16M */
301 {0, 20, 0x1F, FALSE},
304 }, /* relax_code_condition */
305 {4, 4, 4, 8, 16}, /* relax_code_size */
306 {4, 4, 4, 4, 4}, /* relax_branch_isize */
309 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
311 }, /* BR_RANGE_S256 */
313 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
315 }, /* BR_RANGE_S16K */
317 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
319 }, /* BR_RANGE_S64K */
321 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
322 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL5},
323 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
325 }, /* BR_RANGE_S16M */
327 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
328 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL6},
329 {4, 4, 0, BFD_RELOC_NDS32_HI20},
330 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
331 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
332 {8, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
333 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
334 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
335 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
342 BR_RANGE_S16M, /* br_range */
343 {{0, 0, 0, FALSE}}, /* cond_field */
346 (INSN_J8 << 16) /* j8 label */
347 }, /* BR_RANGE_S256 */
350 }, /* BR_RANGE_S16K */
353 }, /* BR_RANGE_S64K */
356 }, /* BR_RANGE_S16M */
358 INSN_SETHI_TA, /* sethi $ta, label */
359 INSN_ORI_TA, /* ori $ta, $ta, label */
360 INSN_JR_TA /* jr $ta */
361 }, /* BR_RANGE_U4G */
362 }, /* relax_code_seq */
364 {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */
365 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */
366 {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */
367 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */
368 {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */
369 }, /* relax_code_condition */
370 {2, 4, 4, 4, 12}, /* relax_code_size */
371 {2, 4, 4, 4, 4}, /* relax_branch_isize */
374 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
376 }, /* BR_RANGE_S256 */
378 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
380 }, /* BR_RANGE_S16K */
382 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
384 }, /* BR_RANGE_S64K */
386 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
388 }, /* BR_RANGE_S16M */
390 {0, 4, 0, BFD_RELOC_NDS32_HI20},
391 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP4},
392 {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI},
393 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
394 {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
395 {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
396 {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
403 BR_RANGE_S256, /* br_range */
404 {{0, 0, 0, FALSE}}, /* cond_field */
407 (INSN_J8 << 16) /* j8 label */
408 }, /* BR_RANGE_S256 */
411 }, /* BR_RANGE_S16K */
414 }, /* BR_RANGE_S64K */
417 }, /* BR_RANGE_S16M */
419 INSN_SETHI_TA, /* sethi $ta, label */
420 INSN_ORI_TA, /* ori $ta, $ta, label */
421 INSN_JR_TA /* jr $ta */
422 }, /* BR_RANGE_U4G */
423 }, /* relax_code_seq */
425 {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */
426 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */
427 {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */
428 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */
429 {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */
430 }, /* relax_code_condition */
431 {2, 4, 4, 4, 12}, /* relax_code_size */
432 {2, 4, 4, 4, 4}, /* relax_branch_isize */
435 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
437 }, /* BR_RANGE_S256 */
439 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
441 }, /* BR_RANGE_S16K */
443 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
445 }, /* BR_RANGE_S64K */
447 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
449 }, /* BR_RANGE_S16M */
451 {0, 4, 0, BFD_RELOC_NDS32_HI20},
452 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP4},
453 {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI},
454 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
455 {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
456 {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
457 {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
464 BR_RANGE_S64K, /* br_range */
466 {0, 20, 0x1F, FALSE},
471 INSN_BEQZ /* beqz $rt, label */
472 }, /* BR_RANGE_S256 */
474 INSN_BEQZ /* beqz $rt, label */
475 }, /* BR_RANGE_S16K */
477 INSN_BEQZ /* beqz $rt, label */
478 }, /* BR_RANGE_S64K */
480 INSN_BNEZ, /* bnez $rt, $1 */
482 }, /* BR_RANGE_S16M */
484 INSN_BNEZ, /* bnez $rt, $1 */
485 INSN_SETHI_TA, /* sethi $ta, label */
486 INSN_ORI_TA, /* ori $ta, $ta, label */
487 INSN_JR_TA /* jr $ta */
489 }, /* relax_code_seq */
492 {0, 20, 0x1F, FALSE},
494 }, /* BR_RANGE_S256 */
496 {0, 20, 0x1F, FALSE},
498 }, /* BR_RANGE_S16K */
500 {0, 20, 0x1F, FALSE},
502 }, /* BR_RANGE_S64K */
504 {0, 20, 0x1F, FALSE},
506 }, /* BR_RANGE_S16M */
508 {0, 20, 0x1F, FALSE},
511 }, /* relax_code_condition */
512 {4, 4, 4, 8, 16}, /* relax_code_size */
513 {4, 4, 4, 4, 4}, /* relax_branch_isize */
516 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
517 {0, 4, NDS32_INSN16 , BFD_RELOC_NDS32_INSN16},
519 }, /* BR_RANGE_S256 */
521 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
523 }, /* BR_RANGE_S16K */
525 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
527 }, /* BR_RANGE_S64K */
529 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
530 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
531 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
532 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
533 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
535 }, /* BR_RANGE_S16M */
537 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
538 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
539 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
540 {4, 4, 0, BFD_RELOC_NDS32_HI20},
541 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
542 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
543 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
544 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
545 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
546 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
553 BR_RANGE_S64K, /* br_range */
555 {0, 20, 0x1F, FALSE},
560 INSN_BGEZ /* bgez $rt, label */
561 }, /* BR_RANGE_S256 */
563 INSN_BGEZ /* bgez $rt, label */
564 }, /* BR_RANGE_S16K */
566 INSN_BGEZ /* bgez $rt, label */
567 }, /* BR_RANGE_S64K */
569 INSN_BLTZ, /* bltz $rt, $1 */
571 }, /* BR_RANGE_S16M */
573 INSN_BLTZ, /* bltz $rt, $1 */
574 INSN_SETHI_TA, /* sethi $ta, label */
575 INSN_ORI_TA, /* ori $ta, $ta, label */
576 INSN_JR_TA /* jr $ta */
578 }, /* relax_code_seq */
581 {0, 20, 0x1F, FALSE},
583 }, /* BR_RANGE_S256 */
585 {0, 20, 0x1F, FALSE},
587 }, /* BR_RANGE_S16K */
589 {0, 20, 0x1F, FALSE},
591 }, /* BR_RANGE_S64K */
593 {0, 20, 0x1F, FALSE},
595 }, /* BR_RANGE_S16M */
597 {0, 20, 0x1F, FALSE},
600 }, /* relax_code_condition */
601 {4, 4, 4, 8, 16}, /* relax_code_size */
602 {4, 4, 4, 4, 4}, /* relax_branch_isize */
605 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
607 }, /* BR_RANGE_S256 */
609 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
611 }, /* BR_RANGE_S16K */
613 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
615 }, /* BR_RANGE_S64K */
617 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
618 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
619 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
621 }, /* BR_RANGE_S16M */
623 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
624 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
625 {4, 4, 0, BFD_RELOC_NDS32_HI20},
626 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
627 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
628 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
629 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
630 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
631 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
638 BR_RANGE_S64K, /* br_range */
640 {0, 20, 0x1F, FALSE},
645 INSN_BNEZ /* bnez $rt, label */
646 }, /* BR_RANGE_S256 */
648 INSN_BNEZ /* bnez $rt, label */
649 }, /* BR_RANGE_S16K */
651 INSN_BNEZ /* bnez $rt, label */
652 }, /* BR_RANGE_S64K */
654 INSN_BEQZ, /* beqz $rt, $1 */
656 }, /* BR_RANGE_S16M */
658 INSN_BEQZ, /* beqz $rt, $1 */
659 INSN_SETHI_TA, /* sethi $ta, label */
660 INSN_ORI_TA, /* ori $ta, $ta, label */
661 INSN_JR_TA /* jr $ta */
663 }, /* relax_code_seq */
666 {0, 20, 0x1F, FALSE},
668 }, /* BR_RANGE_S256 */
670 {0, 20, 0x1F, FALSE},
672 }, /* BR_RANGE_S16K */
674 {0, 20, 0x1F, FALSE},
676 }, /* BR_RANGE_S64K */
678 {0, 20, 0x1F, FALSE},
680 }, /* BR_RANGE_S16M */
682 {0, 20, 0x1F, FALSE},
685 }, /* relax_code_condition */
686 {4, 4, 4, 8, 16}, /* relax_code_size */
687 {4, 4, 4, 4, 4}, /* relax_branch_isize */
690 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
691 {0, 4, NDS32_INSN16 , BFD_RELOC_NDS32_INSN16},
693 }, /* BR_RANGE_S256 */
695 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
697 }, /* BR_RANGE_S16K */
699 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
701 }, /* BR_RANGE_S64K */
703 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
704 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
705 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
706 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
707 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
709 }, /* BR_RANGE_S16M */
711 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
712 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
713 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
714 {4, 4, 0, BFD_RELOC_NDS32_HI20},
715 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
716 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
717 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
718 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
719 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
720 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
727 BR_RANGE_S64K, /* br_range */
729 {0, 20, 0x1F, FALSE},
734 INSN_BGTZ /* bgtz $rt, label */
735 }, /* BR_RANGE_S256 */
737 INSN_BGTZ /* bgtz $rt, label */
738 }, /* BR_RANGE_S16K */
740 INSN_BGTZ /* bgtz $rt, label */
741 }, /* BR_RANGE_S64K */
743 INSN_BLEZ, /* blez $rt, $1 */
745 }, /* BR_RANGE_S16M */
747 INSN_BLEZ, /* blez $rt, $1 */
748 INSN_SETHI_TA, /* sethi $ta, label */
749 INSN_ORI_TA, /* ori $ta, $ta, label */
750 INSN_JR_TA /* jr $ta */
752 }, /* relax_code_seq */
755 {0, 20, 0x1F, FALSE},
757 }, /* BR_RANGE_S256 */
759 {0, 20, 0x1F, FALSE},
761 }, /* BR_RANGE_S16K */
763 {0, 20, 0x1F, FALSE},
765 }, /* BR_RANGE_S64K */
767 {0, 20, 0x1F, FALSE},
769 }, /* BR_RANGE_S16M */
771 {0, 20, 0x1F, FALSE},
774 }, /* relax_code_condition */
775 {4, 4, 4, 8, 16}, /* relax_code_size */
776 {4, 4, 4, 4, 4}, /* relax_branch_isize */
779 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
781 }, /* BR_RANGE_S256 */
783 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
785 }, /* BR_RANGE_S16K */
787 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
789 }, /* BR_RANGE_S64K */
791 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
792 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
793 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
795 }, /* BR_RANGE_S16M */
797 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
798 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
799 {4, 4, 0, BFD_RELOC_NDS32_HI20},
800 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
801 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
802 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
803 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
804 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
805 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
812 BR_RANGE_S64K, /* br_range */
814 {0, 20, 0x1F, FALSE},
819 INSN_BLEZ /* blez $rt, label */
820 }, /* BR_RANGE_S256 */
822 INSN_BLEZ /* blez $rt, label */
823 }, /* BR_RANGE_S16K */
825 INSN_BLEZ /* blez $rt, label */
826 }, /* BR_RANGE_S64K */
828 INSN_BGTZ, /* bgtz $rt, $1 */
830 }, /* BR_RANGE_S16M */
832 INSN_BGTZ, /* bgtz $rt, $1 */
833 INSN_SETHI_TA, /* sethi $ta, label */
834 INSN_ORI_TA, /* ori $ta, $ta, label */
835 INSN_JR_TA /* jr $ta */
837 }, /* relax_code_seq */
840 {0, 20, 0x1F, FALSE},
842 }, /* BR_RANGE_S256 */
844 {0, 20, 0x1F, FALSE},
846 }, /* BR_RANGE_S16K */
848 {0, 20, 0x1F, FALSE},
850 }, /* BR_RANGE_S64K */
852 {0, 20, 0x1F, FALSE},
854 }, /* BR_RANGE_S16M */
856 {0, 20, 0x1F, FALSE},
859 }, /* relax_code_condition */
860 {4, 4, 4, 8, 16}, /* relax_code_size */
861 {4, 4, 4, 4, 4}, /* relax_branch_isize */
864 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
866 }, /* BR_RANGE_S256 */
868 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
870 }, /* BR_RANGE_S16K */
872 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
874 }, /* BR_RANGE_S64K */
876 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
877 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
878 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
880 }, /* BR_RANGE_S16M */
882 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
883 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
884 {4, 4, 0, BFD_RELOC_NDS32_HI20},
885 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
886 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
887 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
888 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
889 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
890 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
897 BR_RANGE_S64K, /* br_range */
899 {0, 20, 0x1F, FALSE},
904 INSN_BLTZ /* bltz $rt, label */
905 }, /* BR_RANGE_S256 */
907 INSN_BLTZ /* bltz $rt, label */
908 }, /* BR_RANGE_S16K */
910 INSN_BLTZ /* bltz $rt, label */
911 }, /* BR_RANGE_S64K */
913 INSN_BGEZ, /* bgez $rt, $1 */
915 }, /* BR_RANGE_S16M */
917 INSN_BGEZ, /* bgez $rt, $1 */
918 INSN_SETHI_TA, /* sethi $ta, label */
919 INSN_ORI_TA, /* ori $ta, $ta, label */
920 INSN_JR_TA /* jr $ta */
922 }, /* relax_code_seq */
925 {0, 20, 0x1F, FALSE},
927 }, /* BR_RANGE_S256 */
929 {0, 20, 0x1F, FALSE},
931 }, /* BR_RANGE_S16K */
933 {0, 20, 0x1F, FALSE},
935 }, /* BR_RANGE_S64K */
937 {0, 20, 0x1F, FALSE},
939 }, /* BR_RANGE_S16M */
941 {0, 20, 0x1F, FALSE},
944 }, /* relax_code_condition */
945 {4, 4, 4, 8, 16}, /* relax_code_size */
946 {4, 4, 4, 4, 4}, /* relax_branch_isize */
949 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
951 }, /* BR_RANGE_S256 */
953 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
955 }, /* BR_RANGE_S16K */
957 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
959 }, /* BR_RANGE_S64K */
961 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
962 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
963 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
965 }, /* BR_RANGE_S16M */
967 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
968 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
969 {4, 4, 0, BFD_RELOC_NDS32_HI20},
970 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
971 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
972 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
973 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
974 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
975 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
982 BR_RANGE_S16K, /* br_range */
984 {0, 20, 0x1F, FALSE},
985 {0, 15, 0x1F, FALSE},
990 INSN_BEQ /* beq $rt, $ra, label */
991 }, /* BR_RANGE_S256 */
993 INSN_BEQ /* beq $rt, $ra, label */
994 }, /* BR_RANGE_S16K */
996 INSN_BNE, /* bne $rt, $ra, $1 */
998 }, /* BR_RANGE_S64K */
1000 INSN_BNE, /* bne $rt, $ra, $1 */
1001 INSN_J /* j label */
1002 }, /* BR_RANGE_S16M */
1004 INSN_BNE, /* bne $rt, $ra, $1 */
1005 INSN_SETHI_TA, /* sethi $ta, label */
1006 INSN_ORI_TA, /* ori $ta, $ta, label */
1007 INSN_JR_TA /* jr $ta */
1008 } /* BR_RANGE_U4G */
1009 }, /* relax_code_seq */
1012 {0, 20, 0x1F, FALSE},
1013 {0, 15, 0x1F, FALSE},
1015 }, /* BR_RANGE_S256 */
1017 {0, 20, 0x1F, FALSE},
1018 {0, 15, 0x1F, FALSE},
1020 }, /* BR_RANGE_S16K */
1022 {0, 20, 0x1F, FALSE},
1023 {0, 15, 0x1F, FALSE},
1025 }, /* BR_RANGE_S64K */
1027 {0, 20, 0x1F, FALSE},
1028 {0, 15, 0x1F, FALSE},
1030 }, /* BR_RANGE_S16M */
1032 {0, 20, 0x1F, FALSE},
1033 {0, 15, 0x1F, FALSE},
1035 } /* BR_RANGE_U4G */
1036 }, /* relax_code_condition */
1037 {4, 4, 8, 8, 16}, /* relax_code_size */
1038 {4, 4, 4, 4, 4}, /* relax_branch_isize */
1041 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1042 {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
1044 }, /* BR_RANGE_S256 */
1046 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1048 }, /* BR_RANGE_S16K */
1050 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1051 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1052 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1053 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1054 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1056 }, /* BR_RANGE_S64K */
1058 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1059 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1060 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1061 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1062 {4, 4, NDS32_ABS, BFD_RELOC_NDS32_EMPTY},
1063 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1065 }, /* BR_RANGE_S16M */
1067 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1068 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1069 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1070 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1071 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1072 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1073 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1074 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1075 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1076 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1078 } /* BR_RANGE_U4G */
1083 BR_RANGE_S16K, /* br_range */
1085 {0, 20, 0x1F, FALSE},
1086 {0, 15, 0x1F, FALSE},
1091 INSN_BNE /* bne $rt, $ra, label */
1092 }, /* BR_RANGE_S256 */
1094 INSN_BNE /* bne $rt, $ra, label */
1095 }, /* BR_RANGE_S16K */
1097 INSN_BEQ, /* beq $rt, $ra, $1 */
1098 INSN_J /* j label */
1099 }, /* BR_RANGE_S64K */
1101 INSN_BEQ, /* beq $rt, $ra, $1 */
1102 INSN_J /* j label */
1103 }, /* BR_RANGE_S16M */
1105 INSN_BEQ, /* beq $rt, $ra, $1 */
1106 INSN_SETHI_TA, /* sethi $ta, label */
1107 INSN_ORI_TA, /* ori $ta, $ta, label */
1108 INSN_JR_TA /* jr $ta */
1109 } /* BR_RANGE_U4G */
1110 }, /* relax_code_seq */
1113 {0, 20, 0x1F, FALSE},
1114 {0, 15, 0x1F, FALSE},
1116 }, /* BR_RANGE_S256 */
1118 {0, 20, 0x1F, FALSE},
1119 {0, 15, 0x1F, FALSE},
1121 }, /* BR_RANGE_S16K */
1123 {0, 20, 0x1F, FALSE},
1124 {0, 15, 0x1F, FALSE},
1126 }, /* BR_RANGE_S64K */
1128 {0, 20, 0x1F, FALSE},
1129 {0, 15, 0x1F, FALSE},
1131 }, /* BR_RANGE_S16M */
1133 {0, 20, 0x1F, FALSE},
1134 {0, 15, 0x1F, FALSE},
1136 } /* BR_RANGE_U4G */
1137 }, /* relax_code_condition */
1138 {4, 4, 8, 8, 16}, /* relax_code_size */
1139 {4, 4, 4, 4, 4}, /* relax_branch_isize */
1142 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1143 {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
1145 }, /* BR_RANGE_S256 */
1147 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1149 }, /* BR_RANGE_S16K */
1151 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1152 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1153 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1154 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1155 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1157 }, /* BR_RANGE_S64K */
1159 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1160 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1161 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1162 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1163 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1165 }, /* BR_RANGE_S16M */
1167 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1168 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1169 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1170 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1171 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1172 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1173 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1174 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1175 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1176 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1178 } /* BR_RANGE_U4G */
1182 "beqz38", /* opcode */
1183 BR_RANGE_S256, /* br_range */
1190 INSN_BEQZ38 << 16 /* beqz $rt, label */
1191 }, /* BR_RANGE_S256 */
1193 INSN_BEQZ /* beqz $rt, label */
1194 }, /* BR_RANGE_S16K */
1196 INSN_BEQZ /* beqz $rt, label */
1197 }, /* BR_RANGE_S64K */
1199 INSN_BNEZ, /* bnez $rt, $1 */
1200 INSN_J /* j label */
1201 }, /* BR_RANGE_S16M */
1203 INSN_BNEZ, /* bnez $rt, $1 */
1204 INSN_SETHI_TA, /* sethi $ta, label */
1205 INSN_ORI_TA, /* ori $ta, $ta, label */
1206 INSN_JR_TA /* jr $ta */
1207 } /* BR_RANGE_U4G */
1208 }, /* relax_code_seq */
1213 }, /* BR_RANGE_S256 */
1215 {0, 20, 0x1F, FALSE},
1217 }, /* BR_RANGE_S16K */
1219 {0, 20, 0x1F, FALSE},
1221 }, /* BR_RANGE_S64K */
1223 {0, 20, 0x1F, FALSE},
1225 }, /* BR_RANGE_S16M */
1227 {0, 20, 0x1F, FALSE},
1229 } /* BR_RANGE_U4G */
1230 }, /* relax_code_condition */
1231 {2, 4, 4, 8, 16}, /* relax_code_size */
1232 {2, 4, 4, 4, 4}, /* relax_branch_isize */
1235 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
1237 }, /* BR_RANGE_S256 */
1239 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1241 }, /* BR_RANGE_S16K */
1243 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1245 }, /* BR_RANGE_S64K */
1247 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1248 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1249 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1250 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1251 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1253 }, /* BR_RANGE_S16M */
1255 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1256 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1257 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1258 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1259 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1260 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1261 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1262 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1263 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1264 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1266 } /* BR_RANGE_U4G */
1270 "bnez38", /* opcode */
1271 BR_RANGE_S256, /* br_range */
1278 INSN_BNEZ38 << 16 /* bnez $rt, label */
1279 }, /* BR_RANGE_S256 */
1281 INSN_BNEZ /* bnez $rt, label */
1282 }, /* BR_RANGE_S16K */
1284 INSN_BNEZ /* bnez $rt, label */
1285 }, /* BR_RANGE_S64K */
1287 INSN_BEQZ, /* beqz $rt, $1 */
1288 INSN_J /* j label */
1289 }, /* BR_RANGE_S16M */
1291 INSN_BEQZ, /* beqz $rt, $1 */
1292 INSN_SETHI_TA, /* sethi $ta, label */
1293 INSN_ORI_TA, /* ori $ta, $ta, label */
1294 INSN_JR_TA /* jr $ta */
1295 } /* BR_RANGE_U4G */
1296 }, /* relax_code_seq */
1301 }, /* BR_RANGE_S256 */
1303 {0, 20, 0x1F, FALSE},
1305 }, /* BR_RANGE_S16K */
1307 {0, 20, 0x1F, FALSE},
1309 }, /* BR_RANGE_S64K */
1311 {0, 20, 0x1F, FALSE},
1313 }, /* BR_RANGE_S16M */
1315 {0, 20, 0x1F, FALSE},
1317 } /* BR_RANGE_U4G */
1318 }, /* relax_code_condition */
1319 {2, 4, 4, 8, 16}, /* relax_code_size */
1320 {2, 4, 4, 4, 4}, /* relax_branch_isize */
1323 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
1325 }, /* BR_RANGE_S256 */
1327 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1329 }, /* BR_RANGE_S16K */
1331 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1333 }, /* BR_RANGE_S64K */
1335 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1336 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1337 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1338 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1339 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1341 }, /* BR_RANGE_S16M */
1343 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1344 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1345 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1346 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1347 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1348 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1349 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1350 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1351 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1352 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1354 } /* BR_RANGE_U4G */
1358 "beqzs8", /* opcode */
1359 BR_RANGE_S256, /* br_range */
1360 {{0, 0, 0, FALSE}}, /* cond_field */
1363 INSN_BEQZS8 << 16 /* beqz $r15, label */
1364 }, /* BR_RANGE_S256 */
1366 INSN_BEQZ_TA /* bnez $rt, label */
1367 }, /* BR_RANGE_S16K */
1369 INSN_BEQZ_TA /* bnez $rt, label */
1370 }, /* BR_RANGE_S64K */
1372 INSN_BNEZ_TA, /* bnez $r15, $1 */
1373 INSN_J /* j label */
1374 }, /* BR_RANGE_S16M */
1376 INSN_BNEZ_TA, /* bnez $r15, $1 */
1377 INSN_SETHI_TA, /* sethi $ta, label */
1378 INSN_ORI_TA, /* ori $ta, $ta, label */
1379 INSN_JR_TA /* jr $ta */
1380 } /* BR_RANGE_U4G */
1381 }, /* relax_code_seq */
1383 {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */
1384 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */
1385 {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */
1386 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */
1387 {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */
1388 }, /* relax_code_condition */
1389 {2, 4, 4, 8, 16}, /* relax_code_size */
1390 {2, 4, 4, 4, 4}, /* relax_branch_isize */
1393 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
1395 }, /* BR_RANGE_S256 */
1397 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1399 }, /* BR_RANGE_S16K */
1401 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1403 }, /* BR_RANGE_S64K */
1405 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1406 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1407 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1408 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1409 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1411 }, /* BR_RANGE_S16M */
1413 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1414 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1415 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1416 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1417 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1418 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1419 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1420 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1421 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1422 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1424 } /* BR_RANGE_U4G */
1428 "bnezs8", /* opcode */
1429 BR_RANGE_S256, /* br_range */
1430 {{0, 0, 0, FALSE}}, /* cond_field */
1433 INSN_BNEZS8 << 16 /* bnez $r15, label */
1434 }, /* BR_RANGE_S256 */
1436 INSN_BNEZ_TA /* bnez $r15, label */
1437 }, /* BR_RANGE_S16K */
1439 INSN_BNEZ_TA /* bnez $r15, label */
1440 }, /* BR_RANGE_S64K */
1442 INSN_BEQZ_TA, /* beqz $r15, $1 */
1443 INSN_J /* j label */
1444 }, /* BR_RANGE_S16M */
1446 INSN_BEQZ_TA, /* beqz $r15, $1 */
1447 INSN_SETHI_TA, /* sethi $ta, label */
1448 INSN_ORI_TA, /* ori $ta, $ta, label */
1449 INSN_JR_TA /* jr $ta */
1450 } /* BR_RANGE_U4G */
1451 }, /* relax_code_seq */
1453 {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */
1454 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */
1455 {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */
1456 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */
1457 {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */
1458 }, /* relax_code_condition */
1459 {2, 4, 4, 8, 16}, /* relax_code_size */
1460 {2, 4, 4, 4, 4}, /* relax_branch_isize */
1463 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
1465 }, /* BR_RANGE_S256 */
1467 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1469 }, /* BR_RANGE_S16K */
1471 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1473 }, /* BR_RANGE_S64K */
1475 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1476 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1477 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1478 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1479 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1481 }, /* BR_RANGE_S16M */
1483 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1484 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1485 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1486 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1487 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1488 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1489 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1490 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1491 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1492 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1494 } /* BR_RANGE_U4G */
1498 "bnes38", /* opcode */
1499 BR_RANGE_S256, /* br_range */
1506 INSN_BNES38 << 16 /* bne $rt, $R5, label */
1507 }, /* BR_RANGE_S256 */
1509 INSN_BNE_R5 /* bne $rt, $R5, label */
1510 }, /* BR_RANGE_S16K */
1512 INSN_BEQ_R5, /* beq $rt, $R5, $1 */
1513 INSN_J /* j label */
1514 }, /* BR_RANGE_S64K */
1516 INSN_BEQ_R5, /* beq $rt, $R5, $1 */
1517 INSN_J /* j label */
1518 }, /* BR_RANGE_S16M */
1520 INSN_BEQ_R5, /* beq $rt, $R5, $1 */
1521 INSN_SETHI_TA, /* sethi $ta, label */
1522 INSN_ORI_TA, /* ori $ta, $ta, label */
1523 INSN_JR_TA /* jr $ta */
1524 } /* BR_RANGE_U4G */
1525 }, /* relax_code_seq */
1530 }, /* BR_RANGE_S256 */
1532 {0, 20, 0x1F, FALSE},
1534 }, /* BR_RANGE_S16K */
1536 {0, 20, 0x1F, FALSE},
1538 }, /* BR_RANGE_S64K */
1540 {0, 20, 0x1F, FALSE},
1542 }, /* BR_RANGE_S16M */
1544 {0, 20, 0x1F, FALSE},
1546 } /* BR_RANGE_U4G */
1547 }, /* relax_code_condition */
1548 {2, 4, 8, 8, 16}, /* relax_code_size */
1549 {2, 4, 4, 4, 4}, /* relax_branch_isize */
1552 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
1554 }, /* BR_RANGE_S256 */
1556 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1558 }, /* BR_RANGE_S16K */
1560 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1561 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1562 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1563 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1564 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1566 }, /* BR_RANGE_S64K */
1568 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1569 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1570 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1571 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1572 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1574 }, /* BR_RANGE_S16M */
1576 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1577 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1578 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1579 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1580 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1581 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1582 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1583 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1584 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1585 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1587 } /* BR_RANGE_U4G */
1591 "beqs38", /* opcode */
1592 BR_RANGE_S256, /* br_range */
1599 INSN_BEQS38 << 16 /* beq $rt, $R5, label */
1600 }, /* BR_RANGE_S256 */
1602 INSN_BEQ_R5 /* beq $rt, $R5, label */
1603 }, /* BR_RANGE_S16K */
1605 INSN_BNE_R5, /* bne $rt, $R5, $1 */
1606 INSN_J /* j label */
1607 }, /* BR_RANGE_S64K */
1609 INSN_BNE_R5, /* bne $rt, $R5, $1 */
1610 INSN_J /* j label */
1611 }, /* BR_RANGE_S16M */
1613 INSN_BNE_R5, /* bne $rt, $R5, $1 */
1614 INSN_SETHI_TA, /* sethi $ta, label */
1615 INSN_ORI_TA, /* ori $ta, $ta, label */
1616 INSN_JR_TA /* jr $ta */
1617 } /* BR_RANGE_U4G */
1618 }, /* relax_code_seq */
1623 }, /* BR_RANGE_S256 */
1625 {0, 20, 0x1F, FALSE},
1627 }, /* BR_RANGE_S16K */
1629 {0, 20, 0x1F, FALSE},
1631 }, /* BR_RANGE_S64K */
1633 {0, 20, 0x1F, FALSE},
1635 }, /* BR_RANGE_S16M */
1637 {0, 20, 0x1F, FALSE},
1639 } /* BR_RANGE_U4G */
1640 }, /* relax_code_condition */
1641 {2, 4, 8, 8, 16}, /* relax_code_size */
1642 {2, 4, 4, 4, 4}, /* relax_branch_isize */
1645 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
1647 }, /* BR_RANGE_S256 */
1649 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1651 }, /* BR_RANGE_S16K */
1653 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1654 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1655 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1656 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1657 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1659 }, /* BR_RANGE_S64K */
1661 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1662 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1663 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1664 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1665 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1667 }, /* BR_RANGE_S16M */
1669 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1670 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1671 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1672 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1673 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1674 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1675 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1676 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1677 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1678 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1680 } /* BR_RANGE_U4G */
1684 "beqc", /* opcode */
1685 BR_RANGE_S256, /* br_range */
1687 {0, 8, 0x7FF, TRUE},
1688 {0, 20, 0x1F, FALSE},
1693 INSN_BEQC /* beqc $rt, imm11s, label */
1694 }, /* BR_RANGE_S256 */
1696 INSN_MOVI_TA, /* movi $ta, imm11s */
1697 INSN_BEQ_TA /* beq $rt, $ta, label */
1698 }, /* BR_RANGE_S16K */
1700 INSN_BNEC, /* bnec $rt, imm11s, $1 */
1701 INSN_J /* j label */
1702 }, /* BR_RANGE_S64K */
1704 INSN_BNEC, /* bnec $rt, imm11s, $1 */
1705 INSN_J /* j label */
1706 }, /* BR_RANGE_S16M */
1708 INSN_BNEC, /* bnec $rt, imm11s, $1 */
1709 INSN_SETHI_TA, /* sethi $ta, label */
1710 INSN_ORI_TA, /* ori $ta, $ta, label */
1711 INSN_JR_TA /* jr $ta */
1712 } /* BR_RANGE_U4G */
1713 }, /* relax_code_seq */
1716 {0, 8, 0x7FF, TRUE},
1717 {0, 20, 0x1F, FALSE},
1719 }, /* BR_RANGE_S256 */
1721 {0, 0, 0xFFFFF, FALSE},
1722 {4, 20, 0x1F, FALSE},
1724 }, /* BR_RANGE_S16K */
1726 {0, 8, 0x7FF, FALSE},
1727 {0, 20, 0x1F, FALSE},
1729 }, /* BR_RANGE_S64K */
1731 {0, 8, 0x7FF, FALSE},
1732 {0, 20, 0x1F, FALSE},
1734 }, /* BR_RANGE_S16M */
1736 {0, 8, 0x7FF, FALSE},
1737 {0, 20, 0x1F, FALSE},
1739 } /* BR_RANGE_U4G */
1740 }, /* relax_code_condition */
1741 {4, 8, 8, 8, 16}, /* relax_code_size */
1742 {4, 4, 4, 4, 4}, /* relax_branch_isize */
1745 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
1747 }, /* BR_RANGE_S256 */
1749 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1750 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP7},
1751 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1753 }, /* BR_RANGE_S16K */
1755 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
1756 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1758 }, /* BR_RANGE_S64K */
1760 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
1761 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1763 }, /* BR_RANGE_S16M */
1765 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
1766 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1767 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
1768 {12, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
1770 } /* BR_RANGE_U4G */
1774 "bnec", /* opcode */
1775 BR_RANGE_S256, /* br_range */
1777 {0, 8, 0x7FF, TRUE},
1778 {0, 20, 0x1F, FALSE},
1783 INSN_BNEC /* bnec $rt, imm11s, label */
1784 }, /* BR_RANGE_S256 */
1786 INSN_MOVI_TA, /* movi $ta, imm11s */
1787 INSN_BNE_TA /* bne $rt, $ta, label */
1788 }, /* BR_RANGE_S16K */
1790 INSN_BEQC, /* beqc $rt, imm11s, $1 */
1791 INSN_J /* j label */
1792 }, /* BR_RANGE_S64K */
1794 INSN_BEQC, /* beqc $rt, imm11s, $1 */
1795 INSN_J /* j label */
1796 }, /* BR_RANGE_S16M */
1798 INSN_BEQC, /* beqc $rt, imm11s, $1 */
1799 INSN_SETHI_TA, /* sethi $ta, label */
1800 INSN_ORI_TA, /* ori $ta, $ta, label */
1801 INSN_JR_TA /* jr $ta */
1802 } /* BR_RANGE_U4G */
1803 }, /* relax_code_seq */
1806 {0, 8, 0x7FF, TRUE},
1807 {0, 20, 0x1F, FALSE},
1809 }, /* BR_RANGE_S256 */
1811 {0, 0, 0xFFFFF, FALSE},
1812 {4, 20, 0x1F, FALSE},
1814 }, /* BR_RANGE_S16K */
1816 {0, 8, 0x7FF, FALSE},
1817 {0, 20, 0x1F, FALSE},
1819 }, /* BR_RANGE_S64K */
1821 {0, 8, 0x7FF, FALSE},
1822 {0, 20, 0x1F, FALSE},
1824 }, /* BR_RANGE_S16M */
1826 {0, 8, 0x7FF, FALSE},
1827 {0, 20, 0x1F, FALSE},
1829 } /* BR_RANGE_U4G */
1830 }, /* relax_code_condition */
1831 {4, 8, 8, 8, 16}, /* relax_code_size */
1832 {4, 4, 4, 4, 4}, /* relax_branch_isize */
1835 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
1837 }, /* BR_RANGE_S256 */
1839 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1840 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP7},
1841 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1843 }, /* BR_RANGE_S16K */
1845 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
1846 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1848 }, /* BR_RANGE_S64K */
1850 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
1851 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1853 }, /* BR_RANGE_S16M */
1855 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
1856 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1857 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
1858 {12, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
1860 } /* BR_RANGE_U4G */
1865 /* GAS definitions for command-line options. */
1868 OPTION_BIG = OPTION_MD_BASE,
1872 OPTION_RELAX_FP_AS_GP_OFF,
1873 OPTION_RELAX_B2BB_ON,
1874 OPTION_RELAX_ALL_OFF,
1876 OPTION_OPTIMIZE_SPACE
1879 const char *md_shortopts = "m:O:";
1880 struct option md_longopts[] =
1882 {"O1", no_argument, NULL, OPTION_OPTIMIZE},
1883 {"Os", no_argument, NULL, OPTION_OPTIMIZE_SPACE},
1884 {"big", no_argument, NULL, OPTION_BIG},
1885 {"little", no_argument, NULL, OPTION_LITTLE},
1886 {"EB", no_argument, NULL, OPTION_BIG},
1887 {"EL", no_argument, NULL, OPTION_LITTLE},
1888 {"meb", no_argument, NULL, OPTION_BIG},
1889 {"mel", no_argument, NULL, OPTION_LITTLE},
1890 {"mall-ext", no_argument, NULL, OPTION_TURBO},
1891 {"mext-all", no_argument, NULL, OPTION_TURBO},
1892 {"mpic", no_argument, NULL, OPTION_PIC},
1893 /* Relaxation related options. */
1894 {"mno-fp-as-gp-relax", no_argument, NULL, OPTION_RELAX_FP_AS_GP_OFF},
1895 {"mb2bb", no_argument, NULL, OPTION_RELAX_B2BB_ON},
1896 {"mno-all-relax", no_argument, NULL, OPTION_RELAX_ALL_OFF},
1897 {NULL, no_argument, NULL, 0}
1900 size_t md_longopts_size = sizeof (md_longopts);
1902 struct nds32_parse_option_table
1904 const char *name; /* Option string. */
1905 const char *help; /* Help description. */
1906 int (*func) (const char *arg); /* How to parse it. */
1910 /* The value `-1' represents this option has *NOT* been set. */
1911 #ifdef NDS32_DEFAULT_ARCH_NAME
1912 static const char* nds32_arch_name = NDS32_DEFAULT_ARCH_NAME;
1914 static const char* nds32_arch_name = "v3";
1916 static int nds32_baseline = -1;
1917 static int nds32_gpr16 = -1;
1918 static int nds32_fpu_sp_ext = -1;
1919 static int nds32_fpu_dp_ext = -1;
1920 static int nds32_freg = -1;
1921 static int nds32_abi = -1;
1923 /* Record ELF flags */
1924 static int nds32_elf_flags = 0;
1925 static int nds32_fpu_com = 0;
1927 static int nds32_parse_arch (const char *str);
1928 static int nds32_parse_baseline (const char *str);
1929 static int nds32_parse_freg (const char *str);
1930 static int nds32_parse_abi (const char *str);
1932 static struct nds32_parse_option_table parse_opts [] =
1934 {"arch=", N_("<arch name>\t Assemble for architecture <arch name>\n\
1935 <arch name> could be\n\
1936 v3, v3j, v3m, v3f, v3s, "\
1937 "v2, v2j, v2f, v2s"), nds32_parse_arch},
1938 {"baseline=", N_("<baseline>\t Assemble for baseline <baseline>\n\
1939 <baseline> could be v2, v3, v3m"),
1940 nds32_parse_baseline},
1941 {"fpu-freg=", N_("<freg>\t Specify a FPU configuration\n\
1943 0: 8 SP / 4 DP registers\n\
1944 1: 16 SP / 8 DP registers\n\
1945 2: 32 SP / 16 DP registers\n\
1946 3: 32 SP / 32 DP registers"), nds32_parse_freg},
1947 {"abi=", N_("<abi>\t Specify a abi version\n\
1948 <abi> could be v1, v2, v2fp, v2fpp"), nds32_parse_abi},
1952 static int nds32_mac = 1;
1953 static int nds32_div = 1;
1954 static int nds32_16bit_ext = 1;
1955 static int nds32_dx_regs = 1;
1956 static int nds32_perf_ext = 1;
1957 static int nds32_perf_ext2 = 1;
1958 static int nds32_string_ext = 1;
1959 static int nds32_audio_ext = 1;
1960 static int nds32_fpu_fma = 0;
1961 static int nds32_pic = 0;
1962 static int nds32_relax_fp_as_gp = 1;
1963 static int nds32_relax_b2bb = 0;
1964 static int nds32_relax_all = 1;
1965 struct nds32_set_option_table
1967 const char *name; /* Option string. */
1968 const char *help; /* Help description. */
1969 int *var; /* Variable to be set. */
1970 int value; /* Value to set. */
1973 /* The option in this group has both Enable/Disable settings.
1974 Just list on here. */
1976 static struct nds32_set_option_table toggle_opts [] =
1978 {"mac", N_("Multiply instructions support"), &nds32_mac, 1},
1979 {"div", N_("Divide instructions support"), &nds32_div, 1},
1980 {"16bit-ext", N_("16-bit extension"), &nds32_16bit_ext, 1},
1981 {"dx-regs", N_("d0/d1 registers"), &nds32_dx_regs, 1},
1982 {"perf-ext", N_("Performance extension"), &nds32_perf_ext, 1},
1983 {"perf2-ext", N_("Performance extension 2"), &nds32_perf_ext2, 1},
1984 {"string-ext", N_("String extension"), &nds32_string_ext, 1},
1985 {"reduced-regs", N_("Reduced Register configuration (GPR16) option"), &nds32_gpr16, 1},
1986 {"audio-isa-ext", N_("AUDIO ISA extension"), &nds32_audio_ext, 1},
1987 {"fpu-sp-ext", N_("FPU SP extension"), &nds32_fpu_sp_ext, 1},
1988 {"fpu-dp-ext", N_("FPU DP extension"), &nds32_fpu_dp_ext, 1},
1989 {"fpu-fma", N_("FPU fused-multiply-add instructions"), &nds32_fpu_fma, 1},
1990 {NULL, NULL, NULL, 0}
1994 /* GAS declarations. */
1996 /* This is the callback for nds32-asm.c to parse operands. */
1998 nds32_asm_parse_operand (struct nds32_asm_desc *pdesc,
1999 struct nds32_asm_insn *pinsn,
2000 char **pstr, int64_t *value);
2003 struct nds32_asm_desc asm_desc;
2005 /* md_after_parse_args ()
2007 GAS will call md_after_parse_args whenever it is defined.
2008 This function checks any conflicting options specified. */
2011 nds32_after_parse_args (void)
2013 /* If -march option is not used in command-line, set the value of option
2014 variable according to NDS32_DEFAULT_ARCH_NAME. */
2015 nds32_parse_arch (nds32_arch_name);
2018 /* This function is called when printing usage message (--help). */
2021 md_show_usage (FILE *stream)
2023 struct nds32_parse_option_table *coarse_tune;
2024 struct nds32_set_option_table *fine_tune;
2026 fprintf (stream, _("\n NDS32-specific assembler options:\n"));
2027 fprintf (stream, _("\
2028 -O1, Optimize for performance\n\
2029 -Os Optimize for space\n"));
2030 fprintf (stream, _("\
2031 -EL, -mel or -little Produce little endian output\n\
2032 -EB, -meb or -big Produce big endian output\n\
2033 -mpic Generate PIC\n\
2034 -mno-fp-as-gp-relax Suppress fp-as-gp relaxation for this file\n\
2035 -mb2bb-relax Back-to-back branch optimization\n\
2036 -mno-all-relax Suppress all relaxation for this file\n"));
2038 for (coarse_tune = parse_opts; coarse_tune->name != NULL; coarse_tune++)
2040 if (coarse_tune->help != NULL)
2041 fprintf (stream, _(" -m%s%s\n"),
2042 coarse_tune->name, _(coarse_tune->help));
2045 for (fine_tune = toggle_opts; fine_tune->name != NULL; fine_tune++)
2047 if (fine_tune->help != NULL)
2048 fprintf (stream, _(" -m[no-]%-17sEnable/Disable %s\n"),
2049 fine_tune->name, _(fine_tune->help));
2052 fprintf (stream, _("\
2053 -mall-ext Turn on all extensions and instructions support\n"));
2057 nds32_frag_init (fragS *fragp)
2059 fragp->tc_frag_data.flag = 0;
2060 fragp->tc_frag_data.opcode = NULL;
2061 fragp->tc_frag_data.fixup = NULL;
2066 /* This function reads an expression from a C string and returns a pointer past
2067 the end of the expression. */
2070 parse_expression (char *str, expressionS *exp)
2075 tmp = input_line_pointer; /* Save line pointer. */
2076 input_line_pointer = str;
2078 s = input_line_pointer;
2079 input_line_pointer = tmp; /* Restore line pointer. */
2081 return s; /* Return pointer to where parsing stopped. */
2085 nds32_start_line_hook (void)
2093 typedef void (*nds32_pseudo_opcode_func) (int argc, char *argv[], int pv);
2094 struct nds32_pseudo_opcode
2098 nds32_pseudo_opcode_func proc;
2101 /* Some instructions are not pseudo opcode, but they might still be
2102 expanded or changed with other instruction combination for some
2103 conditions. We also apply this structure to assist such work.
2105 For example, if the distance of branch target '.L0' is larger than
2112 will be transformed into:
2118 However, sometimes we do not want assembler to do such changes
2119 because compiler knows how to generate corresponding instruction sequence.
2120 Use this field to indicate that this opcode is also a physical instruction.
2121 If the flag 'verbatim' is nozero and this opcode
2122 is a physical instruction, we should not expand it. */
2125 #define PV_DONT_CARE 0
2127 static struct hash_control *nds32_pseudo_opcode_hash = NULL;
2130 builtin_isreg (const char *s, const char *x ATTRIBUTE_UNUSED)
2132 if (s [0] == '$' && hash_find (nds32_gprs_hash, (s + 1)))
2138 builtin_regnum (const char *s, const char *x ATTRIBUTE_UNUSED)
2140 struct nds32_keyword *k;
2144 k = hash_find (nds32_gprs_hash, s);
2153 builtin_addend (const char *s, char *x ATTRIBUTE_UNUSED)
2155 const char *ptr = s;
2157 while (*ptr != '+' && *ptr != '-' && *ptr)
2163 return strtol (ptr, NULL, 0);
2167 md_assemblef (const char *format, ...)
2169 /* FIXME: hope this is long enough. */
2174 va_start (ap, format);
2175 r = vsnprintf (line, sizeof (line), format, ap);
2178 gas_assert (r < sizeof (line));
2181 /* Some prototypes here, since some op may use another op. */
2182 static void do_pseudo_li_internal (const char *rt, int imm32s);
2183 static void do_pseudo_move_reg_internal (char *dst, char *src);
2186 do_pseudo_b (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
2188 char *arg_label = argv[0];
2191 if (nds32_pic && strstr (arg_label, "@PLT"))
2193 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2194 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2195 md_assemble ((char *) "add $ta,$ta,$gp");
2196 md_assemble ((char *) "jr $ta");
2200 md_assemblef ("j %s", arg_label);
2206 do_pseudo_bal (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
2208 char *arg_label = argv[0];
2210 /* bal|call label */
2212 && (strstr (arg_label, "@GOT") || strstr (arg_label, "@PLT")))
2214 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2215 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2216 md_assemble ((char *) "add $ta,$ta,$gp");
2217 md_assemble ((char *) "jral $ta");
2221 md_assemblef ("jal %s", arg_label);
2227 do_pseudo_bge (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
2229 /* rt5, ra5, label */
2230 md_assemblef ("slt $ta,%s,%s", argv[0], argv[1]);
2231 md_assemblef ("beqz $ta,%s", argv[2]);
2235 do_pseudo_bges (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
2237 /* rt5, ra5, label */
2238 md_assemblef ("slts $ta,%s,%s", argv[0], argv[1]);
2239 md_assemblef ("beqz $ta,%s", argv[2]);
2243 do_pseudo_bgt (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
2245 /* bgt rt5, ra5, label */
2246 md_assemblef ("slt $ta,%s,%s", argv[1], argv[0]);
2247 md_assemblef ("bnez $ta,%s", argv[2]);
2251 do_pseudo_bgts (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
2253 /* bgt rt5, ra5, label */
2254 md_assemblef ("slts $ta,%s,%s", argv[1], argv[0]);
2255 md_assemblef ("bnez $ta,%s", argv[2]);
2259 do_pseudo_ble (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
2261 /* bgt rt5, ra5, label */
2262 md_assemblef ("slt $ta,%s,%s", argv[1], argv[0]);
2263 md_assemblef ("beqz $ta,%s", argv[2]);
2267 do_pseudo_bles (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
2269 /* bgt rt5, ra5, label */
2270 md_assemblef ("slts $ta,%s,%s", argv[1], argv[0]);
2271 md_assemblef ("beqz $ta,%s", argv[2]);
2275 do_pseudo_blt (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
2277 /* rt5, ra5, label */
2278 md_assemblef ("slt $ta,%s,%s", argv[0], argv[1]);
2279 md_assemblef ("bnez $ta,%s", argv[2]);
2283 do_pseudo_blts (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
2285 /* rt5, ra5, label */
2286 md_assemblef ("slts $ta,%s,%s", argv[0], argv[1]);
2287 md_assemblef ("bnez $ta,%s", argv[2]);
2291 do_pseudo_br (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
2293 md_assemblef ("jr %s", argv[0]);
2297 do_pseudo_bral (int argc, char *argv[], int pv ATTRIBUTE_UNUSED)
2300 md_assemblef ("jral $lp,%s", argv[0]);
2302 md_assemblef ("jral %s,%s", argv[0], argv[1]);
2306 do_pseudo_la_internal (const char *arg_reg, char *arg_label,
2311 parse_expression (arg_label, &exp);
2312 if (exp.X_op != O_symbol)
2314 as_bad (_("la must use with symbol. '%s'"), line);
2320 if (!nds32_pic && !strstr(arg_label, "@"))
2322 md_assemblef ("sethi %s,hi20(%s)", arg_reg, arg_label);
2323 md_assemblef ("ori %s,%s,lo12(%s)", arg_reg, arg_reg, arg_label);
2325 else if (strstr (arg_label, "@TPOFF"))
2327 /* la $rt, sym@TPOFF */
2328 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2329 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2330 md_assemblef ("add %s,$ta,%s", arg_reg, TLS_REG);
2332 else if (strstr(arg_label, "@GOTTPOFF"))
2334 /* la $rt, sym@GOTTPOFF*/
2335 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2336 md_assemblef ("lwi $ta,[$ta+lo12(%s)]", arg_label);
2337 md_assemblef ("add %s,$ta,%s", arg_reg, TLS_REG);
2339 else if (nds32_pic && ((strstr (arg_label, "@PLT")
2340 || strstr (arg_label, "@GOTOFF"))))
2342 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2343 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2344 md_assemblef ("add %s,$ta,$gp", arg_reg);
2346 else if (nds32_pic && strstr (arg_label, "@GOT"))
2348 long addend = builtin_addend (arg_label, NULL);
2350 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2351 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2352 md_assemblef ("lw %s,[$gp+$ta]", arg_reg);
2355 if (addend < 0x4000 && addend >= -0x4000)
2357 md_assemblef ("addi %s,%s,%d", arg_reg, arg_reg, addend);
2361 do_pseudo_li_internal ("$ta", addend);
2362 md_assemblef ("add %s,$ta,%s", arg_reg, arg_reg);
2367 as_bad (_("need PIC qualifier with symbol. '%s'"), line);
2372 do_pseudo_la (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
2374 do_pseudo_la_internal (argv[0], argv[1], argv[argc]);
2378 do_pseudo_li_internal (const char *rt, int imm32s)
2380 if (enable_16bit && imm32s <= 0xf && imm32s >= -0x10)
2381 md_assemblef ("movi55 %s,%d", rt, imm32s);
2382 else if (imm32s <= 0x7ffff && imm32s >= -0x80000)
2383 md_assemblef ("movi %s,%d", rt, imm32s);
2384 else if ((imm32s & 0xfff) == 0)
2385 md_assemblef ("sethi %s,hi20(%d)", rt, imm32s);
2388 md_assemblef ("sethi %s,hi20(%d)", rt, imm32s);
2389 md_assemblef ("ori %s,%s,lo12(%d)", rt, rt, imm32s);
2394 do_pseudo_li (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
2396 /* Validate argv[1] for constant expression. */
2399 parse_expression (argv[1], &exp);
2400 if (exp.X_op != O_constant)
2402 as_bad (_("Operand is not a constant. `%s'"), argv[argc]);
2406 do_pseudo_li_internal (argv[0], exp.X_add_number);
2410 do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED, char *argv[], int pv)
2414 const char *sign = "";
2416 /* Prepare arguments for various load/store. */
2417 sign = (pv & 0x10) ? "s" : "";
2418 ls = (pv & 0x80000000) ? 's' : 'l';
2421 case 0: size = 'b'; break;
2422 case 1: size = 'h'; break;
2423 case 2: size = 'w'; break;
2426 if (ls == 's' || size == 'w')
2429 if (builtin_isreg (argv[1], NULL))
2432 md_assemblef ("%c%ci %s,[%s]", ls, size, argv[0], argv[1]);
2434 else if (!nds32_pic)
2437 if (strstr (argv[1], "@TPOFF"))
2439 /* ls.w $rt, sym@TPOFF */
2440 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2441 md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
2442 md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], TLS_REG);
2444 else if (strstr (argv[1], "@GOTTPOFF"))
2446 /* ls.w $rt, sym@GOTTPOFF */
2447 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2448 md_assemblef ("lwi $ta,[$ta+lo12(%s)]", argv[1]);
2449 md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], TLS_REG);
2454 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2455 md_assemblef ("%c%c%si %s,[$ta+lo12(%s)]", ls, size, sign, argv[0], argv[1]);
2463 if (strstr (argv[1], "@GOTOFF"))
2466 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2467 md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
2468 md_assemblef ("%c%c%s %s,[$ta+$gp]", ls, size, sign, argv[0]);
2470 else if (strstr (argv[1], "@GOT"))
2472 long addend = builtin_addend (argv[1], NULL);
2474 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2475 md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
2476 md_assemble ((char *) "lw $ta,[$gp+$ta]"); /* Load address word. */
2477 if (addend < 0x10000 && addend >= -0x10000)
2479 md_assemblef ("%c%c%si %s,[$ta+(%d)]", ls, size, sign, argv[0], addend);
2484 do_pseudo_li_internal (argv[0], addend);
2485 md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], argv[0]);
2490 as_bad (_("needs @GOT or @GOTOFF. %s"), argv[argc]);
2497 do_pseudo_ls_bhwp (int argc ATTRIBUTE_UNUSED, char *argv[], int pv)
2499 char *arg_rt = argv[0];
2500 char *arg_label = argv[1];
2501 char *arg_inc = argv[2];
2504 const char *sign = "";
2506 /* Prepare arguments for various load/store. */
2507 sign = (pv & 0x10) ? "s" : "";
2508 ls = (pv & 0x80000000) ? 's' : 'l';
2511 case 0: size = 'b'; break;
2512 case 1: size = 'h'; break;
2513 case 2: size = 'w'; break;
2516 if (ls == 's' || size == 'w')
2519 do_pseudo_la_internal ("$ta", arg_label, argv[argc]);
2520 md_assemblef ("%c%c%si.bi %s,[$ta],%s", ls, size, sign, arg_rt, arg_inc);
2524 do_pseudo_ls_bhwpc (int argc ATTRIBUTE_UNUSED, char *argv[], int pv)
2526 char *arg_rt = argv[0];
2527 char *arg_inc = argv[1];
2530 const char *sign = "";
2532 /* Prepare arguments for various load/store. */
2533 sign = (pv & 0x10) ? "s" : "";
2534 ls = (pv & 0x80000000) ? 's' : 'l';
2537 case 0: size = 'b'; break;
2538 case 1: size = 'h'; break;
2539 case 2: size = 'w'; break;
2542 if (ls == 's' || size == 'w')
2545 md_assemblef ("%c%c%si.bi %s,[$ta],%s", ls, size, sign, arg_rt, arg_inc);
2549 do_pseudo_ls_bhwi (int argc ATTRIBUTE_UNUSED, char *argv[], int pv)
2553 const char *sign = "";
2555 /* Prepare arguments for various load/store. */
2556 sign = (pv & 0x10) ? "s" : "";
2557 ls = (pv & 0x80000000) ? 's' : 'l';
2560 case 0: size = 'b'; break;
2561 case 1: size = 'h'; break;
2562 case 2: size = 'w'; break;
2565 if (ls == 's' || size == 'w')
2568 md_assemblef ("%c%c%si.bi %s,%s,%s",
2569 ls, size, sign, argv[0], argv[1], argv[2]);
2573 do_pseudo_move_reg_internal (char *dst, char *src)
2576 md_assemblef ("mov55 %s,%s", dst, src);
2578 md_assemblef ("ori %s,%s,0", dst, src);
2582 do_pseudo_move (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
2586 if (builtin_isreg (argv[1], NULL))
2587 do_pseudo_move_reg_internal (argv[0], argv[1]);
2590 parse_expression (argv[1], &exp);
2591 if (exp.X_op == O_constant)
2592 /* move $rt, imm -> li $rt, imm */
2593 do_pseudo_li_internal (argv[0], exp.X_add_number);
2595 /* l.w $rt, var -> l.w $rt, var */
2596 do_pseudo_ls_bhw (argc, argv, 2);
2601 do_pseudo_neg (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
2603 /* Instead of "subri". */
2604 md_assemblef ("subri %s,%s,0", argv[0], argv[1]);
2608 do_pseudo_not (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
2610 md_assemblef ("nor %s,%s,%s", argv[0], argv[1], argv[1]);
2614 do_pseudo_pushpopm (int argc, char *argv[], int pv ATTRIBUTE_UNUSED)
2616 /* posh/pop $ra, $rb */
2617 /* SMW.{b | a}{i | d}{m?} Rb, [Ra], Re, Enable4 */
2618 int rb, re, ra, en4;
2620 const char *opc = "pushpopm";
2623 as_bad ("'pushm/popm $ra5, $rb5, $label' is deprecated. "
2624 "Only 'pushm/popm $ra5' is supported now. %s", argv[argc]);
2626 as_bad ("'pushm/popm $ra5, $rb5'. %s\n", argv[argc]);
2628 if (strstr (argv[argc], "pop") == argv[argc])
2630 else if (strstr (argv[argc], "push") == argv[argc])
2633 as_fatal ("nds32-as internal error. %s", argv[argc]);
2635 rb = builtin_regnum (argv[0], NULL);
2636 re = builtin_regnum (argv[1], NULL);
2640 as_warn ("$rb should not be smaller than $ra. %s", argv[argc]);
2641 /* Swap to right order. */
2647 /* Build enable4 mask. */
2649 if (re >= 28 || rb >= 28)
2651 for (i = (rb >= 28? rb: 28); i <= re; i++)
2652 en4 |= 1 << (3 - (i - 28));
2655 /* Adjust $re, $rb. */
2658 else if (nds32_gpr16 != 1 && re >= 28)
2661 /* Reduce register. */
2662 if (nds32_gpr16 && re > 10 && !(rb == 31 && re == 31))
2664 if (re >= 15 && strstr(opc, "smw") != NULL)
2665 md_assemblef ("%s $r15,[$sp],$r15,%d", opc, en4);
2667 md_assemblef ("%s $r%d,[$sp],$r10, 0x0", opc, rb);
2668 if (re >= 15 && strstr(opc, "lmw") != NULL)
2669 md_assemblef ("%s $r15,[$sp],$r15,%d", opc, en4);
2672 md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc, rb, re, en4);
2676 do_pseudo_pushpop (int argc, char *argv[], int pv ATTRIBUTE_UNUSED)
2678 /* push/pop $ra5, $label=$sp */
2682 as_bad ("'push/pop $ra5, rb5' is deprecated. "
2683 "Only 'push/pop $ra5' is supported now. %s", argv[argc]);
2687 argvm[2] = argv[argc];
2688 do_pseudo_pushpopm (2, argvm, PV_DONT_CARE);
2692 do_pseudo_v3push (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
2694 md_assemblef ("push25 %s,%s", argv[0], argv[1]);
2698 do_pseudo_v3pop (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
2700 md_assemblef ("pop25 %s,%s", argv[0], argv[1]);
2703 /* pv == 0, parsing "push.s" pseudo instruction operands.
2704 pv != 0, parsing "pop.s" pseudo instruction operands. */
2707 do_pseudo_pushpop_stack (int argc, char *argv[], int pv)
2709 /* push.s Rb,Re,{$fp $gp $lp $sp} ==> smw.adm Rb,[$sp],Re,Eable4 */
2710 /* pop.s Rb,Re,{$fp $gp $lp $sp} ==> lmw.bim Rb,[$sp],Re,Eable4 */
2715 const char *opc = (pv == 0) ? "smw.adm" : "lmw.bim";
2721 /* argc=1, operands pattern: { $fp $gp $lp $sp } */
2723 /* Set register number Rb = Re = $sp = $r31. */
2726 else if (argc == 2 || argc == 3)
2728 /* argc=2, operands pattern: Rb, Re */
2729 /* argc=3, operands pattern: Rb, Re, { $fp $gp $lp $sp } */
2731 /* Get register number in integer. */
2732 rb = builtin_regnum (argv[0], NULL);
2733 re = builtin_regnum (argv[1], NULL);
2735 /* Rb should be equal/less than Re. */
2737 as_bad ("The first operand (%s) should be equal to or smaller than "
2738 "second operand (%s).", argv[0], argv[1]);
2740 /* forbid using $fp|$gp|$lp|$sp in Rb or Re
2743 as_bad ("Cannot use $fp, $gp, $lp, or $sp at first operand !!");
2745 as_bad ("Cannot use $fp, $gp, $lp, or $sp at second operand !!");
2749 as_bad ("Invalid operands pattern !!");
2752 /* Build Enable4 mask. */
2753 /* Using last_arg_index for argc=1|2|3 is safe, because $fp, $gp, $lp,
2754 and $sp only appear in argc=1 or argc=3 if argc=2, en4 remains 0,
2755 which is also valid for code generation. */
2757 last_arg_index = argc - 1;
2758 if (strstr (argv[last_arg_index], "$fp"))
2760 if (strstr (argv[last_arg_index], "$gp"))
2762 if (strstr (argv[last_arg_index], "$lp"))
2764 if (strstr (argv[last_arg_index], "$sp"))
2767 md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc, rb, re, en4);
2771 do_pseudo_push_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
2774 /* If users omit push location, use $sp as default value. */
2775 char location[8] = "$sp"; /* 8 is enough for register name. */
2779 case 0: size = 'b'; break;
2780 case 1: size = 'h'; break;
2781 case 2: size = 'w'; break;
2782 case 3: size = 'w'; break;
2787 strncpy (location, argv[1], 8);
2791 md_assemblef ("l.%c $ta,%s", size, argv[0]);
2792 md_assemblef ("smw.adm $ta,[%s],$ta", location);
2794 if ((pv & 0x3) == 0x3) /* double-word */
2796 md_assemblef ("l.w $ta,%s+4", argv[0]);
2797 md_assemblef ("smw.adm $ta,[%s],$ta", location);
2802 do_pseudo_pop_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
2805 /* If users omit pop location, use $sp as default value. */
2806 char location[8] = "$sp"; /* 8 is enough for register name. */
2810 case 0: size = 'b'; break;
2811 case 1: size = 'h'; break;
2812 case 2: size = 'w'; break;
2813 case 3: size = 'w'; break;
2818 strncpy (location, argv[2], 8);
2822 if ((pv & 0x3) == 0x3) /* double-word */
2824 md_assemblef ("lmw.bim %s,[%s],%s", argv[1], location, argv[1]);
2825 md_assemblef ("s.w %s,%s+4", argv[1], argv[0]);
2828 md_assemblef ("lmw.bim %s,[%s],%s", argv[1], location, argv[1]);
2829 md_assemblef ("s.%c %s,%s", size, argv[1], argv[0]);
2833 do_pseudo_pusha (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
2835 /* If users omit push location, use $sp as default value. */
2836 char location[8] = "$sp"; /* 8 is enough for register name. */
2840 strncpy (location, argv[1], 8);
2844 md_assemblef ("la $ta,%s", argv[0]);
2845 md_assemblef ("smw.adm $ta,[%s],$ta", location);
2849 do_pseudo_pushi (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
2851 /* If users omit push location, use $sp as default value. */
2852 char location[8] = "$sp"; /* 8 is enough for register name. */
2856 strncpy (location, argv[1], 8);
2860 md_assemblef ("li $ta,%s", argv[0]);
2861 md_assemblef ("smw.adm $ta,[%s],$ta", location);
2864 struct nds32_pseudo_opcode nds32_pseudo_opcode_table[] =
2866 {"b", 1, do_pseudo_b, 0, 0},
2867 {"bal", 1, do_pseudo_bal, 0, 0},
2869 {"bge", 3, do_pseudo_bge, 0, 0},
2870 {"bges", 3, do_pseudo_bges, 0, 0},
2872 {"bgt", 3, do_pseudo_bgt, 0, 0},
2873 {"bgts", 3, do_pseudo_bgts, 0, 0},
2875 {"ble", 3, do_pseudo_ble, 0, 0},
2876 {"bles", 3, do_pseudo_bles, 0, 0},
2878 {"blt", 3, do_pseudo_blt, 0, 0},
2879 {"blts", 3, do_pseudo_blts, 0, 0},
2881 {"br", 1, do_pseudo_br, 0, 0},
2882 {"bral", 1, do_pseudo_bral, 0, 0},
2884 {"call", 1, do_pseudo_bal, 0, 0},
2886 {"la", 2, do_pseudo_la, 0, 0},
2887 {"li", 2, do_pseudo_li, 0, 0},
2889 {"l.b", 2, do_pseudo_ls_bhw, 0, 0},
2890 {"l.h", 2, do_pseudo_ls_bhw, 1, 0},
2891 {"l.w", 2, do_pseudo_ls_bhw, 2, 0},
2892 {"l.bs", 2, do_pseudo_ls_bhw, 0 | 0x10, 0},
2893 {"l.hs", 2, do_pseudo_ls_bhw, 1 | 0x10, 0},
2894 {"s.b", 2, do_pseudo_ls_bhw, 0 | 0x80000000, 0},
2895 {"s.h", 2, do_pseudo_ls_bhw, 1 | 0x80000000, 0},
2896 {"s.w", 2, do_pseudo_ls_bhw, 2 | 0x80000000, 0},
2898 {"l.bp", 3, do_pseudo_ls_bhwp, 0, 0},
2899 {"l.bpc", 3, do_pseudo_ls_bhwpc, 0, 0},
2900 {"l.hp", 3, do_pseudo_ls_bhwp, 1, 0},
2901 {"l.hpc", 3, do_pseudo_ls_bhwpc, 1, 0},
2902 {"l.wp", 3, do_pseudo_ls_bhwp, 2, 0},
2903 {"l.wpc", 3, do_pseudo_ls_bhwpc, 2, 0},
2904 {"l.bsp", 3, do_pseudo_ls_bhwp, 0 | 0x10, 0},
2905 {"l.bspc", 3, do_pseudo_ls_bhwpc, 0 | 0x10, 0},
2906 {"l.hsp", 3, do_pseudo_ls_bhwp, 1 | 0x10, 0},
2907 {"l.hspc", 3, do_pseudo_ls_bhwpc, 1 | 0x10, 0},
2908 {"s.bp", 3, do_pseudo_ls_bhwp, 0 | 0x80000000, 0},
2909 {"s.bpc", 3, do_pseudo_ls_bhwpc, 0 | 0x80000000, 0},
2910 {"s.hp", 3, do_pseudo_ls_bhwp, 1 | 0x80000000, 0},
2911 {"s.hpc", 3, do_pseudo_ls_bhwpc, 1 | 0x80000000, 0},
2912 {"s.wp", 3, do_pseudo_ls_bhwp, 2 | 0x80000000, 0},
2913 {"s.wpc", 3, do_pseudo_ls_bhwpc, 2 | 0x80000000, 0},
2914 {"s.bsp", 3, do_pseudo_ls_bhwp, 0 | 0x80000000 | 0x10, 0},
2915 {"s.hsp", 3, do_pseudo_ls_bhwp, 1 | 0x80000000 | 0x10, 0},
2917 {"lbi.p", 3, do_pseudo_ls_bhwi, 0, 0},
2918 {"lhi.p", 3, do_pseudo_ls_bhwi, 1, 0},
2919 {"lwi.p", 3, do_pseudo_ls_bhwi, 2, 0},
2920 {"sbi.p", 3, do_pseudo_ls_bhwi, 0 | 0x80000000, 0},
2921 {"shi.p", 3, do_pseudo_ls_bhwi, 1 | 0x80000000, 0},
2922 {"swi.p", 3, do_pseudo_ls_bhwi, 2 | 0x80000000, 0},
2923 {"lbsi.p", 3, do_pseudo_ls_bhwi, 0 | 0x10, 0},
2924 {"lhsi.p", 3, do_pseudo_ls_bhwi, 1 | 0x10, 0},
2925 {"lwsi.p", 3, do_pseudo_ls_bhwi, 2 | 0x10, 0},
2927 {"move", 2, do_pseudo_move, 0, 0},
2928 {"neg", 2, do_pseudo_neg, 0, 0},
2929 {"not", 2, do_pseudo_not, 0, 0},
2931 {"pop", 2, do_pseudo_pushpop, 0, 0},
2932 {"push", 2, do_pseudo_pushpop, 0, 0},
2933 {"popm", 2, do_pseudo_pushpopm, 0, 0},
2934 {"pushm", 3, do_pseudo_pushpopm, 0, 0},
2936 {"v3push", 2, do_pseudo_v3push, 0, 0},
2937 {"v3pop", 2, do_pseudo_v3pop, 0, 0},
2939 /* Support pseudo instructions of pushing/poping registers into/from stack
2940 push.s Rb, Re, { $fp $gp $lp $sp } ==> smw.adm Rb,[$sp],Re,Enable4
2941 pop.s Rb, Re, { $fp $gp $lp $sp } ==> lmw.bim Rb,[$sp],Re,Enable4 */
2942 { "push.s", 3, do_pseudo_pushpop_stack, 0, 0 },
2943 { "pop.s", 3, do_pseudo_pushpop_stack, 1, 0 },
2944 { "push.b", 2, do_pseudo_push_bhwd, 0, 0 },
2945 { "push.h", 2, do_pseudo_push_bhwd, 1, 0 },
2946 { "push.w", 2, do_pseudo_push_bhwd, 2, 0 },
2947 { "push.d", 2, do_pseudo_push_bhwd, 3, 0 },
2948 { "pop.b", 3, do_pseudo_pop_bhwd, 0, 0 },
2949 { "pop.h", 3, do_pseudo_pop_bhwd, 1, 0 },
2950 { "pop.w", 3, do_pseudo_pop_bhwd, 2, 0 },
2951 { "pop.d", 3, do_pseudo_pop_bhwd, 3, 0 },
2952 { "pusha", 2, do_pseudo_pusha, 0, 0 },
2953 { "pushi", 2, do_pseudo_pushi, 0, 0 },
2955 {NULL, 0, NULL, 0, 0}
2959 nds32_init_nds32_pseudo_opcodes (void)
2961 struct nds32_pseudo_opcode *opcode = nds32_pseudo_opcode_table;
2963 nds32_pseudo_opcode_hash = hash_new ();
2964 for ( ; opcode->opcode; opcode++)
2968 op = hash_find (nds32_pseudo_opcode_hash, opcode->opcode);
2971 as_warn (_("Duplicated pseudo-opcode %s."), opcode->opcode);
2974 hash_insert (nds32_pseudo_opcode_hash, opcode->opcode, opcode);
2978 static struct nds32_pseudo_opcode *
2979 nds32_lookup_pseudo_opcode (const char *str)
2982 /* Assume pseudo-opcode are less than 16-char in length. */
2985 for (i = 0; i < (int)ARRAY_SIZE (op); i++)
2987 if (ISSPACE (op[i] = str[i]))
2991 if (i >= (int)ARRAY_SIZE (op))
2996 return hash_find (nds32_pseudo_opcode_hash, op);
3000 nds32_pseudo_opcode_wrapper (char *line, struct nds32_pseudo_opcode *opcode)
3003 char *argv[8] = {NULL};
3005 char *str = xstrdup (line);
3007 /* Parse arguments for opcode. */
3008 s = str + strlen (opcode->opcode);
3013 /* Dummy comma to ease separate arguments as below. */
3019 if (argc >= opcode->argc
3020 || (argc >= (int)ARRAY_SIZE (argv) - 1))
3021 as_bad (_("Too many argument. `%s'"), line);
3028 } while (s[0] != '\0');
3030 /* Put the origin line for debugging. */
3032 opcode->proc (argc, argv, opcode->pseudo_val);
3036 /* This function will be invoked from function `nds32_after_parse_args'.
3037 Thus, if the value of option has been set, keep the value the way it is. */
3040 nds32_parse_arch (const char *str)
3042 static const struct nds32_arch
3053 {"v3m", ISA_V3M, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3054 {"v3j", ISA_V3, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3055 {"v3s", ISA_V3, 0, 1, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3056 {"v3f", ISA_V3, 0, 1, 1, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3057 {"v3", ISA_V3, 0, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3058 {"v2j", ISA_V2, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3059 {"v2s", ISA_V2, 0, 1, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3060 {"v2f", ISA_V2, 0, 1, 1, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3061 {"v2", ISA_V2, 0, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3065 for (i = 0; i < ARRAY_SIZE (archs); i++)
3067 if (strcmp (str, archs[i].name) != 0)
3070 /* The value `-1' represents this option has *NOT* been set. */
3071 nds32_baseline = (-1 != nds32_baseline) ? nds32_baseline : archs[i].baseline;
3072 nds32_gpr16 = (-1 != nds32_gpr16) ? nds32_gpr16 : archs[i].reduced_reg;
3073 nds32_fpu_sp_ext = (-1 != nds32_fpu_sp_ext) ? nds32_fpu_sp_ext : archs[i].fpu_sp_ext;
3074 nds32_fpu_dp_ext = (-1 != nds32_fpu_dp_ext) ? nds32_fpu_dp_ext : archs[i].fpu_dp_ext;
3075 nds32_freg = (-1 != nds32_freg) ? nds32_freg : archs[i].fpu_freg;
3076 nds32_abi = (-1 != nds32_abi) ? nds32_abi : archs[i].abi;
3081 /* Logic here rejects the input arch name. */
3082 as_bad (_("unknown arch name `%s'\n"), str);
3087 /* This function parses "baseline" specified. */
3090 nds32_parse_baseline (const char *str)
3092 if (strcmp (str, "v3") == 0)
3093 nds32_baseline = ISA_V3;
3094 else if (strcmp (str, "v3m") == 0)
3095 nds32_baseline = ISA_V3M;
3096 else if (strcmp (str, "v2") == 0)
3097 nds32_baseline = ISA_V2;
3100 /* Logic here rejects the input baseline. */
3101 as_bad (_("unknown baseline `%s'\n"), str);
3108 /* This function parses "fpu-freg" specified. */
3111 nds32_parse_freg (const char *str)
3113 if (strcmp (str, "2") == 0)
3114 nds32_freg = E_NDS32_FPU_REG_32SP_16DP;
3115 else if (strcmp (str, "3") == 0)
3116 nds32_freg = E_NDS32_FPU_REG_32SP_32DP;
3117 else if (strcmp (str, "1") == 0)
3118 nds32_freg = E_NDS32_FPU_REG_16SP_8DP;
3119 else if (strcmp (str, "0") == 0)
3120 nds32_freg = E_NDS32_FPU_REG_8SP_4DP;
3123 /* Logic here rejects the input FPU configuration. */
3124 as_bad (_("unknown FPU configuration `%s'\n"), str);
3131 /* This function parse "abi=" specified. */
3134 nds32_parse_abi (const char *str)
3136 if (strcmp (str, "v2") == 0)
3137 nds32_abi = E_NDS_ABI_AABI;
3139 else if (strcmp (str, "v2fp") == 0)
3140 nds32_abi = E_NDS_ABI_V2FP;
3141 else if (strcmp (str, "v1") == 0)
3142 nds32_abi = E_NDS_ABI_V1;
3143 else if (strcmp (str,"v2fpp") == 0)
3144 nds32_abi = E_NDS_ABI_V2FP_PLUS;
3147 /* Logic here rejects the input abi version. */
3148 as_bad (_("unknown ABI version`%s'\n"), str);
3155 /* This function turn on all extensions and instructions support. */
3158 nds32_all_ext (void)
3163 nds32_16bit_ext = 1;
3165 nds32_perf_ext2 = 1;
3166 nds32_string_ext = 1;
3167 nds32_audio_ext = 1;
3169 nds32_fpu_sp_ext = 1;
3170 nds32_fpu_dp_ext = 1;
3175 /* GAS will call md_parse_option whenever getopt returns an unrecognized code,
3176 presumably indicating a special code value which appears in md_longopts.
3177 This function should return non-zero if it handled the option and zero
3178 otherwise. There is no need to print a message about an option not being
3179 recognized. This will be handled by the generic code. */
3182 nds32_parse_option (int c, const char *arg)
3184 struct nds32_parse_option_table *coarse_tune;
3185 struct nds32_set_option_table *fine_tune;
3186 const char *ptr_arg = NULL;
3190 case OPTION_OPTIMIZE:
3192 optimize_for_space = 0;
3194 case OPTION_OPTIMIZE_SPACE:
3196 optimize_for_space = 1;
3199 target_big_endian = 1;
3202 target_big_endian = 0;
3210 case OPTION_RELAX_FP_AS_GP_OFF:
3211 nds32_relax_fp_as_gp = 0;
3213 case OPTION_RELAX_B2BB_ON:
3214 nds32_relax_b2bb = 1;
3216 case OPTION_RELAX_ALL_OFF:
3217 nds32_relax_all = 0;
3220 /* Determination of which option table to search for to save time. */
3224 ptr_arg = strchr (arg, '=');
3228 /* Find the value after '='. */
3229 if (ptr_arg != NULL)
3231 for (coarse_tune = parse_opts; coarse_tune->name != NULL; coarse_tune++)
3233 if (strncmp (arg, coarse_tune->name, (ptr_arg - arg)) == 0)
3235 coarse_tune->func (ptr_arg);
3244 /* Filter out the Disable option first. */
3245 if (strncmp (arg, "no-", 3) == 0)
3251 for (fine_tune = toggle_opts; fine_tune->name != NULL; fine_tune++)
3253 if (strcmp (arg, fine_tune->name) == 0)
3255 if (fine_tune->var != NULL)
3256 *fine_tune->var = (disable) ? 0 : 1;
3261 /* Nothing match. */
3268 /* tc_check_label */
3271 nds32_check_label (symbolS *label ATTRIBUTE_UNUSED)
3273 /* The code used to create BB is move to frob_label.
3274 They should go there. */
3278 set_endian_little (int on)
3280 target_big_endian = !on;
3283 /* These functions toggles the generation of 16-bit. First encounter signals
3284 the beginning of not generating 16-bit instructions and next encounter
3285 signals the restoring back to default behavior. */
3288 trigger_16bit (int trigger)
3290 enable_16bit = trigger;
3293 static int backup_16bit_mode;
3295 restore_16bit (int no_use ATTRIBUTE_UNUSED)
3297 enable_16bit = backup_16bit_mode;
3301 off_16bit (int no_use ATTRIBUTE_UNUSED)
3303 backup_16bit_mode = enable_16bit;
3307 /* Built-in segments for small object. */
3308 typedef struct nds32_seg_entryT
3315 nds32_seg_entry nds32_seg_table[] =
3317 {NULL, ".sdata_f", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3318 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3319 {NULL, ".sdata_b", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3320 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3321 {NULL, ".sdata_h", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3322 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3323 {NULL, ".sdata_w", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3324 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3325 {NULL, ".sdata_d", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3326 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3327 {NULL, ".sbss_f", SEC_ALLOC | SEC_SMALL_DATA},
3328 {NULL, ".sbss_b", SEC_ALLOC | SEC_SMALL_DATA},
3329 {NULL, ".sbss_h", SEC_ALLOC | SEC_SMALL_DATA},
3330 {NULL, ".sbss_w", SEC_ALLOC | SEC_SMALL_DATA},
3331 {NULL, ".sbss_d", SEC_ALLOC | SEC_SMALL_DATA}
3334 /* Indexes to nds32_seg_table[]. */
3335 enum NDS32_SECTIONS_ENUM
3337 SDATA_F_SECTION = 0,
3338 SDATA_B_SECTION = 1,
3339 SDATA_H_SECTION = 2,
3340 SDATA_W_SECTION = 3,
3341 SDATA_D_SECTION = 4,
3349 /* The following code is borrowed from v850_seg. Revise this is needed. */
3352 do_nds32_seg (int i, subsegT sub)
3354 nds32_seg_entry *seg = nds32_seg_table + i;
3356 obj_elf_section_change_hook ();
3359 subseg_set (seg->s, sub);
3362 seg->s = subseg_new (seg->name, sub);
3363 if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
3365 bfd_set_section_flags (stdoutput, seg->s, seg->flags);
3366 if ((seg->flags & SEC_LOAD) == 0)
3367 seg_info (seg->s)->bss = 1;
3375 subsegT sub = get_absolute_expression ();
3377 do_nds32_seg (i, sub);
3378 demand_empty_rest_of_line ();
3381 /* Set if label adjustment is needed. I should not adjust .xbyte in dwarf. */
3382 static symbolS *nds32_last_label; /* Last label for aligment. */
3384 /* This code is referred from D30V for adjust label to be with pedning
3385 aligment. For example,
3389 Without this, the above label will not attatch to incoming data. */
3392 nds32_adjust_label (int n)
3394 /* FIXME: I think adjust lable and alignment is
3395 the programmer's obligation. Saddly, VLSI team doesn't
3396 properly use .align for their test cases.
3397 So I re-implement cons_align and auto adjust labels, again.
3399 I think d30v's implmentation is simple and good enough. */
3401 symbolS *label = nds32_last_label;
3402 nds32_last_label = NULL;
3404 /* SEC_ALLOC is used to eliminate .debug_ sections.
3405 SEC_CODE is used to include section for ILM. */
3406 if (((now_seg->flags & SEC_ALLOC) == 0 && (now_seg->flags & SEC_CODE) == 0)
3407 || strcmp (now_seg->name, ".eh_frame") == 0
3408 || strcmp (now_seg->name, ".gcc_except_table") == 0)
3411 /* Only frag by alignment when needed.
3412 Otherwise, it will fail to optimize labels on 4-byte boundary. (bug8454)
3413 See md_convert_frag () and RELAX_SET_RELAXABLE (frag) for details. */
3414 if (frag_now_fix () & ((1 << n) -1 ))
3416 if (subseg_text_p (now_seg))
3417 frag_align_code (n, 0);
3419 frag_align (n, 0, 0);
3421 /* Record the minimum alignment for this segment. */
3422 record_alignment (now_seg, n - OCTETS_PER_BYTE_POWER);
3428 int label_seen = FALSE;
3429 struct frag *old_frag;
3430 valueT old_value, new_value;
3432 gas_assert (S_GET_SEGMENT (label) == now_seg);
3434 old_frag = symbol_get_frag (label);
3435 old_value = S_GET_VALUE (label);
3436 new_value = (valueT) frag_now_fix ();
3438 /* Multiple labels may be on the same address. And the last symbol
3439 may not be a label at all, e.g., register name, external function names,
3440 so I have to track the last label in tc_frob_label instead of
3441 just using symbol_lastP. */
3442 for (sym = symbol_lastP; sym != NULL; sym = symbol_previous (sym))
3444 if (symbol_get_frag (sym) == old_frag
3445 && S_GET_VALUE (sym) == old_value)
3449 symbol_set_frag (sym, frag_now);
3450 S_SET_VALUE (sym, new_value);
3452 else if (label_seen && symbol_get_frag (sym) != old_frag)
3459 nds32_cons_align (int size ATTRIBUTE_UNUSED)
3462 This is called before `md_flush_pending_output' is called by `cons'.
3464 There are two things should be done for auto-adjust-label.
3465 1. Align data/instructions and adjust label to be attached to them.
3466 2. Clear auto-adjust state, so incommng data/instructions will not
3474 in this case, '.word 0x2' will adjust the label, .L0, but '.word 0x3' should not.
3476 I think `md_flush_pending_output' is a good place to clear the auto-adjust state,
3477 but it is also called by `cons' before this function.
3478 To simplify the code, instead of overriding .zero, .fill, .space, etc,
3479 I think we should just adjust label in `nds32_aligned_X_cons' instead of here. */
3483 nds32_aligned_cons (int idx)
3485 nds32_adjust_label (idx);
3486 /* Call default handler. */
3488 if (now_seg->flags & SEC_CODE
3489 && now_seg->flags & SEC_ALLOC && now_seg->flags & SEC_RELOC)
3491 /* Use BFD_RELOC_NDS32_DATA to avoid EX9 optimization replacing data. */
3494 exp.X_add_number = 0;
3495 exp.X_op = O_constant;
3496 fix_new_exp (frag_now, frag_now_fix () - (1 << idx), 1 << idx,
3497 &exp, 0, BFD_RELOC_NDS32_DATA);
3501 /* `.double' directive. */
3504 nds32_aligned_float_cons (int type)
3512 nds32_adjust_label (2);
3518 nds32_adjust_label (4);
3521 as_bad ("Unrecognized float type, %c\n", (char)type);
3523 /* Call default handler. */
3528 nds32_enable_pic (int ignore ATTRIBUTE_UNUSED)
3530 /* Another way to do -mpic.
3531 This is for GCC internal use and should always be first line
3532 of code, otherwise, the effect is not determined. */
3537 nds32_set_abi (int ver)
3542 /* Relax directive to set relocation R_NDS32_RELAX_ENTRY value. */
3545 nds32_relax_relocs (int relax)
3550 const char *subtype_relax[] =
3551 {"", "", "ex9", "ifc"};
3553 name = input_line_pointer;
3554 while (*input_line_pointer && !ISSPACE (*input_line_pointer))
3555 input_line_pointer++;
3556 saved_char = *input_line_pointer;
3557 *input_line_pointer = 0;
3559 for (i = 0; i < (int) ARRAY_SIZE (subtype_relax); i++)
3561 if (strcmp (name, subtype_relax[i]) == 0)
3567 enable_relax_relocs = relax & enable_relax_relocs;
3568 enable_relax_ex9 = relax & enable_relax_ex9;
3569 enable_relax_ifc = relax & enable_relax_ifc;
3572 enable_relax_ex9 = relax;
3575 enable_relax_ifc = relax;
3583 *input_line_pointer = saved_char;
3584 ignore_rest_of_line ();
3587 /* Record which arguments register($r0 ~ $r5) is not used in callee.
3591 nds32_set_hint_func_args (int ignore ATTRIBUTE_UNUSED)
3593 ignore_rest_of_line ();
3596 /* Insert relocations to mark the begin and end of a fp-omitted function,
3597 for further relaxation use.
3601 nds32_omit_fp_begin (int mode)
3605 if (nds32_relax_fp_as_gp == 0)
3607 exp.X_op = O_symbol;
3608 exp.X_add_symbol = abs_section_sym;
3612 exp.X_add_number = R_NDS32_RELAX_REGION_OMIT_FP_FLAG;
3613 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
3614 BFD_RELOC_NDS32_RELAX_REGION_BEGIN);
3619 exp.X_add_number = R_NDS32_RELAX_REGION_OMIT_FP_FLAG;
3620 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
3621 BFD_RELOC_NDS32_RELAX_REGION_END);
3625 /* Insert relocations to mark the begin and end of ex9 region,
3626 for further relaxation use.
3630 nds32_no_ex9_begin (int mode)
3634 exp.X_op = O_symbol;
3635 exp.X_add_symbol = abs_section_sym;
3638 exp.X_add_number = R_NDS32_RELAX_REGION_NO_EX9_FLAG;
3639 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
3640 BFD_RELOC_NDS32_RELAX_REGION_BEGIN);
3644 exp.X_add_number = R_NDS32_RELAX_REGION_NO_EX9_FLAG;
3645 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
3646 BFD_RELOC_NDS32_RELAX_REGION_END);
3651 nds32_loop_begin (int mode)
3653 /* Insert loop region relocation here. */
3656 exp.X_op = O_symbol;
3657 exp.X_add_symbol = abs_section_sym;
3660 exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG;
3661 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
3662 BFD_RELOC_NDS32_RELAX_REGION_BEGIN);
3666 exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG;
3667 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
3668 BFD_RELOC_NDS32_RELAX_REGION_END);
3672 struct nds32_relocs_group
3674 struct nds32_relocs_pattern *pattern;
3675 struct nds32_relocs_group *next;
3678 static struct nds32_relocs_group *nds32_relax_hint_current = NULL;
3680 /* Insert a relax hint. */
3683 nds32_relax_hint (int mode ATTRIBUTE_UNUSED)
3687 struct nds32_relocs_pattern *relocs = NULL;
3688 struct nds32_relocs_group *group, *new;
3690 name = input_line_pointer;
3691 while (*input_line_pointer && !ISSPACE (*input_line_pointer))
3692 input_line_pointer++;
3693 saved_char = *input_line_pointer;
3694 *input_line_pointer = 0;
3695 name = strdup (name);
3697 /* Find relax hint entry for next instruction, and all member will be
3698 initialized at that time. */
3699 relocs = hash_find (nds32_hint_hash, name);
3702 relocs = XNEW (struct nds32_relocs_pattern);
3703 hash_insert (nds32_hint_hash, name, relocs);
3707 while (relocs->next)
3708 relocs=relocs->next;
3709 relocs->next = XNEW (struct nds32_relocs_pattern);
3710 relocs = relocs->next;
3713 relocs->next = NULL;
3714 *input_line_pointer = saved_char;
3715 ignore_rest_of_line ();
3717 /* Get the final one of relax hint series. */
3719 /* It has to build this list because there are maybe more than one
3720 instructions relative to the same instruction. It to connect to
3721 next instruction after md_assemble. */
3722 new = XNEW (struct nds32_relocs_group);
3723 new->pattern = relocs;
3725 group = nds32_relax_hint_current;
3727 nds32_relax_hint_current = new;
3730 while (group->next != NULL)
3731 group = group->next;
3737 /* Decide the size of vector entries, only accepts 4 or 16 now. */
3740 nds32_vec_size (int ignore ATTRIBUTE_UNUSED)
3746 if (exp.X_op == O_constant)
3748 if (exp.X_add_number == 4 || exp.X_add_number == 16)
3751 vec_size = exp.X_add_number;
3752 else if (vec_size != exp.X_add_number)
3753 as_warn (_("Different arguments of .vec_size are found, "
3754 "previous %d, current %d"),
3755 (int) vec_size, (int) exp.X_add_number);
3758 as_warn (_("Argument of .vec_size is expected 4 or 16, actual: %d."),
3759 (int) exp.X_add_number);
3762 as_warn (_("Argument of .vec_size is not a constant."));
3765 /* The behavior of ".flag" directive varies depending on the target.
3766 In nds32 target, we use it to recognize whether this assembly content is
3767 generated by compiler. Other features can also be added in this function
3771 nds32_flag (int ignore ATTRIBUTE_UNUSED)
3776 const char *possible_flags[] = { "verbatim" };
3778 /* Skip whitespaces. */
3779 name = input_line_pointer;
3780 while (*input_line_pointer && !ISSPACE (*input_line_pointer))
3781 input_line_pointer++;
3782 saved_char = *input_line_pointer;
3783 *input_line_pointer = 0;
3785 for (i = 0; i < (int) ARRAY_SIZE (possible_flags); i++)
3787 if (strcmp (name, possible_flags[i]) == 0)
3792 /* flag: verbatim */
3798 /* Already found the flag, no need to continue next loop. */
3803 *input_line_pointer = saved_char;
3804 ignore_rest_of_line ();
3808 nds32_n12hc (int ignore ATTRIBUTE_UNUSED)
3810 /* N1213HC core is used. */
3814 /* The target specific pseudo-ops which we support. */
3815 const pseudo_typeS md_pseudo_table[] =
3817 /* Forced alignment if declared these ways. */
3818 {"ascii", stringer, 8 + 0},
3819 {"asciz", stringer, 8 + 1},
3820 {"double", nds32_aligned_float_cons, 'd'},
3821 {"dword", nds32_aligned_cons, 3},
3822 {"float", nds32_aligned_float_cons, 'f'},
3823 {"half", nds32_aligned_cons, 1},
3824 {"hword", nds32_aligned_cons, 1},
3825 {"int", nds32_aligned_cons, 2},
3826 {"long", nds32_aligned_cons, 2},
3827 {"octa", nds32_aligned_cons, 4},
3828 {"quad", nds32_aligned_cons, 3},
3829 {"qword", nds32_aligned_cons, 4},
3830 {"short", nds32_aligned_cons, 1},
3831 {"byte", nds32_aligned_cons, 0},
3832 {"single", nds32_aligned_float_cons, 'f'},
3833 {"string", stringer, 8 + 1},
3834 {"word", nds32_aligned_cons, 2},
3836 {"little", set_endian_little, 1},
3837 {"big", set_endian_little, 0},
3838 {"16bit_on", trigger_16bit, 1},
3839 {"16bit_off", trigger_16bit, 0},
3840 {"restore_16bit", restore_16bit, 0},
3841 {"off_16bit", off_16bit, 0},
3843 {"sdata_d", nds32_seg, SDATA_D_SECTION},
3844 {"sdata_w", nds32_seg, SDATA_W_SECTION},
3845 {"sdata_h", nds32_seg, SDATA_H_SECTION},
3846 {"sdata_b", nds32_seg, SDATA_B_SECTION},
3847 {"sdata_f", nds32_seg, SDATA_F_SECTION},
3849 {"sbss_d", nds32_seg, SBSS_D_SECTION},
3850 {"sbss_w", nds32_seg, SBSS_W_SECTION},
3851 {"sbss_h", nds32_seg, SBSS_H_SECTION},
3852 {"sbss_b", nds32_seg, SBSS_B_SECTION},
3853 {"sbss_f", nds32_seg, SBSS_F_SECTION},
3855 {"pic", nds32_enable_pic, 0},
3856 {"n12_hc", nds32_n12hc, 0},
3857 {"abi_1", nds32_set_abi, E_NDS_ABI_V1},
3858 {"abi_2", nds32_set_abi, E_NDS_ABI_AABI},
3860 {"abi_2fp", nds32_set_abi, E_NDS_ABI_V2FP},
3861 {"abi_2fp_plus", nds32_set_abi, E_NDS_ABI_V2FP_PLUS},
3862 {"relax", nds32_relax_relocs, 1},
3863 {"no_relax", nds32_relax_relocs, 0},
3864 {"hint_func_args", nds32_set_hint_func_args, 0}, /* Abandon?? */
3865 {"omit_fp_begin", nds32_omit_fp_begin, 1},
3866 {"omit_fp_end", nds32_omit_fp_begin, 0},
3867 {"no_ex9_begin", nds32_no_ex9_begin, 1},
3868 {"no_ex9_end", nds32_no_ex9_begin, 0},
3869 {"vec_size", nds32_vec_size, 0},
3870 {"flag", nds32_flag, 0},
3871 {"innermost_loop_begin", nds32_loop_begin, 1},
3872 {"innermost_loop_end", nds32_loop_begin, 0},
3873 {"relax_hint", nds32_relax_hint, 0},
3878 nds32_pre_do_align (int n, char *fill, int len, int max)
3880 /* Only make a frag if we HAVE to... */
3882 if (n != 0 && !need_pass_2)
3886 if (subseg_text_p (now_seg))
3888 dwarf2_emit_insn (0);
3890 frag_align_code (n, max);
3892 /* Tag this alignment when there is a lable before it. */
3895 fragP->tc_frag_data.flag = NDS32_FRAG_LABEL;
3900 frag_align (n, 0, max);
3903 frag_align (n, *fill, max);
3905 frag_align_pattern (n, fill, len, max);
3910 nds32_do_align (int n)
3912 /* Optimize for space and label exists. */
3915 /* FIXME:I think this will break debug info sections and except_table. */
3916 if (!enable_relax_relocs || !subseg_text_p (now_seg))
3919 /* Create and attach a BFD_RELOC_NDS32_LABEL fixup
3920 the size of instruction may not be correct because
3921 it could be relaxable. */
3922 exp.X_op = O_symbol;
3923 exp.X_add_symbol = section_symbol (now_seg);
3924 exp.X_add_number = n;
3925 fix_new_exp (frag_now,
3926 frag_now_fix (), 0, &exp, 0, BFD_RELOC_NDS32_LABEL);
3929 /* Supported Andes machines. */
3932 enum bfd_architecture bfd_mach;
3936 /* This is the callback for nds32-asm.c to parse operands. */
3939 nds32_asm_parse_operand (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED,
3940 struct nds32_asm_insn *pinsn,
3941 char **pstr, int64_t *value)
3944 expressionS *pexp = pinsn->info;
3946 hold = input_line_pointer;
3947 input_line_pointer = *pstr;
3949 *pstr = input_line_pointer;
3950 input_line_pointer = hold;
3956 return NASM_R_SYMBOL;
3958 *value = pexp->X_add_number;
3959 return NASM_R_CONST;
3964 return NASM_R_ILLEGAL;
3968 /* GAS will call this function at the start of the assembly, after the command
3969 line arguments have been parsed and all the machine independent
3970 initializations have been completed. */
3975 struct nds32_keyword *k;
3978 bfd_set_arch_mach (stdoutput, TARGET_ARCH, nds32_baseline);
3980 nds32_init_nds32_pseudo_opcodes ();
3981 asm_desc.parse_operand = nds32_asm_parse_operand;
3982 nds32_asm_init (&asm_desc, 0);
3984 /* Initial general pupose registers hash table. */
3985 nds32_gprs_hash = hash_new ();
3986 for (k = keyword_gpr; k->name; k++)
3987 hash_insert (nds32_gprs_hash, k->name, k);
3989 /* Initial branch hash table. */
3990 nds32_relax_info_hash = hash_new ();
3991 for (i = 0; i < ARRAY_SIZE (relax_table); i++)
3992 hash_insert (nds32_relax_info_hash, relax_table[i].opcode,
3995 /* Initial relax hint hash table. */
3996 nds32_hint_hash = hash_new ();
3997 enable_16bit = nds32_16bit_ext;
4000 /* HANDLE_ALIGN in write.c. */
4003 nds32_handle_align (fragS *fragp)
4005 static const unsigned char nop16[] = { 0x92, 0x00 };
4006 static const unsigned char nop32[] = { 0x40, 0x00, 0x00, 0x09 };
4010 if (fragp->fr_type != rs_align_code)
4013 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
4014 p = fragp->fr_literal + fragp->fr_fix;
4025 exp_t.X_op = O_symbol;
4026 exp_t.X_add_symbol = abs_section_sym;
4027 exp_t.X_add_number = R_NDS32_INSN16_CONVERT_FLAG;
4028 fix_new_exp (fragp, fragp->fr_fix, 2, &exp_t, 0,
4029 BFD_RELOC_NDS32_INSN16);
4030 memcpy (p, nop16, 2);
4037 memcpy (p, nop32, 4);
4042 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
4043 fragp->fr_fix += bytes;
4046 /* md_flush_pending_output */
4049 nds32_flush_pending_output (void)
4051 nds32_last_label = NULL;
4055 nds32_frob_label (symbolS *label)
4057 dwarf2_emit_label (label);
4060 /* TC_START_LABEL */
4063 nds32_start_label (int asmdone ATTRIBUTE_UNUSED, int secdone ATTRIBUTE_UNUSED)
4065 if (optimize && subseg_text_p (now_seg))
4073 nds32_target_format (void)
4076 if (target_big_endian)
4077 return "elf32-nds32be-linux";
4079 return "elf32-nds32le-linux";
4081 if (target_big_endian)
4082 return "elf32-nds32be";
4084 return "elf32-nds32le";
4088 static enum nds32_br_range
4089 get_range_type (const struct nds32_field *field)
4091 gas_assert (field != NULL);
4093 if (field->bitpos != 0)
4094 return BR_RANGE_U4G;
4096 if (field->bitsize == 24 && field->shift == 1)
4097 return BR_RANGE_S16M;
4098 else if (field->bitsize == 16 && field->shift == 1)
4099 return BR_RANGE_S64K;
4100 else if (field->bitsize == 14 && field->shift == 1)
4101 return BR_RANGE_S16K;
4102 else if (field->bitsize == 8 && field->shift == 1)
4103 return BR_RANGE_S256;
4105 return BR_RANGE_U4G;
4108 /* Save pseudo instruction relocation list. */
4110 static struct nds32_relocs_pattern*
4111 nds32_elf_save_pseudo_pattern (fixS* fixP, struct nds32_opcode *opcode,
4112 char *out, symbolS *sym,
4113 struct nds32_relocs_pattern *reloc_ptr,
4117 reloc_ptr = XNEW (struct nds32_relocs_pattern);
4118 reloc_ptr->seg = now_seg;
4119 reloc_ptr->sym = sym;
4120 reloc_ptr->frag = fragP;
4121 reloc_ptr->frchain = frchain_now;
4122 reloc_ptr->fixP = fixP;
4123 reloc_ptr->opcode = opcode;
4124 reloc_ptr->where = out;
4125 reloc_ptr->next = NULL;
4129 /* Check X_md to transform relocation. */
4132 nds32_elf_record_fixup_exp (fragS *fragP, const char *str,
4133 const struct nds32_field *fld,
4134 expressionS *pexp, char* out,
4135 struct nds32_asm_insn *insn)
4141 /* Handle instruction relocation. */
4142 if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_HI20))
4144 /* Relocation for hi20 modifier. */
4147 case BFD_RELOC_NDS32_GOTOFF: /* @GOTOFF */
4148 reloc = BFD_RELOC_NDS32_GOTOFF_HI20;
4150 case BFD_RELOC_NDS32_GOT20: /* @GOT */
4151 reloc = BFD_RELOC_NDS32_GOT_HI20;
4153 case BFD_RELOC_NDS32_25_PLTREL: /* @PLT */
4155 as_bad (_("Invalid PIC expression."));
4157 reloc = BFD_RELOC_NDS32_PLT_GOTREL_HI20;
4159 case BFD_RELOC_NDS32_GOTPC20: /* _GLOBAL_OFFSET_TABLE_ */
4160 reloc = BFD_RELOC_NDS32_GOTPC_HI20;
4162 case BFD_RELOC_NDS32_TPOFF: /* @TPOFF */
4163 reloc = BFD_RELOC_NDS32_TLS_LE_HI20;
4165 case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */
4166 reloc = BFD_RELOC_NDS32_TLS_IE_HI20;
4168 default: /* No suffix. */
4169 reloc = BFD_RELOC_NDS32_HI20;
4172 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4173 insn->info, 0 /* pcrel */, reloc);
4175 else if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_LO12))
4177 /* Relocation for lo12 modifier. */
4178 if (fld->bitsize == 15 && fld->shift == 0)
4183 case BFD_RELOC_NDS32_GOTOFF: /* @GOTOFF */
4184 reloc = BFD_RELOC_NDS32_GOTOFF_LO12;
4186 case BFD_RELOC_NDS32_GOT20: /* @GOT */
4187 reloc = BFD_RELOC_NDS32_GOT_LO12;
4189 case BFD_RELOC_NDS32_25_PLTREL: /* @PLT */
4191 as_bad (_("Invalid PIC expression."));
4193 reloc = BFD_RELOC_NDS32_PLT_GOTREL_LO12;
4195 case BFD_RELOC_NDS32_GOTPC20: /* _GLOBAL_OFFSET_TABLE_ */
4196 reloc = BFD_RELOC_NDS32_GOTPC_LO12;
4198 case BFD_RELOC_NDS32_TPOFF: /* @TPOFF */
4199 reloc = BFD_RELOC_NDS32_TLS_LE_LO12;
4201 default: /* No suffix. */
4202 reloc = BFD_RELOC_NDS32_LO12S0;
4206 else if (fld->bitsize == 15 && fld->shift == 1)
4207 reloc = BFD_RELOC_NDS32_LO12S1; /* [ls]hi */
4208 else if (fld->bitsize == 15 && fld->shift == 2)
4213 case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */
4214 reloc = BFD_RELOC_NDS32_TLS_IE_LO12S2;
4216 default: /* No suffix. */
4217 reloc = BFD_RELOC_NDS32_LO12S2;
4221 else if (fld->bitsize == 15 && fld->shift == 3)
4222 reloc = BFD_RELOC_NDS32_LO12S3; /* [ls]di */
4223 else if (fld->bitsize == 12 && fld->shift == 2)
4224 reloc = R_NDS32_LO12S2_SP_RELA; /* f[ls][sd]i */
4226 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4227 insn->info, 0 /* pcrel */, reloc);
4229 else if (fld && fld->bitpos == 0 && insn->opcode->isize == 4
4230 && (insn->attr & NASM_ATTR_PCREL))
4232 /* Relocation for 32-bit branch instructions. */
4233 if (fld->bitsize == 24 && fld->shift == 1)
4234 reloc = BFD_RELOC_NDS32_25_PCREL;
4235 else if (fld->bitsize == 16 && fld->shift == 1)
4236 reloc = BFD_RELOC_NDS32_17_PCREL;
4237 else if (fld->bitsize == 14 && fld->shift == 1)
4238 reloc = BFD_RELOC_NDS32_15_PCREL;
4239 else if (fld->bitsize == 8 && fld->shift == 1)
4240 reloc = BFD_RELOC_NDS32_WORD_9_PCREL;
4244 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4245 insn->info, 1 /* pcrel */, reloc);
4247 else if (fld && fld->bitpos == 0 && insn->opcode->isize == 4
4248 && (insn->attr & NASM_ATTR_GPREL))
4250 /* Relocation for 32-bit gp-relative instructions. */
4251 if (fld->bitsize == 19 && fld->shift == 0)
4252 reloc = BFD_RELOC_NDS32_SDA19S0;
4253 else if (fld->bitsize == 18 && fld->shift == 1)
4254 reloc = BFD_RELOC_NDS32_SDA18S1;
4255 else if (fld->bitsize == 17 && fld->shift == 2)
4256 reloc = BFD_RELOC_NDS32_SDA17S2;
4260 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4261 insn->info, 0 /* pcrel */, reloc);
4262 /* Insert INSN16 for converting fp_as_gp. */
4263 exp.X_op = O_symbol;
4264 exp.X_add_symbol = abs_section_sym;
4265 exp.X_add_number = 0;
4266 if (in_omit_fp && reloc == BFD_RELOC_NDS32_SDA17S2)
4267 fix_new_exp (fragP, out - fragP->fr_literal,
4268 insn->opcode->isize, &exp, 0 /* pcrel */,
4269 BFD_RELOC_NDS32_INSN16);
4271 else if (fld && fld->bitpos == 0 && insn->opcode->isize == 2
4272 && (insn->attr & NASM_ATTR_PCREL))
4274 /* Relocation for 16-bit branch instructions. */
4275 if (fld->bitsize == 8 && fld->shift == 1)
4276 reloc = BFD_RELOC_NDS32_9_PCREL;
4280 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4281 insn->info, 1 /* pcrel */, reloc);
4283 else if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_IFC_EXT))
4285 /* Relocation for ifcall instruction. */
4286 if (insn->opcode->isize == 2 && fld->bitsize == 9 && fld->shift == 1)
4287 reloc = BFD_RELOC_NDS32_10IFCU_PCREL;
4288 else if (insn->opcode->isize == 4 && fld->bitsize == 16
4290 reloc = BFD_RELOC_NDS32_17IFC_PCREL;
4294 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4295 insn->info, 1 /* pcrel */, reloc);
4298 as_bad (_("Don't know how to handle this field. %s"), str);
4303 /* Build instruction pattern to relax. There are two type group pattern
4304 including pseudo instruction and relax hint. */
4307 nds32_elf_build_relax_relation (fixS *fixP, expressionS *pexp, char* out,
4308 struct nds32_opcode *opcode, fragS *fragP,
4309 const struct nds32_field *fld)
4311 struct nds32_relocs_pattern *reloc_ptr;
4312 struct nds32_relocs_group *group;
4313 symbolS *sym = NULL;
4315 /* The expression may be used uninitialized. */
4317 sym = pexp->X_add_symbol;
4321 /* Save instruction relation for pseudo instruction expanding pattern. */
4322 reloc_ptr = nds32_elf_save_pseudo_pattern (fixP, opcode, out, sym,
4325 relocs_list = reloc_ptr;
4328 struct nds32_relocs_pattern *temp = relocs_list;
4331 temp->next = reloc_ptr;
4334 else if (nds32_relax_hint_current)
4336 /* Save instruction relation by relax hint. */
4337 group = nds32_relax_hint_current;
4340 nds32_elf_save_pseudo_pattern (fixP, opcode, out, sym,
4341 group->pattern, fragP);
4342 group = group->next;
4343 free (nds32_relax_hint_current);
4344 nds32_relax_hint_current = group;
4348 /* Set relaxing false only for relax_hint trigger it. */
4353 #define N32_MEM_EXT(insn) ((N32_OP6_MEM << 25) | insn)
4355 /* Relax pattern for link time relaxation. */
4357 static struct nds32_relax_hint_table relax_ls_table[] =
4360 /* Set address: la -> sethi ori. */
4361 NDS32_RELAX_HINT_LA, /* main_type */
4362 8, /* relax_code_size */
4366 }, /* relax_code_seq */
4368 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
4369 {4, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_INSN16}
4373 /* Set address: l.w -> sethi ori. */
4374 NDS32_RELAX_HINT_LS, /* main_type */
4375 8, /* relax_code_size */
4379 }, /* relax_code_seq */
4381 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
4382 {4, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_INSN16}
4393 /* Since sethi loadstore relocation has to using next instruction to determine
4394 elimination itself or not, we have to return the next instruction range. */
4397 nds32_elf_sethi_range (struct nds32_relocs_pattern *pattern)
4402 switch (pattern->opcode->value)
4407 case N32_MEM_EXT (N32_MEM_LB):
4408 case N32_MEM_EXT (N32_MEM_LBS):
4409 case N32_MEM_EXT (N32_MEM_SB):
4410 range = NDS32_LOADSTORE_BYTE;
4415 case N32_MEM_EXT (N32_MEM_LH):
4416 case N32_MEM_EXT (N32_MEM_LHS):
4417 case N32_MEM_EXT (N32_MEM_SH):
4418 range = NDS32_LOADSTORE_HALF;
4422 case N32_MEM_EXT (N32_MEM_LW):
4423 case N32_MEM_EXT (N32_MEM_SW):
4424 range = NDS32_LOADSTORE_WORD;
4428 range = NDS32_LOADSTORE_FLOAT_S;
4432 range = NDS32_LOADSTORE_FLOAT_D;
4435 range = NDS32_LOADSTORE_IMM;
4438 range = NDS32_LOADSTORE_NONE;
4441 if (range != NDS32_LOADSTORE_NONE)
4443 pattern = pattern->next;
4448 /* The args means: instruction size, the 1st instruction is converted to 16 or
4449 not, optimize option, 16 bit instruction is enable. */
4450 #define SET_ADDEND(size, convertible, optimize, insn16_on) \
4451 (((size) & 0xff) | ((convertible) ? 1 << 31 : 0) \
4452 | ((optimize) ? 1<< 30 : 0) | (insn16_on ? 1 << 29 : 0))
4455 nds32_set_elf_flags_by_insn (struct nds32_asm_insn * insn)
4457 /* Set E_NDS32_HAS_EXT_INST. */
4458 if (insn->opcode->attr & NASM_ATTR_PERF_EXT)
4461 nds32_elf_flags |= E_NDS32_HAS_EXT_INST;
4463 as_bad (_("instruction %s requires enabling performance extension"),
4464 insn->opcode->opcode);
4466 else if (insn->opcode->attr & NASM_ATTR_PERF2_EXT)
4468 if (nds32_perf_ext2)
4469 nds32_elf_flags |= E_NDS32_HAS_EXT2_INST;
4471 as_bad (_("instruction %s requires enabling performance extension II"),
4472 insn->opcode->opcode);
4474 else if (insn->opcode->attr & NASM_ATTR_AUDIO_ISAEXT)
4476 if (nds32_audio_ext)
4477 nds32_elf_flags |= E_NDS32_HAS_AUDIO_INST;
4479 as_bad (_("instruction %s requires enabling AUDIO extension"),
4480 insn->opcode->opcode);
4482 else if (insn->opcode->attr & NASM_ATTR_STR_EXT)
4484 if (nds32_string_ext)
4485 nds32_elf_flags |= E_NDS32_HAS_STRING_INST;
4487 as_bad (_("instruction %s requires enabling STRING extension"),
4488 insn->opcode->opcode);
4490 else if ((insn->opcode->attr & NASM_ATTR_DIV)
4491 && (insn->opcode->attr & NASM_ATTR_DXREG))
4493 if (nds32_div && nds32_dx_regs)
4494 nds32_elf_flags |= E_NDS32_HAS_DIV_DX_INST;
4496 as_bad (_("instruction %s requires enabling DIV & DX_REGS extension"),
4497 insn->opcode->opcode);
4499 else if (insn->opcode->attr & NASM_ATTR_FPU)
4501 if (nds32_fpu_sp_ext || nds32_fpu_dp_ext)
4503 if (!(nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST)))
4507 as_bad (_("instruction %s requires enabling FPU extension"),
4508 insn->opcode->opcode);
4510 else if (insn->opcode->attr & NASM_ATTR_FPU_SP_EXT)
4512 if (nds32_fpu_sp_ext)
4513 nds32_elf_flags |= E_NDS32_HAS_FPU_INST;
4515 as_bad (_("instruction %s requires enabling FPU_SP extension"),
4516 insn->opcode->opcode);
4518 else if ((insn->opcode->attr & NASM_ATTR_FPU_SP_EXT)
4519 && (insn->opcode->attr & NASM_ATTR_MAC))
4521 if (nds32_fpu_sp_ext && nds32_mac)
4523 nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST;
4524 nds32_elf_flags |= E_NDS32_HAS_FPU_INST;
4527 as_bad (_("instruction %s requires enabling FPU_MAC extension"),
4528 insn->opcode->opcode);
4530 else if (insn->opcode->attr & NASM_ATTR_FPU_DP_EXT)
4532 if (nds32_fpu_dp_ext)
4533 nds32_elf_flags |= E_NDS32_HAS_FPU_DP_INST;
4535 as_bad (_("instruction %s requires enabling FPU_DP extension"),
4536 insn->opcode->opcode);
4538 else if ((insn->opcode->attr & NASM_ATTR_FPU_DP_EXT)
4539 && (insn->opcode->attr & NASM_ATTR_MAC))
4541 if (nds32_fpu_dp_ext && nds32_mac)
4543 nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST;
4544 nds32_elf_flags |= E_NDS32_HAS_FPU_DP_INST;
4547 as_bad (_("instruction %s requires enabling FPU_MAC extension"),
4548 insn->opcode->opcode);
4550 /* TODO: FPU_BOTH */
4551 else if ((insn->opcode->attr & NASM_ATTR_MAC)
4552 && (insn->opcode->attr & NASM_ATTR_DXREG))
4554 if (nds32_mac && nds32_dx_regs)
4555 nds32_elf_flags |= E_NDS32_HAS_MAC_DX_INST;
4557 as_bad (_("instruction %s requires enabling DX_REGS extension"),
4558 insn->opcode->opcode);
4560 /* TODO: for DX_REG set but not for MAC, DIV, AUDIO */
4561 else if (insn->opcode->attr & NASM_ATTR_IFC_EXT)
4563 nds32_elf_flags |= E_NDS32_HAS_IFC_INST;
4565 /* TODO: E_NDS32_HAS_SATURATION_INST */
4568 /* Flag for analysis relaxation type. */
4570 enum nds32_insn_type
4572 N32_RELAX_SETHI = 1,
4573 N32_RELAX_BR = (1 << 1),
4574 N32_RELAX_LSI = (1 << 2),
4575 N32_RELAX_JUMP = (1 << 3),
4576 N32_RELAX_CALL = (1 << 4),
4577 N32_RELAX_ORI = (1 << 5),
4578 N32_RELAX_MEM = (1 << 6),
4579 N32_RELAX_MOVI = (1 << 7),
4582 struct nds32_hint_map
4584 bfd_reloc_code_real_type hi_type;
4586 enum nds32_relax_hint_type hint_type;
4587 enum nds32_br_range range;
4588 enum nds32_insn_type insn_list;
4591 /* Table to match instructions with hint and relax pattern. */
4593 static struct nds32_hint_map hint_map [] =
4597 BFD_RELOC_NDS32_HI20,
4599 NDS32_RELAX_HINT_NONE,
4601 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL
4605 _dummy_first_bfd_reloc_code_real,
4607 NDS32_RELAX_HINT_NONE,
4609 N32_RELAX_BR | N32_RELAX_CALL
4613 BFD_RELOC_NDS32_HI20,
4615 NDS32_RELAX_HINT_NONE,
4617 N32_RELAX_BR | N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL
4621 BFD_RELOC_NDS32_HI20,
4623 NDS32_RELAX_HINT_NONE,
4625 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_JUMP
4629 /* There is two kinds of veriation of LONGJUMP5. One of them
4630 generate EMPTY relocation for converted INSN16 if needed.
4631 But we don't distinguish them here. */
4632 _dummy_first_bfd_reloc_code_real,
4634 NDS32_RELAX_HINT_NONE,
4636 N32_RELAX_BR | N32_RELAX_JUMP
4640 BFD_RELOC_NDS32_HI20,
4642 NDS32_RELAX_HINT_NONE,
4644 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_BR | N32_RELAX_JUMP
4648 _dummy_first_bfd_reloc_code_real,
4650 NDS32_RELAX_HINT_NONE,
4652 N32_RELAX_MOVI | N32_RELAX_BR
4655 /* LOADSTORE ADDRESS. */
4656 BFD_RELOC_NDS32_HI20,
4658 NDS32_RELAX_HINT_LA,
4660 N32_RELAX_SETHI | N32_RELAX_ORI
4663 /* LOADSTORE ADDRESS. */
4664 BFD_RELOC_NDS32_HI20,
4666 NDS32_RELAX_HINT_LS,
4668 N32_RELAX_SETHI | N32_RELAX_LSI
4673 /* Find the relaxation pattern according to instructions. */
4676 nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern,
4677 struct nds32_relax_hint_table *hint_info)
4679 unsigned int opcode, seq_size;
4680 enum nds32_br_range range;
4681 struct nds32_relocs_pattern *pattern, *hi_pattern = NULL;
4682 const char *opc = NULL;
4683 relax_info_t *relax_info = NULL;
4684 nds32_relax_fixup_info_t *fixup_info, *hint_fixup;
4685 enum nds32_relax_hint_type hint_type = NDS32_RELAX_HINT_NONE;
4686 struct nds32_relax_hint_table *table_ptr;
4687 uint32_t *code_seq, *hint_code;
4688 enum nds32_insn_type relax_type = 0;
4689 struct nds32_hint_map *map_ptr = hint_map;
4691 const char *check_insn[] =
4692 { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8" };
4694 /* TODO: PLT GOT. */
4695 /* Traverse all pattern instruction and set flag. */
4696 pattern = relocs_pattern;
4699 if (pattern->opcode->isize == 4)
4701 /* 4 byte instruction. */
4702 opcode = N32_OP6 (pattern->opcode->value);
4706 hi_pattern = pattern;
4707 relax_type |= N32_RELAX_SETHI;
4710 relax_type |= N32_RELAX_MEM;
4713 relax_type |= N32_RELAX_ORI;
4718 relax_type |= N32_RELAX_BR;
4721 relax_type |= N32_RELAX_MOVI;
4733 relax_type |= N32_RELAX_LSI;
4736 if (__GF (pattern->opcode->value, 0, 1) == 1)
4737 relax_type |= N32_RELAX_CALL;
4739 relax_type |= N32_RELAX_JUMP;
4742 if (__GF (pattern->opcode->value, 24, 1) == 1)
4743 relax_type |= N32_RELAX_CALL;
4745 relax_type |= N32_RELAX_JUMP;
4748 as_warn (_("relax hint unrecognized instruction: line %d."),
4749 pattern->frag->fr_line);
4755 /* 2 byte instruction. Compare by opcode name because the opcode of
4756 2byte instruction is not regular. */
4757 for (i = 0; i < sizeof (check_insn) / sizeof (check_insn[0]); i++)
4759 if (strcmp (pattern->opcode->opcode, check_insn[i]) == 0)
4761 relax_type |= N32_RELAX_BR;
4765 if (strcmp (pattern->opcode->opcode, "movi55") == 0)
4766 relax_type |= N32_RELAX_MOVI;
4768 pattern = pattern->next;
4771 /* Analysis instruction flag to choose relaxation table. */
4772 while (map_ptr->insn_list != 0)
4774 if (map_ptr->insn_list == relax_type
4776 || (hi_pattern->fixP
4777 && hi_pattern->fixP->fx_r_type == map_ptr->hi_type)))
4780 hint_type = map_ptr->hint_type;
4781 range = map_ptr->range;
4787 if (map_ptr->insn_list == 0)
4789 as_warn (_("Can not find match relax hint. line : %d"),
4790 relocs_pattern->frag->fr_line);
4794 /* Get the match table. */
4797 /* Branch relax pattern. */
4798 relax_info = hash_find (nds32_relax_info_hash, opc);
4801 fixup_info = relax_info->relax_fixup[range];
4802 code_seq = relax_info->relax_code_seq[range];
4803 seq_size = relax_info->relax_code_size[range];
4807 /* Load-store relax pattern. */
4808 table_ptr = relax_ls_table;
4809 while (table_ptr->main_type != 0)
4811 if (table_ptr->main_type == hint_type)
4813 fixup_info = table_ptr->relax_fixup;
4814 code_seq = table_ptr->relax_code_seq;
4815 seq_size = table_ptr->relax_code_size;
4820 if (table_ptr->main_type == 0)
4826 hint_fixup = hint_info->relax_fixup;
4827 hint_code = hint_info->relax_code_seq;
4828 hint_info->relax_code_size = seq_size;
4830 while (fixup_info->size != 0)
4832 if (fixup_info->ramp & NDS32_HINT)
4834 memcpy (hint_fixup, fixup_info, sizeof (nds32_relax_fixup_info_t));
4839 /* Clear final relocation. */
4840 memset (hint_fixup, 0, sizeof (nds32_relax_fixup_info_t));
4841 /* Copy code sequance. */
4842 memcpy (hint_code, code_seq, seq_size);
4846 /* Because there are a lot of variant of load-store, check
4847 all these type here. */
4849 #define CLEAN_REG(insn) ((insn) & 0xff0003ff)
4851 nds32_match_hint_insn (struct nds32_opcode *opcode, uint32_t seq)
4853 const char *check_insn[] =
4854 { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8" };
4855 uint32_t insn = opcode->value;
4858 insn = CLEAN_REG (opcode->value);
4865 /* In relocation_table, it regards instruction LBI as representation
4866 of all the NDS32_RELAX_HINT_LS pattern. */
4867 if (insn == OP6 (LBI) || insn == OP6 (SBI) || insn == OP6 (LBSI)
4868 || insn == OP6 (LHI) || insn == OP6 (SHI) || insn == OP6 (LHSI)
4869 || insn == OP6 (LWI) || insn == OP6 (SWI)
4870 || insn == OP6 (LWC) || insn == OP6 (SWC))
4874 /* This is for LONGCALL5 and LONGCALL6. */
4875 if (insn == OP6 (BR2))
4879 /* This is for LONGJUMP5 and LONGJUMP6. */
4880 if (opcode->isize == 4
4881 && (insn == OP6 (BR1) || insn == OP6 (BR2) || insn == OP6 (BR3)))
4883 else if (opcode->isize == 2)
4885 for (i = 0; i < sizeof (check_insn) / sizeof (check_insn[0]); i++)
4886 if (strcmp (opcode->opcode, check_insn[i]) == 0)
4891 /* This is for LONGJUMP7. */
4892 if (opcode->isize == 2 && strcmp (opcode->opcode, "movi55") == 0)
4899 /* Append relax relocation for link time relaxing. */
4902 nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value)
4904 struct nds32_relocs_pattern *relocs_pattern =
4905 (struct nds32_relocs_pattern *) value;
4906 struct nds32_relocs_pattern *pattern_temp, *pattern_now;
4907 symbolS *sym, *hi_sym = NULL;
4910 segT seg_bak = now_seg;
4911 frchainS *frchain_bak = frchain_now;
4912 struct nds32_relax_hint_table hint_info;
4913 nds32_relax_fixup_info_t *hint_fixup, *fixup_now;
4915 offsetT branch_offset;
4918 unsigned int ptr_offset, hint_count, relax_code_size, count = 0;
4919 uint32_t *code_seq, code_insn;
4923 if (!relocs_pattern)
4926 if (!nds32_find_reloc_table (relocs_pattern, &hint_info))
4929 /* Save symbol for some EMPTY relocation using. */
4930 pattern_now = relocs_pattern;
4933 if (pattern_now->opcode->value == OP6 (SETHI))
4935 hi_sym = pattern_now->sym;
4938 pattern_now = pattern_now->next;
4941 /* Inserting fix up must specify now_seg or frchain_now. */
4942 now_seg = relocs_pattern->seg;
4943 frchain_now = relocs_pattern->frchain;
4944 fragP = relocs_pattern->frag;
4945 branch_offset = fragP->fr_offset;
4947 hint_fixup = hint_info.relax_fixup;
4948 code_seq = hint_info.relax_code_seq;
4949 relax_code_size = hint_info.relax_code_size;
4950 pattern_now = relocs_pattern;
4952 /* Insert relaxation. */
4953 exp.X_op = O_symbol;
4957 /* Choose the match fixup by instruction. */
4958 code_insn = CLEAN_REG (*(code_seq + count));
4959 if (!nds32_match_hint_insn (pattern_now->opcode, code_insn))
4962 code_insn = CLEAN_REG (*(code_seq + count));
4964 while (!nds32_match_hint_insn (pattern_now->opcode, code_insn))
4967 if (count >= relax_code_size / 4)
4969 as_bad (_("Internal error: Relax hint error. %s: %x"),
4970 now_seg->name, pattern_now->opcode->value);
4973 code_insn = CLEAN_REG (*(code_seq + count));
4976 fragP = pattern_now->frag;
4977 sym = pattern_now->sym;
4978 branch_offset = fragP->fr_offset;
4980 where = pattern_now->where;
4981 /* Find the instruction map fix. */
4982 fixup_now = hint_fixup;
4983 while (fixup_now->offset != offset)
4986 if (fixup_now->size == 0)
4989 /* This element is without relaxation relocation. */
4990 if (fixup_now->size == 0)
4992 pattern_now = pattern_now->next;
4995 fixup_size = fixup_now->size;
4997 /* Insert all fixup. */
4998 while (fixup_size != 0 && fixup_now->offset == offset)
5000 /* Set the real instruction size in element. */
5001 fixup_size = pattern_now->opcode->isize;
5002 pcrel = ((fixup_now->ramp & NDS32_PCREL) != 0) ? 1 : 0;
5003 if (fixup_now->ramp & NDS32_FIX)
5005 /* Convert original relocation. */
5006 pattern_now->fixP->fx_r_type = fixup_now->r_type ;
5009 else if ((fixup_now->ramp & NDS32_PTR) != 0)
5011 /* This relocation has to point to another instruction. Make
5012 sure each resolved relocation has to be pointed. */
5013 pattern_temp = relocs_pattern;
5014 /* All instruction in relax_table should be 32-bit. */
5015 hint_count = hint_info.relax_code_size / 4;
5016 code_insn = CLEAN_REG (*(code_seq + hint_count - 1));
5017 while (pattern_temp)
5019 /* Point to every resolved relocation. */
5020 if (nds32_match_hint_insn (pattern_temp->opcode, code_insn))
5023 pattern_temp->where - pattern_temp->frag->fr_literal;
5024 exp.X_add_symbol = symbol_temp_new (now_seg, ptr_offset,
5025 pattern_temp->frag);
5026 exp.X_add_number = 0;
5028 fix_new_exp (fragP, where - fragP->fr_literal,
5029 fixup_size, &exp, 0, fixup_now->r_type);
5030 fixP->fx_addnumber = fixP->fx_offset;
5032 pattern_temp = pattern_temp->next;
5036 else if (fixup_now->ramp & NDS32_ADDEND)
5038 range = nds32_elf_sethi_range (relocs_pattern);
5039 if (range == NDS32_LOADSTORE_NONE)
5041 as_bad (_("Internal error: Range error. %s"), now_seg->name);
5044 exp.X_add_symbol = abs_section_sym;
5045 exp.X_add_number = SET_ADDEND (4, 0, optimize, enable_16bit);
5046 exp.X_add_number |= ((range & 0x3f) << 8);
5048 else if ((fixup_now->ramp & NDS32_ABS) != 0)
5050 /* This is a tag relocation. */
5051 exp.X_add_symbol = abs_section_sym;
5052 exp.X_add_number = 0;
5054 else if ((fixup_now->ramp & NDS32_INSN16) != 0)
5058 /* This is a tag relocation. */
5059 exp.X_add_symbol = abs_section_sym;
5060 exp.X_add_number = 0;
5062 else if ((fixup_now->ramp & NDS32_SYM) != 0)
5064 /* For EMPTY relocation save the true symbol. */
5065 exp.X_add_symbol = hi_sym;
5066 exp.X_add_number = branch_offset;
5070 exp.X_add_symbol = sym;
5071 exp.X_add_number = branch_offset;
5074 if (fixup_size != 0)
5076 fixP = fix_new_exp (fragP, where - fragP->fr_literal, fixup_size,
5077 &exp, pcrel, fixup_now->r_type);
5078 fixP->fx_addnumber = fixP->fx_offset;
5081 fixup_size = fixup_now->size;
5083 if (count < relax_code_size / 4)
5085 pattern_now = pattern_now->next;
5090 frchain_now = frchain_bak;
5093 /* Check instruction if it can be used for the baseline. */
5096 nds32_check_insn_available (struct nds32_asm_insn insn, const char *str)
5098 int attr = insn.attr & ATTR_ALL;
5099 static int baseline_isa = 0;
5100 /* No isa setting or all isa can use. */
5101 if (attr == 0 || attr == ATTR_ALL)
5104 if (baseline_isa == 0)
5106 /* Map option baseline and instruction attribute. */
5107 switch (nds32_baseline)
5110 baseline_isa = ATTR (ISA_V2);
5113 baseline_isa = ATTR (ISA_V3);
5116 baseline_isa = ATTR (ISA_V3M);
5121 if ((baseline_isa & attr) == 0)
5123 as_bad (_("Not support instrcution %s in the baseline."), str);
5129 /* Stub of machine dependent. */
5132 md_assemble (char *str)
5134 struct nds32_asm_insn insn;
5137 struct nds32_pseudo_opcode *popcode;
5138 const struct nds32_field *fld = NULL;
5141 struct nds32_relocs_pattern *relocs_temp;
5144 int label = label_exist;
5146 popcode = nds32_lookup_pseudo_opcode (str);
5147 /* Note that we need to check 'verbatim' and
5148 'opcode->physical_op'. If the assembly content is generated by
5149 compiler and this opcode is a physical instruction, there is no
5150 need to perform pseudo instruction expansion/transformation. */
5151 if (popcode && !(verbatim && popcode->physical_op))
5153 pseudo_opcode = TRUE;
5154 nds32_pseudo_opcode_wrapper (str, popcode);
5155 pseudo_opcode = FALSE;
5156 nds32_elf_append_relax_relocs (NULL, relocs_list);
5158 /* Free pseudo list. */
5159 relocs_temp = relocs_list;
5162 relocs_list = relocs_list->next;
5164 relocs_temp = relocs_list;
5172 asm_desc.result = NASM_OK;
5173 nds32_assemble (&asm_desc, &insn, str);
5175 switch (asm_desc.result)
5177 case NASM_ERR_UNKNOWN_OP:
5178 as_bad (_("Unrecognized opcode, %s."), str);
5180 case NASM_ERR_SYNTAX:
5181 as_bad (_("Incorrect syntax, %s."), str);
5183 case NASM_ERR_OPERAND:
5184 as_bad (_("Unrecognized operand/register, %s."), str);
5186 case NASM_ERR_OUT_OF_RANGE:
5187 as_bad (_("Operand out of range, %s."), str);
5189 case NASM_ERR_REG_REDUCED:
5190 as_bad (_("Prohibited register used for reduced-register, %s."), str);
5192 case NASM_ERR_JUNK_EOL:
5193 as_bad (_("Junk at end of line, %s."), str);
5197 gas_assert (insn.opcode);
5199 nds32_set_elf_flags_by_insn (&insn);
5201 gas_assert (insn.opcode->isize == 4 || insn.opcode->isize == 2);
5203 if (!nds32_check_insn_available (insn, str))
5206 /* Make sure the begining of text being 2-byte align. */
5207 nds32_adjust_label (1);
5209 /* Try to allocate the max size to guarantee relaxable same branch
5210 instructions in the same fragment. */
5211 frag_grow (NDS32_MAXCHAR);
5213 if (fld && (insn.attr & NASM_ATTR_BRANCH)
5214 && (pseudo_opcode || (insn.opcode->value != INSN_JAL
5215 && insn.opcode->value != INSN_J))
5216 && (!verbatim || pseudo_opcode))
5218 /* User assembly code branch relax for it. */
5219 /* If fld is not NULL, it is a symbol. */
5220 /* Branch msut relax to proper pattern in user assembly code exclude
5221 J and JAL. Keep these two in original type for users which wants
5222 to keep their size be fixed. In general, assembler does not convert
5223 instruction generated by compiler. But jump instruction may be
5224 truncated in text virtual model. For workaround, compiler generate
5225 pseudo jump to fix this issue currently. */
5227 /* Get branch range type. */
5228 dwarf2_emit_insn (0);
5229 enum nds32_br_range range_type;
5232 range_type = get_range_type (fld);
5234 out = frag_var (rs_machine_dependent, NDS32_MAXCHAR,
5235 0, /* VAR is un-used. */
5236 range_type, /* SUBTYPE is used as range type. */
5237 pexp->X_add_symbol, pexp->X_add_number, 0);
5239 fragP->fr_fix += insn.opcode->isize;
5240 fragP->tc_frag_data.opcode = insn.opcode;
5241 fragP->tc_frag_data.insn = insn.insn;
5242 if (insn.opcode->isize == 4)
5243 bfd_putb32 (insn.insn, out);
5244 else if (insn.opcode->isize == 2)
5245 bfd_putb16 (insn.insn, out);
5246 fragP->tc_frag_data.flag |= NDS32_FRAG_BRANCH;
5248 /* md_convert_frag will insert relocations. */
5250 else if (!relaxing && enable_16bit && (optimize || optimize_for_space)
5251 && ((!fld && !verbatim && insn.opcode->isize == 4
5252 && nds32_convert_32_to_16 (stdoutput, insn.insn, &insn_16, NULL))
5253 || (insn.opcode->isize == 2
5254 && nds32_convert_16_to_32 (stdoutput, insn.insn, NULL))))
5256 /* Record this one is relaxable. */
5258 dwarf2_emit_insn (0);
5261 out = frag_var (rs_machine_dependent,
5262 4, /* Max size is 32-bit instruction. */
5263 0, /* VAR is un-used. */
5264 0, pexp->X_add_symbol, pexp->X_add_number, 0);
5265 fragP->tc_frag_data.flag |= NDS32_FRAG_RELAXABLE_BRANCH;
5268 out = frag_var (rs_machine_dependent,
5269 4, /* Max size is 32-bit instruction. */
5270 0, /* VAR is un-used. */
5272 fragP->tc_frag_data.flag |= NDS32_FRAG_RELAXABLE;
5273 fragP->tc_frag_data.opcode = insn.opcode;
5274 fragP->tc_frag_data.insn = insn.insn;
5277 /* In original, we don't relax the instrucion with label on it,
5278 but this may cause some redundant nop16. Therefore, tag this
5279 relaxable instruction and relax it carefully. */
5281 fragP->tc_frag_data.flag |= NDS32_FRAG_LABEL;
5283 if (insn.opcode->isize == 4)
5284 bfd_putb16 (insn_16, out);
5285 else if (insn.opcode->isize == 2)
5286 bfd_putb16 (insn.insn, out);
5289 else if ((verbatim || !relaxing) && optimize && label)
5291 /* This instruction is with label. */
5293 out = frag_var (rs_machine_dependent, insn.opcode->isize,
5294 0, 0, NULL, 0, NULL);
5295 /* If this insturction is branch target, it is not relaxable. */
5296 fragP->tc_frag_data.flag = NDS32_FRAG_LABEL;
5297 fragP->tc_frag_data.opcode = insn.opcode;
5298 fragP->tc_frag_data.insn = insn.insn;
5299 fragP->fr_fix += insn.opcode->isize;
5300 if (insn.opcode->isize == 4)
5302 exp.X_op = O_symbol;
5303 exp.X_add_symbol = abs_section_sym;
5304 exp.X_add_number = 0;
5305 fixP = fix_new_exp (fragP, fragP->fr_fix - 4, 0, &exp,
5306 0, BFD_RELOC_NDS32_LABEL);
5308 fragP->tc_frag_data.flag = NDS32_FRAG_ALIGN;
5312 out = frag_more (insn.opcode->isize);
5314 if (insn.opcode->isize == 4)
5315 bfd_putb32 (insn.insn, out);
5316 if (insn.opcode->isize == 2)
5317 bfd_putb16 (insn.insn, out);
5319 dwarf2_emit_insn (insn.opcode->isize);
5321 /* Compiler generating code and user assembly pseudo load-store, insert
5324 fixP = nds32_elf_record_fixup_exp (fragP, str, fld, pexp, out, &insn);
5325 /* Build relaxation pattern when relaxing is enable. */
5327 nds32_elf_build_relax_relation (fixP, pexp, out, insn.opcode, fragP, fld);
5330 /* md_macro_start */
5333 nds32_macro_start (void)
5340 nds32_macro_info (void *info ATTRIBUTE_UNUSED)
5347 nds32_macro_end (void)
5351 /* GAS will call this function with one argument, an expressionS pointer, for
5352 any expression that can not be recognized. When the function is called,
5353 input_line_pointer will point to the start of the expression. */
5356 md_operand (expressionS *expressionP)
5358 if (*input_line_pointer == '#')
5360 input_line_pointer++;
5361 expression (expressionP);
5365 /* GAS will call this function for each section at the end of the assembly, to
5366 permit the CPU back end to adjust the alignment of a section. The function
5367 must take two arguments, a segT for the section and a valueT for the size of
5368 the section, and return a valueT for the rounded size. */
5371 md_section_align (segT segment, valueT size)
5373 int align = bfd_get_section_alignment (stdoutput, segment);
5375 return ((size + (1 << align) - 1) & -(1 << align));
5378 /* GAS will call this function when a symbol table lookup fails, before it
5379 creates a new symbol. Typically this would be used to supply symbols whose
5380 name or value changes dynamically, possibly in a context sensitive way.
5381 Predefined symbols with fixed values, such as register names or condition
5382 codes, are typically entered directly into the symbol table when md_begin
5383 is called. One argument is passed, a char * for the symbol. */
5386 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
5392 nds32_calc_branch_offset (segT segment, fragS *fragP,
5393 long stretch ATTRIBUTE_UNUSED,
5394 relax_info_t *relax_info,
5395 enum nds32_br_range branch_range_type)
5397 struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
5398 symbolS *branch_symbol = fragP->fr_symbol;
5399 offsetT branch_offset = fragP->fr_offset;
5400 offsetT branch_target_address;
5401 offsetT branch_insn_address;
5404 if ((S_GET_SEGMENT (branch_symbol) != segment)
5405 || S_IS_WEAK (branch_symbol))
5407 /* The symbol is not in the SEGMENT. It could be far far away. */
5408 offset = 0x80000000;
5412 /* Calculate symbol-to-instruction offset. */
5413 branch_target_address = S_GET_VALUE (branch_symbol) + branch_offset;
5414 /* If the destination symbol is beyond current frag address,
5415 STRETCH will take effect to symbol's position. */
5416 if (S_GET_VALUE (branch_symbol) > fragP->fr_address)
5417 branch_target_address += stretch;
5419 branch_insn_address = fragP->fr_address + fragP->fr_fix;
5420 branch_insn_address -= opcode->isize;
5422 /* Update BRANCH_INSN_ADDRESS to relaxed position. */
5423 branch_insn_address += (relax_info->relax_code_size[branch_range_type]
5424 - relax_info->relax_branch_isize[branch_range_type]);
5426 offset = branch_target_address - branch_insn_address;
5432 static enum nds32_br_range
5433 nds32_convert_to_range_type (long offset)
5435 enum nds32_br_range range_type;
5437 if (-(0x100) <= offset && offset < 0x100) /* 256 bytes */
5438 range_type = BR_RANGE_S256;
5439 else if (-(0x4000) <= offset && offset < 0x4000) /* 16K bytes */
5440 range_type = BR_RANGE_S16K;
5441 else if (-(0x10000) <= offset && offset < 0x10000) /* 64K bytes */
5442 range_type = BR_RANGE_S64K;
5443 else if (-(0x1000000) <= offset && offset < 0x1000000) /* 16M bytes */
5444 range_type = BR_RANGE_S16M;
5446 range_type = BR_RANGE_U4G;
5451 /* Set insntruction register mask. */
5454 nds32_elf_get_set_cond (relax_info_t *relax_info, int offset, uint32_t *insn,
5455 uint32_t ori_insn, int range)
5457 nds32_cond_field_t *cond_fields = relax_info->cond_field;
5458 nds32_cond_field_t *code_seq_cond = relax_info->relax_code_condition[range];
5462 /* The instruction has conditions. Collect condition values. */
5463 while (code_seq_cond[i].bitmask != 0)
5465 if (offset == code_seq_cond[i].offset)
5467 mask = (ori_insn >> cond_fields[i].bitpos) & cond_fields[i].bitmask;
5469 if (cond_fields[i].signed_extend)
5470 mask = (mask ^ ((cond_fields[i].bitmask + 1) >> 1)) -
5471 ((cond_fields[i].bitmask + 1) >> 1);
5472 *insn |= (mask & code_seq_cond[i].bitmask) << code_seq_cond[i].bitpos;
5480 nds32_relax_branch_instructions (segT segment, fragS *fragP,
5481 long stretch ATTRIBUTE_UNUSED,
5484 enum nds32_br_range branch_range_type;
5485 struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
5487 enum nds32_br_range real_range_type;
5489 relax_info_t *relax_info;
5496 int code_seq_offset;
5498 /* Replace with gas_assert (fragP->fr_symbol != NULL); */
5499 if (fragP->fr_symbol == NULL)
5502 /* If frag_var is not enough room, the previos frag is fr_full and with
5503 opcode. The new one is rs_dependent but without opcode. */
5507 relax_info = hash_find (nds32_relax_info_hash, opcode->opcode);
5509 if (relax_info == NULL)
5513 branch_range_type = relax_info->br_range;
5515 branch_range_type = fragP->fr_subtype;
5517 offset = nds32_calc_branch_offset (segment, fragP, stretch,
5518 relax_info, branch_range_type);
5520 real_range_type = nds32_convert_to_range_type (offset);
5522 /* If actual range is equal to instruction jump range, do nothing. */
5523 if (real_range_type == branch_range_type)
5526 /* Find out proper relaxation code sequence. */
5527 for (i = BR_RANGE_S256; i < BR_RANGE_NUM; i++)
5529 if (real_range_type <= (unsigned int) i)
5532 diff = relax_info->relax_code_size[i] - opcode->isize;
5534 diff = relax_info->relax_code_size[i]
5535 - relax_info->relax_code_size[branch_range_type];
5537 /* If the instruction could be converted to 16-bits,
5538 minus the difference. */
5539 code_seq_offset = 0;
5542 code_seq_size = relax_info->relax_code_size[i];
5543 code_seq = relax_info->relax_code_seq[i];
5544 while (code_seq_offset < code_seq_size)
5547 if (insn & 0x80000000) /* 16-bits instruction. */
5551 else /* 32-bits instruction. */
5555 while (relax_info->relax_fixup[i][k].size !=0
5556 && relax_info->relax_fixup[i][k].offset < code_seq_offset)
5560 code_seq_offset += insn_size;
5564 /* Update fr_subtype to new NDS32_BR_RANGE. */
5565 fragP->fr_subtype = i;
5570 return diff + adjust;
5573 /* Adjust relaxable frag till current frag. */
5576 nds32_adjust_relaxable_frag (fragS *startP, fragS *fragP)
5579 if (startP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
5584 startP->tc_frag_data.flag ^= NDS32_FRAG_RELAXED;
5588 startP = startP->fr_next;
5591 startP->fr_address += adj;
5592 if (startP == fragP)
5600 nds32_get_align (addressT address, int align)
5602 addressT mask, new_address;
5604 mask = ~((~0U) << align);
5605 new_address = (address + mask) & (~mask);
5606 return (new_address - address);
5609 /* Check the prev_frag is legal. */
5611 invalid_prev_frag (fragS * fragP, fragS **prev_frag)
5614 fragS *frag_start = *prev_frag;
5619 if (frag_start->last_fr_address >= fragP->last_fr_address)
5625 fragS *frag_t = *prev_frag;
5626 while (frag_t != fragP)
5628 if (frag_t->fr_type == rs_align
5629 || frag_t->fr_type == rs_align_code
5630 || frag_t->fr_type == rs_align_test)
5632 /* Relax instruction can not walk across lable. */
5633 if (frag_t->tc_frag_data.flag & NDS32_FRAG_LABEL)
5638 /* Relax previos relaxable to align rs_align frag. */
5639 address = frag_t->fr_address + frag_t->fr_fix;
5640 addressT offset = nds32_get_align (address, (int) frag_t->fr_offset);
5643 /* If there is label on the prev_frag, check if it is aligned. */
5644 if (!((*prev_frag)->tc_frag_data.flag & NDS32_FRAG_LABEL)
5645 || (((*prev_frag)->fr_address + (*prev_frag)->fr_fix - 2 )
5647 nds32_adjust_relaxable_frag (*prev_frag, frag_t);
5652 frag_t = frag_t->fr_next;
5655 if (fragP->tc_frag_data.flag & NDS32_FRAG_ALIGN)
5657 address = fragP->fr_address;
5658 addressT offset = nds32_get_align (address, 2);
5661 /* If there is label on the prev_frag, check if it is aligned. */
5662 if (!((*prev_frag)->tc_frag_data.flag & NDS32_FRAG_LABEL)
5663 || (((*prev_frag)->fr_address + (*prev_frag)->fr_fix - 2 )
5665 nds32_adjust_relaxable_frag (*prev_frag, fragP);
5675 nds32_relax_frag (segT segment, fragS *fragP, long stretch ATTRIBUTE_UNUSED)
5677 /* Currently, there are two kinds of relaxation in nds32 assembler.
5679 2. relax for 32-bits to 16-bits */
5681 static fragS *prev_frag = NULL;
5684 invalid_prev_frag (fragP, &prev_frag);
5686 if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
5687 adjust = nds32_relax_branch_instructions (segment, fragP, stretch, 0);
5688 if (fragP->tc_frag_data.flag & NDS32_FRAG_LABEL)
5690 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE
5691 && (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED) == 0)
5692 /* Here is considered relaxed case originally. But it may cause
5693 unendless loop when relaxing. Once the instruction is relaxed,
5694 it can not be undo. */
5700 /* This function returns an initial guess of the length by which a fragment
5701 must grow to hold a branch to reach its destination. Also updates
5702 fr_type/fr_subtype as necessary.
5704 It is called just before doing relaxation. Any symbol that is now undefined
5705 will not become defined. The guess for fr_var is ACTUALLY the growth beyond
5706 fr_fix. Whatever we do to grow fr_fix or fr_var contributes to our returned
5707 value. Although it may not be explicit in the frag, pretend fr_var starts
5711 md_estimate_size_before_relax (fragS *fragP, segT segment)
5713 /* Currently, there are two kinds of relaxation in nds32 assembler.
5715 2. relax for 32-bits to 16-bits */
5717 /* Save previos relaxable frag. */
5718 static fragS *prev_frag = NULL;
5721 invalid_prev_frag (fragP, &prev_frag);
5723 if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
5724 adjust = nds32_relax_branch_instructions (segment, fragP, 0, 1);
5725 if (fragP->tc_frag_data.flag & NDS32_FRAG_LABEL)
5727 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
5729 else if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE)
5735 /* GAS will call this for each rs_machine_dependent fragment. The instruction
5736 is completed using the data from the relaxation pass. It may also create any
5737 necessary relocations.
5739 *FRAGP has been relaxed to its final size, and now needs to have the bytes
5740 inside it modified to conform to the new size. It is called after relaxation
5743 fragP->fr_type == rs_machine_dependent.
5744 fragP->fr_subtype is the subtype of what the address relaxed to. */
5747 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP)
5749 /* Convert branch relaxation instructions. */
5750 symbolS *branch_symbol = fragP->fr_symbol;
5751 offsetT branch_offset = fragP->fr_offset;
5752 enum nds32_br_range branch_range_type = fragP->fr_subtype;
5753 struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
5754 uint32_t origin_insn = fragP->tc_frag_data.insn;
5755 relax_info_t *relax_info;
5758 int addend ATTRIBUTE_UNUSED;
5759 offsetT branch_target_address, branch_insn_address;
5764 int code_size, insn_size, offset, fixup_size;
5765 int buf_offset, pcrel;
5768 nds32_relax_fixup_info_t fixup_info[MAX_RELAX_FIX];
5769 /* Save the 1st instruction is converted to 16 bit or not. */
5770 unsigned int branch_size;
5772 /* Replace with gas_assert (branch_symbol != NULL); */
5773 if (branch_symbol == NULL && !(fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED))
5776 /* If frag_var is not enough room, the previos frag is fr_full and with
5777 opcode. The new one is rs_dependent but without opcode. */
5781 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE_BRANCH)
5783 relax_info = hash_find (nds32_relax_info_hash, opcode->opcode);
5785 if (relax_info == NULL)
5789 while (i < BR_RANGE_NUM
5790 && relax_info->relax_code_size[i]
5791 != (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED ? 4 : 2))
5794 if (i >= BR_RANGE_NUM)
5795 as_bad ("Internal error: Cannot find relocation of"
5796 "relaxable branch.");
5798 exp.X_op = O_symbol;
5799 exp.X_add_symbol = branch_symbol;
5800 exp.X_add_number = branch_offset;
5801 pcrel = ((relax_info->relax_fixup[i][0].ramp & NDS32_PCREL) != 0) ? 1 : 0;
5802 fr_where = fragP->fr_fix - 2;
5803 fixP = fix_new_exp (fragP, fr_where, relax_info->relax_fixup[i][0].size,
5804 &exp, pcrel, relax_info->relax_fixup[i][0].r_type);
5805 fixP->fx_addnumber = fixP->fx_offset;
5807 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
5809 insn_16 = fragP->tc_frag_data.insn;
5810 nds32_convert_16_to_32 (stdoutput, insn_16, &insn);
5811 fr_buffer = fragP->fr_literal + fr_where;
5813 exp.X_op = O_symbol;
5814 exp.X_add_symbol = abs_section_sym;
5815 exp.X_add_number = 0;
5816 fix_new_exp (fragP, fr_where, 4,
5817 &exp, 0, BFD_RELOC_NDS32_INSN16);
5818 number_to_chars_bigendian (fr_buffer, insn, 4);
5821 else if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
5823 if (fragP->tc_frag_data.opcode->isize == 2)
5825 insn_16 = fragP->tc_frag_data.insn;
5826 nds32_convert_16_to_32 (stdoutput, insn_16, &insn);
5829 insn = fragP->tc_frag_data.insn;
5831 fr_where = fragP->fr_fix - 4;
5832 fr_buffer = fragP->fr_literal + fr_where;
5833 exp.X_op = O_symbol;
5834 exp.X_add_symbol = abs_section_sym;
5835 exp.X_add_number = 0;
5836 fix_new_exp (fragP, fr_where, 4, &exp, 0,
5837 BFD_RELOC_NDS32_INSN16);
5838 number_to_chars_bigendian (fr_buffer, insn, 4);
5840 else if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
5842 /* Branch instruction adjust and append relocations. */
5843 relax_info = hash_find (nds32_relax_info_hash, opcode->opcode);
5845 if (relax_info == NULL)
5848 fr_where = fragP->fr_fix - opcode->isize;
5849 fr_buffer = fragP->fr_literal + fr_where;
5851 if ((S_GET_SEGMENT (branch_symbol) != sec)
5852 || S_IS_WEAK (branch_symbol))
5854 if (fragP->fr_offset & 3)
5855 as_warn (_("Addend to unresolved symbol is not on word boundary."));
5860 /* Calculate symbol-to-instruction offset. */
5861 branch_target_address = S_GET_VALUE (branch_symbol) + branch_offset;
5862 branch_insn_address = fragP->fr_address + fr_where;
5863 addend = (branch_target_address - branch_insn_address) >> 1;
5866 code_size = relax_info->relax_code_size[branch_range_type];
5867 code_seq = relax_info->relax_code_seq[branch_range_type];
5869 memcpy (fixup_info, relax_info->relax_fixup[branch_range_type],
5870 sizeof (fixup_info));
5875 offset = 0; /* code_seq offset */
5876 buf_offset = 0; /* fr_buffer offset */
5877 while (offset < code_size)
5880 if (insn & 0x80000000) /* 16-bits instruction. */
5882 insn = (insn >> 16) & 0xFFFF;
5885 else /* 32-bits instruction. */
5890 nds32_elf_get_set_cond (relax_info, offset, &insn,
5891 origin_insn, branch_range_type);
5893 /* Try to convert to 16-bits instruction. Currently, only the first
5894 insntruction in pattern can be converted. EX: bnez sethi ori jr,
5895 only bnez can be converted to 16 bit and ori can't. */
5897 while (fixup_info[k].size != 0
5898 && relax_info->relax_fixup[branch_range_type][k].offset < offset)
5901 number_to_chars_bigendian (fr_buffer + buf_offset, insn, insn_size);
5902 buf_offset += insn_size;
5904 offset += insn_size;
5909 exp.X_op = O_symbol;
5911 for (i = 0; fixup_info[i].size != 0; i++)
5913 fixup_size = fixup_info[i].size;
5914 pcrel = ((fixup_info[i].ramp & NDS32_PCREL) != 0) ? 1 : 0;
5916 if ((fixup_info[i].ramp & NDS32_CREATE_LABEL) != 0)
5918 /* This is a reverse branch. */
5919 exp.X_add_symbol = symbol_temp_new (sec, 0, fragP->fr_next);
5920 exp.X_add_number = 0;
5922 else if ((fixup_info[i].ramp & NDS32_PTR) != 0)
5924 /* This relocation has to point to another instruction. */
5925 branch_size = fr_where + code_size - 4;
5926 exp.X_add_symbol = symbol_temp_new (sec, branch_size, fragP);
5927 exp.X_add_number = 0;
5929 else if ((fixup_info[i].ramp & NDS32_ABS) != 0)
5931 /* This is a tag relocation. */
5932 exp.X_add_symbol = abs_section_sym;
5933 exp.X_add_number = 0;
5935 else if ((fixup_info[i].ramp & NDS32_INSN16) != 0)
5939 /* This is a tag relocation. */
5940 exp.X_add_symbol = abs_section_sym;
5941 exp.X_add_number = 0;
5945 exp.X_add_symbol = branch_symbol;
5946 exp.X_add_number = branch_offset;
5949 if (fixup_info[i].r_type != 0)
5951 fixP = fix_new_exp (fragP, fr_where + fixup_info[i].offset,
5952 fixup_size, &exp, pcrel,
5953 fixup_info[i].r_type);
5954 fixP->fx_addnumber = fixP->fx_offset;
5958 fragP->fr_fix = fr_where + buf_offset;
5962 /* tc_frob_file_before_fix */
5965 nds32_frob_file_before_fix (void)
5970 nds32_relaxable_section (asection *sec)
5972 return ((sec->flags & SEC_DEBUGGING) == 0
5973 && strcmp (sec->name, ".eh_frame") != 0);
5976 /* TC_FORCE_RELOCATION */
5978 nds32_force_relocation (fixS * fix)
5980 switch (fix->fx_r_type)
5982 case BFD_RELOC_NDS32_INSN16:
5983 case BFD_RELOC_NDS32_LABEL:
5984 case BFD_RELOC_NDS32_LONGCALL1:
5985 case BFD_RELOC_NDS32_LONGCALL2:
5986 case BFD_RELOC_NDS32_LONGCALL3:
5987 case BFD_RELOC_NDS32_LONGJUMP1:
5988 case BFD_RELOC_NDS32_LONGJUMP2:
5989 case BFD_RELOC_NDS32_LONGJUMP3:
5990 case BFD_RELOC_NDS32_LOADSTORE:
5991 case BFD_RELOC_NDS32_9_FIXED:
5992 case BFD_RELOC_NDS32_15_FIXED:
5993 case BFD_RELOC_NDS32_17_FIXED:
5994 case BFD_RELOC_NDS32_25_FIXED:
5995 case BFD_RELOC_NDS32_9_PCREL:
5996 case BFD_RELOC_NDS32_15_PCREL:
5997 case BFD_RELOC_NDS32_17_PCREL:
5998 case BFD_RELOC_NDS32_WORD_9_PCREL:
5999 case BFD_RELOC_NDS32_10_UPCREL:
6000 case BFD_RELOC_NDS32_25_PCREL:
6001 case BFD_RELOC_NDS32_MINUEND:
6002 case BFD_RELOC_NDS32_SUBTRAHEND:
6008 case BFD_RELOC_NDS32_DIFF_ULEB128:
6009 /* Linker should handle difference between two symbol. */
6010 return fix->fx_subsy != NULL
6011 && nds32_relaxable_section (S_GET_SEGMENT (fix->fx_addsy));
6014 as_bad ("Double word for difference between two symbols "
6015 "is not supported across relaxation.");
6020 if (generic_force_reloc (fix))
6023 return fix->fx_pcrel;
6026 /* TC_VALIDATE_FIX_SUB */
6029 nds32_validate_fix_sub (fixS *fix, segT add_symbol_segment)
6031 segT sub_symbol_segment;
6033 /* This code is referred from Xtensa. Check their implementation for
6036 /* Make sure both symbols are in the same segment, and that segment is
6037 "normal" and relaxable. */
6038 sub_symbol_segment = S_GET_SEGMENT (fix->fx_subsy);
6039 return (sub_symbol_segment == add_symbol_segment
6040 && add_symbol_segment != undefined_section);
6044 md_number_to_chars (char *buf, valueT val, int n)
6046 if (target_big_endian)
6047 number_to_chars_bigendian (buf, val, n);
6049 number_to_chars_littleendian (buf, val, n);
6052 /* Equal to MAX_PRECISION in atof-ieee.c. */
6053 #define MAX_LITTLENUMS 6
6055 /* This function is called to convert an ASCII string into a floating point
6056 value in format used by the CPU. */
6059 md_atof (int type, char *litP, int *sizeP)
6063 LITTLENUM_TYPE words[MAX_LITTLENUMS];
6082 return _("Bad call to md_atof()");
6085 t = atof_ieee (input_line_pointer, type, words);
6087 input_line_pointer = t;
6088 *sizeP = prec * sizeof (LITTLENUM_TYPE);
6090 if (target_big_endian)
6092 for (i = 0; i < prec; i++)
6094 md_number_to_chars (litP, (valueT) words[i],
6095 sizeof (LITTLENUM_TYPE));
6096 litP += sizeof (LITTLENUM_TYPE);
6101 for (i = prec - 1; i >= 0; i--)
6103 md_number_to_chars (litP, (valueT) words[i],
6104 sizeof (LITTLENUM_TYPE));
6105 litP += sizeof (LITTLENUM_TYPE);
6112 /* md_elf_section_change_hook */
6115 nds32_elf_section_change_hook (void)
6122 nds32_cleanup (void)
6126 /* This function is used to scan leb128 subtraction expressions,
6127 and insert fixups for them.
6129 e.g., .leb128 .L1 - .L0
6131 These expressions are heavily used in debug information or
6132 exception tables. Because relaxation will change code size,
6133 we must resolve them in link time. */
6136 nds32_insert_leb128_fixes (bfd *abfd ATTRIBUTE_UNUSED,
6137 asection *sec, void *xxx ATTRIBUTE_UNUSED)
6139 segment_info_type *seginfo = seg_info (sec);
6142 subseg_set (sec, 0);
6144 for (fragP = seginfo->frchainP->frch_root;
6145 fragP; fragP = fragP->fr_next)
6149 /* Only unsigned leb128 can be handle. */
6150 if (fragP->fr_type != rs_leb128 || fragP->fr_subtype != 0
6151 || fragP->fr_symbol == NULL)
6154 exp = symbol_get_value_expression (fragP->fr_symbol);
6156 if (exp->X_op != O_subtract)
6159 fix_new_exp (fragP, fragP->fr_fix, 0,
6160 exp, 0, BFD_RELOC_NDS32_DIFF_ULEB128);
6165 nds32_insert_relax_entry (bfd *abfd ATTRIBUTE_UNUSED, asection *sec,
6166 void *xxx ATTRIBUTE_UNUSED)
6168 segment_info_type *seginfo;
6174 seginfo = seg_info (sec);
6175 if (!seginfo || !symbol_rootP || !subseg_text_p (sec) || sec->size == 0)
6177 /* If there is no relocation and relax is disabled, it is not necessary to
6178 insert R_NDS32_RELAX_ENTRY for linker do EX9 or IFC optimization. */
6179 for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
6182 if (!fixp && !enable_relax_ex9 && !verbatim)
6185 subseg_change (sec, 0);
6187 /* Set RELAX_ENTRY flags for linker. */
6188 fragP = seginfo->frchainP->frch_root;
6189 exp.X_op = O_symbol;
6190 exp.X_add_symbol = section_symbol (sec);
6191 exp.X_add_number = 0;
6192 if (!enable_relax_relocs)
6193 exp.X_add_number |= R_NDS32_RELAX_ENTRY_DISABLE_RELAX_FLAG;
6196 /* These flags are only enabled when global relax is enabled.
6197 Maybe we can check DISABLE_RELAX_FLAG at linke-time,
6198 so we set them anyway. */
6199 if (enable_relax_ex9)
6200 exp.X_add_number |= R_NDS32_RELAX_ENTRY_EX9_FLAG;
6201 if (enable_relax_ifc)
6202 exp.X_add_number |= R_NDS32_RELAX_ENTRY_IFC_FLAG;
6204 exp.X_add_number |= R_NDS32_RELAX_ENTRY_VERBATIM_FLAG;
6207 exp.X_add_number |= R_NDS32_RELAX_ENTRY_OPTIMIZE_FLAG;
6208 if (optimize_for_space)
6209 exp.X_add_number |= R_NDS32_RELAX_ENTRY_OPTIMIZE_FOR_SPACE_FLAG;
6211 fixP = fix_new_exp (fragP, 0, 0, &exp, 0, BFD_RELOC_NDS32_RELAX_ENTRY);
6212 fixP->fx_no_overflow = 1;
6215 /* Analysis relax hint and insert suitable relocation pattern. */
6218 nds32_elf_analysis_relax_hint (void)
6220 hash_traverse (nds32_hint_hash, nds32_elf_append_relax_relocs);
6224 nds32_elf_insert_final_frag (void)
6226 struct frchain *frchainP;
6233 for (s = stdoutput->sections; s; s = s->next)
6235 segment_info_type *seginfo = seg_info (s);
6239 for (frchainP = seginfo->frchainP; frchainP != NULL;
6240 frchainP = frchainP->frch_next)
6242 subseg_set (s, frchainP->frch_subseg);
6244 if (subseg_text_p (now_seg))
6247 frag_var (rs_machine_dependent, 2, /* Max size. */
6248 0, /* VAR is un-used. */ 0, NULL, 0, NULL);
6249 fragP->tc_frag_data.flag |= NDS32_FRAG_FINAL;
6258 nds32_elf_insert_final_frag ();
6259 nds32_elf_analysis_relax_hint ();
6260 bfd_map_over_sections (stdoutput, nds32_insert_leb128_fixes, NULL);
6263 /* Implement md_allow_local_subtract. */
6266 nds32_allow_local_subtract (expressionS *expr_l ATTRIBUTE_UNUSED,
6267 expressionS *expr_r ATTRIBUTE_UNUSED,
6268 segT sec ATTRIBUTE_UNUSED)
6270 /* Don't allow any subtraction, because relax may change the code. */
6274 /* Sort relocation by address.
6276 We didn't use qsort () in stdlib, because quick-sort is not a stable
6277 sorting algorithm. Relocations at the same address (r_offset) must keep
6278 their relative order. For example, RELAX_ENTRY must be the very first
6281 Currently, this function implements insertion-sort. */
6284 compar_relent (const void *lhs, const void *rhs)
6286 const arelent **l = (const arelent **) lhs;
6287 const arelent **r = (const arelent **) rhs;
6289 if ((*l)->address > (*r)->address)
6291 else if ((*l)->address == (*r)->address)
6297 /* SET_SECTION_RELOCS ()
6299 Although this macro is originally used to set a relocation for each section,
6300 we use it to sort relocations in the same section by the address of the
6304 nds32_set_section_relocs (asection *sec, arelent ** relocs ATTRIBUTE_UNUSED,
6305 unsigned int n ATTRIBUTE_UNUSED)
6307 bfd *abfd ATTRIBUTE_UNUSED = sec->owner;
6308 if (bfd_get_section_flags (abfd, sec) & (flagword) SEC_RELOC)
6309 nds32_insertion_sort (sec->orelocation, sec->reloc_count,
6310 sizeof (arelent**), compar_relent);
6314 nds32_pcrel_from_section (fixS *fixP, segT sec ATTRIBUTE_UNUSED)
6316 if (fixP->fx_addsy == NULL || !S_IS_DEFINED (fixP->fx_addsy)
6317 || S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy))
6319 /* Let linker resolve undefined symbols. */
6323 return fixP->fx_frag->fr_address + fixP->fx_where;
6326 /* md_post_relax_hook ()
6327 Insert relax entry relocation into sections. */
6330 nds32_post_relax_hook (void)
6332 bfd_map_over_sections (stdoutput, nds32_insert_relax_entry, NULL);
6335 /* tc_fix_adjustable ()
6337 Return whether this symbol (fixup) can be replaced with
6341 nds32_fix_adjustable (fixS *fixP)
6343 switch (fixP->fx_r_type)
6345 case BFD_RELOC_NDS32_WORD_9_PCREL:
6346 case BFD_RELOC_NDS32_9_PCREL:
6347 case BFD_RELOC_NDS32_15_PCREL:
6348 case BFD_RELOC_NDS32_17_PCREL:
6349 case BFD_RELOC_NDS32_25_PCREL:
6350 case BFD_RELOC_NDS32_HI20:
6351 case BFD_RELOC_NDS32_LO12S0:
6355 case BFD_RELOC_NDS32_PTR:
6356 case BFD_RELOC_NDS32_LONGCALL4:
6357 case BFD_RELOC_NDS32_LONGCALL5:
6358 case BFD_RELOC_NDS32_LONGCALL6:
6359 case BFD_RELOC_NDS32_LONGJUMP4:
6360 case BFD_RELOC_NDS32_LONGJUMP5:
6361 case BFD_RELOC_NDS32_LONGJUMP6:
6362 case BFD_RELOC_NDS32_LONGJUMP7:
6369 /* elf_tc_final_processing */
6372 elf_nds32_final_processing (void)
6374 /* An FPU_COM instruction is found without previous non-FPU_COM
6377 && !(nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST)))
6379 /* Since only FPU_COM instructions are used and no other FPU instructions
6380 are used. The nds32_elf_flags will be decided by the enabled options
6381 by command line or default configuration. */
6382 if (nds32_fpu_dp_ext || nds32_fpu_sp_ext)
6384 nds32_elf_flags |= nds32_fpu_dp_ext ? E_NDS32_HAS_FPU_DP_INST : 0;
6385 nds32_elf_flags |= nds32_fpu_sp_ext ? E_NDS32_HAS_FPU_INST : 0;
6389 /* Should never here. */
6390 as_bad (_("Used FPU instructions requires enabling FPU extension"));
6394 if (nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST))
6396 /* Single/double FPU has been used, set FPU register config. */
6397 /* We did not check the actual number of register used. We may
6398 want to do it while assemble. */
6399 nds32_elf_flags &= ~E_NDS32_FPU_REG_CONF;
6400 nds32_elf_flags |= (nds32_freg << E_NDS32_FPU_REG_CONF_SHIFT);
6404 nds32_elf_flags |= E_NDS32_HAS_PIC;
6407 nds32_elf_flags |= E_NDS32_HAS_REDUCED_REGS;
6409 nds32_elf_flags |= (E_NDS32_ELF_VER_1_4 | nds32_abi);
6410 elf_elfheader (stdoutput)->e_flags |= nds32_elf_flags;
6413 /* Implement md_apply_fix. Apply the fix-up or tranform the fix-up for
6414 later relocation generation. */
6417 nds32_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
6419 char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
6420 bfd_vma value = *valP;
6422 if (fixP->fx_r_type < BFD_RELOC_UNUSED
6423 && fixP->fx_r_type > BFD_RELOC_NONE
6424 && fixP->fx_r_type != BFD_RELOC_NDS32_DIFF_ULEB128)
6426 /* In our old nds32 binutils, it must convert relocations which is
6427 generated by CGEN. However, it does not have to consider this anymore.
6428 In current, it only deal with data relocations which enum
6429 is smaller than BFD_RELOC_NONE and BFD_RELOC_NDS32_DIFF_ULEB128.
6430 It is believed that we can construct a better mechanism to
6431 deal with the whole relocation issue in nds32 target
6432 without using CGEN. */
6433 fixP->fx_addnumber = value;
6434 fixP->tc_fix_data = NULL;
6436 /* Tranform specific relocations here for later relocation generation.
6437 Tag data here for ex9 relaxtion and tag tls data for linker. */
6438 switch (fixP->fx_r_type)
6440 case BFD_RELOC_NDS32_DATA:
6441 if (!enable_relax_ex9)
6444 case BFD_RELOC_NDS32_TPOFF:
6445 case BFD_RELOC_NDS32_TLS_LE_HI20:
6446 case BFD_RELOC_NDS32_TLS_LE_LO12:
6447 case BFD_RELOC_NDS32_TLS_LE_ADD:
6448 case BFD_RELOC_NDS32_TLS_LE_LS:
6449 case BFD_RELOC_NDS32_GOTTPOFF:
6450 case BFD_RELOC_NDS32_TLS_IE_HI20:
6451 case BFD_RELOC_NDS32_TLS_IE_LO12S2:
6452 S_SET_THREAD_LOCAL (fixP->fx_addsy);
6460 if (fixP->fx_addsy == (symbolS *) NULL)
6463 if (fixP->fx_subsy != (symbolS *) NULL)
6465 /* HOW DIFF RELOCATION WORKS.
6467 First of all, this relocation is used to calculate the distance
6468 between two symbols in the SAME section. It is used for jump-
6469 table, debug information, exception table, et al. Therefore,
6470 it is a unsigned positive value. It is NOT used for general-
6473 Consider this example, the distance between .LEND and .LBEGIN
6474 is stored at the address of foo.
6476 ---- >8 ---- >8 ---- >8 ---- >8 ----
6479 .word .LBEGIN - .LEND
6489 ---- 8< ---- 8< ---- 8< ---- 8< ----
6491 We use a single relocation entry for this expression.
6492 * The initial distance value is stored direcly in that location
6493 specified by r_offset (i.e., foo in this example.)
6494 * The begin of the region, i.e., .LBEGIN, is specified by
6495 r_info/R_SYM and r_addend, e.g., .text + 0x32.
6496 * The end of region, i.e., .LEND, is represented by
6497 .LBEGIN + distance instead of .LEND, so we only need
6498 a single relocation entry instead of two.
6500 When an instruction is relaxed, we adjust the relocation entry
6501 depending on where the instruction locates. There are three
6502 cases, before, after and between the region.
6503 * between: Distance value is read from r_offset, adjusted and
6504 written back into r_offset.
6505 * before: Only r_addend is adjust.
6506 * after: We don't care about it.
6508 Hereby, there are some limitation.
6510 `(.LEND - 1) - .LBEGIN' and `(.LEND - .LBEGIN) - 1'
6511 are semantically different, and we cannot handle latter case
6514 The latter expression means subtracting 1 from the distance
6515 between .LEND and .LBEGIN. And the former expression means
6516 the distance between (.LEND - 1) and .LBEGIN.
6518 The nuance affects whether to adjust distance value when relax
6519 an instruction. In another words, whether the instruction
6520 locates in the region. Because we use a single relocation entry,
6521 there is no field left for .LEND and the subtrahend.
6523 Since GCC-4.5, GCC may produce debug information in such expression
6525 in order to describe register clobbering during an function-call.
6530 Check http://gcc.gnu.org/ml/gcc-patches/2009-06/msg01317.html
6533 value -= S_GET_VALUE (fixP->fx_subsy);
6535 fixP->fx_subsy = NULL;
6536 fixP->fx_offset -= value;
6538 switch (fixP->fx_r_type)
6541 fixP->fx_r_type = BFD_RELOC_NDS32_DIFF8;
6542 md_number_to_chars (where, value, 1);
6545 fixP->fx_r_type = BFD_RELOC_NDS32_DIFF16;
6546 md_number_to_chars (where, value, 2);
6549 fixP->fx_r_type = BFD_RELOC_NDS32_DIFF32;
6550 md_number_to_chars (where, value, 4);
6552 case BFD_RELOC_NDS32_DIFF_ULEB128:
6553 /* cvt_frag_to_fill () has called output_leb128 () for us. */
6556 as_bad_where (fixP->fx_file, fixP->fx_line,
6557 _("expression too complex"));
6561 else if (fixP->fx_done)
6563 /* We're finished with this fixup. Install it because
6564 bfd_install_relocation won't be called to do it. */
6565 switch (fixP->fx_r_type)
6568 md_number_to_chars (where, value, 1);
6571 md_number_to_chars (where, value, 2);
6574 md_number_to_chars (where, value, 4);
6577 md_number_to_chars (where, value, 8);
6579 as_bad_where (fixP->fx_file, fixP->fx_line,
6580 _("Internal error: Unknown fixup type %d (`%s')"),
6582 bfd_get_reloc_code_name (fixP->fx_r_type));
6588 /* Implement tc_gen_reloc. Generate ELF relocation for a fix-up. */
6591 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
6594 bfd_reloc_code_real_type code;
6596 reloc = XNEW (arelent);
6598 reloc->sym_ptr_ptr = XNEW (asymbol *);
6599 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
6600 reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
6602 code = fixP->fx_r_type;
6604 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
6605 if (reloc->howto == (reloc_howto_type *) NULL)
6607 as_bad_where (fixP->fx_file, fixP->fx_line,
6608 _("internal error: can't export reloc type %d (`%s')"),
6609 fixP->fx_r_type, bfd_get_reloc_code_name (code));
6613 /* Add relocation handling here. */
6615 switch (fixP->fx_r_type)
6618 /* In general, addend of a relocation is the offset to the
6619 associated symbol. */
6620 reloc->addend = fixP->fx_offset;
6623 case BFD_RELOC_NDS32_DATA:
6624 /* Prevent linker from optimizing data in text sections.
6625 For example, jump table. */
6626 reloc->addend = fixP->fx_size;
6633 struct suffix_name suffix_table[] =
6635 {"GOTOFF", BFD_RELOC_NDS32_GOTOFF, 1},
6636 {"GOT", BFD_RELOC_NDS32_GOT20, 1},
6637 {"TPOFF", BFD_RELOC_NDS32_TPOFF, 0},
6638 {"PLT", BFD_RELOC_NDS32_25_PLTREL, 1},
6639 {"GOTTPOFF", BFD_RELOC_NDS32_GOTTPOFF, 0}
6642 /* Implement md_parse_name. */
6645 nds32_parse_name (char const *name, expressionS *exprP,
6646 enum expr_mode mode ATTRIBUTE_UNUSED,
6647 char *nextcharP ATTRIBUTE_UNUSED)
6651 exprP->X_op_symbol = NULL;
6652 exprP->X_md = BFD_RELOC_UNUSED;
6654 exprP->X_add_symbol = symbol_find_or_make (name);
6655 exprP->X_op = O_symbol;
6656 exprP->X_add_number = 0;
6658 /* Check the specail name if a symbol. */
6659 segment = S_GET_SEGMENT (exprP->X_add_symbol);
6660 if (segment != undefined_section)
6663 if (strcmp (name, GOT_NAME) == 0 && *nextcharP != '@')
6665 /* Set for _GOT_OFFSET_TABLE_. */
6666 exprP->X_md = BFD_RELOC_NDS32_GOTPC20;
6668 else if (*nextcharP == '@')
6672 for (i = 0; i < ARRAY_SIZE (suffix_table); i++)
6674 next = input_line_pointer + 1 + strlen(suffix_table[i].suffix);
6675 if (strncasecmp (input_line_pointer + 1, suffix_table[i].suffix,
6676 strlen (suffix_table[i].suffix)) == 0
6677 && !is_part_of_name (*next))
6679 if (!nds32_pic && suffix_table[i].pic)
6680 as_bad (_("need PIC qualifier with symbol."));
6681 exprP->X_md = suffix_table[i].reloc;
6682 *input_line_pointer = *nextcharP;
6683 input_line_pointer = next;
6684 *nextcharP = *input_line_pointer;
6685 *input_line_pointer = '\0';
6693 /* Implement tc_regname_to_dw2regnum. */
6696 tc_nds32_regname_to_dw2regnum (char *regname)
6698 struct nds32_keyword *sym = hash_find (nds32_gprs_hash, regname);
6707 tc_nds32_frame_initial_instructions (void)
6710 /* Default cfa is register-31/sp. */
6711 cfi_add_CFA_def_cfa (31, 0);