tc-nds32.c revision 1.1.1.8 1 /* tc-nds32.c -- Assemble for the nds32
2 Copyright (C) 2012-2025 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 /* Tag there is relax relocation having to link. */
101 static bool relaxing = false;
102 /* ICT model. */
103 enum ict_option {
104 ICT_NONE = 0,
105 ICT_SMALL,
106 ICT_LARGE
107 };
108 static enum ict_option ict_flag = ICT_NONE;
109
110
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
2302
2304 /* GAS definitions for command-line options. */
2305 enum options
2306 {
2307 OPTION_BIG = OPTION_MD_BASE,
2308 OPTION_LITTLE,
2309 OPTION_TURBO,
2310 OPTION_PIC,
2311 OPTION_RELAX_FP_AS_GP_OFF,
2312 OPTION_RELAX_B2BB_ON,
2313 OPTION_RELAX_ALL_OFF,
2314 OPTION_OPTIMIZE,
2315 OPTION_OPTIMIZE_SPACE
2316 };
2317
2318 const char md_shortopts[] = "m:O:";
2319 const struct option md_longopts[] =
2320 {
2321 {"O1", no_argument, NULL, OPTION_OPTIMIZE},
2322 {"Os", no_argument, NULL, OPTION_OPTIMIZE_SPACE},
2323 {"big", no_argument, NULL, OPTION_BIG},
2324 {"little", no_argument, NULL, OPTION_LITTLE},
2325 {"EB", no_argument, NULL, OPTION_BIG},
2326 {"EL", no_argument, NULL, OPTION_LITTLE},
2327 {"meb", no_argument, NULL, OPTION_BIG},
2328 {"mel", no_argument, NULL, OPTION_LITTLE},
2329 {"mall-ext", no_argument, NULL, OPTION_TURBO},
2330 {"mext-all", no_argument, NULL, OPTION_TURBO},
2331 {"mpic", no_argument, NULL, OPTION_PIC},
2332 /* Relaxation related options. */
2333 {"mno-fp-as-gp-relax", no_argument, NULL, OPTION_RELAX_FP_AS_GP_OFF},
2334 {"mb2bb", no_argument, NULL, OPTION_RELAX_B2BB_ON},
2335 {"mno-all-relax", no_argument, NULL, OPTION_RELAX_ALL_OFF},
2336 {NULL, no_argument, NULL, 0}
2337 };
2338
2339 const size_t md_longopts_size = sizeof (md_longopts);
2340
2341 struct nds32_parse_option_table
2342 {
2343 const char *name; /* Option string. */
2344 const char *help; /* Help description. */
2345 int (*func) (const char *arg); /* How to parse it. */
2346 };
2347
2348
2349 /* The value `-1' represents this option has *NOT* been set. */
2350 #ifdef NDS32_DEFAULT_ARCH_NAME
2351 static const char* nds32_arch_name = NDS32_DEFAULT_ARCH_NAME;
2352 #else
2353 static const char* nds32_arch_name = "v3";
2354 #endif
2355 static int nds32_baseline = -1;
2356 static int nds32_gpr16 = -1;
2357 static int nds32_fpu_sp_ext = -1;
2358 static int nds32_fpu_dp_ext = -1;
2359 static int nds32_freg = -1;
2360 static int nds32_abi = -1;
2361
2362 /* Record ELF flags */
2363 static int nds32_elf_flags = 0;
2364 static int nds32_fpu_com = 0;
2365
2366 static int nds32_parse_arch (const char *str);
2367 static int nds32_parse_baseline (const char *str);
2368 static int nds32_parse_freg (const char *str);
2369 static int nds32_parse_abi (const char *str);
2370 static void add_mapping_symbol (enum mstate state,
2371 unsigned int padding_byte,
2372 unsigned int align);
2373
2374 static struct nds32_parse_option_table parse_opts [] =
2375 {
2376 {"arch=", N_("<arch name>\t Assemble for architecture <arch name>\n\
2377 <arch name> could be\n\
2378 v3, v3j, v3m, v3f, v3s, "\
2379 "v2, v2j, v2f, v2s"), nds32_parse_arch},
2380 {"baseline=", N_("<baseline>\t Assemble for baseline <baseline>\n\
2381 <baseline> could be v2, v3, v3m"),
2382 nds32_parse_baseline},
2383 {"fpu-freg=", N_("<freg>\t Specify a FPU configuration\n\
2384 <freg>\n\
2385 0: 8 SP / 4 DP registers\n\
2386 1: 16 SP / 8 DP registers\n\
2387 2: 32 SP / 16 DP registers\n\
2388 3: 32 SP / 32 DP registers"), nds32_parse_freg},
2389 {"abi=", N_("<abi>\t Specify a abi version\n\
2390 <abi> could be v1, v2, v2fp, v2fpp"), nds32_parse_abi},
2391 {NULL, NULL, NULL}
2392 };
2393
2394 static int nds32_mac = 1;
2395 static int nds32_div = 1;
2396 static int nds32_16bit_ext = 1;
2397 static int nds32_dx_regs = NDS32_DEFAULT_DX_REGS;
2398 static int nds32_perf_ext = NDS32_DEFAULT_PERF_EXT;
2399 static int nds32_perf_ext2 = NDS32_DEFAULT_PERF_EXT2;
2400 static int nds32_string_ext = NDS32_DEFAULT_STRING_EXT;
2401 static int nds32_audio_ext = NDS32_DEFAULT_AUDIO_EXT;
2402 static int nds32_dsp_ext = NDS32_DEFAULT_DSP_EXT;
2403 static int nds32_zol_ext = NDS32_DEFAULT_ZOL_EXT;
2404 static int nds32_fpu_fma = 0;
2405 static int nds32_pic = 0;
2406 static int nds32_relax_fp_as_gp = 1;
2407 static int nds32_relax_b2bb = 0;
2408 static int nds32_relax_all = 1;
2409 struct nds32_set_option_table
2410 {
2411 const char *name; /* Option string. */
2412 const char *help; /* Help description. */
2413 int *var; /* Variable to be set. */
2414 int value; /* Value to set. */
2415 };
2416
2417 /* The option in this group has both Enable/Disable settings.
2418 Just list on here. */
2419
2420 static struct nds32_set_option_table toggle_opts [] =
2421 {
2422 {"mac", N_("Multiply instructions support"), &nds32_mac, 1},
2423 {"div", N_("Divide instructions support"), &nds32_div, 1},
2424 {"16bit-ext", N_("16-bit extension"), &nds32_16bit_ext, 1},
2425 {"dx-regs", N_("d0/d1 registers"), &nds32_dx_regs, 1},
2426 {"perf-ext", N_("Performance extension"), &nds32_perf_ext, 1},
2427 {"perf2-ext", N_("Performance extension 2"), &nds32_perf_ext2, 1},
2428 {"string-ext", N_("String extension"), &nds32_string_ext, 1},
2429 {"reduced-regs", N_("Reduced Register configuration (GPR16) option"), &nds32_gpr16, 1},
2430 {"audio-isa-ext", N_("AUDIO ISA extension"), &nds32_audio_ext, 1},
2431 {"fpu-sp-ext", N_("FPU SP extension"), &nds32_fpu_sp_ext, 1},
2432 {"fpu-dp-ext", N_("FPU DP extension"), &nds32_fpu_dp_ext, 1},
2433 {"fpu-fma", N_("FPU fused-multiply-add instructions"), &nds32_fpu_fma, 1},
2434 {"dsp-ext", N_("DSP extension"), &nds32_dsp_ext, 1},
2435 {"zol-ext", N_("hardware loop extension"), &nds32_zol_ext, 1},
2436 {NULL, NULL, NULL, 0}
2437 };
2438
2439
2440 /* GAS declarations. */
2442
2443 /* This is the callback for nds32-asm.c to parse operands. */
2444 int
2445 nds32_asm_parse_operand (struct nds32_asm_desc *pdesc,
2446 struct nds32_asm_insn *pinsn,
2447 char **pstr, int64_t *value);
2448
2449
2450 static struct nds32_asm_desc asm_desc;
2452
2453 /* md_after_parse_args ()
2454
2455 GAS will call md_after_parse_args whenever it is defined.
2456 This function checks any conflicting options specified. */
2457
2458 void
2459 nds32_after_parse_args (void)
2460 {
2461 /* If -march option is not used in command-line, set the value of option
2462 variable according to NDS32_DEFAULT_ARCH_NAME. */
2463 nds32_parse_arch (nds32_arch_name);
2464 }
2465
2466 /* This function is called when printing usage message (--help). */
2467
2468 void
2469 md_show_usage (FILE *stream)
2470 {
2471 struct nds32_parse_option_table *coarse_tune;
2472 struct nds32_set_option_table *fine_tune;
2473
2474 fprintf (stream, _("\n NDS32-specific assembler options:\n"));
2475 fprintf (stream, _("\
2476 -O1, Optimize for performance\n\
2477 -Os Optimize for space\n"));
2478 fprintf (stream, _("\
2479 -EL, -mel or -little Produce little endian output\n\
2480 -EB, -meb or -big Produce big endian output\n\
2481 -mpic Generate PIC\n\
2482 -mno-fp-as-gp-relax Suppress fp-as-gp relaxation for this file\n\
2483 -mb2bb-relax Back-to-back branch optimization\n\
2484 -mno-all-relax Suppress all relaxation for this file\n"));
2485
2486 for (coarse_tune = parse_opts; coarse_tune->name != NULL; coarse_tune++)
2487 {
2488 if (coarse_tune->help != NULL)
2489 fprintf (stream, _(" -m%s%s\n"),
2490 coarse_tune->name, _(coarse_tune->help));
2491 }
2492
2493 for (fine_tune = toggle_opts; fine_tune->name != NULL; fine_tune++)
2494 {
2495 if (fine_tune->help != NULL)
2496 fprintf (stream, _(" -m[no-]%-17sEnable/Disable %s\n"),
2497 fine_tune->name, _(fine_tune->help));
2498 }
2499
2500 fprintf (stream, _("\
2501 -mall-ext Turn on all extensions and instructions support\n"));
2502 }
2503
2504 void
2505 nds32_frag_init (fragS *fragp)
2506 {
2507 fragp->tc_frag_data.flag = 0;
2508 fragp->tc_frag_data.opcode = NULL;
2509 fragp->tc_frag_data.fixup = NULL;
2510 }
2511
2512
2513
2515 /* This function reads an expression from a C string and returns a pointer past
2516 the end of the expression. */
2517
2518 static char *
2519 parse_expression (char *str, expressionS *exp)
2520 {
2521 char *s;
2522 char *tmp;
2523
2524 tmp = input_line_pointer; /* Save line pointer. */
2525 input_line_pointer = str;
2526 expression (exp);
2527 resolve_register (exp);
2528 s = input_line_pointer;
2529 input_line_pointer = tmp; /* Restore line pointer. */
2530
2531 return s; /* Return pointer to where parsing stopped. */
2532 }
2533
2534 void
2535 nds32_start_line_hook (void)
2536 {
2537 }
2538
2539 /*
2541 * Pseudo opcodes
2542 */
2543
2544 typedef void (*nds32_pseudo_opcode_func) (int argc, char *argv[], unsigned int pv);
2545 struct nds32_pseudo_opcode
2546 {
2547 const char *opcode;
2548 int argc;
2549 nds32_pseudo_opcode_func proc;
2550 unsigned int pseudo_val;
2551
2552 /* Some instructions are not pseudo opcode, but they might still be
2553 expanded or changed with other instruction combination for some
2554 conditions. We also apply this structure to assist such work.
2555
2556 For example, if the distance of branch target '.L0' is larger than
2557 imm8s<<1 range,
2558
2559 the instruction:
2560
2561 beqzs8 .L0
2562
2563 will be transformed into:
2564
2565 bnezs8 .LCB0
2566 j .L0
2567 .LCB0:
2568
2569 However, sometimes we do not want assembler to do such changes
2570 because compiler knows how to generate corresponding instruction sequence.
2571 Use this field to indicate that this opcode is also a physical instruction.
2572 If the flag 'verbatim' is nozero and this opcode
2573 is a physical instruction, we should not expand it. */
2574 int physical_op;
2575 };
2576 #define PV_DONT_CARE 0
2577
2578 static htab_t nds32_pseudo_opcode_hash = NULL;
2579
2580 static int
2581 builtin_isreg (const char *s, const char *x ATTRIBUTE_UNUSED)
2582 {
2583 if (s [0] == '$' && str_hash_find (nds32_gprs_hash, (s + 1)))
2584 return 1;
2585 return 0;
2586 }
2587
2588 static int
2589 builtin_regnum (const char *s, const char *x ATTRIBUTE_UNUSED)
2590 {
2591 struct nds32_keyword *k;
2592 if (*s != '$')
2593 return -1;
2594 s++;
2595 k = str_hash_find (nds32_gprs_hash, s);
2596
2597 if (k == NULL)
2598 return -1;
2599
2600 return k->value;
2601 }
2602
2603 static int
2604 builtin_addend (const char *s, char *x ATTRIBUTE_UNUSED)
2605 {
2606 const char *ptr = s;
2607
2608 while (*ptr != '+' && *ptr != '-' && *ptr)
2609 ++ptr;
2610
2611 if (*ptr == 0)
2612 return 0;
2613 else
2614 return strtol (ptr, NULL, 0);
2615 }
2616
2617 static void
2618 md_assemblef (const char *format, ...)
2619 {
2620 /* FIXME: hope this is long enough. */
2621 char line[1024];
2622 va_list ap;
2623 unsigned int r;
2624
2625 va_start (ap, format);
2626 r = vsnprintf (line, sizeof (line), format, ap);
2627 md_assemble (line);
2628
2629 gas_assert (r < sizeof (line));
2630 }
2631
2632 /* Some prototypes here, since some op may use another op. */
2633 static void do_pseudo_li_internal (const char *rt, int imm32s);
2634 static void do_pseudo_move_reg_internal (char *dst, char *src);
2635
2636 static void
2637 do_pseudo_b (int argc ATTRIBUTE_UNUSED, char *argv[],
2638 unsigned int pv ATTRIBUTE_UNUSED)
2639 {
2640 char *arg_label = argv[0];
2641 relaxing = true;
2642 /* b label */
2643 if (nds32_pic)
2644 {
2645 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2646 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2647 md_assemble ((char *) "add $ta,$ta,$gp");
2648 md_assemble ((char *) "jr $ta");
2649 }
2650 else
2651 {
2652 md_assemblef ("j %s", arg_label);
2653 }
2654 relaxing = false;
2655 }
2656
2657 static void
2658 do_pseudo_bal (int argc ATTRIBUTE_UNUSED, char *argv[],
2659 unsigned int pv ATTRIBUTE_UNUSED)
2660 {
2661 char *arg_label = argv[0];
2662 relaxing = true;
2663 /* bal|call label */
2664 if (nds32_pic)
2665 {
2666 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2667 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2668 md_assemble ((char *) "add $ta,$ta,$gp");
2669 md_assemble ((char *) "jral $ta");
2670 }
2671 else
2672 {
2673 md_assemblef ("jal %s", arg_label);
2674 }
2675 relaxing = false;
2676 }
2677
2678 static void
2679 do_pseudo_bge (int argc ATTRIBUTE_UNUSED, char *argv[],
2680 unsigned int pv ATTRIBUTE_UNUSED)
2681 {
2682 /* rt5, ra5, label */
2683 md_assemblef ("slt $ta,%s,%s", argv[0], argv[1]);
2684 md_assemblef ("beqz $ta,%s", argv[2]);
2685 }
2686
2687 static void
2688 do_pseudo_bges (int argc ATTRIBUTE_UNUSED, char *argv[],
2689 unsigned int pv ATTRIBUTE_UNUSED)
2690 {
2691 /* rt5, ra5, label */
2692 md_assemblef ("slts $ta,%s,%s", argv[0], argv[1]);
2693 md_assemblef ("beqz $ta,%s", argv[2]);
2694 }
2695
2696 static void
2697 do_pseudo_bgt (int argc ATTRIBUTE_UNUSED, char *argv[],
2698 unsigned int pv ATTRIBUTE_UNUSED)
2699 {
2700 /* bgt rt5, ra5, label */
2701 md_assemblef ("slt $ta,%s,%s", argv[1], argv[0]);
2702 md_assemblef ("bnez $ta,%s", argv[2]);
2703 }
2704
2705 static void
2706 do_pseudo_bgts (int argc ATTRIBUTE_UNUSED, char *argv[],
2707 unsigned int pv ATTRIBUTE_UNUSED)
2708 {
2709 /* bgt rt5, ra5, label */
2710 md_assemblef ("slts $ta,%s,%s", argv[1], argv[0]);
2711 md_assemblef ("bnez $ta,%s", argv[2]);
2712 }
2713
2714 static void
2715 do_pseudo_ble (int argc ATTRIBUTE_UNUSED, char *argv[],
2716 unsigned int pv ATTRIBUTE_UNUSED)
2717 {
2718 /* bgt rt5, ra5, label */
2719 md_assemblef ("slt $ta,%s,%s", argv[1], argv[0]);
2720 md_assemblef ("beqz $ta,%s", argv[2]);
2721 }
2722
2723 static void
2724 do_pseudo_bles (int argc ATTRIBUTE_UNUSED, char *argv[],
2725 unsigned int pv ATTRIBUTE_UNUSED)
2726 {
2727 /* bgt rt5, ra5, label */
2728 md_assemblef ("slts $ta,%s,%s", argv[1], argv[0]);
2729 md_assemblef ("beqz $ta,%s", argv[2]);
2730 }
2731
2732 static void
2733 do_pseudo_blt (int argc ATTRIBUTE_UNUSED, char *argv[],
2734 unsigned int pv ATTRIBUTE_UNUSED)
2735 {
2736 /* rt5, ra5, label */
2737 md_assemblef ("slt $ta,%s,%s", argv[0], argv[1]);
2738 md_assemblef ("bnez $ta,%s", argv[2]);
2739 }
2740
2741 static void
2742 do_pseudo_blts (int argc ATTRIBUTE_UNUSED, char *argv[],
2743 unsigned int pv ATTRIBUTE_UNUSED)
2744 {
2745 /* rt5, ra5, label */
2746 md_assemblef ("slts $ta,%s,%s", argv[0], argv[1]);
2747 md_assemblef ("bnez $ta,%s", argv[2]);
2748 }
2749
2750 static void
2751 do_pseudo_br (int argc ATTRIBUTE_UNUSED, char *argv[],
2752 unsigned int pv ATTRIBUTE_UNUSED)
2753 {
2754 md_assemblef ("jr %s", argv[0]);
2755 }
2756
2757 static void
2758 do_pseudo_bral (int argc, char *argv[],
2759 unsigned int pv ATTRIBUTE_UNUSED)
2760 {
2761 if (argc == 1)
2762 md_assemblef ("jral $lp,%s", argv[0]);
2763 else
2764 md_assemblef ("jral %s,%s", argv[0], argv[1]);
2765 }
2766
2767 static void
2768 do_pseudo_la_internal (const char *arg_reg, char *arg_label,
2769 const char *line)
2770 {
2771 expressionS exp;
2772
2773 parse_expression (arg_label, &exp);
2774 if (exp.X_op != O_symbol)
2775 {
2776 as_bad (_("la must use with symbol. '%s'"), line);
2777 return;
2778 }
2779
2780 relaxing = true;
2781 /* rt, label */
2782 if (!nds32_pic && !strstr (arg_label, "@"))
2783 {
2784 md_assemblef ("sethi %s,hi20(%s)", arg_reg, arg_label);
2785 md_assemblef ("ori %s,%s,lo12(%s)", arg_reg, arg_reg, arg_label);
2786 }
2787 else if (strstr (arg_label, "@TPOFF"))
2788 {
2789 /* la $rt, sym@TPOFF */
2790 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2791 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2792 md_assemblef ("add %s,$ta,%s", arg_reg, TLS_REG);
2793 }
2794 else if (strstr(arg_label, "@GOTTPOFF"))
2795 {
2796 /* la $rt, sym@GOTTPOFF*/
2797 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2798 md_assemblef ("lwi $ta,[$ta+lo12(%s)]", arg_label);
2799 md_assemblef ("add %s,$ta,%s", arg_reg, TLS_REG);
2800 }
2801 else if (nds32_pic && ((strstr (arg_label, "@PLT")
2802 || strstr (arg_label, "@GOTOFF"))))
2803 {
2804 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2805 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2806 md_assemblef ("add %s,$ta,$gp", arg_reg);
2807 }
2808 else if (nds32_pic && strstr (arg_label, "@GOT"))
2809 {
2810 long addend = builtin_addend (arg_label, NULL);
2811
2812 md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2813 md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2814 md_assemblef ("lw %s,[$gp+$ta]", arg_reg);
2815 if (addend != 0)
2816 {
2817 if (addend < 0x4000 && addend >= -0x4000)
2818 {
2819 md_assemblef ("addi %s,%s,%d", arg_reg, arg_reg, addend);
2820 }
2821 else
2822 {
2823 do_pseudo_li_internal ("$ta", addend);
2824 md_assemblef ("add %s,$ta,%s", arg_reg, arg_reg);
2825 }
2826 }
2827 }
2828 else
2829 as_bad (_("need PIC qualifier with symbol. '%s'"), line);
2830 relaxing = false;
2831 }
2832
2833 static void
2834 do_pseudo_la (int argc ATTRIBUTE_UNUSED, char *argv[],
2835 unsigned int pv ATTRIBUTE_UNUSED)
2836 {
2837 do_pseudo_la_internal (argv[0], argv[1], argv[argc]);
2838 }
2839
2840 static void
2841 do_pseudo_li_internal (const char *rt, int imm32s)
2842 {
2843 if (enable_16bit && imm32s <= 0xf && imm32s >= -0x10)
2844 md_assemblef ("movi55 %s,%d", rt, imm32s);
2845 else if (imm32s <= 0x7ffff && imm32s >= -0x80000)
2846 md_assemblef ("movi %s,%d", rt, imm32s);
2847 else if ((imm32s & 0xfff) == 0)
2848 md_assemblef ("sethi %s,hi20(%d)", rt, imm32s);
2849 else
2850 {
2851 md_assemblef ("sethi %s,hi20(%d)", rt, imm32s);
2852 md_assemblef ("ori %s,%s,lo12(%d)", rt, rt, imm32s);
2853 }
2854 }
2855
2856 static void
2857 do_pseudo_li (int argc ATTRIBUTE_UNUSED, char *argv[],
2858 unsigned int pv ATTRIBUTE_UNUSED)
2859 {
2860 /* Validate argv[1] for constant expression. */
2861 expressionS exp;
2862
2863 parse_expression (argv[1], &exp);
2864 if (exp.X_op != O_constant)
2865 {
2866 as_bad (_("Operand is not a constant. `%s'"), argv[argc]);
2867 return;
2868 }
2869
2870 do_pseudo_li_internal (argv[0], exp.X_add_number);
2871 }
2872
2873 static void
2874 do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED, char *argv[],
2875 unsigned int pv)
2876 {
2877 char ls = 'r';
2878 char size = 'x';
2879 const char *sign = "";
2880
2881 /* Prepare arguments for various load/store. */
2882 sign = (pv & 0x10) ? "s" : "";
2883 ls = (pv & 0x80000000) ? 's' : 'l';
2884 switch (pv & 0x3)
2885 {
2886 case 0: size = 'b'; break;
2887 case 1: size = 'h'; break;
2888 case 2: size = 'w'; break;
2889 }
2890
2891 if (ls == 's' || size == 'w')
2892 sign = "";
2893
2894 if (builtin_isreg (argv[1], NULL))
2895 {
2896 /* lwi */
2897 md_assemblef ("%c%ci %s,[%s]", ls, size, argv[0], argv[1]);
2898 }
2899 else if (!nds32_pic)
2900 {
2901 relaxing = true;
2902 if (strstr (argv[1], "@TPOFF"))
2903 {
2904 /* ls.w $rt, sym@TPOFF */
2905 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2906 md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
2907 md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], TLS_REG);
2908 }
2909 else if (strstr (argv[1], "@GOTTPOFF"))
2910 {
2911 /* ls.w $rt, sym@GOTTPOFF */
2912 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2913 md_assemblef ("lwi $ta,[$ta+lo12(%s)]", argv[1]);
2914 md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], TLS_REG);
2915 }
2916 else
2917 {
2918 /* lwi */
2919 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2920 md_assemblef ("%c%c%si %s,[$ta+lo12(%s)]", ls, size, sign, argv[0], argv[1]);
2921 }
2922 relaxing = false;
2923 }
2924 else
2925 {
2926 relaxing = true;
2927 /* PIC code. */
2928 if (strstr (argv[1], "@GOTOFF"))
2929 {
2930 /* lw */
2931 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2932 md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
2933 md_assemblef ("%c%c%s %s,[$ta+$gp]", ls, size, sign, argv[0]);
2934 }
2935 else if (strstr (argv[1], "@GOT"))
2936 {
2937 long addend = builtin_addend (argv[1], NULL);
2938 /* lw */
2939 md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2940 md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
2941 md_assemble ((char *) "lw $ta,[$gp+$ta]"); /* Load address word. */
2942 if (addend < 0x10000 && addend >= -0x10000)
2943 {
2944 md_assemblef ("%c%c%si %s,[$ta+(%d)]", ls, size, sign, argv[0], addend);
2945 }
2946 else
2947 {
2948 /* lw */
2949 do_pseudo_li_internal (argv[0], addend);
2950 md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], argv[0]);
2951 }
2952 }
2953 else
2954 {
2955 as_bad (_("needs @GOT or @GOTOFF. %s"), argv[argc]);
2956 }
2957 relaxing = false;
2958 }
2959 }
2960
2961 static void
2962 do_pseudo_ls_bhwp (int argc ATTRIBUTE_UNUSED, char *argv[],
2963 unsigned int pv)
2964 {
2965 char *arg_rt = argv[0];
2966 char *arg_label = argv[1];
2967 char *arg_inc = argv[2];
2968 char ls = 'r';
2969 char size = 'x';
2970 const char *sign = "";
2971
2972 /* Prepare arguments for various load/store. */
2973 sign = (pv & 0x10) ? "s" : "";
2974 ls = (pv & 0x80000000) ? 's' : 'l';
2975 switch (pv & 0x3)
2976 {
2977 case 0: size = 'b'; break;
2978 case 1: size = 'h'; break;
2979 case 2: size = 'w'; break;
2980 }
2981
2982 if (ls == 's' || size == 'w')
2983 sign = "";
2984
2985 do_pseudo_la_internal ("$ta", arg_label, argv[argc]);
2986 md_assemblef ("%c%c%si.bi %s,[$ta],%s", ls, size, sign, arg_rt, arg_inc);
2987 }
2988
2989 static void
2990 do_pseudo_ls_bhwpc (int argc ATTRIBUTE_UNUSED, char *argv[],
2991 unsigned int pv)
2992 {
2993 char *arg_rt = argv[0];
2994 char *arg_inc = argv[1];
2995 char ls = 'r';
2996 char size = 'x';
2997 const char *sign = "";
2998
2999 /* Prepare arguments for various load/store. */
3000 sign = (pv & 0x10) ? "s" : "";
3001 ls = (pv & 0x80000000) ? 's' : 'l';
3002 switch (pv & 0x3)
3003 {
3004 case 0: size = 'b'; break;
3005 case 1: size = 'h'; break;
3006 case 2: size = 'w'; break;
3007 }
3008
3009 if (ls == 's' || size == 'w')
3010 sign = "";
3011
3012 md_assemblef ("%c%c%si.bi %s,[$ta],%s", ls, size, sign, arg_rt, arg_inc);
3013 }
3014
3015 static void
3016 do_pseudo_ls_bhwi (int argc ATTRIBUTE_UNUSED, char *argv[],
3017 unsigned int pv)
3018 {
3019 char ls = 'r';
3020 char size = 'x';
3021 const char *sign = "";
3022
3023 /* Prepare arguments for various load/store. */
3024 sign = (pv & 0x10) ? "s" : "";
3025 ls = (pv & 0x80000000) ? 's' : 'l';
3026 switch (pv & 0x3)
3027 {
3028 case 0: size = 'b'; break;
3029 case 1: size = 'h'; break;
3030 case 2: size = 'w'; break;
3031 }
3032
3033 if (ls == 's' || size == 'w')
3034 sign = "";
3035
3036 md_assemblef ("%c%c%si.bi %s,%s,%s",
3037 ls, size, sign, argv[0], argv[1], argv[2]);
3038 }
3039
3040 static void
3041 do_pseudo_move_reg_internal (char *dst, char *src)
3042 {
3043 if (enable_16bit)
3044 md_assemblef ("mov55 %s,%s", dst, src);
3045 else
3046 md_assemblef ("ori %s,%s,0", dst, src);
3047 }
3048
3049 static void
3050 do_pseudo_move (int argc ATTRIBUTE_UNUSED, char *argv[],
3051 unsigned int pv ATTRIBUTE_UNUSED)
3052 {
3053 expressionS exp;
3054
3055 if (builtin_isreg (argv[1], NULL))
3056 do_pseudo_move_reg_internal (argv[0], argv[1]);
3057 else
3058 {
3059 parse_expression (argv[1], &exp);
3060 if (exp.X_op == O_constant)
3061 /* move $rt, imm -> li $rt, imm */
3062 do_pseudo_li_internal (argv[0], exp.X_add_number);
3063 else
3064 /* l.w $rt, var -> l.w $rt, var */
3065 do_pseudo_ls_bhw (argc, argv, 2);
3066 }
3067 }
3068
3069 static void
3070 do_pseudo_neg (int argc ATTRIBUTE_UNUSED, char *argv[],
3071 unsigned int pv ATTRIBUTE_UNUSED)
3072 {
3073 /* Instead of "subri". */
3074 md_assemblef ("subri %s,%s,0", argv[0], argv[1]);
3075 }
3076
3077 static void
3078 do_pseudo_not (int argc ATTRIBUTE_UNUSED, char *argv[],
3079 unsigned int pv ATTRIBUTE_UNUSED)
3080 {
3081 md_assemblef ("nor %s,%s,%s", argv[0], argv[1], argv[1]);
3082 }
3083
3084 static void
3085 do_pseudo_pushpopm (int argc, char *argv[],
3086 unsigned int pv ATTRIBUTE_UNUSED)
3087 {
3088 /* posh/pop $ra, $rb */
3089 /* SMW.{b | a}{i | d}{m?} Rb, [Ra], Re, Enable4 */
3090 int rb, re, ra, en4;
3091 int i;
3092 const char *opc = "pushpopm";
3093
3094 if (argc == 3)
3095 as_bad ("'pushm/popm $ra5, $rb5, $label' is deprecated. "
3096 "Only 'pushm/popm $ra5' is supported now. %s", argv[argc]);
3097 else if (argc == 1)
3098 as_bad ("'pushm/popm $ra5, $rb5'. %s\n", argv[argc]);
3099
3100 if (strstr (argv[argc], "pop") == argv[argc])
3101 opc = "lmw.bim";
3102 else if (strstr (argv[argc], "push") == argv[argc])
3103 opc = "smw.adm";
3104 else
3105 as_fatal ("nds32-as internal error. %s", argv[argc]);
3106
3107 rb = builtin_regnum (argv[0], NULL);
3108 re = builtin_regnum (argv[1], NULL);
3109
3110 if (re < rb)
3111 {
3112 as_warn ("$rb should not be smaller than $ra. %s", argv[argc]);
3113 /* Swap to right order. */
3114 ra = re;
3115 re = rb;
3116 rb = ra;
3117 }
3118
3119 /* Build enable4 mask. */
3120 en4 = 0;
3121 if (re >= 28 || rb >= 28)
3122 {
3123 for (i = (rb >= 28? rb: 28); i <= re; i++)
3124 en4 |= 1 << (3 - (i - 28));
3125 }
3126
3127 /* Adjust $re, $rb. */
3128 if (rb >= 28)
3129 rb = re = 31;
3130 else if (nds32_gpr16 != 1 && re >= 28)
3131 re = 27;
3132
3133 /* Reduce register. */
3134 if (nds32_gpr16 && re > 10 && !(rb == 31 && re == 31))
3135 {
3136 if (re >= 15 && strstr (opc, "smw") != NULL)
3137 md_assemblef ("%s $r15,[$sp],$r15,%d", opc, en4);
3138 if (rb <= 10)
3139 md_assemblef ("%s $r%d,[$sp],$r10, 0x0", opc, rb);
3140 if (re >= 15 && strstr (opc, "lmw") != NULL)
3141 md_assemblef ("%s $r15,[$sp],$r15,%d", opc, en4);
3142 }
3143 else
3144 md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc, rb, re, en4);
3145 }
3146
3147 static void
3148 do_pseudo_pushpop (int argc, char *argv[],
3149 unsigned int pv ATTRIBUTE_UNUSED)
3150 {
3151 /* push/pop $ra5, $label=$sp */
3152 char *argvm[3];
3153
3154 if (argc == 2)
3155 as_bad ("'push/pop $ra5, rb5' is deprecated. "
3156 "Only 'push/pop $ra5' is supported now. %s", argv[argc]);
3157
3158 argvm[0] = argv[0];
3159 argvm[1] = argv[0];
3160 argvm[2] = argv[argc];
3161 do_pseudo_pushpopm (2, argvm, PV_DONT_CARE);
3162 }
3163
3164 static void
3165 do_pseudo_v3push (int argc ATTRIBUTE_UNUSED, char *argv[],
3166 unsigned int pv ATTRIBUTE_UNUSED)
3167 {
3168 md_assemblef ("push25 %s,%s", argv[0], argv[1]);
3169 }
3170
3171 static void
3172 do_pseudo_v3pop (int argc ATTRIBUTE_UNUSED, char *argv[],
3173 unsigned int pv ATTRIBUTE_UNUSED)
3174 {
3175 md_assemblef ("pop25 %s,%s", argv[0], argv[1]);
3176 }
3177
3178 /* pv == 0, parsing "push.s" pseudo instruction operands.
3179 pv != 0, parsing "pop.s" pseudo instruction operands. */
3180
3181 static void
3182 do_pseudo_pushpop_stack (int argc, char *argv[],
3183 unsigned int pv)
3184 {
3185 /* push.s Rb,Re,{$fp $gp $lp $sp} ==> smw.adm Rb,[$sp],Re,Eable4 */
3186 /* pop.s Rb,Re,{$fp $gp $lp $sp} ==> lmw.bim Rb,[$sp],Re,Eable4 */
3187
3188 int rb, re;
3189 int en4;
3190 int last_arg_index;
3191 const char *opc = (pv == 0) ? "smw.adm" : "lmw.bim";
3192
3193 rb = re = 0;
3194
3195 if (argc == 1)
3196 {
3197 /* argc=1, operands pattern: { $fp $gp $lp $sp } */
3198
3199 /* Set register number Rb = Re = $sp = $r31. */
3200 rb = re = 31;
3201 }
3202 else if (argc == 2 || argc == 3)
3203 {
3204 /* argc=2, operands pattern: Rb, Re */
3205 /* argc=3, operands pattern: Rb, Re, { $fp $gp $lp $sp } */
3206
3207 /* Get register number in integer. */
3208 rb = builtin_regnum (argv[0], NULL);
3209 re = builtin_regnum (argv[1], NULL);
3210
3211 /* Rb should be equal/less than Re. */
3212 if (rb > re)
3213 as_bad ("The first operand (%s) should be equal to or smaller than "
3214 "second operand (%s).", argv[0], argv[1]);
3215
3216 /* forbid using $fp|$gp|$lp|$sp in Rb or Re
3217 r28 r29 r30 r31 */
3218 if (rb >= 28)
3219 as_bad ("Cannot use $fp, $gp, $lp, or $sp at first operand !!");
3220 if (re >= 28)
3221 as_bad ("Cannot use $fp, $gp, $lp, or $sp at second operand !!");
3222 }
3223 else
3224 {
3225 as_bad ("Invalid operands pattern !!");
3226 }
3227
3228 /* Build Enable4 mask. */
3229 /* Using last_arg_index for argc=1|2|3 is safe, because $fp, $gp, $lp,
3230 and $sp only appear in argc=1 or argc=3 if argc=2, en4 remains 0,
3231 which is also valid for code generation. */
3232 en4 = 0;
3233 last_arg_index = argc - 1;
3234 if (strstr (argv[last_arg_index], "$fp"))
3235 en4 |= 8;
3236 if (strstr (argv[last_arg_index], "$gp"))
3237 en4 |= 4;
3238 if (strstr (argv[last_arg_index], "$lp"))
3239 en4 |= 2;
3240 if (strstr (argv[last_arg_index], "$sp"))
3241 en4 |= 1;
3242
3243 md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc, rb, re, en4);
3244 }
3245
3246 static void
3247 do_pseudo_push_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[],
3248 unsigned int pv ATTRIBUTE_UNUSED)
3249 {
3250 char size = 'x';
3251 /* If users omit push location, use $sp as default value. */
3252 char location[8] = "$sp"; /* 8 is enough for register name. */
3253
3254 switch (pv & 0x3)
3255 {
3256 case 0: size = 'b'; break;
3257 case 1: size = 'h'; break;
3258 case 2: size = 'w'; break;
3259 case 3: size = 'w'; break;
3260 }
3261
3262 if (argc == 2)
3263 {
3264 strncpy (location, argv[1], sizeof (location) - 1);
3265 location[sizeof (location) - 1] = '\0';
3266 }
3267
3268 md_assemblef ("l.%c $ta,%s", size, argv[0]);
3269 md_assemblef ("smw.adm $ta,[%s],$ta", location);
3270
3271 if ((pv & 0x3) == 0x3) /* double-word */
3272 {
3273 md_assemblef ("l.w $ta,%s+4", argv[0]);
3274 md_assemblef ("smw.adm $ta,[%s],$ta", location);
3275 }
3276 }
3277
3278 static void
3279 do_pseudo_pop_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[],
3280 unsigned int pv ATTRIBUTE_UNUSED)
3281 {
3282 char size = 'x';
3283 /* If users omit pop location, use $sp as default value. */
3284 char location[8] = "$sp"; /* 8 is enough for register name. */
3285
3286 switch (pv & 0x3)
3287 {
3288 case 0: size = 'b'; break;
3289 case 1: size = 'h'; break;
3290 case 2: size = 'w'; break;
3291 case 3: size = 'w'; break;
3292 }
3293
3294 if (argc == 3)
3295 {
3296 strncpy (location, argv[2], sizeof (location) - 1);
3297 location[sizeof (location) - 1] = '\0';
3298 }
3299
3300 if ((pv & 0x3) == 0x3) /* double-word */
3301 {
3302 md_assemblef ("lmw.bim %s,[%s],%s", argv[1], location, argv[1]);
3303 md_assemblef ("s.w %s,%s+4", argv[1], argv[0]);
3304 }
3305
3306 md_assemblef ("lmw.bim %s,[%s],%s", argv[1], location, argv[1]);
3307 md_assemblef ("s.%c %s,%s", size, argv[1], argv[0]);
3308 }
3309
3310 static void
3311 do_pseudo_pusha (int argc ATTRIBUTE_UNUSED, char *argv[],
3312 unsigned int pv ATTRIBUTE_UNUSED)
3313 {
3314 /* If users omit push location, use $sp as default value. */
3315 char location[8] = "$sp"; /* 8 is enough for register name. */
3316
3317 if (argc == 2)
3318 {
3319 strncpy (location, argv[1], sizeof (location) - 1);
3320 location[sizeof (location) - 1] = '\0';
3321 }
3322
3323 md_assemblef ("la $ta,%s", argv[0]);
3324 md_assemblef ("smw.adm $ta,[%s],$ta", location);
3325 }
3326
3327 static void
3328 do_pseudo_pushi (int argc ATTRIBUTE_UNUSED, char *argv[],
3329 unsigned int pv ATTRIBUTE_UNUSED)
3330 {
3331 /* If users omit push location, use $sp as default value. */
3332 char location[8] = "$sp"; /* 8 is enough for register name. */
3333
3334 if (argc == 2)
3335 {
3336 strncpy (location, argv[1], sizeof (location) - 1);
3337 location[sizeof (location) - 1] = '\0';
3338 }
3339
3340 md_assemblef ("li $ta,%s", argv[0]);
3341 md_assemblef ("smw.adm $ta,[%s],$ta", location);
3342 }
3343
3344 static struct nds32_pseudo_opcode nds32_pseudo_opcode_table[] =
3345 {
3346 {"b", 1, do_pseudo_b, 0, 0},
3347 {"bal", 1, do_pseudo_bal, 0, 0},
3348
3349 {"bge", 3, do_pseudo_bge, 0, 0},
3350 {"bges", 3, do_pseudo_bges, 0, 0},
3351
3352 {"bgt", 3, do_pseudo_bgt, 0, 0},
3353 {"bgts", 3, do_pseudo_bgts, 0, 0},
3354
3355 {"ble", 3, do_pseudo_ble, 0, 0},
3356 {"bles", 3, do_pseudo_bles, 0, 0},
3357
3358 {"blt", 3, do_pseudo_blt, 0, 0},
3359 {"blts", 3, do_pseudo_blts, 0, 0},
3360
3361 {"br", 1, do_pseudo_br, 0, 0},
3362 {"bral", 1, do_pseudo_bral, 0, 0},
3363
3364 {"call", 1, do_pseudo_bal, 0, 0},
3365
3366 {"la", 2, do_pseudo_la, 0, 0},
3367 {"li", 2, do_pseudo_li, 0, 0},
3368
3369 {"l.b", 2, do_pseudo_ls_bhw, 0, 0},
3370 {"l.h", 2, do_pseudo_ls_bhw, 1, 0},
3371 {"l.w", 2, do_pseudo_ls_bhw, 2, 0},
3372 {"l.bs", 2, do_pseudo_ls_bhw, 0 | 0x10, 0},
3373 {"l.hs", 2, do_pseudo_ls_bhw, 1 | 0x10, 0},
3374 {"s.b", 2, do_pseudo_ls_bhw, 0 | 0x80000000, 0},
3375 {"s.h", 2, do_pseudo_ls_bhw, 1 | 0x80000000, 0},
3376 {"s.w", 2, do_pseudo_ls_bhw, 2 | 0x80000000, 0},
3377
3378 {"l.bp", 3, do_pseudo_ls_bhwp, 0, 0},
3379 {"l.bpc", 3, do_pseudo_ls_bhwpc, 0, 0},
3380 {"l.hp", 3, do_pseudo_ls_bhwp, 1, 0},
3381 {"l.hpc", 3, do_pseudo_ls_bhwpc, 1, 0},
3382 {"l.wp", 3, do_pseudo_ls_bhwp, 2, 0},
3383 {"l.wpc", 3, do_pseudo_ls_bhwpc, 2, 0},
3384 {"l.bsp", 3, do_pseudo_ls_bhwp, 0 | 0x10, 0},
3385 {"l.bspc", 3, do_pseudo_ls_bhwpc, 0 | 0x10, 0},
3386 {"l.hsp", 3, do_pseudo_ls_bhwp, 1 | 0x10, 0},
3387 {"l.hspc", 3, do_pseudo_ls_bhwpc, 1 | 0x10, 0},
3388 {"s.bp", 3, do_pseudo_ls_bhwp, 0 | 0x80000000, 0},
3389 {"s.bpc", 3, do_pseudo_ls_bhwpc, 0 | 0x80000000, 0},
3390 {"s.hp", 3, do_pseudo_ls_bhwp, 1 | 0x80000000, 0},
3391 {"s.hpc", 3, do_pseudo_ls_bhwpc, 1 | 0x80000000, 0},
3392 {"s.wp", 3, do_pseudo_ls_bhwp, 2 | 0x80000000, 0},
3393 {"s.wpc", 3, do_pseudo_ls_bhwpc, 2 | 0x80000000, 0},
3394 {"s.bsp", 3, do_pseudo_ls_bhwp, 0 | 0x80000000 | 0x10, 0},
3395 {"s.hsp", 3, do_pseudo_ls_bhwp, 1 | 0x80000000 | 0x10, 0},
3396
3397 {"lbi.p", 3, do_pseudo_ls_bhwi, 0, 0},
3398 {"lhi.p", 3, do_pseudo_ls_bhwi, 1, 0},
3399 {"lwi.p", 3, do_pseudo_ls_bhwi, 2, 0},
3400 {"sbi.p", 3, do_pseudo_ls_bhwi, 0 | 0x80000000, 0},
3401 {"shi.p", 3, do_pseudo_ls_bhwi, 1 | 0x80000000, 0},
3402 {"swi.p", 3, do_pseudo_ls_bhwi, 2 | 0x80000000, 0},
3403 {"lbsi.p", 3, do_pseudo_ls_bhwi, 0 | 0x10, 0},
3404 {"lhsi.p", 3, do_pseudo_ls_bhwi, 1 | 0x10, 0},
3405 {"lwsi.p", 3, do_pseudo_ls_bhwi, 2 | 0x10, 0},
3406
3407 {"move", 2, do_pseudo_move, 0, 0},
3408 {"neg", 2, do_pseudo_neg, 0, 0},
3409 {"not", 2, do_pseudo_not, 0, 0},
3410
3411 {"pop", 2, do_pseudo_pushpop, 0, 0},
3412 {"push", 2, do_pseudo_pushpop, 0, 0},
3413 {"popm", 2, do_pseudo_pushpopm, 0, 0},
3414 {"pushm", 3, do_pseudo_pushpopm, 0, 0},
3415
3416 {"v3push", 2, do_pseudo_v3push, 0, 0},
3417 {"v3pop", 2, do_pseudo_v3pop, 0, 0},
3418
3419 /* Support pseudo instructions of pushing/poping registers into/from stack
3420 push.s Rb, Re, { $fp $gp $lp $sp } ==> smw.adm Rb,[$sp],Re,Enable4
3421 pop.s Rb, Re, { $fp $gp $lp $sp } ==> lmw.bim Rb,[$sp],Re,Enable4 */
3422 { "push.s", 3, do_pseudo_pushpop_stack, 0, 0 },
3423 { "pop.s", 3, do_pseudo_pushpop_stack, 1, 0 },
3424 { "push.b", 2, do_pseudo_push_bhwd, 0, 0 },
3425 { "push.h", 2, do_pseudo_push_bhwd, 1, 0 },
3426 { "push.w", 2, do_pseudo_push_bhwd, 2, 0 },
3427 { "push.d", 2, do_pseudo_push_bhwd, 3, 0 },
3428 { "pop.b", 3, do_pseudo_pop_bhwd, 0, 0 },
3429 { "pop.h", 3, do_pseudo_pop_bhwd, 1, 0 },
3430 { "pop.w", 3, do_pseudo_pop_bhwd, 2, 0 },
3431 { "pop.d", 3, do_pseudo_pop_bhwd, 3, 0 },
3432 { "pusha", 2, do_pseudo_pusha, 0, 0 },
3433 { "pushi", 2, do_pseudo_pushi, 0, 0 },
3434
3435 {NULL, 0, NULL, 0, 0}
3436 };
3437
3438 static void
3439 nds32_init_nds32_pseudo_opcodes (void)
3440 {
3441 struct nds32_pseudo_opcode *opcode;
3442
3443 nds32_pseudo_opcode_hash = str_htab_create ();
3444 for (opcode = nds32_pseudo_opcode_table; opcode->opcode; opcode++)
3445 if (str_hash_insert (nds32_pseudo_opcode_hash, opcode->opcode, opcode, 0))
3446 as_fatal (_("duplicate %s"), opcode->opcode);
3447 }
3448
3449 static struct nds32_pseudo_opcode *
3450 nds32_lookup_pseudo_opcode (const char *str)
3451 {
3452 struct nds32_pseudo_opcode *result;
3453 int i = 0;
3454
3455 /* (*op) is the first word of current source line (*str) */
3456 int maxlen = strlen (str);
3457 char *op = xmalloc (maxlen + 1);
3458
3459 for (i = 0; i < maxlen; i++)
3460 {
3461 if (is_whitespace (op[i] = str[i]))
3462 break;
3463 }
3464 op[i] = '\0';
3465
3466 result = str_hash_find (nds32_pseudo_opcode_hash, op);
3467 free (op);
3468 return result;
3469 }
3470
3471 static void
3472 nds32_pseudo_opcode_wrapper (char *line, struct nds32_pseudo_opcode *opcode)
3473 {
3474 int argc = 0;
3475 char *argv[8] = {NULL};
3476 char *s;
3477 char *str = xstrdup (line);
3478
3479 /* Parse arguments for opcode. */
3480 s = str + strlen (opcode->opcode);
3481
3482 if (!s[0])
3483 goto end;
3484
3485 /* Dummy comma to ease separate arguments as below. */
3486 s[0] = ',';
3487 do
3488 {
3489 if (s[0] == ',')
3490 {
3491 if (argc >= opcode->argc
3492 || (argc >= (int)ARRAY_SIZE (argv) - 1))
3493 as_bad (_("Too many argument. `%s'"), line);
3494
3495 argv[argc] = s + 1;
3496 argc ++;
3497 s[0] = '\0';
3498 }
3499 ++s;
3500 } while (s[0] != '\0');
3501 end:
3502 /* Put the origin line for debugging. */
3503 argv[argc] = line;
3504 opcode->proc (argc, argv, opcode->pseudo_val);
3505 free (str);
3506 }
3507
3508 /* This function will be invoked from function `nds32_after_parse_args'.
3510 Thus, if the value of option has been set, keep the value the way it is. */
3511
3512 static int
3513 nds32_parse_arch (const char *str)
3514 {
3515 static const struct nds32_arch
3516 {
3517 const char *name;
3518 int baseline;
3519 int reduced_reg;
3520 int fpu_sp_ext;
3521 int fpu_dp_ext;
3522 int fpu_freg;
3523 int abi;
3524 } archs[] =
3525 {
3526 {"v3m", ISA_V3M, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3527 {"v3j", ISA_V3, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3528 {"v3s", ISA_V3, 0, 1, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3529 {"v3f", ISA_V3, 0, 1, 1, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3530 {"v3", ISA_V3, 0, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3531 {"v2j", ISA_V2, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3532 {"v2s", ISA_V2, 0, 1, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3533 {"v2f", ISA_V2, 0, 1, 1, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3534 {"v2", ISA_V2, 0, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3535 };
3536 size_t i;
3537
3538 for (i = 0; i < ARRAY_SIZE (archs); i++)
3539 {
3540 if (strcmp (str, archs[i].name) != 0)
3541 continue;
3542
3543 /* The value `-1' represents this option has *NOT* been set. */
3544 nds32_baseline = (-1 != nds32_baseline) ? nds32_baseline : archs[i].baseline;
3545 nds32_gpr16 = (-1 != nds32_gpr16) ? nds32_gpr16 : archs[i].reduced_reg;
3546 nds32_fpu_sp_ext = (-1 != nds32_fpu_sp_ext) ? nds32_fpu_sp_ext : archs[i].fpu_sp_ext;
3547 nds32_fpu_dp_ext = (-1 != nds32_fpu_dp_ext) ? nds32_fpu_dp_ext : archs[i].fpu_dp_ext;
3548 nds32_freg = (-1 != nds32_freg) ? nds32_freg : archs[i].fpu_freg;
3549 nds32_abi = (-1 != nds32_abi) ? nds32_abi : archs[i].abi;
3550
3551 return 1;
3552 }
3553
3554 /* Logic here rejects the input arch name. */
3555 as_bad (_("unknown arch name `%s'\n"), str);
3556
3557 return 1;
3558 }
3559
3560 /* This function parses "baseline" specified. */
3561
3562 static int
3563 nds32_parse_baseline (const char *str)
3564 {
3565 if (strcmp (str, "v3") == 0)
3566 nds32_baseline = ISA_V3;
3567 else if (strcmp (str, "v3m") == 0)
3568 nds32_baseline = ISA_V3M;
3569 else if (strcmp (str, "v2") == 0)
3570 nds32_baseline = ISA_V2;
3571 else
3572 {
3573 /* Logic here rejects the input baseline. */
3574 as_bad (_("unknown baseline `%s'\n"), str);
3575 return 0;
3576 }
3577
3578 return 1;
3579 }
3580
3581 /* This function parses "fpu-freg" specified. */
3582
3583 static int
3584 nds32_parse_freg (const char *str)
3585 {
3586 if (strcmp (str, "2") == 0)
3587 nds32_freg = E_NDS32_FPU_REG_32SP_16DP;
3588 else if (strcmp (str, "3") == 0)
3589 nds32_freg = E_NDS32_FPU_REG_32SP_32DP;
3590 else if (strcmp (str, "1") == 0)
3591 nds32_freg = E_NDS32_FPU_REG_16SP_8DP;
3592 else if (strcmp (str, "0") == 0)
3593 nds32_freg = E_NDS32_FPU_REG_8SP_4DP;
3594 else
3595 {
3596 /* Logic here rejects the input FPU configuration. */
3597 as_bad (_("unknown FPU configuration `%s'\n"), str);
3598 return 0;
3599 }
3600
3601 return 1;
3602 }
3603
3604 /* This function parse "abi=" specified. */
3605
3606 static int
3607 nds32_parse_abi (const char *str)
3608 {
3609 if (strcmp (str, "v2") == 0)
3610 nds32_abi = E_NDS_ABI_AABI;
3611 /* Obsolete. */
3612 else if (strcmp (str, "v2fp") == 0)
3613 nds32_abi = E_NDS_ABI_V2FP;
3614 else if (strcmp (str, "v1") == 0)
3615 nds32_abi = E_NDS_ABI_V1;
3616 else if (strcmp (str,"v2fpp") == 0)
3617 nds32_abi = E_NDS_ABI_V2FP_PLUS;
3618 else
3619 {
3620 /* Logic here rejects the input abi version. */
3621 as_bad (_("unknown ABI version`%s'\n"), str);
3622 return 0;
3623 }
3624
3625 return 1;
3626 }
3627
3628 /* This function turn on all extensions and instructions support. */
3629
3630 static int
3631 nds32_all_ext (void)
3632 {
3633 nds32_mac = 1;
3634 nds32_div = 1;
3635 nds32_dx_regs = 1;
3636 nds32_16bit_ext = 1;
3637 nds32_perf_ext = 1;
3638 nds32_perf_ext2 = 1;
3639 nds32_string_ext = 1;
3640 nds32_audio_ext = 1;
3641 nds32_fpu_fma = 1;
3642 nds32_fpu_sp_ext = 1;
3643 nds32_fpu_dp_ext = 1;
3644 nds32_dsp_ext = 1;
3645 nds32_zol_ext = 1;
3646 /* Turn off reduced register. */
3647 nds32_gpr16 = 0;
3648
3649 return 1;
3650 }
3651
3652 /* GAS will call md_parse_option whenever getopt returns an unrecognized code,
3653 presumably indicating a special code value which appears in md_longopts.
3654 This function should return non-zero if it handled the option and zero
3655 otherwise. There is no need to print a message about an option not being
3656 recognized. This will be handled by the generic code. */
3657
3658 int
3659 nds32_parse_option (int c, const char *arg)
3660 {
3661 struct nds32_parse_option_table *coarse_tune;
3662 struct nds32_set_option_table *fine_tune;
3663 const char *ptr_arg = NULL;
3664
3665 switch (c)
3666 {
3667 case OPTION_OPTIMIZE:
3668 optimize = 1;
3669 optimize_for_space = 0;
3670 break;
3671 case OPTION_OPTIMIZE_SPACE:
3672 optimize = 0;
3673 optimize_for_space = 1;
3674 break;
3675 case OPTION_BIG:
3676 target_big_endian = 1;
3677 break;
3678 case OPTION_LITTLE:
3679 target_big_endian = 0;
3680 break;
3681 case OPTION_TURBO:
3682 nds32_all_ext ();
3683 break;
3684 case OPTION_PIC:
3685 nds32_pic = 1;
3686 break;
3687 case OPTION_RELAX_FP_AS_GP_OFF:
3688 nds32_relax_fp_as_gp = 0;
3689 break;
3690 case OPTION_RELAX_B2BB_ON:
3691 nds32_relax_b2bb = 1;
3692 break;
3693 case OPTION_RELAX_ALL_OFF:
3694 nds32_relax_all = 0;
3695 break;
3696 default:
3697 /* Determination of which option table to search for to save time. */
3698 if (!arg)
3699 return 0;
3700
3701 ptr_arg = strchr (arg, '=');
3702
3703 if (ptr_arg)
3704 {
3705 /* Find the value after '='. */
3706 if (ptr_arg != NULL)
3707 ptr_arg++;
3708 for (coarse_tune = parse_opts; coarse_tune->name != NULL; coarse_tune++)
3709 {
3710 if (strncmp (arg, coarse_tune->name, (ptr_arg - arg)) == 0)
3711 {
3712 coarse_tune->func (ptr_arg);
3713 return 1;
3714 }
3715 }
3716 }
3717 else
3718 {
3719 int disable = 0;
3720
3721 /* Filter out the Disable option first. */
3722 if (startswith (arg, "no-"))
3723 {
3724 disable = 1;
3725 arg += 3;
3726 }
3727
3728 for (fine_tune = toggle_opts; fine_tune->name != NULL; fine_tune++)
3729 {
3730 if (strcmp (arg, fine_tune->name) == 0)
3731 {
3732 if (fine_tune->var != NULL)
3733 *fine_tune->var = (disable) ? 0 : 1;
3734 return 1;
3735 }
3736 }
3737 }
3738 /* Nothing match. */
3739 return 0;
3740 }
3741
3742 return 1;
3743 }
3744
3745 /* tc_check_label */
3746
3747 void
3748 nds32_check_label (symbolS *label ATTRIBUTE_UNUSED)
3749 {
3750 /* The code used to create BB is move to frob_label.
3751 They should go there. */
3752 }
3753
3754 static void
3755 set_endian_little (int on)
3756 {
3757 target_big_endian = !on;
3758 }
3759
3760 /* These functions toggles the generation of 16-bit. First encounter signals
3761 the beginning of not generating 16-bit instructions and next encounter
3762 signals the restoring back to default behavior. */
3763
3764 static void
3765 trigger_16bit (int trigger)
3766 {
3767 enable_16bit = trigger;
3768 }
3769
3770 static int backup_16bit_mode;
3771 static void
3772 restore_16bit (int no_use ATTRIBUTE_UNUSED)
3773 {
3774 enable_16bit = backup_16bit_mode;
3775 }
3776
3777 static void
3778 off_16bit (int no_use ATTRIBUTE_UNUSED)
3779 {
3780 backup_16bit_mode = enable_16bit;
3781 enable_16bit = 0;
3782 }
3783
3784 /* Built-in segments for small object. */
3785 typedef struct nds32_seg_entryT
3786 {
3787 segT s;
3788 const char *name;
3789 flagword flags;
3790 } nds32_seg_entry;
3791
3792 nds32_seg_entry nds32_seg_table[] =
3793 {
3794 {NULL, ".sdata_f", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3795 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3796 {NULL, ".sdata_b", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3797 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3798 {NULL, ".sdata_h", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3799 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3800 {NULL, ".sdata_w", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3801 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3802 {NULL, ".sdata_d", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3803 | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3804 {NULL, ".sbss_f", SEC_ALLOC | SEC_SMALL_DATA},
3805 {NULL, ".sbss_b", SEC_ALLOC | SEC_SMALL_DATA},
3806 {NULL, ".sbss_h", SEC_ALLOC | SEC_SMALL_DATA},
3807 {NULL, ".sbss_w", SEC_ALLOC | SEC_SMALL_DATA},
3808 {NULL, ".sbss_d", SEC_ALLOC | SEC_SMALL_DATA}
3809 };
3810
3811 /* Indexes to nds32_seg_table[]. */
3812 enum NDS32_SECTIONS_ENUM
3813 {
3814 SDATA_F_SECTION = 0,
3815 SDATA_B_SECTION = 1,
3816 SDATA_H_SECTION = 2,
3817 SDATA_W_SECTION = 3,
3818 SDATA_D_SECTION = 4,
3819 SBSS_F_SECTION = 5,
3820 SBSS_B_SECTION = 6,
3821 SBSS_H_SECTION = 7,
3822 SBSS_W_SECTION = 8,
3823 SBSS_D_SECTION = 9
3824 };
3825
3826 /* The following code is borrowed from v850_seg. Revise this is needed. */
3827
3828 static void
3829 do_nds32_seg (int i, subsegT sub)
3830 {
3831 nds32_seg_entry *seg = nds32_seg_table + i;
3832
3833 obj_elf_section_change_hook ();
3834
3835 if (seg->s != NULL)
3836 subseg_set (seg->s, sub);
3837 else
3838 {
3839 seg->s = subseg_new (seg->name, sub);
3840 if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
3841 {
3842 bfd_set_section_flags (seg->s, seg->flags);
3843 if ((seg->flags & SEC_LOAD) == 0)
3844 seg_info (seg->s)->bss = 1;
3845 }
3846 }
3847 }
3848
3849 static void
3850 nds32_seg (int i)
3851 {
3852 subsegT sub = get_absolute_expression ();
3853
3854 do_nds32_seg (i, sub);
3855 demand_empty_rest_of_line ();
3856 }
3857
3858 /* Set if label adjustment is needed. I should not adjust .xbyte in dwarf. */
3859 static symbolS *nds32_last_label; /* Last label for alignment. */
3860
3861 static void
3862 add_mapping_symbol_for_align (int shift, valueT addr, int is_data_align)
3863 {
3864 if ((shift > 1) && (addr & 1))
3865 {
3866 int n = (1 << shift) - 1;
3867 if (!is_data_align)
3868 add_mapping_symbol (MAP_CODE, 1, 0);
3869 else if ((int) (addr & n) != n)
3870 add_mapping_symbol (MAP_CODE, 1, 0);
3871 }
3872 else if ((shift > 1) && ((int) (addr & 1) == 0))
3873 add_mapping_symbol (MAP_CODE, 0, 0);
3874 }
3875
3876 /* This code is referred from D30V for adjust label to be with pending
3877 alignment. For example,
3878 LBYTE: .byte 0x12
3879 LHALF: .half 0x12
3880 LWORD: .word 0x12
3881 Without this, the above label will not attach to incoming data. */
3882
3883 static void
3884 nds32_adjust_label (int n)
3885 {
3886 /* FIXME: I think adjust label and alignment is
3887 the programmer's obligation. Sadly, VLSI team doesn't
3888 properly use .align for their test cases.
3889 So I re-implement cons_align and auto adjust labels, again.
3890
3891 I think d30v's implementation is simple and good enough. */
3892
3893 symbolS *label = nds32_last_label;
3894 nds32_last_label = NULL;
3895
3896 /* SEC_ALLOC is used to eliminate .debug_ sections.
3897 SEC_CODE is used to include section for ILM. */
3898 if (((now_seg->flags & SEC_ALLOC) == 0 && (now_seg->flags & SEC_CODE) == 0)
3899 || strcmp (now_seg->name, ".eh_frame") == 0
3900 || strcmp (now_seg->name, ".gcc_except_table") == 0)
3901 return;
3902
3903 /* Only frag by alignment when needed.
3904 Otherwise, it will fail to optimize labels on 4-byte boundary. (bug8454)
3905 See md_convert_frag () and RELAX_SET_RELAXABLE (frag) for details. */
3906 if (frag_now_fix () & (((addressT) 1 << n) - 1))
3907 {
3908 if (subseg_text_p (now_seg))
3909 {
3910 add_mapping_symbol_for_align (n, frag_now_fix (), 1);
3911 frag_align_code (n, 0);
3912 }
3913 else
3914 frag_align (n, 0, 0);
3915
3916 /* Record the minimum alignment for this segment. */
3917 record_alignment (now_seg, n - OCTETS_PER_BYTE_POWER);
3918 }
3919
3920 if (label != NULL)
3921 {
3922 symbolS *sym;
3923 int label_seen = false;
3924 struct frag *old_frag;
3925 valueT old_value, new_value;
3926
3927 gas_assert (S_GET_SEGMENT (label) == now_seg);
3928
3929 old_frag = symbol_get_frag (label);
3930 old_value = S_GET_VALUE (label);
3931 new_value = frag_now_fix ();
3932
3933 /* Multiple labels may be on the same address. And the last symbol
3934 may not be a label at all, e.g., register name, external function names,
3935 so I have to track the last label in tc_frob_label instead of
3936 just using symbol_lastP. */
3937 for (sym = symbol_lastP; sym != NULL; sym = symbol_previous (sym))
3938 {
3939 if (symbol_get_frag (sym) == old_frag
3940 && S_GET_VALUE (sym) == old_value)
3941 {
3942 /* Warning HERE! */
3943 label_seen = true;
3944 symbol_set_frag (sym, frag_now);
3945 S_SET_VALUE (sym, new_value);
3946 }
3947 else if (label_seen && symbol_get_frag (sym) != old_frag)
3948 break;
3949 }
3950 }
3951 }
3952
3953 void
3954 nds32_cons_align (int size ATTRIBUTE_UNUSED)
3955 {
3956 /* Do nothing here.
3957 This is called before `md_flush_pending_output' is called by `cons'.
3958
3959 There are two things should be done for auto-adjust-label.
3960 1. Align data/instructions and adjust label to be attached to them.
3961 2. Clear auto-adjust state, so incoming data/instructions will not
3962 adjust the label.
3963
3964 For example,
3965 .byte 0x1
3966 .L0:
3967 .word 0x2
3968 .word 0x3
3969 in this case, '.word 0x2' will adjust the label, .L0, but '.word 0x3' should not.
3970
3971 I think `md_flush_pending_output' is a good place to clear the auto-adjust state,
3972 but it is also called by `cons' before this function.
3973 To simplify the code, instead of overriding .zero, .fill, .space, etc,
3974 I think we should just adjust label in `nds32_aligned_X_cons' instead of here. */
3975 }
3976
3977 static void
3978 make_mapping_symbol (enum mstate state, valueT value, fragS * frag, unsigned int align)
3979 {
3980 symbolS *symbol_p = NULL;
3981 const char *symbol_name = NULL;
3982 switch (state)
3983 {
3984 case MAP_DATA:
3985 if (align == 0)
3986 symbol_name = "$d0";
3987 else if (align == 1)
3988 symbol_name = "$d1";
3989 else if (align == 2)
3990 symbol_name = "$d2";
3991 else if (align == 3)
3992 symbol_name = "$d3";
3993 else if (align == 4)
3994 symbol_name = "$d4";
3995 break;
3996 case MAP_CODE:
3997 symbol_name = "$c";
3998 break;
3999 default:
4000 abort ();
4001 }
4002
4003 symbol_p = symbol_new (symbol_name, now_seg, frag, value);
4004 /* local scope attribute */
4005 symbol_get_bfdsym (symbol_p)->flags |= BSF_NO_FLAGS | BSF_LOCAL;
4006 }
4007
4008 static void
4009 add_mapping_symbol (enum mstate state, unsigned int padding_byte,
4010 unsigned int align)
4011 {
4012 enum mstate current_mapping_state =
4013 seg_info (now_seg)->tc_segment_info_data.mapstate;
4014
4015 if (state == MAP_CODE
4016 && current_mapping_state == state)
4017 return;
4018
4019 if (!SEG_NORMAL (now_seg)
4020 || !subseg_text_p (now_seg))
4021 return;
4022
4023 /* start adding mapping symbol */
4024 seg_info (now_seg)->tc_segment_info_data.mapstate = state;
4025 make_mapping_symbol (state, frag_now_fix () + padding_byte,
4026 frag_now, align);
4027 }
4028
4029 static void
4030 nds32_aligned_cons (int idx)
4031 {
4032 nds32_adjust_label (idx);
4033 add_mapping_symbol (MAP_DATA, 0, idx);
4034 /* Call default handler. */
4035 cons (1 << idx);
4036 if (now_seg->flags & SEC_CODE
4037 && now_seg->flags & SEC_ALLOC && now_seg->flags & SEC_RELOC)
4038 {
4039 /* Use BFD_RELOC_NDS32_DATA to avoid linker
4040 optimization replacing data. */
4041 expressionS exp;
4042
4043 exp.X_add_number = 0;
4044 exp.X_op = O_constant;
4045 fix_new_exp (frag_now, frag_now_fix () - (1 << idx), 1 << idx,
4046 &exp, 0, BFD_RELOC_NDS32_DATA);
4047 }
4048 }
4049
4050 /* `.double' directive. */
4051
4052 static void
4053 nds32_aligned_float_cons (int type)
4054 {
4055 switch (type)
4056 {
4057 case 'f':
4058 case 'F':
4059 case 's':
4060 case 'S':
4061 nds32_adjust_label (2);
4062 break;
4063 case 'd':
4064 case 'D':
4065 case 'r':
4066 case 'R':
4067 nds32_adjust_label (4);
4068 break;
4069 default:
4070 as_bad ("Unrecognized float type, %c\n", (char)type);
4071 }
4072 /* Call default handler. */
4073 float_cons (type);
4074 }
4075
4076 static void
4077 nds32_enable_pic (int ignore ATTRIBUTE_UNUSED)
4078 {
4079 /* Another way to do -mpic.
4080 This is for GCC internal use and should always be first line
4081 of code, otherwise, the effect is not determined. */
4082 nds32_pic = 1;
4083 }
4084
4085 static void
4086 nds32_set_abi (int ver)
4087 {
4088 nds32_abi = ver;
4089 }
4090
4091 /* Relax directive to set relocation R_NDS32_RELAX_ENTRY value. */
4092
4093 static void
4094 nds32_relax_relocs (int relax)
4095 {
4096 char saved_char;
4097 char *name;
4098 int i;
4099 const char *subtype_relax[] =
4100 {"", "",};
4101
4102 name = input_line_pointer;
4103 while (*input_line_pointer && !is_whitespace (*input_line_pointer))
4104 input_line_pointer++;
4105 saved_char = *input_line_pointer;
4106 *input_line_pointer = 0;
4107
4108 for (i = 0; i < (int) ARRAY_SIZE (subtype_relax); i++)
4109 {
4110 if (strcmp (name, subtype_relax[i]) == 0)
4111 {
4112 switch (i)
4113 {
4114 case 0:
4115 case 1:
4116 enable_relax_relocs = relax & enable_relax_relocs;
4117 break;
4118 default:
4119 break;
4120 }
4121 break;
4122 }
4123 }
4124 *input_line_pointer = saved_char;
4125 ignore_rest_of_line ();
4126 }
4127
4128 /* Record which arguments register($r0 ~ $r5) is not used in callee.
4129 bit[i] for $ri */
4130
4131 static void
4132 nds32_set_hint_func_args (int ignore ATTRIBUTE_UNUSED)
4133 {
4134 ignore_rest_of_line ();
4135 }
4136
4137 /* Insert relocations to mark the begin and end of a fp-omitted function,
4138 for further relaxation use.
4139 bit[i] for $ri */
4140
4141 static void
4142 nds32_omit_fp_begin (int mode)
4143 {
4144 expressionS exp;
4145
4146 if (nds32_relax_fp_as_gp == 0)
4147 return;
4148 exp.X_op = O_symbol;
4149 exp.X_add_symbol = abs_section_sym;
4150 if (mode == 1)
4151 {
4152 in_omit_fp = 1;
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_BEGIN);
4156 }
4157 else
4158 {
4159 in_omit_fp = 0;
4160 exp.X_add_number = R_NDS32_RELAX_REGION_OMIT_FP_FLAG;
4161 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
4162 BFD_RELOC_NDS32_RELAX_REGION_END);
4163 }
4164 }
4165
4166 static void
4167 nds32_loop_begin (int mode)
4168 {
4169 /* Insert loop region relocation here. */
4170 expressionS exp;
4171
4172 exp.X_op = O_symbol;
4173 exp.X_add_symbol = abs_section_sym;
4174 if (mode == 1)
4175 {
4176 exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG;
4177 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
4178 BFD_RELOC_NDS32_RELAX_REGION_BEGIN);
4179 }
4180 else
4181 {
4182 exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG;
4183 fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
4184 BFD_RELOC_NDS32_RELAX_REGION_END);
4185 }
4186 }
4187
4188 struct nds32_relocs_group
4189 {
4190 struct nds32_relocs_pattern *pattern;
4191 struct nds32_relocs_group *next;
4192 };
4193
4194 static struct nds32_relocs_group *nds32_relax_hint_current = NULL;
4195 /* Used to reorder the id for ".relax_hint id". */
4196 static int relax_hint_bias = 0;
4197 /* Record current relax hint id. */
4198 static int relax_hint_id_current = -1;
4199 int reset_bias = 0;
4200 /* If ".relax_hint begin" is triggered? */
4201 int relax_hint_begin = 0;
4202
4203 /* Record the reordered relax hint id. */
4204
4205 struct relax_hint_id
4206 {
4207 int old_id;
4208 int new_id;
4209 struct relax_hint_id *next;
4210 };
4211
4212 /* FIXME: Need to find somewhere to free the list. */
4213 struct relax_hint_id *record_id_head = NULL;
4214
4215 /* Is the buffer large enough? */
4216 #define MAX_BUFFER 12
4217
4218 static char *
4219 nds_itoa (int n)
4220 {
4221 char *buf = xmalloc (MAX_BUFFER * sizeof (char));
4222 snprintf (buf, MAX_BUFFER, "%d", n);
4223 return buf;
4224 }
4225
4226 /* Insert a relax hint. */
4227
4228 static void
4229 nds32_relax_hint (int mode ATTRIBUTE_UNUSED)
4230 {
4231 char *name = NULL;
4232 char saved_char;
4233 struct nds32_relocs_pattern *relocs = NULL;
4234 struct nds32_relocs_group *group, *new;
4235 struct relax_hint_id *record_id;
4236
4237 name = input_line_pointer;
4238 while (*input_line_pointer && !is_whitespace (*input_line_pointer))
4239 input_line_pointer++;
4240 saved_char = *input_line_pointer;
4241 *input_line_pointer = 0;
4242 name = strdup (name);
4243
4244 if (name && strcmp (name, "begin") == 0)
4245 {
4246 if (relax_hint_id_current == -1)
4247 reset_bias = 1;
4248 relax_hint_bias++;
4249 relax_hint_id_current++;
4250 relax_hint_begin = 1;
4251 }
4252
4253 /* Original case ".relax_hint id". It's id may need to be reordered. */
4254 if (!relax_hint_begin)
4255 {
4256 int tmp = strtol (name, NULL, 10);
4257 record_id = record_id_head;
4258 while (record_id)
4259 {
4260 if (record_id->old_id == tmp)
4261 {
4262 name = nds_itoa (record_id->new_id);
4263 goto reordered_id;
4264 }
4265 record_id = record_id->next;
4266 }
4267 if (reset_bias)
4268 {
4269 relax_hint_bias = relax_hint_id_current - atoi (name) + 1;
4270 reset_bias = 0;
4271 }
4272 relax_hint_id_current = tmp + relax_hint_bias;
4273
4274 /* Insert the element to the head of the link list. */
4275 struct relax_hint_id *tmp_id = malloc (sizeof (struct relax_hint_id));
4276 tmp_id->old_id = tmp;
4277 tmp_id->new_id = relax_hint_id_current;
4278 tmp_id->next = record_id_head;
4279 record_id_head = tmp_id;
4280 }
4281
4282 if (name && strcmp (name, "end") == 0)
4283 relax_hint_begin = 0;
4284 name = nds_itoa (relax_hint_id_current);
4285
4286 reordered_id:
4287
4288 /* Find relax hint entry for next instruction, and all member will be
4289 initialized at that time. */
4290 relocs = str_hash_find (nds32_hint_hash, name);
4291 if (relocs == NULL)
4292 {
4293 relocs = notes_calloc (1, sizeof (*relocs));
4294 str_hash_insert (nds32_hint_hash, name, relocs, 0);
4295 }
4296 else
4297 {
4298 while (relocs->next)
4299 relocs = relocs->next;
4300 relocs->next = notes_calloc (1, sizeof (*relocs));
4301 relocs = relocs->next;
4302 }
4303
4304 *input_line_pointer = saved_char;
4305 ignore_rest_of_line ();
4306
4307 /* Get the final one of relax hint series. */
4308
4309 /* It has to build this list because there are maybe more than one
4310 instructions relative to the same instruction. It to connect to
4311 next instruction after md_assemble. */
4312 new = XNEW (struct nds32_relocs_group);
4313 memset (new, 0, sizeof (struct nds32_relocs_group));
4314 new->pattern = relocs;
4315 new->next = NULL;
4316 group = nds32_relax_hint_current;
4317 if (!group)
4318 nds32_relax_hint_current = new;
4319 else
4320 {
4321 while (group->next != NULL)
4322 group = group->next;
4323 group->next = new;
4324 }
4325 relaxing = true;
4326 }
4327
4328 /* Decide the size of vector entries, only accepts 4 or 16 now. */
4329
4330 static void
4331 nds32_vec_size (int ignore ATTRIBUTE_UNUSED)
4332 {
4333 expressionS exp;
4334
4335 expression (&exp);
4336
4337 if (exp.X_op == O_constant)
4338 {
4339 if (exp.X_add_number == 4 || exp.X_add_number == 16)
4340 {
4341 if (vec_size == 0)
4342 vec_size = exp.X_add_number;
4343 else if (vec_size != exp.X_add_number)
4344 as_warn (_("Different arguments of .vec_size are found, "
4345 "previous %d, current %d"),
4346 (int) vec_size, (int) exp.X_add_number);
4347 }
4348 else
4349 as_warn (_("Argument of .vec_size is expected 4 or 16, actual: %d."),
4350 (int) exp.X_add_number);
4351 }
4352 else
4353 as_warn (_("Argument of .vec_size is not a constant."));
4354 }
4355
4356 /* The behavior of ".flag" directive varies depending on the target.
4357 In nds32 target, we use it to recognize whether this assembly content is
4358 generated by compiler. Other features can also be added in this function
4359 in the future. */
4360
4361 static void
4362 nds32_flag (int ignore ATTRIBUTE_UNUSED)
4363 {
4364 char *name;
4365 char saved_char;
4366 int i;
4367 const char *possible_flags[] = { "verbatim" };
4368
4369 /* Skip whitespaces. */
4370 name = input_line_pointer;
4371 while (*input_line_pointer && !is_whitespace (*input_line_pointer))
4372 input_line_pointer++;
4373 saved_char = *input_line_pointer;
4374 *input_line_pointer = 0;
4375
4376 for (i = 0; i < (int) ARRAY_SIZE (possible_flags); i++)
4377 {
4378 if (strcmp (name, possible_flags[i]) == 0)
4379 {
4380 switch (i)
4381 {
4382 case 0:
4383 /* flag: verbatim */
4384 verbatim = 1;
4385 break;
4386 default:
4387 break;
4388 }
4389 /* Already found the flag, no need to continue next loop. */
4390 break;
4391 }
4392 }
4393
4394 *input_line_pointer = saved_char;
4395 ignore_rest_of_line ();
4396 }
4397
4398 static void
4399 ict_model (int ignore ATTRIBUTE_UNUSED)
4400 {
4401 char *name;
4402 char saved_char;
4403 int i;
4404 const char *possible_flags[] = { "small", "large" };
4405
4406 /* Skip whitespaces. */
4407 name = input_line_pointer;
4408 while (*input_line_pointer && !is_whitespace (*input_line_pointer))
4409 input_line_pointer++;
4410 saved_char = *input_line_pointer;
4411 *input_line_pointer = 0;
4412
4413 for (i = 0; i < (int) ARRAY_SIZE (possible_flags); i++)
4414 {
4415 if (strcmp (name, possible_flags[i]) == 0)
4416 {
4417 switch (i)
4418 {
4419 case 0:
4420 /* flag: verbatim */
4421 ict_flag = ICT_SMALL;
4422 break;
4423 case 1:
4424 ict_flag = ICT_LARGE;
4425 break;
4426 default:
4427 break;
4428 }
4429 /* Already found the flag, no need to continue next loop. */
4430 break;
4431 }
4432 }
4433
4434 *input_line_pointer = saved_char;
4435 ignore_rest_of_line ();
4436 }
4437
4438 static void
4439 nds32_n12hc (int ignore ATTRIBUTE_UNUSED)
4440 {
4441 /* N1213HC core is used. */
4442 }
4443
4444
4445 /* The target specific pseudo-ops which we support. */
4446 const pseudo_typeS md_pseudo_table[] =
4447 {
4448 /* Forced alignment if declared these ways. */
4449 {"ascii", stringer, 8 + 0},
4450 {"asciz", stringer, 8 + 1},
4451 {"double", nds32_aligned_float_cons, 'd'},
4452 {"dword", nds32_aligned_cons, 3},
4453 {"float", nds32_aligned_float_cons, 'f'},
4454 {"half", nds32_aligned_cons, 1},
4455 {"hword", nds32_aligned_cons, 1},
4456 {"int", nds32_aligned_cons, 2},
4457 {"long", nds32_aligned_cons, 2},
4458 {"octa", nds32_aligned_cons, 4},
4459 {"quad", nds32_aligned_cons, 3},
4460 {"qword", nds32_aligned_cons, 4},
4461 {"short", nds32_aligned_cons, 1},
4462 {"byte", nds32_aligned_cons, 0},
4463 {"single", nds32_aligned_float_cons, 'f'},
4464 {"string", stringer, 8 + 1},
4465 {"word", nds32_aligned_cons, 2},
4466
4467 {"little", set_endian_little, 1},
4468 {"big", set_endian_little, 0},
4469 {"16bit_on", trigger_16bit, 1},
4470 {"16bit_off", trigger_16bit, 0},
4471 {"restore_16bit", restore_16bit, 0},
4472 {"off_16bit", off_16bit, 0},
4473
4474 {"sdata_d", nds32_seg, SDATA_D_SECTION},
4475 {"sdata_w", nds32_seg, SDATA_W_SECTION},
4476 {"sdata_h", nds32_seg, SDATA_H_SECTION},
4477 {"sdata_b", nds32_seg, SDATA_B_SECTION},
4478 {"sdata_f", nds32_seg, SDATA_F_SECTION},
4479
4480 {"sbss_d", nds32_seg, SBSS_D_SECTION},
4481 {"sbss_w", nds32_seg, SBSS_W_SECTION},
4482 {"sbss_h", nds32_seg, SBSS_H_SECTION},
4483 {"sbss_b", nds32_seg, SBSS_B_SECTION},
4484 {"sbss_f", nds32_seg, SBSS_F_SECTION},
4485
4486 {"pic", nds32_enable_pic, 0},
4487 {"n12_hc", nds32_n12hc, 0},
4488 {"abi_1", nds32_set_abi, E_NDS_ABI_V1},
4489 {"abi_2", nds32_set_abi, E_NDS_ABI_AABI},
4490 /* Obsolete. */
4491 {"abi_2fp", nds32_set_abi, E_NDS_ABI_V2FP},
4492 {"abi_2fp_plus", nds32_set_abi, E_NDS_ABI_V2FP_PLUS},
4493 {"relax", nds32_relax_relocs, 1},
4494 {"no_relax", nds32_relax_relocs, 0},
4495 {"hint_func_args", nds32_set_hint_func_args, 0}, /* Abandon?? */
4496 {"omit_fp_begin", nds32_omit_fp_begin, 1},
4497 {"omit_fp_end", nds32_omit_fp_begin, 0},
4498 {"vec_size", nds32_vec_size, 0},
4499 {"flag", nds32_flag, 0},
4500 {"innermost_loop_begin", nds32_loop_begin, 1},
4501 {"innermost_loop_end", nds32_loop_begin, 0},
4502 {"relax_hint", nds32_relax_hint, 0},
4503 {"ict_model", ict_model, 0},
4504 {NULL, NULL, 0}
4505 };
4506
4507 void
4508 nds32_pre_do_align (int n, char *fill, int len, int max)
4509 {
4510 /* Only make a frag if we HAVE to... */
4511 fragS *fragP;
4512 if (n != 0 && !need_pass_2)
4513 {
4514 if (fill == NULL)
4515 {
4516 if (subseg_text_p (now_seg))
4517 {
4518 dwarf2_emit_insn (0);
4519 fragP = frag_now;
4520 add_mapping_symbol_for_align (n, frag_now_fix (), 0);
4521 frag_align_code (n, max);
4522
4523 /* Tag this alignment when there is a label before it. */
4524 if (label_exist)
4525 {
4526 fragP->tc_frag_data.flag = NDS32_FRAG_LABEL;
4527 label_exist = 0;
4528 }
4529 }
4530 else
4531 frag_align (n, 0, max);
4532 }
4533 else if (len <= 1)
4534 frag_align (n, *fill, max);
4535 else
4536 frag_align_pattern (n, fill, len, max);
4537 }
4538 }
4539
4540 void
4541 nds32_do_align (int n)
4542 {
4543 /* Optimize for space and label exists. */
4544 expressionS exp;
4545
4546 /* FIXME:I think this will break debug info sections and except_table. */
4547 if (!enable_relax_relocs || !subseg_text_p (now_seg))
4548 return;
4549
4550 /* Create and attach a BFD_RELOC_NDS32_LABEL fixup
4551 the size of instruction may not be correct because
4552 it could be relaxable. */
4553 exp.X_op = O_symbol;
4554 exp.X_add_symbol = section_symbol (now_seg);
4555 exp.X_add_number = n;
4556 fix_new_exp (frag_now,
4557 frag_now_fix (), 0, &exp, 0, BFD_RELOC_NDS32_LABEL);
4558 }
4559
4560 /* Supported Andes machines. */
4561 struct nds32_machs
4562 {
4563 enum bfd_architecture bfd_mach;
4564 int mach_flags;
4565 };
4566
4567 /* This is the callback for nds32-asm.c to parse operands. */
4568
4569 int
4570 nds32_asm_parse_operand (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED,
4571 struct nds32_asm_insn *pinsn,
4572 char **pstr, int64_t *value)
4573 {
4574 char *hold;
4575 expressionS *pexp = pinsn->info;
4576
4577 hold = input_line_pointer;
4578 input_line_pointer = *pstr;
4579 expression (pexp);
4580 resolve_register (pexp);
4581 *pstr = input_line_pointer;
4582 input_line_pointer = hold;
4583
4584 switch (pexp->X_op)
4585 {
4586 case O_symbol:
4587 *value = 0;
4588 return NASM_R_SYMBOL;
4589 case O_constant:
4590 *value = pexp->X_add_number;
4591 return NASM_R_CONST;
4592 case O_illegal:
4593 case O_absent:
4594 case O_register:
4595 default:
4596 return NASM_R_ILLEGAL;
4597 }
4598 }
4599
4600 /* GAS will call this function at the start of the assembly, after the command
4601 line arguments have been parsed and all the machine independent
4602 initializations have been completed. */
4603
4604 void
4605 md_begin (void)
4606 {
4607 const struct nds32_keyword *k;
4608 relax_info_t *relax_info;
4609 int flags = 0;
4610
4611 bfd_set_arch_mach (stdoutput, TARGET_ARCH, nds32_baseline);
4612
4613 nds32_init_nds32_pseudo_opcodes ();
4614 asm_desc.parse_operand = nds32_asm_parse_operand;
4615 if (nds32_gpr16)
4616 flags |= NASM_OPEN_REDUCED_REG;
4617 nds32_asm_init (&asm_desc, flags);
4618
4619 /* Initial general purpose registers hash table. */
4620 nds32_gprs_hash = str_htab_create ();
4621 for (k = nds32_keyword_gpr; k->name; k++)
4622 str_hash_insert (nds32_gprs_hash, k->name, k, 0);
4623
4624 /* Initial branch hash table. */
4625 nds32_relax_info_hash = str_htab_create ();
4626 for (relax_info = relax_table; relax_info->opcode; relax_info++)
4627 str_hash_insert (nds32_relax_info_hash, relax_info->opcode, relax_info, 0);
4628
4629 /* Initial relax hint hash table. */
4630 nds32_hint_hash = str_htab_create ();
4631 enable_16bit = nds32_16bit_ext;
4632 }
4633
4634 /* HANDLE_ALIGN in write.c. */
4635
4636 void
4637 nds32_handle_align (fragS *fragp)
4638 {
4639 static const unsigned char nop16[] = { 0x92, 0x00 };
4640 static const unsigned char nop32[] = { 0x40, 0x00, 0x00, 0x09 };
4641
4642 if (fragp->fr_type != rs_align_code)
4643 return;
4644
4645 int bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
4646 char *p = fragp->fr_literal + fragp->fr_fix;
4647 int fix = bytes & 1;
4648
4649 if (fix != 0)
4650 {
4651 *p++ = 0;
4652 bytes--;
4653 }
4654
4655 if (bytes & 2)
4656 {
4657 expressionS exp_t;
4658 exp_t.X_op = O_symbol;
4659 exp_t.X_add_symbol = abs_section_sym;
4660 exp_t.X_add_number = R_NDS32_INSN16_CONVERT_FLAG;
4661 fix_new_exp (fragp, fragp->fr_fix, 2, &exp_t, 0,
4662 BFD_RELOC_NDS32_INSN16);
4663 memcpy (p, nop16, 2);
4664 p += 2;
4665 bytes -= 2;
4666 fix += 2;
4667 }
4668 fragp->fr_fix += fix;
4669
4670 if (bytes != 0)
4671 {
4672 fragp->fr_var = 4;
4673 memcpy (p, nop32, 4);
4674 }
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 (const 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 (const 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 const 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 const struct nds32_relocs_pattern *relocs_pattern = value;
5937 const struct nds32_relocs_pattern *pattern_temp, *pattern_now;
5938 symbolS *sym, *hi_sym = NULL;
5939 expressionS exp;
5940 fragS *fragP;
5941 segT seg_bak = now_seg;
5942 frchainS *frchain_bak = frchain_now;
5943 struct nds32_relax_hint_table hint_info;
5944 nds32_relax_fixup_info_t *hint_fixup, *fixup_now;
5945 size_t fixup_size;
5946 offsetT branch_offset, hi_branch_offset = 0;
5947 fixS *fixP;
5948 int range, offset;
5949 unsigned int ptr_offset, hint_count, relax_code_size, count = 0;
5950 uint32_t *code_seq, code_insn;
5951 char *where;
5952 int pcrel;
5953
5954 if (!relocs_pattern)
5955 return;
5956
5957 if (!nds32_find_reloc_table (relocs_pattern, &hint_info))
5958 return;
5959
5960 /* Save symbol for some EMPTY relocation using. */
5961 pattern_now = relocs_pattern;
5962 while (pattern_now)
5963 {
5964 if (pattern_now->opcode->value == OP6 (SETHI))
5965 {
5966 hi_sym = pattern_now->sym;
5967 hi_branch_offset = pattern_now->fixP->fx_offset;
5968 break;
5969 }
5970 pattern_now = pattern_now->next;
5971 }
5972
5973 /* Inserting fix up must specify now_seg or frchain_now. */
5974 now_seg = relocs_pattern->seg;
5975 frchain_now = relocs_pattern->frchain;
5976 fragP = relocs_pattern->frag;
5977 branch_offset = fragP->fr_offset;
5978
5979 hint_fixup = hint_info.relax_fixup;
5980 code_seq = hint_info.relax_code_seq;
5981 relax_code_size = hint_info.relax_code_size;
5982 pattern_now = relocs_pattern;
5983
5984 #ifdef NDS32_LINUX_TOOLCHAIN
5985 /* prepare group relocation ID (number). */
5986 long group_id = 0;
5987 if (key)
5988 {
5989 /* convert .relax_hint key to number */
5990 errno = 0;
5991 group_id = strtol (key, NULL, 10);
5992 if ((errno == ERANGE && (group_id == LONG_MAX || group_id == LONG_MIN))
5993 || (errno != 0 && group_id == 0))
5994 {
5995 as_bad (_("Internal error: .relax_hint KEY is not a number!"));
5996 goto restore;
5997 }
5998 }
5999 #endif
6000
6001 /* Insert relaxation. */
6002 exp.X_op = O_symbol;
6003
6004 /* For each instruction in the hint group. */
6005 while (pattern_now)
6006 {
6007 if (count >= relax_code_size / 4)
6008 count = 0;
6009
6010 /* Choose the match fixup by instruction. */
6011 code_insn = CLEAN_REG (*(code_seq + count));
6012 if (!nds32_match_hint_insn (pattern_now->opcode, code_insn))
6013 {
6014 /* Try search from head again */
6015 count = 0;
6016 code_insn = CLEAN_REG (*(code_seq + count));
6017
6018 while (!nds32_match_hint_insn (pattern_now->opcode, code_insn))
6019 {
6020 count++;
6021 if (count >= relax_code_size / 4)
6022 {
6023 as_bad (_("Internal error: Relax hint (%s) error. %s: %s (%x)"),
6024 key,
6025 now_seg->name,
6026 pattern_now->opcode->opcode,
6027 pattern_now->opcode->value);
6028 goto restore;
6029 }
6030 code_insn = CLEAN_REG (*(code_seq + count));
6031 }
6032 }
6033 fragP = pattern_now->frag;
6034 sym = pattern_now->sym;
6035 branch_offset = fragP->fr_offset;
6036 offset = count * 4;
6037 where = pattern_now->where;
6038 /* Find the instruction map fix. */
6039 fixup_now = hint_fixup;
6040 while (fixup_now->offset != offset)
6041 {
6042 fixup_now++;
6043 if (fixup_now->size == 0)
6044 break;
6045 }
6046 /* This element is without relaxation relocation. */
6047 if (fixup_now->size == 0)
6048 {
6049 pattern_now = pattern_now->next;
6050 continue;
6051 }
6052 fixup_size = fixup_now->size;
6053
6054 /* Insert all fixup. */
6055 pcrel = 0;
6056 while (fixup_size != 0 && fixup_now->offset == offset)
6057 {
6058 /* Set the real instruction size in element. */
6059 fixup_size = pattern_now->opcode->isize;
6060 pcrel = ((fixup_now->ramp & NDS32_PCREL) != 0) ? 1 : 0;
6061 if (fixup_now->ramp & NDS32_FIX)
6062 {
6063 /* Convert original relocation. */
6064 pattern_now->fixP->fx_r_type = fixup_now->r_type ;
6065 fixup_size = 0;
6066 }
6067 else if ((fixup_now->ramp & NDS32_PTR) != 0)
6068 {
6069 /* This relocation has to point to another instruction. Make
6070 sure each resolved relocation has to be pointed. */
6071 pattern_temp = relocs_pattern;
6072 /* All instruction in relax_table should be 32-bit. */
6073 hint_count = hint_info.relax_code_size / 4;
6074 code_insn = CLEAN_REG (*(code_seq + hint_count - 1));
6075 while (pattern_temp)
6076 {
6077 /* Point to every resolved relocation. */
6078 if (nds32_match_hint_insn (pattern_temp->opcode, code_insn))
6079 {
6080 ptr_offset =
6081 pattern_temp->where - pattern_temp->frag->fr_literal;
6082 exp.X_add_symbol = symbol_temp_new (now_seg,
6083 pattern_temp->frag,
6084 ptr_offset);
6085 exp.X_add_number = 0;
6086 fixP =
6087 fix_new_exp (fragP, where - fragP->fr_literal,
6088 fixup_size, &exp, 0, fixup_now->r_type);
6089 fixP->fx_addnumber = fixP->fx_offset;
6090 }
6091 pattern_temp = pattern_temp->next;
6092 }
6093 fixup_size = 0;
6094 }
6095 else if (fixup_now->ramp & NDS32_ADDEND)
6096 {
6097 range = nds32_elf_sethi_range (relocs_pattern);
6098 if (range == NDS32_LOADSTORE_NONE)
6099 {
6100 as_bad (_("Internal error: Range error. %s"), now_seg->name);
6101 return;
6102 }
6103 exp.X_add_symbol = abs_section_sym;
6104 exp.X_add_number = SET_ADDEND (4, 0, optimize, enable_16bit);
6105 exp.X_add_number |= ((range & 0x3f) << 8);
6106 }
6107 else if ((fixup_now->ramp & NDS32_ABS) != 0)
6108 {
6109 /* This is a tag relocation. */
6110 exp.X_add_symbol = abs_section_sym;
6111 exp.X_add_number = 0;
6112 }
6113 else if ((fixup_now->ramp & NDS32_INSN16) != 0)
6114 {
6115 if (!enable_16bit)
6116 fixup_size = 0;
6117 /* This is a tag relocation. */
6118 exp.X_add_symbol = abs_section_sym;
6119 exp.X_add_number = 0;
6120 }
6121 else if ((fixup_now->ramp & NDS32_SYM) != 0)
6122 {
6123 /* For EMPTY relocation save the true symbol. */
6124 exp.X_add_symbol = hi_sym;
6125 exp.X_add_number = hi_branch_offset;
6126 }
6127 else if (NDS32_SYM_DESC_MEM & fixup_now->ramp)
6128 {
6129 /* Do the same as NDS32_SYM. */
6130 exp.X_add_symbol = hi_sym;
6131 exp.X_add_number = hi_branch_offset;
6132
6133 /* Extra to NDS32_SYM. */
6134 /* Detect if DESC_FUNC relax type do apply. */
6135 if ((REG_GP == N32_RA5 (pattern_now->insn))
6136 || (REG_GP == N32_RB5 (pattern_now->insn)))
6137 {
6138 fixP = fix_new_exp (fragP, where - fragP->fr_literal,
6139 fixup_size, &exp, pcrel,
6140 BFD_RELOC_NDS32_TLS_DESC_FUNC);
6141 fixP->fx_addnumber = fixP->fx_offset;
6142
6143 fixup_size = 0;
6144 }
6145 /* Else do as usual. */
6146 }
6147 else if (fixup_now->ramp & NDS32_PTR_PATTERN)
6148 {
6149 /* Find out PTR_RESOLVED code pattern. */
6150 nds32_relax_fixup_info_t *next_fixup = fixup_now + 1;
6151 uint32_t resolved_pattern = 0;
6152 while (next_fixup->offset)
6153 {
6154 if (next_fixup->r_type == BFD_RELOC_NDS32_PTR_RESOLVED)
6155 {
6156 uint32_t new_pattern = code_seq[next_fixup->offset >> 2];
6157 if (!resolved_pattern)
6158 resolved_pattern = new_pattern;
6159 else if (new_pattern != resolved_pattern)
6160 {
6161 as_warn (_("Multiple BFD_RELOC_NDS32_PTR_RESOLVED "
6162 "patterns are not supported yet!"));
6163 break;
6164 }
6165 }
6166 ++next_fixup;
6167 }
6168
6169 /* Find matched code and insert fix-ups. */
6170 struct nds32_relocs_pattern *next_pattern = pattern_now->next;
6171 /* This relocation has to point to another instruction.
6172 Make sure each resolved relocation has to be pointed. */
6173 /* All instruction in relax_table should be 32-bit. */
6174 while (next_pattern)
6175 {
6176 uint32_t cur_pattern = GET_OPCODE (next_pattern->opcode->value);
6177 if (cur_pattern == resolved_pattern)
6178 {
6179 ptr_offset = next_pattern->where
6180 - next_pattern->frag->fr_literal;
6181 exp.X_add_symbol = symbol_temp_new (now_seg,
6182 next_pattern->frag,
6183 ptr_offset);
6184 exp.X_add_number = 0;
6185 fixP = fix_new_exp (fragP, where - fragP->fr_literal,
6186 fixup_size, &exp, 0,
6187 fixup_now->r_type);
6188 fixP->fx_addnumber = fixP->fx_offset;
6189 }
6190 next_pattern = next_pattern->next;
6191 }
6192
6193 fixup_size = 0;
6194 }
6195 else if (fixup_now->ramp & NDS32_PTR_MULTIPLE)
6196 {
6197 /* Find each PTR_RESOLVED pattern after PTR. */
6198 nds32_relax_fixup_info_t *next_fixup = fixup_now + 1;
6199 while (next_fixup->offset)
6200 {
6201 if (next_fixup->r_type == BFD_RELOC_NDS32_PTR_RESOLVED)
6202 {
6203 uint32_t pattern = code_seq[next_fixup->offset >> 2];
6204 /* Find matched code to insert fix-ups. */
6205 struct nds32_relocs_pattern *next_insn = pattern_now->next;
6206 while (next_insn)
6207 {
6208 uint32_t insn_pattern = GET_OPCODE (next_insn->opcode->value);
6209 if (insn_pattern == pattern)
6210 {
6211 ptr_offset = next_insn->where
6212 - next_insn->frag->fr_literal;
6213 exp.X_add_symbol = symbol_temp_new (now_seg,
6214 next_insn->frag,
6215 ptr_offset);
6216 exp.X_add_number = 0;
6217 fixP = fix_new_exp (fragP,
6218 where - fragP->fr_literal,
6219 fixup_size, &exp, 0,
6220 fixup_now->r_type);
6221 fixP->fx_addnumber = fixP->fx_offset;
6222 }
6223 next_insn = next_insn->next;
6224 }
6225 }
6226 ++next_fixup;
6227 }
6228 fixup_size = 0;
6229 }
6230 else
6231 {
6232 exp.X_add_symbol = sym;
6233 exp.X_add_number = branch_offset;
6234 }
6235
6236 if (fixup_size != 0)
6237 {
6238 fixP = fix_new_exp (fragP, where - fragP->fr_literal, fixup_size,
6239 &exp, pcrel, fixup_now->r_type);
6240 fixP->fx_addnumber = fixP->fx_offset;
6241 }
6242 fixup_now++;
6243 fixup_size = fixup_now->size;
6244 }
6245
6246 #ifdef NDS32_LINUX_TOOLCHAIN
6247 /* Insert group relocation for each relax hint. */
6248 if (key)
6249 {
6250 exp.X_add_symbol = hi_sym; /* for eyes only */
6251 exp.X_add_number = group_id;
6252 fixP = fix_new_exp (fragP, where - fragP->fr_literal, fixup_size,
6253 &exp, pcrel, BFD_RELOC_NDS32_GROUP);
6254 fixP->fx_addnumber = fixP->fx_offset;
6255 }
6256 #endif
6257
6258 if (count < relax_code_size / 4)
6259 count++;
6260 pattern_now = pattern_now->next;
6261 }
6262
6263 restore:
6264 now_seg = seg_bak;
6265 frchain_now = frchain_bak;
6266 }
6267
6268 static int
6269 nds32_elf_append_relax_relocs_traverse (void **slot, void *arg ATTRIBUTE_UNUSED)
6270 {
6271 string_tuple_t *tuple = *((string_tuple_t **) slot);
6272 nds32_elf_append_relax_relocs (tuple->key, (const void *) tuple->value);
6273 return 1;
6274 }
6275
6276
6277 static void
6278 nds32_str_tolower (const char *src, char *dest)
6279 {
6280 unsigned int i, len;
6281
6282 len = strlen (src);
6283
6284 for (i = 0; i < len; i++)
6285 *(dest + i) = TOLOWER (*(src + i));
6286
6287 *(dest + i) = '\0';
6288 }
6289
6290 /* Check instruction if it can be used for the baseline. */
6291
6292 static bool
6293 nds32_check_insn_available (struct nds32_asm_insn insn, const char *str)
6294 {
6295 int attr = insn.attr & ATTR_ALL;
6296 static int baseline_isa = 0;
6297 char *s;
6298
6299 s = xmalloc (strlen (str) + 1);
6300 nds32_str_tolower (str, s);
6301 if (verbatim
6302 && (((insn.opcode->value == ALU2 (MTUSR)
6303 || insn.opcode->value == ALU2 (MFUSR))
6304 && (strstr (s, "lc")
6305 || strstr (s, "le")
6306 || strstr (s, "lb")))
6307 || (insn.attr & NASM_ATTR_ZOL)))
6308 {
6309 as_bad (_("Not support instruction %s in verbatim."), str);
6310 return false;
6311 }
6312 free (s);
6313
6314 if (!enable_16bit && insn.opcode->isize == 2)
6315 {
6316 as_bad (_("16-bit instruction is disabled: %s."), str);
6317 return false;
6318 }
6319
6320 /* No isa setting or all isa can use. */
6321 if (attr == 0 || attr == ATTR_ALL)
6322 return true;
6323
6324 if (baseline_isa == 0)
6325 {
6326 /* Map option baseline and instruction attribute. */
6327 switch (nds32_baseline)
6328 {
6329 case ISA_V2:
6330 baseline_isa = ATTR (ISA_V2);
6331 break;
6332 case ISA_V3:
6333 baseline_isa = ATTR (ISA_V3);
6334 break;
6335 case ISA_V3M:
6336 baseline_isa = ATTR (ISA_V3M);
6337 break;
6338 }
6339 }
6340
6341 if ((baseline_isa & attr) == 0)
6342 {
6343 as_bad (_("Instruction %s not supported in the baseline."), str);
6344 return false;
6345 }
6346 return true;
6347 }
6348
6349 /* Stub of machine dependent. */
6350
6351 void
6352 md_assemble (char *str)
6353 {
6354 struct nds32_asm_insn insn;
6355 char *out;
6356 struct nds32_pseudo_opcode *popcode;
6357 const struct nds32_field *fld = NULL;
6358 fixS *fixP;
6359 uint16_t insn_16;
6360 struct nds32_relocs_pattern *relocs_temp;
6361 struct nds32_relocs_group *group_temp;
6362 fragS *fragP;
6363 int label = label_exist;
6364 static bool pseudo_hint = false;
6365
6366 popcode = nds32_lookup_pseudo_opcode (str);
6367 /* Note that we need to check 'verbatim' and
6368 'opcode->physical_op'. If the assembly content is generated by
6369 compiler and this opcode is a physical instruction, there is no
6370 need to perform pseudo instruction expansion/transformation. */
6371 if (popcode && !(verbatim && popcode->physical_op))
6372 {
6373 /* Pseudo instruction is with relax_hint. */
6374 if (relaxing)
6375 pseudo_hint = true;
6376 pseudo_opcode = true;
6377 nds32_pseudo_opcode_wrapper (str, popcode);
6378 pseudo_opcode = false;
6379 pseudo_hint = false;
6380 nds32_elf_append_relax_relocs (NULL, relocs_list);
6381
6382 /* Free relax_hint group list. */
6383 while (nds32_relax_hint_current)
6384 {
6385 group_temp = nds32_relax_hint_current->next;
6386 free (nds32_relax_hint_current);
6387 nds32_relax_hint_current = group_temp;
6388 }
6389
6390 /* Free pseudo list. */
6391 relocs_temp = relocs_list;
6392 while (relocs_temp)
6393 {
6394 relocs_list = relocs_list->next;
6395 free (relocs_temp);
6396 relocs_temp = relocs_list;
6397 }
6398
6399 return;
6400 }
6401
6402 label_exist = 0;
6403 insn.info = XNEW (expressionS);
6404 asm_desc.result = NASM_OK;
6405 nds32_assemble (&asm_desc, &insn, str);
6406
6407 switch (asm_desc.result)
6408 {
6409 case NASM_ERR_UNKNOWN_OP:
6410 as_bad (_("Unrecognized opcode, %s."), str);
6411 return;
6412 case NASM_ERR_SYNTAX:
6413 as_bad (_("Incorrect syntax, %s."), str);
6414 return;
6415 case NASM_ERR_OPERAND:
6416 as_bad (_("Unrecognized operand/register, %s."), str);
6417 return;
6418 case NASM_ERR_OUT_OF_RANGE:
6419 as_bad (_("Operand out of range, %s."), str);
6420 return;
6421 case NASM_ERR_REG_REDUCED:
6422 as_bad (_("Prohibited register used for reduced-register, %s."), str);
6423 return;
6424 case NASM_ERR_JUNK_EOL:
6425 as_bad (_("Junk at end of line, %s."), str);
6426 return;
6427 }
6428
6429 gas_assert (insn.opcode);
6430
6431 nds32_set_elf_flags_by_insn (&insn);
6432
6433 gas_assert (insn.opcode->isize == 4 || insn.opcode->isize == 2);
6434
6435 if (!nds32_check_insn_available (insn, str))
6436 return;
6437
6438 /* Make sure the beginning of text being 2-byte align. */
6439 nds32_adjust_label (1);
6440 add_mapping_symbol (MAP_CODE, 0, 0);
6441 fld = insn.field;
6442 /* Try to allocate the max size to guarantee relaxable same branch
6443 instructions in the same fragment. */
6444 frag_grow (NDS32_MAXCHAR);
6445 fragP = frag_now;
6446
6447 if (fld && (insn.attr & NASM_ATTR_BRANCH)
6448 && (pseudo_opcode || (insn.opcode->value != INSN_JAL
6449 && insn.opcode->value != INSN_J))
6450 && (!verbatim || pseudo_opcode))
6451 {
6452 /* User assembly code branch relax for it. */
6453 /* If fld is not NULL, it is a symbol. */
6454 /* Branch must relax to proper pattern in user assembly code exclude
6455 J and JAL. Keep these two in original type for users which wants
6456 to keep their size be fixed. In general, assembler does not convert
6457 instruction generated by compiler. But jump instruction may be
6458 truncated in text virtual model. For workaround, compiler generate
6459 pseudo jump to fix this issue currently. */
6460
6461 /* Get branch range type. */
6462 dwarf2_emit_insn (0);
6463 enum nds32_br_range range_type;
6464 expressionS *pexp = insn.info;
6465
6466 range_type = get_range_type (fld);
6467
6468 out = frag_var (rs_machine_dependent, NDS32_MAXCHAR,
6469 0, /* VAR is un-used. */
6470 range_type, /* SUBTYPE is used as range type. */
6471 pexp->X_add_symbol, pexp->X_add_number, 0);
6472
6473 fragP->fr_fix += insn.opcode->isize;
6474 fragP->tc_frag_data.opcode = insn.opcode;
6475 fragP->tc_frag_data.insn = insn.insn;
6476 if (insn.opcode->isize == 4)
6477 bfd_putb32 (insn.insn, out);
6478 else if (insn.opcode->isize == 2)
6479 bfd_putb16 (insn.insn, out);
6480 fragP->tc_frag_data.flag |= NDS32_FRAG_BRANCH;
6481
6482 free (insn.info);
6483 return;
6484 /* md_convert_frag will insert relocations. */
6485 }
6486 else if (!relaxing && enable_16bit && (optimize || optimize_for_space)
6487 && ((!fld && !verbatim && insn.opcode->isize == 4
6488 && nds32_convert_32_to_16 (stdoutput, insn.insn, &insn_16, NULL))
6489 || (insn.opcode->isize == 2
6490 && nds32_convert_16_to_32 (stdoutput, insn.insn, NULL))))
6491 {
6492 /* Record this one is relaxable. */
6493 expressionS *pexp = insn.info;
6494 dwarf2_emit_insn (0);
6495 if (fld)
6496 {
6497 out = frag_var (rs_machine_dependent,
6498 4, /* Max size is 32-bit instruction. */
6499 0, /* VAR is un-used. */
6500 0, pexp->X_add_symbol, pexp->X_add_number, 0);
6501 fragP->tc_frag_data.flag |= NDS32_FRAG_RELAXABLE_BRANCH;
6502 }
6503 else
6504 out = frag_var (rs_machine_dependent,
6505 4, /* Max size is 32-bit instruction. */
6506 0, /* VAR is un-used. */
6507 0, NULL, 0, NULL);
6508 fragP->tc_frag_data.flag |= NDS32_FRAG_RELAXABLE;
6509 fragP->tc_frag_data.opcode = insn.opcode;
6510 fragP->tc_frag_data.insn = insn.insn;
6511 fragP->fr_fix += 2;
6512
6513 /* In original, we don't relax the instruction with label on it,
6514 but this may cause some redundant nop16. Therefore, tag this
6515 relaxable instruction and relax it carefully. */
6516 if (label)
6517 fragP->tc_frag_data.flag |= NDS32_FRAG_LABEL;
6518
6519 if (insn.opcode->isize == 4)
6520 bfd_putb16 (insn_16, out);
6521 else if (insn.opcode->isize == 2)
6522 bfd_putb16 (insn.insn, out);
6523
6524 free (insn.info);
6525 return;
6526 }
6527 else if ((verbatim || !relaxing) && optimize && label)
6528 {
6529 /* This instruction is with label. */
6530 expressionS exp;
6531 out = frag_var (rs_machine_dependent, insn.opcode->isize,
6532 0, 0, NULL, 0, NULL);
6533 /* If this instruction is branch target, it is not relaxable. */
6534 fragP->tc_frag_data.flag = NDS32_FRAG_LABEL;
6535 fragP->tc_frag_data.opcode = insn.opcode;
6536 fragP->tc_frag_data.insn = insn.insn;
6537 fragP->fr_fix += insn.opcode->isize;
6538 if (insn.opcode->isize == 4)
6539 {
6540 exp.X_op = O_symbol;
6541 exp.X_add_symbol = abs_section_sym;
6542 exp.X_add_number = 0;
6543 fixP = fix_new_exp (fragP, fragP->fr_fix - 4, 0, &exp,
6544 0, BFD_RELOC_NDS32_LABEL);
6545 if (!verbatim)
6546 fragP->tc_frag_data.flag = NDS32_FRAG_ALIGN;
6547 }
6548 }
6549 else
6550 out = frag_more (insn.opcode->isize);
6551
6552 if (insn.opcode->isize == 4)
6553 bfd_putb32 (insn.insn, out);
6554 else if (insn.opcode->isize == 2)
6555 bfd_putb16 (insn.insn, out);
6556
6557 dwarf2_emit_insn (insn.opcode->isize);
6558
6559 /* Compiler generating code and user assembly pseudo load-store, insert
6560 fixup here. */
6561 expressionS *pexp = insn.info;
6562 fixP = nds32_elf_record_fixup_exp (fragP, str, fld, pexp, out, &insn);
6563 /* Build relaxation pattern when relaxing is enable. */
6564 if (relaxing)
6565 nds32_elf_build_relax_relation (fixP, pexp, out, &insn, fragP, fld,
6566 pseudo_hint);
6567
6568 free (insn.info);
6569 }
6570
6571 /* md_macro_start */
6572
6573 void
6574 nds32_macro_start (void)
6575 {
6576 }
6577
6578 /* md_macro_info */
6579
6580 void
6581 nds32_macro_info (void *info ATTRIBUTE_UNUSED)
6582 {
6583 }
6584
6585 /* md_macro_end */
6586
6587 void
6588 nds32_macro_end (void)
6589 {
6590 }
6591
6592 /* GAS will call this function with one argument, an expressionS pointer, for
6593 any expression that can not be recognized. When the function is called,
6594 input_line_pointer will point to the start of the expression. */
6595
6596 void
6597 md_operand (expressionS *expressionP)
6598 {
6599 if (*input_line_pointer == '#')
6600 {
6601 input_line_pointer++;
6602 expression (expressionP);
6603 }
6604 }
6605
6606 /* GAS will call this function for each section at the end of the assembly, to
6607 permit the CPU back end to adjust the alignment of a section. The function
6608 must take two arguments, a segT for the section and a valueT for the size of
6609 the section, and return a valueT for the rounded size. */
6610
6611 valueT
6612 md_section_align (segT segment, valueT size)
6613 {
6614 int align = bfd_section_alignment (segment);
6615
6616 return (size + ((valueT) 1 << align) - 1) & -((valueT) 1 << align);
6617 }
6618
6619 /* GAS will call this function when a symbol table lookup fails, before it
6620 creates a new symbol. Typically this would be used to supply symbols whose
6621 name or value changes dynamically, possibly in a context sensitive way.
6622 Predefined symbols with fixed values, such as register names or condition
6623 codes, are typically entered directly into the symbol table when md_begin
6624 is called. One argument is passed, a char * for the symbol. */
6625
6626 symbolS *
6627 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
6628 {
6629 return NULL;
6630 }
6631
6632 static long
6633 nds32_calc_branch_offset (segT segment, fragS *fragP,
6634 long stretch ATTRIBUTE_UNUSED,
6635 relax_info_t *relax_info,
6636 enum nds32_br_range branch_range_type)
6637 {
6638 struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
6639 symbolS *branch_symbol = fragP->fr_symbol;
6640 offsetT branch_offset = fragP->fr_offset;
6641 offsetT branch_target_address;
6642 offsetT branch_insn_address;
6643 long offset = 0;
6644
6645 if ((S_GET_SEGMENT (branch_symbol) != segment)
6646 || S_IS_WEAK (branch_symbol))
6647 {
6648 /* The symbol is not in the SEGMENT. It could be far far away. */
6649 offset = 0x80000000;
6650 }
6651 else
6652 {
6653 /* Calculate symbol-to-instruction offset. */
6654 branch_target_address = S_GET_VALUE (branch_symbol) + branch_offset;
6655 /* If the destination symbol is beyond current frag address,
6656 STRETCH will take effect to symbol's position. */
6657 if (S_GET_VALUE (branch_symbol) > fragP->fr_address)
6658 branch_target_address += stretch;
6659
6660 branch_insn_address = fragP->fr_address + fragP->fr_fix;
6661 branch_insn_address -= opcode->isize;
6662
6663 /* Update BRANCH_INSN_ADDRESS to relaxed position. */
6664 branch_insn_address += (relax_info->relax_code_size[branch_range_type]
6665 - relax_info->relax_branch_isize[branch_range_type]);
6666
6667 offset = branch_target_address - branch_insn_address;
6668 }
6669
6670 return offset;
6671 }
6672
6673 static enum nds32_br_range
6674 nds32_convert_to_range_type (long offset)
6675 {
6676 enum nds32_br_range range_type;
6677
6678 if (-(0x100) <= offset && offset < 0x100) /* 256 bytes */
6679 range_type = BR_RANGE_S256;
6680 else if (-(0x4000) <= offset && offset < 0x4000) /* 16K bytes */
6681 range_type = BR_RANGE_S16K;
6682 else if (-(0x10000) <= offset && offset < 0x10000) /* 64K bytes */
6683 range_type = BR_RANGE_S64K;
6684 else if (-(0x1000000) <= offset && offset < 0x1000000) /* 16M bytes */
6685 range_type = BR_RANGE_S16M;
6686 else /* 4G bytes */
6687 range_type = BR_RANGE_U4G;
6688
6689 return range_type;
6690 }
6691
6692 /* Set instruction register mask. */
6693
6694 static void
6695 nds32_elf_get_set_cond (relax_info_t *relax_info, int offset, uint32_t *insn,
6696 uint32_t ori_insn, int range)
6697 {
6698 nds32_cond_field_t *cond_fields = relax_info->cond_field;
6699 nds32_cond_field_t *code_seq_cond = relax_info->relax_code_condition[range];
6700 uint32_t mask;
6701 int i = 0;
6702
6703 /* The instruction has conditions. Collect condition values. */
6704 while (code_seq_cond[i].bitmask != 0)
6705 {
6706 if (offset == code_seq_cond[i].offset)
6707 {
6708 mask = (ori_insn >> cond_fields[i].bitpos) & cond_fields[i].bitmask;
6709 /* Sign extend. */
6710 if (cond_fields[i].signed_extend)
6711 mask = (mask ^ ((cond_fields[i].bitmask + 1) >> 1)) -
6712 ((cond_fields[i].bitmask + 1) >> 1);
6713 *insn |= (mask & code_seq_cond[i].bitmask) << code_seq_cond[i].bitpos;
6714 }
6715 i++;
6716 }
6717 }
6718
6719 static int
6720 nds32_relax_branch_instructions (segT segment, fragS *fragP,
6721 long stretch ATTRIBUTE_UNUSED,
6722 int init)
6723 {
6724 enum nds32_br_range branch_range_type;
6725 struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
6726 long offset = 0;
6727 enum nds32_br_range real_range_type;
6728 int adjust = 0;
6729 relax_info_t *relax_info;
6730 int diff = 0;
6731 int i, j, k;
6732 int code_seq_size;
6733 uint32_t *code_seq;
6734 uint32_t insn;
6735 int insn_size;
6736 int code_seq_offset;
6737
6738 /* Replace with gas_assert (fragP->fr_symbol != NULL); */
6739 if (fragP->fr_symbol == NULL)
6740 return adjust;
6741
6742 /* If frag_var is not enough room, the previous frag is fr_full and with
6743 opcode. The new one is rs_dependent but without opcode. */
6744 if (opcode == NULL)
6745 return adjust;
6746
6747 /* Use U4G mode for b and bal in verbatim mode because lto may combine
6748 functions into a file. And order the file in the last when linking.
6749 Once there is multiple definition, the same function will be kicked.
6750 This may cause relocation truncated error. */
6751 if (verbatim && !nds32_pic
6752 && (strcmp (opcode->opcode, "j") == 0
6753 || strcmp (opcode->opcode, "jal") == 0))
6754 {
6755 fragP->fr_subtype = BR_RANGE_U4G;
6756 if (init)
6757 return 8;
6758 else
6759 return 0;
6760 }
6761
6762 relax_info = str_hash_find (nds32_relax_info_hash, opcode->opcode);
6763
6764 if (relax_info == NULL)
6765 return adjust;
6766
6767 if (init)
6768 {
6769 branch_range_type = relax_info->br_range;
6770 i = BR_RANGE_S256;
6771 }
6772 else
6773 {
6774 branch_range_type = fragP->fr_subtype;
6775 i = branch_range_type;
6776 }
6777
6778 offset = nds32_calc_branch_offset (segment, fragP, stretch,
6779 relax_info, branch_range_type);
6780
6781 real_range_type = nds32_convert_to_range_type (offset);
6782
6783 /* If actual range is equal to instruction jump range, do nothing. */
6784 if (real_range_type == branch_range_type)
6785 {
6786 fragP->fr_subtype = real_range_type;
6787 return adjust;
6788 }
6789
6790 /* Find out proper relaxation code sequence. */
6791 for (; i < BR_RANGE_NUM; i++)
6792 {
6793 if (real_range_type <= (unsigned int) i)
6794 {
6795 if (init)
6796 diff = relax_info->relax_code_size[i] - opcode->isize;
6797 else if (real_range_type < (unsigned int) i)
6798 diff = relax_info->relax_code_size[real_range_type]
6799 - relax_info->relax_code_size[branch_range_type];
6800 else
6801 diff = relax_info->relax_code_size[i]
6802 - relax_info->relax_code_size[branch_range_type];
6803
6804 /* If the instruction could be converted to 16-bits,
6805 minus the difference. */
6806 code_seq_offset = 0;
6807 j = 0;
6808 k = 0;
6809 code_seq_size = relax_info->relax_code_size[i];
6810 code_seq = relax_info->relax_code_seq[i];
6811 while (code_seq_offset < code_seq_size)
6812 {
6813 insn = code_seq[j];
6814 if (insn & 0x80000000) /* 16-bits instruction. */
6815 {
6816 insn_size = 2;
6817 }
6818 else /* 32-bits instruction. */
6819 {
6820 insn_size = 4;
6821
6822 while (relax_info->relax_fixup[i][k].size !=0
6823 && relax_info->relax_fixup[i][k].offset < code_seq_offset)
6824 k++;
6825 }
6826
6827 code_seq_offset += insn_size;
6828 j++;
6829 }
6830
6831 /* Update fr_subtype to new NDS32_BR_RANGE. */
6832 fragP->fr_subtype = real_range_type;
6833 break;
6834 }
6835 }
6836
6837 return diff + adjust;
6838 }
6839
6840 /* Adjust relaxable frag till current frag. */
6841
6842 static int
6843 nds32_adjust_relaxable_frag (fragS *startP, fragS *fragP)
6844 {
6845 int adj;
6846 if (startP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
6847 adj = -2;
6848 else
6849 adj = 2;
6850
6851 startP->tc_frag_data.flag ^= NDS32_FRAG_RELAXED;
6852
6853 while (startP)
6854 {
6855 startP = startP->fr_next;
6856 if (startP)
6857 {
6858 startP->fr_address += adj;
6859 if (startP == fragP)
6860 break;
6861 }
6862 }
6863 return adj;
6864 }
6865
6866 static addressT
6867 nds32_get_align (addressT address, int align)
6868 {
6869 addressT mask, new_address;
6870
6871 mask = ~((addressT) (~0) << align);
6872 new_address = (address + mask) & (~mask);
6873 return (new_address - address);
6874 }
6875
6876 /* Check the prev_frag is legal. */
6877 static void
6878 invalid_prev_frag (fragS * fragP, fragS **prev_frag, bool relax)
6879 {
6880 addressT address;
6881 fragS *frag_start = *prev_frag;
6882
6883 if (!frag_start || !relax)
6884 return;
6885
6886 if (frag_start->last_fr_address >= fragP->last_fr_address)
6887 {
6888 *prev_frag = NULL;
6889 return;
6890 }
6891
6892 fragS *frag_t = *prev_frag;
6893 while (frag_t != fragP)
6894 {
6895 if (frag_t->fr_type == rs_align
6896 || frag_t->fr_type == rs_align_code
6897 || frag_t->fr_type == rs_align_test)
6898 {
6899 /* Relax instruction can not walk across label. */
6900 if (frag_t->tc_frag_data.flag & NDS32_FRAG_LABEL)
6901 {
6902 prev_frag = NULL;
6903 return;
6904 }
6905 /* Relax previous relaxable to align rs_align frag. */
6906 address = frag_t->fr_address + frag_t->fr_fix;
6907 addressT offset = nds32_get_align (address, (int) frag_t->fr_offset);
6908 if (offset & 0x2)
6909 {
6910 /* If there is label on the prev_frag, check if it is aligned. */
6911 if (!((*prev_frag)->tc_frag_data.flag & NDS32_FRAG_LABEL)
6912 || (((*prev_frag)->fr_address + (*prev_frag)->fr_fix - 2 )
6913 & 0x2) == 0)
6914 nds32_adjust_relaxable_frag (*prev_frag, frag_t);
6915 }
6916 *prev_frag = NULL;
6917 return;
6918 }
6919 frag_t = frag_t->fr_next;
6920 }
6921
6922 if (fragP->tc_frag_data.flag & NDS32_FRAG_ALIGN)
6923 {
6924 address = fragP->fr_address;
6925 addressT offset = nds32_get_align (address, 2);
6926 if (offset & 0x2)
6927 {
6928 /* If there is label on the prev_frag, check if it is aligned. */
6929 if (!((*prev_frag)->tc_frag_data.flag & NDS32_FRAG_LABEL)
6930 || (((*prev_frag)->fr_address + (*prev_frag)->fr_fix - 2 )
6931 & 0x2) == 0)
6932 nds32_adjust_relaxable_frag (*prev_frag, fragP);
6933 }
6934 *prev_frag = NULL;
6935 return;
6936 }
6937 }
6938
6939 /* md_relax_frag */
6940
6941 int
6942 nds32_relax_frag (segT segment, fragS *fragP, long stretch ATTRIBUTE_UNUSED)
6943 {
6944 /* Currently, there are two kinds of relaxation in nds32 assembler.
6945 1. relax for branch
6946 2. relax for 32-bits to 16-bits */
6947
6948 static fragS *prev_frag = NULL;
6949 int adjust = 0;
6950
6951 invalid_prev_frag (fragP, &prev_frag, true);
6952
6953 if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
6954 adjust = nds32_relax_branch_instructions (segment, fragP, stretch, 0);
6955 if (fragP->tc_frag_data.flag & NDS32_FRAG_LABEL)
6956 prev_frag = NULL;
6957 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE
6958 && (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED) == 0)
6959 /* Here is considered relaxed case originally. But it may cause
6960 an endless loop when relaxing. Once the instruction is relaxed,
6961 it can not be undone. */
6962 prev_frag = fragP;
6963
6964 return adjust;
6965 }
6966
6967 /* This function returns an initial guess of the length by which a fragment
6968 must grow to hold a branch to reach its destination. Also updates
6969 fr_type/fr_subtype as necessary.
6970
6971 It is called just before doing relaxation. Any symbol that is now undefined
6972 will not become defined. The guess for fr_var is ACTUALLY the growth beyond
6973 fr_fix. Whatever we do to grow fr_fix or fr_var contributes to our returned
6974 value. Although it may not be explicit in the frag, pretend fr_var starts
6975 with a 0 value. */
6976
6977 int
6978 md_estimate_size_before_relax (fragS *fragP, segT segment)
6979 {
6980 /* Currently, there are two kinds of relaxation in nds32 assembler.
6981 1. relax for branch
6982 2. relax for 32-bits to 16-bits */
6983
6984 /* Save previous relaxable frag. */
6985 static fragS *prev_frag = NULL;
6986 int adjust = 0;
6987
6988 invalid_prev_frag (fragP, &prev_frag, false);
6989
6990 if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
6991 adjust = nds32_relax_branch_instructions (segment, fragP, 0, 1);
6992 if (fragP->tc_frag_data.flag & NDS32_FRAG_LABEL)
6993 prev_frag = NULL;
6994 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
6995 adjust = 2;
6996 else if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE)
6997 prev_frag = fragP;
6998
6999 return adjust;
7000 }
7001
7002 /* GAS will call this for each rs_machine_dependent fragment. The instruction
7003 is completed using the data from the relaxation pass. It may also create any
7004 necessary relocations.
7005
7006 *FRAGP has been relaxed to its final size, and now needs to have the bytes
7007 inside it modified to conform to the new size. It is called after relaxation
7008 is finished.
7009
7010 fragP->fr_type == rs_machine_dependent.
7011 fragP->fr_subtype is the subtype of what the address relaxed to. */
7012
7013 void
7014 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP)
7015 {
7016 /* Convert branch relaxation instructions. */
7017 symbolS *branch_symbol = fragP->fr_symbol;
7018 offsetT branch_offset = fragP->fr_offset;
7019 enum nds32_br_range branch_range_type = fragP->fr_subtype;
7020 struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
7021 uint32_t origin_insn = fragP->tc_frag_data.insn;
7022 relax_info_t *relax_info;
7023 char *fr_buffer;
7024 int fr_where;
7025 int addend ATTRIBUTE_UNUSED;
7026 offsetT branch_target_address, branch_insn_address;
7027 expressionS exp;
7028 fixS *fixP;
7029 uint32_t *code_seq;
7030 uint32_t insn;
7031 int code_size, insn_size, offset, fixup_size;
7032 int buf_offset, pcrel;
7033 int i, k;
7034 uint16_t insn_16;
7035 nds32_relax_fixup_info_t fixup_info[MAX_RELAX_FIX];
7036 /* Save the 1st instruction is converted to 16 bit or not. */
7037 unsigned int branch_size;
7038 enum bfd_reloc_code_real final_r_type;
7039
7040 /* Replace with gas_assert (branch_symbol != NULL); */
7041 if (branch_symbol == NULL && !(fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED))
7042 return;
7043
7044 /* If frag_var is not enough room, the previous frag is fr_full and with
7045 opcode. The new one is rs_dependent but without opcode. */
7046 if (opcode == NULL)
7047 return;
7048
7049 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE_BRANCH)
7050 {
7051 relax_info = str_hash_find (nds32_relax_info_hash, opcode->opcode);
7052
7053 if (relax_info == NULL)
7054 return;
7055
7056 i = BR_RANGE_S256;
7057 while (i < BR_RANGE_NUM
7058 && relax_info->relax_code_size[i]
7059 != (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED ? 4 : 2))
7060 i++;
7061
7062 if (i >= BR_RANGE_NUM)
7063 as_bad ("Internal error: Cannot find relocation of"
7064 "relaxable branch.");
7065
7066 exp.X_op = O_symbol;
7067 exp.X_add_symbol = branch_symbol;
7068 exp.X_add_number = branch_offset;
7069 pcrel = ((relax_info->relax_fixup[i][0].ramp & NDS32_PCREL) != 0) ? 1 : 0;
7070 fr_where = fragP->fr_fix - 2;
7071 fixP = fix_new_exp (fragP, fr_where, relax_info->relax_fixup[i][0].size,
7072 &exp, pcrel, relax_info->relax_fixup[i][0].r_type);
7073 fixP->fx_addnumber = fixP->fx_offset;
7074
7075 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
7076 {
7077 insn_16 = fragP->tc_frag_data.insn;
7078 nds32_convert_16_to_32 (stdoutput, insn_16, &insn);
7079 fr_buffer = fragP->fr_literal + fr_where;
7080 fragP->fr_fix += 2;
7081 exp.X_op = O_symbol;
7082 exp.X_add_symbol = abs_section_sym;
7083 exp.X_add_number = 0;
7084 fix_new_exp (fragP, fr_where, 4,
7085 &exp, 0, BFD_RELOC_NDS32_INSN16);
7086 number_to_chars_bigendian (fr_buffer, insn, 4);
7087 }
7088 }
7089 else if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
7090 {
7091 if (fragP->tc_frag_data.opcode->isize == 2)
7092 {
7093 insn_16 = fragP->tc_frag_data.insn;
7094 nds32_convert_16_to_32 (stdoutput, insn_16, &insn);
7095 }
7096 else
7097 insn = fragP->tc_frag_data.insn;
7098 fragP->fr_fix += 2;
7099 fr_where = fragP->fr_fix - 4;
7100 fr_buffer = fragP->fr_literal + fr_where;
7101 exp.X_op = O_symbol;
7102 exp.X_add_symbol = abs_section_sym;
7103 exp.X_add_number = 0;
7104 fix_new_exp (fragP, fr_where, 4, &exp, 0,
7105 BFD_RELOC_NDS32_INSN16);
7106 number_to_chars_bigendian (fr_buffer, insn, 4);
7107 }
7108 else if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
7109 {
7110 /* Branch instruction adjust and append relocations. */
7111 relax_info = str_hash_find (nds32_relax_info_hash, opcode->opcode);
7112
7113 if (relax_info == NULL)
7114 return;
7115
7116 fr_where = fragP->fr_fix - opcode->isize;
7117 fr_buffer = fragP->fr_literal + fr_where;
7118
7119 if ((S_GET_SEGMENT (branch_symbol) != sec)
7120 || S_IS_WEAK (branch_symbol))
7121 {
7122 if (fragP->fr_offset & 3)
7123 as_warn (_("Addend to unresolved symbol is not on word boundary."));
7124 addend = 0;
7125 }
7126 else
7127 {
7128 /* Calculate symbol-to-instruction offset. */
7129 branch_target_address = S_GET_VALUE (branch_symbol) + branch_offset;
7130 branch_insn_address = fragP->fr_address + fr_where;
7131 addend = (branch_target_address - branch_insn_address) >> 1;
7132 }
7133
7134 code_size = relax_info->relax_code_size[branch_range_type];
7135 code_seq = relax_info->relax_code_seq[branch_range_type];
7136
7137 memcpy (fixup_info, relax_info->relax_fixup[branch_range_type],
7138 sizeof (fixup_info));
7139
7140 /* Fill in frag. */
7141 i = 0;
7142 k = 0;
7143 offset = 0; /* code_seq offset */
7144 buf_offset = 0; /* fr_buffer offset */
7145 while (offset < code_size)
7146 {
7147 insn = code_seq[i];
7148 if (insn & 0x80000000) /* 16-bits instruction. */
7149 {
7150 insn = (insn >> 16) & 0xFFFF;
7151 insn_size = 2;
7152 }
7153 else /* 32-bits instruction. */
7154 {
7155 insn_size = 4;
7156 }
7157
7158 nds32_elf_get_set_cond (relax_info, offset, &insn,
7159 origin_insn, branch_range_type);
7160
7161 /* Try to convert to 16-bits instruction. Currently, only the first
7162 instruction in pattern can be converted. EX: bnez sethi ori jr,
7163 only bnez can be converted to 16 bit and ori can't. */
7164
7165 while (fixup_info[k].size != 0
7166 && relax_info->relax_fixup[branch_range_type][k].offset < offset)
7167 k++;
7168
7169 number_to_chars_bigendian (fr_buffer + buf_offset, insn, insn_size);
7170 buf_offset += insn_size;
7171
7172 offset += insn_size;
7173 i++;
7174 }
7175
7176 /* Set up fixup. */
7177 exp.X_op = O_symbol;
7178
7179 for (i = 0; fixup_info[i].size != 0; i++)
7180 {
7181 fixup_size = fixup_info[i].size;
7182 pcrel = ((fixup_info[i].ramp & NDS32_PCREL) != 0) ? 1 : 0;
7183
7184 if ((fixup_info[i].ramp & NDS32_CREATE_LABEL) != 0)
7185 {
7186 /* This is a reverse branch. */
7187 exp.X_add_symbol = symbol_temp_new (sec, fragP->fr_next, 0);
7188 exp.X_add_number = 0;
7189 }
7190 else if ((fixup_info[i].ramp & NDS32_PTR) != 0)
7191 {
7192 /* This relocation has to point to another instruction. */
7193 branch_size = fr_where + code_size - 4;
7194 exp.X_add_symbol = symbol_temp_new (sec, fragP, branch_size);
7195 exp.X_add_number = 0;
7196 }
7197 else if ((fixup_info[i].ramp & NDS32_ABS) != 0)
7198 {
7199 /* This is a tag relocation. */
7200 exp.X_add_symbol = abs_section_sym;
7201 exp.X_add_number = 0;
7202 }
7203 else if ((fixup_info[i].ramp & NDS32_INSN16) != 0)
7204 {
7205 if (!enable_16bit)
7206 continue;
7207 /* This is a tag relocation. */
7208 exp.X_add_symbol = abs_section_sym;
7209 exp.X_add_number = 0;
7210 }
7211 else
7212 {
7213 exp.X_add_symbol = branch_symbol;
7214 exp.X_add_number = branch_offset;
7215 }
7216
7217 if (fixup_info[i].r_type != 0)
7218 {
7219 final_r_type = fixup_info[i].r_type;
7220 fixP = fix_new_exp (fragP, fr_where + fixup_info[i].offset,
7221 fixup_size, &exp, pcrel,
7222 final_r_type);
7223 fixP->fx_addnumber = fixP->fx_offset;
7224 }
7225 }
7226
7227 fragP->fr_fix = fr_where + buf_offset;
7228 }
7229 }
7230
7231 /* tc_frob_file_before_fix */
7232
7233 void
7234 nds32_frob_file_before_fix (void)
7235 {
7236 }
7237
7238 static bool
7239 nds32_relaxable_section (asection *sec)
7240 {
7241 return ((sec->flags & SEC_DEBUGGING) == 0
7242 && strcmp (sec->name, ".eh_frame") != 0);
7243 }
7244
7245 /* TC_FORCE_RELOCATION */
7246 int
7247 nds32_force_relocation (fixS * fix)
7248 {
7249 switch (fix->fx_r_type)
7250 {
7251 case BFD_RELOC_NDS32_INSN16:
7252 case BFD_RELOC_NDS32_LABEL:
7253 case BFD_RELOC_NDS32_LONGCALL1:
7254 case BFD_RELOC_NDS32_LONGCALL2:
7255 case BFD_RELOC_NDS32_LONGCALL3:
7256 case BFD_RELOC_NDS32_LONGJUMP1:
7257 case BFD_RELOC_NDS32_LONGJUMP2:
7258 case BFD_RELOC_NDS32_LONGJUMP3:
7259 case BFD_RELOC_NDS32_LOADSTORE:
7260 case BFD_RELOC_NDS32_9_FIXED:
7261 case BFD_RELOC_NDS32_15_FIXED:
7262 case BFD_RELOC_NDS32_17_FIXED:
7263 case BFD_RELOC_NDS32_25_FIXED:
7264 case BFD_RELOC_NDS32_9_PCREL:
7265 case BFD_RELOC_NDS32_15_PCREL:
7266 case BFD_RELOC_NDS32_17_PCREL:
7267 case BFD_RELOC_NDS32_WORD_9_PCREL:
7268 case BFD_RELOC_NDS32_10_UPCREL:
7269 case BFD_RELOC_NDS32_25_PCREL:
7270 case BFD_RELOC_NDS32_MINUEND:
7271 case BFD_RELOC_NDS32_SUBTRAHEND:
7272 return 1;
7273
7274 case BFD_RELOC_8:
7275 case BFD_RELOC_16:
7276 case BFD_RELOC_32:
7277 case BFD_RELOC_NDS32_DIFF_ULEB128:
7278 /* Linker should handle difference between two symbol. */
7279 return fix->fx_subsy != NULL
7280 && nds32_relaxable_section (S_GET_SEGMENT (fix->fx_addsy));
7281 case BFD_RELOC_64:
7282 if (fix->fx_subsy)
7283 as_bad ("Double word for difference between two symbols "
7284 "is not supported across relaxation.");
7285 default:
7286 ;
7287 }
7288
7289 if (generic_force_reloc (fix))
7290 return 1;
7291
7292 return fix->fx_pcrel;
7293 }
7294
7295 /* TC_VALIDATE_FIX_SUB */
7296
7297 int
7298 nds32_validate_fix_sub (fixS *fix, segT add_symbol_segment)
7299 {
7300 segT sub_symbol_segment;
7301
7302 /* This code is referred from Xtensa. Check their implementation for
7303 details. */
7304
7305 /* Make sure both symbols are in the same segment, and that segment is
7306 "normal" and relaxable. */
7307 sub_symbol_segment = S_GET_SEGMENT (fix->fx_subsy);
7308 return (sub_symbol_segment == add_symbol_segment
7309 && add_symbol_segment != undefined_section);
7310 }
7311
7312 void
7313 md_number_to_chars (char *buf, valueT val, int n)
7314 {
7315 if (target_big_endian)
7316 number_to_chars_bigendian (buf, val, n);
7317 else
7318 number_to_chars_littleendian (buf, val, n);
7319 }
7320
7321 /* This function is called to convert an ASCII string into a floating point
7322 value in format used by the CPU. */
7323
7324 const char *
7325 md_atof (int type, char *litP, int *sizeP)
7326 {
7327 int i;
7328 int prec;
7329 LITTLENUM_TYPE words[MAX_LITTLENUMS];
7330 char *t;
7331
7332 switch (type)
7333 {
7334 case 'f':
7335 case 'F':
7336 case 's':
7337 case 'S':
7338 prec = 2;
7339 break;
7340 case 'd':
7341 case 'D':
7342 case 'r':
7343 case 'R':
7344 prec = 4;
7345 break;
7346 default:
7347 *sizeP = 0;
7348 return _("Bad call to md_atof()");
7349 }
7350
7351 t = atof_ieee (input_line_pointer, type, words);
7352 if (t)
7353 input_line_pointer = t;
7354 *sizeP = prec * sizeof (LITTLENUM_TYPE);
7355
7356 if (target_big_endian)
7357 {
7358 for (i = 0; i < prec; i++)
7359 {
7360 md_number_to_chars (litP, words[i], sizeof (LITTLENUM_TYPE));
7361 litP += sizeof (LITTLENUM_TYPE);
7362 }
7363 }
7364 else
7365 {
7366 for (i = prec - 1; i >= 0; i--)
7367 {
7368 md_number_to_chars (litP, words[i], sizeof (LITTLENUM_TYPE));
7369 litP += sizeof (LITTLENUM_TYPE);
7370 }
7371 }
7372
7373 return 0;
7374 }
7375
7376 /* md_elf_section_change_hook */
7377
7378 void
7379 nds32_elf_section_change_hook (void)
7380 {
7381 }
7382
7383 /* md_cleanup */
7384
7385 void
7386 nds32_cleanup (void)
7387 {
7388 }
7389
7390 /* This function is used to scan leb128 subtraction expressions,
7391 and insert fixups for them.
7392
7393 e.g., .leb128 .L1 - .L0
7394
7395 These expressions are heavily used in debug information or
7396 exception tables. Because relaxation will change code size,
7397 we must resolve them in link time. */
7398
7399 static void
7400 nds32_insert_leb128_fixes (bfd *abfd ATTRIBUTE_UNUSED,
7401 asection *sec, void *xxx ATTRIBUTE_UNUSED)
7402 {
7403 segment_info_type *seginfo = seg_info (sec);
7404 struct frag *fragP;
7405
7406 subseg_set (sec, 0);
7407
7408 for (fragP = seginfo->frchainP->frch_root;
7409 fragP; fragP = fragP->fr_next)
7410 {
7411 expressionS *exp;
7412
7413 /* Only unsigned leb128 can be handle. */
7414 if (fragP->fr_type != rs_leb128 || fragP->fr_subtype != 0
7415 || fragP->fr_symbol == NULL)
7416 continue;
7417
7418 exp = symbol_get_value_expression (fragP->fr_symbol);
7419
7420 if (exp->X_op != O_subtract)
7421 continue;
7422
7423 fix_new_exp (fragP, fragP->fr_fix, 0,
7424 exp, 0, BFD_RELOC_NDS32_DIFF_ULEB128);
7425 }
7426 }
7427
7428 static void
7429 nds32_insert_relax_entry (bfd *abfd ATTRIBUTE_UNUSED, asection *sec,
7430 void *xxx ATTRIBUTE_UNUSED)
7431 {
7432 segment_info_type *seginfo;
7433 fragS *fragP;
7434 fixS *fixP;
7435 expressionS exp;
7436 fixS *fixp;
7437
7438 seginfo = seg_info (sec);
7439 if (!seginfo || !symbol_rootP || !subseg_text_p (sec) || sec->size == 0)
7440 return;
7441
7442 for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
7443 if (!fixp->fx_done)
7444 break;
7445
7446 if (!fixp && !verbatim && ict_flag == ICT_NONE)
7447 return;
7448
7449 subseg_change (sec, 0);
7450
7451 /* Set RELAX_ENTRY flags for linker. */
7452 fragP = seginfo->frchainP->frch_root;
7453 exp.X_op = O_symbol;
7454 exp.X_add_symbol = abs_section_sym;
7455 exp.X_add_number = 0;
7456 if (!enable_relax_relocs)
7457 exp.X_add_number |= R_NDS32_RELAX_ENTRY_DISABLE_RELAX_FLAG;
7458 else
7459 {
7460 /* These flags are only enabled when global relax is enabled.
7461 Maybe we can check DISABLE_RELAX_FLAG at link-time,
7462 so we set them anyway. */
7463 if (verbatim)
7464 exp.X_add_number |= R_NDS32_RELAX_ENTRY_VERBATIM_FLAG;
7465 if (ict_flag == ICT_SMALL)
7466 exp.X_add_number |= R_NDS32_RELAX_ENTRY_ICT_SMALL;
7467 else if (ict_flag == ICT_LARGE)
7468 exp.X_add_number |= R_NDS32_RELAX_ENTRY_ICT_LARGE;
7469 }
7470 if (optimize)
7471 exp.X_add_number |= R_NDS32_RELAX_ENTRY_OPTIMIZE_FLAG;
7472 if (optimize_for_space)
7473 exp.X_add_number |= R_NDS32_RELAX_ENTRY_OPTIMIZE_FOR_SPACE_FLAG;
7474
7475 fixP = fix_new_exp (fragP, 0, 0, &exp, 0, BFD_RELOC_NDS32_RELAX_ENTRY);
7476 fixP->fx_no_overflow = 1;
7477 }
7478
7479 /* Analysis relax hint and insert suitable relocation pattern. */
7480
7481 static void
7482 nds32_elf_analysis_relax_hint (void)
7483 {
7484 htab_traverse_noresize (nds32_hint_hash,
7485 nds32_elf_append_relax_relocs_traverse, NULL);
7486 }
7487
7488 static void
7489 nds32_elf_insert_final_frag (void)
7490 {
7491 struct frchain *frchainP;
7492 asection *s;
7493 fragS *fragP;
7494
7495 if (!optimize)
7496 return;
7497
7498 for (s = stdoutput->sections; s; s = s->next)
7499 {
7500 segment_info_type *seginfo = seg_info (s);
7501 if (!seginfo)
7502 continue;
7503
7504 for (frchainP = seginfo->frchainP; frchainP != NULL;
7505 frchainP = frchainP->frch_next)
7506 {
7507 subseg_set (s, frchainP->frch_subseg);
7508
7509 if (subseg_text_p (now_seg))
7510 {
7511 fragP = frag_now;
7512 frag_var (rs_machine_dependent, 2, /* Max size. */
7513 0, /* VAR is un-used. */ 0, NULL, 0, NULL);
7514 fragP->tc_frag_data.flag |= NDS32_FRAG_FINAL;
7515 }
7516 }
7517 }
7518 }
7519
7520 void
7521 md_finish (void)
7522 {
7523 nds32_elf_insert_final_frag ();
7524 nds32_elf_analysis_relax_hint ();
7525 bfd_map_over_sections (stdoutput, nds32_insert_leb128_fixes, NULL);
7526 }
7527
7528 /* Implement md_allow_local_subtract. */
7529
7530 bool
7531 nds32_allow_local_subtract (expressionS *expr_l ATTRIBUTE_UNUSED,
7532 expressionS *expr_r ATTRIBUTE_UNUSED,
7533 segT sec ATTRIBUTE_UNUSED)
7534 {
7535 /* Don't allow any subtraction, because relax may change the code. */
7536 return false;
7537 }
7538
7539 long
7540 nds32_pcrel_from_section (fixS *fixP, segT sec ATTRIBUTE_UNUSED)
7541 {
7542 if (fixP->fx_addsy == NULL || !S_IS_DEFINED (fixP->fx_addsy)
7543 || S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy))
7544 {
7545 /* Let linker resolve undefined symbols. */
7546 return 0;
7547 }
7548
7549 return fixP->fx_frag->fr_address + fixP->fx_where;
7550 }
7551
7552 /* md_post_relax_hook ()
7553 Insert relax entry relocation into sections. */
7554
7555 void
7556 nds32_post_relax_hook (void)
7557 {
7558 bfd_map_over_sections (stdoutput, nds32_insert_relax_entry, NULL);
7559 }
7560
7561 /* tc_fix_adjustable ()
7562
7563 Return whether this symbol (fixup) can be replaced with
7564 section symbols. */
7565
7566 bool
7567 nds32_fix_adjustable (fixS *fixP)
7568 {
7569 switch (fixP->fx_r_type)
7570 {
7571 case BFD_RELOC_NDS32_WORD_9_PCREL:
7572 case BFD_RELOC_NDS32_9_PCREL:
7573 case BFD_RELOC_NDS32_15_PCREL:
7574 case BFD_RELOC_NDS32_17_PCREL:
7575 case BFD_RELOC_NDS32_25_PCREL:
7576 case BFD_RELOC_NDS32_HI20:
7577 case BFD_RELOC_NDS32_LO12S0:
7578 case BFD_RELOC_8:
7579 case BFD_RELOC_16:
7580 case BFD_RELOC_32:
7581 case BFD_RELOC_NDS32_PTR:
7582 case BFD_RELOC_NDS32_LONGCALL4:
7583 case BFD_RELOC_NDS32_LONGCALL5:
7584 case BFD_RELOC_NDS32_LONGCALL6:
7585 case BFD_RELOC_NDS32_LONGJUMP4:
7586 case BFD_RELOC_NDS32_LONGJUMP5:
7587 case BFD_RELOC_NDS32_LONGJUMP6:
7588 case BFD_RELOC_NDS32_LONGJUMP7:
7589 return 1;
7590 default:
7591 return 0;
7592 }
7593 }
7594
7595 /* elf_tc_final_processing */
7596
7597 void
7598 elf_nds32_final_processing (void)
7599 {
7600 /* An FPU_COM instruction is found without previous non-FPU_COM
7601 instruction. */
7602 if (nds32_fpu_com
7603 && !(nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST)))
7604 {
7605 /* Since only FPU_COM instructions are used and no other FPU instructions
7606 are used. The nds32_elf_flags will be decided by the enabled options
7607 by command line or default configuration. */
7608 if (nds32_fpu_dp_ext || nds32_fpu_sp_ext)
7609 {
7610 nds32_elf_flags |= nds32_fpu_dp_ext ? E_NDS32_HAS_FPU_DP_INST : 0;
7611 nds32_elf_flags |= nds32_fpu_sp_ext ? E_NDS32_HAS_FPU_INST : 0;
7612 }
7613 else
7614 {
7615 /* Should never here. */
7616 as_bad (_("Used FPU instructions requires enabling FPU extension"));
7617 }
7618 }
7619
7620 if (nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST))
7621 {
7622 /* Single/double FPU has been used, set FPU register config. */
7623 /* We did not check the actual number of register used. We may
7624 want to do it while assemble. */
7625 nds32_elf_flags &= ~E_NDS32_FPU_REG_CONF;
7626 nds32_elf_flags |= (nds32_freg << E_NDS32_FPU_REG_CONF_SHIFT);
7627 }
7628
7629 if (nds32_pic)
7630 nds32_elf_flags |= E_NDS32_HAS_PIC;
7631
7632 if (nds32_gpr16)
7633 nds32_elf_flags |= E_NDS32_HAS_REDUCED_REGS;
7634
7635 nds32_elf_flags |= (E_NDS32_ELF_VER_1_4 | nds32_abi);
7636 elf_elfheader (stdoutput)->e_flags |= nds32_elf_flags;
7637 }
7638
7639 /* Implement md_apply_fix. Apply the fix-up or transform the fix-up for
7640 later relocation generation. */
7641
7642 void
7643 nds32_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
7644 {
7645 char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
7646 bfd_vma value = *valP;
7647
7648 if (fixP->fx_r_type < BFD_RELOC_UNUSED
7649 && fixP->fx_r_type > BFD_RELOC_NONE
7650 && fixP->fx_r_type != BFD_RELOC_NDS32_DIFF_ULEB128)
7651 {
7652 /* In our old nds32 binutils, it must convert relocations which is
7653 generated by CGEN. However, it does not have to consider this anymore.
7654 In current, it only deal with data relocations which enum
7655 is smaller than BFD_RELOC_NONE and BFD_RELOC_NDS32_DIFF_ULEB128.
7656 It is believed that we can construct a better mechanism to
7657 deal with the whole relocation issue in nds32 target
7658 without using CGEN. */
7659 fixP->fx_addnumber = value;
7660 fixP->tc_fix_data = NULL;
7661
7662 /* Transform specific relocations here for later relocation generation.
7663 Tag tls data for linker. */
7664 switch (fixP->fx_r_type)
7665 {
7666 case BFD_RELOC_NDS32_DATA:
7667 /* This reloc is obselete, we do not need it so far. */
7668 fixP->fx_done = 1;
7669 break;
7670 case BFD_RELOC_NDS32_TPOFF:
7671 case BFD_RELOC_NDS32_TLS_LE_HI20:
7672 case BFD_RELOC_NDS32_TLS_LE_LO12:
7673 case BFD_RELOC_NDS32_TLS_LE_ADD:
7674 case BFD_RELOC_NDS32_TLS_LE_LS:
7675 case BFD_RELOC_NDS32_GOTTPOFF:
7676 case BFD_RELOC_NDS32_TLS_IE_HI20:
7677 case BFD_RELOC_NDS32_TLS_IE_LO12S2:
7678 case BFD_RELOC_NDS32_TLS_DESC_HI20:
7679 case BFD_RELOC_NDS32_TLS_DESC_LO12:
7680 case BFD_RELOC_NDS32_TLS_IE_LO12:
7681 case BFD_RELOC_NDS32_TLS_IEGP_HI20:
7682 case BFD_RELOC_NDS32_TLS_IEGP_LO12:
7683 case BFD_RELOC_NDS32_TLS_IEGP_LO12S2:
7684 S_SET_THREAD_LOCAL (fixP->fx_addsy);
7685 break;
7686 default:
7687 break;
7688 }
7689 return;
7690 }
7691
7692 if (fixP->fx_addsy == NULL)
7693 fixP->fx_done = 1;
7694
7695 if (fixP->fx_subsy != NULL)
7696 {
7697 /* HOW DIFF RELOCATION WORKS.
7698
7699 First of all, this relocation is used to calculate the distance
7700 between two symbols in the SAME section. It is used for jump-
7701 table, debug information, exception table, et al. Therefore,
7702 it is a unsigned positive value. It is NOT used for general-
7703 purpose arithmetic.
7704
7705 Consider this example, the distance between .LEND and .LBEGIN
7706 is stored at the address of foo.
7707
7708 ---- >8 ---- >8 ---- >8 ---- >8 ----
7709 .data
7710 foo:
7711 .word .LBEGIN - .LEND
7712
7713 .text
7714 [before]
7715 .LBEGIN
7716 \
7717 [between] distance
7718 /
7719 .LEND
7720 [after]
7721 ---- 8< ---- 8< ---- 8< ---- 8< ----
7722
7723 We use a single relocation entry for this expression.
7724 * The initial distance value is stored directly in that location
7725 specified by r_offset (i.e., foo in this example.)
7726 * The begin of the region, i.e., .LBEGIN, is specified by
7727 r_info/R_SYM and r_addend, e.g., .text + 0x32.
7728 * The end of region, i.e., .LEND, is represented by
7729 .LBEGIN + distance instead of .LEND, so we only need
7730 a single relocation entry instead of two.
7731
7732 When an instruction is relaxed, we adjust the relocation entry
7733 depending on where the instruction locates. There are three
7734 cases, before, after and between the region.
7735 * between: Distance value is read from r_offset, adjusted and
7736 written back into r_offset.
7737 * before: Only r_addend is adjust.
7738 * after: We don't care about it.
7739
7740 Hereby, there are some limitation.
7741
7742 `(.LEND - 1) - .LBEGIN' and `(.LEND - .LBEGIN) - 1'
7743 are semantically different, and we cannot handle latter case
7744 when relaxation.
7745
7746 The latter expression means subtracting 1 from the distance
7747 between .LEND and .LBEGIN. And the former expression means
7748 the distance between (.LEND - 1) and .LBEGIN.
7749
7750 The nuance affects whether to adjust distance value when relax
7751 an instruction. In another words, whether the instruction
7752 locates in the region. Because we use a single relocation entry,
7753 there is no field left for .LEND and the subtrahend.
7754
7755 Since GCC-4.5, GCC may produce debug information in such expression
7756 .long .L1-1-.L0
7757 in order to describe register clobbering during an function-call.
7758 .L0:
7759 call foo
7760 .L1:
7761
7762 Check http://gcc.gnu.org/ml/gcc-patches/2009-06/msg01317.html
7763 for details. */
7764
7765 value -= S_GET_VALUE (fixP->fx_subsy);
7766 *valP = value;
7767 fixP->fx_subsy = NULL;
7768 fixP->fx_offset -= value;
7769
7770 switch (fixP->fx_r_type)
7771 {
7772 case BFD_RELOC_8:
7773 fixP->fx_r_type = BFD_RELOC_NDS32_DIFF8;
7774 md_number_to_chars (where, value, 1);
7775 break;
7776 case BFD_RELOC_16:
7777 fixP->fx_r_type = BFD_RELOC_NDS32_DIFF16;
7778 md_number_to_chars (where, value, 2);
7779 break;
7780 case BFD_RELOC_32:
7781 fixP->fx_r_type = BFD_RELOC_NDS32_DIFF32;
7782 md_number_to_chars (where, value, 4);
7783 break;
7784 case BFD_RELOC_NDS32_DIFF_ULEB128:
7785 /* cvt_frag_to_fill () has called output_leb128 () for us. */
7786 break;
7787 default:
7788 as_bad_subtract (fixP);
7789 return;
7790 }
7791 }
7792 else if (fixP->fx_done)
7793 {
7794 /* We're finished with this fixup. Install it because
7795 bfd_install_relocation won't be called to do it. */
7796 switch (fixP->fx_r_type)
7797 {
7798 case BFD_RELOC_8:
7799 md_number_to_chars (where, value, 1);
7800 break;
7801 case BFD_RELOC_16:
7802 md_number_to_chars (where, value, 2);
7803 break;
7804 case BFD_RELOC_32:
7805 md_number_to_chars (where, value, 4);
7806 break;
7807 case BFD_RELOC_64:
7808 md_number_to_chars (where, value, 8);
7809 break;
7810 default:
7811 as_bad_where (fixP->fx_file, fixP->fx_line,
7812 _("Internal error: Unknown fixup type %d (`%s')"),
7813 fixP->fx_r_type,
7814 bfd_get_reloc_code_name (fixP->fx_r_type));
7815 break;
7816 }
7817 }
7818 }
7819
7820 /* Implement tc_gen_reloc. Generate ELF relocation for a fix-up. */
7821
7822 arelent *
7823 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
7824 {
7825 arelent *reloc;
7826 bfd_reloc_code_real_type code;
7827
7828 reloc = notes_alloc (sizeof (arelent));
7829 reloc->sym_ptr_ptr = notes_alloc (sizeof (asymbol *));
7830 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
7831 reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
7832
7833 code = fixP->fx_r_type;
7834
7835 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
7836 if (reloc->howto == NULL)
7837 {
7838 as_bad_where (fixP->fx_file, fixP->fx_line,
7839 _("internal error: can't export reloc type %d (`%s')"),
7840 fixP->fx_r_type, bfd_get_reloc_code_name (code));
7841 return NULL;
7842 }
7843
7844 /* Add relocation handling here. */
7845
7846 switch (fixP->fx_r_type)
7847 {
7848 default:
7849 /* In general, addend of a relocation is the offset to the
7850 associated symbol. */
7851 reloc->addend = fixP->fx_offset;
7852 break;
7853
7854 case BFD_RELOC_NDS32_DATA:
7855 /* Prevent linker from optimizing data in text sections.
7856 For example, jump table. */
7857 reloc->addend = fixP->fx_size;
7858 break;
7859 }
7860
7861 return reloc;
7862 }
7863
7864 static struct suffix_name suffix_table[] =
7865 {
7866 {"GOTOFF", BFD_RELOC_NDS32_GOTOFF},
7867 {"GOT", BFD_RELOC_NDS32_GOT20},
7868 {"TPOFF", BFD_RELOC_NDS32_TPOFF},
7869 {"PLT", BFD_RELOC_NDS32_25_PLTREL},
7870 {"GOTTPOFF", BFD_RELOC_NDS32_GOTTPOFF},
7871 {"TLSDESC", BFD_RELOC_NDS32_TLS_DESC},
7872 };
7873
7874 /* Implement md_parse_name. */
7875
7876 int
7877 nds32_parse_name (char const *name, expressionS *exprP,
7878 enum expr_mode mode ATTRIBUTE_UNUSED,
7879 char *nextcharP ATTRIBUTE_UNUSED)
7880 {
7881 segT segment;
7882
7883 exprP->X_op_symbol = NULL;
7884 exprP->X_md = BFD_RELOC_UNUSED;
7885
7886 exprP->X_add_symbol = symbol_find_or_make (name);
7887 exprP->X_op = O_symbol;
7888 exprP->X_add_number = 0;
7889
7890 /* Check the special name if a symbol. */
7891 segment = S_GET_SEGMENT (exprP->X_add_symbol);
7892 if ((segment != undefined_section) && (*nextcharP != '@'))
7893 return 0;
7894
7895 if (strcmp (name, GOT_NAME) == 0 && *nextcharP != '@')
7896 {
7897 /* Set for _GOT_OFFSET_TABLE_. */
7898 exprP->X_md = BFD_RELOC_NDS32_GOTPC20;
7899 }
7900 else if (*nextcharP == '@')
7901 {
7902 size_t i;
7903 char *next;
7904 for (i = 0; i < ARRAY_SIZE (suffix_table); i++)
7905 {
7906 next = input_line_pointer + 1 + strlen (suffix_table[i].suffix);
7907 if (strncasecmp (input_line_pointer + 1, suffix_table[i].suffix,
7908 strlen (suffix_table[i].suffix)) == 0
7909 && !is_part_of_name (*next))
7910 {
7911 exprP->X_md = suffix_table[i].reloc;
7912 *input_line_pointer = *nextcharP;
7913 input_line_pointer = next;
7914 *nextcharP = *input_line_pointer;
7915 *input_line_pointer = '\0';
7916 break;
7917 }
7918 }
7919 }
7920
7921 return 1;
7922 }
7923
7924 /* Implement tc_regname_to_dw2regnum. */
7925
7926 int
7927 tc_nds32_regname_to_dw2regnum (char *regname)
7928 {
7929 struct nds32_keyword *sym = str_hash_find (nds32_gprs_hash, regname);
7930
7931 if (!sym)
7932 return -1;
7933
7934 return sym->value;
7935 }
7936
7937 void
7938 tc_nds32_frame_initial_instructions (void)
7939 {
7940 /* CIE */
7941 /* Default cfa is register-31/sp. */
7942 cfi_add_CFA_def_cfa (31, 0);
7943 }
7944