1 /* tc-nds32.c -- Assemble for the nds32
2 Copyright (C) 2012-2023 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 "opcode/nds32.h"
40 /* GAS definitions. */
42 /* Characters which start a comment. */
43 const char comment_chars
[] = "!";
44 /* Characters which start a comment when they appear at the start of a line. */
45 const char line_comment_chars
[] = "#!";
46 /* Characters which separate lines (null and newline are by default). */
47 const char line_separator_chars
[] = ";";
48 /* Characters which may be used as the exponent character
49 in a floating point number. */
50 const char EXP_CHARS
[] = "eE";
51 /* Characters which may be used to indicate a floating point constant. */
52 const char FLT_CHARS
[] = "dDfF";
54 static int enable_16bit
= 1;
55 /* Save for md_assemble to distinguish if this instruction is
56 expanded from the pseudo instruction. */
57 static bool pseudo_opcode
= false;
58 static struct nds32_relocs_pattern
*relocs_list
= NULL
;
59 /* Save instruction relation to inserting relaxation relocation. */
60 struct nds32_relocs_pattern
67 struct nds32_opcode
*opcode
;
69 struct nds32_relocs_pattern
*next
;
70 /* Assembled instruction bytes. */
74 /* Suffix name and relocation. */
78 short unsigned int reloc
;
80 static int vec_size
= 0;
81 /* If the assembly code is generated by compiler, it is supposed to have
82 ".flag verbatim" at beginning of the content. We have
83 'nds32_flag' to parse it and set this field to be non-zero. */
84 static int verbatim
= 0;
85 static htab_t nds32_gprs_hash
;
86 static htab_t nds32_hint_hash
;
87 #define TLS_REG "$r27"
88 #define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
90 /* Generate relocation for relax or not, and the default is true. */
91 static int enable_relax_relocs
= 1;
92 /* Save option -O for performance. */
93 static int optimize
= 0;
94 /* Save option -Os for code size. */
95 static int optimize_for_space
= 0;
96 /* Flag to save label exist. */
97 static int label_exist
= 0;
98 /* Flag to save state in omit_fp region. */
99 static int in_omit_fp
= 0;
100 /* Tag there is relax relocation having to link. */
101 static bool relaxing
= false;
108 static enum ict_option ict_flag
= ICT_NONE
;
111 static htab_t nds32_relax_info_hash
;
113 /* Branch patterns. */
114 static relax_info_t relax_table
[] =
118 .br_range
= BR_RANGE_S16M
,
123 .relax_code_seq
[BR_RANGE_S256
] =
125 INSN_JAL
/* jal label */
127 .relax_code_size
[BR_RANGE_S256
] = 4,
128 .relax_branch_isize
[BR_RANGE_S256
] = 4,
129 .relax_fixup
[BR_RANGE_S256
] =
131 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
135 .relax_code_seq
[BR_RANGE_S16K
] =
137 INSN_JAL
/* jal label */
139 .relax_code_size
[BR_RANGE_S16K
] = 4,
140 .relax_branch_isize
[BR_RANGE_S16K
] = 4,
141 .relax_fixup
[BR_RANGE_S16K
] =
143 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
147 .relax_code_seq
[BR_RANGE_S64K
] =
149 INSN_JAL
/* jal label */
151 .relax_code_size
[BR_RANGE_S64K
] = 4,
152 .relax_branch_isize
[BR_RANGE_S64K
] = 4,
153 .relax_fixup
[BR_RANGE_S64K
] =
155 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
159 .relax_code_seq
[BR_RANGE_S16M
] =
161 INSN_JAL
/* jal label */
163 .relax_code_size
[BR_RANGE_S16M
] = 4,
164 .relax_branch_isize
[BR_RANGE_S16M
] = 4,
165 .relax_fixup
[BR_RANGE_S16M
] =
167 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
171 .relax_code_seq
[BR_RANGE_U4G
] =
173 INSN_SETHI_TA
, /* sethi $ta, label */
174 INSN_ORI_TA
, /* ori $ta, $ta, label */
175 INSN_JRAL_TA
/* jral $ta */
177 .relax_code_size
[BR_RANGE_U4G
] = 12,
178 .relax_branch_isize
[BR_RANGE_U4G
] = 4,
179 .relax_fixup
[BR_RANGE_U4G
] =
181 {0, 4, 0, BFD_RELOC_NDS32_HI20
},
182 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGCALL4
},
183 {4, 4, NDS32_HINT
| NDS32_FIX
, BFD_RELOC_NDS32_LO12S0_ORI
},
184 {4, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
185 {8, 4, NDS32_ABS
| NDS32_HINT
, BFD_RELOC_NDS32_PTR_RESOLVED
},
186 {8, 4, NDS32_SYM
| NDS32_HINT
, BFD_RELOC_NDS32_EMPTY
},
187 {8, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
193 .br_range
= BR_RANGE_S64K
,
196 {0, 20, 0x1F, false},
199 .relax_code_seq
[BR_RANGE_S256
] =
201 INSN_BGEZAL
/* bgezal $rt, label */
203 .relax_code_condition
[BR_RANGE_S256
] =
205 {0, 20, 0x1F, false},
208 .relax_code_size
[BR_RANGE_S256
] = 4,
209 .relax_branch_isize
[BR_RANGE_S256
] = 4,
210 .relax_fixup
[BR_RANGE_S256
] =
212 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
216 .relax_code_seq
[BR_RANGE_S16K
] =
218 INSN_BGEZAL
/* bgezal $rt, label */
220 .relax_code_condition
[BR_RANGE_S16K
] =
222 {0, 20, 0x1F, false},
225 .relax_code_size
[BR_RANGE_S16K
] = 4,
226 .relax_branch_isize
[BR_RANGE_S16K
] = 4,
227 .relax_fixup
[BR_RANGE_S16K
] =
229 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
233 .relax_code_seq
[BR_RANGE_S64K
] =
235 INSN_BGEZAL
/* bgezal $rt, label */
237 .relax_code_condition
[BR_RANGE_S64K
] =
239 {0, 20, 0x1F, false},
242 .relax_code_size
[BR_RANGE_S64K
] = 4,
243 .relax_branch_isize
[BR_RANGE_S64K
] = 4,
244 .relax_fixup
[BR_RANGE_S64K
] =
246 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
250 .relax_code_seq
[BR_RANGE_S16M
] =
252 INSN_BLTZ
, /* bltz $rt, $1 */
253 INSN_JAL
/* jal label */
255 .relax_code_condition
[BR_RANGE_S16M
] =
257 {0, 20, 0x1F, false},
260 .relax_code_size
[BR_RANGE_S16M
] = 8,
261 .relax_branch_isize
[BR_RANGE_S16M
] = 4,
262 .relax_fixup
[BR_RANGE_S16M
] =
264 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
265 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGCALL5
},
266 {4, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
270 .relax_code_seq
[BR_RANGE_U4G
] =
272 INSN_BLTZ
, /* bltz $rt, $1 */
273 INSN_SETHI_TA
, /* sethi $ta, label */
274 INSN_ORI_TA
, /* ori $ta, $ta, label */
275 INSN_JRAL_TA
/* jral $ta */
277 .relax_code_condition
[BR_RANGE_U4G
] =
279 {0, 20, 0x1F, false},
282 .relax_code_size
[BR_RANGE_U4G
] = 16,
283 .relax_branch_isize
[BR_RANGE_U4G
] = 4,
284 .relax_fixup
[BR_RANGE_U4G
] =
286 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
287 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGCALL6
},
288 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
289 {4, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
290 {8, 4, NDS32_FIX
| NDS32_HINT
, BFD_RELOC_NDS32_LO12S0_ORI
},
291 {8, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
292 {12, 4, NDS32_ABS
| NDS32_HINT
, BFD_RELOC_NDS32_PTR_RESOLVED
},
293 {12, 4, NDS32_SYM
| NDS32_HINT
, BFD_RELOC_NDS32_EMPTY
},
294 {12, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
300 .br_range
= BR_RANGE_S64K
,
303 {0, 20, 0x1F, false},
306 .relax_code_seq
[BR_RANGE_S256
] =
308 INSN_BLTZAL
/* bltzal $rt, label */
310 .relax_code_condition
[BR_RANGE_S256
] =
312 {0, 20, 0x1F, false},
315 .relax_code_size
[BR_RANGE_S256
] = 4,
316 .relax_branch_isize
[BR_RANGE_S256
] = 4,
317 .relax_fixup
[BR_RANGE_S256
] =
319 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
323 .relax_code_seq
[BR_RANGE_S16K
] =
325 INSN_BLTZAL
/* bltzal $rt, label */
327 .relax_code_condition
[BR_RANGE_S16K
] =
329 {0, 20, 0x1F, false},
332 .relax_code_size
[BR_RANGE_S16K
] = 4,
333 .relax_branch_isize
[BR_RANGE_S16K
] = 4,
334 .relax_fixup
[BR_RANGE_S16K
] =
336 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
340 .relax_code_seq
[BR_RANGE_S64K
] =
342 INSN_BLTZAL
/* bltzal $rt, label */
344 .relax_code_condition
[BR_RANGE_S64K
] =
346 {0, 20, 0x1F, false},
349 .relax_code_size
[BR_RANGE_S64K
] = 4,
350 .relax_branch_isize
[BR_RANGE_S64K
] = 4,
351 .relax_fixup
[BR_RANGE_S64K
] =
353 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
357 .relax_code_seq
[BR_RANGE_S16M
] =
359 INSN_BGEZ
, /* bgez $rt, $1 */
360 INSN_JAL
/* jal label */
362 .relax_code_condition
[BR_RANGE_S16M
] =
364 {0, 20, 0x1F, false},
367 .relax_code_size
[BR_RANGE_S16M
] = 8,
368 .relax_branch_isize
[BR_RANGE_S16M
] = 4,
369 .relax_fixup
[BR_RANGE_S16M
] =
371 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
372 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGCALL5
},
373 {4, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
377 .relax_code_seq
[BR_RANGE_U4G
] =
379 INSN_BGEZ
, /* bgez $rt, $1 */
380 INSN_SETHI_TA
, /* sethi $ta, label */
381 INSN_ORI_TA
, /* ori $ta, $ta, label */
382 INSN_JRAL_TA
/* jral $ta */
384 .relax_code_condition
[BR_RANGE_U4G
] =
386 {0, 20, 0x1F, false},
389 .relax_code_size
[BR_RANGE_U4G
] = 16,
390 .relax_branch_isize
[BR_RANGE_U4G
] = 4,
391 .relax_fixup
[BR_RANGE_U4G
] =
393 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
394 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGCALL6
},
395 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
396 {4, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
397 {8, 4, NDS32_FIX
| NDS32_HINT
, BFD_RELOC_NDS32_LO12S0_ORI
},
398 {8, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
399 {12, 4, NDS32_ABS
| NDS32_HINT
, BFD_RELOC_NDS32_PTR_RESOLVED
},
400 {12, 4, NDS32_SYM
| NDS32_HINT
, BFD_RELOC_NDS32_EMPTY
},
401 {12, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
407 .br_range
= BR_RANGE_S16M
,
412 .relax_code_seq
[BR_RANGE_S256
] =
414 (INSN_J8
<< 16) /* j8 label */
416 .relax_code_size
[BR_RANGE_S256
] = 2,
417 .relax_branch_isize
[BR_RANGE_S256
] = 2,
418 .relax_fixup
[BR_RANGE_S256
] =
420 {0, 2, NDS32_PCREL
, BFD_RELOC_NDS32_9_PCREL
},
424 .relax_code_seq
[BR_RANGE_S16K
] =
428 . relax_code_size
[BR_RANGE_S16K
] = 4,
429 .relax_branch_isize
[BR_RANGE_S16K
] = 4,
430 .relax_fixup
[BR_RANGE_S16K
] =
432 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
436 .relax_code_seq
[BR_RANGE_S64K
] =
440 .relax_code_size
[BR_RANGE_S64K
] = 4,
441 .relax_branch_isize
[BR_RANGE_S64K
] = 4,
442 .relax_fixup
[BR_RANGE_S64K
] =
444 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
448 .relax_code_seq
[BR_RANGE_S16M
] =
452 .relax_code_size
[BR_RANGE_S16M
] = 4,
453 .relax_branch_isize
[BR_RANGE_S16M
] = 4,
454 .relax_fixup
[BR_RANGE_S16M
] =
456 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
460 .relax_code_seq
[BR_RANGE_U4G
] =
462 INSN_SETHI_TA
, /* sethi $ta, label */
463 INSN_ORI_TA
, /* ori $ta, $ta, label */
464 INSN_JR_TA
/* jr $ta */
466 .relax_code_size
[BR_RANGE_U4G
] = 12,
467 .relax_branch_isize
[BR_RANGE_U4G
] = 4,
468 .relax_fixup
[BR_RANGE_U4G
] =
470 {0, 4, 0, BFD_RELOC_NDS32_HI20
},
471 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP4
},
472 {4, 4, NDS32_HINT
| NDS32_FIX
, BFD_RELOC_NDS32_LO12S0_ORI
},
473 {4, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
474 {8, 4, NDS32_ABS
| NDS32_HINT
, BFD_RELOC_NDS32_PTR_RESOLVED
},
475 {8, 4, NDS32_SYM
| NDS32_HINT
, BFD_RELOC_NDS32_EMPTY
},
476 {8, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
482 .br_range
= BR_RANGE_S256
,
487 .relax_code_seq
[BR_RANGE_S256
] =
489 (INSN_J8
<< 16) /* j8 label */
491 .relax_code_size
[BR_RANGE_S256
] = 2,
492 .relax_branch_isize
[BR_RANGE_S256
] = 2,
493 .relax_fixup
[BR_RANGE_S256
] =
495 {0, 2, NDS32_PCREL
, BFD_RELOC_NDS32_9_PCREL
},
499 .relax_code_seq
[BR_RANGE_S16K
] =
503 .relax_code_size
[BR_RANGE_S16K
] = 4,
504 .relax_branch_isize
[BR_RANGE_S16K
] = 4,
505 .relax_fixup
[BR_RANGE_S16K
] =
507 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
511 .relax_code_seq
[BR_RANGE_S64K
] =
515 .relax_code_size
[BR_RANGE_S64K
] = 4,
516 .relax_branch_isize
[BR_RANGE_S64K
] = 4,
517 .relax_fixup
[BR_RANGE_S64K
] =
519 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
523 .relax_code_seq
[BR_RANGE_S16M
] =
527 .relax_code_size
[BR_RANGE_S16M
] = 4,
528 .relax_branch_isize
[BR_RANGE_S16M
] = 4,
529 .relax_fixup
[BR_RANGE_S16M
] =
531 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
535 .relax_code_seq
[BR_RANGE_U4G
] =
537 INSN_SETHI_TA
, /* sethi $ta, label */
538 INSN_ORI_TA
, /* ori $ta, $ta, label */
539 INSN_JR_TA
/* jr $ta */
541 .relax_code_size
[BR_RANGE_U4G
] = 12,
542 .relax_branch_isize
[BR_RANGE_U4G
] = 4,
543 .relax_fixup
[BR_RANGE_U4G
] =
545 {0, 4, 0, BFD_RELOC_NDS32_HI20
},
546 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP4
},
547 {4, 4, NDS32_HINT
| NDS32_FIX
, BFD_RELOC_NDS32_LO12S0_ORI
},
548 {4, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
549 {8, 4, NDS32_ABS
| NDS32_HINT
, BFD_RELOC_NDS32_PTR_RESOLVED
},
550 {8, 4, NDS32_SYM
| NDS32_HINT
, BFD_RELOC_NDS32_EMPTY
},
551 {8, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
557 .br_range
= BR_RANGE_S64K
,
560 {0, 20, 0x1F, false},
563 /* We do not use beqz38 and beqzs8 here directly because we
564 don't want to check register number for specail condition. */
565 .relax_code_seq
[BR_RANGE_S256
] =
567 INSN_BEQZ
/* beqz $rt, label */
569 .relax_code_condition
[BR_RANGE_S256
] =
571 {0, 20, 0x1F, false},
574 .relax_code_size
[BR_RANGE_S256
] = 4,
575 .relax_branch_isize
[BR_RANGE_S256
] = 4,
576 .relax_fixup
[BR_RANGE_S256
] =
578 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
579 {0, 4, NDS32_INSN16
, BFD_RELOC_NDS32_INSN16
},
583 .relax_code_seq
[BR_RANGE_S16K
] =
585 INSN_BEQZ
/* beqz $rt, label */
587 .relax_code_condition
[BR_RANGE_S16K
] =
589 {0, 20, 0x1F, false},
592 .relax_code_size
[BR_RANGE_S16K
] = 4,
593 .relax_branch_isize
[BR_RANGE_S16K
] = 4,
594 .relax_fixup
[BR_RANGE_S16K
] =
596 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
600 .relax_code_seq
[BR_RANGE_S64K
] =
602 INSN_BEQZ
/* beqz $rt, label */
604 .relax_code_condition
[BR_RANGE_S64K
] =
606 {0, 20, 0x1F, false},
609 .relax_code_size
[BR_RANGE_S64K
] = 4,
610 .relax_branch_isize
[BR_RANGE_S64K
] = 4,
611 .relax_fixup
[BR_RANGE_S64K
] =
613 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
617 .relax_code_seq
[BR_RANGE_S16M
] =
619 INSN_BNEZ
, /* bnez $rt, $1 */
622 .relax_code_condition
[BR_RANGE_S16M
] =
624 {0, 20, 0x1F, false},
627 .relax_code_size
[BR_RANGE_S16M
] = 8,
628 .relax_branch_isize
[BR_RANGE_S16M
] = 4,
629 .relax_fixup
[BR_RANGE_S16M
] =
631 /* bnez range is 17 pcrel, but it use 15 pcrel here since link time
632 relaxtion. If 17 pcrel can reach, it do not have to use S16M.
633 Therefore, 15 pcrel is just for linker to distinguish LONGJUMP5
635 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
636 {0, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
637 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP5
},
638 {4, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
639 {4, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
643 .relax_code_seq
[BR_RANGE_U4G
] =
645 INSN_BNEZ
, /* bnez $rt, $1 */
646 INSN_SETHI_TA
, /* sethi $ta, label */
647 INSN_ORI_TA
, /* ori $ta, $ta, label */
648 INSN_JR_TA
/* jr $ta */
650 .relax_code_condition
[BR_RANGE_U4G
] =
652 {0, 20, 0x1F, false},
655 .relax_code_size
[BR_RANGE_U4G
] = 16,
656 .relax_branch_isize
[BR_RANGE_U4G
] = 4,
657 .relax_fixup
[BR_RANGE_U4G
] =
659 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
660 {0, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
661 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP6
},
662 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
663 {4, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
664 {8, 4, NDS32_FIX
| NDS32_HINT
, BFD_RELOC_NDS32_LO12S0_ORI
},
665 {8, 4, NDS32_PTR
|NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
666 {12, 4, NDS32_ABS
| NDS32_HINT
, BFD_RELOC_NDS32_PTR_RESOLVED
},
667 {12, 4, NDS32_SYM
| NDS32_HINT
, BFD_RELOC_NDS32_EMPTY
},
668 {12, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
674 .br_range
= BR_RANGE_S64K
,
677 {0, 20, 0x1F, false},
680 .relax_code_seq
[BR_RANGE_S256
] =
682 INSN_BGEZ
/* bgez $rt, label */
684 .relax_code_condition
[BR_RANGE_S256
] =
686 {0, 20, 0x1F, false},
689 .relax_code_size
[BR_RANGE_S256
] = 4,
690 .relax_branch_isize
[BR_RANGE_S256
] = 4,
691 .relax_fixup
[BR_RANGE_S256
] =
693 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
697 .relax_code_seq
[BR_RANGE_S16K
] =
699 INSN_BGEZ
/* bgez $rt, label */
701 .relax_code_condition
[BR_RANGE_S16K
] =
703 {0, 20, 0x1F, false},
706 .relax_code_size
[BR_RANGE_S16K
] = 4,
707 .relax_branch_isize
[BR_RANGE_S16K
] = 4,
708 .relax_fixup
[BR_RANGE_S16K
] =
710 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
714 .relax_code_seq
[BR_RANGE_S64K
] =
716 INSN_BGEZ
/* bgez $rt, label */
718 .relax_code_condition
[BR_RANGE_S64K
] =
720 {0, 20, 0x1F, false},
723 .relax_code_size
[BR_RANGE_S64K
] = 4,
724 .relax_branch_isize
[BR_RANGE_S64K
] = 4,
725 .relax_fixup
[BR_RANGE_S64K
] =
727 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
731 .relax_code_seq
[BR_RANGE_S16M
] =
733 INSN_BLTZ
, /* bltz $rt, $1 */
736 .relax_code_condition
[BR_RANGE_S16M
] =
738 {0, 20, 0x1F, false},
741 .relax_code_size
[BR_RANGE_S16M
] = 8,
742 .relax_branch_isize
[BR_RANGE_S16M
] = 4,
743 .relax_fixup
[BR_RANGE_S16M
] =
745 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
746 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP5
},
747 {4, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
750 .relax_code_seq
[BR_RANGE_U4G
] =
752 INSN_BLTZ
, /* bltz $rt, $1 */
753 INSN_SETHI_TA
, /* sethi $ta, label */
754 INSN_ORI_TA
, /* ori $ta, $ta, label */
755 INSN_JR_TA
/* jr $ta */
757 .relax_code_condition
[BR_RANGE_U4G
] =
759 {0, 20, 0x1F, false},
762 .relax_code_size
[BR_RANGE_U4G
] = 16,
763 .relax_branch_isize
[BR_RANGE_U4G
] = 4,
764 .relax_fixup
[BR_RANGE_U4G
] =
766 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
767 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP6
},
768 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
769 {4, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
770 {8, 4, NDS32_FIX
| NDS32_HINT
, BFD_RELOC_NDS32_LO12S0_ORI
},
771 {8, 4, NDS32_PTR
|NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
772 {12, 4, NDS32_ABS
| NDS32_HINT
, BFD_RELOC_NDS32_PTR_RESOLVED
},
773 {12, 4, NDS32_SYM
| NDS32_HINT
, BFD_RELOC_NDS32_EMPTY
},
774 {12, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
780 .br_range
= BR_RANGE_S64K
,
783 {0, 20, 0x1F, false},
786 .relax_code_seq
[BR_RANGE_S256
] =
788 INSN_BNEZ
/* bnez $rt, label */
790 .relax_code_condition
[BR_RANGE_S256
] =
792 {0, 20, 0x1F, false},
795 .relax_code_size
[BR_RANGE_S256
] = 4,
796 .relax_branch_isize
[BR_RANGE_S256
] = 4,
797 .relax_fixup
[BR_RANGE_S256
] =
799 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
800 {0, 4, NDS32_INSN16
, BFD_RELOC_NDS32_INSN16
},
804 .relax_code_seq
[BR_RANGE_S16K
] =
806 INSN_BNEZ
/* bnez $rt, label */
808 .relax_code_condition
[BR_RANGE_S16K
] =
810 {0, 20, 0x1F, false},
813 .relax_code_size
[BR_RANGE_S16K
] = 4,
814 .relax_branch_isize
[BR_RANGE_S16K
] = 4,
815 .relax_fixup
[BR_RANGE_S16K
] =
817 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
821 .relax_code_seq
[BR_RANGE_S64K
] =
823 INSN_BNEZ
/* bnez $rt, label */
825 .relax_code_condition
[BR_RANGE_S64K
] =
827 {0, 20, 0x1F, false},
830 .relax_code_size
[BR_RANGE_S64K
] = 4,
831 .relax_branch_isize
[BR_RANGE_S64K
] = 4,
832 .relax_fixup
[BR_RANGE_S64K
] =
834 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
838 .relax_code_seq
[BR_RANGE_S16M
] =
840 INSN_BEQZ
, /* beqz $rt, $1 */
843 .relax_code_condition
[BR_RANGE_S16M
] =
845 {0, 20, 0x1F, false},
848 .relax_code_size
[BR_RANGE_S16M
] = 8,
849 .relax_branch_isize
[BR_RANGE_S16M
] = 4,
850 .relax_fixup
[BR_RANGE_S16M
] =
852 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
853 {0, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
854 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP5
},
855 {4, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
856 {4, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
860 .relax_code_seq
[BR_RANGE_U4G
] =
862 INSN_BEQZ
, /* beqz $rt, $1 */
863 INSN_SETHI_TA
, /* sethi $ta, label */
864 INSN_ORI_TA
, /* ori $ta, $ta, label */
865 INSN_JR_TA
/* jr $ta */
867 .relax_code_condition
[BR_RANGE_U4G
] =
869 {0, 20, 0x1F, false},
872 .relax_code_size
[BR_RANGE_U4G
] = 16,
873 .relax_branch_isize
[BR_RANGE_U4G
] = 4,
874 .relax_fixup
[BR_RANGE_U4G
] =
876 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
877 {0, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
878 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP6
},
879 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
880 {4, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
881 {8, 4, NDS32_FIX
| NDS32_HINT
, BFD_RELOC_NDS32_LO12S0_ORI
},
882 {8, 4, NDS32_PTR
|NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
883 {12, 4, NDS32_ABS
| NDS32_HINT
, BFD_RELOC_NDS32_PTR_RESOLVED
},
884 {12, 4, NDS32_SYM
| NDS32_HINT
, BFD_RELOC_NDS32_EMPTY
},
885 {12, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
891 .br_range
= BR_RANGE_S64K
,
894 {0, 20, 0x1F, false},
897 .relax_code_seq
[BR_RANGE_S256
] =
899 INSN_BGTZ
/* bgtz $rt, label */
901 .relax_code_condition
[BR_RANGE_S256
] =
903 {0, 20, 0x1F, false},
906 .relax_code_size
[BR_RANGE_S256
] = 4,
907 .relax_branch_isize
[BR_RANGE_S256
] = 4,
908 .relax_fixup
[BR_RANGE_S256
] =
910 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
914 .relax_code_seq
[BR_RANGE_S16K
] =
916 INSN_BGTZ
/* bgtz $rt, label */
918 .relax_code_condition
[BR_RANGE_S16K
] =
920 {0, 20, 0x1F, false},
923 .relax_code_size
[BR_RANGE_S16K
] = 4,
924 .relax_branch_isize
[BR_RANGE_S16K
] = 4,
925 .relax_fixup
[BR_RANGE_S16K
] =
927 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
931 .relax_code_seq
[BR_RANGE_S64K
] =
933 INSN_BGTZ
/* bgtz $rt, label */
935 .relax_code_condition
[BR_RANGE_S64K
] =
937 {0, 20, 0x1F, false},
940 .relax_code_size
[BR_RANGE_S64K
] = 4,
941 .relax_branch_isize
[BR_RANGE_S64K
] = 4,
942 .relax_fixup
[BR_RANGE_S64K
] =
944 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
948 .relax_code_seq
[BR_RANGE_S16M
] =
950 INSN_BLEZ
, /* blez $rt, $1 */
953 .relax_code_condition
[BR_RANGE_S16M
] =
955 {0, 20, 0x1F, false},
958 .relax_code_size
[BR_RANGE_S16M
] = 8,
959 .relax_branch_isize
[BR_RANGE_S16M
] = 4,
960 .relax_fixup
[BR_RANGE_S16M
] =
962 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
963 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP5
},
964 {4, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
968 .relax_code_seq
[BR_RANGE_U4G
] =
970 INSN_BLEZ
, /* blez $rt, $1 */
971 INSN_SETHI_TA
, /* sethi $ta, label */
972 INSN_ORI_TA
, /* ori $ta, $ta, label */
973 INSN_JR_TA
/* jr $ta */
975 .relax_code_condition
[BR_RANGE_U4G
] =
977 {0, 20, 0x1F, false},
980 .relax_code_size
[BR_RANGE_U4G
] = 16,
981 .relax_branch_isize
[BR_RANGE_U4G
] = 4,
982 .relax_fixup
[BR_RANGE_U4G
] =
984 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
985 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP6
},
986 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
987 {4, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
988 {8, 4, NDS32_FIX
| NDS32_HINT
, BFD_RELOC_NDS32_LO12S0_ORI
},
989 {8, 4, NDS32_PTR
|NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
990 {12, 4, NDS32_ABS
| NDS32_HINT
, BFD_RELOC_NDS32_PTR_RESOLVED
},
991 {12, 4, NDS32_SYM
| NDS32_HINT
, BFD_RELOC_NDS32_EMPTY
},
992 {12, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
998 .br_range
= BR_RANGE_S64K
,
1001 {0, 20, 0x1F, false},
1004 .relax_code_seq
[BR_RANGE_S256
] =
1006 INSN_BLEZ
/* blez $rt, label */
1008 .relax_code_condition
[BR_RANGE_S256
] =
1010 {0, 20, 0x1F, false},
1013 .relax_code_size
[BR_RANGE_S256
] = 4,
1014 .relax_branch_isize
[BR_RANGE_S256
] = 4,
1015 .relax_fixup
[BR_RANGE_S256
] =
1017 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
1021 .relax_code_seq
[BR_RANGE_S16K
] =
1023 INSN_BLEZ
/* blez $rt, label */
1025 .relax_code_condition
[BR_RANGE_S16K
] =
1027 {0, 20, 0x1F, false},
1030 .relax_code_size
[BR_RANGE_S16K
] = 4,
1031 .relax_branch_isize
[BR_RANGE_S16K
] = 4,
1032 .relax_fixup
[BR_RANGE_S16K
] =
1034 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
1038 .relax_code_seq
[BR_RANGE_S64K
] =
1040 INSN_BLEZ
/* blez $rt, label */
1042 .relax_code_condition
[BR_RANGE_S64K
] =
1044 {0, 20, 0x1F, false},
1047 .relax_code_size
[BR_RANGE_S64K
] = 4,
1048 .relax_branch_isize
[BR_RANGE_S64K
] = 4,
1049 .relax_fixup
[BR_RANGE_S64K
] =
1051 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
1055 .relax_code_seq
[BR_RANGE_S16M
] =
1057 INSN_BGTZ
, /* bgtz $rt, $1 */
1058 INSN_J
/* j label */
1060 .relax_code_condition
[BR_RANGE_S16M
] =
1062 {0, 20, 0x1F, false},
1065 .relax_code_size
[BR_RANGE_S16M
] = 8,
1066 .relax_branch_isize
[BR_RANGE_S16M
] = 4,
1067 .relax_fixup
[BR_RANGE_S16M
] =
1069 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
1070 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP5
},
1071 {4, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
1075 .relax_code_seq
[BR_RANGE_U4G
] =
1077 INSN_BGTZ
, /* bgtz $rt, $1 */
1078 INSN_SETHI_TA
, /* sethi $ta, label */
1079 INSN_ORI_TA
, /* ori $ta, $ta, label */
1080 INSN_JR_TA
/* jr $ta */
1082 .relax_code_condition
[BR_RANGE_U4G
] =
1084 {0, 20, 0x1F, false},
1087 .relax_code_size
[BR_RANGE_U4G
] = 16,
1088 .relax_branch_isize
[BR_RANGE_U4G
] = 4,
1089 .relax_fixup
[BR_RANGE_U4G
] =
1091 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
1092 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP6
},
1093 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
1094 {4, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
1095 {8, 4, NDS32_FIX
| NDS32_HINT
, BFD_RELOC_NDS32_LO12S0_ORI
},
1096 {8, 4, NDS32_PTR
|NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
1097 {12, 4, NDS32_ABS
| NDS32_HINT
, BFD_RELOC_NDS32_PTR_RESOLVED
},
1098 {12, 4, NDS32_SYM
| NDS32_HINT
, BFD_RELOC_NDS32_EMPTY
},
1099 {12, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1105 .br_range
= BR_RANGE_S64K
,
1108 {0, 20, 0x1F, false},
1111 .relax_code_seq
[BR_RANGE_S256
] =
1113 INSN_BLTZ
/* bltz $rt, label */
1115 .relax_code_condition
[BR_RANGE_S256
] =
1117 {0, 20, 0x1F, false},
1120 .relax_code_size
[BR_RANGE_S256
] = 4,
1121 .relax_branch_isize
[BR_RANGE_S256
] = 4,
1122 .relax_fixup
[BR_RANGE_S256
] =
1124 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
1128 .relax_code_seq
[BR_RANGE_S16K
] =
1130 INSN_BLTZ
/* bltz $rt, label */
1132 .relax_code_condition
[BR_RANGE_S16K
] =
1134 {0, 20, 0x1F, false},
1137 .relax_code_size
[BR_RANGE_S16K
] = 4,
1138 .relax_branch_isize
[BR_RANGE_S16K
] = 4,
1139 .relax_fixup
[BR_RANGE_S16K
] =
1141 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
1145 .relax_code_seq
[BR_RANGE_S64K
] =
1147 INSN_BLTZ
/* bltz $rt, label */
1149 .relax_code_condition
[BR_RANGE_S64K
] =
1151 {0, 20, 0x1F, false},
1154 .relax_code_size
[BR_RANGE_S64K
] = 4,
1155 .relax_branch_isize
[BR_RANGE_S64K
] = 4,
1156 .relax_fixup
[BR_RANGE_S64K
] =
1158 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
1162 .relax_code_seq
[BR_RANGE_S16M
] =
1164 INSN_BGEZ
, /* bgez $rt, $1 */
1165 INSN_J
/* j label */
1167 .relax_code_condition
[BR_RANGE_S16M
] =
1169 {0, 20, 0x1F, false},
1172 .relax_code_size
[BR_RANGE_S16M
] = 8,
1173 .relax_branch_isize
[BR_RANGE_S16M
] = 4,
1174 .relax_fixup
[BR_RANGE_S16M
] =
1176 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
1177 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP5
},
1178 {4, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
1182 .relax_code_seq
[BR_RANGE_U4G
] =
1184 INSN_BGEZ
, /* bgez $rt, $1 */
1185 INSN_SETHI_TA
, /* sethi $ta, label */
1186 INSN_ORI_TA
, /* ori $ta, $ta, label */
1187 INSN_JR_TA
/* jr $ta */
1189 .relax_code_condition
[BR_RANGE_U4G
] =
1191 {0, 20, 0x1F, false},
1194 .relax_code_size
[BR_RANGE_U4G
] = 16,
1195 .relax_branch_isize
[BR_RANGE_U4G
] = 4,
1196 .relax_fixup
[BR_RANGE_U4G
] =
1198 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
1199 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP6
},
1200 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
1201 {4, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
1202 {8, 4, NDS32_FIX
| NDS32_HINT
, BFD_RELOC_NDS32_LO12S0_ORI
},
1203 {8, 4, NDS32_PTR
|NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
1204 {12, 4, NDS32_ABS
| NDS32_HINT
, BFD_RELOC_NDS32_PTR_RESOLVED
},
1205 {12, 4, NDS32_SYM
| NDS32_HINT
, BFD_RELOC_NDS32_EMPTY
},
1206 {12, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1212 .br_range
= BR_RANGE_S16K
,
1215 {0, 20, 0x1F, false},
1216 {0, 15, 0x1F, false},
1219 .relax_code_seq
[BR_RANGE_S256
] =
1221 INSN_BEQ
/* beq $rt, $ra, label */
1223 .relax_code_condition
[BR_RANGE_S256
] =
1225 {0, 20, 0x1F, false},
1226 {0, 15, 0x1F, false},
1229 .relax_code_size
[BR_RANGE_S256
] = 4,
1230 .relax_branch_isize
[BR_RANGE_S256
] = 4,
1231 .relax_fixup
[BR_RANGE_S256
] =
1233 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
1234 {0, 4, NDS32_INSN16
, BFD_RELOC_NDS32_INSN16
},
1238 .relax_code_seq
[BR_RANGE_S16K
] =
1240 INSN_BEQ
/* beq $rt, $ra, label */
1242 .relax_code_condition
[BR_RANGE_S16K
] =
1244 {0, 20, 0x1F, false},
1245 {0, 15, 0x1F, false},
1248 .relax_code_size
[BR_RANGE_S16K
] = 4,
1249 .relax_branch_isize
[BR_RANGE_S16K
] = 4,
1250 .relax_fixup
[BR_RANGE_S16K
] =
1252 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
1256 .relax_code_seq
[BR_RANGE_S64K
] =
1258 INSN_BNE
, /* bne $rt, $ra, $1 */
1259 INSN_J
/* j label */
1261 .relax_code_condition
[BR_RANGE_S64K
] =
1263 {0, 20, 0x1F, false},
1264 {0, 15, 0x1F, false},
1267 .relax_code_size
[BR_RANGE_S64K
] = 8,
1268 .relax_branch_isize
[BR_RANGE_S64K
] = 4,
1269 .relax_fixup
[BR_RANGE_S64K
] =
1271 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
1272 {0, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1273 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP5
},
1274 {4, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
1275 {4, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1279 .relax_code_seq
[BR_RANGE_S16M
] =
1281 INSN_BNE
, /* bne $rt, $ra, $1 */
1282 INSN_J
/* j label */
1284 .relax_code_condition
[BR_RANGE_S16M
] =
1286 {0, 20, 0x1F, false},
1287 {0, 15, 0x1F, false},
1290 .relax_code_size
[BR_RANGE_S16M
] = 8,
1291 .relax_branch_isize
[BR_RANGE_S16M
] = 4,
1292 .relax_fixup
[BR_RANGE_S16M
] =
1294 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
1295 {0, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1296 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP5
},
1297 {4, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
1298 {4, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1302 .relax_code_seq
[BR_RANGE_U4G
] =
1304 INSN_BNE
, /* bne $rt, $ra, $1 */
1305 INSN_SETHI_TA
, /* sethi $ta, label */
1306 INSN_ORI_TA
, /* ori $ta, $ta, label */
1307 INSN_JR_TA
/* jr $ta */
1309 .relax_code_condition
[BR_RANGE_U4G
] =
1311 {0, 20, 0x1F, false},
1312 {0, 15, 0x1F, false},
1315 .relax_code_size
[BR_RANGE_U4G
] = 16,
1316 .relax_branch_isize
[BR_RANGE_U4G
] = 4,
1317 .relax_fixup
[BR_RANGE_U4G
] =
1319 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
1320 {0, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1321 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP6
},
1322 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
1323 {4, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
1324 {8, 4, NDS32_FIX
| NDS32_HINT
, BFD_RELOC_NDS32_LO12S0_ORI
},
1325 {8, 4, NDS32_PTR
|NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
1326 {12, 4, NDS32_ABS
| NDS32_HINT
, BFD_RELOC_NDS32_PTR_RESOLVED
},
1327 {12, 4, NDS32_SYM
| NDS32_HINT
, BFD_RELOC_NDS32_EMPTY
},
1328 {12, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1334 .br_range
= BR_RANGE_S16K
,
1337 {0, 20, 0x1F, false},
1338 {0, 15, 0x1F, false},
1341 .relax_code_seq
[BR_RANGE_S256
] =
1343 INSN_BNE
/* bne $rt, $ra, label */
1345 .relax_code_condition
[BR_RANGE_S256
] =
1347 {0, 20, 0x1F, false},
1348 {0, 15, 0x1F, false},
1351 .relax_code_size
[BR_RANGE_S256
] = 4,
1352 .relax_branch_isize
[BR_RANGE_S256
] = 4,
1353 .relax_fixup
[BR_RANGE_S256
] =
1355 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
1356 {0, 4, NDS32_INSN16
, BFD_RELOC_NDS32_INSN16
},
1360 .relax_code_seq
[BR_RANGE_S16K
] =
1362 INSN_BNE
/* bne $rt, $ra, label */
1364 .relax_code_condition
[BR_RANGE_S16K
] =
1366 {0, 20, 0x1F, false},
1367 {0, 15, 0x1F, false},
1370 .relax_code_size
[BR_RANGE_S16K
] = 4,
1371 .relax_branch_isize
[BR_RANGE_S16K
] = 4,
1372 .relax_fixup
[BR_RANGE_S16K
] =
1374 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
1378 .relax_code_seq
[BR_RANGE_S64K
] =
1380 INSN_BEQ
, /* beq $rt, $ra, $1 */
1381 INSN_J
/* j label */
1383 .relax_code_condition
[BR_RANGE_S64K
] =
1385 {0, 20, 0x1F, false},
1386 {0, 15, 0x1F, false},
1389 .relax_code_size
[BR_RANGE_S64K
] = 8,
1390 .relax_branch_isize
[BR_RANGE_S64K
] = 4,
1391 .relax_fixup
[BR_RANGE_S64K
] =
1393 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
1394 {0, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1395 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP5
},
1396 {4, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
1397 {4, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1401 .relax_code_seq
[BR_RANGE_S16M
] =
1403 INSN_BEQ
, /* beq $rt, $ra, $1 */
1404 INSN_J
/* j label */
1406 .relax_code_condition
[BR_RANGE_S16M
] =
1408 {0, 20, 0x1F, false},
1409 {0, 15, 0x1F, false},
1412 .relax_code_size
[BR_RANGE_S16M
] = 8,
1413 .relax_branch_isize
[BR_RANGE_S16M
] = 4,
1414 .relax_fixup
[BR_RANGE_S16M
] =
1416 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
1417 {0, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1418 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP5
},
1419 {4, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
1420 {4, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1424 .relax_code_seq
[BR_RANGE_U4G
] =
1426 INSN_BEQ
, /* beq $rt, $ra, $1 */
1427 INSN_SETHI_TA
, /* sethi $ta, label */
1428 INSN_ORI_TA
, /* ori $ta, $ta, label */
1429 INSN_JR_TA
/* jr $ta */
1431 .relax_code_condition
[BR_RANGE_U4G
] =
1433 {0, 20, 0x1F, false},
1434 {0, 15, 0x1F, false},
1437 .relax_code_size
[BR_RANGE_U4G
] = 16,
1438 .relax_branch_isize
[BR_RANGE_U4G
] = 4,
1439 .relax_fixup
[BR_RANGE_U4G
] =
1441 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
1442 {0, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1443 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP6
},
1444 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
1445 {4, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
1446 {8, 4, NDS32_FIX
| NDS32_HINT
, BFD_RELOC_NDS32_LO12S0_ORI
},
1447 {8, 4, NDS32_PTR
|NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
1448 {12, 4, NDS32_ABS
| NDS32_HINT
, BFD_RELOC_NDS32_PTR_RESOLVED
},
1449 {12, 4, NDS32_SYM
| NDS32_HINT
, BFD_RELOC_NDS32_EMPTY
},
1450 {12, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1456 .br_range
= BR_RANGE_S256
,
1462 .relax_code_seq
[BR_RANGE_S256
] =
1464 INSN_BEQZ38
<< 16 /* beqz $rt, label */
1466 .relax_code_condition
[BR_RANGE_S256
] =
1471 .relax_code_size
[BR_RANGE_S256
] = 2,
1472 .relax_branch_isize
[BR_RANGE_S256
] = 2,
1473 .relax_fixup
[BR_RANGE_S256
] =
1475 {0, 2, NDS32_PCREL
, BFD_RELOC_NDS32_9_PCREL
},
1479 .relax_code_seq
[BR_RANGE_S16K
] =
1481 INSN_BEQZ
/* beqz $rt, label */
1483 .relax_code_condition
[BR_RANGE_S16K
] =
1485 {0, 20, 0x1F, false},
1488 .relax_code_size
[BR_RANGE_S16K
] = 4,
1489 .relax_branch_isize
[BR_RANGE_S16K
] = 4,
1490 .relax_fixup
[BR_RANGE_S16K
] =
1492 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
1496 .relax_code_seq
[BR_RANGE_S64K
] =
1498 INSN_BEQZ
/* beqz $rt, label */
1500 .relax_code_condition
[BR_RANGE_S64K
] =
1502 {0, 20, 0x1F, false},
1505 .relax_code_size
[BR_RANGE_S64K
] = 4,
1506 .relax_branch_isize
[BR_RANGE_S64K
] = 4,
1507 .relax_fixup
[BR_RANGE_S64K
] =
1509 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
1513 .relax_code_seq
[BR_RANGE_S16M
] =
1515 INSN_BNEZ
, /* bnez $rt, $1 */
1516 INSN_J
/* j label */
1518 .relax_code_condition
[BR_RANGE_S16M
] =
1520 {0, 20, 0x1F, false},
1523 .relax_code_size
[BR_RANGE_S16M
] = 8,
1524 .relax_branch_isize
[BR_RANGE_S16M
] = 4,
1525 .relax_fixup
[BR_RANGE_S16M
] =
1527 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
1528 {0, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1529 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP5
},
1530 {4, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
1531 {4, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1535 .relax_code_seq
[BR_RANGE_U4G
] =
1537 INSN_BNEZ
, /* bnez $rt, $1 */
1538 INSN_SETHI_TA
, /* sethi $ta, label */
1539 INSN_ORI_TA
, /* ori $ta, $ta, label */
1540 INSN_JR_TA
/* jr $ta */
1542 .relax_code_condition
[BR_RANGE_U4G
] =
1544 {0, 20, 0x1F, false},
1547 .relax_code_size
[BR_RANGE_U4G
] = 16,
1548 .relax_branch_isize
[BR_RANGE_U4G
] = 4,
1549 .relax_fixup
[BR_RANGE_U4G
] =
1551 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
1552 {0, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1553 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP6
},
1554 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
1555 {4, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
1556 {8, 4, NDS32_FIX
| NDS32_HINT
, BFD_RELOC_NDS32_LO12S0_ORI
},
1557 {8, 4, NDS32_PTR
|NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
1558 {12, 4, NDS32_ABS
| NDS32_HINT
, BFD_RELOC_NDS32_PTR_RESOLVED
},
1559 {12, 4, NDS32_SYM
| NDS32_HINT
, BFD_RELOC_NDS32_EMPTY
},
1560 {12, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1566 .br_range
= BR_RANGE_S256
,
1572 .relax_code_seq
[BR_RANGE_S256
] =
1574 INSN_BNEZ38
<< 16 /* bnez $rt, label */
1576 .relax_code_condition
[BR_RANGE_S256
] =
1581 .relax_code_size
[BR_RANGE_S256
] = 2,
1582 .relax_branch_isize
[BR_RANGE_S256
] = 2,
1583 .relax_fixup
[BR_RANGE_S256
] =
1585 {0, 2, NDS32_PCREL
, BFD_RELOC_NDS32_9_PCREL
},
1589 .relax_code_seq
[BR_RANGE_S16K
] =
1591 INSN_BNEZ
/* bnez $rt, label */
1593 .relax_code_condition
[BR_RANGE_S16K
] =
1595 {0, 20, 0x1F, false},
1598 .relax_code_size
[BR_RANGE_S16K
] = 4,
1599 .relax_branch_isize
[BR_RANGE_S16K
] = 4,
1600 .relax_fixup
[BR_RANGE_S16K
] =
1602 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
1606 .relax_code_seq
[BR_RANGE_S64K
] =
1608 INSN_BNEZ
/* bnez $rt, label */
1610 .relax_code_condition
[BR_RANGE_S64K
] =
1612 {0, 20, 0x1F, false},
1615 .relax_code_size
[BR_RANGE_S64K
] = 4,
1616 .relax_branch_isize
[BR_RANGE_S64K
] = 4,
1617 .relax_fixup
[BR_RANGE_S64K
] =
1619 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
1623 .relax_code_seq
[BR_RANGE_S16M
] =
1625 INSN_BEQZ
, /* beqz $rt, $1 */
1626 INSN_J
/* j label */
1628 .relax_code_condition
[BR_RANGE_S16M
] =
1630 {0, 20, 0x1F, false},
1633 .relax_code_size
[BR_RANGE_S16M
] = 8,
1634 .relax_branch_isize
[BR_RANGE_S16M
] = 4,
1635 .relax_fixup
[BR_RANGE_S16M
] =
1637 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
1638 {0, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1639 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP5
},
1640 {4, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
1641 {4, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1645 .relax_code_seq
[BR_RANGE_U4G
] =
1647 INSN_BEQZ
, /* beqz $rt, $1 */
1648 INSN_SETHI_TA
, /* sethi $ta, label */
1649 INSN_ORI_TA
, /* ori $ta, $ta, label */
1650 INSN_JR_TA
/* jr $ta */
1652 .relax_code_condition
[BR_RANGE_U4G
] =
1654 {0, 20, 0x1F, false},
1657 .relax_code_size
[BR_RANGE_U4G
] = 16,
1658 .relax_branch_isize
[BR_RANGE_U4G
] = 4,
1659 .relax_fixup
[BR_RANGE_U4G
] =
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_LONGJUMP6
},
1664 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
1665 {4, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
1666 {8, 4, NDS32_FIX
| NDS32_HINT
, BFD_RELOC_NDS32_LO12S0_ORI
},
1667 {8, 4, NDS32_PTR
|NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
1668 {12, 4, NDS32_ABS
| NDS32_HINT
, BFD_RELOC_NDS32_PTR_RESOLVED
},
1669 {12, 4, NDS32_SYM
| NDS32_HINT
, BFD_RELOC_NDS32_EMPTY
},
1670 {12, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1676 .br_range
= BR_RANGE_S256
,
1681 .relax_code_seq
[BR_RANGE_S256
] =
1683 INSN_BEQZS8
<< 16 /* beqz $r15, label */
1685 .relax_code_size
[BR_RANGE_S256
] = 2,
1686 .relax_branch_isize
[BR_RANGE_S256
] = 2,
1687 .relax_fixup
[BR_RANGE_S256
] =
1689 {0, 2, NDS32_PCREL
, BFD_RELOC_NDS32_9_PCREL
},
1693 .relax_code_seq
[BR_RANGE_S16K
] =
1695 INSN_BEQZ_TA
/* beqz $r15, label */
1697 .relax_code_size
[BR_RANGE_S16K
] = 4,
1698 .relax_branch_isize
[BR_RANGE_S16K
] = 4,
1699 .relax_fixup
[BR_RANGE_S16K
] =
1701 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
1705 .relax_code_seq
[BR_RANGE_S64K
] =
1707 INSN_BEQZ_TA
/* beqz $r15, label */
1709 .relax_code_size
[BR_RANGE_S64K
] = 4,
1710 .relax_branch_isize
[BR_RANGE_S64K
] = 4,
1711 .relax_fixup
[BR_RANGE_S64K
] =
1713 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
1717 .relax_code_seq
[BR_RANGE_S16M
] =
1719 INSN_BNEZ_TA
, /* bnez $r15, $1 */
1720 INSN_J
/* j label */
1722 .relax_code_size
[BR_RANGE_S16M
] = 8,
1723 .relax_branch_isize
[BR_RANGE_S16M
] = 4,
1724 .relax_fixup
[BR_RANGE_S16M
] =
1726 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
1727 {0, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1728 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP5
},
1729 {4, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
1730 {4, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1734 .relax_code_seq
[BR_RANGE_U4G
] =
1736 INSN_BNEZ_TA
, /* bnez $r15, $1 */
1737 INSN_SETHI_TA
, /* sethi $ta, label */
1738 INSN_ORI_TA
, /* ori $ta, $ta, label */
1739 INSN_JR_TA
/* jr $ta */
1741 .relax_code_size
[BR_RANGE_U4G
] = 16,
1742 .relax_branch_isize
[BR_RANGE_U4G
] = 4,
1743 .relax_fixup
[BR_RANGE_U4G
] =
1745 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
1746 {0, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1747 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP6
},
1748 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
1749 {4, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
1750 {8, 4, NDS32_FIX
| NDS32_HINT
, BFD_RELOC_NDS32_LO12S0_ORI
},
1751 {8, 4, NDS32_PTR
|NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
1752 {12, 4, NDS32_ABS
| NDS32_HINT
, BFD_RELOC_NDS32_PTR_RESOLVED
},
1753 {12, 4, NDS32_SYM
| NDS32_HINT
, BFD_RELOC_NDS32_EMPTY
},
1754 {12, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1760 .br_range
= BR_RANGE_S256
,
1765 .relax_code_seq
[BR_RANGE_S256
] =
1767 INSN_BNEZS8
<< 16 /* bnez $r15, label */
1769 .relax_code_size
[BR_RANGE_S256
] = 2,
1770 .relax_branch_isize
[BR_RANGE_S256
] = 2,
1771 .relax_fixup
[BR_RANGE_S256
] =
1773 {0, 2, NDS32_PCREL
, BFD_RELOC_NDS32_9_PCREL
},
1777 .relax_code_seq
[BR_RANGE_S16K
] =
1779 INSN_BNEZ_TA
/* bnez $r15, label */
1781 .relax_code_size
[BR_RANGE_S16K
] = 4,
1782 .relax_branch_isize
[BR_RANGE_S16K
] = 4,
1783 .relax_fixup
[BR_RANGE_S16K
] =
1785 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
1789 .relax_code_seq
[BR_RANGE_S64K
] =
1791 INSN_BNEZ_TA
/* bnez $r15, label */
1793 .relax_code_size
[BR_RANGE_S64K
] = 4,
1794 .relax_branch_isize
[BR_RANGE_S64K
] = 4,
1795 .relax_fixup
[BR_RANGE_S64K
] =
1797 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_17_PCREL
},
1801 .relax_code_seq
[BR_RANGE_S16M
] =
1803 INSN_BEQZ_TA
, /* beqz $r15, $1 */
1804 INSN_J
/* j label */
1806 .relax_code_size
[BR_RANGE_S16M
] = 8,
1807 .relax_branch_isize
[BR_RANGE_S16M
] = 4,
1808 .relax_fixup
[BR_RANGE_S16M
] =
1810 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
1811 {0, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1812 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP5
},
1813 {4, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
1814 {4, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1818 .relax_code_seq
[BR_RANGE_U4G
] =
1820 INSN_BEQZ_TA
, /* beqz $r15, $1 */
1821 INSN_SETHI_TA
, /* sethi $ta, label */
1822 INSN_ORI_TA
, /* ori $ta, $ta, label */
1823 INSN_JR_TA
/* jr $ta */
1825 .relax_code_size
[BR_RANGE_U4G
] = 16,
1826 .relax_branch_isize
[BR_RANGE_U4G
] = 4,
1827 .relax_fixup
[BR_RANGE_U4G
] =
1829 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
1830 {0, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1831 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP6
},
1832 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
1833 {4, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
1834 {8, 4, NDS32_FIX
| NDS32_HINT
, BFD_RELOC_NDS32_LO12S0_ORI
},
1835 {8, 4, NDS32_PTR
|NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
1836 {12, 4, NDS32_ABS
| NDS32_HINT
, BFD_RELOC_NDS32_PTR_RESOLVED
},
1837 {12, 4, NDS32_SYM
| NDS32_HINT
, BFD_RELOC_NDS32_EMPTY
},
1838 {12, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1844 .br_range
= BR_RANGE_S256
,
1850 .relax_code_seq
[BR_RANGE_S256
] =
1852 INSN_BNES38
<< 16 /* bne $rt, $r5, label */
1854 .relax_code_condition
[BR_RANGE_S256
] =
1859 .relax_code_size
[BR_RANGE_S256
] = 2,
1860 .relax_branch_isize
[BR_RANGE_S256
] = 2,
1861 .relax_fixup
[BR_RANGE_S256
] =
1863 {0, 2, NDS32_PCREL
, BFD_RELOC_NDS32_9_PCREL
},
1867 .relax_code_seq
[BR_RANGE_S16K
] =
1869 INSN_BNE_R5
/* bne $rt, $r5, label */
1871 .relax_code_condition
[BR_RANGE_S16K
] =
1873 {0, 20, 0x1F, false},
1876 .relax_code_size
[BR_RANGE_S16K
] = 4,
1877 .relax_branch_isize
[BR_RANGE_S16K
] = 4,
1878 .relax_fixup
[BR_RANGE_S16K
] =
1880 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
1884 .relax_code_seq
[BR_RANGE_S64K
] =
1886 INSN_BEQ_R5
, /* beq $rt, $r5, $1 */
1887 INSN_J
/* j label */
1889 .relax_code_condition
[BR_RANGE_S64K
] =
1891 {0, 20, 0x1F, false},
1894 .relax_code_size
[BR_RANGE_S64K
] = 8,
1895 .relax_branch_isize
[BR_RANGE_S64K
] = 4,
1896 .relax_fixup
[BR_RANGE_S64K
] =
1898 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
1899 {0, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1900 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP5
},
1901 {4, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
1902 {4, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1906 .relax_code_seq
[BR_RANGE_S16M
] =
1908 INSN_BEQ_R5
, /* beq $rt, $r5, $1 */
1909 INSN_J
/* j label */
1911 .relax_code_condition
[BR_RANGE_S16M
] =
1913 {0, 20, 0x1F, false},
1916 .relax_code_size
[BR_RANGE_S16M
] = 8,
1917 .relax_branch_isize
[BR_RANGE_S16M
] = 4,
1918 .relax_fixup
[BR_RANGE_S16M
] =
1920 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
1921 {0, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1922 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP5
},
1923 {4, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
1924 {4, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1928 .relax_code_seq
[BR_RANGE_U4G
] =
1930 INSN_BEQ_R5
, /* beq $rt, $r5, $1 */
1931 INSN_SETHI_TA
, /* sethi $ta, label */
1932 INSN_ORI_TA
, /* ori $ta, $ta, label */
1933 INSN_JR_TA
/* jr $ta */
1935 .relax_code_condition
[BR_RANGE_U4G
] =
1937 {0, 20, 0x1F, false},
1940 .relax_code_size
[BR_RANGE_U4G
] = 16,
1941 .relax_branch_isize
[BR_RANGE_U4G
] = 4,
1942 .relax_fixup
[BR_RANGE_U4G
] =
1944 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
1945 {0, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1946 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP6
},
1947 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
1948 {4, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
1949 {8, 4, NDS32_FIX
| NDS32_HINT
, BFD_RELOC_NDS32_LO12S0_ORI
},
1950 {8, 4, NDS32_PTR
|NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
1951 {12, 4, NDS32_ABS
| NDS32_HINT
, BFD_RELOC_NDS32_PTR_RESOLVED
},
1952 {12, 4, NDS32_SYM
| NDS32_HINT
, BFD_RELOC_NDS32_EMPTY
},
1953 {12, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
1959 .br_range
= BR_RANGE_S256
,
1965 .relax_code_seq
[BR_RANGE_S256
] =
1967 INSN_BEQS38
<< 16 /* beq $rt, $r5, label */
1969 .relax_code_condition
[BR_RANGE_S256
] =
1974 .relax_code_size
[BR_RANGE_S256
] = 2,
1975 .relax_branch_isize
[BR_RANGE_S256
] = 2,
1976 .relax_fixup
[BR_RANGE_S256
] =
1978 {0, 2, NDS32_PCREL
, BFD_RELOC_NDS32_9_PCREL
},
1982 .relax_code_seq
[BR_RANGE_S16K
] =
1984 INSN_BEQ_R5
/* beq $rt, $r5, label */
1986 .relax_code_condition
[BR_RANGE_S16K
] =
1988 {0, 20, 0x1F, false},
1991 .relax_code_size
[BR_RANGE_S16K
] = 4,
1992 .relax_branch_isize
[BR_RANGE_S16K
] = 4,
1993 .relax_fixup
[BR_RANGE_S16K
] =
1995 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
1999 .relax_code_seq
[BR_RANGE_S64K
] =
2001 INSN_BNE_R5
, /* bne $rt, $r5, $1 */
2002 INSN_J
/* j label */
2004 .relax_code_condition
[BR_RANGE_S64K
] =
2006 {0, 20, 0x1F, false},
2009 .relax_code_size
[BR_RANGE_S64K
] = 8,
2010 .relax_branch_isize
[BR_RANGE_S64K
] = 4,
2011 .relax_fixup
[BR_RANGE_S64K
] =
2013 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
2014 {0, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
2015 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP5
},
2016 {4, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
2017 {4, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
2021 .relax_code_seq
[BR_RANGE_S16M
] =
2023 INSN_BNE_R5
, /* bne $rt, $r5, $1 */
2024 INSN_J
/* j label */
2026 .relax_code_condition
[BR_RANGE_S16M
] =
2028 {0, 20, 0x1F, false},
2031 .relax_code_size
[BR_RANGE_S16M
] = 8,
2032 .relax_branch_isize
[BR_RANGE_S16M
] = 4,
2033 .relax_fixup
[BR_RANGE_S16M
] =
2035 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
2036 {0, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
2037 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP5
},
2038 {4, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
2039 {4, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
2043 .relax_code_seq
[BR_RANGE_U4G
] =
2045 INSN_BNE_R5
, /* bne $rt, $r5, $1 */
2046 INSN_SETHI_TA
, /* sethi $ta, label */
2047 INSN_ORI_TA
, /* ori $ta, $ta, label */
2048 INSN_JR_TA
/* jr $ta */
2050 .relax_code_condition
[BR_RANGE_U4G
] =
2052 {0, 20, 0x1F, false},
2055 .relax_code_size
[BR_RANGE_U4G
] = 16,
2056 .relax_branch_isize
[BR_RANGE_U4G
] = 4,
2057 .relax_fixup
[BR_RANGE_U4G
] =
2059 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
2060 {0, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
2061 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP6
},
2062 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
2063 {4, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
2064 {8, 4, NDS32_FIX
| NDS32_HINT
, BFD_RELOC_NDS32_LO12S0_ORI
},
2065 {8, 4, NDS32_PTR
|NDS32_HINT
, BFD_RELOC_NDS32_PTR
},
2066 {12, 4, NDS32_ABS
| NDS32_HINT
, BFD_RELOC_NDS32_PTR_RESOLVED
},
2067 {12, 4, NDS32_SYM
| NDS32_HINT
, BFD_RELOC_NDS32_EMPTY
},
2068 {12, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
2074 .br_range
= BR_RANGE_S256
,
2077 {0, 8, 0x7FF, true},
2078 {0, 20, 0x1F, false},
2081 .relax_code_seq
[BR_RANGE_S256
] =
2083 INSN_BEQC
/* beqc $rt, imm11s, label */
2085 .relax_code_condition
[BR_RANGE_S256
] =
2087 {0, 8, 0x7FF, false},
2088 {0, 20, 0x1F, false},
2091 .relax_code_size
[BR_RANGE_S256
] = 4,
2092 .relax_branch_isize
[BR_RANGE_S256
] = 4,
2093 .relax_fixup
[BR_RANGE_S256
] =
2095 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_WORD_9_PCREL
},
2099 .relax_code_seq
[BR_RANGE_S16K
] =
2101 INSN_MOVI_TA
, /* movi $ta, imm11s */
2102 INSN_BEQ_TA
/* beq $rt, $ta, label */
2104 .relax_code_condition
[BR_RANGE_S16K
] =
2106 {0, 0, 0xFFFFF, false},
2107 {4, 20, 0x1F, false},
2110 .relax_code_size
[BR_RANGE_S16K
] = 8,
2111 .relax_branch_isize
[BR_RANGE_S16K
] = 4,
2112 .relax_fixup
[BR_RANGE_S16K
] =
2114 {0, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
2115 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP7
},
2116 {4, 4, NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
2120 .relax_code_seq
[BR_RANGE_S64K
] =
2122 INSN_BNEC
, /* bnec $rt, imm11s, $1 */
2123 INSN_J
/* j label */
2125 .relax_code_condition
[BR_RANGE_S64K
] =
2127 {0, 8, 0x7FF, false},
2128 {0, 20, 0x1F, false},
2131 .relax_code_size
[BR_RANGE_S64K
] = 8,
2132 .relax_branch_isize
[BR_RANGE_S64K
] = 4,
2133 .relax_fixup
[BR_RANGE_S64K
] =
2135 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_WORD_9_PCREL
},
2136 {4, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
2140 .relax_code_seq
[BR_RANGE_S16M
] =
2142 INSN_BNEC
, /* bnec $rt, imm11s, $1 */
2143 INSN_J
/* j label */
2145 .relax_code_condition
[BR_RANGE_S16M
] =
2147 {0, 8, 0x7FF, false},
2148 {0, 20, 0x1F, false},
2151 .relax_code_size
[BR_RANGE_S16M
] = 8,
2152 .relax_branch_isize
[BR_RANGE_S16M
] = 4,
2153 .relax_fixup
[BR_RANGE_S16M
] =
2155 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_WORD_9_PCREL
},
2156 {4, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
2160 .relax_code_seq
[BR_RANGE_U4G
] =
2162 INSN_BNEC
, /* bnec $rt, imm11s, $1 */
2163 INSN_SETHI_TA
, /* sethi $ta, label */
2164 INSN_ORI_TA
, /* ori $ta, $ta, label */
2165 INSN_JR_TA
/* jr $ta */
2167 .relax_code_condition
[BR_RANGE_U4G
] =
2169 {0, 8, 0x7FF, false},
2170 {0, 20, 0x1F, false},
2173 .relax_code_size
[BR_RANGE_U4G
] = 16,
2174 .relax_branch_isize
[BR_RANGE_U4G
] = 4,
2175 .relax_fixup
[BR_RANGE_U4G
] =
2177 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_WORD_9_PCREL
},
2178 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
2179 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI
},
2180 {12, 4, NDS32_INSN16
, BFD_RELOC_NDS32_INSN16
},
2186 .br_range
= BR_RANGE_S256
,
2189 {0, 8, 0x7FF, true},
2190 {0, 20, 0x1F, false},
2193 .relax_code_seq
[BR_RANGE_S256
] =
2195 INSN_BNEC
/* bnec $rt, imm11s, label */
2197 .relax_code_condition
[BR_RANGE_S256
] =
2199 {0, 8, 0x7FF, false},
2200 {0, 20, 0x1F, false},
2203 .relax_code_size
[BR_RANGE_S256
] = 4,
2204 .relax_branch_isize
[BR_RANGE_S256
] = 4,
2205 .relax_fixup
[BR_RANGE_S256
] =
2207 {0, 4, NDS32_PCREL
, BFD_RELOC_NDS32_WORD_9_PCREL
},
2211 .relax_code_seq
[BR_RANGE_S16K
] =
2213 INSN_MOVI_TA
, /* movi $ta, imm11s */
2214 INSN_BNE_TA
/* bne $rt, $ta, label */
2216 .relax_code_condition
[BR_RANGE_S16K
] =
2218 {0, 0, 0xFFFFF, false},
2219 {4, 20, 0x1F, false},
2222 .relax_code_size
[BR_RANGE_S16K
] = 8,
2223 .relax_branch_isize
[BR_RANGE_S16K
] = 4,
2224 .relax_fixup
[BR_RANGE_S16K
] =
2226 {0, 4, NDS32_INSN16
| NDS32_HINT
, BFD_RELOC_NDS32_INSN16
},
2227 {0, 4, NDS32_PTR
| NDS32_HINT
, BFD_RELOC_NDS32_LONGJUMP7
},
2228 {4, 4, NDS32_PCREL
, BFD_RELOC_NDS32_15_PCREL
},
2232 .relax_code_seq
[BR_RANGE_S64K
] =
2234 INSN_BEQC
, /* beqc $rt, imm11s, $1 */
2235 INSN_J
/* j label */
2237 .relax_code_condition
[BR_RANGE_S64K
] =
2239 {0, 8, 0x7FF, false},
2240 {0, 20, 0x1F, false},
2243 .relax_code_size
[BR_RANGE_S64K
] = 8,
2244 .relax_branch_isize
[BR_RANGE_S64K
] = 4,
2245 .relax_fixup
[BR_RANGE_S64K
] =
2247 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_WORD_9_PCREL
},
2248 {4, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
2252 .relax_code_seq
[BR_RANGE_S16M
] =
2254 INSN_BEQC
, /* beqc $rt, imm11s, $1 */
2255 INSN_J
/* j label */
2257 .relax_code_condition
[BR_RANGE_S16M
] =
2259 {0, 8, 0x7FF, false},
2260 {0, 20, 0x1F, false},
2263 .relax_code_size
[BR_RANGE_S16M
] = 8,
2264 .relax_branch_isize
[BR_RANGE_S16M
] = 4,
2265 .relax_fixup
[BR_RANGE_S16M
] =
2267 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_WORD_9_PCREL
},
2268 {4, 4, NDS32_PCREL
, BFD_RELOC_NDS32_25_PCREL
},
2272 .relax_code_seq
[BR_RANGE_U4G
] =
2274 INSN_BEQC
, /* beqc $rt, imm11s, $1 */
2275 INSN_SETHI_TA
, /* sethi $ta, label */
2276 INSN_ORI_TA
, /* ori $ta, $ta, label */
2277 INSN_JR_TA
/* jr $ta */
2279 .relax_code_condition
[BR_RANGE_U4G
] =
2281 {0, 8, 0x7FF, false},
2282 {0, 20, 0x1F, false},
2285 .relax_code_size
[BR_RANGE_U4G
] = 16,
2286 .relax_branch_isize
[BR_RANGE_U4G
] = 4,
2287 .relax_fixup
[BR_RANGE_U4G
] =
2289 {0, 4, NDS32_CREATE_LABEL
| NDS32_PCREL
, BFD_RELOC_NDS32_WORD_9_PCREL
},
2290 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
2291 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI
},
2292 {12, 4, NDS32_INSN16
, BFD_RELOC_NDS32_INSN16
},
2302 /* GAS definitions for command-line options. */
2305 OPTION_BIG
= OPTION_MD_BASE
,
2309 OPTION_RELAX_FP_AS_GP_OFF
,
2310 OPTION_RELAX_B2BB_ON
,
2311 OPTION_RELAX_ALL_OFF
,
2313 OPTION_OPTIMIZE_SPACE
2316 const char *md_shortopts
= "m:O:";
2317 struct option md_longopts
[] =
2319 {"O1", no_argument
, NULL
, OPTION_OPTIMIZE
},
2320 {"Os", no_argument
, NULL
, OPTION_OPTIMIZE_SPACE
},
2321 {"big", no_argument
, NULL
, OPTION_BIG
},
2322 {"little", no_argument
, NULL
, OPTION_LITTLE
},
2323 {"EB", no_argument
, NULL
, OPTION_BIG
},
2324 {"EL", no_argument
, NULL
, OPTION_LITTLE
},
2325 {"meb", no_argument
, NULL
, OPTION_BIG
},
2326 {"mel", no_argument
, NULL
, OPTION_LITTLE
},
2327 {"mall-ext", no_argument
, NULL
, OPTION_TURBO
},
2328 {"mext-all", no_argument
, NULL
, OPTION_TURBO
},
2329 {"mpic", no_argument
, NULL
, OPTION_PIC
},
2330 /* Relaxation related options. */
2331 {"mno-fp-as-gp-relax", no_argument
, NULL
, OPTION_RELAX_FP_AS_GP_OFF
},
2332 {"mb2bb", no_argument
, NULL
, OPTION_RELAX_B2BB_ON
},
2333 {"mno-all-relax", no_argument
, NULL
, OPTION_RELAX_ALL_OFF
},
2334 {NULL
, no_argument
, NULL
, 0}
2337 size_t md_longopts_size
= sizeof (md_longopts
);
2339 struct nds32_parse_option_table
2341 const char *name
; /* Option string. */
2342 const char *help
; /* Help description. */
2343 int (*func
) (const char *arg
); /* How to parse it. */
2347 /* The value `-1' represents this option has *NOT* been set. */
2348 #ifdef NDS32_DEFAULT_ARCH_NAME
2349 static const char* nds32_arch_name
= NDS32_DEFAULT_ARCH_NAME
;
2351 static const char* nds32_arch_name
= "v3";
2353 static int nds32_baseline
= -1;
2354 static int nds32_gpr16
= -1;
2355 static int nds32_fpu_sp_ext
= -1;
2356 static int nds32_fpu_dp_ext
= -1;
2357 static int nds32_freg
= -1;
2358 static int nds32_abi
= -1;
2360 /* Record ELF flags */
2361 static int nds32_elf_flags
= 0;
2362 static int nds32_fpu_com
= 0;
2364 static int nds32_parse_arch (const char *str
);
2365 static int nds32_parse_baseline (const char *str
);
2366 static int nds32_parse_freg (const char *str
);
2367 static int nds32_parse_abi (const char *str
);
2368 static void add_mapping_symbol (enum mstate state
,
2369 unsigned int padding_byte
,
2370 unsigned int align
);
2372 static struct nds32_parse_option_table parse_opts
[] =
2374 {"arch=", N_("<arch name>\t Assemble for architecture <arch name>\n\
2375 <arch name> could be\n\
2376 v3, v3j, v3m, v3f, v3s, "\
2377 "v2, v2j, v2f, v2s"), nds32_parse_arch
},
2378 {"baseline=", N_("<baseline>\t Assemble for baseline <baseline>\n\
2379 <baseline> could be v2, v3, v3m"),
2380 nds32_parse_baseline
},
2381 {"fpu-freg=", N_("<freg>\t Specify a FPU configuration\n\
2383 0: 8 SP / 4 DP registers\n\
2384 1: 16 SP / 8 DP registers\n\
2385 2: 32 SP / 16 DP registers\n\
2386 3: 32 SP / 32 DP registers"), nds32_parse_freg
},
2387 {"abi=", N_("<abi>\t Specify a abi version\n\
2388 <abi> could be v1, v2, v2fp, v2fpp"), nds32_parse_abi
},
2392 static int nds32_mac
= 1;
2393 static int nds32_div
= 1;
2394 static int nds32_16bit_ext
= 1;
2395 static int nds32_dx_regs
= NDS32_DEFAULT_DX_REGS
;
2396 static int nds32_perf_ext
= NDS32_DEFAULT_PERF_EXT
;
2397 static int nds32_perf_ext2
= NDS32_DEFAULT_PERF_EXT2
;
2398 static int nds32_string_ext
= NDS32_DEFAULT_STRING_EXT
;
2399 static int nds32_audio_ext
= NDS32_DEFAULT_AUDIO_EXT
;
2400 static int nds32_dsp_ext
= NDS32_DEFAULT_DSP_EXT
;
2401 static int nds32_zol_ext
= NDS32_DEFAULT_ZOL_EXT
;
2402 static int nds32_fpu_fma
= 0;
2403 static int nds32_pic
= 0;
2404 static int nds32_relax_fp_as_gp
= 1;
2405 static int nds32_relax_b2bb
= 0;
2406 static int nds32_relax_all
= 1;
2407 struct nds32_set_option_table
2409 const char *name
; /* Option string. */
2410 const char *help
; /* Help description. */
2411 int *var
; /* Variable to be set. */
2412 int value
; /* Value to set. */
2415 /* The option in this group has both Enable/Disable settings.
2416 Just list on here. */
2418 static struct nds32_set_option_table toggle_opts
[] =
2420 {"mac", N_("Multiply instructions support"), &nds32_mac
, 1},
2421 {"div", N_("Divide instructions support"), &nds32_div
, 1},
2422 {"16bit-ext", N_("16-bit extension"), &nds32_16bit_ext
, 1},
2423 {"dx-regs", N_("d0/d1 registers"), &nds32_dx_regs
, 1},
2424 {"perf-ext", N_("Performance extension"), &nds32_perf_ext
, 1},
2425 {"perf2-ext", N_("Performance extension 2"), &nds32_perf_ext2
, 1},
2426 {"string-ext", N_("String extension"), &nds32_string_ext
, 1},
2427 {"reduced-regs", N_("Reduced Register configuration (GPR16) option"), &nds32_gpr16
, 1},
2428 {"audio-isa-ext", N_("AUDIO ISA extension"), &nds32_audio_ext
, 1},
2429 {"fpu-sp-ext", N_("FPU SP extension"), &nds32_fpu_sp_ext
, 1},
2430 {"fpu-dp-ext", N_("FPU DP extension"), &nds32_fpu_dp_ext
, 1},
2431 {"fpu-fma", N_("FPU fused-multiply-add instructions"), &nds32_fpu_fma
, 1},
2432 {"dsp-ext", N_("DSP extension"), &nds32_dsp_ext
, 1},
2433 {"zol-ext", N_("hardware loop extension"), &nds32_zol_ext
, 1},
2434 {NULL
, NULL
, NULL
, 0}
2438 /* GAS declarations. */
2440 /* This is the callback for nds32-asm.c to parse operands. */
2442 nds32_asm_parse_operand (struct nds32_asm_desc
*pdesc
,
2443 struct nds32_asm_insn
*pinsn
,
2444 char **pstr
, int64_t *value
);
2447 static struct nds32_asm_desc asm_desc
;
2449 /* md_after_parse_args ()
2451 GAS will call md_after_parse_args whenever it is defined.
2452 This function checks any conflicting options specified. */
2455 nds32_after_parse_args (void)
2457 /* If -march option is not used in command-line, set the value of option
2458 variable according to NDS32_DEFAULT_ARCH_NAME. */
2459 nds32_parse_arch (nds32_arch_name
);
2462 /* This function is called when printing usage message (--help). */
2465 md_show_usage (FILE *stream
)
2467 struct nds32_parse_option_table
*coarse_tune
;
2468 struct nds32_set_option_table
*fine_tune
;
2470 fprintf (stream
, _("\n NDS32-specific assembler options:\n"));
2471 fprintf (stream
, _("\
2472 -O1, Optimize for performance\n\
2473 -Os Optimize for space\n"));
2474 fprintf (stream
, _("\
2475 -EL, -mel or -little Produce little endian output\n\
2476 -EB, -meb or -big Produce big endian output\n\
2477 -mpic Generate PIC\n\
2478 -mno-fp-as-gp-relax Suppress fp-as-gp relaxation for this file\n\
2479 -mb2bb-relax Back-to-back branch optimization\n\
2480 -mno-all-relax Suppress all relaxation for this file\n"));
2482 for (coarse_tune
= parse_opts
; coarse_tune
->name
!= NULL
; coarse_tune
++)
2484 if (coarse_tune
->help
!= NULL
)
2485 fprintf (stream
, _(" -m%s%s\n"),
2486 coarse_tune
->name
, _(coarse_tune
->help
));
2489 for (fine_tune
= toggle_opts
; fine_tune
->name
!= NULL
; fine_tune
++)
2491 if (fine_tune
->help
!= NULL
)
2492 fprintf (stream
, _(" -m[no-]%-17sEnable/Disable %s\n"),
2493 fine_tune
->name
, _(fine_tune
->help
));
2496 fprintf (stream
, _("\
2497 -mall-ext Turn on all extensions and instructions support\n"));
2501 nds32_frag_init (fragS
*fragp
)
2503 fragp
->tc_frag_data
.flag
= 0;
2504 fragp
->tc_frag_data
.opcode
= NULL
;
2505 fragp
->tc_frag_data
.fixup
= NULL
;
2510 /* This function reads an expression from a C string and returns a pointer past
2511 the end of the expression. */
2514 parse_expression (char *str
, expressionS
*exp
)
2519 tmp
= input_line_pointer
; /* Save line pointer. */
2520 input_line_pointer
= str
;
2522 resolve_register (exp
);
2523 s
= input_line_pointer
;
2524 input_line_pointer
= tmp
; /* Restore line pointer. */
2526 return s
; /* Return pointer to where parsing stopped. */
2530 nds32_start_line_hook (void)
2538 typedef void (*nds32_pseudo_opcode_func
) (int argc
, char *argv
[], unsigned int pv
);
2539 struct nds32_pseudo_opcode
2543 nds32_pseudo_opcode_func proc
;
2544 unsigned int pseudo_val
;
2546 /* Some instructions are not pseudo opcode, but they might still be
2547 expanded or changed with other instruction combination for some
2548 conditions. We also apply this structure to assist such work.
2550 For example, if the distance of branch target '.L0' is larger than
2557 will be transformed into:
2563 However, sometimes we do not want assembler to do such changes
2564 because compiler knows how to generate corresponding instruction sequence.
2565 Use this field to indicate that this opcode is also a physical instruction.
2566 If the flag 'verbatim' is nozero and this opcode
2567 is a physical instruction, we should not expand it. */
2570 #define PV_DONT_CARE 0
2572 static htab_t nds32_pseudo_opcode_hash
= NULL
;
2575 builtin_isreg (const char *s
, const char *x ATTRIBUTE_UNUSED
)
2577 if (s
[0] == '$' && str_hash_find (nds32_gprs_hash
, (s
+ 1)))
2583 builtin_regnum (const char *s
, const char *x ATTRIBUTE_UNUSED
)
2585 struct nds32_keyword
*k
;
2589 k
= str_hash_find (nds32_gprs_hash
, s
);
2598 builtin_addend (const char *s
, char *x ATTRIBUTE_UNUSED
)
2600 const char *ptr
= s
;
2602 while (*ptr
!= '+' && *ptr
!= '-' && *ptr
)
2608 return strtol (ptr
, NULL
, 0);
2612 md_assemblef (const char *format
, ...)
2614 /* FIXME: hope this is long enough. */
2619 va_start (ap
, format
);
2620 r
= vsnprintf (line
, sizeof (line
), format
, ap
);
2623 gas_assert (r
< sizeof (line
));
2626 /* Some prototypes here, since some op may use another op. */
2627 static void do_pseudo_li_internal (const char *rt
, int imm32s
);
2628 static void do_pseudo_move_reg_internal (char *dst
, char *src
);
2631 do_pseudo_b (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2632 unsigned int pv ATTRIBUTE_UNUSED
)
2634 char *arg_label
= argv
[0];
2639 md_assemblef ("sethi $ta,hi20(%s)", arg_label
);
2640 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label
);
2641 md_assemble ((char *) "add $ta,$ta,$gp");
2642 md_assemble ((char *) "jr $ta");
2646 md_assemblef ("j %s", arg_label
);
2652 do_pseudo_bal (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2653 unsigned int pv ATTRIBUTE_UNUSED
)
2655 char *arg_label
= argv
[0];
2657 /* bal|call label */
2660 md_assemblef ("sethi $ta,hi20(%s)", arg_label
);
2661 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label
);
2662 md_assemble ((char *) "add $ta,$ta,$gp");
2663 md_assemble ((char *) "jral $ta");
2667 md_assemblef ("jal %s", arg_label
);
2673 do_pseudo_bge (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2674 unsigned int pv ATTRIBUTE_UNUSED
)
2676 /* rt5, ra5, label */
2677 md_assemblef ("slt $ta,%s,%s", argv
[0], argv
[1]);
2678 md_assemblef ("beqz $ta,%s", argv
[2]);
2682 do_pseudo_bges (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2683 unsigned int pv ATTRIBUTE_UNUSED
)
2685 /* rt5, ra5, label */
2686 md_assemblef ("slts $ta,%s,%s", argv
[0], argv
[1]);
2687 md_assemblef ("beqz $ta,%s", argv
[2]);
2691 do_pseudo_bgt (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2692 unsigned int pv ATTRIBUTE_UNUSED
)
2694 /* bgt rt5, ra5, label */
2695 md_assemblef ("slt $ta,%s,%s", argv
[1], argv
[0]);
2696 md_assemblef ("bnez $ta,%s", argv
[2]);
2700 do_pseudo_bgts (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2701 unsigned int pv ATTRIBUTE_UNUSED
)
2703 /* bgt rt5, ra5, label */
2704 md_assemblef ("slts $ta,%s,%s", argv
[1], argv
[0]);
2705 md_assemblef ("bnez $ta,%s", argv
[2]);
2709 do_pseudo_ble (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2710 unsigned int pv ATTRIBUTE_UNUSED
)
2712 /* bgt rt5, ra5, label */
2713 md_assemblef ("slt $ta,%s,%s", argv
[1], argv
[0]);
2714 md_assemblef ("beqz $ta,%s", argv
[2]);
2718 do_pseudo_bles (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2719 unsigned int pv ATTRIBUTE_UNUSED
)
2721 /* bgt rt5, ra5, label */
2722 md_assemblef ("slts $ta,%s,%s", argv
[1], argv
[0]);
2723 md_assemblef ("beqz $ta,%s", argv
[2]);
2727 do_pseudo_blt (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2728 unsigned int pv ATTRIBUTE_UNUSED
)
2730 /* rt5, ra5, label */
2731 md_assemblef ("slt $ta,%s,%s", argv
[0], argv
[1]);
2732 md_assemblef ("bnez $ta,%s", argv
[2]);
2736 do_pseudo_blts (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2737 unsigned int pv ATTRIBUTE_UNUSED
)
2739 /* rt5, ra5, label */
2740 md_assemblef ("slts $ta,%s,%s", argv
[0], argv
[1]);
2741 md_assemblef ("bnez $ta,%s", argv
[2]);
2745 do_pseudo_br (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2746 unsigned int pv ATTRIBUTE_UNUSED
)
2748 md_assemblef ("jr %s", argv
[0]);
2752 do_pseudo_bral (int argc
, char *argv
[],
2753 unsigned int pv ATTRIBUTE_UNUSED
)
2756 md_assemblef ("jral $lp,%s", argv
[0]);
2758 md_assemblef ("jral %s,%s", argv
[0], argv
[1]);
2762 do_pseudo_la_internal (const char *arg_reg
, char *arg_label
,
2767 parse_expression (arg_label
, &exp
);
2768 if (exp
.X_op
!= O_symbol
)
2770 as_bad (_("la must use with symbol. '%s'"), line
);
2776 if (!nds32_pic
&& !strstr (arg_label
, "@"))
2778 md_assemblef ("sethi %s,hi20(%s)", arg_reg
, arg_label
);
2779 md_assemblef ("ori %s,%s,lo12(%s)", arg_reg
, arg_reg
, arg_label
);
2781 else if (strstr (arg_label
, "@TPOFF"))
2783 /* la $rt, sym@TPOFF */
2784 md_assemblef ("sethi $ta,hi20(%s)", arg_label
);
2785 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label
);
2786 md_assemblef ("add %s,$ta,%s", arg_reg
, TLS_REG
);
2788 else if (strstr(arg_label
, "@GOTTPOFF"))
2790 /* la $rt, sym@GOTTPOFF*/
2791 md_assemblef ("sethi $ta,hi20(%s)", arg_label
);
2792 md_assemblef ("lwi $ta,[$ta+lo12(%s)]", arg_label
);
2793 md_assemblef ("add %s,$ta,%s", arg_reg
, TLS_REG
);
2795 else if (nds32_pic
&& ((strstr (arg_label
, "@PLT")
2796 || strstr (arg_label
, "@GOTOFF"))))
2798 md_assemblef ("sethi $ta,hi20(%s)", arg_label
);
2799 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label
);
2800 md_assemblef ("add %s,$ta,$gp", arg_reg
);
2802 else if (nds32_pic
&& strstr (arg_label
, "@GOT"))
2804 long addend
= builtin_addend (arg_label
, NULL
);
2806 md_assemblef ("sethi $ta,hi20(%s)", arg_label
);
2807 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label
);
2808 md_assemblef ("lw %s,[$gp+$ta]", arg_reg
);
2811 if (addend
< 0x4000 && addend
>= -0x4000)
2813 md_assemblef ("addi %s,%s,%d", arg_reg
, arg_reg
, addend
);
2817 do_pseudo_li_internal ("$ta", addend
);
2818 md_assemblef ("add %s,$ta,%s", arg_reg
, arg_reg
);
2823 as_bad (_("need PIC qualifier with symbol. '%s'"), line
);
2828 do_pseudo_la (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2829 unsigned int pv ATTRIBUTE_UNUSED
)
2831 do_pseudo_la_internal (argv
[0], argv
[1], argv
[argc
]);
2835 do_pseudo_li_internal (const char *rt
, int imm32s
)
2837 if (enable_16bit
&& imm32s
<= 0xf && imm32s
>= -0x10)
2838 md_assemblef ("movi55 %s,%d", rt
, imm32s
);
2839 else if (imm32s
<= 0x7ffff && imm32s
>= -0x80000)
2840 md_assemblef ("movi %s,%d", rt
, imm32s
);
2841 else if ((imm32s
& 0xfff) == 0)
2842 md_assemblef ("sethi %s,hi20(%d)", rt
, imm32s
);
2845 md_assemblef ("sethi %s,hi20(%d)", rt
, imm32s
);
2846 md_assemblef ("ori %s,%s,lo12(%d)", rt
, rt
, imm32s
);
2851 do_pseudo_li (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2852 unsigned int pv ATTRIBUTE_UNUSED
)
2854 /* Validate argv[1] for constant expression. */
2857 parse_expression (argv
[1], &exp
);
2858 if (exp
.X_op
!= O_constant
)
2860 as_bad (_("Operand is not a constant. `%s'"), argv
[argc
]);
2864 do_pseudo_li_internal (argv
[0], exp
.X_add_number
);
2868 do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2873 const char *sign
= "";
2875 /* Prepare arguments for various load/store. */
2876 sign
= (pv
& 0x10) ? "s" : "";
2877 ls
= (pv
& 0x80000000) ? 's' : 'l';
2880 case 0: size
= 'b'; break;
2881 case 1: size
= 'h'; break;
2882 case 2: size
= 'w'; break;
2885 if (ls
== 's' || size
== 'w')
2888 if (builtin_isreg (argv
[1], NULL
))
2891 md_assemblef ("%c%ci %s,[%s]", ls
, size
, argv
[0], argv
[1]);
2893 else if (!nds32_pic
)
2896 if (strstr (argv
[1], "@TPOFF"))
2898 /* ls.w $rt, sym@TPOFF */
2899 md_assemblef ("sethi $ta,hi20(%s)", argv
[1]);
2900 md_assemblef ("ori $ta,$ta,lo12(%s)", argv
[1]);
2901 md_assemblef ("%c%c%s %s,[$ta+%s]", ls
, size
, sign
, argv
[0], TLS_REG
);
2903 else if (strstr (argv
[1], "@GOTTPOFF"))
2905 /* ls.w $rt, sym@GOTTPOFF */
2906 md_assemblef ("sethi $ta,hi20(%s)", argv
[1]);
2907 md_assemblef ("lwi $ta,[$ta+lo12(%s)]", argv
[1]);
2908 md_assemblef ("%c%c%s %s,[$ta+%s]", ls
, size
, sign
, argv
[0], TLS_REG
);
2913 md_assemblef ("sethi $ta,hi20(%s)", argv
[1]);
2914 md_assemblef ("%c%c%si %s,[$ta+lo12(%s)]", ls
, size
, sign
, argv
[0], argv
[1]);
2922 if (strstr (argv
[1], "@GOTOFF"))
2925 md_assemblef ("sethi $ta,hi20(%s)", argv
[1]);
2926 md_assemblef ("ori $ta,$ta,lo12(%s)", argv
[1]);
2927 md_assemblef ("%c%c%s %s,[$ta+$gp]", ls
, size
, sign
, argv
[0]);
2929 else if (strstr (argv
[1], "@GOT"))
2931 long addend
= builtin_addend (argv
[1], NULL
);
2933 md_assemblef ("sethi $ta,hi20(%s)", argv
[1]);
2934 md_assemblef ("ori $ta,$ta,lo12(%s)", argv
[1]);
2935 md_assemble ((char *) "lw $ta,[$gp+$ta]"); /* Load address word. */
2936 if (addend
< 0x10000 && addend
>= -0x10000)
2938 md_assemblef ("%c%c%si %s,[$ta+(%d)]", ls
, size
, sign
, argv
[0], addend
);
2943 do_pseudo_li_internal (argv
[0], addend
);
2944 md_assemblef ("%c%c%s %s,[$ta+%s]", ls
, size
, sign
, argv
[0], argv
[0]);
2949 as_bad (_("needs @GOT or @GOTOFF. %s"), argv
[argc
]);
2956 do_pseudo_ls_bhwp (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2959 char *arg_rt
= argv
[0];
2960 char *arg_label
= argv
[1];
2961 char *arg_inc
= argv
[2];
2964 const char *sign
= "";
2966 /* Prepare arguments for various load/store. */
2967 sign
= (pv
& 0x10) ? "s" : "";
2968 ls
= (pv
& 0x80000000) ? 's' : 'l';
2971 case 0: size
= 'b'; break;
2972 case 1: size
= 'h'; break;
2973 case 2: size
= 'w'; break;
2976 if (ls
== 's' || size
== 'w')
2979 do_pseudo_la_internal ("$ta", arg_label
, argv
[argc
]);
2980 md_assemblef ("%c%c%si.bi %s,[$ta],%s", ls
, size
, sign
, arg_rt
, arg_inc
);
2984 do_pseudo_ls_bhwpc (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2987 char *arg_rt
= argv
[0];
2988 char *arg_inc
= argv
[1];
2991 const char *sign
= "";
2993 /* Prepare arguments for various load/store. */
2994 sign
= (pv
& 0x10) ? "s" : "";
2995 ls
= (pv
& 0x80000000) ? 's' : 'l';
2998 case 0: size
= 'b'; break;
2999 case 1: size
= 'h'; break;
3000 case 2: size
= 'w'; break;
3003 if (ls
== 's' || size
== 'w')
3006 md_assemblef ("%c%c%si.bi %s,[$ta],%s", ls
, size
, sign
, arg_rt
, arg_inc
);
3010 do_pseudo_ls_bhwi (int argc ATTRIBUTE_UNUSED
, char *argv
[],
3015 const char *sign
= "";
3017 /* Prepare arguments for various load/store. */
3018 sign
= (pv
& 0x10) ? "s" : "";
3019 ls
= (pv
& 0x80000000) ? 's' : 'l';
3022 case 0: size
= 'b'; break;
3023 case 1: size
= 'h'; break;
3024 case 2: size
= 'w'; break;
3027 if (ls
== 's' || size
== 'w')
3030 md_assemblef ("%c%c%si.bi %s,%s,%s",
3031 ls
, size
, sign
, argv
[0], argv
[1], argv
[2]);
3035 do_pseudo_move_reg_internal (char *dst
, char *src
)
3038 md_assemblef ("mov55 %s,%s", dst
, src
);
3040 md_assemblef ("ori %s,%s,0", dst
, src
);
3044 do_pseudo_move (int argc ATTRIBUTE_UNUSED
, char *argv
[],
3045 unsigned int pv ATTRIBUTE_UNUSED
)
3049 if (builtin_isreg (argv
[1], NULL
))
3050 do_pseudo_move_reg_internal (argv
[0], argv
[1]);
3053 parse_expression (argv
[1], &exp
);
3054 if (exp
.X_op
== O_constant
)
3055 /* move $rt, imm -> li $rt, imm */
3056 do_pseudo_li_internal (argv
[0], exp
.X_add_number
);
3058 /* l.w $rt, var -> l.w $rt, var */
3059 do_pseudo_ls_bhw (argc
, argv
, 2);
3064 do_pseudo_neg (int argc ATTRIBUTE_UNUSED
, char *argv
[],
3065 unsigned int pv ATTRIBUTE_UNUSED
)
3067 /* Instead of "subri". */
3068 md_assemblef ("subri %s,%s,0", argv
[0], argv
[1]);
3072 do_pseudo_not (int argc ATTRIBUTE_UNUSED
, char *argv
[],
3073 unsigned int pv ATTRIBUTE_UNUSED
)
3075 md_assemblef ("nor %s,%s,%s", argv
[0], argv
[1], argv
[1]);
3079 do_pseudo_pushpopm (int argc
, char *argv
[],
3080 unsigned int pv ATTRIBUTE_UNUSED
)
3082 /* posh/pop $ra, $rb */
3083 /* SMW.{b | a}{i | d}{m?} Rb, [Ra], Re, Enable4 */
3084 int rb
, re
, ra
, en4
;
3086 const char *opc
= "pushpopm";
3089 as_bad ("'pushm/popm $ra5, $rb5, $label' is deprecated. "
3090 "Only 'pushm/popm $ra5' is supported now. %s", argv
[argc
]);
3092 as_bad ("'pushm/popm $ra5, $rb5'. %s\n", argv
[argc
]);
3094 if (strstr (argv
[argc
], "pop") == argv
[argc
])
3096 else if (strstr (argv
[argc
], "push") == argv
[argc
])
3099 as_fatal ("nds32-as internal error. %s", argv
[argc
]);
3101 rb
= builtin_regnum (argv
[0], NULL
);
3102 re
= builtin_regnum (argv
[1], NULL
);
3106 as_warn ("$rb should not be smaller than $ra. %s", argv
[argc
]);
3107 /* Swap to right order. */
3113 /* Build enable4 mask. */
3115 if (re
>= 28 || rb
>= 28)
3117 for (i
= (rb
>= 28? rb
: 28); i
<= re
; i
++)
3118 en4
|= 1 << (3 - (i
- 28));
3121 /* Adjust $re, $rb. */
3124 else if (nds32_gpr16
!= 1 && re
>= 28)
3127 /* Reduce register. */
3128 if (nds32_gpr16
&& re
> 10 && !(rb
== 31 && re
== 31))
3130 if (re
>= 15 && strstr (opc
, "smw") != NULL
)
3131 md_assemblef ("%s $r15,[$sp],$r15,%d", opc
, en4
);
3133 md_assemblef ("%s $r%d,[$sp],$r10, 0x0", opc
, rb
);
3134 if (re
>= 15 && strstr (opc
, "lmw") != NULL
)
3135 md_assemblef ("%s $r15,[$sp],$r15,%d", opc
, en4
);
3138 md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc
, rb
, re
, en4
);
3142 do_pseudo_pushpop (int argc
, char *argv
[],
3143 unsigned int pv ATTRIBUTE_UNUSED
)
3145 /* push/pop $ra5, $label=$sp */
3149 as_bad ("'push/pop $ra5, rb5' is deprecated. "
3150 "Only 'push/pop $ra5' is supported now. %s", argv
[argc
]);
3154 argvm
[2] = argv
[argc
];
3155 do_pseudo_pushpopm (2, argvm
, PV_DONT_CARE
);
3159 do_pseudo_v3push (int argc ATTRIBUTE_UNUSED
, char *argv
[],
3160 unsigned int pv ATTRIBUTE_UNUSED
)
3162 md_assemblef ("push25 %s,%s", argv
[0], argv
[1]);
3166 do_pseudo_v3pop (int argc ATTRIBUTE_UNUSED
, char *argv
[],
3167 unsigned int pv ATTRIBUTE_UNUSED
)
3169 md_assemblef ("pop25 %s,%s", argv
[0], argv
[1]);
3172 /* pv == 0, parsing "push.s" pseudo instruction operands.
3173 pv != 0, parsing "pop.s" pseudo instruction operands. */
3176 do_pseudo_pushpop_stack (int argc
, char *argv
[],
3179 /* push.s Rb,Re,{$fp $gp $lp $sp} ==> smw.adm Rb,[$sp],Re,Eable4 */
3180 /* pop.s Rb,Re,{$fp $gp $lp $sp} ==> lmw.bim Rb,[$sp],Re,Eable4 */
3185 const char *opc
= (pv
== 0) ? "smw.adm" : "lmw.bim";
3191 /* argc=1, operands pattern: { $fp $gp $lp $sp } */
3193 /* Set register number Rb = Re = $sp = $r31. */
3196 else if (argc
== 2 || argc
== 3)
3198 /* argc=2, operands pattern: Rb, Re */
3199 /* argc=3, operands pattern: Rb, Re, { $fp $gp $lp $sp } */
3201 /* Get register number in integer. */
3202 rb
= builtin_regnum (argv
[0], NULL
);
3203 re
= builtin_regnum (argv
[1], NULL
);
3205 /* Rb should be equal/less than Re. */
3207 as_bad ("The first operand (%s) should be equal to or smaller than "
3208 "second operand (%s).", argv
[0], argv
[1]);
3210 /* forbid using $fp|$gp|$lp|$sp in Rb or Re
3213 as_bad ("Cannot use $fp, $gp, $lp, or $sp at first operand !!");
3215 as_bad ("Cannot use $fp, $gp, $lp, or $sp at second operand !!");
3219 as_bad ("Invalid operands pattern !!");
3222 /* Build Enable4 mask. */
3223 /* Using last_arg_index for argc=1|2|3 is safe, because $fp, $gp, $lp,
3224 and $sp only appear in argc=1 or argc=3 if argc=2, en4 remains 0,
3225 which is also valid for code generation. */
3227 last_arg_index
= argc
- 1;
3228 if (strstr (argv
[last_arg_index
], "$fp"))
3230 if (strstr (argv
[last_arg_index
], "$gp"))
3232 if (strstr (argv
[last_arg_index
], "$lp"))
3234 if (strstr (argv
[last_arg_index
], "$sp"))
3237 md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc
, rb
, re
, en4
);
3241 do_pseudo_push_bhwd (int argc ATTRIBUTE_UNUSED
, char *argv
[],
3242 unsigned int pv ATTRIBUTE_UNUSED
)
3245 /* If users omit push location, use $sp as default value. */
3246 char location
[8] = "$sp"; /* 8 is enough for register name. */
3250 case 0: size
= 'b'; break;
3251 case 1: size
= 'h'; break;
3252 case 2: size
= 'w'; break;
3253 case 3: size
= 'w'; break;
3258 strncpy (location
, argv
[1], sizeof (location
) - 1);
3259 location
[sizeof (location
) - 1] = '\0';
3262 md_assemblef ("l.%c $ta,%s", size
, argv
[0]);
3263 md_assemblef ("smw.adm $ta,[%s],$ta", location
);
3265 if ((pv
& 0x3) == 0x3) /* double-word */
3267 md_assemblef ("l.w $ta,%s+4", argv
[0]);
3268 md_assemblef ("smw.adm $ta,[%s],$ta", location
);
3273 do_pseudo_pop_bhwd (int argc ATTRIBUTE_UNUSED
, char *argv
[],
3274 unsigned int pv ATTRIBUTE_UNUSED
)
3277 /* If users omit pop location, use $sp as default value. */
3278 char location
[8] = "$sp"; /* 8 is enough for register name. */
3282 case 0: size
= 'b'; break;
3283 case 1: size
= 'h'; break;
3284 case 2: size
= 'w'; break;
3285 case 3: size
= 'w'; break;
3290 strncpy (location
, argv
[2], sizeof (location
) - 1);
3291 location
[sizeof (location
) - 1] = '\0';
3294 if ((pv
& 0x3) == 0x3) /* double-word */
3296 md_assemblef ("lmw.bim %s,[%s],%s", argv
[1], location
, argv
[1]);
3297 md_assemblef ("s.w %s,%s+4", argv
[1], argv
[0]);
3300 md_assemblef ("lmw.bim %s,[%s],%s", argv
[1], location
, argv
[1]);
3301 md_assemblef ("s.%c %s,%s", size
, argv
[1], argv
[0]);
3305 do_pseudo_pusha (int argc ATTRIBUTE_UNUSED
, char *argv
[],
3306 unsigned int pv ATTRIBUTE_UNUSED
)
3308 /* If users omit push location, use $sp as default value. */
3309 char location
[8] = "$sp"; /* 8 is enough for register name. */
3313 strncpy (location
, argv
[1], sizeof (location
) - 1);
3314 location
[sizeof (location
) - 1] = '\0';
3317 md_assemblef ("la $ta,%s", argv
[0]);
3318 md_assemblef ("smw.adm $ta,[%s],$ta", location
);
3322 do_pseudo_pushi (int argc ATTRIBUTE_UNUSED
, char *argv
[],
3323 unsigned int pv ATTRIBUTE_UNUSED
)
3325 /* If users omit push location, use $sp as default value. */
3326 char location
[8] = "$sp"; /* 8 is enough for register name. */
3330 strncpy (location
, argv
[1], sizeof (location
) - 1);
3331 location
[sizeof (location
) - 1] = '\0';
3334 md_assemblef ("li $ta,%s", argv
[0]);
3335 md_assemblef ("smw.adm $ta,[%s],$ta", location
);
3338 static struct nds32_pseudo_opcode nds32_pseudo_opcode_table
[] =
3340 {"b", 1, do_pseudo_b
, 0, 0},
3341 {"bal", 1, do_pseudo_bal
, 0, 0},
3343 {"bge", 3, do_pseudo_bge
, 0, 0},
3344 {"bges", 3, do_pseudo_bges
, 0, 0},
3346 {"bgt", 3, do_pseudo_bgt
, 0, 0},
3347 {"bgts", 3, do_pseudo_bgts
, 0, 0},
3349 {"ble", 3, do_pseudo_ble
, 0, 0},
3350 {"bles", 3, do_pseudo_bles
, 0, 0},
3352 {"blt", 3, do_pseudo_blt
, 0, 0},
3353 {"blts", 3, do_pseudo_blts
, 0, 0},
3355 {"br", 1, do_pseudo_br
, 0, 0},
3356 {"bral", 1, do_pseudo_bral
, 0, 0},
3358 {"call", 1, do_pseudo_bal
, 0, 0},
3360 {"la", 2, do_pseudo_la
, 0, 0},
3361 {"li", 2, do_pseudo_li
, 0, 0},
3363 {"l.b", 2, do_pseudo_ls_bhw
, 0, 0},
3364 {"l.h", 2, do_pseudo_ls_bhw
, 1, 0},
3365 {"l.w", 2, do_pseudo_ls_bhw
, 2, 0},
3366 {"l.bs", 2, do_pseudo_ls_bhw
, 0 | 0x10, 0},
3367 {"l.hs", 2, do_pseudo_ls_bhw
, 1 | 0x10, 0},
3368 {"s.b", 2, do_pseudo_ls_bhw
, 0 | 0x80000000, 0},
3369 {"s.h", 2, do_pseudo_ls_bhw
, 1 | 0x80000000, 0},
3370 {"s.w", 2, do_pseudo_ls_bhw
, 2 | 0x80000000, 0},
3372 {"l.bp", 3, do_pseudo_ls_bhwp
, 0, 0},
3373 {"l.bpc", 3, do_pseudo_ls_bhwpc
, 0, 0},
3374 {"l.hp", 3, do_pseudo_ls_bhwp
, 1, 0},
3375 {"l.hpc", 3, do_pseudo_ls_bhwpc
, 1, 0},
3376 {"l.wp", 3, do_pseudo_ls_bhwp
, 2, 0},
3377 {"l.wpc", 3, do_pseudo_ls_bhwpc
, 2, 0},
3378 {"l.bsp", 3, do_pseudo_ls_bhwp
, 0 | 0x10, 0},
3379 {"l.bspc", 3, do_pseudo_ls_bhwpc
, 0 | 0x10, 0},
3380 {"l.hsp", 3, do_pseudo_ls_bhwp
, 1 | 0x10, 0},
3381 {"l.hspc", 3, do_pseudo_ls_bhwpc
, 1 | 0x10, 0},
3382 {"s.bp", 3, do_pseudo_ls_bhwp
, 0 | 0x80000000, 0},
3383 {"s.bpc", 3, do_pseudo_ls_bhwpc
, 0 | 0x80000000, 0},
3384 {"s.hp", 3, do_pseudo_ls_bhwp
, 1 | 0x80000000, 0},
3385 {"s.hpc", 3, do_pseudo_ls_bhwpc
, 1 | 0x80000000, 0},
3386 {"s.wp", 3, do_pseudo_ls_bhwp
, 2 | 0x80000000, 0},
3387 {"s.wpc", 3, do_pseudo_ls_bhwpc
, 2 | 0x80000000, 0},
3388 {"s.bsp", 3, do_pseudo_ls_bhwp
, 0 | 0x80000000 | 0x10, 0},
3389 {"s.hsp", 3, do_pseudo_ls_bhwp
, 1 | 0x80000000 | 0x10, 0},
3391 {"lbi.p", 3, do_pseudo_ls_bhwi
, 0, 0},
3392 {"lhi.p", 3, do_pseudo_ls_bhwi
, 1, 0},
3393 {"lwi.p", 3, do_pseudo_ls_bhwi
, 2, 0},
3394 {"sbi.p", 3, do_pseudo_ls_bhwi
, 0 | 0x80000000, 0},
3395 {"shi.p", 3, do_pseudo_ls_bhwi
, 1 | 0x80000000, 0},
3396 {"swi.p", 3, do_pseudo_ls_bhwi
, 2 | 0x80000000, 0},
3397 {"lbsi.p", 3, do_pseudo_ls_bhwi
, 0 | 0x10, 0},
3398 {"lhsi.p", 3, do_pseudo_ls_bhwi
, 1 | 0x10, 0},
3399 {"lwsi.p", 3, do_pseudo_ls_bhwi
, 2 | 0x10, 0},
3401 {"move", 2, do_pseudo_move
, 0, 0},
3402 {"neg", 2, do_pseudo_neg
, 0, 0},
3403 {"not", 2, do_pseudo_not
, 0, 0},
3405 {"pop", 2, do_pseudo_pushpop
, 0, 0},
3406 {"push", 2, do_pseudo_pushpop
, 0, 0},
3407 {"popm", 2, do_pseudo_pushpopm
, 0, 0},
3408 {"pushm", 3, do_pseudo_pushpopm
, 0, 0},
3410 {"v3push", 2, do_pseudo_v3push
, 0, 0},
3411 {"v3pop", 2, do_pseudo_v3pop
, 0, 0},
3413 /* Support pseudo instructions of pushing/poping registers into/from stack
3414 push.s Rb, Re, { $fp $gp $lp $sp } ==> smw.adm Rb,[$sp],Re,Enable4
3415 pop.s Rb, Re, { $fp $gp $lp $sp } ==> lmw.bim Rb,[$sp],Re,Enable4 */
3416 { "push.s", 3, do_pseudo_pushpop_stack
, 0, 0 },
3417 { "pop.s", 3, do_pseudo_pushpop_stack
, 1, 0 },
3418 { "push.b", 2, do_pseudo_push_bhwd
, 0, 0 },
3419 { "push.h", 2, do_pseudo_push_bhwd
, 1, 0 },
3420 { "push.w", 2, do_pseudo_push_bhwd
, 2, 0 },
3421 { "push.d", 2, do_pseudo_push_bhwd
, 3, 0 },
3422 { "pop.b", 3, do_pseudo_pop_bhwd
, 0, 0 },
3423 { "pop.h", 3, do_pseudo_pop_bhwd
, 1, 0 },
3424 { "pop.w", 3, do_pseudo_pop_bhwd
, 2, 0 },
3425 { "pop.d", 3, do_pseudo_pop_bhwd
, 3, 0 },
3426 { "pusha", 2, do_pseudo_pusha
, 0, 0 },
3427 { "pushi", 2, do_pseudo_pushi
, 0, 0 },
3429 {NULL
, 0, NULL
, 0, 0}
3433 nds32_init_nds32_pseudo_opcodes (void)
3435 struct nds32_pseudo_opcode
*opcode
;
3437 nds32_pseudo_opcode_hash
= str_htab_create ();
3438 for (opcode
= nds32_pseudo_opcode_table
; opcode
->opcode
; opcode
++)
3439 if (str_hash_insert (nds32_pseudo_opcode_hash
, opcode
->opcode
, opcode
, 0))
3440 as_fatal (_("duplicate %s"), opcode
->opcode
);
3443 static struct nds32_pseudo_opcode
*
3444 nds32_lookup_pseudo_opcode (const char *str
)
3446 struct nds32_pseudo_opcode
*result
;
3449 /* (*op) is the first word of current source line (*str) */
3450 int maxlen
= strlen (str
);
3451 char *op
= xmalloc (maxlen
+ 1);
3453 for (i
= 0; i
< maxlen
; i
++)
3455 if (ISSPACE (op
[i
] = str
[i
]))
3460 result
= str_hash_find (nds32_pseudo_opcode_hash
, op
);
3466 nds32_pseudo_opcode_wrapper (char *line
, struct nds32_pseudo_opcode
*opcode
)
3469 char *argv
[8] = {NULL
};
3471 char *str
= xstrdup (line
);
3473 /* Parse arguments for opcode. */
3474 s
= str
+ strlen (opcode
->opcode
);
3479 /* Dummy comma to ease separate arguments as below. */
3485 if (argc
>= opcode
->argc
3486 || (argc
>= (int)ARRAY_SIZE (argv
) - 1))
3487 as_bad (_("Too many argument. `%s'"), line
);
3494 } while (s
[0] != '\0');
3496 /* Put the origin line for debugging. */
3498 opcode
->proc (argc
, argv
, opcode
->pseudo_val
);
3502 /* This function will be invoked from function `nds32_after_parse_args'.
3503 Thus, if the value of option has been set, keep the value the way it is. */
3506 nds32_parse_arch (const char *str
)
3508 static const struct nds32_arch
3519 {"v3m", ISA_V3M
, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_AABI
},
3520 {"v3j", ISA_V3
, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_AABI
},
3521 {"v3s", ISA_V3
, 0, 1, 0, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_V2FP_PLUS
},
3522 {"v3f", ISA_V3
, 0, 1, 1, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_V2FP_PLUS
},
3523 {"v3", ISA_V3
, 0, 0, 0, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_AABI
},
3524 {"v2j", ISA_V2
, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_AABI
},
3525 {"v2s", ISA_V2
, 0, 1, 0, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_V2FP_PLUS
},
3526 {"v2f", ISA_V2
, 0, 1, 1, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_V2FP_PLUS
},
3527 {"v2", ISA_V2
, 0, 0, 0, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_AABI
},
3531 for (i
= 0; i
< ARRAY_SIZE (archs
); i
++)
3533 if (strcmp (str
, archs
[i
].name
) != 0)
3536 /* The value `-1' represents this option has *NOT* been set. */
3537 nds32_baseline
= (-1 != nds32_baseline
) ? nds32_baseline
: archs
[i
].baseline
;
3538 nds32_gpr16
= (-1 != nds32_gpr16
) ? nds32_gpr16
: archs
[i
].reduced_reg
;
3539 nds32_fpu_sp_ext
= (-1 != nds32_fpu_sp_ext
) ? nds32_fpu_sp_ext
: archs
[i
].fpu_sp_ext
;
3540 nds32_fpu_dp_ext
= (-1 != nds32_fpu_dp_ext
) ? nds32_fpu_dp_ext
: archs
[i
].fpu_dp_ext
;
3541 nds32_freg
= (-1 != nds32_freg
) ? nds32_freg
: archs
[i
].fpu_freg
;
3542 nds32_abi
= (-1 != nds32_abi
) ? nds32_abi
: archs
[i
].abi
;
3547 /* Logic here rejects the input arch name. */
3548 as_bad (_("unknown arch name `%s'\n"), str
);
3553 /* This function parses "baseline" specified. */
3556 nds32_parse_baseline (const char *str
)
3558 if (strcmp (str
, "v3") == 0)
3559 nds32_baseline
= ISA_V3
;
3560 else if (strcmp (str
, "v3m") == 0)
3561 nds32_baseline
= ISA_V3M
;
3562 else if (strcmp (str
, "v2") == 0)
3563 nds32_baseline
= ISA_V2
;
3566 /* Logic here rejects the input baseline. */
3567 as_bad (_("unknown baseline `%s'\n"), str
);
3574 /* This function parses "fpu-freg" specified. */
3577 nds32_parse_freg (const char *str
)
3579 if (strcmp (str
, "2") == 0)
3580 nds32_freg
= E_NDS32_FPU_REG_32SP_16DP
;
3581 else if (strcmp (str
, "3") == 0)
3582 nds32_freg
= E_NDS32_FPU_REG_32SP_32DP
;
3583 else if (strcmp (str
, "1") == 0)
3584 nds32_freg
= E_NDS32_FPU_REG_16SP_8DP
;
3585 else if (strcmp (str
, "0") == 0)
3586 nds32_freg
= E_NDS32_FPU_REG_8SP_4DP
;
3589 /* Logic here rejects the input FPU configuration. */
3590 as_bad (_("unknown FPU configuration `%s'\n"), str
);
3597 /* This function parse "abi=" specified. */
3600 nds32_parse_abi (const char *str
)
3602 if (strcmp (str
, "v2") == 0)
3603 nds32_abi
= E_NDS_ABI_AABI
;
3605 else if (strcmp (str
, "v2fp") == 0)
3606 nds32_abi
= E_NDS_ABI_V2FP
;
3607 else if (strcmp (str
, "v1") == 0)
3608 nds32_abi
= E_NDS_ABI_V1
;
3609 else if (strcmp (str
,"v2fpp") == 0)
3610 nds32_abi
= E_NDS_ABI_V2FP_PLUS
;
3613 /* Logic here rejects the input abi version. */
3614 as_bad (_("unknown ABI version`%s'\n"), str
);
3621 /* This function turn on all extensions and instructions support. */
3624 nds32_all_ext (void)
3629 nds32_16bit_ext
= 1;
3631 nds32_perf_ext2
= 1;
3632 nds32_string_ext
= 1;
3633 nds32_audio_ext
= 1;
3635 nds32_fpu_sp_ext
= 1;
3636 nds32_fpu_dp_ext
= 1;
3639 /* Turn off reduced register. */
3645 /* GAS will call md_parse_option whenever getopt returns an unrecognized code,
3646 presumably indicating a special code value which appears in md_longopts.
3647 This function should return non-zero if it handled the option and zero
3648 otherwise. There is no need to print a message about an option not being
3649 recognized. This will be handled by the generic code. */
3652 nds32_parse_option (int c
, const char *arg
)
3654 struct nds32_parse_option_table
*coarse_tune
;
3655 struct nds32_set_option_table
*fine_tune
;
3656 const char *ptr_arg
= NULL
;
3660 case OPTION_OPTIMIZE
:
3662 optimize_for_space
= 0;
3664 case OPTION_OPTIMIZE_SPACE
:
3666 optimize_for_space
= 1;
3669 target_big_endian
= 1;
3672 target_big_endian
= 0;
3680 case OPTION_RELAX_FP_AS_GP_OFF
:
3681 nds32_relax_fp_as_gp
= 0;
3683 case OPTION_RELAX_B2BB_ON
:
3684 nds32_relax_b2bb
= 1;
3686 case OPTION_RELAX_ALL_OFF
:
3687 nds32_relax_all
= 0;
3690 /* Determination of which option table to search for to save time. */
3694 ptr_arg
= strchr (arg
, '=');
3698 /* Find the value after '='. */
3699 if (ptr_arg
!= NULL
)
3701 for (coarse_tune
= parse_opts
; coarse_tune
->name
!= NULL
; coarse_tune
++)
3703 if (strncmp (arg
, coarse_tune
->name
, (ptr_arg
- arg
)) == 0)
3705 coarse_tune
->func (ptr_arg
);
3714 /* Filter out the Disable option first. */
3715 if (startswith (arg
, "no-"))
3721 for (fine_tune
= toggle_opts
; fine_tune
->name
!= NULL
; fine_tune
++)
3723 if (strcmp (arg
, fine_tune
->name
) == 0)
3725 if (fine_tune
->var
!= NULL
)
3726 *fine_tune
->var
= (disable
) ? 0 : 1;
3731 /* Nothing match. */
3738 /* tc_check_label */
3741 nds32_check_label (symbolS
*label ATTRIBUTE_UNUSED
)
3743 /* The code used to create BB is move to frob_label.
3744 They should go there. */
3748 set_endian_little (int on
)
3750 target_big_endian
= !on
;
3753 /* These functions toggles the generation of 16-bit. First encounter signals
3754 the beginning of not generating 16-bit instructions and next encounter
3755 signals the restoring back to default behavior. */
3758 trigger_16bit (int trigger
)
3760 enable_16bit
= trigger
;
3763 static int backup_16bit_mode
;
3765 restore_16bit (int no_use ATTRIBUTE_UNUSED
)
3767 enable_16bit
= backup_16bit_mode
;
3771 off_16bit (int no_use ATTRIBUTE_UNUSED
)
3773 backup_16bit_mode
= enable_16bit
;
3777 /* Built-in segments for small object. */
3778 typedef struct nds32_seg_entryT
3785 nds32_seg_entry nds32_seg_table
[] =
3787 {NULL
, ".sdata_f", SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
| SEC_DATA
3788 | SEC_HAS_CONTENTS
| SEC_SMALL_DATA
},
3789 {NULL
, ".sdata_b", SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
| SEC_DATA
3790 | SEC_HAS_CONTENTS
| SEC_SMALL_DATA
},
3791 {NULL
, ".sdata_h", SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
| SEC_DATA
3792 | SEC_HAS_CONTENTS
| SEC_SMALL_DATA
},
3793 {NULL
, ".sdata_w", SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
| SEC_DATA
3794 | SEC_HAS_CONTENTS
| SEC_SMALL_DATA
},
3795 {NULL
, ".sdata_d", SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
| SEC_DATA
3796 | SEC_HAS_CONTENTS
| SEC_SMALL_DATA
},
3797 {NULL
, ".sbss_f", SEC_ALLOC
| SEC_SMALL_DATA
},
3798 {NULL
, ".sbss_b", SEC_ALLOC
| SEC_SMALL_DATA
},
3799 {NULL
, ".sbss_h", SEC_ALLOC
| SEC_SMALL_DATA
},
3800 {NULL
, ".sbss_w", SEC_ALLOC
| SEC_SMALL_DATA
},
3801 {NULL
, ".sbss_d", SEC_ALLOC
| SEC_SMALL_DATA
}
3804 /* Indexes to nds32_seg_table[]. */
3805 enum NDS32_SECTIONS_ENUM
3807 SDATA_F_SECTION
= 0,
3808 SDATA_B_SECTION
= 1,
3809 SDATA_H_SECTION
= 2,
3810 SDATA_W_SECTION
= 3,
3811 SDATA_D_SECTION
= 4,
3819 /* The following code is borrowed from v850_seg. Revise this is needed. */
3822 do_nds32_seg (int i
, subsegT sub
)
3824 nds32_seg_entry
*seg
= nds32_seg_table
+ i
;
3826 obj_elf_section_change_hook ();
3829 subseg_set (seg
->s
, sub
);
3832 seg
->s
= subseg_new (seg
->name
, sub
);
3833 if (OUTPUT_FLAVOR
== bfd_target_elf_flavour
)
3835 bfd_set_section_flags (seg
->s
, seg
->flags
);
3836 if ((seg
->flags
& SEC_LOAD
) == 0)
3837 seg_info (seg
->s
)->bss
= 1;
3845 subsegT sub
= get_absolute_expression ();
3847 do_nds32_seg (i
, sub
);
3848 demand_empty_rest_of_line ();
3851 /* Set if label adjustment is needed. I should not adjust .xbyte in dwarf. */
3852 static symbolS
*nds32_last_label
; /* Last label for alignment. */
3855 add_mapping_symbol_for_align (int shift
, valueT addr
, int is_data_align
)
3857 if ((shift
> 1) && (addr
& 1))
3859 int n
= (1 << shift
) - 1;
3861 add_mapping_symbol (MAP_CODE
, 1, 0);
3862 else if ((int) (addr
& n
) != n
)
3863 add_mapping_symbol (MAP_CODE
, 1, 0);
3865 else if ((shift
> 1) && ((int) (addr
& 1) == 0))
3866 add_mapping_symbol (MAP_CODE
, 0, 0);
3869 /* This code is referred from D30V for adjust label to be with pending
3870 alignment. For example,
3874 Without this, the above label will not attach to incoming data. */
3877 nds32_adjust_label (int n
)
3879 /* FIXME: I think adjust label and alignment is
3880 the programmer's obligation. Sadly, VLSI team doesn't
3881 properly use .align for their test cases.
3882 So I re-implement cons_align and auto adjust labels, again.
3884 I think d30v's implementation is simple and good enough. */
3886 symbolS
*label
= nds32_last_label
;
3887 nds32_last_label
= NULL
;
3889 /* SEC_ALLOC is used to eliminate .debug_ sections.
3890 SEC_CODE is used to include section for ILM. */
3891 if (((now_seg
->flags
& SEC_ALLOC
) == 0 && (now_seg
->flags
& SEC_CODE
) == 0)
3892 || strcmp (now_seg
->name
, ".eh_frame") == 0
3893 || strcmp (now_seg
->name
, ".gcc_except_table") == 0)
3896 /* Only frag by alignment when needed.
3897 Otherwise, it will fail to optimize labels on 4-byte boundary. (bug8454)
3898 See md_convert_frag () and RELAX_SET_RELAXABLE (frag) for details. */
3899 if (frag_now_fix () & ((1 << n
) -1 ))
3901 if (subseg_text_p (now_seg
))
3903 add_mapping_symbol_for_align (n
, frag_now_fix (), 1);
3904 frag_align_code (n
, 0);
3907 frag_align (n
, 0, 0);
3909 /* Record the minimum alignment for this segment. */
3910 record_alignment (now_seg
, n
- OCTETS_PER_BYTE_POWER
);
3916 int label_seen
= false;
3917 struct frag
*old_frag
;
3918 valueT old_value
, new_value
;
3920 gas_assert (S_GET_SEGMENT (label
) == now_seg
);
3922 old_frag
= symbol_get_frag (label
);
3923 old_value
= S_GET_VALUE (label
);
3924 new_value
= (valueT
) frag_now_fix ();
3926 /* Multiple labels may be on the same address. And the last symbol
3927 may not be a label at all, e.g., register name, external function names,
3928 so I have to track the last label in tc_frob_label instead of
3929 just using symbol_lastP. */
3930 for (sym
= symbol_lastP
; sym
!= NULL
; sym
= symbol_previous (sym
))
3932 if (symbol_get_frag (sym
) == old_frag
3933 && S_GET_VALUE (sym
) == old_value
)
3937 symbol_set_frag (sym
, frag_now
);
3938 S_SET_VALUE (sym
, new_value
);
3940 else if (label_seen
&& symbol_get_frag (sym
) != old_frag
)
3947 nds32_cons_align (int size ATTRIBUTE_UNUSED
)
3950 This is called before `md_flush_pending_output' is called by `cons'.
3952 There are two things should be done for auto-adjust-label.
3953 1. Align data/instructions and adjust label to be attached to them.
3954 2. Clear auto-adjust state, so incoming data/instructions will not
3962 in this case, '.word 0x2' will adjust the label, .L0, but '.word 0x3' should not.
3964 I think `md_flush_pending_output' is a good place to clear the auto-adjust state,
3965 but it is also called by `cons' before this function.
3966 To simplify the code, instead of overriding .zero, .fill, .space, etc,
3967 I think we should just adjust label in `nds32_aligned_X_cons' instead of here. */
3971 make_mapping_symbol (enum mstate state
, valueT value
, fragS
* frag
, unsigned int align
)
3973 symbolS
*symbol_p
= NULL
;
3974 const char *symbol_name
= NULL
;
3979 symbol_name
= "$d0";
3980 else if (align
== 1)
3981 symbol_name
= "$d1";
3982 else if (align
== 2)
3983 symbol_name
= "$d2";
3984 else if (align
== 3)
3985 symbol_name
= "$d3";
3986 else if (align
== 4)
3987 symbol_name
= "$d4";
3996 symbol_p
= symbol_new (symbol_name
, now_seg
, frag
, value
);
3997 /* local scope attribute */
3998 symbol_get_bfdsym (symbol_p
)->flags
|= BSF_NO_FLAGS
| BSF_LOCAL
;
4002 add_mapping_symbol (enum mstate state
, unsigned int padding_byte
,
4005 enum mstate current_mapping_state
=
4006 seg_info (now_seg
)->tc_segment_info_data
.mapstate
;
4008 if (state
== MAP_CODE
4009 && current_mapping_state
== state
)
4012 if (!SEG_NORMAL (now_seg
)
4013 || !subseg_text_p (now_seg
))
4016 /* start adding mapping symbol */
4017 seg_info (now_seg
)->tc_segment_info_data
.mapstate
= state
;
4018 make_mapping_symbol (state
, (valueT
) frag_now_fix () + padding_byte
,
4023 nds32_aligned_cons (int idx
)
4025 nds32_adjust_label (idx
);
4026 add_mapping_symbol (MAP_DATA
, 0, idx
);
4027 /* Call default handler. */
4029 if (now_seg
->flags
& SEC_CODE
4030 && now_seg
->flags
& SEC_ALLOC
&& now_seg
->flags
& SEC_RELOC
)
4032 /* Use BFD_RELOC_NDS32_DATA to avoid linker
4033 optimization replacing data. */
4036 exp
.X_add_number
= 0;
4037 exp
.X_op
= O_constant
;
4038 fix_new_exp (frag_now
, frag_now_fix () - (1 << idx
), 1 << idx
,
4039 &exp
, 0, BFD_RELOC_NDS32_DATA
);
4043 /* `.double' directive. */
4046 nds32_aligned_float_cons (int type
)
4054 nds32_adjust_label (2);
4060 nds32_adjust_label (4);
4063 as_bad ("Unrecognized float type, %c\n", (char)type
);
4065 /* Call default handler. */
4070 nds32_enable_pic (int ignore ATTRIBUTE_UNUSED
)
4072 /* Another way to do -mpic.
4073 This is for GCC internal use and should always be first line
4074 of code, otherwise, the effect is not determined. */
4079 nds32_set_abi (int ver
)
4084 /* Relax directive to set relocation R_NDS32_RELAX_ENTRY value. */
4087 nds32_relax_relocs (int relax
)
4092 const char *subtype_relax
[] =
4095 name
= input_line_pointer
;
4096 while (*input_line_pointer
&& !ISSPACE (*input_line_pointer
))
4097 input_line_pointer
++;
4098 saved_char
= *input_line_pointer
;
4099 *input_line_pointer
= 0;
4101 for (i
= 0; i
< (int) ARRAY_SIZE (subtype_relax
); i
++)
4103 if (strcmp (name
, subtype_relax
[i
]) == 0)
4109 enable_relax_relocs
= relax
& enable_relax_relocs
;
4117 *input_line_pointer
= saved_char
;
4118 ignore_rest_of_line ();
4121 /* Record which arguments register($r0 ~ $r5) is not used in callee.
4125 nds32_set_hint_func_args (int ignore ATTRIBUTE_UNUSED
)
4127 ignore_rest_of_line ();
4130 /* Insert relocations to mark the begin and end of a fp-omitted function,
4131 for further relaxation use.
4135 nds32_omit_fp_begin (int mode
)
4139 if (nds32_relax_fp_as_gp
== 0)
4141 exp
.X_op
= O_symbol
;
4142 exp
.X_add_symbol
= abs_section_sym
;
4146 exp
.X_add_number
= R_NDS32_RELAX_REGION_OMIT_FP_FLAG
;
4147 fix_new_exp (frag_now
, frag_now_fix (), 0, &exp
, 0,
4148 BFD_RELOC_NDS32_RELAX_REGION_BEGIN
);
4153 exp
.X_add_number
= R_NDS32_RELAX_REGION_OMIT_FP_FLAG
;
4154 fix_new_exp (frag_now
, frag_now_fix (), 0, &exp
, 0,
4155 BFD_RELOC_NDS32_RELAX_REGION_END
);
4160 nds32_loop_begin (int mode
)
4162 /* Insert loop region relocation here. */
4165 exp
.X_op
= O_symbol
;
4166 exp
.X_add_symbol
= abs_section_sym
;
4169 exp
.X_add_number
= R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG
;
4170 fix_new_exp (frag_now
, frag_now_fix (), 0, &exp
, 0,
4171 BFD_RELOC_NDS32_RELAX_REGION_BEGIN
);
4175 exp
.X_add_number
= R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG
;
4176 fix_new_exp (frag_now
, frag_now_fix (), 0, &exp
, 0,
4177 BFD_RELOC_NDS32_RELAX_REGION_END
);
4181 struct nds32_relocs_group
4183 struct nds32_relocs_pattern
*pattern
;
4184 struct nds32_relocs_group
*next
;
4187 static struct nds32_relocs_group
*nds32_relax_hint_current
= NULL
;
4188 /* Used to reorder the id for ".relax_hint id". */
4189 static int relax_hint_bias
= 0;
4190 /* Record current relax hint id. */
4191 static int relax_hint_id_current
= -1;
4193 /* If ".relax_hint begin" is triggered? */
4194 int relax_hint_begin
= 0;
4196 /* Record the reordered relax hint id. */
4198 struct relax_hint_id
4202 struct relax_hint_id
*next
;
4205 /* FIXME: Need to find somewhere to free the list. */
4206 struct relax_hint_id
*record_id_head
= NULL
;
4208 /* Is the buffer large enough? */
4209 #define MAX_BUFFER 12
4211 static char *nds_itoa (int n
);
4216 char *buf
= xmalloc (MAX_BUFFER
* sizeof (char));
4217 snprintf (buf
, MAX_BUFFER
, "%d", n
);
4221 /* Insert a relax hint. */
4224 nds32_relax_hint (int mode ATTRIBUTE_UNUSED
)
4228 struct nds32_relocs_pattern
*relocs
= NULL
;
4229 struct nds32_relocs_group
*group
, *new;
4230 struct relax_hint_id
*record_id
;
4232 name
= input_line_pointer
;
4233 while (*input_line_pointer
&& !ISSPACE (*input_line_pointer
))
4234 input_line_pointer
++;
4235 saved_char
= *input_line_pointer
;
4236 *input_line_pointer
= 0;
4237 name
= strdup (name
);
4239 if (name
&& strcmp (name
, "begin") == 0)
4241 if (relax_hint_id_current
== -1)
4244 relax_hint_id_current
++;
4245 relax_hint_begin
= 1;
4248 /* Original case ".relax_hint id". It's id may need to be reordered. */
4249 if (!relax_hint_begin
)
4251 int tmp
= strtol (name
, NULL
, 10);
4252 record_id
= record_id_head
;
4255 if (record_id
->old_id
== tmp
)
4257 name
= nds_itoa (record_id
->new_id
);
4260 record_id
= record_id
->next
;
4264 relax_hint_bias
= relax_hint_id_current
- atoi (name
) + 1;
4267 relax_hint_id_current
= tmp
+ relax_hint_bias
;
4269 /* Insert the element to the head of the link list. */
4270 struct relax_hint_id
*tmp_id
= malloc (sizeof (struct relax_hint_id
));
4271 tmp_id
->old_id
= tmp
;
4272 tmp_id
->new_id
= relax_hint_id_current
;
4273 tmp_id
->next
= record_id_head
;
4274 record_id_head
= tmp_id
;
4277 if (name
&& strcmp (name
, "end") == 0)
4278 relax_hint_begin
= 0;
4279 name
= nds_itoa (relax_hint_id_current
);
4283 /* Find relax hint entry for next instruction, and all member will be
4284 initialized at that time. */
4285 relocs
= str_hash_find (nds32_hint_hash
, name
);
4288 relocs
= notes_calloc (1, sizeof (*relocs
));
4289 str_hash_insert (nds32_hint_hash
, name
, relocs
, 0);
4293 while (relocs
->next
)
4294 relocs
= relocs
->next
;
4295 relocs
->next
= notes_calloc (1, sizeof (*relocs
));
4296 relocs
= relocs
->next
;
4299 *input_line_pointer
= saved_char
;
4300 ignore_rest_of_line ();
4302 /* Get the final one of relax hint series. */
4304 /* It has to build this list because there are maybe more than one
4305 instructions relative to the same instruction. It to connect to
4306 next instruction after md_assemble. */
4307 new = XNEW (struct nds32_relocs_group
);
4308 memset (new, 0, sizeof (struct nds32_relocs_group
));
4309 new->pattern
= relocs
;
4311 group
= nds32_relax_hint_current
;
4313 nds32_relax_hint_current
= new;
4316 while (group
->next
!= NULL
)
4317 group
= group
->next
;
4323 /* Decide the size of vector entries, only accepts 4 or 16 now. */
4326 nds32_vec_size (int ignore ATTRIBUTE_UNUSED
)
4332 if (exp
.X_op
== O_constant
)
4334 if (exp
.X_add_number
== 4 || exp
.X_add_number
== 16)
4337 vec_size
= exp
.X_add_number
;
4338 else if (vec_size
!= exp
.X_add_number
)
4339 as_warn (_("Different arguments of .vec_size are found, "
4340 "previous %d, current %d"),
4341 (int) vec_size
, (int) exp
.X_add_number
);
4344 as_warn (_("Argument of .vec_size is expected 4 or 16, actual: %d."),
4345 (int) exp
.X_add_number
);
4348 as_warn (_("Argument of .vec_size is not a constant."));
4351 /* The behavior of ".flag" directive varies depending on the target.
4352 In nds32 target, we use it to recognize whether this assembly content is
4353 generated by compiler. Other features can also be added in this function
4357 nds32_flag (int ignore ATTRIBUTE_UNUSED
)
4362 const char *possible_flags
[] = { "verbatim" };
4364 /* Skip whitespaces. */
4365 name
= input_line_pointer
;
4366 while (*input_line_pointer
&& !ISSPACE (*input_line_pointer
))
4367 input_line_pointer
++;
4368 saved_char
= *input_line_pointer
;
4369 *input_line_pointer
= 0;
4371 for (i
= 0; i
< (int) ARRAY_SIZE (possible_flags
); i
++)
4373 if (strcmp (name
, possible_flags
[i
]) == 0)
4378 /* flag: verbatim */
4384 /* Already found the flag, no need to continue next loop. */
4389 *input_line_pointer
= saved_char
;
4390 ignore_rest_of_line ();
4394 ict_model (int ignore ATTRIBUTE_UNUSED
)
4399 const char *possible_flags
[] = { "small", "large" };
4401 /* Skip whitespaces. */
4402 name
= input_line_pointer
;
4403 while (*input_line_pointer
&& !ISSPACE (*input_line_pointer
))
4404 input_line_pointer
++;
4405 saved_char
= *input_line_pointer
;
4406 *input_line_pointer
= 0;
4408 for (i
= 0; i
< (int) ARRAY_SIZE (possible_flags
); i
++)
4410 if (strcmp (name
, possible_flags
[i
]) == 0)
4415 /* flag: verbatim */
4416 ict_flag
= ICT_SMALL
;
4419 ict_flag
= ICT_LARGE
;
4424 /* Already found the flag, no need to continue next loop. */
4429 *input_line_pointer
= saved_char
;
4430 ignore_rest_of_line ();
4434 nds32_n12hc (int ignore ATTRIBUTE_UNUSED
)
4436 /* N1213HC core is used. */
4440 /* The target specific pseudo-ops which we support. */
4441 const pseudo_typeS md_pseudo_table
[] =
4443 /* Forced alignment if declared these ways. */
4444 {"ascii", stringer
, 8 + 0},
4445 {"asciz", stringer
, 8 + 1},
4446 {"double", nds32_aligned_float_cons
, 'd'},
4447 {"dword", nds32_aligned_cons
, 3},
4448 {"float", nds32_aligned_float_cons
, 'f'},
4449 {"half", nds32_aligned_cons
, 1},
4450 {"hword", nds32_aligned_cons
, 1},
4451 {"int", nds32_aligned_cons
, 2},
4452 {"long", nds32_aligned_cons
, 2},
4453 {"octa", nds32_aligned_cons
, 4},
4454 {"quad", nds32_aligned_cons
, 3},
4455 {"qword", nds32_aligned_cons
, 4},
4456 {"short", nds32_aligned_cons
, 1},
4457 {"byte", nds32_aligned_cons
, 0},
4458 {"single", nds32_aligned_float_cons
, 'f'},
4459 {"string", stringer
, 8 + 1},
4460 {"word", nds32_aligned_cons
, 2},
4462 {"little", set_endian_little
, 1},
4463 {"big", set_endian_little
, 0},
4464 {"16bit_on", trigger_16bit
, 1},
4465 {"16bit_off", trigger_16bit
, 0},
4466 {"restore_16bit", restore_16bit
, 0},
4467 {"off_16bit", off_16bit
, 0},
4469 {"sdata_d", nds32_seg
, SDATA_D_SECTION
},
4470 {"sdata_w", nds32_seg
, SDATA_W_SECTION
},
4471 {"sdata_h", nds32_seg
, SDATA_H_SECTION
},
4472 {"sdata_b", nds32_seg
, SDATA_B_SECTION
},
4473 {"sdata_f", nds32_seg
, SDATA_F_SECTION
},
4475 {"sbss_d", nds32_seg
, SBSS_D_SECTION
},
4476 {"sbss_w", nds32_seg
, SBSS_W_SECTION
},
4477 {"sbss_h", nds32_seg
, SBSS_H_SECTION
},
4478 {"sbss_b", nds32_seg
, SBSS_B_SECTION
},
4479 {"sbss_f", nds32_seg
, SBSS_F_SECTION
},
4481 {"pic", nds32_enable_pic
, 0},
4482 {"n12_hc", nds32_n12hc
, 0},
4483 {"abi_1", nds32_set_abi
, E_NDS_ABI_V1
},
4484 {"abi_2", nds32_set_abi
, E_NDS_ABI_AABI
},
4486 {"abi_2fp", nds32_set_abi
, E_NDS_ABI_V2FP
},
4487 {"abi_2fp_plus", nds32_set_abi
, E_NDS_ABI_V2FP_PLUS
},
4488 {"relax", nds32_relax_relocs
, 1},
4489 {"no_relax", nds32_relax_relocs
, 0},
4490 {"hint_func_args", nds32_set_hint_func_args
, 0}, /* Abandon?? */
4491 {"omit_fp_begin", nds32_omit_fp_begin
, 1},
4492 {"omit_fp_end", nds32_omit_fp_begin
, 0},
4493 {"vec_size", nds32_vec_size
, 0},
4494 {"flag", nds32_flag
, 0},
4495 {"innermost_loop_begin", nds32_loop_begin
, 1},
4496 {"innermost_loop_end", nds32_loop_begin
, 0},
4497 {"relax_hint", nds32_relax_hint
, 0},
4498 {"ict_model", ict_model
, 0},
4503 nds32_pre_do_align (int n
, char *fill
, int len
, int max
)
4505 /* Only make a frag if we HAVE to... */
4507 if (n
!= 0 && !need_pass_2
)
4511 if (subseg_text_p (now_seg
))
4513 dwarf2_emit_insn (0);
4515 add_mapping_symbol_for_align (n
, frag_now_fix (), 0);
4516 frag_align_code (n
, max
);
4518 /* Tag this alignment when there is a label before it. */
4521 fragP
->tc_frag_data
.flag
= NDS32_FRAG_LABEL
;
4526 frag_align (n
, 0, max
);
4529 frag_align (n
, *fill
, max
);
4531 frag_align_pattern (n
, fill
, len
, max
);
4536 nds32_do_align (int n
)
4538 /* Optimize for space and label exists. */
4541 /* FIXME:I think this will break debug info sections and except_table. */
4542 if (!enable_relax_relocs
|| !subseg_text_p (now_seg
))
4545 /* Create and attach a BFD_RELOC_NDS32_LABEL fixup
4546 the size of instruction may not be correct because
4547 it could be relaxable. */
4548 exp
.X_op
= O_symbol
;
4549 exp
.X_add_symbol
= section_symbol (now_seg
);
4550 exp
.X_add_number
= n
;
4551 fix_new_exp (frag_now
,
4552 frag_now_fix (), 0, &exp
, 0, BFD_RELOC_NDS32_LABEL
);
4555 /* Supported Andes machines. */
4558 enum bfd_architecture bfd_mach
;
4562 /* This is the callback for nds32-asm.c to parse operands. */
4565 nds32_asm_parse_operand (struct nds32_asm_desc
*pdesc ATTRIBUTE_UNUSED
,
4566 struct nds32_asm_insn
*pinsn
,
4567 char **pstr
, int64_t *value
)
4570 expressionS
*pexp
= pinsn
->info
;
4572 hold
= input_line_pointer
;
4573 input_line_pointer
= *pstr
;
4575 resolve_register (pexp
);
4576 *pstr
= input_line_pointer
;
4577 input_line_pointer
= hold
;
4583 return NASM_R_SYMBOL
;
4585 *value
= pexp
->X_add_number
;
4586 return NASM_R_CONST
;
4591 return NASM_R_ILLEGAL
;
4595 /* GAS will call this function at the start of the assembly, after the command
4596 line arguments have been parsed and all the machine independent
4597 initializations have been completed. */
4602 const struct nds32_keyword
*k
;
4603 relax_info_t
*relax_info
;
4606 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, nds32_baseline
);
4608 nds32_init_nds32_pseudo_opcodes ();
4609 asm_desc
.parse_operand
= nds32_asm_parse_operand
;
4611 flags
|= NASM_OPEN_REDUCED_REG
;
4612 nds32_asm_init (&asm_desc
, flags
);
4614 /* Initial general purpose registers hash table. */
4615 nds32_gprs_hash
= str_htab_create ();
4616 for (k
= nds32_keyword_gpr
; k
->name
; k
++)
4617 str_hash_insert (nds32_gprs_hash
, k
->name
, k
, 0);
4619 /* Initial branch hash table. */
4620 nds32_relax_info_hash
= str_htab_create ();
4621 for (relax_info
= relax_table
; relax_info
->opcode
; relax_info
++)
4622 str_hash_insert (nds32_relax_info_hash
, relax_info
->opcode
, relax_info
, 0);
4624 /* Initial relax hint hash table. */
4625 nds32_hint_hash
= str_htab_create ();
4626 enable_16bit
= nds32_16bit_ext
;
4629 /* HANDLE_ALIGN in write.c. */
4632 nds32_handle_align (fragS
*fragp
)
4634 static const unsigned char nop16
[] = { 0x92, 0x00 };
4635 static const unsigned char nop32
[] = { 0x40, 0x00, 0x00, 0x09 };
4639 if (fragp
->fr_type
!= rs_align_code
)
4642 bytes
= fragp
->fr_next
->fr_address
- fragp
->fr_address
- fragp
->fr_fix
;
4643 p
= fragp
->fr_literal
+ fragp
->fr_fix
;
4654 exp_t
.X_op
= O_symbol
;
4655 exp_t
.X_add_symbol
= abs_section_sym
;
4656 exp_t
.X_add_number
= R_NDS32_INSN16_CONVERT_FLAG
;
4657 fix_new_exp (fragp
, fragp
->fr_fix
, 2, &exp_t
, 0,
4658 BFD_RELOC_NDS32_INSN16
);
4659 memcpy (p
, nop16
, 2);
4666 memcpy (p
, nop32
, 4);
4671 bytes
= fragp
->fr_next
->fr_address
- fragp
->fr_address
- fragp
->fr_fix
;
4672 fragp
->fr_fix
+= bytes
;
4675 /* md_flush_pending_output */
4678 nds32_flush_pending_output (void)
4680 nds32_last_label
= NULL
;
4684 nds32_frob_label (symbolS
*label
)
4686 dwarf2_emit_label (label
);
4689 /* TC_START_LABEL */
4692 nds32_start_label (int asmdone ATTRIBUTE_UNUSED
, int secdone ATTRIBUTE_UNUSED
)
4694 if (optimize
&& subseg_text_p (now_seg
))
4702 nds32_target_format (void)
4705 if (target_big_endian
)
4706 return "elf32-nds32be-linux";
4708 return "elf32-nds32le-linux";
4710 if (target_big_endian
)
4711 return "elf32-nds32be";
4713 return "elf32-nds32le";
4717 static enum nds32_br_range
4718 get_range_type (const struct nds32_field
*field
)
4720 gas_assert (field
!= NULL
);
4722 if (field
->bitpos
!= 0)
4723 return BR_RANGE_U4G
;
4725 if (field
->bitsize
== 24 && field
->shift
== 1)
4726 return BR_RANGE_S16M
;
4727 else if (field
->bitsize
== 16 && field
->shift
== 1)
4728 return BR_RANGE_S64K
;
4729 else if (field
->bitsize
== 14 && field
->shift
== 1)
4730 return BR_RANGE_S16K
;
4731 else if (field
->bitsize
== 8 && field
->shift
== 1)
4732 return BR_RANGE_S256
;
4734 return BR_RANGE_U4G
;
4737 /* Save pseudo instruction relocation list. */
4739 static struct nds32_relocs_pattern
*
4740 nds32_elf_save_pseudo_pattern (fixS
* fixP
, struct nds32_asm_insn
*insn
,
4741 char *out
, symbolS
*sym
,
4742 struct nds32_relocs_pattern
*reloc_ptr
,
4745 struct nds32_opcode
*opcode
= insn
->opcode
;
4747 reloc_ptr
= XNEW (struct nds32_relocs_pattern
);
4748 reloc_ptr
->seg
= now_seg
;
4749 reloc_ptr
->sym
= sym
;
4750 reloc_ptr
->frag
= fragP
;
4751 reloc_ptr
->frchain
= frchain_now
;
4752 reloc_ptr
->fixP
= fixP
;
4753 reloc_ptr
->opcode
= opcode
;
4754 reloc_ptr
->where
= out
;
4755 reloc_ptr
->insn
= insn
->insn
;
4756 reloc_ptr
->next
= NULL
;
4760 /* Check X_md to transform relocation. */
4763 nds32_elf_record_fixup_exp (fragS
*fragP
, const char *str
,
4764 const struct nds32_field
*fld
,
4765 expressionS
*pexp
, char* out
,
4766 struct nds32_asm_insn
*insn
)
4772 /* Handle instruction relocation. */
4773 if (fld
&& fld
->bitpos
== 0 && (insn
->attr
& NASM_ATTR_HI20
))
4775 /* Relocation for hi20 modifier. */
4778 case BFD_RELOC_NDS32_GOTOFF
: /* @GOTOFF */
4779 reloc
= BFD_RELOC_NDS32_GOTOFF_HI20
;
4781 case BFD_RELOC_NDS32_GOT20
: /* @GOT */
4782 reloc
= BFD_RELOC_NDS32_GOT_HI20
;
4784 case BFD_RELOC_NDS32_25_PLTREL
: /* @PLT */
4786 as_bad (_("Invalid PIC expression."));
4788 reloc
= BFD_RELOC_NDS32_PLT_GOTREL_HI20
;
4790 case BFD_RELOC_NDS32_GOTPC20
: /* _GLOBAL_OFFSET_TABLE_ */
4791 reloc
= BFD_RELOC_NDS32_GOTPC_HI20
;
4793 case BFD_RELOC_NDS32_TPOFF
: /* @TPOFF */
4794 reloc
= BFD_RELOC_NDS32_TLS_LE_HI20
;
4796 case BFD_RELOC_NDS32_GOTTPOFF
: /* @GOTTPOFF */
4797 reloc
= nds32_pic
? BFD_RELOC_NDS32_TLS_IEGP_HI20
: BFD_RELOC_NDS32_TLS_IE_HI20
;
4799 case BFD_RELOC_NDS32_TLS_DESC
: /* @TLSDESC */
4800 reloc
= BFD_RELOC_NDS32_TLS_DESC_HI20
;
4802 default: /* No suffix */
4804 /* When the file is pic, the address must be offset to gp.
4805 It may define another relocation or use GOTOFF. */
4806 reloc
= BFD_RELOC_NDS32_PLT_GOTREL_HI20
;
4808 reloc
= BFD_RELOC_NDS32_HI20
;
4811 fixP
= fix_new_exp (fragP
, out
- fragP
->fr_literal
, insn
->opcode
->isize
,
4812 insn
->info
, 0 /* pcrel */, reloc
);
4814 else if (fld
&& fld
->bitpos
== 0 && (insn
->attr
& NASM_ATTR_LO12
))
4816 /* Relocation for lo12 modifier. */
4817 if (fld
->bitsize
== 15 && fld
->shift
== 0)
4822 case BFD_RELOC_NDS32_GOTOFF
: /* @GOTOFF */
4823 reloc
= BFD_RELOC_NDS32_GOTOFF_LO12
;
4825 case BFD_RELOC_NDS32_GOT20
: /* @GOT */
4826 reloc
= BFD_RELOC_NDS32_GOT_LO12
;
4828 case BFD_RELOC_NDS32_25_PLTREL
: /* @PLT */
4830 as_bad (_("Invalid PIC expression."));
4832 reloc
= BFD_RELOC_NDS32_PLT_GOTREL_LO12
;
4834 case BFD_RELOC_NDS32_GOTPC20
: /* _GLOBAL_OFFSET_TABLE_ */
4835 reloc
= BFD_RELOC_NDS32_GOTPC_LO12
;
4837 case BFD_RELOC_NDS32_TPOFF
: /* @TPOFF */
4838 reloc
= BFD_RELOC_NDS32_TLS_LE_LO12
;
4840 case BFD_RELOC_NDS32_GOTTPOFF
: /* @GOTTPOFF */
4841 reloc
= nds32_pic
? BFD_RELOC_NDS32_TLS_IEGP_LO12
: BFD_RELOC_NDS32_TLS_IE_LO12
;
4843 case BFD_RELOC_NDS32_TLS_DESC
: /* @TLSDESC */
4844 reloc
= BFD_RELOC_NDS32_TLS_DESC_LO12
;
4846 default: /* No suffix */
4848 /* When the file is pic, the address must be offset to gp.
4849 It may define another relocation or use GOTOFF. */
4850 reloc
= BFD_RELOC_NDS32_PLT_GOTREL_LO12
;
4852 reloc
= BFD_RELOC_NDS32_LO12S0
;
4856 else if (fld
->bitsize
== 15 && fld
->shift
== 1)
4857 reloc
= BFD_RELOC_NDS32_LO12S1
; /* [ls]hi */
4858 else if (fld
->bitsize
== 15 && fld
->shift
== 2)
4863 case BFD_RELOC_NDS32_GOTTPOFF
: /* @GOTTPOFF */
4864 reloc
= nds32_pic
? BFD_RELOC_NDS32_TLS_IEGP_LO12S2
: BFD_RELOC_NDS32_TLS_IE_LO12S2
;
4866 default: /* No suffix */
4867 reloc
= BFD_RELOC_NDS32_LO12S2
;
4871 else if (fld
->bitsize
== 15 && fld
->shift
== 3)
4872 reloc
= BFD_RELOC_NDS32_LO12S3
; /* [ls]di */
4873 else if (fld
->bitsize
== 12 && fld
->shift
== 2)
4874 reloc
= BFD_RELOC_NDS32_LO12S2_SP
; /* f[ls][sd]i */
4876 fixP
= fix_new_exp (fragP
, out
- fragP
->fr_literal
, insn
->opcode
->isize
,
4877 insn
->info
, 0 /* pcrel */, reloc
);
4879 else if (fld
&& fld
->bitpos
== 0 && insn
->opcode
->isize
== 4
4880 && (insn
->attr
& NASM_ATTR_PCREL
))
4882 /* Relocation for 32-bit branch instructions. */
4883 if (fld
->bitsize
== 24 && fld
->shift
== 1)
4884 reloc
= BFD_RELOC_NDS32_25_PCREL
;
4885 else if (fld
->bitsize
== 16 && fld
->shift
== 1)
4886 reloc
= BFD_RELOC_NDS32_17_PCREL
;
4887 else if (fld
->bitsize
== 14 && fld
->shift
== 1)
4888 reloc
= BFD_RELOC_NDS32_15_PCREL
;
4889 else if (fld
->bitsize
== 8 && fld
->shift
== 1)
4890 reloc
= BFD_RELOC_NDS32_WORD_9_PCREL
;
4894 fixP
= fix_new_exp (fragP
, out
- fragP
->fr_literal
, insn
->opcode
->isize
,
4895 insn
->info
, 1 /* pcrel */, reloc
);
4897 else if (fld
&& fld
->bitpos
== 0 && insn
->opcode
->isize
== 4
4898 && (insn
->attr
& NASM_ATTR_GPREL
))
4900 /* Relocation for 32-bit gp-relative instructions. */
4901 if (fld
->bitsize
== 19 && fld
->shift
== 0)
4902 reloc
= BFD_RELOC_NDS32_SDA19S0
;
4903 else if (fld
->bitsize
== 18 && fld
->shift
== 1)
4904 reloc
= BFD_RELOC_NDS32_SDA18S1
;
4905 else if (fld
->bitsize
== 17 && fld
->shift
== 2)
4906 reloc
= BFD_RELOC_NDS32_SDA17S2
;
4910 fixP
= fix_new_exp (fragP
, out
- fragP
->fr_literal
, insn
->opcode
->isize
,
4911 insn
->info
, 0 /* pcrel */, reloc
);
4912 /* Insert INSN16 for converting fp_as_gp. */
4913 exp
.X_op
= O_symbol
;
4914 exp
.X_add_symbol
= abs_section_sym
;
4915 exp
.X_add_number
= 0;
4916 if (in_omit_fp
&& reloc
== BFD_RELOC_NDS32_SDA17S2
)
4917 fix_new_exp (fragP
, out
- fragP
->fr_literal
,
4918 insn
->opcode
->isize
, &exp
, 0 /* pcrel */,
4919 BFD_RELOC_NDS32_INSN16
);
4921 else if (fld
&& fld
->bitpos
== 0 && insn
->opcode
->isize
== 2
4922 && (insn
->attr
& NASM_ATTR_PCREL
))
4924 /* Relocation for 16-bit branch instructions. */
4925 if (fld
->bitsize
== 8 && fld
->shift
== 1)
4926 reloc
= BFD_RELOC_NDS32_9_PCREL
;
4930 fixP
= fix_new_exp (fragP
, out
- fragP
->fr_literal
, insn
->opcode
->isize
,
4931 insn
->info
, 1 /* pcrel */, reloc
);
4934 as_bad (_("Don't know how to handle this field. %s"), str
);
4939 /* Build instruction pattern to relax. There are two type group pattern
4940 including pseudo instruction and relax hint. */
4943 nds32_elf_build_relax_relation (fixS
*fixP
, expressionS
*pexp
, char* out
,
4944 struct nds32_asm_insn
*insn
, fragS
*fragP
,
4945 const struct nds32_field
*fld
,
4948 struct nds32_relocs_pattern
*reloc_ptr
;
4949 struct nds32_relocs_group
*group
;
4950 symbolS
*sym
= NULL
;
4952 /* The expression may be used uninitialized. */
4954 sym
= pexp
->X_add_symbol
;
4958 /* We cannot know how many instructions will be expanded for
4959 the pseudo instruction here. The first expanded instruction fills
4960 the memory created by relax_hint. The follower will created and link
4962 group
= nds32_relax_hint_current
;
4965 if (group
->pattern
->opcode
== NULL
)
4966 nds32_elf_save_pseudo_pattern (fixP
, insn
, out
, sym
,
4967 group
->pattern
, fragP
);
4970 group
->pattern
->next
=
4971 nds32_elf_save_pseudo_pattern (fixP
, insn
, out
, sym
,
4973 group
->pattern
= group
->pattern
->next
;
4975 group
= group
->next
;
4978 else if (pseudo_opcode
)
4980 /* Save instruction relation for pseudo instruction expanding pattern. */
4981 reloc_ptr
= nds32_elf_save_pseudo_pattern (fixP
, insn
, out
, sym
,
4984 relocs_list
= reloc_ptr
;
4987 struct nds32_relocs_pattern
*temp
= relocs_list
;
4990 temp
->next
= reloc_ptr
;
4993 else if (nds32_relax_hint_current
)
4995 /* Save instruction relation by relax hint. */
4996 group
= nds32_relax_hint_current
;
4999 nds32_elf_save_pseudo_pattern (fixP
, insn
, out
, sym
,
5000 group
->pattern
, fragP
);
5001 group
= group
->next
;
5002 free (nds32_relax_hint_current
);
5003 nds32_relax_hint_current
= group
;
5007 /* Set relaxing false only for relax_hint trigger it. */
5012 #define N32_MEM_EXT(insn) ((N32_OP6_MEM << 25) | insn)
5014 /* Relax pattern for link time relaxation. */
5015 /* Relaxation types only! relocation types are not necessary. */
5016 /* Refer to nds32_elf_record_fixup_exp (). */
5018 static struct nds32_relax_hint_table relax_ls_table
[] =
5021 /* LA and Floating LSI. */
5022 .main_type
= NDS32_RELAX_HINT_LA_FLSI
,
5023 .relax_code_size
= 12,
5032 {0, 4, NDS32_HINT
| NDS32_ADDEND
, BFD_RELOC_NDS32_LOADSTORE
},
5033 {4, 4, NDS32_HINT
| NDS32_PTR
, BFD_RELOC_NDS32_PTR
},
5034 {4, 4, NDS32_HINT
| NDS32_INSN16
, BFD_RELOC_NDS32_INSN16
},
5035 {8, 4, NDS32_HINT
| NDS32_SYM
, BFD_RELOC_NDS32_LSI
},
5036 {8, 4, NDS32_HINT
| NDS32_ABS
, BFD_RELOC_NDS32_PTR_RESOLVED
},
5037 {8, 4, NDS32_HINT
| NDS32_INSN16
, BFD_RELOC_NDS32_INSN16
},
5042 /* Load Address / Load-Store (LALS). */
5043 .main_type
= NDS32_RELAX_HINT_LALS
,
5044 .relax_code_size
= 12,
5053 {0, 4, NDS32_HINT
| NDS32_ADDEND
, BFD_RELOC_NDS32_LOADSTORE
},
5054 {4, 4, NDS32_HINT
| NDS32_INSN16
, BFD_RELOC_NDS32_INSN16
},
5055 {8, 4, NDS32_HINT
| NDS32_INSN16
, BFD_RELOC_NDS32_INSN16
},
5060 /* B(AL) symbol@PLT */
5061 .main_type
= NDS32_RELAX_HINT_LA_PLT
,
5062 .relax_code_size
= 16,
5072 {0, 4, NDS32_HINT
| NDS32_ADDEND
, BFD_RELOC_NDS32_LOADSTORE
},
5073 {4, 4, NDS32_HINT
| NDS32_PTR
, BFD_RELOC_NDS32_PTR
},
5074 {8, 4, NDS32_HINT
| NDS32_PTR
, BFD_RELOC_NDS32_PTR
},
5075 {12, 4, NDS32_HINT
| NDS32_ABS
, BFD_RELOC_NDS32_PLT_GOT_SUFF
},
5076 {12, 4, NDS32_HINT
| NDS32_ABS
, BFD_RELOC_NDS32_PTR_RESOLVED
},
5077 {12, 4, NDS32_HINT
| NDS32_INSN16
, BFD_RELOC_NDS32_INSN16
},
5083 .main_type
= NDS32_RELAX_HINT_LA_GOT
,
5084 .relax_code_size
= 12,
5093 {0, 4, NDS32_HINT
| NDS32_ADDEND
, BFD_RELOC_NDS32_LOADSTORE
},
5094 {4, 4, NDS32_HINT
| NDS32_PTR
, BFD_RELOC_NDS32_PTR
},
5095 {8, 4, NDS32_HINT
| NDS32_ABS
, BFD_RELOC_NDS32_PTR_RESOLVED
},
5096 {8, 4, NDS32_HINT
| NDS32_ABS
, BFD_RELOC_NDS32_GOT_SUFF
},
5102 .main_type
= NDS32_RELAX_HINT_LA_GOTOFF
,
5103 .relax_code_size
= 16,
5113 {0, 4, NDS32_HINT
| NDS32_ADDEND
, BFD_RELOC_NDS32_LOADSTORE
},
5114 {4, 4, NDS32_HINT
| NDS32_PTR
, BFD_RELOC_NDS32_PTR
},
5115 {8, 4, NDS32_HINT
| NDS32_ABS
, BFD_RELOC_NDS32_PTR_RESOLVED
},
5116 {8, 4, NDS32_HINT
| NDS32_ABS
, BFD_RELOC_NDS32_GOTOFF_SUFF
},
5117 {12, 4, NDS32_HINT
| NDS32_ABS
, BFD_RELOC_NDS32_PTR_RESOLVED
},
5118 {12, 4, NDS32_HINT
| NDS32_ABS
, BFD_RELOC_NDS32_GOTOFF_SUFF
},
5124 .main_type
= NDS32_RELAX_HINT_TLS_LE_LS
,
5125 .relax_code_size
= 16,
5135 {0, 4, NDS32_HINT
| NDS32_ADDEND
, BFD_RELOC_NDS32_LOADSTORE
},
5136 {4, 4, NDS32_HINT
| NDS32_PTR_MULTIPLE
, BFD_RELOC_NDS32_PTR
},
5137 {8, 4, NDS32_HINT
| NDS32_ABS
, BFD_RELOC_NDS32_PTR_RESOLVED
},
5138 {8, 4, NDS32_HINT
| NDS32_SYM
, BFD_RELOC_NDS32_TLS_LE_LS
},
5139 {12, 4, NDS32_HINT
| NDS32_ABS
, BFD_RELOC_NDS32_PTR_RESOLVED
},
5140 {12, 4, NDS32_HINT
| NDS32_SYM
, BFD_RELOC_NDS32_TLS_LE_ADD
},
5146 .main_type
= NDS32_RELAX_HINT_TLS_IE_LA
,
5147 .relax_code_size
= 8,
5155 {0, 4, NDS32_HINT
| NDS32_ADDEND
, BFD_RELOC_NDS32_LOADSTORE
},
5156 {4, 4, NDS32_HINT
| NDS32_INSN16
, BFD_RELOC_NDS32_INSN16
},
5162 .main_type
= NDS32_RELAX_HINT_TLS_IEGP_LA
,
5163 .relax_code_size
= 12,
5172 {0, 4, NDS32_HINT
| NDS32_ADDEND
, BFD_RELOC_NDS32_LOADSTORE
},
5173 {4, 4, NDS32_HINT
| NDS32_PTR_PATTERN
, BFD_RELOC_NDS32_PTR
},
5174 {8, 4, NDS32_HINT
| NDS32_ABS
, BFD_RELOC_NDS32_PTR_RESOLVED
},
5175 {8, 4, NDS32_HINT
| NDS32_SYM
, BFD_RELOC_NDS32_TLS_IEGP_LW
},
5181 .main_type
= NDS32_RELAX_HINT_TLS_DESC_LS
,
5182 .relax_code_size
= 24,
5188 OP6 (LBI
), /* load argument */
5190 OP6 (MEM
), /* load/store variable or load argument */
5194 {0, 4, NDS32_HINT
| NDS32_ADDEND
, BFD_RELOC_NDS32_LOADSTORE
},
5195 {4, 4, NDS32_HINT
| NDS32_PTR_PATTERN
, BFD_RELOC_NDS32_PTR
},
5196 {8, 4, NDS32_HINT
| NDS32_ABS
, BFD_RELOC_NDS32_PTR_RESOLVED
},
5197 {8, 4, NDS32_HINT
| NDS32_SYM
, BFD_RELOC_NDS32_TLS_DESC_ADD
},
5198 {12, 4, NDS32_HINT
| NDS32_SYM
, BFD_RELOC_NDS32_TLS_DESC_FUNC
},
5199 {16, 4, NDS32_HINT
| NDS32_SYM
, BFD_RELOC_NDS32_TLS_DESC_CALL
},
5200 {20, 4, NDS32_HINT
| NDS32_SYM_DESC_MEM
, BFD_RELOC_NDS32_TLS_DESC_MEM
},
5206 .relax_code_seq
= {0},
5207 .relax_fixup
= {{0, 0 , 0, 0}}
5211 /* Since sethi loadstore relocation has to using next instruction to determine
5212 elimination itself or not, we have to return the next instruction range. */
5215 nds32_elf_sethi_range (struct nds32_relocs_pattern
*pattern
)
5220 switch (pattern
->opcode
->value
)
5225 case N32_MEM_EXT (N32_MEM_LB
):
5226 case N32_MEM_EXT (N32_MEM_LBS
):
5227 case N32_MEM_EXT (N32_MEM_SB
):
5228 range
= NDS32_LOADSTORE_BYTE
;
5233 case N32_MEM_EXT (N32_MEM_LH
):
5234 case N32_MEM_EXT (N32_MEM_LHS
):
5235 case N32_MEM_EXT (N32_MEM_SH
):
5236 range
= NDS32_LOADSTORE_HALF
;
5240 case N32_MEM_EXT (N32_MEM_LW
):
5241 case N32_MEM_EXT (N32_MEM_SW
):
5242 range
= NDS32_LOADSTORE_WORD
;
5246 range
= NDS32_LOADSTORE_FLOAT_S
;
5250 range
= NDS32_LOADSTORE_FLOAT_D
;
5253 range
= NDS32_LOADSTORE_IMM
;
5256 range
= NDS32_LOADSTORE_NONE
;
5259 if (range
!= NDS32_LOADSTORE_NONE
)
5261 pattern
= pattern
->next
;
5266 /* The args means: instruction size, the 1st instruction is converted to 16 or
5267 not, optimize option, 16 bit instruction is enable. */
5269 #define SET_ADDEND(size, convertible, optimize, insn16_on) \
5270 (((size) & 0xff) | ((convertible) ? 1u << 31 : 0) \
5271 | ((optimize) ? 1 << 30 : 0) | (insn16_on ? 1 << 29 : 0))
5272 #define MAC_COMBO (E_NDS32_HAS_FPU_MAC_INST|E_NDS32_HAS_MAC_DX_INST)
5275 nds32_set_elf_flags_by_insn (struct nds32_asm_insn
* insn
)
5277 static int skip_flags
= NASM_ATTR_FPU_FMA
5278 | NASM_ATTR_BRANCH
| NASM_ATTR_SATURATION_EXT
5279 | NASM_ATTR_GPREL
| NASM_ATTR_DXREG
5280 | NASM_ATTR_ISA_V1
| NASM_ATTR_ISA_V2
5281 | NASM_ATTR_ISA_V3
| NASM_ATTR_ISA_V3M
5284 int new_flags
= insn
->opcode
->attr
& ~skip_flags
;
5287 int next
= 1 << (ffs (new_flags
) - 1);
5291 case NASM_ATTR_PERF_EXT
:
5295 nds32_elf_flags
|= E_NDS32_HAS_EXT_INST
;
5296 skip_flags
|= NASM_ATTR_PERF_EXT
;
5299 as_bad (_("instruction %s requires enabling performance "
5300 "extension"), insn
->opcode
->opcode
);
5303 case NASM_ATTR_PERF2_EXT
:
5305 if (nds32_perf_ext2
)
5307 nds32_elf_flags
|= E_NDS32_HAS_EXT2_INST
;
5308 skip_flags
|= NASM_ATTR_PERF2_EXT
;
5311 as_bad (_("instruction %s requires enabling performance "
5312 "extension II"), insn
->opcode
->opcode
);
5315 case NASM_ATTR_AUDIO_ISAEXT
:
5317 if (nds32_audio_ext
)
5319 nds32_elf_flags
|= E_NDS32_HAS_AUDIO_INST
;
5320 skip_flags
|= NASM_ATTR_AUDIO_ISAEXT
;
5323 as_bad (_("instruction %s requires enabling AUDIO extension"),
5324 insn
->opcode
->opcode
);
5327 case NASM_ATTR_STR_EXT
:
5329 if (nds32_string_ext
)
5331 nds32_elf_flags
|= E_NDS32_HAS_STRING_INST
;
5332 skip_flags
|= NASM_ATTR_STR_EXT
;
5335 as_bad (_("instruction %s requires enabling STRING extension"),
5336 insn
->opcode
->opcode
);
5341 if (insn
->opcode
->attr
& NASM_ATTR_DXREG
)
5343 if (nds32_div
&& nds32_dx_regs
)
5345 nds32_elf_flags
|= E_NDS32_HAS_DIV_DX_INST
;
5346 skip_flags
|= NASM_ATTR_DIV
;
5349 as_bad (_("instruction %s requires enabling DIV & DX_REGS "
5350 "extension"), insn
->opcode
->opcode
);
5356 if (nds32_fpu_sp_ext
|| nds32_fpu_dp_ext
)
5358 if (!(nds32_elf_flags
5359 & (E_NDS32_HAS_FPU_INST
| E_NDS32_HAS_FPU_DP_INST
)))
5361 skip_flags
|= NASM_ATTR_FPU
;
5364 as_bad (_("instruction %s requires enabling FPU extension"),
5365 insn
->opcode
->opcode
);
5368 case NASM_ATTR_FPU_SP_EXT
:
5370 if (nds32_fpu_sp_ext
)
5372 nds32_elf_flags
|= E_NDS32_HAS_FPU_INST
;
5373 skip_flags
|= NASM_ATTR_FPU_SP_EXT
;
5376 as_bad (_("instruction %s requires enabling FPU_SP extension"),
5377 insn
->opcode
->opcode
);
5380 case NASM_ATTR_FPU_DP_EXT
:
5382 if (nds32_fpu_dp_ext
)
5384 nds32_elf_flags
|= E_NDS32_HAS_FPU_DP_INST
;
5385 skip_flags
|= NASM_ATTR_FPU_DP_EXT
;
5388 as_bad (_("instruction %s requires enabling FPU_DP extension"),
5389 insn
->opcode
->opcode
);
5394 if (insn
->opcode
->attr
& NASM_ATTR_FPU_SP_EXT
)
5396 if (nds32_fpu_sp_ext
&& nds32_mac
)
5397 nds32_elf_flags
|= E_NDS32_HAS_FPU_MAC_INST
;
5399 as_bad (_("instruction %s requires enabling FPU_MAC "
5400 "extension"), insn
->opcode
->opcode
);
5402 else if (insn
->opcode
->attr
& NASM_ATTR_FPU_DP_EXT
)
5404 if (nds32_fpu_dp_ext
&& nds32_mac
)
5405 nds32_elf_flags
|= E_NDS32_HAS_FPU_MAC_INST
;
5407 as_bad (_("instruction %s requires enabling FPU_MAC "
5408 "extension"), insn
->opcode
->opcode
);
5410 else if (insn
->opcode
->attr
& NASM_ATTR_DXREG
)
5412 if (nds32_dx_regs
&& nds32_mac
)
5413 nds32_elf_flags
|= E_NDS32_HAS_MAC_DX_INST
;
5415 as_bad (_("instruction %s requires enabling DX_REGS "
5416 "extension"), insn
->opcode
->opcode
);
5419 if (MAC_COMBO
== (MAC_COMBO
& nds32_elf_flags
))
5420 skip_flags
|= NASM_ATTR_MAC
;
5423 case NASM_ATTR_DSP_ISAEXT
:
5427 nds32_elf_flags
|= E_NDS32_HAS_DSP_INST
;
5428 skip_flags
|= NASM_ATTR_DSP_ISAEXT
;
5431 as_bad (_("instruction %s requires enabling dsp extension"),
5432 insn
->opcode
->opcode
);
5439 nds32_elf_flags
|= E_NDS32_HAS_ZOL
;
5440 skip_flags
|= NASM_ATTR_ZOL
;
5443 as_bad (_("instruction %s requires enabling zol extension"),
5444 insn
->opcode
->opcode
);
5448 as_bad (_("internal error: unknown instruction attribute: 0x%08x"),
5454 /* Flag for analysis relaxation type. */
5456 enum nds32_insn_type
5458 N32_RELAX_SETHI
= 1,
5459 N32_RELAX_BR
= (1 << 1),
5460 N32_RELAX_LSI
= (1 << 2),
5461 N32_RELAX_JUMP
= (1 << 3),
5462 N32_RELAX_CALL
= (1 << 4),
5463 N32_RELAX_ORI
= (1 << 5),
5464 N32_RELAX_MEM
= (1 << 6),
5465 N32_RELAX_MOVI
= (1 << 7),
5466 N32_RELAX_ALU1
= (1 << 8),
5467 N32_RELAX_16BIT
= (1 << 9),
5470 struct nds32_hint_map
5472 /* the preamble relocation */
5473 bfd_reloc_code_real_type hi_type
;
5476 /* relax pattern ID */
5477 enum nds32_relax_hint_type hint_type
;
5479 enum nds32_br_range range
;
5480 /* pattern character flags */
5481 enum nds32_insn_type insn_list
;
5482 /* optional pattern character flags */
5483 enum nds32_insn_type option_list
;
5486 /* Table to match instructions with hint and relax pattern. */
5488 static struct nds32_hint_map hint_map
[] =
5492 BFD_RELOC_NDS32_HI20
,
5494 NDS32_RELAX_HINT_NONE
,
5496 N32_RELAX_SETHI
| N32_RELAX_ORI
| N32_RELAX_CALL
,
5501 _dummy_first_bfd_reloc_code_real
,
5503 NDS32_RELAX_HINT_NONE
,
5505 N32_RELAX_BR
| N32_RELAX_CALL
,
5510 BFD_RELOC_NDS32_HI20
,
5512 NDS32_RELAX_HINT_NONE
,
5514 N32_RELAX_BR
| N32_RELAX_SETHI
| N32_RELAX_ORI
| N32_RELAX_CALL
,
5519 BFD_RELOC_NDS32_HI20
,
5521 NDS32_RELAX_HINT_NONE
,
5523 N32_RELAX_SETHI
| N32_RELAX_ORI
| N32_RELAX_JUMP
,
5528 /* There is two kinds of variation of LONGJUMP5. One of them
5529 generate EMPTY relocation for converted INSN16 if needed.
5530 But we don't distinguish them here. */
5531 _dummy_first_bfd_reloc_code_real
,
5533 NDS32_RELAX_HINT_NONE
,
5535 N32_RELAX_BR
| N32_RELAX_JUMP
,
5540 BFD_RELOC_NDS32_HI20
,
5542 NDS32_RELAX_HINT_NONE
,
5544 N32_RELAX_SETHI
| N32_RELAX_ORI
| N32_RELAX_BR
| N32_RELAX_JUMP
,
5549 _dummy_first_bfd_reloc_code_real
,
5551 NDS32_RELAX_HINT_NONE
,
5553 N32_RELAX_MOVI
| N32_RELAX_BR
,
5557 /* LONGCALL (BAL|JR|LA symbol@PLT). */
5558 BFD_RELOC_NDS32_PLT_GOTREL_HI20
,
5560 NDS32_RELAX_HINT_LA_PLT
,
5562 N32_RELAX_SETHI
| N32_RELAX_ORI
,
5563 N32_RELAX_ALU1
| N32_RELAX_CALL
| N32_RELAX_JUMP
,
5565 /* relative issue: #12566 */
5567 /* LA and Floating LSI. */
5568 BFD_RELOC_NDS32_HI20
,
5570 NDS32_RELAX_HINT_LA_FLSI
,
5572 N32_RELAX_SETHI
| N32_RELAX_ORI
| N32_RELAX_LSI
,
5575 /* relative issue: #11685 #11602 */
5577 /* load address / load-store (LALS). */
5578 BFD_RELOC_NDS32_HI20
,
5580 NDS32_RELAX_HINT_LALS
,
5583 N32_RELAX_ORI
| N32_RELAX_LSI
,
5586 /* setup $GP (_GLOBAL_OFFSET_TABLE_) */
5587 BFD_RELOC_NDS32_GOTPC_HI20
,
5589 NDS32_RELAX_HINT_LALS
,
5591 N32_RELAX_SETHI
| N32_RELAX_ORI
,
5595 /* GOT LA/LS (symbol@GOT) */
5596 BFD_RELOC_NDS32_GOT_HI20
,
5598 NDS32_RELAX_HINT_LA_GOT
,
5600 N32_RELAX_SETHI
| N32_RELAX_ORI
,
5604 /* GOTOFF LA/LS (symbol@GOTOFF) */
5605 BFD_RELOC_NDS32_GOTOFF_HI20
,
5607 NDS32_RELAX_HINT_LA_GOTOFF
,
5609 N32_RELAX_SETHI
| N32_RELAX_ORI
,
5610 N32_RELAX_ALU1
| N32_RELAX_MEM
, /* | N32_RELAX_LSI, */
5613 /* TLS LE LA|LS (@TPOFF) */
5614 BFD_RELOC_NDS32_TLS_LE_HI20
,
5616 NDS32_RELAX_HINT_TLS_LE_LS
,
5618 N32_RELAX_SETHI
| N32_RELAX_ORI
,
5619 N32_RELAX_ALU1
| N32_RELAX_MEM
,
5623 BFD_RELOC_NDS32_TLS_IE_HI20
,
5625 NDS32_RELAX_HINT_TLS_IE_LA
,
5627 N32_RELAX_SETHI
| N32_RELAX_LSI
,
5632 BFD_RELOC_NDS32_TLS_IE_HI20
,
5634 NDS32_RELAX_HINT_TLS_IE_LS
,
5636 N32_RELAX_SETHI
| N32_RELAX_LSI
| N32_RELAX_MEM
,
5641 BFD_RELOC_NDS32_TLS_IEGP_HI20
,
5643 NDS32_RELAX_HINT_TLS_IEGP_LA
,
5645 N32_RELAX_SETHI
| N32_RELAX_ORI
| N32_RELAX_MEM
,
5650 BFD_RELOC_NDS32_TLS_DESC_HI20
,
5652 NDS32_RELAX_HINT_TLS_DESC_LS
,
5654 N32_RELAX_SETHI
| N32_RELAX_ORI
| N32_RELAX_ALU1
| N32_RELAX_CALL
,
5655 N32_RELAX_LSI
| N32_RELAX_MEM
,
5658 {0, NULL
, 0, 0 ,0, 0}
5661 /* Find the relaxation pattern according to instructions. */
5664 nds32_find_reloc_table (struct nds32_relocs_pattern
*relocs_pattern
,
5665 struct nds32_relax_hint_table
*hint_info
)
5667 unsigned int opcode
, seq_size
;
5668 enum nds32_br_range range
;
5669 struct nds32_relocs_pattern
*pattern
, *hi_pattern
= NULL
;
5670 const char *opc
= NULL
;
5671 relax_info_t
*relax_info
= NULL
;
5672 nds32_relax_fixup_info_t
*fixup_info
, *hint_fixup
;
5673 enum nds32_relax_hint_type hint_type
= NDS32_RELAX_HINT_NONE
;
5674 struct nds32_relax_hint_table
*table_ptr
;
5675 uint32_t *code_seq
, *hint_code
;
5676 enum nds32_insn_type relax_type
= 0;
5677 struct nds32_hint_map
*map_ptr
= hint_map
;
5679 const char *check_insn
[] =
5680 { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8" };
5682 /* TODO: PLT GOT. */
5683 /* Traverse all pattern instruction and set flag. */
5684 pattern
= relocs_pattern
;
5687 if (pattern
->opcode
->isize
== 4)
5689 /* 4 byte instruction. */
5690 opcode
= N32_OP6 (pattern
->opcode
->value
);
5694 hi_pattern
= pattern
;
5695 relax_type
|= N32_RELAX_SETHI
;
5698 relax_type
|= N32_RELAX_MEM
;
5701 relax_type
|= N32_RELAX_ALU1
;
5704 relax_type
|= N32_RELAX_ORI
;
5709 relax_type
|= N32_RELAX_BR
;
5712 relax_type
|= N32_RELAX_MOVI
;
5726 relax_type
|= N32_RELAX_LSI
;
5729 if (__GF (pattern
->opcode
->value
, 0, 1) == 1)
5730 relax_type
|= N32_RELAX_CALL
;
5732 relax_type
|= N32_RELAX_JUMP
;
5735 if (__GF (pattern
->opcode
->value
, 24, 1) == 1)
5736 relax_type
|= N32_RELAX_CALL
;
5738 relax_type
|= N32_RELAX_JUMP
;
5741 as_warn (_("relax hint unrecognized instruction: line %d."),
5742 pattern
->frag
->fr_line
);
5748 /* 2 byte instruction. Compare by opcode name because
5749 the opcode of 2byte instruction is not regular. */
5751 for (i
= 0; i
< ARRAY_SIZE (check_insn
); i
++)
5753 if (strcmp (pattern
->opcode
->opcode
, check_insn
[i
]) == 0)
5755 relax_type
|= N32_RELAX_BR
;
5761 relax_type
|= N32_RELAX_16BIT
;
5763 pattern
= pattern
->next
;
5766 /* Analysis instruction flag to choose relaxation table. */
5767 while (map_ptr
->insn_list
!= 0)
5769 struct nds32_hint_map
*hint
= map_ptr
++;
5770 enum nds32_insn_type must
= hint
->insn_list
;
5771 enum nds32_insn_type optional
= hint
->option_list
;
5772 enum nds32_insn_type extra
;
5774 if (must
!= (must
& relax_type
))
5777 extra
= relax_type
^ must
;
5778 if (extra
!= (extra
& optional
))
5782 || (hi_pattern
->fixP
5783 && hi_pattern
->fixP
->fx_r_type
== hint
->hi_type
))
5786 hint_type
= hint
->hint_type
;
5787 range
= hint
->range
;
5793 if (map_ptr
->insn_list
== 0)
5796 as_warn (_("Can not find match relax hint. Line: %d"),
5797 relocs_pattern
->frag
->fr_line
);
5801 /* Get the match table. */
5804 /* Branch relax pattern. */
5805 relax_info
= str_hash_find (nds32_relax_info_hash
, opc
);
5808 fixup_info
= relax_info
->relax_fixup
[range
];
5809 code_seq
= relax_info
->relax_code_seq
[range
];
5810 seq_size
= relax_info
->relax_code_size
[range
];
5814 /* Load-store relax pattern. */
5815 table_ptr
= relax_ls_table
;
5816 while (table_ptr
->main_type
!= 0)
5818 if (table_ptr
->main_type
== hint_type
)
5820 fixup_info
= table_ptr
->relax_fixup
;
5821 code_seq
= table_ptr
->relax_code_seq
;
5822 seq_size
= table_ptr
->relax_code_size
;
5827 if (table_ptr
->main_type
== 0)
5833 hint_fixup
= hint_info
->relax_fixup
;
5834 hint_code
= hint_info
->relax_code_seq
;
5835 hint_info
->relax_code_size
= seq_size
;
5837 while (fixup_info
->size
!= 0)
5839 if (fixup_info
->ramp
& NDS32_HINT
)
5841 memcpy (hint_fixup
, fixup_info
, sizeof (nds32_relax_fixup_info_t
));
5846 /* Clear final relocation. */
5847 memset (hint_fixup
, 0, sizeof (nds32_relax_fixup_info_t
));
5848 /* Copy code sequence. */
5849 memcpy (hint_code
, code_seq
, seq_size
);
5853 /* Because there are a lot of variant of load-store, check
5854 all these type here. */
5856 #define CLEAN_REG(insn) ((insn) & 0xfe0003ff)
5857 #define GET_OPCODE(insn) ((insn) & 0xfe000000)
5860 nds32_match_hint_insn (struct nds32_opcode
*opcode
, uint32_t seq
)
5862 const char *check_insn
[] =
5863 { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8", "jral5" };
5864 uint32_t insn
= opcode
->value
;
5867 insn
= CLEAN_REG (opcode
->value
);
5874 /* In relocation_table, it regards instruction LBI as representation
5875 of all the NDS32_RELAX_HINT_LS pattern. */
5876 if (insn
== OP6 (LBI
) || insn
== OP6 (SBI
) || insn
== OP6 (LBSI
)
5877 || insn
== OP6 (LHI
) || insn
== OP6 (SHI
) || insn
== OP6 (LHSI
)
5878 || insn
== OP6 (LWI
) || insn
== OP6 (SWI
)
5879 || insn
== OP6 (LWC
) || insn
== OP6 (SWC
)
5880 || insn
== OP6 (LDC
) || insn
== OP6 (SDC
))
5884 /* This is for LONGCALL5 and LONGCALL6. */
5885 if (insn
== OP6 (BR2
))
5889 /* This is for LONGJUMP5 and LONGJUMP6. */
5890 if (opcode
->isize
== 4
5891 && (insn
== OP6 (BR1
) || insn
== OP6 (BR2
) || insn
== OP6 (BR3
)))
5893 else if (opcode
->isize
== 2)
5895 for (i
= 0; i
< ARRAY_SIZE (check_insn
); i
++)
5896 if (strcmp (opcode
->opcode
, check_insn
[i
]) == 0)
5901 /* This is for LONGJUMP7. */
5902 if (opcode
->isize
== 2 && strcmp (opcode
->opcode
, "movi55") == 0)
5906 if (OP6 (MEM
) == GET_OPCODE (insn
))
5910 /* bit 24: N32_JI_JAL */ /* feed me! */
5911 if ((insn
& ~(N32_BIT (24))) == JREG (JRAL
))
5915 if (opcode
->isize
== 2)
5917 for (i
= 0; i
< ARRAY_SIZE (check_insn
); i
++)
5918 if (strcmp (opcode
->opcode
, check_insn
[i
]) == 0)
5921 if ((strcmp (opcode
->opcode
, "add5.pc") == 0) ||
5922 (strcmp (opcode
->opcode
, "add45") == 0))
5929 /* Append relax relocation for link time relaxing. */
5932 nds32_elf_append_relax_relocs (const char *key
, const void *value
)
5934 struct nds32_relocs_pattern
*relocs_pattern
=
5935 (struct nds32_relocs_pattern
*) value
;
5936 struct nds32_relocs_pattern
*pattern_temp
, *pattern_now
;
5937 symbolS
*sym
, *hi_sym
= NULL
;
5940 segT seg_bak
= now_seg
;
5941 frchainS
*frchain_bak
= frchain_now
;
5942 struct nds32_relax_hint_table hint_info
;
5943 nds32_relax_fixup_info_t
*hint_fixup
, *fixup_now
;
5945 offsetT branch_offset
, hi_branch_offset
= 0;
5948 unsigned int ptr_offset
, hint_count
, relax_code_size
, count
= 0;
5949 uint32_t *code_seq
, code_insn
;
5953 if (!relocs_pattern
)
5956 if (!nds32_find_reloc_table (relocs_pattern
, &hint_info
))
5959 /* Save symbol for some EMPTY relocation using. */
5960 pattern_now
= relocs_pattern
;
5963 if (pattern_now
->opcode
->value
== OP6 (SETHI
))
5965 hi_sym
= pattern_now
->sym
;
5966 hi_branch_offset
= pattern_now
->fixP
->fx_offset
;
5969 pattern_now
= pattern_now
->next
;
5972 /* Inserting fix up must specify now_seg or frchain_now. */
5973 now_seg
= relocs_pattern
->seg
;
5974 frchain_now
= relocs_pattern
->frchain
;
5975 fragP
= relocs_pattern
->frag
;
5976 branch_offset
= fragP
->fr_offset
;
5978 hint_fixup
= hint_info
.relax_fixup
;
5979 code_seq
= hint_info
.relax_code_seq
;
5980 relax_code_size
= hint_info
.relax_code_size
;
5981 pattern_now
= relocs_pattern
;
5983 #ifdef NDS32_LINUX_TOOLCHAIN
5984 /* prepare group relocation ID (number). */
5988 /* convert .relax_hint key to number */
5990 group_id
= strtol (key
, NULL
, 10);
5991 if ((errno
== ERANGE
&& (group_id
== LONG_MAX
|| group_id
== LONG_MIN
))
5992 || (errno
!= 0 && group_id
== 0))
5994 as_bad (_("Internal error: .relax_hint KEY is not a number!"));
6000 /* Insert relaxation. */
6001 exp
.X_op
= O_symbol
;
6003 /* For each instruction in the hint group. */
6006 if (count
>= relax_code_size
/ 4)
6009 /* Choose the match fixup by instruction. */
6010 code_insn
= CLEAN_REG (*(code_seq
+ count
));
6011 if (!nds32_match_hint_insn (pattern_now
->opcode
, code_insn
))
6013 /* Try search from head again */
6015 code_insn
= CLEAN_REG (*(code_seq
+ count
));
6017 while (!nds32_match_hint_insn (pattern_now
->opcode
, code_insn
))
6020 if (count
>= relax_code_size
/ 4)
6022 as_bad (_("Internal error: Relax hint (%s) error. %s: %s (%x)"),
6025 pattern_now
->opcode
->opcode
,
6026 pattern_now
->opcode
->value
);
6029 code_insn
= CLEAN_REG (*(code_seq
+ count
));
6032 fragP
= pattern_now
->frag
;
6033 sym
= pattern_now
->sym
;
6034 branch_offset
= fragP
->fr_offset
;
6036 where
= pattern_now
->where
;
6037 /* Find the instruction map fix. */
6038 fixup_now
= hint_fixup
;
6039 while (fixup_now
->offset
!= offset
)
6042 if (fixup_now
->size
== 0)
6045 /* This element is without relaxation relocation. */
6046 if (fixup_now
->size
== 0)
6048 pattern_now
= pattern_now
->next
;
6051 fixup_size
= fixup_now
->size
;
6053 /* Insert all fixup. */
6055 while (fixup_size
!= 0 && fixup_now
->offset
== offset
)
6057 /* Set the real instruction size in element. */
6058 fixup_size
= pattern_now
->opcode
->isize
;
6059 pcrel
= ((fixup_now
->ramp
& NDS32_PCREL
) != 0) ? 1 : 0;
6060 if (fixup_now
->ramp
& NDS32_FIX
)
6062 /* Convert original relocation. */
6063 pattern_now
->fixP
->fx_r_type
= fixup_now
->r_type
;
6066 else if ((fixup_now
->ramp
& NDS32_PTR
) != 0)
6068 /* This relocation has to point to another instruction. Make
6069 sure each resolved relocation has to be pointed. */
6070 pattern_temp
= relocs_pattern
;
6071 /* All instruction in relax_table should be 32-bit. */
6072 hint_count
= hint_info
.relax_code_size
/ 4;
6073 code_insn
= CLEAN_REG (*(code_seq
+ hint_count
- 1));
6074 while (pattern_temp
)
6076 /* Point to every resolved relocation. */
6077 if (nds32_match_hint_insn (pattern_temp
->opcode
, code_insn
))
6080 pattern_temp
->where
- pattern_temp
->frag
->fr_literal
;
6081 exp
.X_add_symbol
= symbol_temp_new (now_seg
,
6084 exp
.X_add_number
= 0;
6086 fix_new_exp (fragP
, where
- fragP
->fr_literal
,
6087 fixup_size
, &exp
, 0, fixup_now
->r_type
);
6088 fixP
->fx_addnumber
= fixP
->fx_offset
;
6090 pattern_temp
= pattern_temp
->next
;
6094 else if (fixup_now
->ramp
& NDS32_ADDEND
)
6096 range
= nds32_elf_sethi_range (relocs_pattern
);
6097 if (range
== NDS32_LOADSTORE_NONE
)
6099 as_bad (_("Internal error: Range error. %s"), now_seg
->name
);
6102 exp
.X_add_symbol
= abs_section_sym
;
6103 exp
.X_add_number
= SET_ADDEND (4, 0, optimize
, enable_16bit
);
6104 exp
.X_add_number
|= ((range
& 0x3f) << 8);
6106 else if ((fixup_now
->ramp
& NDS32_ABS
) != 0)
6108 /* This is a tag relocation. */
6109 exp
.X_add_symbol
= abs_section_sym
;
6110 exp
.X_add_number
= 0;
6112 else if ((fixup_now
->ramp
& NDS32_INSN16
) != 0)
6116 /* This is a tag relocation. */
6117 exp
.X_add_symbol
= abs_section_sym
;
6118 exp
.X_add_number
= 0;
6120 else if ((fixup_now
->ramp
& NDS32_SYM
) != 0)
6122 /* For EMPTY relocation save the true symbol. */
6123 exp
.X_add_symbol
= hi_sym
;
6124 exp
.X_add_number
= hi_branch_offset
;
6126 else if (NDS32_SYM_DESC_MEM
& fixup_now
->ramp
)
6128 /* Do the same as NDS32_SYM. */
6129 exp
.X_add_symbol
= hi_sym
;
6130 exp
.X_add_number
= hi_branch_offset
;
6132 /* Extra to NDS32_SYM. */
6133 /* Detect if DESC_FUNC relax type do apply. */
6134 if ((REG_GP
== N32_RA5 (pattern_now
->insn
))
6135 || (REG_GP
== N32_RB5 (pattern_now
->insn
)))
6137 fixP
= fix_new_exp (fragP
, where
- fragP
->fr_literal
,
6138 fixup_size
, &exp
, pcrel
,
6139 BFD_RELOC_NDS32_TLS_DESC_FUNC
);
6140 fixP
->fx_addnumber
= fixP
->fx_offset
;
6144 /* Else do as usual. */
6146 else if (fixup_now
->ramp
& NDS32_PTR_PATTERN
)
6148 /* Find out PTR_RESOLVED code pattern. */
6149 nds32_relax_fixup_info_t
*next_fixup
= fixup_now
+ 1;
6150 uint32_t resolved_pattern
= 0;
6151 while (next_fixup
->offset
)
6153 if (next_fixup
->r_type
== BFD_RELOC_NDS32_PTR_RESOLVED
)
6155 uint32_t new_pattern
= code_seq
[next_fixup
->offset
>> 2];
6156 if (!resolved_pattern
)
6157 resolved_pattern
= new_pattern
;
6158 else if (new_pattern
!= resolved_pattern
)
6160 as_warn (_("Multiple BFD_RELOC_NDS32_PTR_RESOLVED "
6161 "patterns are not supported yet!"));
6168 /* Find matched code and insert fix-ups. */
6169 struct nds32_relocs_pattern
*next_pattern
= pattern_now
->next
;
6170 /* This relocation has to point to another instruction.
6171 Make sure each resolved relocation has to be pointed. */
6172 /* All instruction in relax_table should be 32-bit. */
6173 while (next_pattern
)
6175 uint32_t cur_pattern
= GET_OPCODE (next_pattern
->opcode
->value
);
6176 if (cur_pattern
== resolved_pattern
)
6178 ptr_offset
= next_pattern
->where
6179 - next_pattern
->frag
->fr_literal
;
6180 exp
.X_add_symbol
= symbol_temp_new (now_seg
,
6183 exp
.X_add_number
= 0;
6184 fixP
= fix_new_exp (fragP
, where
- fragP
->fr_literal
,
6185 fixup_size
, &exp
, 0,
6187 fixP
->fx_addnumber
= fixP
->fx_offset
;
6189 next_pattern
= next_pattern
->next
;
6194 else if (fixup_now
->ramp
& NDS32_PTR_MULTIPLE
)
6196 /* Find each PTR_RESOLVED pattern after PTR. */
6197 nds32_relax_fixup_info_t
*next_fixup
= fixup_now
+ 1;
6198 while (next_fixup
->offset
)
6200 if (next_fixup
->r_type
== BFD_RELOC_NDS32_PTR_RESOLVED
)
6202 uint32_t pattern
= code_seq
[next_fixup
->offset
>> 2];
6203 /* Find matched code to insert fix-ups. */
6204 struct nds32_relocs_pattern
*next_insn
= pattern_now
->next
;
6207 uint32_t insn_pattern
= GET_OPCODE (next_insn
->opcode
->value
);
6208 if (insn_pattern
== pattern
)
6210 ptr_offset
= next_insn
->where
6211 - next_insn
->frag
->fr_literal
;
6212 exp
.X_add_symbol
= symbol_temp_new (now_seg
,
6215 exp
.X_add_number
= 0;
6216 fixP
= fix_new_exp (fragP
,
6217 where
- fragP
->fr_literal
,
6218 fixup_size
, &exp
, 0,
6220 fixP
->fx_addnumber
= fixP
->fx_offset
;
6222 next_insn
= next_insn
->next
;
6231 exp
.X_add_symbol
= sym
;
6232 exp
.X_add_number
= branch_offset
;
6235 if (fixup_size
!= 0)
6237 fixP
= fix_new_exp (fragP
, where
- fragP
->fr_literal
, fixup_size
,
6238 &exp
, pcrel
, fixup_now
->r_type
);
6239 fixP
->fx_addnumber
= fixP
->fx_offset
;
6242 fixup_size
= fixup_now
->size
;
6245 #ifdef NDS32_LINUX_TOOLCHAIN
6246 /* Insert group relocation for each relax hint. */
6249 exp
.X_add_symbol
= hi_sym
; /* for eyes only */
6250 exp
.X_add_number
= group_id
;
6251 fixP
= fix_new_exp (fragP
, where
- fragP
->fr_literal
, fixup_size
,
6252 &exp
, pcrel
, BFD_RELOC_NDS32_GROUP
);
6253 fixP
->fx_addnumber
= fixP
->fx_offset
;
6257 if (count
< relax_code_size
/ 4)
6259 pattern_now
= pattern_now
->next
;
6264 frchain_now
= frchain_bak
;
6268 nds32_elf_append_relax_relocs_traverse (void **slot
, void *arg ATTRIBUTE_UNUSED
)
6270 string_tuple_t
*tuple
= *((string_tuple_t
**) slot
);
6271 nds32_elf_append_relax_relocs (tuple
->key
, tuple
->value
);
6277 nds32_str_tolower (const char *src
, char *dest
)
6279 unsigned int i
, len
;
6283 for (i
= 0; i
< len
; i
++)
6284 *(dest
+ i
) = TOLOWER (*(src
+ i
));
6289 /* Check instruction if it can be used for the baseline. */
6292 nds32_check_insn_available (struct nds32_asm_insn insn
, const char *str
)
6294 int attr
= insn
.attr
& ATTR_ALL
;
6295 static int baseline_isa
= 0;
6298 s
= xmalloc (strlen (str
) + 1);
6299 nds32_str_tolower (str
, s
);
6301 && (((insn
.opcode
->value
== ALU2 (MTUSR
)
6302 || insn
.opcode
->value
== ALU2 (MFUSR
))
6303 && (strstr (s
, "lc")
6305 || strstr (s
, "lb")))
6306 || (insn
.attr
& NASM_ATTR_ZOL
)))
6308 as_bad (_("Not support instruction %s in verbatim."), str
);
6313 if (!enable_16bit
&& insn
.opcode
->isize
== 2)
6315 as_bad (_("16-bit instruction is disabled: %s."), str
);
6319 /* No isa setting or all isa can use. */
6320 if (attr
== 0 || attr
== ATTR_ALL
)
6323 if (baseline_isa
== 0)
6325 /* Map option baseline and instruction attribute. */
6326 switch (nds32_baseline
)
6329 baseline_isa
= ATTR (ISA_V2
);
6332 baseline_isa
= ATTR (ISA_V3
);
6335 baseline_isa
= ATTR (ISA_V3M
);
6340 if ((baseline_isa
& attr
) == 0)
6342 as_bad (_("Instruction %s not supported in the baseline."), str
);
6348 /* Stub of machine dependent. */
6351 md_assemble (char *str
)
6353 struct nds32_asm_insn insn
;
6355 struct nds32_pseudo_opcode
*popcode
;
6356 const struct nds32_field
*fld
= NULL
;
6359 struct nds32_relocs_pattern
*relocs_temp
;
6360 struct nds32_relocs_group
*group_temp
;
6362 int label
= label_exist
;
6363 static bool pseudo_hint
= false;
6365 popcode
= nds32_lookup_pseudo_opcode (str
);
6366 /* Note that we need to check 'verbatim' and
6367 'opcode->physical_op'. If the assembly content is generated by
6368 compiler and this opcode is a physical instruction, there is no
6369 need to perform pseudo instruction expansion/transformation. */
6370 if (popcode
&& !(verbatim
&& popcode
->physical_op
))
6372 /* Pseudo instruction is with relax_hint. */
6375 pseudo_opcode
= true;
6376 nds32_pseudo_opcode_wrapper (str
, popcode
);
6377 pseudo_opcode
= false;
6378 pseudo_hint
= false;
6379 nds32_elf_append_relax_relocs (NULL
, relocs_list
);
6381 /* Free relax_hint group list. */
6382 while (nds32_relax_hint_current
)
6384 group_temp
= nds32_relax_hint_current
->next
;
6385 free (nds32_relax_hint_current
);
6386 nds32_relax_hint_current
= group_temp
;
6389 /* Free pseudo list. */
6390 relocs_temp
= relocs_list
;
6393 relocs_list
= relocs_list
->next
;
6395 relocs_temp
= relocs_list
;
6402 insn
.info
= XNEW (expressionS
);
6403 asm_desc
.result
= NASM_OK
;
6404 nds32_assemble (&asm_desc
, &insn
, str
);
6406 switch (asm_desc
.result
)
6408 case NASM_ERR_UNKNOWN_OP
:
6409 as_bad (_("Unrecognized opcode, %s."), str
);
6411 case NASM_ERR_SYNTAX
:
6412 as_bad (_("Incorrect syntax, %s."), str
);
6414 case NASM_ERR_OPERAND
:
6415 as_bad (_("Unrecognized operand/register, %s."), str
);
6417 case NASM_ERR_OUT_OF_RANGE
:
6418 as_bad (_("Operand out of range, %s."), str
);
6420 case NASM_ERR_REG_REDUCED
:
6421 as_bad (_("Prohibited register used for reduced-register, %s."), str
);
6423 case NASM_ERR_JUNK_EOL
:
6424 as_bad (_("Junk at end of line, %s."), str
);
6428 gas_assert (insn
.opcode
);
6430 nds32_set_elf_flags_by_insn (&insn
);
6432 gas_assert (insn
.opcode
->isize
== 4 || insn
.opcode
->isize
== 2);
6434 if (!nds32_check_insn_available (insn
, str
))
6437 /* Make sure the beginning of text being 2-byte align. */
6438 nds32_adjust_label (1);
6439 add_mapping_symbol (MAP_CODE
, 0, 0);
6441 /* Try to allocate the max size to guarantee relaxable same branch
6442 instructions in the same fragment. */
6443 frag_grow (NDS32_MAXCHAR
);
6446 if (fld
&& (insn
.attr
& NASM_ATTR_BRANCH
)
6447 && (pseudo_opcode
|| (insn
.opcode
->value
!= INSN_JAL
6448 && insn
.opcode
->value
!= INSN_J
))
6449 && (!verbatim
|| pseudo_opcode
))
6451 /* User assembly code branch relax for it. */
6452 /* If fld is not NULL, it is a symbol. */
6453 /* Branch must relax to proper pattern in user assembly code exclude
6454 J and JAL. Keep these two in original type for users which wants
6455 to keep their size be fixed. In general, assembler does not convert
6456 instruction generated by compiler. But jump instruction may be
6457 truncated in text virtual model. For workaround, compiler generate
6458 pseudo jump to fix this issue currently. */
6460 /* Get branch range type. */
6461 dwarf2_emit_insn (0);
6462 enum nds32_br_range range_type
;
6463 expressionS
*pexp
= insn
.info
;
6465 range_type
= get_range_type (fld
);
6467 out
= frag_var (rs_machine_dependent
, NDS32_MAXCHAR
,
6468 0, /* VAR is un-used. */
6469 range_type
, /* SUBTYPE is used as range type. */
6470 pexp
->X_add_symbol
, pexp
->X_add_number
, 0);
6472 fragP
->fr_fix
+= insn
.opcode
->isize
;
6473 fragP
->tc_frag_data
.opcode
= insn
.opcode
;
6474 fragP
->tc_frag_data
.insn
= insn
.insn
;
6475 if (insn
.opcode
->isize
== 4)
6476 bfd_putb32 (insn
.insn
, out
);
6477 else if (insn
.opcode
->isize
== 2)
6478 bfd_putb16 (insn
.insn
, out
);
6479 fragP
->tc_frag_data
.flag
|= NDS32_FRAG_BRANCH
;
6483 /* md_convert_frag will insert relocations. */
6485 else if (!relaxing
&& enable_16bit
&& (optimize
|| optimize_for_space
)
6486 && ((!fld
&& !verbatim
&& insn
.opcode
->isize
== 4
6487 && nds32_convert_32_to_16 (stdoutput
, insn
.insn
, &insn_16
, NULL
))
6488 || (insn
.opcode
->isize
== 2
6489 && nds32_convert_16_to_32 (stdoutput
, insn
.insn
, NULL
))))
6491 /* Record this one is relaxable. */
6492 expressionS
*pexp
= insn
.info
;
6493 dwarf2_emit_insn (0);
6496 out
= frag_var (rs_machine_dependent
,
6497 4, /* Max size is 32-bit instruction. */
6498 0, /* VAR is un-used. */
6499 0, pexp
->X_add_symbol
, pexp
->X_add_number
, 0);
6500 fragP
->tc_frag_data
.flag
|= NDS32_FRAG_RELAXABLE_BRANCH
;
6503 out
= frag_var (rs_machine_dependent
,
6504 4, /* Max size is 32-bit instruction. */
6505 0, /* VAR is un-used. */
6507 fragP
->tc_frag_data
.flag
|= NDS32_FRAG_RELAXABLE
;
6508 fragP
->tc_frag_data
.opcode
= insn
.opcode
;
6509 fragP
->tc_frag_data
.insn
= insn
.insn
;
6512 /* In original, we don't relax the instruction with label on it,
6513 but this may cause some redundant nop16. Therefore, tag this
6514 relaxable instruction and relax it carefully. */
6516 fragP
->tc_frag_data
.flag
|= NDS32_FRAG_LABEL
;
6518 if (insn
.opcode
->isize
== 4)
6519 bfd_putb16 (insn_16
, out
);
6520 else if (insn
.opcode
->isize
== 2)
6521 bfd_putb16 (insn
.insn
, out
);
6526 else if ((verbatim
|| !relaxing
) && optimize
&& label
)
6528 /* This instruction is with label. */
6530 out
= frag_var (rs_machine_dependent
, insn
.opcode
->isize
,
6531 0, 0, NULL
, 0, NULL
);
6532 /* If this instruction is branch target, it is not relaxable. */
6533 fragP
->tc_frag_data
.flag
= NDS32_FRAG_LABEL
;
6534 fragP
->tc_frag_data
.opcode
= insn
.opcode
;
6535 fragP
->tc_frag_data
.insn
= insn
.insn
;
6536 fragP
->fr_fix
+= insn
.opcode
->isize
;
6537 if (insn
.opcode
->isize
== 4)
6539 exp
.X_op
= O_symbol
;
6540 exp
.X_add_symbol
= abs_section_sym
;
6541 exp
.X_add_number
= 0;
6542 fixP
= fix_new_exp (fragP
, fragP
->fr_fix
- 4, 0, &exp
,
6543 0, BFD_RELOC_NDS32_LABEL
);
6545 fragP
->tc_frag_data
.flag
= NDS32_FRAG_ALIGN
;
6549 out
= frag_more (insn
.opcode
->isize
);
6551 if (insn
.opcode
->isize
== 4)
6552 bfd_putb32 (insn
.insn
, out
);
6553 else if (insn
.opcode
->isize
== 2)
6554 bfd_putb16 (insn
.insn
, out
);
6556 dwarf2_emit_insn (insn
.opcode
->isize
);
6558 /* Compiler generating code and user assembly pseudo load-store, insert
6560 expressionS
*pexp
= insn
.info
;
6561 fixP
= nds32_elf_record_fixup_exp (fragP
, str
, fld
, pexp
, out
, &insn
);
6562 /* Build relaxation pattern when relaxing is enable. */
6564 nds32_elf_build_relax_relation (fixP
, pexp
, out
, &insn
, fragP
, fld
,
6570 /* md_macro_start */
6573 nds32_macro_start (void)
6580 nds32_macro_info (void *info ATTRIBUTE_UNUSED
)
6587 nds32_macro_end (void)
6591 /* GAS will call this function with one argument, an expressionS pointer, for
6592 any expression that can not be recognized. When the function is called,
6593 input_line_pointer will point to the start of the expression. */
6596 md_operand (expressionS
*expressionP
)
6598 if (*input_line_pointer
== '#')
6600 input_line_pointer
++;
6601 expression (expressionP
);
6605 /* GAS will call this function for each section at the end of the assembly, to
6606 permit the CPU back end to adjust the alignment of a section. The function
6607 must take two arguments, a segT for the section and a valueT for the size of
6608 the section, and return a valueT for the rounded size. */
6611 md_section_align (segT segment
, valueT size
)
6613 int align
= bfd_section_alignment (segment
);
6615 return ((size
+ (1 << align
) - 1) & ((valueT
) -1 << align
));
6618 /* GAS will call this function when a symbol table lookup fails, before it
6619 creates a new symbol. Typically this would be used to supply symbols whose
6620 name or value changes dynamically, possibly in a context sensitive way.
6621 Predefined symbols with fixed values, such as register names or condition
6622 codes, are typically entered directly into the symbol table when md_begin
6623 is called. One argument is passed, a char * for the symbol. */
6626 md_undefined_symbol (char *name ATTRIBUTE_UNUSED
)
6632 nds32_calc_branch_offset (segT segment
, fragS
*fragP
,
6633 long stretch ATTRIBUTE_UNUSED
,
6634 relax_info_t
*relax_info
,
6635 enum nds32_br_range branch_range_type
)
6637 struct nds32_opcode
*opcode
= fragP
->tc_frag_data
.opcode
;
6638 symbolS
*branch_symbol
= fragP
->fr_symbol
;
6639 offsetT branch_offset
= fragP
->fr_offset
;
6640 offsetT branch_target_address
;
6641 offsetT branch_insn_address
;
6644 if ((S_GET_SEGMENT (branch_symbol
) != segment
)
6645 || S_IS_WEAK (branch_symbol
))
6647 /* The symbol is not in the SEGMENT. It could be far far away. */
6648 offset
= 0x80000000;
6652 /* Calculate symbol-to-instruction offset. */
6653 branch_target_address
= S_GET_VALUE (branch_symbol
) + branch_offset
;
6654 /* If the destination symbol is beyond current frag address,
6655 STRETCH will take effect to symbol's position. */
6656 if (S_GET_VALUE (branch_symbol
) > fragP
->fr_address
)
6657 branch_target_address
+= stretch
;
6659 branch_insn_address
= fragP
->fr_address
+ fragP
->fr_fix
;
6660 branch_insn_address
-= opcode
->isize
;
6662 /* Update BRANCH_INSN_ADDRESS to relaxed position. */
6663 branch_insn_address
+= (relax_info
->relax_code_size
[branch_range_type
]
6664 - relax_info
->relax_branch_isize
[branch_range_type
]);
6666 offset
= branch_target_address
- branch_insn_address
;
6672 static enum nds32_br_range
6673 nds32_convert_to_range_type (long offset
)
6675 enum nds32_br_range range_type
;
6677 if (-(0x100) <= offset
&& offset
< 0x100) /* 256 bytes */
6678 range_type
= BR_RANGE_S256
;
6679 else if (-(0x4000) <= offset
&& offset
< 0x4000) /* 16K bytes */
6680 range_type
= BR_RANGE_S16K
;
6681 else if (-(0x10000) <= offset
&& offset
< 0x10000) /* 64K bytes */
6682 range_type
= BR_RANGE_S64K
;
6683 else if (-(0x1000000) <= offset
&& offset
< 0x1000000) /* 16M bytes */
6684 range_type
= BR_RANGE_S16M
;
6686 range_type
= BR_RANGE_U4G
;
6691 /* Set instruction register mask. */
6694 nds32_elf_get_set_cond (relax_info_t
*relax_info
, int offset
, uint32_t *insn
,
6695 uint32_t ori_insn
, int range
)
6697 nds32_cond_field_t
*cond_fields
= relax_info
->cond_field
;
6698 nds32_cond_field_t
*code_seq_cond
= relax_info
->relax_code_condition
[range
];
6702 /* The instruction has conditions. Collect condition values. */
6703 while (code_seq_cond
[i
].bitmask
!= 0)
6705 if (offset
== code_seq_cond
[i
].offset
)
6707 mask
= (ori_insn
>> cond_fields
[i
].bitpos
) & cond_fields
[i
].bitmask
;
6709 if (cond_fields
[i
].signed_extend
)
6710 mask
= (mask
^ ((cond_fields
[i
].bitmask
+ 1) >> 1)) -
6711 ((cond_fields
[i
].bitmask
+ 1) >> 1);
6712 *insn
|= (mask
& code_seq_cond
[i
].bitmask
) << code_seq_cond
[i
].bitpos
;
6719 nds32_relax_branch_instructions (segT segment
, fragS
*fragP
,
6720 long stretch ATTRIBUTE_UNUSED
,
6723 enum nds32_br_range branch_range_type
;
6724 struct nds32_opcode
*opcode
= fragP
->tc_frag_data
.opcode
;
6726 enum nds32_br_range real_range_type
;
6728 relax_info_t
*relax_info
;
6735 int code_seq_offset
;
6737 /* Replace with gas_assert (fragP->fr_symbol != NULL); */
6738 if (fragP
->fr_symbol
== NULL
)
6741 /* If frag_var is not enough room, the previous frag is fr_full and with
6742 opcode. The new one is rs_dependent but without opcode. */
6746 /* Use U4G mode for b and bal in verbatim mode because lto may combine
6747 functions into a file. And order the file in the last when linking.
6748 Once there is multiple definition, the same function will be kicked.
6749 This may cause relocation truncated error. */
6750 if (verbatim
&& !nds32_pic
6751 && (strcmp (opcode
->opcode
, "j") == 0
6752 || strcmp (opcode
->opcode
, "jal") == 0))
6754 fragP
->fr_subtype
= BR_RANGE_U4G
;
6761 relax_info
= str_hash_find (nds32_relax_info_hash
, opcode
->opcode
);
6763 if (relax_info
== NULL
)
6768 branch_range_type
= relax_info
->br_range
;
6773 branch_range_type
= fragP
->fr_subtype
;
6774 i
= branch_range_type
;
6777 offset
= nds32_calc_branch_offset (segment
, fragP
, stretch
,
6778 relax_info
, branch_range_type
);
6780 real_range_type
= nds32_convert_to_range_type (offset
);
6782 /* If actual range is equal to instruction jump range, do nothing. */
6783 if (real_range_type
== branch_range_type
)
6785 fragP
->fr_subtype
= real_range_type
;
6789 /* Find out proper relaxation code sequence. */
6790 for (; i
< BR_RANGE_NUM
; i
++)
6792 if (real_range_type
<= (unsigned int) i
)
6795 diff
= relax_info
->relax_code_size
[i
] - opcode
->isize
;
6796 else if (real_range_type
< (unsigned int) i
)
6797 diff
= relax_info
->relax_code_size
[real_range_type
]
6798 - relax_info
->relax_code_size
[branch_range_type
];
6800 diff
= relax_info
->relax_code_size
[i
]
6801 - relax_info
->relax_code_size
[branch_range_type
];
6803 /* If the instruction could be converted to 16-bits,
6804 minus the difference. */
6805 code_seq_offset
= 0;
6808 code_seq_size
= relax_info
->relax_code_size
[i
];
6809 code_seq
= relax_info
->relax_code_seq
[i
];
6810 while (code_seq_offset
< code_seq_size
)
6813 if (insn
& 0x80000000) /* 16-bits instruction. */
6817 else /* 32-bits instruction. */
6821 while (relax_info
->relax_fixup
[i
][k
].size
!=0
6822 && relax_info
->relax_fixup
[i
][k
].offset
< code_seq_offset
)
6826 code_seq_offset
+= insn_size
;
6830 /* Update fr_subtype to new NDS32_BR_RANGE. */
6831 fragP
->fr_subtype
= real_range_type
;
6836 return diff
+ adjust
;
6839 /* Adjust relaxable frag till current frag. */
6842 nds32_adjust_relaxable_frag (fragS
*startP
, fragS
*fragP
)
6845 if (startP
->tc_frag_data
.flag
& NDS32_FRAG_RELAXED
)
6850 startP
->tc_frag_data
.flag
^= NDS32_FRAG_RELAXED
;
6854 startP
= startP
->fr_next
;
6857 startP
->fr_address
+= adj
;
6858 if (startP
== fragP
)
6866 nds32_get_align (addressT address
, int align
)
6868 addressT mask
, new_address
;
6870 mask
= ~((addressT
) (~0) << align
);
6871 new_address
= (address
+ mask
) & (~mask
);
6872 return (new_address
- address
);
6875 /* Check the prev_frag is legal. */
6877 invalid_prev_frag (fragS
* fragP
, fragS
**prev_frag
, bool relax
)
6880 fragS
*frag_start
= *prev_frag
;
6882 if (!frag_start
|| !relax
)
6885 if (frag_start
->last_fr_address
>= fragP
->last_fr_address
)
6891 fragS
*frag_t
= *prev_frag
;
6892 while (frag_t
!= fragP
)
6894 if (frag_t
->fr_type
== rs_align
6895 || frag_t
->fr_type
== rs_align_code
6896 || frag_t
->fr_type
== rs_align_test
)
6898 /* Relax instruction can not walk across label. */
6899 if (frag_t
->tc_frag_data
.flag
& NDS32_FRAG_LABEL
)
6904 /* Relax previous relaxable to align rs_align frag. */
6905 address
= frag_t
->fr_address
+ frag_t
->fr_fix
;
6906 addressT offset
= nds32_get_align (address
, (int) frag_t
->fr_offset
);
6909 /* If there is label on the prev_frag, check if it is aligned. */
6910 if (!((*prev_frag
)->tc_frag_data
.flag
& NDS32_FRAG_LABEL
)
6911 || (((*prev_frag
)->fr_address
+ (*prev_frag
)->fr_fix
- 2 )
6913 nds32_adjust_relaxable_frag (*prev_frag
, frag_t
);
6918 frag_t
= frag_t
->fr_next
;
6921 if (fragP
->tc_frag_data
.flag
& NDS32_FRAG_ALIGN
)
6923 address
= fragP
->fr_address
;
6924 addressT offset
= nds32_get_align (address
, 2);
6927 /* If there is label on the prev_frag, check if it is aligned. */
6928 if (!((*prev_frag
)->tc_frag_data
.flag
& NDS32_FRAG_LABEL
)
6929 || (((*prev_frag
)->fr_address
+ (*prev_frag
)->fr_fix
- 2 )
6931 nds32_adjust_relaxable_frag (*prev_frag
, fragP
);
6941 nds32_relax_frag (segT segment
, fragS
*fragP
, long stretch ATTRIBUTE_UNUSED
)
6943 /* Currently, there are two kinds of relaxation in nds32 assembler.
6945 2. relax for 32-bits to 16-bits */
6947 static fragS
*prev_frag
= NULL
;
6950 invalid_prev_frag (fragP
, &prev_frag
, true);
6952 if (fragP
->tc_frag_data
.flag
& NDS32_FRAG_BRANCH
)
6953 adjust
= nds32_relax_branch_instructions (segment
, fragP
, stretch
, 0);
6954 if (fragP
->tc_frag_data
.flag
& NDS32_FRAG_LABEL
)
6956 if (fragP
->tc_frag_data
.flag
& NDS32_FRAG_RELAXABLE
6957 && (fragP
->tc_frag_data
.flag
& NDS32_FRAG_RELAXED
) == 0)
6958 /* Here is considered relaxed case originally. But it may cause
6959 an endless loop when relaxing. Once the instruction is relaxed,
6960 it can not be undone. */
6966 /* This function returns an initial guess of the length by which a fragment
6967 must grow to hold a branch to reach its destination. Also updates
6968 fr_type/fr_subtype as necessary.
6970 It is called just before doing relaxation. Any symbol that is now undefined
6971 will not become defined. The guess for fr_var is ACTUALLY the growth beyond
6972 fr_fix. Whatever we do to grow fr_fix or fr_var contributes to our returned
6973 value. Although it may not be explicit in the frag, pretend fr_var starts
6977 md_estimate_size_before_relax (fragS
*fragP
, segT segment
)
6979 /* Currently, there are two kinds of relaxation in nds32 assembler.
6981 2. relax for 32-bits to 16-bits */
6983 /* Save previous relaxable frag. */
6984 static fragS
*prev_frag
= NULL
;
6987 invalid_prev_frag (fragP
, &prev_frag
, false);
6989 if (fragP
->tc_frag_data
.flag
& NDS32_FRAG_BRANCH
)
6990 adjust
= nds32_relax_branch_instructions (segment
, fragP
, 0, 1);
6991 if (fragP
->tc_frag_data
.flag
& NDS32_FRAG_LABEL
)
6993 if (fragP
->tc_frag_data
.flag
& NDS32_FRAG_RELAXED
)
6995 else if (fragP
->tc_frag_data
.flag
& NDS32_FRAG_RELAXABLE
)
7001 /* GAS will call this for each rs_machine_dependent fragment. The instruction
7002 is completed using the data from the relaxation pass. It may also create any
7003 necessary relocations.
7005 *FRAGP has been relaxed to its final size, and now needs to have the bytes
7006 inside it modified to conform to the new size. It is called after relaxation
7009 fragP->fr_type == rs_machine_dependent.
7010 fragP->fr_subtype is the subtype of what the address relaxed to. */
7013 md_convert_frag (bfd
*abfd ATTRIBUTE_UNUSED
, segT sec
, fragS
*fragP
)
7015 /* Convert branch relaxation instructions. */
7016 symbolS
*branch_symbol
= fragP
->fr_symbol
;
7017 offsetT branch_offset
= fragP
->fr_offset
;
7018 enum nds32_br_range branch_range_type
= fragP
->fr_subtype
;
7019 struct nds32_opcode
*opcode
= fragP
->tc_frag_data
.opcode
;
7020 uint32_t origin_insn
= fragP
->tc_frag_data
.insn
;
7021 relax_info_t
*relax_info
;
7024 int addend ATTRIBUTE_UNUSED
;
7025 offsetT branch_target_address
, branch_insn_address
;
7030 int code_size
, insn_size
, offset
, fixup_size
;
7031 int buf_offset
, pcrel
;
7034 nds32_relax_fixup_info_t fixup_info
[MAX_RELAX_FIX
];
7035 /* Save the 1st instruction is converted to 16 bit or not. */
7036 unsigned int branch_size
;
7037 enum bfd_reloc_code_real final_r_type
;
7039 /* Replace with gas_assert (branch_symbol != NULL); */
7040 if (branch_symbol
== NULL
&& !(fragP
->tc_frag_data
.flag
& NDS32_FRAG_RELAXED
))
7043 /* If frag_var is not enough room, the previous frag is fr_full and with
7044 opcode. The new one is rs_dependent but without opcode. */
7048 if (fragP
->tc_frag_data
.flag
& NDS32_FRAG_RELAXABLE_BRANCH
)
7050 relax_info
= str_hash_find (nds32_relax_info_hash
, opcode
->opcode
);
7052 if (relax_info
== NULL
)
7056 while (i
< BR_RANGE_NUM
7057 && relax_info
->relax_code_size
[i
]
7058 != (fragP
->tc_frag_data
.flag
& NDS32_FRAG_RELAXED
? 4 : 2))
7061 if (i
>= BR_RANGE_NUM
)
7062 as_bad ("Internal error: Cannot find relocation of"
7063 "relaxable branch.");
7065 exp
.X_op
= O_symbol
;
7066 exp
.X_add_symbol
= branch_symbol
;
7067 exp
.X_add_number
= branch_offset
;
7068 pcrel
= ((relax_info
->relax_fixup
[i
][0].ramp
& NDS32_PCREL
) != 0) ? 1 : 0;
7069 fr_where
= fragP
->fr_fix
- 2;
7070 fixP
= fix_new_exp (fragP
, fr_where
, relax_info
->relax_fixup
[i
][0].size
,
7071 &exp
, pcrel
, relax_info
->relax_fixup
[i
][0].r_type
);
7072 fixP
->fx_addnumber
= fixP
->fx_offset
;
7074 if (fragP
->tc_frag_data
.flag
& NDS32_FRAG_RELAXED
)
7076 insn_16
= fragP
->tc_frag_data
.insn
;
7077 nds32_convert_16_to_32 (stdoutput
, insn_16
, &insn
);
7078 fr_buffer
= fragP
->fr_literal
+ fr_where
;
7080 exp
.X_op
= O_symbol
;
7081 exp
.X_add_symbol
= abs_section_sym
;
7082 exp
.X_add_number
= 0;
7083 fix_new_exp (fragP
, fr_where
, 4,
7084 &exp
, 0, BFD_RELOC_NDS32_INSN16
);
7085 number_to_chars_bigendian (fr_buffer
, insn
, 4);
7088 else if (fragP
->tc_frag_data
.flag
& NDS32_FRAG_RELAXED
)
7090 if (fragP
->tc_frag_data
.opcode
->isize
== 2)
7092 insn_16
= fragP
->tc_frag_data
.insn
;
7093 nds32_convert_16_to_32 (stdoutput
, insn_16
, &insn
);
7096 insn
= fragP
->tc_frag_data
.insn
;
7098 fr_where
= fragP
->fr_fix
- 4;
7099 fr_buffer
= fragP
->fr_literal
+ fr_where
;
7100 exp
.X_op
= O_symbol
;
7101 exp
.X_add_symbol
= abs_section_sym
;
7102 exp
.X_add_number
= 0;
7103 fix_new_exp (fragP
, fr_where
, 4, &exp
, 0,
7104 BFD_RELOC_NDS32_INSN16
);
7105 number_to_chars_bigendian (fr_buffer
, insn
, 4);
7107 else if (fragP
->tc_frag_data
.flag
& NDS32_FRAG_BRANCH
)
7109 /* Branch instruction adjust and append relocations. */
7110 relax_info
= str_hash_find (nds32_relax_info_hash
, opcode
->opcode
);
7112 if (relax_info
== NULL
)
7115 fr_where
= fragP
->fr_fix
- opcode
->isize
;
7116 fr_buffer
= fragP
->fr_literal
+ fr_where
;
7118 if ((S_GET_SEGMENT (branch_symbol
) != sec
)
7119 || S_IS_WEAK (branch_symbol
))
7121 if (fragP
->fr_offset
& 3)
7122 as_warn (_("Addend to unresolved symbol is not on word boundary."));
7127 /* Calculate symbol-to-instruction offset. */
7128 branch_target_address
= S_GET_VALUE (branch_symbol
) + branch_offset
;
7129 branch_insn_address
= fragP
->fr_address
+ fr_where
;
7130 addend
= (branch_target_address
- branch_insn_address
) >> 1;
7133 code_size
= relax_info
->relax_code_size
[branch_range_type
];
7134 code_seq
= relax_info
->relax_code_seq
[branch_range_type
];
7136 memcpy (fixup_info
, relax_info
->relax_fixup
[branch_range_type
],
7137 sizeof (fixup_info
));
7142 offset
= 0; /* code_seq offset */
7143 buf_offset
= 0; /* fr_buffer offset */
7144 while (offset
< code_size
)
7147 if (insn
& 0x80000000) /* 16-bits instruction. */
7149 insn
= (insn
>> 16) & 0xFFFF;
7152 else /* 32-bits instruction. */
7157 nds32_elf_get_set_cond (relax_info
, offset
, &insn
,
7158 origin_insn
, branch_range_type
);
7160 /* Try to convert to 16-bits instruction. Currently, only the first
7161 instruction in pattern can be converted. EX: bnez sethi ori jr,
7162 only bnez can be converted to 16 bit and ori can't. */
7164 while (fixup_info
[k
].size
!= 0
7165 && relax_info
->relax_fixup
[branch_range_type
][k
].offset
< offset
)
7168 number_to_chars_bigendian (fr_buffer
+ buf_offset
, insn
, insn_size
);
7169 buf_offset
+= insn_size
;
7171 offset
+= insn_size
;
7176 exp
.X_op
= O_symbol
;
7178 for (i
= 0; fixup_info
[i
].size
!= 0; i
++)
7180 fixup_size
= fixup_info
[i
].size
;
7181 pcrel
= ((fixup_info
[i
].ramp
& NDS32_PCREL
) != 0) ? 1 : 0;
7183 if ((fixup_info
[i
].ramp
& NDS32_CREATE_LABEL
) != 0)
7185 /* This is a reverse branch. */
7186 exp
.X_add_symbol
= symbol_temp_new (sec
, fragP
->fr_next
, 0);
7187 exp
.X_add_number
= 0;
7189 else if ((fixup_info
[i
].ramp
& NDS32_PTR
) != 0)
7191 /* This relocation has to point to another instruction. */
7192 branch_size
= fr_where
+ code_size
- 4;
7193 exp
.X_add_symbol
= symbol_temp_new (sec
, fragP
, branch_size
);
7194 exp
.X_add_number
= 0;
7196 else if ((fixup_info
[i
].ramp
& NDS32_ABS
) != 0)
7198 /* This is a tag relocation. */
7199 exp
.X_add_symbol
= abs_section_sym
;
7200 exp
.X_add_number
= 0;
7202 else if ((fixup_info
[i
].ramp
& NDS32_INSN16
) != 0)
7206 /* This is a tag relocation. */
7207 exp
.X_add_symbol
= abs_section_sym
;
7208 exp
.X_add_number
= 0;
7212 exp
.X_add_symbol
= branch_symbol
;
7213 exp
.X_add_number
= branch_offset
;
7216 if (fixup_info
[i
].r_type
!= 0)
7218 final_r_type
= fixup_info
[i
].r_type
;
7219 fixP
= fix_new_exp (fragP
, fr_where
+ fixup_info
[i
].offset
,
7220 fixup_size
, &exp
, pcrel
,
7222 fixP
->fx_addnumber
= fixP
->fx_offset
;
7226 fragP
->fr_fix
= fr_where
+ buf_offset
;
7230 /* tc_frob_file_before_fix */
7233 nds32_frob_file_before_fix (void)
7238 nds32_relaxable_section (asection
*sec
)
7240 return ((sec
->flags
& SEC_DEBUGGING
) == 0
7241 && strcmp (sec
->name
, ".eh_frame") != 0);
7244 /* TC_FORCE_RELOCATION */
7246 nds32_force_relocation (fixS
* fix
)
7248 switch (fix
->fx_r_type
)
7250 case BFD_RELOC_NDS32_INSN16
:
7251 case BFD_RELOC_NDS32_LABEL
:
7252 case BFD_RELOC_NDS32_LONGCALL1
:
7253 case BFD_RELOC_NDS32_LONGCALL2
:
7254 case BFD_RELOC_NDS32_LONGCALL3
:
7255 case BFD_RELOC_NDS32_LONGJUMP1
:
7256 case BFD_RELOC_NDS32_LONGJUMP2
:
7257 case BFD_RELOC_NDS32_LONGJUMP3
:
7258 case BFD_RELOC_NDS32_LOADSTORE
:
7259 case BFD_RELOC_NDS32_9_FIXED
:
7260 case BFD_RELOC_NDS32_15_FIXED
:
7261 case BFD_RELOC_NDS32_17_FIXED
:
7262 case BFD_RELOC_NDS32_25_FIXED
:
7263 case BFD_RELOC_NDS32_9_PCREL
:
7264 case BFD_RELOC_NDS32_15_PCREL
:
7265 case BFD_RELOC_NDS32_17_PCREL
:
7266 case BFD_RELOC_NDS32_WORD_9_PCREL
:
7267 case BFD_RELOC_NDS32_10_UPCREL
:
7268 case BFD_RELOC_NDS32_25_PCREL
:
7269 case BFD_RELOC_NDS32_MINUEND
:
7270 case BFD_RELOC_NDS32_SUBTRAHEND
:
7276 case BFD_RELOC_NDS32_DIFF_ULEB128
:
7277 /* Linker should handle difference between two symbol. */
7278 return fix
->fx_subsy
!= NULL
7279 && nds32_relaxable_section (S_GET_SEGMENT (fix
->fx_addsy
));
7282 as_bad ("Double word for difference between two symbols "
7283 "is not supported across relaxation.");
7288 if (generic_force_reloc (fix
))
7291 return fix
->fx_pcrel
;
7294 /* TC_VALIDATE_FIX_SUB */
7297 nds32_validate_fix_sub (fixS
*fix
, segT add_symbol_segment
)
7299 segT sub_symbol_segment
;
7301 /* This code is referred from Xtensa. Check their implementation for
7304 /* Make sure both symbols are in the same segment, and that segment is
7305 "normal" and relaxable. */
7306 sub_symbol_segment
= S_GET_SEGMENT (fix
->fx_subsy
);
7307 return (sub_symbol_segment
== add_symbol_segment
7308 && add_symbol_segment
!= undefined_section
);
7312 md_number_to_chars (char *buf
, valueT val
, int n
)
7314 if (target_big_endian
)
7315 number_to_chars_bigendian (buf
, val
, n
);
7317 number_to_chars_littleendian (buf
, val
, n
);
7320 /* This function is called to convert an ASCII string into a floating point
7321 value in format used by the CPU. */
7324 md_atof (int type
, char *litP
, int *sizeP
)
7328 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
7347 return _("Bad call to md_atof()");
7350 t
= atof_ieee (input_line_pointer
, type
, words
);
7352 input_line_pointer
= t
;
7353 *sizeP
= prec
* sizeof (LITTLENUM_TYPE
);
7355 if (target_big_endian
)
7357 for (i
= 0; i
< prec
; i
++)
7359 md_number_to_chars (litP
, (valueT
) words
[i
],
7360 sizeof (LITTLENUM_TYPE
));
7361 litP
+= sizeof (LITTLENUM_TYPE
);
7366 for (i
= prec
- 1; i
>= 0; i
--)
7368 md_number_to_chars (litP
, (valueT
) words
[i
],
7369 sizeof (LITTLENUM_TYPE
));
7370 litP
+= sizeof (LITTLENUM_TYPE
);
7377 /* md_elf_section_change_hook */
7380 nds32_elf_section_change_hook (void)
7387 nds32_cleanup (void)
7391 /* This function is used to scan leb128 subtraction expressions,
7392 and insert fixups for them.
7394 e.g., .leb128 .L1 - .L0
7396 These expressions are heavily used in debug information or
7397 exception tables. Because relaxation will change code size,
7398 we must resolve them in link time. */
7401 nds32_insert_leb128_fixes (bfd
*abfd ATTRIBUTE_UNUSED
,
7402 asection
*sec
, void *xxx ATTRIBUTE_UNUSED
)
7404 segment_info_type
*seginfo
= seg_info (sec
);
7407 subseg_set (sec
, 0);
7409 for (fragP
= seginfo
->frchainP
->frch_root
;
7410 fragP
; fragP
= fragP
->fr_next
)
7414 /* Only unsigned leb128 can be handle. */
7415 if (fragP
->fr_type
!= rs_leb128
|| fragP
->fr_subtype
!= 0
7416 || fragP
->fr_symbol
== NULL
)
7419 exp
= symbol_get_value_expression (fragP
->fr_symbol
);
7421 if (exp
->X_op
!= O_subtract
)
7424 fix_new_exp (fragP
, fragP
->fr_fix
, 0,
7425 exp
, 0, BFD_RELOC_NDS32_DIFF_ULEB128
);
7430 nds32_insert_relax_entry (bfd
*abfd ATTRIBUTE_UNUSED
, asection
*sec
,
7431 void *xxx ATTRIBUTE_UNUSED
)
7433 segment_info_type
*seginfo
;
7439 seginfo
= seg_info (sec
);
7440 if (!seginfo
|| !symbol_rootP
|| !subseg_text_p (sec
) || sec
->size
== 0)
7443 for (fixp
= seginfo
->fix_root
; fixp
; fixp
= fixp
->fx_next
)
7447 if (!fixp
&& !verbatim
&& ict_flag
== ICT_NONE
)
7450 subseg_change (sec
, 0);
7452 /* Set RELAX_ENTRY flags for linker. */
7453 fragP
= seginfo
->frchainP
->frch_root
;
7454 exp
.X_op
= O_symbol
;
7455 exp
.X_add_symbol
= abs_section_sym
;
7456 exp
.X_add_number
= 0;
7457 if (!enable_relax_relocs
)
7458 exp
.X_add_number
|= R_NDS32_RELAX_ENTRY_DISABLE_RELAX_FLAG
;
7461 /* These flags are only enabled when global relax is enabled.
7462 Maybe we can check DISABLE_RELAX_FLAG at link-time,
7463 so we set them anyway. */
7465 exp
.X_add_number
|= R_NDS32_RELAX_ENTRY_VERBATIM_FLAG
;
7466 if (ict_flag
== ICT_SMALL
)
7467 exp
.X_add_number
|= R_NDS32_RELAX_ENTRY_ICT_SMALL
;
7468 else if (ict_flag
== ICT_LARGE
)
7469 exp
.X_add_number
|= R_NDS32_RELAX_ENTRY_ICT_LARGE
;
7472 exp
.X_add_number
|= R_NDS32_RELAX_ENTRY_OPTIMIZE_FLAG
;
7473 if (optimize_for_space
)
7474 exp
.X_add_number
|= R_NDS32_RELAX_ENTRY_OPTIMIZE_FOR_SPACE_FLAG
;
7476 fixP
= fix_new_exp (fragP
, 0, 0, &exp
, 0, BFD_RELOC_NDS32_RELAX_ENTRY
);
7477 fixP
->fx_no_overflow
= 1;
7480 /* Analysis relax hint and insert suitable relocation pattern. */
7483 nds32_elf_analysis_relax_hint (void)
7485 htab_traverse_noresize (nds32_hint_hash
,
7486 nds32_elf_append_relax_relocs_traverse
, NULL
);
7490 nds32_elf_insert_final_frag (void)
7492 struct frchain
*frchainP
;
7499 for (s
= stdoutput
->sections
; s
; s
= s
->next
)
7501 segment_info_type
*seginfo
= seg_info (s
);
7505 for (frchainP
= seginfo
->frchainP
; frchainP
!= NULL
;
7506 frchainP
= frchainP
->frch_next
)
7508 subseg_set (s
, frchainP
->frch_subseg
);
7510 if (subseg_text_p (now_seg
))
7513 frag_var (rs_machine_dependent
, 2, /* Max size. */
7514 0, /* VAR is un-used. */ 0, NULL
, 0, NULL
);
7515 fragP
->tc_frag_data
.flag
|= NDS32_FRAG_FINAL
;
7524 nds32_elf_insert_final_frag ();
7525 nds32_elf_analysis_relax_hint ();
7526 bfd_map_over_sections (stdoutput
, nds32_insert_leb128_fixes
, NULL
);
7529 /* Implement md_allow_local_subtract. */
7532 nds32_allow_local_subtract (expressionS
*expr_l ATTRIBUTE_UNUSED
,
7533 expressionS
*expr_r ATTRIBUTE_UNUSED
,
7534 segT sec ATTRIBUTE_UNUSED
)
7536 /* Don't allow any subtraction, because relax may change the code. */
7541 nds32_pcrel_from_section (fixS
*fixP
, segT sec ATTRIBUTE_UNUSED
)
7543 if (fixP
->fx_addsy
== NULL
|| !S_IS_DEFINED (fixP
->fx_addsy
)
7544 || S_IS_EXTERNAL (fixP
->fx_addsy
) || S_IS_WEAK (fixP
->fx_addsy
))
7546 /* Let linker resolve undefined symbols. */
7550 return fixP
->fx_frag
->fr_address
+ fixP
->fx_where
;
7553 /* md_post_relax_hook ()
7554 Insert relax entry relocation into sections. */
7557 nds32_post_relax_hook (void)
7559 bfd_map_over_sections (stdoutput
, nds32_insert_relax_entry
, NULL
);
7562 /* tc_fix_adjustable ()
7564 Return whether this symbol (fixup) can be replaced with
7568 nds32_fix_adjustable (fixS
*fixP
)
7570 switch (fixP
->fx_r_type
)
7572 case BFD_RELOC_NDS32_WORD_9_PCREL
:
7573 case BFD_RELOC_NDS32_9_PCREL
:
7574 case BFD_RELOC_NDS32_15_PCREL
:
7575 case BFD_RELOC_NDS32_17_PCREL
:
7576 case BFD_RELOC_NDS32_25_PCREL
:
7577 case BFD_RELOC_NDS32_HI20
:
7578 case BFD_RELOC_NDS32_LO12S0
:
7582 case BFD_RELOC_NDS32_PTR
:
7583 case BFD_RELOC_NDS32_LONGCALL4
:
7584 case BFD_RELOC_NDS32_LONGCALL5
:
7585 case BFD_RELOC_NDS32_LONGCALL6
:
7586 case BFD_RELOC_NDS32_LONGJUMP4
:
7587 case BFD_RELOC_NDS32_LONGJUMP5
:
7588 case BFD_RELOC_NDS32_LONGJUMP6
:
7589 case BFD_RELOC_NDS32_LONGJUMP7
:
7596 /* elf_tc_final_processing */
7599 elf_nds32_final_processing (void)
7601 /* An FPU_COM instruction is found without previous non-FPU_COM
7604 && !(nds32_elf_flags
& (E_NDS32_HAS_FPU_INST
| E_NDS32_HAS_FPU_DP_INST
)))
7606 /* Since only FPU_COM instructions are used and no other FPU instructions
7607 are used. The nds32_elf_flags will be decided by the enabled options
7608 by command line or default configuration. */
7609 if (nds32_fpu_dp_ext
|| nds32_fpu_sp_ext
)
7611 nds32_elf_flags
|= nds32_fpu_dp_ext
? E_NDS32_HAS_FPU_DP_INST
: 0;
7612 nds32_elf_flags
|= nds32_fpu_sp_ext
? E_NDS32_HAS_FPU_INST
: 0;
7616 /* Should never here. */
7617 as_bad (_("Used FPU instructions requires enabling FPU extension"));
7621 if (nds32_elf_flags
& (E_NDS32_HAS_FPU_INST
| E_NDS32_HAS_FPU_DP_INST
))
7623 /* Single/double FPU has been used, set FPU register config. */
7624 /* We did not check the actual number of register used. We may
7625 want to do it while assemble. */
7626 nds32_elf_flags
&= ~E_NDS32_FPU_REG_CONF
;
7627 nds32_elf_flags
|= (nds32_freg
<< E_NDS32_FPU_REG_CONF_SHIFT
);
7631 nds32_elf_flags
|= E_NDS32_HAS_PIC
;
7634 nds32_elf_flags
|= E_NDS32_HAS_REDUCED_REGS
;
7636 nds32_elf_flags
|= (E_NDS32_ELF_VER_1_4
| nds32_abi
);
7637 elf_elfheader (stdoutput
)->e_flags
|= nds32_elf_flags
;
7640 /* Implement md_apply_fix. Apply the fix-up or transform the fix-up for
7641 later relocation generation. */
7644 nds32_apply_fix (fixS
*fixP
, valueT
*valP
, segT seg ATTRIBUTE_UNUSED
)
7646 char *where
= fixP
->fx_frag
->fr_literal
+ fixP
->fx_where
;
7647 bfd_vma value
= *valP
;
7649 if (fixP
->fx_r_type
< BFD_RELOC_UNUSED
7650 && fixP
->fx_r_type
> BFD_RELOC_NONE
7651 && fixP
->fx_r_type
!= BFD_RELOC_NDS32_DIFF_ULEB128
)
7653 /* In our old nds32 binutils, it must convert relocations which is
7654 generated by CGEN. However, it does not have to consider this anymore.
7655 In current, it only deal with data relocations which enum
7656 is smaller than BFD_RELOC_NONE and BFD_RELOC_NDS32_DIFF_ULEB128.
7657 It is believed that we can construct a better mechanism to
7658 deal with the whole relocation issue in nds32 target
7659 without using CGEN. */
7660 fixP
->fx_addnumber
= value
;
7661 fixP
->tc_fix_data
= NULL
;
7663 /* Transform specific relocations here for later relocation generation.
7664 Tag tls data for linker. */
7665 switch (fixP
->fx_r_type
)
7667 case BFD_RELOC_NDS32_DATA
:
7668 /* This reloc is obselete, we do not need it so far. */
7671 case BFD_RELOC_NDS32_TPOFF
:
7672 case BFD_RELOC_NDS32_TLS_LE_HI20
:
7673 case BFD_RELOC_NDS32_TLS_LE_LO12
:
7674 case BFD_RELOC_NDS32_TLS_LE_ADD
:
7675 case BFD_RELOC_NDS32_TLS_LE_LS
:
7676 case BFD_RELOC_NDS32_GOTTPOFF
:
7677 case BFD_RELOC_NDS32_TLS_IE_HI20
:
7678 case BFD_RELOC_NDS32_TLS_IE_LO12S2
:
7679 case BFD_RELOC_NDS32_TLS_DESC_HI20
:
7680 case BFD_RELOC_NDS32_TLS_DESC_LO12
:
7681 case BFD_RELOC_NDS32_TLS_IE_LO12
:
7682 case BFD_RELOC_NDS32_TLS_IEGP_HI20
:
7683 case BFD_RELOC_NDS32_TLS_IEGP_LO12
:
7684 case BFD_RELOC_NDS32_TLS_IEGP_LO12S2
:
7685 S_SET_THREAD_LOCAL (fixP
->fx_addsy
);
7693 if (fixP
->fx_addsy
== (symbolS
*) NULL
)
7696 if (fixP
->fx_subsy
!= (symbolS
*) NULL
)
7698 /* HOW DIFF RELOCATION WORKS.
7700 First of all, this relocation is used to calculate the distance
7701 between two symbols in the SAME section. It is used for jump-
7702 table, debug information, exception table, et al. Therefore,
7703 it is a unsigned positive value. It is NOT used for general-
7706 Consider this example, the distance between .LEND and .LBEGIN
7707 is stored at the address of foo.
7709 ---- >8 ---- >8 ---- >8 ---- >8 ----
7712 .word .LBEGIN - .LEND
7722 ---- 8< ---- 8< ---- 8< ---- 8< ----
7724 We use a single relocation entry for this expression.
7725 * The initial distance value is stored directly in that location
7726 specified by r_offset (i.e., foo in this example.)
7727 * The begin of the region, i.e., .LBEGIN, is specified by
7728 r_info/R_SYM and r_addend, e.g., .text + 0x32.
7729 * The end of region, i.e., .LEND, is represented by
7730 .LBEGIN + distance instead of .LEND, so we only need
7731 a single relocation entry instead of two.
7733 When an instruction is relaxed, we adjust the relocation entry
7734 depending on where the instruction locates. There are three
7735 cases, before, after and between the region.
7736 * between: Distance value is read from r_offset, adjusted and
7737 written back into r_offset.
7738 * before: Only r_addend is adjust.
7739 * after: We don't care about it.
7741 Hereby, there are some limitation.
7743 `(.LEND - 1) - .LBEGIN' and `(.LEND - .LBEGIN) - 1'
7744 are semantically different, and we cannot handle latter case
7747 The latter expression means subtracting 1 from the distance
7748 between .LEND and .LBEGIN. And the former expression means
7749 the distance between (.LEND - 1) and .LBEGIN.
7751 The nuance affects whether to adjust distance value when relax
7752 an instruction. In another words, whether the instruction
7753 locates in the region. Because we use a single relocation entry,
7754 there is no field left for .LEND and the subtrahend.
7756 Since GCC-4.5, GCC may produce debug information in such expression
7758 in order to describe register clobbering during an function-call.
7763 Check http://gcc.gnu.org/ml/gcc-patches/2009-06/msg01317.html
7766 value
-= S_GET_VALUE (fixP
->fx_subsy
);
7768 fixP
->fx_subsy
= NULL
;
7769 fixP
->fx_offset
-= value
;
7771 switch (fixP
->fx_r_type
)
7774 fixP
->fx_r_type
= BFD_RELOC_NDS32_DIFF8
;
7775 md_number_to_chars (where
, value
, 1);
7778 fixP
->fx_r_type
= BFD_RELOC_NDS32_DIFF16
;
7779 md_number_to_chars (where
, value
, 2);
7782 fixP
->fx_r_type
= BFD_RELOC_NDS32_DIFF32
;
7783 md_number_to_chars (where
, value
, 4);
7785 case BFD_RELOC_NDS32_DIFF_ULEB128
:
7786 /* cvt_frag_to_fill () has called output_leb128 () for us. */
7789 as_bad_subtract (fixP
);
7793 else if (fixP
->fx_done
)
7795 /* We're finished with this fixup. Install it because
7796 bfd_install_relocation won't be called to do it. */
7797 switch (fixP
->fx_r_type
)
7800 md_number_to_chars (where
, value
, 1);
7803 md_number_to_chars (where
, value
, 2);
7806 md_number_to_chars (where
, value
, 4);
7809 md_number_to_chars (where
, value
, 8);
7812 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
7813 _("Internal error: Unknown fixup type %d (`%s')"),
7815 bfd_get_reloc_code_name (fixP
->fx_r_type
));
7821 /* Implement tc_gen_reloc. Generate ELF relocation for a fix-up. */
7824 tc_gen_reloc (asection
*section ATTRIBUTE_UNUSED
, fixS
*fixP
)
7827 bfd_reloc_code_real_type code
;
7829 reloc
= XNEW (arelent
);
7831 reloc
->sym_ptr_ptr
= XNEW (asymbol
*);
7832 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixP
->fx_addsy
);
7833 reloc
->address
= fixP
->fx_frag
->fr_address
+ fixP
->fx_where
;
7835 code
= fixP
->fx_r_type
;
7837 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
7838 if (reloc
->howto
== (reloc_howto_type
*) NULL
)
7840 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
7841 _("internal error: can't export reloc type %d (`%s')"),
7842 fixP
->fx_r_type
, bfd_get_reloc_code_name (code
));
7846 /* Add relocation handling here. */
7848 switch (fixP
->fx_r_type
)
7851 /* In general, addend of a relocation is the offset to the
7852 associated symbol. */
7853 reloc
->addend
= fixP
->fx_offset
;
7856 case BFD_RELOC_NDS32_DATA
:
7857 /* Prevent linker from optimizing data in text sections.
7858 For example, jump table. */
7859 reloc
->addend
= fixP
->fx_size
;
7866 static struct suffix_name suffix_table
[] =
7868 {"GOTOFF", BFD_RELOC_NDS32_GOTOFF
},
7869 {"GOT", BFD_RELOC_NDS32_GOT20
},
7870 {"TPOFF", BFD_RELOC_NDS32_TPOFF
},
7871 {"PLT", BFD_RELOC_NDS32_25_PLTREL
},
7872 {"GOTTPOFF", BFD_RELOC_NDS32_GOTTPOFF
},
7873 {"TLSDESC", BFD_RELOC_NDS32_TLS_DESC
},
7876 /* Implement md_parse_name. */
7879 nds32_parse_name (char const *name
, expressionS
*exprP
,
7880 enum expr_mode mode ATTRIBUTE_UNUSED
,
7881 char *nextcharP ATTRIBUTE_UNUSED
)
7885 exprP
->X_op_symbol
= NULL
;
7886 exprP
->X_md
= BFD_RELOC_UNUSED
;
7888 exprP
->X_add_symbol
= symbol_find_or_make (name
);
7889 exprP
->X_op
= O_symbol
;
7890 exprP
->X_add_number
= 0;
7892 /* Check the special name if a symbol. */
7893 segment
= S_GET_SEGMENT (exprP
->X_add_symbol
);
7894 if ((segment
!= undefined_section
) && (*nextcharP
!= '@'))
7897 if (strcmp (name
, GOT_NAME
) == 0 && *nextcharP
!= '@')
7899 /* Set for _GOT_OFFSET_TABLE_. */
7900 exprP
->X_md
= BFD_RELOC_NDS32_GOTPC20
;
7902 else if (*nextcharP
== '@')
7906 for (i
= 0; i
< ARRAY_SIZE (suffix_table
); i
++)
7908 next
= input_line_pointer
+ 1 + strlen (suffix_table
[i
].suffix
);
7909 if (strncasecmp (input_line_pointer
+ 1, suffix_table
[i
].suffix
,
7910 strlen (suffix_table
[i
].suffix
)) == 0
7911 && !is_part_of_name (*next
))
7913 exprP
->X_md
= suffix_table
[i
].reloc
;
7914 *input_line_pointer
= *nextcharP
;
7915 input_line_pointer
= next
;
7916 *nextcharP
= *input_line_pointer
;
7917 *input_line_pointer
= '\0';
7926 /* Implement tc_regname_to_dw2regnum. */
7929 tc_nds32_regname_to_dw2regnum (char *regname
)
7931 struct nds32_keyword
*sym
= str_hash_find (nds32_gprs_hash
, regname
);
7940 tc_nds32_frame_initial_instructions (void)
7943 /* Default cfa is register-31/sp. */
7944 cfi_add_CFA_def_cfa (31, 0);