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