1 /* tc-nds32.c -- Assemble for the nds32
2 Copyright (C) 2012-2013 Free Software Foundation, Inc.
3 Contributed by Andes Technology Corporation.
5 This file is part of GAS, the GNU Assembler.
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to the Free
19 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
23 #include "safe-ctype.h"
26 #include "dwarf2dbg.h"
27 #include "dw2gencfi.h"
28 #include "opcodes/nds32-asm.h"
29 #include "elf/nds32.h"
30 #include "bfd/elf32-nds32.h"
34 #include "struc-symbol.h"
35 #include "opcode/nds32.h"
39 /* GAS definitions. */
41 /* Characters which start a comment. */
42 const char comment_chars
[] = "!";
43 /* Characters which start a comment when they appear at the start of a line. */
44 const char line_comment_chars
[] = "#!";
45 /* Characters which separate lines (null and newline are by default). */
46 const char line_separator_chars
[] = ";";
47 /* Characters which may be used as the exponent character
48 in a floating point number. */
49 const char EXP_CHARS
[] = "eE";
50 /* Characters which may be used to indicate a floating point constant. */
51 const char FLT_CHARS
[] = "dDfF";
53 static int enable_16bit
= 1;
54 /* Save for md_assemble to distinguish if this instruction is
55 expanded from the pseudo instruction. */
56 static bfd_boolean pseudo_opcode
= FALSE
;
57 static struct nds32_relocs_pattern
*relocs_list
= NULL
;
58 struct nds32_relocs_pattern
68 struct nds32_relocs_pattern
*next
;
71 static int relax_jal_bound = 3;
72 static int multi_call_relax;
73 static int pltgot_call_relax;
75 static int vec_size
= 0;
76 /* If the assembly code is generated by compiler, it is supposed to have
77 ".flag verbatim" at beginning of the content. We have
78 'nds32_flag' to parse it and set this field to be non-zero. */
79 static int verbatim
= 0;
80 static struct hash_control
*nds32_gprs_hash
;
81 static struct hash_control
*nds32_hint_hash
;
83 /* Generate relocation for relax or not, and the default is true. */
84 static int enable_relax_relocs
= 1;
85 /* The value will be used in RELAX_ENTRY. */
86 static int enable_relax_ex9
= 0;
87 /* The value will be used in RELAX_ENTRY. */
88 static int enable_relax_ifc
= 0;
89 /* Save option -O for perfomance. */
90 static int optimize
= 0;
91 /* Save option -Os for code size. */
92 static int optimize_for_space
= 0;
94 struct nds32_keyword nds32_fsrs
[] =
97 {"$fs0", 0, 0}, {"$fs1", 1, 0}, {"$fs2", 2, 0}, {"$fs3", 3, 0},
98 {"$fs4", 4, 0}, {"$fs5", 5, 0}, {"$fs6", 6, 0}, {"$fs7", 7, 0},
99 {"$fs8", 8, 0}, {"$fs9", 9, 0}, {"$fs10", 10, 0}, {"$fs11", 11, 0},
100 {"$fs12", 12, 0}, {"$fs13", 13, 0}, {"$fs14", 14, 0}, {"$fs15", 15, 0},
101 {"$fs16", 16, 0}, {"$fs17", 17, 0}, {"$fs18", 18, 0}, {"$fs19", 19, 0},
102 {"$fs20", 20, 0}, {"$fs21", 21, 0}, {"$fs22", 22, 0}, {"$fs23", 23, 0},
103 {"$fs24", 24, 0}, {"$fs25", 25, 0}, {"$fs26", 26, 0}, {"$fs27", 27, 0},
104 {"$fs28", 28, 0}, {"$fs29", 29, 0}, {"$fs30", 30, 0}, {"$fs31", 31, 0},
108 struct nds32_keyword nds32_fdrs
[] =
110 /* Standard names. */
111 {"$fd0", 0, 0}, {"$fd1", 1, 0}, {"$fd2", 2, 0}, {"$fd3", 3, 0},
112 {"$fd4", 4, 0}, {"$fd5", 5, 0}, {"$fd6", 6, 0}, {"$fd7", 7, 0},
113 {"$fd8", 8, 0}, {"$fd9", 9, 0}, {"$fd10", 10, 0}, {"$fd11", 11, 0},
114 {"$fd12", 12, 0}, {"$fd13", 13, 0}, {"$fd14", 14, 0}, {"$fd15", 15, 0},
115 {"$fd16", 16, 0}, {"$fd17", 17, 0}, {"$fd18", 18, 0}, {"$fd19", 19, 0},
116 {"$fd20", 20, 0}, {"$fd21", 21, 0}, {"$fd22", 22, 0}, {"$fd23", 23, 0},
117 {"$fd24", 24, 0}, {"$fd25", 25, 0}, {"$fd26", 26, 0}, {"$fd27", 27, 0},
118 {"$fd28", 28, 0}, {"$fd29", 29, 0}, {"$fd30", 30, 0}, {"$fd31", 31, 0},
122 struct nds32_keyword nds32_gprs
[] =
124 /* Standard names. */
125 {"$r0", 0, 0}, {"$r1", 1, 0}, {"$r2", 2, 0}, {"$r3", 3, 0},
126 {"$r4", 4, 0}, {"$r5", 5, 0}, {"$r6", 6, 0}, {"$r7", 7, 0},
127 {"$r8", 8, 0}, {"$r9", 9, 0}, {"$r10", 10, 0}, {"$r11", 11, 0},
128 {"$r12", 12, 0}, {"$r13", 13, 0}, {"$r14", 14, 0}, {"$r15", 15, 0},
129 {"$r16", 16, 0}, {"$r17", 17, 0}, {"$r18", 18, 0}, {"$r19", 19, 0},
130 {"$r20", 20, 0}, {"$r21", 21, 0}, {"$r22", 22, 0}, {"$r23", 23, 0},
131 {"$r24", 24, 0}, {"$r25", 25, 0}, {"$r26", 26, 0}, {"$r27", 27, 0},
132 {"$r28", 28, 0}, {"$r29", 29, 0}, {"$r30", 30, 0}, {"$r31", 31, 0},
133 /* Names for parameter passing. */
134 {"$a0", 0, 0}, {"$a1", 1, 0}, {"$a2", 2, 0}, {"$a3", 3, 0},
135 {"$a4", 4, 0}, {"$a5", 5, 0},
136 /* Names reserved for 5-bit addressing only. */
137 {"$s0", 6, 0}, {"$s1", 7, 0}, {"$s2", 8, 0}, {"$s3", 9, 0},
138 {"$s4", 10, 0}, {"$s5", 11, 0}, {"$s6", 12, 0}, {"$s7", 13, 0},
139 {"$s8", 14, 0}, {"$s9", 28, 0},
141 {"$t0", 16, 0}, {"$t1", 17, 0}, {"$t2", 18, 0}, {"$t3", 19, 0},
142 {"$t4", 20, 0}, {"$t5", 21, 0}, {"$t6", 22, 0}, {"$t7", 23, 0},
143 {"$t8", 24, 0}, {"$t9", 25, 0},
144 {"$p0", 26, 0}, {"$p1", 27, 0},
145 {"$fp", 28, 0}, {"$gp", 29, 0}, {"$lp", 30, 0}, {"$sp", 31, 0},
146 /* Names reserved for 4-bit addressing only. */
147 {"$h0", 0, 0}, {"$h1", 1, 0}, {"$h2", 2, 0}, {"$h3", 3, 0},
148 {"$h4", 4, 0}, {"$h5", 5, 0}, {"$h6", 6, 0}, {"$h7", 7, 0},
149 {"$h8", 8, 0}, {"$h9", 9, 0}, {"$h10", 10, 0}, {"$h11", 11, 0},
150 {"$h12", 16, 0}, {"$h13", 17, 0}, {"$h14", 18, 0}, {"$h15", 19, 0},
151 /* Names reserved for 3-bit addressing only. */
152 {"$o0", 0, 0}, {"$o1", 1, 0}, {"$o2", 2, 0}, {"$o3", 3, 0},
153 {"$o4", 4, 0}, {"$o5", 5, 0}, {"$o6", 6, 0}, {"$o7", 7, 0},
158 static struct hash_control
*nds32_relax_info_hash
;
159 static relax_info_t relax_table
[] =
163 BR_RANGE_S16M
, /* br_range */
164 {{0, 0, 0}}, /* cond_field */
167 INSN_JAL
/* jal label */
168 }, /* BR_RANGE_S256 */
170 INSN_JAL
/* jal label */
171 }, /* BR_RANGE_S16K */
173 INSN_JAL
/* jal label */
174 }, /* BR_RANGE_S64K */
176 INSN_JAL
/* jal label */
177 }, /* BR_RANGE_S16M */
179 INSN_SETHI_TA
, /* sethi $ta, label */
180 INSN_ORI_TA
, /* ori $ta, $ta, label */
182 }, /* BR_RANGE_U4G */
183 }, /* relax_code_seq */
185 {{0, 0, 0}}, /* BR_RANGE_S256 */
186 {{0, 0, 0}}, /* BR_RANGE_S16K */
187 {{0, 0, 0}}, /* BR_RANGE_S64K */
188 {{0, 0, 0}}, /* BR_RANGE_S16M */
189 {{0, 0, 0}} /* BR_RANGE_U4G */
190 }, /* relax_code_condition */
191 {4, 4, 4, 4, 12}, /* relax_code_size */
192 {4, 4, 4, 4, 4}, /* relax_branch_isize */
195 {0, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
197 }, /* BR_RANGE_S256 */
199 {0, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
201 }, /* BR_RANGE_S16K */
203 {0, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
205 }, /* BR_RANGE_S64K */
207 {0, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
209 }, /* BR_RANGE_S16M */
211 {0, 4, 0, BFD_RELOC_NDS32_HI20
},
212 {0, 12, NDS32_RELAX
, BFD_RELOC_NDS32_LONGCALL1
},
213 {4, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI
},
214 {8, 4, NDS32_ORIGIN
, 0},
215 {8, 2, NDS32_CONVERT
, 0},
221 "bltzal", /* opcode */
222 BR_RANGE_S64K
, /* br_range */
229 INSN_BLTZAL
/* bltzal $rt, label */
230 }, /* BR_RANGE_S256 */
232 INSN_BLTZAL
/* bltzal $rt, label */
233 }, /* BR_RANGE_S16K */
235 INSN_BLTZAL
/* bltzal $rt, label */
236 }, /* BR_RANGE_S64K */
238 INSN_BGEZ
, /* bgez $rt, $1 */
239 INSN_JAL
/* jal label */
240 }, /* BR_RANGE_S16M */
242 INSN_BGEZ
, /* bgez $rt, $1 */
243 INSN_SETHI_TA
, /* sethi $ta, label */
244 INSN_ORI_TA
, /* ori $ta, $ta, label */
245 INSN_JRAL_TA
/* jral $ta */
247 }, /* relax_code_seq */
252 }, /* BR_RANGE_S256 */
256 }, /* BR_RANGE_S16K */
260 }, /* BR_RANGE_S64K */
264 }, /* BR_RANGE_S16M */
269 }, /* relax_code_condition */
270 {4, 4, 4, 8, 16}, /* relax_code_size */
271 {4, 4, 4, 4, 4}, /* relax_branch_isize */
274 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
276 }, /* BR_RANGE_S256 */
278 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
280 }, /* BR_RANGE_S16K */
282 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
284 }, /* BR_RANGE_S64K */
286 {0, 4, NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_17_PCREL
},
287 {0, 8, NDS32_RELAX
, BFD_RELOC_NDS32_LONGCALL2
},
288 {4, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
290 }, /* BR_RANGE_S16M */
292 {0, 4, NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_17_PCREL
},
293 {0, 16, NDS32_RELAX
, BFD_RELOC_NDS32_LONGCALL3
},
294 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
295 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI
},
296 {12, 4, NDS32_ORIGIN
, 0},
297 {12, 2, NDS32_CONVERT
, 0},
303 "bgezal", /* opcode */
304 BR_RANGE_S64K
, /* br_range */
311 INSN_BGEZAL
/* bgezal $rt, label */
312 }, /* BR_RANGE_S256 */
314 INSN_BGEZAL
/* bgezal $rt, label */
315 }, /* BR_RANGE_S16K */
317 INSN_BGEZAL
/* bgezal $rt, label */
318 }, /* BR_RANGE_S64K */
320 INSN_BLTZ
, /* bltz $rt, $1 */
321 INSN_JAL
/* jal label */
322 }, /* BR_RANGE_S16M */
324 INSN_BLTZ
, /* bltz $rt, $1 */
325 INSN_SETHI_TA
, /* sethi $ta, label */
326 INSN_ORI_TA
, /* ori $ta, $ta, label */
327 INSN_JRAL_TA
/* jral $ta */
329 }, /* relax_code_seq */
334 }, /* BR_RANGE_S256 */
338 }, /* BR_RANGE_S16K */
342 }, /* BR_RANGE_S64K */
346 }, /* BR_RANGE_S16M */
351 }, /* relax_code_condition */
352 {4, 4, 4, 8, 16}, /* relax_code_size */
353 {4, 4, 4, 4, 4}, /* relax_branch_isize */
356 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
358 }, /* BR_RANGE_S256 */
360 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
362 }, /* BR_RANGE_S16K */
364 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
366 }, /* BR_RANGE_S64K */
368 {0, 4, NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_17_PCREL
},
369 {0, 8, NDS32_RELAX
, BFD_RELOC_NDS32_LONGCALL2
},
370 {4, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
372 }, /* BR_RANGE_S16M */
374 {0, 4, NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_17_PCREL
},
375 {0, 16, NDS32_RELAX
, BFD_RELOC_NDS32_LONGCALL3
},
376 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
377 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI
},
378 {12, 4, NDS32_ORIGIN
, 0},
379 {12, 2, NDS32_CONVERT
, 0},
386 BR_RANGE_S16M
, /* br_range */
387 {{0, 0, 0}}, /* cond_field */
390 (INSN_J8
<< 16) /* j8 label */
391 }, /* BR_RANGE_S256 */
394 }, /* BR_RANGE_S16K */
397 }, /* BR_RANGE_S64K */
400 }, /* BR_RANGE_S16M */
402 INSN_SETHI_TA
, /* sethi $ta, label */
403 INSN_ORI_TA
, /* ori $ta, $ta, label */
404 INSN_JR_TA
/* jr $ta */
405 }, /* BR_RANGE_U4G */
406 }, /* relax_code_seq */
408 {{0, 0, 0}}, /* BR_RANGE_S256 */
409 {{0, 0, 0}}, /* BR_RANGE_S16K */
410 {{0, 0, 0}}, /* BR_RANGE_S64K */
411 {{0, 0, 0}}, /* BR_RANGE_S16M */
412 {{0, 0, 0}} /* BR_RANGE_U4G */
413 }, /* relax_code_condition */
414 {2, 4, 4, 4, 12}, /* relax_code_size */
415 {2, 4, 4, 4, 4}, /* relax_branch_isize */
418 {0, 2, 0, BFD_RELOC_NDS32_9_PCREL
},
420 }, /* BR_RANGE_S256 */
422 {0, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
424 }, /* BR_RANGE_S16K */
426 {0, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
428 }, /* BR_RANGE_S64K */
430 {0, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
432 }, /* BR_RANGE_S16M */
434 {0, 4, 0, BFD_RELOC_NDS32_HI20
},
435 {0, 12, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP1
},
436 {4, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI
},
437 {8, 4, NDS32_ORIGIN
, 0},
438 {8, 2, NDS32_CONVERT
, 0},
445 BR_RANGE_S256
, /* br_range */
446 {{0, 0, 0}}, /* cond_field */
449 (INSN_J8
<< 16) /* j8 label */
450 }, /* BR_RANGE_S256 */
453 }, /* BR_RANGE_S16K */
456 }, /* BR_RANGE_S64K */
459 }, /* BR_RANGE_S16M */
461 INSN_SETHI_TA
, /* sethi $ta, label */
462 INSN_ORI_TA
, /* ori $ta, $ta, label */
463 INSN_JR_TA
/* jr $ta */
464 }, /* BR_RANGE_U4G */
465 }, /* relax_code_seq */
467 {{0, 0, 0}}, /* BR_RANGE_S256 */
468 {{0, 0, 0}}, /* BR_RANGE_S16K */
469 {{0, 0, 0}}, /* BR_RANGE_S64K */
470 {{0, 0, 0}}, /* BR_RANGE_S16M */
471 {{0, 0, 0}} /* BR_RANGE_U4G */
472 }, /* relax_code_condition */
473 {2, 4, 4, 4, 12}, /* relax_code_size */
474 {2, 4, 4, 4, 4}, /* relax_branch_isize */
477 {0, 2, 0, BFD_RELOC_NDS32_9_PCREL
},
479 }, /* BR_RANGE_S256 */
481 {0, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
483 }, /* BR_RANGE_S16K */
485 {0, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
487 }, /* BR_RANGE_S64K */
489 {0, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
491 }, /* BR_RANGE_S16M */
493 {0, 4, 0, BFD_RELOC_NDS32_HI20
},
494 {0, 12, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP1
},
495 {4, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI
},
496 {8, 4, NDS32_ORIGIN
, 0},
497 {8, 2, NDS32_CONVERT
, 0},
504 BR_RANGE_S64K
, /* br_range */
511 INSN_BEQZ
/* beqz $rt, label */
512 }, /* BR_RANGE_S256 */
514 INSN_BEQZ
/* beqz $rt, label */
515 }, /* BR_RANGE_S16K */
517 INSN_BEQZ
/* beqz $rt, label */
518 }, /* BR_RANGE_S64K */
520 INSN_BNEZ
, /* bnez $rt, $1 */
522 }, /* BR_RANGE_S16M */
524 INSN_BNEZ
, /* bnez $rt, $1 */
525 INSN_SETHI_TA
, /* sethi $ta, label */
526 INSN_ORI_TA
, /* ori $ta, $ta, label */
527 INSN_JR_TA
/* jr $ta */
529 }, /* relax_code_seq */
534 }, /* BR_RANGE_S256 */
538 }, /* BR_RANGE_S16K */
542 }, /* BR_RANGE_S64K */
546 }, /* BR_RANGE_S16M */
551 }, /* relax_code_condition */
552 {4, 4, 4, 8, 16}, /* relax_code_size */
553 {4, 4, 4, 4, 4}, /* relax_branch_isize */
556 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
557 {0, 2, NDS32_CONVERT
, BFD_RELOC_NDS32_9_PCREL
},
559 }, /* BR_RANGE_S256 */
561 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
563 }, /* BR_RANGE_S16K */
565 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
567 }, /* BR_RANGE_S64K */
569 {0, 4, NDS32_ORIGIN
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
570 {0, 2, NDS32_CONVERT
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_9_PCREL
},
571 {0, 8, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP2
},
572 {4, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
574 }, /* BR_RANGE_S16M */
576 {0, 4, NDS32_ORIGIN
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
577 {0, 2, NDS32_CONVERT
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_9_PCREL
},
578 {0, 16, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP3
},
579 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
580 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI
},
581 {12, 4, NDS32_ORIGIN
, 0},
582 {12, 2, NDS32_CONVERT
, 0},
589 BR_RANGE_S64K
, /* br_range */
596 INSN_BGEZ
/* bgez $rt, label */
597 }, /* BR_RANGE_S256 */
599 INSN_BGEZ
/* bgez $rt, label */
600 }, /* BR_RANGE_S16K */
602 INSN_BGEZ
/* bgez $rt, label */
603 }, /* BR_RANGE_S64K */
605 INSN_BLTZ
, /* bltz $rt, $1 */
607 }, /* BR_RANGE_S16M */
609 INSN_BLTZ
, /* bltz $rt, $1 */
610 INSN_SETHI_TA
, /* sethi $ta, label */
611 INSN_ORI_TA
, /* ori $ta, $ta, label */
612 INSN_JR_TA
/* jr $ta */
614 }, /* relax_code_seq */
619 }, /* BR_RANGE_S256 */
623 }, /* BR_RANGE_S16K */
627 }, /* BR_RANGE_S64K */
631 }, /* BR_RANGE_S16M */
636 }, /* relax_code_condition */
637 {4, 4, 4, 8, 16}, /* relax_code_size */
638 {4, 4, 4, 4, 4}, /* relax_branch_isize */
641 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
643 }, /* BR_RANGE_S256 */
645 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
647 }, /* BR_RANGE_S16K */
649 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
651 }, /* BR_RANGE_S64K */
653 {0, 4, NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
654 {0, 8, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP2
},
655 {4, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
657 }, /* BR_RANGE_S16M */
659 {0, 4, NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
660 {0, 16, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP3
},
661 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
662 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI
},
663 {12, 4, NDS32_ORIGIN
, 0},
664 {12, 2, NDS32_CONVERT
, 0},
671 BR_RANGE_S64K
, /* br_range */
678 INSN_BNEZ
/* bnez $rt, label */
679 }, /* BR_RANGE_S256 */
681 INSN_BNEZ
/* bnez $rt, label */
682 }, /* BR_RANGE_S16K */
684 INSN_BNEZ
/* bnez $rt, label */
685 }, /* BR_RANGE_S64K */
687 INSN_BEQZ
, /* beqz $rt, $1 */
689 }, /* BR_RANGE_S16M */
691 INSN_BEQZ
, /* beqz $rt, $1 */
692 INSN_SETHI_TA
, /* sethi $ta, label */
693 INSN_ORI_TA
, /* ori $ta, $ta, label */
694 INSN_JR_TA
/* jr $ta */
696 }, /* relax_code_seq */
701 }, /* BR_RANGE_S256 */
705 }, /* BR_RANGE_S16K */
709 }, /* BR_RANGE_S64K */
713 }, /* BR_RANGE_S16M */
718 }, /* relax_code_condition */
719 {4, 4, 4, 8, 16}, /* relax_code_size */
720 {4, 4, 4, 4, 4}, /* relax_branch_isize */
723 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
724 {0, 2, NDS32_CONVERT
, BFD_RELOC_NDS32_9_PCREL
},
726 }, /* BR_RANGE_S256 */
728 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
730 }, /* BR_RANGE_S16K */
732 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
734 }, /* BR_RANGE_S64K */
736 {0, 4, NDS32_ORIGIN
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
737 {0, 2, NDS32_CONVERT
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_9_PCREL
},
738 {0, 8, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP2
},
739 {4, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
741 }, /* BR_RANGE_S16M */
743 {0, 4, NDS32_ORIGIN
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
744 {0, 2, NDS32_CONVERT
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_9_PCREL
},
745 {0, 16, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP3
},
746 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
747 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI
},
748 {12, 4, NDS32_ORIGIN
, 0},
749 {12, 2, NDS32_CONVERT
, 0},
756 BR_RANGE_S64K
, /* br_range */
763 INSN_BGTZ
/* bgtz $rt, label */
764 }, /* BR_RANGE_S256 */
766 INSN_BGTZ
/* bgtz $rt, label */
767 }, /* BR_RANGE_S16K */
769 INSN_BGTZ
/* bgtz $rt, label */
770 }, /* BR_RANGE_S64K */
772 INSN_BLEZ
, /* blez $rt, $1 */
774 }, /* BR_RANGE_S16M */
776 INSN_BLEZ
, /* blez $rt, $1 */
777 INSN_SETHI_TA
, /* sethi $ta, label */
778 INSN_ORI_TA
, /* ori $ta, $ta, label */
779 INSN_JR_TA
/* jr $ta */
781 }, /* relax_code_seq */
786 }, /* BR_RANGE_S256 */
790 }, /* BR_RANGE_S16K */
794 }, /* BR_RANGE_S64K */
798 }, /* BR_RANGE_S16M */
803 }, /* relax_code_condition */
804 {4, 4, 4, 8, 16}, /* relax_code_size */
805 {4, 4, 4, 4, 4}, /* relax_branch_isize */
808 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
810 }, /* BR_RANGE_S256 */
812 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
814 }, /* BR_RANGE_S16K */
816 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
818 }, /* BR_RANGE_S64K */
820 {0, 4, NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
821 {0, 8, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP2
},
822 {4, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
824 }, /* BR_RANGE_S16M */
826 {0, 4, NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
827 {0, 16, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP3
},
828 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
829 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI
},
830 {12, 4, NDS32_ORIGIN
, 0},
831 {12, 2, NDS32_CONVERT
, 0},
838 BR_RANGE_S64K
, /* br_range */
845 INSN_BLEZ
/* blez $rt, label */
846 }, /* BR_RANGE_S256 */
848 INSN_BLEZ
/* blez $rt, label */
849 }, /* BR_RANGE_S16K */
851 INSN_BLEZ
/* blez $rt, label */
852 }, /* BR_RANGE_S64K */
854 INSN_BGTZ
, /* bgtz $rt, $1 */
856 }, /* BR_RANGE_S16M */
858 INSN_BGTZ
, /* bgtz $rt, $1 */
859 INSN_SETHI_TA
, /* sethi $ta, label */
860 INSN_ORI_TA
, /* ori $ta, $ta, label */
861 INSN_JR_TA
/* jr $ta */
863 }, /* relax_code_seq */
868 }, /* BR_RANGE_S256 */
872 }, /* BR_RANGE_S16K */
876 }, /* BR_RANGE_S64K */
880 }, /* BR_RANGE_S16M */
885 }, /* relax_code_condition */
886 {4, 4, 4, 8, 16}, /* relax_code_size */
887 {4, 4, 4, 4, 4}, /* relax_branch_isize */
890 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
892 }, /* BR_RANGE_S256 */
894 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
896 }, /* BR_RANGE_S16K */
898 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
900 }, /* BR_RANGE_S64K */
902 {0, 4, NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
903 {0, 8, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP2
},
904 {4, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
906 }, /* BR_RANGE_S16M */
908 {0, 4, NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
909 {0, 16, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP3
},
910 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
911 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI
},
912 {12, 4, NDS32_ORIGIN
, 0},
913 {12, 2, NDS32_CONVERT
, 0},
920 BR_RANGE_S64K
, /* br_range */
927 INSN_BLTZ
/* bltz $rt, label */
928 }, /* BR_RANGE_S256 */
930 INSN_BLTZ
/* bltz $rt, label */
931 }, /* BR_RANGE_S16K */
933 INSN_BLTZ
/* bltz $rt, label */
934 }, /* BR_RANGE_S64K */
936 INSN_BGEZ
, /* bgez $rt, $1 */
938 }, /* BR_RANGE_S16M */
940 INSN_BGEZ
, /* bgez $rt, $1 */
941 INSN_SETHI_TA
, /* sethi $ta, label */
942 INSN_ORI_TA
, /* ori $ta, $ta, label */
943 INSN_JR_TA
/* jr $ta */
945 }, /* relax_code_seq */
950 }, /* BR_RANGE_S256 */
954 }, /* BR_RANGE_S16K */
958 }, /* BR_RANGE_S64K */
962 }, /* BR_RANGE_S16M */
967 }, /* relax_code_condition */
968 {4, 4, 4, 8, 16}, /* relax_code_size */
969 {4, 4, 4, 4, 4}, /* relax_branch_isize */
972 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
974 }, /* BR_RANGE_S256 */
976 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
978 }, /* BR_RANGE_S16K */
980 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
982 }, /* BR_RANGE_S64K */
984 {0, 4, NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
985 {0, 8, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP2
},
986 {4, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
988 }, /* BR_RANGE_S16M */
990 {0, 4, NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
991 {0, 16, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP3
},
992 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
993 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI
},
994 {12, 4, NDS32_ORIGIN
, 0},
995 {12, 2, NDS32_CONVERT
, 0},
1002 BR_RANGE_S16K
, /* br_range */
1010 INSN_BEQ
/* beq $rt, $ra, label */
1011 }, /* BR_RANGE_S256 */
1013 INSN_BEQ
/* beq $rt, $ra, label */
1014 }, /* BR_RANGE_S16K */
1016 INSN_BNE
, /* bne $rt, $ra, $1 */
1017 INSN_J
/* j label */
1018 }, /* BR_RANGE_S64K */
1020 INSN_BNE
, /* bne $rt, $ra, $1 */
1021 INSN_J
/* j label */
1022 }, /* BR_RANGE_S16M */
1024 INSN_BNE
, /* bne $rt, $ra, $1 */
1025 INSN_SETHI_TA
, /* sethi $ta, label */
1026 INSN_ORI_TA
, /* ori $ta, $ta, label */
1027 INSN_JR_TA
/* jr $ta */
1028 } /* BR_RANGE_U4G */
1029 }, /* relax_code_seq */
1035 }, /* BR_RANGE_S256 */
1040 }, /* BR_RANGE_S16K */
1045 }, /* BR_RANGE_S64K */
1050 }, /* BR_RANGE_S16M */
1055 } /* BR_RANGE_U4G */
1056 }, /* relax_code_condition */
1057 {4, 4, 8, 8, 16}, /* relax_code_size */
1058 {4, 4, 4, 4, 4}, /* relax_branch_isize */
1061 {0, 4, NDS32_ORIGIN
, BFD_RELOC_NDS32_15_PCREL
},
1062 {0, 2, NDS32_CONVERT
, BFD_RELOC_NDS32_9_PCREL
},
1064 }, /* BR_RANGE_S256 */
1066 {0, 4, 0, BFD_RELOC_NDS32_15_PCREL
},
1068 }, /* BR_RANGE_S16K */
1070 {0, 4, NDS32_ORIGIN
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
1071 {0, 2, NDS32_CONVERT
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_9_PCREL
},
1072 {0, 8, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP2
},
1073 {4, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
1075 }, /* BR_RANGE_S64K */
1077 {0, 4, NDS32_ORIGIN
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
1078 {0, 2, NDS32_CONVERT
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_9_PCREL
},
1079 {0, 8, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP2
},
1080 {4, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
1082 }, /* BR_RANGE_S16M */
1084 {0, 4, NDS32_ORIGIN
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
1085 {0, 2, NDS32_CONVERT
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_9_PCREL
},
1086 {0, 16, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP3
},
1087 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
1088 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI
},
1089 {12, 4, NDS32_ORIGIN
, 0},
1090 {12, 2, NDS32_CONVERT
, 0},
1092 } /* BR_RANGE_U4G */
1097 BR_RANGE_S16K
, /* br_range */
1105 INSN_BNE
/* bne $rt, $ra, label */
1106 }, /* BR_RANGE_S256 */
1108 INSN_BNE
/* bne $rt, $ra, label */
1109 }, /* BR_RANGE_S16K */
1111 INSN_BEQ
, /* beq $rt, $ra, $1 */
1112 INSN_J
/* j label */
1113 }, /* BR_RANGE_S64K */
1115 INSN_BEQ
, /* beq $rt, $ra, $1 */
1116 INSN_J
/* j label */
1117 }, /* BR_RANGE_S16M */
1119 INSN_BEQ
, /* beq $rt, $ra, $1 */
1120 INSN_SETHI_TA
, /* sethi $ta, label */
1121 INSN_ORI_TA
, /* ori $ta, $ta, label */
1122 INSN_JR_TA
/* jr $ta */
1123 } /* BR_RANGE_U4G */
1124 }, /* relax_code_seq */
1130 }, /* BR_RANGE_S256 */
1135 }, /* BR_RANGE_S16K */
1140 }, /* BR_RANGE_S64K */
1145 }, /* BR_RANGE_S16M */
1150 } /* BR_RANGE_U4G */
1151 }, /* relax_code_condition */
1152 {4, 4, 8, 8, 16}, /* relax_code_size */
1153 {4, 4, 4, 4, 4}, /* relax_branch_isize */
1156 {0, 4, NDS32_ORIGIN
, BFD_RELOC_NDS32_15_PCREL
},
1157 {0, 2, NDS32_CONVERT
, BFD_RELOC_NDS32_9_PCREL
},
1159 }, /* BR_RANGE_S256 */
1161 {0, 4, 0, BFD_RELOC_NDS32_15_PCREL
},
1163 }, /* BR_RANGE_S16K */
1165 {0, 4, NDS32_ORIGIN
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
1166 {0, 2, NDS32_CONVERT
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_9_PCREL
},
1167 {0, 8, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP2
},
1168 {4, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
1170 }, /* BR_RANGE_S64K */
1172 {0, 4, NDS32_ORIGIN
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
1173 {0, 2, NDS32_CONVERT
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_9_PCREL
},
1174 {0, 8, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP2
},
1175 {4, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
1177 }, /* BR_RANGE_S16M */
1179 {0, 4, NDS32_ORIGIN
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
1180 {0, 2, NDS32_CONVERT
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_9_PCREL
},
1181 {0, 16, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP3
},
1182 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
1183 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI
},
1184 {12, 4, NDS32_ORIGIN
, 0},
1185 {12, 2, NDS32_CONVERT
, 0},
1187 } /* BR_RANGE_U4G */
1191 "beqz38", /* opcode */
1192 BR_RANGE_S256
, /* br_range */
1199 INSN_BEQZ
/* beqz $rt, label */
1200 }, /* BR_RANGE_S256 */
1202 INSN_BEQZ
/* beqz $rt, label */
1203 }, /* BR_RANGE_S16K */
1205 INSN_BEQZ
/* beqz $rt, label */
1206 }, /* BR_RANGE_S64K */
1208 INSN_BNEZ
, /* bnez $rt, $1 */
1209 INSN_J
/* j label */
1210 }, /* BR_RANGE_S16M */
1212 INSN_BNEZ
, /* bnez $rt, $1 */
1213 INSN_SETHI_TA
, /* sethi $ta, label */
1214 INSN_ORI_TA
, /* ori $ta, $ta, label */
1215 INSN_JR_TA
/* jr $ta */
1216 } /* BR_RANGE_U4G */
1217 }, /* relax_code_seq */
1222 }, /* BR_RANGE_S256 */
1226 }, /* BR_RANGE_S16K */
1230 }, /* BR_RANGE_S64K */
1234 }, /* BR_RANGE_S16M */
1238 } /* BR_RANGE_U4G */
1239 }, /* relax_code_condition */
1240 {4, 4, 4, 8, 16}, /* relax_code_size */
1241 {4, 4, 4, 4, 4}, /* relax_branch_isize */
1244 {0, 4, NDS32_ORIGIN
, BFD_RELOC_NDS32_17_PCREL
},
1245 {0, 2, NDS32_CONVERT
, BFD_RELOC_NDS32_9_PCREL
},
1247 }, /* BR_RANGE_S256 */
1249 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
1251 }, /* BR_RANGE_S16K */
1253 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
1255 }, /* BR_RANGE_S64K */
1257 {0, 4, NDS32_ORIGIN
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
1258 {0, 2, NDS32_CONVERT
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_9_PCREL
},
1259 {0, 8, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP2
},
1260 {4, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
1262 }, /* BR_RANGE_S16M */
1264 {0, 4, NDS32_ORIGIN
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
1265 {0, 2, NDS32_CONVERT
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_9_PCREL
},
1266 {0, 16, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP3
},
1267 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
1268 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI
},
1269 {12, 4, NDS32_ORIGIN
, 0},
1270 {12, 2, NDS32_CONVERT
, 0},
1272 } /* BR_RANGE_U4G */
1276 "bnez38", /* opcode */
1277 BR_RANGE_S256
, /* br_range */
1284 INSN_BNEZ
/* bnez $rt, label */
1285 }, /* BR_RANGE_S256 */
1287 INSN_BNEZ
/* bnez $rt, label */
1288 }, /* BR_RANGE_S16K */
1290 INSN_BNEZ
/* bnez $rt, label */
1291 }, /* BR_RANGE_S64K */
1293 INSN_BEQZ
, /* beqz $rt, $1 */
1294 INSN_J
/* j label */
1295 }, /* BR_RANGE_S16M */
1297 INSN_BEQZ
, /* beqz $rt, $1 */
1298 INSN_SETHI_TA
, /* sethi $ta, label */
1299 INSN_ORI_TA
, /* ori $ta, $ta, label */
1300 INSN_JR_TA
/* jr $ta */
1301 } /* BR_RANGE_U4G */
1302 }, /* relax_code_seq */
1307 }, /* BR_RANGE_S256 */
1311 }, /* BR_RANGE_S16K */
1315 }, /* BR_RANGE_S64K */
1319 }, /* BR_RANGE_S16M */
1323 } /* BR_RANGE_U4G */
1324 }, /* relax_code_condition */
1325 {4, 4, 4, 8, 16}, /* relax_code_size */
1326 {4, 4, 4, 4, 4}, /* relax_branch_isize */
1329 {0, 4, NDS32_ORIGIN
, BFD_RELOC_NDS32_17_PCREL
},
1330 {0, 2, NDS32_CONVERT
, BFD_RELOC_NDS32_9_PCREL
},
1332 }, /* BR_RANGE_S256 */
1334 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
1336 }, /* BR_RANGE_S16K */
1338 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
1340 }, /* BR_RANGE_S64K */
1342 {0, 4, NDS32_ORIGIN
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
1343 {0, 2, NDS32_CONVERT
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_9_PCREL
},
1344 {0, 8, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP2
},
1345 {4, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
1347 }, /* BR_RANGE_S16M */
1349 {0, 4, NDS32_ORIGIN
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
1350 {0, 2, NDS32_CONVERT
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_9_PCREL
},
1351 {0, 16, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP3
},
1352 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
1353 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI
},
1354 {12, 4, NDS32_ORIGIN
, 0},
1355 {12, 2, NDS32_CONVERT
, 0},
1357 } /* BR_RANGE_U4G */
1361 "beqzs8", /* opcode */
1362 BR_RANGE_S256
, /* br_range */
1363 {{0, 0, 0}}, /* cond_field */
1366 INSN_BEQZ_TA
/* beqz $r15, label */
1367 }, /* BR_RANGE_S256 */
1369 INSN_BNEZ
/* bnez $rt, label */
1370 }, /* BR_RANGE_S16K */
1372 INSN_BNEZ
/* bnez $rt, label */
1373 }, /* BR_RANGE_S64K */
1375 INSN_BNEZ_TA
, /* bnez $r15, $1 */
1376 INSN_J
/* j label */
1377 }, /* BR_RANGE_S16M */
1379 INSN_BNEZ_TA
, /* bnez $r15, $1 */
1380 INSN_SETHI_TA
, /* sethi $ta, label */
1381 INSN_ORI_TA
, /* ori $ta, $ta, label */
1382 INSN_JR_TA
/* jr $ta */
1383 } /* BR_RANGE_U4G */
1384 }, /* relax_code_seq */
1386 {{0, 0, 0}}, /* BR_RANGE_S256 */
1387 {{0, 0, 0}}, /* BR_RANGE_S16K */
1388 {{0, 0, 0}}, /* BR_RANGE_S64K */
1389 {{0, 0, 0}}, /* BR_RANGE_S16M */
1390 {{0, 0, 0}} /* BR_RANGE_U4G */
1391 }, /* relax_code_condition */
1392 {4, 4, 4, 8, 16}, /* relax_code_size */
1393 {4, 4, 4, 4, 4}, /* relax_branch_isize */
1396 {0, 4, NDS32_ORIGIN
, BFD_RELOC_NDS32_17_PCREL
},
1397 {0, 2, NDS32_CONVERT
, BFD_RELOC_NDS32_9_PCREL
},
1399 }, /* BR_RANGE_S256 */
1401 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
1403 }, /* BR_RANGE_S16K */
1405 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
1407 }, /* BR_RANGE_S64K */
1409 {0, 4, NDS32_ORIGIN
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
1410 {0, 2, NDS32_CONVERT
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_9_PCREL
},
1411 {0, 8, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP2
},
1412 {4, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
1414 }, /* BR_RANGE_S16M */
1416 {0, 4, NDS32_ORIGIN
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
1417 {0, 2, NDS32_CONVERT
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_9_PCREL
},
1418 {0, 16, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP3
},
1419 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
1420 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI
},
1421 {12, 4, NDS32_ORIGIN
, 0},
1422 {12, 2, NDS32_CONVERT
, 0},
1424 } /* BR_RANGE_U4G */
1428 "bnezs8", /* opcode */
1429 BR_RANGE_S256
, /* br_range */
1430 {{0, 0, 0}}, /* cond_field */
1433 INSN_BNEZ_TA
/* bnez $r15, label */
1434 }, /* BR_RANGE_S256 */
1436 INSN_BNEZ_TA
/* bnez $r15, label */
1437 }, /* BR_RANGE_S16K */
1439 INSN_BNEZ_TA
/* bnez $r15, label */
1440 }, /* BR_RANGE_S64K */
1442 INSN_BEQZ_TA
, /* beqz $r15, $1 */
1443 INSN_J
/* j label */
1444 }, /* BR_RANGE_S16M */
1446 INSN_BEQZ_TA
, /* beqz $r15, $1 */
1447 INSN_SETHI_TA
, /* sethi $ta, label */
1448 INSN_ORI_TA
, /* ori $ta, $ta, label */
1449 INSN_JR_TA
/* jr $ta */
1450 } /* BR_RANGE_U4G */
1451 }, /* relax_code_seq */
1453 {{0, 0, 0}}, /* BR_RANGE_S256 */
1454 {{0, 0, 0}}, /* BR_RANGE_S16K */
1455 {{0, 0, 0}}, /* BR_RANGE_S64K */
1456 {{0, 0, 0}}, /* BR_RANGE_S16M */
1457 {{0, 0, 0}} /* BR_RANGE_U4G */
1458 }, /* relax_code_condition */
1459 {4, 4, 4, 8, 16}, /* relax_code_size */
1460 {4, 4, 4, 4, 4}, /* relax_branch_isize */
1463 {0, 4, NDS32_ORIGIN
, BFD_RELOC_NDS32_17_PCREL
},
1464 {0, 2, NDS32_CONVERT
, BFD_RELOC_NDS32_9_PCREL
},
1466 }, /* BR_RANGE_S256 */
1468 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
1470 }, /* BR_RANGE_S16K */
1472 {0, 4, 0, BFD_RELOC_NDS32_17_PCREL
},
1474 }, /* BR_RANGE_S64K */
1476 {0, 4, NDS32_ORIGIN
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
1477 {0, 2, NDS32_CONVERT
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_9_PCREL
},
1478 {0, 8, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP2
},
1479 {4, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
1481 }, /* BR_RANGE_S16M */
1483 {0, 4, NDS32_ORIGIN
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
1484 {0, 2, NDS32_CONVERT
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_9_PCREL
},
1485 {0, 16, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP3
},
1486 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
1487 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI
},
1488 {12, 4, NDS32_ORIGIN
, 0},
1489 {12, 2, NDS32_CONVERT
, 0},
1491 } /* BR_RANGE_U4G */
1495 "bnes38", /* opcode */
1496 BR_RANGE_S256
, /* br_range */
1503 INSN_BNE_R5
/* bne $rt, $r5, label */
1504 }, /* BR_RANGE_S256 */
1506 INSN_BNE_R5
/* bne $rt, $r5, label */
1507 }, /* BR_RANGE_S16K */
1509 INSN_BEQ_R5
, /* beq $rt, $r5, $1 */
1510 INSN_J
/* j label */
1511 }, /* BR_RANGE_S64K */
1513 INSN_BEQ_R5
, /* beq $rt, $r5, $1 */
1514 INSN_J
/* j label */
1515 }, /* BR_RANGE_S16M */
1517 INSN_BEQ_R5
, /* beq $rt, $r5, $1 */
1518 INSN_SETHI_TA
, /* sethi $ta, label */
1519 INSN_ORI_TA
, /* ori $ta, $ta, label */
1520 INSN_JR_TA
/* jr $ta */
1521 } /* BR_RANGE_U4G */
1522 }, /* relax_code_seq */
1527 }, /* BR_RANGE_S256 */
1531 }, /* BR_RANGE_S16K */
1535 }, /* BR_RANGE_S64K */
1539 }, /* BR_RANGE_S16M */
1543 } /* BR_RANGE_U4G */
1544 }, /* relax_code_condition */
1545 {4, 4, 8, 8, 16}, /* relax_code_size */
1546 {4, 4, 4, 4, 4}, /* relax_branch_isize */
1549 {0, 4, NDS32_ORIGIN
, BFD_RELOC_NDS32_17_PCREL
},
1550 {0, 2, NDS32_CONVERT
, BFD_RELOC_NDS32_9_PCREL
},
1552 }, /* BR_RANGE_S256 */
1554 {0, 4, 0, BFD_RELOC_NDS32_15_PCREL
},
1556 }, /* BR_RANGE_S16K */
1558 {0, 4, NDS32_ORIGIN
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
1559 {0, 2, NDS32_CONVERT
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_9_PCREL
},
1560 {0, 8, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP2
},
1561 {4, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
1563 }, /* BR_RANGE_S64K */
1565 {0, 4, NDS32_ORIGIN
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
1566 {0, 2, NDS32_CONVERT
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_9_PCREL
},
1567 {0, 8, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP2
},
1568 {4, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
1570 }, /* BR_RANGE_S16M */
1572 {0, 4, NDS32_ORIGIN
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
1573 {0, 2, NDS32_CONVERT
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_9_PCREL
},
1574 {0, 16, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP3
},
1575 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
1576 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI
},
1577 {12, 4, NDS32_ORIGIN
, 0},
1578 {12, 2, NDS32_CONVERT
, 0},
1580 } /* BR_RANGE_U4G */
1584 "beqs38", /* opcode */
1585 BR_RANGE_S256
, /* br_range */
1592 INSN_BEQ_R5
/* beq $rt, $r5, label */
1593 }, /* BR_RANGE_S256 */
1595 INSN_BEQ_R5
/* beq $rt, $r5, label */
1596 }, /* BR_RANGE_S16K */
1598 INSN_BNE_R5
, /* bne $rt, $r5, $1 */
1599 INSN_J
/* j label */
1600 }, /* BR_RANGE_S64K */
1602 INSN_BNE_R5
, /* bne $rt, $r5, $1 */
1603 INSN_J
/* j label */
1604 }, /* BR_RANGE_S16M */
1606 INSN_BNE_R5
, /* bne $rt, $r5, $1 */
1607 INSN_SETHI_TA
, /* sethi $ta, label */
1608 INSN_ORI_TA
, /* ori $ta, $ta, label */
1609 INSN_JR_TA
/* jr $ta */
1610 } /* BR_RANGE_U4G */
1611 }, /* relax_code_seq */
1616 }, /* BR_RANGE_S256 */
1620 }, /* BR_RANGE_S16K */
1624 }, /* BR_RANGE_S64K */
1628 }, /* BR_RANGE_S16M */
1632 } /* BR_RANGE_U4G */
1633 }, /* relax_code_condition */
1634 {4, 4, 8, 8, 16}, /* relax_code_size */
1635 {4, 4, 4, 4, 4}, /* relax_branch_isize */
1638 {0, 4, NDS32_ORIGIN
, BFD_RELOC_NDS32_17_PCREL
},
1639 {0, 2, NDS32_CONVERT
, BFD_RELOC_NDS32_9_PCREL
},
1641 }, /* BR_RANGE_S256 */
1643 {0, 4, 0, BFD_RELOC_NDS32_15_PCREL
},
1645 }, /* BR_RANGE_S16K */
1647 {0, 4, NDS32_ORIGIN
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
1648 {0, 2, NDS32_CONVERT
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_9_PCREL
},
1649 {0, 8, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP2
},
1650 {4, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
1652 }, /* BR_RANGE_S64K */
1654 {0, 4, NDS32_ORIGIN
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
1655 {0, 2, NDS32_CONVERT
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_9_PCREL
},
1656 {0, 8, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP2
},
1657 {4, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
1659 }, /* BR_RANGE_S16M */
1661 {0, 4, NDS32_ORIGIN
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_15_PCREL
},
1662 {0, 2, NDS32_CONVERT
| NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_9_PCREL
},
1663 {0, 16, NDS32_RELAX
, BFD_RELOC_NDS32_LONGJUMP3
},
1664 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
1665 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI
},
1666 {12, 4, NDS32_ORIGIN
, 0},
1667 {12, 2, NDS32_CONVERT
, 0},
1669 } /* BR_RANGE_U4G */
1673 "beqc", /* opcode */
1674 BR_RANGE_S256
, /* br_range */
1682 INSN_BEQC
/* beqc $rt, imm11s, label */
1683 }, /* BR_RANGE_S256 */
1685 INSN_MOVI_TA
, /* movi $ta, imm11s */
1686 INSN_BEQ_TA
/* beq $rt, $ta, label */
1687 }, /* BR_RANGE_S16K */
1689 INSN_MOVI_TA
, /* movi $ta, imm11s */
1690 INSN_BEQ_TA
/* beq $rt, $ta, label */
1691 }, /* BR_RANGE_S64K */
1693 INSN_BNEC
, /* bnec $rt, imm11s, $1 */
1694 INSN_J
/* j label */
1695 }, /* BR_RANGE_S16M */
1697 INSN_BNEC
, /* bnec $rt, imm11s, $1 */
1698 INSN_SETHI_TA
, /* sethi $ta, label */
1699 INSN_ORI_TA
, /* ori $ta, $ta, label */
1700 INSN_JR_TA
/* jr $ta */
1701 } /* BR_RANGE_U4G */
1702 }, /* relax_code_seq */
1708 }, /* BR_RANGE_S256 */
1713 }, /* BR_RANGE_S16K */
1718 }, /* BR_RANGE_S64K */
1723 }, /* BR_RANGE_S16M */
1728 } /* BR_RANGE_U4G */
1729 }, /* relax_code_condition */
1730 {4, 8, 8, 8, 16}, /* relax_code_size */
1731 {4, 4, 4, 4, 4}, /* relax_branch_isize */
1734 {0, 4, 0, BFD_RELOC_NDS32_WORD_9_PCREL
},
1736 }, /* BR_RANGE_S256 */
1738 {4, 4, 0, BFD_RELOC_NDS32_15_PCREL
},
1740 }, /* BR_RANGE_S16K */
1742 {4, 4, 0, BFD_RELOC_NDS32_15_PCREL
},
1744 }, /* BR_RANGE_S64K */
1746 {0, 4, NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_WORD_9_PCREL
},
1747 {4, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
1749 }, /* BR_RANGE_S16M */
1751 {0, 4, NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_WORD_9_PCREL
},
1752 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
1753 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI
},
1754 {12, 4, NDS32_ORIGIN
, 0},
1755 {12, 2, NDS32_CONVERT
, 0},
1757 } /* BR_RANGE_U4G */
1761 "bnec", /* opcode */
1762 BR_RANGE_S256
, /* br_range */
1770 INSN_BNEC
/* bnec $rt, imm11s, label */
1771 }, /* BR_RANGE_S256 */
1773 INSN_MOVI_TA
, /* movi $ta, imm11s */
1774 INSN_BNE_TA
/* bne $rt, $ta, label */
1775 }, /* BR_RANGE_S16K */
1777 INSN_MOVI_TA
, /* movi $ta, imm11s */
1778 INSN_BNE_TA
/* bne $rt, $ta, label */
1779 }, /* BR_RANGE_S64K */
1781 INSN_BEQC
, /* beqc $rt, imm11s, $1 */
1782 INSN_J
/* j label */
1783 }, /* BR_RANGE_S16M */
1785 INSN_BEQC
, /* beqc $rt, imm11s, $1 */
1786 INSN_SETHI_TA
, /* sethi $ta, label */
1787 INSN_ORI_TA
, /* ori $ta, $ta, label */
1788 INSN_JR_TA
/* jr $ta */
1789 } /* BR_RANGE_U4G */
1790 }, /* relax_code_seq */
1796 }, /* BR_RANGE_S256 */
1801 }, /* BR_RANGE_S16K */
1806 }, /* BR_RANGE_S64K */
1811 }, /* BR_RANGE_S16M */
1816 } /* BR_RANGE_U4G */
1817 }, /* relax_code_condition */
1818 {4, 8, 8, 8, 16}, /* relax_code_size */
1819 {4, 4, 4, 4, 4}, /* relax_branch_isize */
1822 {0, 4, 0, BFD_RELOC_NDS32_WORD_9_PCREL
},
1824 }, /* BR_RANGE_S256 */
1826 {4, 4, 0, BFD_RELOC_NDS32_15_PCREL
},
1828 }, /* BR_RANGE_S16K */
1830 {4, 4, 0, BFD_RELOC_NDS32_15_PCREL
},
1832 }, /* BR_RANGE_S64K */
1834 {0, 4, NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_WORD_9_PCREL
},
1835 {4, 4, 0, BFD_RELOC_NDS32_25_PCREL
},
1837 }, /* BR_RANGE_S16M */
1839 {0, 4, NDS32_CREATE_LABLE
, BFD_RELOC_NDS32_WORD_9_PCREL
},
1840 {4, 4, 0, BFD_RELOC_NDS32_HI20
},
1841 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI
},
1842 {12, 4, NDS32_ORIGIN
, 0},
1843 {12, 2, NDS32_CONVERT
, 0},
1845 } /* BR_RANGE_U4G */
1851 {{0, 0, 0}}, /* cond_field */
1852 {{0}}, /* relax_code_seq */
1853 {{{0, 0, 0}}}, /* relax_code_condition */
1854 {0}, /* relax_code_size */
1855 {0}, /* relax_branch_isize */
1856 {{{0, 0, 0, 0}}}, /* relax_fixup */
1861 /* GAS definitions for command-line options. */
1864 OPTION_BIG
= OPTION_MD_BASE
,
1868 OPTION_RELAX_FP_AS_GP_OFF
,
1869 OPTION_RELAX_B2BB_ON
,
1870 OPTION_RELAX_ALL_OFF
,
1872 OPTION_OPTIMIZE_SPACE
1875 const char *md_shortopts
= "m:G:O";
1876 struct option md_longopts
[] =
1878 {"O1", no_argument
, NULL
, OPTION_OPTIMIZE
},
1879 {"Os", no_argument
, NULL
, OPTION_OPTIMIZE_SPACE
},
1880 {"big", no_argument
, NULL
, OPTION_BIG
},
1881 {"little", no_argument
, NULL
, OPTION_LITTLE
},
1882 {"EB", no_argument
, NULL
, OPTION_BIG
},
1883 {"EL", no_argument
, NULL
, OPTION_LITTLE
},
1884 {"meb", no_argument
, NULL
, OPTION_BIG
},
1885 {"mel", no_argument
, NULL
, OPTION_LITTLE
},
1886 {"mall-ext", no_argument
, NULL
, OPTION_TURBO
},
1887 {"mpic", no_argument
, NULL
, OPTION_PIC
},
1888 /* Relaxation related options. */
1889 {"mno-fp-as-gp-relax", no_argument
, NULL
, OPTION_RELAX_FP_AS_GP_OFF
},
1890 {"mb2bb", no_argument
, NULL
, OPTION_RELAX_B2BB_ON
},
1891 {"mno-all-relax", no_argument
, NULL
, OPTION_RELAX_ALL_OFF
},
1892 {NULL
, no_argument
, NULL
, 0}
1895 size_t md_longopts_size
= sizeof (md_longopts
);
1897 struct nds32_parse_option_table
1899 const char *name
; /* Option string. */
1900 char *help
; /* Help description. */
1901 int (*func
) (char *arg
); /* How to parse it. */
1905 /* The value `-1' represents this option has *NOT* been set. */
1906 #ifdef NDS32_DEFAULT_ARCH_NAME
1907 static char* nds32_arch_name
= NDS32_DEFAULT_ARCH_NAME
;
1909 static char* nds32_arch_name
= "v3";
1911 static int nds32_baseline
= -1;
1912 static int nds32_gpr16
= -1;
1913 static int nds32_fpu_sp_ext
= -1;
1914 static int nds32_fpu_dp_ext
= -1;
1915 static int nds32_freg
= -1;
1916 static int nds32_abi
= -1;
1918 /* Record ELF flags */
1919 static int nds32_elf_flags
= 0;
1920 static int nds32_fpu_com
= 0;
1922 static int nds32_parse_arch (char *str
);
1923 static int nds32_parse_baseline (char *str
);
1924 static int nds32_parse_freg (char *str
);
1925 static int nds32_parse_abi (char *str
);
1927 static struct nds32_parse_option_table parse_opts
[] =
1929 {"arch=", N_("<arch name>\t Assemble for architecture <arch name>\n\
1930 <arch name> could be\n\
1931 v3, v3j, v3m, v3f, v3s, "\
1932 "v2, v2j, v2f, v2s"), nds32_parse_arch
},
1933 {"baseline=", N_("<baseline>\t Assemble for baseline <baseline>\n\
1934 <baseline> could be v2, v3, v3m"),
1935 nds32_parse_baseline
},
1936 {"fpu-freg=", N_("<freg>\t Specify a FPU configuration\n\
1938 0: 8 SP / 4 DP registers\n\
1939 1: 16 SP / 8 DP registers\n\
1940 2: 32 SP / 16 DP registers\n\
1941 3: 32 SP / 32 DP registers"), nds32_parse_freg
},
1942 {"abi=", N_("<abi>\t Specify a abi version\n\
1943 <abi> could be v1, v2, v2fp, v2fpp"), nds32_parse_abi
},
1947 static int nds32_mac
= 1;
1948 static int nds32_div
= 1;
1949 static int nds32_16bit_ext
= 1;
1950 static int nds32_dx_regs
= 1;
1951 static int nds32_perf_ext
= 1;
1952 static int nds32_perf_ext2
= 1;
1953 static int nds32_string_ext
= 1;
1954 static int nds32_audio_ext
= 1;
1955 static int nds32_fpu_fma
= 0;
1956 static int nds32_pic
= 0;
1957 static int nds32_relax_fp_as_gp
= 1;
1958 static int nds32_relax_b2bb
= 0;
1959 static int nds32_relax_all
= 1;
1960 struct nds32_set_option_table
1962 const char *name
; /* Option string. */
1963 char *help
; /* Help description. */
1964 int *var
; /* Variable to be set. */
1965 int value
; /* Value to set. */
1968 /* The option in this group has both Enable/Disable settings.
1969 Just list on here. */
1971 static struct nds32_set_option_table toggle_opts
[] =
1973 {"mac", N_("Multiply instructions support"), &nds32_mac
, 1},
1974 {"div", N_("Divide instructions support"), &nds32_div
, 1},
1975 {"16bit-ext", N_("16-bit extension"), &nds32_16bit_ext
, 1},
1976 {"dx-regs", N_("d0/d1 registers"), &nds32_dx_regs
, 1},
1977 {"perf-ext", N_("Performance extension"), &nds32_perf_ext
, 1},
1978 {"perf2-ext", N_("Performance extension 2"), &nds32_perf_ext2
, 1},
1979 {"string-ext", N_("String extension"), &nds32_string_ext
, 1},
1980 {"reduced-regs", N_("Reduced Register configuration (GPR16) option"), &nds32_gpr16
, 1},
1981 {"audio-isa-ext", N_("AUDIO ISA extension"), &nds32_audio_ext
, 1},
1982 {"fpu-sp-ext", N_("FPU SP extension"), &nds32_fpu_sp_ext
, 1},
1983 {"fpu-dp-ext", N_("FPU DP extension"), &nds32_fpu_dp_ext
, 1},
1984 {"fpu-fma", N_("FPU fused-multiply-add instructions"), &nds32_fpu_fma
, 1},
1985 {NULL
, NULL
, NULL
, 0}
1989 /* GAS declarations. */
1991 /* This is the callback for nds32-asm.c to parse operands. */
1993 nds32_asm_parse_operand (struct nds32_asm_desc
*pdesc
,
1994 struct nds32_asm_insn
*pinsn
,
1995 char **pstr
, int64_t *value
);
1998 struct nds32_asm_desc asm_desc
;
2000 /* md_after_parse_args ()
2002 GAS will call md_after_parse_args whenever it is defined.
2003 This function checks any conflicting options specified. */
2006 nds32_after_parse_args (void)
2008 /* If -march option is not used in command-line, set the value of option
2009 variable according to NDS32_DEFAULT_ARCH_NAME. */
2010 nds32_parse_arch (nds32_arch_name
);
2013 /* This function is called when printing usage message (--help). */
2016 md_show_usage (FILE *stream
)
2018 struct nds32_parse_option_table
*coarse_tune
;
2019 struct nds32_set_option_table
*fine_tune
;
2021 fprintf (stream
, _("\n NDS32-specific assembler options:\n"));
2022 fprintf (stream
, _("\
2023 -O1, Optimize for performance\n\
2024 -Os Optimize for space\n"));
2025 fprintf (stream
, _("\
2026 -EL, -mel or -little Produce little endian output\n\
2027 -EB, -meb or -big Produce big endian output\n\
2028 -mpic Generate PIC\n\
2029 -mno-fp-as-gp-relax Suppress fp-as-gp relaxation for this file\n\
2030 -mb2bb-relax Back-to-back branch optimization\n\
2031 -mno-all-relax Suppress all relaxation for this file\n"));
2033 for (coarse_tune
= parse_opts
; coarse_tune
->name
!= NULL
; coarse_tune
++)
2035 if (coarse_tune
->help
!= NULL
)
2036 fprintf (stream
, _(" -m%s%s\n"),
2037 coarse_tune
->name
, _(coarse_tune
->help
));
2040 for (fine_tune
= toggle_opts
; fine_tune
->name
!= NULL
; fine_tune
++)
2042 if (fine_tune
->help
!= NULL
)
2043 fprintf (stream
, _(" -m[no-]%-17sEnable/Disable %s\n"),
2044 fine_tune
->name
, _(fine_tune
->help
));
2047 fprintf (stream
, _("\
2048 -mall-ext Turn on all extensions and instructions support\n"));
2052 nds32_frag_init (fragS
*fragp
)
2054 fragp
->tc_frag_data
.flag
= 0;
2055 fragp
->tc_frag_data
.opcode
= NULL
;
2056 fragp
->tc_frag_data
.fixup
= NULL
;
2061 /* This function reads an expression from a C string and returns a pointer past
2062 the end of the expression. */
2065 parse_expression (char *str
, expressionS
*exp
)
2070 tmp
= input_line_pointer
; /* Save line pointer. */
2071 input_line_pointer
= str
;
2073 s
= input_line_pointer
;
2074 input_line_pointer
= tmp
; /* Restore line pointer. */
2076 return s
; /* Return pointer to where parsing stopped. */
2080 nds32_start_line_hook (void)
2088 typedef void (*nds32_pseudo_opcode_func
) (int argc
, char *argv
[], int pv
);
2089 struct nds32_pseudo_opcode
2093 nds32_pseudo_opcode_func proc
;
2096 /* Some instructions are not pseudo opcode, but they might still be
2097 expanded or changed with other instruction combination for some
2098 conditions. We also apply this structure to assist such work.
2100 For example, if the distance of branch target '.L0' is larger than
2107 will be transformed into:
2113 However, sometimes we do not want assembler to do such changes
2114 because compiler knows how to generate corresponding instruction sequence.
2115 Use this field to indicate that this opcode is also a physical instruction.
2116 If the flag 'verbatim' is nozero and this opcode
2117 is a physical instruction, we should not expand it. */
2120 #define PV_DONT_CARE 0
2122 static struct hash_control
*nds32_pseudo_opcode_hash
= NULL
;
2125 builtin_isreg (const char *s
, const char *x ATTRIBUTE_UNUSED
)
2131 builtin_regnum (const char *s
, const char *x ATTRIBUTE_UNUSED
)
2133 struct nds32_keyword
*k
;
2135 k
= hash_find (nds32_gprs_hash
, s
);
2144 builtin_addend (const char *s
, char *x ATTRIBUTE_UNUSED
)
2146 const char *ptr
= s
;
2148 while (*ptr
!= '+' && *ptr
!= '-' && *ptr
)
2154 return strtol (ptr
, NULL
, 0);
2158 md_assemblef (char *format
, ...)
2160 /* FIXME: hope this is long enough. */
2165 va_start (ap
, format
);
2166 r
= vsnprintf (line
, sizeof (line
), format
, ap
);
2169 gas_assert (r
< sizeof (line
));
2172 /* Some prototypes here, since some op may use another op. */
2173 static void do_pseudo_li_internal (char *rt
, int imm32s
);
2174 static void do_pseudo_move_reg_internal (char *dst
, char *src
);
2177 do_pseudo_b (int argc ATTRIBUTE_UNUSED
, char *argv
[], int pv ATTRIBUTE_UNUSED
)
2179 char *arg_label
= argv
[0];
2182 && (strstr (arg_label
, "@GOT") || strstr (arg_label
, "@PLT")))
2184 md_assemblef ("sethi $ta,hi20(%s)", arg_label
);
2185 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label
);
2186 md_assemble ("add $ta,$ta,$gp");
2187 md_assemble ("jr $ta");
2191 md_assemblef ("j %s", arg_label
);
2196 do_pseudo_bal (int argc ATTRIBUTE_UNUSED
, char *argv
[], int pv ATTRIBUTE_UNUSED
)
2198 char *arg_label
= argv
[0];
2199 /* bal|call label */
2201 && (strstr (arg_label
, "@GOT") || strstr (arg_label
, "@PLT")))
2203 md_assemblef ("sethi $ta,hi20(%s)", arg_label
);
2204 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label
);
2205 md_assemble ("add $ta,$ta,$gp");
2206 md_assemble ("jral $ta");
2210 md_assemblef ("jal %s", arg_label
);
2215 do_pseudo_bge (int argc ATTRIBUTE_UNUSED
, char *argv
[], int pv ATTRIBUTE_UNUSED
)
2217 /* rt5, ra5, label */
2218 md_assemblef ("slt $ta,%s,%s", argv
[0], argv
[1]);
2219 md_assemblef ("beqz $ta,%s", argv
[2]);
2223 do_pseudo_bges (int argc ATTRIBUTE_UNUSED
, char *argv
[], int pv ATTRIBUTE_UNUSED
)
2225 /* rt5, ra5, label */
2226 md_assemblef ("slts $ta,%s,%s", argv
[0], argv
[1]);
2227 md_assemblef ("beqz $ta,%s", argv
[2]);
2231 do_pseudo_bgt (int argc ATTRIBUTE_UNUSED
, char *argv
[], int pv ATTRIBUTE_UNUSED
)
2233 /* bgt rt5, ra5, label */
2234 md_assemblef ("slt $ta,%s,%s", argv
[1], argv
[0]);
2235 md_assemblef ("bnez $ta,%s", argv
[2]);
2239 do_pseudo_bgts (int argc ATTRIBUTE_UNUSED
, char *argv
[], int pv ATTRIBUTE_UNUSED
)
2241 /* bgt rt5, ra5, label */
2242 md_assemblef ("slts $ta,%s,%s", argv
[1], argv
[0]);
2243 md_assemblef ("bnez $ta,%s", argv
[2]);
2247 do_pseudo_ble (int argc ATTRIBUTE_UNUSED
, char *argv
[], int pv ATTRIBUTE_UNUSED
)
2249 /* bgt rt5, ra5, label */
2250 md_assemblef ("slt $ta,%s,%s", argv
[1], argv
[0]);
2251 md_assemblef ("beqz $ta,%s", argv
[2]);
2255 do_pseudo_bles (int argc ATTRIBUTE_UNUSED
, char *argv
[], int pv ATTRIBUTE_UNUSED
)
2257 /* bgt rt5, ra5, label */
2258 md_assemblef ("slts $ta,%s,%s", argv
[1], argv
[0]);
2259 md_assemblef ("beqz $ta,%s", argv
[2]);
2263 do_pseudo_blt (int argc ATTRIBUTE_UNUSED
, char *argv
[], int pv ATTRIBUTE_UNUSED
)
2265 /* rt5, ra5, label */
2266 md_assemblef ("slt $ta,%s,%s", argv
[0], argv
[1]);
2267 md_assemblef ("bnez $ta,%s", argv
[2]);
2271 do_pseudo_blts (int argc ATTRIBUTE_UNUSED
, char *argv
[], int pv ATTRIBUTE_UNUSED
)
2273 /* rt5, ra5, label */
2274 md_assemblef ("slts $ta,%s,%s", argv
[0], argv
[1]);
2275 md_assemblef ("bnez $ta,%s", argv
[2]);
2279 do_pseudo_br (int argc ATTRIBUTE_UNUSED
, char *argv
[], int pv ATTRIBUTE_UNUSED
)
2281 md_assemblef ("jr %s", argv
[0]);
2285 do_pseudo_bral (int argc
, char *argv
[], int pv ATTRIBUTE_UNUSED
)
2288 md_assemblef ("jral $lp,%s", argv
[0]);
2290 md_assemblef ("jral %s,%s", argv
[0], argv
[1]);
2294 do_pseudo_la_internal (const char *arg_reg
, const char *arg_label
, const char *line
)
2299 md_assemblef ("sethi %s,hi20(%s)", arg_reg
, arg_label
);
2300 md_assemblef ("ori %s,%s,lo12(%s)", arg_reg
, arg_reg
, arg_label
);
2302 else if ((strstr (arg_label
, "@PLT") || strstr (arg_label
, "@GOTOFF")))
2304 md_assemblef ("sethi $ta,hi20(%s)", arg_label
);
2305 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label
);
2306 md_assemblef ("add %s,$ta,$gp", arg_reg
);
2308 else if (strstr (arg_label
, "@GOT"))
2310 long addend
= builtin_addend (arg_label
, NULL
);
2312 md_assemblef ("sethi $ta,hi20(%s)", arg_label
);
2313 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label
);
2314 md_assemblef ("lw %s,[$gp+$ta]", arg_reg
);
2317 if (addend
< 0x4000 && addend
>= -0x4000)
2319 md_assemblef ("addi %s,%s,%d", arg_reg
, arg_reg
, addend
);
2323 do_pseudo_li_internal ("$ta", addend
);
2324 md_assemblef ("add %s,$ta,%s", arg_reg
, arg_reg
);
2329 as_bad (_("need PIC qualifier with symbol. '%s'"), line
);
2333 do_pseudo_la (int argc ATTRIBUTE_UNUSED
, char *argv
[], int pv ATTRIBUTE_UNUSED
)
2335 do_pseudo_la_internal (argv
[0], argv
[1], argv
[argc
]);
2339 do_pseudo_li_internal (char *rt
, int imm32s
)
2341 if (enable_16bit
&& imm32s
<= 0xf && imm32s
>= -0x10)
2342 md_assemblef ("movi55 %s,%d", rt
, imm32s
);
2343 else if (imm32s
<= 0x7ffff && imm32s
>= -0x80000)
2344 md_assemblef ("movi %s,%d", rt
, imm32s
);
2345 else if ((imm32s
& 0xfff) == 0)
2346 md_assemblef ("sethi %s,hi20(%d)", rt
, imm32s
);
2349 md_assemblef ("sethi %s,hi20(%d)", rt
, imm32s
);
2350 md_assemblef ("ori %s,%s,lo12(%d)", rt
, rt
, imm32s
);
2355 do_pseudo_li (int argc ATTRIBUTE_UNUSED
, char *argv
[], int pv ATTRIBUTE_UNUSED
)
2357 /* Validate argv[1] for constant expression. */
2360 parse_expression (argv
[1], &exp
);
2361 if (exp
.X_op
!= O_constant
)
2363 as_bad (_("Operand is not a constant. `%s'"), argv
[argc
]);
2367 do_pseudo_li_internal (argv
[0], exp
.X_add_number
);
2371 do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED
, char *argv
[], int pv
)
2375 const char *sign
= "";
2377 /* Prepare arguments for various load/store. */
2378 sign
= (pv
& 0x10) ? "s" : "";
2379 ls
= (pv
& 0x80000000) ? 's' : 'l';
2382 case 0: size
= 'b'; break;
2383 case 1: size
= 'h'; break;
2384 case 2: size
= 'w'; break;
2387 if (ls
== 's' || size
== 'w')
2390 if (builtin_isreg (argv
[1], NULL
))
2393 md_assemblef ("%c%c%si %s,[%s]", ls
, size
, argv
[0], argv
[1]);
2395 else if (!nds32_pic
)
2398 md_assemblef ("sethi $ta,hi20(%s)", argv
[1]);
2399 md_assemblef ("%c%c%si %s,[$ta+lo12(%s)]", ls
, size
, sign
, argv
[0], argv
[1]);
2404 if (strstr (argv
[1], "@GOTOFF"))
2407 md_assemblef ("sethi $ta,hi20(%s)", argv
[1]);
2408 md_assemblef ("ori $ta,$ta,lo12(%s)", argv
[1]);
2409 md_assemblef ("%c%c%s %s,[$ta+$gp]", ls
, size
, sign
, argv
[0]);
2411 else if (strstr (argv
[1], "@GOT"))
2413 long addend
= builtin_addend (argv
[1], NULL
);
2415 md_assemblef ("sethi $ta,hi20(%s)", argv
[1]);
2416 md_assemblef ("ori $ta,$ta,lo12(%s)", argv
[1]);
2417 md_assemble ("lw $ta,[$gp+$ta]"); /* Load address word. */
2418 if (addend
< 0x10000 && addend
>= -0x10000)
2420 md_assemblef ("%c%c%si %s,[$ta+(%d)]", ls
, size
, sign
, argv
[0], addend
);
2425 do_pseudo_li_internal (argv
[0], addend
);
2426 md_assemblef ("%c%c%s %s,[$ta+%s]", ls
, size
, sign
, argv
[0], argv
[0]);
2431 as_bad (_("needs @GOT or @GOTOFF. %s"), argv
[argc
]);
2437 do_pseudo_ls_bhwp (int argc ATTRIBUTE_UNUSED
, char *argv
[], int pv
)
2439 char *arg_rt
= argv
[0];
2440 char *arg_label
= argv
[1];
2441 char *arg_inc
= argv
[2];
2444 const char *sign
= "";
2446 /* Prepare arguments for various load/store. */
2447 sign
= (pv
& 0x10) ? "s" : "";
2448 ls
= (pv
& 0x80000000) ? 's' : 'l';
2451 case 0: size
= 'b'; break;
2452 case 1: size
= 'h'; break;
2453 case 2: size
= 'w'; break;
2456 if (ls
== 's' || size
== 'w')
2459 do_pseudo_la_internal ("$ta", arg_label
, argv
[argc
]);
2460 md_assemblef ("%c%c%si.bi %s,[$ta],%s", ls
, size
, sign
, arg_rt
, arg_inc
);
2464 do_pseudo_ls_bhwpc (int argc ATTRIBUTE_UNUSED
, char *argv
[], int pv
)
2466 char *arg_rt
= argv
[0];
2467 char *arg_inc
= argv
[2];
2470 const char *sign
= "";
2472 /* Prepare arguments for various load/store. */
2473 sign
= (pv
& 0x10) ? "s" : "";
2474 ls
= (pv
& 0x80000000) ? 's' : 'l';
2477 case 0: size
= 'b'; break;
2478 case 1: size
= 'h'; break;
2479 case 2: size
= 'w'; break;
2482 if (ls
== 's' || size
== 'w')
2485 md_assemblef ("%c%c%si.bi %s,[$ta],%s", ls
, size
, sign
, arg_rt
, arg_inc
);
2489 do_pseudo_ls_bhwi (int argc ATTRIBUTE_UNUSED
, char *argv
[], int pv
)
2493 const char *sign
= "";
2495 /* Prepare arguments for various load/store. */
2496 sign
= (pv
& 0x10) ? "s" : "";
2497 ls
= (pv
& 0x80000000) ? 's' : 'l';
2500 case 0: size
= 'b'; break;
2501 case 1: size
= 'h'; break;
2502 case 2: size
= 'w'; break;
2505 if (ls
== 's' || size
== 'w')
2508 md_assemblef ("%c%c%si.bi %s,%s,%s",
2509 ls
, size
, sign
, argv
[0], argv
[1], argv
[2]);
2513 do_pseudo_move_reg_internal (char *dst
, char *src
)
2516 md_assemblef ("mov55 %s,%s", dst
, src
);
2518 md_assemblef ("ori %s,%s,0", dst
, src
);
2522 do_pseudo_move (int argc ATTRIBUTE_UNUSED
, char *argv
[], int pv ATTRIBUTE_UNUSED
)
2524 if (builtin_isreg (argv
[1], NULL
))
2525 do_pseudo_move_reg_internal (argv
[0], argv
[1]);
2527 /* move $rt, imm -> li $rt, imm */
2528 do_pseudo_li (argc
, argv
, PV_DONT_CARE
);
2532 do_pseudo_neg (int argc ATTRIBUTE_UNUSED
, char *argv
[], int pv ATTRIBUTE_UNUSED
)
2534 md_assemble ("movi $ta,0");
2535 md_assemblef ("sub %s,$ta,%s", argv
[0], argv
[1]);
2539 do_pseudo_not (int argc ATTRIBUTE_UNUSED
, char *argv
[], int pv ATTRIBUTE_UNUSED
)
2541 md_assemblef ("nor %s,%s,%s", argv
[0], argv
[1], argv
[1]);
2545 do_pseudo_pushpopm (int argc
, char *argv
[], int pv ATTRIBUTE_UNUSED
)
2547 /* posh/pop $ra, $rb */
2548 /* SMW.{b | a}{i | d}{m?} Rb, [Ra], Re, Enable4 */
2549 int rb
, re
, ra
, en4
;
2551 char *opc
= "pushpopm";
2554 as_bad ("'pushm/popm $ra5, $rb5, $label' is deprecated. "
2555 "Only 'pushm/popm $ra5' is supported now. %s", argv
[argc
]);
2557 as_bad ("'pushm/popm $ra5, $rb5'. %s\n", argv
[argc
]);
2559 if (strstr (argv
[argc
], "pop") == argv
[argc
])
2561 else if (strstr (argv
[argc
], "push") == argv
[argc
])
2564 as_fatal ("nds32-as internal error. %s", argv
[argc
]);
2566 rb
= builtin_regnum (argv
[0], NULL
);
2567 re
= builtin_regnum (argv
[1], NULL
);
2571 as_warn ("$rb should not be smaller than $ra. %s", argv
[argc
]);
2572 /* Swap to right order. */
2578 /* Build enable4 mask. */
2580 if (re
>= 28 || rb
>= 28)
2582 for (i
= (rb
>= 28? rb
: 28); i
<= re
; i
++)
2583 en4
|= 1 << (3 - (i
- 28));
2586 /* Adjust $re, $rb. */
2592 md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc
, rb
, re
, en4
);
2596 do_pseudo_pushpop (int argc
, char *argv
[], int pv ATTRIBUTE_UNUSED
)
2598 /* push/pop $ra5, $label=$sp */
2602 as_bad ("'push/pop $ra5, rb5' is deprecated. "
2603 "Only 'push/pop $ra5' is supported now. %s", argv
[argc
]);
2607 argvm
[2] = argv
[argc
];
2608 do_pseudo_pushpopm (2, argvm
, PV_DONT_CARE
);
2612 do_pseudo_v3push (int argc ATTRIBUTE_UNUSED
, char *argv
[], int pv ATTRIBUTE_UNUSED
)
2614 md_assemblef ("push25 %s,%s", argv
[0], argv
[1]);
2618 do_pseudo_v3pop (int argc ATTRIBUTE_UNUSED
, char *argv
[], int pv ATTRIBUTE_UNUSED
)
2620 md_assemblef ("pop25 %s,%s", argv
[0], argv
[1]);
2623 /* pv == 0, parsing "push.s" pseudo instruction operands.
2624 pv != 0, parsing "pop.s" pseudo instruction operands. */
2627 do_pseudo_pushpop_stack (int argc
, char *argv
[], int pv
)
2629 /* push.s Rb,Re,{$fp $gp $lp $sp} ==> smw.adm Rb,[$sp],Re,Eable4 */
2630 /* pop.s Rb,Re,{$fp $gp $lp $sp} ==> lmw.bim Rb,[$sp],Re,Eable4 */
2635 char *opc
= (pv
== 0) ? "smw.adm" : "lmw.bim";
2641 /* argc=1, operands pattern: { $fp $gp $lp $sp } */
2643 /* Set register number Rb = Re = $sp = $r31. */
2646 else if (argc
== 2 || argc
== 3)
2648 /* argc=2, operands pattern: Rb, Re */
2649 /* argc=3, operands pattern: Rb, Re, { $fp $gp $lp $sp } */
2651 /* Get register number in integer. */
2652 rb
= builtin_regnum (argv
[0], NULL
);
2653 re
= builtin_regnum (argv
[1], NULL
);
2655 /* Rb should be equal/less than Re. */
2657 as_bad ("The first operand (%s) should be equal to or smaller than "
2658 "second operand (%s).", argv
[0], argv
[1]);
2660 /* forbid using $fp|$gp|$lp|$sp in Rb or Re
2663 as_bad ("Cannot use $fp, $gp, $lp, or $sp at first operand !!");
2665 as_bad ("Cannot use $fp, $gp, $lp, or $sp at second operand !!");
2669 as_bad ("Invalid operands pattern !!");
2672 /* Build Enable4 mask. */
2673 /* Using last_arg_index for argc=1|2|3 is safe, because $fp, $gp, $lp,
2674 and $sp only appear in argc=1 or argc=3 if argc=2, en4 remains 0,
2675 which is also valid for code generation. */
2677 last_arg_index
= argc
- 1;
2678 if (strstr (argv
[last_arg_index
], "$fp"))
2680 if (strstr (argv
[last_arg_index
], "$gp"))
2682 if (strstr (argv
[last_arg_index
], "$lp"))
2684 if (strstr (argv
[last_arg_index
], "$sp"))
2687 md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc
, rb
, re
, en4
);
2691 do_pseudo_push_bhwd (int argc ATTRIBUTE_UNUSED
, char *argv
[], int pv ATTRIBUTE_UNUSED
)
2694 /* If users omit push location, use $sp as default value. */
2695 char location
[8] = "$sp"; /* 8 is enough for register name. */
2699 case 0: size
= 'b'; break;
2700 case 1: size
= 'h'; break;
2701 case 2: size
= 'w'; break;
2702 case 3: size
= 'w'; break;
2707 strncpy (location
, argv
[1], 8);
2711 md_assemblef ("l.%c $ta,%s", size
, argv
[0]);
2712 md_assemblef ("smw.adm $ta,[%s],$ta", location
);
2714 if ((pv
& 0x3) == 0x3) /* double-word */
2716 md_assemblef ("l.w $ta,%s+4", argv
[0]);
2717 md_assemblef ("smw.adm $ta,[%s],$ta", location
);
2722 do_pseudo_pop_bhwd (int argc ATTRIBUTE_UNUSED
, char *argv
[], int pv ATTRIBUTE_UNUSED
)
2725 /* If users omit pop location, use $sp as default value. */
2726 char location
[8] = "$sp"; /* 8 is enough for register name. */
2730 case 0: size
= 'b'; break;
2731 case 1: size
= 'h'; break;
2732 case 2: size
= 'w'; break;
2733 case 3: size
= 'w'; break;
2738 strncpy (location
, argv
[2], 8);
2742 if ((pv
& 0x3) == 0x3) /* double-word */
2744 md_assemblef ("lmw.bim %s,[%s],%s", argv
[1], location
, argv
[1]);
2745 md_assemblef ("s.w %s,%s+4", argv
[1], argv
[0]);
2748 md_assemblef ("lmw.bim %s,[%s],%s", argv
[1], location
, argv
[1]);
2749 md_assemblef ("s.%c %s,%s", size
, argv
[1], argv
[0]);
2753 do_pseudo_pusha (int argc ATTRIBUTE_UNUSED
, char *argv
[], int pv ATTRIBUTE_UNUSED
)
2755 /* If users omit push location, use $sp as default value. */
2756 char location
[8] = "$sp"; /* 8 is enough for register name. */
2760 strncpy (location
, argv
[1], 8);
2764 md_assemblef ("la $ta,%s", argv
[0]);
2765 md_assemblef ("smw.adm $ta,[%s],$ta", location
);
2769 do_pseudo_pushi (int argc ATTRIBUTE_UNUSED
, char *argv
[], int pv ATTRIBUTE_UNUSED
)
2771 /* If users omit push location, use $sp as default value. */
2772 char location
[8] = "$sp"; /* 8 is enough for register name. */
2776 strncpy (location
, argv
[1], 8);
2780 md_assemblef ("li $ta,%s", argv
[0]);
2781 md_assemblef ("smw.adm $ta,[%s],$ta", location
);
2784 struct nds32_pseudo_opcode nds32_pseudo_opcode_table
[] =
2786 {"b", 1, do_pseudo_b
, 0, 0},
2787 {"bal", 1, do_pseudo_bal
, 0, 0},
2789 {"bge", 3, do_pseudo_bge
, 0, 0},
2790 {"bges", 3, do_pseudo_bges
, 0, 0},
2792 {"bgt", 3, do_pseudo_bgt
, 0, 0},
2793 {"bgts", 3, do_pseudo_bgts
, 0, 0},
2795 {"ble", 3, do_pseudo_ble
, 0, 0},
2796 {"bles", 3, do_pseudo_bles
, 0, 0},
2798 {"blt", 3, do_pseudo_blt
, 0, 0},
2799 {"blts", 3, do_pseudo_blts
, 0, 0},
2801 {"br", 1, do_pseudo_br
, 0, 0},
2802 {"bral", 1, do_pseudo_bral
, 0, 0},
2804 {"call", 1, do_pseudo_bal
, 0, 0},
2806 {"la", 2, do_pseudo_la
, 0, 0},
2807 {"li", 2, do_pseudo_li
, 0, 0},
2809 {"l.b", 2, do_pseudo_ls_bhw
, 0, 0},
2810 {"l.h", 2, do_pseudo_ls_bhw
, 1, 0},
2811 {"l.w", 2, do_pseudo_ls_bhw
, 2, 0},
2812 {"l.bs", 2, do_pseudo_ls_bhw
, 0 | 0x10, 0},
2813 {"l.hs", 2, do_pseudo_ls_bhw
, 1 | 0x10, 0},
2814 {"s.b", 2, do_pseudo_ls_bhw
, 0 | 0x80000000, 0},
2815 {"s.h", 2, do_pseudo_ls_bhw
, 1 | 0x80000000, 0},
2816 {"s.w", 2, do_pseudo_ls_bhw
, 2 | 0x80000000, 0},
2818 {"l.bp", 3, do_pseudo_ls_bhwp
, 0, 0},
2819 {"l.bpc", 3, do_pseudo_ls_bhwpc
, 0, 0},
2820 {"l.hp", 3, do_pseudo_ls_bhwp
, 1, 0},
2821 {"l.hpc", 3, do_pseudo_ls_bhwpc
, 1, 0},
2822 {"l.wp", 3, do_pseudo_ls_bhwp
, 2, 0},
2823 {"l.wpc", 3, do_pseudo_ls_bhwpc
, 2, 0},
2824 {"l.bsp", 3, do_pseudo_ls_bhwp
, 0 | 0x10, 0},
2825 {"l.bspc", 3, do_pseudo_ls_bhwpc
, 0 | 0x10, 0},
2826 {"l.hsp", 3, do_pseudo_ls_bhwp
, 1 | 0x10, 0},
2827 {"l.hspc", 3, do_pseudo_ls_bhwpc
, 1 | 0x10, 0},
2828 {"s.bp", 3, do_pseudo_ls_bhwp
, 0 | 0x80000000, 0},
2829 {"s.bpc", 3, do_pseudo_ls_bhwpc
, 0 | 0x80000000, 0},
2830 {"s.hp", 3, do_pseudo_ls_bhwp
, 1 | 0x80000000, 0},
2831 {"s.hpc", 3, do_pseudo_ls_bhwpc
, 1 | 0x80000000, 0},
2832 {"s.wp", 3, do_pseudo_ls_bhwp
, 2 | 0x80000000, 0},
2833 {"s.wpc", 3, do_pseudo_ls_bhwpc
, 2 | 0x80000000, 0},
2834 {"s.bsp", 3, do_pseudo_ls_bhwp
, 0 | 0x80000000 | 0x10, 0},
2835 {"s.hsp", 3, do_pseudo_ls_bhwp
, 1 | 0x80000000 | 0x10, 0},
2837 {"lbi.p", 3, do_pseudo_ls_bhwi
, 0, 0},
2838 {"lhi.p", 3, do_pseudo_ls_bhwi
, 1, 0},
2839 {"lwi.p", 3, do_pseudo_ls_bhwi
, 2, 0},
2840 {"sbi.p", 3, do_pseudo_ls_bhwi
, 0 | 0x80000000, 0},
2841 {"shi.p", 3, do_pseudo_ls_bhwi
, 1 | 0x80000000, 0},
2842 {"swi.p", 3, do_pseudo_ls_bhwi
, 2 | 0x80000000, 0},
2843 {"lbsi.p", 3, do_pseudo_ls_bhwi
, 0 | 0x10, 0},
2844 {"lhsi.p", 3, do_pseudo_ls_bhwi
, 1 | 0x10, 0},
2845 {"lwsi.p", 3, do_pseudo_ls_bhwi
, 0 | 0x10, 0},
2847 {"move", 2, do_pseudo_move
, 0, 0},
2848 {"neg", 2, do_pseudo_neg
, 0, 0},
2849 {"not", 2, do_pseudo_not
, 0, 0},
2851 {"pop", 2, do_pseudo_pushpop
, 0, 0},
2852 {"push", 2, do_pseudo_pushpop
, 0, 0},
2853 {"popm", 2, do_pseudo_pushpopm
, 0, 0},
2854 {"pushm", 3, do_pseudo_pushpopm
, 0, 0},
2856 {"v3push", 2, do_pseudo_v3push
, 0, 0},
2857 {"v3pop", 2, do_pseudo_v3pop
, 0, 0},
2859 /* Support pseudo instructions of pushing/poping registers into/from stack
2860 push.s Rb, Re, { $fp $gp $lp $sp } ==> smw.adm Rb,[$sp],Re,Enable4
2861 pop.s Rb, Re, { $fp $gp $lp $sp } ==> lmw.bim Rb,[$sp],Re,Enable4 */
2862 { "push.s", 3, do_pseudo_pushpop_stack
, 0, 0 },
2863 { "pop.s", 3, do_pseudo_pushpop_stack
, 1, 0 },
2864 { "push.b", 2, do_pseudo_push_bhwd
, 0, 0 },
2865 { "push.h", 2, do_pseudo_push_bhwd
, 1, 0 },
2866 { "push.w", 2, do_pseudo_push_bhwd
, 2, 0 },
2867 { "push.d", 2, do_pseudo_push_bhwd
, 3, 0 },
2868 { "pop.b", 3, do_pseudo_pop_bhwd
, 0, 0 },
2869 { "pop.h", 3, do_pseudo_pop_bhwd
, 1, 0 },
2870 { "pop.w", 3, do_pseudo_pop_bhwd
, 2, 0 },
2871 { "pop.d", 3, do_pseudo_pop_bhwd
, 3, 0 },
2872 { "pusha", 2, do_pseudo_pusha
, 0, 0 },
2873 { "pushi", 2, do_pseudo_pushi
, 0, 0 },
2875 {NULL
, 0, NULL
, 0, 0}
2879 nds32_init_nds32_pseudo_opcodes (void)
2881 struct nds32_pseudo_opcode
*opcode
= nds32_pseudo_opcode_table
;
2883 nds32_pseudo_opcode_hash
= hash_new ();
2884 for ( ; opcode
->opcode
; opcode
++)
2888 op
= hash_find (nds32_pseudo_opcode_hash
, opcode
->opcode
);
2891 as_warn (_("Duplicated pseudo-opcode %s."), opcode
->opcode
);
2894 hash_insert (nds32_pseudo_opcode_hash
, opcode
->opcode
, opcode
);
2898 static struct nds32_pseudo_opcode
*
2899 nds32_lookup_pseudo_opcode (char *str
)
2902 /* Assume pseudo-opcode are less than 16-char in length. */
2905 for (i
= 0; i
< (int)ARRAY_SIZE (op
); i
++)
2907 if (ISSPACE (op
[i
] = str
[i
]))
2911 if (i
>= (int)ARRAY_SIZE (op
))
2916 return hash_find (nds32_pseudo_opcode_hash
, op
);
2920 nds32_pseudo_opcode_wrapper (char *line
, struct nds32_pseudo_opcode
*opcode
)
2923 char *argv
[8] = {NULL
};
2925 char *str
= xstrdup (line
);
2927 /* Parse arguments for opcode. */
2928 s
= str
+ strlen (opcode
->opcode
);
2933 /* Dummy comma to ease separate arguments as below. */
2939 if (argc
>= opcode
->argc
2940 || (argc
>= (int)ARRAY_SIZE (argv
) - 1))
2941 as_bad (_("Too many argument. `%s'"), line
);
2948 } while (s
[0] != '\0');
2950 /* Put the origin line for debugging. */
2952 opcode
->proc (argc
, argv
, opcode
->pseudo_val
);
2956 /* This function will be invoked from function `nds32_after_parse_args'.
2957 Thus, if the value of option has been set, keep the value the way it is. */
2960 nds32_parse_arch (char *str
)
2962 static const struct nds32_arch
2973 {"v3m", ISA_V3M
, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_AABI
},
2974 {"v3j", ISA_V3
, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_AABI
},
2975 {"v3s", ISA_V3
, 0, 1, 0, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_V2FP_PLUS
},
2976 {"v3f", ISA_V3
, 0, 1, 1, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_V2FP_PLUS
},
2977 {"v3", ISA_V3
, 0, 0, 0, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_AABI
},
2978 {"v2j", ISA_V2
, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_AABI
},
2979 {"v2s", ISA_V2
, 0, 1, 0, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_V2FP_PLUS
},
2980 {"v2f", ISA_V2
, 0, 1, 1, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_V2FP_PLUS
},
2981 {"v2", ISA_V2
, 0, 0, 0, E_NDS32_FPU_REG_32SP_16DP
, E_NDS_ABI_AABI
},
2985 for (i
= 0; i
< ARRAY_SIZE (archs
); i
++)
2987 if (strcmp (str
, archs
[i
].name
) != 0)
2990 /* The value `-1' represents this option has *NOT* been set. */
2991 nds32_baseline
= (-1 != nds32_baseline
) ? nds32_baseline
: archs
[i
].baseline
;
2992 nds32_gpr16
= (-1 != nds32_gpr16
) ? nds32_gpr16
: archs
[i
].reduced_reg
;
2993 nds32_fpu_sp_ext
= (-1 != nds32_fpu_sp_ext
) ? nds32_fpu_sp_ext
: archs
[i
].fpu_sp_ext
;
2994 nds32_fpu_dp_ext
= (-1 != nds32_fpu_dp_ext
) ? nds32_fpu_dp_ext
: archs
[i
].fpu_dp_ext
;
2995 nds32_freg
= (-1 != nds32_freg
) ? nds32_freg
: archs
[i
].fpu_freg
;
2996 nds32_abi
= (-1 != nds32_abi
) ? nds32_abi
: archs
[i
].abi
;
3001 /* Logic here rejects the input arch name. */
3002 as_bad (_("unknown arch name `%s'\n"), str
);
3007 /* This function parses "baseline" specified. */
3010 nds32_parse_baseline (char *str
)
3012 if (strcmp (str
, "v3") == 0)
3013 nds32_baseline
= ISA_V3
;
3014 else if (strcmp (str
, "v3m") == 0)
3015 nds32_baseline
= ISA_V3M
;
3016 else if (strcmp (str
, "v2") == 0)
3017 nds32_baseline
= ISA_V2
;
3020 /* Logic here rejects the input baseline. */
3021 as_bad (_("unknown baseline `%s'\n"), str
);
3028 /* This function parses "fpu-freg" specified. */
3031 nds32_parse_freg (char *str
)
3033 if (strcmp (str
, "2") == 0)
3034 nds32_freg
= E_NDS32_FPU_REG_32SP_16DP
;
3035 else if (strcmp (str
, "3") == 0)
3036 nds32_freg
= E_NDS32_FPU_REG_32SP_32DP
;
3037 else if (strcmp (str
, "1") == 0)
3038 nds32_freg
= E_NDS32_FPU_REG_16SP_8DP
;
3039 else if (strcmp (str
, "0") == 0)
3040 nds32_freg
= E_NDS32_FPU_REG_8SP_4DP
;
3043 /* Logic here rejects the input FPU configuration. */
3044 as_bad (_("unknown FPU configuration `%s'\n"), str
);
3051 /* This function parse "abi=" specified. */
3054 nds32_parse_abi (char *str
)
3056 if (strcmp (str
, "v2") == 0)
3057 nds32_abi
= E_NDS_ABI_AABI
;
3059 else if (strcmp (str
, "v2fp") == 0)
3060 nds32_abi
= E_NDS_ABI_V2FP
;
3061 else if (strcmp (str
, "v1") == 0)
3062 nds32_abi
= E_NDS_ABI_V1
;
3063 else if (strcmp (str
,"v2fpp") == 0)
3064 nds32_abi
= E_NDS_ABI_V2FP_PLUS
;
3067 /* Logic here rejects the input abi version. */
3068 as_bad (_("unknown ABI version`%s'\n"), str
);
3075 /* This function turn on all extensions and instructions support. */
3078 nds32_all_ext (void)
3083 nds32_16bit_ext
= 1;
3085 nds32_perf_ext2
= 1;
3086 nds32_string_ext
= 1;
3087 nds32_audio_ext
= 1;
3089 nds32_fpu_sp_ext
= 1;
3090 nds32_fpu_dp_ext
= 1;
3095 /* GAS will call md_parse_option whenever getopt returns an unrecognized code,
3096 presumably indicating a special code value which appears in md_longopts.
3097 This function should return non-zero if it handled the option and zero
3098 otherwise. There is no need to print a message about an option not being
3099 recognized. This will be handled by the generic code. */
3102 nds32_parse_option (int c
, char *arg
)
3104 struct nds32_parse_option_table
*coarse_tune
;
3105 struct nds32_set_option_table
*fine_tune
;
3106 char *ptr_arg
= NULL
;
3110 case OPTION_OPTIMIZE
:
3112 optimize_for_space
= 0;
3114 case OPTION_OPTIMIZE_SPACE
:
3116 optimize_for_space
= 1;
3119 target_big_endian
= 1;
3122 target_big_endian
= 0;
3130 case OPTION_RELAX_FP_AS_GP_OFF
:
3131 nds32_relax_fp_as_gp
= 0;
3133 case OPTION_RELAX_B2BB_ON
:
3134 nds32_relax_b2bb
= 1;
3136 case OPTION_RELAX_ALL_OFF
:
3137 nds32_relax_all
= 0;
3140 /* Determination of which option table to search for to save time. */
3141 ptr_arg
= strchr (arg
, '=');
3144 /* Find the value after '='. */
3145 if (ptr_arg
!= NULL
)
3147 for (coarse_tune
= parse_opts
; coarse_tune
->name
!= NULL
; coarse_tune
++)
3149 if (strncmp (arg
, coarse_tune
->name
, (ptr_arg
- arg
)) == 0)
3151 coarse_tune
->func (ptr_arg
);
3158 for (fine_tune
= toggle_opts
; fine_tune
->name
!= NULL
; fine_tune
++)
3162 /* Filter out the Disable option first. */
3163 if (strncmp (arg
, "no-", 3) == 0)
3169 if (strcmp (arg
, fine_tune
->name
) == 0)
3171 if (fine_tune
->var
!= NULL
)
3172 *fine_tune
->var
= (disable
) ? 0 : 1;
3177 /* Nothing match. */
3184 /* tc_check_label */
3187 nds32_check_label (symbolS
*label ATTRIBUTE_UNUSED
)
3189 /* The code used to create BB is move to frob_label.
3190 They should go there. */
3194 set_endian_little (int on
)
3196 target_big_endian
= !on
;
3199 /* These functions toggles the generation of 16-bit. First encounter signals
3200 the beginning of not generating 16-bit instructions and next encounter
3201 signals the restoring back to default behavior. */
3204 trigger_16bit (int trigger
)
3206 enable_16bit
= trigger
;
3209 static int backup_16bit_mode
;
3211 restore_16bit (int no_use ATTRIBUTE_UNUSED
)
3213 enable_16bit
= backup_16bit_mode
;
3217 off_16bit (int no_use ATTRIBUTE_UNUSED
)
3219 backup_16bit_mode
= enable_16bit
;
3223 /* Built-in segments for small object. */
3224 typedef struct nds32_seg_entryT
3231 nds32_seg_entry nds32_seg_table
[] =
3233 {NULL
, ".sdata_f", SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
| SEC_DATA
3234 | SEC_HAS_CONTENTS
| SEC_SMALL_DATA
},
3235 {NULL
, ".sdata_b", SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
| SEC_DATA
3236 | SEC_HAS_CONTENTS
| SEC_SMALL_DATA
},
3237 {NULL
, ".sdata_h", SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
| SEC_DATA
3238 | SEC_HAS_CONTENTS
| SEC_SMALL_DATA
},
3239 {NULL
, ".sdata_w", SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
| SEC_DATA
3240 | SEC_HAS_CONTENTS
| SEC_SMALL_DATA
},
3241 {NULL
, ".sdata_d", SEC_ALLOC
| SEC_LOAD
| SEC_RELOC
| SEC_DATA
3242 | SEC_HAS_CONTENTS
| SEC_SMALL_DATA
},
3243 {NULL
, ".sbss_f", SEC_ALLOC
| SEC_SMALL_DATA
},
3244 {NULL
, ".sbss_b", SEC_ALLOC
| SEC_SMALL_DATA
},
3245 {NULL
, ".sbss_h", SEC_ALLOC
| SEC_SMALL_DATA
},
3246 {NULL
, ".sbss_w", SEC_ALLOC
| SEC_SMALL_DATA
},
3247 {NULL
, ".sbss_d", SEC_ALLOC
| SEC_SMALL_DATA
}
3250 /* Indexes to nds32_seg_table[]. */
3251 enum NDS32_SECTIONS_ENUM
3253 SDATA_F_SECTION
= 0,
3254 SDATA_B_SECTION
= 1,
3255 SDATA_H_SECTION
= 2,
3256 SDATA_W_SECTION
= 3,
3257 SDATA_D_SECTION
= 4,
3265 /* The following code is borrowed from v850_seg. Revise this is needed. */
3268 do_nds32_seg (int i
, subsegT sub
)
3270 nds32_seg_entry
*seg
= nds32_seg_table
+ i
;
3272 obj_elf_section_change_hook ();
3275 subseg_set (seg
->s
, sub
);
3278 seg
->s
= subseg_new (seg
->name
, sub
);
3279 if (OUTPUT_FLAVOR
== bfd_target_elf_flavour
)
3281 bfd_set_section_flags (stdoutput
, seg
->s
, seg
->flags
);
3282 if ((seg
->flags
& SEC_LOAD
) == 0)
3283 seg_info (seg
->s
)->bss
= 1;
3291 subsegT sub
= get_absolute_expression ();
3293 do_nds32_seg (i
, sub
);
3294 demand_empty_rest_of_line ();
3297 /* Set if label adjustment is needed. I should not adjust .xbyte in dwarf. */
3298 static symbolS
*nds32_last_label
; /* Last label for aligment. */
3300 /* This code is referred from D30V for adjust label to be with pedning
3301 aligment. For example,
3305 Without this, the above label will not attatch to incoming data. */
3308 nds32_adjust_label (int n
)
3310 /* FIXME: I think adjust lable and alignment is
3311 the programmer's obligation. Saddly, VLSI team doesn't
3312 properly use .align for their test cases.
3313 So I re-implement cons_align and auto adjust labels, again.
3315 I think d30v's implmentation is simple and good enough. */
3317 symbolS
*label
= nds32_last_label
;
3318 nds32_last_label
= NULL
;
3320 /* SEC_ALLOC is used to eliminate .debug_ sections.
3321 SEC_CODE is used to include section for ILM. */
3322 if (((now_seg
->flags
& SEC_ALLOC
) == 0 && (now_seg
->flags
& SEC_CODE
) == 0)
3323 || strcmp (now_seg
->name
, ".eh_frame") == 0
3324 || strcmp (now_seg
->name
, ".gcc_except_table") == 0)
3327 /* Only frag by alignment when needed.
3328 Otherwise, it will fail to optimize labels on 4-byte boundary. (bug8454)
3329 See md_convert_frag () and RELAX_SET_RELAXABLE (frag) for details. */
3330 if (frag_now_fix () & ((1 << n
) -1 ))
3332 if (subseg_text_p (now_seg
))
3333 frag_align_code (n
, 0);
3335 frag_align (n
, 0, 0);
3337 /* Record the minimum alignment for this segment. */
3338 record_alignment (now_seg
, n
- OCTETS_PER_BYTE_POWER
);
3344 int label_seen
= FALSE
;
3345 struct frag
*old_frag
;
3346 valueT old_value
, new_value
;
3348 gas_assert (S_GET_SEGMENT (label
) == now_seg
);
3350 old_frag
= symbol_get_frag (label
);
3351 old_value
= S_GET_VALUE (label
);
3352 new_value
= (valueT
) frag_now_fix ();
3354 /* Multiple labels may be on the same address. And the last symbol
3355 may not be a label at all, e.g., register name, external function names,
3356 so I have to track the last label in tc_frob_label instead of
3357 just using symbol_lastP. */
3358 for (sym
= symbol_lastP
; sym
!= NULL
; sym
= symbol_previous (sym
))
3360 if (symbol_get_frag (sym
) == old_frag
3361 && S_GET_VALUE (sym
) == old_value
)
3365 symbol_set_frag (sym
, frag_now
);
3366 S_SET_VALUE (sym
, new_value
);
3368 else if (label_seen
&& symbol_get_frag (sym
) != old_frag
)
3375 nds32_cons_align (int size ATTRIBUTE_UNUSED
)
3378 This is called before `md_flush_pending_output' is called by `cons'.
3380 There are two things should be done for auto-adjust-label.
3381 1. Align data/instructions and adjust label to be attached to them.
3382 2. Clear auto-adjust state, so incommng data/instructions will not
3390 in this case, '.word 0x2' will adjust the label, .L0, but '.word 0x3' should not.
3392 I think `md_flush_pending_output' is a good place to clear the auto-adjust state,
3393 but it is also called by `cons' before this function.
3394 To simplify the code, instead of overriding .zero, .fill, .space, etc,
3395 I think we should just adjust label in `nds32_aligned_X_cons' instead of here. */
3399 nds32_aligned_cons (int idx
)
3401 nds32_adjust_label (idx
);
3402 /* Call default handler. */
3404 if (now_seg
->flags
& SEC_CODE
3405 && now_seg
->flags
& SEC_ALLOC
&& now_seg
->flags
& SEC_RELOC
)
3407 /* Use BFD_RELOC_NDS32_DATA to avoid EX9 optimization replacing data. */
3410 exp
.X_add_number
= 0;
3411 exp
.X_op
= O_constant
;
3412 fix_new_exp (frag_now
,
3413 frag_now_fix () - (1 << idx
),
3417 BFD_RELOC_NDS32_DATA
);
3421 /* `.double' directive. */
3424 nds32_aligned_float_cons (int type
)
3432 nds32_adjust_label (2);
3438 nds32_adjust_label (4);
3441 as_bad ("Unrecognized float type, %c\n", (char)type
);
3443 /* Call default handler. */
3448 nds32_enable_pic (int ignore ATTRIBUTE_UNUSED
)
3450 /* Another way to do -mpic.
3451 This is for GCC internal use and should always be first line
3452 of code, otherwise, the effect is not determined. */
3457 nds32_set_abi (int ver
)
3462 /* Relax directive to set relocation R_NDS32_RELAX_ENTRY value. */
3465 nds32_relax_relocs (int relax
)
3470 char *subtype_relax
[] =
3471 {"", "", "ex9", "ifc"};
3473 name
= input_line_pointer
;
3474 while (*input_line_pointer
&& !ISSPACE (*input_line_pointer
))
3475 input_line_pointer
++;
3476 saved_char
= *input_line_pointer
;
3477 *input_line_pointer
= 0;
3479 for (i
= 0; i
< (int) ARRAY_SIZE (subtype_relax
); i
++)
3481 if (strcmp (name
, subtype_relax
[i
]) == 0)
3487 enable_relax_relocs
= relax
& enable_relax_relocs
;
3488 enable_relax_ex9
= relax
& enable_relax_ex9
;
3489 enable_relax_ifc
= relax
& enable_relax_ifc
;
3492 enable_relax_ex9
= relax
;
3495 enable_relax_ifc
= relax
;
3503 *input_line_pointer
= saved_char
;
3504 ignore_rest_of_line ();
3507 /* Record which arguments register($r0 ~ $r5) is not used in callee.
3511 nds32_set_hint_func_args (int ignore ATTRIBUTE_UNUSED
)
3513 ignore_rest_of_line ();
3516 /* Insert relocations to mark the begin and end of a fp-omitted function,
3517 for further relaxation use.
3521 nds32_omit_fp_begin (int mode
)
3525 if (nds32_relax_fp_as_gp
== 0)
3527 exp
.X_op
= O_symbol
;
3528 exp
.X_add_symbol
= abs_section_sym
;
3531 exp
.X_add_number
= R_NDS32_RELAX_REGION_OMIT_FP_FLAG
;
3532 fix_new_exp (frag_now
, frag_now_fix (), 0, &exp
, 0,
3533 BFD_RELOC_NDS32_RELAX_REGION_BEGIN
);
3537 exp
.X_add_number
= R_NDS32_RELAX_REGION_OMIT_FP_FLAG
;
3538 fix_new_exp (frag_now
, frag_now_fix (), 0, &exp
, 0,
3539 BFD_RELOC_NDS32_RELAX_REGION_END
);
3543 /* Insert relocations to mark the begin and end of ex9 region,
3544 for further relaxation use.
3548 nds32_no_ex9_begin (int mode
)
3552 exp
.X_op
= O_symbol
;
3553 exp
.X_add_symbol
= abs_section_sym
;
3556 exp
.X_add_number
= R_NDS32_RELAX_REGION_NO_EX9_FLAG
;
3557 fix_new_exp (frag_now
, frag_now_fix (), 0, &exp
, 0,
3558 BFD_RELOC_NDS32_RELAX_REGION_BEGIN
);
3562 exp
.X_add_number
= R_NDS32_RELAX_REGION_NO_EX9_FLAG
;
3563 fix_new_exp (frag_now
, frag_now_fix (), 0, &exp
, 0,
3564 BFD_RELOC_NDS32_RELAX_REGION_END
);
3569 nds32_loop_begin (int mode
)
3571 /* Insert loop region relocation here. */
3574 exp
.X_op
= O_symbol
;
3575 exp
.X_add_symbol
= abs_section_sym
;
3578 exp
.X_add_number
= R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG
;
3579 fix_new_exp (frag_now
, frag_now_fix (), 0, &exp
, 0,
3580 BFD_RELOC_NDS32_RELAX_REGION_BEGIN
);
3584 exp
.X_add_number
= R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG
;
3585 fix_new_exp (frag_now
, frag_now_fix (), 0, &exp
, 0,
3586 BFD_RELOC_NDS32_RELAX_REGION_END
);
3590 struct nds32_relocs_group
3592 struct nds32_relocs_pattern
*pattern
;
3593 struct nds32_relocs_group
*next
;
3596 static struct nds32_relocs_group
*nds32_relax_hint_current
= NULL
;
3598 /* Insert a relax hint. */
3601 nds32_relax_hint (int mode ATTRIBUTE_UNUSED
)
3605 struct nds32_relocs_pattern
*relocs
= NULL
;
3606 struct nds32_relocs_group
*group
, *new;
3608 name
= input_line_pointer
;
3609 while (*input_line_pointer
&& !ISSPACE (*input_line_pointer
))
3610 input_line_pointer
++;
3611 saved_char
= *input_line_pointer
;
3612 *input_line_pointer
= 0;
3613 name
= strdup (name
);
3615 /* Find relax hint entry for next instruction, and all member will be
3616 initialized at that time. */
3617 relocs
= hash_find (nds32_hint_hash
, name
);
3620 relocs
= malloc (sizeof (struct nds32_relocs_pattern
));
3621 hash_insert (nds32_hint_hash
, name
, relocs
);
3625 while (relocs
->next
)
3626 relocs
=relocs
->next
;
3627 relocs
->next
= malloc (sizeof (struct nds32_relocs_pattern
));
3628 relocs
= relocs
->next
;
3631 relocs
->next
= NULL
;
3632 *input_line_pointer
= saved_char
;
3633 ignore_rest_of_line ();
3635 /* Get the final one of relax hint series. */
3637 /* It has to build this list because there are maybe more than one
3638 instructions relative to the same instruction. It to connect to
3639 next instruction after md_assemble. */
3640 new = malloc (sizeof (struct nds32_relocs_group
));
3641 new->pattern
= relocs
;
3643 group
= nds32_relax_hint_current
;
3645 nds32_relax_hint_current
= new;
3648 while (group
->next
!= NULL
)
3649 group
= group
->next
;
3654 /* Decide the size of vector entries, only accepts 4 or 16 now. */
3657 nds32_vec_size (int ignore ATTRIBUTE_UNUSED
)
3663 if (exp
.X_op
== O_constant
)
3665 if (exp
.X_add_number
== 4 || exp
.X_add_number
== 16)
3668 vec_size
= exp
.X_add_number
;
3669 else if (vec_size
!= exp
.X_add_number
)
3670 as_warn (_("Different arguments of .vec_size are found, "
3671 "previous %d, current %d"),
3672 (int) vec_size
, (int) exp
.X_add_number
);
3675 as_warn (_("Argument of .vec_size is expected 4 or 16, actual: %d."),
3676 (int) exp
.X_add_number
);
3679 as_warn (_("Argument of .vec_size is not a constant."));
3682 /* The behavior of ".flag" directive varies depending on the target.
3683 In nds32 target, we use it to recognize whether this assembly content is
3684 generated by compiler. Other features can also be added in this function
3688 nds32_flag (int ignore ATTRIBUTE_UNUSED
)
3693 char *possible_flags
[] = { "verbatim" };
3695 /* Skip whitespaces. */
3696 name
= input_line_pointer
;
3697 while (*input_line_pointer
&& !ISSPACE (*input_line_pointer
))
3698 input_line_pointer
++;
3699 saved_char
= *input_line_pointer
;
3700 *input_line_pointer
= 0;
3702 for (i
= 0; i
< (int) ARRAY_SIZE (possible_flags
); i
++)
3704 if (strcmp (name
, possible_flags
[i
]) == 0)
3709 /* flag: verbatim */
3715 /* Already found the flag, no need to continue next loop. */
3720 *input_line_pointer
= saved_char
;
3721 ignore_rest_of_line ();
3725 nds32_n12hc (int ignore ATTRIBUTE_UNUSED
)
3727 /* N1213HC core is used. */
3731 /* The target specific pseudo-ops which we support. */
3732 const pseudo_typeS md_pseudo_table
[] =
3734 /* Forced alignment if declared these ways. */
3735 {"ascii", stringer
, 8 + 0},
3736 {"asciz", stringer
, 8 + 1},
3737 {"double", nds32_aligned_float_cons
, 'd'},
3738 {"dword", nds32_aligned_cons
, 3},
3739 {"float", nds32_aligned_float_cons
, 'f'},
3740 {"half", nds32_aligned_cons
, 1},
3741 {"hword", nds32_aligned_cons
, 1},
3742 {"int", nds32_aligned_cons
, 2},
3743 {"long", nds32_aligned_cons
, 2},
3744 {"octa", nds32_aligned_cons
, 4},
3745 {"quad", nds32_aligned_cons
, 3},
3746 {"qword", nds32_aligned_cons
, 4},
3747 {"short", nds32_aligned_cons
, 1},
3748 {"byte", nds32_aligned_cons
, 0},
3749 {"single", nds32_aligned_float_cons
, 'f'},
3750 {"string", stringer
, 8 + 1},
3751 {"word", nds32_aligned_cons
, 2},
3753 {"little", set_endian_little
, 1},
3754 {"big", set_endian_little
, 0},
3755 {"16bit_on", trigger_16bit
, 1},
3756 {"16bit_off", trigger_16bit
, 0},
3757 {"restore_16bit", restore_16bit
, 0},
3758 {"off_16bit", off_16bit
, 0},
3760 {"sdata_d", nds32_seg
, SDATA_D_SECTION
},
3761 {"sdata_w", nds32_seg
, SDATA_W_SECTION
},
3762 {"sdata_h", nds32_seg
, SDATA_H_SECTION
},
3763 {"sdata_b", nds32_seg
, SDATA_B_SECTION
},
3764 {"sdata_f", nds32_seg
, SDATA_F_SECTION
},
3766 {"sbss_d", nds32_seg
, SBSS_D_SECTION
},
3767 {"sbss_w", nds32_seg
, SBSS_W_SECTION
},
3768 {"sbss_h", nds32_seg
, SBSS_H_SECTION
},
3769 {"sbss_b", nds32_seg
, SBSS_B_SECTION
},
3770 {"sbss_f", nds32_seg
, SBSS_F_SECTION
},
3772 {"pic", nds32_enable_pic
, 0},
3773 {"n12_hc", nds32_n12hc
, 0},
3774 {"abi_1", nds32_set_abi
, E_NDS_ABI_V1
},
3775 {"abi_2", nds32_set_abi
, E_NDS_ABI_AABI
},
3777 {"abi_2fp", nds32_set_abi
, E_NDS_ABI_V2FP
},
3778 {"abi_2fp_plus", nds32_set_abi
, E_NDS_ABI_V2FP_PLUS
},
3779 {"relax", nds32_relax_relocs
, 1},
3780 {"no_relax", nds32_relax_relocs
, 0},
3781 {"hint_func_args", nds32_set_hint_func_args
, 0}, /* Abandon?? */
3782 {"omit_fp_begin", nds32_omit_fp_begin
, 1},
3783 {"omit_fp_end", nds32_omit_fp_begin
, 0},
3784 {"no_ex9_begin", nds32_no_ex9_begin
, 1},
3785 {"no_ex9_end", nds32_no_ex9_begin
, 0},
3786 {"vec_size", nds32_vec_size
, 0},
3787 {"flag", nds32_flag
, 0},
3788 {"innermost_loop_begin", nds32_loop_begin
, 1},
3789 {"innermost_loop_end", nds32_loop_begin
, 0},
3790 {"relax_hint", nds32_relax_hint
, 0},
3795 nds32_pre_do_align (int n
, char *fill
, int len
, int max
)
3797 /* Only make a frag if we HAVE to... */
3798 if (n
!= 0 && !need_pass_2
)
3802 if (subseg_text_p (now_seg
))
3803 frag_align_code (n
, max
);
3805 frag_align (n
, 0, max
);
3808 frag_align (n
, *fill
, max
);
3810 frag_align_pattern (n
, fill
, len
, max
);
3815 nds32_do_align (int n
)
3817 /* Optimize for space and label exists. */
3820 /* FIXME:I think this will break debug info sections and except_table. */
3821 if (!enable_relax_relocs
|| !subseg_text_p (now_seg
))
3824 /* Create and attach a BFD_RELOC_NDS32_LABEL fixup
3825 the size of instruction may not be correct because
3826 it could be relaxable. */
3827 exp
.X_op
= O_symbol
;
3828 exp
.X_add_symbol
= section_symbol (now_seg
);
3829 exp
.X_add_number
= n
;
3830 fix_new_exp (frag_now
,
3831 frag_now_fix (), 0, &exp
, 0, BFD_RELOC_NDS32_LABEL
);
3834 /* Supported Andes machines. */
3837 enum bfd_architecture bfd_mach
;
3841 /* This is the callback for nds32-asm.c to parse operands. */
3844 nds32_asm_parse_operand (struct nds32_asm_desc
*pdesc ATTRIBUTE_UNUSED
,
3845 struct nds32_asm_insn
*pinsn
,
3846 char **pstr
, int64_t *value
)
3849 expressionS
*pexp
= pinsn
->info
;
3851 hold
= input_line_pointer
;
3852 input_line_pointer
= *pstr
;
3854 *pstr
= input_line_pointer
;
3855 input_line_pointer
= hold
;
3861 return NASM_R_SYMBOL
;
3863 *value
= pexp
->X_add_number
;
3864 return NASM_R_CONST
;
3869 return NASM_R_ILLEGAL
;
3873 /* GAS will call this function at the start of the assembly, after the command
3874 line arguments have been parsed and all the machine independent
3875 initializations have been completed. */
3880 struct nds32_keyword
*k
;
3881 relax_info_t
*relax_info
;
3883 bfd_set_arch_mach (stdoutput
, TARGET_ARCH
, nds32_baseline
);
3885 nds32_init_nds32_pseudo_opcodes ();
3886 asm_desc
.parse_operand
= nds32_asm_parse_operand
;
3887 nds32_asm_init (&asm_desc
, 0);
3889 /* Initial general pupose registers hash table. */
3890 nds32_gprs_hash
= hash_new ();
3891 for (k
= nds32_gprs
; k
->name
; k
++)
3892 hash_insert (nds32_gprs_hash
, k
->name
, k
);
3894 /* Initial branch hash table. */
3895 nds32_relax_info_hash
= hash_new ();
3896 for (relax_info
= relax_table
; relax_info
->opcode
; relax_info
++)
3897 hash_insert (nds32_relax_info_hash
, relax_info
->opcode
, relax_info
);
3899 /* Initial relax hint hash table. */
3900 nds32_hint_hash
= hash_new ();
3903 /* HANDLE_ALIGN in write.c. */
3906 nds32_handle_align (fragS
*fragp
)
3908 static const unsigned char nop16
[] = { 0x92, 0x00 };
3909 static const unsigned char nop32
[] = { 0x40, 0x00, 0x00, 0x09 };
3913 if (fragp
->fr_type
!= rs_align_code
)
3916 bytes
= fragp
->fr_next
->fr_address
- fragp
->fr_address
- fragp
->fr_fix
;
3917 p
= fragp
->fr_literal
+ fragp
->fr_fix
;
3928 exp_t
.X_op
= O_symbol
;
3929 exp_t
.X_add_symbol
= abs_section_sym
;
3930 exp_t
.X_add_number
= R_NDS32_INSN16_CONVERT_FLAG
;
3931 fix_new_exp (fragp
, fragp
->fr_fix
, 2, &exp_t
, 0,
3932 BFD_RELOC_NDS32_INSN16
);
3933 memcpy (p
, nop16
, 2);
3940 memcpy (p
, nop32
, 4);
3945 bytes
= fragp
->fr_next
->fr_address
- fragp
->fr_address
- fragp
->fr_fix
;
3946 fragp
->fr_fix
+= bytes
;
3949 /* md_flush_pending_output */
3952 nds32_flush_pending_output (void)
3954 nds32_last_label
= NULL
;
3958 nds32_frob_label (symbolS
*label
)
3960 dwarf2_emit_label (label
);
3963 /* TC_START_LABEL */
3966 nds32_start_label (int asmdone ATTRIBUTE_UNUSED
, int secdone ATTRIBUTE_UNUSED
)
3974 nds32_target_format (void)
3977 if (target_big_endian
)
3978 return "elf32-nds32be-linux";
3980 return "elf32-nds32le-linux";
3982 if (target_big_endian
)
3983 return "elf32-nds32be";
3985 return "elf32-nds32le";
3989 static enum nds32_br_range
3990 get_range_type (const struct nds32_field
*field
)
3992 gas_assert (field
!= NULL
);
3994 if (field
->bitpos
!= 0)
3995 return BR_RANGE_U4G
;
3997 if (field
->bitsize
== 24 && field
->shift
== 1)
3998 return BR_RANGE_S16M
;
3999 else if (field
->bitsize
== 16 && field
->shift
== 1)
4000 return BR_RANGE_S64K
;
4001 else if (field
->bitsize
== 14 && field
->shift
== 1)
4002 return BR_RANGE_S16K
;
4003 else if (field
->bitsize
== 8 && field
->shift
== 1)
4004 return BR_RANGE_S256
;
4006 return BR_RANGE_U4G
;
4009 /* Save pseudo instruction relocation list. */
4011 static struct nds32_relocs_pattern
*
4012 nds32_elf_save_pseudo_pattern (int reloc
, struct nds32_asm_insn
*insn
,
4013 char *out
, symbolS
*sym
,
4014 struct nds32_relocs_pattern
*reloc_ptr
)
4017 reloc_ptr
= malloc (sizeof (struct nds32_relocs_pattern
));
4018 reloc_ptr
->seg
= now_seg
;
4019 reloc_ptr
->sym
= sym
;
4020 reloc_ptr
->frag
= frag_now
;
4021 reloc_ptr
->frchain
= frchain_now
;
4022 reloc_ptr
->reloc
= reloc
;
4023 reloc_ptr
->insn
= insn
->opcode
->value
;
4024 reloc_ptr
->size
= insn
->opcode
->isize
;
4025 reloc_ptr
->where
= out
;
4026 reloc_ptr
->next
= NULL
;
4030 /* Check X_md to transform relocation. */
4033 nds32_elf_record_fixup_exp (char *str
, const struct nds32_field
*fld
,
4034 expressionS
*pexp
, char* out
,
4035 struct nds32_asm_insn
*insn
)
4038 symbolS
*sym
= NULL
;
4039 struct nds32_relocs_group
*group
;
4040 struct nds32_relocs_pattern
*reloc_ptr
;
4042 /* Handle instruction relocation. */
4043 if (fld
&& fld
->bitpos
== 0 && (insn
->attr
& NASM_ATTR_HI20
))
4045 /* Relocation for hi20 modifier. */
4046 sym
= pexp
->X_add_symbol
;
4049 case BFD_RELOC_NDS32_GOTOFF
:
4051 reloc
= BFD_RELOC_NDS32_GOTOFF_HI20
;
4053 case BFD_RELOC_NDS32_GOT20
:
4055 reloc
= BFD_RELOC_NDS32_GOT_HI20
;
4057 case BFD_RELOC_NDS32_25_PLTREL
:
4060 as_bad (_("Invalid PIC expression."));
4062 reloc
= BFD_RELOC_NDS32_PLT_GOTREL_HI20
;
4066 reloc
= BFD_RELOC_NDS32_HI20
;
4070 fix_new_exp (frag_now
, out
- frag_now
->fr_literal
,
4071 insn
->opcode
->isize
, insn
->info
, 0 /* pcrel */,
4074 else if (fld
&& fld
->bitpos
== 0 && (insn
->attr
& NASM_ATTR_LO12
))
4076 /* Relocation for lo12 modifier. */
4077 if (fld
->bitsize
== 15 && fld
->shift
== 0)
4081 case BFD_RELOC_NDS32_GOTOFF
:
4083 reloc
= BFD_RELOC_NDS32_GOTOFF_LO12
;
4085 case BFD_RELOC_NDS32_GOT20
:
4087 reloc
= BFD_RELOC_NDS32_GOT_LO12
;
4089 case BFD_RELOC_NDS32_25_PLTREL
:
4092 as_bad (_("Invalid PIC expression."));
4094 reloc
= BFD_RELOC_NDS32_PLT_GOTREL_LO12
;
4098 reloc
= BFD_RELOC_NDS32_LO12S0
; /* [ls]bi || ori */
4102 else if (fld
->bitsize
== 15 && fld
->shift
== 1)
4103 reloc
= BFD_RELOC_NDS32_LO12S1
; /* [ls]hi */
4104 else if (fld
->bitsize
== 15 && fld
->shift
== 2)
4105 reloc
= BFD_RELOC_NDS32_LO12S2
; /* [ls]wi */
4106 else if (fld
->bitsize
== 15 && fld
->shift
== 3)
4107 reloc
= BFD_RELOC_NDS32_LO12S3
; /* [ls]di */
4108 else if (fld
->bitsize
== 12 && fld
->shift
== 2)
4109 reloc
= BFD_RELOC_NDS32_LO12S2
; /* f[ls][sd]i */
4111 fix_new_exp (frag_now
, out
- frag_now
->fr_literal
,
4112 insn
->opcode
->isize
, insn
->info
, 0 /* pcrel */,
4115 else if (fld
&& fld
->bitpos
== 0 && insn
->opcode
->isize
== 4
4116 && (insn
->attr
& NASM_ATTR_PCREL
))
4118 /* Relocation for 32-bit branch instructions. */
4119 if (fld
->bitsize
== 24 && fld
->shift
== 1)
4120 reloc
= BFD_RELOC_NDS32_25_PCREL
;
4121 else if (fld
->bitsize
== 16 && fld
->shift
== 1)
4122 reloc
= BFD_RELOC_NDS32_17_PCREL
;
4123 else if (fld
->bitsize
== 14 && fld
->shift
== 1)
4124 reloc
= BFD_RELOC_NDS32_15_PCREL
;
4125 else if (fld
->bitsize
== 8 && fld
->shift
== 1)
4126 reloc
= BFD_RELOC_NDS32_WORD_9_PCREL
;
4130 fix_new_exp (frag_now
, out
- frag_now
->fr_literal
,
4131 insn
->opcode
->isize
, insn
->info
, 1 /* pcrel */,
4134 else if (fld
&& fld
->bitpos
== 0 && insn
->opcode
->isize
== 4
4135 && (insn
->attr
& NASM_ATTR_GPREL
))
4137 /* Relocation for 32-bit gp-relative instructions. */
4138 if (fld
->bitsize
== 19 && fld
->shift
== 0)
4139 reloc
= BFD_RELOC_NDS32_SDA19S0
;
4140 else if (fld
->bitsize
== 18 && fld
->shift
== 1)
4141 reloc
= BFD_RELOC_NDS32_SDA18S1
;
4142 else if (fld
->bitsize
== 17 && fld
->shift
== 2)
4143 reloc
= BFD_RELOC_NDS32_SDA17S2
;
4147 fix_new_exp (frag_now
, out
- frag_now
->fr_literal
,
4148 insn
->opcode
->isize
, insn
->info
, 0 /* pcrel */,
4151 else if (fld
&& fld
->bitpos
== 0 && insn
->opcode
->isize
== 2
4152 && (insn
->attr
& NASM_ATTR_PCREL
))
4154 /* Relocation for 16-bit branch instructions. */
4155 if (fld
->bitsize
== 8 && fld
->shift
== 1)
4156 reloc
= BFD_RELOC_NDS32_9_PCREL
;
4160 fix_new_exp (frag_now
, out
- frag_now
->fr_literal
,
4161 insn
->opcode
->isize
, insn
->info
, 1 /* pcrel */,
4166 as_bad (_("Don't know how to handle this field. %s"),
4172 /* Save instruction relation for pseudo instruction expanding pattern. */
4173 reloc_ptr
= nds32_elf_save_pseudo_pattern (reloc
, insn
, out
, sym
, NULL
);
4175 relocs_list
= reloc_ptr
;
4178 struct nds32_relocs_pattern
*temp
= relocs_list
;
4181 temp
->next
= reloc_ptr
;
4184 else if (nds32_relax_hint_current
)
4186 /* Save instruction relation by relax hint. */
4187 group
= nds32_relax_hint_current
;
4190 nds32_elf_save_pseudo_pattern (reloc
, insn
, out
, sym
, group
->pattern
);
4191 group
= group
->next
;
4192 free (nds32_relax_hint_current
);
4193 nds32_relax_hint_current
= group
;
4198 #define N32_MEM_EXT(insn) (N32_OP6_MEM<< 25| insn)
4200 /* Relax pattern for link time relaxation. */
4202 static struct nds32_relocation_map relocation_table
[] =
4205 /* Load-Store: sethi lwi+
4206 Load address: sethi ori */
4207 BFD_RELOC_NDS32_HI20
, /* main_type */
4210 {BFD_RELOC_NDS32_LOADSTORE
, 0},
4214 {BFD_RELOC_NDS32_INSN16
, 0},
4223 /* Load-Store: sethi ori lwi+
4224 Load address: sethi ori add */
4225 BFD_RELOC_NDS32_GOTOFF_HI20
, /* main_type */
4228 {BFD_RELOC_NDS32_LOADSTORE
, 0},
4232 {BFD_RELOC_NDS32_INSN16
, 0},
4233 {BFD_RELOC_NDS32_PTR
, 0},
4234 {BFD_RELOC_NDS32_PTR_COUNT
, 0},
4238 {BFD_RELOC_NDS32_GOTOFF_SUFF
, 0},
4239 {BFD_RELOC_NDS32_PTR_RESOLVED
, 0},
4248 /* Load-Store: sethi ori lw lwi+
4249 Load address: sethi ori lw [addi|add] */
4250 BFD_RELOC_NDS32_GOT_HI20
, /* main_type */
4253 {BFD_RELOC_NDS32_LOADSTORE
, 0},
4257 {BFD_RELOC_NDS32_INSN16
, 0},
4258 /* For pseudo la and l.w.
4259 Lw is the next one instruction. */
4260 {BFD_RELOC_NDS32_PTR
, N32_MEM_EXT (N32_MEM_LW
)},
4261 {BFD_RELOC_NDS32_PTR_COUNT
, 0},
4265 {BFD_RELOC_NDS32_GOT_SUFF
, N32_MEM_EXT (N32_MEM_LW
)},
4266 {BFD_RELOC_NDS32_PTR_RESOLVED
, N32_MEM_EXT (N32_MEM_LW
)},
4275 BFD_RELOC_NDS32_PLT_GOTREL_HI20
, /* main_type */
4278 {BFD_RELOC_NDS32_LOADSTORE
, 0},
4282 {BFD_RELOC_NDS32_INSN16
, 0},
4284 jral is the target instruction. */
4285 {BFD_RELOC_NDS32_PTR
, INSN_JRAL
},
4286 {BFD_RELOC_NDS32_PTR
, (INSN_JRAL
| (REG_LP
<< 20))},
4287 {BFD_RELOC_NDS32_PTR_COUNT
, 0},
4292 jral is the target instruction. */
4293 {BFD_RELOC_NDS32_PTR
, INSN_JRAL
},
4294 {BFD_RELOC_NDS32_PTR
, (INSN_JRAL
| (REG_LP
<< 20))},
4295 {BFD_RELOC_NDS32_PTR_COUNT
, 0},
4299 {BFD_RELOC_NDS32_PLT_GOT_SUFF
, 0},
4300 {BFD_RELOC_NDS32_PTR_RESOLVED
, 0},
4318 /* Since sethi loadstore relocation has to using next instruction to determine
4319 elimination itself or not, we have to return the next instruction range. */
4322 nds32_elf_sethi_range (struct nds32_relocs_pattern
*relocs_ptr
)
4324 unsigned int insn
= relocs_ptr
->insn
;
4331 case N32_MEM_EXT (N32_MEM_LB
):
4332 case N32_MEM_EXT (N32_MEM_LBS
):
4333 case N32_MEM_EXT (N32_MEM_SB
):
4339 case N32_MEM_EXT (N32_MEM_LH
):
4340 case N32_MEM_EXT (N32_MEM_LHS
):
4341 case N32_MEM_EXT (N32_MEM_SH
):
4346 case N32_MEM_EXT (N32_MEM_LW
):
4347 case N32_MEM_EXT (N32_MEM_SW
):
4368 /* The args means: instruction size, the 1st instruction is converted to 16 or
4369 not, optimize option, 16 bit instruction is enable. */
4370 #define SET_ADDEND( size, convertible, optimize, insn16_on ) \
4371 (((size) & 0xff) | ((convertible) ? 1 << 31 : 0) \
4372 | ((optimize) ? 1<< 30 : 0) | (insn16_on ? 1 << 29 : 0))
4374 /* Insert new fix. */
4377 nds32_elf_insert_relocation (struct nds32_relocs_pattern
*pattern
, unsigned int reloc
,
4378 unsigned int insn_mask
, symbolS
*sym
)
4382 struct nds32_relocs_pattern
*pattern_t
;
4384 fragS
*frag
= pattern
->frag
;
4385 char *out
= pattern
->where
;
4386 unsigned int size
= pattern
->size
;
4387 static int ptr_count
= 0;
4389 exp
.X_op
= O_symbol
;
4390 exp
.X_add_symbol
= abs_section_sym
;
4391 exp
.X_add_number
= 0;
4395 case BFD_RELOC_NDS32_LOADSTORE
:
4396 /* To get the sethi match pattern. */
4397 range
= nds32_elf_sethi_range (pattern
->next
);
4398 exp
.X_add_number
= SET_ADDEND (4 /* size */, 0, optimize
, enable_16bit
);
4399 exp
.X_add_number
|= ((range
& 0x3f) << 8);
4400 fix_new_exp (frag
, out
- frag
->fr_literal
, size
, &exp
, 0 /* pcrel */, reloc
);
4403 case BFD_RELOC_NDS32_PTR
:
4404 pattern_t
= pattern
->next
;
4407 if (insn_mask
== 0 || pattern_t
->insn
== insn_mask
)
4409 sym_t
= symbol_temp_new (pattern_t
->seg
,
4410 pattern_t
->where
- pattern_t
->frag
->fr_literal
,
4412 exp
.X_add_symbol
= sym_t
;
4413 fix_new_exp (frag
, out
- frag
->fr_literal
, 0, &exp
, 0 /* pcrel */, reloc
);
4417 pattern_t
= pattern_t
->next
;
4421 case BFD_RELOC_NDS32_PTR_COUNT
:
4422 /* In current design, it only be referanced once. */
4425 exp
.X_add_number
= ptr_count
;
4426 fix_new_exp (frag
, out
- frag
->fr_literal
, size
, &exp
, 0, reloc
);
4431 case BFD_RELOC_NDS32_GOTOFF_SUFF
:
4432 case BFD_RELOC_NDS32_GOT_SUFF
:
4433 case BFD_RELOC_NDS32_PLT_GOT_SUFF
:
4434 /* It has to record symbol. */
4435 if (insn_mask
== 0 || pattern
->insn
== insn_mask
)
4437 exp
.X_add_symbol
= sym
;
4438 fix_new_exp (frag
, out
- frag
->fr_literal
, size
, &exp
, 0, reloc
);
4442 case BFD_RELOC_NDS32_PTR_RESOLVED
:
4444 if (insn_mask
== 0 || pattern
->insn
== insn_mask
)
4446 fix_new_exp (frag
, out
- frag
->fr_literal
, size
, &exp
, 0, reloc
);
4452 nds32_set_elf_flags_by_insn (struct nds32_asm_insn
* insn
)
4454 /* Set E_NDS32_HAS_EXT_INST. */
4455 if (insn
->opcode
->attr
& NASM_ATTR_PERF_EXT
)
4458 nds32_elf_flags
|= E_NDS32_HAS_EXT_INST
;
4460 as_bad (_("instruction %s requires enabling performance extension"),
4461 insn
->opcode
->opcode
);
4463 else if (insn
->opcode
->attr
& NASM_ATTR_PERF2_EXT
)
4465 if (nds32_perf_ext2
)
4466 nds32_elf_flags
|= E_NDS32_HAS_EXT2_INST
;
4468 as_bad (_("instruction %s requires enabling performance extension II"),
4469 insn
->opcode
->opcode
);
4471 else if (insn
->opcode
->attr
& NASM_ATTR_AUDIO_ISAEXT
)
4473 if (nds32_audio_ext
)
4474 nds32_elf_flags
|= E_NDS32_HAS_AUDIO_INST
;
4476 as_bad (_("instruction %s requires enabling AUDIO extension"),
4477 insn
->opcode
->opcode
);
4479 else if (insn
->opcode
->attr
& NASM_ATTR_STR_EXT
)
4481 if (nds32_string_ext
)
4482 nds32_elf_flags
|= E_NDS32_HAS_STRING_INST
;
4484 as_bad (_("instruction %s requires enabling STRING extension"),
4485 insn
->opcode
->opcode
);
4487 else if ((insn
->opcode
->attr
& NASM_ATTR_DIV
)
4488 && (insn
->opcode
->attr
& NASM_ATTR_DXREG
))
4490 if (nds32_div
&& nds32_dx_regs
)
4491 nds32_elf_flags
|= E_NDS32_HAS_DIV_DX_INST
;
4493 as_bad (_("instruction %s requires enabling DIV & DX_REGS extension"),
4494 insn
->opcode
->opcode
);
4496 else if (insn
->opcode
->attr
& NASM_ATTR_FPU
)
4498 if (nds32_fpu_sp_ext
|| nds32_fpu_dp_ext
)
4500 if (!(nds32_elf_flags
& (E_NDS32_HAS_FPU_INST
| E_NDS32_HAS_FPU_DP_INST
)))
4504 as_bad (_("instruction %s requires enabling FPU extension"),
4505 insn
->opcode
->opcode
);
4507 else if (insn
->opcode
->attr
& NASM_ATTR_FPU_SP_EXT
)
4509 if (nds32_fpu_sp_ext
)
4510 nds32_elf_flags
|= E_NDS32_HAS_FPU_INST
;
4512 as_bad (_("instruction %s requires enabling FPU_SP extension"),
4513 insn
->opcode
->opcode
);
4515 else if ((insn
->opcode
->attr
& NASM_ATTR_FPU_SP_EXT
)
4516 && (insn
->opcode
->attr
& NASM_ATTR_MAC
))
4518 if (nds32_fpu_sp_ext
&& nds32_mac
)
4520 nds32_elf_flags
|= E_NDS32_HAS_FPU_MAC_INST
;
4521 nds32_elf_flags
|= E_NDS32_HAS_FPU_INST
;
4524 as_bad (_("instruction %s requires enabling FPU_MAC extension"),
4525 insn
->opcode
->opcode
);
4527 else if (insn
->opcode
->attr
& NASM_ATTR_FPU_DP_EXT
)
4529 if (nds32_fpu_dp_ext
)
4530 nds32_elf_flags
|= E_NDS32_HAS_FPU_DP_INST
;
4532 as_bad (_("instruction %s requires enabling FPU_DP extension"),
4533 insn
->opcode
->opcode
);
4535 else if ((insn
->opcode
->attr
& NASM_ATTR_FPU_DP_EXT
)
4536 && (insn
->opcode
->attr
& NASM_ATTR_MAC
))
4538 if (nds32_fpu_dp_ext
&& nds32_mac
)
4540 nds32_elf_flags
|= E_NDS32_HAS_FPU_MAC_INST
;
4541 nds32_elf_flags
|= E_NDS32_HAS_FPU_DP_INST
;
4544 as_bad (_("instruction %s requires enabling FPU_MAC extension"),
4545 insn
->opcode
->opcode
);
4547 /* TODO: FPU_BOTH */
4548 else if ((insn
->opcode
->attr
& NASM_ATTR_MAC
)
4549 && (insn
->opcode
->attr
& NASM_ATTR_DXREG
))
4551 if (nds32_mac
&& nds32_dx_regs
)
4552 nds32_elf_flags
|= E_NDS32_HAS_MAC_DX_INST
;
4554 as_bad (_("instruction %s requires enabling DX_REGS extension"),
4555 insn
->opcode
->opcode
);
4557 /* TODO: for DX_REG set but not for MAC, DIV, AUDIO */
4558 else if (insn
->opcode
->attr
& NASM_ATTR_IFC_EXT
)
4560 nds32_elf_flags
|= E_NDS32_HAS_IFC_INST
;
4562 /* TODO: E_NDS32_HAS_SATURATION_INST */
4565 /* Append relax relocation for link time relaxing. */
4568 nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED
, void *value
)
4570 struct nds32_relocs_pattern
*relocs_temp
=
4571 (struct nds32_relocs_pattern
*) value
;
4572 unsigned int reloc
, group_type
, insn
;
4574 unsigned int i
= 0, x
= 0, y
;
4575 segT seg_bak
= now_seg
;
4576 frchainS
*frchain_bak
= frchain_now
;
4581 group_type
= relocs_temp
->reloc
;
4582 sym
= relocs_temp
->sym
;
4583 /* Inserting fix up must specify now_seg or frchain_now. */
4584 now_seg
= relocs_temp
->seg
;
4585 frchain_now
= relocs_temp
->frchain
;
4587 /* Find pattern in relocation table. */
4588 while (i
< (sizeof (relocation_table
)/sizeof (relocation_table
[0]))
4589 &&relocation_table
[i
].main_type
!= group_type
)
4592 /* Can not find relocation pattern. */
4593 if (relocation_table
[i
].main_type
== 0)
4600 while (relocation_table
[i
].reloc_insn
[x
][y
][0] != 0)
4602 reloc
= relocation_table
[i
].reloc_insn
[x
][y
][0];
4603 insn
= relocation_table
[i
].reloc_insn
[x
][y
][1];
4604 nds32_elf_insert_relocation (relocs_temp
, reloc
, insn
, sym
);
4608 /* Next instruction. */
4609 relocs_temp
= relocs_temp
->next
;
4611 /* There are load store instruction shared setting symbol part, so
4612 re-using the final relocation. */
4613 if (relocation_table
[i
].reloc_insn
[x
+1][0][0] != 0)
4618 frchain_now
= frchain_bak
;
4621 /* Check instruction if it can be used for the baseline. */
4624 nds32_check_insn_available (struct nds32_asm_insn insn
, char *str
)
4626 int attr
= insn
.attr
& ATTR_ALL
;
4627 static int baseline_isa
= 0;
4628 /* No isa setting or all isa can use. */
4629 if (attr
== 0 || attr
== ATTR_ALL
)
4632 if (baseline_isa
== 0)
4634 /* Map option baseline and instruction attribute. */
4635 switch (nds32_baseline
)
4638 baseline_isa
= ATTR (ISA_V2
);
4641 baseline_isa
= ATTR (ISA_V3
);
4644 baseline_isa
= ATTR (ISA_V3M
);
4649 if ((baseline_isa
& attr
) == 0)
4651 as_bad (_("Not support instrcution %s in the baseline."), str
);
4657 /* Stub of machine dependent. */
4660 md_assemble (char *str
)
4662 struct nds32_asm_insn insn
;
4664 struct nds32_pseudo_opcode
*popcode
;
4665 const struct nds32_field
*fld
= NULL
;
4666 fixS
*fixP ATTRIBUTE_UNUSED
;
4670 struct nds32_relocs_pattern
*relocs_temp
;
4673 popcode
= nds32_lookup_pseudo_opcode (str
);
4674 /* Note that we need to check 'verbatim' and
4675 'opcode->physical_op'. If the assembly content is generated by
4676 compiler and this opcode is a physical instruction, there is no
4677 need to perform pseudo instruction expansion/transformation. */
4678 if (popcode
&& !(verbatim
&& popcode
->physical_op
))
4680 pseudo_opcode
= TRUE
;
4681 nds32_pseudo_opcode_wrapper (str
, popcode
);
4682 pseudo_opcode
= FALSE
;
4683 nds32_elf_append_relax_relocs (NULL
, relocs_list
);
4685 /* Free pseudo list. */
4686 relocs_temp
= relocs_list
;
4689 relocs_list
= relocs_list
->next
;
4691 relocs_temp
= relocs_list
;
4697 insn
.info
= (expressionS
*) alloca (sizeof (expressionS
));
4698 nds32_assemble (&asm_desc
, &insn
, str
);
4700 switch (asm_desc
.result
)
4702 case NASM_ERR_UNKNOWN_OP
:
4703 as_bad (_("Unrecognized opcode, %s."), str
);
4705 case NASM_ERR_SYNTAX
:
4706 as_bad (_("Incorrect syntax, %s."), str
);
4708 case NASM_ERR_OPERAND
:
4709 as_bad (_("Unrecognized operand, %s."), str
);
4711 case NASM_ERR_OUT_OF_RANGE
:
4712 as_bad (_("Operand out of range, %s."), str
);
4714 case NASM_ERR_REG_REDUCED
:
4715 as_bad (_("Prohibited register used for reduced-register, %s."), str
);
4717 case NASM_ERR_JUNK_EOL
:
4718 as_bad (_("Junk at end of line, %s."), str
);
4722 gas_assert (insn
.opcode
);
4724 nds32_set_elf_flags_by_insn (&insn
);
4726 gas_assert (insn
.opcode
->isize
== 4 || insn
.opcode
->isize
== 2);
4728 if (!nds32_check_insn_available (insn
, str
))
4731 /* Create new frag if the instruction can be relaxed. */
4733 if (!verbatim
&& fld
&& (insn
.attr
& NASM_ATTR_BRANCH
))
4735 /* User assembly code branch relax for it. */
4736 fragS
*fragp
= frag_now
;
4738 /* If fld is not NULL, it is a symbol. */
4739 /* Get branch range type. */
4740 enum nds32_br_range range_type
;
4741 range_type
= get_range_type (fld
);
4745 out
= frag_var (rs_machine_dependent
,
4747 0, /* VAR is un-used. */
4748 range_type
, /* SUBTYPE is used as range type. */
4752 /* If the original frag is full, the instruction must save in next
4754 while (fragp
->fr_next
!= frag_now
)
4755 fragp
= fragp
->fr_next
;
4756 fragp
->fr_fix
+= insn
.opcode
->isize
;
4757 fragp
->tc_frag_data
.opcode
= insn
.opcode
;
4758 fragp
->tc_frag_data
.insn
= insn
.insn
;
4759 dwarf2_emit_insn (insn
.opcode
->isize
);
4760 if (insn
.opcode
->isize
== 4)
4761 bfd_putb32 (insn
.insn
, out
);
4762 else if (insn
.opcode
->isize
== 2)
4763 bfd_putb16 (insn
.insn
, out
);
4765 /* md_convert_frag will insert relocations. */
4767 else if (!verbatim
&& !fld
&& (optimize
|| optimize_for_space
))
4769 /* User assembly code without relocating convert it to 16bits if needed. */
4770 insn_32
= insn
.insn
;
4772 /* Convert instruction to 16-bits. */
4773 if (insn
.opcode
->isize
== 4
4774 && nds32_convert_32_to_16 (stdoutput
, insn_32
,
4775 &insn_16
, &insn_type
))
4777 out
= frag_more (2);
4778 frag_var (rs_fill
, 0, 0, 0, NULL
, 0, NULL
);
4779 bfd_putb16 (insn_16
, out
);
4780 dwarf2_emit_insn (2);
4785 out
= frag_more (insn
.opcode
->isize
);
4787 if (insn
.opcode
->isize
== 4)
4788 bfd_putb32 (insn
.insn
, out
);
4789 else if (insn
.opcode
->isize
== 2)
4790 bfd_putb16 (insn
.insn
, out
);
4792 dwarf2_emit_insn (insn
.opcode
->isize
);
4796 /* Compiler generating code and user assembly pseudo load-store, insert
4799 nds32_elf_record_fixup_exp (str
, fld
, pexp
, out
, &insn
);
4803 /* md_macro_start */
4806 nds32_macro_start (void)
4813 nds32_macro_info (void *info ATTRIBUTE_UNUSED
)
4820 nds32_macro_end (void)
4824 /* GAS will call this function with one argument, an expressionS pointer, for
4825 any expression that can not be recognized. When the function is called,
4826 input_line_pointer will point to the start of the expression. */
4829 md_operand (expressionS
*expressionP
)
4831 if (*input_line_pointer
== '#')
4833 input_line_pointer
++;
4834 expression (expressionP
);
4838 /* GAS will call this function for each section at the end of the assembly, to
4839 permit the CPU back end to adjust the alignment of a section. The function
4840 must take two arguments, a segT for the section and a valueT for the size of
4841 the section, and return a valueT for the rounded size. */
4844 md_section_align (segT segment
, valueT size
)
4846 int align
= bfd_get_section_alignment (stdoutput
, segment
);
4848 return ((size
+ (1 << align
) - 1) & (-1 << align
));
4851 /* GAS will call this function when a symbol table lookup fails, before it
4852 creates a new symbol. Typically this would be used to supply symbols whose
4853 name or value changes dynamically, possibly in a context sensitive way.
4854 Predefined symbols with fixed values, such as register names or condition
4855 codes, are typically entered directly into the symbol table when md_begin
4856 is called. One argument is passed, a char * for the symbol. */
4859 md_undefined_symbol (char *name ATTRIBUTE_UNUSED
)
4865 nds32_calc_branch_offset (segT segment
, fragS
*fragP
,
4866 long stretch ATTRIBUTE_UNUSED
,
4867 relax_info_t
*relax_info
,
4868 enum nds32_br_range branch_range_type
)
4870 struct nds32_opcode
*opcode
= fragP
->tc_frag_data
.opcode
;
4871 symbolS
*branch_symbol
= fragP
->fr_symbol
;
4872 offsetT branch_offset
= fragP
->fr_offset
;
4873 offsetT branch_target_address
;
4874 offsetT branch_insn_address
;
4877 if ((S_GET_SEGMENT (branch_symbol
) != segment
)
4878 || S_IS_WEAK (branch_symbol
))
4880 /* The symbol is not in the SEGMENT. It could be far far away. */
4881 offset
= 0x80000000;
4885 /* Calculate symbol-to-instruction offset. */
4886 branch_target_address
= S_GET_VALUE (branch_symbol
) + branch_offset
;
4887 /* If the destination symbol is beyond current frag address,
4888 STRETCH will take effect to symbol's position. */
4889 if (S_GET_VALUE (branch_symbol
) > fragP
->fr_address
)
4890 branch_target_address
+= stretch
;
4892 branch_insn_address
= fragP
->fr_address
+ fragP
->fr_fix
;
4893 branch_insn_address
-= opcode
->isize
;
4895 /* Update BRANCH_INSN_ADDRESS to relaxed position. */
4896 branch_insn_address
+= (relax_info
->relax_code_size
[branch_range_type
]
4897 - relax_info
->relax_branch_isize
[branch_range_type
]);
4899 offset
= branch_target_address
- branch_insn_address
;
4905 static enum nds32_br_range
4906 nds32_convert_to_range_type (long offset
)
4908 enum nds32_br_range range_type
;
4910 if (-(0x100) <= offset
&& offset
< 0x100) /* 256 bytes */
4911 range_type
= BR_RANGE_S256
;
4912 else if (-(0x4000) <= offset
&& offset
< 0x4000) /* 16K bytes */
4913 range_type
= BR_RANGE_S16K
;
4914 else if (-(0x10000) <= offset
&& offset
< 0x10000) /* 64K bytes */
4915 range_type
= BR_RANGE_S64K
;
4916 else if (-(0x1000000) <= offset
&& offset
< 0x1000000) /* 16M bytes */
4917 range_type
= BR_RANGE_S16M
;
4919 range_type
= BR_RANGE_U4G
;
4924 /* Set insntruction register mask. */
4927 nds32_elf_get_set_cond (relax_info_t
*relax_info
, int offset
, uint32_t *insn
,
4928 uint32_t ori_insn
, int range
)
4930 nds32_cond_field_t
*cond_fields
= relax_info
->cond_field
;
4931 nds32_cond_field_t
*code_seq_cond
= relax_info
->relax_code_condition
[range
];
4935 /* The instruction has conditions. Collect condition values. */
4936 while (offset
== code_seq_cond
[i
].offset
)
4938 mask
= (ori_insn
>> cond_fields
[i
].bitpos
) & cond_fields
[i
].bitmask
;
4939 *insn
|= (mask
& code_seq_cond
[i
].bitmask
) << code_seq_cond
[i
].bitpos
;
4946 nds32_relax_branch_instructions (segT segment
, fragS
*fragP
,
4947 long stretch ATTRIBUTE_UNUSED
,
4950 enum nds32_br_range branch_range_type
;
4951 struct nds32_opcode
*opcode
= fragP
->tc_frag_data
.opcode
;
4953 enum nds32_br_range real_range_type
;
4955 relax_info_t
*relax_info
;
4964 int code_seq_offset
;
4966 /* Replace with gas_assert (fragP->fr_symbol != NULL); */
4967 if (fragP
->fr_symbol
== NULL
)
4970 /* If frag_var is not enough room, the previos frag is fr_full and with
4971 opcode. The new one is rs_dependent but without opcode. */
4975 relax_info
= hash_find (nds32_relax_info_hash
, opcode
->opcode
);
4977 if (relax_info
== NULL
)
4981 branch_range_type
= relax_info
->br_range
;
4983 branch_range_type
= fragP
->fr_subtype
;
4985 offset
= nds32_calc_branch_offset (segment
, fragP
, stretch
,
4986 relax_info
, branch_range_type
);
4988 real_range_type
= nds32_convert_to_range_type (offset
);
4990 /* If actual range is equal to instruction jump range, do nothing. */
4991 if (real_range_type
== branch_range_type
)
4994 /* Find out proper relaxation code sequence. */
4995 for (i
= BR_RANGE_S256
; i
< BR_RANGE_NUM
; i
++)
4997 if (real_range_type
<= (unsigned int) i
)
5000 diff
= relax_info
->relax_code_size
[i
] - opcode
->isize
;
5002 diff
= relax_info
->relax_code_size
[i
]
5003 - relax_info
->relax_code_size
[branch_range_type
];
5005 /* If the instruction could be converted to 16-bits,
5006 minus the difference. */
5007 code_seq_offset
= 0;
5010 code_seq_size
= relax_info
->relax_code_size
[i
];
5011 code_seq
= relax_info
->relax_code_seq
[i
];
5012 while (code_seq_offset
< code_seq_size
)
5015 if (insn
& 0x80000000) /* 16-bits instruction. */
5019 else /* 32-bits instruction. */
5023 while (relax_info
->relax_fixup
[i
][k
].size
!=0
5024 && relax_info
->relax_fixup
[i
][k
].offset
< code_seq_offset
)
5026 if (relax_info
->relax_fixup
[i
][k
].size
!=0
5027 && relax_info
->relax_fixup
[i
][k
].ramp
& NDS32_ORIGIN
)
5029 /* Set register num to insntruction. */
5030 nds32_elf_get_set_cond (relax_info
, code_seq_offset
, &insn
,
5031 fragP
->tc_frag_data
.insn
, i
);
5033 /* Try to convert to 16-bits instruction. */
5034 if (nds32_convert_32_to_16 (stdoutput
,
5035 insn
, &insn_16
, &insn_type
))
5040 code_seq_offset
+= insn_size
;
5044 /* Update fr_subtype to new NDS32_BR_RANGE. */
5045 fragP
->fr_subtype
= i
;
5050 return diff
+ adjust
;
5056 nds32_relax_frag (segT segment
, fragS
*fragP
, long stretch ATTRIBUTE_UNUSED
)
5058 /* Currently, there are two kinds of relaxation in nds32 assembler.
5060 2. relax for 32-bits to 16-bits */
5064 adjust
= nds32_relax_branch_instructions (segment
, fragP
, stretch
, 0);
5069 /* This function returns an initial guess of the length by which a fragment
5070 must grow to hold a branch to reach its destination. Also updates
5071 fr_type/fr_subtype as necessary.
5073 It is called just before doing relaxation. Any symbol that is now undefined
5074 will not become defined. The guess for fr_var is ACTUALLY the growth beyond
5075 fr_fix. Whatever we do to grow fr_fix or fr_var contributes to our returned
5076 value. Although it may not be explicit in the frag, pretend fr_var starts
5080 md_estimate_size_before_relax (fragS
*fragP
, segT segment
)
5082 /* Currently, there are two kinds of relaxation in nds32 assembler.
5084 2. relax for 32-bits to 16-bits */
5088 adjust
= nds32_relax_branch_instructions (segment
, fragP
, 0, 1);
5093 /* GAS will call this for each rs_machine_dependent fragment. The instruction
5094 is completed using the data from the relaxation pass. It may also create any
5095 necessary relocations.
5097 *FRAGP has been relaxed to its final size, and now needs to have the bytes
5098 inside it modified to conform to the new size. It is called after relaxation
5101 fragP->fr_type == rs_machine_dependent.
5102 fragP->fr_subtype is the subtype of what the address relaxed to. */
5105 md_convert_frag (bfd
*abfd ATTRIBUTE_UNUSED
, segT sec
, fragS
*fragP
)
5107 /* Convert branch relaxation instructions. */
5108 symbolS
*branch_symbol
= fragP
->fr_symbol
;
5109 offsetT branch_offset
= fragP
->fr_offset
;
5110 enum nds32_br_range branch_range_type
= fragP
->fr_subtype
;
5111 struct nds32_opcode
*opcode
= fragP
->tc_frag_data
.opcode
;
5112 uint32_t origin_insn
= fragP
->tc_frag_data
.insn
;
5114 relax_info_t
*relax_info
;
5117 int addend ATTRIBUTE_UNUSED
;
5118 offsetT branch_target_address
;
5119 offsetT branch_insn_address
;
5131 nds32_relax_fixup_info_t fixup_info
[MAX_RELAX_NUM
];
5132 /* Save the 1st instruction is converted to 16 bit or not. */
5133 bfd_boolean insn_convert
= FALSE
;
5136 /* Replace with gas_assert (branch_symbol != NULL); */
5137 if (branch_symbol
== NULL
)
5140 /* If frag_var is not enough room, the previos frag is fr_full and with
5141 opcode. The new one is rs_dependent but without opcode. */
5145 relax_info
= hash_find (nds32_relax_info_hash
, opcode
->opcode
);
5147 if (relax_info
== NULL
)
5150 backup_endian
= target_big_endian
;
5151 target_big_endian
= 1;
5153 fr_where
= fragP
->fr_fix
- opcode
->isize
;
5154 fr_buffer
= fragP
->fr_literal
+ fr_where
;
5156 if ((S_GET_SEGMENT (branch_symbol
) != sec
)
5157 || S_IS_WEAK (branch_symbol
))
5159 if (fragP
->fr_offset
& 3)
5160 as_warn (_("Addend to unresolved symbol is not on word boundary."));
5165 /* Calculate symbol-to-instruction offset. */
5166 branch_target_address
= S_GET_VALUE (branch_symbol
) + branch_offset
;
5167 branch_insn_address
= fragP
->fr_address
+ fr_where
;
5168 addend
= (branch_target_address
- branch_insn_address
) >> 1;
5171 code_size
= relax_info
->relax_code_size
[branch_range_type
];
5172 code_seq
= relax_info
->relax_code_seq
[branch_range_type
];
5175 relax_info
->relax_fixup
[branch_range_type
],
5176 sizeof (fixup_info
));
5181 offset
= 0; /* code_seq offset */
5182 buf_offset
= 0; /* fr_buffer offset */
5183 while (offset
< code_size
)
5186 if (insn
& 0x80000000) /* 16-bits instruction. */
5188 insn
= (insn
>> 16) & 0xFFFF;
5191 else /* 32-bits instruction. */
5196 nds32_elf_get_set_cond (relax_info
, offset
, &insn
,
5197 origin_insn
, branch_range_type
);
5199 /* Try to convert to 16-bits instruction. Currently, only the first
5200 insntruction in pattern can be converted. EX: bnez sethi ori jr,
5201 only bnez can be converted to 16 bit and ori can't. */
5203 while (fixup_info
[k
].size
!= 0
5204 && relax_info
->relax_fixup
[branch_range_type
][k
].offset
< offset
)
5206 if ((fixup_info
[k
].size
!= 0
5207 && fixup_info
[k
].ramp
& NDS32_ORIGIN
)
5208 && nds32_convert_32_to_16 (stdoutput
, insn
, &insn_16
, &insn_type
))
5210 /* Reduce to 16-bits instructions, adjust fixup_info[j]->offset. */
5211 for (j
= 0; fixup_info
[j
].size
!= 0; j
++)
5213 if (fixup_info
[j
].ramp
& NDS32_RELAX
)
5214 fixup_info
[j
].size
-= 2;
5216 if (fixup_info
[j
].offset
> buf_offset
)
5217 fixup_info
[j
].offset
-= 2;
5220 md_number_to_chars (fr_buffer
+ buf_offset
, insn_16
, 2);
5223 insn_convert
= TRUE
;
5227 md_number_to_chars (fr_buffer
+ buf_offset
, insn
, insn_size
);
5228 buf_offset
+= insn_size
;
5231 offset
+= insn_size
;
5236 exp
.X_op
= O_symbol
;
5238 for (i
= 0; fixup_info
[i
].size
!= 0; i
++)
5240 fixup_size
= fixup_info
[i
].size
;
5242 if (((fixup_info
[i
].ramp
& NDS32_ORIGIN
) && insn_convert
== TRUE
)
5243 ||((fixup_info
[i
].ramp
& NDS32_CONVERT
) && insn_convert
== FALSE
))
5246 if ((fixup_info
[i
].ramp
& NDS32_CREATE_LABLE
) != 0)
5248 /* This is a reverse branch. */
5249 exp
.X_add_symbol
= symbol_temp_new (sec
, 0, fragP
->fr_next
);
5250 exp
.X_add_number
= 0;
5252 else if ((fixup_info
[i
].ramp
& NDS32_RELAX
) != 0)
5254 /* This is a relax relocation. */
5255 exp
.X_add_symbol
= abs_section_sym
;
5257 SET_ADDEND (fixup_size
/* size */ ,
5258 insn_convert
, optimize
, enable_16bit
);
5262 exp
.X_add_symbol
= branch_symbol
;
5263 exp
.X_add_number
= branch_offset
;
5266 if (fixup_info
[i
].r_type
!= 0)
5268 fixP
= fix_new_exp (fragP
,
5269 fr_where
+ fixup_info
[i
].offset
,
5273 fixup_info
[i
].r_type
);
5274 fixP
->fx_addnumber
= fixP
->fx_offset
;
5278 fragP
->fr_fix
= fr_where
+ buf_offset
;
5280 target_big_endian
= backup_endian
;
5283 /* tc_frob_file_before_fix */
5286 nds32_frob_file_before_fix (void)
5290 /* TC_FORCE_RELOCATION */
5293 nds32_force_relocation (fixS
*fix ATTRIBUTE_UNUSED
)
5295 /* Always force relocation, because linker may adjust the code. */
5300 /* TC_VALIDATE_FIX_SUB */
5303 nds32_validate_fix_sub (fixS
*fix
, segT add_symbol_segment
)
5305 segT sub_symbol_segment
;
5307 /* This code is referred from Xtensa. Check their implementation for
5310 /* Make sure both symbols are in the same segment, and that segment is
5311 "normal" and relaxable. */
5312 sub_symbol_segment
= S_GET_SEGMENT (fix
->fx_subsy
);
5313 return (sub_symbol_segment
== add_symbol_segment
5314 && add_symbol_segment
!= undefined_section
);
5318 md_number_to_chars (char *buf
, valueT val
, int n
)
5320 if (target_big_endian
)
5321 number_to_chars_bigendian (buf
, val
, n
);
5323 number_to_chars_littleendian (buf
, val
, n
);
5326 /* Equal to MAX_PRECISION in atof-ieee.c. */
5327 #define MAX_LITTLENUMS 6
5329 /* This function is called to convert an ASCII string into a floating point
5330 value in format used by the CPU. */
5333 md_atof (int type
, char *litP
, int *sizeP
)
5337 LITTLENUM_TYPE words
[MAX_LITTLENUMS
];
5356 return _("Bad call to md_atof()");
5359 t
= atof_ieee (input_line_pointer
, type
, words
);
5361 input_line_pointer
= t
;
5362 *sizeP
= prec
* sizeof (LITTLENUM_TYPE
);
5364 if (target_big_endian
)
5366 for (i
= 0; i
< prec
; i
++)
5368 md_number_to_chars (litP
, (valueT
) words
[i
],
5369 sizeof (LITTLENUM_TYPE
));
5370 litP
+= sizeof (LITTLENUM_TYPE
);
5375 for (i
= prec
- 1; i
>= 0; i
--)
5377 md_number_to_chars (litP
, (valueT
) words
[i
],
5378 sizeof (LITTLENUM_TYPE
));
5379 litP
+= sizeof (LITTLENUM_TYPE
);
5386 /* md_elf_section_change_hook */
5389 nds32_elf_section_change_hook (void)
5396 nds32_cleanup (void)
5400 /* This function is used to scan leb128 subtraction expressions,
5401 and insert fixups for them.
5403 e.g., .leb128 .L1 - .L0
5405 These expressions are heavily used in debug information or
5406 exception tables. Because relaxation will change code size,
5407 we must resolve them in link time. */
5410 nds32_insert_leb128_fixes (bfd
*abfd ATTRIBUTE_UNUSED
,
5411 asection
*sec
, void *xxx ATTRIBUTE_UNUSED
)
5413 segment_info_type
*seginfo
= seg_info (sec
);
5416 subseg_set (sec
, 0);
5418 for (fragP
= seginfo
->frchainP
->frch_root
;
5419 fragP
; fragP
= fragP
->fr_next
)
5423 /* Only unsigned leb128 can be handle. */
5424 if (fragP
->fr_type
!= rs_leb128
|| fragP
->fr_subtype
!= 0
5425 || fragP
->fr_symbol
== NULL
)
5428 exp
= symbol_get_value_expression (fragP
->fr_symbol
);
5430 if (exp
->X_op
!= O_subtract
)
5433 fix_new_exp (fragP
, fragP
->fr_fix
, 0,
5434 exp
, 0, BFD_RELOC_NDS32_DIFF_ULEB128
);
5439 nds32_insert_relax_entry (bfd
*abfd ATTRIBUTE_UNUSED
, asection
*sec
,
5440 void *xxx ATTRIBUTE_UNUSED
)
5442 segment_info_type
*seginfo
;
5448 seginfo
= seg_info (sec
);
5449 if (!seginfo
|| !symbol_rootP
|| !subseg_text_p (sec
))
5451 /* If there is no relocation and relax is disabled, it is not necessary to
5452 insert R_NDS32_RELAX_ENTRY for linker do EX9 or IFC optimization. */
5453 for (fixp
= seginfo
->fix_root
; fixp
; fixp
= fixp
->fx_next
)
5456 if (!fixp
&& !enable_relax_ex9
&& !verbatim
)
5459 subseg_change (sec
, 0);
5461 /* Set RELAX_ENTRY flags for linker. */
5462 fragP
= seginfo
->frchainP
->frch_root
;
5463 exp
.X_op
= O_symbol
;
5464 exp
.X_add_symbol
= section_symbol (sec
);
5465 exp
.X_add_number
= 0;
5466 if (!enable_relax_relocs
)
5467 exp
.X_add_number
|= R_NDS32_RELAX_ENTRY_DISABLE_RELAX_FLAG
;
5470 /* These flags are only enabled when global relax is enabled.
5471 Maybe we can check DISABLE_RELAX_FLAG at linke-time,
5472 so we set them anyway. */
5473 if (enable_relax_ex9
)
5474 exp
.X_add_number
|= R_NDS32_RELAX_ENTRY_EX9_FLAG
;
5475 if (enable_relax_ifc
)
5476 exp
.X_add_number
|= R_NDS32_RELAX_ENTRY_IFC_FLAG
;
5478 exp
.X_add_number
|= R_NDS32_RELAX_ENTRY_VERBATIM_FLAG
;
5481 exp
.X_add_number
|= R_NDS32_RELAX_ENTRY_OPTIMIZE_FLAG
;
5482 if (optimize_for_space
)
5483 exp
.X_add_number
|= R_NDS32_RELAX_ENTRY_OPTIMIZE_FOR_SPACE_FLAG
;
5485 fixP
= fix_new_exp (fragP
, 0, 0, &exp
, 0, BFD_RELOC_NDS32_RELAX_ENTRY
);
5486 fixP
->fx_no_overflow
= 1;
5489 /* Analysis relax hint and insert suitable relocation pattern. */
5492 nds32_elf_analysis_relax_hint (void)
5494 hash_traverse (nds32_hint_hash
, nds32_elf_append_relax_relocs
);
5500 nds32_elf_analysis_relax_hint ();
5501 bfd_map_over_sections (stdoutput
, nds32_insert_leb128_fixes
, NULL
);
5504 /* Implement md_allow_local_subtract. */
5507 nds32_allow_local_subtract (expressionS
*expr_l ATTRIBUTE_UNUSED
,
5508 expressionS
*expr_r ATTRIBUTE_UNUSED
,
5509 segT sec ATTRIBUTE_UNUSED
)
5511 /* Don't allow any subtraction, because relax may change the code. */
5515 /* Sort relocation by address.
5517 We didn't use qsort () in stdlib, because quick-sort is not a stable
5518 sorting algorithm. Relocations at the same address (r_offset) must keep
5519 their relative order. For example, RELAX_ENTRY must be the very first
5522 Currently, this function implements insertion-sort. */
5525 compar_relent (const void *lhs
, const void *rhs
)
5527 const arelent
**l
= (const arelent
**) lhs
;
5528 const arelent
**r
= (const arelent
**) rhs
;
5530 if ((*l
)->address
> (*r
)->address
)
5532 else if ((*l
)->address
== (*r
)->address
)
5538 /* SET_SECTION_RELOCS ()
5540 Although this macro is originally used to set a relocation for each section,
5541 we use it to sort relocations in the same section by the address of the
5545 nds32_set_section_relocs (asection
*sec
, arelent
** relocs ATTRIBUTE_UNUSED
,
5546 unsigned int n ATTRIBUTE_UNUSED
)
5548 bfd
*abfd ATTRIBUTE_UNUSED
= sec
->owner
;
5549 if (bfd_get_section_flags (abfd
, sec
) & (flagword
) SEC_RELOC
)
5550 nds32_insertion_sort (sec
->orelocation
, sec
->reloc_count
, sizeof (arelent
**),
5555 nds32_pcrel_from_section (fixS
*fixP
, segT sec ATTRIBUTE_UNUSED
)
5557 if (fixP
->fx_addsy
== NULL
|| !S_IS_DEFINED (fixP
->fx_addsy
)
5558 || S_IS_EXTERNAL (fixP
->fx_addsy
) || S_IS_WEAK (fixP
->fx_addsy
))
5560 /* Let linker resolve undefined symbols. */
5564 return fixP
->fx_frag
->fr_address
+ fixP
->fx_where
;
5567 /* md_post_relax_hook ()
5568 Insert relax entry relocation into sections. */
5571 nds32_post_relax_hook (void)
5573 bfd_map_over_sections (stdoutput
, nds32_insert_relax_entry
, NULL
);
5578 /* tc_fix_adjustable ()
5580 Return whether this symbol (fixup) can be replaced with
5584 nds32_fix_adjustable (fixS
*fixP
)
5586 switch (fixP
->fx_r_type
)
5588 case BFD_RELOC_NDS32_WORD_9_PCREL
:
5589 case BFD_RELOC_NDS32_9_PCREL
:
5590 case BFD_RELOC_NDS32_15_PCREL
:
5591 case BFD_RELOC_NDS32_17_PCREL
:
5592 case BFD_RELOC_NDS32_25_PCREL
:
5593 case BFD_RELOC_NDS32_HI20
:
5594 case BFD_RELOC_NDS32_LO12S0
:
5598 case BFD_RELOC_NDS32_PTR
:
5605 /* elf_tc_final_processing */
5608 elf_nds32_final_processing (void)
5610 /* An FPU_COM instruction is found without previous non-FPU_COM instruction. */
5612 && !(nds32_elf_flags
& (E_NDS32_HAS_FPU_INST
| E_NDS32_HAS_FPU_DP_INST
)))
5614 /* Since only FPU_COM instructions are used and no other FPU instructions
5615 are used. The nds32_elf_flags will be decided by the enabled options by
5616 command line or default configuration. */
5617 if (nds32_fpu_dp_ext
|| nds32_fpu_sp_ext
)
5619 nds32_elf_flags
|= nds32_fpu_dp_ext
? E_NDS32_HAS_FPU_DP_INST
: 0;
5620 nds32_elf_flags
|= nds32_fpu_sp_ext
? E_NDS32_HAS_FPU_INST
: 0;
5624 /* Should never here. */
5625 as_bad (_("Used FPU instructions requires enabling FPU extension"));
5629 if (nds32_elf_flags
& (E_NDS32_HAS_FPU_INST
| E_NDS32_HAS_FPU_DP_INST
))
5631 /* Single/double FPU has been used, set FPU register config. */
5632 /* We did not check the actual number of register used. We may
5633 want to do it while assemble. */
5634 nds32_elf_flags
&= ~E_NDS32_FPU_REG_CONF
;
5635 nds32_elf_flags
|= (nds32_freg
<< E_NDS32_FPU_REG_CONF_SHIFT
);
5639 nds32_elf_flags
|= E_NDS32_HAS_PIC
;
5642 nds32_elf_flags
|= E_NDS32_HAS_REDUCED_REGS
;
5644 nds32_elf_flags
|= (E_NDS32_ELF_VER_1_4
| nds32_abi
);
5645 elf_elfheader (stdoutput
)->e_flags
|= nds32_elf_flags
;
5648 /* Implement md_apply_fix. Apply the fix-up or tranform the fix-up for
5649 later relocation generation. */
5652 nds32_apply_fix (fixS
*fixP
, valueT
*valP
, segT seg ATTRIBUTE_UNUSED
)
5654 char *where
= fixP
->fx_frag
->fr_literal
+ fixP
->fx_where
;
5655 bfd_vma value
= *valP
;
5657 if (fixP
->fx_r_type
< BFD_RELOC_UNUSED
5658 && fixP
->fx_r_type
> BFD_RELOC_NONE
5659 && fixP
->fx_r_type
!= BFD_RELOC_NDS32_DIFF_ULEB128
)
5661 /* FIXME: This implementation is partially borrowed from our old
5662 nds32 binutils. Its purpose is to leave original bfd
5663 relocation untouched, while other relocation created by CGEN
5664 will be converted into general bfd relocations.
5665 However, since we no longer use CGEN, we can simply use
5666 a little piece of code to deal with general bfd relocation,
5667 especially for the BFD_RELOC_NDS32_DATA, which is just used
5668 as a marker for different purpose.
5669 It is believed that we can construct a better mechanism to
5670 deal with the whole relocation issue in nds32 target
5671 without using CGEN. */
5672 fixP
->fx_addnumber
= value
;
5673 fixP
->tc_fix_data
= NULL
;
5674 if (fixP
->fx_r_type
== BFD_RELOC_NDS32_DATA
)
5679 if (fixP
->fx_addsy
== (symbolS
*) NULL
)
5682 if (fixP
->fx_subsy
!= (symbolS
*) NULL
)
5684 /* HOW DIFF RELOCATION WORKS.
5686 First of all, this relocation is used to calculate the distance
5687 between two symbols in the SAME section. It is used for jump-
5688 table, debug information, exception table, et al. Therefore,
5689 it is a unsigned positive value. It is NOT used for general-
5692 Consider this example, the distance between .LEND and .LBEGIN
5693 is stored at the address of foo.
5695 ---- >8 ---- >8 ---- >8 ---- >8 ----
5698 .word .LBEGIN - .LEND
5708 ---- 8< ---- 8< ---- 8< ---- 8< ----
5710 We use a single relocation entry for this expression.
5711 * The initial distance value is stored direcly in that location
5712 specified by r_offset (i.e., foo in this example.)
5713 * The begin of the region, i.e., .LBEGIN, is specified by
5714 r_info/R_SYM and r_addend, e.g., .text + 0x32.
5715 * The end of region, i.e., .LEND, is represented by
5716 .LBEGIN + distance instead of .LEND, so we only need
5717 a single relocation entry instead of two.
5719 When an instruction is relaxed, we adjust the relocation entry
5720 depending on where the instruction locates. There are three
5721 cases, before, after and between the region.
5722 * between: Distance value is read from r_offset, adjusted and
5723 written back into r_offset.
5724 * before: Only r_addend is adjust.
5725 * after: We don't care about it.
5727 Hereby, there are some limitation.
5729 `(.LEND - 1) - .LBEGIN' and `(.LEND - .LBEGIN) - 1'
5730 are semantically different, and we cannot handle latter case
5733 The latter expression means subtracting 1 from the distance
5734 between .LEND and .LBEGIN. And the former expression means
5735 the distance between (.LEND - 1) and .LBEGIN.
5737 The nuance affects whether to adjust distance value when relax
5738 an instruction. In another words, whether the instruction
5739 locates in the region. Because we use a single relocation entry,
5740 there is no field left for .LEND and the subtrahend.
5742 Since GCC-4.5, GCC may produce debug information in such expression
5744 in order to describe register clobbering during an function-call.
5749 Check http://gcc.gnu.org/ml/gcc-patches/2009-06/msg01317.html
5752 value
-= S_GET_VALUE (fixP
->fx_subsy
);
5754 fixP
->fx_subsy
= NULL
;
5755 fixP
->fx_offset
-= value
;
5757 switch (fixP
->fx_r_type
)
5760 fixP
->fx_r_type
= BFD_RELOC_NDS32_DIFF8
;
5761 md_number_to_chars (where
, value
, 1);
5764 fixP
->fx_r_type
= BFD_RELOC_NDS32_DIFF16
;
5765 md_number_to_chars (where
, value
, 2);
5768 fixP
->fx_r_type
= BFD_RELOC_NDS32_DIFF32
;
5769 md_number_to_chars (where
, value
, 4);
5771 case BFD_RELOC_NDS32_DIFF_ULEB128
:
5772 /* cvt_frag_to_fill () has called output_leb128 () for us. */
5775 as_bad_where (fixP
->fx_file
, fixP
->fx_line
, _("expression too complex"));
5779 else if (fixP
->fx_done
)
5781 /* We're finished with this fixup. Install it because
5782 bfd_install_relocation won't be called to do it. */
5783 switch (fixP
->fx_r_type
)
5786 md_number_to_chars (where
, value
, 1);
5789 md_number_to_chars (where
, value
, 2);
5792 md_number_to_chars (where
, value
, 4);
5795 md_number_to_chars (where
, value
, 8);
5797 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5798 _("Internal error: Unknown fixup type %d (`%s')"),
5799 fixP
->fx_r_type
, bfd_get_reloc_code_name (fixP
->fx_r_type
));
5805 /* Implement tc_gen_reloc. Generate ELF relocation for a fix-up. */
5808 tc_gen_reloc (asection
*section ATTRIBUTE_UNUSED
, fixS
*fixP
)
5811 bfd_reloc_code_real_type code
;
5813 reloc
= (arelent
*) xmalloc (sizeof (arelent
));
5815 reloc
->sym_ptr_ptr
= (asymbol
**) xmalloc (sizeof (asymbol
*));
5816 *reloc
->sym_ptr_ptr
= symbol_get_bfdsym (fixP
->fx_addsy
);
5817 reloc
->address
= fixP
->fx_frag
->fr_address
+ fixP
->fx_where
;
5819 code
= fixP
->fx_r_type
;
5821 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, code
);
5822 if (reloc
->howto
== (reloc_howto_type
*) NULL
)
5824 as_bad_where (fixP
->fx_file
, fixP
->fx_line
,
5825 _("internal error: can't export reloc type %d (`%s')"),
5826 fixP
->fx_r_type
, bfd_get_reloc_code_name (code
));
5830 /* Add relocation handling here. */
5832 switch (fixP
->fx_r_type
)
5835 /* In general, addend of a relocation is the offset to the
5836 associated symbol. */
5837 reloc
->addend
= fixP
->fx_offset
;
5840 case BFD_RELOC_NDS32_DATA
:
5841 /* Prevent linker from optimizing data in text sections.
5842 For example, jump table. */
5843 reloc
->addend
= fixP
->fx_size
;
5850 /* Implement md_parse_name. */
5853 nds32_parse_name (char const *name
, expressionS
*exprP
,
5854 enum expr_mode mode ATTRIBUTE_UNUSED
,
5855 char *nextcharP ATTRIBUTE_UNUSED
)
5857 char *suffix_table
[] = { "GOTOFF", "GOT", "PLT" };
5858 short unsigned int reloc_table
[] =
5860 BFD_RELOC_NDS32_GOTOFF
, BFD_RELOC_NDS32_GOT20
,
5861 BFD_RELOC_NDS32_25_PLTREL
5865 exprP
->X_op_symbol
= NULL
;
5866 exprP
->X_md
= BFD_RELOC_UNUSED
;
5868 exprP
->X_add_symbol
= symbol_find_or_make (name
);
5870 segment
= S_GET_SEGMENT (exprP
->X_add_symbol
);
5871 if (segment
!= undefined_section
)
5874 if (*nextcharP
== '@')
5878 for (i
= 0; i
< ARRAY_SIZE (suffix_table
); i
++)
5880 next
= input_line_pointer
+ 1 + strlen (suffix_table
[i
]);
5881 if (strncasecmp (input_line_pointer
+ 1, suffix_table
[i
],
5882 strlen (suffix_table
[i
])) == 0
5883 && !is_part_of_name (*next
))
5885 exprP
->X_md
= reloc_table
[i
];
5886 *input_line_pointer
= *nextcharP
;
5887 input_line_pointer
= next
;
5888 *nextcharP
= *input_line_pointer
;
5889 *input_line_pointer
= '\0';
5895 exprP
->X_op
= O_symbol
;
5896 exprP
->X_add_number
= 0;
5901 /* Implement tc_regname_to_dw2regnum. */
5904 tc_nds32_regname_to_dw2regnum (char *regname
)
5906 symbolS
*sym
= symbol_find (regname
);
5908 if (S_GET_SEGMENT (sym
) == reg_section
5909 && sym
->sy_value
.X_add_number
< 32)
5910 return sym
->sy_value
.X_add_number
;
5915 tc_nds32_frame_initial_instructions (void)
5918 /* Default cfa is register-28/sp. */
5919 cfi_add_CFA_def_cfa (31, 0);