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