Fix building for the s390 target with clang
[binutils-gdb.git] / gas / config / tc-nds32.c
blobd576c426d76377d369da0c22097c607415ce3ee0
1 /* tc-nds32.c -- Assemble for the nds32
2 Copyright (C) 2012-2023 Free Software Foundation, Inc.
3 Contributed by Andes Technology Corporation.
5 This file is part of GAS, the GNU Assembler.
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
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
20 02110-1301, USA. */
22 #include "as.h"
23 #include "safe-ctype.h"
24 #include "subsegs.h"
25 #include "symcat.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"
31 #include "hash.h"
32 #include "sb.h"
33 #include "macro.h"
34 #include "opcode/nds32.h"
36 #include <stdio.h>
37 #include <errno.h>
38 #include <limits.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
62 segT seg;
63 fragS *frag;
64 frchainS *frchain;
65 symbolS *sym;
66 fixS* fixP;
67 struct nds32_opcode *opcode;
68 char *where;
69 struct nds32_relocs_pattern *next;
70 /* Assembled instruction bytes. */
71 uint32_t insn;
74 /* Suffix name and relocation. */
75 struct suffix_name
77 const char *suffix;
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;
102 /* ICT model. */
103 enum ict_option {
104 ICT_NONE = 0,
105 ICT_SMALL,
106 ICT_LARGE
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[] =
117 .opcode = "jal",
118 .br_range = BR_RANGE_S16M,
119 .cond_field =
121 {0, 0, 0, false}
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},
132 {0, 0, 0, 0}
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},
144 {0, 0, 0, 0}
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},
156 {0, 0, 0, 0}
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},
168 {0, 0, 0, 0}
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},
188 {0, 0, 0, 0}
192 .opcode = "bgezal",
193 .br_range = BR_RANGE_S64K,
194 .cond_field =
196 {0, 20, 0x1F, false},
197 {0, 0, 0, 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},
206 {0, 0, 0, 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},
213 {0, 0, 0, 0}
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},
223 {0, 0, 0, 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},
230 {0, 0, 0, 0}
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},
240 {0, 0, 0, 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},
247 {0, 0, 0, 0}
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},
258 {0, 0, 0, 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},
267 {0, 0, 0, 0}
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},
280 {0, 0, 0, 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},
295 {0, 0, 0, 0}
299 .opcode = "bltzal",
300 .br_range = BR_RANGE_S64K,
301 .cond_field =
303 {0, 20, 0x1F, false},
304 {0, 0, 0, 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},
313 {0, 0, 0, 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},
320 {0, 0, 0, 0}
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},
330 {0, 0, 0, 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},
337 {0, 0, 0, 0}
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},
347 {0, 0, 0, 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},
354 {0, 0, 0, 0}
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},
365 {0, 0, 0, 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},
374 {0, 0, 0, 0}
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},
387 {0, 0, 0, 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},
402 {0, 0, 0, 0}
406 .opcode = "j",
407 .br_range = BR_RANGE_S16M,
408 .cond_field =
410 {0, 0, 0, false}
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},
421 {0, 0, 0, 0}
424 .relax_code_seq[BR_RANGE_S16K] =
426 INSN_J /* j label */
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},
433 {0, 0, 0, 0}
436 .relax_code_seq[BR_RANGE_S64K] =
438 INSN_J /* j label */
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},
445 {0, 0, 0, 0}
448 .relax_code_seq[BR_RANGE_S16M] =
450 INSN_J /* j label */
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},
457 {0, 0, 0, 0}
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},
477 {0, 0, 0, 0}
481 .opcode = "j8",
482 .br_range = BR_RANGE_S256,
483 .cond_field =
485 {0, 0, 0, false}
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},
496 {0, 0, 0, 0}
499 .relax_code_seq[BR_RANGE_S16K] =
501 INSN_J /* j label */
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},
508 {0, 0, 0, 0}
511 .relax_code_seq[BR_RANGE_S64K] =
513 INSN_J /* j label */
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},
520 {0, 0, 0, 0}
523 .relax_code_seq[BR_RANGE_S16M] =
525 INSN_J /* j label */
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},
532 {0, 0, 0, 0}
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},
552 {0, 0, 0, 0}
556 .opcode = "beqz",
557 .br_range = BR_RANGE_S64K,
558 .cond_field =
560 {0, 20, 0x1F, false},
561 {0, 0, 0, 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},
572 {0, 0, 0, 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},
580 {0, 0, 0, 0}
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},
590 {0, 0, 0, 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},
597 {0, 0, 0, 0}
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},
607 {0, 0, 0, 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},
614 {0, 0, 0, 0}
617 .relax_code_seq[BR_RANGE_S16M] =
619 INSN_BNEZ, /* bnez $rt, $1 */
620 INSN_J /* j label */
622 .relax_code_condition[BR_RANGE_S16M] =
624 {0, 20, 0x1F, false},
625 {0, 0, 0, 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
634 and LONGJUMP6. */
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},
640 {0, 0, 0, 0}
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},
653 {0, 0, 0, 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},
669 {0, 0, 0, 0}
673 .opcode = "bgez",
674 .br_range = BR_RANGE_S64K,
675 .cond_field =
677 {0, 20, 0x1F, false},
678 {0, 0, 0, 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},
687 {0, 0, 0, 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},
694 {0, 0, 0, 0}
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},
704 {0, 0, 0, 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},
711 {0, 0, 0, 0}
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},
721 {0, 0, 0, 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},
728 {0, 0, 0, 0}
731 .relax_code_seq[BR_RANGE_S16M] =
733 INSN_BLTZ, /* bltz $rt, $1 */
734 INSN_J /* j label */
736 .relax_code_condition[BR_RANGE_S16M] =
738 {0, 20, 0x1F, false},
739 {0, 0, 0, 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},
748 {0, 0, 0, 0}
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},
760 {0, 0, 0, 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},
775 {0, 0, 0, 0}
779 .opcode = "bnez",
780 .br_range = BR_RANGE_S64K,
781 .cond_field =
783 {0, 20, 0x1F, false},
784 {0, 0, 0, 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},
793 {0, 0, 0, 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},
801 {0, 0, 0, 0}
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},
811 {0, 0, 0, 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},
818 {0, 0, 0, 0}
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},
828 {0, 0, 0, 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},
835 {0, 0, 0, 0}
838 .relax_code_seq[BR_RANGE_S16M] =
840 INSN_BEQZ, /* beqz $rt, $1 */
841 INSN_J /* j label */
843 .relax_code_condition[BR_RANGE_S16M] =
845 {0, 20, 0x1F, false},
846 {0, 0, 0, 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},
857 {0, 0, 0, 0}
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},
870 {0, 0, 0, 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},
886 {0, 0, 0, 0}
890 .opcode = "bgtz",
891 .br_range = BR_RANGE_S64K,
892 .cond_field =
894 {0, 20, 0x1F, false},
895 {0, 0, 0, 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},
904 {0, 0, 0, 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},
911 {0, 0, 0, 0}
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},
921 {0, 0, 0, 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},
928 {0, 0, 0, 0}
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},
938 {0, 0, 0, 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},
945 {0, 0, 0, 0}
948 .relax_code_seq[BR_RANGE_S16M] =
950 INSN_BLEZ, /* blez $rt, $1 */
951 INSN_J /* j label */
953 .relax_code_condition[BR_RANGE_S16M] =
955 {0, 20, 0x1F, false},
956 {0, 0, 0, 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},
965 {0, 0, 0, 0}
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},
978 {0, 0, 0, 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},
993 {0, 0, 0, 0}
997 .opcode = "blez",
998 .br_range = BR_RANGE_S64K,
999 .cond_field =
1001 {0, 20, 0x1F, false},
1002 {0, 0, 0, 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},
1011 {0, 0, 0, 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},
1018 {0, 0, 0, 0}
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},
1028 {0, 0, 0, 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},
1035 {0, 0, 0, 0}
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},
1045 {0, 0, 0, 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},
1052 {0, 0, 0, 0}
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},
1063 {0, 0, 0, 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},
1072 {0, 0, 0, 0}
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},
1085 {0, 0, 0, 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},
1100 {0, 0, 0, 0}
1104 .opcode = "bltz",
1105 .br_range = BR_RANGE_S64K,
1106 .cond_field =
1108 {0, 20, 0x1F, false},
1109 {0, 0, 0, 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},
1118 {0, 0, 0, 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},
1125 {0, 0, 0, 0}
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},
1135 {0, 0, 0, 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},
1142 {0, 0, 0, 0}
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},
1152 {0, 0, 0, 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},
1159 {0, 0, 0, 0}
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},
1170 {0, 0, 0, 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},
1179 {0, 0, 0, 0}
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},
1192 {0, 0, 0, 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},
1207 {0, 0, 0, 0}
1211 .opcode = "beq",
1212 .br_range = BR_RANGE_S16K,
1213 .cond_field =
1215 {0, 20, 0x1F, false},
1216 {0, 15, 0x1F, false},
1217 {0, 0, 0, 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},
1227 {0, 0, 0, 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},
1235 {0, 0, 0, 0}
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},
1246 {0, 0, 0, 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},
1253 {0, 0, 0, 0}
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},
1265 {0, 0, 0, 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},
1276 {0, 0, 0, 0}
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},
1288 {0, 0, 0, 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},
1299 {0, 0, 0, 0}
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},
1313 {0, 0, 0, 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},
1329 {0, 0, 0, 0}
1333 .opcode = "bne",
1334 .br_range = BR_RANGE_S16K,
1335 .cond_field =
1337 {0, 20, 0x1F, false},
1338 {0, 15, 0x1F, false},
1339 {0, 0, 0, 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},
1349 {0, 0, 0, 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},
1357 {0, 0, 0, 0}
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},
1368 {0, 0, 0, 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},
1375 {0, 0, 0, 0}
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},
1387 {0, 0, 0, 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},
1398 {0, 0, 0, 0}
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},
1410 {0, 0, 0, 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},
1421 {0, 0, 0, 0}
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},
1435 {0, 0, 0, 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},
1451 {0, 0, 0, 0}
1455 .opcode = "beqz38",
1456 .br_range = BR_RANGE_S256,
1457 .cond_field =
1459 {0, 8, 0x7, false},
1460 {0, 0, 0, false}
1462 .relax_code_seq[BR_RANGE_S256] =
1464 INSN_BEQZ38 << 16 /* beqz $rt, label */
1466 .relax_code_condition[BR_RANGE_S256] =
1468 {0, 8, 0x7, false},
1469 {0, 0, 0, false}
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},
1476 {0, 0, 0, 0}
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},
1486 {0, 0, 0, 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},
1493 {0, 0, 0, 0}
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},
1503 {0, 0, 0, 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},
1510 {0, 0, 0, 0}
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},
1521 {0, 0, 0, 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},
1532 {0, 0, 0, 0}
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},
1545 {0, 0, 0, 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},
1561 {0, 0, 0, 0}
1565 .opcode = "bnez38",
1566 .br_range = BR_RANGE_S256,
1567 .cond_field =
1569 {0, 8, 0x7, false},
1570 {0, 0, 0, false}
1572 .relax_code_seq[BR_RANGE_S256] =
1574 INSN_BNEZ38 << 16 /* bnez $rt, label */
1576 .relax_code_condition[BR_RANGE_S256] =
1578 {0, 8, 0x7, false},
1579 {0, 0, 0, false}
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},
1586 {0, 0, 0, 0}
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},
1596 {0, 0, 0, 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},
1603 {0, 0, 0, 0}
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},
1613 {0, 0, 0, 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},
1620 {0, 0, 0, 0}
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},
1631 {0, 0, 0, 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},
1642 {0, 0, 0, 0}
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},
1655 {0, 0, 0, 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},
1671 {0, 0, 0, 0}
1675 .opcode = "beqzs8",
1676 .br_range = BR_RANGE_S256,
1677 .cond_field =
1679 {0, 0, 0, false}
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},
1690 {0, 0, 0, 0}
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},
1702 {0, 0, 0, 0}
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},
1714 {0, 0, 0, 0}
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},
1731 {0, 0, 0, 0}
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},
1755 {0, 0, 0, 0}
1759 .opcode = "bnezs8",
1760 .br_range = BR_RANGE_S256,
1761 .cond_field =
1763 {0, 0, 0, false}
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},
1774 {0, 0, 0, 0}
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},
1786 {0, 0, 0, 0}
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},
1798 {0, 0, 0, 0}
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},
1815 {0, 0, 0, 0}
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},
1839 {0, 0, 0, 0}
1843 .opcode = "bnes38",
1844 .br_range = BR_RANGE_S256,
1845 .cond_field =
1847 {0, 8, 0x7, false},
1848 {0, 0, 0, false}
1850 .relax_code_seq[BR_RANGE_S256] =
1852 INSN_BNES38 << 16 /* bne $rt, $r5, label */
1854 .relax_code_condition[BR_RANGE_S256] =
1856 {0, 8, 0x7, false},
1857 {0, 0, 0, false}
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},
1864 {0, 0, 0, 0}
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},
1874 {0, 0, 0, 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},
1881 {0, 0, 0, 0}
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},
1892 {0, 0, 0, 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},
1903 {0, 0, 0, 0}
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},
1914 {0, 0, 0, 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},
1925 {0, 0, 0, 0}
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},
1938 {0, 0, 0, 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},
1954 {0, 0, 0, 0}
1958 .opcode = "beqs38",
1959 .br_range = BR_RANGE_S256,
1960 .cond_field =
1962 {0, 8, 0x7, false},
1963 {0, 0, 0, false}
1965 .relax_code_seq[BR_RANGE_S256] =
1967 INSN_BEQS38 << 16 /* beq $rt, $r5, label */
1969 .relax_code_condition[BR_RANGE_S256] =
1971 {0, 8, 0x7, false},
1972 {0, 0, 0, false}
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},
1979 {0, 0, 0, 0}
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},
1989 {0, 0, 0, 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},
1996 {0, 0, 0, 0}
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},
2007 {0, 0, 0, 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},
2018 {0, 0, 0, 0}
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},
2029 {0, 0, 0, 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},
2040 {0, 0, 0, 0}
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},
2053 {0, 0, 0, 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},
2069 {0, 0, 0, 0}
2073 .opcode = "beqc",
2074 .br_range = BR_RANGE_S256,
2075 .cond_field =
2077 {0, 8, 0x7FF, true},
2078 {0, 20, 0x1F, false},
2079 {0, 0, 0, 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},
2089 {0, 0, 0, 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},
2096 {0, 0, 0, 0}
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},
2108 {0, 0, 0, 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},
2117 {0, 0, 0, 0}
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},
2129 {0, 0, 0, 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},
2137 {0, 0, 0, 0}
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},
2149 {0, 0, 0, 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},
2157 {0, 0, 0, 0}
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},
2171 {0, 0, 0, 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},
2181 {0, 0, 0, 0}
2185 .opcode = "bnec",
2186 .br_range = BR_RANGE_S256,
2187 .cond_field =
2189 {0, 8, 0x7FF, true},
2190 {0, 20, 0x1F, false},
2191 {0, 0, 0, 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},
2201 {0, 0, 0, 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},
2208 {0, 0, 0, 0}
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},
2220 {0, 0, 0, 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},
2229 {0, 0, 0, 0}
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},
2241 {0, 0, 0, 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},
2249 {0, 0, 0, 0}
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},
2261 {0, 0, 0, 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},
2269 {0, 0, 0, 0}
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},
2283 {0, 0, 0, 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},
2293 {0, 0, 0, 0}
2297 .opcode = NULL,
2302 /* GAS definitions for command-line options. */
2303 enum options
2305 OPTION_BIG = OPTION_MD_BASE,
2306 OPTION_LITTLE,
2307 OPTION_TURBO,
2308 OPTION_PIC,
2309 OPTION_RELAX_FP_AS_GP_OFF,
2310 OPTION_RELAX_B2BB_ON,
2311 OPTION_RELAX_ALL_OFF,
2312 OPTION_OPTIMIZE,
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;
2350 #else
2351 static const char* nds32_arch_name = "v3";
2352 #endif
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\
2382 <freg>\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},
2389 {NULL, NULL, NULL}
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. */
2454 void
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). */
2464 void
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"));
2500 void
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. */
2513 static char *
2514 parse_expression (char *str, expressionS *exp)
2516 char *s;
2517 char *tmp;
2519 tmp = input_line_pointer; /* Save line pointer. */
2520 input_line_pointer = str;
2521 expression (exp);
2522 resolve_register (exp);
2523 s = input_line_pointer;
2524 input_line_pointer = tmp; /* Restore line pointer. */
2526 return s; /* Return pointer to where parsing stopped. */
2529 void
2530 nds32_start_line_hook (void)
2535 * Pseudo opcodes
2538 typedef void (*nds32_pseudo_opcode_func) (int argc, char *argv[], unsigned int pv);
2539 struct nds32_pseudo_opcode
2541 const char *opcode;
2542 int argc;
2543 nds32_pseudo_opcode_func proc;
2544 unsigned int pseudo_val;
2546 /* Some instructions are not pseudo opcode, but they might still be
2547 expanded or changed with other instruction combination for some
2548 conditions. We also apply this structure to assist such work.
2550 For example, if the distance of branch target '.L0' is larger than
2551 imm8s<<1 range,
2553 the instruction:
2555 beqzs8 .L0
2557 will be transformed into:
2559 bnezs8 .LCB0
2560 j .L0
2561 .LCB0:
2563 However, sometimes we do not want assembler to do such changes
2564 because compiler knows how to generate corresponding instruction sequence.
2565 Use this field to indicate that this opcode is also a physical instruction.
2566 If the flag 'verbatim' is nozero and this opcode
2567 is a physical instruction, we should not expand it. */
2568 int physical_op;
2570 #define PV_DONT_CARE 0
2572 static htab_t nds32_pseudo_opcode_hash = NULL;
2574 static int
2575 builtin_isreg (const char *s, const char *x ATTRIBUTE_UNUSED)
2577 if (s [0] == '$' && str_hash_find (nds32_gprs_hash, (s + 1)))
2578 return 1;
2579 return 0;
2582 static int
2583 builtin_regnum (const char *s, const char *x ATTRIBUTE_UNUSED)
2585 struct nds32_keyword *k;
2586 if (*s != '$')
2587 return -1;
2588 s++;
2589 k = str_hash_find (nds32_gprs_hash, s);
2591 if (k == NULL)
2592 return -1;
2594 return k->value;
2597 static int
2598 builtin_addend (const char *s, char *x ATTRIBUTE_UNUSED)
2600 const char *ptr = s;
2602 while (*ptr != '+' && *ptr != '-' && *ptr)
2603 ++ptr;
2605 if (*ptr == 0)
2606 return 0;
2607 else
2608 return strtol (ptr, NULL, 0);
2611 static void
2612 md_assemblef (const char *format, ...)
2614 /* FIXME: hope this is long enough. */
2615 char line[1024];
2616 va_list ap;
2617 unsigned int r;
2619 va_start (ap, format);
2620 r = vsnprintf (line, sizeof (line), format, ap);
2621 md_assemble (line);
2623 gas_assert (r < sizeof (line));
2626 /* Some prototypes here, since some op may use another op. */
2627 static void do_pseudo_li_internal (const char *rt, int imm32s);
2628 static void do_pseudo_move_reg_internal (char *dst, char *src);
2630 static void
2631 do_pseudo_b (int argc ATTRIBUTE_UNUSED, char *argv[],
2632 unsigned int pv ATTRIBUTE_UNUSED)
2634 char *arg_label = argv[0];
2635 relaxing = true;
2636 /* b label */
2637 if (nds32_pic)
2639 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2640 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2641 md_assemble ((char *) "add $ta,$ta,$gp");
2642 md_assemble ((char *) "jr $ta");
2644 else
2646 md_assemblef ("j %s", arg_label);
2648 relaxing = false;
2651 static void
2652 do_pseudo_bal (int argc ATTRIBUTE_UNUSED, char *argv[],
2653 unsigned int pv ATTRIBUTE_UNUSED)
2655 char *arg_label = argv[0];
2656 relaxing = true;
2657 /* bal|call label */
2658 if (nds32_pic)
2660 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2661 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2662 md_assemble ((char *) "add $ta,$ta,$gp");
2663 md_assemble ((char *) "jral $ta");
2665 else
2667 md_assemblef ("jal %s", arg_label);
2669 relaxing = false;
2672 static void
2673 do_pseudo_bge (int argc ATTRIBUTE_UNUSED, char *argv[],
2674 unsigned int pv ATTRIBUTE_UNUSED)
2676 /* rt5, ra5, label */
2677 md_assemblef ("slt $ta,%s,%s", argv[0], argv[1]);
2678 md_assemblef ("beqz $ta,%s", argv[2]);
2681 static void
2682 do_pseudo_bges (int argc ATTRIBUTE_UNUSED, char *argv[],
2683 unsigned int pv ATTRIBUTE_UNUSED)
2685 /* rt5, ra5, label */
2686 md_assemblef ("slts $ta,%s,%s", argv[0], argv[1]);
2687 md_assemblef ("beqz $ta,%s", argv[2]);
2690 static void
2691 do_pseudo_bgt (int argc ATTRIBUTE_UNUSED, char *argv[],
2692 unsigned int pv ATTRIBUTE_UNUSED)
2694 /* bgt rt5, ra5, label */
2695 md_assemblef ("slt $ta,%s,%s", argv[1], argv[0]);
2696 md_assemblef ("bnez $ta,%s", argv[2]);
2699 static void
2700 do_pseudo_bgts (int argc ATTRIBUTE_UNUSED, char *argv[],
2701 unsigned int pv ATTRIBUTE_UNUSED)
2703 /* bgt rt5, ra5, label */
2704 md_assemblef ("slts $ta,%s,%s", argv[1], argv[0]);
2705 md_assemblef ("bnez $ta,%s", argv[2]);
2708 static void
2709 do_pseudo_ble (int argc ATTRIBUTE_UNUSED, char *argv[],
2710 unsigned int pv ATTRIBUTE_UNUSED)
2712 /* bgt rt5, ra5, label */
2713 md_assemblef ("slt $ta,%s,%s", argv[1], argv[0]);
2714 md_assemblef ("beqz $ta,%s", argv[2]);
2717 static void
2718 do_pseudo_bles (int argc ATTRIBUTE_UNUSED, char *argv[],
2719 unsigned int pv ATTRIBUTE_UNUSED)
2721 /* bgt rt5, ra5, label */
2722 md_assemblef ("slts $ta,%s,%s", argv[1], argv[0]);
2723 md_assemblef ("beqz $ta,%s", argv[2]);
2726 static void
2727 do_pseudo_blt (int argc ATTRIBUTE_UNUSED, char *argv[],
2728 unsigned int pv ATTRIBUTE_UNUSED)
2730 /* rt5, ra5, label */
2731 md_assemblef ("slt $ta,%s,%s", argv[0], argv[1]);
2732 md_assemblef ("bnez $ta,%s", argv[2]);
2735 static void
2736 do_pseudo_blts (int argc ATTRIBUTE_UNUSED, char *argv[],
2737 unsigned int pv ATTRIBUTE_UNUSED)
2739 /* rt5, ra5, label */
2740 md_assemblef ("slts $ta,%s,%s", argv[0], argv[1]);
2741 md_assemblef ("bnez $ta,%s", argv[2]);
2744 static void
2745 do_pseudo_br (int argc ATTRIBUTE_UNUSED, char *argv[],
2746 unsigned int pv ATTRIBUTE_UNUSED)
2748 md_assemblef ("jr %s", argv[0]);
2751 static void
2752 do_pseudo_bral (int argc, char *argv[],
2753 unsigned int pv ATTRIBUTE_UNUSED)
2755 if (argc == 1)
2756 md_assemblef ("jral $lp,%s", argv[0]);
2757 else
2758 md_assemblef ("jral %s,%s", argv[0], argv[1]);
2761 static void
2762 do_pseudo_la_internal (const char *arg_reg, char *arg_label,
2763 const char *line)
2765 expressionS exp;
2767 parse_expression (arg_label, &exp);
2768 if (exp.X_op != O_symbol)
2770 as_bad (_("la must use with symbol. '%s'"), line);
2771 return;
2774 relaxing = true;
2775 /* rt, label */
2776 if (!nds32_pic && !strstr (arg_label, "@"))
2778 md_assemblef ("sethi %s,hi20(%s)", arg_reg, arg_label);
2779 md_assemblef ("ori %s,%s,lo12(%s)", arg_reg, arg_reg, arg_label);
2781 else if (strstr (arg_label, "@TPOFF"))
2783 /* la $rt, sym@TPOFF */
2784 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2785 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2786 md_assemblef ("add %s,$ta,%s", arg_reg, TLS_REG);
2788 else if (strstr(arg_label, "@GOTTPOFF"))
2790 /* la $rt, sym@GOTTPOFF*/
2791 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2792 md_assemblef ("lwi $ta,[$ta+lo12(%s)]", arg_label);
2793 md_assemblef ("add %s,$ta,%s", arg_reg, TLS_REG);
2795 else if (nds32_pic && ((strstr (arg_label, "@PLT")
2796 || strstr (arg_label, "@GOTOFF"))))
2798 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2799 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2800 md_assemblef ("add %s,$ta,$gp", arg_reg);
2802 else if (nds32_pic && strstr (arg_label, "@GOT"))
2804 long addend = builtin_addend (arg_label, NULL);
2806 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2807 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2808 md_assemblef ("lw %s,[$gp+$ta]", arg_reg);
2809 if (addend != 0)
2811 if (addend < 0x4000 && addend >= -0x4000)
2813 md_assemblef ("addi %s,%s,%d", arg_reg, arg_reg, addend);
2815 else
2817 do_pseudo_li_internal ("$ta", addend);
2818 md_assemblef ("add %s,$ta,%s", arg_reg, arg_reg);
2822 else
2823 as_bad (_("need PIC qualifier with symbol. '%s'"), line);
2824 relaxing = false;
2827 static void
2828 do_pseudo_la (int argc ATTRIBUTE_UNUSED, char *argv[],
2829 unsigned int pv ATTRIBUTE_UNUSED)
2831 do_pseudo_la_internal (argv[0], argv[1], argv[argc]);
2834 static void
2835 do_pseudo_li_internal (const char *rt, int imm32s)
2837 if (enable_16bit && imm32s <= 0xf && imm32s >= -0x10)
2838 md_assemblef ("movi55 %s,%d", rt, imm32s);
2839 else if (imm32s <= 0x7ffff && imm32s >= -0x80000)
2840 md_assemblef ("movi %s,%d", rt, imm32s);
2841 else if ((imm32s & 0xfff) == 0)
2842 md_assemblef ("sethi %s,hi20(%d)", rt, imm32s);
2843 else
2845 md_assemblef ("sethi %s,hi20(%d)", rt, imm32s);
2846 md_assemblef ("ori %s,%s,lo12(%d)", rt, rt, imm32s);
2850 static void
2851 do_pseudo_li (int argc ATTRIBUTE_UNUSED, char *argv[],
2852 unsigned int pv ATTRIBUTE_UNUSED)
2854 /* Validate argv[1] for constant expression. */
2855 expressionS exp;
2857 parse_expression (argv[1], &exp);
2858 if (exp.X_op != O_constant)
2860 as_bad (_("Operand is not a constant. `%s'"), argv[argc]);
2861 return;
2864 do_pseudo_li_internal (argv[0], exp.X_add_number);
2867 static void
2868 do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED, char *argv[],
2869 unsigned int pv)
2871 char ls = 'r';
2872 char size = 'x';
2873 const char *sign = "";
2875 /* Prepare arguments for various load/store. */
2876 sign = (pv & 0x10) ? "s" : "";
2877 ls = (pv & 0x80000000) ? 's' : 'l';
2878 switch (pv & 0x3)
2880 case 0: size = 'b'; break;
2881 case 1: size = 'h'; break;
2882 case 2: size = 'w'; break;
2885 if (ls == 's' || size == 'w')
2886 sign = "";
2888 if (builtin_isreg (argv[1], NULL))
2890 /* lwi */
2891 md_assemblef ("%c%ci %s,[%s]", ls, size, argv[0], argv[1]);
2893 else if (!nds32_pic)
2895 relaxing = true;
2896 if (strstr (argv[1], "@TPOFF"))
2898 /* ls.w $rt, sym@TPOFF */
2899 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2900 md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
2901 md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], TLS_REG);
2903 else if (strstr (argv[1], "@GOTTPOFF"))
2905 /* ls.w $rt, sym@GOTTPOFF */
2906 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2907 md_assemblef ("lwi $ta,[$ta+lo12(%s)]", argv[1]);
2908 md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], TLS_REG);
2910 else
2912 /* lwi */
2913 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2914 md_assemblef ("%c%c%si %s,[$ta+lo12(%s)]", ls, size, sign, argv[0], argv[1]);
2916 relaxing = false;
2918 else
2920 relaxing = true;
2921 /* PIC code. */
2922 if (strstr (argv[1], "@GOTOFF"))
2924 /* lw */
2925 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2926 md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
2927 md_assemblef ("%c%c%s %s,[$ta+$gp]", ls, size, sign, argv[0]);
2929 else if (strstr (argv[1], "@GOT"))
2931 long addend = builtin_addend (argv[1], NULL);
2932 /* lw */
2933 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2934 md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
2935 md_assemble ((char *) "lw $ta,[$gp+$ta]"); /* Load address word. */
2936 if (addend < 0x10000 && addend >= -0x10000)
2938 md_assemblef ("%c%c%si %s,[$ta+(%d)]", ls, size, sign, argv[0], addend);
2940 else
2942 /* lw */
2943 do_pseudo_li_internal (argv[0], addend);
2944 md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], argv[0]);
2947 else
2949 as_bad (_("needs @GOT or @GOTOFF. %s"), argv[argc]);
2951 relaxing = false;
2955 static void
2956 do_pseudo_ls_bhwp (int argc ATTRIBUTE_UNUSED, char *argv[],
2957 unsigned int pv)
2959 char *arg_rt = argv[0];
2960 char *arg_label = argv[1];
2961 char *arg_inc = argv[2];
2962 char ls = 'r';
2963 char size = 'x';
2964 const char *sign = "";
2966 /* Prepare arguments for various load/store. */
2967 sign = (pv & 0x10) ? "s" : "";
2968 ls = (pv & 0x80000000) ? 's' : 'l';
2969 switch (pv & 0x3)
2971 case 0: size = 'b'; break;
2972 case 1: size = 'h'; break;
2973 case 2: size = 'w'; break;
2976 if (ls == 's' || size == 'w')
2977 sign = "";
2979 do_pseudo_la_internal ("$ta", arg_label, argv[argc]);
2980 md_assemblef ("%c%c%si.bi %s,[$ta],%s", ls, size, sign, arg_rt, arg_inc);
2983 static void
2984 do_pseudo_ls_bhwpc (int argc ATTRIBUTE_UNUSED, char *argv[],
2985 unsigned int pv)
2987 char *arg_rt = argv[0];
2988 char *arg_inc = argv[1];
2989 char ls = 'r';
2990 char size = 'x';
2991 const char *sign = "";
2993 /* Prepare arguments for various load/store. */
2994 sign = (pv & 0x10) ? "s" : "";
2995 ls = (pv & 0x80000000) ? 's' : 'l';
2996 switch (pv & 0x3)
2998 case 0: size = 'b'; break;
2999 case 1: size = 'h'; break;
3000 case 2: size = 'w'; break;
3003 if (ls == 's' || size == 'w')
3004 sign = "";
3006 md_assemblef ("%c%c%si.bi %s,[$ta],%s", ls, size, sign, arg_rt, arg_inc);
3009 static void
3010 do_pseudo_ls_bhwi (int argc ATTRIBUTE_UNUSED, char *argv[],
3011 unsigned int pv)
3013 char ls = 'r';
3014 char size = 'x';
3015 const char *sign = "";
3017 /* Prepare arguments for various load/store. */
3018 sign = (pv & 0x10) ? "s" : "";
3019 ls = (pv & 0x80000000) ? 's' : 'l';
3020 switch (pv & 0x3)
3022 case 0: size = 'b'; break;
3023 case 1: size = 'h'; break;
3024 case 2: size = 'w'; break;
3027 if (ls == 's' || size == 'w')
3028 sign = "";
3030 md_assemblef ("%c%c%si.bi %s,%s,%s",
3031 ls, size, sign, argv[0], argv[1], argv[2]);
3034 static void
3035 do_pseudo_move_reg_internal (char *dst, char *src)
3037 if (enable_16bit)
3038 md_assemblef ("mov55 %s,%s", dst, src);
3039 else
3040 md_assemblef ("ori %s,%s,0", dst, src);
3043 static void
3044 do_pseudo_move (int argc ATTRIBUTE_UNUSED, char *argv[],
3045 unsigned int pv ATTRIBUTE_UNUSED)
3047 expressionS exp;
3049 if (builtin_isreg (argv[1], NULL))
3050 do_pseudo_move_reg_internal (argv[0], argv[1]);
3051 else
3053 parse_expression (argv[1], &exp);
3054 if (exp.X_op == O_constant)
3055 /* move $rt, imm -> li $rt, imm */
3056 do_pseudo_li_internal (argv[0], exp.X_add_number);
3057 else
3058 /* l.w $rt, var -> l.w $rt, var */
3059 do_pseudo_ls_bhw (argc, argv, 2);
3063 static void
3064 do_pseudo_neg (int argc ATTRIBUTE_UNUSED, char *argv[],
3065 unsigned int pv ATTRIBUTE_UNUSED)
3067 /* Instead of "subri". */
3068 md_assemblef ("subri %s,%s,0", argv[0], argv[1]);
3071 static void
3072 do_pseudo_not (int argc ATTRIBUTE_UNUSED, char *argv[],
3073 unsigned int pv ATTRIBUTE_UNUSED)
3075 md_assemblef ("nor %s,%s,%s", argv[0], argv[1], argv[1]);
3078 static void
3079 do_pseudo_pushpopm (int argc, char *argv[],
3080 unsigned int pv ATTRIBUTE_UNUSED)
3082 /* posh/pop $ra, $rb */
3083 /* SMW.{b | a}{i | d}{m?} Rb, [Ra], Re, Enable4 */
3084 int rb, re, ra, en4;
3085 int i;
3086 const char *opc = "pushpopm";
3088 if (argc == 3)
3089 as_bad ("'pushm/popm $ra5, $rb5, $label' is deprecated. "
3090 "Only 'pushm/popm $ra5' is supported now. %s", argv[argc]);
3091 else if (argc == 1)
3092 as_bad ("'pushm/popm $ra5, $rb5'. %s\n", argv[argc]);
3094 if (strstr (argv[argc], "pop") == argv[argc])
3095 opc = "lmw.bim";
3096 else if (strstr (argv[argc], "push") == argv[argc])
3097 opc = "smw.adm";
3098 else
3099 as_fatal ("nds32-as internal error. %s", argv[argc]);
3101 rb = builtin_regnum (argv[0], NULL);
3102 re = builtin_regnum (argv[1], NULL);
3104 if (re < rb)
3106 as_warn ("$rb should not be smaller than $ra. %s", argv[argc]);
3107 /* Swap to right order. */
3108 ra = re;
3109 re = rb;
3110 rb = ra;
3113 /* Build enable4 mask. */
3114 en4 = 0;
3115 if (re >= 28 || rb >= 28)
3117 for (i = (rb >= 28? rb: 28); i <= re; i++)
3118 en4 |= 1 << (3 - (i - 28));
3121 /* Adjust $re, $rb. */
3122 if (rb >= 28)
3123 rb = re = 31;
3124 else if (nds32_gpr16 != 1 && re >= 28)
3125 re = 27;
3127 /* Reduce register. */
3128 if (nds32_gpr16 && re > 10 && !(rb == 31 && re == 31))
3130 if (re >= 15 && strstr (opc, "smw") != NULL)
3131 md_assemblef ("%s $r15,[$sp],$r15,%d", opc, en4);
3132 if (rb <= 10)
3133 md_assemblef ("%s $r%d,[$sp],$r10, 0x0", opc, rb);
3134 if (re >= 15 && strstr (opc, "lmw") != NULL)
3135 md_assemblef ("%s $r15,[$sp],$r15,%d", opc, en4);
3137 else
3138 md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc, rb, re, en4);
3141 static void
3142 do_pseudo_pushpop (int argc, char *argv[],
3143 unsigned int pv ATTRIBUTE_UNUSED)
3145 /* push/pop $ra5, $label=$sp */
3146 char *argvm[3];
3148 if (argc == 2)
3149 as_bad ("'push/pop $ra5, rb5' is deprecated. "
3150 "Only 'push/pop $ra5' is supported now. %s", argv[argc]);
3152 argvm[0] = argv[0];
3153 argvm[1] = argv[0];
3154 argvm[2] = argv[argc];
3155 do_pseudo_pushpopm (2, argvm, PV_DONT_CARE);
3158 static void
3159 do_pseudo_v3push (int argc ATTRIBUTE_UNUSED, char *argv[],
3160 unsigned int pv ATTRIBUTE_UNUSED)
3162 md_assemblef ("push25 %s,%s", argv[0], argv[1]);
3165 static void
3166 do_pseudo_v3pop (int argc ATTRIBUTE_UNUSED, char *argv[],
3167 unsigned int pv ATTRIBUTE_UNUSED)
3169 md_assemblef ("pop25 %s,%s", argv[0], argv[1]);
3172 /* pv == 0, parsing "push.s" pseudo instruction operands.
3173 pv != 0, parsing "pop.s" pseudo instruction operands. */
3175 static void
3176 do_pseudo_pushpop_stack (int argc, char *argv[],
3177 unsigned int pv)
3179 /* push.s Rb,Re,{$fp $gp $lp $sp} ==> smw.adm Rb,[$sp],Re,Eable4 */
3180 /* pop.s Rb,Re,{$fp $gp $lp $sp} ==> lmw.bim Rb,[$sp],Re,Eable4 */
3182 int rb, re;
3183 int en4;
3184 int last_arg_index;
3185 const char *opc = (pv == 0) ? "smw.adm" : "lmw.bim";
3187 rb = re = 0;
3189 if (argc == 1)
3191 /* argc=1, operands pattern: { $fp $gp $lp $sp } */
3193 /* Set register number Rb = Re = $sp = $r31. */
3194 rb = re = 31;
3196 else if (argc == 2 || argc == 3)
3198 /* argc=2, operands pattern: Rb, Re */
3199 /* argc=3, operands pattern: Rb, Re, { $fp $gp $lp $sp } */
3201 /* Get register number in integer. */
3202 rb = builtin_regnum (argv[0], NULL);
3203 re = builtin_regnum (argv[1], NULL);
3205 /* Rb should be equal/less than Re. */
3206 if (rb > re)
3207 as_bad ("The first operand (%s) should be equal to or smaller than "
3208 "second operand (%s).", argv[0], argv[1]);
3210 /* forbid using $fp|$gp|$lp|$sp in Rb or Re
3211 r28 r29 r30 r31 */
3212 if (rb >= 28)
3213 as_bad ("Cannot use $fp, $gp, $lp, or $sp at first operand !!");
3214 if (re >= 28)
3215 as_bad ("Cannot use $fp, $gp, $lp, or $sp at second operand !!");
3217 else
3219 as_bad ("Invalid operands pattern !!");
3222 /* Build Enable4 mask. */
3223 /* Using last_arg_index for argc=1|2|3 is safe, because $fp, $gp, $lp,
3224 and $sp only appear in argc=1 or argc=3 if argc=2, en4 remains 0,
3225 which is also valid for code generation. */
3226 en4 = 0;
3227 last_arg_index = argc - 1;
3228 if (strstr (argv[last_arg_index], "$fp"))
3229 en4 |= 8;
3230 if (strstr (argv[last_arg_index], "$gp"))
3231 en4 |= 4;
3232 if (strstr (argv[last_arg_index], "$lp"))
3233 en4 |= 2;
3234 if (strstr (argv[last_arg_index], "$sp"))
3235 en4 |= 1;
3237 md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc, rb, re, en4);
3240 static void
3241 do_pseudo_push_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[],
3242 unsigned int pv ATTRIBUTE_UNUSED)
3244 char size = 'x';
3245 /* If users omit push location, use $sp as default value. */
3246 char location[8] = "$sp"; /* 8 is enough for register name. */
3248 switch (pv & 0x3)
3250 case 0: size = 'b'; break;
3251 case 1: size = 'h'; break;
3252 case 2: size = 'w'; break;
3253 case 3: size = 'w'; break;
3256 if (argc == 2)
3258 strncpy (location, argv[1], sizeof (location) - 1);
3259 location[sizeof (location) - 1] = '\0';
3262 md_assemblef ("l.%c $ta,%s", size, argv[0]);
3263 md_assemblef ("smw.adm $ta,[%s],$ta", location);
3265 if ((pv & 0x3) == 0x3) /* double-word */
3267 md_assemblef ("l.w $ta,%s+4", argv[0]);
3268 md_assemblef ("smw.adm $ta,[%s],$ta", location);
3272 static void
3273 do_pseudo_pop_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[],
3274 unsigned int pv ATTRIBUTE_UNUSED)
3276 char size = 'x';
3277 /* If users omit pop location, use $sp as default value. */
3278 char location[8] = "$sp"; /* 8 is enough for register name. */
3280 switch (pv & 0x3)
3282 case 0: size = 'b'; break;
3283 case 1: size = 'h'; break;
3284 case 2: size = 'w'; break;
3285 case 3: size = 'w'; break;
3288 if (argc == 3)
3290 strncpy (location, argv[2], sizeof (location) - 1);
3291 location[sizeof (location) - 1] = '\0';
3294 if ((pv & 0x3) == 0x3) /* double-word */
3296 md_assemblef ("lmw.bim %s,[%s],%s", argv[1], location, argv[1]);
3297 md_assemblef ("s.w %s,%s+4", argv[1], argv[0]);
3300 md_assemblef ("lmw.bim %s,[%s],%s", argv[1], location, argv[1]);
3301 md_assemblef ("s.%c %s,%s", size, argv[1], argv[0]);
3304 static void
3305 do_pseudo_pusha (int argc ATTRIBUTE_UNUSED, char *argv[],
3306 unsigned int pv ATTRIBUTE_UNUSED)
3308 /* If users omit push location, use $sp as default value. */
3309 char location[8] = "$sp"; /* 8 is enough for register name. */
3311 if (argc == 2)
3313 strncpy (location, argv[1], sizeof (location) - 1);
3314 location[sizeof (location) - 1] = '\0';
3317 md_assemblef ("la $ta,%s", argv[0]);
3318 md_assemblef ("smw.adm $ta,[%s],$ta", location);
3321 static void
3322 do_pseudo_pushi (int argc ATTRIBUTE_UNUSED, char *argv[],
3323 unsigned int pv ATTRIBUTE_UNUSED)
3325 /* If users omit push location, use $sp as default value. */
3326 char location[8] = "$sp"; /* 8 is enough for register name. */
3328 if (argc == 2)
3330 strncpy (location, argv[1], sizeof (location) - 1);
3331 location[sizeof (location) - 1] = '\0';
3334 md_assemblef ("li $ta,%s", argv[0]);
3335 md_assemblef ("smw.adm $ta,[%s],$ta", location);
3338 static struct nds32_pseudo_opcode nds32_pseudo_opcode_table[] =
3340 {"b", 1, do_pseudo_b, 0, 0},
3341 {"bal", 1, do_pseudo_bal, 0, 0},
3343 {"bge", 3, do_pseudo_bge, 0, 0},
3344 {"bges", 3, do_pseudo_bges, 0, 0},
3346 {"bgt", 3, do_pseudo_bgt, 0, 0},
3347 {"bgts", 3, do_pseudo_bgts, 0, 0},
3349 {"ble", 3, do_pseudo_ble, 0, 0},
3350 {"bles", 3, do_pseudo_bles, 0, 0},
3352 {"blt", 3, do_pseudo_blt, 0, 0},
3353 {"blts", 3, do_pseudo_blts, 0, 0},
3355 {"br", 1, do_pseudo_br, 0, 0},
3356 {"bral", 1, do_pseudo_bral, 0, 0},
3358 {"call", 1, do_pseudo_bal, 0, 0},
3360 {"la", 2, do_pseudo_la, 0, 0},
3361 {"li", 2, do_pseudo_li, 0, 0},
3363 {"l.b", 2, do_pseudo_ls_bhw, 0, 0},
3364 {"l.h", 2, do_pseudo_ls_bhw, 1, 0},
3365 {"l.w", 2, do_pseudo_ls_bhw, 2, 0},
3366 {"l.bs", 2, do_pseudo_ls_bhw, 0 | 0x10, 0},
3367 {"l.hs", 2, do_pseudo_ls_bhw, 1 | 0x10, 0},
3368 {"s.b", 2, do_pseudo_ls_bhw, 0 | 0x80000000, 0},
3369 {"s.h", 2, do_pseudo_ls_bhw, 1 | 0x80000000, 0},
3370 {"s.w", 2, do_pseudo_ls_bhw, 2 | 0x80000000, 0},
3372 {"l.bp", 3, do_pseudo_ls_bhwp, 0, 0},
3373 {"l.bpc", 3, do_pseudo_ls_bhwpc, 0, 0},
3374 {"l.hp", 3, do_pseudo_ls_bhwp, 1, 0},
3375 {"l.hpc", 3, do_pseudo_ls_bhwpc, 1, 0},
3376 {"l.wp", 3, do_pseudo_ls_bhwp, 2, 0},
3377 {"l.wpc", 3, do_pseudo_ls_bhwpc, 2, 0},
3378 {"l.bsp", 3, do_pseudo_ls_bhwp, 0 | 0x10, 0},
3379 {"l.bspc", 3, do_pseudo_ls_bhwpc, 0 | 0x10, 0},
3380 {"l.hsp", 3, do_pseudo_ls_bhwp, 1 | 0x10, 0},
3381 {"l.hspc", 3, do_pseudo_ls_bhwpc, 1 | 0x10, 0},
3382 {"s.bp", 3, do_pseudo_ls_bhwp, 0 | 0x80000000, 0},
3383 {"s.bpc", 3, do_pseudo_ls_bhwpc, 0 | 0x80000000, 0},
3384 {"s.hp", 3, do_pseudo_ls_bhwp, 1 | 0x80000000, 0},
3385 {"s.hpc", 3, do_pseudo_ls_bhwpc, 1 | 0x80000000, 0},
3386 {"s.wp", 3, do_pseudo_ls_bhwp, 2 | 0x80000000, 0},
3387 {"s.wpc", 3, do_pseudo_ls_bhwpc, 2 | 0x80000000, 0},
3388 {"s.bsp", 3, do_pseudo_ls_bhwp, 0 | 0x80000000 | 0x10, 0},
3389 {"s.hsp", 3, do_pseudo_ls_bhwp, 1 | 0x80000000 | 0x10, 0},
3391 {"lbi.p", 3, do_pseudo_ls_bhwi, 0, 0},
3392 {"lhi.p", 3, do_pseudo_ls_bhwi, 1, 0},
3393 {"lwi.p", 3, do_pseudo_ls_bhwi, 2, 0},
3394 {"sbi.p", 3, do_pseudo_ls_bhwi, 0 | 0x80000000, 0},
3395 {"shi.p", 3, do_pseudo_ls_bhwi, 1 | 0x80000000, 0},
3396 {"swi.p", 3, do_pseudo_ls_bhwi, 2 | 0x80000000, 0},
3397 {"lbsi.p", 3, do_pseudo_ls_bhwi, 0 | 0x10, 0},
3398 {"lhsi.p", 3, do_pseudo_ls_bhwi, 1 | 0x10, 0},
3399 {"lwsi.p", 3, do_pseudo_ls_bhwi, 2 | 0x10, 0},
3401 {"move", 2, do_pseudo_move, 0, 0},
3402 {"neg", 2, do_pseudo_neg, 0, 0},
3403 {"not", 2, do_pseudo_not, 0, 0},
3405 {"pop", 2, do_pseudo_pushpop, 0, 0},
3406 {"push", 2, do_pseudo_pushpop, 0, 0},
3407 {"popm", 2, do_pseudo_pushpopm, 0, 0},
3408 {"pushm", 3, do_pseudo_pushpopm, 0, 0},
3410 {"v3push", 2, do_pseudo_v3push, 0, 0},
3411 {"v3pop", 2, do_pseudo_v3pop, 0, 0},
3413 /* Support pseudo instructions of pushing/poping registers into/from stack
3414 push.s Rb, Re, { $fp $gp $lp $sp } ==> smw.adm Rb,[$sp],Re,Enable4
3415 pop.s Rb, Re, { $fp $gp $lp $sp } ==> lmw.bim Rb,[$sp],Re,Enable4 */
3416 { "push.s", 3, do_pseudo_pushpop_stack, 0, 0 },
3417 { "pop.s", 3, do_pseudo_pushpop_stack, 1, 0 },
3418 { "push.b", 2, do_pseudo_push_bhwd, 0, 0 },
3419 { "push.h", 2, do_pseudo_push_bhwd, 1, 0 },
3420 { "push.w", 2, do_pseudo_push_bhwd, 2, 0 },
3421 { "push.d", 2, do_pseudo_push_bhwd, 3, 0 },
3422 { "pop.b", 3, do_pseudo_pop_bhwd, 0, 0 },
3423 { "pop.h", 3, do_pseudo_pop_bhwd, 1, 0 },
3424 { "pop.w", 3, do_pseudo_pop_bhwd, 2, 0 },
3425 { "pop.d", 3, do_pseudo_pop_bhwd, 3, 0 },
3426 { "pusha", 2, do_pseudo_pusha, 0, 0 },
3427 { "pushi", 2, do_pseudo_pushi, 0, 0 },
3429 {NULL, 0, NULL, 0, 0}
3432 static void
3433 nds32_init_nds32_pseudo_opcodes (void)
3435 struct nds32_pseudo_opcode *opcode;
3437 nds32_pseudo_opcode_hash = str_htab_create ();
3438 for (opcode = nds32_pseudo_opcode_table; opcode->opcode; opcode++)
3439 if (str_hash_insert (nds32_pseudo_opcode_hash, opcode->opcode, opcode, 0))
3440 as_fatal (_("duplicate %s"), opcode->opcode);
3443 static struct nds32_pseudo_opcode *
3444 nds32_lookup_pseudo_opcode (const char *str)
3446 struct nds32_pseudo_opcode *result;
3447 int i = 0;
3449 /* (*op) is the first word of current source line (*str) */
3450 int maxlen = strlen (str);
3451 char *op = xmalloc (maxlen + 1);
3453 for (i = 0; i < maxlen; i++)
3455 if (ISSPACE (op[i] = str[i]))
3456 break;
3458 op[i] = '\0';
3460 result = str_hash_find (nds32_pseudo_opcode_hash, op);
3461 free (op);
3462 return result;
3465 static void
3466 nds32_pseudo_opcode_wrapper (char *line, struct nds32_pseudo_opcode *opcode)
3468 int argc = 0;
3469 char *argv[8] = {NULL};
3470 char *s;
3471 char *str = xstrdup (line);
3473 /* Parse arguments for opcode. */
3474 s = str + strlen (opcode->opcode);
3476 if (!s[0])
3477 goto end;
3479 /* Dummy comma to ease separate arguments as below. */
3480 s[0] = ',';
3483 if (s[0] == ',')
3485 if (argc >= opcode->argc
3486 || (argc >= (int)ARRAY_SIZE (argv) - 1))
3487 as_bad (_("Too many argument. `%s'"), line);
3489 argv[argc] = s + 1;
3490 argc ++;
3491 s[0] = '\0';
3493 ++s;
3494 } while (s[0] != '\0');
3495 end:
3496 /* Put the origin line for debugging. */
3497 argv[argc] = line;
3498 opcode->proc (argc, argv, opcode->pseudo_val);
3499 free (str);
3502 /* This function will be invoked from function `nds32_after_parse_args'.
3503 Thus, if the value of option has been set, keep the value the way it is. */
3505 static int
3506 nds32_parse_arch (const char *str)
3508 static const struct nds32_arch
3510 const char *name;
3511 int baseline;
3512 int reduced_reg;
3513 int fpu_sp_ext;
3514 int fpu_dp_ext;
3515 int fpu_freg;
3516 int abi;
3517 } archs[] =
3519 {"v3m", ISA_V3M, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3520 {"v3j", ISA_V3, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3521 {"v3s", ISA_V3, 0, 1, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3522 {"v3f", ISA_V3, 0, 1, 1, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3523 {"v3", ISA_V3, 0, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3524 {"v2j", ISA_V2, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3525 {"v2s", ISA_V2, 0, 1, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3526 {"v2f", ISA_V2, 0, 1, 1, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3527 {"v2", ISA_V2, 0, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3529 size_t i;
3531 for (i = 0; i < ARRAY_SIZE (archs); i++)
3533 if (strcmp (str, archs[i].name) != 0)
3534 continue;
3536 /* The value `-1' represents this option has *NOT* been set. */
3537 nds32_baseline = (-1 != nds32_baseline) ? nds32_baseline : archs[i].baseline;
3538 nds32_gpr16 = (-1 != nds32_gpr16) ? nds32_gpr16 : archs[i].reduced_reg;
3539 nds32_fpu_sp_ext = (-1 != nds32_fpu_sp_ext) ? nds32_fpu_sp_ext : archs[i].fpu_sp_ext;
3540 nds32_fpu_dp_ext = (-1 != nds32_fpu_dp_ext) ? nds32_fpu_dp_ext : archs[i].fpu_dp_ext;
3541 nds32_freg = (-1 != nds32_freg) ? nds32_freg : archs[i].fpu_freg;
3542 nds32_abi = (-1 != nds32_abi) ? nds32_abi : archs[i].abi;
3544 return 1;
3547 /* Logic here rejects the input arch name. */
3548 as_bad (_("unknown arch name `%s'\n"), str);
3550 return 1;
3553 /* This function parses "baseline" specified. */
3555 static int
3556 nds32_parse_baseline (const char *str)
3558 if (strcmp (str, "v3") == 0)
3559 nds32_baseline = ISA_V3;
3560 else if (strcmp (str, "v3m") == 0)
3561 nds32_baseline = ISA_V3M;
3562 else if (strcmp (str, "v2") == 0)
3563 nds32_baseline = ISA_V2;
3564 else
3566 /* Logic here rejects the input baseline. */
3567 as_bad (_("unknown baseline `%s'\n"), str);
3568 return 0;
3571 return 1;
3574 /* This function parses "fpu-freg" specified. */
3576 static int
3577 nds32_parse_freg (const char *str)
3579 if (strcmp (str, "2") == 0)
3580 nds32_freg = E_NDS32_FPU_REG_32SP_16DP;
3581 else if (strcmp (str, "3") == 0)
3582 nds32_freg = E_NDS32_FPU_REG_32SP_32DP;
3583 else if (strcmp (str, "1") == 0)
3584 nds32_freg = E_NDS32_FPU_REG_16SP_8DP;
3585 else if (strcmp (str, "0") == 0)
3586 nds32_freg = E_NDS32_FPU_REG_8SP_4DP;
3587 else
3589 /* Logic here rejects the input FPU configuration. */
3590 as_bad (_("unknown FPU configuration `%s'\n"), str);
3591 return 0;
3594 return 1;
3597 /* This function parse "abi=" specified. */
3599 static int
3600 nds32_parse_abi (const char *str)
3602 if (strcmp (str, "v2") == 0)
3603 nds32_abi = E_NDS_ABI_AABI;
3604 /* Obsolete. */
3605 else if (strcmp (str, "v2fp") == 0)
3606 nds32_abi = E_NDS_ABI_V2FP;
3607 else if (strcmp (str, "v1") == 0)
3608 nds32_abi = E_NDS_ABI_V1;
3609 else if (strcmp (str,"v2fpp") == 0)
3610 nds32_abi = E_NDS_ABI_V2FP_PLUS;
3611 else
3613 /* Logic here rejects the input abi version. */
3614 as_bad (_("unknown ABI version`%s'\n"), str);
3615 return 0;
3618 return 1;
3621 /* This function turn on all extensions and instructions support. */
3623 static int
3624 nds32_all_ext (void)
3626 nds32_mac = 1;
3627 nds32_div = 1;
3628 nds32_dx_regs = 1;
3629 nds32_16bit_ext = 1;
3630 nds32_perf_ext = 1;
3631 nds32_perf_ext2 = 1;
3632 nds32_string_ext = 1;
3633 nds32_audio_ext = 1;
3634 nds32_fpu_fma = 1;
3635 nds32_fpu_sp_ext = 1;
3636 nds32_fpu_dp_ext = 1;
3637 nds32_dsp_ext = 1;
3638 nds32_zol_ext = 1;
3639 /* Turn off reduced register. */
3640 nds32_gpr16 = 0;
3642 return 1;
3645 /* GAS will call md_parse_option whenever getopt returns an unrecognized code,
3646 presumably indicating a special code value which appears in md_longopts.
3647 This function should return non-zero if it handled the option and zero
3648 otherwise. There is no need to print a message about an option not being
3649 recognized. This will be handled by the generic code. */
3652 nds32_parse_option (int c, const char *arg)
3654 struct nds32_parse_option_table *coarse_tune;
3655 struct nds32_set_option_table *fine_tune;
3656 const char *ptr_arg = NULL;
3658 switch (c)
3660 case OPTION_OPTIMIZE:
3661 optimize = 1;
3662 optimize_for_space = 0;
3663 break;
3664 case OPTION_OPTIMIZE_SPACE:
3665 optimize = 0;
3666 optimize_for_space = 1;
3667 break;
3668 case OPTION_BIG:
3669 target_big_endian = 1;
3670 break;
3671 case OPTION_LITTLE:
3672 target_big_endian = 0;
3673 break;
3674 case OPTION_TURBO:
3675 nds32_all_ext ();
3676 break;
3677 case OPTION_PIC:
3678 nds32_pic = 1;
3679 break;
3680 case OPTION_RELAX_FP_AS_GP_OFF:
3681 nds32_relax_fp_as_gp = 0;
3682 break;
3683 case OPTION_RELAX_B2BB_ON:
3684 nds32_relax_b2bb = 1;
3685 break;
3686 case OPTION_RELAX_ALL_OFF:
3687 nds32_relax_all = 0;
3688 break;
3689 default:
3690 /* Determination of which option table to search for to save time. */
3691 if (!arg)
3692 return 0;
3694 ptr_arg = strchr (arg, '=');
3696 if (ptr_arg)
3698 /* Find the value after '='. */
3699 if (ptr_arg != NULL)
3700 ptr_arg++;
3701 for (coarse_tune = parse_opts; coarse_tune->name != NULL; coarse_tune++)
3703 if (strncmp (arg, coarse_tune->name, (ptr_arg - arg)) == 0)
3705 coarse_tune->func (ptr_arg);
3706 return 1;
3710 else
3712 int disable = 0;
3714 /* Filter out the Disable option first. */
3715 if (startswith (arg, "no-"))
3717 disable = 1;
3718 arg += 3;
3721 for (fine_tune = toggle_opts; fine_tune->name != NULL; fine_tune++)
3723 if (strcmp (arg, fine_tune->name) == 0)
3725 if (fine_tune->var != NULL)
3726 *fine_tune->var = (disable) ? 0 : 1;
3727 return 1;
3731 /* Nothing match. */
3732 return 0;
3735 return 1;
3738 /* tc_check_label */
3740 void
3741 nds32_check_label (symbolS *label ATTRIBUTE_UNUSED)
3743 /* The code used to create BB is move to frob_label.
3744 They should go there. */
3747 static void
3748 set_endian_little (int on)
3750 target_big_endian = !on;
3753 /* These functions toggles the generation of 16-bit. First encounter signals
3754 the beginning of not generating 16-bit instructions and next encounter
3755 signals the restoring back to default behavior. */
3757 static void
3758 trigger_16bit (int trigger)
3760 enable_16bit = trigger;
3763 static int backup_16bit_mode;
3764 static void
3765 restore_16bit (int no_use ATTRIBUTE_UNUSED)
3767 enable_16bit = backup_16bit_mode;
3770 static void
3771 off_16bit (int no_use ATTRIBUTE_UNUSED)
3773 backup_16bit_mode = enable_16bit;
3774 enable_16bit = 0;
3777 /* Built-in segments for small object. */
3778 typedef struct nds32_seg_entryT
3780 segT s;
3781 const char *name;
3782 flagword flags;
3783 } nds32_seg_entry;
3785 nds32_seg_entry nds32_seg_table[] =
3787 {NULL, ".sdata_f", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3788 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3789 {NULL, ".sdata_b", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3790 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3791 {NULL, ".sdata_h", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3792 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3793 {NULL, ".sdata_w", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3794 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3795 {NULL, ".sdata_d", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3796 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3797 {NULL, ".sbss_f", SEC_ALLOC | SEC_SMALL_DATA},
3798 {NULL, ".sbss_b", SEC_ALLOC | SEC_SMALL_DATA},
3799 {NULL, ".sbss_h", SEC_ALLOC | SEC_SMALL_DATA},
3800 {NULL, ".sbss_w", SEC_ALLOC | SEC_SMALL_DATA},
3801 {NULL, ".sbss_d", SEC_ALLOC | SEC_SMALL_DATA}
3804 /* Indexes to nds32_seg_table[]. */
3805 enum NDS32_SECTIONS_ENUM
3807 SDATA_F_SECTION = 0,
3808 SDATA_B_SECTION = 1,
3809 SDATA_H_SECTION = 2,
3810 SDATA_W_SECTION = 3,
3811 SDATA_D_SECTION = 4,
3812 SBSS_F_SECTION = 5,
3813 SBSS_B_SECTION = 6,
3814 SBSS_H_SECTION = 7,
3815 SBSS_W_SECTION = 8,
3816 SBSS_D_SECTION = 9
3819 /* The following code is borrowed from v850_seg. Revise this is needed. */
3821 static void
3822 do_nds32_seg (int i, subsegT sub)
3824 nds32_seg_entry *seg = nds32_seg_table + i;
3826 obj_elf_section_change_hook ();
3828 if (seg->s != NULL)
3829 subseg_set (seg->s, sub);
3830 else
3832 seg->s = subseg_new (seg->name, sub);
3833 if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
3835 bfd_set_section_flags (seg->s, seg->flags);
3836 if ((seg->flags & SEC_LOAD) == 0)
3837 seg_info (seg->s)->bss = 1;
3842 static void
3843 nds32_seg (int i)
3845 subsegT sub = get_absolute_expression ();
3847 do_nds32_seg (i, sub);
3848 demand_empty_rest_of_line ();
3851 /* Set if label adjustment is needed. I should not adjust .xbyte in dwarf. */
3852 static symbolS *nds32_last_label; /* Last label for alignment. */
3854 static void
3855 add_mapping_symbol_for_align (int shift, valueT addr, int is_data_align)
3857 if ((shift > 1) && (addr & 1))
3859 int n = (1 << shift) - 1;
3860 if (!is_data_align)
3861 add_mapping_symbol (MAP_CODE, 1, 0);
3862 else if ((int) (addr & n) != n)
3863 add_mapping_symbol (MAP_CODE, 1, 0);
3865 else if ((shift > 1) && ((int) (addr & 1) == 0))
3866 add_mapping_symbol (MAP_CODE, 0, 0);
3869 /* This code is referred from D30V for adjust label to be with pending
3870 alignment. For example,
3871 LBYTE: .byte 0x12
3872 LHALF: .half 0x12
3873 LWORD: .word 0x12
3874 Without this, the above label will not attach to incoming data. */
3876 static void
3877 nds32_adjust_label (int n)
3879 /* FIXME: I think adjust label and alignment is
3880 the programmer's obligation. Sadly, VLSI team doesn't
3881 properly use .align for their test cases.
3882 So I re-implement cons_align and auto adjust labels, again.
3884 I think d30v's implementation is simple and good enough. */
3886 symbolS *label = nds32_last_label;
3887 nds32_last_label = NULL;
3889 /* SEC_ALLOC is used to eliminate .debug_ sections.
3890 SEC_CODE is used to include section for ILM. */
3891 if (((now_seg->flags & SEC_ALLOC) == 0 && (now_seg->flags & SEC_CODE) == 0)
3892 || strcmp (now_seg->name, ".eh_frame") == 0
3893 || strcmp (now_seg->name, ".gcc_except_table") == 0)
3894 return;
3896 /* Only frag by alignment when needed.
3897 Otherwise, it will fail to optimize labels on 4-byte boundary. (bug8454)
3898 See md_convert_frag () and RELAX_SET_RELAXABLE (frag) for details. */
3899 if (frag_now_fix () & ((1 << n) -1 ))
3901 if (subseg_text_p (now_seg))
3903 add_mapping_symbol_for_align (n, frag_now_fix (), 1);
3904 frag_align_code (n, 0);
3906 else
3907 frag_align (n, 0, 0);
3909 /* Record the minimum alignment for this segment. */
3910 record_alignment (now_seg, n - OCTETS_PER_BYTE_POWER);
3913 if (label != NULL)
3915 symbolS *sym;
3916 int label_seen = false;
3917 struct frag *old_frag;
3918 valueT old_value, new_value;
3920 gas_assert (S_GET_SEGMENT (label) == now_seg);
3922 old_frag = symbol_get_frag (label);
3923 old_value = S_GET_VALUE (label);
3924 new_value = (valueT) frag_now_fix ();
3926 /* Multiple labels may be on the same address. And the last symbol
3927 may not be a label at all, e.g., register name, external function names,
3928 so I have to track the last label in tc_frob_label instead of
3929 just using symbol_lastP. */
3930 for (sym = symbol_lastP; sym != NULL; sym = symbol_previous (sym))
3932 if (symbol_get_frag (sym) == old_frag
3933 && S_GET_VALUE (sym) == old_value)
3935 /* Warning HERE! */
3936 label_seen = true;
3937 symbol_set_frag (sym, frag_now);
3938 S_SET_VALUE (sym, new_value);
3940 else if (label_seen && symbol_get_frag (sym) != old_frag)
3941 break;
3946 void
3947 nds32_cons_align (int size ATTRIBUTE_UNUSED)
3949 /* Do nothing here.
3950 This is called before `md_flush_pending_output' is called by `cons'.
3952 There are two things should be done for auto-adjust-label.
3953 1. Align data/instructions and adjust label to be attached to them.
3954 2. Clear auto-adjust state, so incoming data/instructions will not
3955 adjust the label.
3957 For example,
3958 .byte 0x1
3959 .L0:
3960 .word 0x2
3961 .word 0x3
3962 in this case, '.word 0x2' will adjust the label, .L0, but '.word 0x3' should not.
3964 I think `md_flush_pending_output' is a good place to clear the auto-adjust state,
3965 but it is also called by `cons' before this function.
3966 To simplify the code, instead of overriding .zero, .fill, .space, etc,
3967 I think we should just adjust label in `nds32_aligned_X_cons' instead of here. */
3970 static void
3971 make_mapping_symbol (enum mstate state, valueT value, fragS * frag, unsigned int align)
3973 symbolS *symbol_p = NULL;
3974 const char *symbol_name = NULL;
3975 switch (state)
3977 case MAP_DATA:
3978 if (align == 0)
3979 symbol_name = "$d0";
3980 else if (align == 1)
3981 symbol_name = "$d1";
3982 else if (align == 2)
3983 symbol_name = "$d2";
3984 else if (align == 3)
3985 symbol_name = "$d3";
3986 else if (align == 4)
3987 symbol_name = "$d4";
3988 break;
3989 case MAP_CODE:
3990 symbol_name = "$c";
3991 break;
3992 default:
3993 abort ();
3996 symbol_p = symbol_new (symbol_name, now_seg, frag, value);
3997 /* local scope attribute */
3998 symbol_get_bfdsym (symbol_p)->flags |= BSF_NO_FLAGS | BSF_LOCAL;
4001 static void
4002 add_mapping_symbol (enum mstate state, unsigned int padding_byte,
4003 unsigned int align)
4005 enum mstate current_mapping_state =
4006 seg_info (now_seg)->tc_segment_info_data.mapstate;
4008 if (state == MAP_CODE
4009 && current_mapping_state == state)
4010 return;
4012 if (!SEG_NORMAL (now_seg)
4013 || !subseg_text_p (now_seg))
4014 return;
4016 /* start adding mapping symbol */
4017 seg_info (now_seg)->tc_segment_info_data.mapstate = state;
4018 make_mapping_symbol (state, (valueT) frag_now_fix () + padding_byte,
4019 frag_now, align);
4022 static void
4023 nds32_aligned_cons (int idx)
4025 nds32_adjust_label (idx);
4026 add_mapping_symbol (MAP_DATA, 0, idx);
4027 /* Call default handler. */
4028 cons (1 << idx);
4029 if (now_seg->flags & SEC_CODE
4030 && now_seg->flags & SEC_ALLOC && now_seg->flags & SEC_RELOC)
4032 /* Use BFD_RELOC_NDS32_DATA to avoid linker
4033 optimization replacing data. */
4034 expressionS exp;
4036 exp.X_add_number = 0;
4037 exp.X_op = O_constant;
4038 fix_new_exp (frag_now, frag_now_fix () - (1 << idx), 1 << idx,
4039 &exp, 0, BFD_RELOC_NDS32_DATA);
4043 /* `.double' directive. */
4045 static void
4046 nds32_aligned_float_cons (int type)
4048 switch (type)
4050 case 'f':
4051 case 'F':
4052 case 's':
4053 case 'S':
4054 nds32_adjust_label (2);
4055 break;
4056 case 'd':
4057 case 'D':
4058 case 'r':
4059 case 'R':
4060 nds32_adjust_label (4);
4061 break;
4062 default:
4063 as_bad ("Unrecognized float type, %c\n", (char)type);
4065 /* Call default handler. */
4066 float_cons (type);
4069 static void
4070 nds32_enable_pic (int ignore ATTRIBUTE_UNUSED)
4072 /* Another way to do -mpic.
4073 This is for GCC internal use and should always be first line
4074 of code, otherwise, the effect is not determined. */
4075 nds32_pic = 1;
4078 static void
4079 nds32_set_abi (int ver)
4081 nds32_abi = ver;
4084 /* Relax directive to set relocation R_NDS32_RELAX_ENTRY value. */
4086 static void
4087 nds32_relax_relocs (int relax)
4089 char saved_char;
4090 char *name;
4091 int i;
4092 const char *subtype_relax[] =
4093 {"", "",};
4095 name = input_line_pointer;
4096 while (*input_line_pointer && !ISSPACE (*input_line_pointer))
4097 input_line_pointer++;
4098 saved_char = *input_line_pointer;
4099 *input_line_pointer = 0;
4101 for (i = 0; i < (int) ARRAY_SIZE (subtype_relax); i++)
4103 if (strcmp (name, subtype_relax[i]) == 0)
4105 switch (i)
4107 case 0:
4108 case 1:
4109 enable_relax_relocs = relax & enable_relax_relocs;
4110 break;
4111 default:
4112 break;
4114 break;
4117 *input_line_pointer = saved_char;
4118 ignore_rest_of_line ();
4121 /* Record which arguments register($r0 ~ $r5) is not used in callee.
4122 bit[i] for $ri */
4124 static void
4125 nds32_set_hint_func_args (int ignore ATTRIBUTE_UNUSED)
4127 ignore_rest_of_line ();
4130 /* Insert relocations to mark the begin and end of a fp-omitted function,
4131 for further relaxation use.
4132 bit[i] for $ri */
4134 static void
4135 nds32_omit_fp_begin (int mode)
4137 expressionS exp;
4139 if (nds32_relax_fp_as_gp == 0)
4140 return;
4141 exp.X_op = O_symbol;
4142 exp.X_add_symbol = abs_section_sym;
4143 if (mode == 1)
4145 in_omit_fp = 1;
4146 exp.X_add_number = R_NDS32_RELAX_REGION_OMIT_FP_FLAG;
4147 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
4148 BFD_RELOC_NDS32_RELAX_REGION_BEGIN);
4150 else
4152 in_omit_fp = 0;
4153 exp.X_add_number = R_NDS32_RELAX_REGION_OMIT_FP_FLAG;
4154 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
4155 BFD_RELOC_NDS32_RELAX_REGION_END);
4159 static void
4160 nds32_loop_begin (int mode)
4162 /* Insert loop region relocation here. */
4163 expressionS exp;
4165 exp.X_op = O_symbol;
4166 exp.X_add_symbol = abs_section_sym;
4167 if (mode == 1)
4169 exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG;
4170 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
4171 BFD_RELOC_NDS32_RELAX_REGION_BEGIN);
4173 else
4175 exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG;
4176 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
4177 BFD_RELOC_NDS32_RELAX_REGION_END);
4181 struct nds32_relocs_group
4183 struct nds32_relocs_pattern *pattern;
4184 struct nds32_relocs_group *next;
4187 static struct nds32_relocs_group *nds32_relax_hint_current = NULL;
4188 /* Used to reorder the id for ".relax_hint id". */
4189 static int relax_hint_bias = 0;
4190 /* Record current relax hint id. */
4191 static int relax_hint_id_current = -1;
4192 int reset_bias = 0;
4193 /* If ".relax_hint begin" is triggered? */
4194 int relax_hint_begin = 0;
4196 /* Record the reordered relax hint id. */
4198 struct relax_hint_id
4200 int old_id;
4201 int new_id;
4202 struct relax_hint_id *next;
4205 /* FIXME: Need to find somewhere to free the list. */
4206 struct relax_hint_id *record_id_head = NULL;
4208 /* Is the buffer large enough? */
4209 #define MAX_BUFFER 12
4211 static char *nds_itoa (int n);
4213 static char *
4214 nds_itoa (int n)
4216 char *buf = xmalloc (MAX_BUFFER * sizeof (char));
4217 snprintf (buf, MAX_BUFFER, "%d", n);
4218 return buf;
4221 /* Insert a relax hint. */
4223 static void
4224 nds32_relax_hint (int mode ATTRIBUTE_UNUSED)
4226 char *name = NULL;
4227 char saved_char;
4228 struct nds32_relocs_pattern *relocs = NULL;
4229 struct nds32_relocs_group *group, *new;
4230 struct relax_hint_id *record_id;
4232 name = input_line_pointer;
4233 while (*input_line_pointer && !ISSPACE (*input_line_pointer))
4234 input_line_pointer++;
4235 saved_char = *input_line_pointer;
4236 *input_line_pointer = 0;
4237 name = strdup (name);
4239 if (name && strcmp (name, "begin") == 0)
4241 if (relax_hint_id_current == -1)
4242 reset_bias = 1;
4243 relax_hint_bias++;
4244 relax_hint_id_current++;
4245 relax_hint_begin = 1;
4248 /* Original case ".relax_hint id". It's id may need to be reordered. */
4249 if (!relax_hint_begin)
4251 int tmp = strtol (name, NULL, 10);
4252 record_id = record_id_head;
4253 while (record_id)
4255 if (record_id->old_id == tmp)
4257 name = nds_itoa (record_id->new_id);
4258 goto reordered_id;
4260 record_id = record_id->next;
4262 if (reset_bias)
4264 relax_hint_bias = relax_hint_id_current - atoi (name) + 1;
4265 reset_bias = 0;
4267 relax_hint_id_current = tmp + relax_hint_bias;
4269 /* Insert the element to the head of the link list. */
4270 struct relax_hint_id *tmp_id = malloc (sizeof (struct relax_hint_id));
4271 tmp_id->old_id = tmp;
4272 tmp_id->new_id = relax_hint_id_current;
4273 tmp_id->next = record_id_head;
4274 record_id_head = tmp_id;
4277 if (name && strcmp (name, "end") == 0)
4278 relax_hint_begin = 0;
4279 name = nds_itoa (relax_hint_id_current);
4281 reordered_id:
4283 /* Find relax hint entry for next instruction, and all member will be
4284 initialized at that time. */
4285 relocs = str_hash_find (nds32_hint_hash, name);
4286 if (relocs == NULL)
4288 relocs = notes_calloc (1, sizeof (*relocs));
4289 str_hash_insert (nds32_hint_hash, name, relocs, 0);
4291 else
4293 while (relocs->next)
4294 relocs = relocs->next;
4295 relocs->next = notes_calloc (1, sizeof (*relocs));
4296 relocs = relocs->next;
4299 *input_line_pointer = saved_char;
4300 ignore_rest_of_line ();
4302 /* Get the final one of relax hint series. */
4304 /* It has to build this list because there are maybe more than one
4305 instructions relative to the same instruction. It to connect to
4306 next instruction after md_assemble. */
4307 new = XNEW (struct nds32_relocs_group);
4308 memset (new, 0, sizeof (struct nds32_relocs_group));
4309 new->pattern = relocs;
4310 new->next = NULL;
4311 group = nds32_relax_hint_current;
4312 if (!group)
4313 nds32_relax_hint_current = new;
4314 else
4316 while (group->next != NULL)
4317 group = group->next;
4318 group->next = new;
4320 relaxing = true;
4323 /* Decide the size of vector entries, only accepts 4 or 16 now. */
4325 static void
4326 nds32_vec_size (int ignore ATTRIBUTE_UNUSED)
4328 expressionS exp;
4330 expression (&exp);
4332 if (exp.X_op == O_constant)
4334 if (exp.X_add_number == 4 || exp.X_add_number == 16)
4336 if (vec_size == 0)
4337 vec_size = exp.X_add_number;
4338 else if (vec_size != exp.X_add_number)
4339 as_warn (_("Different arguments of .vec_size are found, "
4340 "previous %d, current %d"),
4341 (int) vec_size, (int) exp.X_add_number);
4343 else
4344 as_warn (_("Argument of .vec_size is expected 4 or 16, actual: %d."),
4345 (int) exp.X_add_number);
4347 else
4348 as_warn (_("Argument of .vec_size is not a constant."));
4351 /* The behavior of ".flag" directive varies depending on the target.
4352 In nds32 target, we use it to recognize whether this assembly content is
4353 generated by compiler. Other features can also be added in this function
4354 in the future. */
4356 static void
4357 nds32_flag (int ignore ATTRIBUTE_UNUSED)
4359 char *name;
4360 char saved_char;
4361 int i;
4362 const char *possible_flags[] = { "verbatim" };
4364 /* Skip whitespaces. */
4365 name = input_line_pointer;
4366 while (*input_line_pointer && !ISSPACE (*input_line_pointer))
4367 input_line_pointer++;
4368 saved_char = *input_line_pointer;
4369 *input_line_pointer = 0;
4371 for (i = 0; i < (int) ARRAY_SIZE (possible_flags); i++)
4373 if (strcmp (name, possible_flags[i]) == 0)
4375 switch (i)
4377 case 0:
4378 /* flag: verbatim */
4379 verbatim = 1;
4380 break;
4381 default:
4382 break;
4384 /* Already found the flag, no need to continue next loop. */
4385 break;
4389 *input_line_pointer = saved_char;
4390 ignore_rest_of_line ();
4393 static void
4394 ict_model (int ignore ATTRIBUTE_UNUSED)
4396 char *name;
4397 char saved_char;
4398 int i;
4399 const char *possible_flags[] = { "small", "large" };
4401 /* Skip whitespaces. */
4402 name = input_line_pointer;
4403 while (*input_line_pointer && !ISSPACE (*input_line_pointer))
4404 input_line_pointer++;
4405 saved_char = *input_line_pointer;
4406 *input_line_pointer = 0;
4408 for (i = 0; i < (int) ARRAY_SIZE (possible_flags); i++)
4410 if (strcmp (name, possible_flags[i]) == 0)
4412 switch (i)
4414 case 0:
4415 /* flag: verbatim */
4416 ict_flag = ICT_SMALL;
4417 break;
4418 case 1:
4419 ict_flag = ICT_LARGE;
4420 break;
4421 default:
4422 break;
4424 /* Already found the flag, no need to continue next loop. */
4425 break;
4429 *input_line_pointer = saved_char;
4430 ignore_rest_of_line ();
4433 static void
4434 nds32_n12hc (int ignore ATTRIBUTE_UNUSED)
4436 /* N1213HC core is used. */
4440 /* The target specific pseudo-ops which we support. */
4441 const pseudo_typeS md_pseudo_table[] =
4443 /* Forced alignment if declared these ways. */
4444 {"ascii", stringer, 8 + 0},
4445 {"asciz", stringer, 8 + 1},
4446 {"double", nds32_aligned_float_cons, 'd'},
4447 {"dword", nds32_aligned_cons, 3},
4448 {"float", nds32_aligned_float_cons, 'f'},
4449 {"half", nds32_aligned_cons, 1},
4450 {"hword", nds32_aligned_cons, 1},
4451 {"int", nds32_aligned_cons, 2},
4452 {"long", nds32_aligned_cons, 2},
4453 {"octa", nds32_aligned_cons, 4},
4454 {"quad", nds32_aligned_cons, 3},
4455 {"qword", nds32_aligned_cons, 4},
4456 {"short", nds32_aligned_cons, 1},
4457 {"byte", nds32_aligned_cons, 0},
4458 {"single", nds32_aligned_float_cons, 'f'},
4459 {"string", stringer, 8 + 1},
4460 {"word", nds32_aligned_cons, 2},
4462 {"little", set_endian_little, 1},
4463 {"big", set_endian_little, 0},
4464 {"16bit_on", trigger_16bit, 1},
4465 {"16bit_off", trigger_16bit, 0},
4466 {"restore_16bit", restore_16bit, 0},
4467 {"off_16bit", off_16bit, 0},
4469 {"sdata_d", nds32_seg, SDATA_D_SECTION},
4470 {"sdata_w", nds32_seg, SDATA_W_SECTION},
4471 {"sdata_h", nds32_seg, SDATA_H_SECTION},
4472 {"sdata_b", nds32_seg, SDATA_B_SECTION},
4473 {"sdata_f", nds32_seg, SDATA_F_SECTION},
4475 {"sbss_d", nds32_seg, SBSS_D_SECTION},
4476 {"sbss_w", nds32_seg, SBSS_W_SECTION},
4477 {"sbss_h", nds32_seg, SBSS_H_SECTION},
4478 {"sbss_b", nds32_seg, SBSS_B_SECTION},
4479 {"sbss_f", nds32_seg, SBSS_F_SECTION},
4481 {"pic", nds32_enable_pic, 0},
4482 {"n12_hc", nds32_n12hc, 0},
4483 {"abi_1", nds32_set_abi, E_NDS_ABI_V1},
4484 {"abi_2", nds32_set_abi, E_NDS_ABI_AABI},
4485 /* Obsolete. */
4486 {"abi_2fp", nds32_set_abi, E_NDS_ABI_V2FP},
4487 {"abi_2fp_plus", nds32_set_abi, E_NDS_ABI_V2FP_PLUS},
4488 {"relax", nds32_relax_relocs, 1},
4489 {"no_relax", nds32_relax_relocs, 0},
4490 {"hint_func_args", nds32_set_hint_func_args, 0}, /* Abandon?? */
4491 {"omit_fp_begin", nds32_omit_fp_begin, 1},
4492 {"omit_fp_end", nds32_omit_fp_begin, 0},
4493 {"vec_size", nds32_vec_size, 0},
4494 {"flag", nds32_flag, 0},
4495 {"innermost_loop_begin", nds32_loop_begin, 1},
4496 {"innermost_loop_end", nds32_loop_begin, 0},
4497 {"relax_hint", nds32_relax_hint, 0},
4498 {"ict_model", ict_model, 0},
4499 {NULL, NULL, 0}
4502 void
4503 nds32_pre_do_align (int n, char *fill, int len, int max)
4505 /* Only make a frag if we HAVE to... */
4506 fragS *fragP;
4507 if (n != 0 && !need_pass_2)
4509 if (fill == NULL)
4511 if (subseg_text_p (now_seg))
4513 dwarf2_emit_insn (0);
4514 fragP = frag_now;
4515 add_mapping_symbol_for_align (n, frag_now_fix (), 0);
4516 frag_align_code (n, max);
4518 /* Tag this alignment when there is a label before it. */
4519 if (label_exist)
4521 fragP->tc_frag_data.flag = NDS32_FRAG_LABEL;
4522 label_exist = 0;
4525 else
4526 frag_align (n, 0, max);
4528 else if (len <= 1)
4529 frag_align (n, *fill, max);
4530 else
4531 frag_align_pattern (n, fill, len, max);
4535 void
4536 nds32_do_align (int n)
4538 /* Optimize for space and label exists. */
4539 expressionS exp;
4541 /* FIXME:I think this will break debug info sections and except_table. */
4542 if (!enable_relax_relocs || !subseg_text_p (now_seg))
4543 return;
4545 /* Create and attach a BFD_RELOC_NDS32_LABEL fixup
4546 the size of instruction may not be correct because
4547 it could be relaxable. */
4548 exp.X_op = O_symbol;
4549 exp.X_add_symbol = section_symbol (now_seg);
4550 exp.X_add_number = n;
4551 fix_new_exp (frag_now,
4552 frag_now_fix (), 0, &exp, 0, BFD_RELOC_NDS32_LABEL);
4555 /* Supported Andes machines. */
4556 struct nds32_machs
4558 enum bfd_architecture bfd_mach;
4559 int mach_flags;
4562 /* This is the callback for nds32-asm.c to parse operands. */
4565 nds32_asm_parse_operand (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED,
4566 struct nds32_asm_insn *pinsn,
4567 char **pstr, int64_t *value)
4569 char *hold;
4570 expressionS *pexp = pinsn->info;
4572 hold = input_line_pointer;
4573 input_line_pointer = *pstr;
4574 expression (pexp);
4575 resolve_register (pexp);
4576 *pstr = input_line_pointer;
4577 input_line_pointer = hold;
4579 switch (pexp->X_op)
4581 case O_symbol:
4582 *value = 0;
4583 return NASM_R_SYMBOL;
4584 case O_constant:
4585 *value = pexp->X_add_number;
4586 return NASM_R_CONST;
4587 case O_illegal:
4588 case O_absent:
4589 case O_register:
4590 default:
4591 return NASM_R_ILLEGAL;
4595 /* GAS will call this function at the start of the assembly, after the command
4596 line arguments have been parsed and all the machine independent
4597 initializations have been completed. */
4599 void
4600 md_begin (void)
4602 const struct nds32_keyword *k;
4603 relax_info_t *relax_info;
4604 int flags = 0;
4606 bfd_set_arch_mach (stdoutput, TARGET_ARCH, nds32_baseline);
4608 nds32_init_nds32_pseudo_opcodes ();
4609 asm_desc.parse_operand = nds32_asm_parse_operand;
4610 if (nds32_gpr16)
4611 flags |= NASM_OPEN_REDUCED_REG;
4612 nds32_asm_init (&asm_desc, flags);
4614 /* Initial general purpose registers hash table. */
4615 nds32_gprs_hash = str_htab_create ();
4616 for (k = nds32_keyword_gpr; k->name; k++)
4617 str_hash_insert (nds32_gprs_hash, k->name, k, 0);
4619 /* Initial branch hash table. */
4620 nds32_relax_info_hash = str_htab_create ();
4621 for (relax_info = relax_table; relax_info->opcode; relax_info++)
4622 str_hash_insert (nds32_relax_info_hash, relax_info->opcode, relax_info, 0);
4624 /* Initial relax hint hash table. */
4625 nds32_hint_hash = str_htab_create ();
4626 enable_16bit = nds32_16bit_ext;
4629 /* HANDLE_ALIGN in write.c. */
4631 void
4632 nds32_handle_align (fragS *fragp)
4634 static const unsigned char nop16[] = { 0x92, 0x00 };
4635 static const unsigned char nop32[] = { 0x40, 0x00, 0x00, 0x09 };
4636 int bytes;
4637 char *p;
4639 if (fragp->fr_type != rs_align_code)
4640 return;
4642 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
4643 p = fragp->fr_literal + fragp->fr_fix;
4645 if (bytes & 1)
4647 *p++ = 0;
4648 bytes--;
4651 if (bytes & 2)
4653 expressionS exp_t;
4654 exp_t.X_op = O_symbol;
4655 exp_t.X_add_symbol = abs_section_sym;
4656 exp_t.X_add_number = R_NDS32_INSN16_CONVERT_FLAG;
4657 fix_new_exp (fragp, fragp->fr_fix, 2, &exp_t, 0,
4658 BFD_RELOC_NDS32_INSN16);
4659 memcpy (p, nop16, 2);
4660 p += 2;
4661 bytes -= 2;
4664 while (bytes >= 4)
4666 memcpy (p, nop32, 4);
4667 p += 4;
4668 bytes -= 4;
4671 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
4672 fragp->fr_fix += bytes;
4675 /* md_flush_pending_output */
4677 void
4678 nds32_flush_pending_output (void)
4680 nds32_last_label = NULL;
4683 void
4684 nds32_frob_label (symbolS *label)
4686 dwarf2_emit_label (label);
4689 /* TC_START_LABEL */
4692 nds32_start_label (int asmdone ATTRIBUTE_UNUSED, int secdone ATTRIBUTE_UNUSED)
4694 if (optimize && subseg_text_p (now_seg))
4695 label_exist = 1;
4696 return 1;
4699 /* TARGET_FORMAT */
4701 const char *
4702 nds32_target_format (void)
4704 #ifdef TE_LINUX
4705 if (target_big_endian)
4706 return "elf32-nds32be-linux";
4707 else
4708 return "elf32-nds32le-linux";
4709 #else
4710 if (target_big_endian)
4711 return "elf32-nds32be";
4712 else
4713 return "elf32-nds32le";
4714 #endif
4717 static enum nds32_br_range
4718 get_range_type (const struct nds32_field *field)
4720 gas_assert (field != NULL);
4722 if (field->bitpos != 0)
4723 return BR_RANGE_U4G;
4725 if (field->bitsize == 24 && field->shift == 1)
4726 return BR_RANGE_S16M;
4727 else if (field->bitsize == 16 && field->shift == 1)
4728 return BR_RANGE_S64K;
4729 else if (field->bitsize == 14 && field->shift == 1)
4730 return BR_RANGE_S16K;
4731 else if (field->bitsize == 8 && field->shift == 1)
4732 return BR_RANGE_S256;
4733 else
4734 return BR_RANGE_U4G;
4737 /* Save pseudo instruction relocation list. */
4739 static struct nds32_relocs_pattern*
4740 nds32_elf_save_pseudo_pattern (fixS* fixP, struct nds32_asm_insn *insn,
4741 char *out, symbolS *sym,
4742 struct nds32_relocs_pattern *reloc_ptr,
4743 fragS *fragP)
4745 struct nds32_opcode *opcode = insn->opcode;
4746 if (!reloc_ptr)
4747 reloc_ptr = XNEW (struct nds32_relocs_pattern);
4748 reloc_ptr->seg = now_seg;
4749 reloc_ptr->sym = sym;
4750 reloc_ptr->frag = fragP;
4751 reloc_ptr->frchain = frchain_now;
4752 reloc_ptr->fixP = fixP;
4753 reloc_ptr->opcode = opcode;
4754 reloc_ptr->where = out;
4755 reloc_ptr->insn = insn->insn;
4756 reloc_ptr->next = NULL;
4757 return reloc_ptr;
4760 /* Check X_md to transform relocation. */
4762 static fixS*
4763 nds32_elf_record_fixup_exp (fragS *fragP, const char *str,
4764 const struct nds32_field *fld,
4765 expressionS *pexp, char* out,
4766 struct nds32_asm_insn *insn)
4768 int reloc = -1;
4769 expressionS exp;
4770 fixS *fixP = NULL;
4772 /* Handle instruction relocation. */
4773 if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_HI20))
4775 /* Relocation for hi20 modifier. */
4776 switch (pexp->X_md)
4778 case BFD_RELOC_NDS32_GOTOFF: /* @GOTOFF */
4779 reloc = BFD_RELOC_NDS32_GOTOFF_HI20;
4780 break;
4781 case BFD_RELOC_NDS32_GOT20: /* @GOT */
4782 reloc = BFD_RELOC_NDS32_GOT_HI20;
4783 break;
4784 case BFD_RELOC_NDS32_25_PLTREL: /* @PLT */
4785 if (!nds32_pic)
4786 as_bad (_("Invalid PIC expression."));
4787 else
4788 reloc = BFD_RELOC_NDS32_PLT_GOTREL_HI20;
4789 break;
4790 case BFD_RELOC_NDS32_GOTPC20: /* _GLOBAL_OFFSET_TABLE_ */
4791 reloc = BFD_RELOC_NDS32_GOTPC_HI20;
4792 break;
4793 case BFD_RELOC_NDS32_TPOFF: /* @TPOFF */
4794 reloc = BFD_RELOC_NDS32_TLS_LE_HI20;
4795 break;
4796 case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */
4797 reloc = nds32_pic ? BFD_RELOC_NDS32_TLS_IEGP_HI20 : BFD_RELOC_NDS32_TLS_IE_HI20;
4798 break;
4799 case BFD_RELOC_NDS32_TLS_DESC: /* @TLSDESC */
4800 reloc = BFD_RELOC_NDS32_TLS_DESC_HI20;
4801 break;
4802 default: /* No suffix */
4803 if (nds32_pic)
4804 /* When the file is pic, the address must be offset to gp.
4805 It may define another relocation or use GOTOFF. */
4806 reloc = BFD_RELOC_NDS32_PLT_GOTREL_HI20;
4807 else
4808 reloc = BFD_RELOC_NDS32_HI20;
4809 break;
4811 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4812 insn->info, 0 /* pcrel */, reloc);
4814 else if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_LO12))
4816 /* Relocation for lo12 modifier. */
4817 if (fld->bitsize == 15 && fld->shift == 0)
4819 /* [ls]bi || ori */
4820 switch (pexp->X_md)
4822 case BFD_RELOC_NDS32_GOTOFF: /* @GOTOFF */
4823 reloc = BFD_RELOC_NDS32_GOTOFF_LO12;
4824 break;
4825 case BFD_RELOC_NDS32_GOT20: /* @GOT */
4826 reloc = BFD_RELOC_NDS32_GOT_LO12;
4827 break;
4828 case BFD_RELOC_NDS32_25_PLTREL: /* @PLT */
4829 if (!nds32_pic)
4830 as_bad (_("Invalid PIC expression."));
4831 else
4832 reloc = BFD_RELOC_NDS32_PLT_GOTREL_LO12;
4833 break;
4834 case BFD_RELOC_NDS32_GOTPC20: /* _GLOBAL_OFFSET_TABLE_ */
4835 reloc = BFD_RELOC_NDS32_GOTPC_LO12;
4836 break;
4837 case BFD_RELOC_NDS32_TPOFF: /* @TPOFF */
4838 reloc = BFD_RELOC_NDS32_TLS_LE_LO12;
4839 break;
4840 case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */
4841 reloc = nds32_pic ? BFD_RELOC_NDS32_TLS_IEGP_LO12 : BFD_RELOC_NDS32_TLS_IE_LO12;
4842 break;
4843 case BFD_RELOC_NDS32_TLS_DESC: /* @TLSDESC */
4844 reloc = BFD_RELOC_NDS32_TLS_DESC_LO12;
4845 break;
4846 default: /* No suffix */
4847 if (nds32_pic)
4848 /* When the file is pic, the address must be offset to gp.
4849 It may define another relocation or use GOTOFF. */
4850 reloc = BFD_RELOC_NDS32_PLT_GOTREL_LO12;
4851 else
4852 reloc = BFD_RELOC_NDS32_LO12S0;
4853 break;
4856 else if (fld->bitsize == 15 && fld->shift == 1)
4857 reloc = BFD_RELOC_NDS32_LO12S1; /* [ls]hi */
4858 else if (fld->bitsize == 15 && fld->shift == 2)
4860 /* [ls]wi */
4861 switch (pexp->X_md)
4863 case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */
4864 reloc = nds32_pic ? BFD_RELOC_NDS32_TLS_IEGP_LO12S2 : BFD_RELOC_NDS32_TLS_IE_LO12S2;
4865 break;
4866 default: /* No suffix */
4867 reloc = BFD_RELOC_NDS32_LO12S2;
4868 break;
4871 else if (fld->bitsize == 15 && fld->shift == 3)
4872 reloc = BFD_RELOC_NDS32_LO12S3; /* [ls]di */
4873 else if (fld->bitsize == 12 && fld->shift == 2)
4874 reloc = BFD_RELOC_NDS32_LO12S2_SP; /* f[ls][sd]i */
4876 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4877 insn->info, 0 /* pcrel */, reloc);
4879 else if (fld && fld->bitpos == 0 && insn->opcode->isize == 4
4880 && (insn->attr & NASM_ATTR_PCREL))
4882 /* Relocation for 32-bit branch instructions. */
4883 if (fld->bitsize == 24 && fld->shift == 1)
4884 reloc = BFD_RELOC_NDS32_25_PCREL;
4885 else if (fld->bitsize == 16 && fld->shift == 1)
4886 reloc = BFD_RELOC_NDS32_17_PCREL;
4887 else if (fld->bitsize == 14 && fld->shift == 1)
4888 reloc = BFD_RELOC_NDS32_15_PCREL;
4889 else if (fld->bitsize == 8 && fld->shift == 1)
4890 reloc = BFD_RELOC_NDS32_WORD_9_PCREL;
4891 else
4892 abort ();
4894 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4895 insn->info, 1 /* pcrel */, reloc);
4897 else if (fld && fld->bitpos == 0 && insn->opcode->isize == 4
4898 && (insn->attr & NASM_ATTR_GPREL))
4900 /* Relocation for 32-bit gp-relative instructions. */
4901 if (fld->bitsize == 19 && fld->shift == 0)
4902 reloc = BFD_RELOC_NDS32_SDA19S0;
4903 else if (fld->bitsize == 18 && fld->shift == 1)
4904 reloc = BFD_RELOC_NDS32_SDA18S1;
4905 else if (fld->bitsize == 17 && fld->shift == 2)
4906 reloc = BFD_RELOC_NDS32_SDA17S2;
4907 else
4908 abort ();
4910 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4911 insn->info, 0 /* pcrel */, reloc);
4912 /* Insert INSN16 for converting fp_as_gp. */
4913 exp.X_op = O_symbol;
4914 exp.X_add_symbol = abs_section_sym;
4915 exp.X_add_number = 0;
4916 if (in_omit_fp && reloc == BFD_RELOC_NDS32_SDA17S2)
4917 fix_new_exp (fragP, out - fragP->fr_literal,
4918 insn->opcode->isize, &exp, 0 /* pcrel */,
4919 BFD_RELOC_NDS32_INSN16);
4921 else if (fld && fld->bitpos == 0 && insn->opcode->isize == 2
4922 && (insn->attr & NASM_ATTR_PCREL))
4924 /* Relocation for 16-bit branch instructions. */
4925 if (fld->bitsize == 8 && fld->shift == 1)
4926 reloc = BFD_RELOC_NDS32_9_PCREL;
4927 else
4928 abort ();
4930 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4931 insn->info, 1 /* pcrel */, reloc);
4933 else if (fld)
4934 as_bad (_("Don't know how to handle this field. %s"), str);
4936 return fixP;
4939 /* Build instruction pattern to relax. There are two type group pattern
4940 including pseudo instruction and relax hint. */
4942 static void
4943 nds32_elf_build_relax_relation (fixS *fixP, expressionS *pexp, char* out,
4944 struct nds32_asm_insn *insn, fragS *fragP,
4945 const struct nds32_field *fld,
4946 bool pseudo_hint)
4948 struct nds32_relocs_pattern *reloc_ptr;
4949 struct nds32_relocs_group *group;
4950 symbolS *sym = NULL;
4952 /* The expression may be used uninitialized. */
4953 if (fld)
4954 sym = pexp->X_add_symbol;
4956 if (pseudo_hint)
4958 /* We cannot know how many instructions will be expanded for
4959 the pseudo instruction here. The first expanded instruction fills
4960 the memory created by relax_hint. The follower will created and link
4961 here. */
4962 group = nds32_relax_hint_current;
4963 while (group)
4965 if (group->pattern->opcode == NULL)
4966 nds32_elf_save_pseudo_pattern (fixP, insn, out, sym,
4967 group->pattern, fragP);
4968 else
4970 group->pattern->next =
4971 nds32_elf_save_pseudo_pattern (fixP, insn, out, sym,
4972 NULL, fragP);
4973 group->pattern = group->pattern->next;
4975 group = group->next;
4978 else if (pseudo_opcode)
4980 /* Save instruction relation for pseudo instruction expanding pattern. */
4981 reloc_ptr = nds32_elf_save_pseudo_pattern (fixP, insn, out, sym,
4982 NULL, fragP);
4983 if (!relocs_list)
4984 relocs_list = reloc_ptr;
4985 else
4987 struct nds32_relocs_pattern *temp = relocs_list;
4988 while (temp->next)
4989 temp = temp->next;
4990 temp->next = reloc_ptr;
4993 else if (nds32_relax_hint_current)
4995 /* Save instruction relation by relax hint. */
4996 group = nds32_relax_hint_current;
4997 while (group)
4999 nds32_elf_save_pseudo_pattern (fixP, insn, out, sym,
5000 group->pattern, fragP);
5001 group = group->next;
5002 free (nds32_relax_hint_current);
5003 nds32_relax_hint_current = group;
5007 /* Set relaxing false only for relax_hint trigger it. */
5008 if (!pseudo_opcode)
5009 relaxing = false;
5012 #define N32_MEM_EXT(insn) ((N32_OP6_MEM << 25) | insn)
5014 /* Relax pattern for link time relaxation. */
5015 /* Relaxation types only! relocation types are not necessary. */
5016 /* Refer to nds32_elf_record_fixup_exp (). */
5018 static struct nds32_relax_hint_table relax_ls_table[] =
5021 /* LA and Floating LSI. */
5022 .main_type = NDS32_RELAX_HINT_LA_FLSI,
5023 .relax_code_size = 12,
5024 .relax_code_seq =
5026 OP6 (SETHI),
5027 OP6 (ORI),
5028 OP6 (LBI),
5030 .relax_fixup =
5032 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5033 {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
5034 {4, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5035 {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_LSI},
5036 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5037 {8, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5038 {0, 0, 0, 0}
5042 /* Load Address / Load-Store (LALS). */
5043 .main_type = NDS32_RELAX_HINT_LALS,
5044 .relax_code_size = 12,
5045 .relax_code_seq =
5047 OP6 (SETHI),
5048 OP6 (ORI),
5049 OP6 (LBI),
5051 .relax_fixup =
5053 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5054 {4, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5055 {8, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5056 {0, 0, 0, 0}
5060 /* B(AL) symbol@PLT */
5061 .main_type = NDS32_RELAX_HINT_LA_PLT,
5062 .relax_code_size = 16,
5063 .relax_code_seq =
5065 OP6 (SETHI),
5066 OP6 (ORI),
5067 OP6 (ALU1),
5068 OP6 (JREG),
5070 .relax_fixup =
5072 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5073 {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
5074 {8, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
5075 {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PLT_GOT_SUFF},
5076 {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5077 {12, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5078 {0, 0, 0, 0}
5082 /* LA (@GOT). */
5083 .main_type = NDS32_RELAX_HINT_LA_GOT,
5084 .relax_code_size = 12,
5085 .relax_code_seq =
5087 OP6 (SETHI),
5088 OP6 (ORI),
5089 OP6 (MEM),
5091 .relax_fixup =
5093 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5094 {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
5095 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5096 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_GOT_SUFF},
5097 {0, 0, 0, 0}
5101 /* LA (@GOTOFF). */
5102 .main_type = NDS32_RELAX_HINT_LA_GOTOFF,
5103 .relax_code_size = 16,
5104 .relax_code_seq =
5106 OP6 (SETHI),
5107 OP6 (ORI),
5108 OP6 (ALU1),
5109 OP6 (MEM),
5111 .relax_fixup =
5113 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5114 {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
5115 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5116 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_GOTOFF_SUFF},
5117 {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5118 {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_GOTOFF_SUFF},
5119 {0, 0, 0, 0}
5123 /* TLS LE LS|LA */
5124 .main_type = NDS32_RELAX_HINT_TLS_LE_LS,
5125 .relax_code_size = 16,
5126 .relax_code_seq =
5128 OP6(SETHI),
5129 OP6(ORI),
5130 OP6(MEM),
5131 OP6(ALU1),
5133 .relax_fixup =
5135 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5136 {4, 4, NDS32_HINT | NDS32_PTR_MULTIPLE, BFD_RELOC_NDS32_PTR},
5137 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5138 {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_LE_LS},
5139 {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5140 {12, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_LE_ADD},
5141 {0, 0, 0, 0}
5145 /* TLS IE LA */
5146 .main_type = NDS32_RELAX_HINT_TLS_IE_LA,
5147 .relax_code_size = 8,
5148 .relax_code_seq =
5150 OP6(SETHI),
5151 OP6(LBI),
5153 .relax_fixup =
5155 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5156 {4, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5157 {0, 0, 0, 0}
5161 /* TLS IEGP LA */
5162 .main_type = NDS32_RELAX_HINT_TLS_IEGP_LA,
5163 .relax_code_size = 12,
5164 .relax_code_seq =
5166 OP6 (SETHI),
5167 OP6 (ORI),
5168 OP6 (MEM),
5170 .relax_fixup =
5172 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5173 {4, 4, NDS32_HINT | NDS32_PTR_PATTERN, BFD_RELOC_NDS32_PTR},
5174 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5175 {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_IEGP_LW},
5176 {0, 0, 0, 0}
5180 /* TLS DESC LS: */
5181 .main_type = NDS32_RELAX_HINT_TLS_DESC_LS,
5182 .relax_code_size = 24,
5183 .relax_code_seq =
5185 OP6 (SETHI),
5186 OP6 (ORI),
5187 OP6 (ALU1),
5188 OP6 (LBI), /* load argument */
5189 OP6 (JREG),
5190 OP6 (MEM), /* load/store variable or load argument */
5192 .relax_fixup =
5194 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5195 {4, 4, NDS32_HINT | NDS32_PTR_PATTERN, BFD_RELOC_NDS32_PTR},
5196 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5197 {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_DESC_ADD},
5198 {12, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_DESC_FUNC},
5199 {16, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_DESC_CALL},
5200 {20, 4, NDS32_HINT | NDS32_SYM_DESC_MEM, BFD_RELOC_NDS32_TLS_DESC_MEM},
5201 {0, 0, 0, 0}
5205 .main_type = 0,
5206 .relax_code_seq = {0},
5207 .relax_fixup = {{0, 0 , 0, 0}}
5211 /* Since sethi loadstore relocation has to using next instruction to determine
5212 elimination itself or not, we have to return the next instruction range. */
5214 static int
5215 nds32_elf_sethi_range (struct nds32_relocs_pattern *pattern)
5217 int range = 0;
5218 while (pattern)
5220 switch (pattern->opcode->value)
5222 case INSN_LBI:
5223 case INSN_SBI:
5224 case INSN_LBSI:
5225 case N32_MEM_EXT (N32_MEM_LB):
5226 case N32_MEM_EXT (N32_MEM_LBS):
5227 case N32_MEM_EXT (N32_MEM_SB):
5228 range = NDS32_LOADSTORE_BYTE;
5229 break;
5230 case INSN_LHI:
5231 case INSN_SHI:
5232 case INSN_LHSI:
5233 case N32_MEM_EXT (N32_MEM_LH):
5234 case N32_MEM_EXT (N32_MEM_LHS):
5235 case N32_MEM_EXT (N32_MEM_SH):
5236 range = NDS32_LOADSTORE_HALF;
5237 break;
5238 case INSN_LWI:
5239 case INSN_SWI:
5240 case N32_MEM_EXT (N32_MEM_LW):
5241 case N32_MEM_EXT (N32_MEM_SW):
5242 range = NDS32_LOADSTORE_WORD;
5243 break;
5244 case INSN_FLSI:
5245 case INSN_FSSI:
5246 range = NDS32_LOADSTORE_FLOAT_S;
5247 break;
5248 case INSN_FLDI:
5249 case INSN_FSDI:
5250 range = NDS32_LOADSTORE_FLOAT_D;
5251 break;
5252 case INSN_ORI:
5253 range = NDS32_LOADSTORE_IMM;
5254 break;
5255 default:
5256 range = NDS32_LOADSTORE_NONE;
5257 break;
5259 if (range != NDS32_LOADSTORE_NONE)
5260 break;
5261 pattern = pattern->next;
5263 return range;
5266 /* The args means: instruction size, the 1st instruction is converted to 16 or
5267 not, optimize option, 16 bit instruction is enable. */
5269 #define SET_ADDEND(size, convertible, optimize, insn16_on) \
5270 (((size) & 0xff) | ((convertible) ? 1u << 31 : 0) \
5271 | ((optimize) ? 1 << 30 : 0) | (insn16_on ? 1 << 29 : 0))
5272 #define MAC_COMBO (E_NDS32_HAS_FPU_MAC_INST|E_NDS32_HAS_MAC_DX_INST)
5274 static void
5275 nds32_set_elf_flags_by_insn (struct nds32_asm_insn * insn)
5277 static int skip_flags = NASM_ATTR_FPU_FMA
5278 | NASM_ATTR_BRANCH | NASM_ATTR_SATURATION_EXT
5279 | NASM_ATTR_GPREL | NASM_ATTR_DXREG
5280 | NASM_ATTR_ISA_V1 | NASM_ATTR_ISA_V2
5281 | NASM_ATTR_ISA_V3 | NASM_ATTR_ISA_V3M
5282 | NASM_ATTR_PCREL;
5284 int new_flags = insn->opcode->attr & ~skip_flags;
5285 while (new_flags)
5287 int next = 1 << (ffs (new_flags) - 1);
5288 new_flags &= ~next;
5289 switch (next)
5291 case NASM_ATTR_PERF_EXT:
5293 if (nds32_perf_ext)
5295 nds32_elf_flags |= E_NDS32_HAS_EXT_INST;
5296 skip_flags |= NASM_ATTR_PERF_EXT;
5298 else
5299 as_bad (_("instruction %s requires enabling performance "
5300 "extension"), insn->opcode->opcode);
5302 break;
5303 case NASM_ATTR_PERF2_EXT:
5305 if (nds32_perf_ext2)
5307 nds32_elf_flags |= E_NDS32_HAS_EXT2_INST;
5308 skip_flags |= NASM_ATTR_PERF2_EXT;
5310 else
5311 as_bad (_("instruction %s requires enabling performance "
5312 "extension II"), insn->opcode->opcode);
5314 break;
5315 case NASM_ATTR_AUDIO_ISAEXT:
5317 if (nds32_audio_ext)
5319 nds32_elf_flags |= E_NDS32_HAS_AUDIO_INST;
5320 skip_flags |= NASM_ATTR_AUDIO_ISAEXT;
5322 else
5323 as_bad (_("instruction %s requires enabling AUDIO extension"),
5324 insn->opcode->opcode);
5326 break;
5327 case NASM_ATTR_STR_EXT:
5329 if (nds32_string_ext)
5331 nds32_elf_flags |= E_NDS32_HAS_STRING_INST;
5332 skip_flags |= NASM_ATTR_STR_EXT;
5334 else
5335 as_bad (_("instruction %s requires enabling STRING extension"),
5336 insn->opcode->opcode);
5338 break;
5339 case NASM_ATTR_DIV:
5341 if (insn->opcode->attr & NASM_ATTR_DXREG)
5343 if (nds32_div && nds32_dx_regs)
5345 nds32_elf_flags |= E_NDS32_HAS_DIV_DX_INST;
5346 skip_flags |= NASM_ATTR_DIV;
5348 else
5349 as_bad (_("instruction %s requires enabling DIV & DX_REGS "
5350 "extension"), insn->opcode->opcode);
5353 break;
5354 case NASM_ATTR_FPU:
5356 if (nds32_fpu_sp_ext || nds32_fpu_dp_ext)
5358 if (!(nds32_elf_flags
5359 & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST)))
5360 nds32_fpu_com = 1;
5361 skip_flags |= NASM_ATTR_FPU;
5363 else
5364 as_bad (_("instruction %s requires enabling FPU extension"),
5365 insn->opcode->opcode);
5367 break;
5368 case NASM_ATTR_FPU_SP_EXT:
5370 if (nds32_fpu_sp_ext)
5372 nds32_elf_flags |= E_NDS32_HAS_FPU_INST;
5373 skip_flags |= NASM_ATTR_FPU_SP_EXT;
5375 else
5376 as_bad (_("instruction %s requires enabling FPU_SP extension"),
5377 insn->opcode->opcode);
5379 break;
5380 case NASM_ATTR_FPU_DP_EXT:
5382 if (nds32_fpu_dp_ext)
5384 nds32_elf_flags |= E_NDS32_HAS_FPU_DP_INST;
5385 skip_flags |= NASM_ATTR_FPU_DP_EXT;
5387 else
5388 as_bad (_("instruction %s requires enabling FPU_DP extension"),
5389 insn->opcode->opcode);
5391 break;
5392 case NASM_ATTR_MAC:
5394 if (insn->opcode->attr & NASM_ATTR_FPU_SP_EXT)
5396 if (nds32_fpu_sp_ext && nds32_mac)
5397 nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST;
5398 else
5399 as_bad (_("instruction %s requires enabling FPU_MAC "
5400 "extension"), insn->opcode->opcode);
5402 else if (insn->opcode->attr & NASM_ATTR_FPU_DP_EXT)
5404 if (nds32_fpu_dp_ext && nds32_mac)
5405 nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST;
5406 else
5407 as_bad (_("instruction %s requires enabling FPU_MAC "
5408 "extension"), insn->opcode->opcode);
5410 else if (insn->opcode->attr & NASM_ATTR_DXREG)
5412 if (nds32_dx_regs && nds32_mac)
5413 nds32_elf_flags |= E_NDS32_HAS_MAC_DX_INST;
5414 else
5415 as_bad (_("instruction %s requires enabling DX_REGS "
5416 "extension"), insn->opcode->opcode);
5419 if (MAC_COMBO == (MAC_COMBO & nds32_elf_flags))
5420 skip_flags |= NASM_ATTR_MAC;
5422 break;
5423 case NASM_ATTR_DSP_ISAEXT:
5425 if (nds32_dsp_ext)
5427 nds32_elf_flags |= E_NDS32_HAS_DSP_INST;
5428 skip_flags |= NASM_ATTR_DSP_ISAEXT;
5430 else
5431 as_bad (_("instruction %s requires enabling dsp extension"),
5432 insn->opcode->opcode);
5434 break;
5435 case NASM_ATTR_ZOL:
5437 if (nds32_zol_ext)
5439 nds32_elf_flags |= E_NDS32_HAS_ZOL;
5440 skip_flags |= NASM_ATTR_ZOL;
5442 else
5443 as_bad (_("instruction %s requires enabling zol extension"),
5444 insn->opcode->opcode);
5446 break;
5447 default:
5448 as_bad (_("internal error: unknown instruction attribute: 0x%08x"),
5449 next);
5454 /* Flag for analysis relaxation type. */
5456 enum nds32_insn_type
5458 N32_RELAX_SETHI = 1,
5459 N32_RELAX_BR = (1 << 1),
5460 N32_RELAX_LSI = (1 << 2),
5461 N32_RELAX_JUMP = (1 << 3),
5462 N32_RELAX_CALL = (1 << 4),
5463 N32_RELAX_ORI = (1 << 5),
5464 N32_RELAX_MEM = (1 << 6),
5465 N32_RELAX_MOVI = (1 << 7),
5466 N32_RELAX_ALU1 = (1 << 8),
5467 N32_RELAX_16BIT = (1 << 9),
5470 struct nds32_hint_map
5472 /* the preamble relocation */
5473 bfd_reloc_code_real_type hi_type;
5474 /* mnemonic */
5475 const char *opc;
5476 /* relax pattern ID */
5477 enum nds32_relax_hint_type hint_type;
5478 /* range */
5479 enum nds32_br_range range;
5480 /* pattern character flags */
5481 enum nds32_insn_type insn_list;
5482 /* optional pattern character flags */
5483 enum nds32_insn_type option_list;
5486 /* Table to match instructions with hint and relax pattern. */
5488 static struct nds32_hint_map hint_map [] =
5491 /* LONGCALL4. */
5492 BFD_RELOC_NDS32_HI20,
5493 "jal",
5494 NDS32_RELAX_HINT_NONE,
5495 BR_RANGE_U4G,
5496 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL,
5500 /* LONGCALL5. */
5501 _dummy_first_bfd_reloc_code_real,
5502 "bgezal",
5503 NDS32_RELAX_HINT_NONE,
5504 BR_RANGE_S16M,
5505 N32_RELAX_BR | N32_RELAX_CALL,
5509 /* LONGCALL6. */
5510 BFD_RELOC_NDS32_HI20,
5511 "bgezal",
5512 NDS32_RELAX_HINT_NONE,
5513 BR_RANGE_U4G,
5514 N32_RELAX_BR | N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL,
5518 /* LONGJUMP4. */
5519 BFD_RELOC_NDS32_HI20,
5520 "j",
5521 NDS32_RELAX_HINT_NONE,
5522 BR_RANGE_U4G,
5523 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_JUMP,
5527 /* LONGJUMP5. */
5528 /* There is two kinds of variation of LONGJUMP5. One of them
5529 generate EMPTY relocation for converted INSN16 if needed.
5530 But we don't distinguish them here. */
5531 _dummy_first_bfd_reloc_code_real,
5532 "beq",
5533 NDS32_RELAX_HINT_NONE,
5534 BR_RANGE_S16M,
5535 N32_RELAX_BR | N32_RELAX_JUMP,
5539 /* LONGJUMP6. */
5540 BFD_RELOC_NDS32_HI20,
5541 "beq",
5542 NDS32_RELAX_HINT_NONE,
5543 BR_RANGE_U4G,
5544 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_BR | N32_RELAX_JUMP,
5548 /* LONGJUMP7. */
5549 _dummy_first_bfd_reloc_code_real,
5550 "beqc",
5551 NDS32_RELAX_HINT_NONE,
5552 BR_RANGE_S16K,
5553 N32_RELAX_MOVI | N32_RELAX_BR,
5557 /* LONGCALL (BAL|JR|LA symbol@PLT). */
5558 BFD_RELOC_NDS32_PLT_GOTREL_HI20,
5559 NULL,
5560 NDS32_RELAX_HINT_LA_PLT,
5561 BR_RANGE_U4G,
5562 N32_RELAX_SETHI | N32_RELAX_ORI,
5563 N32_RELAX_ALU1 | N32_RELAX_CALL | N32_RELAX_JUMP,
5565 /* relative issue: #12566 */
5567 /* LA and Floating LSI. */
5568 BFD_RELOC_NDS32_HI20,
5569 NULL,
5570 NDS32_RELAX_HINT_LA_FLSI,
5571 BR_RANGE_U4G,
5572 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_LSI,
5575 /* relative issue: #11685 #11602 */
5577 /* load address / load-store (LALS). */
5578 BFD_RELOC_NDS32_HI20,
5579 NULL,
5580 NDS32_RELAX_HINT_LALS,
5581 BR_RANGE_U4G,
5582 N32_RELAX_SETHI,
5583 N32_RELAX_ORI | N32_RELAX_LSI,
5586 /* setup $GP (_GLOBAL_OFFSET_TABLE_) */
5587 BFD_RELOC_NDS32_GOTPC_HI20,
5588 NULL,
5589 NDS32_RELAX_HINT_LALS,
5590 BR_RANGE_U4G,
5591 N32_RELAX_SETHI | N32_RELAX_ORI,
5595 /* GOT LA/LS (symbol@GOT) */
5596 BFD_RELOC_NDS32_GOT_HI20,
5597 NULL,
5598 NDS32_RELAX_HINT_LA_GOT,
5599 BR_RANGE_U4G,
5600 N32_RELAX_SETHI | N32_RELAX_ORI,
5601 N32_RELAX_MEM,
5604 /* GOTOFF LA/LS (symbol@GOTOFF) */
5605 BFD_RELOC_NDS32_GOTOFF_HI20,
5606 NULL,
5607 NDS32_RELAX_HINT_LA_GOTOFF,
5608 BR_RANGE_U4G,
5609 N32_RELAX_SETHI | N32_RELAX_ORI,
5610 N32_RELAX_ALU1 | N32_RELAX_MEM, /* | N32_RELAX_LSI, */
5613 /* TLS LE LA|LS (@TPOFF) */
5614 BFD_RELOC_NDS32_TLS_LE_HI20,
5615 NULL,
5616 NDS32_RELAX_HINT_TLS_LE_LS,
5617 BR_RANGE_U4G,
5618 N32_RELAX_SETHI | N32_RELAX_ORI,
5619 N32_RELAX_ALU1 | N32_RELAX_MEM,
5622 /* TLS IE LA */
5623 BFD_RELOC_NDS32_TLS_IE_HI20,
5624 NULL,
5625 NDS32_RELAX_HINT_TLS_IE_LA,
5626 BR_RANGE_U4G,
5627 N32_RELAX_SETHI | N32_RELAX_LSI,
5631 /* TLS IE LS */
5632 BFD_RELOC_NDS32_TLS_IE_HI20,
5633 NULL,
5634 NDS32_RELAX_HINT_TLS_IE_LS,
5635 BR_RANGE_U4G,
5636 N32_RELAX_SETHI | N32_RELAX_LSI | N32_RELAX_MEM,
5640 /* TLS IEGP LA */
5641 BFD_RELOC_NDS32_TLS_IEGP_HI20,
5642 NULL,
5643 NDS32_RELAX_HINT_TLS_IEGP_LA,
5644 BR_RANGE_U4G,
5645 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_MEM,
5649 /* TLS DESC LS */
5650 BFD_RELOC_NDS32_TLS_DESC_HI20,
5651 NULL,
5652 NDS32_RELAX_HINT_TLS_DESC_LS,
5653 BR_RANGE_U4G,
5654 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_ALU1 | N32_RELAX_CALL,
5655 N32_RELAX_LSI | N32_RELAX_MEM,
5657 /* last one */
5658 {0, NULL, 0, 0 ,0, 0}
5661 /* Find the relaxation pattern according to instructions. */
5663 static bool
5664 nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern,
5665 struct nds32_relax_hint_table *hint_info)
5667 unsigned int opcode, seq_size;
5668 enum nds32_br_range range;
5669 struct nds32_relocs_pattern *pattern, *hi_pattern = NULL;
5670 const char *opc = NULL;
5671 relax_info_t *relax_info = NULL;
5672 nds32_relax_fixup_info_t *fixup_info, *hint_fixup;
5673 enum nds32_relax_hint_type hint_type = NDS32_RELAX_HINT_NONE;
5674 struct nds32_relax_hint_table *table_ptr;
5675 uint32_t *code_seq, *hint_code;
5676 enum nds32_insn_type relax_type = 0;
5677 struct nds32_hint_map *map_ptr = hint_map;
5678 unsigned int i;
5679 const char *check_insn[] =
5680 { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8" };
5682 /* TODO: PLT GOT. */
5683 /* Traverse all pattern instruction and set flag. */
5684 pattern = relocs_pattern;
5685 while (pattern)
5687 if (pattern->opcode->isize == 4)
5689 /* 4 byte instruction. */
5690 opcode = N32_OP6 (pattern->opcode->value);
5691 switch (opcode)
5693 case N32_OP6_SETHI:
5694 hi_pattern = pattern;
5695 relax_type |= N32_RELAX_SETHI;
5696 break;
5697 case N32_OP6_MEM:
5698 relax_type |= N32_RELAX_MEM;
5699 break;
5700 case N32_OP6_ALU1:
5701 relax_type |= N32_RELAX_ALU1;
5702 break;
5703 case N32_OP6_ORI:
5704 relax_type |= N32_RELAX_ORI;
5705 break;
5706 case N32_OP6_BR1:
5707 case N32_OP6_BR2:
5708 case N32_OP6_BR3:
5709 relax_type |= N32_RELAX_BR;
5710 break;
5711 case N32_OP6_MOVI:
5712 relax_type |= N32_RELAX_MOVI;
5713 break;
5714 case N32_OP6_LBI:
5715 case N32_OP6_SBI:
5716 case N32_OP6_LBSI:
5717 case N32_OP6_LHI:
5718 case N32_OP6_SHI:
5719 case N32_OP6_LHSI:
5720 case N32_OP6_LWI:
5721 case N32_OP6_SWI:
5722 case N32_OP6_LWC:
5723 case N32_OP6_SWC:
5724 case N32_OP6_LDC:
5725 case N32_OP6_SDC:
5726 relax_type |= N32_RELAX_LSI;
5727 break;
5728 case N32_OP6_JREG:
5729 if (__GF (pattern->opcode->value, 0, 1) == 1)
5730 relax_type |= N32_RELAX_CALL;
5731 else
5732 relax_type |= N32_RELAX_JUMP;
5733 break;
5734 case N32_OP6_JI:
5735 if (__GF (pattern->opcode->value, 24, 1) == 1)
5736 relax_type |= N32_RELAX_CALL;
5737 else
5738 relax_type |= N32_RELAX_JUMP;
5739 break;
5740 default:
5741 as_warn (_("relax hint unrecognized instruction: line %d."),
5742 pattern->frag->fr_line);
5743 return false;
5746 else
5748 /* 2 byte instruction. Compare by opcode name because
5749 the opcode of 2byte instruction is not regular. */
5750 int is_matched = 0;
5751 for (i = 0; i < ARRAY_SIZE (check_insn); i++)
5753 if (strcmp (pattern->opcode->opcode, check_insn[i]) == 0)
5755 relax_type |= N32_RELAX_BR;
5756 is_matched += 1;
5757 break;
5760 if (!is_matched)
5761 relax_type |= N32_RELAX_16BIT;
5763 pattern = pattern->next;
5766 /* Analysis instruction flag to choose relaxation table. */
5767 while (map_ptr->insn_list != 0)
5769 struct nds32_hint_map *hint = map_ptr++;
5770 enum nds32_insn_type must = hint->insn_list;
5771 enum nds32_insn_type optional = hint->option_list;
5772 enum nds32_insn_type extra;
5774 if (must != (must & relax_type))
5775 continue;
5777 extra = relax_type ^ must;
5778 if (extra != (extra & optional))
5779 continue;
5781 if (!hi_pattern
5782 || (hi_pattern->fixP
5783 && hi_pattern->fixP->fx_r_type == hint->hi_type))
5785 opc = hint->opc;
5786 hint_type = hint->hint_type;
5787 range = hint->range;
5788 map_ptr = hint;
5789 break;
5793 if (map_ptr->insn_list == 0)
5795 if (!nds32_pic)
5796 as_warn (_("Can not find match relax hint. Line: %d"),
5797 relocs_pattern->frag->fr_line);
5798 return false;
5801 /* Get the match table. */
5802 if (opc)
5804 /* Branch relax pattern. */
5805 relax_info = str_hash_find (nds32_relax_info_hash, opc);
5806 if (!relax_info)
5807 return false;
5808 fixup_info = relax_info->relax_fixup[range];
5809 code_seq = relax_info->relax_code_seq[range];
5810 seq_size = relax_info->relax_code_size[range];
5812 else if (hint_type)
5814 /* Load-store relax pattern. */
5815 table_ptr = relax_ls_table;
5816 while (table_ptr->main_type != 0)
5818 if (table_ptr->main_type == hint_type)
5820 fixup_info = table_ptr->relax_fixup;
5821 code_seq = table_ptr->relax_code_seq;
5822 seq_size = table_ptr->relax_code_size;
5823 break;
5825 table_ptr++;
5827 if (table_ptr->main_type == 0)
5828 return false;
5830 else
5831 return false;
5833 hint_fixup = hint_info->relax_fixup;
5834 hint_code = hint_info->relax_code_seq;
5835 hint_info->relax_code_size = seq_size;
5837 while (fixup_info->size != 0)
5839 if (fixup_info->ramp & NDS32_HINT)
5841 memcpy (hint_fixup, fixup_info, sizeof (nds32_relax_fixup_info_t));
5842 hint_fixup++;
5844 fixup_info++;
5846 /* Clear final relocation. */
5847 memset (hint_fixup, 0, sizeof (nds32_relax_fixup_info_t));
5848 /* Copy code sequence. */
5849 memcpy (hint_code, code_seq, seq_size);
5850 return true;
5853 /* Because there are a lot of variant of load-store, check
5854 all these type here. */
5856 #define CLEAN_REG(insn) ((insn) & 0xfe0003ff)
5857 #define GET_OPCODE(insn) ((insn) & 0xfe000000)
5859 static bool
5860 nds32_match_hint_insn (struct nds32_opcode *opcode, uint32_t seq)
5862 const char *check_insn[] =
5863 { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8", "jral5" };
5864 uint32_t insn = opcode->value;
5865 unsigned int i;
5867 insn = CLEAN_REG (opcode->value);
5868 if (insn == seq)
5869 return true;
5871 switch (seq)
5873 case OP6 (LBI):
5874 /* In relocation_table, it regards instruction LBI as representation
5875 of all the NDS32_RELAX_HINT_LS pattern. */
5876 if (insn == OP6 (LBI) || insn == OP6 (SBI) || insn == OP6 (LBSI)
5877 || insn == OP6 (LHI) || insn == OP6 (SHI) || insn == OP6 (LHSI)
5878 || insn == OP6 (LWI) || insn == OP6 (SWI)
5879 || insn == OP6 (LWC) || insn == OP6 (SWC)
5880 || insn == OP6 (LDC) || insn == OP6 (SDC))
5881 return true;
5882 break;
5883 case OP6 (BR2):
5884 /* This is for LONGCALL5 and LONGCALL6. */
5885 if (insn == OP6 (BR2))
5886 return true;
5887 break;
5888 case OP6 (BR1):
5889 /* This is for LONGJUMP5 and LONGJUMP6. */
5890 if (opcode->isize == 4
5891 && (insn == OP6 (BR1) || insn == OP6 (BR2) || insn == OP6 (BR3)))
5892 return true;
5893 else if (opcode->isize == 2)
5895 for (i = 0; i < ARRAY_SIZE (check_insn); i++)
5896 if (strcmp (opcode->opcode, check_insn[i]) == 0)
5897 return true;
5899 break;
5900 case OP6 (MOVI):
5901 /* This is for LONGJUMP7. */
5902 if (opcode->isize == 2 && strcmp (opcode->opcode, "movi55") == 0)
5903 return true;
5904 break;
5905 case OP6 (MEM):
5906 if (OP6 (MEM) == GET_OPCODE (insn))
5907 return true;
5908 break;
5909 case OP6 (JREG):
5910 /* bit 24: N32_JI_JAL */ /* feed me! */
5911 if ((insn & ~(N32_BIT (24))) == JREG (JRAL))
5912 return true;
5913 break;
5914 default:
5915 if (opcode->isize == 2)
5917 for (i = 0; i < ARRAY_SIZE (check_insn); i++)
5918 if (strcmp (opcode->opcode, check_insn[i]) == 0)
5919 return true;
5921 if ((strcmp (opcode->opcode, "add5.pc") == 0) ||
5922 (strcmp (opcode->opcode, "add45") == 0))
5923 return true;
5926 return false;
5929 /* Append relax relocation for link time relaxing. */
5931 static void
5932 nds32_elf_append_relax_relocs (const char *key, const void *value)
5934 struct nds32_relocs_pattern *relocs_pattern =
5935 (struct nds32_relocs_pattern *) value;
5936 struct nds32_relocs_pattern *pattern_temp, *pattern_now;
5937 symbolS *sym, *hi_sym = NULL;
5938 expressionS exp;
5939 fragS *fragP;
5940 segT seg_bak = now_seg;
5941 frchainS *frchain_bak = frchain_now;
5942 struct nds32_relax_hint_table hint_info;
5943 nds32_relax_fixup_info_t *hint_fixup, *fixup_now;
5944 size_t fixup_size;
5945 offsetT branch_offset, hi_branch_offset = 0;
5946 fixS *fixP;
5947 int range, offset;
5948 unsigned int ptr_offset, hint_count, relax_code_size, count = 0;
5949 uint32_t *code_seq, code_insn;
5950 char *where;
5951 int pcrel;
5953 if (!relocs_pattern)
5954 return;
5956 if (!nds32_find_reloc_table (relocs_pattern, &hint_info))
5957 return;
5959 /* Save symbol for some EMPTY relocation using. */
5960 pattern_now = relocs_pattern;
5961 while (pattern_now)
5963 if (pattern_now->opcode->value == OP6 (SETHI))
5965 hi_sym = pattern_now->sym;
5966 hi_branch_offset = pattern_now->fixP->fx_offset;
5967 break;
5969 pattern_now = pattern_now->next;
5972 /* Inserting fix up must specify now_seg or frchain_now. */
5973 now_seg = relocs_pattern->seg;
5974 frchain_now = relocs_pattern->frchain;
5975 fragP = relocs_pattern->frag;
5976 branch_offset = fragP->fr_offset;
5978 hint_fixup = hint_info.relax_fixup;
5979 code_seq = hint_info.relax_code_seq;
5980 relax_code_size = hint_info.relax_code_size;
5981 pattern_now = relocs_pattern;
5983 #ifdef NDS32_LINUX_TOOLCHAIN
5984 /* prepare group relocation ID (number). */
5985 long group_id = 0;
5986 if (key)
5988 /* convert .relax_hint key to number */
5989 errno = 0;
5990 group_id = strtol (key, NULL, 10);
5991 if ((errno == ERANGE && (group_id == LONG_MAX || group_id == LONG_MIN))
5992 || (errno != 0 && group_id == 0))
5994 as_bad (_("Internal error: .relax_hint KEY is not a number!"));
5995 goto restore;
5998 #endif
6000 /* Insert relaxation. */
6001 exp.X_op = O_symbol;
6003 /* For each instruction in the hint group. */
6004 while (pattern_now)
6006 if (count >= relax_code_size / 4)
6007 count = 0;
6009 /* Choose the match fixup by instruction. */
6010 code_insn = CLEAN_REG (*(code_seq + count));
6011 if (!nds32_match_hint_insn (pattern_now->opcode, code_insn))
6013 /* Try search from head again */
6014 count = 0;
6015 code_insn = CLEAN_REG (*(code_seq + count));
6017 while (!nds32_match_hint_insn (pattern_now->opcode, code_insn))
6019 count++;
6020 if (count >= relax_code_size / 4)
6022 as_bad (_("Internal error: Relax hint (%s) error. %s: %s (%x)"),
6023 key,
6024 now_seg->name,
6025 pattern_now->opcode->opcode,
6026 pattern_now->opcode->value);
6027 goto restore;
6029 code_insn = CLEAN_REG (*(code_seq + count));
6032 fragP = pattern_now->frag;
6033 sym = pattern_now->sym;
6034 branch_offset = fragP->fr_offset;
6035 offset = count * 4;
6036 where = pattern_now->where;
6037 /* Find the instruction map fix. */
6038 fixup_now = hint_fixup;
6039 while (fixup_now->offset != offset)
6041 fixup_now++;
6042 if (fixup_now->size == 0)
6043 break;
6045 /* This element is without relaxation relocation. */
6046 if (fixup_now->size == 0)
6048 pattern_now = pattern_now->next;
6049 continue;
6051 fixup_size = fixup_now->size;
6053 /* Insert all fixup. */
6054 pcrel = 0;
6055 while (fixup_size != 0 && fixup_now->offset == offset)
6057 /* Set the real instruction size in element. */
6058 fixup_size = pattern_now->opcode->isize;
6059 pcrel = ((fixup_now->ramp & NDS32_PCREL) != 0) ? 1 : 0;
6060 if (fixup_now->ramp & NDS32_FIX)
6062 /* Convert original relocation. */
6063 pattern_now->fixP->fx_r_type = fixup_now->r_type ;
6064 fixup_size = 0;
6066 else if ((fixup_now->ramp & NDS32_PTR) != 0)
6068 /* This relocation has to point to another instruction. Make
6069 sure each resolved relocation has to be pointed. */
6070 pattern_temp = relocs_pattern;
6071 /* All instruction in relax_table should be 32-bit. */
6072 hint_count = hint_info.relax_code_size / 4;
6073 code_insn = CLEAN_REG (*(code_seq + hint_count - 1));
6074 while (pattern_temp)
6076 /* Point to every resolved relocation. */
6077 if (nds32_match_hint_insn (pattern_temp->opcode, code_insn))
6079 ptr_offset =
6080 pattern_temp->where - pattern_temp->frag->fr_literal;
6081 exp.X_add_symbol = symbol_temp_new (now_seg,
6082 pattern_temp->frag,
6083 ptr_offset);
6084 exp.X_add_number = 0;
6085 fixP =
6086 fix_new_exp (fragP, where - fragP->fr_literal,
6087 fixup_size, &exp, 0, fixup_now->r_type);
6088 fixP->fx_addnumber = fixP->fx_offset;
6090 pattern_temp = pattern_temp->next;
6092 fixup_size = 0;
6094 else if (fixup_now->ramp & NDS32_ADDEND)
6096 range = nds32_elf_sethi_range (relocs_pattern);
6097 if (range == NDS32_LOADSTORE_NONE)
6099 as_bad (_("Internal error: Range error. %s"), now_seg->name);
6100 return;
6102 exp.X_add_symbol = abs_section_sym;
6103 exp.X_add_number = SET_ADDEND (4, 0, optimize, enable_16bit);
6104 exp.X_add_number |= ((range & 0x3f) << 8);
6106 else if ((fixup_now->ramp & NDS32_ABS) != 0)
6108 /* This is a tag relocation. */
6109 exp.X_add_symbol = abs_section_sym;
6110 exp.X_add_number = 0;
6112 else if ((fixup_now->ramp & NDS32_INSN16) != 0)
6114 if (!enable_16bit)
6115 fixup_size = 0;
6116 /* This is a tag relocation. */
6117 exp.X_add_symbol = abs_section_sym;
6118 exp.X_add_number = 0;
6120 else if ((fixup_now->ramp & NDS32_SYM) != 0)
6122 /* For EMPTY relocation save the true symbol. */
6123 exp.X_add_symbol = hi_sym;
6124 exp.X_add_number = hi_branch_offset;
6126 else if (NDS32_SYM_DESC_MEM & fixup_now->ramp)
6128 /* Do the same as NDS32_SYM. */
6129 exp.X_add_symbol = hi_sym;
6130 exp.X_add_number = hi_branch_offset;
6132 /* Extra to NDS32_SYM. */
6133 /* Detect if DESC_FUNC relax type do apply. */
6134 if ((REG_GP == N32_RA5 (pattern_now->insn))
6135 || (REG_GP == N32_RB5 (pattern_now->insn)))
6137 fixP = fix_new_exp (fragP, where - fragP->fr_literal,
6138 fixup_size, &exp, pcrel,
6139 BFD_RELOC_NDS32_TLS_DESC_FUNC);
6140 fixP->fx_addnumber = fixP->fx_offset;
6142 fixup_size = 0;
6144 /* Else do as usual. */
6146 else if (fixup_now->ramp & NDS32_PTR_PATTERN)
6148 /* Find out PTR_RESOLVED code pattern. */
6149 nds32_relax_fixup_info_t *next_fixup = fixup_now + 1;
6150 uint32_t resolved_pattern = 0;
6151 while (next_fixup->offset)
6153 if (next_fixup->r_type == BFD_RELOC_NDS32_PTR_RESOLVED)
6155 uint32_t new_pattern = code_seq[next_fixup->offset >> 2];
6156 if (!resolved_pattern)
6157 resolved_pattern = new_pattern;
6158 else if (new_pattern != resolved_pattern)
6160 as_warn (_("Multiple BFD_RELOC_NDS32_PTR_RESOLVED "
6161 "patterns are not supported yet!"));
6162 break;
6165 ++next_fixup;
6168 /* Find matched code and insert fix-ups. */
6169 struct nds32_relocs_pattern *next_pattern = pattern_now->next;
6170 /* This relocation has to point to another instruction.
6171 Make sure each resolved relocation has to be pointed. */
6172 /* All instruction in relax_table should be 32-bit. */
6173 while (next_pattern)
6175 uint32_t cur_pattern = GET_OPCODE (next_pattern->opcode->value);
6176 if (cur_pattern == resolved_pattern)
6178 ptr_offset = next_pattern->where
6179 - next_pattern->frag->fr_literal;
6180 exp.X_add_symbol = symbol_temp_new (now_seg,
6181 next_pattern->frag,
6182 ptr_offset);
6183 exp.X_add_number = 0;
6184 fixP = fix_new_exp (fragP, where - fragP->fr_literal,
6185 fixup_size, &exp, 0,
6186 fixup_now->r_type);
6187 fixP->fx_addnumber = fixP->fx_offset;
6189 next_pattern = next_pattern->next;
6192 fixup_size = 0;
6194 else if (fixup_now->ramp & NDS32_PTR_MULTIPLE)
6196 /* Find each PTR_RESOLVED pattern after PTR. */
6197 nds32_relax_fixup_info_t *next_fixup = fixup_now + 1;
6198 while (next_fixup->offset)
6200 if (next_fixup->r_type == BFD_RELOC_NDS32_PTR_RESOLVED)
6202 uint32_t pattern = code_seq[next_fixup->offset >> 2];
6203 /* Find matched code to insert fix-ups. */
6204 struct nds32_relocs_pattern *next_insn = pattern_now->next;
6205 while (next_insn)
6207 uint32_t insn_pattern = GET_OPCODE (next_insn->opcode->value);
6208 if (insn_pattern == pattern)
6210 ptr_offset = next_insn->where
6211 - next_insn->frag->fr_literal;
6212 exp.X_add_symbol = symbol_temp_new (now_seg,
6213 next_insn->frag,
6214 ptr_offset);
6215 exp.X_add_number = 0;
6216 fixP = fix_new_exp (fragP,
6217 where - fragP->fr_literal,
6218 fixup_size, &exp, 0,
6219 fixup_now->r_type);
6220 fixP->fx_addnumber = fixP->fx_offset;
6222 next_insn = next_insn->next;
6225 ++next_fixup;
6227 fixup_size = 0;
6229 else
6231 exp.X_add_symbol = sym;
6232 exp.X_add_number = branch_offset;
6235 if (fixup_size != 0)
6237 fixP = fix_new_exp (fragP, where - fragP->fr_literal, fixup_size,
6238 &exp, pcrel, fixup_now->r_type);
6239 fixP->fx_addnumber = fixP->fx_offset;
6241 fixup_now++;
6242 fixup_size = fixup_now->size;
6245 #ifdef NDS32_LINUX_TOOLCHAIN
6246 /* Insert group relocation for each relax hint. */
6247 if (key)
6249 exp.X_add_symbol = hi_sym; /* for eyes only */
6250 exp.X_add_number = group_id;
6251 fixP = fix_new_exp (fragP, where - fragP->fr_literal, fixup_size,
6252 &exp, pcrel, BFD_RELOC_NDS32_GROUP);
6253 fixP->fx_addnumber = fixP->fx_offset;
6255 #endif
6257 if (count < relax_code_size / 4)
6258 count++;
6259 pattern_now = pattern_now->next;
6262 restore:
6263 now_seg = seg_bak;
6264 frchain_now = frchain_bak;
6267 static int
6268 nds32_elf_append_relax_relocs_traverse (void **slot, void *arg ATTRIBUTE_UNUSED)
6270 string_tuple_t *tuple = *((string_tuple_t **) slot);
6271 nds32_elf_append_relax_relocs (tuple->key, tuple->value);
6272 return 1;
6276 static void
6277 nds32_str_tolower (const char *src, char *dest)
6279 unsigned int i, len;
6281 len = strlen (src);
6283 for (i = 0; i < len; i++)
6284 *(dest + i) = TOLOWER (*(src + i));
6286 *(dest + i) = '\0';
6289 /* Check instruction if it can be used for the baseline. */
6291 static bool
6292 nds32_check_insn_available (struct nds32_asm_insn insn, const char *str)
6294 int attr = insn.attr & ATTR_ALL;
6295 static int baseline_isa = 0;
6296 char *s;
6298 s = xmalloc (strlen (str) + 1);
6299 nds32_str_tolower (str, s);
6300 if (verbatim
6301 && (((insn.opcode->value == ALU2 (MTUSR)
6302 || insn.opcode->value == ALU2 (MFUSR))
6303 && (strstr (s, "lc")
6304 || strstr (s, "le")
6305 || strstr (s, "lb")))
6306 || (insn.attr & NASM_ATTR_ZOL)))
6308 as_bad (_("Not support instruction %s in verbatim."), str);
6309 return false;
6311 free (s);
6313 if (!enable_16bit && insn.opcode->isize == 2)
6315 as_bad (_("16-bit instruction is disabled: %s."), str);
6316 return false;
6319 /* No isa setting or all isa can use. */
6320 if (attr == 0 || attr == ATTR_ALL)
6321 return true;
6323 if (baseline_isa == 0)
6325 /* Map option baseline and instruction attribute. */
6326 switch (nds32_baseline)
6328 case ISA_V2:
6329 baseline_isa = ATTR (ISA_V2);
6330 break;
6331 case ISA_V3:
6332 baseline_isa = ATTR (ISA_V3);
6333 break;
6334 case ISA_V3M:
6335 baseline_isa = ATTR (ISA_V3M);
6336 break;
6340 if ((baseline_isa & attr) == 0)
6342 as_bad (_("Instruction %s not supported in the baseline."), str);
6343 return false;
6345 return true;
6348 /* Stub of machine dependent. */
6350 void
6351 md_assemble (char *str)
6353 struct nds32_asm_insn insn;
6354 char *out;
6355 struct nds32_pseudo_opcode *popcode;
6356 const struct nds32_field *fld = NULL;
6357 fixS *fixP;
6358 uint16_t insn_16;
6359 struct nds32_relocs_pattern *relocs_temp;
6360 struct nds32_relocs_group *group_temp;
6361 fragS *fragP;
6362 int label = label_exist;
6363 static bool pseudo_hint = false;
6365 popcode = nds32_lookup_pseudo_opcode (str);
6366 /* Note that we need to check 'verbatim' and
6367 'opcode->physical_op'. If the assembly content is generated by
6368 compiler and this opcode is a physical instruction, there is no
6369 need to perform pseudo instruction expansion/transformation. */
6370 if (popcode && !(verbatim && popcode->physical_op))
6372 /* Pseudo instruction is with relax_hint. */
6373 if (relaxing)
6374 pseudo_hint = true;
6375 pseudo_opcode = true;
6376 nds32_pseudo_opcode_wrapper (str, popcode);
6377 pseudo_opcode = false;
6378 pseudo_hint = false;
6379 nds32_elf_append_relax_relocs (NULL, relocs_list);
6381 /* Free relax_hint group list. */
6382 while (nds32_relax_hint_current)
6384 group_temp = nds32_relax_hint_current->next;
6385 free (nds32_relax_hint_current);
6386 nds32_relax_hint_current = group_temp;
6389 /* Free pseudo list. */
6390 relocs_temp = relocs_list;
6391 while (relocs_temp)
6393 relocs_list = relocs_list->next;
6394 free (relocs_temp);
6395 relocs_temp = relocs_list;
6398 return;
6401 label_exist = 0;
6402 insn.info = XNEW (expressionS);
6403 asm_desc.result = NASM_OK;
6404 nds32_assemble (&asm_desc, &insn, str);
6406 switch (asm_desc.result)
6408 case NASM_ERR_UNKNOWN_OP:
6409 as_bad (_("Unrecognized opcode, %s."), str);
6410 return;
6411 case NASM_ERR_SYNTAX:
6412 as_bad (_("Incorrect syntax, %s."), str);
6413 return;
6414 case NASM_ERR_OPERAND:
6415 as_bad (_("Unrecognized operand/register, %s."), str);
6416 return;
6417 case NASM_ERR_OUT_OF_RANGE:
6418 as_bad (_("Operand out of range, %s."), str);
6419 return;
6420 case NASM_ERR_REG_REDUCED:
6421 as_bad (_("Prohibited register used for reduced-register, %s."), str);
6422 return;
6423 case NASM_ERR_JUNK_EOL:
6424 as_bad (_("Junk at end of line, %s."), str);
6425 return;
6428 gas_assert (insn.opcode);
6430 nds32_set_elf_flags_by_insn (&insn);
6432 gas_assert (insn.opcode->isize == 4 || insn.opcode->isize == 2);
6434 if (!nds32_check_insn_available (insn, str))
6435 return;
6437 /* Make sure the beginning of text being 2-byte align. */
6438 nds32_adjust_label (1);
6439 add_mapping_symbol (MAP_CODE, 0, 0);
6440 fld = insn.field;
6441 /* Try to allocate the max size to guarantee relaxable same branch
6442 instructions in the same fragment. */
6443 frag_grow (NDS32_MAXCHAR);
6444 fragP = frag_now;
6446 if (fld && (insn.attr & NASM_ATTR_BRANCH)
6447 && (pseudo_opcode || (insn.opcode->value != INSN_JAL
6448 && insn.opcode->value != INSN_J))
6449 && (!verbatim || pseudo_opcode))
6451 /* User assembly code branch relax for it. */
6452 /* If fld is not NULL, it is a symbol. */
6453 /* Branch must relax to proper pattern in user assembly code exclude
6454 J and JAL. Keep these two in original type for users which wants
6455 to keep their size be fixed. In general, assembler does not convert
6456 instruction generated by compiler. But jump instruction may be
6457 truncated in text virtual model. For workaround, compiler generate
6458 pseudo jump to fix this issue currently. */
6460 /* Get branch range type. */
6461 dwarf2_emit_insn (0);
6462 enum nds32_br_range range_type;
6463 expressionS *pexp = insn.info;
6465 range_type = get_range_type (fld);
6467 out = frag_var (rs_machine_dependent, NDS32_MAXCHAR,
6468 0, /* VAR is un-used. */
6469 range_type, /* SUBTYPE is used as range type. */
6470 pexp->X_add_symbol, pexp->X_add_number, 0);
6472 fragP->fr_fix += insn.opcode->isize;
6473 fragP->tc_frag_data.opcode = insn.opcode;
6474 fragP->tc_frag_data.insn = insn.insn;
6475 if (insn.opcode->isize == 4)
6476 bfd_putb32 (insn.insn, out);
6477 else if (insn.opcode->isize == 2)
6478 bfd_putb16 (insn.insn, out);
6479 fragP->tc_frag_data.flag |= NDS32_FRAG_BRANCH;
6481 free (insn.info);
6482 return;
6483 /* md_convert_frag will insert relocations. */
6485 else if (!relaxing && enable_16bit && (optimize || optimize_for_space)
6486 && ((!fld && !verbatim && insn.opcode->isize == 4
6487 && nds32_convert_32_to_16 (stdoutput, insn.insn, &insn_16, NULL))
6488 || (insn.opcode->isize == 2
6489 && nds32_convert_16_to_32 (stdoutput, insn.insn, NULL))))
6491 /* Record this one is relaxable. */
6492 expressionS *pexp = insn.info;
6493 dwarf2_emit_insn (0);
6494 if (fld)
6496 out = frag_var (rs_machine_dependent,
6497 4, /* Max size is 32-bit instruction. */
6498 0, /* VAR is un-used. */
6499 0, pexp->X_add_symbol, pexp->X_add_number, 0);
6500 fragP->tc_frag_data.flag |= NDS32_FRAG_RELAXABLE_BRANCH;
6502 else
6503 out = frag_var (rs_machine_dependent,
6504 4, /* Max size is 32-bit instruction. */
6505 0, /* VAR is un-used. */
6506 0, NULL, 0, NULL);
6507 fragP->tc_frag_data.flag |= NDS32_FRAG_RELAXABLE;
6508 fragP->tc_frag_data.opcode = insn.opcode;
6509 fragP->tc_frag_data.insn = insn.insn;
6510 fragP->fr_fix += 2;
6512 /* In original, we don't relax the instruction with label on it,
6513 but this may cause some redundant nop16. Therefore, tag this
6514 relaxable instruction and relax it carefully. */
6515 if (label)
6516 fragP->tc_frag_data.flag |= NDS32_FRAG_LABEL;
6518 if (insn.opcode->isize == 4)
6519 bfd_putb16 (insn_16, out);
6520 else if (insn.opcode->isize == 2)
6521 bfd_putb16 (insn.insn, out);
6523 free (insn.info);
6524 return;
6526 else if ((verbatim || !relaxing) && optimize && label)
6528 /* This instruction is with label. */
6529 expressionS exp;
6530 out = frag_var (rs_machine_dependent, insn.opcode->isize,
6531 0, 0, NULL, 0, NULL);
6532 /* If this instruction is branch target, it is not relaxable. */
6533 fragP->tc_frag_data.flag = NDS32_FRAG_LABEL;
6534 fragP->tc_frag_data.opcode = insn.opcode;
6535 fragP->tc_frag_data.insn = insn.insn;
6536 fragP->fr_fix += insn.opcode->isize;
6537 if (insn.opcode->isize == 4)
6539 exp.X_op = O_symbol;
6540 exp.X_add_symbol = abs_section_sym;
6541 exp.X_add_number = 0;
6542 fixP = fix_new_exp (fragP, fragP->fr_fix - 4, 0, &exp,
6543 0, BFD_RELOC_NDS32_LABEL);
6544 if (!verbatim)
6545 fragP->tc_frag_data.flag = NDS32_FRAG_ALIGN;
6548 else
6549 out = frag_more (insn.opcode->isize);
6551 if (insn.opcode->isize == 4)
6552 bfd_putb32 (insn.insn, out);
6553 else if (insn.opcode->isize == 2)
6554 bfd_putb16 (insn.insn, out);
6556 dwarf2_emit_insn (insn.opcode->isize);
6558 /* Compiler generating code and user assembly pseudo load-store, insert
6559 fixup here. */
6560 expressionS *pexp = insn.info;
6561 fixP = nds32_elf_record_fixup_exp (fragP, str, fld, pexp, out, &insn);
6562 /* Build relaxation pattern when relaxing is enable. */
6563 if (relaxing)
6564 nds32_elf_build_relax_relation (fixP, pexp, out, &insn, fragP, fld,
6565 pseudo_hint);
6567 free (insn.info);
6570 /* md_macro_start */
6572 void
6573 nds32_macro_start (void)
6577 /* md_macro_info */
6579 void
6580 nds32_macro_info (void *info ATTRIBUTE_UNUSED)
6584 /* md_macro_end */
6586 void
6587 nds32_macro_end (void)
6591 /* GAS will call this function with one argument, an expressionS pointer, for
6592 any expression that can not be recognized. When the function is called,
6593 input_line_pointer will point to the start of the expression. */
6595 void
6596 md_operand (expressionS *expressionP)
6598 if (*input_line_pointer == '#')
6600 input_line_pointer++;
6601 expression (expressionP);
6605 /* GAS will call this function for each section at the end of the assembly, to
6606 permit the CPU back end to adjust the alignment of a section. The function
6607 must take two arguments, a segT for the section and a valueT for the size of
6608 the section, and return a valueT for the rounded size. */
6610 valueT
6611 md_section_align (segT segment, valueT size)
6613 int align = bfd_section_alignment (segment);
6615 return ((size + (1 << align) - 1) & ((valueT) -1 << align));
6618 /* GAS will call this function when a symbol table lookup fails, before it
6619 creates a new symbol. Typically this would be used to supply symbols whose
6620 name or value changes dynamically, possibly in a context sensitive way.
6621 Predefined symbols with fixed values, such as register names or condition
6622 codes, are typically entered directly into the symbol table when md_begin
6623 is called. One argument is passed, a char * for the symbol. */
6625 symbolS *
6626 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
6628 return NULL;
6631 static long
6632 nds32_calc_branch_offset (segT segment, fragS *fragP,
6633 long stretch ATTRIBUTE_UNUSED,
6634 relax_info_t *relax_info,
6635 enum nds32_br_range branch_range_type)
6637 struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
6638 symbolS *branch_symbol = fragP->fr_symbol;
6639 offsetT branch_offset = fragP->fr_offset;
6640 offsetT branch_target_address;
6641 offsetT branch_insn_address;
6642 long offset = 0;
6644 if ((S_GET_SEGMENT (branch_symbol) != segment)
6645 || S_IS_WEAK (branch_symbol))
6647 /* The symbol is not in the SEGMENT. It could be far far away. */
6648 offset = 0x80000000;
6650 else
6652 /* Calculate symbol-to-instruction offset. */
6653 branch_target_address = S_GET_VALUE (branch_symbol) + branch_offset;
6654 /* If the destination symbol is beyond current frag address,
6655 STRETCH will take effect to symbol's position. */
6656 if (S_GET_VALUE (branch_symbol) > fragP->fr_address)
6657 branch_target_address += stretch;
6659 branch_insn_address = fragP->fr_address + fragP->fr_fix;
6660 branch_insn_address -= opcode->isize;
6662 /* Update BRANCH_INSN_ADDRESS to relaxed position. */
6663 branch_insn_address += (relax_info->relax_code_size[branch_range_type]
6664 - relax_info->relax_branch_isize[branch_range_type]);
6666 offset = branch_target_address - branch_insn_address;
6669 return offset;
6672 static enum nds32_br_range
6673 nds32_convert_to_range_type (long offset)
6675 enum nds32_br_range range_type;
6677 if (-(0x100) <= offset && offset < 0x100) /* 256 bytes */
6678 range_type = BR_RANGE_S256;
6679 else if (-(0x4000) <= offset && offset < 0x4000) /* 16K bytes */
6680 range_type = BR_RANGE_S16K;
6681 else if (-(0x10000) <= offset && offset < 0x10000) /* 64K bytes */
6682 range_type = BR_RANGE_S64K;
6683 else if (-(0x1000000) <= offset && offset < 0x1000000) /* 16M bytes */
6684 range_type = BR_RANGE_S16M;
6685 else /* 4G bytes */
6686 range_type = BR_RANGE_U4G;
6688 return range_type;
6691 /* Set instruction register mask. */
6693 static void
6694 nds32_elf_get_set_cond (relax_info_t *relax_info, int offset, uint32_t *insn,
6695 uint32_t ori_insn, int range)
6697 nds32_cond_field_t *cond_fields = relax_info->cond_field;
6698 nds32_cond_field_t *code_seq_cond = relax_info->relax_code_condition[range];
6699 uint32_t mask;
6700 int i = 0;
6702 /* The instruction has conditions. Collect condition values. */
6703 while (code_seq_cond[i].bitmask != 0)
6705 if (offset == code_seq_cond[i].offset)
6707 mask = (ori_insn >> cond_fields[i].bitpos) & cond_fields[i].bitmask;
6708 /* Sign extend. */
6709 if (cond_fields[i].signed_extend)
6710 mask = (mask ^ ((cond_fields[i].bitmask + 1) >> 1)) -
6711 ((cond_fields[i].bitmask + 1) >> 1);
6712 *insn |= (mask & code_seq_cond[i].bitmask) << code_seq_cond[i].bitpos;
6714 i++;
6718 static int
6719 nds32_relax_branch_instructions (segT segment, fragS *fragP,
6720 long stretch ATTRIBUTE_UNUSED,
6721 int init)
6723 enum nds32_br_range branch_range_type;
6724 struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
6725 long offset = 0;
6726 enum nds32_br_range real_range_type;
6727 int adjust = 0;
6728 relax_info_t *relax_info;
6729 int diff = 0;
6730 int i, j, k;
6731 int code_seq_size;
6732 uint32_t *code_seq;
6733 uint32_t insn;
6734 int insn_size;
6735 int code_seq_offset;
6737 /* Replace with gas_assert (fragP->fr_symbol != NULL); */
6738 if (fragP->fr_symbol == NULL)
6739 return adjust;
6741 /* If frag_var is not enough room, the previous frag is fr_full and with
6742 opcode. The new one is rs_dependent but without opcode. */
6743 if (opcode == NULL)
6744 return adjust;
6746 /* Use U4G mode for b and bal in verbatim mode because lto may combine
6747 functions into a file. And order the file in the last when linking.
6748 Once there is multiple definition, the same function will be kicked.
6749 This may cause relocation truncated error. */
6750 if (verbatim && !nds32_pic
6751 && (strcmp (opcode->opcode, "j") == 0
6752 || strcmp (opcode->opcode, "jal") == 0))
6754 fragP->fr_subtype = BR_RANGE_U4G;
6755 if (init)
6756 return 8;
6757 else
6758 return 0;
6761 relax_info = str_hash_find (nds32_relax_info_hash, opcode->opcode);
6763 if (relax_info == NULL)
6764 return adjust;
6766 if (init)
6768 branch_range_type = relax_info->br_range;
6769 i = BR_RANGE_S256;
6771 else
6773 branch_range_type = fragP->fr_subtype;
6774 i = branch_range_type;
6777 offset = nds32_calc_branch_offset (segment, fragP, stretch,
6778 relax_info, branch_range_type);
6780 real_range_type = nds32_convert_to_range_type (offset);
6782 /* If actual range is equal to instruction jump range, do nothing. */
6783 if (real_range_type == branch_range_type)
6785 fragP->fr_subtype = real_range_type;
6786 return adjust;
6789 /* Find out proper relaxation code sequence. */
6790 for (; i < BR_RANGE_NUM; i++)
6792 if (real_range_type <= (unsigned int) i)
6794 if (init)
6795 diff = relax_info->relax_code_size[i] - opcode->isize;
6796 else if (real_range_type < (unsigned int) i)
6797 diff = relax_info->relax_code_size[real_range_type]
6798 - relax_info->relax_code_size[branch_range_type];
6799 else
6800 diff = relax_info->relax_code_size[i]
6801 - relax_info->relax_code_size[branch_range_type];
6803 /* If the instruction could be converted to 16-bits,
6804 minus the difference. */
6805 code_seq_offset = 0;
6806 j = 0;
6807 k = 0;
6808 code_seq_size = relax_info->relax_code_size[i];
6809 code_seq = relax_info->relax_code_seq[i];
6810 while (code_seq_offset < code_seq_size)
6812 insn = code_seq[j];
6813 if (insn & 0x80000000) /* 16-bits instruction. */
6815 insn_size = 2;
6817 else /* 32-bits instruction. */
6819 insn_size = 4;
6821 while (relax_info->relax_fixup[i][k].size !=0
6822 && relax_info->relax_fixup[i][k].offset < code_seq_offset)
6823 k++;
6826 code_seq_offset += insn_size;
6827 j++;
6830 /* Update fr_subtype to new NDS32_BR_RANGE. */
6831 fragP->fr_subtype = real_range_type;
6832 break;
6836 return diff + adjust;
6839 /* Adjust relaxable frag till current frag. */
6841 static int
6842 nds32_adjust_relaxable_frag (fragS *startP, fragS *fragP)
6844 int adj;
6845 if (startP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
6846 adj = -2;
6847 else
6848 adj = 2;
6850 startP->tc_frag_data.flag ^= NDS32_FRAG_RELAXED;
6852 while (startP)
6854 startP = startP->fr_next;
6855 if (startP)
6857 startP->fr_address += adj;
6858 if (startP == fragP)
6859 break;
6862 return adj;
6865 static addressT
6866 nds32_get_align (addressT address, int align)
6868 addressT mask, new_address;
6870 mask = ~((addressT) (~0) << align);
6871 new_address = (address + mask) & (~mask);
6872 return (new_address - address);
6875 /* Check the prev_frag is legal. */
6876 static void
6877 invalid_prev_frag (fragS * fragP, fragS **prev_frag, bool relax)
6879 addressT address;
6880 fragS *frag_start = *prev_frag;
6882 if (!frag_start || !relax)
6883 return;
6885 if (frag_start->last_fr_address >= fragP->last_fr_address)
6887 *prev_frag = NULL;
6888 return;
6891 fragS *frag_t = *prev_frag;
6892 while (frag_t != fragP)
6894 if (frag_t->fr_type == rs_align
6895 || frag_t->fr_type == rs_align_code
6896 || frag_t->fr_type == rs_align_test)
6898 /* Relax instruction can not walk across label. */
6899 if (frag_t->tc_frag_data.flag & NDS32_FRAG_LABEL)
6901 prev_frag = NULL;
6902 return;
6904 /* Relax previous relaxable to align rs_align frag. */
6905 address = frag_t->fr_address + frag_t->fr_fix;
6906 addressT offset = nds32_get_align (address, (int) frag_t->fr_offset);
6907 if (offset & 0x2)
6909 /* If there is label on the prev_frag, check if it is aligned. */
6910 if (!((*prev_frag)->tc_frag_data.flag & NDS32_FRAG_LABEL)
6911 || (((*prev_frag)->fr_address + (*prev_frag)->fr_fix - 2 )
6912 & 0x2) == 0)
6913 nds32_adjust_relaxable_frag (*prev_frag, frag_t);
6915 *prev_frag = NULL;
6916 return;
6918 frag_t = frag_t->fr_next;
6921 if (fragP->tc_frag_data.flag & NDS32_FRAG_ALIGN)
6923 address = fragP->fr_address;
6924 addressT offset = nds32_get_align (address, 2);
6925 if (offset & 0x2)
6927 /* If there is label on the prev_frag, check if it is aligned. */
6928 if (!((*prev_frag)->tc_frag_data.flag & NDS32_FRAG_LABEL)
6929 || (((*prev_frag)->fr_address + (*prev_frag)->fr_fix - 2 )
6930 & 0x2) == 0)
6931 nds32_adjust_relaxable_frag (*prev_frag, fragP);
6933 *prev_frag = NULL;
6934 return;
6938 /* md_relax_frag */
6941 nds32_relax_frag (segT segment, fragS *fragP, long stretch ATTRIBUTE_UNUSED)
6943 /* Currently, there are two kinds of relaxation in nds32 assembler.
6944 1. relax for branch
6945 2. relax for 32-bits to 16-bits */
6947 static fragS *prev_frag = NULL;
6948 int adjust = 0;
6950 invalid_prev_frag (fragP, &prev_frag, true);
6952 if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
6953 adjust = nds32_relax_branch_instructions (segment, fragP, stretch, 0);
6954 if (fragP->tc_frag_data.flag & NDS32_FRAG_LABEL)
6955 prev_frag = NULL;
6956 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE
6957 && (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED) == 0)
6958 /* Here is considered relaxed case originally. But it may cause
6959 an endless loop when relaxing. Once the instruction is relaxed,
6960 it can not be undone. */
6961 prev_frag = fragP;
6963 return adjust;
6966 /* This function returns an initial guess of the length by which a fragment
6967 must grow to hold a branch to reach its destination. Also updates
6968 fr_type/fr_subtype as necessary.
6970 It is called just before doing relaxation. Any symbol that is now undefined
6971 will not become defined. The guess for fr_var is ACTUALLY the growth beyond
6972 fr_fix. Whatever we do to grow fr_fix or fr_var contributes to our returned
6973 value. Although it may not be explicit in the frag, pretend fr_var starts
6974 with a 0 value. */
6977 md_estimate_size_before_relax (fragS *fragP, segT segment)
6979 /* Currently, there are two kinds of relaxation in nds32 assembler.
6980 1. relax for branch
6981 2. relax for 32-bits to 16-bits */
6983 /* Save previous relaxable frag. */
6984 static fragS *prev_frag = NULL;
6985 int adjust = 0;
6987 invalid_prev_frag (fragP, &prev_frag, false);
6989 if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
6990 adjust = nds32_relax_branch_instructions (segment, fragP, 0, 1);
6991 if (fragP->tc_frag_data.flag & NDS32_FRAG_LABEL)
6992 prev_frag = NULL;
6993 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
6994 adjust = 2;
6995 else if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE)
6996 prev_frag = fragP;
6998 return adjust;
7001 /* GAS will call this for each rs_machine_dependent fragment. The instruction
7002 is completed using the data from the relaxation pass. It may also create any
7003 necessary relocations.
7005 *FRAGP has been relaxed to its final size, and now needs to have the bytes
7006 inside it modified to conform to the new size. It is called after relaxation
7007 is finished.
7009 fragP->fr_type == rs_machine_dependent.
7010 fragP->fr_subtype is the subtype of what the address relaxed to. */
7012 void
7013 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP)
7015 /* Convert branch relaxation instructions. */
7016 symbolS *branch_symbol = fragP->fr_symbol;
7017 offsetT branch_offset = fragP->fr_offset;
7018 enum nds32_br_range branch_range_type = fragP->fr_subtype;
7019 struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
7020 uint32_t origin_insn = fragP->tc_frag_data.insn;
7021 relax_info_t *relax_info;
7022 char *fr_buffer;
7023 int fr_where;
7024 int addend ATTRIBUTE_UNUSED;
7025 offsetT branch_target_address, branch_insn_address;
7026 expressionS exp;
7027 fixS *fixP;
7028 uint32_t *code_seq;
7029 uint32_t insn;
7030 int code_size, insn_size, offset, fixup_size;
7031 int buf_offset, pcrel;
7032 int i, k;
7033 uint16_t insn_16;
7034 nds32_relax_fixup_info_t fixup_info[MAX_RELAX_FIX];
7035 /* Save the 1st instruction is converted to 16 bit or not. */
7036 unsigned int branch_size;
7037 enum bfd_reloc_code_real final_r_type;
7039 /* Replace with gas_assert (branch_symbol != NULL); */
7040 if (branch_symbol == NULL && !(fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED))
7041 return;
7043 /* If frag_var is not enough room, the previous frag is fr_full and with
7044 opcode. The new one is rs_dependent but without opcode. */
7045 if (opcode == NULL)
7046 return;
7048 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE_BRANCH)
7050 relax_info = str_hash_find (nds32_relax_info_hash, opcode->opcode);
7052 if (relax_info == NULL)
7053 return;
7055 i = BR_RANGE_S256;
7056 while (i < BR_RANGE_NUM
7057 && relax_info->relax_code_size[i]
7058 != (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED ? 4 : 2))
7059 i++;
7061 if (i >= BR_RANGE_NUM)
7062 as_bad ("Internal error: Cannot find relocation of"
7063 "relaxable branch.");
7065 exp.X_op = O_symbol;
7066 exp.X_add_symbol = branch_symbol;
7067 exp.X_add_number = branch_offset;
7068 pcrel = ((relax_info->relax_fixup[i][0].ramp & NDS32_PCREL) != 0) ? 1 : 0;
7069 fr_where = fragP->fr_fix - 2;
7070 fixP = fix_new_exp (fragP, fr_where, relax_info->relax_fixup[i][0].size,
7071 &exp, pcrel, relax_info->relax_fixup[i][0].r_type);
7072 fixP->fx_addnumber = fixP->fx_offset;
7074 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
7076 insn_16 = fragP->tc_frag_data.insn;
7077 nds32_convert_16_to_32 (stdoutput, insn_16, &insn);
7078 fr_buffer = fragP->fr_literal + fr_where;
7079 fragP->fr_fix += 2;
7080 exp.X_op = O_symbol;
7081 exp.X_add_symbol = abs_section_sym;
7082 exp.X_add_number = 0;
7083 fix_new_exp (fragP, fr_where, 4,
7084 &exp, 0, BFD_RELOC_NDS32_INSN16);
7085 number_to_chars_bigendian (fr_buffer, insn, 4);
7088 else if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
7090 if (fragP->tc_frag_data.opcode->isize == 2)
7092 insn_16 = fragP->tc_frag_data.insn;
7093 nds32_convert_16_to_32 (stdoutput, insn_16, &insn);
7095 else
7096 insn = fragP->tc_frag_data.insn;
7097 fragP->fr_fix += 2;
7098 fr_where = fragP->fr_fix - 4;
7099 fr_buffer = fragP->fr_literal + fr_where;
7100 exp.X_op = O_symbol;
7101 exp.X_add_symbol = abs_section_sym;
7102 exp.X_add_number = 0;
7103 fix_new_exp (fragP, fr_where, 4, &exp, 0,
7104 BFD_RELOC_NDS32_INSN16);
7105 number_to_chars_bigendian (fr_buffer, insn, 4);
7107 else if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
7109 /* Branch instruction adjust and append relocations. */
7110 relax_info = str_hash_find (nds32_relax_info_hash, opcode->opcode);
7112 if (relax_info == NULL)
7113 return;
7115 fr_where = fragP->fr_fix - opcode->isize;
7116 fr_buffer = fragP->fr_literal + fr_where;
7118 if ((S_GET_SEGMENT (branch_symbol) != sec)
7119 || S_IS_WEAK (branch_symbol))
7121 if (fragP->fr_offset & 3)
7122 as_warn (_("Addend to unresolved symbol is not on word boundary."));
7123 addend = 0;
7125 else
7127 /* Calculate symbol-to-instruction offset. */
7128 branch_target_address = S_GET_VALUE (branch_symbol) + branch_offset;
7129 branch_insn_address = fragP->fr_address + fr_where;
7130 addend = (branch_target_address - branch_insn_address) >> 1;
7133 code_size = relax_info->relax_code_size[branch_range_type];
7134 code_seq = relax_info->relax_code_seq[branch_range_type];
7136 memcpy (fixup_info, relax_info->relax_fixup[branch_range_type],
7137 sizeof (fixup_info));
7139 /* Fill in frag. */
7140 i = 0;
7141 k = 0;
7142 offset = 0; /* code_seq offset */
7143 buf_offset = 0; /* fr_buffer offset */
7144 while (offset < code_size)
7146 insn = code_seq[i];
7147 if (insn & 0x80000000) /* 16-bits instruction. */
7149 insn = (insn >> 16) & 0xFFFF;
7150 insn_size = 2;
7152 else /* 32-bits instruction. */
7154 insn_size = 4;
7157 nds32_elf_get_set_cond (relax_info, offset, &insn,
7158 origin_insn, branch_range_type);
7160 /* Try to convert to 16-bits instruction. Currently, only the first
7161 instruction in pattern can be converted. EX: bnez sethi ori jr,
7162 only bnez can be converted to 16 bit and ori can't. */
7164 while (fixup_info[k].size != 0
7165 && relax_info->relax_fixup[branch_range_type][k].offset < offset)
7166 k++;
7168 number_to_chars_bigendian (fr_buffer + buf_offset, insn, insn_size);
7169 buf_offset += insn_size;
7171 offset += insn_size;
7172 i++;
7175 /* Set up fixup. */
7176 exp.X_op = O_symbol;
7178 for (i = 0; fixup_info[i].size != 0; i++)
7180 fixup_size = fixup_info[i].size;
7181 pcrel = ((fixup_info[i].ramp & NDS32_PCREL) != 0) ? 1 : 0;
7183 if ((fixup_info[i].ramp & NDS32_CREATE_LABEL) != 0)
7185 /* This is a reverse branch. */
7186 exp.X_add_symbol = symbol_temp_new (sec, fragP->fr_next, 0);
7187 exp.X_add_number = 0;
7189 else if ((fixup_info[i].ramp & NDS32_PTR) != 0)
7191 /* This relocation has to point to another instruction. */
7192 branch_size = fr_where + code_size - 4;
7193 exp.X_add_symbol = symbol_temp_new (sec, fragP, branch_size);
7194 exp.X_add_number = 0;
7196 else if ((fixup_info[i].ramp & NDS32_ABS) != 0)
7198 /* This is a tag relocation. */
7199 exp.X_add_symbol = abs_section_sym;
7200 exp.X_add_number = 0;
7202 else if ((fixup_info[i].ramp & NDS32_INSN16) != 0)
7204 if (!enable_16bit)
7205 continue;
7206 /* This is a tag relocation. */
7207 exp.X_add_symbol = abs_section_sym;
7208 exp.X_add_number = 0;
7210 else
7212 exp.X_add_symbol = branch_symbol;
7213 exp.X_add_number = branch_offset;
7216 if (fixup_info[i].r_type != 0)
7218 final_r_type = fixup_info[i].r_type;
7219 fixP = fix_new_exp (fragP, fr_where + fixup_info[i].offset,
7220 fixup_size, &exp, pcrel,
7221 final_r_type);
7222 fixP->fx_addnumber = fixP->fx_offset;
7226 fragP->fr_fix = fr_where + buf_offset;
7230 /* tc_frob_file_before_fix */
7232 void
7233 nds32_frob_file_before_fix (void)
7237 static bool
7238 nds32_relaxable_section (asection *sec)
7240 return ((sec->flags & SEC_DEBUGGING) == 0
7241 && strcmp (sec->name, ".eh_frame") != 0);
7244 /* TC_FORCE_RELOCATION */
7246 nds32_force_relocation (fixS * fix)
7248 switch (fix->fx_r_type)
7250 case BFD_RELOC_NDS32_INSN16:
7251 case BFD_RELOC_NDS32_LABEL:
7252 case BFD_RELOC_NDS32_LONGCALL1:
7253 case BFD_RELOC_NDS32_LONGCALL2:
7254 case BFD_RELOC_NDS32_LONGCALL3:
7255 case BFD_RELOC_NDS32_LONGJUMP1:
7256 case BFD_RELOC_NDS32_LONGJUMP2:
7257 case BFD_RELOC_NDS32_LONGJUMP3:
7258 case BFD_RELOC_NDS32_LOADSTORE:
7259 case BFD_RELOC_NDS32_9_FIXED:
7260 case BFD_RELOC_NDS32_15_FIXED:
7261 case BFD_RELOC_NDS32_17_FIXED:
7262 case BFD_RELOC_NDS32_25_FIXED:
7263 case BFD_RELOC_NDS32_9_PCREL:
7264 case BFD_RELOC_NDS32_15_PCREL:
7265 case BFD_RELOC_NDS32_17_PCREL:
7266 case BFD_RELOC_NDS32_WORD_9_PCREL:
7267 case BFD_RELOC_NDS32_10_UPCREL:
7268 case BFD_RELOC_NDS32_25_PCREL:
7269 case BFD_RELOC_NDS32_MINUEND:
7270 case BFD_RELOC_NDS32_SUBTRAHEND:
7271 return 1;
7273 case BFD_RELOC_8:
7274 case BFD_RELOC_16:
7275 case BFD_RELOC_32:
7276 case BFD_RELOC_NDS32_DIFF_ULEB128:
7277 /* Linker should handle difference between two symbol. */
7278 return fix->fx_subsy != NULL
7279 && nds32_relaxable_section (S_GET_SEGMENT (fix->fx_addsy));
7280 case BFD_RELOC_64:
7281 if (fix->fx_subsy)
7282 as_bad ("Double word for difference between two symbols "
7283 "is not supported across relaxation.");
7284 default:
7288 if (generic_force_reloc (fix))
7289 return 1;
7291 return fix->fx_pcrel;
7294 /* TC_VALIDATE_FIX_SUB */
7297 nds32_validate_fix_sub (fixS *fix, segT add_symbol_segment)
7299 segT sub_symbol_segment;
7301 /* This code is referred from Xtensa. Check their implementation for
7302 details. */
7304 /* Make sure both symbols are in the same segment, and that segment is
7305 "normal" and relaxable. */
7306 sub_symbol_segment = S_GET_SEGMENT (fix->fx_subsy);
7307 return (sub_symbol_segment == add_symbol_segment
7308 && add_symbol_segment != undefined_section);
7311 void
7312 md_number_to_chars (char *buf, valueT val, int n)
7314 if (target_big_endian)
7315 number_to_chars_bigendian (buf, val, n);
7316 else
7317 number_to_chars_littleendian (buf, val, n);
7320 /* This function is called to convert an ASCII string into a floating point
7321 value in format used by the CPU. */
7323 const char *
7324 md_atof (int type, char *litP, int *sizeP)
7326 int i;
7327 int prec;
7328 LITTLENUM_TYPE words[MAX_LITTLENUMS];
7329 char *t;
7331 switch (type)
7333 case 'f':
7334 case 'F':
7335 case 's':
7336 case 'S':
7337 prec = 2;
7338 break;
7339 case 'd':
7340 case 'D':
7341 case 'r':
7342 case 'R':
7343 prec = 4;
7344 break;
7345 default:
7346 *sizeP = 0;
7347 return _("Bad call to md_atof()");
7350 t = atof_ieee (input_line_pointer, type, words);
7351 if (t)
7352 input_line_pointer = t;
7353 *sizeP = prec * sizeof (LITTLENUM_TYPE);
7355 if (target_big_endian)
7357 for (i = 0; i < prec; i++)
7359 md_number_to_chars (litP, (valueT) words[i],
7360 sizeof (LITTLENUM_TYPE));
7361 litP += sizeof (LITTLENUM_TYPE);
7364 else
7366 for (i = prec - 1; i >= 0; i--)
7368 md_number_to_chars (litP, (valueT) words[i],
7369 sizeof (LITTLENUM_TYPE));
7370 litP += sizeof (LITTLENUM_TYPE);
7374 return 0;
7377 /* md_elf_section_change_hook */
7379 void
7380 nds32_elf_section_change_hook (void)
7384 /* md_cleanup */
7386 void
7387 nds32_cleanup (void)
7391 /* This function is used to scan leb128 subtraction expressions,
7392 and insert fixups for them.
7394 e.g., .leb128 .L1 - .L0
7396 These expressions are heavily used in debug information or
7397 exception tables. Because relaxation will change code size,
7398 we must resolve them in link time. */
7400 static void
7401 nds32_insert_leb128_fixes (bfd *abfd ATTRIBUTE_UNUSED,
7402 asection *sec, void *xxx ATTRIBUTE_UNUSED)
7404 segment_info_type *seginfo = seg_info (sec);
7405 struct frag *fragP;
7407 subseg_set (sec, 0);
7409 for (fragP = seginfo->frchainP->frch_root;
7410 fragP; fragP = fragP->fr_next)
7412 expressionS *exp;
7414 /* Only unsigned leb128 can be handle. */
7415 if (fragP->fr_type != rs_leb128 || fragP->fr_subtype != 0
7416 || fragP->fr_symbol == NULL)
7417 continue;
7419 exp = symbol_get_value_expression (fragP->fr_symbol);
7421 if (exp->X_op != O_subtract)
7422 continue;
7424 fix_new_exp (fragP, fragP->fr_fix, 0,
7425 exp, 0, BFD_RELOC_NDS32_DIFF_ULEB128);
7429 static void
7430 nds32_insert_relax_entry (bfd *abfd ATTRIBUTE_UNUSED, asection *sec,
7431 void *xxx ATTRIBUTE_UNUSED)
7433 segment_info_type *seginfo;
7434 fragS *fragP;
7435 fixS *fixP;
7436 expressionS exp;
7437 fixS *fixp;
7439 seginfo = seg_info (sec);
7440 if (!seginfo || !symbol_rootP || !subseg_text_p (sec) || sec->size == 0)
7441 return;
7443 for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
7444 if (!fixp->fx_done)
7445 break;
7447 if (!fixp && !verbatim && ict_flag == ICT_NONE)
7448 return;
7450 subseg_change (sec, 0);
7452 /* Set RELAX_ENTRY flags for linker. */
7453 fragP = seginfo->frchainP->frch_root;
7454 exp.X_op = O_symbol;
7455 exp.X_add_symbol = abs_section_sym;
7456 exp.X_add_number = 0;
7457 if (!enable_relax_relocs)
7458 exp.X_add_number |= R_NDS32_RELAX_ENTRY_DISABLE_RELAX_FLAG;
7459 else
7461 /* These flags are only enabled when global relax is enabled.
7462 Maybe we can check DISABLE_RELAX_FLAG at link-time,
7463 so we set them anyway. */
7464 if (verbatim)
7465 exp.X_add_number |= R_NDS32_RELAX_ENTRY_VERBATIM_FLAG;
7466 if (ict_flag == ICT_SMALL)
7467 exp.X_add_number |= R_NDS32_RELAX_ENTRY_ICT_SMALL;
7468 else if (ict_flag == ICT_LARGE)
7469 exp.X_add_number |= R_NDS32_RELAX_ENTRY_ICT_LARGE;
7471 if (optimize)
7472 exp.X_add_number |= R_NDS32_RELAX_ENTRY_OPTIMIZE_FLAG;
7473 if (optimize_for_space)
7474 exp.X_add_number |= R_NDS32_RELAX_ENTRY_OPTIMIZE_FOR_SPACE_FLAG;
7476 fixP = fix_new_exp (fragP, 0, 0, &exp, 0, BFD_RELOC_NDS32_RELAX_ENTRY);
7477 fixP->fx_no_overflow = 1;
7480 /* Analysis relax hint and insert suitable relocation pattern. */
7482 static void
7483 nds32_elf_analysis_relax_hint (void)
7485 htab_traverse_noresize (nds32_hint_hash,
7486 nds32_elf_append_relax_relocs_traverse, NULL);
7489 static void
7490 nds32_elf_insert_final_frag (void)
7492 struct frchain *frchainP;
7493 asection *s;
7494 fragS *fragP;
7496 if (!optimize)
7497 return;
7499 for (s = stdoutput->sections; s; s = s->next)
7501 segment_info_type *seginfo = seg_info (s);
7502 if (!seginfo)
7503 continue;
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))
7512 fragP = frag_now;
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;
7521 void
7522 md_finish (void)
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. */
7531 bool
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. */
7537 return false;
7540 long
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. */
7547 return 0;
7550 return fixP->fx_frag->fr_address + fixP->fx_where;
7553 /* md_post_relax_hook ()
7554 Insert relax entry relocation into sections. */
7556 void
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
7565 section symbols. */
7567 bool
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:
7579 case BFD_RELOC_8:
7580 case BFD_RELOC_16:
7581 case BFD_RELOC_32:
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:
7590 return 1;
7591 default:
7592 return 0;
7596 /* elf_tc_final_processing */
7598 void
7599 elf_nds32_final_processing (void)
7601 /* An FPU_COM instruction is found without previous non-FPU_COM
7602 instruction. */
7603 if (nds32_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;
7614 else
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);
7630 if (nds32_pic)
7631 nds32_elf_flags |= E_NDS32_HAS_PIC;
7633 if (nds32_gpr16)
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. */
7643 void
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. */
7669 fixP->fx_done = 1;
7670 break;
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);
7686 break;
7687 default:
7688 break;
7690 return;
7693 if (fixP->fx_addsy == (symbolS *) NULL)
7694 fixP->fx_done = 1;
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-
7704 purpose arithmetic.
7706 Consider this example, the distance between .LEND and .LBEGIN
7707 is stored at the address of foo.
7709 ---- >8 ---- >8 ---- >8 ---- >8 ----
7710 .data
7711 foo:
7712 .word .LBEGIN - .LEND
7714 .text
7715 [before]
7716 .LBEGIN
7718 [between] distance
7720 .LEND
7721 [after]
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
7745 when relaxation.
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
7757 .long .L1-1-.L0
7758 in order to describe register clobbering during an function-call.
7759 .L0:
7760 call foo
7761 .L1:
7763 Check http://gcc.gnu.org/ml/gcc-patches/2009-06/msg01317.html
7764 for details. */
7766 value -= S_GET_VALUE (fixP->fx_subsy);
7767 *valP = value;
7768 fixP->fx_subsy = NULL;
7769 fixP->fx_offset -= value;
7771 switch (fixP->fx_r_type)
7773 case BFD_RELOC_8:
7774 fixP->fx_r_type = BFD_RELOC_NDS32_DIFF8;
7775 md_number_to_chars (where, value, 1);
7776 break;
7777 case BFD_RELOC_16:
7778 fixP->fx_r_type = BFD_RELOC_NDS32_DIFF16;
7779 md_number_to_chars (where, value, 2);
7780 break;
7781 case BFD_RELOC_32:
7782 fixP->fx_r_type = BFD_RELOC_NDS32_DIFF32;
7783 md_number_to_chars (where, value, 4);
7784 break;
7785 case BFD_RELOC_NDS32_DIFF_ULEB128:
7786 /* cvt_frag_to_fill () has called output_leb128 () for us. */
7787 break;
7788 default:
7789 as_bad_subtract (fixP);
7790 return;
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)
7799 case BFD_RELOC_8:
7800 md_number_to_chars (where, value, 1);
7801 break;
7802 case BFD_RELOC_16:
7803 md_number_to_chars (where, value, 2);
7804 break;
7805 case BFD_RELOC_32:
7806 md_number_to_chars (where, value, 4);
7807 break;
7808 case BFD_RELOC_64:
7809 md_number_to_chars (where, value, 8);
7810 break;
7811 default:
7812 as_bad_where (fixP->fx_file, fixP->fx_line,
7813 _("Internal error: Unknown fixup type %d (`%s')"),
7814 fixP->fx_r_type,
7815 bfd_get_reloc_code_name (fixP->fx_r_type));
7816 break;
7821 /* Implement tc_gen_reloc. Generate ELF relocation for a fix-up. */
7823 arelent *
7824 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
7826 arelent *reloc;
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));
7843 return NULL;
7846 /* Add relocation handling here. */
7848 switch (fixP->fx_r_type)
7850 default:
7851 /* In general, addend of a relocation is the offset to the
7852 associated symbol. */
7853 reloc->addend = fixP->fx_offset;
7854 break;
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;
7860 break;
7863 return reloc;
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)
7883 segT segment;
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 != '@'))
7895 return 0;
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 == '@')
7904 size_t i;
7905 char *next;
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';
7918 break;
7923 return 1;
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);
7933 if (!sym)
7934 return -1;
7936 return sym->value;
7939 void
7940 tc_nds32_frame_initial_instructions (void)
7942 /* CIE */
7943 /* Default cfa is register-31/sp. */
7944 cfi_add_CFA_def_cfa (31, 0);