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