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