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