1 /* tc-nds32.c -- Assemble for the nds32
2 Copyright (C) 2012-2022 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 s
= input_line_pointer
;
2523 input_line_pointer
= tmp
; /* Restore line pointer. */
2525 return s
; /* Return pointer to where parsing stopped. */
2529 nds32_start_line_hook (void)
2537 typedef void (*nds32_pseudo_opcode_func
) (int argc
, char *argv
[], unsigned int pv
);
2538 struct nds32_pseudo_opcode
2542 nds32_pseudo_opcode_func proc
;
2543 unsigned int pseudo_val
;
2545 /* Some instructions are not pseudo opcode, but they might still be
2546 expanded or changed with other instruction combination for some
2547 conditions. We also apply this structure to assist such work.
2549 For example, if the distance of branch target '.L0' is larger than
2556 will be transformed into:
2562 However, sometimes we do not want assembler to do such changes
2563 because compiler knows how to generate corresponding instruction sequence.
2564 Use this field to indicate that this opcode is also a physical instruction.
2565 If the flag 'verbatim' is nozero and this opcode
2566 is a physical instruction, we should not expand it. */
2569 #define PV_DONT_CARE 0
2571 static htab_t nds32_pseudo_opcode_hash
= NULL
;
2574 builtin_isreg (const char *s
, const char *x ATTRIBUTE_UNUSED
)
2576 if (s
[0] == '$' && str_hash_find (nds32_gprs_hash
, (s
+ 1)))
2582 builtin_regnum (const char *s
, const char *x ATTRIBUTE_UNUSED
)
2584 struct nds32_keyword
*k
;
2588 k
= str_hash_find (nds32_gprs_hash
, s
);
2597 builtin_addend (const char *s
, char *x ATTRIBUTE_UNUSED
)
2599 const char *ptr
= s
;
2601 while (*ptr
!= '+' && *ptr
!= '-' && *ptr
)
2607 return strtol (ptr
, NULL
, 0);
2611 md_assemblef (const char *format
, ...)
2613 /* FIXME: hope this is long enough. */
2618 va_start (ap
, format
);
2619 r
= vsnprintf (line
, sizeof (line
), format
, ap
);
2622 gas_assert (r
< sizeof (line
));
2625 /* Some prototypes here, since some op may use another op. */
2626 static void do_pseudo_li_internal (const char *rt
, int imm32s
);
2627 static void do_pseudo_move_reg_internal (char *dst
, char *src
);
2630 do_pseudo_b (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2631 unsigned int pv ATTRIBUTE_UNUSED
)
2633 char *arg_label
= argv
[0];
2638 md_assemblef ("sethi $ta,hi20(%s)", arg_label
);
2639 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label
);
2640 md_assemble ((char *) "add $ta,$ta,$gp");
2641 md_assemble ((char *) "jr $ta");
2645 md_assemblef ("j %s", arg_label
);
2651 do_pseudo_bal (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2652 unsigned int pv ATTRIBUTE_UNUSED
)
2654 char *arg_label
= argv
[0];
2656 /* bal|call label */
2659 md_assemblef ("sethi $ta,hi20(%s)", arg_label
);
2660 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label
);
2661 md_assemble ((char *) "add $ta,$ta,$gp");
2662 md_assemble ((char *) "jral $ta");
2666 md_assemblef ("jal %s", arg_label
);
2672 do_pseudo_bge (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2673 unsigned int pv ATTRIBUTE_UNUSED
)
2675 /* rt5, ra5, label */
2676 md_assemblef ("slt $ta,%s,%s", argv
[0], argv
[1]);
2677 md_assemblef ("beqz $ta,%s", argv
[2]);
2681 do_pseudo_bges (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2682 unsigned int pv ATTRIBUTE_UNUSED
)
2684 /* rt5, ra5, label */
2685 md_assemblef ("slts $ta,%s,%s", argv
[0], argv
[1]);
2686 md_assemblef ("beqz $ta,%s", argv
[2]);
2690 do_pseudo_bgt (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2691 unsigned int pv ATTRIBUTE_UNUSED
)
2693 /* bgt rt5, ra5, label */
2694 md_assemblef ("slt $ta,%s,%s", argv
[1], argv
[0]);
2695 md_assemblef ("bnez $ta,%s", argv
[2]);
2699 do_pseudo_bgts (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2700 unsigned int pv ATTRIBUTE_UNUSED
)
2702 /* bgt rt5, ra5, label */
2703 md_assemblef ("slts $ta,%s,%s", argv
[1], argv
[0]);
2704 md_assemblef ("bnez $ta,%s", argv
[2]);
2708 do_pseudo_ble (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2709 unsigned int pv ATTRIBUTE_UNUSED
)
2711 /* bgt rt5, ra5, label */
2712 md_assemblef ("slt $ta,%s,%s", argv
[1], argv
[0]);
2713 md_assemblef ("beqz $ta,%s", argv
[2]);
2717 do_pseudo_bles (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2718 unsigned int pv ATTRIBUTE_UNUSED
)
2720 /* bgt rt5, ra5, label */
2721 md_assemblef ("slts $ta,%s,%s", argv
[1], argv
[0]);
2722 md_assemblef ("beqz $ta,%s", argv
[2]);
2726 do_pseudo_blt (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2727 unsigned int pv ATTRIBUTE_UNUSED
)
2729 /* rt5, ra5, label */
2730 md_assemblef ("slt $ta,%s,%s", argv
[0], argv
[1]);
2731 md_assemblef ("bnez $ta,%s", argv
[2]);
2735 do_pseudo_blts (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2736 unsigned int pv ATTRIBUTE_UNUSED
)
2738 /* rt5, ra5, label */
2739 md_assemblef ("slts $ta,%s,%s", argv
[0], argv
[1]);
2740 md_assemblef ("bnez $ta,%s", argv
[2]);
2744 do_pseudo_br (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2745 unsigned int pv ATTRIBUTE_UNUSED
)
2747 md_assemblef ("jr %s", argv
[0]);
2751 do_pseudo_bral (int argc
, char *argv
[],
2752 unsigned int pv ATTRIBUTE_UNUSED
)
2755 md_assemblef ("jral $lp,%s", argv
[0]);
2757 md_assemblef ("jral %s,%s", argv
[0], argv
[1]);
2761 do_pseudo_la_internal (const char *arg_reg
, char *arg_label
,
2766 parse_expression (arg_label
, &exp
);
2767 if (exp
.X_op
!= O_symbol
)
2769 as_bad (_("la must use with symbol. '%s'"), line
);
2775 if (!nds32_pic
&& !strstr (arg_label
, "@"))
2777 md_assemblef ("sethi %s,hi20(%s)", arg_reg
, arg_label
);
2778 md_assemblef ("ori %s,%s,lo12(%s)", arg_reg
, arg_reg
, arg_label
);
2780 else if (strstr (arg_label
, "@TPOFF"))
2782 /* la $rt, sym@TPOFF */
2783 md_assemblef ("sethi $ta,hi20(%s)", arg_label
);
2784 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label
);
2785 md_assemblef ("add %s,$ta,%s", arg_reg
, TLS_REG
);
2787 else if (strstr(arg_label
, "@GOTTPOFF"))
2789 /* la $rt, sym@GOTTPOFF*/
2790 md_assemblef ("sethi $ta,hi20(%s)", arg_label
);
2791 md_assemblef ("lwi $ta,[$ta+lo12(%s)]", arg_label
);
2792 md_assemblef ("add %s,$ta,%s", arg_reg
, TLS_REG
);
2794 else if (nds32_pic
&& ((strstr (arg_label
, "@PLT")
2795 || strstr (arg_label
, "@GOTOFF"))))
2797 md_assemblef ("sethi $ta,hi20(%s)", arg_label
);
2798 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label
);
2799 md_assemblef ("add %s,$ta,$gp", arg_reg
);
2801 else if (nds32_pic
&& strstr (arg_label
, "@GOT"))
2803 long addend
= builtin_addend (arg_label
, NULL
);
2805 md_assemblef ("sethi $ta,hi20(%s)", arg_label
);
2806 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label
);
2807 md_assemblef ("lw %s,[$gp+$ta]", arg_reg
);
2810 if (addend
< 0x4000 && addend
>= -0x4000)
2812 md_assemblef ("addi %s,%s,%d", arg_reg
, arg_reg
, addend
);
2816 do_pseudo_li_internal ("$ta", addend
);
2817 md_assemblef ("add %s,$ta,%s", arg_reg
, arg_reg
);
2822 as_bad (_("need PIC qualifier with symbol. '%s'"), line
);
2827 do_pseudo_la (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2828 unsigned int pv ATTRIBUTE_UNUSED
)
2830 do_pseudo_la_internal (argv
[0], argv
[1], argv
[argc
]);
2834 do_pseudo_li_internal (const char *rt
, int imm32s
)
2836 if (enable_16bit
&& imm32s
<= 0xf && imm32s
>= -0x10)
2837 md_assemblef ("movi55 %s,%d", rt
, imm32s
);
2838 else if (imm32s
<= 0x7ffff && imm32s
>= -0x80000)
2839 md_assemblef ("movi %s,%d", rt
, imm32s
);
2840 else if ((imm32s
& 0xfff) == 0)
2841 md_assemblef ("sethi %s,hi20(%d)", rt
, imm32s
);
2844 md_assemblef ("sethi %s,hi20(%d)", rt
, imm32s
);
2845 md_assemblef ("ori %s,%s,lo12(%d)", rt
, rt
, imm32s
);
2850 do_pseudo_li (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2851 unsigned int pv ATTRIBUTE_UNUSED
)
2853 /* Validate argv[1] for constant expression. */
2856 parse_expression (argv
[1], &exp
);
2857 if (exp
.X_op
!= O_constant
)
2859 as_bad (_("Operand is not a constant. `%s'"), argv
[argc
]);
2863 do_pseudo_li_internal (argv
[0], exp
.X_add_number
);
2867 do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2872 const char *sign
= "";
2874 /* Prepare arguments for various load/store. */
2875 sign
= (pv
& 0x10) ? "s" : "";
2876 ls
= (pv
& 0x80000000) ? 's' : 'l';
2879 case 0: size
= 'b'; break;
2880 case 1: size
= 'h'; break;
2881 case 2: size
= 'w'; break;
2884 if (ls
== 's' || size
== 'w')
2887 if (builtin_isreg (argv
[1], NULL
))
2890 md_assemblef ("%c%ci %s,[%s]", ls
, size
, argv
[0], argv
[1]);
2892 else if (!nds32_pic
)
2895 if (strstr (argv
[1], "@TPOFF"))
2897 /* ls.w $rt, sym@TPOFF */
2898 md_assemblef ("sethi $ta,hi20(%s)", argv
[1]);
2899 md_assemblef ("ori $ta,$ta,lo12(%s)", argv
[1]);
2900 md_assemblef ("%c%c%s %s,[$ta+%s]", ls
, size
, sign
, argv
[0], TLS_REG
);
2902 else if (strstr (argv
[1], "@GOTTPOFF"))
2904 /* ls.w $rt, sym@GOTTPOFF */
2905 md_assemblef ("sethi $ta,hi20(%s)", argv
[1]);
2906 md_assemblef ("lwi $ta,[$ta+lo12(%s)]", argv
[1]);
2907 md_assemblef ("%c%c%s %s,[$ta+%s]", ls
, size
, sign
, argv
[0], TLS_REG
);
2912 md_assemblef ("sethi $ta,hi20(%s)", argv
[1]);
2913 md_assemblef ("%c%c%si %s,[$ta+lo12(%s)]", ls
, size
, sign
, argv
[0], argv
[1]);
2921 if (strstr (argv
[1], "@GOTOFF"))
2924 md_assemblef ("sethi $ta,hi20(%s)", argv
[1]);
2925 md_assemblef ("ori $ta,$ta,lo12(%s)", argv
[1]);
2926 md_assemblef ("%c%c%s %s,[$ta+$gp]", ls
, size
, sign
, argv
[0]);
2928 else if (strstr (argv
[1], "@GOT"))
2930 long addend
= builtin_addend (argv
[1], NULL
);
2932 md_assemblef ("sethi $ta,hi20(%s)", argv
[1]);
2933 md_assemblef ("ori $ta,$ta,lo12(%s)", argv
[1]);
2934 md_assemble ((char *) "lw $ta,[$gp+$ta]"); /* Load address word. */
2935 if (addend
< 0x10000 && addend
>= -0x10000)
2937 md_assemblef ("%c%c%si %s,[$ta+(%d)]", ls
, size
, sign
, argv
[0], addend
);
2942 do_pseudo_li_internal (argv
[0], addend
);
2943 md_assemblef ("%c%c%s %s,[$ta+%s]", ls
, size
, sign
, argv
[0], argv
[0]);
2948 as_bad (_("needs @GOT or @GOTOFF. %s"), argv
[argc
]);
2955 do_pseudo_ls_bhwp (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2958 char *arg_rt
= argv
[0];
2959 char *arg_label
= argv
[1];
2960 char *arg_inc
= argv
[2];
2963 const char *sign
= "";
2965 /* Prepare arguments for various load/store. */
2966 sign
= (pv
& 0x10) ? "s" : "";
2967 ls
= (pv
& 0x80000000) ? 's' : 'l';
2970 case 0: size
= 'b'; break;
2971 case 1: size
= 'h'; break;
2972 case 2: size
= 'w'; break;
2975 if (ls
== 's' || size
== 'w')
2978 do_pseudo_la_internal ("$ta", arg_label
, argv
[argc
]);
2979 md_assemblef ("%c%c%si.bi %s,[$ta],%s", ls
, size
, sign
, arg_rt
, arg_inc
);
2983 do_pseudo_ls_bhwpc (int argc ATTRIBUTE_UNUSED
, char *argv
[],
2986 char *arg_rt
= argv
[0];
2987 char *arg_inc
= argv
[1];
2990 const char *sign
= "";
2992 /* Prepare arguments for various load/store. */
2993 sign
= (pv
& 0x10) ? "s" : "";
2994 ls
= (pv
& 0x80000000) ? 's' : 'l';
2997 case 0: size
= 'b'; break;
2998 case 1: size
= 'h'; break;
2999 case 2: size
= 'w'; break;
3002 if (ls
== 's' || size
== 'w')
3005 md_assemblef ("%c%c%si.bi %s,[$ta],%s", ls
, size
, sign
, arg_rt
, arg_inc
);
3009 do_pseudo_ls_bhwi (int argc ATTRIBUTE_UNUSED
, char *argv
[],
3014 const char *sign
= "";
3016 /* Prepare arguments for various load/store. */
3017 sign
= (pv
& 0x10) ? "s" : "";
3018 ls
= (pv
& 0x80000000) ? 's' : 'l';
3021 case 0: size
= 'b'; break;
3022 case 1: size
= 'h'; break;
3023 case 2: size
= 'w'; break;
3026 if (ls
== 's' || size
== 'w')
3029 md_assemblef ("%c%c%si.bi %s,%s,%s",
3030 ls
, size
, sign
, argv
[0], argv
[1], argv
[2]);
3034 do_pseudo_move_reg_internal (char *dst
, char *src
)
3037 md_assemblef ("mov55 %s,%s", dst
, src
);
3039 md_assemblef ("ori %s,%s,0", dst
, src
);
3043 do_pseudo_move (int argc ATTRIBUTE_UNUSED
, char *argv
[],
3044 unsigned int pv ATTRIBUTE_UNUSED
)
3048 if (builtin_isreg (argv
[1], NULL
))
3049 do_pseudo_move_reg_internal (argv
[0], argv
[1]);
3052 parse_expression (argv
[1], &exp
);
3053 if (exp
.X_op
== O_constant
)
3054 /* move $rt, imm -> li $rt, imm */
3055 do_pseudo_li_internal (argv
[0], exp
.X_add_number
);
3057 /* l.w $rt, var -> l.w $rt, var */
3058 do_pseudo_ls_bhw (argc
, argv
, 2);
3063 do_pseudo_neg (int argc ATTRIBUTE_UNUSED
, char *argv
[],
3064 unsigned int pv ATTRIBUTE_UNUSED
)
3066 /* Instead of "subri". */
3067 md_assemblef ("subri %s,%s,0", argv
[0], argv
[1]);
3071 do_pseudo_not (int argc ATTRIBUTE_UNUSED
, char *argv
[],
3072 unsigned int pv ATTRIBUTE_UNUSED
)
3074 md_assemblef ("nor %s,%s,%s", argv
[0], argv
[1], argv
[1]);
3078 do_pseudo_pushpopm (int argc
, char *argv
[],
3079 unsigned int pv ATTRIBUTE_UNUSED
)
3081 /* posh/pop $ra, $rb */
3082 /* SMW.{b | a}{i | d}{m?} Rb, [Ra], Re, Enable4 */
3083 int rb
, re
, ra
, en4
;
3085 const char *opc
= "pushpopm";
3088 as_bad ("'pushm/popm $ra5, $rb5, $label' is deprecated. "
3089 "Only 'pushm/popm $ra5' is supported now. %s", argv
[argc
]);
3091 as_bad ("'pushm/popm $ra5, $rb5'. %s\n", argv
[argc
]);
3093 if (strstr (argv
[argc
], "pop") == argv
[argc
])
3095 else if (strstr (argv
[argc
], "push") == argv
[argc
])
3098 as_fatal ("nds32-as internal error. %s", argv
[argc
]);
3100 rb
= builtin_regnum (argv
[0], NULL
);
3101 re
= builtin_regnum (argv
[1], NULL
);
3105 as_warn ("$rb should not be smaller than $ra. %s", argv
[argc
]);
3106 /* Swap to right order. */
3112 /* Build enable4 mask. */
3114 if (re
>= 28 || rb
>= 28)
3116 for (i
= (rb
>= 28? rb
: 28); i
<= re
; i
++)
3117 en4
|= 1 << (3 - (i
- 28));
3120 /* Adjust $re, $rb. */
3123 else if (nds32_gpr16
!= 1 && re
>= 28)
3126 /* Reduce register. */
3127 if (nds32_gpr16
&& re
> 10 && !(rb
== 31 && re
== 31))
3129 if (re
>= 15 && strstr (opc
, "smw") != NULL
)
3130 md_assemblef ("%s $r15,[$sp],$r15,%d", opc
, en4
);
3132 md_assemblef ("%s $r%d,[$sp],$r10, 0x0", opc
, rb
);
3133 if (re
>= 15 && strstr (opc
, "lmw") != NULL
)
3134 md_assemblef ("%s $r15,[$sp],$r15,%d", opc
, en4
);
3137 md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc
, rb
, re
, en4
);
3141 do_pseudo_pushpop (int argc
, char *argv
[],
3142 unsigned int pv ATTRIBUTE_UNUSED
)
3144 /* push/pop $ra5, $label=$sp */
3148 as_bad ("'push/pop $ra5, rb5' is deprecated. "
3149 "Only 'push/pop $ra5' is supported now. %s", argv
[argc
]);
3153 argvm
[2] = argv
[argc
];
3154 do_pseudo_pushpopm (2, argvm
, PV_DONT_CARE
);
3158 do_pseudo_v3push (int argc ATTRIBUTE_UNUSED
, char *argv
[],
3159 unsigned int pv ATTRIBUTE_UNUSED
)
3161 md_assemblef ("push25 %s,%s", argv
[0], argv
[1]);
3165 do_pseudo_v3pop (int argc ATTRIBUTE_UNUSED
, char *argv
[],
3166 unsigned int pv ATTRIBUTE_UNUSED
)
3168 md_assemblef ("pop25 %s,%s", argv
[0], argv
[1]);
3171 /* pv == 0, parsing "push.s" pseudo instruction operands.
3172 pv != 0, parsing "pop.s" pseudo instruction operands. */
3175 do_pseudo_pushpop_stack (int argc
, char *argv
[],
3178 /* push.s Rb,Re,{$fp $gp $lp $sp} ==> smw.adm Rb,[$sp],Re,Eable4 */
3179 /* pop.s Rb,Re,{$fp $gp $lp $sp} ==> lmw.bim Rb,[$sp],Re,Eable4 */
3184 const char *opc
= (pv
== 0) ? "smw.adm" : "lmw.bim";
3190 /* argc=1, operands pattern: { $fp $gp $lp $sp } */
3192 /* Set register number Rb = Re = $sp = $r31. */
3195 else if (argc
== 2 || argc
== 3)
3197 /* argc=2, operands pattern: Rb, Re */
3198 /* argc=3, operands pattern: Rb, Re, { $fp $gp $lp $sp } */
3200 /* Get register number in integer. */
3201 rb
= builtin_regnum (argv
[0], NULL
);
3202 re
= builtin_regnum (argv
[1], NULL
);
3204 /* Rb should be equal/less than Re. */
3206 as_bad ("The first operand (%s) should be equal to or smaller than "
3207 "second operand (%s).", argv
[0], argv
[1]);
3209 /* forbid using $fp|$gp|$lp|$sp in Rb or Re
3212 as_bad ("Cannot use $fp, $gp, $lp, or $sp at first operand !!");
3214 as_bad ("Cannot use $fp, $gp, $lp, or $sp at second operand !!");
3218 as_bad ("Invalid operands pattern !!");
3221 /* Build Enable4 mask. */
3222 /* Using last_arg_index for argc=1|2|3 is safe, because $fp, $gp, $lp,
3223 and $sp only appear in argc=1 or argc=3 if argc=2, en4 remains 0,
3224 which is also valid for code generation. */
3226 last_arg_index
= argc
- 1;
3227 if (strstr (argv
[last_arg_index
], "$fp"))
3229 if (strstr (argv
[last_arg_index
], "$gp"))
3231 if (strstr (argv
[last_arg_index
], "$lp"))
3233 if (strstr (argv
[last_arg_index
], "$sp"))
3236 md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc
, rb
, re
, en4
);
3240 do_pseudo_push_bhwd (int argc ATTRIBUTE_UNUSED
, char *argv
[],
3241 unsigned int pv ATTRIBUTE_UNUSED
)
3244 /* If users omit push location, use $sp as default value. */
3245 char location
[8] = "$sp"; /* 8 is enough for register name. */
3249 case 0: size
= 'b'; break;
3250 case 1: size
= 'h'; break;
3251 case 2: size
= 'w'; break;
3252 case 3: size
= 'w'; break;
3257 strncpy (location
, argv
[1], sizeof (location
) - 1);
3258 location
[sizeof (location
) - 1] = '\0';
3261 md_assemblef ("l.%c $ta,%s", size
, argv
[0]);
3262 md_assemblef ("smw.adm $ta,[%s],$ta", location
);
3264 if ((pv
& 0x3) == 0x3) /* double-word */
3266 md_assemblef ("l.w $ta,%s+4", argv
[0]);
3267 md_assemblef ("smw.adm $ta,[%s],$ta", location
);
3272 do_pseudo_pop_bhwd (int argc ATTRIBUTE_UNUSED
, char *argv
[],
3273 unsigned int pv ATTRIBUTE_UNUSED
)
3276 /* If users omit pop location, use $sp as default value. */
3277 char location
[8] = "$sp"; /* 8 is enough for register name. */
3281 case 0: size
= 'b'; break;
3282 case 1: size
= 'h'; break;
3283 case 2: size
= 'w'; break;
3284 case 3: size
= 'w'; break;
3289 strncpy (location
, argv
[2], sizeof (location
) - 1);
3290 location
[sizeof (location
) - 1] = '\0';
3293 if ((pv
& 0x3) == 0x3) /* double-word */
3295 md_assemblef ("lmw.bim %s,[%s],%s", argv
[1], location
, argv
[1]);
3296 md_assemblef ("s.w %s,%s+4", argv
[1], argv
[0]);
3299 md_assemblef ("lmw.bim %s,[%s],%s", argv
[1], location
, argv
[1]);
3300 md_assemblef ("s.%c %s,%s", size
, argv
[1], argv
[0]);
3304 do_pseudo_pusha (int argc ATTRIBUTE_UNUSED
, char *argv
[],
3305 unsigned int pv ATTRIBUTE_UNUSED
)
3307 /* If users omit push location, use $sp as default value. */
3308 char location
[8] = "$sp"; /* 8 is enough for register name. */
3312 strncpy (location
, argv
[1], sizeof (location
) - 1);
3313 location
[sizeof (location
) - 1] = '\0';
3316 md_assemblef ("la $ta,%s", argv
[0]);
3317 md_assemblef ("smw.adm $ta,[%s],$ta", location
);
3321 do_pseudo_pushi (int argc ATTRIBUTE_UNUSED
, char *argv
[],
3322 unsigned int pv ATTRIBUTE_UNUSED
)
3324 /* If users omit push location, use $sp as default value. */
3325 char location
[8] = "$sp"; /* 8 is enough for register name. */
3329 strncpy (location
, argv
[1], sizeof (location
) - 1);
3330 location
[sizeof (location
) - 1] = '\0';
3333 md_assemblef ("li $ta,%s", argv
[0]);
3334 md_assemblef ("smw.adm $ta,[%s],$ta", location
);
3337 static struct nds32_pseudo_opcode nds32_pseudo_opcode_table
[] =
3339 {"b", 1, do_pseudo_b
, 0, 0},
3340 {"bal", 1, do_pseudo_bal
, 0, 0},
3342 {"bge", 3, do_pseudo_bge
, 0, 0},
3343 {"bges", 3, do_pseudo_bges
, 0, 0},
3345 {"bgt", 3, do_pseudo_bgt
, 0, 0},
3346 {"bgts", 3, do_pseudo_bgts
, 0, 0},
3348 {"ble", 3, do_pseudo_ble
, 0, 0},
3349 {"bles", 3, do_pseudo_bles
, 0, 0},
3351 {"blt", 3, do_pseudo_blt
, 0, 0},
3352 {"blts", 3, do_pseudo_blts
, 0, 0},
3354 {"br", 1, do_pseudo_br
, 0, 0},
3355 {"bral", 1, do_pseudo_bral
, 0, 0},
3357 {"call", 1, do_pseudo_bal
, 0, 0},
3359 {"la", 2, do_pseudo_la
, 0, 0},
3360 {"li", 2, do_pseudo_li
, 0, 0},
3362 {"l.b", 2, do_pseudo_ls_bhw
, 0, 0},
3363 {"l.h", 2, do_pseudo_ls_bhw
, 1, 0},
3364 {"l.w", 2, do_pseudo_ls_bhw
, 2, 0},
3365 {"l.bs", 2, do_pseudo_ls_bhw
, 0 | 0x10, 0},
3366 {"l.hs", 2, do_pseudo_ls_bhw
, 1 | 0x10, 0},
3367 {"s.b", 2, do_pseudo_ls_bhw
, 0 | 0x80000000, 0},
3368 {"s.h", 2, do_pseudo_ls_bhw
, 1 | 0x80000000, 0},
3369 {"s.w", 2, do_pseudo_ls_bhw
, 2 | 0x80000000, 0},
3371 {"l.bp", 3, do_pseudo_ls_bhwp
, 0, 0},
3372 {"l.bpc", 3, do_pseudo_ls_bhwpc
, 0, 0},
3373 {"l.hp", 3, do_pseudo_ls_bhwp
, 1, 0},
3374 {"l.hpc", 3, do_pseudo_ls_bhwpc
, 1, 0},
3375 {"l.wp", 3, do_pseudo_ls_bhwp
, 2, 0},
3376 {"l.wpc", 3, do_pseudo_ls_bhwpc
, 2, 0},
3377 {"l.bsp", 3, do_pseudo_ls_bhwp
, 0 | 0x10, 0},
3378 {"l.bspc", 3, do_pseudo_ls_bhwpc
, 0 | 0x10, 0},
3379 {"l.hsp", 3, do_pseudo_ls_bhwp
, 1 | 0x10, 0},
3380 {"l.hspc", 3, do_pseudo_ls_bhwpc
, 1 | 0x10, 0},
3381 {"s.bp", 3, do_pseudo_ls_bhwp
, 0 | 0x80000000, 0},
3382 {"s.bpc", 3, do_pseudo_ls_bhwpc
, 0 | 0x80000000, 0},
3383 {"s.hp", 3, do_pseudo_ls_bhwp
, 1 | 0x80000000, 0},
3384 {"s.hpc", 3, do_pseudo_ls_bhwpc
, 1 | 0x80000000, 0},
3385 {"s.wp", 3, do_pseudo_ls_bhwp
, 2 | 0x80000000, 0},
3386 {"s.wpc", 3, do_pseudo_ls_bhwpc
, 2 | 0x80000000, 0},
3387 {"s.bsp", 3, do_pseudo_ls_bhwp
, 0 | 0x80000000 | 0x10, 0},
3388 {"s.hsp", 3, do_pseudo_ls_bhwp
, 1 | 0x80000000 | 0x10, 0},
3390 {"lbi.p", 3, do_pseudo_ls_bhwi
, 0, 0},
3391 {"lhi.p", 3, do_pseudo_ls_bhwi
, 1, 0},
3392 {"lwi.p", 3, do_pseudo_ls_bhwi
, 2, 0},
3393 {"sbi.p", 3, do_pseudo_ls_bhwi
, 0 | 0x80000000, 0},
3394 {"shi.p", 3, do_pseudo_ls_bhwi
, 1 | 0x80000000, 0},
3395 {"swi.p", 3, do_pseudo_ls_bhwi
, 2 | 0x80000000, 0},
3396 {"lbsi.p", 3, do_pseudo_ls_bhwi
, 0 | 0x10, 0},
3397 {"lhsi.p", 3, do_pseudo_ls_bhwi
, 1 | 0x10, 0},
3398 {"lwsi.p", 3, do_pseudo_ls_bhwi
, 2 | 0x10, 0},
3400 {"move", 2, do_pseudo_move
, 0, 0},
3401 {"neg", 2, do_pseudo_neg
, 0, 0},
3402 {"not", 2, do_pseudo_not
, 0, 0},
3404 {"pop", 2, do_pseudo_pushpop
, 0, 0},
3405 {"push", 2, do_pseudo_pushpop
, 0, 0},
3406 {"popm", 2, do_pseudo_pushpopm
, 0, 0},
3407 {"pushm", 3, do_pseudo_pushpopm
, 0, 0},
3409 {"v3push", 2, do_pseudo_v3push
, 0, 0},
3410 {"v3pop", 2, do_pseudo_v3pop
, 0, 0},
3412 /* Support pseudo instructions of pushing/poping registers into/from stack
3413 push.s Rb, Re, { $fp $gp $lp $sp } ==> smw.adm Rb,[$sp],Re,Enable4
3414 pop.s Rb, Re, { $fp $gp $lp $sp } ==> lmw.bim Rb,[$sp],Re,Enable4 */
3415 { "push.s", 3, do_pseudo_pushpop_stack
, 0, 0 },
3416 { "pop.s", 3, do_pseudo_pushpop_stack
, 1, 0 },
3417 { "push.b", 2, do_pseudo_push_bhwd
, 0, 0 },
3418 { "push.h", 2, do_pseudo_push_bhwd
, 1, 0 },
3419 { "push.w", 2, do_pseudo_push_bhwd
, 2, 0 },
3420 { "push.d", 2, do_pseudo_push_bhwd
, 3, 0 },
3421 { "pop.b", 3, do_pseudo_pop_bhwd
, 0, 0 },
3422 { "pop.h", 3, do_pseudo_pop_bhwd
, 1, 0 },
3423 { "pop.w", 3, do_pseudo_pop_bhwd
, 2, 0 },
3424 { "pop.d", 3, do_pseudo_pop_bhwd
, 3, 0 },
3425 { "pusha", 2, do_pseudo_pusha
, 0, 0 },
3426 { "pushi", 2, do_pseudo_pushi
, 0, 0 },
3428 {NULL
, 0, NULL
, 0, 0}
3432 nds32_init_nds32_pseudo_opcodes (void)
3434 struct nds32_pseudo_opcode
*opcode
;
3436 nds32_pseudo_opcode_hash
= str_htab_create ();
3437 for (opcode
= nds32_pseudo_opcode_table
; opcode
->opcode
; opcode
++)
3438 if (str_hash_insert (nds32_pseudo_opcode_hash
, opcode
->opcode
, opcode
, 0))
3439 as_fatal (_("duplicate %s"), opcode
->opcode
);
3442 static struct nds32_pseudo_opcode
*
3443 nds32_lookup_pseudo_opcode (const char *str
)
3445 struct nds32_pseudo_opcode
*result
;
3448 /* (*op) is the first word of current source line (*str) */
3449 int maxlen
= strlen (str
);
3450 char *op
= xmalloc (maxlen
+ 1);
3452 for (i
= 0; i
< maxlen
; i
++)
3454 if (ISSPACE (op
[i
] = str
[i
]))
3459 result
= str_hash_find (nds32_pseudo_opcode_hash
, op
);
3465 nds32_pseudo_opcode_wrapper (char *line
, struct nds32_pseudo_opcode
*opcode
)
3468 char *argv
[8] = {NULL
};
3470 char *str
= xstrdup (line
);
3472 /* Parse arguments for opcode. */
3473 s
= str
+ strlen (opcode
->opcode
);
3478 /* Dummy comma to ease separate arguments as below. */
3484 if (argc
>= opcode
->argc
3485 || (argc
>= (int)ARRAY_SIZE (argv
) - 1))
3486 as_bad (_("Too many argument. `%s'"), line
);
3493 } while (s
[0] != '\0');
3495 /* Put the origin line for debugging. */
3497 opcode
->proc (argc
, argv
, opcode
->pseudo_val
);
3501 /* This function will be invoked from function `nds32_after_parse_args'.
3502 Thus, if the value of option has been set, keep the value the way it is. */
3505 nds32_parse_arch (const char *str
)
3507 static const struct nds32_arch
3518 {"v3m", ISA_V3M
, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_AABI
},
3519 {"v3j", ISA_V3
, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_AABI
},
3520 {"v3s", ISA_V3
, 0, 1, 0, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_V2FP_PLUS
},
3521 {"v3f", ISA_V3
, 0, 1, 1, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_V2FP_PLUS
},
3522 {"v3", ISA_V3
, 0, 0, 0, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_AABI
},
3523 {"v2j", ISA_V2
, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_AABI
},
3524 {"v2s", ISA_V2
, 0, 1, 0, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_V2FP_PLUS
},
3525 {"v2f", ISA_V2
, 0, 1, 1, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_V2FP_PLUS
},
3526 {"v2", ISA_V2
, 0, 0, 0, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_AABI
},
3530 for (i
= 0; i
< ARRAY_SIZE (archs
); i
++)
3532 if (strcmp (str
, archs
[i
].name
) != 0)
3535 /* The value `-1' represents this option has *NOT* been set. */
3536 nds32_baseline
= (-1 != nds32_baseline
) ? nds32_baseline
: archs
[i
].baseline
;
3537 nds32_gpr16
= (-1 != nds32_gpr16
) ? nds32_gpr16
: archs
[i
].reduced_reg
;
3538 nds32_fpu_sp_ext
= (-1 != nds32_fpu_sp_ext
) ? nds32_fpu_sp_ext
: archs
[i
].fpu_sp_ext
;
3539 nds32_fpu_dp_ext
= (-1 != nds32_fpu_dp_ext
) ? nds32_fpu_dp_ext
: archs
[i
].fpu_dp_ext
;
3540 nds32_freg
= (-1 != nds32_freg
) ? nds32_freg
: archs
[i
].fpu_freg
;
3541 nds32_abi
= (-1 != nds32_abi
) ? nds32_abi
: archs
[i
].abi
;
3546 /* Logic here rejects the input arch name. */
3547 as_bad (_("unknown arch name `%s'\n"), str
);
3552 /* This function parses "baseline" specified. */
3555 nds32_parse_baseline (const char *str
)
3557 if (strcmp (str
, "v3") == 0)
3558 nds32_baseline
= ISA_V3
;
3559 else if (strcmp (str
, "v3m") == 0)
3560 nds32_baseline
= ISA_V3M
;
3561 else if (strcmp (str
, "v2") == 0)
3562 nds32_baseline
= ISA_V2
;
3565 /* Logic here rejects the input baseline. */
3566 as_bad (_("unknown baseline `%s'\n"), str
);
3573 /* This function parses "fpu-freg" specified. */
3576 nds32_parse_freg (const char *str
)
3578 if (strcmp (str
, "2") == 0)
3579 nds32_freg
= E_NDS32_FPU_REG_32SP_16DP
;
3580 else if (strcmp (str
, "3") == 0)
3581 nds32_freg
= E_NDS32_FPU_REG_32SP_32DP
;
3582 else if (strcmp (str
, "1") == 0)
3583 nds32_freg
= E_NDS32_FPU_REG_16SP_8DP
;
3584 else if (strcmp (str
, "0") == 0)
3585 nds32_freg
= E_NDS32_FPU_REG_8SP_4DP
;
3588 /* Logic here rejects the input FPU configuration. */
3589 as_bad (_("unknown FPU configuration `%s'\n"), str
);
3596 /* This function parse "abi=" specified. */
3599 nds32_parse_abi (const char *str
)
3601 if (strcmp (str
, "v2") == 0)
3602 nds32_abi
= E_NDS_ABI_AABI
;
3604 else if (strcmp (str
, "v2fp") == 0)
3605 nds32_abi
= E_NDS_ABI_V2FP
;
3606 else if (strcmp (str
, "v1") == 0)
3607 nds32_abi
= E_NDS_ABI_V1
;
3608 else if (strcmp (str
,"v2fpp") == 0)
3609 nds32_abi
= E_NDS_ABI_V2FP_PLUS
;
3612 /* Logic here rejects the input abi version. */
3613 as_bad (_("unknown ABI version`%s'\n"), str
);
3620 /* This function turn on all extensions and instructions support. */
3623 nds32_all_ext (void)
3628 nds32_16bit_ext
= 1;
3630 nds32_perf_ext2
= 1;
3631 nds32_string_ext
= 1;
3632 nds32_audio_ext
= 1;
3634 nds32_fpu_sp_ext
= 1;
3635 nds32_fpu_dp_ext
= 1;
3638 /* Turn off reduced register. */
3644 /* GAS will call md_parse_option whenever getopt returns an unrecognized code,
3645 presumably indicating a special code value which appears in md_longopts.
3646 This function should return non-zero if it handled the option and zero
3647 otherwise. There is no need to print a message about an option not being
3648 recognized. This will be handled by the generic code. */
3651 nds32_parse_option (int c
, const char *arg
)
3653 struct nds32_parse_option_table
*coarse_tune
;
3654 struct nds32_set_option_table
*fine_tune
;
3655 const char *ptr_arg
= NULL
;
3659 case OPTION_OPTIMIZE
:
3661 optimize_for_space
= 0;
3663 case OPTION_OPTIMIZE_SPACE
:
3665 optimize_for_space
= 1;
3668 target_big_endian
= 1;
3671 target_big_endian
= 0;
3679 case OPTION_RELAX_FP_AS_GP_OFF
:
3680 nds32_relax_fp_as_gp
= 0;
3682 case OPTION_RELAX_B2BB_ON
:
3683 nds32_relax_b2bb
= 1;
3685 case OPTION_RELAX_ALL_OFF
:
3686 nds32_relax_all
= 0;
3689 /* Determination of which option table to search for to save time. */
3693 ptr_arg
= strchr (arg
, '=');
3697 /* Find the value after '='. */
3698 if (ptr_arg
!= NULL
)
3700 for (coarse_tune
= parse_opts
; coarse_tune
->name
!= NULL
; coarse_tune
++)
3702 if (strncmp (arg
, coarse_tune
->name
, (ptr_arg
- arg
)) == 0)
3704 coarse_tune
->func (ptr_arg
);
3713 /* Filter out the Disable option first. */
3714 if (startswith (arg
, "no-"))
3720 for (fine_tune
= toggle_opts
; fine_tune
->name
!= NULL
; fine_tune
++)
3722 if (strcmp (arg
, fine_tune
->name
) == 0)
3724 if (fine_tune
->var
!= NULL
)
3725 *fine_tune
->var
= (disable
) ? 0 : 1;
3730 /* Nothing match. */
3737 /* tc_check_label */
3740 nds32_check_label (symbolS
*label ATTRIBUTE_UNUSED
)
3742 /* The code used to create BB is move to frob_label.
3743 They should go there. */
3747 set_endian_little (int on
)
3749 target_big_endian
= !on
;
3752 /* These functions toggles the generation of 16-bit. First encounter signals
3753 the beginning of not generating 16-bit instructions and next encounter
3754 signals the restoring back to default behavior. */
3757 trigger_16bit (int trigger
)
3759 enable_16bit
= trigger
;
3762 static int backup_16bit_mode
;
3764 restore_16bit (int no_use ATTRIBUTE_UNUSED
)
3766 enable_16bit
= backup_16bit_mode
;
3770 off_16bit (int no_use ATTRIBUTE_UNUSED
)
3772 backup_16bit_mode
= enable_16bit
;
3776 /* Built-in segments for small object. */
3777 typedef struct nds32_seg_entryT
3784 nds32_seg_entry nds32_seg_table
[] =
3786 {NULL
, ".sdata_f", SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
| SEC_DATA
3787 | SEC_HAS_CONTENTS
| SEC_SMALL_DATA
},
3788 {NULL
, ".sdata_b", SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
| SEC_DATA
3789 | SEC_HAS_CONTENTS
| SEC_SMALL_DATA
},
3790 {NULL
, ".sdata_h", SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
| SEC_DATA
3791 | SEC_HAS_CONTENTS
| SEC_SMALL_DATA
},
3792 {NULL
, ".sdata_w", SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
| SEC_DATA
3793 | SEC_HAS_CONTENTS
| SEC_SMALL_DATA
},
3794 {NULL
, ".sdata_d", SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
| SEC_DATA
3795 | SEC_HAS_CONTENTS
| SEC_SMALL_DATA
},
3796 {NULL
, ".sbss_f", SEC_ALLOC
| SEC_SMALL_DATA
},
3797 {NULL
, ".sbss_b", SEC_ALLOC
| SEC_SMALL_DATA
},
3798 {NULL
, ".sbss_h", SEC_ALLOC
| SEC_SMALL_DATA
},
3799 {NULL
, ".sbss_w", SEC_ALLOC
| SEC_SMALL_DATA
},
3800 {NULL
, ".sbss_d", SEC_ALLOC
| SEC_SMALL_DATA
}
3803 /* Indexes to nds32_seg_table[]. */
3804 enum NDS32_SECTIONS_ENUM
3806 SDATA_F_SECTION
= 0,
3807 SDATA_B_SECTION
= 1,
3808 SDATA_H_SECTION
= 2,
3809 SDATA_W_SECTION
= 3,
3810 SDATA_D_SECTION
= 4,
3818 /* The following code is borrowed from v850_seg. Revise this is needed. */
3821 do_nds32_seg (int i
, subsegT sub
)
3823 nds32_seg_entry
*seg
= nds32_seg_table
+ i
;
3825 obj_elf_section_change_hook ();
3828 subseg_set (seg
->s
, sub
);
3831 seg
->s
= subseg_new (seg
->name
, sub
);
3832 if (OUTPUT_FLAVOR
== bfd_target_elf_flavour
)
3834 bfd_set_section_flags (seg
->s
, seg
->flags
);
3835 if ((seg
->flags
& SEC_LOAD
) == 0)
3836 seg_info (seg
->s
)->bss
= 1;
3844 subsegT sub
= get_absolute_expression ();
3846 do_nds32_seg (i
, sub
);
3847 demand_empty_rest_of_line ();
3850 /* Set if label adjustment is needed. I should not adjust .xbyte in dwarf. */
3851 static symbolS
*nds32_last_label
; /* Last label for alignment. */
3854 add_mapping_symbol_for_align (int shift
, valueT addr
, int is_data_align
)
3856 if ((shift
> 1) && (addr
& 1))
3858 int n
= (1 << shift
) - 1;
3860 add_mapping_symbol (MAP_CODE
, 1, 0);
3861 else if ((int) (addr
& n
) != n
)
3862 add_mapping_symbol (MAP_CODE
, 1, 0);
3864 else if ((shift
> 1) && ((int) (addr
& 1) == 0))
3865 add_mapping_symbol (MAP_CODE
, 0, 0);
3868 /* This code is referred from D30V for adjust label to be with pending
3869 alignment. For example,
3873 Without this, the above label will not attach to incoming data. */
3876 nds32_adjust_label (int n
)
3878 /* FIXME: I think adjust label and alignment is
3879 the programmer's obligation. Sadly, VLSI team doesn't
3880 properly use .align for their test cases.
3881 So I re-implement cons_align and auto adjust labels, again.
3883 I think d30v's implementation is simple and good enough. */
3885 symbolS
*label
= nds32_last_label
;
3886 nds32_last_label
= NULL
;
3888 /* SEC_ALLOC is used to eliminate .debug_ sections.
3889 SEC_CODE is used to include section for ILM. */
3890 if (((now_seg
->flags
& SEC_ALLOC
) == 0 && (now_seg
->flags
& SEC_CODE
) == 0)
3891 || strcmp (now_seg
->name
, ".eh_frame") == 0
3892 || strcmp (now_seg
->name
, ".gcc_except_table") == 0)
3895 /* Only frag by alignment when needed.
3896 Otherwise, it will fail to optimize labels on 4-byte boundary. (bug8454)
3897 See md_convert_frag () and RELAX_SET_RELAXABLE (frag) for details. */
3898 if (frag_now_fix () & ((1 << n
) -1 ))
3900 if (subseg_text_p (now_seg
))
3902 add_mapping_symbol_for_align (n
, frag_now_fix (), 1);
3903 frag_align_code (n
, 0);
3906 frag_align (n
, 0, 0);
3908 /* Record the minimum alignment for this segment. */
3909 record_alignment (now_seg
, n
- OCTETS_PER_BYTE_POWER
);
3915 int label_seen
= false;
3916 struct frag
*old_frag
;
3917 valueT old_value
, new_value
;
3919 gas_assert (S_GET_SEGMENT (label
) == now_seg
);
3921 old_frag
= symbol_get_frag (label
);
3922 old_value
= S_GET_VALUE (label
);
3923 new_value
= (valueT
) frag_now_fix ();
3925 /* Multiple labels may be on the same address. And the last symbol
3926 may not be a label at all, e.g., register name, external function names,
3927 so I have to track the last label in tc_frob_label instead of
3928 just using symbol_lastP. */
3929 for (sym
= symbol_lastP
; sym
!= NULL
; sym
= symbol_previous (sym
))
3931 if (symbol_get_frag (sym
) == old_frag
3932 && S_GET_VALUE (sym
) == old_value
)
3936 symbol_set_frag (sym
, frag_now
);
3937 S_SET_VALUE (sym
, new_value
);
3939 else if (label_seen
&& symbol_get_frag (sym
) != old_frag
)
3946 nds32_cons_align (int size ATTRIBUTE_UNUSED
)
3949 This is called before `md_flush_pending_output' is called by `cons'.
3951 There are two things should be done for auto-adjust-label.
3952 1. Align data/instructions and adjust label to be attached to them.
3953 2. Clear auto-adjust state, so incoming data/instructions will not
3961 in this case, '.word 0x2' will adjust the label, .L0, but '.word 0x3' should not.
3963 I think `md_flush_pending_output' is a good place to clear the auto-adjust state,
3964 but it is also called by `cons' before this function.
3965 To simplify the code, instead of overriding .zero, .fill, .space, etc,
3966 I think we should just adjust label in `nds32_aligned_X_cons' instead of here. */
3970 make_mapping_symbol (enum mstate state
, valueT value
, fragS
* frag
, unsigned int align
)
3972 symbolS
*symbol_p
= NULL
;
3973 const char *symbol_name
= NULL
;
3978 symbol_name
= "$d0";
3979 else if (align
== 1)
3980 symbol_name
= "$d1";
3981 else if (align
== 2)
3982 symbol_name
= "$d2";
3983 else if (align
== 3)
3984 symbol_name
= "$d3";
3985 else if (align
== 4)
3986 symbol_name
= "$d4";
3995 symbol_p
= symbol_new (symbol_name
, now_seg
, frag
, value
);
3996 /* local scope attribute */
3997 symbol_get_bfdsym (symbol_p
)->flags
|= BSF_NO_FLAGS
| BSF_LOCAL
;
4001 add_mapping_symbol (enum mstate state
, unsigned int padding_byte
,
4004 enum mstate current_mapping_state
=
4005 seg_info (now_seg
)->tc_segment_info_data
.mapstate
;
4007 if (state
== MAP_CODE
4008 && current_mapping_state
== state
)
4011 if (!SEG_NORMAL (now_seg
)
4012 || !subseg_text_p (now_seg
))
4015 /* start adding mapping symbol */
4016 seg_info (now_seg
)->tc_segment_info_data
.mapstate
= state
;
4017 make_mapping_symbol (state
, (valueT
) frag_now_fix () + padding_byte
,
4022 nds32_aligned_cons (int idx
)
4024 nds32_adjust_label (idx
);
4025 add_mapping_symbol (MAP_DATA
, 0, idx
);
4026 /* Call default handler. */
4028 if (now_seg
->flags
& SEC_CODE
4029 && now_seg
->flags
& SEC_ALLOC
&& now_seg
->flags
& SEC_RELOC
)
4031 /* Use BFD_RELOC_NDS32_DATA to avoid linker
4032 optimization replacing data. */
4035 exp
.X_add_number
= 0;
4036 exp
.X_op
= O_constant
;
4037 fix_new_exp (frag_now
, frag_now_fix () - (1 << idx
), 1 << idx
,
4038 &exp
, 0, BFD_RELOC_NDS32_DATA
);
4042 /* `.double' directive. */
4045 nds32_aligned_float_cons (int type
)
4053 nds32_adjust_label (2);
4059 nds32_adjust_label (4);
4062 as_bad ("Unrecognized float type, %c\n", (char)type
);
4064 /* Call default handler. */
4069 nds32_enable_pic (int ignore ATTRIBUTE_UNUSED
)
4071 /* Another way to do -mpic.
4072 This is for GCC internal use and should always be first line
4073 of code, otherwise, the effect is not determined. */
4078 nds32_set_abi (int ver
)
4083 /* Relax directive to set relocation R_NDS32_RELAX_ENTRY value. */
4086 nds32_relax_relocs (int relax
)
4091 const char *subtype_relax
[] =
4094 name
= input_line_pointer
;
4095 while (*input_line_pointer
&& !ISSPACE (*input_line_pointer
))
4096 input_line_pointer
++;
4097 saved_char
= *input_line_pointer
;
4098 *input_line_pointer
= 0;
4100 for (i
= 0; i
< (int) ARRAY_SIZE (subtype_relax
); i
++)
4102 if (strcmp (name
, subtype_relax
[i
]) == 0)
4108 enable_relax_relocs
= relax
& enable_relax_relocs
;
4116 *input_line_pointer
= saved_char
;
4117 ignore_rest_of_line ();
4120 /* Record which arguments register($r0 ~ $r5) is not used in callee.
4124 nds32_set_hint_func_args (int ignore ATTRIBUTE_UNUSED
)
4126 ignore_rest_of_line ();
4129 /* Insert relocations to mark the begin and end of a fp-omitted function,
4130 for further relaxation use.
4134 nds32_omit_fp_begin (int mode
)
4138 if (nds32_relax_fp_as_gp
== 0)
4140 exp
.X_op
= O_symbol
;
4141 exp
.X_add_symbol
= abs_section_sym
;
4145 exp
.X_add_number
= R_NDS32_RELAX_REGION_OMIT_FP_FLAG
;
4146 fix_new_exp (frag_now
, frag_now_fix (), 0, &exp
, 0,
4147 BFD_RELOC_NDS32_RELAX_REGION_BEGIN
);
4152 exp
.X_add_number
= R_NDS32_RELAX_REGION_OMIT_FP_FLAG
;
4153 fix_new_exp (frag_now
, frag_now_fix (), 0, &exp
, 0,
4154 BFD_RELOC_NDS32_RELAX_REGION_END
);
4159 nds32_loop_begin (int mode
)
4161 /* Insert loop region relocation here. */
4164 exp
.X_op
= O_symbol
;
4165 exp
.X_add_symbol
= abs_section_sym
;
4168 exp
.X_add_number
= R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG
;
4169 fix_new_exp (frag_now
, frag_now_fix (), 0, &exp
, 0,
4170 BFD_RELOC_NDS32_RELAX_REGION_BEGIN
);
4174 exp
.X_add_number
= R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG
;
4175 fix_new_exp (frag_now
, frag_now_fix (), 0, &exp
, 0,
4176 BFD_RELOC_NDS32_RELAX_REGION_END
);
4180 struct nds32_relocs_group
4182 struct nds32_relocs_pattern
*pattern
;
4183 struct nds32_relocs_group
*next
;
4186 static struct nds32_relocs_group
*nds32_relax_hint_current
= NULL
;
4187 /* Used to reorder the id for ".relax_hint id". */
4188 static int relax_hint_bias
= 0;
4189 /* Record current relax hint id. */
4190 static int relax_hint_id_current
= -1;
4192 /* If ".relax_hint begin" is triggered? */
4193 int relax_hint_begin
= 0;
4195 /* Record the reordered relax hint id. */
4197 struct relax_hint_id
4201 struct relax_hint_id
*next
;
4204 /* FIXME: Need to find somewhere to free the list. */
4205 struct relax_hint_id
*record_id_head
= NULL
;
4207 /* Is the buffer large enough? */
4208 #define MAX_BUFFER 12
4210 static char *nds_itoa (int n
);
4215 char *buf
= xmalloc (MAX_BUFFER
* sizeof (char));
4216 snprintf (buf
, MAX_BUFFER
, "%d", n
);
4220 /* Insert a relax hint. */
4223 nds32_relax_hint (int mode ATTRIBUTE_UNUSED
)
4227 struct nds32_relocs_pattern
*relocs
= NULL
;
4228 struct nds32_relocs_group
*group
, *new;
4229 struct relax_hint_id
*record_id
;
4231 name
= input_line_pointer
;
4232 while (*input_line_pointer
&& !ISSPACE (*input_line_pointer
))
4233 input_line_pointer
++;
4234 saved_char
= *input_line_pointer
;
4235 *input_line_pointer
= 0;
4236 name
= strdup (name
);
4238 if (name
&& strcmp (name
, "begin") == 0)
4240 if (relax_hint_id_current
== -1)
4243 relax_hint_id_current
++;
4244 relax_hint_begin
= 1;
4247 /* Original case ".relax_hint id". It's id may need to be reordered. */
4248 if (!relax_hint_begin
)
4250 int tmp
= strtol (name
, NULL
, 10);
4251 record_id
= record_id_head
;
4254 if (record_id
->old_id
== tmp
)
4256 name
= nds_itoa (record_id
->new_id
);
4259 record_id
= record_id
->next
;
4263 relax_hint_bias
= relax_hint_id_current
- atoi (name
) + 1;
4266 relax_hint_id_current
= tmp
+ relax_hint_bias
;
4268 /* Insert the element to the head of the link list. */
4269 struct relax_hint_id
*tmp_id
= malloc (sizeof (struct relax_hint_id
));
4270 tmp_id
->old_id
= tmp
;
4271 tmp_id
->new_id
= relax_hint_id_current
;
4272 tmp_id
->next
= record_id_head
;
4273 record_id_head
= tmp_id
;
4276 if (name
&& strcmp (name
, "end") == 0)
4277 relax_hint_begin
= 0;
4278 name
= nds_itoa (relax_hint_id_current
);
4282 /* Find relax hint entry for next instruction, and all member will be
4283 initialized at that time. */
4284 relocs
= str_hash_find (nds32_hint_hash
, name
);
4287 relocs
= XNEW (struct nds32_relocs_pattern
);
4288 memset (relocs
, 0, sizeof (struct nds32_relocs_pattern
));
4289 str_hash_insert (nds32_hint_hash
, name
, relocs
, 0);
4293 while (relocs
->next
)
4294 relocs
=relocs
->next
;
4295 relocs
->next
= XNEW (struct nds32_relocs_pattern
);
4296 relocs
= relocs
->next
;
4297 memset (relocs
, 0, sizeof (struct nds32_relocs_pattern
));
4300 relocs
->next
= NULL
;
4301 *input_line_pointer
= saved_char
;
4302 ignore_rest_of_line ();
4304 /* Get the final one of relax hint series. */
4306 /* It has to build this list because there are maybe more than one
4307 instructions relative to the same instruction. It to connect to
4308 next instruction after md_assemble. */
4309 new = XNEW (struct nds32_relocs_group
);
4310 memset (new, 0, sizeof (struct nds32_relocs_group
));
4311 new->pattern
= relocs
;
4313 group
= nds32_relax_hint_current
;
4315 nds32_relax_hint_current
= new;
4318 while (group
->next
!= NULL
)
4319 group
= group
->next
;
4325 /* Decide the size of vector entries, only accepts 4 or 16 now. */
4328 nds32_vec_size (int ignore ATTRIBUTE_UNUSED
)
4334 if (exp
.X_op
== O_constant
)
4336 if (exp
.X_add_number
== 4 || exp
.X_add_number
== 16)
4339 vec_size
= exp
.X_add_number
;
4340 else if (vec_size
!= exp
.X_add_number
)
4341 as_warn (_("Different arguments of .vec_size are found, "
4342 "previous %d, current %d"),
4343 (int) vec_size
, (int) exp
.X_add_number
);
4346 as_warn (_("Argument of .vec_size is expected 4 or 16, actual: %d."),
4347 (int) exp
.X_add_number
);
4350 as_warn (_("Argument of .vec_size is not a constant."));
4353 /* The behavior of ".flag" directive varies depending on the target.
4354 In nds32 target, we use it to recognize whether this assembly content is
4355 generated by compiler. Other features can also be added in this function
4359 nds32_flag (int ignore ATTRIBUTE_UNUSED
)
4364 const char *possible_flags
[] = { "verbatim" };
4366 /* Skip whitespaces. */
4367 name
= input_line_pointer
;
4368 while (*input_line_pointer
&& !ISSPACE (*input_line_pointer
))
4369 input_line_pointer
++;
4370 saved_char
= *input_line_pointer
;
4371 *input_line_pointer
= 0;
4373 for (i
= 0; i
< (int) ARRAY_SIZE (possible_flags
); i
++)
4375 if (strcmp (name
, possible_flags
[i
]) == 0)
4380 /* flag: verbatim */
4386 /* Already found the flag, no need to continue next loop. */
4391 *input_line_pointer
= saved_char
;
4392 ignore_rest_of_line ();
4396 ict_model (int ignore ATTRIBUTE_UNUSED
)
4401 const char *possible_flags
[] = { "small", "large" };
4403 /* Skip whitespaces. */
4404 name
= input_line_pointer
;
4405 while (*input_line_pointer
&& !ISSPACE (*input_line_pointer
))
4406 input_line_pointer
++;
4407 saved_char
= *input_line_pointer
;
4408 *input_line_pointer
= 0;
4410 for (i
= 0; i
< (int) ARRAY_SIZE (possible_flags
); i
++)
4412 if (strcmp (name
, possible_flags
[i
]) == 0)
4417 /* flag: verbatim */
4418 ict_flag
= ICT_SMALL
;
4421 ict_flag
= ICT_LARGE
;
4426 /* Already found the flag, no need to continue next loop. */
4431 *input_line_pointer
= saved_char
;
4432 ignore_rest_of_line ();
4436 nds32_n12hc (int ignore ATTRIBUTE_UNUSED
)
4438 /* N1213HC core is used. */
4442 /* The target specific pseudo-ops which we support. */
4443 const pseudo_typeS md_pseudo_table
[] =
4445 /* Forced alignment if declared these ways. */
4446 {"ascii", stringer
, 8 + 0},
4447 {"asciz", stringer
, 8 + 1},
4448 {"double", nds32_aligned_float_cons
, 'd'},
4449 {"dword", nds32_aligned_cons
, 3},
4450 {"float", nds32_aligned_float_cons
, 'f'},
4451 {"half", nds32_aligned_cons
, 1},
4452 {"hword", nds32_aligned_cons
, 1},
4453 {"int", nds32_aligned_cons
, 2},
4454 {"long", nds32_aligned_cons
, 2},
4455 {"octa", nds32_aligned_cons
, 4},
4456 {"quad", nds32_aligned_cons
, 3},
4457 {"qword", nds32_aligned_cons
, 4},
4458 {"short", nds32_aligned_cons
, 1},
4459 {"byte", nds32_aligned_cons
, 0},
4460 {"single", nds32_aligned_float_cons
, 'f'},
4461 {"string", stringer
, 8 + 1},
4462 {"word", nds32_aligned_cons
, 2},
4464 {"little", set_endian_little
, 1},
4465 {"big", set_endian_little
, 0},
4466 {"16bit_on", trigger_16bit
, 1},
4467 {"16bit_off", trigger_16bit
, 0},
4468 {"restore_16bit", restore_16bit
, 0},
4469 {"off_16bit", off_16bit
, 0},
4471 {"sdata_d", nds32_seg
, SDATA_D_SECTION
},
4472 {"sdata_w", nds32_seg
, SDATA_W_SECTION
},
4473 {"sdata_h", nds32_seg
, SDATA_H_SECTION
},
4474 {"sdata_b", nds32_seg
, SDATA_B_SECTION
},
4475 {"sdata_f", nds32_seg
, SDATA_F_SECTION
},
4477 {"sbss_d", nds32_seg
, SBSS_D_SECTION
},
4478 {"sbss_w", nds32_seg
, SBSS_W_SECTION
},
4479 {"sbss_h", nds32_seg
, SBSS_H_SECTION
},
4480 {"sbss_b", nds32_seg
, SBSS_B_SECTION
},
4481 {"sbss_f", nds32_seg
, SBSS_F_SECTION
},
4483 {"pic", nds32_enable_pic
, 0},
4484 {"n12_hc", nds32_n12hc
, 0},
4485 {"abi_1", nds32_set_abi
, E_NDS_ABI_V1
},
4486 {"abi_2", nds32_set_abi
, E_NDS_ABI_AABI
},
4488 {"abi_2fp", nds32_set_abi
, E_NDS_ABI_V2FP
},
4489 {"abi_2fp_plus", nds32_set_abi
, E_NDS_ABI_V2FP_PLUS
},
4490 {"relax", nds32_relax_relocs
, 1},
4491 {"no_relax", nds32_relax_relocs
, 0},
4492 {"hint_func_args", nds32_set_hint_func_args
, 0}, /* Abandon?? */
4493 {"omit_fp_begin", nds32_omit_fp_begin
, 1},
4494 {"omit_fp_end", nds32_omit_fp_begin
, 0},
4495 {"vec_size", nds32_vec_size
, 0},
4496 {"flag", nds32_flag
, 0},
4497 {"innermost_loop_begin", nds32_loop_begin
, 1},
4498 {"innermost_loop_end", nds32_loop_begin
, 0},
4499 {"relax_hint", nds32_relax_hint
, 0},
4500 {"ict_model", ict_model
, 0},
4505 nds32_pre_do_align (int n
, char *fill
, int len
, int max
)
4507 /* Only make a frag if we HAVE to... */
4509 if (n
!= 0 && !need_pass_2
)
4513 if (subseg_text_p (now_seg
))
4515 dwarf2_emit_insn (0);
4517 add_mapping_symbol_for_align (n
, frag_now_fix (), 0);
4518 frag_align_code (n
, max
);
4520 /* Tag this alignment when there is a label before it. */
4523 fragP
->tc_frag_data
.flag
= NDS32_FRAG_LABEL
;
4528 frag_align (n
, 0, max
);
4531 frag_align (n
, *fill
, max
);
4533 frag_align_pattern (n
, fill
, len
, max
);
4538 nds32_do_align (int n
)
4540 /* Optimize for space and label exists. */
4543 /* FIXME:I think this will break debug info sections and except_table. */
4544 if (!enable_relax_relocs
|| !subseg_text_p (now_seg
))
4547 /* Create and attach a BFD_RELOC_NDS32_LABEL fixup
4548 the size of instruction may not be correct because
4549 it could be relaxable. */
4550 exp
.X_op
= O_symbol
;
4551 exp
.X_add_symbol
= section_symbol (now_seg
);
4552 exp
.X_add_number
= n
;
4553 fix_new_exp (frag_now
,
4554 frag_now_fix (), 0, &exp
, 0, BFD_RELOC_NDS32_LABEL
);
4557 /* Supported Andes machines. */
4560 enum bfd_architecture bfd_mach
;
4564 /* This is the callback for nds32-asm.c to parse operands. */
4567 nds32_asm_parse_operand (struct nds32_asm_desc
*pdesc ATTRIBUTE_UNUSED
,
4568 struct nds32_asm_insn
*pinsn
,
4569 char **pstr
, int64_t *value
)
4572 expressionS
*pexp
= pinsn
->info
;
4574 hold
= input_line_pointer
;
4575 input_line_pointer
= *pstr
;
4577 *pstr
= input_line_pointer
;
4578 input_line_pointer
= hold
;
4584 return NASM_R_SYMBOL
;
4586 *value
= pexp
->X_add_number
;
4587 return NASM_R_CONST
;
4592 return NASM_R_ILLEGAL
;
4596 /* GAS will call this function at the start of the assembly, after the command
4597 line arguments have been parsed and all the machine independent
4598 initializations have been completed. */
4603 const struct nds32_keyword
*k
;
4604 relax_info_t
*relax_info
;
4607 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, nds32_baseline
);
4609 nds32_init_nds32_pseudo_opcodes ();
4610 asm_desc
.parse_operand
= nds32_asm_parse_operand
;
4612 flags
|= NASM_OPEN_REDUCED_REG
;
4613 nds32_asm_init (&asm_desc
, flags
);
4615 /* Initial general purpose registers hash table. */
4616 nds32_gprs_hash
= str_htab_create ();
4617 for (k
= nds32_keyword_gpr
; k
->name
; k
++)
4618 str_hash_insert (nds32_gprs_hash
, k
->name
, k
, 0);
4620 /* Initial branch hash table. */
4621 nds32_relax_info_hash
= str_htab_create ();
4622 for (relax_info
= relax_table
; relax_info
->opcode
; relax_info
++)
4623 str_hash_insert (nds32_relax_info_hash
, relax_info
->opcode
, relax_info
, 0);
4625 /* Initial relax hint hash table. */
4626 nds32_hint_hash
= str_htab_create ();
4627 enable_16bit
= nds32_16bit_ext
;
4630 /* HANDLE_ALIGN in write.c. */
4633 nds32_handle_align (fragS
*fragp
)
4635 static const unsigned char nop16
[] = { 0x92, 0x00 };
4636 static const unsigned char nop32
[] = { 0x40, 0x00, 0x00, 0x09 };
4640 if (fragp
->fr_type
!= rs_align_code
)
4643 bytes
= fragp
->fr_next
->fr_address
- fragp
->fr_address
- fragp
->fr_fix
;
4644 p
= fragp
->fr_literal
+ fragp
->fr_fix
;
4655 exp_t
.X_op
= O_symbol
;
4656 exp_t
.X_add_symbol
= abs_section_sym
;
4657 exp_t
.X_add_number
= R_NDS32_INSN16_CONVERT_FLAG
;
4658 fix_new_exp (fragp
, fragp
->fr_fix
, 2, &exp_t
, 0,
4659 BFD_RELOC_NDS32_INSN16
);
4660 memcpy (p
, nop16
, 2);
4667 memcpy (p
, nop32
, 4);
4672 bytes
= fragp
->fr_next
->fr_address
- fragp
->fr_address
- fragp
->fr_fix
;
4673 fragp
->fr_fix
+= bytes
;
4676 /* md_flush_pending_output */
4679 nds32_flush_pending_output (void)
4681 nds32_last_label
= NULL
;
4685 nds32_frob_label (symbolS
*label
)
4687 dwarf2_emit_label (label
);
4690 /* TC_START_LABEL */
4693 nds32_start_label (int asmdone ATTRIBUTE_UNUSED
, int secdone ATTRIBUTE_UNUSED
)
4695 if (optimize
&& subseg_text_p (now_seg
))
4703 nds32_target_format (void)
4706 if (target_big_endian
)
4707 return "elf32-nds32be-linux";
4709 return "elf32-nds32le-linux";
4711 if (target_big_endian
)
4712 return "elf32-nds32be";
4714 return "elf32-nds32le";
4718 static enum nds32_br_range
4719 get_range_type (const struct nds32_field
*field
)
4721 gas_assert (field
!= NULL
);
4723 if (field
->bitpos
!= 0)
4724 return BR_RANGE_U4G
;
4726 if (field
->bitsize
== 24 && field
->shift
== 1)
4727 return BR_RANGE_S16M
;
4728 else if (field
->bitsize
== 16 && field
->shift
== 1)
4729 return BR_RANGE_S64K
;
4730 else if (field
->bitsize
== 14 && field
->shift
== 1)
4731 return BR_RANGE_S16K
;
4732 else if (field
->bitsize
== 8 && field
->shift
== 1)
4733 return BR_RANGE_S256
;
4735 return BR_RANGE_U4G
;
4738 /* Save pseudo instruction relocation list. */
4740 static struct nds32_relocs_pattern
*
4741 nds32_elf_save_pseudo_pattern (fixS
* fixP
, struct nds32_asm_insn
*insn
,
4742 char *out
, symbolS
*sym
,
4743 struct nds32_relocs_pattern
*reloc_ptr
,
4746 struct nds32_opcode
*opcode
= insn
->opcode
;
4748 reloc_ptr
= XNEW (struct nds32_relocs_pattern
);
4749 reloc_ptr
->seg
= now_seg
;
4750 reloc_ptr
->sym
= sym
;
4751 reloc_ptr
->frag
= fragP
;
4752 reloc_ptr
->frchain
= frchain_now
;
4753 reloc_ptr
->fixP
= fixP
;
4754 reloc_ptr
->opcode
= opcode
;
4755 reloc_ptr
->where
= out
;
4756 reloc_ptr
->insn
= insn
->insn
;
4757 reloc_ptr
->next
= NULL
;
4761 /* Check X_md to transform relocation. */
4764 nds32_elf_record_fixup_exp (fragS
*fragP
, const char *str
,
4765 const struct nds32_field
*fld
,
4766 expressionS
*pexp
, char* out
,
4767 struct nds32_asm_insn
*insn
)
4773 /* Handle instruction relocation. */
4774 if (fld
&& fld
->bitpos
== 0 && (insn
->attr
& NASM_ATTR_HI20
))
4776 /* Relocation for hi20 modifier. */
4779 case BFD_RELOC_NDS32_GOTOFF
: /* @GOTOFF */
4780 reloc
= BFD_RELOC_NDS32_GOTOFF_HI20
;
4782 case BFD_RELOC_NDS32_GOT20
: /* @GOT */
4783 reloc
= BFD_RELOC_NDS32_GOT_HI20
;
4785 case BFD_RELOC_NDS32_25_PLTREL
: /* @PLT */
4787 as_bad (_("Invalid PIC expression."));
4789 reloc
= BFD_RELOC_NDS32_PLT_GOTREL_HI20
;
4791 case BFD_RELOC_NDS32_GOTPC20
: /* _GLOBAL_OFFSET_TABLE_ */
4792 reloc
= BFD_RELOC_NDS32_GOTPC_HI20
;
4794 case BFD_RELOC_NDS32_TPOFF
: /* @TPOFF */
4795 reloc
= BFD_RELOC_NDS32_TLS_LE_HI20
;
4797 case BFD_RELOC_NDS32_GOTTPOFF
: /* @GOTTPOFF */
4798 reloc
= nds32_pic
? BFD_RELOC_NDS32_TLS_IEGP_HI20
: BFD_RELOC_NDS32_TLS_IE_HI20
;
4800 case BFD_RELOC_NDS32_TLS_DESC
: /* @TLSDESC */
4801 reloc
= BFD_RELOC_NDS32_TLS_DESC_HI20
;
4803 default: /* No suffix */
4805 /* When the file is pic, the address must be offset to gp.
4806 It may define another relocation or use GOTOFF. */
4807 reloc
= BFD_RELOC_NDS32_PLT_GOTREL_HI20
;
4809 reloc
= BFD_RELOC_NDS32_HI20
;
4812 fixP
= fix_new_exp (fragP
, out
- fragP
->fr_literal
, insn
->opcode
->isize
,
4813 insn
->info
, 0 /* pcrel */, reloc
);
4815 else if (fld
&& fld
->bitpos
== 0 && (insn
->attr
& NASM_ATTR_LO12
))
4817 /* Relocation for lo12 modifier. */
4818 if (fld
->bitsize
== 15 && fld
->shift
== 0)
4823 case BFD_RELOC_NDS32_GOTOFF
: /* @GOTOFF */
4824 reloc
= BFD_RELOC_NDS32_GOTOFF_LO12
;
4826 case BFD_RELOC_NDS32_GOT20
: /* @GOT */
4827 reloc
= BFD_RELOC_NDS32_GOT_LO12
;
4829 case BFD_RELOC_NDS32_25_PLTREL
: /* @PLT */
4831 as_bad (_("Invalid PIC expression."));
4833 reloc
= BFD_RELOC_NDS32_PLT_GOTREL_LO12
;
4835 case BFD_RELOC_NDS32_GOTPC20
: /* _GLOBAL_OFFSET_TABLE_ */
4836 reloc
= BFD_RELOC_NDS32_GOTPC_LO12
;
4838 case BFD_RELOC_NDS32_TPOFF
: /* @TPOFF */
4839 reloc
= BFD_RELOC_NDS32_TLS_LE_LO12
;
4841 case BFD_RELOC_NDS32_GOTTPOFF
: /* @GOTTPOFF */
4842 reloc
= nds32_pic
? BFD_RELOC_NDS32_TLS_IEGP_LO12
: BFD_RELOC_NDS32_TLS_IE_LO12
;
4844 case BFD_RELOC_NDS32_TLS_DESC
: /* @TLSDESC */
4845 reloc
= BFD_RELOC_NDS32_TLS_DESC_LO12
;
4847 default: /* No suffix */
4849 /* When the file is pic, the address must be offset to gp.
4850 It may define another relocation or use GOTOFF. */
4851 reloc
= BFD_RELOC_NDS32_PLT_GOTREL_LO12
;
4853 reloc
= BFD_RELOC_NDS32_LO12S0
;
4857 else if (fld
->bitsize
== 15 && fld
->shift
== 1)
4858 reloc
= BFD_RELOC_NDS32_LO12S1
; /* [ls]hi */
4859 else if (fld
->bitsize
== 15 && fld
->shift
== 2)
4864 case BFD_RELOC_NDS32_GOTTPOFF
: /* @GOTTPOFF */
4865 reloc
= nds32_pic
? BFD_RELOC_NDS32_TLS_IEGP_LO12S2
: BFD_RELOC_NDS32_TLS_IE_LO12S2
;
4867 default: /* No suffix */
4868 reloc
= BFD_RELOC_NDS32_LO12S2
;
4872 else if (fld
->bitsize
== 15 && fld
->shift
== 3)
4873 reloc
= BFD_RELOC_NDS32_LO12S3
; /* [ls]di */
4874 else if (fld
->bitsize
== 12 && fld
->shift
== 2)
4875 reloc
= BFD_RELOC_NDS32_LO12S2_SP
; /* f[ls][sd]i */
4877 fixP
= fix_new_exp (fragP
, out
- fragP
->fr_literal
, insn
->opcode
->isize
,
4878 insn
->info
, 0 /* pcrel */, reloc
);
4880 else if (fld
&& fld
->bitpos
== 0 && insn
->opcode
->isize
== 4
4881 && (insn
->attr
& NASM_ATTR_PCREL
))
4883 /* Relocation for 32-bit branch instructions. */
4884 if (fld
->bitsize
== 24 && fld
->shift
== 1)
4885 reloc
= BFD_RELOC_NDS32_25_PCREL
;
4886 else if (fld
->bitsize
== 16 && fld
->shift
== 1)
4887 reloc
= BFD_RELOC_NDS32_17_PCREL
;
4888 else if (fld
->bitsize
== 14 && fld
->shift
== 1)
4889 reloc
= BFD_RELOC_NDS32_15_PCREL
;
4890 else if (fld
->bitsize
== 8 && fld
->shift
== 1)
4891 reloc
= BFD_RELOC_NDS32_WORD_9_PCREL
;
4895 fixP
= fix_new_exp (fragP
, out
- fragP
->fr_literal
, insn
->opcode
->isize
,
4896 insn
->info
, 1 /* pcrel */, reloc
);
4898 else if (fld
&& fld
->bitpos
== 0 && insn
->opcode
->isize
== 4
4899 && (insn
->attr
& NASM_ATTR_GPREL
))
4901 /* Relocation for 32-bit gp-relative instructions. */
4902 if (fld
->bitsize
== 19 && fld
->shift
== 0)
4903 reloc
= BFD_RELOC_NDS32_SDA19S0
;
4904 else if (fld
->bitsize
== 18 && fld
->shift
== 1)
4905 reloc
= BFD_RELOC_NDS32_SDA18S1
;
4906 else if (fld
->bitsize
== 17 && fld
->shift
== 2)
4907 reloc
= BFD_RELOC_NDS32_SDA17S2
;
4911 fixP
= fix_new_exp (fragP
, out
- fragP
->fr_literal
, insn
->opcode
->isize
,
4912 insn
->info
, 0 /* pcrel */, reloc
);
4913 /* Insert INSN16 for converting fp_as_gp. */
4914 exp
.X_op
= O_symbol
;
4915 exp
.X_add_symbol
= abs_section_sym
;
4916 exp
.X_add_number
= 0;
4917 if (in_omit_fp
&& reloc
== BFD_RELOC_NDS32_SDA17S2
)
4918 fix_new_exp (fragP
, out
- fragP
->fr_literal
,
4919 insn
->opcode
->isize
, &exp
, 0 /* pcrel */,
4920 BFD_RELOC_NDS32_INSN16
);
4922 else if (fld
&& fld
->bitpos
== 0 && insn
->opcode
->isize
== 2
4923 && (insn
->attr
& NASM_ATTR_PCREL
))
4925 /* Relocation for 16-bit branch instructions. */
4926 if (fld
->bitsize
== 8 && fld
->shift
== 1)
4927 reloc
= BFD_RELOC_NDS32_9_PCREL
;
4931 fixP
= fix_new_exp (fragP
, out
- fragP
->fr_literal
, insn
->opcode
->isize
,
4932 insn
->info
, 1 /* pcrel */, reloc
);
4935 as_bad (_("Don't know how to handle this field. %s"), str
);
4940 /* Build instruction pattern to relax. There are two type group pattern
4941 including pseudo instruction and relax hint. */
4944 nds32_elf_build_relax_relation (fixS
*fixP
, expressionS
*pexp
, char* out
,
4945 struct nds32_asm_insn
*insn
, fragS
*fragP
,
4946 const struct nds32_field
*fld
,
4949 struct nds32_relocs_pattern
*reloc_ptr
;
4950 struct nds32_relocs_group
*group
;
4951 symbolS
*sym
= NULL
;
4953 /* The expression may be used uninitialized. */
4955 sym
= pexp
->X_add_symbol
;
4959 /* We cannot know how many instructions will be expanded for
4960 the pseudo instruction here. The first expanded instruction fills
4961 the memory created by relax_hint. The follower will created and link
4963 group
= nds32_relax_hint_current
;
4966 if (group
->pattern
->opcode
== NULL
)
4967 nds32_elf_save_pseudo_pattern (fixP
, insn
, out
, sym
,
4968 group
->pattern
, fragP
);
4971 group
->pattern
->next
=
4972 nds32_elf_save_pseudo_pattern (fixP
, insn
, out
, sym
,
4974 group
->pattern
= group
->pattern
->next
;
4976 group
= group
->next
;
4979 else if (pseudo_opcode
)
4981 /* Save instruction relation for pseudo instruction expanding pattern. */
4982 reloc_ptr
= nds32_elf_save_pseudo_pattern (fixP
, insn
, out
, sym
,
4985 relocs_list
= reloc_ptr
;
4988 struct nds32_relocs_pattern
*temp
= relocs_list
;
4991 temp
->next
= reloc_ptr
;
4994 else if (nds32_relax_hint_current
)
4996 /* Save instruction relation by relax hint. */
4997 group
= nds32_relax_hint_current
;
5000 nds32_elf_save_pseudo_pattern (fixP
, insn
, out
, sym
,
5001 group
->pattern
, fragP
);
5002 group
= group
->next
;
5003 free (nds32_relax_hint_current
);
5004 nds32_relax_hint_current
= group
;
5008 /* Set relaxing false only for relax_hint trigger it. */
5013 #define N32_MEM_EXT(insn) ((N32_OP6_MEM << 25) | insn)
5015 /* Relax pattern for link time relaxation. */
5016 /* Relaxation types only! relocation types are not necessary. */
5017 /* Refer to nds32_elf_record_fixup_exp (). */
5019 static struct nds32_relax_hint_table relax_ls_table
[] =
5022 /* LA and Floating LSI. */
5023 .main_type
= NDS32_RELAX_HINT_LA_FLSI
,
5024 .relax_code_size
= 12,
5033 {0, 4, NDS32_HINT
| NDS32_ADDEND
, BFD_RELOC_NDS32_LOADSTORE
},
5034 {4, 4, NDS32_HINT
| NDS32_PTR
, BFD_RELOC_NDS32_PTR
},
5035 {4, 4, NDS32_HINT
| NDS32_INSN16
, BFD_RELOC_NDS32_INSN16
},
5036 {8, 4, NDS32_HINT
| NDS32_SYM
, BFD_RELOC_NDS32_LSI
},
5037 {8, 4, NDS32_HINT
| NDS32_ABS
, BFD_RELOC_NDS32_PTR_RESOLVED
},
5038 {8, 4, NDS32_HINT
| NDS32_INSN16
, BFD_RELOC_NDS32_INSN16
},
5043 /* Load Address / Load-Store (LALS). */
5044 .main_type
= NDS32_RELAX_HINT_LALS
,
5045 .relax_code_size
= 12,
5054 {0, 4, NDS32_HINT
| NDS32_ADDEND
, BFD_RELOC_NDS32_LOADSTORE
},
5055 {4, 4, NDS32_HINT
| NDS32_INSN16
, BFD_RELOC_NDS32_INSN16
},
5056 {8, 4, NDS32_HINT
| NDS32_INSN16
, BFD_RELOC_NDS32_INSN16
},
5061 /* B(AL) symbol@PLT */
5062 .main_type
= NDS32_RELAX_HINT_LA_PLT
,
5063 .relax_code_size
= 16,
5073 {0, 4, NDS32_HINT
| NDS32_ADDEND
, BFD_RELOC_NDS32_LOADSTORE
},
5074 {4, 4, NDS32_HINT
| NDS32_PTR
, BFD_RELOC_NDS32_PTR
},
5075 {8, 4, NDS32_HINT
| NDS32_PTR
, BFD_RELOC_NDS32_PTR
},
5076 {12, 4, NDS32_HINT
| NDS32_ABS
, BFD_RELOC_NDS32_PLT_GOT_SUFF
},
5077 {12, 4, NDS32_HINT
| NDS32_ABS
, BFD_RELOC_NDS32_PTR_RESOLVED
},
5078 {12, 4, NDS32_HINT
| NDS32_INSN16
, BFD_RELOC_NDS32_INSN16
},
5084 .main_type
= NDS32_RELAX_HINT_LA_GOT
,
5085 .relax_code_size
= 12,
5094 {0, 4, NDS32_HINT
| NDS32_ADDEND
, BFD_RELOC_NDS32_LOADSTORE
},
5095 {4, 4, NDS32_HINT
| NDS32_PTR
, BFD_RELOC_NDS32_PTR
},
5096 {8, 4, NDS32_HINT
| NDS32_ABS
, BFD_RELOC_NDS32_PTR_RESOLVED
},
5097 {8, 4, NDS32_HINT
| NDS32_ABS
, BFD_RELOC_NDS32_GOT_SUFF
},
5103 .main_type
= NDS32_RELAX_HINT_LA_GOTOFF
,
5104 .relax_code_size
= 16,
5114 {0, 4, NDS32_HINT
| NDS32_ADDEND
, BFD_RELOC_NDS32_LOADSTORE
},
5115 {4, 4, NDS32_HINT
| NDS32_PTR
, BFD_RELOC_NDS32_PTR
},
5116 {8, 4, NDS32_HINT
| NDS32_ABS
, BFD_RELOC_NDS32_PTR_RESOLVED
},
5117 {8, 4, NDS32_HINT
| NDS32_ABS
, BFD_RELOC_NDS32_GOTOFF_SUFF
},
5118 {12, 4, NDS32_HINT
| NDS32_ABS
, BFD_RELOC_NDS32_PTR_RESOLVED
},
5119 {12, 4, NDS32_HINT
| NDS32_ABS
, BFD_RELOC_NDS32_GOTOFF_SUFF
},
5125 .main_type
= NDS32_RELAX_HINT_TLS_LE_LS
,
5126 .relax_code_size
= 16,
5136 {0, 4, NDS32_HINT
| NDS32_ADDEND
, BFD_RELOC_NDS32_LOADSTORE
},
5137 {4, 4, NDS32_HINT
| NDS32_PTR_MULTIPLE
, BFD_RELOC_NDS32_PTR
},
5138 {8, 4, NDS32_HINT
| NDS32_ABS
, BFD_RELOC_NDS32_PTR_RESOLVED
},
5139 {8, 4, NDS32_HINT
| NDS32_SYM
, BFD_RELOC_NDS32_TLS_LE_LS
},
5140 {12, 4, NDS32_HINT
| NDS32_ABS
, BFD_RELOC_NDS32_PTR_RESOLVED
},
5141 {12, 4, NDS32_HINT
| NDS32_SYM
, BFD_RELOC_NDS32_TLS_LE_ADD
},
5147 .main_type
= NDS32_RELAX_HINT_TLS_IE_LA
,
5148 .relax_code_size
= 8,
5156 {0, 4, NDS32_HINT
| NDS32_ADDEND
, BFD_RELOC_NDS32_LOADSTORE
},
5157 {4, 4, NDS32_HINT
| NDS32_INSN16
, BFD_RELOC_NDS32_INSN16
},
5163 .main_type
= NDS32_RELAX_HINT_TLS_IEGP_LA
,
5164 .relax_code_size
= 12,
5173 {0, 4, NDS32_HINT
| NDS32_ADDEND
, BFD_RELOC_NDS32_LOADSTORE
},
5174 {4, 4, NDS32_HINT
| NDS32_PTR_PATTERN
, BFD_RELOC_NDS32_PTR
},
5175 {8, 4, NDS32_HINT
| NDS32_ABS
, BFD_RELOC_NDS32_PTR_RESOLVED
},
5176 {8, 4, NDS32_HINT
| NDS32_SYM
, BFD_RELOC_NDS32_TLS_IEGP_LW
},
5182 .main_type
= NDS32_RELAX_HINT_TLS_DESC_LS
,
5183 .relax_code_size
= 24,
5189 OP6 (LBI
), /* load argument */
5191 OP6 (MEM
), /* load/store variable or load argument */
5195 {0, 4, NDS32_HINT
| NDS32_ADDEND
, BFD_RELOC_NDS32_LOADSTORE
},
5196 {4, 4, NDS32_HINT
| NDS32_PTR_PATTERN
, BFD_RELOC_NDS32_PTR
},
5197 {8, 4, NDS32_HINT
| NDS32_ABS
, BFD_RELOC_NDS32_PTR_RESOLVED
},
5198 {8, 4, NDS32_HINT
| NDS32_SYM
, BFD_RELOC_NDS32_TLS_DESC_ADD
},
5199 {12, 4, NDS32_HINT
| NDS32_SYM
, BFD_RELOC_NDS32_TLS_DESC_FUNC
},
5200 {16, 4, NDS32_HINT
| NDS32_SYM
, BFD_RELOC_NDS32_TLS_DESC_CALL
},
5201 {20, 4, NDS32_HINT
| NDS32_SYM_DESC_MEM
, BFD_RELOC_NDS32_TLS_DESC_MEM
},
5207 .relax_code_seq
= {0},
5208 .relax_fixup
= {{0, 0 , 0, 0}}
5212 /* Since sethi loadstore relocation has to using next instruction to determine
5213 elimination itself or not, we have to return the next instruction range. */
5216 nds32_elf_sethi_range (struct nds32_relocs_pattern
*pattern
)
5221 switch (pattern
->opcode
->value
)
5226 case N32_MEM_EXT (N32_MEM_LB
):
5227 case N32_MEM_EXT (N32_MEM_LBS
):
5228 case N32_MEM_EXT (N32_MEM_SB
):
5229 range
= NDS32_LOADSTORE_BYTE
;
5234 case N32_MEM_EXT (N32_MEM_LH
):
5235 case N32_MEM_EXT (N32_MEM_LHS
):
5236 case N32_MEM_EXT (N32_MEM_SH
):
5237 range
= NDS32_LOADSTORE_HALF
;
5241 case N32_MEM_EXT (N32_MEM_LW
):
5242 case N32_MEM_EXT (N32_MEM_SW
):
5243 range
= NDS32_LOADSTORE_WORD
;
5247 range
= NDS32_LOADSTORE_FLOAT_S
;
5251 range
= NDS32_LOADSTORE_FLOAT_D
;
5254 range
= NDS32_LOADSTORE_IMM
;
5257 range
= NDS32_LOADSTORE_NONE
;
5260 if (range
!= NDS32_LOADSTORE_NONE
)
5262 pattern
= pattern
->next
;
5267 /* The args means: instruction size, the 1st instruction is converted to 16 or
5268 not, optimize option, 16 bit instruction is enable. */
5270 #define SET_ADDEND(size, convertible, optimize, insn16_on) \
5271 (((size) & 0xff) | ((convertible) ? 1u << 31 : 0) \
5272 | ((optimize) ? 1 << 30 : 0) | (insn16_on ? 1 << 29 : 0))
5273 #define MAC_COMBO (E_NDS32_HAS_FPU_MAC_INST|E_NDS32_HAS_MAC_DX_INST)
5276 nds32_set_elf_flags_by_insn (struct nds32_asm_insn
* insn
)
5278 static int skip_flags
= NASM_ATTR_FPU_FMA
5279 | NASM_ATTR_BRANCH
| NASM_ATTR_SATURATION_EXT
5280 | NASM_ATTR_GPREL
| NASM_ATTR_DXREG
5281 | NASM_ATTR_ISA_V1
| NASM_ATTR_ISA_V2
5282 | NASM_ATTR_ISA_V3
| NASM_ATTR_ISA_V3M
5285 int new_flags
= insn
->opcode
->attr
& ~skip_flags
;
5288 int next
= 1 << (ffs (new_flags
) - 1);
5292 case NASM_ATTR_PERF_EXT
:
5296 nds32_elf_flags
|= E_NDS32_HAS_EXT_INST
;
5297 skip_flags
|= NASM_ATTR_PERF_EXT
;
5300 as_bad (_("instruction %s requires enabling performance "
5301 "extension"), insn
->opcode
->opcode
);
5304 case NASM_ATTR_PERF2_EXT
:
5306 if (nds32_perf_ext2
)
5308 nds32_elf_flags
|= E_NDS32_HAS_EXT2_INST
;
5309 skip_flags
|= NASM_ATTR_PERF2_EXT
;
5312 as_bad (_("instruction %s requires enabling performance "
5313 "extension II"), insn
->opcode
->opcode
);
5316 case NASM_ATTR_AUDIO_ISAEXT
:
5318 if (nds32_audio_ext
)
5320 nds32_elf_flags
|= E_NDS32_HAS_AUDIO_INST
;
5321 skip_flags
|= NASM_ATTR_AUDIO_ISAEXT
;
5324 as_bad (_("instruction %s requires enabling AUDIO extension"),
5325 insn
->opcode
->opcode
);
5328 case NASM_ATTR_STR_EXT
:
5330 if (nds32_string_ext
)
5332 nds32_elf_flags
|= E_NDS32_HAS_STRING_INST
;
5333 skip_flags
|= NASM_ATTR_STR_EXT
;
5336 as_bad (_("instruction %s requires enabling STRING extension"),
5337 insn
->opcode
->opcode
);
5342 if (insn
->opcode
->attr
& NASM_ATTR_DXREG
)
5344 if (nds32_div
&& nds32_dx_regs
)
5346 nds32_elf_flags
|= E_NDS32_HAS_DIV_DX_INST
;
5347 skip_flags
|= NASM_ATTR_DIV
;
5350 as_bad (_("instruction %s requires enabling DIV & DX_REGS "
5351 "extension"), insn
->opcode
->opcode
);
5357 if (nds32_fpu_sp_ext
|| nds32_fpu_dp_ext
)
5359 if (!(nds32_elf_flags
5360 & (E_NDS32_HAS_FPU_INST
| E_NDS32_HAS_FPU_DP_INST
)))
5362 skip_flags
|= NASM_ATTR_FPU
;
5365 as_bad (_("instruction %s requires enabling FPU extension"),
5366 insn
->opcode
->opcode
);
5369 case NASM_ATTR_FPU_SP_EXT
:
5371 if (nds32_fpu_sp_ext
)
5373 nds32_elf_flags
|= E_NDS32_HAS_FPU_INST
;
5374 skip_flags
|= NASM_ATTR_FPU_SP_EXT
;
5377 as_bad (_("instruction %s requires enabling FPU_SP extension"),
5378 insn
->opcode
->opcode
);
5381 case NASM_ATTR_FPU_DP_EXT
:
5383 if (nds32_fpu_dp_ext
)
5385 nds32_elf_flags
|= E_NDS32_HAS_FPU_DP_INST
;
5386 skip_flags
|= NASM_ATTR_FPU_DP_EXT
;
5389 as_bad (_("instruction %s requires enabling FPU_DP extension"),
5390 insn
->opcode
->opcode
);
5395 if (insn
->opcode
->attr
& NASM_ATTR_FPU_SP_EXT
)
5397 if (nds32_fpu_sp_ext
&& nds32_mac
)
5398 nds32_elf_flags
|= E_NDS32_HAS_FPU_MAC_INST
;
5400 as_bad (_("instruction %s requires enabling FPU_MAC "
5401 "extension"), insn
->opcode
->opcode
);
5403 else if (insn
->opcode
->attr
& NASM_ATTR_FPU_DP_EXT
)
5405 if (nds32_fpu_dp_ext
&& nds32_mac
)
5406 nds32_elf_flags
|= E_NDS32_HAS_FPU_MAC_INST
;
5408 as_bad (_("instruction %s requires enabling FPU_MAC "
5409 "extension"), insn
->opcode
->opcode
);
5411 else if (insn
->opcode
->attr
& NASM_ATTR_DXREG
)
5413 if (nds32_dx_regs
&& nds32_mac
)
5414 nds32_elf_flags
|= E_NDS32_HAS_MAC_DX_INST
;
5416 as_bad (_("instruction %s requires enabling DX_REGS "
5417 "extension"), insn
->opcode
->opcode
);
5420 if (MAC_COMBO
== (MAC_COMBO
& nds32_elf_flags
))
5421 skip_flags
|= NASM_ATTR_MAC
;
5424 case NASM_ATTR_DSP_ISAEXT
:
5428 nds32_elf_flags
|= E_NDS32_HAS_DSP_INST
;
5429 skip_flags
|= NASM_ATTR_DSP_ISAEXT
;
5432 as_bad (_("instruction %s requires enabling dsp extension"),
5433 insn
->opcode
->opcode
);
5440 nds32_elf_flags
|= E_NDS32_HAS_ZOL
;
5441 skip_flags
|= NASM_ATTR_ZOL
;
5444 as_bad (_("instruction %s requires enabling zol extension"),
5445 insn
->opcode
->opcode
);
5449 as_bad (_("internal error: unknown instruction attribute: 0x%08x"),
5455 /* Flag for analysis relaxation type. */
5457 enum nds32_insn_type
5459 N32_RELAX_SETHI
= 1,
5460 N32_RELAX_BR
= (1 << 1),
5461 N32_RELAX_LSI
= (1 << 2),
5462 N32_RELAX_JUMP
= (1 << 3),
5463 N32_RELAX_CALL
= (1 << 4),
5464 N32_RELAX_ORI
= (1 << 5),
5465 N32_RELAX_MEM
= (1 << 6),
5466 N32_RELAX_MOVI
= (1 << 7),
5467 N32_RELAX_ALU1
= (1 << 8),
5468 N32_RELAX_16BIT
= (1 << 9),
5471 struct nds32_hint_map
5473 /* the preamble relocation */
5474 bfd_reloc_code_real_type hi_type
;
5477 /* relax pattern ID */
5478 enum nds32_relax_hint_type hint_type
;
5480 enum nds32_br_range range
;
5481 /* pattern character flags */
5482 enum nds32_insn_type insn_list
;
5483 /* optional pattern character flags */
5484 enum nds32_insn_type option_list
;
5487 /* Table to match instructions with hint and relax pattern. */
5489 static struct nds32_hint_map hint_map
[] =
5493 BFD_RELOC_NDS32_HI20
,
5495 NDS32_RELAX_HINT_NONE
,
5497 N32_RELAX_SETHI
| N32_RELAX_ORI
| N32_RELAX_CALL
,
5502 _dummy_first_bfd_reloc_code_real
,
5504 NDS32_RELAX_HINT_NONE
,
5506 N32_RELAX_BR
| N32_RELAX_CALL
,
5511 BFD_RELOC_NDS32_HI20
,
5513 NDS32_RELAX_HINT_NONE
,
5515 N32_RELAX_BR
| N32_RELAX_SETHI
| N32_RELAX_ORI
| N32_RELAX_CALL
,
5520 BFD_RELOC_NDS32_HI20
,
5522 NDS32_RELAX_HINT_NONE
,
5524 N32_RELAX_SETHI
| N32_RELAX_ORI
| N32_RELAX_JUMP
,
5529 /* There is two kinds of variation of LONGJUMP5. One of them
5530 generate EMPTY relocation for converted INSN16 if needed.
5531 But we don't distinguish them here. */
5532 _dummy_first_bfd_reloc_code_real
,
5534 NDS32_RELAX_HINT_NONE
,
5536 N32_RELAX_BR
| N32_RELAX_JUMP
,
5541 BFD_RELOC_NDS32_HI20
,
5543 NDS32_RELAX_HINT_NONE
,
5545 N32_RELAX_SETHI
| N32_RELAX_ORI
| N32_RELAX_BR
| N32_RELAX_JUMP
,
5550 _dummy_first_bfd_reloc_code_real
,
5552 NDS32_RELAX_HINT_NONE
,
5554 N32_RELAX_MOVI
| N32_RELAX_BR
,
5558 /* LONGCALL (BAL|JR|LA symbol@PLT). */
5559 BFD_RELOC_NDS32_PLT_GOTREL_HI20
,
5561 NDS32_RELAX_HINT_LA_PLT
,
5563 N32_RELAX_SETHI
| N32_RELAX_ORI
,
5564 N32_RELAX_ALU1
| N32_RELAX_CALL
| N32_RELAX_JUMP
,
5566 /* relative issue: #12566 */
5568 /* LA and Floating LSI. */
5569 BFD_RELOC_NDS32_HI20
,
5571 NDS32_RELAX_HINT_LA_FLSI
,
5573 N32_RELAX_SETHI
| N32_RELAX_ORI
| N32_RELAX_LSI
,
5576 /* relative issue: #11685 #11602 */
5578 /* load address / load-store (LALS). */
5579 BFD_RELOC_NDS32_HI20
,
5581 NDS32_RELAX_HINT_LALS
,
5584 N32_RELAX_ORI
| N32_RELAX_LSI
,
5587 /* setup $GP (_GLOBAL_OFFSET_TABLE_) */
5588 BFD_RELOC_NDS32_GOTPC_HI20
,
5590 NDS32_RELAX_HINT_LALS
,
5592 N32_RELAX_SETHI
| N32_RELAX_ORI
,
5596 /* GOT LA/LS (symbol@GOT) */
5597 BFD_RELOC_NDS32_GOT_HI20
,
5599 NDS32_RELAX_HINT_LA_GOT
,
5601 N32_RELAX_SETHI
| N32_RELAX_ORI
,
5605 /* GOTOFF LA/LS (symbol@GOTOFF) */
5606 BFD_RELOC_NDS32_GOTOFF_HI20
,
5608 NDS32_RELAX_HINT_LA_GOTOFF
,
5610 N32_RELAX_SETHI
| N32_RELAX_ORI
,
5611 N32_RELAX_ALU1
| N32_RELAX_MEM
, /* | N32_RELAX_LSI, */
5614 /* TLS LE LA|LS (@TPOFF) */
5615 BFD_RELOC_NDS32_TLS_LE_HI20
,
5617 NDS32_RELAX_HINT_TLS_LE_LS
,
5619 N32_RELAX_SETHI
| N32_RELAX_ORI
,
5620 N32_RELAX_ALU1
| N32_RELAX_MEM
,
5624 BFD_RELOC_NDS32_TLS_IE_HI20
,
5626 NDS32_RELAX_HINT_TLS_IE_LA
,
5628 N32_RELAX_SETHI
| N32_RELAX_LSI
,
5633 BFD_RELOC_NDS32_TLS_IE_HI20
,
5635 NDS32_RELAX_HINT_TLS_IE_LS
,
5637 N32_RELAX_SETHI
| N32_RELAX_LSI
| N32_RELAX_MEM
,
5642 BFD_RELOC_NDS32_TLS_IEGP_HI20
,
5644 NDS32_RELAX_HINT_TLS_IEGP_LA
,
5646 N32_RELAX_SETHI
| N32_RELAX_ORI
| N32_RELAX_MEM
,
5651 BFD_RELOC_NDS32_TLS_DESC_HI20
,
5653 NDS32_RELAX_HINT_TLS_DESC_LS
,
5655 N32_RELAX_SETHI
| N32_RELAX_ORI
| N32_RELAX_ALU1
| N32_RELAX_CALL
,
5656 N32_RELAX_LSI
| N32_RELAX_MEM
,
5659 {0, NULL
, 0, 0 ,0, 0}
5662 /* Find the relaxation pattern according to instructions. */
5665 nds32_find_reloc_table (struct nds32_relocs_pattern
*relocs_pattern
,
5666 struct nds32_relax_hint_table
*hint_info
)
5668 unsigned int opcode
, seq_size
;
5669 enum nds32_br_range range
;
5670 struct nds32_relocs_pattern
*pattern
, *hi_pattern
= NULL
;
5671 const char *opc
= NULL
;
5672 relax_info_t
*relax_info
= NULL
;
5673 nds32_relax_fixup_info_t
*fixup_info
, *hint_fixup
;
5674 enum nds32_relax_hint_type hint_type
= NDS32_RELAX_HINT_NONE
;
5675 struct nds32_relax_hint_table
*table_ptr
;
5676 uint32_t *code_seq
, *hint_code
;
5677 enum nds32_insn_type relax_type
= 0;
5678 struct nds32_hint_map
*map_ptr
= hint_map
;
5680 const char *check_insn
[] =
5681 { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8" };
5683 /* TODO: PLT GOT. */
5684 /* Traverse all pattern instruction and set flag. */
5685 pattern
= relocs_pattern
;
5688 if (pattern
->opcode
->isize
== 4)
5690 /* 4 byte instruction. */
5691 opcode
= N32_OP6 (pattern
->opcode
->value
);
5695 hi_pattern
= pattern
;
5696 relax_type
|= N32_RELAX_SETHI
;
5699 relax_type
|= N32_RELAX_MEM
;
5702 relax_type
|= N32_RELAX_ALU1
;
5705 relax_type
|= N32_RELAX_ORI
;
5710 relax_type
|= N32_RELAX_BR
;
5713 relax_type
|= N32_RELAX_MOVI
;
5727 relax_type
|= N32_RELAX_LSI
;
5730 if (__GF (pattern
->opcode
->value
, 0, 1) == 1)
5731 relax_type
|= N32_RELAX_CALL
;
5733 relax_type
|= N32_RELAX_JUMP
;
5736 if (__GF (pattern
->opcode
->value
, 24, 1) == 1)
5737 relax_type
|= N32_RELAX_CALL
;
5739 relax_type
|= N32_RELAX_JUMP
;
5742 as_warn (_("relax hint unrecognized instruction: line %d."),
5743 pattern
->frag
->fr_line
);
5749 /* 2 byte instruction. Compare by opcode name because
5750 the opcode of 2byte instruction is not regular. */
5752 for (i
= 0; i
< ARRAY_SIZE (check_insn
); i
++)
5754 if (strcmp (pattern
->opcode
->opcode
, check_insn
[i
]) == 0)
5756 relax_type
|= N32_RELAX_BR
;
5762 relax_type
|= N32_RELAX_16BIT
;
5764 pattern
= pattern
->next
;
5767 /* Analysis instruction flag to choose relaxation table. */
5768 while (map_ptr
->insn_list
!= 0)
5770 struct nds32_hint_map
*hint
= map_ptr
++;
5771 enum nds32_insn_type must
= hint
->insn_list
;
5772 enum nds32_insn_type optional
= hint
->option_list
;
5773 enum nds32_insn_type extra
;
5775 if (must
!= (must
& relax_type
))
5778 extra
= relax_type
^ must
;
5779 if (extra
!= (extra
& optional
))
5783 || (hi_pattern
->fixP
5784 && hi_pattern
->fixP
->fx_r_type
== hint
->hi_type
))
5787 hint_type
= hint
->hint_type
;
5788 range
= hint
->range
;
5794 if (map_ptr
->insn_list
== 0)
5797 as_warn (_("Can not find match relax hint. Line: %d"),
5798 relocs_pattern
->frag
->fr_line
);
5802 /* Get the match table. */
5805 /* Branch relax pattern. */
5806 relax_info
= str_hash_find (nds32_relax_info_hash
, opc
);
5809 fixup_info
= relax_info
->relax_fixup
[range
];
5810 code_seq
= relax_info
->relax_code_seq
[range
];
5811 seq_size
= relax_info
->relax_code_size
[range
];
5815 /* Load-store relax pattern. */
5816 table_ptr
= relax_ls_table
;
5817 while (table_ptr
->main_type
!= 0)
5819 if (table_ptr
->main_type
== hint_type
)
5821 fixup_info
= table_ptr
->relax_fixup
;
5822 code_seq
= table_ptr
->relax_code_seq
;
5823 seq_size
= table_ptr
->relax_code_size
;
5828 if (table_ptr
->main_type
== 0)
5834 hint_fixup
= hint_info
->relax_fixup
;
5835 hint_code
= hint_info
->relax_code_seq
;
5836 hint_info
->relax_code_size
= seq_size
;
5838 while (fixup_info
->size
!= 0)
5840 if (fixup_info
->ramp
& NDS32_HINT
)
5842 memcpy (hint_fixup
, fixup_info
, sizeof (nds32_relax_fixup_info_t
));
5847 /* Clear final relocation. */
5848 memset (hint_fixup
, 0, sizeof (nds32_relax_fixup_info_t
));
5849 /* Copy code sequence. */
5850 memcpy (hint_code
, code_seq
, seq_size
);
5854 /* Because there are a lot of variant of load-store, check
5855 all these type here. */
5857 #define CLEAN_REG(insn) ((insn) & 0xfe0003ff)
5858 #define GET_OPCODE(insn) ((insn) & 0xfe000000)
5861 nds32_match_hint_insn (struct nds32_opcode
*opcode
, uint32_t seq
)
5863 const char *check_insn
[] =
5864 { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8", "jral5" };
5865 uint32_t insn
= opcode
->value
;
5868 insn
= CLEAN_REG (opcode
->value
);
5875 /* In relocation_table, it regards instruction LBI as representation
5876 of all the NDS32_RELAX_HINT_LS pattern. */
5877 if (insn
== OP6 (LBI
) || insn
== OP6 (SBI
) || insn
== OP6 (LBSI
)
5878 || insn
== OP6 (LHI
) || insn
== OP6 (SHI
) || insn
== OP6 (LHSI
)
5879 || insn
== OP6 (LWI
) || insn
== OP6 (SWI
)
5880 || insn
== OP6 (LWC
) || insn
== OP6 (SWC
)
5881 || insn
== OP6 (LDC
) || insn
== OP6 (SDC
))
5885 /* This is for LONGCALL5 and LONGCALL6. */
5886 if (insn
== OP6 (BR2
))
5890 /* This is for LONGJUMP5 and LONGJUMP6. */
5891 if (opcode
->isize
== 4
5892 && (insn
== OP6 (BR1
) || insn
== OP6 (BR2
) || insn
== OP6 (BR3
)))
5894 else if (opcode
->isize
== 2)
5896 for (i
= 0; i
< ARRAY_SIZE (check_insn
); i
++)
5897 if (strcmp (opcode
->opcode
, check_insn
[i
]) == 0)
5902 /* This is for LONGJUMP7. */
5903 if (opcode
->isize
== 2 && strcmp (opcode
->opcode
, "movi55") == 0)
5907 if (OP6 (MEM
) == GET_OPCODE (insn
))
5911 /* bit 24: N32_JI_JAL */ /* feed me! */
5912 if ((insn
& ~(N32_BIT (24))) == JREG (JRAL
))
5916 if (opcode
->isize
== 2)
5918 for (i
= 0; i
< ARRAY_SIZE (check_insn
); i
++)
5919 if (strcmp (opcode
->opcode
, check_insn
[i
]) == 0)
5922 if ((strcmp (opcode
->opcode
, "add5.pc") == 0) ||
5923 (strcmp (opcode
->opcode
, "add45") == 0))
5930 /* Append relax relocation for link time relaxing. */
5933 nds32_elf_append_relax_relocs (const char *key
, const void *value
)
5935 struct nds32_relocs_pattern
*relocs_pattern
=
5936 (struct nds32_relocs_pattern
*) value
;
5937 struct nds32_relocs_pattern
*pattern_temp
, *pattern_now
;
5938 symbolS
*sym
, *hi_sym
= NULL
;
5941 segT seg_bak
= now_seg
;
5942 frchainS
*frchain_bak
= frchain_now
;
5943 struct nds32_relax_hint_table hint_info
;
5944 nds32_relax_fixup_info_t
*hint_fixup
, *fixup_now
;
5946 offsetT branch_offset
, hi_branch_offset
= 0;
5949 unsigned int ptr_offset
, hint_count
, relax_code_size
, count
= 0;
5950 uint32_t *code_seq
, code_insn
;
5954 if (!relocs_pattern
)
5957 if (!nds32_find_reloc_table (relocs_pattern
, &hint_info
))
5960 /* Save symbol for some EMPTY relocation using. */
5961 pattern_now
= relocs_pattern
;
5964 if (pattern_now
->opcode
->value
== OP6 (SETHI
))
5966 hi_sym
= pattern_now
->sym
;
5967 hi_branch_offset
= pattern_now
->fixP
->fx_offset
;
5970 pattern_now
= pattern_now
->next
;
5973 /* Inserting fix up must specify now_seg or frchain_now. */
5974 now_seg
= relocs_pattern
->seg
;
5975 frchain_now
= relocs_pattern
->frchain
;
5976 fragP
= relocs_pattern
->frag
;
5977 branch_offset
= fragP
->fr_offset
;
5979 hint_fixup
= hint_info
.relax_fixup
;
5980 code_seq
= hint_info
.relax_code_seq
;
5981 relax_code_size
= hint_info
.relax_code_size
;
5982 pattern_now
= relocs_pattern
;
5984 #ifdef NDS32_LINUX_TOOLCHAIN
5985 /* prepare group relocation ID (number). */
5989 /* convert .relax_hint key to number */
5991 group_id
= strtol (key
, NULL
, 10);
5992 if ((errno
== ERANGE
&& (group_id
== LONG_MAX
|| group_id
== LONG_MIN
))
5993 || (errno
!= 0 && group_id
== 0))
5995 as_bad (_("Internal error: .relax_hint KEY is not a number!"));
6001 /* Insert relaxation. */
6002 exp
.X_op
= O_symbol
;
6004 /* For each instruction in the hint group. */
6007 if (count
>= relax_code_size
/ 4)
6010 /* Choose the match fixup by instruction. */
6011 code_insn
= CLEAN_REG (*(code_seq
+ count
));
6012 if (!nds32_match_hint_insn (pattern_now
->opcode
, code_insn
))
6014 /* Try search from head again */
6016 code_insn
= CLEAN_REG (*(code_seq
+ count
));
6018 while (!nds32_match_hint_insn (pattern_now
->opcode
, code_insn
))
6021 if (count
>= relax_code_size
/ 4)
6023 as_bad (_("Internal error: Relax hint (%s) error. %s: %s (%x)"),
6026 pattern_now
->opcode
->opcode
,
6027 pattern_now
->opcode
->value
);
6030 code_insn
= CLEAN_REG (*(code_seq
+ count
));
6033 fragP
= pattern_now
->frag
;
6034 sym
= pattern_now
->sym
;
6035 branch_offset
= fragP
->fr_offset
;
6037 where
= pattern_now
->where
;
6038 /* Find the instruction map fix. */
6039 fixup_now
= hint_fixup
;
6040 while (fixup_now
->offset
!= offset
)
6043 if (fixup_now
->size
== 0)
6046 /* This element is without relaxation relocation. */
6047 if (fixup_now
->size
== 0)
6049 pattern_now
= pattern_now
->next
;
6052 fixup_size
= fixup_now
->size
;
6054 /* Insert all fixup. */
6056 while (fixup_size
!= 0 && fixup_now
->offset
== offset
)
6058 /* Set the real instruction size in element. */
6059 fixup_size
= pattern_now
->opcode
->isize
;
6060 pcrel
= ((fixup_now
->ramp
& NDS32_PCREL
) != 0) ? 1 : 0;
6061 if (fixup_now
->ramp
& NDS32_FIX
)
6063 /* Convert original relocation. */
6064 pattern_now
->fixP
->fx_r_type
= fixup_now
->r_type
;
6067 else if ((fixup_now
->ramp
& NDS32_PTR
) != 0)
6069 /* This relocation has to point to another instruction. Make
6070 sure each resolved relocation has to be pointed. */
6071 pattern_temp
= relocs_pattern
;
6072 /* All instruction in relax_table should be 32-bit. */
6073 hint_count
= hint_info
.relax_code_size
/ 4;
6074 code_insn
= CLEAN_REG (*(code_seq
+ hint_count
- 1));
6075 while (pattern_temp
)
6077 /* Point to every resolved relocation. */
6078 if (nds32_match_hint_insn (pattern_temp
->opcode
, code_insn
))
6081 pattern_temp
->where
- pattern_temp
->frag
->fr_literal
;
6082 exp
.X_add_symbol
= symbol_temp_new (now_seg
,
6085 exp
.X_add_number
= 0;
6087 fix_new_exp (fragP
, where
- fragP
->fr_literal
,
6088 fixup_size
, &exp
, 0, fixup_now
->r_type
);
6089 fixP
->fx_addnumber
= fixP
->fx_offset
;
6091 pattern_temp
= pattern_temp
->next
;
6095 else if (fixup_now
->ramp
& NDS32_ADDEND
)
6097 range
= nds32_elf_sethi_range (relocs_pattern
);
6098 if (range
== NDS32_LOADSTORE_NONE
)
6100 as_bad (_("Internal error: Range error. %s"), now_seg
->name
);
6103 exp
.X_add_symbol
= abs_section_sym
;
6104 exp
.X_add_number
= SET_ADDEND (4, 0, optimize
, enable_16bit
);
6105 exp
.X_add_number
|= ((range
& 0x3f) << 8);
6107 else if ((fixup_now
->ramp
& NDS32_ABS
) != 0)
6109 /* This is a tag relocation. */
6110 exp
.X_add_symbol
= abs_section_sym
;
6111 exp
.X_add_number
= 0;
6113 else if ((fixup_now
->ramp
& NDS32_INSN16
) != 0)
6117 /* This is a tag relocation. */
6118 exp
.X_add_symbol
= abs_section_sym
;
6119 exp
.X_add_number
= 0;
6121 else if ((fixup_now
->ramp
& NDS32_SYM
) != 0)
6123 /* For EMPTY relocation save the true symbol. */
6124 exp
.X_add_symbol
= hi_sym
;
6125 exp
.X_add_number
= hi_branch_offset
;
6127 else if (NDS32_SYM_DESC_MEM
& fixup_now
->ramp
)
6129 /* Do the same as NDS32_SYM. */
6130 exp
.X_add_symbol
= hi_sym
;
6131 exp
.X_add_number
= hi_branch_offset
;
6133 /* Extra to NDS32_SYM. */
6134 /* Detect if DESC_FUNC relax type do apply. */
6135 if ((REG_GP
== N32_RA5 (pattern_now
->insn
))
6136 || (REG_GP
== N32_RB5 (pattern_now
->insn
)))
6138 fixP
= fix_new_exp (fragP
, where
- fragP
->fr_literal
,
6139 fixup_size
, &exp
, pcrel
,
6140 BFD_RELOC_NDS32_TLS_DESC_FUNC
);
6141 fixP
->fx_addnumber
= fixP
->fx_offset
;
6145 /* Else do as usual. */
6147 else if (fixup_now
->ramp
& NDS32_PTR_PATTERN
)
6149 /* Find out PTR_RESOLVED code pattern. */
6150 nds32_relax_fixup_info_t
*next_fixup
= fixup_now
+ 1;
6151 uint32_t resolved_pattern
= 0;
6152 while (next_fixup
->offset
)
6154 if (next_fixup
->r_type
== BFD_RELOC_NDS32_PTR_RESOLVED
)
6156 uint32_t new_pattern
= code_seq
[next_fixup
->offset
>> 2];
6157 if (!resolved_pattern
)
6158 resolved_pattern
= new_pattern
;
6159 else if (new_pattern
!= resolved_pattern
)
6161 as_warn (_("Multiple BFD_RELOC_NDS32_PTR_RESOLVED "
6162 "patterns are not supported yet!"));
6169 /* Find matched code and insert fix-ups. */
6170 struct nds32_relocs_pattern
*next_pattern
= pattern_now
->next
;
6171 /* This relocation has to point to another instruction.
6172 Make sure each resolved relocation has to be pointed. */
6173 /* All instruction in relax_table should be 32-bit. */
6174 while (next_pattern
)
6176 uint32_t cur_pattern
= GET_OPCODE (next_pattern
->opcode
->value
);
6177 if (cur_pattern
== resolved_pattern
)
6179 ptr_offset
= next_pattern
->where
6180 - next_pattern
->frag
->fr_literal
;
6181 exp
.X_add_symbol
= symbol_temp_new (now_seg
,
6184 exp
.X_add_number
= 0;
6185 fixP
= fix_new_exp (fragP
, where
- fragP
->fr_literal
,
6186 fixup_size
, &exp
, 0,
6188 fixP
->fx_addnumber
= fixP
->fx_offset
;
6190 next_pattern
= next_pattern
->next
;
6195 else if (fixup_now
->ramp
& NDS32_PTR_MULTIPLE
)
6197 /* Find each PTR_RESOLVED pattern after PTR. */
6198 nds32_relax_fixup_info_t
*next_fixup
= fixup_now
+ 1;
6199 while (next_fixup
->offset
)
6201 if (next_fixup
->r_type
== BFD_RELOC_NDS32_PTR_RESOLVED
)
6203 uint32_t pattern
= code_seq
[next_fixup
->offset
>> 2];
6204 /* Find matched code to insert fix-ups. */
6205 struct nds32_relocs_pattern
*next_insn
= pattern_now
->next
;
6208 uint32_t insn_pattern
= GET_OPCODE (next_insn
->opcode
->value
);
6209 if (insn_pattern
== pattern
)
6211 ptr_offset
= next_insn
->where
6212 - next_insn
->frag
->fr_literal
;
6213 exp
.X_add_symbol
= symbol_temp_new (now_seg
,
6216 exp
.X_add_number
= 0;
6217 fixP
= fix_new_exp (fragP
,
6218 where
- fragP
->fr_literal
,
6219 fixup_size
, &exp
, 0,
6221 fixP
->fx_addnumber
= fixP
->fx_offset
;
6223 next_insn
= next_insn
->next
;
6232 exp
.X_add_symbol
= sym
;
6233 exp
.X_add_number
= branch_offset
;
6236 if (fixup_size
!= 0)
6238 fixP
= fix_new_exp (fragP
, where
- fragP
->fr_literal
, fixup_size
,
6239 &exp
, pcrel
, fixup_now
->r_type
);
6240 fixP
->fx_addnumber
= fixP
->fx_offset
;
6243 fixup_size
= fixup_now
->size
;
6246 #ifdef NDS32_LINUX_TOOLCHAIN
6247 /* Insert group relocation for each relax hint. */
6250 exp
.X_add_symbol
= hi_sym
; /* for eyes only */
6251 exp
.X_add_number
= group_id
;
6252 fixP
= fix_new_exp (fragP
, where
- fragP
->fr_literal
, fixup_size
,
6253 &exp
, pcrel
, BFD_RELOC_NDS32_GROUP
);
6254 fixP
->fx_addnumber
= fixP
->fx_offset
;
6258 if (count
< relax_code_size
/ 4)
6260 pattern_now
= pattern_now
->next
;
6265 frchain_now
= frchain_bak
;
6269 nds32_elf_append_relax_relocs_traverse (void **slot
, void *arg ATTRIBUTE_UNUSED
)
6271 string_tuple_t
*tuple
= *((string_tuple_t
**) slot
);
6272 nds32_elf_append_relax_relocs (tuple
->key
, tuple
->value
);
6278 nds32_str_tolower (const char *src
, char *dest
)
6280 unsigned int i
, len
;
6284 for (i
= 0; i
< len
; i
++)
6285 *(dest
+ i
) = TOLOWER (*(src
+ i
));
6290 /* Check instruction if it can be used for the baseline. */
6293 nds32_check_insn_available (struct nds32_asm_insn insn
, const char *str
)
6295 int attr
= insn
.attr
& ATTR_ALL
;
6296 static int baseline_isa
= 0;
6299 s
= xmalloc (strlen (str
) + 1);
6300 nds32_str_tolower (str
, s
);
6302 && (((insn
.opcode
->value
== ALU2 (MTUSR
)
6303 || insn
.opcode
->value
== ALU2 (MFUSR
))
6304 && (strstr (s
, "lc")
6306 || strstr (s
, "lb")))
6307 || (insn
.attr
& NASM_ATTR_ZOL
)))
6309 as_bad (_("Not support instruction %s in verbatim."), str
);
6314 if (!enable_16bit
&& insn
.opcode
->isize
== 2)
6316 as_bad (_("16-bit instruction is disabled: %s."), str
);
6320 /* No isa setting or all isa can use. */
6321 if (attr
== 0 || attr
== ATTR_ALL
)
6324 if (baseline_isa
== 0)
6326 /* Map option baseline and instruction attribute. */
6327 switch (nds32_baseline
)
6330 baseline_isa
= ATTR (ISA_V2
);
6333 baseline_isa
= ATTR (ISA_V3
);
6336 baseline_isa
= ATTR (ISA_V3M
);
6341 if ((baseline_isa
& attr
) == 0)
6343 as_bad (_("Instruction %s not supported in the baseline."), str
);
6349 /* Stub of machine dependent. */
6352 md_assemble (char *str
)
6354 struct nds32_asm_insn insn
;
6356 struct nds32_pseudo_opcode
*popcode
;
6357 const struct nds32_field
*fld
= NULL
;
6360 struct nds32_relocs_pattern
*relocs_temp
;
6361 struct nds32_relocs_group
*group_temp
;
6363 int label
= label_exist
;
6364 static bool pseudo_hint
= false;
6366 popcode
= nds32_lookup_pseudo_opcode (str
);
6367 /* Note that we need to check 'verbatim' and
6368 'opcode->physical_op'. If the assembly content is generated by
6369 compiler and this opcode is a physical instruction, there is no
6370 need to perform pseudo instruction expansion/transformation. */
6371 if (popcode
&& !(verbatim
&& popcode
->physical_op
))
6373 /* Pseudo instruction is with relax_hint. */
6376 pseudo_opcode
= true;
6377 nds32_pseudo_opcode_wrapper (str
, popcode
);
6378 pseudo_opcode
= false;
6379 pseudo_hint
= false;
6380 nds32_elf_append_relax_relocs (NULL
, relocs_list
);
6382 /* Free relax_hint group list. */
6383 while (nds32_relax_hint_current
)
6385 group_temp
= nds32_relax_hint_current
->next
;
6386 free (nds32_relax_hint_current
);
6387 nds32_relax_hint_current
= group_temp
;
6390 /* Free pseudo list. */
6391 relocs_temp
= relocs_list
;
6394 relocs_list
= relocs_list
->next
;
6396 relocs_temp
= relocs_list
;
6403 insn
.info
= XNEW (expressionS
);
6404 asm_desc
.result
= NASM_OK
;
6405 nds32_assemble (&asm_desc
, &insn
, str
);
6407 switch (asm_desc
.result
)
6409 case NASM_ERR_UNKNOWN_OP
:
6410 as_bad (_("Unrecognized opcode, %s."), str
);
6412 case NASM_ERR_SYNTAX
:
6413 as_bad (_("Incorrect syntax, %s."), str
);
6415 case NASM_ERR_OPERAND
:
6416 as_bad (_("Unrecognized operand/register, %s."), str
);
6418 case NASM_ERR_OUT_OF_RANGE
:
6419 as_bad (_("Operand out of range, %s."), str
);
6421 case NASM_ERR_REG_REDUCED
:
6422 as_bad (_("Prohibited register used for reduced-register, %s."), str
);
6424 case NASM_ERR_JUNK_EOL
:
6425 as_bad (_("Junk at end of line, %s."), str
);
6429 gas_assert (insn
.opcode
);
6431 nds32_set_elf_flags_by_insn (&insn
);
6433 gas_assert (insn
.opcode
->isize
== 4 || insn
.opcode
->isize
== 2);
6435 if (!nds32_check_insn_available (insn
, str
))
6438 /* Make sure the beginning of text being 2-byte align. */
6439 nds32_adjust_label (1);
6440 add_mapping_symbol (MAP_CODE
, 0, 0);
6442 /* Try to allocate the max size to guarantee relaxable same branch
6443 instructions in the same fragment. */
6444 frag_grow (NDS32_MAXCHAR
);
6447 if (fld
&& (insn
.attr
& NASM_ATTR_BRANCH
)
6448 && (pseudo_opcode
|| (insn
.opcode
->value
!= INSN_JAL
6449 && insn
.opcode
->value
!= INSN_J
))
6450 && (!verbatim
|| pseudo_opcode
))
6452 /* User assembly code branch relax for it. */
6453 /* If fld is not NULL, it is a symbol. */
6454 /* Branch must relax to proper pattern in user assembly code exclude
6455 J and JAL. Keep these two in original type for users which wants
6456 to keep their size be fixed. In general, assembler does not convert
6457 instruction generated by compiler. But jump instruction may be
6458 truncated in text virtual model. For workaround, compiler generate
6459 pseudo jump to fix this issue currently. */
6461 /* Get branch range type. */
6462 dwarf2_emit_insn (0);
6463 enum nds32_br_range range_type
;
6464 expressionS
*pexp
= insn
.info
;
6466 range_type
= get_range_type (fld
);
6468 out
= frag_var (rs_machine_dependent
, NDS32_MAXCHAR
,
6469 0, /* VAR is un-used. */
6470 range_type
, /* SUBTYPE is used as range type. */
6471 pexp
->X_add_symbol
, pexp
->X_add_number
, 0);
6473 fragP
->fr_fix
+= insn
.opcode
->isize
;
6474 fragP
->tc_frag_data
.opcode
= insn
.opcode
;
6475 fragP
->tc_frag_data
.insn
= insn
.insn
;
6476 if (insn
.opcode
->isize
== 4)
6477 bfd_putb32 (insn
.insn
, out
);
6478 else if (insn
.opcode
->isize
== 2)
6479 bfd_putb16 (insn
.insn
, out
);
6480 fragP
->tc_frag_data
.flag
|= NDS32_FRAG_BRANCH
;
6484 /* md_convert_frag will insert relocations. */
6486 else if (!relaxing
&& enable_16bit
&& (optimize
|| optimize_for_space
)
6487 && ((!fld
&& !verbatim
&& insn
.opcode
->isize
== 4
6488 && nds32_convert_32_to_16 (stdoutput
, insn
.insn
, &insn_16
, NULL
))
6489 || (insn
.opcode
->isize
== 2
6490 && nds32_convert_16_to_32 (stdoutput
, insn
.insn
, NULL
))))
6492 /* Record this one is relaxable. */
6493 expressionS
*pexp
= insn
.info
;
6494 dwarf2_emit_insn (0);
6497 out
= frag_var (rs_machine_dependent
,
6498 4, /* Max size is 32-bit instruction. */
6499 0, /* VAR is un-used. */
6500 0, pexp
->X_add_symbol
, pexp
->X_add_number
, 0);
6501 fragP
->tc_frag_data
.flag
|= NDS32_FRAG_RELAXABLE_BRANCH
;
6504 out
= frag_var (rs_machine_dependent
,
6505 4, /* Max size is 32-bit instruction. */
6506 0, /* VAR is un-used. */
6508 fragP
->tc_frag_data
.flag
|= NDS32_FRAG_RELAXABLE
;
6509 fragP
->tc_frag_data
.opcode
= insn
.opcode
;
6510 fragP
->tc_frag_data
.insn
= insn
.insn
;
6513 /* In original, we don't relax the instruction with label on it,
6514 but this may cause some redundant nop16. Therefore, tag this
6515 relaxable instruction and relax it carefully. */
6517 fragP
->tc_frag_data
.flag
|= NDS32_FRAG_LABEL
;
6519 if (insn
.opcode
->isize
== 4)
6520 bfd_putb16 (insn_16
, out
);
6521 else if (insn
.opcode
->isize
== 2)
6522 bfd_putb16 (insn
.insn
, out
);
6527 else if ((verbatim
|| !relaxing
) && optimize
&& label
)
6529 /* This instruction is with label. */
6531 out
= frag_var (rs_machine_dependent
, insn
.opcode
->isize
,
6532 0, 0, NULL
, 0, NULL
);
6533 /* If this instruction is branch target, it is not relaxable. */
6534 fragP
->tc_frag_data
.flag
= NDS32_FRAG_LABEL
;
6535 fragP
->tc_frag_data
.opcode
= insn
.opcode
;
6536 fragP
->tc_frag_data
.insn
= insn
.insn
;
6537 fragP
->fr_fix
+= insn
.opcode
->isize
;
6538 if (insn
.opcode
->isize
== 4)
6540 exp
.X_op
= O_symbol
;
6541 exp
.X_add_symbol
= abs_section_sym
;
6542 exp
.X_add_number
= 0;
6543 fixP
= fix_new_exp (fragP
, fragP
->fr_fix
- 4, 0, &exp
,
6544 0, BFD_RELOC_NDS32_LABEL
);
6546 fragP
->tc_frag_data
.flag
= NDS32_FRAG_ALIGN
;
6550 out
= frag_more (insn
.opcode
->isize
);
6552 if (insn
.opcode
->isize
== 4)
6553 bfd_putb32 (insn
.insn
, out
);
6554 else if (insn
.opcode
->isize
== 2)
6555 bfd_putb16 (insn
.insn
, out
);
6557 dwarf2_emit_insn (insn
.opcode
->isize
);
6559 /* Compiler generating code and user assembly pseudo load-store, insert
6561 expressionS
*pexp
= insn
.info
;
6562 fixP
= nds32_elf_record_fixup_exp (fragP
, str
, fld
, pexp
, out
, &insn
);
6563 /* Build relaxation pattern when relaxing is enable. */
6565 nds32_elf_build_relax_relation (fixP
, pexp
, out
, &insn
, fragP
, fld
,
6571 /* md_macro_start */
6574 nds32_macro_start (void)
6581 nds32_macro_info (void *info ATTRIBUTE_UNUSED
)
6588 nds32_macro_end (void)
6592 /* GAS will call this function with one argument, an expressionS pointer, for
6593 any expression that can not be recognized. When the function is called,
6594 input_line_pointer will point to the start of the expression. */
6597 md_operand (expressionS
*expressionP
)
6599 if (*input_line_pointer
== '#')
6601 input_line_pointer
++;
6602 expression (expressionP
);
6606 /* GAS will call this function for each section at the end of the assembly, to
6607 permit the CPU back end to adjust the alignment of a section. The function
6608 must take two arguments, a segT for the section and a valueT for the size of
6609 the section, and return a valueT for the rounded size. */
6612 md_section_align (segT segment
, valueT size
)
6614 int align
= bfd_section_alignment (segment
);
6616 return ((size
+ (1 << align
) - 1) & ((valueT
) -1 << align
));
6619 /* GAS will call this function when a symbol table lookup fails, before it
6620 creates a new symbol. Typically this would be used to supply symbols whose
6621 name or value changes dynamically, possibly in a context sensitive way.
6622 Predefined symbols with fixed values, such as register names or condition
6623 codes, are typically entered directly into the symbol table when md_begin
6624 is called. One argument is passed, a char * for the symbol. */
6627 md_undefined_symbol (char *name ATTRIBUTE_UNUSED
)
6633 nds32_calc_branch_offset (segT segment
, fragS
*fragP
,
6634 long stretch ATTRIBUTE_UNUSED
,
6635 relax_info_t
*relax_info
,
6636 enum nds32_br_range branch_range_type
)
6638 struct nds32_opcode
*opcode
= fragP
->tc_frag_data
.opcode
;
6639 symbolS
*branch_symbol
= fragP
->fr_symbol
;
6640 offsetT branch_offset
= fragP
->fr_offset
;
6641 offsetT branch_target_address
;
6642 offsetT branch_insn_address
;
6645 if ((S_GET_SEGMENT (branch_symbol
) != segment
)
6646 || S_IS_WEAK (branch_symbol
))
6648 /* The symbol is not in the SEGMENT. It could be far far away. */
6649 offset
= 0x80000000;
6653 /* Calculate symbol-to-instruction offset. */
6654 branch_target_address
= S_GET_VALUE (branch_symbol
) + branch_offset
;
6655 /* If the destination symbol is beyond current frag address,
6656 STRETCH will take effect to symbol's position. */
6657 if (S_GET_VALUE (branch_symbol
) > fragP
->fr_address
)
6658 branch_target_address
+= stretch
;
6660 branch_insn_address
= fragP
->fr_address
+ fragP
->fr_fix
;
6661 branch_insn_address
-= opcode
->isize
;
6663 /* Update BRANCH_INSN_ADDRESS to relaxed position. */
6664 branch_insn_address
+= (relax_info
->relax_code_size
[branch_range_type
]
6665 - relax_info
->relax_branch_isize
[branch_range_type
]);
6667 offset
= branch_target_address
- branch_insn_address
;
6673 static enum nds32_br_range
6674 nds32_convert_to_range_type (long offset
)
6676 enum nds32_br_range range_type
;
6678 if (-(0x100) <= offset
&& offset
< 0x100) /* 256 bytes */
6679 range_type
= BR_RANGE_S256
;
6680 else if (-(0x4000) <= offset
&& offset
< 0x4000) /* 16K bytes */
6681 range_type
= BR_RANGE_S16K
;
6682 else if (-(0x10000) <= offset
&& offset
< 0x10000) /* 64K bytes */
6683 range_type
= BR_RANGE_S64K
;
6684 else if (-(0x1000000) <= offset
&& offset
< 0x1000000) /* 16M bytes */
6685 range_type
= BR_RANGE_S16M
;
6687 range_type
= BR_RANGE_U4G
;
6692 /* Set instruction register mask. */
6695 nds32_elf_get_set_cond (relax_info_t
*relax_info
, int offset
, uint32_t *insn
,
6696 uint32_t ori_insn
, int range
)
6698 nds32_cond_field_t
*cond_fields
= relax_info
->cond_field
;
6699 nds32_cond_field_t
*code_seq_cond
= relax_info
->relax_code_condition
[range
];
6703 /* The instruction has conditions. Collect condition values. */
6704 while (code_seq_cond
[i
].bitmask
!= 0)
6706 if (offset
== code_seq_cond
[i
].offset
)
6708 mask
= (ori_insn
>> cond_fields
[i
].bitpos
) & cond_fields
[i
].bitmask
;
6710 if (cond_fields
[i
].signed_extend
)
6711 mask
= (mask
^ ((cond_fields
[i
].bitmask
+ 1) >> 1)) -
6712 ((cond_fields
[i
].bitmask
+ 1) >> 1);
6713 *insn
|= (mask
& code_seq_cond
[i
].bitmask
) << code_seq_cond
[i
].bitpos
;
6720 nds32_relax_branch_instructions (segT segment
, fragS
*fragP
,
6721 long stretch ATTRIBUTE_UNUSED
,
6724 enum nds32_br_range branch_range_type
;
6725 struct nds32_opcode
*opcode
= fragP
->tc_frag_data
.opcode
;
6727 enum nds32_br_range real_range_type
;
6729 relax_info_t
*relax_info
;
6736 int code_seq_offset
;
6738 /* Replace with gas_assert (fragP->fr_symbol != NULL); */
6739 if (fragP
->fr_symbol
== NULL
)
6742 /* If frag_var is not enough room, the previous frag is fr_full and with
6743 opcode. The new one is rs_dependent but without opcode. */
6747 /* Use U4G mode for b and bal in verbatim mode because lto may combine
6748 functions into a file. And order the file in the last when linking.
6749 Once there is multiple definition, the same function will be kicked.
6750 This may cause relocation truncated error. */
6751 if (verbatim
&& !nds32_pic
6752 && (strcmp (opcode
->opcode
, "j") == 0
6753 || strcmp (opcode
->opcode
, "jal") == 0))
6755 fragP
->fr_subtype
= BR_RANGE_U4G
;
6762 relax_info
= str_hash_find (nds32_relax_info_hash
, opcode
->opcode
);
6764 if (relax_info
== NULL
)
6769 branch_range_type
= relax_info
->br_range
;
6774 branch_range_type
= fragP
->fr_subtype
;
6775 i
= branch_range_type
;
6778 offset
= nds32_calc_branch_offset (segment
, fragP
, stretch
,
6779 relax_info
, branch_range_type
);
6781 real_range_type
= nds32_convert_to_range_type (offset
);
6783 /* If actual range is equal to instruction jump range, do nothing. */
6784 if (real_range_type
== branch_range_type
)
6786 fragP
->fr_subtype
= real_range_type
;
6790 /* Find out proper relaxation code sequence. */
6791 for (; i
< BR_RANGE_NUM
; i
++)
6793 if (real_range_type
<= (unsigned int) i
)
6796 diff
= relax_info
->relax_code_size
[i
] - opcode
->isize
;
6797 else if (real_range_type
< (unsigned int) i
)
6798 diff
= relax_info
->relax_code_size
[real_range_type
]
6799 - relax_info
->relax_code_size
[branch_range_type
];
6801 diff
= relax_info
->relax_code_size
[i
]
6802 - relax_info
->relax_code_size
[branch_range_type
];
6804 /* If the instruction could be converted to 16-bits,
6805 minus the difference. */
6806 code_seq_offset
= 0;
6809 code_seq_size
= relax_info
->relax_code_size
[i
];
6810 code_seq
= relax_info
->relax_code_seq
[i
];
6811 while (code_seq_offset
< code_seq_size
)
6814 if (insn
& 0x80000000) /* 16-bits instruction. */
6818 else /* 32-bits instruction. */
6822 while (relax_info
->relax_fixup
[i
][k
].size
!=0
6823 && relax_info
->relax_fixup
[i
][k
].offset
< code_seq_offset
)
6827 code_seq_offset
+= insn_size
;
6831 /* Update fr_subtype to new NDS32_BR_RANGE. */
6832 fragP
->fr_subtype
= real_range_type
;
6837 return diff
+ adjust
;
6840 /* Adjust relaxable frag till current frag. */
6843 nds32_adjust_relaxable_frag (fragS
*startP
, fragS
*fragP
)
6846 if (startP
->tc_frag_data
.flag
& NDS32_FRAG_RELAXED
)
6851 startP
->tc_frag_data
.flag
^= NDS32_FRAG_RELAXED
;
6855 startP
= startP
->fr_next
;
6858 startP
->fr_address
+= adj
;
6859 if (startP
== fragP
)
6867 nds32_get_align (addressT address
, int align
)
6869 addressT mask
, new_address
;
6871 mask
= ~((addressT
) (~0) << align
);
6872 new_address
= (address
+ mask
) & (~mask
);
6873 return (new_address
- address
);
6876 /* Check the prev_frag is legal. */
6878 invalid_prev_frag (fragS
* fragP
, fragS
**prev_frag
, bool relax
)
6881 fragS
*frag_start
= *prev_frag
;
6883 if (!frag_start
|| !relax
)
6886 if (frag_start
->last_fr_address
>= fragP
->last_fr_address
)
6892 fragS
*frag_t
= *prev_frag
;
6893 while (frag_t
!= fragP
)
6895 if (frag_t
->fr_type
== rs_align
6896 || frag_t
->fr_type
== rs_align_code
6897 || frag_t
->fr_type
== rs_align_test
)
6899 /* Relax instruction can not walk across label. */
6900 if (frag_t
->tc_frag_data
.flag
& NDS32_FRAG_LABEL
)
6905 /* Relax previous relaxable to align rs_align frag. */
6906 address
= frag_t
->fr_address
+ frag_t
->fr_fix
;
6907 addressT offset
= nds32_get_align (address
, (int) frag_t
->fr_offset
);
6910 /* If there is label on the prev_frag, check if it is aligned. */
6911 if (!((*prev_frag
)->tc_frag_data
.flag
& NDS32_FRAG_LABEL
)
6912 || (((*prev_frag
)->fr_address
+ (*prev_frag
)->fr_fix
- 2 )
6914 nds32_adjust_relaxable_frag (*prev_frag
, frag_t
);
6919 frag_t
= frag_t
->fr_next
;
6922 if (fragP
->tc_frag_data
.flag
& NDS32_FRAG_ALIGN
)
6924 address
= fragP
->fr_address
;
6925 addressT offset
= nds32_get_align (address
, 2);
6928 /* If there is label on the prev_frag, check if it is aligned. */
6929 if (!((*prev_frag
)->tc_frag_data
.flag
& NDS32_FRAG_LABEL
)
6930 || (((*prev_frag
)->fr_address
+ (*prev_frag
)->fr_fix
- 2 )
6932 nds32_adjust_relaxable_frag (*prev_frag
, fragP
);
6942 nds32_relax_frag (segT segment
, fragS
*fragP
, long stretch ATTRIBUTE_UNUSED
)
6944 /* Currently, there are two kinds of relaxation in nds32 assembler.
6946 2. relax for 32-bits to 16-bits */
6948 static fragS
*prev_frag
= NULL
;
6951 invalid_prev_frag (fragP
, &prev_frag
, true);
6953 if (fragP
->tc_frag_data
.flag
& NDS32_FRAG_BRANCH
)
6954 adjust
= nds32_relax_branch_instructions (segment
, fragP
, stretch
, 0);
6955 if (fragP
->tc_frag_data
.flag
& NDS32_FRAG_LABEL
)
6957 if (fragP
->tc_frag_data
.flag
& NDS32_FRAG_RELAXABLE
6958 && (fragP
->tc_frag_data
.flag
& NDS32_FRAG_RELAXED
) == 0)
6959 /* Here is considered relaxed case originally. But it may cause
6960 an endless loop when relaxing. Once the instruction is relaxed,
6961 it can not be undone. */
6967 /* This function returns an initial guess of the length by which a fragment
6968 must grow to hold a branch to reach its destination. Also updates
6969 fr_type/fr_subtype as necessary.
6971 It is called just before doing relaxation. Any symbol that is now undefined
6972 will not become defined. The guess for fr_var is ACTUALLY the growth beyond
6973 fr_fix. Whatever we do to grow fr_fix or fr_var contributes to our returned
6974 value. Although it may not be explicit in the frag, pretend fr_var starts
6978 md_estimate_size_before_relax (fragS
*fragP
, segT segment
)
6980 /* Currently, there are two kinds of relaxation in nds32 assembler.
6982 2. relax for 32-bits to 16-bits */
6984 /* Save previous relaxable frag. */
6985 static fragS
*prev_frag
= NULL
;
6988 invalid_prev_frag (fragP
, &prev_frag
, false);
6990 if (fragP
->tc_frag_data
.flag
& NDS32_FRAG_BRANCH
)
6991 adjust
= nds32_relax_branch_instructions (segment
, fragP
, 0, 1);
6992 if (fragP
->tc_frag_data
.flag
& NDS32_FRAG_LABEL
)
6994 if (fragP
->tc_frag_data
.flag
& NDS32_FRAG_RELAXED
)
6996 else if (fragP
->tc_frag_data
.flag
& NDS32_FRAG_RELAXABLE
)
7002 /* GAS will call this for each rs_machine_dependent fragment. The instruction
7003 is completed using the data from the relaxation pass. It may also create any
7004 necessary relocations.
7006 *FRAGP has been relaxed to its final size, and now needs to have the bytes
7007 inside it modified to conform to the new size. It is called after relaxation
7010 fragP->fr_type == rs_machine_dependent.
7011 fragP->fr_subtype is the subtype of what the address relaxed to. */
7014 md_convert_frag (bfd
*abfd ATTRIBUTE_UNUSED
, segT sec
, fragS
*fragP
)
7016 /* Convert branch relaxation instructions. */
7017 symbolS
*branch_symbol
= fragP
->fr_symbol
;
7018 offsetT branch_offset
= fragP
->fr_offset
;
7019 enum nds32_br_range branch_range_type
= fragP
->fr_subtype
;
7020 struct nds32_opcode
*opcode
= fragP
->tc_frag_data
.opcode
;
7021 uint32_t origin_insn
= fragP
->tc_frag_data
.insn
;
7022 relax_info_t
*relax_info
;
7025 int addend ATTRIBUTE_UNUSED
;
7026 offsetT branch_target_address
, branch_insn_address
;
7031 int code_size
, insn_size
, offset
, fixup_size
;
7032 int buf_offset
, pcrel
;
7035 nds32_relax_fixup_info_t fixup_info
[MAX_RELAX_FIX
];
7036 /* Save the 1st instruction is converted to 16 bit or not. */
7037 unsigned int branch_size
;
7038 enum bfd_reloc_code_real final_r_type
;
7040 /* Replace with gas_assert (branch_symbol != NULL); */
7041 if (branch_symbol
== NULL
&& !(fragP
->tc_frag_data
.flag
& NDS32_FRAG_RELAXED
))
7044 /* If frag_var is not enough room, the previous frag is fr_full and with
7045 opcode. The new one is rs_dependent but without opcode. */
7049 if (fragP
->tc_frag_data
.flag
& NDS32_FRAG_RELAXABLE_BRANCH
)
7051 relax_info
= str_hash_find (nds32_relax_info_hash
, opcode
->opcode
);
7053 if (relax_info
== NULL
)
7057 while (i
< BR_RANGE_NUM
7058 && relax_info
->relax_code_size
[i
]
7059 != (fragP
->tc_frag_data
.flag
& NDS32_FRAG_RELAXED
? 4 : 2))
7062 if (i
>= BR_RANGE_NUM
)
7063 as_bad ("Internal error: Cannot find relocation of"
7064 "relaxable branch.");
7066 exp
.X_op
= O_symbol
;
7067 exp
.X_add_symbol
= branch_symbol
;
7068 exp
.X_add_number
= branch_offset
;
7069 pcrel
= ((relax_info
->relax_fixup
[i
][0].ramp
& NDS32_PCREL
) != 0) ? 1 : 0;
7070 fr_where
= fragP
->fr_fix
- 2;
7071 fixP
= fix_new_exp (fragP
, fr_where
, relax_info
->relax_fixup
[i
][0].size
,
7072 &exp
, pcrel
, relax_info
->relax_fixup
[i
][0].r_type
);
7073 fixP
->fx_addnumber
= fixP
->fx_offset
;
7075 if (fragP
->tc_frag_data
.flag
& NDS32_FRAG_RELAXED
)
7077 insn_16
= fragP
->tc_frag_data
.insn
;
7078 nds32_convert_16_to_32 (stdoutput
, insn_16
, &insn
);
7079 fr_buffer
= fragP
->fr_literal
+ fr_where
;
7081 exp
.X_op
= O_symbol
;
7082 exp
.X_add_symbol
= abs_section_sym
;
7083 exp
.X_add_number
= 0;
7084 fix_new_exp (fragP
, fr_where
, 4,
7085 &exp
, 0, BFD_RELOC_NDS32_INSN16
);
7086 number_to_chars_bigendian (fr_buffer
, insn
, 4);
7089 else if (fragP
->tc_frag_data
.flag
& NDS32_FRAG_RELAXED
)
7091 if (fragP
->tc_frag_data
.opcode
->isize
== 2)
7093 insn_16
= fragP
->tc_frag_data
.insn
;
7094 nds32_convert_16_to_32 (stdoutput
, insn_16
, &insn
);
7097 insn
= fragP
->tc_frag_data
.insn
;
7099 fr_where
= fragP
->fr_fix
- 4;
7100 fr_buffer
= fragP
->fr_literal
+ fr_where
;
7101 exp
.X_op
= O_symbol
;
7102 exp
.X_add_symbol
= abs_section_sym
;
7103 exp
.X_add_number
= 0;
7104 fix_new_exp (fragP
, fr_where
, 4, &exp
, 0,
7105 BFD_RELOC_NDS32_INSN16
);
7106 number_to_chars_bigendian (fr_buffer
, insn
, 4);
7108 else if (fragP
->tc_frag_data
.flag
& NDS32_FRAG_BRANCH
)
7110 /* Branch instruction adjust and append relocations. */
7111 relax_info
= str_hash_find (nds32_relax_info_hash
, opcode
->opcode
);
7113 if (relax_info
== NULL
)
7116 fr_where
= fragP
->fr_fix
- opcode
->isize
;
7117 fr_buffer
= fragP
->fr_literal
+ fr_where
;
7119 if ((S_GET_SEGMENT (branch_symbol
) != sec
)
7120 || S_IS_WEAK (branch_symbol
))
7122 if (fragP
->fr_offset
& 3)
7123 as_warn (_("Addend to unresolved symbol is not on word boundary."));
7128 /* Calculate symbol-to-instruction offset. */
7129 branch_target_address
= S_GET_VALUE (branch_symbol
) + branch_offset
;
7130 branch_insn_address
= fragP
->fr_address
+ fr_where
;
7131 addend
= (branch_target_address
- branch_insn_address
) >> 1;
7134 code_size
= relax_info
->relax_code_size
[branch_range_type
];
7135 code_seq
= relax_info
->relax_code_seq
[branch_range_type
];
7137 memcpy (fixup_info
, relax_info
->relax_fixup
[branch_range_type
],
7138 sizeof (fixup_info
));
7143 offset
= 0; /* code_seq offset */
7144 buf_offset
= 0; /* fr_buffer offset */
7145 while (offset
< code_size
)
7148 if (insn
& 0x80000000) /* 16-bits instruction. */
7150 insn
= (insn
>> 16) & 0xFFFF;
7153 else /* 32-bits instruction. */
7158 nds32_elf_get_set_cond (relax_info
, offset
, &insn
,
7159 origin_insn
, branch_range_type
);
7161 /* Try to convert to 16-bits instruction. Currently, only the first
7162 instruction in pattern can be converted. EX: bnez sethi ori jr,
7163 only bnez can be converted to 16 bit and ori can't. */
7165 while (fixup_info
[k
].size
!= 0
7166 && relax_info
->relax_fixup
[branch_range_type
][k
].offset
< offset
)
7169 number_to_chars_bigendian (fr_buffer
+ buf_offset
, insn
, insn_size
);
7170 buf_offset
+= insn_size
;
7172 offset
+= insn_size
;
7177 exp
.X_op
= O_symbol
;
7179 for (i
= 0; fixup_info
[i
].size
!= 0; i
++)
7181 fixup_size
= fixup_info
[i
].size
;
7182 pcrel
= ((fixup_info
[i
].ramp
& NDS32_PCREL
) != 0) ? 1 : 0;
7184 if ((fixup_info
[i
].ramp
& NDS32_CREATE_LABEL
) != 0)
7186 /* This is a reverse branch. */
7187 exp
.X_add_symbol
= symbol_temp_new (sec
, fragP
->fr_next
, 0);
7188 exp
.X_add_number
= 0;
7190 else if ((fixup_info
[i
].ramp
& NDS32_PTR
) != 0)
7192 /* This relocation has to point to another instruction. */
7193 branch_size
= fr_where
+ code_size
- 4;
7194 exp
.X_add_symbol
= symbol_temp_new (sec
, fragP
, branch_size
);
7195 exp
.X_add_number
= 0;
7197 else if ((fixup_info
[i
].ramp
& NDS32_ABS
) != 0)
7199 /* This is a tag relocation. */
7200 exp
.X_add_symbol
= abs_section_sym
;
7201 exp
.X_add_number
= 0;
7203 else if ((fixup_info
[i
].ramp
& NDS32_INSN16
) != 0)
7207 /* This is a tag relocation. */
7208 exp
.X_add_symbol
= abs_section_sym
;
7209 exp
.X_add_number
= 0;
7213 exp
.X_add_symbol
= branch_symbol
;
7214 exp
.X_add_number
= branch_offset
;
7217 if (fixup_info
[i
].r_type
!= 0)
7219 final_r_type
= fixup_info
[i
].r_type
;
7220 fixP
= fix_new_exp (fragP
, fr_where
+ fixup_info
[i
].offset
,
7221 fixup_size
, &exp
, pcrel
,
7223 fixP
->fx_addnumber
= fixP
->fx_offset
;
7227 fragP
->fr_fix
= fr_where
+ buf_offset
;
7231 /* tc_frob_file_before_fix */
7234 nds32_frob_file_before_fix (void)
7239 nds32_relaxable_section (asection
*sec
)
7241 return ((sec
->flags
& SEC_DEBUGGING
) == 0
7242 && strcmp (sec
->name
, ".eh_frame") != 0);
7245 /* TC_FORCE_RELOCATION */
7247 nds32_force_relocation (fixS
* fix
)
7249 switch (fix
->fx_r_type
)
7251 case BFD_RELOC_NDS32_INSN16
:
7252 case BFD_RELOC_NDS32_LABEL
:
7253 case BFD_RELOC_NDS32_LONGCALL1
:
7254 case BFD_RELOC_NDS32_LONGCALL2
:
7255 case BFD_RELOC_NDS32_LONGCALL3
:
7256 case BFD_RELOC_NDS32_LONGJUMP1
:
7257 case BFD_RELOC_NDS32_LONGJUMP2
:
7258 case BFD_RELOC_NDS32_LONGJUMP3
:
7259 case BFD_RELOC_NDS32_LOADSTORE
:
7260 case BFD_RELOC_NDS32_9_FIXED
:
7261 case BFD_RELOC_NDS32_15_FIXED
:
7262 case BFD_RELOC_NDS32_17_FIXED
:
7263 case BFD_RELOC_NDS32_25_FIXED
:
7264 case BFD_RELOC_NDS32_9_PCREL
:
7265 case BFD_RELOC_NDS32_15_PCREL
:
7266 case BFD_RELOC_NDS32_17_PCREL
:
7267 case BFD_RELOC_NDS32_WORD_9_PCREL
:
7268 case BFD_RELOC_NDS32_10_UPCREL
:
7269 case BFD_RELOC_NDS32_25_PCREL
:
7270 case BFD_RELOC_NDS32_MINUEND
:
7271 case BFD_RELOC_NDS32_SUBTRAHEND
:
7277 case BFD_RELOC_NDS32_DIFF_ULEB128
:
7278 /* Linker should handle difference between two symbol. */
7279 return fix
->fx_subsy
!= NULL
7280 && nds32_relaxable_section (S_GET_SEGMENT (fix
->fx_addsy
));
7283 as_bad ("Double word for difference between two symbols "
7284 "is not supported across relaxation.");
7289 if (generic_force_reloc (fix
))
7292 return fix
->fx_pcrel
;
7295 /* TC_VALIDATE_FIX_SUB */
7298 nds32_validate_fix_sub (fixS
*fix
, segT add_symbol_segment
)
7300 segT sub_symbol_segment
;
7302 /* This code is referred from Xtensa. Check their implementation for
7305 /* Make sure both symbols are in the same segment, and that segment is
7306 "normal" and relaxable. */
7307 sub_symbol_segment
= S_GET_SEGMENT (fix
->fx_subsy
);
7308 return (sub_symbol_segment
== add_symbol_segment
7309 && add_symbol_segment
!= undefined_section
);
7313 md_number_to_chars (char *buf
, valueT val
, int n
)
7315 if (target_big_endian
)
7316 number_to_chars_bigendian (buf
, val
, n
);
7318 number_to_chars_littleendian (buf
, val
, n
);
7321 /* This function is called to convert an ASCII string into a floating point
7322 value in format used by the CPU. */
7325 md_atof (int type
, char *litP
, int *sizeP
)
7329 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
7348 return _("Bad call to md_atof()");
7351 t
= atof_ieee (input_line_pointer
, type
, words
);
7353 input_line_pointer
= t
;
7354 *sizeP
= prec
* sizeof (LITTLENUM_TYPE
);
7356 if (target_big_endian
)
7358 for (i
= 0; i
< prec
; i
++)
7360 md_number_to_chars (litP
, (valueT
) words
[i
],
7361 sizeof (LITTLENUM_TYPE
));
7362 litP
+= sizeof (LITTLENUM_TYPE
);
7367 for (i
= prec
- 1; i
>= 0; i
--)
7369 md_number_to_chars (litP
, (valueT
) words
[i
],
7370 sizeof (LITTLENUM_TYPE
));
7371 litP
+= sizeof (LITTLENUM_TYPE
);
7378 /* md_elf_section_change_hook */
7381 nds32_elf_section_change_hook (void)
7388 nds32_cleanup (void)
7392 /* This function is used to scan leb128 subtraction expressions,
7393 and insert fixups for them.
7395 e.g., .leb128 .L1 - .L0
7397 These expressions are heavily used in debug information or
7398 exception tables. Because relaxation will change code size,
7399 we must resolve them in link time. */
7402 nds32_insert_leb128_fixes (bfd
*abfd ATTRIBUTE_UNUSED
,
7403 asection
*sec
, void *xxx ATTRIBUTE_UNUSED
)
7405 segment_info_type
*seginfo
= seg_info (sec
);
7408 subseg_set (sec
, 0);
7410 for (fragP
= seginfo
->frchainP
->frch_root
;
7411 fragP
; fragP
= fragP
->fr_next
)
7415 /* Only unsigned leb128 can be handle. */
7416 if (fragP
->fr_type
!= rs_leb128
|| fragP
->fr_subtype
!= 0
7417 || fragP
->fr_symbol
== NULL
)
7420 exp
= symbol_get_value_expression (fragP
->fr_symbol
);
7422 if (exp
->X_op
!= O_subtract
)
7425 fix_new_exp (fragP
, fragP
->fr_fix
, 0,
7426 exp
, 0, BFD_RELOC_NDS32_DIFF_ULEB128
);
7431 nds32_insert_relax_entry (bfd
*abfd ATTRIBUTE_UNUSED
, asection
*sec
,
7432 void *xxx ATTRIBUTE_UNUSED
)
7434 segment_info_type
*seginfo
;
7440 seginfo
= seg_info (sec
);
7441 if (!seginfo
|| !symbol_rootP
|| !subseg_text_p (sec
) || sec
->size
== 0)
7444 for (fixp
= seginfo
->fix_root
; fixp
; fixp
= fixp
->fx_next
)
7448 if (!fixp
&& !verbatim
&& ict_flag
== ICT_NONE
)
7451 subseg_change (sec
, 0);
7453 /* Set RELAX_ENTRY flags for linker. */
7454 fragP
= seginfo
->frchainP
->frch_root
;
7455 exp
.X_op
= O_symbol
;
7456 exp
.X_add_symbol
= abs_section_sym
;
7457 exp
.X_add_number
= 0;
7458 if (!enable_relax_relocs
)
7459 exp
.X_add_number
|= R_NDS32_RELAX_ENTRY_DISABLE_RELAX_FLAG
;
7462 /* These flags are only enabled when global relax is enabled.
7463 Maybe we can check DISABLE_RELAX_FLAG at link-time,
7464 so we set them anyway. */
7466 exp
.X_add_number
|= R_NDS32_RELAX_ENTRY_VERBATIM_FLAG
;
7467 if (ict_flag
== ICT_SMALL
)
7468 exp
.X_add_number
|= R_NDS32_RELAX_ENTRY_ICT_SMALL
;
7469 else if (ict_flag
== ICT_LARGE
)
7470 exp
.X_add_number
|= R_NDS32_RELAX_ENTRY_ICT_LARGE
;
7473 exp
.X_add_number
|= R_NDS32_RELAX_ENTRY_OPTIMIZE_FLAG
;
7474 if (optimize_for_space
)
7475 exp
.X_add_number
|= R_NDS32_RELAX_ENTRY_OPTIMIZE_FOR_SPACE_FLAG
;
7477 fixP
= fix_new_exp (fragP
, 0, 0, &exp
, 0, BFD_RELOC_NDS32_RELAX_ENTRY
);
7478 fixP
->fx_no_overflow
= 1;
7481 /* Analysis relax hint and insert suitable relocation pattern. */
7484 nds32_elf_analysis_relax_hint (void)
7486 htab_traverse (nds32_hint_hash
, 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);