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