tc-nds32.c revision 1.1.1.3 1 /* tc-nds32.c -- Assemble for the nds32
2 Copyright (C) 2012-2018 Free Software Foundation, Inc.
3 Contributed by Andes Technology Corporation.
4
5 This file is part of GAS, the GNU Assembler.
6
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
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.
16
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to the Free
19 Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20 02110-1301, USA. */
21
22 #include "as.h"
23 #include "safe-ctype.h"
24 #include "subsegs.h"
25 #include "symcat.h"
26 #include "dwarf2dbg.h"
27 #include "dw2gencfi.h"
28 #include "opcodes/nds32-asm.h"
29 #include "elf/nds32.h"
30 #include "bfd/elf32-nds32.h"
31 #include "hash.h"
32 #include "sb.h"
33 #include "macro.h"
34 #include "struc-symbol.h"
35 #include "opcode/nds32.h"
36
37 #include <stdio.h>
38
39 /* GAS definitions. */
40
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";
52
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 /* Save instruction relation to inserting relaxation relocation. */
59 struct nds32_relocs_pattern
60 {
61 segT seg;
62 fragS *frag;
63 frchainS *frchain;
64 symbolS *sym;
65 fixS* fixP;
66 struct nds32_opcode *opcode;
67 char *where;
68 struct nds32_relocs_pattern *next;
69 };
70
71 /* Suffix name and relocation. */
72 struct suffix_name
73 {
74 const char *suffix;
75 short unsigned int reloc;
76 int pic;
77 };
78 static int vec_size = 0;
79 /* If the assembly code is generated by compiler, it is supposed to have
80 ".flag verbatim" at beginning of the content. We have
81 'nds32_flag' to parse it and set this field to be non-zero. */
82 static int verbatim = 0;
83 static struct hash_control *nds32_gprs_hash;
84 static struct hash_control *nds32_hint_hash;
85 #define TLS_REG "$r27"
86 #define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
87
88 /* Generate relocation for relax or not, and the default is true. */
89 static int enable_relax_relocs = 1;
90 /* The value will be used in RELAX_ENTRY. */
91 static int enable_relax_ex9 = 0;
92 /* The value will be used in RELAX_ENTRY. */
93 static int enable_relax_ifc = 0;
94 /* Save option -O for performance. */
95 static int optimize = 0;
96 /* Save option -Os for code size. */
97 static int optimize_for_space = 0;
98 /* Flag to save label exist. */
99 static int label_exist = 0;
100 /* Flag to save state in omit_fp region. */
101 static int in_omit_fp = 0;
102 extern struct nds32_keyword keyword_gpr[];
103 /* Tag there is relax relocation having to link. */
104 static bfd_boolean relaxing = FALSE;
105
106 static struct hash_control *nds32_relax_info_hash;
108 static relax_info_t relax_table[] =
109 {
110 {
111 "jal", /* opcode */
112 BR_RANGE_S16M, /* br_range */
113 {{0, 0, 0, FALSE}}, /* cond_field */
114 {
115 {
116 INSN_JAL /* jal label */
117 }, /* BR_RANGE_S256 */
118 {
119 INSN_JAL /* jal label */
120 }, /* BR_RANGE_S16K */
121 {
122 INSN_JAL /* jal label */
123 }, /* BR_RANGE_S64K */
124 {
125 INSN_JAL /* jal label */
126 }, /* BR_RANGE_S16M */
127 {
128 INSN_SETHI_TA, /* sethi $ta, label */
129 INSN_ORI_TA, /* ori $ta, $ta, label */
130 INSN_JRAL_TA
131 }, /* BR_RANGE_U4G */
132 }, /* relax_code_seq */
133 {
134 {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */
135 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */
136 {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */
137 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */
138 {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */
139 }, /* relax_code_condition */
140 {4, 4, 4, 4, 12}, /* relax_code_size */
141 {4, 4, 4, 4, 4}, /* relax_branch_isize */
142 {
143 {
144 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
145 {0, 0, 0, 0}
146 }, /* BR_RANGE_S256 */
147 {
148 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
149 {0, 0, 0, 0}
150 }, /* BR_RANGE_S16K */
151 {
152 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
153 {0, 0, 0, 0}
154 }, /* BR_RANGE_S64K */
155 {
156 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
157 {0, 0, 0, 0}
158 }, /* BR_RANGE_S16M */
159 {
160 {0, 4, 0, BFD_RELOC_NDS32_HI20},
161 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL4},
162 {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI},
163 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
164 {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
165 {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
166 {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
167 {0, 0, 0, 0}
168 } /* BR_RANGE_U4G */
169 } /* relax_fixup */
170 },
171 {
172 "bltzal", /* opcode */
173 BR_RANGE_S64K, /* br_range */
174 {
175 {0, 20, 0x1F, FALSE},
176 {0, 0, 0, FALSE}
177 }, /* cond_field */
178 {
179 {
180 INSN_BLTZAL /* bltzal $rt, label */
181 }, /* BR_RANGE_S256 */
182 {
183 INSN_BLTZAL /* bltzal $rt, label */
184 }, /* BR_RANGE_S16K */
185 {
186 INSN_BLTZAL /* bltzal $rt, label */
187 }, /* BR_RANGE_S64K */
188 {
189 INSN_BGEZ, /* bgez $rt, $1 */
190 INSN_JAL /* jal label */
191 }, /* BR_RANGE_S16M */
192 {
193 INSN_BGEZ, /* bgez $rt, $1 */
194 INSN_SETHI_TA, /* sethi $ta, label */
195 INSN_ORI_TA, /* ori $ta, $ta, label */
196 INSN_JRAL_TA /* jral $ta */
197 } /* BR_RANGE_U4G */
198 }, /* relax_code_seq */
199 {
200 {
201 {0, 20, 0x1F, FALSE},
202 {0, 0, 0, FALSE}
203 }, /* BR_RANGE_S256 */
204 {
205 {0, 20, 0x1F, FALSE},
206 {0, 0, 0, FALSE}
207 }, /* BR_RANGE_S16K */
208 {
209 {0, 20, 0x1F, FALSE},
210 {0, 0, 0, FALSE}
211 }, /* BR_RANGE_S64K */
212 {
213 {0, 20, 0x1F, FALSE},
214 {0, 0, 0, FALSE}
215 }, /* BR_RANGE_S16M */
216 {
217 {0, 20, 0x1F, FALSE},
218 {0, 0, 0, FALSE}
219 } /* BR_RANGE_U4G */
220 }, /* relax_code_condition */
221 {4, 4, 4, 8, 16}, /* relax_code_size */
222 {4, 4, 4, 4, 4}, /* relax_branch_isize */
223 {
224 {
225 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
226 {0, 0, 0, 0}
227 }, /* BR_RANGE_S256 */
228 {
229 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
230 {0, 0, 0, 0}
231 }, /* BR_RANGE_S16K */
232 {
233 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
234 {0, 0, 0, 0}
235 }, /* BR_RANGE_S64K */
236 {
237 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
238 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL5},
239 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
240 {0, 0, 0, 0}
241 }, /* BR_RANGE_S16M */
242 {
243 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
244 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL6},
245 {4, 4, 0, BFD_RELOC_NDS32_HI20},
246 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
247 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
248 {8, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
249 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
250 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
251 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
252 {0, 0, 0, 0}
253 } /* BR_RANGE_U4G */
254 } /* relax_fixup */
255 },
256 {
257 "bgezal", /* opcode */
258 BR_RANGE_S64K, /* br_range */
259 {
260 {0, 20, 0x1F, FALSE},
261 {0, 0, 0, FALSE}
262 }, /* cond_field */
263 {
264 {
265 INSN_BGEZAL /* bgezal $rt, label */
266 }, /* BR_RANGE_S256 */
267 {
268 INSN_BGEZAL /* bgezal $rt, label */
269 }, /* BR_RANGE_S16K */
270 {
271 INSN_BGEZAL /* bgezal $rt, label */
272 }, /* BR_RANGE_S64K */
273 {
274 INSN_BLTZ, /* bltz $rt, $1 */
275 INSN_JAL /* jal label */
276 }, /* BR_RANGE_S16M */
277 {
278 INSN_BLTZ, /* bltz $rt, $1 */
279 INSN_SETHI_TA, /* sethi $ta, label */
280 INSN_ORI_TA, /* ori $ta, $ta, label */
281 INSN_JRAL_TA /* jral $ta */
282 } /* BR_RANGE_U4G */
283 }, /* relax_code_seq */
284 {
285 {
286 {0, 20, 0x1F, FALSE},
287 {0, 0, 0, FALSE}
288 }, /* BR_RANGE_S256 */
289 {
290 {0, 20, 0x1F, FALSE},
291 {0, 0, 0, FALSE}
292 }, /* BR_RANGE_S16K */
293 {
294 {0, 20, 0x1F, FALSE},
295 {0, 0, 0, FALSE}
296 }, /* BR_RANGE_S64K */
297 {
298 {0, 20, 0x1F, FALSE},
299 {0, 0, 0, FALSE}
300 }, /* BR_RANGE_S16M */
301 {
302 {0, 20, 0x1F, FALSE},
303 {0, 0, 0, FALSE}
304 } /* BR_RANGE_U4G */
305 }, /* relax_code_condition */
306 {4, 4, 4, 8, 16}, /* relax_code_size */
307 {4, 4, 4, 4, 4}, /* relax_branch_isize */
308 {
309 {
310 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
311 {0, 0, 0, 0}
312 }, /* BR_RANGE_S256 */
313 {
314 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
315 {0, 0, 0, 0}
316 }, /* BR_RANGE_S16K */
317 {
318 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
319 {0, 0, 0, 0}
320 }, /* BR_RANGE_S64K */
321 {
322 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
323 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL5},
324 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
325 {0, 0, 0, 0}
326 }, /* BR_RANGE_S16M */
327 {
328 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
329 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL6},
330 {4, 4, 0, BFD_RELOC_NDS32_HI20},
331 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
332 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
333 {8, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
334 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
335 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
336 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
337 {0, 0, 0, 0}
338 } /* BR_RANGE_U4G */
339 } /* relax_fixup */
340 },
341 {
342 "j", /* opcode */
343 BR_RANGE_S16M, /* br_range */
344 {{0, 0, 0, FALSE}}, /* cond_field */
345 {
346 {
347 (INSN_J8 << 16) /* j8 label */
348 }, /* BR_RANGE_S256 */
349 {
350 INSN_J /* j label */
351 }, /* BR_RANGE_S16K */
352 {
353 INSN_J /* j label */
354 }, /* BR_RANGE_S64K */
355 {
356 INSN_J /* j label */
357 }, /* BR_RANGE_S16M */
358 {
359 INSN_SETHI_TA, /* sethi $ta, label */
360 INSN_ORI_TA, /* ori $ta, $ta, label */
361 INSN_JR_TA /* jr $ta */
362 }, /* BR_RANGE_U4G */
363 }, /* relax_code_seq */
364 {
365 {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */
366 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */
367 {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */
368 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */
369 {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */
370 }, /* relax_code_condition */
371 {2, 4, 4, 4, 12}, /* relax_code_size */
372 {2, 4, 4, 4, 4}, /* relax_branch_isize */
373 {
374 {
375 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
376 {0, 0, 0, 0}
377 }, /* BR_RANGE_S256 */
378 {
379 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
380 {0, 0, 0, 0}
381 }, /* BR_RANGE_S16K */
382 {
383 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
384 {0, 0, 0, 0}
385 }, /* BR_RANGE_S64K */
386 {
387 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
388 {0, 0, 0, 0}
389 }, /* BR_RANGE_S16M */
390 {
391 {0, 4, 0, BFD_RELOC_NDS32_HI20},
392 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP4},
393 {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI},
394 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
395 {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
396 {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
397 {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
398 {0, 0, 0, 0}
399 } /* BR_RANGE_U4G */
400 } /* relax_fixup */
401 },
402 {
403 "j8", /* opcode */
404 BR_RANGE_S256, /* br_range */
405 {{0, 0, 0, FALSE}}, /* cond_field */
406 {
407 {
408 (INSN_J8 << 16) /* j8 label */
409 }, /* BR_RANGE_S256 */
410 {
411 INSN_J /* j label */
412 }, /* BR_RANGE_S16K */
413 {
414 INSN_J /* j label */
415 }, /* BR_RANGE_S64K */
416 {
417 INSN_J /* j label */
418 }, /* BR_RANGE_S16M */
419 {
420 INSN_SETHI_TA, /* sethi $ta, label */
421 INSN_ORI_TA, /* ori $ta, $ta, label */
422 INSN_JR_TA /* jr $ta */
423 }, /* BR_RANGE_U4G */
424 }, /* relax_code_seq */
425 {
426 {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */
427 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */
428 {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */
429 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */
430 {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */
431 }, /* relax_code_condition */
432 {2, 4, 4, 4, 12}, /* relax_code_size */
433 {2, 4, 4, 4, 4}, /* relax_branch_isize */
434 {
435 {
436 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
437 {0, 0, 0, 0}
438 }, /* BR_RANGE_S256 */
439 {
440 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
441 {0, 0, 0, 0}
442 }, /* BR_RANGE_S16K */
443 {
444 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
445 {0, 0, 0, 0}
446 }, /* BR_RANGE_S64K */
447 {
448 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
449 {0, 0, 0, 0}
450 }, /* BR_RANGE_S16M */
451 {
452 {0, 4, 0, BFD_RELOC_NDS32_HI20},
453 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP4},
454 {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI},
455 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
456 {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
457 {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
458 {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
459 {0, 0, 0, 0}
460 } /* BR_RANGE_U4G */
461 } /* relax_fixup */
462 },
463 {
464 "beqz", /* opcode */
465 BR_RANGE_S64K, /* br_range */
466 {
467 {0, 20, 0x1F, FALSE},
468 {0, 0, 0, FALSE}
469 }, /* cond_field */
470 {
471 {
472 INSN_BEQZ /* beqz $rt, label */
473 }, /* BR_RANGE_S256 */
474 {
475 INSN_BEQZ /* beqz $rt, label */
476 }, /* BR_RANGE_S16K */
477 {
478 INSN_BEQZ /* beqz $rt, label */
479 }, /* BR_RANGE_S64K */
480 {
481 INSN_BNEZ, /* bnez $rt, $1 */
482 INSN_J /* j label */
483 }, /* BR_RANGE_S16M */
484 {
485 INSN_BNEZ, /* bnez $rt, $1 */
486 INSN_SETHI_TA, /* sethi $ta, label */
487 INSN_ORI_TA, /* ori $ta, $ta, label */
488 INSN_JR_TA /* jr $ta */
489 } /* BR_RANGE_U4G */
490 }, /* relax_code_seq */
491 {
492 {
493 {0, 20, 0x1F, FALSE},
494 {0, 0, 0, FALSE}
495 }, /* BR_RANGE_S256 */
496 {
497 {0, 20, 0x1F, FALSE},
498 {0, 0, 0, FALSE}
499 }, /* BR_RANGE_S16K */
500 {
501 {0, 20, 0x1F, FALSE},
502 {0, 0, 0, FALSE}
503 }, /* BR_RANGE_S64K */
504 {
505 {0, 20, 0x1F, FALSE},
506 {0, 0, 0, FALSE}
507 }, /* BR_RANGE_S16M */
508 {
509 {0, 20, 0x1F, FALSE},
510 {0, 0, 0, FALSE}
511 } /* BR_RANGE_U4G */
512 }, /* relax_code_condition */
513 {4, 4, 4, 8, 16}, /* relax_code_size */
514 {4, 4, 4, 4, 4}, /* relax_branch_isize */
515 {
516 {
517 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
518 {0, 4, NDS32_INSN16 , BFD_RELOC_NDS32_INSN16},
519 {0, 0, 0, 0}
520 }, /* BR_RANGE_S256 */
521 {
522 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
523 {0, 0, 0, 0}
524 }, /* BR_RANGE_S16K */
525 {
526 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
527 {0, 0, 0, 0}
528 }, /* BR_RANGE_S64K */
529 {
530 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
531 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
532 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
533 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
534 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
535 {0, 0, 0, 0}
536 }, /* BR_RANGE_S16M */
537 {
538 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
539 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
540 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
541 {4, 4, 0, BFD_RELOC_NDS32_HI20},
542 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
543 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
544 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
545 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
546 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
547 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
548 {0, 0, 0, 0}
549 } /* BR_RANGE_U4G */
550 } /* relax_fixup */
551 },
552 {
553 "bgez", /* opcode */
554 BR_RANGE_S64K, /* br_range */
555 {
556 {0, 20, 0x1F, FALSE},
557 {0, 0, 0, FALSE}
558 }, /* cond_field */
559 {
560 {
561 INSN_BGEZ /* bgez $rt, label */
562 }, /* BR_RANGE_S256 */
563 {
564 INSN_BGEZ /* bgez $rt, label */
565 }, /* BR_RANGE_S16K */
566 {
567 INSN_BGEZ /* bgez $rt, label */
568 }, /* BR_RANGE_S64K */
569 {
570 INSN_BLTZ, /* bltz $rt, $1 */
571 INSN_J /* j label */
572 }, /* BR_RANGE_S16M */
573 {
574 INSN_BLTZ, /* bltz $rt, $1 */
575 INSN_SETHI_TA, /* sethi $ta, label */
576 INSN_ORI_TA, /* ori $ta, $ta, label */
577 INSN_JR_TA /* jr $ta */
578 } /* BR_RANGE_U4G */
579 }, /* relax_code_seq */
580 {
581 {
582 {0, 20, 0x1F, FALSE},
583 {0, 0, 0, FALSE}
584 }, /* BR_RANGE_S256 */
585 {
586 {0, 20, 0x1F, FALSE},
587 {0, 0, 0, FALSE}
588 }, /* BR_RANGE_S16K */
589 {
590 {0, 20, 0x1F, FALSE},
591 {0, 0, 0, FALSE}
592 }, /* BR_RANGE_S64K */
593 {
594 {0, 20, 0x1F, FALSE},
595 {0, 0, 0, FALSE}
596 }, /* BR_RANGE_S16M */
597 {
598 {0, 20, 0x1F, FALSE},
599 {0, 0, 0, FALSE}
600 } /* BR_RANGE_U4G */
601 }, /* relax_code_condition */
602 {4, 4, 4, 8, 16}, /* relax_code_size */
603 {4, 4, 4, 4, 4}, /* relax_branch_isize */
604 {
605 {
606 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
607 {0, 0, 0, 0}
608 }, /* BR_RANGE_S256 */
609 {
610 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
611 {0, 0, 0, 0}
612 }, /* BR_RANGE_S16K */
613 {
614 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
615 {0, 0, 0, 0}
616 }, /* BR_RANGE_S64K */
617 {
618 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
619 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
620 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
621 {0, 0, 0, 0}
622 }, /* BR_RANGE_S16M */
623 {
624 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
625 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
626 {4, 4, 0, BFD_RELOC_NDS32_HI20},
627 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
628 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
629 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
630 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
631 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
632 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
633 {0, 0, 0, 0}
634 } /* BR_RANGE_U4G */
635 } /* relax_fixup */
636 },
637 {
638 "bnez", /* opcode */
639 BR_RANGE_S64K, /* br_range */
640 {
641 {0, 20, 0x1F, FALSE},
642 {0, 0, 0, FALSE}
643 }, /* cond_field */
644 {
645 {
646 INSN_BNEZ /* bnez $rt, label */
647 }, /* BR_RANGE_S256 */
648 {
649 INSN_BNEZ /* bnez $rt, label */
650 }, /* BR_RANGE_S16K */
651 {
652 INSN_BNEZ /* bnez $rt, label */
653 }, /* BR_RANGE_S64K */
654 {
655 INSN_BEQZ, /* beqz $rt, $1 */
656 INSN_J /* j label */
657 }, /* BR_RANGE_S16M */
658 {
659 INSN_BEQZ, /* beqz $rt, $1 */
660 INSN_SETHI_TA, /* sethi $ta, label */
661 INSN_ORI_TA, /* ori $ta, $ta, label */
662 INSN_JR_TA /* jr $ta */
663 } /* BR_RANGE_U4G */
664 }, /* relax_code_seq */
665 {
666 {
667 {0, 20, 0x1F, FALSE},
668 {0, 0, 0, FALSE}
669 }, /* BR_RANGE_S256 */
670 {
671 {0, 20, 0x1F, FALSE},
672 {0, 0, 0, FALSE}
673 }, /* BR_RANGE_S16K */
674 {
675 {0, 20, 0x1F, FALSE},
676 {0, 0, 0, FALSE}
677 }, /* BR_RANGE_S64K */
678 {
679 {0, 20, 0x1F, FALSE},
680 {0, 0, 0, FALSE}
681 }, /* BR_RANGE_S16M */
682 {
683 {0, 20, 0x1F, FALSE},
684 {0, 0, 0, FALSE}
685 } /* BR_RANGE_U4G */
686 }, /* relax_code_condition */
687 {4, 4, 4, 8, 16}, /* relax_code_size */
688 {4, 4, 4, 4, 4}, /* relax_branch_isize */
689 {
690 {
691 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
692 {0, 4, NDS32_INSN16 , BFD_RELOC_NDS32_INSN16},
693 {0, 0, 0, 0}
694 }, /* BR_RANGE_S256 */
695 {
696 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
697 {0, 0, 0, 0}
698 }, /* BR_RANGE_S16K */
699 {
700 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
701 {0, 0, 0, 0}
702 }, /* BR_RANGE_S64K */
703 {
704 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
705 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
706 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
707 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
708 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
709 {0, 0, 0, 0}
710 }, /* BR_RANGE_S16M */
711 {
712 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
713 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
714 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
715 {4, 4, 0, BFD_RELOC_NDS32_HI20},
716 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
717 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
718 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
719 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
720 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
721 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
722 {0, 0, 0, 0}
723 } /* BR_RANGE_U4G */
724 } /* relax_fixup */
725 },
726 {
727 "bgtz", /* opcode */
728 BR_RANGE_S64K, /* br_range */
729 {
730 {0, 20, 0x1F, FALSE},
731 {0, 0, 0, FALSE}
732 }, /* cond_field */
733 {
734 {
735 INSN_BGTZ /* bgtz $rt, label */
736 }, /* BR_RANGE_S256 */
737 {
738 INSN_BGTZ /* bgtz $rt, label */
739 }, /* BR_RANGE_S16K */
740 {
741 INSN_BGTZ /* bgtz $rt, label */
742 }, /* BR_RANGE_S64K */
743 {
744 INSN_BLEZ, /* blez $rt, $1 */
745 INSN_J /* j label */
746 }, /* BR_RANGE_S16M */
747 {
748 INSN_BLEZ, /* blez $rt, $1 */
749 INSN_SETHI_TA, /* sethi $ta, label */
750 INSN_ORI_TA, /* ori $ta, $ta, label */
751 INSN_JR_TA /* jr $ta */
752 } /* BR_RANGE_U4G */
753 }, /* relax_code_seq */
754 {
755 {
756 {0, 20, 0x1F, FALSE},
757 {0, 0, 0, FALSE}
758 }, /* BR_RANGE_S256 */
759 {
760 {0, 20, 0x1F, FALSE},
761 {0, 0, 0, FALSE}
762 }, /* BR_RANGE_S16K */
763 {
764 {0, 20, 0x1F, FALSE},
765 {0, 0, 0, FALSE}
766 }, /* BR_RANGE_S64K */
767 {
768 {0, 20, 0x1F, FALSE},
769 {0, 0, 0, FALSE}
770 }, /* BR_RANGE_S16M */
771 {
772 {0, 20, 0x1F, FALSE},
773 {0, 0, 0, FALSE}
774 } /* BR_RANGE_U4G */
775 }, /* relax_code_condition */
776 {4, 4, 4, 8, 16}, /* relax_code_size */
777 {4, 4, 4, 4, 4}, /* relax_branch_isize */
778 {
779 {
780 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
781 {0, 0, 0, 0}
782 }, /* BR_RANGE_S256 */
783 {
784 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
785 {0, 0, 0, 0}
786 }, /* BR_RANGE_S16K */
787 {
788 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
789 {0, 0, 0, 0}
790 }, /* BR_RANGE_S64K */
791 {
792 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
793 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
794 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
795 {0, 0, 0, 0}
796 }, /* BR_RANGE_S16M */
797 {
798 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
799 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
800 {4, 4, 0, BFD_RELOC_NDS32_HI20},
801 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
802 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
803 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
804 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
805 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
806 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
807 {0, 0, 0, 0}
808 } /* BR_RANGE_U4G */
809 } /* relax_fixup */
810 },
811 {
812 "blez", /* opcode */
813 BR_RANGE_S64K, /* br_range */
814 {
815 {0, 20, 0x1F, FALSE},
816 {0, 0, 0, FALSE}
817 }, /* cond_field */
818 {
819 {
820 INSN_BLEZ /* blez $rt, label */
821 }, /* BR_RANGE_S256 */
822 {
823 INSN_BLEZ /* blez $rt, label */
824 }, /* BR_RANGE_S16K */
825 {
826 INSN_BLEZ /* blez $rt, label */
827 }, /* BR_RANGE_S64K */
828 {
829 INSN_BGTZ, /* bgtz $rt, $1 */
830 INSN_J /* j label */
831 }, /* BR_RANGE_S16M */
832 {
833 INSN_BGTZ, /* bgtz $rt, $1 */
834 INSN_SETHI_TA, /* sethi $ta, label */
835 INSN_ORI_TA, /* ori $ta, $ta, label */
836 INSN_JR_TA /* jr $ta */
837 } /* BR_RANGE_U4G */
838 }, /* relax_code_seq */
839 {
840 {
841 {0, 20, 0x1F, FALSE},
842 {0, 0, 0, FALSE}
843 }, /* BR_RANGE_S256 */
844 {
845 {0, 20, 0x1F, FALSE},
846 {0, 0, 0, FALSE}
847 }, /* BR_RANGE_S16K */
848 {
849 {0, 20, 0x1F, FALSE},
850 {0, 0, 0, FALSE}
851 }, /* BR_RANGE_S64K */
852 {
853 {0, 20, 0x1F, FALSE},
854 {0, 0, 0, FALSE}
855 }, /* BR_RANGE_S16M */
856 {
857 {0, 20, 0x1F, FALSE},
858 {0, 0, 0, FALSE}
859 } /* BR_RANGE_U4G */
860 }, /* relax_code_condition */
861 {4, 4, 4, 8, 16}, /* relax_code_size */
862 {4, 4, 4, 4, 4}, /* relax_branch_isize */
863 {
864 {
865 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
866 {0, 0, 0, 0}
867 }, /* BR_RANGE_S256 */
868 {
869 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
870 {0, 0, 0, 0}
871 }, /* BR_RANGE_S16K */
872 {
873 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
874 {0, 0, 0, 0}
875 }, /* BR_RANGE_S64K */
876 {
877 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
878 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
879 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
880 {0, 0, 0, 0}
881 }, /* BR_RANGE_S16M */
882 {
883 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
884 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
885 {4, 4, 0, BFD_RELOC_NDS32_HI20},
886 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
887 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
888 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
889 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
890 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
891 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
892 {0, 0, 0, 0}
893 } /* BR_RANGE_U4G */
894 } /* relax_fixup */
895 },
896 {
897 "bltz", /* opcode */
898 BR_RANGE_S64K, /* br_range */
899 {
900 {0, 20, 0x1F, FALSE},
901 {0, 0, 0, FALSE}
902 }, /* cond_field */
903 {
904 {
905 INSN_BLTZ /* bltz $rt, label */
906 }, /* BR_RANGE_S256 */
907 {
908 INSN_BLTZ /* bltz $rt, label */
909 }, /* BR_RANGE_S16K */
910 {
911 INSN_BLTZ /* bltz $rt, label */
912 }, /* BR_RANGE_S64K */
913 {
914 INSN_BGEZ, /* bgez $rt, $1 */
915 INSN_J /* j label */
916 }, /* BR_RANGE_S16M */
917 {
918 INSN_BGEZ, /* bgez $rt, $1 */
919 INSN_SETHI_TA, /* sethi $ta, label */
920 INSN_ORI_TA, /* ori $ta, $ta, label */
921 INSN_JR_TA /* jr $ta */
922 } /* BR_RANGE_U4G */
923 }, /* relax_code_seq */
924 {
925 {
926 {0, 20, 0x1F, FALSE},
927 {0, 0, 0, FALSE}
928 }, /* BR_RANGE_S256 */
929 {
930 {0, 20, 0x1F, FALSE},
931 {0, 0, 0, FALSE}
932 }, /* BR_RANGE_S16K */
933 {
934 {0, 20, 0x1F, FALSE},
935 {0, 0, 0, FALSE}
936 }, /* BR_RANGE_S64K */
937 {
938 {0, 20, 0x1F, FALSE},
939 {0, 0, 0, FALSE}
940 }, /* BR_RANGE_S16M */
941 {
942 {0, 20, 0x1F, FALSE},
943 {0, 0, 0, FALSE}
944 } /* BR_RANGE_U4G */
945 }, /* relax_code_condition */
946 {4, 4, 4, 8, 16}, /* relax_code_size */
947 {4, 4, 4, 4, 4}, /* relax_branch_isize */
948 {
949 {
950 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
951 {0, 0, 0, 0}
952 }, /* BR_RANGE_S256 */
953 {
954 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
955 {0, 0, 0, 0}
956 }, /* BR_RANGE_S16K */
957 {
958 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
959 {0, 0, 0, 0}
960 }, /* BR_RANGE_S64K */
961 {
962 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
963 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
964 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
965 {0, 0, 0, 0}
966 }, /* BR_RANGE_S16M */
967 {
968 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
969 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
970 {4, 4, 0, BFD_RELOC_NDS32_HI20},
971 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
972 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
973 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
974 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
975 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
976 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
977 {0, 0, 0, 0}
978 } /* BR_RANGE_U4G */
979 } /* relax_fixup */
980 },
981 {
982 "beq", /* opcode */
983 BR_RANGE_S16K, /* br_range */
984 {
985 {0, 20, 0x1F, FALSE},
986 {0, 15, 0x1F, FALSE},
987 {0, 0, 0, FALSE}
988 }, /* cond_field */
989 {
990 {
991 INSN_BEQ /* beq $rt, $ra, label */
992 }, /* BR_RANGE_S256 */
993 {
994 INSN_BEQ /* beq $rt, $ra, label */
995 }, /* BR_RANGE_S16K */
996 {
997 INSN_BNE, /* bne $rt, $ra, $1 */
998 INSN_J /* j label */
999 }, /* BR_RANGE_S64K */
1000 {
1001 INSN_BNE, /* bne $rt, $ra, $1 */
1002 INSN_J /* j label */
1003 }, /* BR_RANGE_S16M */
1004 {
1005 INSN_BNE, /* bne $rt, $ra, $1 */
1006 INSN_SETHI_TA, /* sethi $ta, label */
1007 INSN_ORI_TA, /* ori $ta, $ta, label */
1008 INSN_JR_TA /* jr $ta */
1009 } /* BR_RANGE_U4G */
1010 }, /* relax_code_seq */
1011 {
1012 {
1013 {0, 20, 0x1F, FALSE},
1014 {0, 15, 0x1F, FALSE},
1015 {0, 0, 0, FALSE}
1016 }, /* BR_RANGE_S256 */
1017 {
1018 {0, 20, 0x1F, FALSE},
1019 {0, 15, 0x1F, FALSE},
1020 {0, 0, 0, FALSE}
1021 }, /* BR_RANGE_S16K */
1022 {
1023 {0, 20, 0x1F, FALSE},
1024 {0, 15, 0x1F, FALSE},
1025 {0, 0, 0, FALSE}
1026 }, /* BR_RANGE_S64K */
1027 {
1028 {0, 20, 0x1F, FALSE},
1029 {0, 15, 0x1F, FALSE},
1030 {0, 0, 0, FALSE}
1031 }, /* BR_RANGE_S16M */
1032 {
1033 {0, 20, 0x1F, FALSE},
1034 {0, 15, 0x1F, FALSE},
1035 {0, 0, 0, FALSE}
1036 } /* BR_RANGE_U4G */
1037 }, /* relax_code_condition */
1038 {4, 4, 8, 8, 16}, /* relax_code_size */
1039 {4, 4, 4, 4, 4}, /* relax_branch_isize */
1040 {
1041 {
1042 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1043 {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
1044 {0, 0, 0, 0}
1045 }, /* BR_RANGE_S256 */
1046 {
1047 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1048 {0, 0, 0, 0}
1049 }, /* BR_RANGE_S16K */
1050 {
1051 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1052 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1053 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1054 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1055 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1056 {0, 0, 0, 0}
1057 }, /* BR_RANGE_S64K */
1058 {
1059 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1060 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1061 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1062 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1063 {4, 4, NDS32_ABS, BFD_RELOC_NDS32_EMPTY},
1064 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1065 {0, 0, 0, 0}
1066 }, /* BR_RANGE_S16M */
1067 {
1068 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1069 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1070 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1071 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1072 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1073 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1074 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1075 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1076 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1077 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1078 {0, 0, 0, 0}
1079 } /* BR_RANGE_U4G */
1080 } /* relax_fixup */
1081 },
1082 {
1083 "bne", /* opcode */
1084 BR_RANGE_S16K, /* br_range */
1085 {
1086 {0, 20, 0x1F, FALSE},
1087 {0, 15, 0x1F, FALSE},
1088 {0, 0, 0, FALSE}
1089 }, /* cond_field */
1090 {
1091 {
1092 INSN_BNE /* bne $rt, $ra, label */
1093 }, /* BR_RANGE_S256 */
1094 {
1095 INSN_BNE /* bne $rt, $ra, label */
1096 }, /* BR_RANGE_S16K */
1097 {
1098 INSN_BEQ, /* beq $rt, $ra, $1 */
1099 INSN_J /* j label */
1100 }, /* BR_RANGE_S64K */
1101 {
1102 INSN_BEQ, /* beq $rt, $ra, $1 */
1103 INSN_J /* j label */
1104 }, /* BR_RANGE_S16M */
1105 {
1106 INSN_BEQ, /* beq $rt, $ra, $1 */
1107 INSN_SETHI_TA, /* sethi $ta, label */
1108 INSN_ORI_TA, /* ori $ta, $ta, label */
1109 INSN_JR_TA /* jr $ta */
1110 } /* BR_RANGE_U4G */
1111 }, /* relax_code_seq */
1112 {
1113 {
1114 {0, 20, 0x1F, FALSE},
1115 {0, 15, 0x1F, FALSE},
1116 {0, 0, 0, FALSE}
1117 }, /* BR_RANGE_S256 */
1118 {
1119 {0, 20, 0x1F, FALSE},
1120 {0, 15, 0x1F, FALSE},
1121 {0, 0, 0, FALSE}
1122 }, /* BR_RANGE_S16K */
1123 {
1124 {0, 20, 0x1F, FALSE},
1125 {0, 15, 0x1F, FALSE},
1126 {0, 0, 0, FALSE}
1127 }, /* BR_RANGE_S64K */
1128 {
1129 {0, 20, 0x1F, FALSE},
1130 {0, 15, 0x1F, FALSE},
1131 {0, 0, 0, FALSE}
1132 }, /* BR_RANGE_S16M */
1133 {
1134 {0, 20, 0x1F, FALSE},
1135 {0, 15, 0x1F, FALSE},
1136 {0, 0, 0, FALSE}
1137 } /* BR_RANGE_U4G */
1138 }, /* relax_code_condition */
1139 {4, 4, 8, 8, 16}, /* relax_code_size */
1140 {4, 4, 4, 4, 4}, /* relax_branch_isize */
1141 {
1142 {
1143 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1144 {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
1145 {0, 0, 0, 0}
1146 }, /* BR_RANGE_S256 */
1147 {
1148 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1149 {0, 0, 0, 0}
1150 }, /* BR_RANGE_S16K */
1151 {
1152 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1153 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1154 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1155 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1156 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1157 {0, 0, 0, 0}
1158 }, /* BR_RANGE_S64K */
1159 {
1160 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1161 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1162 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1163 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1164 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1165 {0, 0, 0, 0}
1166 }, /* BR_RANGE_S16M */
1167 {
1168 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1169 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1170 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1171 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1172 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1173 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1174 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1175 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1176 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1177 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1178 {0, 0, 0, 0}
1179 } /* BR_RANGE_U4G */
1180 } /* relax_fixup */
1181 },
1182 {
1183 "beqz38", /* opcode */
1184 BR_RANGE_S256, /* br_range */
1185 {
1186 {0, 8, 0x7, FALSE},
1187 {0, 0, 0, FALSE}
1188 }, /* cond_field */
1189 {
1190 {
1191 INSN_BEQZ38 << 16 /* beqz $rt, label */
1192 }, /* BR_RANGE_S256 */
1193 {
1194 INSN_BEQZ /* beqz $rt, label */
1195 }, /* BR_RANGE_S16K */
1196 {
1197 INSN_BEQZ /* beqz $rt, label */
1198 }, /* BR_RANGE_S64K */
1199 {
1200 INSN_BNEZ, /* bnez $rt, $1 */
1201 INSN_J /* j label */
1202 }, /* BR_RANGE_S16M */
1203 {
1204 INSN_BNEZ, /* bnez $rt, $1 */
1205 INSN_SETHI_TA, /* sethi $ta, label */
1206 INSN_ORI_TA, /* ori $ta, $ta, label */
1207 INSN_JR_TA /* jr $ta */
1208 } /* BR_RANGE_U4G */
1209 }, /* relax_code_seq */
1210 {
1211 {
1212 {0, 8, 0x7, FALSE},
1213 {0, 0, 0, FALSE}
1214 }, /* BR_RANGE_S256 */
1215 {
1216 {0, 20, 0x1F, FALSE},
1217 {0, 0, 0, FALSE}
1218 }, /* BR_RANGE_S16K */
1219 {
1220 {0, 20, 0x1F, FALSE},
1221 {0, 0, 0, FALSE}
1222 }, /* BR_RANGE_S64K */
1223 {
1224 {0, 20, 0x1F, FALSE},
1225 {0, 0, 0, FALSE}
1226 }, /* BR_RANGE_S16M */
1227 {
1228 {0, 20, 0x1F, FALSE},
1229 {0, 0, 0, FALSE}
1230 } /* BR_RANGE_U4G */
1231 }, /* relax_code_condition */
1232 {2, 4, 4, 8, 16}, /* relax_code_size */
1233 {2, 4, 4, 4, 4}, /* relax_branch_isize */
1234 {
1235 {
1236 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
1237 {0, 0, 0, 0}
1238 }, /* BR_RANGE_S256 */
1239 {
1240 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1241 {0, 0, 0, 0}
1242 }, /* BR_RANGE_S16K */
1243 {
1244 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1245 {0, 0, 0, 0}
1246 }, /* BR_RANGE_S64K */
1247 {
1248 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1249 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1250 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1251 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1252 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1253 {0, 0, 0, 0}
1254 }, /* BR_RANGE_S16M */
1255 {
1256 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1257 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1258 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1259 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1260 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1261 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1262 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1263 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1264 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1265 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1266 {0, 0, 0, 0}
1267 } /* BR_RANGE_U4G */
1268 } /* relax_fixup */
1269 },
1270 {
1271 "bnez38", /* opcode */
1272 BR_RANGE_S256, /* br_range */
1273 {
1274 {0, 8, 0x7, FALSE},
1275 {0, 0, 0, FALSE}
1276 }, /* cond_field */
1277 {
1278 {
1279 INSN_BNEZ38 << 16 /* bnez $rt, label */
1280 }, /* BR_RANGE_S256 */
1281 {
1282 INSN_BNEZ /* bnez $rt, label */
1283 }, /* BR_RANGE_S16K */
1284 {
1285 INSN_BNEZ /* bnez $rt, label */
1286 }, /* BR_RANGE_S64K */
1287 {
1288 INSN_BEQZ, /* beqz $rt, $1 */
1289 INSN_J /* j label */
1290 }, /* BR_RANGE_S16M */
1291 {
1292 INSN_BEQZ, /* beqz $rt, $1 */
1293 INSN_SETHI_TA, /* sethi $ta, label */
1294 INSN_ORI_TA, /* ori $ta, $ta, label */
1295 INSN_JR_TA /* jr $ta */
1296 } /* BR_RANGE_U4G */
1297 }, /* relax_code_seq */
1298 {
1299 {
1300 {0, 8, 0x7, FALSE},
1301 {0, 0, 0, FALSE}
1302 }, /* BR_RANGE_S256 */
1303 {
1304 {0, 20, 0x1F, FALSE},
1305 {0, 0, 0, FALSE}
1306 }, /* BR_RANGE_S16K */
1307 {
1308 {0, 20, 0x1F, FALSE},
1309 {0, 0, 0, FALSE}
1310 }, /* BR_RANGE_S64K */
1311 {
1312 {0, 20, 0x1F, FALSE},
1313 {0, 0, 0, FALSE}
1314 }, /* BR_RANGE_S16M */
1315 {
1316 {0, 20, 0x1F, FALSE},
1317 {0, 0, 0, FALSE}
1318 } /* BR_RANGE_U4G */
1319 }, /* relax_code_condition */
1320 {2, 4, 4, 8, 16}, /* relax_code_size */
1321 {2, 4, 4, 4, 4}, /* relax_branch_isize */
1322 {
1323 {
1324 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
1325 {0, 0, 0, 0}
1326 }, /* BR_RANGE_S256 */
1327 {
1328 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1329 {0, 0, 0, 0}
1330 }, /* BR_RANGE_S16K */
1331 {
1332 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1333 {0, 0, 0, 0}
1334 }, /* BR_RANGE_S64K */
1335 {
1336 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1337 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1338 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1339 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1340 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1341 {0, 0, 0, 0}
1342 }, /* BR_RANGE_S16M */
1343 {
1344 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1345 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1346 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1347 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1348 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1349 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1350 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1351 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1352 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1353 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1354 {0, 0, 0, 0}
1355 } /* BR_RANGE_U4G */
1356 } /* relax_fixup */
1357 },
1358 {
1359 "beqzs8", /* opcode */
1360 BR_RANGE_S256, /* br_range */
1361 {{0, 0, 0, FALSE}}, /* cond_field */
1362 {
1363 {
1364 INSN_BEQZS8 << 16 /* beqz $r15, label */
1365 }, /* BR_RANGE_S256 */
1366 {
1367 INSN_BEQZ_TA /* bnez $rt, label */
1368 }, /* BR_RANGE_S16K */
1369 {
1370 INSN_BEQZ_TA /* bnez $rt, label */
1371 }, /* BR_RANGE_S64K */
1372 {
1373 INSN_BNEZ_TA, /* bnez $r15, $1 */
1374 INSN_J /* j label */
1375 }, /* BR_RANGE_S16M */
1376 {
1377 INSN_BNEZ_TA, /* bnez $r15, $1 */
1378 INSN_SETHI_TA, /* sethi $ta, label */
1379 INSN_ORI_TA, /* ori $ta, $ta, label */
1380 INSN_JR_TA /* jr $ta */
1381 } /* BR_RANGE_U4G */
1382 }, /* relax_code_seq */
1383 {
1384 {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */
1385 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */
1386 {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */
1387 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */
1388 {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */
1389 }, /* relax_code_condition */
1390 {2, 4, 4, 8, 16}, /* relax_code_size */
1391 {2, 4, 4, 4, 4}, /* relax_branch_isize */
1392 {
1393 {
1394 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
1395 {0, 0, 0, 0}
1396 }, /* BR_RANGE_S256 */
1397 {
1398 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1399 {0, 0, 0, 0}
1400 }, /* BR_RANGE_S16K */
1401 {
1402 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1403 {0, 0, 0, 0}
1404 }, /* BR_RANGE_S64K */
1405 {
1406 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1407 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1408 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1409 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1410 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1411 {0, 0, 0, 0}
1412 }, /* BR_RANGE_S16M */
1413 {
1414 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1415 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1416 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1417 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1418 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1419 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1420 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1421 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1422 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1423 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1424 {0, 0, 0, 0}
1425 } /* BR_RANGE_U4G */
1426 } /* relax_fixup */
1427 },
1428 {
1429 "bnezs8", /* opcode */
1430 BR_RANGE_S256, /* br_range */
1431 {{0, 0, 0, FALSE}}, /* cond_field */
1432 {
1433 {
1434 INSN_BNEZS8 << 16 /* bnez $r15, label */
1435 }, /* BR_RANGE_S256 */
1436 {
1437 INSN_BNEZ_TA /* bnez $r15, label */
1438 }, /* BR_RANGE_S16K */
1439 {
1440 INSN_BNEZ_TA /* bnez $r15, label */
1441 }, /* BR_RANGE_S64K */
1442 {
1443 INSN_BEQZ_TA, /* beqz $r15, $1 */
1444 INSN_J /* j label */
1445 }, /* BR_RANGE_S16M */
1446 {
1447 INSN_BEQZ_TA, /* beqz $r15, $1 */
1448 INSN_SETHI_TA, /* sethi $ta, label */
1449 INSN_ORI_TA, /* ori $ta, $ta, label */
1450 INSN_JR_TA /* jr $ta */
1451 } /* BR_RANGE_U4G */
1452 }, /* relax_code_seq */
1453 {
1454 {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */
1455 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */
1456 {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */
1457 {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */
1458 {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */
1459 }, /* relax_code_condition */
1460 {2, 4, 4, 8, 16}, /* relax_code_size */
1461 {2, 4, 4, 4, 4}, /* relax_branch_isize */
1462 {
1463 {
1464 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
1465 {0, 0, 0, 0}
1466 }, /* BR_RANGE_S256 */
1467 {
1468 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1469 {0, 0, 0, 0}
1470 }, /* BR_RANGE_S16K */
1471 {
1472 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1473 {0, 0, 0, 0}
1474 }, /* BR_RANGE_S64K */
1475 {
1476 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1477 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1478 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1479 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1480 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1481 {0, 0, 0, 0}
1482 }, /* BR_RANGE_S16M */
1483 {
1484 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1485 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1486 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1487 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1488 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1489 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1490 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1491 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1492 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1493 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1494 {0, 0, 0, 0}
1495 } /* BR_RANGE_U4G */
1496 } /* relax_fixup */
1497 },
1498 {
1499 "bnes38", /* opcode */
1500 BR_RANGE_S256, /* br_range */
1501 {
1502 {0, 8, 0x7, FALSE},
1503 {0, 0, 0, FALSE}
1504 }, /* cond_field */
1505 {
1506 {
1507 INSN_BNES38 << 16 /* bne $rt, $R5, label */
1508 }, /* BR_RANGE_S256 */
1509 {
1510 INSN_BNE_R5 /* bne $rt, $R5, label */
1511 }, /* BR_RANGE_S16K */
1512 {
1513 INSN_BEQ_R5, /* beq $rt, $R5, $1 */
1514 INSN_J /* j label */
1515 }, /* BR_RANGE_S64K */
1516 {
1517 INSN_BEQ_R5, /* beq $rt, $R5, $1 */
1518 INSN_J /* j label */
1519 }, /* BR_RANGE_S16M */
1520 {
1521 INSN_BEQ_R5, /* beq $rt, $R5, $1 */
1522 INSN_SETHI_TA, /* sethi $ta, label */
1523 INSN_ORI_TA, /* ori $ta, $ta, label */
1524 INSN_JR_TA /* jr $ta */
1525 } /* BR_RANGE_U4G */
1526 }, /* relax_code_seq */
1527 {
1528 {
1529 {0, 8, 0x7, FALSE},
1530 {0, 0, 0, FALSE}
1531 }, /* BR_RANGE_S256 */
1532 {
1533 {0, 20, 0x1F, FALSE},
1534 {0, 0, 0, FALSE}
1535 }, /* BR_RANGE_S16K */
1536 {
1537 {0, 20, 0x1F, FALSE},
1538 {0, 0, 0, FALSE}
1539 }, /* BR_RANGE_S64K */
1540 {
1541 {0, 20, 0x1F, FALSE},
1542 {0, 0, 0, FALSE}
1543 }, /* BR_RANGE_S16M */
1544 {
1545 {0, 20, 0x1F, FALSE},
1546 {0, 0, 0, FALSE}
1547 } /* BR_RANGE_U4G */
1548 }, /* relax_code_condition */
1549 {2, 4, 8, 8, 16}, /* relax_code_size */
1550 {2, 4, 4, 4, 4}, /* relax_branch_isize */
1551 {
1552 {
1553 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
1554 {0, 0, 0, 0}
1555 }, /* BR_RANGE_S256 */
1556 {
1557 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1558 {0, 0, 0, 0}
1559 }, /* BR_RANGE_S16K */
1560 {
1561 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1562 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1563 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1564 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1565 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1566 {0, 0, 0, 0}
1567 }, /* BR_RANGE_S64K */
1568 {
1569 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1570 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1571 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1572 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1573 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1574 {0, 0, 0, 0}
1575 }, /* BR_RANGE_S16M */
1576 {
1577 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1578 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1579 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1580 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1581 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1582 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1583 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1584 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1585 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1586 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1587 {0, 0, 0, 0}
1588 } /* BR_RANGE_U4G */
1589 } /* relax_fixup */
1590 },
1591 {
1592 "beqs38", /* opcode */
1593 BR_RANGE_S256, /* br_range */
1594 {
1595 {0, 8, 0x7, FALSE},
1596 {0, 0, 0, FALSE}
1597 }, /* cond_field */
1598 {
1599 {
1600 INSN_BEQS38 << 16 /* beq $rt, $R5, label */
1601 }, /* BR_RANGE_S256 */
1602 {
1603 INSN_BEQ_R5 /* beq $rt, $R5, label */
1604 }, /* BR_RANGE_S16K */
1605 {
1606 INSN_BNE_R5, /* bne $rt, $R5, $1 */
1607 INSN_J /* j label */
1608 }, /* BR_RANGE_S64K */
1609 {
1610 INSN_BNE_R5, /* bne $rt, $R5, $1 */
1611 INSN_J /* j label */
1612 }, /* BR_RANGE_S16M */
1613 {
1614 INSN_BNE_R5, /* bne $rt, $R5, $1 */
1615 INSN_SETHI_TA, /* sethi $ta, label */
1616 INSN_ORI_TA, /* ori $ta, $ta, label */
1617 INSN_JR_TA /* jr $ta */
1618 } /* BR_RANGE_U4G */
1619 }, /* relax_code_seq */
1620 {
1621 {
1622 {0, 8, 0x7, FALSE},
1623 {0, 0, 0, FALSE}
1624 }, /* BR_RANGE_S256 */
1625 {
1626 {0, 20, 0x1F, FALSE},
1627 {0, 0, 0, FALSE}
1628 }, /* BR_RANGE_S16K */
1629 {
1630 {0, 20, 0x1F, FALSE},
1631 {0, 0, 0, FALSE}
1632 }, /* BR_RANGE_S64K */
1633 {
1634 {0, 20, 0x1F, FALSE},
1635 {0, 0, 0, FALSE}
1636 }, /* BR_RANGE_S16M */
1637 {
1638 {0, 20, 0x1F, FALSE},
1639 {0, 0, 0, FALSE}
1640 } /* BR_RANGE_U4G */
1641 }, /* relax_code_condition */
1642 {2, 4, 8, 8, 16}, /* relax_code_size */
1643 {2, 4, 4, 4, 4}, /* relax_branch_isize */
1644 {
1645 {
1646 {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
1647 {0, 0, 0, 0}
1648 }, /* BR_RANGE_S256 */
1649 {
1650 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1651 {0, 0, 0, 0}
1652 }, /* BR_RANGE_S16K */
1653 {
1654 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1655 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1656 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1657 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1658 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1659 {0, 0, 0, 0}
1660 }, /* BR_RANGE_S64K */
1661 {
1662 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1663 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1664 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1665 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1666 {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1667 {0, 0, 0, 0}
1668 }, /* BR_RANGE_S16M */
1669 {
1670 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1671 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1672 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1673 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1674 {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1675 {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1676 {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1677 {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1678 {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1679 {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1680 {0, 0, 0, 0}
1681 } /* BR_RANGE_U4G */
1682 } /* relax_fixup */
1683 },
1684 {
1685 "beqc", /* opcode */
1686 BR_RANGE_S256, /* br_range */
1687 {
1688 {0, 8, 0x7FF, TRUE},
1689 {0, 20, 0x1F, FALSE},
1690 {0, 0, 0, FALSE}
1691 }, /* cond_field */
1692 {
1693 {
1694 INSN_BEQC /* beqc $rt, imm11s, label */
1695 }, /* BR_RANGE_S256 */
1696 {
1697 INSN_MOVI_TA, /* movi $ta, imm11s */
1698 INSN_BEQ_TA /* beq $rt, $ta, label */
1699 }, /* BR_RANGE_S16K */
1700 {
1701 INSN_BNEC, /* bnec $rt, imm11s, $1 */
1702 INSN_J /* j label */
1703 }, /* BR_RANGE_S64K */
1704 {
1705 INSN_BNEC, /* bnec $rt, imm11s, $1 */
1706 INSN_J /* j label */
1707 }, /* BR_RANGE_S16M */
1708 {
1709 INSN_BNEC, /* bnec $rt, imm11s, $1 */
1710 INSN_SETHI_TA, /* sethi $ta, label */
1711 INSN_ORI_TA, /* ori $ta, $ta, label */
1712 INSN_JR_TA /* jr $ta */
1713 } /* BR_RANGE_U4G */
1714 }, /* relax_code_seq */
1715 {
1716 {
1717 {0, 8, 0x7FF, TRUE},
1718 {0, 20, 0x1F, FALSE},
1719 {0, 0, 0, FALSE}
1720 }, /* BR_RANGE_S256 */
1721 {
1722 {0, 0, 0xFFFFF, FALSE},
1723 {4, 20, 0x1F, FALSE},
1724 {0, 0, 0, FALSE}
1725 }, /* BR_RANGE_S16K */
1726 {
1727 {0, 8, 0x7FF, FALSE},
1728 {0, 20, 0x1F, FALSE},
1729 {0, 0, 0, FALSE}
1730 }, /* BR_RANGE_S64K */
1731 {
1732 {0, 8, 0x7FF, FALSE},
1733 {0, 20, 0x1F, FALSE},
1734 {0, 0, 0, FALSE}
1735 }, /* BR_RANGE_S16M */
1736 {
1737 {0, 8, 0x7FF, FALSE},
1738 {0, 20, 0x1F, FALSE},
1739 {0, 0, 0, FALSE}
1740 } /* BR_RANGE_U4G */
1741 }, /* relax_code_condition */
1742 {4, 8, 8, 8, 16}, /* relax_code_size */
1743 {4, 4, 4, 4, 4}, /* relax_branch_isize */
1744 {
1745 {
1746 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
1747 {0, 0, 0, 0}
1748 }, /* BR_RANGE_S256 */
1749 {
1750 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1751 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP7},
1752 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1753 {0, 0, 0, 0}
1754 }, /* BR_RANGE_S16K */
1755 {
1756 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
1757 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1758 {0, 0, 0, 0}
1759 }, /* BR_RANGE_S64K */
1760 {
1761 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
1762 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1763 {0, 0, 0, 0}
1764 }, /* BR_RANGE_S16M */
1765 {
1766 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
1767 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1768 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
1769 {12, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
1770 {0, 0, 0, 0}
1771 } /* BR_RANGE_U4G */
1772 } /* relax_fixup */
1773 },
1774 {
1775 "bnec", /* opcode */
1776 BR_RANGE_S256, /* br_range */
1777 {
1778 {0, 8, 0x7FF, TRUE},
1779 {0, 20, 0x1F, FALSE},
1780 {0, 0, 0, FALSE}
1781 }, /* cond_field */
1782 {
1783 {
1784 INSN_BNEC /* bnec $rt, imm11s, label */
1785 }, /* BR_RANGE_S256 */
1786 {
1787 INSN_MOVI_TA, /* movi $ta, imm11s */
1788 INSN_BNE_TA /* bne $rt, $ta, label */
1789 }, /* BR_RANGE_S16K */
1790 {
1791 INSN_BEQC, /* beqc $rt, imm11s, $1 */
1792 INSN_J /* j label */
1793 }, /* BR_RANGE_S64K */
1794 {
1795 INSN_BEQC, /* beqc $rt, imm11s, $1 */
1796 INSN_J /* j label */
1797 }, /* BR_RANGE_S16M */
1798 {
1799 INSN_BEQC, /* beqc $rt, imm11s, $1 */
1800 INSN_SETHI_TA, /* sethi $ta, label */
1801 INSN_ORI_TA, /* ori $ta, $ta, label */
1802 INSN_JR_TA /* jr $ta */
1803 } /* BR_RANGE_U4G */
1804 }, /* relax_code_seq */
1805 {
1806 {
1807 {0, 8, 0x7FF, TRUE},
1808 {0, 20, 0x1F, FALSE},
1809 {0, 0, 0, FALSE}
1810 }, /* BR_RANGE_S256 */
1811 {
1812 {0, 0, 0xFFFFF, FALSE},
1813 {4, 20, 0x1F, FALSE},
1814 {0, 0, 0, FALSE}
1815 }, /* BR_RANGE_S16K */
1816 {
1817 {0, 8, 0x7FF, FALSE},
1818 {0, 20, 0x1F, FALSE},
1819 {0, 0, 0, FALSE}
1820 }, /* BR_RANGE_S64K */
1821 {
1822 {0, 8, 0x7FF, FALSE},
1823 {0, 20, 0x1F, FALSE},
1824 {0, 0, 0, FALSE}
1825 }, /* BR_RANGE_S16M */
1826 {
1827 {0, 8, 0x7FF, FALSE},
1828 {0, 20, 0x1F, FALSE},
1829 {0, 0, 0, FALSE}
1830 } /* BR_RANGE_U4G */
1831 }, /* relax_code_condition */
1832 {4, 8, 8, 8, 16}, /* relax_code_size */
1833 {4, 4, 4, 4, 4}, /* relax_branch_isize */
1834 {
1835 {
1836 {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
1837 {0, 0, 0, 0}
1838 }, /* BR_RANGE_S256 */
1839 {
1840 {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1841 {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP7},
1842 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1843 {0, 0, 0, 0}
1844 }, /* BR_RANGE_S16K */
1845 {
1846 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
1847 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1848 {0, 0, 0, 0}
1849 }, /* BR_RANGE_S64K */
1850 {
1851 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
1852 {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1853 {0, 0, 0, 0}
1854 }, /* BR_RANGE_S16M */
1855 {
1856 {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
1857 {4, 4, 0, BFD_RELOC_NDS32_HI20},
1858 {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
1859 {12, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
1860 {0, 0, 0, 0}
1861 } /* BR_RANGE_U4G */
1862 } /* relax_fixup */
1863 }
1864 };
1865
1866 /* GAS definitions for command-line options. */
1868 enum options
1869 {
1870 OPTION_BIG = OPTION_MD_BASE,
1871 OPTION_LITTLE,
1872 OPTION_TURBO,
1873 OPTION_PIC,
1874 OPTION_RELAX_FP_AS_GP_OFF,
1875 OPTION_RELAX_B2BB_ON,
1876 OPTION_RELAX_ALL_OFF,
1877 OPTION_OPTIMIZE,
1878 OPTION_OPTIMIZE_SPACE
1879 };
1880
1881 const char *md_shortopts = "m:O:";
1882 struct option md_longopts[] =
1883 {
1884 {"O1", no_argument, NULL, OPTION_OPTIMIZE},
1885 {"Os", no_argument, NULL, OPTION_OPTIMIZE_SPACE},
1886 {"big", no_argument, NULL, OPTION_BIG},
1887 {"little", no_argument, NULL, OPTION_LITTLE},
1888 {"EB", no_argument, NULL, OPTION_BIG},
1889 {"EL", no_argument, NULL, OPTION_LITTLE},
1890 {"meb", no_argument, NULL, OPTION_BIG},
1891 {"mel", no_argument, NULL, OPTION_LITTLE},
1892 {"mall-ext", no_argument, NULL, OPTION_TURBO},
1893 {"mext-all", no_argument, NULL, OPTION_TURBO},
1894 {"mpic", no_argument, NULL, OPTION_PIC},
1895 /* Relaxation related options. */
1896 {"mno-fp-as-gp-relax", no_argument, NULL, OPTION_RELAX_FP_AS_GP_OFF},
1897 {"mb2bb", no_argument, NULL, OPTION_RELAX_B2BB_ON},
1898 {"mno-all-relax", no_argument, NULL, OPTION_RELAX_ALL_OFF},
1899 {NULL, no_argument, NULL, 0}
1900 };
1901
1902 size_t md_longopts_size = sizeof (md_longopts);
1903
1904 struct nds32_parse_option_table
1905 {
1906 const char *name; /* Option string. */
1907 const char *help; /* Help description. */
1908 int (*func) (const char *arg); /* How to parse it. */
1909 };
1910
1911
1912 /* The value `-1' represents this option has *NOT* been set. */
1913 #ifdef NDS32_DEFAULT_ARCH_NAME
1914 static const char* nds32_arch_name = NDS32_DEFAULT_ARCH_NAME;
1915 #else
1916 static const char* nds32_arch_name = "v3";
1917 #endif
1918 static int nds32_baseline = -1;
1919 static int nds32_gpr16 = -1;
1920 static int nds32_fpu_sp_ext = -1;
1921 static int nds32_fpu_dp_ext = -1;
1922 static int nds32_freg = -1;
1923 static int nds32_abi = -1;
1924
1925 /* Record ELF flags */
1926 static int nds32_elf_flags = 0;
1927 static int nds32_fpu_com = 0;
1928
1929 static int nds32_parse_arch (const char *str);
1930 static int nds32_parse_baseline (const char *str);
1931 static int nds32_parse_freg (const char *str);
1932 static int nds32_parse_abi (const char *str);
1933
1934 static struct nds32_parse_option_table parse_opts [] =
1935 {
1936 {"arch=", N_("<arch name>\t Assemble for architecture <arch name>\n\
1937 <arch name> could be\n\
1938 v3, v3j, v3m, v3f, v3s, "\
1939 "v2, v2j, v2f, v2s"), nds32_parse_arch},
1940 {"baseline=", N_("<baseline>\t Assemble for baseline <baseline>\n\
1941 <baseline> could be v2, v3, v3m"),
1942 nds32_parse_baseline},
1943 {"fpu-freg=", N_("<freg>\t Specify a FPU configuration\n\
1944 <freg>\n\
1945 0: 8 SP / 4 DP registers\n\
1946 1: 16 SP / 8 DP registers\n\
1947 2: 32 SP / 16 DP registers\n\
1948 3: 32 SP / 32 DP registers"), nds32_parse_freg},
1949 {"abi=", N_("<abi>\t Specify a abi version\n\
1950 <abi> could be v1, v2, v2fp, v2fpp"), nds32_parse_abi},
1951 {NULL, NULL, NULL}
1952 };
1953
1954 static int nds32_mac = 1;
1955 static int nds32_div = 1;
1956 static int nds32_16bit_ext = 1;
1957 static int nds32_dx_regs = 1;
1958 static int nds32_perf_ext = 1;
1959 static int nds32_perf_ext2 = 1;
1960 static int nds32_string_ext = 1;
1961 static int nds32_audio_ext = 1;
1962 static int nds32_fpu_fma = 0;
1963 static int nds32_pic = 0;
1964 static int nds32_relax_fp_as_gp = 1;
1965 static int nds32_relax_b2bb = 0;
1966 static int nds32_relax_all = 1;
1967 struct nds32_set_option_table
1968 {
1969 const char *name; /* Option string. */
1970 const char *help; /* Help description. */
1971 int *var; /* Variable to be set. */
1972 int value; /* Value to set. */
1973 };
1974
1975 /* The option in this group has both Enable/Disable settings.
1976 Just list on here. */
1977
1978 static struct nds32_set_option_table toggle_opts [] =
1979 {
1980 {"mac", N_("Multiply instructions support"), &nds32_mac, 1},
1981 {"div", N_("Divide instructions support"), &nds32_div, 1},
1982 {"16bit-ext", N_("16-bit extension"), &nds32_16bit_ext, 1},
1983 {"dx-regs", N_("d0/d1 registers"), &nds32_dx_regs, 1},
1984 {"perf-ext", N_("Performance extension"), &nds32_perf_ext, 1},
1985 {"perf2-ext", N_("Performance extension 2"), &nds32_perf_ext2, 1},
1986 {"string-ext", N_("String extension"), &nds32_string_ext, 1},
1987 {"reduced-regs", N_("Reduced Register configuration (GPR16) option"), &nds32_gpr16, 1},
1988 {"audio-isa-ext", N_("AUDIO ISA extension"), &nds32_audio_ext, 1},
1989 {"fpu-sp-ext", N_("FPU SP extension"), &nds32_fpu_sp_ext, 1},
1990 {"fpu-dp-ext", N_("FPU DP extension"), &nds32_fpu_dp_ext, 1},
1991 {"fpu-fma", N_("FPU fused-multiply-add instructions"), &nds32_fpu_fma, 1},
1992 {NULL, NULL, NULL, 0}
1993 };
1994
1995
1996 /* GAS declarations. */
1998
1999 /* This is the callback for nds32-asm.c to parse operands. */
2000 int
2001 nds32_asm_parse_operand (struct nds32_asm_desc *pdesc,
2002 struct nds32_asm_insn *pinsn,
2003 char **pstr, int64_t *value);
2004
2005
2006 struct nds32_asm_desc asm_desc;
2008
2009 /* md_after_parse_args ()
2010
2011 GAS will call md_after_parse_args whenever it is defined.
2012 This function checks any conflicting options specified. */
2013
2014 void
2015 nds32_after_parse_args (void)
2016 {
2017 /* If -march option is not used in command-line, set the value of option
2018 variable according to NDS32_DEFAULT_ARCH_NAME. */
2019 nds32_parse_arch (nds32_arch_name);
2020 }
2021
2022 /* This function is called when printing usage message (--help). */
2023
2024 void
2025 md_show_usage (FILE *stream)
2026 {
2027 struct nds32_parse_option_table *coarse_tune;
2028 struct nds32_set_option_table *fine_tune;
2029
2030 fprintf (stream, _("\n NDS32-specific assembler options:\n"));
2031 fprintf (stream, _("\
2032 -O1, Optimize for performance\n\
2033 -Os Optimize for space\n"));
2034 fprintf (stream, _("\
2035 -EL, -mel or -little Produce little endian output\n\
2036 -EB, -meb or -big Produce big endian output\n\
2037 -mpic Generate PIC\n\
2038 -mno-fp-as-gp-relax Suppress fp-as-gp relaxation for this file\n\
2039 -mb2bb-relax Back-to-back branch optimization\n\
2040 -mno-all-relax Suppress all relaxation for this file\n"));
2041
2042 for (coarse_tune = parse_opts; coarse_tune->name != NULL; coarse_tune++)
2043 {
2044 if (coarse_tune->help != NULL)
2045 fprintf (stream, _(" -m%s%s\n"),
2046 coarse_tune->name, _(coarse_tune->help));
2047 }
2048
2049 for (fine_tune = toggle_opts; fine_tune->name != NULL; fine_tune++)
2050 {
2051 if (fine_tune->help != NULL)
2052 fprintf (stream, _(" -m[no-]%-17sEnable/Disable %s\n"),
2053 fine_tune->name, _(fine_tune->help));
2054 }
2055
2056 fprintf (stream, _("\
2057 -mall-ext Turn on all extensions and instructions support\n"));
2058 }
2059
2060 void
2061 nds32_frag_init (fragS *fragp)
2062 {
2063 fragp->tc_frag_data.flag = 0;
2064 fragp->tc_frag_data.opcode = NULL;
2065 fragp->tc_frag_data.fixup = NULL;
2066 }
2067
2068
2069
2071 /* This function reads an expression from a C string and returns a pointer past
2072 the end of the expression. */
2073
2074 static char *
2075 parse_expression (char *str, expressionS *exp)
2076 {
2077 char *s;
2078 char *tmp;
2079
2080 tmp = input_line_pointer; /* Save line pointer. */
2081 input_line_pointer = str;
2082 expression (exp);
2083 s = input_line_pointer;
2084 input_line_pointer = tmp; /* Restore line pointer. */
2085
2086 return s; /* Return pointer to where parsing stopped. */
2087 }
2088
2089 void
2090 nds32_start_line_hook (void)
2091 {
2092 }
2093
2094 /*
2096 * Pseudo opcodes
2097 */
2098
2099 typedef void (*nds32_pseudo_opcode_func) (int argc, char *argv[], unsigned int pv);
2100 struct nds32_pseudo_opcode
2101 {
2102 const char *opcode;
2103 int argc;
2104 nds32_pseudo_opcode_func proc;
2105 unsigned int pseudo_val;
2106
2107 /* Some instructions are not pseudo opcode, but they might still be
2108 expanded or changed with other instruction combination for some
2109 conditions. We also apply this structure to assist such work.
2110
2111 For example, if the distance of branch target '.L0' is larger than
2112 imm8s<<1 range,
2113
2114 the instruction:
2115
2116 beqzs8 .L0
2117
2118 will be transformed into:
2119
2120 bnezs8 .LCB0
2121 j .L0
2122 .LCB0:
2123
2124 However, sometimes we do not want assembler to do such changes
2125 because compiler knows how to generate corresponding instruction sequence.
2126 Use this field to indicate that this opcode is also a physical instruction.
2127 If the flag 'verbatim' is nozero and this opcode
2128 is a physical instruction, we should not expand it. */
2129 int physical_op;
2130 };
2131 #define PV_DONT_CARE 0
2132
2133 static struct hash_control *nds32_pseudo_opcode_hash = NULL;
2134
2135 static int
2136 builtin_isreg (const char *s, const char *x ATTRIBUTE_UNUSED)
2137 {
2138 if (s [0] == '$' && hash_find (nds32_gprs_hash, (s + 1)))
2139 return 1;
2140 return 0;
2141 }
2142
2143 static int
2144 builtin_regnum (const char *s, const char *x ATTRIBUTE_UNUSED)
2145 {
2146 struct nds32_keyword *k;
2147 if (*s != '$')
2148 return -1;
2149 s++;
2150 k = hash_find (nds32_gprs_hash, s);
2151
2152 if (k == NULL)
2153 return -1;
2154
2155 return k->value;
2156 }
2157
2158 static int
2159 builtin_addend (const char *s, char *x ATTRIBUTE_UNUSED)
2160 {
2161 const char *ptr = s;
2162
2163 while (*ptr != '+' && *ptr != '-' && *ptr)
2164 ++ptr;
2165
2166 if (*ptr == 0)
2167 return 0;
2168 else
2169 return strtol (ptr, NULL, 0);
2170 }
2171
2172 static void
2173 md_assemblef (const char *format, ...)
2174 {
2175 /* FIXME: hope this is long enough. */
2176 char line[1024];
2177 va_list ap;
2178 unsigned int r;
2179
2180 va_start (ap, format);
2181 r = vsnprintf (line, sizeof (line), format, ap);
2182 md_assemble (line);
2183
2184 gas_assert (r < sizeof (line));
2185 }
2186
2187 /* Some prototypes here, since some op may use another op. */
2188 static void do_pseudo_li_internal (const char *rt, int imm32s);
2189 static void do_pseudo_move_reg_internal (char *dst, char *src);
2190
2191 static void
2192 do_pseudo_b (int argc ATTRIBUTE_UNUSED, char *argv[],
2193 unsigned int pv ATTRIBUTE_UNUSED)
2194 {
2195 char *arg_label = argv[0];
2196 relaxing = TRUE;
2197 /* b label */
2198 if (nds32_pic && strstr (arg_label, "@PLT"))
2199 {
2200 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2201 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2202 md_assemble ((char *) "add $ta,$ta,$gp");
2203 md_assemble ((char *) "jr $ta");
2204 }
2205 else
2206 {
2207 md_assemblef ("j %s", arg_label);
2208 }
2209 relaxing = FALSE;
2210 }
2211
2212 static void
2213 do_pseudo_bal (int argc ATTRIBUTE_UNUSED, char *argv[],
2214 unsigned int pv ATTRIBUTE_UNUSED)
2215 {
2216 char *arg_label = argv[0];
2217 relaxing = TRUE;
2218 /* bal|call label */
2219 if (nds32_pic
2220 && (strstr (arg_label, "@GOT") || strstr (arg_label, "@PLT")))
2221 {
2222 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2223 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2224 md_assemble ((char *) "add $ta,$ta,$gp");
2225 md_assemble ((char *) "jral $ta");
2226 }
2227 else
2228 {
2229 md_assemblef ("jal %s", arg_label);
2230 }
2231 relaxing = FALSE;
2232 }
2233
2234 static void
2235 do_pseudo_bge (int argc ATTRIBUTE_UNUSED, char *argv[],
2236 unsigned int pv ATTRIBUTE_UNUSED)
2237 {
2238 /* rt5, ra5, label */
2239 md_assemblef ("slt $ta,%s,%s", argv[0], argv[1]);
2240 md_assemblef ("beqz $ta,%s", argv[2]);
2241 }
2242
2243 static void
2244 do_pseudo_bges (int argc ATTRIBUTE_UNUSED, char *argv[],
2245 unsigned int pv ATTRIBUTE_UNUSED)
2246 {
2247 /* rt5, ra5, label */
2248 md_assemblef ("slts $ta,%s,%s", argv[0], argv[1]);
2249 md_assemblef ("beqz $ta,%s", argv[2]);
2250 }
2251
2252 static void
2253 do_pseudo_bgt (int argc ATTRIBUTE_UNUSED, char *argv[],
2254 unsigned int pv ATTRIBUTE_UNUSED)
2255 {
2256 /* bgt rt5, ra5, label */
2257 md_assemblef ("slt $ta,%s,%s", argv[1], argv[0]);
2258 md_assemblef ("bnez $ta,%s", argv[2]);
2259 }
2260
2261 static void
2262 do_pseudo_bgts (int argc ATTRIBUTE_UNUSED, char *argv[],
2263 unsigned int pv ATTRIBUTE_UNUSED)
2264 {
2265 /* bgt rt5, ra5, label */
2266 md_assemblef ("slts $ta,%s,%s", argv[1], argv[0]);
2267 md_assemblef ("bnez $ta,%s", argv[2]);
2268 }
2269
2270 static void
2271 do_pseudo_ble (int argc ATTRIBUTE_UNUSED, char *argv[],
2272 unsigned int pv ATTRIBUTE_UNUSED)
2273 {
2274 /* bgt rt5, ra5, label */
2275 md_assemblef ("slt $ta,%s,%s", argv[1], argv[0]);
2276 md_assemblef ("beqz $ta,%s", argv[2]);
2277 }
2278
2279 static void
2280 do_pseudo_bles (int argc ATTRIBUTE_UNUSED, char *argv[],
2281 unsigned int pv ATTRIBUTE_UNUSED)
2282 {
2283 /* bgt rt5, ra5, label */
2284 md_assemblef ("slts $ta,%s,%s", argv[1], argv[0]);
2285 md_assemblef ("beqz $ta,%s", argv[2]);
2286 }
2287
2288 static void
2289 do_pseudo_blt (int argc ATTRIBUTE_UNUSED, char *argv[],
2290 unsigned int pv ATTRIBUTE_UNUSED)
2291 {
2292 /* rt5, ra5, label */
2293 md_assemblef ("slt $ta,%s,%s", argv[0], argv[1]);
2294 md_assemblef ("bnez $ta,%s", argv[2]);
2295 }
2296
2297 static void
2298 do_pseudo_blts (int argc ATTRIBUTE_UNUSED, char *argv[],
2299 unsigned int pv ATTRIBUTE_UNUSED)
2300 {
2301 /* rt5, ra5, label */
2302 md_assemblef ("slts $ta,%s,%s", argv[0], argv[1]);
2303 md_assemblef ("bnez $ta,%s", argv[2]);
2304 }
2305
2306 static void
2307 do_pseudo_br (int argc ATTRIBUTE_UNUSED, char *argv[],
2308 unsigned int pv ATTRIBUTE_UNUSED)
2309 {
2310 md_assemblef ("jr %s", argv[0]);
2311 }
2312
2313 static void
2314 do_pseudo_bral (int argc, char *argv[],
2315 unsigned int pv ATTRIBUTE_UNUSED)
2316 {
2317 if (argc == 1)
2318 md_assemblef ("jral $lp,%s", argv[0]);
2319 else
2320 md_assemblef ("jral %s,%s", argv[0], argv[1]);
2321 }
2322
2323 static void
2324 do_pseudo_la_internal (const char *arg_reg, char *arg_label,
2325 const char *line)
2326 {
2327 expressionS exp;
2328
2329 parse_expression (arg_label, &exp);
2330 if (exp.X_op != O_symbol)
2331 {
2332 as_bad (_("la must use with symbol. '%s'"), line);
2333 return;
2334 }
2335
2336 relaxing = TRUE;
2337 /* rt, label */
2338 if (!nds32_pic && !strstr(arg_label, "@"))
2339 {
2340 md_assemblef ("sethi %s,hi20(%s)", arg_reg, arg_label);
2341 md_assemblef ("ori %s,%s,lo12(%s)", arg_reg, arg_reg, arg_label);
2342 }
2343 else if (strstr (arg_label, "@TPOFF"))
2344 {
2345 /* la $rt, sym@TPOFF */
2346 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2347 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2348 md_assemblef ("add %s,$ta,%s", arg_reg, TLS_REG);
2349 }
2350 else if (strstr(arg_label, "@GOTTPOFF"))
2351 {
2352 /* la $rt, sym@GOTTPOFF*/
2353 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2354 md_assemblef ("lwi $ta,[$ta+lo12(%s)]", arg_label);
2355 md_assemblef ("add %s,$ta,%s", arg_reg, TLS_REG);
2356 }
2357 else if (nds32_pic && ((strstr (arg_label, "@PLT")
2358 || strstr (arg_label, "@GOTOFF"))))
2359 {
2360 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2361 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2362 md_assemblef ("add %s,$ta,$gp", arg_reg);
2363 }
2364 else if (nds32_pic && strstr (arg_label, "@GOT"))
2365 {
2366 long addend = builtin_addend (arg_label, NULL);
2367
2368 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2369 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2370 md_assemblef ("lw %s,[$gp+$ta]", arg_reg);
2371 if (addend != 0)
2372 {
2373 if (addend < 0x4000 && addend >= -0x4000)
2374 {
2375 md_assemblef ("addi %s,%s,%d", arg_reg, arg_reg, addend);
2376 }
2377 else
2378 {
2379 do_pseudo_li_internal ("$ta", addend);
2380 md_assemblef ("add %s,$ta,%s", arg_reg, arg_reg);
2381 }
2382 }
2383 }
2384 else
2385 as_bad (_("need PIC qualifier with symbol. '%s'"), line);
2386 relaxing = FALSE;
2387 }
2388
2389 static void
2390 do_pseudo_la (int argc ATTRIBUTE_UNUSED, char *argv[],
2391 unsigned int pv ATTRIBUTE_UNUSED)
2392 {
2393 do_pseudo_la_internal (argv[0], argv[1], argv[argc]);
2394 }
2395
2396 static void
2397 do_pseudo_li_internal (const char *rt, int imm32s)
2398 {
2399 if (enable_16bit && imm32s <= 0xf && imm32s >= -0x10)
2400 md_assemblef ("movi55 %s,%d", rt, imm32s);
2401 else if (imm32s <= 0x7ffff && imm32s >= -0x80000)
2402 md_assemblef ("movi %s,%d", rt, imm32s);
2403 else if ((imm32s & 0xfff) == 0)
2404 md_assemblef ("sethi %s,hi20(%d)", rt, imm32s);
2405 else
2406 {
2407 md_assemblef ("sethi %s,hi20(%d)", rt, imm32s);
2408 md_assemblef ("ori %s,%s,lo12(%d)", rt, rt, imm32s);
2409 }
2410 }
2411
2412 static void
2413 do_pseudo_li (int argc ATTRIBUTE_UNUSED, char *argv[],
2414 unsigned int pv ATTRIBUTE_UNUSED)
2415 {
2416 /* Validate argv[1] for constant expression. */
2417 expressionS exp;
2418
2419 parse_expression (argv[1], &exp);
2420 if (exp.X_op != O_constant)
2421 {
2422 as_bad (_("Operand is not a constant. `%s'"), argv[argc]);
2423 return;
2424 }
2425
2426 do_pseudo_li_internal (argv[0], exp.X_add_number);
2427 }
2428
2429 static void
2430 do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED, char *argv[],
2431 unsigned int pv)
2432 {
2433 char ls = 'r';
2434 char size = 'x';
2435 const char *sign = "";
2436
2437 /* Prepare arguments for various load/store. */
2438 sign = (pv & 0x10) ? "s" : "";
2439 ls = (pv & 0x80000000) ? 's' : 'l';
2440 switch (pv & 0x3)
2441 {
2442 case 0: size = 'b'; break;
2443 case 1: size = 'h'; break;
2444 case 2: size = 'w'; break;
2445 }
2446
2447 if (ls == 's' || size == 'w')
2448 sign = "";
2449
2450 if (builtin_isreg (argv[1], NULL))
2451 {
2452 /* lwi */
2453 md_assemblef ("%c%ci %s,[%s]", ls, size, argv[0], argv[1]);
2454 }
2455 else if (!nds32_pic)
2456 {
2457 relaxing = TRUE;
2458 if (strstr (argv[1], "@TPOFF"))
2459 {
2460 /* ls.w $rt, sym@TPOFF */
2461 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2462 md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
2463 md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], TLS_REG);
2464 }
2465 else if (strstr (argv[1], "@GOTTPOFF"))
2466 {
2467 /* ls.w $rt, sym@GOTTPOFF */
2468 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2469 md_assemblef ("lwi $ta,[$ta+lo12(%s)]", argv[1]);
2470 md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], TLS_REG);
2471 }
2472 else
2473 {
2474 /* lwi */
2475 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2476 md_assemblef ("%c%c%si %s,[$ta+lo12(%s)]", ls, size, sign, argv[0], argv[1]);
2477 }
2478 relaxing = FALSE;
2479 }
2480 else
2481 {
2482 relaxing = TRUE;
2483 /* PIC code. */
2484 if (strstr (argv[1], "@GOTOFF"))
2485 {
2486 /* lw */
2487 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2488 md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
2489 md_assemblef ("%c%c%s %s,[$ta+$gp]", ls, size, sign, argv[0]);
2490 }
2491 else if (strstr (argv[1], "@GOT"))
2492 {
2493 long addend = builtin_addend (argv[1], NULL);
2494 /* lw */
2495 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2496 md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
2497 md_assemble ((char *) "lw $ta,[$gp+$ta]"); /* Load address word. */
2498 if (addend < 0x10000 && addend >= -0x10000)
2499 {
2500 md_assemblef ("%c%c%si %s,[$ta+(%d)]", ls, size, sign, argv[0], addend);
2501 }
2502 else
2503 {
2504 /* lw */
2505 do_pseudo_li_internal (argv[0], addend);
2506 md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], argv[0]);
2507 }
2508 }
2509 else
2510 {
2511 as_bad (_("needs @GOT or @GOTOFF. %s"), argv[argc]);
2512 }
2513 relaxing = FALSE;
2514 }
2515 }
2516
2517 static void
2518 do_pseudo_ls_bhwp (int argc ATTRIBUTE_UNUSED, char *argv[],
2519 unsigned int pv)
2520 {
2521 char *arg_rt = argv[0];
2522 char *arg_label = argv[1];
2523 char *arg_inc = argv[2];
2524 char ls = 'r';
2525 char size = 'x';
2526 const char *sign = "";
2527
2528 /* Prepare arguments for various load/store. */
2529 sign = (pv & 0x10) ? "s" : "";
2530 ls = (pv & 0x80000000) ? 's' : 'l';
2531 switch (pv & 0x3)
2532 {
2533 case 0: size = 'b'; break;
2534 case 1: size = 'h'; break;
2535 case 2: size = 'w'; break;
2536 }
2537
2538 if (ls == 's' || size == 'w')
2539 sign = "";
2540
2541 do_pseudo_la_internal ("$ta", arg_label, argv[argc]);
2542 md_assemblef ("%c%c%si.bi %s,[$ta],%s", ls, size, sign, arg_rt, arg_inc);
2543 }
2544
2545 static void
2546 do_pseudo_ls_bhwpc (int argc ATTRIBUTE_UNUSED, char *argv[],
2547 unsigned int pv)
2548 {
2549 char *arg_rt = argv[0];
2550 char *arg_inc = argv[1];
2551 char ls = 'r';
2552 char size = 'x';
2553 const char *sign = "";
2554
2555 /* Prepare arguments for various load/store. */
2556 sign = (pv & 0x10) ? "s" : "";
2557 ls = (pv & 0x80000000) ? 's' : 'l';
2558 switch (pv & 0x3)
2559 {
2560 case 0: size = 'b'; break;
2561 case 1: size = 'h'; break;
2562 case 2: size = 'w'; break;
2563 }
2564
2565 if (ls == 's' || size == 'w')
2566 sign = "";
2567
2568 md_assemblef ("%c%c%si.bi %s,[$ta],%s", ls, size, sign, arg_rt, arg_inc);
2569 }
2570
2571 static void
2572 do_pseudo_ls_bhwi (int argc ATTRIBUTE_UNUSED, char *argv[],
2573 unsigned int pv)
2574 {
2575 char ls = 'r';
2576 char size = 'x';
2577 const char *sign = "";
2578
2579 /* Prepare arguments for various load/store. */
2580 sign = (pv & 0x10) ? "s" : "";
2581 ls = (pv & 0x80000000) ? 's' : 'l';
2582 switch (pv & 0x3)
2583 {
2584 case 0: size = 'b'; break;
2585 case 1: size = 'h'; break;
2586 case 2: size = 'w'; break;
2587 }
2588
2589 if (ls == 's' || size == 'w')
2590 sign = "";
2591
2592 md_assemblef ("%c%c%si.bi %s,%s,%s",
2593 ls, size, sign, argv[0], argv[1], argv[2]);
2594 }
2595
2596 static void
2597 do_pseudo_move_reg_internal (char *dst, char *src)
2598 {
2599 if (enable_16bit)
2600 md_assemblef ("mov55 %s,%s", dst, src);
2601 else
2602 md_assemblef ("ori %s,%s,0", dst, src);
2603 }
2604
2605 static void
2606 do_pseudo_move (int argc ATTRIBUTE_UNUSED, char *argv[],
2607 unsigned int pv ATTRIBUTE_UNUSED)
2608 {
2609 expressionS exp;
2610
2611 if (builtin_isreg (argv[1], NULL))
2612 do_pseudo_move_reg_internal (argv[0], argv[1]);
2613 else
2614 {
2615 parse_expression (argv[1], &exp);
2616 if (exp.X_op == O_constant)
2617 /* move $rt, imm -> li $rt, imm */
2618 do_pseudo_li_internal (argv[0], exp.X_add_number);
2619 else
2620 /* l.w $rt, var -> l.w $rt, var */
2621 do_pseudo_ls_bhw (argc, argv, 2);
2622 }
2623 }
2624
2625 static void
2626 do_pseudo_neg (int argc ATTRIBUTE_UNUSED, char *argv[],
2627 unsigned int pv ATTRIBUTE_UNUSED)
2628 {
2629 /* Instead of "subri". */
2630 md_assemblef ("subri %s,%s,0", argv[0], argv[1]);
2631 }
2632
2633 static void
2634 do_pseudo_not (int argc ATTRIBUTE_UNUSED, char *argv[],
2635 unsigned int pv ATTRIBUTE_UNUSED)
2636 {
2637 md_assemblef ("nor %s,%s,%s", argv[0], argv[1], argv[1]);
2638 }
2639
2640 static void
2641 do_pseudo_pushpopm (int argc, char *argv[],
2642 unsigned int pv ATTRIBUTE_UNUSED)
2643 {
2644 /* posh/pop $ra, $rb */
2645 /* SMW.{b | a}{i | d}{m?} Rb, [Ra], Re, Enable4 */
2646 int rb, re, ra, en4;
2647 int i;
2648 const char *opc = "pushpopm";
2649
2650 if (argc == 3)
2651 as_bad ("'pushm/popm $ra5, $rb5, $label' is deprecated. "
2652 "Only 'pushm/popm $ra5' is supported now. %s", argv[argc]);
2653 else if (argc == 1)
2654 as_bad ("'pushm/popm $ra5, $rb5'. %s\n", argv[argc]);
2655
2656 if (strstr (argv[argc], "pop") == argv[argc])
2657 opc = "lmw.bim";
2658 else if (strstr (argv[argc], "push") == argv[argc])
2659 opc = "smw.adm";
2660 else
2661 as_fatal ("nds32-as internal error. %s", argv[argc]);
2662
2663 rb = builtin_regnum (argv[0], NULL);
2664 re = builtin_regnum (argv[1], NULL);
2665
2666 if (re < rb)
2667 {
2668 as_warn ("$rb should not be smaller than $ra. %s", argv[argc]);
2669 /* Swap to right order. */
2670 ra = re;
2671 re = rb;
2672 rb = ra;
2673 }
2674
2675 /* Build enable4 mask. */
2676 en4 = 0;
2677 if (re >= 28 || rb >= 28)
2678 {
2679 for (i = (rb >= 28? rb: 28); i <= re; i++)
2680 en4 |= 1 << (3 - (i - 28));
2681 }
2682
2683 /* Adjust $re, $rb. */
2684 if (rb >= 28)
2685 rb = re = 31;
2686 else if (nds32_gpr16 != 1 && re >= 28)
2687 re = 27;
2688
2689 /* Reduce register. */
2690 if (nds32_gpr16 && re > 10 && !(rb == 31 && re == 31))
2691 {
2692 if (re >= 15 && strstr(opc, "smw") != NULL)
2693 md_assemblef ("%s $r15,[$sp],$r15,%d", opc, en4);
2694 if (rb <= 10)
2695 md_assemblef ("%s $r%d,[$sp],$r10, 0x0", opc, rb);
2696 if (re >= 15 && strstr(opc, "lmw") != NULL)
2697 md_assemblef ("%s $r15,[$sp],$r15,%d", opc, en4);
2698 }
2699 else
2700 md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc, rb, re, en4);
2701 }
2702
2703 static void
2704 do_pseudo_pushpop (int argc, char *argv[],
2705 unsigned int pv ATTRIBUTE_UNUSED)
2706 {
2707 /* push/pop $ra5, $label=$sp */
2708 char *argvm[3];
2709
2710 if (argc == 2)
2711 as_bad ("'push/pop $ra5, rb5' is deprecated. "
2712 "Only 'push/pop $ra5' is supported now. %s", argv[argc]);
2713
2714 argvm[0] = argv[0];
2715 argvm[1] = argv[0];
2716 argvm[2] = argv[argc];
2717 do_pseudo_pushpopm (2, argvm, PV_DONT_CARE);
2718 }
2719
2720 static void
2721 do_pseudo_v3push (int argc ATTRIBUTE_UNUSED, char *argv[],
2722 unsigned int pv ATTRIBUTE_UNUSED)
2723 {
2724 md_assemblef ("push25 %s,%s", argv[0], argv[1]);
2725 }
2726
2727 static void
2728 do_pseudo_v3pop (int argc ATTRIBUTE_UNUSED, char *argv[],
2729 unsigned int pv ATTRIBUTE_UNUSED)
2730 {
2731 md_assemblef ("pop25 %s,%s", argv[0], argv[1]);
2732 }
2733
2734 /* pv == 0, parsing "push.s" pseudo instruction operands.
2735 pv != 0, parsing "pop.s" pseudo instruction operands. */
2736
2737 static void
2738 do_pseudo_pushpop_stack (int argc, char *argv[],
2739 unsigned int pv)
2740 {
2741 /* push.s Rb,Re,{$fp $gp $lp $sp} ==> smw.adm Rb,[$sp],Re,Eable4 */
2742 /* pop.s Rb,Re,{$fp $gp $lp $sp} ==> lmw.bim Rb,[$sp],Re,Eable4 */
2743
2744 int rb, re;
2745 int en4;
2746 int last_arg_index;
2747 const char *opc = (pv == 0) ? "smw.adm" : "lmw.bim";
2748
2749 rb = re = 0;
2750
2751 if (argc == 1)
2752 {
2753 /* argc=1, operands pattern: { $fp $gp $lp $sp } */
2754
2755 /* Set register number Rb = Re = $sp = $r31. */
2756 rb = re = 31;
2757 }
2758 else if (argc == 2 || argc == 3)
2759 {
2760 /* argc=2, operands pattern: Rb, Re */
2761 /* argc=3, operands pattern: Rb, Re, { $fp $gp $lp $sp } */
2762
2763 /* Get register number in integer. */
2764 rb = builtin_regnum (argv[0], NULL);
2765 re = builtin_regnum (argv[1], NULL);
2766
2767 /* Rb should be equal/less than Re. */
2768 if (rb > re)
2769 as_bad ("The first operand (%s) should be equal to or smaller than "
2770 "second operand (%s).", argv[0], argv[1]);
2771
2772 /* forbid using $fp|$gp|$lp|$sp in Rb or Re
2773 r28 r29 r30 r31 */
2774 if (rb >= 28)
2775 as_bad ("Cannot use $fp, $gp, $lp, or $sp at first operand !!");
2776 if (re >= 28)
2777 as_bad ("Cannot use $fp, $gp, $lp, or $sp at second operand !!");
2778 }
2779 else
2780 {
2781 as_bad ("Invalid operands pattern !!");
2782 }
2783
2784 /* Build Enable4 mask. */
2785 /* Using last_arg_index for argc=1|2|3 is safe, because $fp, $gp, $lp,
2786 and $sp only appear in argc=1 or argc=3 if argc=2, en4 remains 0,
2787 which is also valid for code generation. */
2788 en4 = 0;
2789 last_arg_index = argc - 1;
2790 if (strstr (argv[last_arg_index], "$fp"))
2791 en4 |= 8;
2792 if (strstr (argv[last_arg_index], "$gp"))
2793 en4 |= 4;
2794 if (strstr (argv[last_arg_index], "$lp"))
2795 en4 |= 2;
2796 if (strstr (argv[last_arg_index], "$sp"))
2797 en4 |= 1;
2798
2799 md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc, rb, re, en4);
2800 }
2801
2802 static void
2803 do_pseudo_push_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[],
2804 unsigned int pv ATTRIBUTE_UNUSED)
2805 {
2806 char size = 'x';
2807 /* If users omit push location, use $sp as default value. */
2808 char location[8] = "$sp"; /* 8 is enough for register name. */
2809
2810 switch (pv & 0x3)
2811 {
2812 case 0: size = 'b'; break;
2813 case 1: size = 'h'; break;
2814 case 2: size = 'w'; break;
2815 case 3: size = 'w'; break;
2816 }
2817
2818 if (argc == 2)
2819 {
2820 strncpy (location, argv[1], 8);
2821 location[7] = '\0';
2822 }
2823
2824 md_assemblef ("l.%c $ta,%s", size, argv[0]);
2825 md_assemblef ("smw.adm $ta,[%s],$ta", location);
2826
2827 if ((pv & 0x3) == 0x3) /* double-word */
2828 {
2829 md_assemblef ("l.w $ta,%s+4", argv[0]);
2830 md_assemblef ("smw.adm $ta,[%s],$ta", location);
2831 }
2832 }
2833
2834 static void
2835 do_pseudo_pop_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[],
2836 unsigned int pv ATTRIBUTE_UNUSED)
2837 {
2838 char size = 'x';
2839 /* If users omit pop location, use $sp as default value. */
2840 char location[8] = "$sp"; /* 8 is enough for register name. */
2841
2842 switch (pv & 0x3)
2843 {
2844 case 0: size = 'b'; break;
2845 case 1: size = 'h'; break;
2846 case 2: size = 'w'; break;
2847 case 3: size = 'w'; break;
2848 }
2849
2850 if (argc == 3)
2851 {
2852 strncpy (location, argv[2], 8);
2853 location[7] = '\0';
2854 }
2855
2856 if ((pv & 0x3) == 0x3) /* double-word */
2857 {
2858 md_assemblef ("lmw.bim %s,[%s],%s", argv[1], location, argv[1]);
2859 md_assemblef ("s.w %s,%s+4", argv[1], argv[0]);
2860 }
2861
2862 md_assemblef ("lmw.bim %s,[%s],%s", argv[1], location, argv[1]);
2863 md_assemblef ("s.%c %s,%s", size, argv[1], argv[0]);
2864 }
2865
2866 static void
2867 do_pseudo_pusha (int argc ATTRIBUTE_UNUSED, char *argv[],
2868 unsigned int pv ATTRIBUTE_UNUSED)
2869 {
2870 /* If users omit push location, use $sp as default value. */
2871 char location[8] = "$sp"; /* 8 is enough for register name. */
2872
2873 if (argc == 2)
2874 {
2875 strncpy (location, argv[1], 8);
2876 location[7] = '\0';
2877 }
2878
2879 md_assemblef ("la $ta,%s", argv[0]);
2880 md_assemblef ("smw.adm $ta,[%s],$ta", location);
2881 }
2882
2883 static void
2884 do_pseudo_pushi (int argc ATTRIBUTE_UNUSED, char *argv[],
2885 unsigned int pv ATTRIBUTE_UNUSED)
2886 {
2887 /* If users omit push location, use $sp as default value. */
2888 char location[8] = "$sp"; /* 8 is enough for register name. */
2889
2890 if (argc == 2)
2891 {
2892 strncpy (location, argv[1], 8);
2893 location[7] = '\0';
2894 }
2895
2896 md_assemblef ("li $ta,%s", argv[0]);
2897 md_assemblef ("smw.adm $ta,[%s],$ta", location);
2898 }
2899
2900 struct nds32_pseudo_opcode nds32_pseudo_opcode_table[] =
2901 {
2902 {"b", 1, do_pseudo_b, 0, 0},
2903 {"bal", 1, do_pseudo_bal, 0, 0},
2904
2905 {"bge", 3, do_pseudo_bge, 0, 0},
2906 {"bges", 3, do_pseudo_bges, 0, 0},
2907
2908 {"bgt", 3, do_pseudo_bgt, 0, 0},
2909 {"bgts", 3, do_pseudo_bgts, 0, 0},
2910
2911 {"ble", 3, do_pseudo_ble, 0, 0},
2912 {"bles", 3, do_pseudo_bles, 0, 0},
2913
2914 {"blt", 3, do_pseudo_blt, 0, 0},
2915 {"blts", 3, do_pseudo_blts, 0, 0},
2916
2917 {"br", 1, do_pseudo_br, 0, 0},
2918 {"bral", 1, do_pseudo_bral, 0, 0},
2919
2920 {"call", 1, do_pseudo_bal, 0, 0},
2921
2922 {"la", 2, do_pseudo_la, 0, 0},
2923 {"li", 2, do_pseudo_li, 0, 0},
2924
2925 {"l.b", 2, do_pseudo_ls_bhw, 0, 0},
2926 {"l.h", 2, do_pseudo_ls_bhw, 1, 0},
2927 {"l.w", 2, do_pseudo_ls_bhw, 2, 0},
2928 {"l.bs", 2, do_pseudo_ls_bhw, 0 | 0x10, 0},
2929 {"l.hs", 2, do_pseudo_ls_bhw, 1 | 0x10, 0},
2930 {"s.b", 2, do_pseudo_ls_bhw, 0 | 0x80000000, 0},
2931 {"s.h", 2, do_pseudo_ls_bhw, 1 | 0x80000000, 0},
2932 {"s.w", 2, do_pseudo_ls_bhw, 2 | 0x80000000, 0},
2933
2934 {"l.bp", 3, do_pseudo_ls_bhwp, 0, 0},
2935 {"l.bpc", 3, do_pseudo_ls_bhwpc, 0, 0},
2936 {"l.hp", 3, do_pseudo_ls_bhwp, 1, 0},
2937 {"l.hpc", 3, do_pseudo_ls_bhwpc, 1, 0},
2938 {"l.wp", 3, do_pseudo_ls_bhwp, 2, 0},
2939 {"l.wpc", 3, do_pseudo_ls_bhwpc, 2, 0},
2940 {"l.bsp", 3, do_pseudo_ls_bhwp, 0 | 0x10, 0},
2941 {"l.bspc", 3, do_pseudo_ls_bhwpc, 0 | 0x10, 0},
2942 {"l.hsp", 3, do_pseudo_ls_bhwp, 1 | 0x10, 0},
2943 {"l.hspc", 3, do_pseudo_ls_bhwpc, 1 | 0x10, 0},
2944 {"s.bp", 3, do_pseudo_ls_bhwp, 0 | 0x80000000, 0},
2945 {"s.bpc", 3, do_pseudo_ls_bhwpc, 0 | 0x80000000, 0},
2946 {"s.hp", 3, do_pseudo_ls_bhwp, 1 | 0x80000000, 0},
2947 {"s.hpc", 3, do_pseudo_ls_bhwpc, 1 | 0x80000000, 0},
2948 {"s.wp", 3, do_pseudo_ls_bhwp, 2 | 0x80000000, 0},
2949 {"s.wpc", 3, do_pseudo_ls_bhwpc, 2 | 0x80000000, 0},
2950 {"s.bsp", 3, do_pseudo_ls_bhwp, 0 | 0x80000000 | 0x10, 0},
2951 {"s.hsp", 3, do_pseudo_ls_bhwp, 1 | 0x80000000 | 0x10, 0},
2952
2953 {"lbi.p", 3, do_pseudo_ls_bhwi, 0, 0},
2954 {"lhi.p", 3, do_pseudo_ls_bhwi, 1, 0},
2955 {"lwi.p", 3, do_pseudo_ls_bhwi, 2, 0},
2956 {"sbi.p", 3, do_pseudo_ls_bhwi, 0 | 0x80000000, 0},
2957 {"shi.p", 3, do_pseudo_ls_bhwi, 1 | 0x80000000, 0},
2958 {"swi.p", 3, do_pseudo_ls_bhwi, 2 | 0x80000000, 0},
2959 {"lbsi.p", 3, do_pseudo_ls_bhwi, 0 | 0x10, 0},
2960 {"lhsi.p", 3, do_pseudo_ls_bhwi, 1 | 0x10, 0},
2961 {"lwsi.p", 3, do_pseudo_ls_bhwi, 2 | 0x10, 0},
2962
2963 {"move", 2, do_pseudo_move, 0, 0},
2964 {"neg", 2, do_pseudo_neg, 0, 0},
2965 {"not", 2, do_pseudo_not, 0, 0},
2966
2967 {"pop", 2, do_pseudo_pushpop, 0, 0},
2968 {"push", 2, do_pseudo_pushpop, 0, 0},
2969 {"popm", 2, do_pseudo_pushpopm, 0, 0},
2970 {"pushm", 3, do_pseudo_pushpopm, 0, 0},
2971
2972 {"v3push", 2, do_pseudo_v3push, 0, 0},
2973 {"v3pop", 2, do_pseudo_v3pop, 0, 0},
2974
2975 /* Support pseudo instructions of pushing/poping registers into/from stack
2976 push.s Rb, Re, { $fp $gp $lp $sp } ==> smw.adm Rb,[$sp],Re,Enable4
2977 pop.s Rb, Re, { $fp $gp $lp $sp } ==> lmw.bim Rb,[$sp],Re,Enable4 */
2978 { "push.s", 3, do_pseudo_pushpop_stack, 0, 0 },
2979 { "pop.s", 3, do_pseudo_pushpop_stack, 1, 0 },
2980 { "push.b", 2, do_pseudo_push_bhwd, 0, 0 },
2981 { "push.h", 2, do_pseudo_push_bhwd, 1, 0 },
2982 { "push.w", 2, do_pseudo_push_bhwd, 2, 0 },
2983 { "push.d", 2, do_pseudo_push_bhwd, 3, 0 },
2984 { "pop.b", 3, do_pseudo_pop_bhwd, 0, 0 },
2985 { "pop.h", 3, do_pseudo_pop_bhwd, 1, 0 },
2986 { "pop.w", 3, do_pseudo_pop_bhwd, 2, 0 },
2987 { "pop.d", 3, do_pseudo_pop_bhwd, 3, 0 },
2988 { "pusha", 2, do_pseudo_pusha, 0, 0 },
2989 { "pushi", 2, do_pseudo_pushi, 0, 0 },
2990
2991 {NULL, 0, NULL, 0, 0}
2992 };
2993
2994 static void
2995 nds32_init_nds32_pseudo_opcodes (void)
2996 {
2997 struct nds32_pseudo_opcode *opcode = nds32_pseudo_opcode_table;
2998
2999 nds32_pseudo_opcode_hash = hash_new ();
3000 for ( ; opcode->opcode; opcode++)
3001 {
3002 void *op;
3003
3004 op = hash_find (nds32_pseudo_opcode_hash, opcode->opcode);
3005 if (op != NULL)
3006 {
3007 as_warn (_("Duplicated pseudo-opcode %s."), opcode->opcode);
3008 continue;
3009 }
3010 hash_insert (nds32_pseudo_opcode_hash, opcode->opcode, opcode);
3011 }
3012 }
3013
3014 static struct nds32_pseudo_opcode *
3015 nds32_lookup_pseudo_opcode (const char *str)
3016 {
3017 int i = 0;
3018 /* Assume pseudo-opcode are less than 16-char in length. */
3019 char op[16] = {0};
3020
3021 for (i = 0; i < (int)ARRAY_SIZE (op); i++)
3022 {
3023 if (ISSPACE (op[i] = str[i]))
3024 break;
3025 }
3026
3027 if (i >= (int)ARRAY_SIZE (op))
3028 return NULL;
3029
3030 op[i] = '\0';
3031
3032 return hash_find (nds32_pseudo_opcode_hash, op);
3033 }
3034
3035 static void
3036 nds32_pseudo_opcode_wrapper (char *line, struct nds32_pseudo_opcode *opcode)
3037 {
3038 int argc = 0;
3039 char *argv[8] = {NULL};
3040 char *s;
3041 char *str = xstrdup (line);
3042
3043 /* Parse arguments for opcode. */
3044 s = str + strlen (opcode->opcode);
3045
3046 if (!s[0])
3047 goto end;
3048
3049 /* Dummy comma to ease separate arguments as below. */
3050 s[0] = ',';
3051 do
3052 {
3053 if (s[0] == ',')
3054 {
3055 if (argc >= opcode->argc
3056 || (argc >= (int)ARRAY_SIZE (argv) - 1))
3057 as_bad (_("Too many argument. `%s'"), line);
3058
3059 argv[argc] = s + 1;
3060 argc ++;
3061 s[0] = '\0';
3062 }
3063 ++s;
3064 } while (s[0] != '\0');
3065 end:
3066 /* Put the origin line for debugging. */
3067 argv[argc] = line;
3068 opcode->proc (argc, argv, opcode->pseudo_val);
3069 free (str);
3070 }
3071
3072 /* This function will be invoked from function `nds32_after_parse_args'.
3074 Thus, if the value of option has been set, keep the value the way it is. */
3075
3076 static int
3077 nds32_parse_arch (const char *str)
3078 {
3079 static const struct nds32_arch
3080 {
3081 const char *name;
3082 int baseline;
3083 int reduced_reg;
3084 int fpu_sp_ext;
3085 int fpu_dp_ext;
3086 int fpu_freg;
3087 int abi;
3088 } archs[] =
3089 {
3090 {"v3m", ISA_V3M, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3091 {"v3j", ISA_V3, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3092 {"v3s", ISA_V3, 0, 1, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3093 {"v3f", ISA_V3, 0, 1, 1, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3094 {"v3", ISA_V3, 0, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3095 {"v2j", ISA_V2, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3096 {"v2s", ISA_V2, 0, 1, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3097 {"v2f", ISA_V2, 0, 1, 1, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3098 {"v2", ISA_V2, 0, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3099 };
3100 size_t i;
3101
3102 for (i = 0; i < ARRAY_SIZE (archs); i++)
3103 {
3104 if (strcmp (str, archs[i].name) != 0)
3105 continue;
3106
3107 /* The value `-1' represents this option has *NOT* been set. */
3108 nds32_baseline = (-1 != nds32_baseline) ? nds32_baseline : archs[i].baseline;
3109 nds32_gpr16 = (-1 != nds32_gpr16) ? nds32_gpr16 : archs[i].reduced_reg;
3110 nds32_fpu_sp_ext = (-1 != nds32_fpu_sp_ext) ? nds32_fpu_sp_ext : archs[i].fpu_sp_ext;
3111 nds32_fpu_dp_ext = (-1 != nds32_fpu_dp_ext) ? nds32_fpu_dp_ext : archs[i].fpu_dp_ext;
3112 nds32_freg = (-1 != nds32_freg) ? nds32_freg : archs[i].fpu_freg;
3113 nds32_abi = (-1 != nds32_abi) ? nds32_abi : archs[i].abi;
3114
3115 return 1;
3116 }
3117
3118 /* Logic here rejects the input arch name. */
3119 as_bad (_("unknown arch name `%s'\n"), str);
3120
3121 return 1;
3122 }
3123
3124 /* This function parses "baseline" specified. */
3125
3126 static int
3127 nds32_parse_baseline (const char *str)
3128 {
3129 if (strcmp (str, "v3") == 0)
3130 nds32_baseline = ISA_V3;
3131 else if (strcmp (str, "v3m") == 0)
3132 nds32_baseline = ISA_V3M;
3133 else if (strcmp (str, "v2") == 0)
3134 nds32_baseline = ISA_V2;
3135 else
3136 {
3137 /* Logic here rejects the input baseline. */
3138 as_bad (_("unknown baseline `%s'\n"), str);
3139 return 0;
3140 }
3141
3142 return 1;
3143 }
3144
3145 /* This function parses "fpu-freg" specified. */
3146
3147 static int
3148 nds32_parse_freg (const char *str)
3149 {
3150 if (strcmp (str, "2") == 0)
3151 nds32_freg = E_NDS32_FPU_REG_32SP_16DP;
3152 else if (strcmp (str, "3") == 0)
3153 nds32_freg = E_NDS32_FPU_REG_32SP_32DP;
3154 else if (strcmp (str, "1") == 0)
3155 nds32_freg = E_NDS32_FPU_REG_16SP_8DP;
3156 else if (strcmp (str, "0") == 0)
3157 nds32_freg = E_NDS32_FPU_REG_8SP_4DP;
3158 else
3159 {
3160 /* Logic here rejects the input FPU configuration. */
3161 as_bad (_("unknown FPU configuration `%s'\n"), str);
3162 return 0;
3163 }
3164
3165 return 1;
3166 }
3167
3168 /* This function parse "abi=" specified. */
3169
3170 static int
3171 nds32_parse_abi (const char *str)
3172 {
3173 if (strcmp (str, "v2") == 0)
3174 nds32_abi = E_NDS_ABI_AABI;
3175 /* Obsolete. */
3176 else if (strcmp (str, "v2fp") == 0)
3177 nds32_abi = E_NDS_ABI_V2FP;
3178 else if (strcmp (str, "v1") == 0)
3179 nds32_abi = E_NDS_ABI_V1;
3180 else if (strcmp (str,"v2fpp") == 0)
3181 nds32_abi = E_NDS_ABI_V2FP_PLUS;
3182 else
3183 {
3184 /* Logic here rejects the input abi version. */
3185 as_bad (_("unknown ABI version`%s'\n"), str);
3186 return 0;
3187 }
3188
3189 return 1;
3190 }
3191
3192 /* This function turn on all extensions and instructions support. */
3193
3194 static int
3195 nds32_all_ext (void)
3196 {
3197 nds32_mac = 1;
3198 nds32_div = 1;
3199 nds32_dx_regs = 1;
3200 nds32_16bit_ext = 1;
3201 nds32_perf_ext = 1;
3202 nds32_perf_ext2 = 1;
3203 nds32_string_ext = 1;
3204 nds32_audio_ext = 1;
3205 nds32_fpu_fma = 1;
3206 nds32_fpu_sp_ext = 1;
3207 nds32_fpu_dp_ext = 1;
3208
3209 return 1;
3210 }
3211
3212 /* GAS will call md_parse_option whenever getopt returns an unrecognized code,
3213 presumably indicating a special code value which appears in md_longopts.
3214 This function should return non-zero if it handled the option and zero
3215 otherwise. There is no need to print a message about an option not being
3216 recognized. This will be handled by the generic code. */
3217
3218 int
3219 nds32_parse_option (int c, const char *arg)
3220 {
3221 struct nds32_parse_option_table *coarse_tune;
3222 struct nds32_set_option_table *fine_tune;
3223 const char *ptr_arg = NULL;
3224
3225 switch (c)
3226 {
3227 case OPTION_OPTIMIZE:
3228 optimize = 1;
3229 optimize_for_space = 0;
3230 break;
3231 case OPTION_OPTIMIZE_SPACE:
3232 optimize = 0;
3233 optimize_for_space = 1;
3234 break;
3235 case OPTION_BIG:
3236 target_big_endian = 1;
3237 break;
3238 case OPTION_LITTLE:
3239 target_big_endian = 0;
3240 break;
3241 case OPTION_TURBO:
3242 nds32_all_ext ();
3243 break;
3244 case OPTION_PIC:
3245 nds32_pic = 1;
3246 break;
3247 case OPTION_RELAX_FP_AS_GP_OFF:
3248 nds32_relax_fp_as_gp = 0;
3249 break;
3250 case OPTION_RELAX_B2BB_ON:
3251 nds32_relax_b2bb = 1;
3252 break;
3253 case OPTION_RELAX_ALL_OFF:
3254 nds32_relax_all = 0;
3255 break;
3256 default:
3257 /* Determination of which option table to search for to save time. */
3258 if (!arg)
3259 return 0;
3260
3261 ptr_arg = strchr (arg, '=');
3262
3263 if (ptr_arg)
3264 {
3265 /* Find the value after '='. */
3266 if (ptr_arg != NULL)
3267 ptr_arg++;
3268 for (coarse_tune = parse_opts; coarse_tune->name != NULL; coarse_tune++)
3269 {
3270 if (strncmp (arg, coarse_tune->name, (ptr_arg - arg)) == 0)
3271 {
3272 coarse_tune->func (ptr_arg);
3273 return 1;
3274 }
3275 }
3276 }
3277 else
3278 {
3279 int disable = 0;
3280
3281 /* Filter out the Disable option first. */
3282 if (strncmp (arg, "no-", 3) == 0)
3283 {
3284 disable = 1;
3285 arg += 3;
3286 }
3287
3288 for (fine_tune = toggle_opts; fine_tune->name != NULL; fine_tune++)
3289 {
3290 if (strcmp (arg, fine_tune->name) == 0)
3291 {
3292 if (fine_tune->var != NULL)
3293 *fine_tune->var = (disable) ? 0 : 1;
3294 return 1;
3295 }
3296 }
3297 }
3298 /* Nothing match. */
3299 return 0;
3300 }
3301
3302 return 1;
3303 }
3304
3305 /* tc_check_label */
3306
3307 void
3308 nds32_check_label (symbolS *label ATTRIBUTE_UNUSED)
3309 {
3310 /* The code used to create BB is move to frob_label.
3311 They should go there. */
3312 }
3313
3314 static void
3315 set_endian_little (int on)
3316 {
3317 target_big_endian = !on;
3318 }
3319
3320 /* These functions toggles the generation of 16-bit. First encounter signals
3321 the beginning of not generating 16-bit instructions and next encounter
3322 signals the restoring back to default behavior. */
3323
3324 static void
3325 trigger_16bit (int trigger)
3326 {
3327 enable_16bit = trigger;
3328 }
3329
3330 static int backup_16bit_mode;
3331 static void
3332 restore_16bit (int no_use ATTRIBUTE_UNUSED)
3333 {
3334 enable_16bit = backup_16bit_mode;
3335 }
3336
3337 static void
3338 off_16bit (int no_use ATTRIBUTE_UNUSED)
3339 {
3340 backup_16bit_mode = enable_16bit;
3341 enable_16bit = 0;
3342 }
3343
3344 /* Built-in segments for small object. */
3345 typedef struct nds32_seg_entryT
3346 {
3347 segT s;
3348 const char *name;
3349 flagword flags;
3350 } nds32_seg_entry;
3351
3352 nds32_seg_entry nds32_seg_table[] =
3353 {
3354 {NULL, ".sdata_f", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3355 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3356 {NULL, ".sdata_b", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3357 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3358 {NULL, ".sdata_h", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3359 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3360 {NULL, ".sdata_w", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3361 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3362 {NULL, ".sdata_d", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3363 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3364 {NULL, ".sbss_f", SEC_ALLOC | SEC_SMALL_DATA},
3365 {NULL, ".sbss_b", SEC_ALLOC | SEC_SMALL_DATA},
3366 {NULL, ".sbss_h", SEC_ALLOC | SEC_SMALL_DATA},
3367 {NULL, ".sbss_w", SEC_ALLOC | SEC_SMALL_DATA},
3368 {NULL, ".sbss_d", SEC_ALLOC | SEC_SMALL_DATA}
3369 };
3370
3371 /* Indexes to nds32_seg_table[]. */
3372 enum NDS32_SECTIONS_ENUM
3373 {
3374 SDATA_F_SECTION = 0,
3375 SDATA_B_SECTION = 1,
3376 SDATA_H_SECTION = 2,
3377 SDATA_W_SECTION = 3,
3378 SDATA_D_SECTION = 4,
3379 SBSS_F_SECTION = 5,
3380 SBSS_B_SECTION = 6,
3381 SBSS_H_SECTION = 7,
3382 SBSS_W_SECTION = 8,
3383 SBSS_D_SECTION = 9
3384 };
3385
3386 /* The following code is borrowed from v850_seg. Revise this is needed. */
3387
3388 static void
3389 do_nds32_seg (int i, subsegT sub)
3390 {
3391 nds32_seg_entry *seg = nds32_seg_table + i;
3392
3393 obj_elf_section_change_hook ();
3394
3395 if (seg->s != NULL)
3396 subseg_set (seg->s, sub);
3397 else
3398 {
3399 seg->s = subseg_new (seg->name, sub);
3400 if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
3401 {
3402 bfd_set_section_flags (stdoutput, seg->s, seg->flags);
3403 if ((seg->flags & SEC_LOAD) == 0)
3404 seg_info (seg->s)->bss = 1;
3405 }
3406 }
3407 }
3408
3409 static void
3410 nds32_seg (int i)
3411 {
3412 subsegT sub = get_absolute_expression ();
3413
3414 do_nds32_seg (i, sub);
3415 demand_empty_rest_of_line ();
3416 }
3417
3418 /* Set if label adjustment is needed. I should not adjust .xbyte in dwarf. */
3419 static symbolS *nds32_last_label; /* Last label for alignment. */
3420
3421 /* This code is referred from D30V for adjust label to be with pending
3422 alignment. For example,
3423 LBYTE: .byte 0x12
3424 LHALF: .half 0x12
3425 LWORD: .word 0x12
3426 Without this, the above label will not attach to incoming data. */
3427
3428 static void
3429 nds32_adjust_label (int n)
3430 {
3431 /* FIXME: I think adjust label and alignment is
3432 the programmer's obligation. Sadly, VLSI team doesn't
3433 properly use .align for their test cases.
3434 So I re-implement cons_align and auto adjust labels, again.
3435
3436 I think d30v's implementation is simple and good enough. */
3437
3438 symbolS *label = nds32_last_label;
3439 nds32_last_label = NULL;
3440
3441 /* SEC_ALLOC is used to eliminate .debug_ sections.
3442 SEC_CODE is used to include section for ILM. */
3443 if (((now_seg->flags & SEC_ALLOC) == 0 && (now_seg->flags & SEC_CODE) == 0)
3444 || strcmp (now_seg->name, ".eh_frame") == 0
3445 || strcmp (now_seg->name, ".gcc_except_table") == 0)
3446 return;
3447
3448 /* Only frag by alignment when needed.
3449 Otherwise, it will fail to optimize labels on 4-byte boundary. (bug8454)
3450 See md_convert_frag () and RELAX_SET_RELAXABLE (frag) for details. */
3451 if (frag_now_fix () & ((1 << n) -1 ))
3452 {
3453 if (subseg_text_p (now_seg))
3454 frag_align_code (n, 0);
3455 else
3456 frag_align (n, 0, 0);
3457
3458 /* Record the minimum alignment for this segment. */
3459 record_alignment (now_seg, n - OCTETS_PER_BYTE_POWER);
3460 }
3461
3462 if (label != NULL)
3463 {
3464 symbolS *sym;
3465 int label_seen = FALSE;
3466 struct frag *old_frag;
3467 valueT old_value, new_value;
3468
3469 gas_assert (S_GET_SEGMENT (label) == now_seg);
3470
3471 old_frag = symbol_get_frag (label);
3472 old_value = S_GET_VALUE (label);
3473 new_value = (valueT) frag_now_fix ();
3474
3475 /* Multiple labels may be on the same address. And the last symbol
3476 may not be a label at all, e.g., register name, external function names,
3477 so I have to track the last label in tc_frob_label instead of
3478 just using symbol_lastP. */
3479 for (sym = symbol_lastP; sym != NULL; sym = symbol_previous (sym))
3480 {
3481 if (symbol_get_frag (sym) == old_frag
3482 && S_GET_VALUE (sym) == old_value)
3483 {
3484 /* Warning HERE! */
3485 label_seen = TRUE;
3486 symbol_set_frag (sym, frag_now);
3487 S_SET_VALUE (sym, new_value);
3488 }
3489 else if (label_seen && symbol_get_frag (sym) != old_frag)
3490 break;
3491 }
3492 }
3493 }
3494
3495 void
3496 nds32_cons_align (int size ATTRIBUTE_UNUSED)
3497 {
3498 /* Do nothing here.
3499 This is called before `md_flush_pending_output' is called by `cons'.
3500
3501 There are two things should be done for auto-adjust-label.
3502 1. Align data/instructions and adjust label to be attached to them.
3503 2. Clear auto-adjust state, so incoming data/instructions will not
3504 adjust the label.
3505
3506 For example,
3507 .byte 0x1
3508 .L0:
3509 .word 0x2
3510 .word 0x3
3511 in this case, '.word 0x2' will adjust the label, .L0, but '.word 0x3' should not.
3512
3513 I think `md_flush_pending_output' is a good place to clear the auto-adjust state,
3514 but it is also called by `cons' before this function.
3515 To simplify the code, instead of overriding .zero, .fill, .space, etc,
3516 I think we should just adjust label in `nds32_aligned_X_cons' instead of here. */
3517 }
3518
3519 static void
3520 nds32_aligned_cons (int idx)
3521 {
3522 nds32_adjust_label (idx);
3523 /* Call default handler. */
3524 cons (1 << idx);
3525 if (now_seg->flags & SEC_CODE
3526 && now_seg->flags & SEC_ALLOC && now_seg->flags & SEC_RELOC)
3527 {
3528 /* Use BFD_RELOC_NDS32_DATA to avoid EX9 optimization replacing data. */
3529 expressionS exp;
3530
3531 exp.X_add_number = 0;
3532 exp.X_op = O_constant;
3533 fix_new_exp (frag_now, frag_now_fix () - (1 << idx), 1 << idx,
3534 &exp, 0, BFD_RELOC_NDS32_DATA);
3535 }
3536 }
3537
3538 /* `.double' directive. */
3539
3540 static void
3541 nds32_aligned_float_cons (int type)
3542 {
3543 switch (type)
3544 {
3545 case 'f':
3546 case 'F':
3547 case 's':
3548 case 'S':
3549 nds32_adjust_label (2);
3550 break;
3551 case 'd':
3552 case 'D':
3553 case 'r':
3554 case 'R':
3555 nds32_adjust_label (4);
3556 break;
3557 default:
3558 as_bad ("Unrecognized float type, %c\n", (char)type);
3559 }
3560 /* Call default handler. */
3561 float_cons (type);
3562 }
3563
3564 static void
3565 nds32_enable_pic (int ignore ATTRIBUTE_UNUSED)
3566 {
3567 /* Another way to do -mpic.
3568 This is for GCC internal use and should always be first line
3569 of code, otherwise, the effect is not determined. */
3570 nds32_pic = 1;
3571 }
3572
3573 static void
3574 nds32_set_abi (int ver)
3575 {
3576 nds32_abi = ver;
3577 }
3578
3579 /* Relax directive to set relocation R_NDS32_RELAX_ENTRY value. */
3580
3581 static void
3582 nds32_relax_relocs (int relax)
3583 {
3584 char saved_char;
3585 char *name;
3586 int i;
3587 const char *subtype_relax[] =
3588 {"", "", "ex9", "ifc"};
3589
3590 name = input_line_pointer;
3591 while (*input_line_pointer && !ISSPACE (*input_line_pointer))
3592 input_line_pointer++;
3593 saved_char = *input_line_pointer;
3594 *input_line_pointer = 0;
3595
3596 for (i = 0; i < (int) ARRAY_SIZE (subtype_relax); i++)
3597 {
3598 if (strcmp (name, subtype_relax[i]) == 0)
3599 {
3600 switch (i)
3601 {
3602 case 0:
3603 case 1:
3604 enable_relax_relocs = relax & enable_relax_relocs;
3605 enable_relax_ex9 = relax & enable_relax_ex9;
3606 enable_relax_ifc = relax & enable_relax_ifc;
3607 break;
3608 case 2:
3609 enable_relax_ex9 = relax;
3610 break;
3611 case 3:
3612 enable_relax_ifc = relax;
3613 break;
3614 default:
3615 break;
3616 }
3617 break;
3618 }
3619 }
3620 *input_line_pointer = saved_char;
3621 ignore_rest_of_line ();
3622 }
3623
3624 /* Record which arguments register($r0 ~ $r5) is not used in callee.
3625 bit[i] for $ri */
3626
3627 static void
3628 nds32_set_hint_func_args (int ignore ATTRIBUTE_UNUSED)
3629 {
3630 ignore_rest_of_line ();
3631 }
3632
3633 /* Insert relocations to mark the begin and end of a fp-omitted function,
3634 for further relaxation use.
3635 bit[i] for $ri */
3636
3637 static void
3638 nds32_omit_fp_begin (int mode)
3639 {
3640 expressionS exp;
3641
3642 if (nds32_relax_fp_as_gp == 0)
3643 return;
3644 exp.X_op = O_symbol;
3645 exp.X_add_symbol = abs_section_sym;
3646 if (mode == 1)
3647 {
3648 in_omit_fp = 1;
3649 exp.X_add_number = R_NDS32_RELAX_REGION_OMIT_FP_FLAG;
3650 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
3651 BFD_RELOC_NDS32_RELAX_REGION_BEGIN);
3652 }
3653 else
3654 {
3655 in_omit_fp = 0;
3656 exp.X_add_number = R_NDS32_RELAX_REGION_OMIT_FP_FLAG;
3657 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
3658 BFD_RELOC_NDS32_RELAX_REGION_END);
3659 }
3660 }
3661
3662 /* Insert relocations to mark the begin and end of ex9 region,
3663 for further relaxation use.
3664 bit[i] for $ri */
3665
3666 static void
3667 nds32_no_ex9_begin (int mode)
3668 {
3669 expressionS exp;
3670
3671 exp.X_op = O_symbol;
3672 exp.X_add_symbol = abs_section_sym;
3673 if (mode == 1)
3674 {
3675 exp.X_add_number = R_NDS32_RELAX_REGION_NO_EX9_FLAG;
3676 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
3677 BFD_RELOC_NDS32_RELAX_REGION_BEGIN);
3678 }
3679 else
3680 {
3681 exp.X_add_number = R_NDS32_RELAX_REGION_NO_EX9_FLAG;
3682 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
3683 BFD_RELOC_NDS32_RELAX_REGION_END);
3684 }
3685 }
3686
3687 static void
3688 nds32_loop_begin (int mode)
3689 {
3690 /* Insert loop region relocation here. */
3691 expressionS exp;
3692
3693 exp.X_op = O_symbol;
3694 exp.X_add_symbol = abs_section_sym;
3695 if (mode == 1)
3696 {
3697 exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG;
3698 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
3699 BFD_RELOC_NDS32_RELAX_REGION_BEGIN);
3700 }
3701 else
3702 {
3703 exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG;
3704 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
3705 BFD_RELOC_NDS32_RELAX_REGION_END);
3706 }
3707 }
3708
3709 struct nds32_relocs_group
3710 {
3711 struct nds32_relocs_pattern *pattern;
3712 struct nds32_relocs_group *next;
3713 };
3714
3715 static struct nds32_relocs_group *nds32_relax_hint_current = NULL;
3716
3717 /* Insert a relax hint. */
3718
3719 static void
3720 nds32_relax_hint (int mode ATTRIBUTE_UNUSED)
3721 {
3722 char *name;
3723 char saved_char;
3724 struct nds32_relocs_pattern *relocs = NULL;
3725 struct nds32_relocs_group *group, *new;
3726
3727 name = input_line_pointer;
3728 while (*input_line_pointer && !ISSPACE (*input_line_pointer))
3729 input_line_pointer++;
3730 saved_char = *input_line_pointer;
3731 *input_line_pointer = 0;
3732 name = strdup (name);
3733
3734 /* Find relax hint entry for next instruction, and all member will be
3735 initialized at that time. */
3736 relocs = hash_find (nds32_hint_hash, name);
3737 if (relocs == NULL)
3738 {
3739 relocs = XNEW (struct nds32_relocs_pattern);
3740 hash_insert (nds32_hint_hash, name, relocs);
3741 }
3742 else
3743 {
3744 while (relocs->next)
3745 relocs=relocs->next;
3746 relocs->next = XNEW (struct nds32_relocs_pattern);
3747 relocs = relocs->next;
3748 }
3749
3750 relocs->next = NULL;
3751 *input_line_pointer = saved_char;
3752 ignore_rest_of_line ();
3753
3754 /* Get the final one of relax hint series. */
3755
3756 /* It has to build this list because there are maybe more than one
3757 instructions relative to the same instruction. It to connect to
3758 next instruction after md_assemble. */
3759 new = XNEW (struct nds32_relocs_group);
3760 new->pattern = relocs;
3761 new->next = NULL;
3762 group = nds32_relax_hint_current;
3763 if (!group)
3764 nds32_relax_hint_current = new;
3765 else
3766 {
3767 while (group->next != NULL)
3768 group = group->next;
3769 group->next = new;
3770 }
3771 relaxing = TRUE;
3772 }
3773
3774 /* Decide the size of vector entries, only accepts 4 or 16 now. */
3775
3776 static void
3777 nds32_vec_size (int ignore ATTRIBUTE_UNUSED)
3778 {
3779 expressionS exp;
3780
3781 expression (&exp);
3782
3783 if (exp.X_op == O_constant)
3784 {
3785 if (exp.X_add_number == 4 || exp.X_add_number == 16)
3786 {
3787 if (vec_size == 0)
3788 vec_size = exp.X_add_number;
3789 else if (vec_size != exp.X_add_number)
3790 as_warn (_("Different arguments of .vec_size are found, "
3791 "previous %d, current %d"),
3792 (int) vec_size, (int) exp.X_add_number);
3793 }
3794 else
3795 as_warn (_("Argument of .vec_size is expected 4 or 16, actual: %d."),
3796 (int) exp.X_add_number);
3797 }
3798 else
3799 as_warn (_("Argument of .vec_size is not a constant."));
3800 }
3801
3802 /* The behavior of ".flag" directive varies depending on the target.
3803 In nds32 target, we use it to recognize whether this assembly content is
3804 generated by compiler. Other features can also be added in this function
3805 in the future. */
3806
3807 static void
3808 nds32_flag (int ignore ATTRIBUTE_UNUSED)
3809 {
3810 char *name;
3811 char saved_char;
3812 int i;
3813 const char *possible_flags[] = { "verbatim" };
3814
3815 /* Skip whitespaces. */
3816 name = input_line_pointer;
3817 while (*input_line_pointer && !ISSPACE (*input_line_pointer))
3818 input_line_pointer++;
3819 saved_char = *input_line_pointer;
3820 *input_line_pointer = 0;
3821
3822 for (i = 0; i < (int) ARRAY_SIZE (possible_flags); i++)
3823 {
3824 if (strcmp (name, possible_flags[i]) == 0)
3825 {
3826 switch (i)
3827 {
3828 case 0:
3829 /* flag: verbatim */
3830 verbatim = 1;
3831 break;
3832 default:
3833 break;
3834 }
3835 /* Already found the flag, no need to continue next loop. */
3836 break;
3837 }
3838 }
3839
3840 *input_line_pointer = saved_char;
3841 ignore_rest_of_line ();
3842 }
3843
3844 static void
3845 nds32_n12hc (int ignore ATTRIBUTE_UNUSED)
3846 {
3847 /* N1213HC core is used. */
3848 }
3849
3850
3851 /* The target specific pseudo-ops which we support. */
3852 const pseudo_typeS md_pseudo_table[] =
3853 {
3854 /* Forced alignment if declared these ways. */
3855 {"ascii", stringer, 8 + 0},
3856 {"asciz", stringer, 8 + 1},
3857 {"double", nds32_aligned_float_cons, 'd'},
3858 {"dword", nds32_aligned_cons, 3},
3859 {"float", nds32_aligned_float_cons, 'f'},
3860 {"half", nds32_aligned_cons, 1},
3861 {"hword", nds32_aligned_cons, 1},
3862 {"int", nds32_aligned_cons, 2},
3863 {"long", nds32_aligned_cons, 2},
3864 {"octa", nds32_aligned_cons, 4},
3865 {"quad", nds32_aligned_cons, 3},
3866 {"qword", nds32_aligned_cons, 4},
3867 {"short", nds32_aligned_cons, 1},
3868 {"byte", nds32_aligned_cons, 0},
3869 {"single", nds32_aligned_float_cons, 'f'},
3870 {"string", stringer, 8 + 1},
3871 {"word", nds32_aligned_cons, 2},
3872
3873 {"little", set_endian_little, 1},
3874 {"big", set_endian_little, 0},
3875 {"16bit_on", trigger_16bit, 1},
3876 {"16bit_off", trigger_16bit, 0},
3877 {"restore_16bit", restore_16bit, 0},
3878 {"off_16bit", off_16bit, 0},
3879
3880 {"sdata_d", nds32_seg, SDATA_D_SECTION},
3881 {"sdata_w", nds32_seg, SDATA_W_SECTION},
3882 {"sdata_h", nds32_seg, SDATA_H_SECTION},
3883 {"sdata_b", nds32_seg, SDATA_B_SECTION},
3884 {"sdata_f", nds32_seg, SDATA_F_SECTION},
3885
3886 {"sbss_d", nds32_seg, SBSS_D_SECTION},
3887 {"sbss_w", nds32_seg, SBSS_W_SECTION},
3888 {"sbss_h", nds32_seg, SBSS_H_SECTION},
3889 {"sbss_b", nds32_seg, SBSS_B_SECTION},
3890 {"sbss_f", nds32_seg, SBSS_F_SECTION},
3891
3892 {"pic", nds32_enable_pic, 0},
3893 {"n12_hc", nds32_n12hc, 0},
3894 {"abi_1", nds32_set_abi, E_NDS_ABI_V1},
3895 {"abi_2", nds32_set_abi, E_NDS_ABI_AABI},
3896 /* Obsolete. */
3897 {"abi_2fp", nds32_set_abi, E_NDS_ABI_V2FP},
3898 {"abi_2fp_plus", nds32_set_abi, E_NDS_ABI_V2FP_PLUS},
3899 {"relax", nds32_relax_relocs, 1},
3900 {"no_relax", nds32_relax_relocs, 0},
3901 {"hint_func_args", nds32_set_hint_func_args, 0}, /* Abandon?? */
3902 {"omit_fp_begin", nds32_omit_fp_begin, 1},
3903 {"omit_fp_end", nds32_omit_fp_begin, 0},
3904 {"no_ex9_begin", nds32_no_ex9_begin, 1},
3905 {"no_ex9_end", nds32_no_ex9_begin, 0},
3906 {"vec_size", nds32_vec_size, 0},
3907 {"flag", nds32_flag, 0},
3908 {"innermost_loop_begin", nds32_loop_begin, 1},
3909 {"innermost_loop_end", nds32_loop_begin, 0},
3910 {"relax_hint", nds32_relax_hint, 0},
3911 {NULL, NULL, 0}
3912 };
3913
3914 void
3915 nds32_pre_do_align (int n, char *fill, int len, int max)
3916 {
3917 /* Only make a frag if we HAVE to... */
3918 fragS *fragP;
3919 if (n != 0 && !need_pass_2)
3920 {
3921 if (fill == NULL)
3922 {
3923 if (subseg_text_p (now_seg))
3924 {
3925 dwarf2_emit_insn (0);
3926 fragP = frag_now;
3927 frag_align_code (n, max);
3928
3929 /* Tag this alignment when there is a label before it. */
3930 if (label_exist)
3931 {
3932 fragP->tc_frag_data.flag = NDS32_FRAG_LABEL;
3933 label_exist = 0;
3934 }
3935 }
3936 else
3937 frag_align (n, 0, max);
3938 }
3939 else if (len <= 1)
3940 frag_align (n, *fill, max);
3941 else
3942 frag_align_pattern (n, fill, len, max);
3943 }
3944 }
3945
3946 void
3947 nds32_do_align (int n)
3948 {
3949 /* Optimize for space and label exists. */
3950 expressionS exp;
3951
3952 /* FIXME:I think this will break debug info sections and except_table. */
3953 if (!enable_relax_relocs || !subseg_text_p (now_seg))
3954 return;
3955
3956 /* Create and attach a BFD_RELOC_NDS32_LABEL fixup
3957 the size of instruction may not be correct because
3958 it could be relaxable. */
3959 exp.X_op = O_symbol;
3960 exp.X_add_symbol = section_symbol (now_seg);
3961 exp.X_add_number = n;
3962 fix_new_exp (frag_now,
3963 frag_now_fix (), 0, &exp, 0, BFD_RELOC_NDS32_LABEL);
3964 }
3965
3966 /* Supported Andes machines. */
3967 struct nds32_machs
3968 {
3969 enum bfd_architecture bfd_mach;
3970 int mach_flags;
3971 };
3972
3973 /* This is the callback for nds32-asm.c to parse operands. */
3974
3975 int
3976 nds32_asm_parse_operand (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED,
3977 struct nds32_asm_insn *pinsn,
3978 char **pstr, int64_t *value)
3979 {
3980 char *hold;
3981 expressionS *pexp = pinsn->info;
3982
3983 hold = input_line_pointer;
3984 input_line_pointer = *pstr;
3985 expression (pexp);
3986 *pstr = input_line_pointer;
3987 input_line_pointer = hold;
3988
3989 switch (pexp->X_op)
3990 {
3991 case O_symbol:
3992 *value = 0;
3993 return NASM_R_SYMBOL;
3994 case O_constant:
3995 *value = pexp->X_add_number;
3996 return NASM_R_CONST;
3997 case O_illegal:
3998 case O_absent:
3999 case O_register:
4000 default:
4001 return NASM_R_ILLEGAL;
4002 }
4003 }
4004
4005 /* GAS will call this function at the start of the assembly, after the command
4006 line arguments have been parsed and all the machine independent
4007 initializations have been completed. */
4008
4009 void
4010 md_begin (void)
4011 {
4012 struct nds32_keyword *k;
4013 unsigned int i;
4014
4015 bfd_set_arch_mach (stdoutput, TARGET_ARCH, nds32_baseline);
4016
4017 nds32_init_nds32_pseudo_opcodes ();
4018 asm_desc.parse_operand = nds32_asm_parse_operand;
4019 nds32_asm_init (&asm_desc, 0);
4020
4021 /* Initial general purpose registers hash table. */
4022 nds32_gprs_hash = hash_new ();
4023 for (k = keyword_gpr; k->name; k++)
4024 hash_insert (nds32_gprs_hash, k->name, k);
4025
4026 /* Initial branch hash table. */
4027 nds32_relax_info_hash = hash_new ();
4028 for (i = 0; i < ARRAY_SIZE (relax_table); i++)
4029 hash_insert (nds32_relax_info_hash, relax_table[i].opcode,
4030 &relax_table[i]);
4031
4032 /* Initial relax hint hash table. */
4033 nds32_hint_hash = hash_new ();
4034 enable_16bit = nds32_16bit_ext;
4035 }
4036
4037 /* HANDLE_ALIGN in write.c. */
4038
4039 void
4040 nds32_handle_align (fragS *fragp)
4041 {
4042 static const unsigned char nop16[] = { 0x92, 0x00 };
4043 static const unsigned char nop32[] = { 0x40, 0x00, 0x00, 0x09 };
4044 int bytes;
4045 char *p;
4046
4047 if (fragp->fr_type != rs_align_code)
4048 return;
4049
4050 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
4051 p = fragp->fr_literal + fragp->fr_fix;
4052
4053 if (bytes & 1)
4054 {
4055 *p++ = 0;
4056 bytes--;
4057 }
4058
4059 if (bytes & 2)
4060 {
4061 expressionS exp_t;
4062 exp_t.X_op = O_symbol;
4063 exp_t.X_add_symbol = abs_section_sym;
4064 exp_t.X_add_number = R_NDS32_INSN16_CONVERT_FLAG;
4065 fix_new_exp (fragp, fragp->fr_fix, 2, &exp_t, 0,
4066 BFD_RELOC_NDS32_INSN16);
4067 memcpy (p, nop16, 2);
4068 p += 2;
4069 bytes -= 2;
4070 }
4071
4072 while (bytes >= 4)
4073 {
4074 memcpy (p, nop32, 4);
4075 p += 4;
4076 bytes -= 4;
4077 }
4078
4079 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
4080 fragp->fr_fix += bytes;
4081 }
4082
4083 /* md_flush_pending_output */
4084
4085 void
4086 nds32_flush_pending_output (void)
4087 {
4088 nds32_last_label = NULL;
4089 }
4090
4091 void
4092 nds32_frob_label (symbolS *label)
4093 {
4094 dwarf2_emit_label (label);
4095 }
4096
4097 /* TC_START_LABEL */
4098
4099 int
4100 nds32_start_label (int asmdone ATTRIBUTE_UNUSED, int secdone ATTRIBUTE_UNUSED)
4101 {
4102 if (optimize && subseg_text_p (now_seg))
4103 label_exist = 1;
4104 return 1;
4105 }
4106
4107 /* TARGET_FORMAT */
4108
4109 const char *
4110 nds32_target_format (void)
4111 {
4112 #ifdef TE_LINUX
4113 if (target_big_endian)
4114 return "elf32-nds32be-linux";
4115 else
4116 return "elf32-nds32le-linux";
4117 #else
4118 if (target_big_endian)
4119 return "elf32-nds32be";
4120 else
4121 return "elf32-nds32le";
4122 #endif
4123 }
4124
4125 static enum nds32_br_range
4126 get_range_type (const struct nds32_field *field)
4127 {
4128 gas_assert (field != NULL);
4129
4130 if (field->bitpos != 0)
4131 return BR_RANGE_U4G;
4132
4133 if (field->bitsize == 24 && field->shift == 1)
4134 return BR_RANGE_S16M;
4135 else if (field->bitsize == 16 && field->shift == 1)
4136 return BR_RANGE_S64K;
4137 else if (field->bitsize == 14 && field->shift == 1)
4138 return BR_RANGE_S16K;
4139 else if (field->bitsize == 8 && field->shift == 1)
4140 return BR_RANGE_S256;
4141 else
4142 return BR_RANGE_U4G;
4143 }
4144
4145 /* Save pseudo instruction relocation list. */
4146
4147 static struct nds32_relocs_pattern*
4148 nds32_elf_save_pseudo_pattern (fixS* fixP, struct nds32_opcode *opcode,
4149 char *out, symbolS *sym,
4150 struct nds32_relocs_pattern *reloc_ptr,
4151 fragS *fragP)
4152 {
4153 if (!reloc_ptr)
4154 reloc_ptr = XNEW (struct nds32_relocs_pattern);
4155 reloc_ptr->seg = now_seg;
4156 reloc_ptr->sym = sym;
4157 reloc_ptr->frag = fragP;
4158 reloc_ptr->frchain = frchain_now;
4159 reloc_ptr->fixP = fixP;
4160 reloc_ptr->opcode = opcode;
4161 reloc_ptr->where = out;
4162 reloc_ptr->next = NULL;
4163 return reloc_ptr;
4164 }
4165
4166 /* Check X_md to transform relocation. */
4167
4168 static fixS*
4169 nds32_elf_record_fixup_exp (fragS *fragP, const char *str,
4170 const struct nds32_field *fld,
4171 expressionS *pexp, char* out,
4172 struct nds32_asm_insn *insn)
4173 {
4174 int reloc = -1;
4175 expressionS exp;
4176 fixS *fixP = NULL;
4177
4178 /* Handle instruction relocation. */
4179 if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_HI20))
4180 {
4181 /* Relocation for hi20 modifier. */
4182 switch (pexp->X_md)
4183 {
4184 case BFD_RELOC_NDS32_GOTOFF: /* @GOTOFF */
4185 reloc = BFD_RELOC_NDS32_GOTOFF_HI20;
4186 break;
4187 case BFD_RELOC_NDS32_GOT20: /* @GOT */
4188 reloc = BFD_RELOC_NDS32_GOT_HI20;
4189 break;
4190 case BFD_RELOC_NDS32_25_PLTREL: /* @PLT */
4191 if (!nds32_pic)
4192 as_bad (_("Invalid PIC expression."));
4193 else
4194 reloc = BFD_RELOC_NDS32_PLT_GOTREL_HI20;
4195 break;
4196 case BFD_RELOC_NDS32_GOTPC20: /* _GLOBAL_OFFSET_TABLE_ */
4197 reloc = BFD_RELOC_NDS32_GOTPC_HI20;
4198 break;
4199 case BFD_RELOC_NDS32_TPOFF: /* @TPOFF */
4200 reloc = BFD_RELOC_NDS32_TLS_LE_HI20;
4201 break;
4202 case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */
4203 reloc = BFD_RELOC_NDS32_TLS_IE_HI20;
4204 break;
4205 default: /* No suffix. */
4206 reloc = BFD_RELOC_NDS32_HI20;
4207 break;
4208 }
4209 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4210 insn->info, 0 /* pcrel */, reloc);
4211 }
4212 else if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_LO12))
4213 {
4214 /* Relocation for lo12 modifier. */
4215 if (fld->bitsize == 15 && fld->shift == 0)
4216 {
4217 /* [ls]bi || ori */
4218 switch (pexp->X_md)
4219 {
4220 case BFD_RELOC_NDS32_GOTOFF: /* @GOTOFF */
4221 reloc = BFD_RELOC_NDS32_GOTOFF_LO12;
4222 break;
4223 case BFD_RELOC_NDS32_GOT20: /* @GOT */
4224 reloc = BFD_RELOC_NDS32_GOT_LO12;
4225 break;
4226 case BFD_RELOC_NDS32_25_PLTREL: /* @PLT */
4227 if (!nds32_pic)
4228 as_bad (_("Invalid PIC expression."));
4229 else
4230 reloc = BFD_RELOC_NDS32_PLT_GOTREL_LO12;
4231 break;
4232 case BFD_RELOC_NDS32_GOTPC20: /* _GLOBAL_OFFSET_TABLE_ */
4233 reloc = BFD_RELOC_NDS32_GOTPC_LO12;
4234 break;
4235 case BFD_RELOC_NDS32_TPOFF: /* @TPOFF */
4236 reloc = BFD_RELOC_NDS32_TLS_LE_LO12;
4237 break;
4238 default: /* No suffix. */
4239 reloc = BFD_RELOC_NDS32_LO12S0;
4240 break;
4241 }
4242 }
4243 else if (fld->bitsize == 15 && fld->shift == 1)
4244 reloc = BFD_RELOC_NDS32_LO12S1; /* [ls]hi */
4245 else if (fld->bitsize == 15 && fld->shift == 2)
4246 {
4247 /* [ls]wi */
4248 switch (pexp->X_md)
4249 {
4250 case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */
4251 reloc = BFD_RELOC_NDS32_TLS_IE_LO12S2;
4252 break;
4253 default: /* No suffix. */
4254 reloc = BFD_RELOC_NDS32_LO12S2;
4255 break;
4256 }
4257 }
4258 else if (fld->bitsize == 15 && fld->shift == 3)
4259 reloc = BFD_RELOC_NDS32_LO12S3; /* [ls]di */
4260 else if (fld->bitsize == 12 && fld->shift == 2)
4261 reloc = R_NDS32_LO12S2_SP_RELA; /* f[ls][sd]i */
4262
4263 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4264 insn->info, 0 /* pcrel */, reloc);
4265 }
4266 else if (fld && fld->bitpos == 0 && insn->opcode->isize == 4
4267 && (insn->attr & NASM_ATTR_PCREL))
4268 {
4269 /* Relocation for 32-bit branch instructions. */
4270 if (fld->bitsize == 24 && fld->shift == 1)
4271 reloc = BFD_RELOC_NDS32_25_PCREL;
4272 else if (fld->bitsize == 16 && fld->shift == 1)
4273 reloc = BFD_RELOC_NDS32_17_PCREL;
4274 else if (fld->bitsize == 14 && fld->shift == 1)
4275 reloc = BFD_RELOC_NDS32_15_PCREL;
4276 else if (fld->bitsize == 8 && fld->shift == 1)
4277 reloc = BFD_RELOC_NDS32_WORD_9_PCREL;
4278 else
4279 abort ();
4280
4281 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4282 insn->info, 1 /* pcrel */, reloc);
4283 }
4284 else if (fld && fld->bitpos == 0 && insn->opcode->isize == 4
4285 && (insn->attr & NASM_ATTR_GPREL))
4286 {
4287 /* Relocation for 32-bit gp-relative instructions. */
4288 if (fld->bitsize == 19 && fld->shift == 0)
4289 reloc = BFD_RELOC_NDS32_SDA19S0;
4290 else if (fld->bitsize == 18 && fld->shift == 1)
4291 reloc = BFD_RELOC_NDS32_SDA18S1;
4292 else if (fld->bitsize == 17 && fld->shift == 2)
4293 reloc = BFD_RELOC_NDS32_SDA17S2;
4294 else
4295 abort ();
4296
4297 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4298 insn->info, 0 /* pcrel */, reloc);
4299 /* Insert INSN16 for converting fp_as_gp. */
4300 exp.X_op = O_symbol;
4301 exp.X_add_symbol = abs_section_sym;
4302 exp.X_add_number = 0;
4303 if (in_omit_fp && reloc == BFD_RELOC_NDS32_SDA17S2)
4304 fix_new_exp (fragP, out - fragP->fr_literal,
4305 insn->opcode->isize, &exp, 0 /* pcrel */,
4306 BFD_RELOC_NDS32_INSN16);
4307 }
4308 else if (fld && fld->bitpos == 0 && insn->opcode->isize == 2
4309 && (insn->attr & NASM_ATTR_PCREL))
4310 {
4311 /* Relocation for 16-bit branch instructions. */
4312 if (fld->bitsize == 8 && fld->shift == 1)
4313 reloc = BFD_RELOC_NDS32_9_PCREL;
4314 else
4315 abort ();
4316
4317 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4318 insn->info, 1 /* pcrel */, reloc);
4319 }
4320 else if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_IFC_EXT))
4321 {
4322 /* Relocation for ifcall instruction. */
4323 if (insn->opcode->isize == 2 && fld->bitsize == 9 && fld->shift == 1)
4324 reloc = BFD_RELOC_NDS32_10IFCU_PCREL;
4325 else if (insn->opcode->isize == 4 && fld->bitsize == 16
4326 && fld->shift == 1)
4327 reloc = BFD_RELOC_NDS32_17IFC_PCREL;
4328 else
4329 abort ();
4330
4331 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4332 insn->info, 1 /* pcrel */, reloc);
4333 }
4334 else if (fld)
4335 as_bad (_("Don't know how to handle this field. %s"), str);
4336
4337 return fixP;
4338 }
4339
4340 /* Build instruction pattern to relax. There are two type group pattern
4341 including pseudo instruction and relax hint. */
4342
4343 static void
4344 nds32_elf_build_relax_relation (fixS *fixP, expressionS *pexp, char* out,
4345 struct nds32_opcode *opcode, fragS *fragP,
4346 const struct nds32_field *fld)
4347 {
4348 struct nds32_relocs_pattern *reloc_ptr;
4349 struct nds32_relocs_group *group;
4350 symbolS *sym = NULL;
4351
4352 /* The expression may be used uninitialized. */
4353 if (fld)
4354 sym = pexp->X_add_symbol;
4355
4356 if (pseudo_opcode)
4357 {
4358 /* Save instruction relation for pseudo instruction expanding pattern. */
4359 reloc_ptr = nds32_elf_save_pseudo_pattern (fixP, opcode, out, sym,
4360 NULL, fragP);
4361 if (!relocs_list)
4362 relocs_list = reloc_ptr;
4363 else
4364 {
4365 struct nds32_relocs_pattern *temp = relocs_list;
4366 while (temp->next)
4367 temp = temp->next;
4368 temp->next = reloc_ptr;
4369 }
4370 }
4371 else if (nds32_relax_hint_current)
4372 {
4373 /* Save instruction relation by relax hint. */
4374 group = nds32_relax_hint_current;
4375 while (group)
4376 {
4377 nds32_elf_save_pseudo_pattern (fixP, opcode, out, sym,
4378 group->pattern, fragP);
4379 group = group->next;
4380 free (nds32_relax_hint_current);
4381 nds32_relax_hint_current = group;
4382 }
4383 }
4384
4385 /* Set relaxing false only for relax_hint trigger it. */
4386 if (!pseudo_opcode)
4387 relaxing = FALSE;
4388 }
4389
4390 #define N32_MEM_EXT(insn) ((N32_OP6_MEM << 25) | insn)
4391
4392 /* Relax pattern for link time relaxation. */
4393
4394 static struct nds32_relax_hint_table relax_ls_table[] =
4395 {
4396 {
4397 /* Set address: la -> sethi ori. */
4398 NDS32_RELAX_HINT_LA, /* main_type */
4399 8, /* relax_code_size */
4400 {
4401 OP6 (SETHI),
4402 OP6 (ORI),
4403 }, /* relax_code_seq */
4404 {
4405 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
4406 {4, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_INSN16}
4407 } /* relax_fixup */
4408 },
4409 {
4410 /* Set address: l.w -> sethi ori. */
4411 NDS32_RELAX_HINT_LS, /* main_type */
4412 8, /* relax_code_size */
4413 {
4414 OP6 (SETHI),
4415 OP6 (LBI),
4416 }, /* relax_code_seq */
4417 {
4418 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
4419 {4, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_INSN16}
4420 } /* relax_fixup */
4421 },
4422 {
4423 0,
4424 0,
4425 {0},
4426 {{0, 0 , 0, 0}}
4427 }
4428 };
4429
4430 /* Since sethi loadstore relocation has to using next instruction to determine
4431 elimination itself or not, we have to return the next instruction range. */
4432
4433 static int
4434 nds32_elf_sethi_range (struct nds32_relocs_pattern *pattern)
4435 {
4436 int range = 0;
4437 while (pattern)
4438 {
4439 switch (pattern->opcode->value)
4440 {
4441 case INSN_LBI:
4442 case INSN_SBI:
4443 case INSN_LBSI:
4444 case N32_MEM_EXT (N32_MEM_LB):
4445 case N32_MEM_EXT (N32_MEM_LBS):
4446 case N32_MEM_EXT (N32_MEM_SB):
4447 range = NDS32_LOADSTORE_BYTE;
4448 break;
4449 case INSN_LHI:
4450 case INSN_SHI:
4451 case INSN_LHSI:
4452 case N32_MEM_EXT (N32_MEM_LH):
4453 case N32_MEM_EXT (N32_MEM_LHS):
4454 case N32_MEM_EXT (N32_MEM_SH):
4455 range = NDS32_LOADSTORE_HALF;
4456 break;
4457 case INSN_LWI:
4458 case INSN_SWI:
4459 case N32_MEM_EXT (N32_MEM_LW):
4460 case N32_MEM_EXT (N32_MEM_SW):
4461 range = NDS32_LOADSTORE_WORD;
4462 break;
4463 case INSN_FLSI:
4464 case INSN_FSSI:
4465 range = NDS32_LOADSTORE_FLOAT_S;
4466 break;
4467 case INSN_FLDI:
4468 case INSN_FSDI:
4469 range = NDS32_LOADSTORE_FLOAT_D;
4470 break;
4471 case INSN_ORI:
4472 range = NDS32_LOADSTORE_IMM;
4473 break;
4474 default:
4475 range = NDS32_LOADSTORE_NONE;
4476 break;
4477 }
4478 if (range != NDS32_LOADSTORE_NONE)
4479 break;
4480 pattern = pattern->next;
4481 }
4482 return range;
4483 }
4484
4485 /* The args means: instruction size, the 1st instruction is converted to 16 or
4486 not, optimize option, 16 bit instruction is enable. */
4487 #define SET_ADDEND(size, convertible, optimize, insn16_on) \
4488 (((size) & 0xff) | ((convertible) ? 1 << 31 : 0) \
4489 | ((optimize) ? 1<< 30 : 0) | (insn16_on ? 1 << 29 : 0))
4490
4491 static void
4492 nds32_set_elf_flags_by_insn (struct nds32_asm_insn * insn)
4493 {
4494 /* Set E_NDS32_HAS_EXT_INST. */
4495 if (insn->opcode->attr & NASM_ATTR_PERF_EXT)
4496 {
4497 if (nds32_perf_ext)
4498 nds32_elf_flags |= E_NDS32_HAS_EXT_INST;
4499 else
4500 as_bad (_("instruction %s requires enabling performance extension"),
4501 insn->opcode->opcode);
4502 }
4503 else if (insn->opcode->attr & NASM_ATTR_PERF2_EXT)
4504 {
4505 if (nds32_perf_ext2)
4506 nds32_elf_flags |= E_NDS32_HAS_EXT2_INST;
4507 else
4508 as_bad (_("instruction %s requires enabling performance extension II"),
4509 insn->opcode->opcode);
4510 }
4511 else if (insn->opcode->attr & NASM_ATTR_AUDIO_ISAEXT)
4512 {
4513 if (nds32_audio_ext)
4514 nds32_elf_flags |= E_NDS32_HAS_AUDIO_INST;
4515 else
4516 as_bad (_("instruction %s requires enabling AUDIO extension"),
4517 insn->opcode->opcode);
4518 }
4519 else if (insn->opcode->attr & NASM_ATTR_STR_EXT)
4520 {
4521 if (nds32_string_ext)
4522 nds32_elf_flags |= E_NDS32_HAS_STRING_INST;
4523 else
4524 as_bad (_("instruction %s requires enabling STRING extension"),
4525 insn->opcode->opcode);
4526 }
4527 else if ((insn->opcode->attr & NASM_ATTR_DIV)
4528 && (insn->opcode->attr & NASM_ATTR_DXREG))
4529 {
4530 if (nds32_div && nds32_dx_regs)
4531 nds32_elf_flags |= E_NDS32_HAS_DIV_DX_INST;
4532 else
4533 as_bad (_("instruction %s requires enabling DIV & DX_REGS extension"),
4534 insn->opcode->opcode);
4535 }
4536 else if (insn->opcode->attr & NASM_ATTR_FPU)
4537 {
4538 if (nds32_fpu_sp_ext || nds32_fpu_dp_ext)
4539 {
4540 if (!(nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST)))
4541 nds32_fpu_com = 1;
4542 }
4543 else
4544 as_bad (_("instruction %s requires enabling FPU extension"),
4545 insn->opcode->opcode);
4546 }
4547 else if (insn->opcode->attr & NASM_ATTR_FPU_SP_EXT)
4548 {
4549 if (nds32_fpu_sp_ext)
4550 nds32_elf_flags |= E_NDS32_HAS_FPU_INST;
4551 else
4552 as_bad (_("instruction %s requires enabling FPU_SP extension"),
4553 insn->opcode->opcode);
4554 }
4555 else if ((insn->opcode->attr & NASM_ATTR_FPU_SP_EXT)
4556 && (insn->opcode->attr & NASM_ATTR_MAC))
4557 {
4558 if (nds32_fpu_sp_ext && nds32_mac)
4559 {
4560 nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST;
4561 nds32_elf_flags |= E_NDS32_HAS_FPU_INST;
4562 }
4563 else
4564 as_bad (_("instruction %s requires enabling FPU_MAC extension"),
4565 insn->opcode->opcode);
4566 }
4567 else if (insn->opcode->attr & NASM_ATTR_FPU_DP_EXT)
4568 {
4569 if (nds32_fpu_dp_ext)
4570 nds32_elf_flags |= E_NDS32_HAS_FPU_DP_INST;
4571 else
4572 as_bad (_("instruction %s requires enabling FPU_DP extension"),
4573 insn->opcode->opcode);
4574 }
4575 else if ((insn->opcode->attr & NASM_ATTR_FPU_DP_EXT)
4576 && (insn->opcode->attr & NASM_ATTR_MAC))
4577 {
4578 if (nds32_fpu_dp_ext && nds32_mac)
4579 {
4580 nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST;
4581 nds32_elf_flags |= E_NDS32_HAS_FPU_DP_INST;
4582 }
4583 else
4584 as_bad (_("instruction %s requires enabling FPU_MAC extension"),
4585 insn->opcode->opcode);
4586 }
4587 /* TODO: FPU_BOTH */
4588 else if ((insn->opcode->attr & NASM_ATTR_MAC)
4589 && (insn->opcode->attr & NASM_ATTR_DXREG))
4590 {
4591 if (nds32_mac && nds32_dx_regs)
4592 nds32_elf_flags |= E_NDS32_HAS_MAC_DX_INST;
4593 else
4594 as_bad (_("instruction %s requires enabling DX_REGS extension"),
4595 insn->opcode->opcode);
4596 }
4597 /* TODO: for DX_REG set but not for MAC, DIV, AUDIO */
4598 else if (insn->opcode->attr & NASM_ATTR_IFC_EXT)
4599 {
4600 nds32_elf_flags |= E_NDS32_HAS_IFC_INST;
4601 }
4602 /* TODO: E_NDS32_HAS_SATURATION_INST */
4603 }
4604
4605 /* Flag for analysis relaxation type. */
4606
4607 enum nds32_insn_type
4608 {
4609 N32_RELAX_SETHI = 1,
4610 N32_RELAX_BR = (1 << 1),
4611 N32_RELAX_LSI = (1 << 2),
4612 N32_RELAX_JUMP = (1 << 3),
4613 N32_RELAX_CALL = (1 << 4),
4614 N32_RELAX_ORI = (1 << 5),
4615 N32_RELAX_MEM = (1 << 6),
4616 N32_RELAX_MOVI = (1 << 7),
4617 };
4618
4619 struct nds32_hint_map
4620 {
4621 bfd_reloc_code_real_type hi_type;
4622 const char *opc;
4623 enum nds32_relax_hint_type hint_type;
4624 enum nds32_br_range range;
4625 enum nds32_insn_type insn_list;
4626 };
4627
4628 /* Table to match instructions with hint and relax pattern. */
4629
4630 static struct nds32_hint_map hint_map [] =
4631 {
4632 {
4633 /* LONGCALL4. */
4634 BFD_RELOC_NDS32_HI20,
4635 "jal",
4636 NDS32_RELAX_HINT_NONE,
4637 BR_RANGE_U4G,
4638 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL
4639 },
4640 {
4641 /* LONGCALL5. */
4642 _dummy_first_bfd_reloc_code_real,
4643 "bgezal",
4644 NDS32_RELAX_HINT_NONE,
4645 BR_RANGE_S16M,
4646 N32_RELAX_BR | N32_RELAX_CALL
4647 },
4648 {
4649 /* LONGCALL6. */
4650 BFD_RELOC_NDS32_HI20,
4651 "bgezal",
4652 NDS32_RELAX_HINT_NONE,
4653 BR_RANGE_U4G,
4654 N32_RELAX_BR | N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL
4655 },
4656 {
4657 /* LONGJUMP4. */
4658 BFD_RELOC_NDS32_HI20,
4659 "j",
4660 NDS32_RELAX_HINT_NONE,
4661 BR_RANGE_U4G,
4662 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_JUMP
4663 },
4664 {
4665 /* LONGJUMP5. */
4666 /* There is two kinds of variations of LONGJUMP5. One of them
4667 generate EMPTY relocation for converted INSN16 if needed.
4668 But we don't distinguish them here. */
4669 _dummy_first_bfd_reloc_code_real,
4670 "beq",
4671 NDS32_RELAX_HINT_NONE,
4672 BR_RANGE_S16M,
4673 N32_RELAX_BR | N32_RELAX_JUMP
4674 },
4675 {
4676 /* LONGJUMP6. */
4677 BFD_RELOC_NDS32_HI20,
4678 "beq",
4679 NDS32_RELAX_HINT_NONE,
4680 BR_RANGE_U4G,
4681 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_BR | N32_RELAX_JUMP
4682 },
4683 {
4684 /* LONGJUMP7. */
4685 _dummy_first_bfd_reloc_code_real,
4686 "beqc",
4687 NDS32_RELAX_HINT_NONE,
4688 BR_RANGE_S16K,
4689 N32_RELAX_MOVI | N32_RELAX_BR
4690 },
4691 {
4692 /* LOADSTORE ADDRESS. */
4693 BFD_RELOC_NDS32_HI20,
4694 NULL,
4695 NDS32_RELAX_HINT_LA,
4696 BR_RANGE_U4G,
4697 N32_RELAX_SETHI | N32_RELAX_ORI
4698 },
4699 {
4700 /* LOADSTORE ADDRESS. */
4701 BFD_RELOC_NDS32_HI20,
4702 NULL,
4703 NDS32_RELAX_HINT_LS,
4704 BR_RANGE_U4G,
4705 N32_RELAX_SETHI | N32_RELAX_LSI
4706 },
4707 {0, NULL, 0, 0 ,0}
4708 };
4709
4710 /* Find the relaxation pattern according to instructions. */
4711
4712 static bfd_boolean
4713 nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern,
4714 struct nds32_relax_hint_table *hint_info)
4715 {
4716 unsigned int opcode, seq_size;
4717 enum nds32_br_range range;
4718 struct nds32_relocs_pattern *pattern, *hi_pattern = NULL;
4719 const char *opc = NULL;
4720 relax_info_t *relax_info = NULL;
4721 nds32_relax_fixup_info_t *fixup_info, *hint_fixup;
4722 enum nds32_relax_hint_type hint_type = NDS32_RELAX_HINT_NONE;
4723 struct nds32_relax_hint_table *table_ptr;
4724 uint32_t *code_seq, *hint_code;
4725 enum nds32_insn_type relax_type = 0;
4726 struct nds32_hint_map *map_ptr = hint_map;
4727 unsigned int i;
4728 const char *check_insn[] =
4729 { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8" };
4730
4731 /* TODO: PLT GOT. */
4732 /* Traverse all pattern instruction and set flag. */
4733 pattern = relocs_pattern;
4734 while (pattern)
4735 {
4736 if (pattern->opcode->isize == 4)
4737 {
4738 /* 4 byte instruction. */
4739 opcode = N32_OP6 (pattern->opcode->value);
4740 switch (opcode)
4741 {
4742 case N32_OP6_SETHI:
4743 hi_pattern = pattern;
4744 relax_type |= N32_RELAX_SETHI;
4745 break;
4746 case N32_OP6_MEM:
4747 relax_type |= N32_RELAX_MEM;
4748 break;
4749 case N32_OP6_ORI:
4750 relax_type |= N32_RELAX_ORI;
4751 break;
4752 case N32_OP6_BR1:
4753 case N32_OP6_BR2:
4754 case N32_OP6_BR3:
4755 relax_type |= N32_RELAX_BR;
4756 break;
4757 case N32_OP6_MOVI:
4758 relax_type |= N32_RELAX_MOVI;
4759 break;
4760 case N32_OP6_LBI:
4761 case N32_OP6_SBI:
4762 case N32_OP6_LBSI:
4763 case N32_OP6_LHI:
4764 case N32_OP6_SHI:
4765 case N32_OP6_LHSI:
4766 case N32_OP6_LWI:
4767 case N32_OP6_SWI:
4768 case N32_OP6_LWC:
4769 case N32_OP6_SWC:
4770 relax_type |= N32_RELAX_LSI;
4771 break;
4772 case N32_OP6_JREG:
4773 if (__GF (pattern->opcode->value, 0, 1) == 1)
4774 relax_type |= N32_RELAX_CALL;
4775 else
4776 relax_type |= N32_RELAX_JUMP;
4777 break;
4778 case N32_OP6_JI:
4779 if (__GF (pattern->opcode->value, 24, 1) == 1)
4780 relax_type |= N32_RELAX_CALL;
4781 else
4782 relax_type |= N32_RELAX_JUMP;
4783 break;
4784 default:
4785 as_warn (_("relax hint unrecognized instruction: line %d."),
4786 pattern->frag->fr_line);
4787 return FALSE;
4788 }
4789 }
4790 else
4791 {
4792 /* 2 byte instruction. Compare by opcode name because the opcode of
4793 2byte instruction is not regular. */
4794 for (i = 0; i < sizeof (check_insn) / sizeof (check_insn[0]); i++)
4795 {
4796 if (strcmp (pattern->opcode->opcode, check_insn[i]) == 0)
4797 {
4798 relax_type |= N32_RELAX_BR;
4799 break;
4800 }
4801 }
4802 if (strcmp (pattern->opcode->opcode, "movi55") == 0)
4803 relax_type |= N32_RELAX_MOVI;
4804 }
4805 pattern = pattern->next;
4806 }
4807
4808 /* Analysis instruction flag to choose relaxation table. */
4809 while (map_ptr->insn_list != 0)
4810 {
4811 if (map_ptr->insn_list == relax_type
4812 && (!hi_pattern
4813 || (hi_pattern->fixP
4814 && hi_pattern->fixP->fx_r_type == map_ptr->hi_type)))
4815 {
4816 opc = map_ptr->opc;
4817 hint_type = map_ptr->hint_type;
4818 range = map_ptr->range;
4819 break;
4820 }
4821 map_ptr++;
4822 }
4823
4824 if (map_ptr->insn_list == 0)
4825 {
4826 as_warn (_("Can not find match relax hint. Line: %d"),
4827 relocs_pattern->frag->fr_line);
4828 return FALSE;
4829 }
4830
4831 /* Get the match table. */
4832 if (opc)
4833 {
4834 /* Branch relax pattern. */
4835 relax_info = hash_find (nds32_relax_info_hash, opc);
4836 if (!relax_info)
4837 return FALSE;
4838 fixup_info = relax_info->relax_fixup[range];
4839 code_seq = relax_info->relax_code_seq[range];
4840 seq_size = relax_info->relax_code_size[range];
4841 }
4842 else if (hint_type)
4843 {
4844 /* Load-store relax pattern. */
4845 table_ptr = relax_ls_table;
4846 while (table_ptr->main_type != 0)
4847 {
4848 if (table_ptr->main_type == hint_type)
4849 {
4850 fixup_info = table_ptr->relax_fixup;
4851 code_seq = table_ptr->relax_code_seq;
4852 seq_size = table_ptr->relax_code_size;
4853 break;
4854 }
4855 table_ptr++;
4856 }
4857 if (table_ptr->main_type == 0)
4858 return FALSE;
4859 }
4860 else
4861 return FALSE;
4862
4863 hint_fixup = hint_info->relax_fixup;
4864 hint_code = hint_info->relax_code_seq;
4865 hint_info->relax_code_size = seq_size;
4866
4867 while (fixup_info->size != 0)
4868 {
4869 if (fixup_info->ramp & NDS32_HINT)
4870 {
4871 memcpy (hint_fixup, fixup_info, sizeof (nds32_relax_fixup_info_t));
4872 hint_fixup++;
4873 }
4874 fixup_info++;
4875 }
4876 /* Clear final relocation. */
4877 memset (hint_fixup, 0, sizeof (nds32_relax_fixup_info_t));
4878 /* Copy code sequence. */
4879 memcpy (hint_code, code_seq, seq_size);
4880 return TRUE;
4881 }
4882
4883 /* Because there are a lot of variant of load-store, check
4884 all these type here. */
4885
4886 #define CLEAN_REG(insn) ((insn) & 0xff0003ff)
4887 static bfd_boolean
4888 nds32_match_hint_insn (struct nds32_opcode *opcode, uint32_t seq)
4889 {
4890 const char *check_insn[] =
4891 { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8" };
4892 uint32_t insn = opcode->value;
4893 unsigned int i;
4894
4895 insn = CLEAN_REG (opcode->value);
4896 if (insn == seq)
4897 return TRUE;
4898
4899 switch (seq)
4900 {
4901 case OP6 (LBI):
4902 /* In relocation_table, it regards instruction LBI as representation
4903 of all the NDS32_RELAX_HINT_LS pattern. */
4904 if (insn == OP6 (LBI) || insn == OP6 (SBI) || insn == OP6 (LBSI)
4905 || insn == OP6 (LHI) || insn == OP6 (SHI) || insn == OP6 (LHSI)
4906 || insn == OP6 (LWI) || insn == OP6 (SWI)
4907 || insn == OP6 (LWC) || insn == OP6 (SWC))
4908 return TRUE;
4909 break;
4910 case OP6 (BR2):
4911 /* This is for LONGCALL5 and LONGCALL6. */
4912 if (insn == OP6 (BR2))
4913 return TRUE;
4914 break;
4915 case OP6 (BR1):
4916 /* This is for LONGJUMP5 and LONGJUMP6. */
4917 if (opcode->isize == 4
4918 && (insn == OP6 (BR1) || insn == OP6 (BR2) || insn == OP6 (BR3)))
4919 return TRUE;
4920 else if (opcode->isize == 2)
4921 {
4922 for (i = 0; i < sizeof (check_insn) / sizeof (check_insn[0]); i++)
4923 if (strcmp (opcode->opcode, check_insn[i]) == 0)
4924 return TRUE;
4925 }
4926 break;
4927 case OP6 (MOVI):
4928 /* This is for LONGJUMP7. */
4929 if (opcode->isize == 2 && strcmp (opcode->opcode, "movi55") == 0)
4930 return TRUE;
4931 break;
4932 }
4933 return FALSE;
4934 }
4935
4936 /* Append relax relocation for link time relaxing. */
4937
4938 static void
4939 nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value)
4940 {
4941 struct nds32_relocs_pattern *relocs_pattern =
4942 (struct nds32_relocs_pattern *) value;
4943 struct nds32_relocs_pattern *pattern_temp, *pattern_now;
4944 symbolS *sym, *hi_sym = NULL;
4945 expressionS exp;
4946 fragS *fragP;
4947 segT seg_bak = now_seg;
4948 frchainS *frchain_bak = frchain_now;
4949 struct nds32_relax_hint_table hint_info;
4950 nds32_relax_fixup_info_t *hint_fixup, *fixup_now;
4951 size_t fixup_size;
4952 offsetT branch_offset;
4953 fixS *fixP;
4954 int range, offset;
4955 unsigned int ptr_offset, hint_count, relax_code_size, count = 0;
4956 uint32_t *code_seq, code_insn;
4957 char *where;
4958 int pcrel;
4959
4960 if (!relocs_pattern)
4961 return;
4962
4963 if (!nds32_find_reloc_table (relocs_pattern, &hint_info))
4964 return;
4965
4966 /* Save symbol for some EMPTY relocation using. */
4967 pattern_now = relocs_pattern;
4968 while (pattern_now)
4969 {
4970 if (pattern_now->opcode->value == OP6 (SETHI))
4971 {
4972 hi_sym = pattern_now->sym;
4973 break;
4974 }
4975 pattern_now = pattern_now->next;
4976 }
4977
4978 /* Inserting fix up must specify now_seg or frchain_now. */
4979 now_seg = relocs_pattern->seg;
4980 frchain_now = relocs_pattern->frchain;
4981 fragP = relocs_pattern->frag;
4982 branch_offset = fragP->fr_offset;
4983
4984 hint_fixup = hint_info.relax_fixup;
4985 code_seq = hint_info.relax_code_seq;
4986 relax_code_size = hint_info.relax_code_size;
4987 pattern_now = relocs_pattern;
4988
4989 /* Insert relaxation. */
4990 exp.X_op = O_symbol;
4991
4992 while (pattern_now)
4993 {
4994 /* Choose the match fixup by instruction. */
4995 code_insn = CLEAN_REG (*(code_seq + count));
4996 if (!nds32_match_hint_insn (pattern_now->opcode, code_insn))
4997 {
4998 count = 0;
4999 code_insn = CLEAN_REG (*(code_seq + count));
5000
5001 while (!nds32_match_hint_insn (pattern_now->opcode, code_insn))
5002 {
5003 count++;
5004 if (count >= relax_code_size / 4)
5005 {
5006 as_bad (_("Internal error: Relax hint error. %s: %x"),
5007 now_seg->name, pattern_now->opcode->value);
5008 goto restore;
5009 }
5010 code_insn = CLEAN_REG (*(code_seq + count));
5011 }
5012 }
5013 fragP = pattern_now->frag;
5014 sym = pattern_now->sym;
5015 branch_offset = fragP->fr_offset;
5016 offset = count * 4;
5017 where = pattern_now->where;
5018 /* Find the instruction map fix. */
5019 fixup_now = hint_fixup;
5020 while (fixup_now->offset != offset)
5021 {
5022 fixup_now++;
5023 if (fixup_now->size == 0)
5024 break;
5025 }
5026 /* This element is without relaxation relocation. */
5027 if (fixup_now->size == 0)
5028 {
5029 pattern_now = pattern_now->next;
5030 continue;
5031 }
5032 fixup_size = fixup_now->size;
5033
5034 /* Insert all fixup. */
5035 while (fixup_size != 0 && fixup_now->offset == offset)
5036 {
5037 /* Set the real instruction size in element. */
5038 fixup_size = pattern_now->opcode->isize;
5039 pcrel = ((fixup_now->ramp & NDS32_PCREL) != 0) ? 1 : 0;
5040 if (fixup_now->ramp & NDS32_FIX)
5041 {
5042 /* Convert original relocation. */
5043 pattern_now->fixP->fx_r_type = fixup_now->r_type ;
5044 fixup_size = 0;
5045 }
5046 else if ((fixup_now->ramp & NDS32_PTR) != 0)
5047 {
5048 /* This relocation has to point to another instruction. Make
5049 sure each resolved relocation has to be pointed. */
5050 pattern_temp = relocs_pattern;
5051 /* All instruction in relax_table should be 32-bit. */
5052 hint_count = hint_info.relax_code_size / 4;
5053 code_insn = CLEAN_REG (*(code_seq + hint_count - 1));
5054 while (pattern_temp)
5055 {
5056 /* Point to every resolved relocation. */
5057 if (nds32_match_hint_insn (pattern_temp->opcode, code_insn))
5058 {
5059 ptr_offset =
5060 pattern_temp->where - pattern_temp->frag->fr_literal;
5061 exp.X_add_symbol = symbol_temp_new (now_seg, ptr_offset,
5062 pattern_temp->frag);
5063 exp.X_add_number = 0;
5064 fixP =
5065 fix_new_exp (fragP, where - fragP->fr_literal,
5066 fixup_size, &exp, 0, fixup_now->r_type);
5067 fixP->fx_addnumber = fixP->fx_offset;
5068 }
5069 pattern_temp = pattern_temp->next;
5070 }
5071 fixup_size = 0;
5072 }
5073 else if (fixup_now->ramp & NDS32_ADDEND)
5074 {
5075 range = nds32_elf_sethi_range (relocs_pattern);
5076 if (range == NDS32_LOADSTORE_NONE)
5077 {
5078 as_bad (_("Internal error: Range error. %s"), now_seg->name);
5079 return;
5080 }
5081 exp.X_add_symbol = abs_section_sym;
5082 exp.X_add_number = SET_ADDEND (4, 0, optimize, enable_16bit);
5083 exp.X_add_number |= ((range & 0x3f) << 8);
5084 }
5085 else if ((fixup_now->ramp & NDS32_ABS) != 0)
5086 {
5087 /* This is a tag relocation. */
5088 exp.X_add_symbol = abs_section_sym;
5089 exp.X_add_number = 0;
5090 }
5091 else if ((fixup_now->ramp & NDS32_INSN16) != 0)
5092 {
5093 if (!enable_16bit)
5094 fixup_size = 0;
5095 /* This is a tag relocation. */
5096 exp.X_add_symbol = abs_section_sym;
5097 exp.X_add_number = 0;
5098 }
5099 else if ((fixup_now->ramp & NDS32_SYM) != 0)
5100 {
5101 /* For EMPTY relocation save the true symbol. */
5102 exp.X_add_symbol = hi_sym;
5103 exp.X_add_number = branch_offset;
5104 }
5105 else
5106 {
5107 exp.X_add_symbol = sym;
5108 exp.X_add_number = branch_offset;
5109 }
5110
5111 if (fixup_size != 0)
5112 {
5113 fixP = fix_new_exp (fragP, where - fragP->fr_literal, fixup_size,
5114 &exp, pcrel, fixup_now->r_type);
5115 fixP->fx_addnumber = fixP->fx_offset;
5116 }
5117 fixup_now++;
5118 fixup_size = fixup_now->size;
5119 }
5120 if (count < relax_code_size / 4)
5121 count++;
5122 pattern_now = pattern_now->next;
5123 }
5124
5125 restore:
5126 now_seg = seg_bak;
5127 frchain_now = frchain_bak;
5128 }
5129
5130 /* Check instruction if it can be used for the baseline. */
5131
5132 static bfd_boolean
5133 nds32_check_insn_available (struct nds32_asm_insn insn, const char *str)
5134 {
5135 int attr = insn.attr & ATTR_ALL;
5136 static int baseline_isa = 0;
5137 /* No isa setting or all isa can use. */
5138 if (attr == 0 || attr == ATTR_ALL)
5139 return TRUE;
5140
5141 if (baseline_isa == 0)
5142 {
5143 /* Map option baseline and instruction attribute. */
5144 switch (nds32_baseline)
5145 {
5146 case ISA_V2:
5147 baseline_isa = ATTR (ISA_V2);
5148 break;
5149 case ISA_V3:
5150 baseline_isa = ATTR (ISA_V3);
5151 break;
5152 case ISA_V3M:
5153 baseline_isa = ATTR (ISA_V3M);
5154 break;
5155 }
5156 }
5157
5158 if ((baseline_isa & attr) == 0)
5159 {
5160 as_bad (_("Instruction %s not supported in the baseline."), str);
5161 return FALSE;
5162 }
5163 return TRUE;
5164 }
5165
5166 /* Stub of machine dependent. */
5167
5168 void
5169 md_assemble (char *str)
5170 {
5171 struct nds32_asm_insn insn;
5172 expressionS expr;
5173 char *out;
5174 struct nds32_pseudo_opcode *popcode;
5175 const struct nds32_field *fld = NULL;
5176 fixS *fixP;
5177 uint16_t insn_16;
5178 struct nds32_relocs_pattern *relocs_temp;
5179 expressionS *pexp;
5180 fragS *fragP;
5181 int label = label_exist;
5182
5183 popcode = nds32_lookup_pseudo_opcode (str);
5184 /* Note that we need to check 'verbatim' and
5185 'opcode->physical_op'. If the assembly content is generated by
5186 compiler and this opcode is a physical instruction, there is no
5187 need to perform pseudo instruction expansion/transformation. */
5188 if (popcode && !(verbatim && popcode->physical_op))
5189 {
5190 pseudo_opcode = TRUE;
5191 nds32_pseudo_opcode_wrapper (str, popcode);
5192 pseudo_opcode = FALSE;
5193 nds32_elf_append_relax_relocs (NULL, relocs_list);
5194
5195 /* Free pseudo list. */
5196 relocs_temp = relocs_list;
5197 while (relocs_temp)
5198 {
5199 relocs_list = relocs_list->next;
5200 free (relocs_temp);
5201 relocs_temp = relocs_list;
5202 }
5203
5204 return;
5205 }
5206
5207 label_exist = 0;
5208 insn.info = & expr;
5209 asm_desc.result = NASM_OK;
5210 nds32_assemble (&asm_desc, &insn, str);
5211
5212 switch (asm_desc.result)
5213 {
5214 case NASM_ERR_UNKNOWN_OP:
5215 as_bad (_("Unrecognized opcode, %s."), str);
5216 return;
5217 case NASM_ERR_SYNTAX:
5218 as_bad (_("Incorrect syntax, %s."), str);
5219 return;
5220 case NASM_ERR_OPERAND:
5221 as_bad (_("Unrecognized operand/register, %s."), str);
5222 return;
5223 case NASM_ERR_OUT_OF_RANGE:
5224 as_bad (_("Operand out of range, %s."), str);
5225 return;
5226 case NASM_ERR_REG_REDUCED:
5227 as_bad (_("Prohibited register used for reduced-register, %s."), str);
5228 return;
5229 case NASM_ERR_JUNK_EOL:
5230 as_bad (_("Junk at end of line, %s."), str);
5231 return;
5232 }
5233
5234 gas_assert (insn.opcode);
5235
5236 nds32_set_elf_flags_by_insn (&insn);
5237
5238 gas_assert (insn.opcode->isize == 4 || insn.opcode->isize == 2);
5239
5240 if (!nds32_check_insn_available (insn, str))
5241 return;
5242
5243 /* Make sure the beginning of text being 2-byte align. */
5244 nds32_adjust_label (1);
5245 fld = insn.field;
5246 /* Try to allocate the max size to guarantee relaxable same branch
5247 instructions in the same fragment. */
5248 frag_grow (NDS32_MAXCHAR);
5249 fragP = frag_now;
5250 if (fld && (insn.attr & NASM_ATTR_BRANCH)
5251 && (pseudo_opcode || (insn.opcode->value != INSN_JAL
5252 && insn.opcode->value != INSN_J))
5253 && (!verbatim || pseudo_opcode))
5254 {
5255 /* User assembly code branch relax for it. */
5256 /* If fld is not NULL, it is a symbol. */
5257 /* Branch must relax to proper pattern in user assembly code exclude
5258 J and JAL. Keep these two in original type for users which wants
5259 to keep their size be fixed. In general, assembler does not convert
5260 instruction generated by compiler. But jump instruction may be
5261 truncated in text virtual model. For workaround, compiler generate
5262 pseudo jump to fix this issue currently. */
5263
5264 /* Get branch range type. */
5265 dwarf2_emit_insn (0);
5266 enum nds32_br_range range_type;
5267
5268 pexp = insn.info;
5269 range_type = get_range_type (fld);
5270
5271 out = frag_var (rs_machine_dependent, NDS32_MAXCHAR,
5272 0, /* VAR is un-used. */
5273 range_type, /* SUBTYPE is used as range type. */
5274 pexp->X_add_symbol, pexp->X_add_number, 0);
5275
5276 fragP->fr_fix += insn.opcode->isize;
5277 fragP->tc_frag_data.opcode = insn.opcode;
5278 fragP->tc_frag_data.insn = insn.insn;
5279 if (insn.opcode->isize == 4)
5280 bfd_putb32 (insn.insn, out);
5281 else if (insn.opcode->isize == 2)
5282 bfd_putb16 (insn.insn, out);
5283 fragP->tc_frag_data.flag |= NDS32_FRAG_BRANCH;
5284 return;
5285 /* md_convert_frag will insert relocations. */
5286 }
5287 else if (!relaxing && enable_16bit && (optimize || optimize_for_space)
5288 && ((!fld && !verbatim && insn.opcode->isize == 4
5289 && nds32_convert_32_to_16 (stdoutput, insn.insn, &insn_16, NULL))
5290 || (insn.opcode->isize == 2
5291 && nds32_convert_16_to_32 (stdoutput, insn.insn, NULL))))
5292 {
5293 /* Record this one is relaxable. */
5294 pexp = insn.info;
5295 dwarf2_emit_insn (0);
5296 if (fld)
5297 {
5298 out = frag_var (rs_machine_dependent,
5299 4, /* Max size is 32-bit instruction. */
5300 0, /* VAR is un-used. */
5301 0, pexp->X_add_symbol, pexp->X_add_number, 0);
5302 fragP->tc_frag_data.flag |= NDS32_FRAG_RELAXABLE_BRANCH;
5303 }
5304 else
5305 out = frag_var (rs_machine_dependent,
5306 4, /* Max size is 32-bit instruction. */
5307 0, /* VAR is un-used. */
5308 0, NULL, 0, NULL);
5309 fragP->tc_frag_data.flag |= NDS32_FRAG_RELAXABLE;
5310 fragP->tc_frag_data.opcode = insn.opcode;
5311 fragP->tc_frag_data.insn = insn.insn;
5312 fragP->fr_fix += 2;
5313
5314 /* In original, we don't relax the instruction with label on it,
5315 but this may cause some redundant nop16. Therefore, tag this
5316 relaxable instruction and relax it carefully. */
5317 if (label)
5318 fragP->tc_frag_data.flag |= NDS32_FRAG_LABEL;
5319
5320 if (insn.opcode->isize == 4)
5321 bfd_putb16 (insn_16, out);
5322 else if (insn.opcode->isize == 2)
5323 bfd_putb16 (insn.insn, out);
5324 return;
5325 }
5326 else if ((verbatim || !relaxing) && optimize && label)
5327 {
5328 /* This instruction is with label. */
5329 expressionS exp;
5330 out = frag_var (rs_machine_dependent, insn.opcode->isize,
5331 0, 0, NULL, 0, NULL);
5332 /* If this instruction is branch target, it is not relaxable. */
5333 fragP->tc_frag_data.flag = NDS32_FRAG_LABEL;
5334 fragP->tc_frag_data.opcode = insn.opcode;
5335 fragP->tc_frag_data.insn = insn.insn;
5336 fragP->fr_fix += insn.opcode->isize;
5337 if (insn.opcode->isize == 4)
5338 {
5339 exp.X_op = O_symbol;
5340 exp.X_add_symbol = abs_section_sym;
5341 exp.X_add_number = 0;
5342 fixP = fix_new_exp (fragP, fragP->fr_fix - 4, 0, &exp,
5343 0, BFD_RELOC_NDS32_LABEL);
5344 if (!verbatim)
5345 fragP->tc_frag_data.flag = NDS32_FRAG_ALIGN;
5346 }
5347 }
5348 else
5349 out = frag_more (insn.opcode->isize);
5350
5351 if (insn.opcode->isize == 4)
5352 bfd_putb32 (insn.insn, out);
5353 if (insn.opcode->isize == 2)
5354 bfd_putb16 (insn.insn, out);
5355
5356 dwarf2_emit_insn (insn.opcode->isize);
5357
5358 /* Compiler generating code and user assembly pseudo load-store, insert
5359 fixup here. */
5360 pexp = insn.info;
5361 fixP = nds32_elf_record_fixup_exp (fragP, str, fld, pexp, out, &insn);
5362 /* Build relaxation pattern when relaxing is enable. */
5363 if (relaxing)
5364 nds32_elf_build_relax_relation (fixP, pexp, out, insn.opcode, fragP, fld);
5365 }
5366
5367 /* md_macro_start */
5368
5369 void
5370 nds32_macro_start (void)
5371 {
5372 }
5373
5374 /* md_macro_info */
5375
5376 void
5377 nds32_macro_info (void *info ATTRIBUTE_UNUSED)
5378 {
5379 }
5380
5381 /* md_macro_end */
5382
5383 void
5384 nds32_macro_end (void)
5385 {
5386 }
5387
5388 /* GAS will call this function with one argument, an expressionS pointer, for
5389 any expression that can not be recognized. When the function is called,
5390 input_line_pointer will point to the start of the expression. */
5391
5392 void
5393 md_operand (expressionS *expressionP)
5394 {
5395 if (*input_line_pointer == '#')
5396 {
5397 input_line_pointer++;
5398 expression (expressionP);
5399 }
5400 }
5401
5402 /* GAS will call this function for each section at the end of the assembly, to
5403 permit the CPU back end to adjust the alignment of a section. The function
5404 must take two arguments, a segT for the section and a valueT for the size of
5405 the section, and return a valueT for the rounded size. */
5406
5407 valueT
5408 md_section_align (segT segment, valueT size)
5409 {
5410 int align = bfd_get_section_alignment (stdoutput, segment);
5411
5412 return ((size + (1 << align) - 1) & -(1 << align));
5413 }
5414
5415 /* GAS will call this function when a symbol table lookup fails, before it
5416 creates a new symbol. Typically this would be used to supply symbols whose
5417 name or value changes dynamically, possibly in a context sensitive way.
5418 Predefined symbols with fixed values, such as register names or condition
5419 codes, are typically entered directly into the symbol table when md_begin
5420 is called. One argument is passed, a char * for the symbol. */
5421
5422 symbolS *
5423 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
5424 {
5425 return NULL;
5426 }
5427
5428 static long
5429 nds32_calc_branch_offset (segT segment, fragS *fragP,
5430 long stretch ATTRIBUTE_UNUSED,
5431 relax_info_t *relax_info,
5432 enum nds32_br_range branch_range_type)
5433 {
5434 struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
5435 symbolS *branch_symbol = fragP->fr_symbol;
5436 offsetT branch_offset = fragP->fr_offset;
5437 offsetT branch_target_address;
5438 offsetT branch_insn_address;
5439 long offset = 0;
5440
5441 if ((S_GET_SEGMENT (branch_symbol) != segment)
5442 || S_IS_WEAK (branch_symbol))
5443 {
5444 /* The symbol is not in the SEGMENT. It could be far far away. */
5445 offset = 0x80000000;
5446 }
5447 else
5448 {
5449 /* Calculate symbol-to-instruction offset. */
5450 branch_target_address = S_GET_VALUE (branch_symbol) + branch_offset;
5451 /* If the destination symbol is beyond current frag address,
5452 STRETCH will take effect to symbol's position. */
5453 if (S_GET_VALUE (branch_symbol) > fragP->fr_address)
5454 branch_target_address += stretch;
5455
5456 branch_insn_address = fragP->fr_address + fragP->fr_fix;
5457 branch_insn_address -= opcode->isize;
5458
5459 /* Update BRANCH_INSN_ADDRESS to relaxed position. */
5460 branch_insn_address += (relax_info->relax_code_size[branch_range_type]
5461 - relax_info->relax_branch_isize[branch_range_type]);
5462
5463 offset = branch_target_address - branch_insn_address;
5464 }
5465
5466 return offset;
5467 }
5468
5469 static enum nds32_br_range
5470 nds32_convert_to_range_type (long offset)
5471 {
5472 enum nds32_br_range range_type;
5473
5474 if (-(0x100) <= offset && offset < 0x100) /* 256 bytes */
5475 range_type = BR_RANGE_S256;
5476 else if (-(0x4000) <= offset && offset < 0x4000) /* 16K bytes */
5477 range_type = BR_RANGE_S16K;
5478 else if (-(0x10000) <= offset && offset < 0x10000) /* 64K bytes */
5479 range_type = BR_RANGE_S64K;
5480 else if (-(0x1000000) <= offset && offset < 0x1000000) /* 16M bytes */
5481 range_type = BR_RANGE_S16M;
5482 else /* 4G bytes */
5483 range_type = BR_RANGE_U4G;
5484
5485 return range_type;
5486 }
5487
5488 /* Set instruction register mask. */
5489
5490 static void
5491 nds32_elf_get_set_cond (relax_info_t *relax_info, int offset, uint32_t *insn,
5492 uint32_t ori_insn, int range)
5493 {
5494 nds32_cond_field_t *cond_fields = relax_info->cond_field;
5495 nds32_cond_field_t *code_seq_cond = relax_info->relax_code_condition[range];
5496 uint32_t mask;
5497 int i = 0;
5498
5499 /* The instruction has conditions. Collect condition values. */
5500 while (code_seq_cond[i].bitmask != 0)
5501 {
5502 if (offset == code_seq_cond[i].offset)
5503 {
5504 mask = (ori_insn >> cond_fields[i].bitpos) & cond_fields[i].bitmask;
5505 /* Sign extend. */
5506 if (cond_fields[i].signed_extend)
5507 mask = (mask ^ ((cond_fields[i].bitmask + 1) >> 1)) -
5508 ((cond_fields[i].bitmask + 1) >> 1);
5509 *insn |= (mask & code_seq_cond[i].bitmask) << code_seq_cond[i].bitpos;
5510 }
5511 i++;
5512 }
5513 }
5514
5515
5516 static int
5517 nds32_relax_branch_instructions (segT segment, fragS *fragP,
5518 long stretch ATTRIBUTE_UNUSED,
5519 int init)
5520 {
5521 enum nds32_br_range branch_range_type;
5522 struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
5523 long offset = 0;
5524 enum nds32_br_range real_range_type;
5525 int adjust = 0;
5526 relax_info_t *relax_info;
5527 int diff = 0;
5528 int i, j, k;
5529 int code_seq_size;
5530 uint32_t *code_seq;
5531 uint32_t insn;
5532 int insn_size;
5533 int code_seq_offset;
5534
5535 /* Replace with gas_assert (fragP->fr_symbol != NULL); */
5536 if (fragP->fr_symbol == NULL)
5537 return adjust;
5538
5539 /* If frag_var is not enough room, the previous frag is fr_full and with
5540 opcode. The new one is rs_dependent but without opcode. */
5541 if (opcode == NULL)
5542 return adjust;
5543
5544 relax_info = hash_find (nds32_relax_info_hash, opcode->opcode);
5545
5546 if (relax_info == NULL)
5547 return adjust;
5548
5549 if (init)
5550 branch_range_type = relax_info->br_range;
5551 else
5552 branch_range_type = fragP->fr_subtype;
5553
5554 offset = nds32_calc_branch_offset (segment, fragP, stretch,
5555 relax_info, branch_range_type);
5556
5557 real_range_type = nds32_convert_to_range_type (offset);
5558
5559 /* If actual range is equal to instruction jump range, do nothing. */
5560 if (real_range_type == branch_range_type)
5561 return adjust;
5562
5563 /* Find out proper relaxation code sequence. */
5564 for (i = BR_RANGE_S256; i < BR_RANGE_NUM; i++)
5565 {
5566 if (real_range_type <= (unsigned int) i)
5567 {
5568 if (init)
5569 diff = relax_info->relax_code_size[i] - opcode->isize;
5570 else
5571 diff = relax_info->relax_code_size[i]
5572 - relax_info->relax_code_size[branch_range_type];
5573
5574 /* If the instruction could be converted to 16-bits,
5575 minus the difference. */
5576 code_seq_offset = 0;
5577 j = 0;
5578 k = 0;
5579 code_seq_size = relax_info->relax_code_size[i];
5580 code_seq = relax_info->relax_code_seq[i];
5581 while (code_seq_offset < code_seq_size)
5582 {
5583 insn = code_seq[j];
5584 if (insn & 0x80000000) /* 16-bits instruction. */
5585 {
5586 insn_size = 2;
5587 }
5588 else /* 32-bits instruction. */
5589 {
5590 insn_size = 4;
5591
5592 while (relax_info->relax_fixup[i][k].size !=0
5593 && relax_info->relax_fixup[i][k].offset < code_seq_offset)
5594 k++;
5595 }
5596
5597 code_seq_offset += insn_size;
5598 j++;
5599 }
5600
5601 /* Update fr_subtype to new NDS32_BR_RANGE. */
5602 fragP->fr_subtype = i;
5603 break;
5604 }
5605 }
5606
5607 return diff + adjust;
5608 }
5609
5610 /* Adjust relaxable frag till current frag. */
5611
5612 static int
5613 nds32_adjust_relaxable_frag (fragS *startP, fragS *fragP)
5614 {
5615 int adj;
5616 if (startP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
5617 adj = -2;
5618 else
5619 adj = 2;
5620
5621 startP->tc_frag_data.flag ^= NDS32_FRAG_RELAXED;
5622
5623 while (startP)
5624 {
5625 startP = startP->fr_next;
5626 if (startP)
5627 {
5628 startP->fr_address += adj;
5629 if (startP == fragP)
5630 break;
5631 }
5632 }
5633 return adj;
5634 }
5635
5636 static addressT
5637 nds32_get_align (addressT address, int align)
5638 {
5639 addressT mask, new_address;
5640
5641 mask = ~((~0U) << align);
5642 new_address = (address + mask) & (~mask);
5643 return (new_address - address);
5644 }
5645
5646 /* Check the prev_frag is legal. */
5647 static void
5648 invalid_prev_frag (fragS * fragP, fragS **prev_frag)
5649 {
5650 addressT address;
5651 fragS *frag_start = *prev_frag;
5652
5653 if (!frag_start)
5654 return;
5655
5656 if (frag_start->last_fr_address >= fragP->last_fr_address)
5657 {
5658 *prev_frag = NULL;
5659 return;
5660 }
5661
5662 fragS *frag_t = *prev_frag;
5663 while (frag_t != fragP)
5664 {
5665 if (frag_t->fr_type == rs_align
5666 || frag_t->fr_type == rs_align_code
5667 || frag_t->fr_type == rs_align_test)
5668 {
5669 /* Relax instruction can not walk across label. */
5670 if (frag_t->tc_frag_data.flag & NDS32_FRAG_LABEL)
5671 {
5672 prev_frag = NULL;
5673 return;
5674 }
5675 /* Relax previous relaxable to align rs_align frag. */
5676 address = frag_t->fr_address + frag_t->fr_fix;
5677 addressT offset = nds32_get_align (address, (int) frag_t->fr_offset);
5678 if (offset & 0x2)
5679 {
5680 /* If there is label on the prev_frag, check if it is aligned. */
5681 if (!((*prev_frag)->tc_frag_data.flag & NDS32_FRAG_LABEL)
5682 || (((*prev_frag)->fr_address + (*prev_frag)->fr_fix - 2 )
5683 & 0x2) == 0)
5684 nds32_adjust_relaxable_frag (*prev_frag, frag_t);
5685 }
5686 *prev_frag = NULL;
5687 return;
5688 }
5689 frag_t = frag_t->fr_next;
5690 }
5691
5692 if (fragP->tc_frag_data.flag & NDS32_FRAG_ALIGN)
5693 {
5694 address = fragP->fr_address;
5695 addressT offset = nds32_get_align (address, 2);
5696 if (offset & 0x2)
5697 {
5698 /* If there is label on the prev_frag, check if it is aligned. */
5699 if (!((*prev_frag)->tc_frag_data.flag & NDS32_FRAG_LABEL)
5700 || (((*prev_frag)->fr_address + (*prev_frag)->fr_fix - 2 )
5701 & 0x2) == 0)
5702 nds32_adjust_relaxable_frag (*prev_frag, fragP);
5703 }
5704 *prev_frag = NULL;
5705 return;
5706 }
5707 }
5708
5709 /* md_relax_frag */
5710
5711 int
5712 nds32_relax_frag (segT segment, fragS *fragP, long stretch ATTRIBUTE_UNUSED)
5713 {
5714 /* Currently, there are two kinds of relaxation in nds32 assembler.
5715 1. relax for branch
5716 2. relax for 32-bits to 16-bits */
5717
5718 static fragS *prev_frag = NULL;
5719 int adjust = 0;
5720
5721 invalid_prev_frag (fragP, &prev_frag);
5722
5723 if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
5724 adjust = nds32_relax_branch_instructions (segment, fragP, stretch, 0);
5725 if (fragP->tc_frag_data.flag & NDS32_FRAG_LABEL)
5726 prev_frag = NULL;
5727 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE
5728 && (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED) == 0)
5729 /* Here is considered relaxed case originally. But it may cause
5730 an endless loop when relaxing. Once the instruction is relaxed,
5731 it can not be undone. */
5732 prev_frag = fragP;
5733
5734 return adjust;
5735 }
5736
5737 /* This function returns an initial guess of the length by which a fragment
5738 must grow to hold a branch to reach its destination. Also updates
5739 fr_type/fr_subtype as necessary.
5740
5741 It is called just before doing relaxation. Any symbol that is now undefined
5742 will not become defined. The guess for fr_var is ACTUALLY the growth beyond
5743 fr_fix. Whatever we do to grow fr_fix or fr_var contributes to our returned
5744 value. Although it may not be explicit in the frag, pretend fr_var starts
5745 with a 0 value. */
5746
5747 int
5748 md_estimate_size_before_relax (fragS *fragP, segT segment)
5749 {
5750 /* Currently, there are two kinds of relaxation in nds32 assembler.
5751 1. relax for branch
5752 2. relax for 32-bits to 16-bits */
5753
5754 /* Save previous relaxable frag. */
5755 static fragS *prev_frag = NULL;
5756 int adjust = 0;
5757
5758 invalid_prev_frag (fragP, &prev_frag);
5759
5760 if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
5761 adjust = nds32_relax_branch_instructions (segment, fragP, 0, 1);
5762 if (fragP->tc_frag_data.flag & NDS32_FRAG_LABEL)
5763 prev_frag = NULL;
5764 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
5765 adjust = 2;
5766 else if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE)
5767 prev_frag = fragP;
5768
5769 return adjust;
5770 }
5771
5772 /* GAS will call this for each rs_machine_dependent fragment. The instruction
5773 is completed using the data from the relaxation pass. It may also create any
5774 necessary relocations.
5775
5776 *FRAGP has been relaxed to its final size, and now needs to have the bytes
5777 inside it modified to conform to the new size. It is called after relaxation
5778 is finished.
5779
5780 fragP->fr_type == rs_machine_dependent.
5781 fragP->fr_subtype is the subtype of what the address relaxed to. */
5782
5783 void
5784 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP)
5785 {
5786 /* Convert branch relaxation instructions. */
5787 symbolS *branch_symbol = fragP->fr_symbol;
5788 offsetT branch_offset = fragP->fr_offset;
5789 enum nds32_br_range branch_range_type = fragP->fr_subtype;
5790 struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
5791 uint32_t origin_insn = fragP->tc_frag_data.insn;
5792 relax_info_t *relax_info;
5793 char *fr_buffer;
5794 int fr_where;
5795 int addend ATTRIBUTE_UNUSED;
5796 offsetT branch_target_address, branch_insn_address;
5797 expressionS exp;
5798 fixS *fixP;
5799 uint32_t *code_seq;
5800 uint32_t insn;
5801 int code_size, insn_size, offset, fixup_size;
5802 int buf_offset, pcrel;
5803 int i, k;
5804 uint16_t insn_16;
5805 nds32_relax_fixup_info_t fixup_info[MAX_RELAX_FIX];
5806 /* Save the 1st instruction is converted to 16 bit or not. */
5807 unsigned int branch_size;
5808
5809 /* Replace with gas_assert (branch_symbol != NULL); */
5810 if (branch_symbol == NULL && !(fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED))
5811 return;
5812
5813 /* If frag_var is not enough room, the previous frag is fr_full and with
5814 opcode. The new one is rs_dependent but without opcode. */
5815 if (opcode == NULL)
5816 return;
5817
5818 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE_BRANCH)
5819 {
5820 relax_info = hash_find (nds32_relax_info_hash, opcode->opcode);
5821
5822 if (relax_info == NULL)
5823 return;
5824
5825 i = BR_RANGE_S256;
5826 while (i < BR_RANGE_NUM
5827 && relax_info->relax_code_size[i]
5828 != (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED ? 4 : 2))
5829 i++;
5830
5831 if (i >= BR_RANGE_NUM)
5832 as_bad ("Internal error: Cannot find relocation of"
5833 "relaxable branch.");
5834
5835 exp.X_op = O_symbol;
5836 exp.X_add_symbol = branch_symbol;
5837 exp.X_add_number = branch_offset;
5838 pcrel = ((relax_info->relax_fixup[i][0].ramp & NDS32_PCREL) != 0) ? 1 : 0;
5839 fr_where = fragP->fr_fix - 2;
5840 fixP = fix_new_exp (fragP, fr_where, relax_info->relax_fixup[i][0].size,
5841 &exp, pcrel, relax_info->relax_fixup[i][0].r_type);
5842 fixP->fx_addnumber = fixP->fx_offset;
5843
5844 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
5845 {
5846 insn_16 = fragP->tc_frag_data.insn;
5847 nds32_convert_16_to_32 (stdoutput, insn_16, &insn);
5848 fr_buffer = fragP->fr_literal + fr_where;
5849 fragP->fr_fix += 2;
5850 exp.X_op = O_symbol;
5851 exp.X_add_symbol = abs_section_sym;
5852 exp.X_add_number = 0;
5853 fix_new_exp (fragP, fr_where, 4,
5854 &exp, 0, BFD_RELOC_NDS32_INSN16);
5855 number_to_chars_bigendian (fr_buffer, insn, 4);
5856 }
5857 }
5858 else if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
5859 {
5860 if (fragP->tc_frag_data.opcode->isize == 2)
5861 {
5862 insn_16 = fragP->tc_frag_data.insn;
5863 nds32_convert_16_to_32 (stdoutput, insn_16, &insn);
5864 }
5865 else
5866 insn = fragP->tc_frag_data.insn;
5867 fragP->fr_fix += 2;
5868 fr_where = fragP->fr_fix - 4;
5869 fr_buffer = fragP->fr_literal + fr_where;
5870 exp.X_op = O_symbol;
5871 exp.X_add_symbol = abs_section_sym;
5872 exp.X_add_number = 0;
5873 fix_new_exp (fragP, fr_where, 4, &exp, 0,
5874 BFD_RELOC_NDS32_INSN16);
5875 number_to_chars_bigendian (fr_buffer, insn, 4);
5876 }
5877 else if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
5878 {
5879 /* Branch instruction adjust and append relocations. */
5880 relax_info = hash_find (nds32_relax_info_hash, opcode->opcode);
5881
5882 if (relax_info == NULL)
5883 return;
5884
5885 fr_where = fragP->fr_fix - opcode->isize;
5886 fr_buffer = fragP->fr_literal + fr_where;
5887
5888 if ((S_GET_SEGMENT (branch_symbol) != sec)
5889 || S_IS_WEAK (branch_symbol))
5890 {
5891 if (fragP->fr_offset & 3)
5892 as_warn (_("Addend to unresolved symbol is not on word boundary."));
5893 addend = 0;
5894 }
5895 else
5896 {
5897 /* Calculate symbol-to-instruction offset. */
5898 branch_target_address = S_GET_VALUE (branch_symbol) + branch_offset;
5899 branch_insn_address = fragP->fr_address + fr_where;
5900 addend = (branch_target_address - branch_insn_address) >> 1;
5901 }
5902
5903 code_size = relax_info->relax_code_size[branch_range_type];
5904 code_seq = relax_info->relax_code_seq[branch_range_type];
5905
5906 memcpy (fixup_info, relax_info->relax_fixup[branch_range_type],
5907 sizeof (fixup_info));
5908
5909 /* Fill in frag. */
5910 i = 0;
5911 k = 0;
5912 offset = 0; /* code_seq offset */
5913 buf_offset = 0; /* fr_buffer offset */
5914 while (offset < code_size)
5915 {
5916 insn = code_seq[i];
5917 if (insn & 0x80000000) /* 16-bits instruction. */
5918 {
5919 insn = (insn >> 16) & 0xFFFF;
5920 insn_size = 2;
5921 }
5922 else /* 32-bits instruction. */
5923 {
5924 insn_size = 4;
5925 }
5926
5927 nds32_elf_get_set_cond (relax_info, offset, &insn,
5928 origin_insn, branch_range_type);
5929
5930 /* Try to convert to 16-bits instruction. Currently, only the first
5931 instruction in pattern can be converted. EX: bnez sethi ori jr,
5932 only bnez can be converted to 16 bit and ori can't. */
5933
5934 while (fixup_info[k].size != 0
5935 && relax_info->relax_fixup[branch_range_type][k].offset < offset)
5936 k++;
5937
5938 number_to_chars_bigendian (fr_buffer + buf_offset, insn, insn_size);
5939 buf_offset += insn_size;
5940
5941 offset += insn_size;
5942 i++;
5943 }
5944
5945 /* Set up fixup. */
5946 exp.X_op = O_symbol;
5947
5948 for (i = 0; fixup_info[i].size != 0; i++)
5949 {
5950 fixup_size = fixup_info[i].size;
5951 pcrel = ((fixup_info[i].ramp & NDS32_PCREL) != 0) ? 1 : 0;
5952
5953 if ((fixup_info[i].ramp & NDS32_CREATE_LABEL) != 0)
5954 {
5955 /* This is a reverse branch. */
5956 exp.X_add_symbol = symbol_temp_new (sec, 0, fragP->fr_next);
5957 exp.X_add_number = 0;
5958 }
5959 else if ((fixup_info[i].ramp & NDS32_PTR) != 0)
5960 {
5961 /* This relocation has to point to another instruction. */
5962 branch_size = fr_where + code_size - 4;
5963 exp.X_add_symbol = symbol_temp_new (sec, branch_size, fragP);
5964 exp.X_add_number = 0;
5965 }
5966 else if ((fixup_info[i].ramp & NDS32_ABS) != 0)
5967 {
5968 /* This is a tag relocation. */
5969 exp.X_add_symbol = abs_section_sym;
5970 exp.X_add_number = 0;
5971 }
5972 else if ((fixup_info[i].ramp & NDS32_INSN16) != 0)
5973 {
5974 if (!enable_16bit)
5975 continue;
5976 /* This is a tag relocation. */
5977 exp.X_add_symbol = abs_section_sym;
5978 exp.X_add_number = 0;
5979 }
5980 else
5981 {
5982 exp.X_add_symbol = branch_symbol;
5983 exp.X_add_number = branch_offset;
5984 }
5985
5986 if (fixup_info[i].r_type != 0)
5987 {
5988 fixP = fix_new_exp (fragP, fr_where + fixup_info[i].offset,
5989 fixup_size, &exp, pcrel,
5990 fixup_info[i].r_type);
5991 fixP->fx_addnumber = fixP->fx_offset;
5992 }
5993 }
5994
5995 fragP->fr_fix = fr_where + buf_offset;
5996 }
5997 }
5998
5999 /* tc_frob_file_before_fix */
6000
6001 void
6002 nds32_frob_file_before_fix (void)
6003 {
6004 }
6005
6006 static bfd_boolean
6007 nds32_relaxable_section (asection *sec)
6008 {
6009 return ((sec->flags & SEC_DEBUGGING) == 0
6010 && strcmp (sec->name, ".eh_frame") != 0);
6011 }
6012
6013 /* TC_FORCE_RELOCATION */
6014 int
6015 nds32_force_relocation (fixS * fix)
6016 {
6017 switch (fix->fx_r_type)
6018 {
6019 case BFD_RELOC_NDS32_INSN16:
6020 case BFD_RELOC_NDS32_LABEL:
6021 case BFD_RELOC_NDS32_LONGCALL1:
6022 case BFD_RELOC_NDS32_LONGCALL2:
6023 case BFD_RELOC_NDS32_LONGCALL3:
6024 case BFD_RELOC_NDS32_LONGJUMP1:
6025 case BFD_RELOC_NDS32_LONGJUMP2:
6026 case BFD_RELOC_NDS32_LONGJUMP3:
6027 case BFD_RELOC_NDS32_LOADSTORE:
6028 case BFD_RELOC_NDS32_9_FIXED:
6029 case BFD_RELOC_NDS32_15_FIXED:
6030 case BFD_RELOC_NDS32_17_FIXED:
6031 case BFD_RELOC_NDS32_25_FIXED:
6032 case BFD_RELOC_NDS32_9_PCREL:
6033 case BFD_RELOC_NDS32_15_PCREL:
6034 case BFD_RELOC_NDS32_17_PCREL:
6035 case BFD_RELOC_NDS32_WORD_9_PCREL:
6036 case BFD_RELOC_NDS32_10_UPCREL:
6037 case BFD_RELOC_NDS32_25_PCREL:
6038 case BFD_RELOC_NDS32_MINUEND:
6039 case BFD_RELOC_NDS32_SUBTRAHEND:
6040 return 1;
6041
6042 case BFD_RELOC_8:
6043 case BFD_RELOC_16:
6044 case BFD_RELOC_32:
6045 case BFD_RELOC_NDS32_DIFF_ULEB128:
6046 /* Linker should handle difference between two symbol. */
6047 return fix->fx_subsy != NULL
6048 && nds32_relaxable_section (S_GET_SEGMENT (fix->fx_addsy));
6049 case BFD_RELOC_64:
6050 if (fix->fx_subsy)
6051 as_bad ("Double word for difference between two symbols "
6052 "is not supported across relaxation.");
6053 default:
6054 ;
6055 }
6056
6057 if (generic_force_reloc (fix))
6058 return 1;
6059
6060 return fix->fx_pcrel;
6061 }
6062
6063 /* TC_VALIDATE_FIX_SUB */
6064
6065 int
6066 nds32_validate_fix_sub (fixS *fix, segT add_symbol_segment)
6067 {
6068 segT sub_symbol_segment;
6069
6070 /* This code is referred from Xtensa. Check their implementation for
6071 details. */
6072
6073 /* Make sure both symbols are in the same segment, and that segment is
6074 "normal" and relaxable. */
6075 sub_symbol_segment = S_GET_SEGMENT (fix->fx_subsy);
6076 return (sub_symbol_segment == add_symbol_segment
6077 && add_symbol_segment != undefined_section);
6078 }
6079
6080 void
6081 md_number_to_chars (char *buf, valueT val, int n)
6082 {
6083 if (target_big_endian)
6084 number_to_chars_bigendian (buf, val, n);
6085 else
6086 number_to_chars_littleendian (buf, val, n);
6087 }
6088
6089 /* Equal to MAX_PRECISION in atof-ieee.c. */
6090 #define MAX_LITTLENUMS 6
6091
6092 /* This function is called to convert an ASCII string into a floating point
6093 value in format used by the CPU. */
6094
6095 const char *
6096 md_atof (int type, char *litP, int *sizeP)
6097 {
6098 int i;
6099 int prec;
6100 LITTLENUM_TYPE words[MAX_LITTLENUMS];
6101 char *t;
6102
6103 switch (type)
6104 {
6105 case 'f':
6106 case 'F':
6107 case 's':
6108 case 'S':
6109 prec = 2;
6110 break;
6111 case 'd':
6112 case 'D':
6113 case 'r':
6114 case 'R':
6115 prec = 4;
6116 break;
6117 default:
6118 *sizeP = 0;
6119 return _("Bad call to md_atof()");
6120 }
6121
6122 t = atof_ieee (input_line_pointer, type, words);
6123 if (t)
6124 input_line_pointer = t;
6125 *sizeP = prec * sizeof (LITTLENUM_TYPE);
6126
6127 if (target_big_endian)
6128 {
6129 for (i = 0; i < prec; i++)
6130 {
6131 md_number_to_chars (litP, (valueT) words[i],
6132 sizeof (LITTLENUM_TYPE));
6133 litP += sizeof (LITTLENUM_TYPE);
6134 }
6135 }
6136 else
6137 {
6138 for (i = prec - 1; i >= 0; i--)
6139 {
6140 md_number_to_chars (litP, (valueT) words[i],
6141 sizeof (LITTLENUM_TYPE));
6142 litP += sizeof (LITTLENUM_TYPE);
6143 }
6144 }
6145
6146 return 0;
6147 }
6148
6149 /* md_elf_section_change_hook */
6150
6151 void
6152 nds32_elf_section_change_hook (void)
6153 {
6154 }
6155
6156 /* md_cleanup */
6157
6158 void
6159 nds32_cleanup (void)
6160 {
6161 }
6162
6163 /* This function is used to scan leb128 subtraction expressions,
6164 and insert fixups for them.
6165
6166 e.g., .leb128 .L1 - .L0
6167
6168 These expressions are heavily used in debug information or
6169 exception tables. Because relaxation will change code size,
6170 we must resolve them in link time. */
6171
6172 static void
6173 nds32_insert_leb128_fixes (bfd *abfd ATTRIBUTE_UNUSED,
6174 asection *sec, void *xxx ATTRIBUTE_UNUSED)
6175 {
6176 segment_info_type *seginfo = seg_info (sec);
6177 struct frag *fragP;
6178
6179 subseg_set (sec, 0);
6180
6181 for (fragP = seginfo->frchainP->frch_root;
6182 fragP; fragP = fragP->fr_next)
6183 {
6184 expressionS *exp;
6185
6186 /* Only unsigned leb128 can be handle. */
6187 if (fragP->fr_type != rs_leb128 || fragP->fr_subtype != 0
6188 || fragP->fr_symbol == NULL)
6189 continue;
6190
6191 exp = symbol_get_value_expression (fragP->fr_symbol);
6192
6193 if (exp->X_op != O_subtract)
6194 continue;
6195
6196 fix_new_exp (fragP, fragP->fr_fix, 0,
6197 exp, 0, BFD_RELOC_NDS32_DIFF_ULEB128);
6198 }
6199 }
6200
6201 static void
6202 nds32_insert_relax_entry (bfd *abfd ATTRIBUTE_UNUSED, asection *sec,
6203 void *xxx ATTRIBUTE_UNUSED)
6204 {
6205 segment_info_type *seginfo;
6206 fragS *fragP;
6207 fixS *fixP;
6208 expressionS exp;
6209 fixS *fixp;
6210
6211 seginfo = seg_info (sec);
6212 if (!seginfo || !symbol_rootP || !subseg_text_p (sec) || sec->size == 0)
6213 return;
6214 /* If there is no relocation and relax is disabled, it is not necessary to
6215 insert R_NDS32_RELAX_ENTRY for linker do EX9 or IFC optimization. */
6216 for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
6217 if (!fixp->fx_done)
6218 break;
6219 if (!fixp && !enable_relax_ex9 && !verbatim)
6220 return;
6221
6222 subseg_change (sec, 0);
6223
6224 /* Set RELAX_ENTRY flags for linker. */
6225 fragP = seginfo->frchainP->frch_root;
6226 exp.X_op = O_symbol;
6227 exp.X_add_symbol = section_symbol (sec);
6228 exp.X_add_number = 0;
6229 if (!enable_relax_relocs)
6230 exp.X_add_number |= R_NDS32_RELAX_ENTRY_DISABLE_RELAX_FLAG;
6231 else
6232 {
6233 /* These flags are only enabled when global relax is enabled.
6234 Maybe we can check DISABLE_RELAX_FLAG at link-time,
6235 so we set them anyway. */
6236 if (enable_relax_ex9)
6237 exp.X_add_number |= R_NDS32_RELAX_ENTRY_EX9_FLAG;
6238 if (enable_relax_ifc)
6239 exp.X_add_number |= R_NDS32_RELAX_ENTRY_IFC_FLAG;
6240 if (verbatim)
6241 exp.X_add_number |= R_NDS32_RELAX_ENTRY_VERBATIM_FLAG;
6242 }
6243 if (optimize)
6244 exp.X_add_number |= R_NDS32_RELAX_ENTRY_OPTIMIZE_FLAG;
6245 if (optimize_for_space)
6246 exp.X_add_number |= R_NDS32_RELAX_ENTRY_OPTIMIZE_FOR_SPACE_FLAG;
6247
6248 fixP = fix_new_exp (fragP, 0, 0, &exp, 0, BFD_RELOC_NDS32_RELAX_ENTRY);
6249 fixP->fx_no_overflow = 1;
6250 }
6251
6252 /* Analysis relax hint and insert suitable relocation pattern. */
6253
6254 static void
6255 nds32_elf_analysis_relax_hint (void)
6256 {
6257 hash_traverse (nds32_hint_hash, nds32_elf_append_relax_relocs);
6258 }
6259
6260 static void
6261 nds32_elf_insert_final_frag (void)
6262 {
6263 struct frchain *frchainP;
6264 asection *s;
6265 fragS *fragP;
6266
6267 if (!optimize)
6268 return;
6269
6270 for (s = stdoutput->sections; s; s = s->next)
6271 {
6272 segment_info_type *seginfo = seg_info (s);
6273 if (!seginfo)
6274 continue;
6275
6276 for (frchainP = seginfo->frchainP; frchainP != NULL;
6277 frchainP = frchainP->frch_next)
6278 {
6279 subseg_set (s, frchainP->frch_subseg);
6280
6281 if (subseg_text_p (now_seg))
6282 {
6283 fragP = frag_now;
6284 frag_var (rs_machine_dependent, 2, /* Max size. */
6285 0, /* VAR is un-used. */ 0, NULL, 0, NULL);
6286 fragP->tc_frag_data.flag |= NDS32_FRAG_FINAL;
6287 }
6288 }
6289 }
6290 }
6291
6292 void
6293 md_end (void)
6294 {
6295 nds32_elf_insert_final_frag ();
6296 nds32_elf_analysis_relax_hint ();
6297 bfd_map_over_sections (stdoutput, nds32_insert_leb128_fixes, NULL);
6298 }
6299
6300 /* Implement md_allow_local_subtract. */
6301
6302 bfd_boolean
6303 nds32_allow_local_subtract (expressionS *expr_l ATTRIBUTE_UNUSED,
6304 expressionS *expr_r ATTRIBUTE_UNUSED,
6305 segT sec ATTRIBUTE_UNUSED)
6306 {
6307 /* Don't allow any subtraction, because relax may change the code. */
6308 return FALSE;
6309 }
6310
6311 /* Sort relocation by address.
6312
6313 We didn't use qsort () in stdlib, because quick-sort is not a stable
6314 sorting algorithm. Relocations at the same address (r_offset) must keep
6315 their relative order. For example, RELAX_ENTRY must be the very first
6316 relocation entry.
6317
6318 Currently, this function implements insertion-sort. */
6319
6320 static int
6321 compar_relent (const void *lhs, const void *rhs)
6322 {
6323 const arelent **l = (const arelent **) lhs;
6324 const arelent **r = (const arelent **) rhs;
6325
6326 if ((*l)->address > (*r)->address)
6327 return 1;
6328 else if ((*l)->address == (*r)->address)
6329 return 0;
6330 else
6331 return -1;
6332 }
6333
6334 /* SET_SECTION_RELOCS ()
6335
6336 Although this macro is originally used to set a relocation for each section,
6337 we use it to sort relocations in the same section by the address of the
6338 relocation. */
6339
6340 void
6341 nds32_set_section_relocs (asection *sec, arelent ** relocs ATTRIBUTE_UNUSED,
6342 unsigned int n ATTRIBUTE_UNUSED)
6343 {
6344 bfd *abfd ATTRIBUTE_UNUSED = sec->owner;
6345 if (bfd_get_section_flags (abfd, sec) & (flagword) SEC_RELOC)
6346 nds32_insertion_sort (sec->orelocation, sec->reloc_count,
6347 sizeof (arelent**), compar_relent);
6348 }
6349
6350 long
6351 nds32_pcrel_from_section (fixS *fixP, segT sec ATTRIBUTE_UNUSED)
6352 {
6353 if (fixP->fx_addsy == NULL || !S_IS_DEFINED (fixP->fx_addsy)
6354 || S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy))
6355 {
6356 /* Let linker resolve undefined symbols. */
6357 return 0;
6358 }
6359
6360 return fixP->fx_frag->fr_address + fixP->fx_where;
6361 }
6362
6363 /* md_post_relax_hook ()
6364 Insert relax entry relocation into sections. */
6365
6366 void
6367 nds32_post_relax_hook (void)
6368 {
6369 bfd_map_over_sections (stdoutput, nds32_insert_relax_entry, NULL);
6370 }
6371
6372 /* tc_fix_adjustable ()
6373
6374 Return whether this symbol (fixup) can be replaced with
6375 section symbols. */
6376
6377 bfd_boolean
6378 nds32_fix_adjustable (fixS *fixP)
6379 {
6380 switch (fixP->fx_r_type)
6381 {
6382 case BFD_RELOC_NDS32_WORD_9_PCREL:
6383 case BFD_RELOC_NDS32_9_PCREL:
6384 case BFD_RELOC_NDS32_15_PCREL:
6385 case BFD_RELOC_NDS32_17_PCREL:
6386 case BFD_RELOC_NDS32_25_PCREL:
6387 case BFD_RELOC_NDS32_HI20:
6388 case BFD_RELOC_NDS32_LO12S0:
6389 case BFD_RELOC_8:
6390 case BFD_RELOC_16:
6391 case BFD_RELOC_32:
6392 case BFD_RELOC_NDS32_PTR:
6393 case BFD_RELOC_NDS32_LONGCALL4:
6394 case BFD_RELOC_NDS32_LONGCALL5:
6395 case BFD_RELOC_NDS32_LONGCALL6:
6396 case BFD_RELOC_NDS32_LONGJUMP4:
6397 case BFD_RELOC_NDS32_LONGJUMP5:
6398 case BFD_RELOC_NDS32_LONGJUMP6:
6399 case BFD_RELOC_NDS32_LONGJUMP7:
6400 return 1;
6401 default:
6402 return 0;
6403 }
6404 }
6405
6406 /* elf_tc_final_processing */
6407
6408 void
6409 elf_nds32_final_processing (void)
6410 {
6411 /* An FPU_COM instruction is found without previous non-FPU_COM
6412 instruction. */
6413 if (nds32_fpu_com
6414 && !(nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST)))
6415 {
6416 /* Since only FPU_COM instructions are used and no other FPU instructions
6417 are used. The nds32_elf_flags will be decided by the enabled options
6418 by command line or default configuration. */
6419 if (nds32_fpu_dp_ext || nds32_fpu_sp_ext)
6420 {
6421 nds32_elf_flags |= nds32_fpu_dp_ext ? E_NDS32_HAS_FPU_DP_INST : 0;
6422 nds32_elf_flags |= nds32_fpu_sp_ext ? E_NDS32_HAS_FPU_INST : 0;
6423 }
6424 else
6425 {
6426 /* Should never here. */
6427 as_bad (_("Used FPU instructions requires enabling FPU extension"));
6428 }
6429 }
6430
6431 if (nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST))
6432 {
6433 /* Single/double FPU has been used, set FPU register config. */
6434 /* We did not check the actual number of register used. We may
6435 want to do it while assemble. */
6436 nds32_elf_flags &= ~E_NDS32_FPU_REG_CONF;
6437 nds32_elf_flags |= (nds32_freg << E_NDS32_FPU_REG_CONF_SHIFT);
6438 }
6439
6440 if (nds32_pic)
6441 nds32_elf_flags |= E_NDS32_HAS_PIC;
6442
6443 if (nds32_gpr16)
6444 nds32_elf_flags |= E_NDS32_HAS_REDUCED_REGS;
6445
6446 nds32_elf_flags |= (E_NDS32_ELF_VER_1_4 | nds32_abi);
6447 elf_elfheader (stdoutput)->e_flags |= nds32_elf_flags;
6448 }
6449
6450 /* Implement md_apply_fix. Apply the fix-up or transform the fix-up for
6451 later relocation generation. */
6452
6453 void
6454 nds32_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
6455 {
6456 char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
6457 bfd_vma value = *valP;
6458
6459 if (fixP->fx_r_type < BFD_RELOC_UNUSED
6460 && fixP->fx_r_type > BFD_RELOC_NONE
6461 && fixP->fx_r_type != BFD_RELOC_NDS32_DIFF_ULEB128)
6462 {
6463 /* In our old nds32 binutils, it must convert relocations which is
6464 generated by CGEN. However, it does not have to consider this anymore.
6465 In current, it only deal with data relocations which enum
6466 is smaller than BFD_RELOC_NONE and BFD_RELOC_NDS32_DIFF_ULEB128.
6467 It is believed that we can construct a better mechanism to
6468 deal with the whole relocation issue in nds32 target
6469 without using CGEN. */
6470 fixP->fx_addnumber = value;
6471 fixP->tc_fix_data = NULL;
6472
6473 /* Transform specific relocations here for later relocation generation.
6474 Tag data here for ex9 relaxation and tag tls data for linker. */
6475 switch (fixP->fx_r_type)
6476 {
6477 case BFD_RELOC_NDS32_DATA:
6478 if (!enable_relax_ex9)
6479 fixP->fx_done = 1;
6480 break;
6481 case BFD_RELOC_NDS32_TPOFF:
6482 case BFD_RELOC_NDS32_TLS_LE_HI20:
6483 case BFD_RELOC_NDS32_TLS_LE_LO12:
6484 case BFD_RELOC_NDS32_TLS_LE_ADD:
6485 case BFD_RELOC_NDS32_TLS_LE_LS:
6486 case BFD_RELOC_NDS32_GOTTPOFF:
6487 case BFD_RELOC_NDS32_TLS_IE_HI20:
6488 case BFD_RELOC_NDS32_TLS_IE_LO12S2:
6489 S_SET_THREAD_LOCAL (fixP->fx_addsy);
6490 break;
6491 default:
6492 break;
6493 }
6494 return;
6495 }
6496
6497 if (fixP->fx_addsy == (symbolS *) NULL)
6498 fixP->fx_done = 1;
6499
6500 if (fixP->fx_subsy != (symbolS *) NULL)
6501 {
6502 /* HOW DIFF RELOCATION WORKS.
6503
6504 First of all, this relocation is used to calculate the distance
6505 between two symbols in the SAME section. It is used for jump-
6506 table, debug information, exception table, et al. Therefore,
6507 it is a unsigned positive value. It is NOT used for general-
6508 purpose arithmetic.
6509
6510 Consider this example, the distance between .LEND and .LBEGIN
6511 is stored at the address of foo.
6512
6513 ---- >8 ---- >8 ---- >8 ---- >8 ----
6514 .data
6515 foo:
6516 .word .LBEGIN - .LEND
6517
6518 .text
6519 [before]
6520 .LBEGIN
6521 \
6522 [between] distance
6523 /
6524 .LEND
6525 [after]
6526 ---- 8< ---- 8< ---- 8< ---- 8< ----
6527
6528 We use a single relocation entry for this expression.
6529 * The initial distance value is stored directly in that location
6530 specified by r_offset (i.e., foo in this example.)
6531 * The begin of the region, i.e., .LBEGIN, is specified by
6532 r_info/R_SYM and r_addend, e.g., .text + 0x32.
6533 * The end of region, i.e., .LEND, is represented by
6534 .LBEGIN + distance instead of .LEND, so we only need
6535 a single relocation entry instead of two.
6536
6537 When an instruction is relaxed, we adjust the relocation entry
6538 depending on where the instruction locates. There are three
6539 cases, before, after and between the region.
6540 * between: Distance value is read from r_offset, adjusted and
6541 written back into r_offset.
6542 * before: Only r_addend is adjust.
6543 * after: We don't care about it.
6544
6545 Hereby, there are some limitation.
6546
6547 `(.LEND - 1) - .LBEGIN' and `(.LEND - .LBEGIN) - 1'
6548 are semantically different, and we cannot handle latter case
6549 when relaxation.
6550
6551 The latter expression means subtracting 1 from the distance
6552 between .LEND and .LBEGIN. And the former expression means
6553 the distance between (.LEND - 1) and .LBEGIN.
6554
6555 The nuance affects whether to adjust distance value when relax
6556 an instruction. In another words, whether the instruction
6557 locates in the region. Because we use a single relocation entry,
6558 there is no field left for .LEND and the subtrahend.
6559
6560 Since GCC-4.5, GCC may produce debug information in such expression
6561 .long .L1-1-.L0
6562 in order to describe register clobbering during an function-call.
6563 .L0:
6564 call foo
6565 .L1:
6566
6567 Check http://gcc.gnu.org/ml/gcc-patches/2009-06/msg01317.html
6568 for details. */
6569
6570 value -= S_GET_VALUE (fixP->fx_subsy);
6571 *valP = value;
6572 fixP->fx_subsy = NULL;
6573 fixP->fx_offset -= value;
6574
6575 switch (fixP->fx_r_type)
6576 {
6577 case BFD_RELOC_8:
6578 fixP->fx_r_type = BFD_RELOC_NDS32_DIFF8;
6579 md_number_to_chars (where, value, 1);
6580 break;
6581 case BFD_RELOC_16:
6582 fixP->fx_r_type = BFD_RELOC_NDS32_DIFF16;
6583 md_number_to_chars (where, value, 2);
6584 break;
6585 case BFD_RELOC_32:
6586 fixP->fx_r_type = BFD_RELOC_NDS32_DIFF32;
6587 md_number_to_chars (where, value, 4);
6588 break;
6589 case BFD_RELOC_NDS32_DIFF_ULEB128:
6590 /* cvt_frag_to_fill () has called output_leb128 () for us. */
6591 break;
6592 default:
6593 as_bad_where (fixP->fx_file, fixP->fx_line,
6594 _("expression too complex"));
6595 return;
6596 }
6597 }
6598 else if (fixP->fx_done)
6599 {
6600 /* We're finished with this fixup. Install it because
6601 bfd_install_relocation won't be called to do it. */
6602 switch (fixP->fx_r_type)
6603 {
6604 case BFD_RELOC_8:
6605 md_number_to_chars (where, value, 1);
6606 break;
6607 case BFD_RELOC_16:
6608 md_number_to_chars (where, value, 2);
6609 break;
6610 case BFD_RELOC_32:
6611 md_number_to_chars (where, value, 4);
6612 break;
6613 case BFD_RELOC_64:
6614 md_number_to_chars (where, value, 8);
6615 break;
6616 default:
6617 as_bad_where (fixP->fx_file, fixP->fx_line,
6618 _("Internal error: Unknown fixup type %d (`%s')"),
6619 fixP->fx_r_type,
6620 bfd_get_reloc_code_name (fixP->fx_r_type));
6621 break;
6622 }
6623 }
6624 }
6625
6626 /* Implement tc_gen_reloc. Generate ELF relocation for a fix-up. */
6627
6628 arelent *
6629 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
6630 {
6631 arelent *reloc;
6632 bfd_reloc_code_real_type code;
6633
6634 reloc = XNEW (arelent);
6635
6636 reloc->sym_ptr_ptr = XNEW (asymbol *);
6637 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
6638 reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
6639
6640 code = fixP->fx_r_type;
6641
6642 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
6643 if (reloc->howto == (reloc_howto_type *) NULL)
6644 {
6645 as_bad_where (fixP->fx_file, fixP->fx_line,
6646 _("internal error: can't export reloc type %d (`%s')"),
6647 fixP->fx_r_type, bfd_get_reloc_code_name (code));
6648 return NULL;
6649 }
6650
6651 /* Add relocation handling here. */
6652
6653 switch (fixP->fx_r_type)
6654 {
6655 default:
6656 /* In general, addend of a relocation is the offset to the
6657 associated symbol. */
6658 reloc->addend = fixP->fx_offset;
6659 break;
6660
6661 case BFD_RELOC_NDS32_DATA:
6662 /* Prevent linker from optimizing data in text sections.
6663 For example, jump table. */
6664 reloc->addend = fixP->fx_size;
6665 break;
6666 }
6667
6668 return reloc;
6669 }
6670
6671 struct suffix_name suffix_table[] =
6672 {
6673 {"GOTOFF", BFD_RELOC_NDS32_GOTOFF, 1},
6674 {"GOT", BFD_RELOC_NDS32_GOT20, 1},
6675 {"TPOFF", BFD_RELOC_NDS32_TPOFF, 0},
6676 {"PLT", BFD_RELOC_NDS32_25_PLTREL, 1},
6677 {"GOTTPOFF", BFD_RELOC_NDS32_GOTTPOFF, 0}
6678 };
6679
6680 /* Implement md_parse_name. */
6681
6682 int
6683 nds32_parse_name (char const *name, expressionS *exprP,
6684 enum expr_mode mode ATTRIBUTE_UNUSED,
6685 char *nextcharP ATTRIBUTE_UNUSED)
6686 {
6687 segT segment;
6688
6689 exprP->X_op_symbol = NULL;
6690 exprP->X_md = BFD_RELOC_UNUSED;
6691
6692 exprP->X_add_symbol = symbol_find_or_make (name);
6693 exprP->X_op = O_symbol;
6694 exprP->X_add_number = 0;
6695
6696 /* Check the special name if a symbol. */
6697 segment = S_GET_SEGMENT (exprP->X_add_symbol);
6698 if (segment != undefined_section)
6699 return 0;
6700
6701 if (strcmp (name, GOT_NAME) == 0 && *nextcharP != '@')
6702 {
6703 /* Set for _GOT_OFFSET_TABLE_. */
6704 exprP->X_md = BFD_RELOC_NDS32_GOTPC20;
6705 }
6706 else if (*nextcharP == '@')
6707 {
6708 size_t i;
6709 char *next;
6710 for (i = 0; i < ARRAY_SIZE (suffix_table); i++)
6711 {
6712 next = input_line_pointer + 1 + strlen(suffix_table[i].suffix);
6713 if (strncasecmp (input_line_pointer + 1, suffix_table[i].suffix,
6714 strlen (suffix_table[i].suffix)) == 0
6715 && !is_part_of_name (*next))
6716 {
6717 if (!nds32_pic && suffix_table[i].pic)
6718 as_bad (_("need PIC qualifier with symbol."));
6719 exprP->X_md = suffix_table[i].reloc;
6720 *input_line_pointer = *nextcharP;
6721 input_line_pointer = next;
6722 *nextcharP = *input_line_pointer;
6723 *input_line_pointer = '\0';
6724 break;
6725 }
6726 }
6727 }
6728 return 1;
6729 }
6730
6731 /* Implement tc_regname_to_dw2regnum. */
6732
6733 int
6734 tc_nds32_regname_to_dw2regnum (char *regname)
6735 {
6736 struct nds32_keyword *sym = hash_find (nds32_gprs_hash, regname);
6737
6738 if (!sym)
6739 return -1;
6740
6741 return sym->value;
6742 }
6743
6744 void
6745 tc_nds32_frame_initial_instructions (void)
6746 {
6747 /* CIE */
6748 /* Default cfa is register-31/sp. */
6749 cfi_add_CFA_def_cfa (31, 0);
6750 }
6751