gdb/testsuite: fix gdb.trace/signal.exp on x86
[binutils-gdb/blckswan.git] / gas / config / tc-nds32.c
blobe236169ba3c508874b72ea7d5198b91cafabc388
1 /* tc-nds32.c -- Assemble for the nds32
2 Copyright (C) 2012-2022 Free Software Foundation, Inc.
3 Contributed by Andes Technology Corporation.
5 This file is part of GAS, the GNU Assembler.
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
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 s = input_line_pointer;
2523 input_line_pointer = tmp; /* Restore line pointer. */
2525 return s; /* Return pointer to where parsing stopped. */
2528 void
2529 nds32_start_line_hook (void)
2534 * Pseudo opcodes
2537 typedef void (*nds32_pseudo_opcode_func) (int argc, char *argv[], unsigned int pv);
2538 struct nds32_pseudo_opcode
2540 const char *opcode;
2541 int argc;
2542 nds32_pseudo_opcode_func proc;
2543 unsigned int pseudo_val;
2545 /* Some instructions are not pseudo opcode, but they might still be
2546 expanded or changed with other instruction combination for some
2547 conditions. We also apply this structure to assist such work.
2549 For example, if the distance of branch target '.L0' is larger than
2550 imm8s<<1 range,
2552 the instruction:
2554 beqzs8 .L0
2556 will be transformed into:
2558 bnezs8 .LCB0
2559 j .L0
2560 .LCB0:
2562 However, sometimes we do not want assembler to do such changes
2563 because compiler knows how to generate corresponding instruction sequence.
2564 Use this field to indicate that this opcode is also a physical instruction.
2565 If the flag 'verbatim' is nozero and this opcode
2566 is a physical instruction, we should not expand it. */
2567 int physical_op;
2569 #define PV_DONT_CARE 0
2571 static htab_t nds32_pseudo_opcode_hash = NULL;
2573 static int
2574 builtin_isreg (const char *s, const char *x ATTRIBUTE_UNUSED)
2576 if (s [0] == '$' && str_hash_find (nds32_gprs_hash, (s + 1)))
2577 return 1;
2578 return 0;
2581 static int
2582 builtin_regnum (const char *s, const char *x ATTRIBUTE_UNUSED)
2584 struct nds32_keyword *k;
2585 if (*s != '$')
2586 return -1;
2587 s++;
2588 k = str_hash_find (nds32_gprs_hash, s);
2590 if (k == NULL)
2591 return -1;
2593 return k->value;
2596 static int
2597 builtin_addend (const char *s, char *x ATTRIBUTE_UNUSED)
2599 const char *ptr = s;
2601 while (*ptr != '+' && *ptr != '-' && *ptr)
2602 ++ptr;
2604 if (*ptr == 0)
2605 return 0;
2606 else
2607 return strtol (ptr, NULL, 0);
2610 static void
2611 md_assemblef (const char *format, ...)
2613 /* FIXME: hope this is long enough. */
2614 char line[1024];
2615 va_list ap;
2616 unsigned int r;
2618 va_start (ap, format);
2619 r = vsnprintf (line, sizeof (line), format, ap);
2620 md_assemble (line);
2622 gas_assert (r < sizeof (line));
2625 /* Some prototypes here, since some op may use another op. */
2626 static void do_pseudo_li_internal (const char *rt, int imm32s);
2627 static void do_pseudo_move_reg_internal (char *dst, char *src);
2629 static void
2630 do_pseudo_b (int argc ATTRIBUTE_UNUSED, char *argv[],
2631 unsigned int pv ATTRIBUTE_UNUSED)
2633 char *arg_label = argv[0];
2634 relaxing = true;
2635 /* b label */
2636 if (nds32_pic)
2638 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2639 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2640 md_assemble ((char *) "add $ta,$ta,$gp");
2641 md_assemble ((char *) "jr $ta");
2643 else
2645 md_assemblef ("j %s", arg_label);
2647 relaxing = false;
2650 static void
2651 do_pseudo_bal (int argc ATTRIBUTE_UNUSED, char *argv[],
2652 unsigned int pv ATTRIBUTE_UNUSED)
2654 char *arg_label = argv[0];
2655 relaxing = true;
2656 /* bal|call label */
2657 if (nds32_pic)
2659 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2660 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2661 md_assemble ((char *) "add $ta,$ta,$gp");
2662 md_assemble ((char *) "jral $ta");
2664 else
2666 md_assemblef ("jal %s", arg_label);
2668 relaxing = false;
2671 static void
2672 do_pseudo_bge (int argc ATTRIBUTE_UNUSED, char *argv[],
2673 unsigned int pv ATTRIBUTE_UNUSED)
2675 /* rt5, ra5, label */
2676 md_assemblef ("slt $ta,%s,%s", argv[0], argv[1]);
2677 md_assemblef ("beqz $ta,%s", argv[2]);
2680 static void
2681 do_pseudo_bges (int argc ATTRIBUTE_UNUSED, char *argv[],
2682 unsigned int pv ATTRIBUTE_UNUSED)
2684 /* rt5, ra5, label */
2685 md_assemblef ("slts $ta,%s,%s", argv[0], argv[1]);
2686 md_assemblef ("beqz $ta,%s", argv[2]);
2689 static void
2690 do_pseudo_bgt (int argc ATTRIBUTE_UNUSED, char *argv[],
2691 unsigned int pv ATTRIBUTE_UNUSED)
2693 /* bgt rt5, ra5, label */
2694 md_assemblef ("slt $ta,%s,%s", argv[1], argv[0]);
2695 md_assemblef ("bnez $ta,%s", argv[2]);
2698 static void
2699 do_pseudo_bgts (int argc ATTRIBUTE_UNUSED, char *argv[],
2700 unsigned int pv ATTRIBUTE_UNUSED)
2702 /* bgt rt5, ra5, label */
2703 md_assemblef ("slts $ta,%s,%s", argv[1], argv[0]);
2704 md_assemblef ("bnez $ta,%s", argv[2]);
2707 static void
2708 do_pseudo_ble (int argc ATTRIBUTE_UNUSED, char *argv[],
2709 unsigned int pv ATTRIBUTE_UNUSED)
2711 /* bgt rt5, ra5, label */
2712 md_assemblef ("slt $ta,%s,%s", argv[1], argv[0]);
2713 md_assemblef ("beqz $ta,%s", argv[2]);
2716 static void
2717 do_pseudo_bles (int argc ATTRIBUTE_UNUSED, char *argv[],
2718 unsigned int pv ATTRIBUTE_UNUSED)
2720 /* bgt rt5, ra5, label */
2721 md_assemblef ("slts $ta,%s,%s", argv[1], argv[0]);
2722 md_assemblef ("beqz $ta,%s", argv[2]);
2725 static void
2726 do_pseudo_blt (int argc ATTRIBUTE_UNUSED, char *argv[],
2727 unsigned int pv ATTRIBUTE_UNUSED)
2729 /* rt5, ra5, label */
2730 md_assemblef ("slt $ta,%s,%s", argv[0], argv[1]);
2731 md_assemblef ("bnez $ta,%s", argv[2]);
2734 static void
2735 do_pseudo_blts (int argc ATTRIBUTE_UNUSED, char *argv[],
2736 unsigned int pv ATTRIBUTE_UNUSED)
2738 /* rt5, ra5, label */
2739 md_assemblef ("slts $ta,%s,%s", argv[0], argv[1]);
2740 md_assemblef ("bnez $ta,%s", argv[2]);
2743 static void
2744 do_pseudo_br (int argc ATTRIBUTE_UNUSED, char *argv[],
2745 unsigned int pv ATTRIBUTE_UNUSED)
2747 md_assemblef ("jr %s", argv[0]);
2750 static void
2751 do_pseudo_bral (int argc, char *argv[],
2752 unsigned int pv ATTRIBUTE_UNUSED)
2754 if (argc == 1)
2755 md_assemblef ("jral $lp,%s", argv[0]);
2756 else
2757 md_assemblef ("jral %s,%s", argv[0], argv[1]);
2760 static void
2761 do_pseudo_la_internal (const char *arg_reg, char *arg_label,
2762 const char *line)
2764 expressionS exp;
2766 parse_expression (arg_label, &exp);
2767 if (exp.X_op != O_symbol)
2769 as_bad (_("la must use with symbol. '%s'"), line);
2770 return;
2773 relaxing = true;
2774 /* rt, label */
2775 if (!nds32_pic && !strstr (arg_label, "@"))
2777 md_assemblef ("sethi %s,hi20(%s)", arg_reg, arg_label);
2778 md_assemblef ("ori %s,%s,lo12(%s)", arg_reg, arg_reg, arg_label);
2780 else if (strstr (arg_label, "@TPOFF"))
2782 /* la $rt, sym@TPOFF */
2783 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2784 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2785 md_assemblef ("add %s,$ta,%s", arg_reg, TLS_REG);
2787 else if (strstr(arg_label, "@GOTTPOFF"))
2789 /* la $rt, sym@GOTTPOFF*/
2790 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2791 md_assemblef ("lwi $ta,[$ta+lo12(%s)]", arg_label);
2792 md_assemblef ("add %s,$ta,%s", arg_reg, TLS_REG);
2794 else if (nds32_pic && ((strstr (arg_label, "@PLT")
2795 || strstr (arg_label, "@GOTOFF"))))
2797 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2798 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2799 md_assemblef ("add %s,$ta,$gp", arg_reg);
2801 else if (nds32_pic && strstr (arg_label, "@GOT"))
2803 long addend = builtin_addend (arg_label, NULL);
2805 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2806 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2807 md_assemblef ("lw %s,[$gp+$ta]", arg_reg);
2808 if (addend != 0)
2810 if (addend < 0x4000 && addend >= -0x4000)
2812 md_assemblef ("addi %s,%s,%d", arg_reg, arg_reg, addend);
2814 else
2816 do_pseudo_li_internal ("$ta", addend);
2817 md_assemblef ("add %s,$ta,%s", arg_reg, arg_reg);
2821 else
2822 as_bad (_("need PIC qualifier with symbol. '%s'"), line);
2823 relaxing = false;
2826 static void
2827 do_pseudo_la (int argc ATTRIBUTE_UNUSED, char *argv[],
2828 unsigned int pv ATTRIBUTE_UNUSED)
2830 do_pseudo_la_internal (argv[0], argv[1], argv[argc]);
2833 static void
2834 do_pseudo_li_internal (const char *rt, int imm32s)
2836 if (enable_16bit && imm32s <= 0xf && imm32s >= -0x10)
2837 md_assemblef ("movi55 %s,%d", rt, imm32s);
2838 else if (imm32s <= 0x7ffff && imm32s >= -0x80000)
2839 md_assemblef ("movi %s,%d", rt, imm32s);
2840 else if ((imm32s & 0xfff) == 0)
2841 md_assemblef ("sethi %s,hi20(%d)", rt, imm32s);
2842 else
2844 md_assemblef ("sethi %s,hi20(%d)", rt, imm32s);
2845 md_assemblef ("ori %s,%s,lo12(%d)", rt, rt, imm32s);
2849 static void
2850 do_pseudo_li (int argc ATTRIBUTE_UNUSED, char *argv[],
2851 unsigned int pv ATTRIBUTE_UNUSED)
2853 /* Validate argv[1] for constant expression. */
2854 expressionS exp;
2856 parse_expression (argv[1], &exp);
2857 if (exp.X_op != O_constant)
2859 as_bad (_("Operand is not a constant. `%s'"), argv[argc]);
2860 return;
2863 do_pseudo_li_internal (argv[0], exp.X_add_number);
2866 static void
2867 do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED, char *argv[],
2868 unsigned int pv)
2870 char ls = 'r';
2871 char size = 'x';
2872 const char *sign = "";
2874 /* Prepare arguments for various load/store. */
2875 sign = (pv & 0x10) ? "s" : "";
2876 ls = (pv & 0x80000000) ? 's' : 'l';
2877 switch (pv & 0x3)
2879 case 0: size = 'b'; break;
2880 case 1: size = 'h'; break;
2881 case 2: size = 'w'; break;
2884 if (ls == 's' || size == 'w')
2885 sign = "";
2887 if (builtin_isreg (argv[1], NULL))
2889 /* lwi */
2890 md_assemblef ("%c%ci %s,[%s]", ls, size, argv[0], argv[1]);
2892 else if (!nds32_pic)
2894 relaxing = true;
2895 if (strstr (argv[1], "@TPOFF"))
2897 /* ls.w $rt, sym@TPOFF */
2898 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2899 md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
2900 md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], TLS_REG);
2902 else if (strstr (argv[1], "@GOTTPOFF"))
2904 /* ls.w $rt, sym@GOTTPOFF */
2905 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2906 md_assemblef ("lwi $ta,[$ta+lo12(%s)]", argv[1]);
2907 md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], TLS_REG);
2909 else
2911 /* lwi */
2912 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2913 md_assemblef ("%c%c%si %s,[$ta+lo12(%s)]", ls, size, sign, argv[0], argv[1]);
2915 relaxing = false;
2917 else
2919 relaxing = true;
2920 /* PIC code. */
2921 if (strstr (argv[1], "@GOTOFF"))
2923 /* lw */
2924 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2925 md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
2926 md_assemblef ("%c%c%s %s,[$ta+$gp]", ls, size, sign, argv[0]);
2928 else if (strstr (argv[1], "@GOT"))
2930 long addend = builtin_addend (argv[1], NULL);
2931 /* lw */
2932 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2933 md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
2934 md_assemble ((char *) "lw $ta,[$gp+$ta]"); /* Load address word. */
2935 if (addend < 0x10000 && addend >= -0x10000)
2937 md_assemblef ("%c%c%si %s,[$ta+(%d)]", ls, size, sign, argv[0], addend);
2939 else
2941 /* lw */
2942 do_pseudo_li_internal (argv[0], addend);
2943 md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], argv[0]);
2946 else
2948 as_bad (_("needs @GOT or @GOTOFF. %s"), argv[argc]);
2950 relaxing = false;
2954 static void
2955 do_pseudo_ls_bhwp (int argc ATTRIBUTE_UNUSED, char *argv[],
2956 unsigned int pv)
2958 char *arg_rt = argv[0];
2959 char *arg_label = argv[1];
2960 char *arg_inc = argv[2];
2961 char ls = 'r';
2962 char size = 'x';
2963 const char *sign = "";
2965 /* Prepare arguments for various load/store. */
2966 sign = (pv & 0x10) ? "s" : "";
2967 ls = (pv & 0x80000000) ? 's' : 'l';
2968 switch (pv & 0x3)
2970 case 0: size = 'b'; break;
2971 case 1: size = 'h'; break;
2972 case 2: size = 'w'; break;
2975 if (ls == 's' || size == 'w')
2976 sign = "";
2978 do_pseudo_la_internal ("$ta", arg_label, argv[argc]);
2979 md_assemblef ("%c%c%si.bi %s,[$ta],%s", ls, size, sign, arg_rt, arg_inc);
2982 static void
2983 do_pseudo_ls_bhwpc (int argc ATTRIBUTE_UNUSED, char *argv[],
2984 unsigned int pv)
2986 char *arg_rt = argv[0];
2987 char *arg_inc = argv[1];
2988 char ls = 'r';
2989 char size = 'x';
2990 const char *sign = "";
2992 /* Prepare arguments for various load/store. */
2993 sign = (pv & 0x10) ? "s" : "";
2994 ls = (pv & 0x80000000) ? 's' : 'l';
2995 switch (pv & 0x3)
2997 case 0: size = 'b'; break;
2998 case 1: size = 'h'; break;
2999 case 2: size = 'w'; break;
3002 if (ls == 's' || size == 'w')
3003 sign = "";
3005 md_assemblef ("%c%c%si.bi %s,[$ta],%s", ls, size, sign, arg_rt, arg_inc);
3008 static void
3009 do_pseudo_ls_bhwi (int argc ATTRIBUTE_UNUSED, char *argv[],
3010 unsigned int pv)
3012 char ls = 'r';
3013 char size = 'x';
3014 const char *sign = "";
3016 /* Prepare arguments for various load/store. */
3017 sign = (pv & 0x10) ? "s" : "";
3018 ls = (pv & 0x80000000) ? 's' : 'l';
3019 switch (pv & 0x3)
3021 case 0: size = 'b'; break;
3022 case 1: size = 'h'; break;
3023 case 2: size = 'w'; break;
3026 if (ls == 's' || size == 'w')
3027 sign = "";
3029 md_assemblef ("%c%c%si.bi %s,%s,%s",
3030 ls, size, sign, argv[0], argv[1], argv[2]);
3033 static void
3034 do_pseudo_move_reg_internal (char *dst, char *src)
3036 if (enable_16bit)
3037 md_assemblef ("mov55 %s,%s", dst, src);
3038 else
3039 md_assemblef ("ori %s,%s,0", dst, src);
3042 static void
3043 do_pseudo_move (int argc ATTRIBUTE_UNUSED, char *argv[],
3044 unsigned int pv ATTRIBUTE_UNUSED)
3046 expressionS exp;
3048 if (builtin_isreg (argv[1], NULL))
3049 do_pseudo_move_reg_internal (argv[0], argv[1]);
3050 else
3052 parse_expression (argv[1], &exp);
3053 if (exp.X_op == O_constant)
3054 /* move $rt, imm -> li $rt, imm */
3055 do_pseudo_li_internal (argv[0], exp.X_add_number);
3056 else
3057 /* l.w $rt, var -> l.w $rt, var */
3058 do_pseudo_ls_bhw (argc, argv, 2);
3062 static void
3063 do_pseudo_neg (int argc ATTRIBUTE_UNUSED, char *argv[],
3064 unsigned int pv ATTRIBUTE_UNUSED)
3066 /* Instead of "subri". */
3067 md_assemblef ("subri %s,%s,0", argv[0], argv[1]);
3070 static void
3071 do_pseudo_not (int argc ATTRIBUTE_UNUSED, char *argv[],
3072 unsigned int pv ATTRIBUTE_UNUSED)
3074 md_assemblef ("nor %s,%s,%s", argv[0], argv[1], argv[1]);
3077 static void
3078 do_pseudo_pushpopm (int argc, char *argv[],
3079 unsigned int pv ATTRIBUTE_UNUSED)
3081 /* posh/pop $ra, $rb */
3082 /* SMW.{b | a}{i | d}{m?} Rb, [Ra], Re, Enable4 */
3083 int rb, re, ra, en4;
3084 int i;
3085 const char *opc = "pushpopm";
3087 if (argc == 3)
3088 as_bad ("'pushm/popm $ra5, $rb5, $label' is deprecated. "
3089 "Only 'pushm/popm $ra5' is supported now. %s", argv[argc]);
3090 else if (argc == 1)
3091 as_bad ("'pushm/popm $ra5, $rb5'. %s\n", argv[argc]);
3093 if (strstr (argv[argc], "pop") == argv[argc])
3094 opc = "lmw.bim";
3095 else if (strstr (argv[argc], "push") == argv[argc])
3096 opc = "smw.adm";
3097 else
3098 as_fatal ("nds32-as internal error. %s", argv[argc]);
3100 rb = builtin_regnum (argv[0], NULL);
3101 re = builtin_regnum (argv[1], NULL);
3103 if (re < rb)
3105 as_warn ("$rb should not be smaller than $ra. %s", argv[argc]);
3106 /* Swap to right order. */
3107 ra = re;
3108 re = rb;
3109 rb = ra;
3112 /* Build enable4 mask. */
3113 en4 = 0;
3114 if (re >= 28 || rb >= 28)
3116 for (i = (rb >= 28? rb: 28); i <= re; i++)
3117 en4 |= 1 << (3 - (i - 28));
3120 /* Adjust $re, $rb. */
3121 if (rb >= 28)
3122 rb = re = 31;
3123 else if (nds32_gpr16 != 1 && re >= 28)
3124 re = 27;
3126 /* Reduce register. */
3127 if (nds32_gpr16 && re > 10 && !(rb == 31 && re == 31))
3129 if (re >= 15 && strstr (opc, "smw") != NULL)
3130 md_assemblef ("%s $r15,[$sp],$r15,%d", opc, en4);
3131 if (rb <= 10)
3132 md_assemblef ("%s $r%d,[$sp],$r10, 0x0", opc, rb);
3133 if (re >= 15 && strstr (opc, "lmw") != NULL)
3134 md_assemblef ("%s $r15,[$sp],$r15,%d", opc, en4);
3136 else
3137 md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc, rb, re, en4);
3140 static void
3141 do_pseudo_pushpop (int argc, char *argv[],
3142 unsigned int pv ATTRIBUTE_UNUSED)
3144 /* push/pop $ra5, $label=$sp */
3145 char *argvm[3];
3147 if (argc == 2)
3148 as_bad ("'push/pop $ra5, rb5' is deprecated. "
3149 "Only 'push/pop $ra5' is supported now. %s", argv[argc]);
3151 argvm[0] = argv[0];
3152 argvm[1] = argv[0];
3153 argvm[2] = argv[argc];
3154 do_pseudo_pushpopm (2, argvm, PV_DONT_CARE);
3157 static void
3158 do_pseudo_v3push (int argc ATTRIBUTE_UNUSED, char *argv[],
3159 unsigned int pv ATTRIBUTE_UNUSED)
3161 md_assemblef ("push25 %s,%s", argv[0], argv[1]);
3164 static void
3165 do_pseudo_v3pop (int argc ATTRIBUTE_UNUSED, char *argv[],
3166 unsigned int pv ATTRIBUTE_UNUSED)
3168 md_assemblef ("pop25 %s,%s", argv[0], argv[1]);
3171 /* pv == 0, parsing "push.s" pseudo instruction operands.
3172 pv != 0, parsing "pop.s" pseudo instruction operands. */
3174 static void
3175 do_pseudo_pushpop_stack (int argc, char *argv[],
3176 unsigned int pv)
3178 /* push.s Rb,Re,{$fp $gp $lp $sp} ==> smw.adm Rb,[$sp],Re,Eable4 */
3179 /* pop.s Rb,Re,{$fp $gp $lp $sp} ==> lmw.bim Rb,[$sp],Re,Eable4 */
3181 int rb, re;
3182 int en4;
3183 int last_arg_index;
3184 const char *opc = (pv == 0) ? "smw.adm" : "lmw.bim";
3186 rb = re = 0;
3188 if (argc == 1)
3190 /* argc=1, operands pattern: { $fp $gp $lp $sp } */
3192 /* Set register number Rb = Re = $sp = $r31. */
3193 rb = re = 31;
3195 else if (argc == 2 || argc == 3)
3197 /* argc=2, operands pattern: Rb, Re */
3198 /* argc=3, operands pattern: Rb, Re, { $fp $gp $lp $sp } */
3200 /* Get register number in integer. */
3201 rb = builtin_regnum (argv[0], NULL);
3202 re = builtin_regnum (argv[1], NULL);
3204 /* Rb should be equal/less than Re. */
3205 if (rb > re)
3206 as_bad ("The first operand (%s) should be equal to or smaller than "
3207 "second operand (%s).", argv[0], argv[1]);
3209 /* forbid using $fp|$gp|$lp|$sp in Rb or Re
3210 r28 r29 r30 r31 */
3211 if (rb >= 28)
3212 as_bad ("Cannot use $fp, $gp, $lp, or $sp at first operand !!");
3213 if (re >= 28)
3214 as_bad ("Cannot use $fp, $gp, $lp, or $sp at second operand !!");
3216 else
3218 as_bad ("Invalid operands pattern !!");
3221 /* Build Enable4 mask. */
3222 /* Using last_arg_index for argc=1|2|3 is safe, because $fp, $gp, $lp,
3223 and $sp only appear in argc=1 or argc=3 if argc=2, en4 remains 0,
3224 which is also valid for code generation. */
3225 en4 = 0;
3226 last_arg_index = argc - 1;
3227 if (strstr (argv[last_arg_index], "$fp"))
3228 en4 |= 8;
3229 if (strstr (argv[last_arg_index], "$gp"))
3230 en4 |= 4;
3231 if (strstr (argv[last_arg_index], "$lp"))
3232 en4 |= 2;
3233 if (strstr (argv[last_arg_index], "$sp"))
3234 en4 |= 1;
3236 md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc, rb, re, en4);
3239 static void
3240 do_pseudo_push_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[],
3241 unsigned int pv ATTRIBUTE_UNUSED)
3243 char size = 'x';
3244 /* If users omit push location, use $sp as default value. */
3245 char location[8] = "$sp"; /* 8 is enough for register name. */
3247 switch (pv & 0x3)
3249 case 0: size = 'b'; break;
3250 case 1: size = 'h'; break;
3251 case 2: size = 'w'; break;
3252 case 3: size = 'w'; break;
3255 if (argc == 2)
3257 strncpy (location, argv[1], sizeof (location) - 1);
3258 location[sizeof (location) - 1] = '\0';
3261 md_assemblef ("l.%c $ta,%s", size, argv[0]);
3262 md_assemblef ("smw.adm $ta,[%s],$ta", location);
3264 if ((pv & 0x3) == 0x3) /* double-word */
3266 md_assemblef ("l.w $ta,%s+4", argv[0]);
3267 md_assemblef ("smw.adm $ta,[%s],$ta", location);
3271 static void
3272 do_pseudo_pop_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[],
3273 unsigned int pv ATTRIBUTE_UNUSED)
3275 char size = 'x';
3276 /* If users omit pop location, use $sp as default value. */
3277 char location[8] = "$sp"; /* 8 is enough for register name. */
3279 switch (pv & 0x3)
3281 case 0: size = 'b'; break;
3282 case 1: size = 'h'; break;
3283 case 2: size = 'w'; break;
3284 case 3: size = 'w'; break;
3287 if (argc == 3)
3289 strncpy (location, argv[2], sizeof (location) - 1);
3290 location[sizeof (location) - 1] = '\0';
3293 if ((pv & 0x3) == 0x3) /* double-word */
3295 md_assemblef ("lmw.bim %s,[%s],%s", argv[1], location, argv[1]);
3296 md_assemblef ("s.w %s,%s+4", argv[1], argv[0]);
3299 md_assemblef ("lmw.bim %s,[%s],%s", argv[1], location, argv[1]);
3300 md_assemblef ("s.%c %s,%s", size, argv[1], argv[0]);
3303 static void
3304 do_pseudo_pusha (int argc ATTRIBUTE_UNUSED, char *argv[],
3305 unsigned int pv ATTRIBUTE_UNUSED)
3307 /* If users omit push location, use $sp as default value. */
3308 char location[8] = "$sp"; /* 8 is enough for register name. */
3310 if (argc == 2)
3312 strncpy (location, argv[1], sizeof (location) - 1);
3313 location[sizeof (location) - 1] = '\0';
3316 md_assemblef ("la $ta,%s", argv[0]);
3317 md_assemblef ("smw.adm $ta,[%s],$ta", location);
3320 static void
3321 do_pseudo_pushi (int argc ATTRIBUTE_UNUSED, char *argv[],
3322 unsigned int pv ATTRIBUTE_UNUSED)
3324 /* If users omit push location, use $sp as default value. */
3325 char location[8] = "$sp"; /* 8 is enough for register name. */
3327 if (argc == 2)
3329 strncpy (location, argv[1], sizeof (location) - 1);
3330 location[sizeof (location) - 1] = '\0';
3333 md_assemblef ("li $ta,%s", argv[0]);
3334 md_assemblef ("smw.adm $ta,[%s],$ta", location);
3337 static struct nds32_pseudo_opcode nds32_pseudo_opcode_table[] =
3339 {"b", 1, do_pseudo_b, 0, 0},
3340 {"bal", 1, do_pseudo_bal, 0, 0},
3342 {"bge", 3, do_pseudo_bge, 0, 0},
3343 {"bges", 3, do_pseudo_bges, 0, 0},
3345 {"bgt", 3, do_pseudo_bgt, 0, 0},
3346 {"bgts", 3, do_pseudo_bgts, 0, 0},
3348 {"ble", 3, do_pseudo_ble, 0, 0},
3349 {"bles", 3, do_pseudo_bles, 0, 0},
3351 {"blt", 3, do_pseudo_blt, 0, 0},
3352 {"blts", 3, do_pseudo_blts, 0, 0},
3354 {"br", 1, do_pseudo_br, 0, 0},
3355 {"bral", 1, do_pseudo_bral, 0, 0},
3357 {"call", 1, do_pseudo_bal, 0, 0},
3359 {"la", 2, do_pseudo_la, 0, 0},
3360 {"li", 2, do_pseudo_li, 0, 0},
3362 {"l.b", 2, do_pseudo_ls_bhw, 0, 0},
3363 {"l.h", 2, do_pseudo_ls_bhw, 1, 0},
3364 {"l.w", 2, do_pseudo_ls_bhw, 2, 0},
3365 {"l.bs", 2, do_pseudo_ls_bhw, 0 | 0x10, 0},
3366 {"l.hs", 2, do_pseudo_ls_bhw, 1 | 0x10, 0},
3367 {"s.b", 2, do_pseudo_ls_bhw, 0 | 0x80000000, 0},
3368 {"s.h", 2, do_pseudo_ls_bhw, 1 | 0x80000000, 0},
3369 {"s.w", 2, do_pseudo_ls_bhw, 2 | 0x80000000, 0},
3371 {"l.bp", 3, do_pseudo_ls_bhwp, 0, 0},
3372 {"l.bpc", 3, do_pseudo_ls_bhwpc, 0, 0},
3373 {"l.hp", 3, do_pseudo_ls_bhwp, 1, 0},
3374 {"l.hpc", 3, do_pseudo_ls_bhwpc, 1, 0},
3375 {"l.wp", 3, do_pseudo_ls_bhwp, 2, 0},
3376 {"l.wpc", 3, do_pseudo_ls_bhwpc, 2, 0},
3377 {"l.bsp", 3, do_pseudo_ls_bhwp, 0 | 0x10, 0},
3378 {"l.bspc", 3, do_pseudo_ls_bhwpc, 0 | 0x10, 0},
3379 {"l.hsp", 3, do_pseudo_ls_bhwp, 1 | 0x10, 0},
3380 {"l.hspc", 3, do_pseudo_ls_bhwpc, 1 | 0x10, 0},
3381 {"s.bp", 3, do_pseudo_ls_bhwp, 0 | 0x80000000, 0},
3382 {"s.bpc", 3, do_pseudo_ls_bhwpc, 0 | 0x80000000, 0},
3383 {"s.hp", 3, do_pseudo_ls_bhwp, 1 | 0x80000000, 0},
3384 {"s.hpc", 3, do_pseudo_ls_bhwpc, 1 | 0x80000000, 0},
3385 {"s.wp", 3, do_pseudo_ls_bhwp, 2 | 0x80000000, 0},
3386 {"s.wpc", 3, do_pseudo_ls_bhwpc, 2 | 0x80000000, 0},
3387 {"s.bsp", 3, do_pseudo_ls_bhwp, 0 | 0x80000000 | 0x10, 0},
3388 {"s.hsp", 3, do_pseudo_ls_bhwp, 1 | 0x80000000 | 0x10, 0},
3390 {"lbi.p", 3, do_pseudo_ls_bhwi, 0, 0},
3391 {"lhi.p", 3, do_pseudo_ls_bhwi, 1, 0},
3392 {"lwi.p", 3, do_pseudo_ls_bhwi, 2, 0},
3393 {"sbi.p", 3, do_pseudo_ls_bhwi, 0 | 0x80000000, 0},
3394 {"shi.p", 3, do_pseudo_ls_bhwi, 1 | 0x80000000, 0},
3395 {"swi.p", 3, do_pseudo_ls_bhwi, 2 | 0x80000000, 0},
3396 {"lbsi.p", 3, do_pseudo_ls_bhwi, 0 | 0x10, 0},
3397 {"lhsi.p", 3, do_pseudo_ls_bhwi, 1 | 0x10, 0},
3398 {"lwsi.p", 3, do_pseudo_ls_bhwi, 2 | 0x10, 0},
3400 {"move", 2, do_pseudo_move, 0, 0},
3401 {"neg", 2, do_pseudo_neg, 0, 0},
3402 {"not", 2, do_pseudo_not, 0, 0},
3404 {"pop", 2, do_pseudo_pushpop, 0, 0},
3405 {"push", 2, do_pseudo_pushpop, 0, 0},
3406 {"popm", 2, do_pseudo_pushpopm, 0, 0},
3407 {"pushm", 3, do_pseudo_pushpopm, 0, 0},
3409 {"v3push", 2, do_pseudo_v3push, 0, 0},
3410 {"v3pop", 2, do_pseudo_v3pop, 0, 0},
3412 /* Support pseudo instructions of pushing/poping registers into/from stack
3413 push.s Rb, Re, { $fp $gp $lp $sp } ==> smw.adm Rb,[$sp],Re,Enable4
3414 pop.s Rb, Re, { $fp $gp $lp $sp } ==> lmw.bim Rb,[$sp],Re,Enable4 */
3415 { "push.s", 3, do_pseudo_pushpop_stack, 0, 0 },
3416 { "pop.s", 3, do_pseudo_pushpop_stack, 1, 0 },
3417 { "push.b", 2, do_pseudo_push_bhwd, 0, 0 },
3418 { "push.h", 2, do_pseudo_push_bhwd, 1, 0 },
3419 { "push.w", 2, do_pseudo_push_bhwd, 2, 0 },
3420 { "push.d", 2, do_pseudo_push_bhwd, 3, 0 },
3421 { "pop.b", 3, do_pseudo_pop_bhwd, 0, 0 },
3422 { "pop.h", 3, do_pseudo_pop_bhwd, 1, 0 },
3423 { "pop.w", 3, do_pseudo_pop_bhwd, 2, 0 },
3424 { "pop.d", 3, do_pseudo_pop_bhwd, 3, 0 },
3425 { "pusha", 2, do_pseudo_pusha, 0, 0 },
3426 { "pushi", 2, do_pseudo_pushi, 0, 0 },
3428 {NULL, 0, NULL, 0, 0}
3431 static void
3432 nds32_init_nds32_pseudo_opcodes (void)
3434 struct nds32_pseudo_opcode *opcode;
3436 nds32_pseudo_opcode_hash = str_htab_create ();
3437 for (opcode = nds32_pseudo_opcode_table; opcode->opcode; opcode++)
3438 if (str_hash_insert (nds32_pseudo_opcode_hash, opcode->opcode, opcode, 0))
3439 as_fatal (_("duplicate %s"), opcode->opcode);
3442 static struct nds32_pseudo_opcode *
3443 nds32_lookup_pseudo_opcode (const char *str)
3445 struct nds32_pseudo_opcode *result;
3446 int i = 0;
3448 /* (*op) is the first word of current source line (*str) */
3449 int maxlen = strlen (str);
3450 char *op = xmalloc (maxlen + 1);
3452 for (i = 0; i < maxlen; i++)
3454 if (ISSPACE (op[i] = str[i]))
3455 break;
3457 op[i] = '\0';
3459 result = str_hash_find (nds32_pseudo_opcode_hash, op);
3460 free (op);
3461 return result;
3464 static void
3465 nds32_pseudo_opcode_wrapper (char *line, struct nds32_pseudo_opcode *opcode)
3467 int argc = 0;
3468 char *argv[8] = {NULL};
3469 char *s;
3470 char *str = xstrdup (line);
3472 /* Parse arguments for opcode. */
3473 s = str + strlen (opcode->opcode);
3475 if (!s[0])
3476 goto end;
3478 /* Dummy comma to ease separate arguments as below. */
3479 s[0] = ',';
3482 if (s[0] == ',')
3484 if (argc >= opcode->argc
3485 || (argc >= (int)ARRAY_SIZE (argv) - 1))
3486 as_bad (_("Too many argument. `%s'"), line);
3488 argv[argc] = s + 1;
3489 argc ++;
3490 s[0] = '\0';
3492 ++s;
3493 } while (s[0] != '\0');
3494 end:
3495 /* Put the origin line for debugging. */
3496 argv[argc] = line;
3497 opcode->proc (argc, argv, opcode->pseudo_val);
3498 free (str);
3501 /* This function will be invoked from function `nds32_after_parse_args'.
3502 Thus, if the value of option has been set, keep the value the way it is. */
3504 static int
3505 nds32_parse_arch (const char *str)
3507 static const struct nds32_arch
3509 const char *name;
3510 int baseline;
3511 int reduced_reg;
3512 int fpu_sp_ext;
3513 int fpu_dp_ext;
3514 int fpu_freg;
3515 int abi;
3516 } archs[] =
3518 {"v3m", ISA_V3M, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3519 {"v3j", ISA_V3, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3520 {"v3s", ISA_V3, 0, 1, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3521 {"v3f", ISA_V3, 0, 1, 1, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3522 {"v3", ISA_V3, 0, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3523 {"v2j", ISA_V2, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3524 {"v2s", ISA_V2, 0, 1, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3525 {"v2f", ISA_V2, 0, 1, 1, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3526 {"v2", ISA_V2, 0, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3528 size_t i;
3530 for (i = 0; i < ARRAY_SIZE (archs); i++)
3532 if (strcmp (str, archs[i].name) != 0)
3533 continue;
3535 /* The value `-1' represents this option has *NOT* been set. */
3536 nds32_baseline = (-1 != nds32_baseline) ? nds32_baseline : archs[i].baseline;
3537 nds32_gpr16 = (-1 != nds32_gpr16) ? nds32_gpr16 : archs[i].reduced_reg;
3538 nds32_fpu_sp_ext = (-1 != nds32_fpu_sp_ext) ? nds32_fpu_sp_ext : archs[i].fpu_sp_ext;
3539 nds32_fpu_dp_ext = (-1 != nds32_fpu_dp_ext) ? nds32_fpu_dp_ext : archs[i].fpu_dp_ext;
3540 nds32_freg = (-1 != nds32_freg) ? nds32_freg : archs[i].fpu_freg;
3541 nds32_abi = (-1 != nds32_abi) ? nds32_abi : archs[i].abi;
3543 return 1;
3546 /* Logic here rejects the input arch name. */
3547 as_bad (_("unknown arch name `%s'\n"), str);
3549 return 1;
3552 /* This function parses "baseline" specified. */
3554 static int
3555 nds32_parse_baseline (const char *str)
3557 if (strcmp (str, "v3") == 0)
3558 nds32_baseline = ISA_V3;
3559 else if (strcmp (str, "v3m") == 0)
3560 nds32_baseline = ISA_V3M;
3561 else if (strcmp (str, "v2") == 0)
3562 nds32_baseline = ISA_V2;
3563 else
3565 /* Logic here rejects the input baseline. */
3566 as_bad (_("unknown baseline `%s'\n"), str);
3567 return 0;
3570 return 1;
3573 /* This function parses "fpu-freg" specified. */
3575 static int
3576 nds32_parse_freg (const char *str)
3578 if (strcmp (str, "2") == 0)
3579 nds32_freg = E_NDS32_FPU_REG_32SP_16DP;
3580 else if (strcmp (str, "3") == 0)
3581 nds32_freg = E_NDS32_FPU_REG_32SP_32DP;
3582 else if (strcmp (str, "1") == 0)
3583 nds32_freg = E_NDS32_FPU_REG_16SP_8DP;
3584 else if (strcmp (str, "0") == 0)
3585 nds32_freg = E_NDS32_FPU_REG_8SP_4DP;
3586 else
3588 /* Logic here rejects the input FPU configuration. */
3589 as_bad (_("unknown FPU configuration `%s'\n"), str);
3590 return 0;
3593 return 1;
3596 /* This function parse "abi=" specified. */
3598 static int
3599 nds32_parse_abi (const char *str)
3601 if (strcmp (str, "v2") == 0)
3602 nds32_abi = E_NDS_ABI_AABI;
3603 /* Obsolete. */
3604 else if (strcmp (str, "v2fp") == 0)
3605 nds32_abi = E_NDS_ABI_V2FP;
3606 else if (strcmp (str, "v1") == 0)
3607 nds32_abi = E_NDS_ABI_V1;
3608 else if (strcmp (str,"v2fpp") == 0)
3609 nds32_abi = E_NDS_ABI_V2FP_PLUS;
3610 else
3612 /* Logic here rejects the input abi version. */
3613 as_bad (_("unknown ABI version`%s'\n"), str);
3614 return 0;
3617 return 1;
3620 /* This function turn on all extensions and instructions support. */
3622 static int
3623 nds32_all_ext (void)
3625 nds32_mac = 1;
3626 nds32_div = 1;
3627 nds32_dx_regs = 1;
3628 nds32_16bit_ext = 1;
3629 nds32_perf_ext = 1;
3630 nds32_perf_ext2 = 1;
3631 nds32_string_ext = 1;
3632 nds32_audio_ext = 1;
3633 nds32_fpu_fma = 1;
3634 nds32_fpu_sp_ext = 1;
3635 nds32_fpu_dp_ext = 1;
3636 nds32_dsp_ext = 1;
3637 nds32_zol_ext = 1;
3638 /* Turn off reduced register. */
3639 nds32_gpr16 = 0;
3641 return 1;
3644 /* GAS will call md_parse_option whenever getopt returns an unrecognized code,
3645 presumably indicating a special code value which appears in md_longopts.
3646 This function should return non-zero if it handled the option and zero
3647 otherwise. There is no need to print a message about an option not being
3648 recognized. This will be handled by the generic code. */
3651 nds32_parse_option (int c, const char *arg)
3653 struct nds32_parse_option_table *coarse_tune;
3654 struct nds32_set_option_table *fine_tune;
3655 const char *ptr_arg = NULL;
3657 switch (c)
3659 case OPTION_OPTIMIZE:
3660 optimize = 1;
3661 optimize_for_space = 0;
3662 break;
3663 case OPTION_OPTIMIZE_SPACE:
3664 optimize = 0;
3665 optimize_for_space = 1;
3666 break;
3667 case OPTION_BIG:
3668 target_big_endian = 1;
3669 break;
3670 case OPTION_LITTLE:
3671 target_big_endian = 0;
3672 break;
3673 case OPTION_TURBO:
3674 nds32_all_ext ();
3675 break;
3676 case OPTION_PIC:
3677 nds32_pic = 1;
3678 break;
3679 case OPTION_RELAX_FP_AS_GP_OFF:
3680 nds32_relax_fp_as_gp = 0;
3681 break;
3682 case OPTION_RELAX_B2BB_ON:
3683 nds32_relax_b2bb = 1;
3684 break;
3685 case OPTION_RELAX_ALL_OFF:
3686 nds32_relax_all = 0;
3687 break;
3688 default:
3689 /* Determination of which option table to search for to save time. */
3690 if (!arg)
3691 return 0;
3693 ptr_arg = strchr (arg, '=');
3695 if (ptr_arg)
3697 /* Find the value after '='. */
3698 if (ptr_arg != NULL)
3699 ptr_arg++;
3700 for (coarse_tune = parse_opts; coarse_tune->name != NULL; coarse_tune++)
3702 if (strncmp (arg, coarse_tune->name, (ptr_arg - arg)) == 0)
3704 coarse_tune->func (ptr_arg);
3705 return 1;
3709 else
3711 int disable = 0;
3713 /* Filter out the Disable option first. */
3714 if (startswith (arg, "no-"))
3716 disable = 1;
3717 arg += 3;
3720 for (fine_tune = toggle_opts; fine_tune->name != NULL; fine_tune++)
3722 if (strcmp (arg, fine_tune->name) == 0)
3724 if (fine_tune->var != NULL)
3725 *fine_tune->var = (disable) ? 0 : 1;
3726 return 1;
3730 /* Nothing match. */
3731 return 0;
3734 return 1;
3737 /* tc_check_label */
3739 void
3740 nds32_check_label (symbolS *label ATTRIBUTE_UNUSED)
3742 /* The code used to create BB is move to frob_label.
3743 They should go there. */
3746 static void
3747 set_endian_little (int on)
3749 target_big_endian = !on;
3752 /* These functions toggles the generation of 16-bit. First encounter signals
3753 the beginning of not generating 16-bit instructions and next encounter
3754 signals the restoring back to default behavior. */
3756 static void
3757 trigger_16bit (int trigger)
3759 enable_16bit = trigger;
3762 static int backup_16bit_mode;
3763 static void
3764 restore_16bit (int no_use ATTRIBUTE_UNUSED)
3766 enable_16bit = backup_16bit_mode;
3769 static void
3770 off_16bit (int no_use ATTRIBUTE_UNUSED)
3772 backup_16bit_mode = enable_16bit;
3773 enable_16bit = 0;
3776 /* Built-in segments for small object. */
3777 typedef struct nds32_seg_entryT
3779 segT s;
3780 const char *name;
3781 flagword flags;
3782 } nds32_seg_entry;
3784 nds32_seg_entry nds32_seg_table[] =
3786 {NULL, ".sdata_f", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3787 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3788 {NULL, ".sdata_b", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3789 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3790 {NULL, ".sdata_h", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3791 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3792 {NULL, ".sdata_w", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3793 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3794 {NULL, ".sdata_d", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3795 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3796 {NULL, ".sbss_f", SEC_ALLOC | SEC_SMALL_DATA},
3797 {NULL, ".sbss_b", SEC_ALLOC | SEC_SMALL_DATA},
3798 {NULL, ".sbss_h", SEC_ALLOC | SEC_SMALL_DATA},
3799 {NULL, ".sbss_w", SEC_ALLOC | SEC_SMALL_DATA},
3800 {NULL, ".sbss_d", SEC_ALLOC | SEC_SMALL_DATA}
3803 /* Indexes to nds32_seg_table[]. */
3804 enum NDS32_SECTIONS_ENUM
3806 SDATA_F_SECTION = 0,
3807 SDATA_B_SECTION = 1,
3808 SDATA_H_SECTION = 2,
3809 SDATA_W_SECTION = 3,
3810 SDATA_D_SECTION = 4,
3811 SBSS_F_SECTION = 5,
3812 SBSS_B_SECTION = 6,
3813 SBSS_H_SECTION = 7,
3814 SBSS_W_SECTION = 8,
3815 SBSS_D_SECTION = 9
3818 /* The following code is borrowed from v850_seg. Revise this is needed. */
3820 static void
3821 do_nds32_seg (int i, subsegT sub)
3823 nds32_seg_entry *seg = nds32_seg_table + i;
3825 obj_elf_section_change_hook ();
3827 if (seg->s != NULL)
3828 subseg_set (seg->s, sub);
3829 else
3831 seg->s = subseg_new (seg->name, sub);
3832 if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
3834 bfd_set_section_flags (seg->s, seg->flags);
3835 if ((seg->flags & SEC_LOAD) == 0)
3836 seg_info (seg->s)->bss = 1;
3841 static void
3842 nds32_seg (int i)
3844 subsegT sub = get_absolute_expression ();
3846 do_nds32_seg (i, sub);
3847 demand_empty_rest_of_line ();
3850 /* Set if label adjustment is needed. I should not adjust .xbyte in dwarf. */
3851 static symbolS *nds32_last_label; /* Last label for alignment. */
3853 static void
3854 add_mapping_symbol_for_align (int shift, valueT addr, int is_data_align)
3856 if ((shift > 1) && (addr & 1))
3858 int n = (1 << shift) - 1;
3859 if (!is_data_align)
3860 add_mapping_symbol (MAP_CODE, 1, 0);
3861 else if ((int) (addr & n) != n)
3862 add_mapping_symbol (MAP_CODE, 1, 0);
3864 else if ((shift > 1) && ((int) (addr & 1) == 0))
3865 add_mapping_symbol (MAP_CODE, 0, 0);
3868 /* This code is referred from D30V for adjust label to be with pending
3869 alignment. For example,
3870 LBYTE: .byte 0x12
3871 LHALF: .half 0x12
3872 LWORD: .word 0x12
3873 Without this, the above label will not attach to incoming data. */
3875 static void
3876 nds32_adjust_label (int n)
3878 /* FIXME: I think adjust label and alignment is
3879 the programmer's obligation. Sadly, VLSI team doesn't
3880 properly use .align for their test cases.
3881 So I re-implement cons_align and auto adjust labels, again.
3883 I think d30v's implementation is simple and good enough. */
3885 symbolS *label = nds32_last_label;
3886 nds32_last_label = NULL;
3888 /* SEC_ALLOC is used to eliminate .debug_ sections.
3889 SEC_CODE is used to include section for ILM. */
3890 if (((now_seg->flags & SEC_ALLOC) == 0 && (now_seg->flags & SEC_CODE) == 0)
3891 || strcmp (now_seg->name, ".eh_frame") == 0
3892 || strcmp (now_seg->name, ".gcc_except_table") == 0)
3893 return;
3895 /* Only frag by alignment when needed.
3896 Otherwise, it will fail to optimize labels on 4-byte boundary. (bug8454)
3897 See md_convert_frag () and RELAX_SET_RELAXABLE (frag) for details. */
3898 if (frag_now_fix () & ((1 << n) -1 ))
3900 if (subseg_text_p (now_seg))
3902 add_mapping_symbol_for_align (n, frag_now_fix (), 1);
3903 frag_align_code (n, 0);
3905 else
3906 frag_align (n, 0, 0);
3908 /* Record the minimum alignment for this segment. */
3909 record_alignment (now_seg, n - OCTETS_PER_BYTE_POWER);
3912 if (label != NULL)
3914 symbolS *sym;
3915 int label_seen = false;
3916 struct frag *old_frag;
3917 valueT old_value, new_value;
3919 gas_assert (S_GET_SEGMENT (label) == now_seg);
3921 old_frag = symbol_get_frag (label);
3922 old_value = S_GET_VALUE (label);
3923 new_value = (valueT) frag_now_fix ();
3925 /* Multiple labels may be on the same address. And the last symbol
3926 may not be a label at all, e.g., register name, external function names,
3927 so I have to track the last label in tc_frob_label instead of
3928 just using symbol_lastP. */
3929 for (sym = symbol_lastP; sym != NULL; sym = symbol_previous (sym))
3931 if (symbol_get_frag (sym) == old_frag
3932 && S_GET_VALUE (sym) == old_value)
3934 /* Warning HERE! */
3935 label_seen = true;
3936 symbol_set_frag (sym, frag_now);
3937 S_SET_VALUE (sym, new_value);
3939 else if (label_seen && symbol_get_frag (sym) != old_frag)
3940 break;
3945 void
3946 nds32_cons_align (int size ATTRIBUTE_UNUSED)
3948 /* Do nothing here.
3949 This is called before `md_flush_pending_output' is called by `cons'.
3951 There are two things should be done for auto-adjust-label.
3952 1. Align data/instructions and adjust label to be attached to them.
3953 2. Clear auto-adjust state, so incoming data/instructions will not
3954 adjust the label.
3956 For example,
3957 .byte 0x1
3958 .L0:
3959 .word 0x2
3960 .word 0x3
3961 in this case, '.word 0x2' will adjust the label, .L0, but '.word 0x3' should not.
3963 I think `md_flush_pending_output' is a good place to clear the auto-adjust state,
3964 but it is also called by `cons' before this function.
3965 To simplify the code, instead of overriding .zero, .fill, .space, etc,
3966 I think we should just adjust label in `nds32_aligned_X_cons' instead of here. */
3969 static void
3970 make_mapping_symbol (enum mstate state, valueT value, fragS * frag, unsigned int align)
3972 symbolS *symbol_p = NULL;
3973 const char *symbol_name = NULL;
3974 switch (state)
3976 case MAP_DATA:
3977 if (align == 0)
3978 symbol_name = "$d0";
3979 else if (align == 1)
3980 symbol_name = "$d1";
3981 else if (align == 2)
3982 symbol_name = "$d2";
3983 else if (align == 3)
3984 symbol_name = "$d3";
3985 else if (align == 4)
3986 symbol_name = "$d4";
3987 break;
3988 case MAP_CODE:
3989 symbol_name = "$c";
3990 break;
3991 default:
3992 abort ();
3995 symbol_p = symbol_new (symbol_name, now_seg, frag, value);
3996 /* local scope attribute */
3997 symbol_get_bfdsym (symbol_p)->flags |= BSF_NO_FLAGS | BSF_LOCAL;
4000 static void
4001 add_mapping_symbol (enum mstate state, unsigned int padding_byte,
4002 unsigned int align)
4004 enum mstate current_mapping_state =
4005 seg_info (now_seg)->tc_segment_info_data.mapstate;
4007 if (state == MAP_CODE
4008 && current_mapping_state == state)
4009 return;
4011 if (!SEG_NORMAL (now_seg)
4012 || !subseg_text_p (now_seg))
4013 return;
4015 /* start adding mapping symbol */
4016 seg_info (now_seg)->tc_segment_info_data.mapstate = state;
4017 make_mapping_symbol (state, (valueT) frag_now_fix () + padding_byte,
4018 frag_now, align);
4021 static void
4022 nds32_aligned_cons (int idx)
4024 nds32_adjust_label (idx);
4025 add_mapping_symbol (MAP_DATA, 0, idx);
4026 /* Call default handler. */
4027 cons (1 << idx);
4028 if (now_seg->flags & SEC_CODE
4029 && now_seg->flags & SEC_ALLOC && now_seg->flags & SEC_RELOC)
4031 /* Use BFD_RELOC_NDS32_DATA to avoid linker
4032 optimization replacing data. */
4033 expressionS exp;
4035 exp.X_add_number = 0;
4036 exp.X_op = O_constant;
4037 fix_new_exp (frag_now, frag_now_fix () - (1 << idx), 1 << idx,
4038 &exp, 0, BFD_RELOC_NDS32_DATA);
4042 /* `.double' directive. */
4044 static void
4045 nds32_aligned_float_cons (int type)
4047 switch (type)
4049 case 'f':
4050 case 'F':
4051 case 's':
4052 case 'S':
4053 nds32_adjust_label (2);
4054 break;
4055 case 'd':
4056 case 'D':
4057 case 'r':
4058 case 'R':
4059 nds32_adjust_label (4);
4060 break;
4061 default:
4062 as_bad ("Unrecognized float type, %c\n", (char)type);
4064 /* Call default handler. */
4065 float_cons (type);
4068 static void
4069 nds32_enable_pic (int ignore ATTRIBUTE_UNUSED)
4071 /* Another way to do -mpic.
4072 This is for GCC internal use and should always be first line
4073 of code, otherwise, the effect is not determined. */
4074 nds32_pic = 1;
4077 static void
4078 nds32_set_abi (int ver)
4080 nds32_abi = ver;
4083 /* Relax directive to set relocation R_NDS32_RELAX_ENTRY value. */
4085 static void
4086 nds32_relax_relocs (int relax)
4088 char saved_char;
4089 char *name;
4090 int i;
4091 const char *subtype_relax[] =
4092 {"", "",};
4094 name = input_line_pointer;
4095 while (*input_line_pointer && !ISSPACE (*input_line_pointer))
4096 input_line_pointer++;
4097 saved_char = *input_line_pointer;
4098 *input_line_pointer = 0;
4100 for (i = 0; i < (int) ARRAY_SIZE (subtype_relax); i++)
4102 if (strcmp (name, subtype_relax[i]) == 0)
4104 switch (i)
4106 case 0:
4107 case 1:
4108 enable_relax_relocs = relax & enable_relax_relocs;
4109 break;
4110 default:
4111 break;
4113 break;
4116 *input_line_pointer = saved_char;
4117 ignore_rest_of_line ();
4120 /* Record which arguments register($r0 ~ $r5) is not used in callee.
4121 bit[i] for $ri */
4123 static void
4124 nds32_set_hint_func_args (int ignore ATTRIBUTE_UNUSED)
4126 ignore_rest_of_line ();
4129 /* Insert relocations to mark the begin and end of a fp-omitted function,
4130 for further relaxation use.
4131 bit[i] for $ri */
4133 static void
4134 nds32_omit_fp_begin (int mode)
4136 expressionS exp;
4138 if (nds32_relax_fp_as_gp == 0)
4139 return;
4140 exp.X_op = O_symbol;
4141 exp.X_add_symbol = abs_section_sym;
4142 if (mode == 1)
4144 in_omit_fp = 1;
4145 exp.X_add_number = R_NDS32_RELAX_REGION_OMIT_FP_FLAG;
4146 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
4147 BFD_RELOC_NDS32_RELAX_REGION_BEGIN);
4149 else
4151 in_omit_fp = 0;
4152 exp.X_add_number = R_NDS32_RELAX_REGION_OMIT_FP_FLAG;
4153 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
4154 BFD_RELOC_NDS32_RELAX_REGION_END);
4158 static void
4159 nds32_loop_begin (int mode)
4161 /* Insert loop region relocation here. */
4162 expressionS exp;
4164 exp.X_op = O_symbol;
4165 exp.X_add_symbol = abs_section_sym;
4166 if (mode == 1)
4168 exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG;
4169 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
4170 BFD_RELOC_NDS32_RELAX_REGION_BEGIN);
4172 else
4174 exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG;
4175 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
4176 BFD_RELOC_NDS32_RELAX_REGION_END);
4180 struct nds32_relocs_group
4182 struct nds32_relocs_pattern *pattern;
4183 struct nds32_relocs_group *next;
4186 static struct nds32_relocs_group *nds32_relax_hint_current = NULL;
4187 /* Used to reorder the id for ".relax_hint id". */
4188 static int relax_hint_bias = 0;
4189 /* Record current relax hint id. */
4190 static int relax_hint_id_current = -1;
4191 int reset_bias = 0;
4192 /* If ".relax_hint begin" is triggered? */
4193 int relax_hint_begin = 0;
4195 /* Record the reordered relax hint id. */
4197 struct relax_hint_id
4199 int old_id;
4200 int new_id;
4201 struct relax_hint_id *next;
4204 /* FIXME: Need to find somewhere to free the list. */
4205 struct relax_hint_id *record_id_head = NULL;
4207 /* Is the buffer large enough? */
4208 #define MAX_BUFFER 12
4210 static char *nds_itoa (int n);
4212 static char *
4213 nds_itoa (int n)
4215 char *buf = xmalloc (MAX_BUFFER * sizeof (char));
4216 snprintf (buf, MAX_BUFFER, "%d", n);
4217 return buf;
4220 /* Insert a relax hint. */
4222 static void
4223 nds32_relax_hint (int mode ATTRIBUTE_UNUSED)
4225 char *name = NULL;
4226 char saved_char;
4227 struct nds32_relocs_pattern *relocs = NULL;
4228 struct nds32_relocs_group *group, *new;
4229 struct relax_hint_id *record_id;
4231 name = input_line_pointer;
4232 while (*input_line_pointer && !ISSPACE (*input_line_pointer))
4233 input_line_pointer++;
4234 saved_char = *input_line_pointer;
4235 *input_line_pointer = 0;
4236 name = strdup (name);
4238 if (name && strcmp (name, "begin") == 0)
4240 if (relax_hint_id_current == -1)
4241 reset_bias = 1;
4242 relax_hint_bias++;
4243 relax_hint_id_current++;
4244 relax_hint_begin = 1;
4247 /* Original case ".relax_hint id". It's id may need to be reordered. */
4248 if (!relax_hint_begin)
4250 int tmp = strtol (name, NULL, 10);
4251 record_id = record_id_head;
4252 while (record_id)
4254 if (record_id->old_id == tmp)
4256 name = nds_itoa (record_id->new_id);
4257 goto reordered_id;
4259 record_id = record_id->next;
4261 if (reset_bias)
4263 relax_hint_bias = relax_hint_id_current - atoi (name) + 1;
4264 reset_bias = 0;
4266 relax_hint_id_current = tmp + relax_hint_bias;
4268 /* Insert the element to the head of the link list. */
4269 struct relax_hint_id *tmp_id = malloc (sizeof (struct relax_hint_id));
4270 tmp_id->old_id = tmp;
4271 tmp_id->new_id = relax_hint_id_current;
4272 tmp_id->next = record_id_head;
4273 record_id_head = tmp_id;
4276 if (name && strcmp (name, "end") == 0)
4277 relax_hint_begin = 0;
4278 name = nds_itoa (relax_hint_id_current);
4280 reordered_id:
4282 /* Find relax hint entry for next instruction, and all member will be
4283 initialized at that time. */
4284 relocs = str_hash_find (nds32_hint_hash, name);
4285 if (relocs == NULL)
4287 relocs = XNEW (struct nds32_relocs_pattern);
4288 memset (relocs, 0, sizeof (struct nds32_relocs_pattern));
4289 str_hash_insert (nds32_hint_hash, name, relocs, 0);
4291 else
4293 while (relocs->next)
4294 relocs=relocs->next;
4295 relocs->next = XNEW (struct nds32_relocs_pattern);
4296 relocs = relocs->next;
4297 memset (relocs, 0, sizeof (struct nds32_relocs_pattern));
4300 relocs->next = NULL;
4301 *input_line_pointer = saved_char;
4302 ignore_rest_of_line ();
4304 /* Get the final one of relax hint series. */
4306 /* It has to build this list because there are maybe more than one
4307 instructions relative to the same instruction. It to connect to
4308 next instruction after md_assemble. */
4309 new = XNEW (struct nds32_relocs_group);
4310 memset (new, 0, sizeof (struct nds32_relocs_group));
4311 new->pattern = relocs;
4312 new->next = NULL;
4313 group = nds32_relax_hint_current;
4314 if (!group)
4315 nds32_relax_hint_current = new;
4316 else
4318 while (group->next != NULL)
4319 group = group->next;
4320 group->next = new;
4322 relaxing = true;
4325 /* Decide the size of vector entries, only accepts 4 or 16 now. */
4327 static void
4328 nds32_vec_size (int ignore ATTRIBUTE_UNUSED)
4330 expressionS exp;
4332 expression (&exp);
4334 if (exp.X_op == O_constant)
4336 if (exp.X_add_number == 4 || exp.X_add_number == 16)
4338 if (vec_size == 0)
4339 vec_size = exp.X_add_number;
4340 else if (vec_size != exp.X_add_number)
4341 as_warn (_("Different arguments of .vec_size are found, "
4342 "previous %d, current %d"),
4343 (int) vec_size, (int) exp.X_add_number);
4345 else
4346 as_warn (_("Argument of .vec_size is expected 4 or 16, actual: %d."),
4347 (int) exp.X_add_number);
4349 else
4350 as_warn (_("Argument of .vec_size is not a constant."));
4353 /* The behavior of ".flag" directive varies depending on the target.
4354 In nds32 target, we use it to recognize whether this assembly content is
4355 generated by compiler. Other features can also be added in this function
4356 in the future. */
4358 static void
4359 nds32_flag (int ignore ATTRIBUTE_UNUSED)
4361 char *name;
4362 char saved_char;
4363 int i;
4364 const char *possible_flags[] = { "verbatim" };
4366 /* Skip whitespaces. */
4367 name = input_line_pointer;
4368 while (*input_line_pointer && !ISSPACE (*input_line_pointer))
4369 input_line_pointer++;
4370 saved_char = *input_line_pointer;
4371 *input_line_pointer = 0;
4373 for (i = 0; i < (int) ARRAY_SIZE (possible_flags); i++)
4375 if (strcmp (name, possible_flags[i]) == 0)
4377 switch (i)
4379 case 0:
4380 /* flag: verbatim */
4381 verbatim = 1;
4382 break;
4383 default:
4384 break;
4386 /* Already found the flag, no need to continue next loop. */
4387 break;
4391 *input_line_pointer = saved_char;
4392 ignore_rest_of_line ();
4395 static void
4396 ict_model (int ignore ATTRIBUTE_UNUSED)
4398 char *name;
4399 char saved_char;
4400 int i;
4401 const char *possible_flags[] = { "small", "large" };
4403 /* Skip whitespaces. */
4404 name = input_line_pointer;
4405 while (*input_line_pointer && !ISSPACE (*input_line_pointer))
4406 input_line_pointer++;
4407 saved_char = *input_line_pointer;
4408 *input_line_pointer = 0;
4410 for (i = 0; i < (int) ARRAY_SIZE (possible_flags); i++)
4412 if (strcmp (name, possible_flags[i]) == 0)
4414 switch (i)
4416 case 0:
4417 /* flag: verbatim */
4418 ict_flag = ICT_SMALL;
4419 break;
4420 case 1:
4421 ict_flag = ICT_LARGE;
4422 break;
4423 default:
4424 break;
4426 /* Already found the flag, no need to continue next loop. */
4427 break;
4431 *input_line_pointer = saved_char;
4432 ignore_rest_of_line ();
4435 static void
4436 nds32_n12hc (int ignore ATTRIBUTE_UNUSED)
4438 /* N1213HC core is used. */
4442 /* The target specific pseudo-ops which we support. */
4443 const pseudo_typeS md_pseudo_table[] =
4445 /* Forced alignment if declared these ways. */
4446 {"ascii", stringer, 8 + 0},
4447 {"asciz", stringer, 8 + 1},
4448 {"double", nds32_aligned_float_cons, 'd'},
4449 {"dword", nds32_aligned_cons, 3},
4450 {"float", nds32_aligned_float_cons, 'f'},
4451 {"half", nds32_aligned_cons, 1},
4452 {"hword", nds32_aligned_cons, 1},
4453 {"int", nds32_aligned_cons, 2},
4454 {"long", nds32_aligned_cons, 2},
4455 {"octa", nds32_aligned_cons, 4},
4456 {"quad", nds32_aligned_cons, 3},
4457 {"qword", nds32_aligned_cons, 4},
4458 {"short", nds32_aligned_cons, 1},
4459 {"byte", nds32_aligned_cons, 0},
4460 {"single", nds32_aligned_float_cons, 'f'},
4461 {"string", stringer, 8 + 1},
4462 {"word", nds32_aligned_cons, 2},
4464 {"little", set_endian_little, 1},
4465 {"big", set_endian_little, 0},
4466 {"16bit_on", trigger_16bit, 1},
4467 {"16bit_off", trigger_16bit, 0},
4468 {"restore_16bit", restore_16bit, 0},
4469 {"off_16bit", off_16bit, 0},
4471 {"sdata_d", nds32_seg, SDATA_D_SECTION},
4472 {"sdata_w", nds32_seg, SDATA_W_SECTION},
4473 {"sdata_h", nds32_seg, SDATA_H_SECTION},
4474 {"sdata_b", nds32_seg, SDATA_B_SECTION},
4475 {"sdata_f", nds32_seg, SDATA_F_SECTION},
4477 {"sbss_d", nds32_seg, SBSS_D_SECTION},
4478 {"sbss_w", nds32_seg, SBSS_W_SECTION},
4479 {"sbss_h", nds32_seg, SBSS_H_SECTION},
4480 {"sbss_b", nds32_seg, SBSS_B_SECTION},
4481 {"sbss_f", nds32_seg, SBSS_F_SECTION},
4483 {"pic", nds32_enable_pic, 0},
4484 {"n12_hc", nds32_n12hc, 0},
4485 {"abi_1", nds32_set_abi, E_NDS_ABI_V1},
4486 {"abi_2", nds32_set_abi, E_NDS_ABI_AABI},
4487 /* Obsolete. */
4488 {"abi_2fp", nds32_set_abi, E_NDS_ABI_V2FP},
4489 {"abi_2fp_plus", nds32_set_abi, E_NDS_ABI_V2FP_PLUS},
4490 {"relax", nds32_relax_relocs, 1},
4491 {"no_relax", nds32_relax_relocs, 0},
4492 {"hint_func_args", nds32_set_hint_func_args, 0}, /* Abandon?? */
4493 {"omit_fp_begin", nds32_omit_fp_begin, 1},
4494 {"omit_fp_end", nds32_omit_fp_begin, 0},
4495 {"vec_size", nds32_vec_size, 0},
4496 {"flag", nds32_flag, 0},
4497 {"innermost_loop_begin", nds32_loop_begin, 1},
4498 {"innermost_loop_end", nds32_loop_begin, 0},
4499 {"relax_hint", nds32_relax_hint, 0},
4500 {"ict_model", ict_model, 0},
4501 {NULL, NULL, 0}
4504 void
4505 nds32_pre_do_align (int n, char *fill, int len, int max)
4507 /* Only make a frag if we HAVE to... */
4508 fragS *fragP;
4509 if (n != 0 && !need_pass_2)
4511 if (fill == NULL)
4513 if (subseg_text_p (now_seg))
4515 dwarf2_emit_insn (0);
4516 fragP = frag_now;
4517 add_mapping_symbol_for_align (n, frag_now_fix (), 0);
4518 frag_align_code (n, max);
4520 /* Tag this alignment when there is a label before it. */
4521 if (label_exist)
4523 fragP->tc_frag_data.flag = NDS32_FRAG_LABEL;
4524 label_exist = 0;
4527 else
4528 frag_align (n, 0, max);
4530 else if (len <= 1)
4531 frag_align (n, *fill, max);
4532 else
4533 frag_align_pattern (n, fill, len, max);
4537 void
4538 nds32_do_align (int n)
4540 /* Optimize for space and label exists. */
4541 expressionS exp;
4543 /* FIXME:I think this will break debug info sections and except_table. */
4544 if (!enable_relax_relocs || !subseg_text_p (now_seg))
4545 return;
4547 /* Create and attach a BFD_RELOC_NDS32_LABEL fixup
4548 the size of instruction may not be correct because
4549 it could be relaxable. */
4550 exp.X_op = O_symbol;
4551 exp.X_add_symbol = section_symbol (now_seg);
4552 exp.X_add_number = n;
4553 fix_new_exp (frag_now,
4554 frag_now_fix (), 0, &exp, 0, BFD_RELOC_NDS32_LABEL);
4557 /* Supported Andes machines. */
4558 struct nds32_machs
4560 enum bfd_architecture bfd_mach;
4561 int mach_flags;
4564 /* This is the callback for nds32-asm.c to parse operands. */
4567 nds32_asm_parse_operand (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED,
4568 struct nds32_asm_insn *pinsn,
4569 char **pstr, int64_t *value)
4571 char *hold;
4572 expressionS *pexp = pinsn->info;
4574 hold = input_line_pointer;
4575 input_line_pointer = *pstr;
4576 expression (pexp);
4577 *pstr = input_line_pointer;
4578 input_line_pointer = hold;
4580 switch (pexp->X_op)
4582 case O_symbol:
4583 *value = 0;
4584 return NASM_R_SYMBOL;
4585 case O_constant:
4586 *value = pexp->X_add_number;
4587 return NASM_R_CONST;
4588 case O_illegal:
4589 case O_absent:
4590 case O_register:
4591 default:
4592 return NASM_R_ILLEGAL;
4596 /* GAS will call this function at the start of the assembly, after the command
4597 line arguments have been parsed and all the machine independent
4598 initializations have been completed. */
4600 void
4601 md_begin (void)
4603 const struct nds32_keyword *k;
4604 relax_info_t *relax_info;
4605 int flags = 0;
4607 bfd_set_arch_mach (stdoutput, TARGET_ARCH, nds32_baseline);
4609 nds32_init_nds32_pseudo_opcodes ();
4610 asm_desc.parse_operand = nds32_asm_parse_operand;
4611 if (nds32_gpr16)
4612 flags |= NASM_OPEN_REDUCED_REG;
4613 nds32_asm_init (&asm_desc, flags);
4615 /* Initial general purpose registers hash table. */
4616 nds32_gprs_hash = str_htab_create ();
4617 for (k = nds32_keyword_gpr; k->name; k++)
4618 str_hash_insert (nds32_gprs_hash, k->name, k, 0);
4620 /* Initial branch hash table. */
4621 nds32_relax_info_hash = str_htab_create ();
4622 for (relax_info = relax_table; relax_info->opcode; relax_info++)
4623 str_hash_insert (nds32_relax_info_hash, relax_info->opcode, relax_info, 0);
4625 /* Initial relax hint hash table. */
4626 nds32_hint_hash = str_htab_create ();
4627 enable_16bit = nds32_16bit_ext;
4630 /* HANDLE_ALIGN in write.c. */
4632 void
4633 nds32_handle_align (fragS *fragp)
4635 static const unsigned char nop16[] = { 0x92, 0x00 };
4636 static const unsigned char nop32[] = { 0x40, 0x00, 0x00, 0x09 };
4637 int bytes;
4638 char *p;
4640 if (fragp->fr_type != rs_align_code)
4641 return;
4643 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
4644 p = fragp->fr_literal + fragp->fr_fix;
4646 if (bytes & 1)
4648 *p++ = 0;
4649 bytes--;
4652 if (bytes & 2)
4654 expressionS exp_t;
4655 exp_t.X_op = O_symbol;
4656 exp_t.X_add_symbol = abs_section_sym;
4657 exp_t.X_add_number = R_NDS32_INSN16_CONVERT_FLAG;
4658 fix_new_exp (fragp, fragp->fr_fix, 2, &exp_t, 0,
4659 BFD_RELOC_NDS32_INSN16);
4660 memcpy (p, nop16, 2);
4661 p += 2;
4662 bytes -= 2;
4665 while (bytes >= 4)
4667 memcpy (p, nop32, 4);
4668 p += 4;
4669 bytes -= 4;
4672 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
4673 fragp->fr_fix += bytes;
4676 /* md_flush_pending_output */
4678 void
4679 nds32_flush_pending_output (void)
4681 nds32_last_label = NULL;
4684 void
4685 nds32_frob_label (symbolS *label)
4687 dwarf2_emit_label (label);
4690 /* TC_START_LABEL */
4693 nds32_start_label (int asmdone ATTRIBUTE_UNUSED, int secdone ATTRIBUTE_UNUSED)
4695 if (optimize && subseg_text_p (now_seg))
4696 label_exist = 1;
4697 return 1;
4700 /* TARGET_FORMAT */
4702 const char *
4703 nds32_target_format (void)
4705 #ifdef TE_LINUX
4706 if (target_big_endian)
4707 return "elf32-nds32be-linux";
4708 else
4709 return "elf32-nds32le-linux";
4710 #else
4711 if (target_big_endian)
4712 return "elf32-nds32be";
4713 else
4714 return "elf32-nds32le";
4715 #endif
4718 static enum nds32_br_range
4719 get_range_type (const struct nds32_field *field)
4721 gas_assert (field != NULL);
4723 if (field->bitpos != 0)
4724 return BR_RANGE_U4G;
4726 if (field->bitsize == 24 && field->shift == 1)
4727 return BR_RANGE_S16M;
4728 else if (field->bitsize == 16 && field->shift == 1)
4729 return BR_RANGE_S64K;
4730 else if (field->bitsize == 14 && field->shift == 1)
4731 return BR_RANGE_S16K;
4732 else if (field->bitsize == 8 && field->shift == 1)
4733 return BR_RANGE_S256;
4734 else
4735 return BR_RANGE_U4G;
4738 /* Save pseudo instruction relocation list. */
4740 static struct nds32_relocs_pattern*
4741 nds32_elf_save_pseudo_pattern (fixS* fixP, struct nds32_asm_insn *insn,
4742 char *out, symbolS *sym,
4743 struct nds32_relocs_pattern *reloc_ptr,
4744 fragS *fragP)
4746 struct nds32_opcode *opcode = insn->opcode;
4747 if (!reloc_ptr)
4748 reloc_ptr = XNEW (struct nds32_relocs_pattern);
4749 reloc_ptr->seg = now_seg;
4750 reloc_ptr->sym = sym;
4751 reloc_ptr->frag = fragP;
4752 reloc_ptr->frchain = frchain_now;
4753 reloc_ptr->fixP = fixP;
4754 reloc_ptr->opcode = opcode;
4755 reloc_ptr->where = out;
4756 reloc_ptr->insn = insn->insn;
4757 reloc_ptr->next = NULL;
4758 return reloc_ptr;
4761 /* Check X_md to transform relocation. */
4763 static fixS*
4764 nds32_elf_record_fixup_exp (fragS *fragP, const char *str,
4765 const struct nds32_field *fld,
4766 expressionS *pexp, char* out,
4767 struct nds32_asm_insn *insn)
4769 int reloc = -1;
4770 expressionS exp;
4771 fixS *fixP = NULL;
4773 /* Handle instruction relocation. */
4774 if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_HI20))
4776 /* Relocation for hi20 modifier. */
4777 switch (pexp->X_md)
4779 case BFD_RELOC_NDS32_GOTOFF: /* @GOTOFF */
4780 reloc = BFD_RELOC_NDS32_GOTOFF_HI20;
4781 break;
4782 case BFD_RELOC_NDS32_GOT20: /* @GOT */
4783 reloc = BFD_RELOC_NDS32_GOT_HI20;
4784 break;
4785 case BFD_RELOC_NDS32_25_PLTREL: /* @PLT */
4786 if (!nds32_pic)
4787 as_bad (_("Invalid PIC expression."));
4788 else
4789 reloc = BFD_RELOC_NDS32_PLT_GOTREL_HI20;
4790 break;
4791 case BFD_RELOC_NDS32_GOTPC20: /* _GLOBAL_OFFSET_TABLE_ */
4792 reloc = BFD_RELOC_NDS32_GOTPC_HI20;
4793 break;
4794 case BFD_RELOC_NDS32_TPOFF: /* @TPOFF */
4795 reloc = BFD_RELOC_NDS32_TLS_LE_HI20;
4796 break;
4797 case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */
4798 reloc = nds32_pic ? BFD_RELOC_NDS32_TLS_IEGP_HI20 : BFD_RELOC_NDS32_TLS_IE_HI20;
4799 break;
4800 case BFD_RELOC_NDS32_TLS_DESC: /* @TLSDESC */
4801 reloc = BFD_RELOC_NDS32_TLS_DESC_HI20;
4802 break;
4803 default: /* No suffix */
4804 if (nds32_pic)
4805 /* When the file is pic, the address must be offset to gp.
4806 It may define another relocation or use GOTOFF. */
4807 reloc = BFD_RELOC_NDS32_PLT_GOTREL_HI20;
4808 else
4809 reloc = BFD_RELOC_NDS32_HI20;
4810 break;
4812 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4813 insn->info, 0 /* pcrel */, reloc);
4815 else if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_LO12))
4817 /* Relocation for lo12 modifier. */
4818 if (fld->bitsize == 15 && fld->shift == 0)
4820 /* [ls]bi || ori */
4821 switch (pexp->X_md)
4823 case BFD_RELOC_NDS32_GOTOFF: /* @GOTOFF */
4824 reloc = BFD_RELOC_NDS32_GOTOFF_LO12;
4825 break;
4826 case BFD_RELOC_NDS32_GOT20: /* @GOT */
4827 reloc = BFD_RELOC_NDS32_GOT_LO12;
4828 break;
4829 case BFD_RELOC_NDS32_25_PLTREL: /* @PLT */
4830 if (!nds32_pic)
4831 as_bad (_("Invalid PIC expression."));
4832 else
4833 reloc = BFD_RELOC_NDS32_PLT_GOTREL_LO12;
4834 break;
4835 case BFD_RELOC_NDS32_GOTPC20: /* _GLOBAL_OFFSET_TABLE_ */
4836 reloc = BFD_RELOC_NDS32_GOTPC_LO12;
4837 break;
4838 case BFD_RELOC_NDS32_TPOFF: /* @TPOFF */
4839 reloc = BFD_RELOC_NDS32_TLS_LE_LO12;
4840 break;
4841 case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */
4842 reloc = nds32_pic ? BFD_RELOC_NDS32_TLS_IEGP_LO12 : BFD_RELOC_NDS32_TLS_IE_LO12;
4843 break;
4844 case BFD_RELOC_NDS32_TLS_DESC: /* @TLSDESC */
4845 reloc = BFD_RELOC_NDS32_TLS_DESC_LO12;
4846 break;
4847 default: /* No suffix */
4848 if (nds32_pic)
4849 /* When the file is pic, the address must be offset to gp.
4850 It may define another relocation or use GOTOFF. */
4851 reloc = BFD_RELOC_NDS32_PLT_GOTREL_LO12;
4852 else
4853 reloc = BFD_RELOC_NDS32_LO12S0;
4854 break;
4857 else if (fld->bitsize == 15 && fld->shift == 1)
4858 reloc = BFD_RELOC_NDS32_LO12S1; /* [ls]hi */
4859 else if (fld->bitsize == 15 && fld->shift == 2)
4861 /* [ls]wi */
4862 switch (pexp->X_md)
4864 case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */
4865 reloc = nds32_pic ? BFD_RELOC_NDS32_TLS_IEGP_LO12S2 : BFD_RELOC_NDS32_TLS_IE_LO12S2;
4866 break;
4867 default: /* No suffix */
4868 reloc = BFD_RELOC_NDS32_LO12S2;
4869 break;
4872 else if (fld->bitsize == 15 && fld->shift == 3)
4873 reloc = BFD_RELOC_NDS32_LO12S3; /* [ls]di */
4874 else if (fld->bitsize == 12 && fld->shift == 2)
4875 reloc = BFD_RELOC_NDS32_LO12S2_SP; /* f[ls][sd]i */
4877 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4878 insn->info, 0 /* pcrel */, reloc);
4880 else if (fld && fld->bitpos == 0 && insn->opcode->isize == 4
4881 && (insn->attr & NASM_ATTR_PCREL))
4883 /* Relocation for 32-bit branch instructions. */
4884 if (fld->bitsize == 24 && fld->shift == 1)
4885 reloc = BFD_RELOC_NDS32_25_PCREL;
4886 else if (fld->bitsize == 16 && fld->shift == 1)
4887 reloc = BFD_RELOC_NDS32_17_PCREL;
4888 else if (fld->bitsize == 14 && fld->shift == 1)
4889 reloc = BFD_RELOC_NDS32_15_PCREL;
4890 else if (fld->bitsize == 8 && fld->shift == 1)
4891 reloc = BFD_RELOC_NDS32_WORD_9_PCREL;
4892 else
4893 abort ();
4895 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4896 insn->info, 1 /* pcrel */, reloc);
4898 else if (fld && fld->bitpos == 0 && insn->opcode->isize == 4
4899 && (insn->attr & NASM_ATTR_GPREL))
4901 /* Relocation for 32-bit gp-relative instructions. */
4902 if (fld->bitsize == 19 && fld->shift == 0)
4903 reloc = BFD_RELOC_NDS32_SDA19S0;
4904 else if (fld->bitsize == 18 && fld->shift == 1)
4905 reloc = BFD_RELOC_NDS32_SDA18S1;
4906 else if (fld->bitsize == 17 && fld->shift == 2)
4907 reloc = BFD_RELOC_NDS32_SDA17S2;
4908 else
4909 abort ();
4911 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4912 insn->info, 0 /* pcrel */, reloc);
4913 /* Insert INSN16 for converting fp_as_gp. */
4914 exp.X_op = O_symbol;
4915 exp.X_add_symbol = abs_section_sym;
4916 exp.X_add_number = 0;
4917 if (in_omit_fp && reloc == BFD_RELOC_NDS32_SDA17S2)
4918 fix_new_exp (fragP, out - fragP->fr_literal,
4919 insn->opcode->isize, &exp, 0 /* pcrel */,
4920 BFD_RELOC_NDS32_INSN16);
4922 else if (fld && fld->bitpos == 0 && insn->opcode->isize == 2
4923 && (insn->attr & NASM_ATTR_PCREL))
4925 /* Relocation for 16-bit branch instructions. */
4926 if (fld->bitsize == 8 && fld->shift == 1)
4927 reloc = BFD_RELOC_NDS32_9_PCREL;
4928 else
4929 abort ();
4931 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4932 insn->info, 1 /* pcrel */, reloc);
4934 else if (fld)
4935 as_bad (_("Don't know how to handle this field. %s"), str);
4937 return fixP;
4940 /* Build instruction pattern to relax. There are two type group pattern
4941 including pseudo instruction and relax hint. */
4943 static void
4944 nds32_elf_build_relax_relation (fixS *fixP, expressionS *pexp, char* out,
4945 struct nds32_asm_insn *insn, fragS *fragP,
4946 const struct nds32_field *fld,
4947 bool pseudo_hint)
4949 struct nds32_relocs_pattern *reloc_ptr;
4950 struct nds32_relocs_group *group;
4951 symbolS *sym = NULL;
4953 /* The expression may be used uninitialized. */
4954 if (fld)
4955 sym = pexp->X_add_symbol;
4957 if (pseudo_hint)
4959 /* We cannot know how many instructions will be expanded for
4960 the pseudo instruction here. The first expanded instruction fills
4961 the memory created by relax_hint. The follower will created and link
4962 here. */
4963 group = nds32_relax_hint_current;
4964 while (group)
4966 if (group->pattern->opcode == NULL)
4967 nds32_elf_save_pseudo_pattern (fixP, insn, out, sym,
4968 group->pattern, fragP);
4969 else
4971 group->pattern->next =
4972 nds32_elf_save_pseudo_pattern (fixP, insn, out, sym,
4973 NULL, fragP);
4974 group->pattern = group->pattern->next;
4976 group = group->next;
4979 else if (pseudo_opcode)
4981 /* Save instruction relation for pseudo instruction expanding pattern. */
4982 reloc_ptr = nds32_elf_save_pseudo_pattern (fixP, insn, out, sym,
4983 NULL, fragP);
4984 if (!relocs_list)
4985 relocs_list = reloc_ptr;
4986 else
4988 struct nds32_relocs_pattern *temp = relocs_list;
4989 while (temp->next)
4990 temp = temp->next;
4991 temp->next = reloc_ptr;
4994 else if (nds32_relax_hint_current)
4996 /* Save instruction relation by relax hint. */
4997 group = nds32_relax_hint_current;
4998 while (group)
5000 nds32_elf_save_pseudo_pattern (fixP, insn, out, sym,
5001 group->pattern, fragP);
5002 group = group->next;
5003 free (nds32_relax_hint_current);
5004 nds32_relax_hint_current = group;
5008 /* Set relaxing false only for relax_hint trigger it. */
5009 if (!pseudo_opcode)
5010 relaxing = false;
5013 #define N32_MEM_EXT(insn) ((N32_OP6_MEM << 25) | insn)
5015 /* Relax pattern for link time relaxation. */
5016 /* Relaxation types only! relocation types are not necessary. */
5017 /* Refer to nds32_elf_record_fixup_exp (). */
5019 static struct nds32_relax_hint_table relax_ls_table[] =
5022 /* LA and Floating LSI. */
5023 .main_type = NDS32_RELAX_HINT_LA_FLSI,
5024 .relax_code_size = 12,
5025 .relax_code_seq =
5027 OP6 (SETHI),
5028 OP6 (ORI),
5029 OP6 (LBI),
5031 .relax_fixup =
5033 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5034 {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
5035 {4, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5036 {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_LSI},
5037 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5038 {8, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5039 {0, 0, 0, 0}
5043 /* Load Address / Load-Store (LALS). */
5044 .main_type = NDS32_RELAX_HINT_LALS,
5045 .relax_code_size = 12,
5046 .relax_code_seq =
5048 OP6 (SETHI),
5049 OP6 (ORI),
5050 OP6 (LBI),
5052 .relax_fixup =
5054 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5055 {4, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5056 {8, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5057 {0, 0, 0, 0}
5061 /* B(AL) symbol@PLT */
5062 .main_type = NDS32_RELAX_HINT_LA_PLT,
5063 .relax_code_size = 16,
5064 .relax_code_seq =
5066 OP6 (SETHI),
5067 OP6 (ORI),
5068 OP6 (ALU1),
5069 OP6 (JREG),
5071 .relax_fixup =
5073 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5074 {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
5075 {8, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
5076 {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PLT_GOT_SUFF},
5077 {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5078 {12, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5079 {0, 0, 0, 0}
5083 /* LA (@GOT). */
5084 .main_type = NDS32_RELAX_HINT_LA_GOT,
5085 .relax_code_size = 12,
5086 .relax_code_seq =
5088 OP6 (SETHI),
5089 OP6 (ORI),
5090 OP6 (MEM),
5092 .relax_fixup =
5094 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5095 {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
5096 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5097 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_GOT_SUFF},
5098 {0, 0, 0, 0}
5102 /* LA (@GOTOFF). */
5103 .main_type = NDS32_RELAX_HINT_LA_GOTOFF,
5104 .relax_code_size = 16,
5105 .relax_code_seq =
5107 OP6 (SETHI),
5108 OP6 (ORI),
5109 OP6 (ALU1),
5110 OP6 (MEM),
5112 .relax_fixup =
5114 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5115 {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
5116 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5117 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_GOTOFF_SUFF},
5118 {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5119 {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_GOTOFF_SUFF},
5120 {0, 0, 0, 0}
5124 /* TLS LE LS|LA */
5125 .main_type = NDS32_RELAX_HINT_TLS_LE_LS,
5126 .relax_code_size = 16,
5127 .relax_code_seq =
5129 OP6(SETHI),
5130 OP6(ORI),
5131 OP6(MEM),
5132 OP6(ALU1),
5134 .relax_fixup =
5136 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5137 {4, 4, NDS32_HINT | NDS32_PTR_MULTIPLE, BFD_RELOC_NDS32_PTR},
5138 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5139 {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_LE_LS},
5140 {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5141 {12, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_LE_ADD},
5142 {0, 0, 0, 0}
5146 /* TLS IE LA */
5147 .main_type = NDS32_RELAX_HINT_TLS_IE_LA,
5148 .relax_code_size = 8,
5149 .relax_code_seq =
5151 OP6(SETHI),
5152 OP6(LBI),
5154 .relax_fixup =
5156 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5157 {4, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5158 {0, 0, 0, 0}
5162 /* TLS IEGP LA */
5163 .main_type = NDS32_RELAX_HINT_TLS_IEGP_LA,
5164 .relax_code_size = 12,
5165 .relax_code_seq =
5167 OP6 (SETHI),
5168 OP6 (ORI),
5169 OP6 (MEM),
5171 .relax_fixup =
5173 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5174 {4, 4, NDS32_HINT | NDS32_PTR_PATTERN, BFD_RELOC_NDS32_PTR},
5175 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5176 {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_IEGP_LW},
5177 {0, 0, 0, 0}
5181 /* TLS DESC LS: */
5182 .main_type = NDS32_RELAX_HINT_TLS_DESC_LS,
5183 .relax_code_size = 24,
5184 .relax_code_seq =
5186 OP6 (SETHI),
5187 OP6 (ORI),
5188 OP6 (ALU1),
5189 OP6 (LBI), /* load argument */
5190 OP6 (JREG),
5191 OP6 (MEM), /* load/store variable or load argument */
5193 .relax_fixup =
5195 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5196 {4, 4, NDS32_HINT | NDS32_PTR_PATTERN, BFD_RELOC_NDS32_PTR},
5197 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5198 {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_DESC_ADD},
5199 {12, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_DESC_FUNC},
5200 {16, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_DESC_CALL},
5201 {20, 4, NDS32_HINT | NDS32_SYM_DESC_MEM, BFD_RELOC_NDS32_TLS_DESC_MEM},
5202 {0, 0, 0, 0}
5206 .main_type = 0,
5207 .relax_code_seq = {0},
5208 .relax_fixup = {{0, 0 , 0, 0}}
5212 /* Since sethi loadstore relocation has to using next instruction to determine
5213 elimination itself or not, we have to return the next instruction range. */
5215 static int
5216 nds32_elf_sethi_range (struct nds32_relocs_pattern *pattern)
5218 int range = 0;
5219 while (pattern)
5221 switch (pattern->opcode->value)
5223 case INSN_LBI:
5224 case INSN_SBI:
5225 case INSN_LBSI:
5226 case N32_MEM_EXT (N32_MEM_LB):
5227 case N32_MEM_EXT (N32_MEM_LBS):
5228 case N32_MEM_EXT (N32_MEM_SB):
5229 range = NDS32_LOADSTORE_BYTE;
5230 break;
5231 case INSN_LHI:
5232 case INSN_SHI:
5233 case INSN_LHSI:
5234 case N32_MEM_EXT (N32_MEM_LH):
5235 case N32_MEM_EXT (N32_MEM_LHS):
5236 case N32_MEM_EXT (N32_MEM_SH):
5237 range = NDS32_LOADSTORE_HALF;
5238 break;
5239 case INSN_LWI:
5240 case INSN_SWI:
5241 case N32_MEM_EXT (N32_MEM_LW):
5242 case N32_MEM_EXT (N32_MEM_SW):
5243 range = NDS32_LOADSTORE_WORD;
5244 break;
5245 case INSN_FLSI:
5246 case INSN_FSSI:
5247 range = NDS32_LOADSTORE_FLOAT_S;
5248 break;
5249 case INSN_FLDI:
5250 case INSN_FSDI:
5251 range = NDS32_LOADSTORE_FLOAT_D;
5252 break;
5253 case INSN_ORI:
5254 range = NDS32_LOADSTORE_IMM;
5255 break;
5256 default:
5257 range = NDS32_LOADSTORE_NONE;
5258 break;
5260 if (range != NDS32_LOADSTORE_NONE)
5261 break;
5262 pattern = pattern->next;
5264 return range;
5267 /* The args means: instruction size, the 1st instruction is converted to 16 or
5268 not, optimize option, 16 bit instruction is enable. */
5270 #define SET_ADDEND(size, convertible, optimize, insn16_on) \
5271 (((size) & 0xff) | ((convertible) ? 1u << 31 : 0) \
5272 | ((optimize) ? 1 << 30 : 0) | (insn16_on ? 1 << 29 : 0))
5273 #define MAC_COMBO (E_NDS32_HAS_FPU_MAC_INST|E_NDS32_HAS_MAC_DX_INST)
5275 static void
5276 nds32_set_elf_flags_by_insn (struct nds32_asm_insn * insn)
5278 static int skip_flags = NASM_ATTR_FPU_FMA
5279 | NASM_ATTR_BRANCH | NASM_ATTR_SATURATION_EXT
5280 | NASM_ATTR_GPREL | NASM_ATTR_DXREG
5281 | NASM_ATTR_ISA_V1 | NASM_ATTR_ISA_V2
5282 | NASM_ATTR_ISA_V3 | NASM_ATTR_ISA_V3M
5283 | NASM_ATTR_PCREL;
5285 int new_flags = insn->opcode->attr & ~skip_flags;
5286 while (new_flags)
5288 int next = 1 << (ffs (new_flags) - 1);
5289 new_flags &= ~next;
5290 switch (next)
5292 case NASM_ATTR_PERF_EXT:
5294 if (nds32_perf_ext)
5296 nds32_elf_flags |= E_NDS32_HAS_EXT_INST;
5297 skip_flags |= NASM_ATTR_PERF_EXT;
5299 else
5300 as_bad (_("instruction %s requires enabling performance "
5301 "extension"), insn->opcode->opcode);
5303 break;
5304 case NASM_ATTR_PERF2_EXT:
5306 if (nds32_perf_ext2)
5308 nds32_elf_flags |= E_NDS32_HAS_EXT2_INST;
5309 skip_flags |= NASM_ATTR_PERF2_EXT;
5311 else
5312 as_bad (_("instruction %s requires enabling performance "
5313 "extension II"), insn->opcode->opcode);
5315 break;
5316 case NASM_ATTR_AUDIO_ISAEXT:
5318 if (nds32_audio_ext)
5320 nds32_elf_flags |= E_NDS32_HAS_AUDIO_INST;
5321 skip_flags |= NASM_ATTR_AUDIO_ISAEXT;
5323 else
5324 as_bad (_("instruction %s requires enabling AUDIO extension"),
5325 insn->opcode->opcode);
5327 break;
5328 case NASM_ATTR_STR_EXT:
5330 if (nds32_string_ext)
5332 nds32_elf_flags |= E_NDS32_HAS_STRING_INST;
5333 skip_flags |= NASM_ATTR_STR_EXT;
5335 else
5336 as_bad (_("instruction %s requires enabling STRING extension"),
5337 insn->opcode->opcode);
5339 break;
5340 case NASM_ATTR_DIV:
5342 if (insn->opcode->attr & NASM_ATTR_DXREG)
5344 if (nds32_div && nds32_dx_regs)
5346 nds32_elf_flags |= E_NDS32_HAS_DIV_DX_INST;
5347 skip_flags |= NASM_ATTR_DIV;
5349 else
5350 as_bad (_("instruction %s requires enabling DIV & DX_REGS "
5351 "extension"), insn->opcode->opcode);
5354 break;
5355 case NASM_ATTR_FPU:
5357 if (nds32_fpu_sp_ext || nds32_fpu_dp_ext)
5359 if (!(nds32_elf_flags
5360 & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST)))
5361 nds32_fpu_com = 1;
5362 skip_flags |= NASM_ATTR_FPU;
5364 else
5365 as_bad (_("instruction %s requires enabling FPU extension"),
5366 insn->opcode->opcode);
5368 break;
5369 case NASM_ATTR_FPU_SP_EXT:
5371 if (nds32_fpu_sp_ext)
5373 nds32_elf_flags |= E_NDS32_HAS_FPU_INST;
5374 skip_flags |= NASM_ATTR_FPU_SP_EXT;
5376 else
5377 as_bad (_("instruction %s requires enabling FPU_SP extension"),
5378 insn->opcode->opcode);
5380 break;
5381 case NASM_ATTR_FPU_DP_EXT:
5383 if (nds32_fpu_dp_ext)
5385 nds32_elf_flags |= E_NDS32_HAS_FPU_DP_INST;
5386 skip_flags |= NASM_ATTR_FPU_DP_EXT;
5388 else
5389 as_bad (_("instruction %s requires enabling FPU_DP extension"),
5390 insn->opcode->opcode);
5392 break;
5393 case NASM_ATTR_MAC:
5395 if (insn->opcode->attr & NASM_ATTR_FPU_SP_EXT)
5397 if (nds32_fpu_sp_ext && nds32_mac)
5398 nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST;
5399 else
5400 as_bad (_("instruction %s requires enabling FPU_MAC "
5401 "extension"), insn->opcode->opcode);
5403 else if (insn->opcode->attr & NASM_ATTR_FPU_DP_EXT)
5405 if (nds32_fpu_dp_ext && nds32_mac)
5406 nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST;
5407 else
5408 as_bad (_("instruction %s requires enabling FPU_MAC "
5409 "extension"), insn->opcode->opcode);
5411 else if (insn->opcode->attr & NASM_ATTR_DXREG)
5413 if (nds32_dx_regs && nds32_mac)
5414 nds32_elf_flags |= E_NDS32_HAS_MAC_DX_INST;
5415 else
5416 as_bad (_("instruction %s requires enabling DX_REGS "
5417 "extension"), insn->opcode->opcode);
5420 if (MAC_COMBO == (MAC_COMBO & nds32_elf_flags))
5421 skip_flags |= NASM_ATTR_MAC;
5423 break;
5424 case NASM_ATTR_DSP_ISAEXT:
5426 if (nds32_dsp_ext)
5428 nds32_elf_flags |= E_NDS32_HAS_DSP_INST;
5429 skip_flags |= NASM_ATTR_DSP_ISAEXT;
5431 else
5432 as_bad (_("instruction %s requires enabling dsp extension"),
5433 insn->opcode->opcode);
5435 break;
5436 case NASM_ATTR_ZOL:
5438 if (nds32_zol_ext)
5440 nds32_elf_flags |= E_NDS32_HAS_ZOL;
5441 skip_flags |= NASM_ATTR_ZOL;
5443 else
5444 as_bad (_("instruction %s requires enabling zol extension"),
5445 insn->opcode->opcode);
5447 break;
5448 default:
5449 as_bad (_("internal error: unknown instruction attribute: 0x%08x"),
5450 next);
5455 /* Flag for analysis relaxation type. */
5457 enum nds32_insn_type
5459 N32_RELAX_SETHI = 1,
5460 N32_RELAX_BR = (1 << 1),
5461 N32_RELAX_LSI = (1 << 2),
5462 N32_RELAX_JUMP = (1 << 3),
5463 N32_RELAX_CALL = (1 << 4),
5464 N32_RELAX_ORI = (1 << 5),
5465 N32_RELAX_MEM = (1 << 6),
5466 N32_RELAX_MOVI = (1 << 7),
5467 N32_RELAX_ALU1 = (1 << 8),
5468 N32_RELAX_16BIT = (1 << 9),
5471 struct nds32_hint_map
5473 /* the preamble relocation */
5474 bfd_reloc_code_real_type hi_type;
5475 /* mnemonic */
5476 const char *opc;
5477 /* relax pattern ID */
5478 enum nds32_relax_hint_type hint_type;
5479 /* range */
5480 enum nds32_br_range range;
5481 /* pattern character flags */
5482 enum nds32_insn_type insn_list;
5483 /* optional pattern character flags */
5484 enum nds32_insn_type option_list;
5487 /* Table to match instructions with hint and relax pattern. */
5489 static struct nds32_hint_map hint_map [] =
5492 /* LONGCALL4. */
5493 BFD_RELOC_NDS32_HI20,
5494 "jal",
5495 NDS32_RELAX_HINT_NONE,
5496 BR_RANGE_U4G,
5497 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL,
5501 /* LONGCALL5. */
5502 _dummy_first_bfd_reloc_code_real,
5503 "bgezal",
5504 NDS32_RELAX_HINT_NONE,
5505 BR_RANGE_S16M,
5506 N32_RELAX_BR | N32_RELAX_CALL,
5510 /* LONGCALL6. */
5511 BFD_RELOC_NDS32_HI20,
5512 "bgezal",
5513 NDS32_RELAX_HINT_NONE,
5514 BR_RANGE_U4G,
5515 N32_RELAX_BR | N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL,
5519 /* LONGJUMP4. */
5520 BFD_RELOC_NDS32_HI20,
5521 "j",
5522 NDS32_RELAX_HINT_NONE,
5523 BR_RANGE_U4G,
5524 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_JUMP,
5528 /* LONGJUMP5. */
5529 /* There is two kinds of variation of LONGJUMP5. One of them
5530 generate EMPTY relocation for converted INSN16 if needed.
5531 But we don't distinguish them here. */
5532 _dummy_first_bfd_reloc_code_real,
5533 "beq",
5534 NDS32_RELAX_HINT_NONE,
5535 BR_RANGE_S16M,
5536 N32_RELAX_BR | N32_RELAX_JUMP,
5540 /* LONGJUMP6. */
5541 BFD_RELOC_NDS32_HI20,
5542 "beq",
5543 NDS32_RELAX_HINT_NONE,
5544 BR_RANGE_U4G,
5545 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_BR | N32_RELAX_JUMP,
5549 /* LONGJUMP7. */
5550 _dummy_first_bfd_reloc_code_real,
5551 "beqc",
5552 NDS32_RELAX_HINT_NONE,
5553 BR_RANGE_S16K,
5554 N32_RELAX_MOVI | N32_RELAX_BR,
5558 /* LONGCALL (BAL|JR|LA symbol@PLT). */
5559 BFD_RELOC_NDS32_PLT_GOTREL_HI20,
5560 NULL,
5561 NDS32_RELAX_HINT_LA_PLT,
5562 BR_RANGE_U4G,
5563 N32_RELAX_SETHI | N32_RELAX_ORI,
5564 N32_RELAX_ALU1 | N32_RELAX_CALL | N32_RELAX_JUMP,
5566 /* relative issue: #12566 */
5568 /* LA and Floating LSI. */
5569 BFD_RELOC_NDS32_HI20,
5570 NULL,
5571 NDS32_RELAX_HINT_LA_FLSI,
5572 BR_RANGE_U4G,
5573 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_LSI,
5576 /* relative issue: #11685 #11602 */
5578 /* load address / load-store (LALS). */
5579 BFD_RELOC_NDS32_HI20,
5580 NULL,
5581 NDS32_RELAX_HINT_LALS,
5582 BR_RANGE_U4G,
5583 N32_RELAX_SETHI,
5584 N32_RELAX_ORI | N32_RELAX_LSI,
5587 /* setup $GP (_GLOBAL_OFFSET_TABLE_) */
5588 BFD_RELOC_NDS32_GOTPC_HI20,
5589 NULL,
5590 NDS32_RELAX_HINT_LALS,
5591 BR_RANGE_U4G,
5592 N32_RELAX_SETHI | N32_RELAX_ORI,
5596 /* GOT LA/LS (symbol@GOT) */
5597 BFD_RELOC_NDS32_GOT_HI20,
5598 NULL,
5599 NDS32_RELAX_HINT_LA_GOT,
5600 BR_RANGE_U4G,
5601 N32_RELAX_SETHI | N32_RELAX_ORI,
5602 N32_RELAX_MEM,
5605 /* GOTOFF LA/LS (symbol@GOTOFF) */
5606 BFD_RELOC_NDS32_GOTOFF_HI20,
5607 NULL,
5608 NDS32_RELAX_HINT_LA_GOTOFF,
5609 BR_RANGE_U4G,
5610 N32_RELAX_SETHI | N32_RELAX_ORI,
5611 N32_RELAX_ALU1 | N32_RELAX_MEM, /* | N32_RELAX_LSI, */
5614 /* TLS LE LA|LS (@TPOFF) */
5615 BFD_RELOC_NDS32_TLS_LE_HI20,
5616 NULL,
5617 NDS32_RELAX_HINT_TLS_LE_LS,
5618 BR_RANGE_U4G,
5619 N32_RELAX_SETHI | N32_RELAX_ORI,
5620 N32_RELAX_ALU1 | N32_RELAX_MEM,
5623 /* TLS IE LA */
5624 BFD_RELOC_NDS32_TLS_IE_HI20,
5625 NULL,
5626 NDS32_RELAX_HINT_TLS_IE_LA,
5627 BR_RANGE_U4G,
5628 N32_RELAX_SETHI | N32_RELAX_LSI,
5632 /* TLS IE LS */
5633 BFD_RELOC_NDS32_TLS_IE_HI20,
5634 NULL,
5635 NDS32_RELAX_HINT_TLS_IE_LS,
5636 BR_RANGE_U4G,
5637 N32_RELAX_SETHI | N32_RELAX_LSI | N32_RELAX_MEM,
5641 /* TLS IEGP LA */
5642 BFD_RELOC_NDS32_TLS_IEGP_HI20,
5643 NULL,
5644 NDS32_RELAX_HINT_TLS_IEGP_LA,
5645 BR_RANGE_U4G,
5646 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_MEM,
5650 /* TLS DESC LS */
5651 BFD_RELOC_NDS32_TLS_DESC_HI20,
5652 NULL,
5653 NDS32_RELAX_HINT_TLS_DESC_LS,
5654 BR_RANGE_U4G,
5655 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_ALU1 | N32_RELAX_CALL,
5656 N32_RELAX_LSI | N32_RELAX_MEM,
5658 /* last one */
5659 {0, NULL, 0, 0 ,0, 0}
5662 /* Find the relaxation pattern according to instructions. */
5664 static bool
5665 nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern,
5666 struct nds32_relax_hint_table *hint_info)
5668 unsigned int opcode, seq_size;
5669 enum nds32_br_range range;
5670 struct nds32_relocs_pattern *pattern, *hi_pattern = NULL;
5671 const char *opc = NULL;
5672 relax_info_t *relax_info = NULL;
5673 nds32_relax_fixup_info_t *fixup_info, *hint_fixup;
5674 enum nds32_relax_hint_type hint_type = NDS32_RELAX_HINT_NONE;
5675 struct nds32_relax_hint_table *table_ptr;
5676 uint32_t *code_seq, *hint_code;
5677 enum nds32_insn_type relax_type = 0;
5678 struct nds32_hint_map *map_ptr = hint_map;
5679 unsigned int i;
5680 const char *check_insn[] =
5681 { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8" };
5683 /* TODO: PLT GOT. */
5684 /* Traverse all pattern instruction and set flag. */
5685 pattern = relocs_pattern;
5686 while (pattern)
5688 if (pattern->opcode->isize == 4)
5690 /* 4 byte instruction. */
5691 opcode = N32_OP6 (pattern->opcode->value);
5692 switch (opcode)
5694 case N32_OP6_SETHI:
5695 hi_pattern = pattern;
5696 relax_type |= N32_RELAX_SETHI;
5697 break;
5698 case N32_OP6_MEM:
5699 relax_type |= N32_RELAX_MEM;
5700 break;
5701 case N32_OP6_ALU1:
5702 relax_type |= N32_RELAX_ALU1;
5703 break;
5704 case N32_OP6_ORI:
5705 relax_type |= N32_RELAX_ORI;
5706 break;
5707 case N32_OP6_BR1:
5708 case N32_OP6_BR2:
5709 case N32_OP6_BR3:
5710 relax_type |= N32_RELAX_BR;
5711 break;
5712 case N32_OP6_MOVI:
5713 relax_type |= N32_RELAX_MOVI;
5714 break;
5715 case N32_OP6_LBI:
5716 case N32_OP6_SBI:
5717 case N32_OP6_LBSI:
5718 case N32_OP6_LHI:
5719 case N32_OP6_SHI:
5720 case N32_OP6_LHSI:
5721 case N32_OP6_LWI:
5722 case N32_OP6_SWI:
5723 case N32_OP6_LWC:
5724 case N32_OP6_SWC:
5725 case N32_OP6_LDC:
5726 case N32_OP6_SDC:
5727 relax_type |= N32_RELAX_LSI;
5728 break;
5729 case N32_OP6_JREG:
5730 if (__GF (pattern->opcode->value, 0, 1) == 1)
5731 relax_type |= N32_RELAX_CALL;
5732 else
5733 relax_type |= N32_RELAX_JUMP;
5734 break;
5735 case N32_OP6_JI:
5736 if (__GF (pattern->opcode->value, 24, 1) == 1)
5737 relax_type |= N32_RELAX_CALL;
5738 else
5739 relax_type |= N32_RELAX_JUMP;
5740 break;
5741 default:
5742 as_warn (_("relax hint unrecognized instruction: line %d."),
5743 pattern->frag->fr_line);
5744 return false;
5747 else
5749 /* 2 byte instruction. Compare by opcode name because
5750 the opcode of 2byte instruction is not regular. */
5751 int is_matched = 0;
5752 for (i = 0; i < ARRAY_SIZE (check_insn); i++)
5754 if (strcmp (pattern->opcode->opcode, check_insn[i]) == 0)
5756 relax_type |= N32_RELAX_BR;
5757 is_matched += 1;
5758 break;
5761 if (!is_matched)
5762 relax_type |= N32_RELAX_16BIT;
5764 pattern = pattern->next;
5767 /* Analysis instruction flag to choose relaxation table. */
5768 while (map_ptr->insn_list != 0)
5770 struct nds32_hint_map *hint = map_ptr++;
5771 enum nds32_insn_type must = hint->insn_list;
5772 enum nds32_insn_type optional = hint->option_list;
5773 enum nds32_insn_type extra;
5775 if (must != (must & relax_type))
5776 continue;
5778 extra = relax_type ^ must;
5779 if (extra != (extra & optional))
5780 continue;
5782 if (!hi_pattern
5783 || (hi_pattern->fixP
5784 && hi_pattern->fixP->fx_r_type == hint->hi_type))
5786 opc = hint->opc;
5787 hint_type = hint->hint_type;
5788 range = hint->range;
5789 map_ptr = hint;
5790 break;
5794 if (map_ptr->insn_list == 0)
5796 if (!nds32_pic)
5797 as_warn (_("Can not find match relax hint. Line: %d"),
5798 relocs_pattern->frag->fr_line);
5799 return false;
5802 /* Get the match table. */
5803 if (opc)
5805 /* Branch relax pattern. */
5806 relax_info = str_hash_find (nds32_relax_info_hash, opc);
5807 if (!relax_info)
5808 return false;
5809 fixup_info = relax_info->relax_fixup[range];
5810 code_seq = relax_info->relax_code_seq[range];
5811 seq_size = relax_info->relax_code_size[range];
5813 else if (hint_type)
5815 /* Load-store relax pattern. */
5816 table_ptr = relax_ls_table;
5817 while (table_ptr->main_type != 0)
5819 if (table_ptr->main_type == hint_type)
5821 fixup_info = table_ptr->relax_fixup;
5822 code_seq = table_ptr->relax_code_seq;
5823 seq_size = table_ptr->relax_code_size;
5824 break;
5826 table_ptr++;
5828 if (table_ptr->main_type == 0)
5829 return false;
5831 else
5832 return false;
5834 hint_fixup = hint_info->relax_fixup;
5835 hint_code = hint_info->relax_code_seq;
5836 hint_info->relax_code_size = seq_size;
5838 while (fixup_info->size != 0)
5840 if (fixup_info->ramp & NDS32_HINT)
5842 memcpy (hint_fixup, fixup_info, sizeof (nds32_relax_fixup_info_t));
5843 hint_fixup++;
5845 fixup_info++;
5847 /* Clear final relocation. */
5848 memset (hint_fixup, 0, sizeof (nds32_relax_fixup_info_t));
5849 /* Copy code sequence. */
5850 memcpy (hint_code, code_seq, seq_size);
5851 return true;
5854 /* Because there are a lot of variant of load-store, check
5855 all these type here. */
5857 #define CLEAN_REG(insn) ((insn) & 0xfe0003ff)
5858 #define GET_OPCODE(insn) ((insn) & 0xfe000000)
5860 static bool
5861 nds32_match_hint_insn (struct nds32_opcode *opcode, uint32_t seq)
5863 const char *check_insn[] =
5864 { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8", "jral5" };
5865 uint32_t insn = opcode->value;
5866 unsigned int i;
5868 insn = CLEAN_REG (opcode->value);
5869 if (insn == seq)
5870 return true;
5872 switch (seq)
5874 case OP6 (LBI):
5875 /* In relocation_table, it regards instruction LBI as representation
5876 of all the NDS32_RELAX_HINT_LS pattern. */
5877 if (insn == OP6 (LBI) || insn == OP6 (SBI) || insn == OP6 (LBSI)
5878 || insn == OP6 (LHI) || insn == OP6 (SHI) || insn == OP6 (LHSI)
5879 || insn == OP6 (LWI) || insn == OP6 (SWI)
5880 || insn == OP6 (LWC) || insn == OP6 (SWC)
5881 || insn == OP6 (LDC) || insn == OP6 (SDC))
5882 return true;
5883 break;
5884 case OP6 (BR2):
5885 /* This is for LONGCALL5 and LONGCALL6. */
5886 if (insn == OP6 (BR2))
5887 return true;
5888 break;
5889 case OP6 (BR1):
5890 /* This is for LONGJUMP5 and LONGJUMP6. */
5891 if (opcode->isize == 4
5892 && (insn == OP6 (BR1) || insn == OP6 (BR2) || insn == OP6 (BR3)))
5893 return true;
5894 else if (opcode->isize == 2)
5896 for (i = 0; i < ARRAY_SIZE (check_insn); i++)
5897 if (strcmp (opcode->opcode, check_insn[i]) == 0)
5898 return true;
5900 break;
5901 case OP6 (MOVI):
5902 /* This is for LONGJUMP7. */
5903 if (opcode->isize == 2 && strcmp (opcode->opcode, "movi55") == 0)
5904 return true;
5905 break;
5906 case OP6 (MEM):
5907 if (OP6 (MEM) == GET_OPCODE (insn))
5908 return true;
5909 break;
5910 case OP6 (JREG):
5911 /* bit 24: N32_JI_JAL */ /* feed me! */
5912 if ((insn & ~(N32_BIT (24))) == JREG (JRAL))
5913 return true;
5914 break;
5915 default:
5916 if (opcode->isize == 2)
5918 for (i = 0; i < ARRAY_SIZE (check_insn); i++)
5919 if (strcmp (opcode->opcode, check_insn[i]) == 0)
5920 return true;
5922 if ((strcmp (opcode->opcode, "add5.pc") == 0) ||
5923 (strcmp (opcode->opcode, "add45") == 0))
5924 return true;
5927 return false;
5930 /* Append relax relocation for link time relaxing. */
5932 static void
5933 nds32_elf_append_relax_relocs (const char *key, const void *value)
5935 struct nds32_relocs_pattern *relocs_pattern =
5936 (struct nds32_relocs_pattern *) value;
5937 struct nds32_relocs_pattern *pattern_temp, *pattern_now;
5938 symbolS *sym, *hi_sym = NULL;
5939 expressionS exp;
5940 fragS *fragP;
5941 segT seg_bak = now_seg;
5942 frchainS *frchain_bak = frchain_now;
5943 struct nds32_relax_hint_table hint_info;
5944 nds32_relax_fixup_info_t *hint_fixup, *fixup_now;
5945 size_t fixup_size;
5946 offsetT branch_offset, hi_branch_offset = 0;
5947 fixS *fixP;
5948 int range, offset;
5949 unsigned int ptr_offset, hint_count, relax_code_size, count = 0;
5950 uint32_t *code_seq, code_insn;
5951 char *where;
5952 int pcrel;
5954 if (!relocs_pattern)
5955 return;
5957 if (!nds32_find_reloc_table (relocs_pattern, &hint_info))
5958 return;
5960 /* Save symbol for some EMPTY relocation using. */
5961 pattern_now = relocs_pattern;
5962 while (pattern_now)
5964 if (pattern_now->opcode->value == OP6 (SETHI))
5966 hi_sym = pattern_now->sym;
5967 hi_branch_offset = pattern_now->fixP->fx_offset;
5968 break;
5970 pattern_now = pattern_now->next;
5973 /* Inserting fix up must specify now_seg or frchain_now. */
5974 now_seg = relocs_pattern->seg;
5975 frchain_now = relocs_pattern->frchain;
5976 fragP = relocs_pattern->frag;
5977 branch_offset = fragP->fr_offset;
5979 hint_fixup = hint_info.relax_fixup;
5980 code_seq = hint_info.relax_code_seq;
5981 relax_code_size = hint_info.relax_code_size;
5982 pattern_now = relocs_pattern;
5984 #ifdef NDS32_LINUX_TOOLCHAIN
5985 /* prepare group relocation ID (number). */
5986 long group_id = 0;
5987 if (key)
5989 /* convert .relax_hint key to number */
5990 errno = 0;
5991 group_id = strtol (key, NULL, 10);
5992 if ((errno == ERANGE && (group_id == LONG_MAX || group_id == LONG_MIN))
5993 || (errno != 0 && group_id == 0))
5995 as_bad (_("Internal error: .relax_hint KEY is not a number!"));
5996 goto restore;
5999 #endif
6001 /* Insert relaxation. */
6002 exp.X_op = O_symbol;
6004 /* For each instruction in the hint group. */
6005 while (pattern_now)
6007 if (count >= relax_code_size / 4)
6008 count = 0;
6010 /* Choose the match fixup by instruction. */
6011 code_insn = CLEAN_REG (*(code_seq + count));
6012 if (!nds32_match_hint_insn (pattern_now->opcode, code_insn))
6014 /* Try search from head again */
6015 count = 0;
6016 code_insn = CLEAN_REG (*(code_seq + count));
6018 while (!nds32_match_hint_insn (pattern_now->opcode, code_insn))
6020 count++;
6021 if (count >= relax_code_size / 4)
6023 as_bad (_("Internal error: Relax hint (%s) error. %s: %s (%x)"),
6024 key,
6025 now_seg->name,
6026 pattern_now->opcode->opcode,
6027 pattern_now->opcode->value);
6028 goto restore;
6030 code_insn = CLEAN_REG (*(code_seq + count));
6033 fragP = pattern_now->frag;
6034 sym = pattern_now->sym;
6035 branch_offset = fragP->fr_offset;
6036 offset = count * 4;
6037 where = pattern_now->where;
6038 /* Find the instruction map fix. */
6039 fixup_now = hint_fixup;
6040 while (fixup_now->offset != offset)
6042 fixup_now++;
6043 if (fixup_now->size == 0)
6044 break;
6046 /* This element is without relaxation relocation. */
6047 if (fixup_now->size == 0)
6049 pattern_now = pattern_now->next;
6050 continue;
6052 fixup_size = fixup_now->size;
6054 /* Insert all fixup. */
6055 pcrel = 0;
6056 while (fixup_size != 0 && fixup_now->offset == offset)
6058 /* Set the real instruction size in element. */
6059 fixup_size = pattern_now->opcode->isize;
6060 pcrel = ((fixup_now->ramp & NDS32_PCREL) != 0) ? 1 : 0;
6061 if (fixup_now->ramp & NDS32_FIX)
6063 /* Convert original relocation. */
6064 pattern_now->fixP->fx_r_type = fixup_now->r_type ;
6065 fixup_size = 0;
6067 else if ((fixup_now->ramp & NDS32_PTR) != 0)
6069 /* This relocation has to point to another instruction. Make
6070 sure each resolved relocation has to be pointed. */
6071 pattern_temp = relocs_pattern;
6072 /* All instruction in relax_table should be 32-bit. */
6073 hint_count = hint_info.relax_code_size / 4;
6074 code_insn = CLEAN_REG (*(code_seq + hint_count - 1));
6075 while (pattern_temp)
6077 /* Point to every resolved relocation. */
6078 if (nds32_match_hint_insn (pattern_temp->opcode, code_insn))
6080 ptr_offset =
6081 pattern_temp->where - pattern_temp->frag->fr_literal;
6082 exp.X_add_symbol = symbol_temp_new (now_seg,
6083 pattern_temp->frag,
6084 ptr_offset);
6085 exp.X_add_number = 0;
6086 fixP =
6087 fix_new_exp (fragP, where - fragP->fr_literal,
6088 fixup_size, &exp, 0, fixup_now->r_type);
6089 fixP->fx_addnumber = fixP->fx_offset;
6091 pattern_temp = pattern_temp->next;
6093 fixup_size = 0;
6095 else if (fixup_now->ramp & NDS32_ADDEND)
6097 range = nds32_elf_sethi_range (relocs_pattern);
6098 if (range == NDS32_LOADSTORE_NONE)
6100 as_bad (_("Internal error: Range error. %s"), now_seg->name);
6101 return;
6103 exp.X_add_symbol = abs_section_sym;
6104 exp.X_add_number = SET_ADDEND (4, 0, optimize, enable_16bit);
6105 exp.X_add_number |= ((range & 0x3f) << 8);
6107 else if ((fixup_now->ramp & NDS32_ABS) != 0)
6109 /* This is a tag relocation. */
6110 exp.X_add_symbol = abs_section_sym;
6111 exp.X_add_number = 0;
6113 else if ((fixup_now->ramp & NDS32_INSN16) != 0)
6115 if (!enable_16bit)
6116 fixup_size = 0;
6117 /* This is a tag relocation. */
6118 exp.X_add_symbol = abs_section_sym;
6119 exp.X_add_number = 0;
6121 else if ((fixup_now->ramp & NDS32_SYM) != 0)
6123 /* For EMPTY relocation save the true symbol. */
6124 exp.X_add_symbol = hi_sym;
6125 exp.X_add_number = hi_branch_offset;
6127 else if (NDS32_SYM_DESC_MEM & fixup_now->ramp)
6129 /* Do the same as NDS32_SYM. */
6130 exp.X_add_symbol = hi_sym;
6131 exp.X_add_number = hi_branch_offset;
6133 /* Extra to NDS32_SYM. */
6134 /* Detect if DESC_FUNC relax type do apply. */
6135 if ((REG_GP == N32_RA5 (pattern_now->insn))
6136 || (REG_GP == N32_RB5 (pattern_now->insn)))
6138 fixP = fix_new_exp (fragP, where - fragP->fr_literal,
6139 fixup_size, &exp, pcrel,
6140 BFD_RELOC_NDS32_TLS_DESC_FUNC);
6141 fixP->fx_addnumber = fixP->fx_offset;
6143 fixup_size = 0;
6145 /* Else do as usual. */
6147 else if (fixup_now->ramp & NDS32_PTR_PATTERN)
6149 /* Find out PTR_RESOLVED code pattern. */
6150 nds32_relax_fixup_info_t *next_fixup = fixup_now + 1;
6151 uint32_t resolved_pattern = 0;
6152 while (next_fixup->offset)
6154 if (next_fixup->r_type == BFD_RELOC_NDS32_PTR_RESOLVED)
6156 uint32_t new_pattern = code_seq[next_fixup->offset >> 2];
6157 if (!resolved_pattern)
6158 resolved_pattern = new_pattern;
6159 else if (new_pattern != resolved_pattern)
6161 as_warn (_("Multiple BFD_RELOC_NDS32_PTR_RESOLVED "
6162 "patterns are not supported yet!"));
6163 break;
6166 ++next_fixup;
6169 /* Find matched code and insert fix-ups. */
6170 struct nds32_relocs_pattern *next_pattern = pattern_now->next;
6171 /* This relocation has to point to another instruction.
6172 Make sure each resolved relocation has to be pointed. */
6173 /* All instruction in relax_table should be 32-bit. */
6174 while (next_pattern)
6176 uint32_t cur_pattern = GET_OPCODE (next_pattern->opcode->value);
6177 if (cur_pattern == resolved_pattern)
6179 ptr_offset = next_pattern->where
6180 - next_pattern->frag->fr_literal;
6181 exp.X_add_symbol = symbol_temp_new (now_seg,
6182 next_pattern->frag,
6183 ptr_offset);
6184 exp.X_add_number = 0;
6185 fixP = fix_new_exp (fragP, where - fragP->fr_literal,
6186 fixup_size, &exp, 0,
6187 fixup_now->r_type);
6188 fixP->fx_addnumber = fixP->fx_offset;
6190 next_pattern = next_pattern->next;
6193 fixup_size = 0;
6195 else if (fixup_now->ramp & NDS32_PTR_MULTIPLE)
6197 /* Find each PTR_RESOLVED pattern after PTR. */
6198 nds32_relax_fixup_info_t *next_fixup = fixup_now + 1;
6199 while (next_fixup->offset)
6201 if (next_fixup->r_type == BFD_RELOC_NDS32_PTR_RESOLVED)
6203 uint32_t pattern = code_seq[next_fixup->offset >> 2];
6204 /* Find matched code to insert fix-ups. */
6205 struct nds32_relocs_pattern *next_insn = pattern_now->next;
6206 while (next_insn)
6208 uint32_t insn_pattern = GET_OPCODE (next_insn->opcode->value);
6209 if (insn_pattern == pattern)
6211 ptr_offset = next_insn->where
6212 - next_insn->frag->fr_literal;
6213 exp.X_add_symbol = symbol_temp_new (now_seg,
6214 next_insn->frag,
6215 ptr_offset);
6216 exp.X_add_number = 0;
6217 fixP = fix_new_exp (fragP,
6218 where - fragP->fr_literal,
6219 fixup_size, &exp, 0,
6220 fixup_now->r_type);
6221 fixP->fx_addnumber = fixP->fx_offset;
6223 next_insn = next_insn->next;
6226 ++next_fixup;
6228 fixup_size = 0;
6230 else
6232 exp.X_add_symbol = sym;
6233 exp.X_add_number = branch_offset;
6236 if (fixup_size != 0)
6238 fixP = fix_new_exp (fragP, where - fragP->fr_literal, fixup_size,
6239 &exp, pcrel, fixup_now->r_type);
6240 fixP->fx_addnumber = fixP->fx_offset;
6242 fixup_now++;
6243 fixup_size = fixup_now->size;
6246 #ifdef NDS32_LINUX_TOOLCHAIN
6247 /* Insert group relocation for each relax hint. */
6248 if (key)
6250 exp.X_add_symbol = hi_sym; /* for eyes only */
6251 exp.X_add_number = group_id;
6252 fixP = fix_new_exp (fragP, where - fragP->fr_literal, fixup_size,
6253 &exp, pcrel, BFD_RELOC_NDS32_GROUP);
6254 fixP->fx_addnumber = fixP->fx_offset;
6256 #endif
6258 if (count < relax_code_size / 4)
6259 count++;
6260 pattern_now = pattern_now->next;
6263 restore:
6264 now_seg = seg_bak;
6265 frchain_now = frchain_bak;
6268 static int
6269 nds32_elf_append_relax_relocs_traverse (void **slot, void *arg ATTRIBUTE_UNUSED)
6271 string_tuple_t *tuple = *((string_tuple_t **) slot);
6272 nds32_elf_append_relax_relocs (tuple->key, tuple->value);
6273 return 1;
6277 static void
6278 nds32_str_tolower (const char *src, char *dest)
6280 unsigned int i, len;
6282 len = strlen (src);
6284 for (i = 0; i < len; i++)
6285 *(dest + i) = TOLOWER (*(src + i));
6287 *(dest + i) = '\0';
6290 /* Check instruction if it can be used for the baseline. */
6292 static bool
6293 nds32_check_insn_available (struct nds32_asm_insn insn, const char *str)
6295 int attr = insn.attr & ATTR_ALL;
6296 static int baseline_isa = 0;
6297 char *s;
6299 s = xmalloc (strlen (str) + 1);
6300 nds32_str_tolower (str, s);
6301 if (verbatim
6302 && (((insn.opcode->value == ALU2 (MTUSR)
6303 || insn.opcode->value == ALU2 (MFUSR))
6304 && (strstr (s, "lc")
6305 || strstr (s, "le")
6306 || strstr (s, "lb")))
6307 || (insn.attr & NASM_ATTR_ZOL)))
6309 as_bad (_("Not support instruction %s in verbatim."), str);
6310 return false;
6312 free (s);
6314 if (!enable_16bit && insn.opcode->isize == 2)
6316 as_bad (_("16-bit instruction is disabled: %s."), str);
6317 return false;
6320 /* No isa setting or all isa can use. */
6321 if (attr == 0 || attr == ATTR_ALL)
6322 return true;
6324 if (baseline_isa == 0)
6326 /* Map option baseline and instruction attribute. */
6327 switch (nds32_baseline)
6329 case ISA_V2:
6330 baseline_isa = ATTR (ISA_V2);
6331 break;
6332 case ISA_V3:
6333 baseline_isa = ATTR (ISA_V3);
6334 break;
6335 case ISA_V3M:
6336 baseline_isa = ATTR (ISA_V3M);
6337 break;
6341 if ((baseline_isa & attr) == 0)
6343 as_bad (_("Instruction %s not supported in the baseline."), str);
6344 return false;
6346 return true;
6349 /* Stub of machine dependent. */
6351 void
6352 md_assemble (char *str)
6354 struct nds32_asm_insn insn;
6355 char *out;
6356 struct nds32_pseudo_opcode *popcode;
6357 const struct nds32_field *fld = NULL;
6358 fixS *fixP;
6359 uint16_t insn_16;
6360 struct nds32_relocs_pattern *relocs_temp;
6361 struct nds32_relocs_group *group_temp;
6362 fragS *fragP;
6363 int label = label_exist;
6364 static bool pseudo_hint = false;
6366 popcode = nds32_lookup_pseudo_opcode (str);
6367 /* Note that we need to check 'verbatim' and
6368 'opcode->physical_op'. If the assembly content is generated by
6369 compiler and this opcode is a physical instruction, there is no
6370 need to perform pseudo instruction expansion/transformation. */
6371 if (popcode && !(verbatim && popcode->physical_op))
6373 /* Pseudo instruction is with relax_hint. */
6374 if (relaxing)
6375 pseudo_hint = true;
6376 pseudo_opcode = true;
6377 nds32_pseudo_opcode_wrapper (str, popcode);
6378 pseudo_opcode = false;
6379 pseudo_hint = false;
6380 nds32_elf_append_relax_relocs (NULL, relocs_list);
6382 /* Free relax_hint group list. */
6383 while (nds32_relax_hint_current)
6385 group_temp = nds32_relax_hint_current->next;
6386 free (nds32_relax_hint_current);
6387 nds32_relax_hint_current = group_temp;
6390 /* Free pseudo list. */
6391 relocs_temp = relocs_list;
6392 while (relocs_temp)
6394 relocs_list = relocs_list->next;
6395 free (relocs_temp);
6396 relocs_temp = relocs_list;
6399 return;
6402 label_exist = 0;
6403 insn.info = XNEW (expressionS);
6404 asm_desc.result = NASM_OK;
6405 nds32_assemble (&asm_desc, &insn, str);
6407 switch (asm_desc.result)
6409 case NASM_ERR_UNKNOWN_OP:
6410 as_bad (_("Unrecognized opcode, %s."), str);
6411 return;
6412 case NASM_ERR_SYNTAX:
6413 as_bad (_("Incorrect syntax, %s."), str);
6414 return;
6415 case NASM_ERR_OPERAND:
6416 as_bad (_("Unrecognized operand/register, %s."), str);
6417 return;
6418 case NASM_ERR_OUT_OF_RANGE:
6419 as_bad (_("Operand out of range, %s."), str);
6420 return;
6421 case NASM_ERR_REG_REDUCED:
6422 as_bad (_("Prohibited register used for reduced-register, %s."), str);
6423 return;
6424 case NASM_ERR_JUNK_EOL:
6425 as_bad (_("Junk at end of line, %s."), str);
6426 return;
6429 gas_assert (insn.opcode);
6431 nds32_set_elf_flags_by_insn (&insn);
6433 gas_assert (insn.opcode->isize == 4 || insn.opcode->isize == 2);
6435 if (!nds32_check_insn_available (insn, str))
6436 return;
6438 /* Make sure the beginning of text being 2-byte align. */
6439 nds32_adjust_label (1);
6440 add_mapping_symbol (MAP_CODE, 0, 0);
6441 fld = insn.field;
6442 /* Try to allocate the max size to guarantee relaxable same branch
6443 instructions in the same fragment. */
6444 frag_grow (NDS32_MAXCHAR);
6445 fragP = frag_now;
6447 if (fld && (insn.attr & NASM_ATTR_BRANCH)
6448 && (pseudo_opcode || (insn.opcode->value != INSN_JAL
6449 && insn.opcode->value != INSN_J))
6450 && (!verbatim || pseudo_opcode))
6452 /* User assembly code branch relax for it. */
6453 /* If fld is not NULL, it is a symbol. */
6454 /* Branch must relax to proper pattern in user assembly code exclude
6455 J and JAL. Keep these two in original type for users which wants
6456 to keep their size be fixed. In general, assembler does not convert
6457 instruction generated by compiler. But jump instruction may be
6458 truncated in text virtual model. For workaround, compiler generate
6459 pseudo jump to fix this issue currently. */
6461 /* Get branch range type. */
6462 dwarf2_emit_insn (0);
6463 enum nds32_br_range range_type;
6464 expressionS *pexp = insn.info;
6466 range_type = get_range_type (fld);
6468 out = frag_var (rs_machine_dependent, NDS32_MAXCHAR,
6469 0, /* VAR is un-used. */
6470 range_type, /* SUBTYPE is used as range type. */
6471 pexp->X_add_symbol, pexp->X_add_number, 0);
6473 fragP->fr_fix += insn.opcode->isize;
6474 fragP->tc_frag_data.opcode = insn.opcode;
6475 fragP->tc_frag_data.insn = insn.insn;
6476 if (insn.opcode->isize == 4)
6477 bfd_putb32 (insn.insn, out);
6478 else if (insn.opcode->isize == 2)
6479 bfd_putb16 (insn.insn, out);
6480 fragP->tc_frag_data.flag |= NDS32_FRAG_BRANCH;
6482 free (insn.info);
6483 return;
6484 /* md_convert_frag will insert relocations. */
6486 else if (!relaxing && enable_16bit && (optimize || optimize_for_space)
6487 && ((!fld && !verbatim && insn.opcode->isize == 4
6488 && nds32_convert_32_to_16 (stdoutput, insn.insn, &insn_16, NULL))
6489 || (insn.opcode->isize == 2
6490 && nds32_convert_16_to_32 (stdoutput, insn.insn, NULL))))
6492 /* Record this one is relaxable. */
6493 expressionS *pexp = insn.info;
6494 dwarf2_emit_insn (0);
6495 if (fld)
6497 out = frag_var (rs_machine_dependent,
6498 4, /* Max size is 32-bit instruction. */
6499 0, /* VAR is un-used. */
6500 0, pexp->X_add_symbol, pexp->X_add_number, 0);
6501 fragP->tc_frag_data.flag |= NDS32_FRAG_RELAXABLE_BRANCH;
6503 else
6504 out = frag_var (rs_machine_dependent,
6505 4, /* Max size is 32-bit instruction. */
6506 0, /* VAR is un-used. */
6507 0, NULL, 0, NULL);
6508 fragP->tc_frag_data.flag |= NDS32_FRAG_RELAXABLE;
6509 fragP->tc_frag_data.opcode = insn.opcode;
6510 fragP->tc_frag_data.insn = insn.insn;
6511 fragP->fr_fix += 2;
6513 /* In original, we don't relax the instruction with label on it,
6514 but this may cause some redundant nop16. Therefore, tag this
6515 relaxable instruction and relax it carefully. */
6516 if (label)
6517 fragP->tc_frag_data.flag |= NDS32_FRAG_LABEL;
6519 if (insn.opcode->isize == 4)
6520 bfd_putb16 (insn_16, out);
6521 else if (insn.opcode->isize == 2)
6522 bfd_putb16 (insn.insn, out);
6524 free (insn.info);
6525 return;
6527 else if ((verbatim || !relaxing) && optimize && label)
6529 /* This instruction is with label. */
6530 expressionS exp;
6531 out = frag_var (rs_machine_dependent, insn.opcode->isize,
6532 0, 0, NULL, 0, NULL);
6533 /* If this instruction is branch target, it is not relaxable. */
6534 fragP->tc_frag_data.flag = NDS32_FRAG_LABEL;
6535 fragP->tc_frag_data.opcode = insn.opcode;
6536 fragP->tc_frag_data.insn = insn.insn;
6537 fragP->fr_fix += insn.opcode->isize;
6538 if (insn.opcode->isize == 4)
6540 exp.X_op = O_symbol;
6541 exp.X_add_symbol = abs_section_sym;
6542 exp.X_add_number = 0;
6543 fixP = fix_new_exp (fragP, fragP->fr_fix - 4, 0, &exp,
6544 0, BFD_RELOC_NDS32_LABEL);
6545 if (!verbatim)
6546 fragP->tc_frag_data.flag = NDS32_FRAG_ALIGN;
6549 else
6550 out = frag_more (insn.opcode->isize);
6552 if (insn.opcode->isize == 4)
6553 bfd_putb32 (insn.insn, out);
6554 else if (insn.opcode->isize == 2)
6555 bfd_putb16 (insn.insn, out);
6557 dwarf2_emit_insn (insn.opcode->isize);
6559 /* Compiler generating code and user assembly pseudo load-store, insert
6560 fixup here. */
6561 expressionS *pexp = insn.info;
6562 fixP = nds32_elf_record_fixup_exp (fragP, str, fld, pexp, out, &insn);
6563 /* Build relaxation pattern when relaxing is enable. */
6564 if (relaxing)
6565 nds32_elf_build_relax_relation (fixP, pexp, out, &insn, fragP, fld,
6566 pseudo_hint);
6568 free (insn.info);
6571 /* md_macro_start */
6573 void
6574 nds32_macro_start (void)
6578 /* md_macro_info */
6580 void
6581 nds32_macro_info (void *info ATTRIBUTE_UNUSED)
6585 /* md_macro_end */
6587 void
6588 nds32_macro_end (void)
6592 /* GAS will call this function with one argument, an expressionS pointer, for
6593 any expression that can not be recognized. When the function is called,
6594 input_line_pointer will point to the start of the expression. */
6596 void
6597 md_operand (expressionS *expressionP)
6599 if (*input_line_pointer == '#')
6601 input_line_pointer++;
6602 expression (expressionP);
6606 /* GAS will call this function for each section at the end of the assembly, to
6607 permit the CPU back end to adjust the alignment of a section. The function
6608 must take two arguments, a segT for the section and a valueT for the size of
6609 the section, and return a valueT for the rounded size. */
6611 valueT
6612 md_section_align (segT segment, valueT size)
6614 int align = bfd_section_alignment (segment);
6616 return ((size + (1 << align) - 1) & ((valueT) -1 << align));
6619 /* GAS will call this function when a symbol table lookup fails, before it
6620 creates a new symbol. Typically this would be used to supply symbols whose
6621 name or value changes dynamically, possibly in a context sensitive way.
6622 Predefined symbols with fixed values, such as register names or condition
6623 codes, are typically entered directly into the symbol table when md_begin
6624 is called. One argument is passed, a char * for the symbol. */
6626 symbolS *
6627 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
6629 return NULL;
6632 static long
6633 nds32_calc_branch_offset (segT segment, fragS *fragP,
6634 long stretch ATTRIBUTE_UNUSED,
6635 relax_info_t *relax_info,
6636 enum nds32_br_range branch_range_type)
6638 struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
6639 symbolS *branch_symbol = fragP->fr_symbol;
6640 offsetT branch_offset = fragP->fr_offset;
6641 offsetT branch_target_address;
6642 offsetT branch_insn_address;
6643 long offset = 0;
6645 if ((S_GET_SEGMENT (branch_symbol) != segment)
6646 || S_IS_WEAK (branch_symbol))
6648 /* The symbol is not in the SEGMENT. It could be far far away. */
6649 offset = 0x80000000;
6651 else
6653 /* Calculate symbol-to-instruction offset. */
6654 branch_target_address = S_GET_VALUE (branch_symbol) + branch_offset;
6655 /* If the destination symbol is beyond current frag address,
6656 STRETCH will take effect to symbol's position. */
6657 if (S_GET_VALUE (branch_symbol) > fragP->fr_address)
6658 branch_target_address += stretch;
6660 branch_insn_address = fragP->fr_address + fragP->fr_fix;
6661 branch_insn_address -= opcode->isize;
6663 /* Update BRANCH_INSN_ADDRESS to relaxed position. */
6664 branch_insn_address += (relax_info->relax_code_size[branch_range_type]
6665 - relax_info->relax_branch_isize[branch_range_type]);
6667 offset = branch_target_address - branch_insn_address;
6670 return offset;
6673 static enum nds32_br_range
6674 nds32_convert_to_range_type (long offset)
6676 enum nds32_br_range range_type;
6678 if (-(0x100) <= offset && offset < 0x100) /* 256 bytes */
6679 range_type = BR_RANGE_S256;
6680 else if (-(0x4000) <= offset && offset < 0x4000) /* 16K bytes */
6681 range_type = BR_RANGE_S16K;
6682 else if (-(0x10000) <= offset && offset < 0x10000) /* 64K bytes */
6683 range_type = BR_RANGE_S64K;
6684 else if (-(0x1000000) <= offset && offset < 0x1000000) /* 16M bytes */
6685 range_type = BR_RANGE_S16M;
6686 else /* 4G bytes */
6687 range_type = BR_RANGE_U4G;
6689 return range_type;
6692 /* Set instruction register mask. */
6694 static void
6695 nds32_elf_get_set_cond (relax_info_t *relax_info, int offset, uint32_t *insn,
6696 uint32_t ori_insn, int range)
6698 nds32_cond_field_t *cond_fields = relax_info->cond_field;
6699 nds32_cond_field_t *code_seq_cond = relax_info->relax_code_condition[range];
6700 uint32_t mask;
6701 int i = 0;
6703 /* The instruction has conditions. Collect condition values. */
6704 while (code_seq_cond[i].bitmask != 0)
6706 if (offset == code_seq_cond[i].offset)
6708 mask = (ori_insn >> cond_fields[i].bitpos) & cond_fields[i].bitmask;
6709 /* Sign extend. */
6710 if (cond_fields[i].signed_extend)
6711 mask = (mask ^ ((cond_fields[i].bitmask + 1) >> 1)) -
6712 ((cond_fields[i].bitmask + 1) >> 1);
6713 *insn |= (mask & code_seq_cond[i].bitmask) << code_seq_cond[i].bitpos;
6715 i++;
6719 static int
6720 nds32_relax_branch_instructions (segT segment, fragS *fragP,
6721 long stretch ATTRIBUTE_UNUSED,
6722 int init)
6724 enum nds32_br_range branch_range_type;
6725 struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
6726 long offset = 0;
6727 enum nds32_br_range real_range_type;
6728 int adjust = 0;
6729 relax_info_t *relax_info;
6730 int diff = 0;
6731 int i, j, k;
6732 int code_seq_size;
6733 uint32_t *code_seq;
6734 uint32_t insn;
6735 int insn_size;
6736 int code_seq_offset;
6738 /* Replace with gas_assert (fragP->fr_symbol != NULL); */
6739 if (fragP->fr_symbol == NULL)
6740 return adjust;
6742 /* If frag_var is not enough room, the previous frag is fr_full and with
6743 opcode. The new one is rs_dependent but without opcode. */
6744 if (opcode == NULL)
6745 return adjust;
6747 /* Use U4G mode for b and bal in verbatim mode because lto may combine
6748 functions into a file. And order the file in the last when linking.
6749 Once there is multiple definition, the same function will be kicked.
6750 This may cause relocation truncated error. */
6751 if (verbatim && !nds32_pic
6752 && (strcmp (opcode->opcode, "j") == 0
6753 || strcmp (opcode->opcode, "jal") == 0))
6755 fragP->fr_subtype = BR_RANGE_U4G;
6756 if (init)
6757 return 8;
6758 else
6759 return 0;
6762 relax_info = str_hash_find (nds32_relax_info_hash, opcode->opcode);
6764 if (relax_info == NULL)
6765 return adjust;
6767 if (init)
6769 branch_range_type = relax_info->br_range;
6770 i = BR_RANGE_S256;
6772 else
6774 branch_range_type = fragP->fr_subtype;
6775 i = branch_range_type;
6778 offset = nds32_calc_branch_offset (segment, fragP, stretch,
6779 relax_info, branch_range_type);
6781 real_range_type = nds32_convert_to_range_type (offset);
6783 /* If actual range is equal to instruction jump range, do nothing. */
6784 if (real_range_type == branch_range_type)
6786 fragP->fr_subtype = real_range_type;
6787 return adjust;
6790 /* Find out proper relaxation code sequence. */
6791 for (; i < BR_RANGE_NUM; i++)
6793 if (real_range_type <= (unsigned int) i)
6795 if (init)
6796 diff = relax_info->relax_code_size[i] - opcode->isize;
6797 else if (real_range_type < (unsigned int) i)
6798 diff = relax_info->relax_code_size[real_range_type]
6799 - relax_info->relax_code_size[branch_range_type];
6800 else
6801 diff = relax_info->relax_code_size[i]
6802 - relax_info->relax_code_size[branch_range_type];
6804 /* If the instruction could be converted to 16-bits,
6805 minus the difference. */
6806 code_seq_offset = 0;
6807 j = 0;
6808 k = 0;
6809 code_seq_size = relax_info->relax_code_size[i];
6810 code_seq = relax_info->relax_code_seq[i];
6811 while (code_seq_offset < code_seq_size)
6813 insn = code_seq[j];
6814 if (insn & 0x80000000) /* 16-bits instruction. */
6816 insn_size = 2;
6818 else /* 32-bits instruction. */
6820 insn_size = 4;
6822 while (relax_info->relax_fixup[i][k].size !=0
6823 && relax_info->relax_fixup[i][k].offset < code_seq_offset)
6824 k++;
6827 code_seq_offset += insn_size;
6828 j++;
6831 /* Update fr_subtype to new NDS32_BR_RANGE. */
6832 fragP->fr_subtype = real_range_type;
6833 break;
6837 return diff + adjust;
6840 /* Adjust relaxable frag till current frag. */
6842 static int
6843 nds32_adjust_relaxable_frag (fragS *startP, fragS *fragP)
6845 int adj;
6846 if (startP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
6847 adj = -2;
6848 else
6849 adj = 2;
6851 startP->tc_frag_data.flag ^= NDS32_FRAG_RELAXED;
6853 while (startP)
6855 startP = startP->fr_next;
6856 if (startP)
6858 startP->fr_address += adj;
6859 if (startP == fragP)
6860 break;
6863 return adj;
6866 static addressT
6867 nds32_get_align (addressT address, int align)
6869 addressT mask, new_address;
6871 mask = ~((addressT) (~0) << align);
6872 new_address = (address + mask) & (~mask);
6873 return (new_address - address);
6876 /* Check the prev_frag is legal. */
6877 static void
6878 invalid_prev_frag (fragS * fragP, fragS **prev_frag, bool relax)
6880 addressT address;
6881 fragS *frag_start = *prev_frag;
6883 if (!frag_start || !relax)
6884 return;
6886 if (frag_start->last_fr_address >= fragP->last_fr_address)
6888 *prev_frag = NULL;
6889 return;
6892 fragS *frag_t = *prev_frag;
6893 while (frag_t != fragP)
6895 if (frag_t->fr_type == rs_align
6896 || frag_t->fr_type == rs_align_code
6897 || frag_t->fr_type == rs_align_test)
6899 /* Relax instruction can not walk across label. */
6900 if (frag_t->tc_frag_data.flag & NDS32_FRAG_LABEL)
6902 prev_frag = NULL;
6903 return;
6905 /* Relax previous relaxable to align rs_align frag. */
6906 address = frag_t->fr_address + frag_t->fr_fix;
6907 addressT offset = nds32_get_align (address, (int) frag_t->fr_offset);
6908 if (offset & 0x2)
6910 /* If there is label on the prev_frag, check if it is aligned. */
6911 if (!((*prev_frag)->tc_frag_data.flag & NDS32_FRAG_LABEL)
6912 || (((*prev_frag)->fr_address + (*prev_frag)->fr_fix - 2 )
6913 & 0x2) == 0)
6914 nds32_adjust_relaxable_frag (*prev_frag, frag_t);
6916 *prev_frag = NULL;
6917 return;
6919 frag_t = frag_t->fr_next;
6922 if (fragP->tc_frag_data.flag & NDS32_FRAG_ALIGN)
6924 address = fragP->fr_address;
6925 addressT offset = nds32_get_align (address, 2);
6926 if (offset & 0x2)
6928 /* If there is label on the prev_frag, check if it is aligned. */
6929 if (!((*prev_frag)->tc_frag_data.flag & NDS32_FRAG_LABEL)
6930 || (((*prev_frag)->fr_address + (*prev_frag)->fr_fix - 2 )
6931 & 0x2) == 0)
6932 nds32_adjust_relaxable_frag (*prev_frag, fragP);
6934 *prev_frag = NULL;
6935 return;
6939 /* md_relax_frag */
6942 nds32_relax_frag (segT segment, fragS *fragP, long stretch ATTRIBUTE_UNUSED)
6944 /* Currently, there are two kinds of relaxation in nds32 assembler.
6945 1. relax for branch
6946 2. relax for 32-bits to 16-bits */
6948 static fragS *prev_frag = NULL;
6949 int adjust = 0;
6951 invalid_prev_frag (fragP, &prev_frag, true);
6953 if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
6954 adjust = nds32_relax_branch_instructions (segment, fragP, stretch, 0);
6955 if (fragP->tc_frag_data.flag & NDS32_FRAG_LABEL)
6956 prev_frag = NULL;
6957 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE
6958 && (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED) == 0)
6959 /* Here is considered relaxed case originally. But it may cause
6960 an endless loop when relaxing. Once the instruction is relaxed,
6961 it can not be undone. */
6962 prev_frag = fragP;
6964 return adjust;
6967 /* This function returns an initial guess of the length by which a fragment
6968 must grow to hold a branch to reach its destination. Also updates
6969 fr_type/fr_subtype as necessary.
6971 It is called just before doing relaxation. Any symbol that is now undefined
6972 will not become defined. The guess for fr_var is ACTUALLY the growth beyond
6973 fr_fix. Whatever we do to grow fr_fix or fr_var contributes to our returned
6974 value. Although it may not be explicit in the frag, pretend fr_var starts
6975 with a 0 value. */
6978 md_estimate_size_before_relax (fragS *fragP, segT segment)
6980 /* Currently, there are two kinds of relaxation in nds32 assembler.
6981 1. relax for branch
6982 2. relax for 32-bits to 16-bits */
6984 /* Save previous relaxable frag. */
6985 static fragS *prev_frag = NULL;
6986 int adjust = 0;
6988 invalid_prev_frag (fragP, &prev_frag, false);
6990 if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
6991 adjust = nds32_relax_branch_instructions (segment, fragP, 0, 1);
6992 if (fragP->tc_frag_data.flag & NDS32_FRAG_LABEL)
6993 prev_frag = NULL;
6994 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
6995 adjust = 2;
6996 else if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE)
6997 prev_frag = fragP;
6999 return adjust;
7002 /* GAS will call this for each rs_machine_dependent fragment. The instruction
7003 is completed using the data from the relaxation pass. It may also create any
7004 necessary relocations.
7006 *FRAGP has been relaxed to its final size, and now needs to have the bytes
7007 inside it modified to conform to the new size. It is called after relaxation
7008 is finished.
7010 fragP->fr_type == rs_machine_dependent.
7011 fragP->fr_subtype is the subtype of what the address relaxed to. */
7013 void
7014 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP)
7016 /* Convert branch relaxation instructions. */
7017 symbolS *branch_symbol = fragP->fr_symbol;
7018 offsetT branch_offset = fragP->fr_offset;
7019 enum nds32_br_range branch_range_type = fragP->fr_subtype;
7020 struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
7021 uint32_t origin_insn = fragP->tc_frag_data.insn;
7022 relax_info_t *relax_info;
7023 char *fr_buffer;
7024 int fr_where;
7025 int addend ATTRIBUTE_UNUSED;
7026 offsetT branch_target_address, branch_insn_address;
7027 expressionS exp;
7028 fixS *fixP;
7029 uint32_t *code_seq;
7030 uint32_t insn;
7031 int code_size, insn_size, offset, fixup_size;
7032 int buf_offset, pcrel;
7033 int i, k;
7034 uint16_t insn_16;
7035 nds32_relax_fixup_info_t fixup_info[MAX_RELAX_FIX];
7036 /* Save the 1st instruction is converted to 16 bit or not. */
7037 unsigned int branch_size;
7038 enum bfd_reloc_code_real final_r_type;
7040 /* Replace with gas_assert (branch_symbol != NULL); */
7041 if (branch_symbol == NULL && !(fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED))
7042 return;
7044 /* If frag_var is not enough room, the previous frag is fr_full and with
7045 opcode. The new one is rs_dependent but without opcode. */
7046 if (opcode == NULL)
7047 return;
7049 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE_BRANCH)
7051 relax_info = str_hash_find (nds32_relax_info_hash, opcode->opcode);
7053 if (relax_info == NULL)
7054 return;
7056 i = BR_RANGE_S256;
7057 while (i < BR_RANGE_NUM
7058 && relax_info->relax_code_size[i]
7059 != (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED ? 4 : 2))
7060 i++;
7062 if (i >= BR_RANGE_NUM)
7063 as_bad ("Internal error: Cannot find relocation of"
7064 "relaxable branch.");
7066 exp.X_op = O_symbol;
7067 exp.X_add_symbol = branch_symbol;
7068 exp.X_add_number = branch_offset;
7069 pcrel = ((relax_info->relax_fixup[i][0].ramp & NDS32_PCREL) != 0) ? 1 : 0;
7070 fr_where = fragP->fr_fix - 2;
7071 fixP = fix_new_exp (fragP, fr_where, relax_info->relax_fixup[i][0].size,
7072 &exp, pcrel, relax_info->relax_fixup[i][0].r_type);
7073 fixP->fx_addnumber = fixP->fx_offset;
7075 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
7077 insn_16 = fragP->tc_frag_data.insn;
7078 nds32_convert_16_to_32 (stdoutput, insn_16, &insn);
7079 fr_buffer = fragP->fr_literal + fr_where;
7080 fragP->fr_fix += 2;
7081 exp.X_op = O_symbol;
7082 exp.X_add_symbol = abs_section_sym;
7083 exp.X_add_number = 0;
7084 fix_new_exp (fragP, fr_where, 4,
7085 &exp, 0, BFD_RELOC_NDS32_INSN16);
7086 number_to_chars_bigendian (fr_buffer, insn, 4);
7089 else if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
7091 if (fragP->tc_frag_data.opcode->isize == 2)
7093 insn_16 = fragP->tc_frag_data.insn;
7094 nds32_convert_16_to_32 (stdoutput, insn_16, &insn);
7096 else
7097 insn = fragP->tc_frag_data.insn;
7098 fragP->fr_fix += 2;
7099 fr_where = fragP->fr_fix - 4;
7100 fr_buffer = fragP->fr_literal + fr_where;
7101 exp.X_op = O_symbol;
7102 exp.X_add_symbol = abs_section_sym;
7103 exp.X_add_number = 0;
7104 fix_new_exp (fragP, fr_where, 4, &exp, 0,
7105 BFD_RELOC_NDS32_INSN16);
7106 number_to_chars_bigendian (fr_buffer, insn, 4);
7108 else if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
7110 /* Branch instruction adjust and append relocations. */
7111 relax_info = str_hash_find (nds32_relax_info_hash, opcode->opcode);
7113 if (relax_info == NULL)
7114 return;
7116 fr_where = fragP->fr_fix - opcode->isize;
7117 fr_buffer = fragP->fr_literal + fr_where;
7119 if ((S_GET_SEGMENT (branch_symbol) != sec)
7120 || S_IS_WEAK (branch_symbol))
7122 if (fragP->fr_offset & 3)
7123 as_warn (_("Addend to unresolved symbol is not on word boundary."));
7124 addend = 0;
7126 else
7128 /* Calculate symbol-to-instruction offset. */
7129 branch_target_address = S_GET_VALUE (branch_symbol) + branch_offset;
7130 branch_insn_address = fragP->fr_address + fr_where;
7131 addend = (branch_target_address - branch_insn_address) >> 1;
7134 code_size = relax_info->relax_code_size[branch_range_type];
7135 code_seq = relax_info->relax_code_seq[branch_range_type];
7137 memcpy (fixup_info, relax_info->relax_fixup[branch_range_type],
7138 sizeof (fixup_info));
7140 /* Fill in frag. */
7141 i = 0;
7142 k = 0;
7143 offset = 0; /* code_seq offset */
7144 buf_offset = 0; /* fr_buffer offset */
7145 while (offset < code_size)
7147 insn = code_seq[i];
7148 if (insn & 0x80000000) /* 16-bits instruction. */
7150 insn = (insn >> 16) & 0xFFFF;
7151 insn_size = 2;
7153 else /* 32-bits instruction. */
7155 insn_size = 4;
7158 nds32_elf_get_set_cond (relax_info, offset, &insn,
7159 origin_insn, branch_range_type);
7161 /* Try to convert to 16-bits instruction. Currently, only the first
7162 instruction in pattern can be converted. EX: bnez sethi ori jr,
7163 only bnez can be converted to 16 bit and ori can't. */
7165 while (fixup_info[k].size != 0
7166 && relax_info->relax_fixup[branch_range_type][k].offset < offset)
7167 k++;
7169 number_to_chars_bigendian (fr_buffer + buf_offset, insn, insn_size);
7170 buf_offset += insn_size;
7172 offset += insn_size;
7173 i++;
7176 /* Set up fixup. */
7177 exp.X_op = O_symbol;
7179 for (i = 0; fixup_info[i].size != 0; i++)
7181 fixup_size = fixup_info[i].size;
7182 pcrel = ((fixup_info[i].ramp & NDS32_PCREL) != 0) ? 1 : 0;
7184 if ((fixup_info[i].ramp & NDS32_CREATE_LABEL) != 0)
7186 /* This is a reverse branch. */
7187 exp.X_add_symbol = symbol_temp_new (sec, fragP->fr_next, 0);
7188 exp.X_add_number = 0;
7190 else if ((fixup_info[i].ramp & NDS32_PTR) != 0)
7192 /* This relocation has to point to another instruction. */
7193 branch_size = fr_where + code_size - 4;
7194 exp.X_add_symbol = symbol_temp_new (sec, fragP, branch_size);
7195 exp.X_add_number = 0;
7197 else if ((fixup_info[i].ramp & NDS32_ABS) != 0)
7199 /* This is a tag relocation. */
7200 exp.X_add_symbol = abs_section_sym;
7201 exp.X_add_number = 0;
7203 else if ((fixup_info[i].ramp & NDS32_INSN16) != 0)
7205 if (!enable_16bit)
7206 continue;
7207 /* This is a tag relocation. */
7208 exp.X_add_symbol = abs_section_sym;
7209 exp.X_add_number = 0;
7211 else
7213 exp.X_add_symbol = branch_symbol;
7214 exp.X_add_number = branch_offset;
7217 if (fixup_info[i].r_type != 0)
7219 final_r_type = fixup_info[i].r_type;
7220 fixP = fix_new_exp (fragP, fr_where + fixup_info[i].offset,
7221 fixup_size, &exp, pcrel,
7222 final_r_type);
7223 fixP->fx_addnumber = fixP->fx_offset;
7227 fragP->fr_fix = fr_where + buf_offset;
7231 /* tc_frob_file_before_fix */
7233 void
7234 nds32_frob_file_before_fix (void)
7238 static bool
7239 nds32_relaxable_section (asection *sec)
7241 return ((sec->flags & SEC_DEBUGGING) == 0
7242 && strcmp (sec->name, ".eh_frame") != 0);
7245 /* TC_FORCE_RELOCATION */
7247 nds32_force_relocation (fixS * fix)
7249 switch (fix->fx_r_type)
7251 case BFD_RELOC_NDS32_INSN16:
7252 case BFD_RELOC_NDS32_LABEL:
7253 case BFD_RELOC_NDS32_LONGCALL1:
7254 case BFD_RELOC_NDS32_LONGCALL2:
7255 case BFD_RELOC_NDS32_LONGCALL3:
7256 case BFD_RELOC_NDS32_LONGJUMP1:
7257 case BFD_RELOC_NDS32_LONGJUMP2:
7258 case BFD_RELOC_NDS32_LONGJUMP3:
7259 case BFD_RELOC_NDS32_LOADSTORE:
7260 case BFD_RELOC_NDS32_9_FIXED:
7261 case BFD_RELOC_NDS32_15_FIXED:
7262 case BFD_RELOC_NDS32_17_FIXED:
7263 case BFD_RELOC_NDS32_25_FIXED:
7264 case BFD_RELOC_NDS32_9_PCREL:
7265 case BFD_RELOC_NDS32_15_PCREL:
7266 case BFD_RELOC_NDS32_17_PCREL:
7267 case BFD_RELOC_NDS32_WORD_9_PCREL:
7268 case BFD_RELOC_NDS32_10_UPCREL:
7269 case BFD_RELOC_NDS32_25_PCREL:
7270 case BFD_RELOC_NDS32_MINUEND:
7271 case BFD_RELOC_NDS32_SUBTRAHEND:
7272 return 1;
7274 case BFD_RELOC_8:
7275 case BFD_RELOC_16:
7276 case BFD_RELOC_32:
7277 case BFD_RELOC_NDS32_DIFF_ULEB128:
7278 /* Linker should handle difference between two symbol. */
7279 return fix->fx_subsy != NULL
7280 && nds32_relaxable_section (S_GET_SEGMENT (fix->fx_addsy));
7281 case BFD_RELOC_64:
7282 if (fix->fx_subsy)
7283 as_bad ("Double word for difference between two symbols "
7284 "is not supported across relaxation.");
7285 default:
7289 if (generic_force_reloc (fix))
7290 return 1;
7292 return fix->fx_pcrel;
7295 /* TC_VALIDATE_FIX_SUB */
7298 nds32_validate_fix_sub (fixS *fix, segT add_symbol_segment)
7300 segT sub_symbol_segment;
7302 /* This code is referred from Xtensa. Check their implementation for
7303 details. */
7305 /* Make sure both symbols are in the same segment, and that segment is
7306 "normal" and relaxable. */
7307 sub_symbol_segment = S_GET_SEGMENT (fix->fx_subsy);
7308 return (sub_symbol_segment == add_symbol_segment
7309 && add_symbol_segment != undefined_section);
7312 void
7313 md_number_to_chars (char *buf, valueT val, int n)
7315 if (target_big_endian)
7316 number_to_chars_bigendian (buf, val, n);
7317 else
7318 number_to_chars_littleendian (buf, val, n);
7321 /* This function is called to convert an ASCII string into a floating point
7322 value in format used by the CPU. */
7324 const char *
7325 md_atof (int type, char *litP, int *sizeP)
7327 int i;
7328 int prec;
7329 LITTLENUM_TYPE words[MAX_LITTLENUMS];
7330 char *t;
7332 switch (type)
7334 case 'f':
7335 case 'F':
7336 case 's':
7337 case 'S':
7338 prec = 2;
7339 break;
7340 case 'd':
7341 case 'D':
7342 case 'r':
7343 case 'R':
7344 prec = 4;
7345 break;
7346 default:
7347 *sizeP = 0;
7348 return _("Bad call to md_atof()");
7351 t = atof_ieee (input_line_pointer, type, words);
7352 if (t)
7353 input_line_pointer = t;
7354 *sizeP = prec * sizeof (LITTLENUM_TYPE);
7356 if (target_big_endian)
7358 for (i = 0; i < prec; i++)
7360 md_number_to_chars (litP, (valueT) words[i],
7361 sizeof (LITTLENUM_TYPE));
7362 litP += sizeof (LITTLENUM_TYPE);
7365 else
7367 for (i = prec - 1; i >= 0; i--)
7369 md_number_to_chars (litP, (valueT) words[i],
7370 sizeof (LITTLENUM_TYPE));
7371 litP += sizeof (LITTLENUM_TYPE);
7375 return 0;
7378 /* md_elf_section_change_hook */
7380 void
7381 nds32_elf_section_change_hook (void)
7385 /* md_cleanup */
7387 void
7388 nds32_cleanup (void)
7392 /* This function is used to scan leb128 subtraction expressions,
7393 and insert fixups for them.
7395 e.g., .leb128 .L1 - .L0
7397 These expressions are heavily used in debug information or
7398 exception tables. Because relaxation will change code size,
7399 we must resolve them in link time. */
7401 static void
7402 nds32_insert_leb128_fixes (bfd *abfd ATTRIBUTE_UNUSED,
7403 asection *sec, void *xxx ATTRIBUTE_UNUSED)
7405 segment_info_type *seginfo = seg_info (sec);
7406 struct frag *fragP;
7408 subseg_set (sec, 0);
7410 for (fragP = seginfo->frchainP->frch_root;
7411 fragP; fragP = fragP->fr_next)
7413 expressionS *exp;
7415 /* Only unsigned leb128 can be handle. */
7416 if (fragP->fr_type != rs_leb128 || fragP->fr_subtype != 0
7417 || fragP->fr_symbol == NULL)
7418 continue;
7420 exp = symbol_get_value_expression (fragP->fr_symbol);
7422 if (exp->X_op != O_subtract)
7423 continue;
7425 fix_new_exp (fragP, fragP->fr_fix, 0,
7426 exp, 0, BFD_RELOC_NDS32_DIFF_ULEB128);
7430 static void
7431 nds32_insert_relax_entry (bfd *abfd ATTRIBUTE_UNUSED, asection *sec,
7432 void *xxx ATTRIBUTE_UNUSED)
7434 segment_info_type *seginfo;
7435 fragS *fragP;
7436 fixS *fixP;
7437 expressionS exp;
7438 fixS *fixp;
7440 seginfo = seg_info (sec);
7441 if (!seginfo || !symbol_rootP || !subseg_text_p (sec) || sec->size == 0)
7442 return;
7444 for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
7445 if (!fixp->fx_done)
7446 break;
7448 if (!fixp && !verbatim && ict_flag == ICT_NONE)
7449 return;
7451 subseg_change (sec, 0);
7453 /* Set RELAX_ENTRY flags for linker. */
7454 fragP = seginfo->frchainP->frch_root;
7455 exp.X_op = O_symbol;
7456 exp.X_add_symbol = abs_section_sym;
7457 exp.X_add_number = 0;
7458 if (!enable_relax_relocs)
7459 exp.X_add_number |= R_NDS32_RELAX_ENTRY_DISABLE_RELAX_FLAG;
7460 else
7462 /* These flags are only enabled when global relax is enabled.
7463 Maybe we can check DISABLE_RELAX_FLAG at link-time,
7464 so we set them anyway. */
7465 if (verbatim)
7466 exp.X_add_number |= R_NDS32_RELAX_ENTRY_VERBATIM_FLAG;
7467 if (ict_flag == ICT_SMALL)
7468 exp.X_add_number |= R_NDS32_RELAX_ENTRY_ICT_SMALL;
7469 else if (ict_flag == ICT_LARGE)
7470 exp.X_add_number |= R_NDS32_RELAX_ENTRY_ICT_LARGE;
7472 if (optimize)
7473 exp.X_add_number |= R_NDS32_RELAX_ENTRY_OPTIMIZE_FLAG;
7474 if (optimize_for_space)
7475 exp.X_add_number |= R_NDS32_RELAX_ENTRY_OPTIMIZE_FOR_SPACE_FLAG;
7477 fixP = fix_new_exp (fragP, 0, 0, &exp, 0, BFD_RELOC_NDS32_RELAX_ENTRY);
7478 fixP->fx_no_overflow = 1;
7481 /* Analysis relax hint and insert suitable relocation pattern. */
7483 static void
7484 nds32_elf_analysis_relax_hint (void)
7486 htab_traverse (nds32_hint_hash, 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_end (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);