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