tc-nds32.c revision 1.1.1.7 1 /* tc-nds32.c -- Assemble for the nds32
2 Copyright (C) 2012-2024 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 struct option md_longopts[] =
2320 {
2321 {"O1", no_argument, NULL, OPTION_OPTIMIZE},
2322 {"Os", no_argument, NULL, OPTION_OPTIMIZE_SPACE},
2323 {"big", no_argument, NULL, OPTION_BIG},
2324 {"little", no_argument, NULL, OPTION_LITTLE},
2325 {"EB", no_argument, NULL, OPTION_BIG},
2326 {"EL", no_argument, NULL, OPTION_LITTLE},
2327 {"meb", no_argument, NULL, OPTION_BIG},
2328 {"mel", no_argument, NULL, OPTION_LITTLE},
2329 {"mall-ext", no_argument, NULL, OPTION_TURBO},
2330 {"mext-all", no_argument, NULL, OPTION_TURBO},
2331 {"mpic", no_argument, NULL, OPTION_PIC},
2332 /* Relaxation related options. */
2333 {"mno-fp-as-gp-relax", no_argument, NULL, OPTION_RELAX_FP_AS_GP_OFF},
2334 {"mb2bb", no_argument, NULL, OPTION_RELAX_B2BB_ON},
2335 {"mno-all-relax", no_argument, NULL, OPTION_RELAX_ALL_OFF},
2336 {NULL, no_argument, NULL, 0}
2337 };
2338
2339 size_t md_longopts_size = sizeof (md_longopts);
2340
2341 struct nds32_parse_option_table
2342 {
2343 const char *name; /* Option string. */
2344 const char *help; /* Help description. */
2345 int (*func) (const char *arg); /* How to parse it. */
2346 };
2347
2348
2349 /* The value `-1' represents this option has *NOT* been set. */
2350 #ifdef NDS32_DEFAULT_ARCH_NAME
2351 static const char* nds32_arch_name = NDS32_DEFAULT_ARCH_NAME;
2352 #else
2353 static const char* nds32_arch_name = "v3";
2354 #endif
2355 static int nds32_baseline = -1;
2356 static int nds32_gpr16 = -1;
2357 static int nds32_fpu_sp_ext = -1;
2358 static int nds32_fpu_dp_ext = -1;
2359 static int nds32_freg = -1;
2360 static int nds32_abi = -1;
2361
2362 /* Record ELF flags */
2363 static int nds32_elf_flags = 0;
2364 static int nds32_fpu_com = 0;
2365
2366 static int nds32_parse_arch (const char *str);
2367 static int nds32_parse_baseline (const char *str);
2368 static int nds32_parse_freg (const char *str);
2369 static int nds32_parse_abi (const char *str);
2370 static void add_mapping_symbol (enum mstate state,
2371 unsigned int padding_byte,
2372 unsigned int align);
2373
2374 static struct nds32_parse_option_table parse_opts [] =
2375 {
2376 {"arch=", N_("<arch name>\t Assemble for architecture <arch name>\n\
2377 <arch name> could be\n\
2378 v3, v3j, v3m, v3f, v3s, "\
2379 "v2, v2j, v2f, v2s"), nds32_parse_arch},
2380 {"baseline=", N_("<baseline>\t Assemble for baseline <baseline>\n\
2381 <baseline> could be v2, v3, v3m"),
2382 nds32_parse_baseline},
2383 {"fpu-freg=", N_("<freg>\t Specify a FPU configuration\n\
2384 <freg>\n\
2385 0: 8 SP / 4 DP registers\n\
2386 1: 16 SP / 8 DP registers\n\
2387 2: 32 SP / 16 DP registers\n\
2388 3: 32 SP / 32 DP registers"), nds32_parse_freg},
2389 {"abi=", N_("<abi>\t Specify a abi version\n\
2390 <abi> could be v1, v2, v2fp, v2fpp"), nds32_parse_abi},
2391 {NULL, NULL, NULL}
2392 };
2393
2394 static int nds32_mac = 1;
2395 static int nds32_div = 1;
2396 static int nds32_16bit_ext = 1;
2397 static int nds32_dx_regs = NDS32_DEFAULT_DX_REGS;
2398 static int nds32_perf_ext = NDS32_DEFAULT_PERF_EXT;
2399 static int nds32_perf_ext2 = NDS32_DEFAULT_PERF_EXT2;
2400 static int nds32_string_ext = NDS32_DEFAULT_STRING_EXT;
2401 static int nds32_audio_ext = NDS32_DEFAULT_AUDIO_EXT;
2402 static int nds32_dsp_ext = NDS32_DEFAULT_DSP_EXT;
2403 static int nds32_zol_ext = NDS32_DEFAULT_ZOL_EXT;
2404 static int nds32_fpu_fma = 0;
2405 static int nds32_pic = 0;
2406 static int nds32_relax_fp_as_gp = 1;
2407 static int nds32_relax_b2bb = 0;
2408 static int nds32_relax_all = 1;
2409 struct nds32_set_option_table
2410 {
2411 const char *name; /* Option string. */
2412 const char *help; /* Help description. */
2413 int *var; /* Variable to be set. */
2414 int value; /* Value to set. */
2415 };
2416
2417 /* The option in this group has both Enable/Disable settings.
2418 Just list on here. */
2419
2420 static struct nds32_set_option_table toggle_opts [] =
2421 {
2422 {"mac", N_("Multiply instructions support"), &nds32_mac, 1},
2423 {"div", N_("Divide instructions support"), &nds32_div, 1},
2424 {"16bit-ext", N_("16-bit extension"), &nds32_16bit_ext, 1},
2425 {"dx-regs", N_("d0/d1 registers"), &nds32_dx_regs, 1},
2426 {"perf-ext", N_("Performance extension"), &nds32_perf_ext, 1},
2427 {"perf2-ext", N_("Performance extension 2"), &nds32_perf_ext2, 1},
2428 {"string-ext", N_("String extension"), &nds32_string_ext, 1},
2429 {"reduced-regs", N_("Reduced Register configuration (GPR16) option"), &nds32_gpr16, 1},
2430 {"audio-isa-ext", N_("AUDIO ISA extension"), &nds32_audio_ext, 1},
2431 {"fpu-sp-ext", N_("FPU SP extension"), &nds32_fpu_sp_ext, 1},
2432 {"fpu-dp-ext", N_("FPU DP extension"), &nds32_fpu_dp_ext, 1},
2433 {"fpu-fma", N_("FPU fused-multiply-add instructions"), &nds32_fpu_fma, 1},
2434 {"dsp-ext", N_("DSP extension"), &nds32_dsp_ext, 1},
2435 {"zol-ext", N_("hardware loop extension"), &nds32_zol_ext, 1},
2436 {NULL, NULL, NULL, 0}
2437 };
2438
2439
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 (ISSPACE (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 () & ((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 = (valueT) 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, (valueT) 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 && !ISSPACE (*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 *nds_itoa (int n);
4219
4220 static char *
4221 nds_itoa (int n)
4222 {
4223 char *buf = xmalloc (MAX_BUFFER * sizeof (char));
4224 snprintf (buf, MAX_BUFFER, "%d", n);
4225 return buf;
4226 }
4227
4228 /* Insert a relax hint. */
4229
4230 static void
4231 nds32_relax_hint (int mode ATTRIBUTE_UNUSED)
4232 {
4233 char *name = NULL;
4234 char saved_char;
4235 struct nds32_relocs_pattern *relocs = NULL;
4236 struct nds32_relocs_group *group, *new;
4237 struct relax_hint_id *record_id;
4238
4239 name = input_line_pointer;
4240 while (*input_line_pointer && !ISSPACE (*input_line_pointer))
4241 input_line_pointer++;
4242 saved_char = *input_line_pointer;
4243 *input_line_pointer = 0;
4244 name = strdup (name);
4245
4246 if (name && strcmp (name, "begin") == 0)
4247 {
4248 if (relax_hint_id_current == -1)
4249 reset_bias = 1;
4250 relax_hint_bias++;
4251 relax_hint_id_current++;
4252 relax_hint_begin = 1;
4253 }
4254
4255 /* Original case ".relax_hint id". It's id may need to be reordered. */
4256 if (!relax_hint_begin)
4257 {
4258 int tmp = strtol (name, NULL, 10);
4259 record_id = record_id_head;
4260 while (record_id)
4261 {
4262 if (record_id->old_id == tmp)
4263 {
4264 name = nds_itoa (record_id->new_id);
4265 goto reordered_id;
4266 }
4267 record_id = record_id->next;
4268 }
4269 if (reset_bias)
4270 {
4271 relax_hint_bias = relax_hint_id_current - atoi (name) + 1;
4272 reset_bias = 0;
4273 }
4274 relax_hint_id_current = tmp + relax_hint_bias;
4275
4276 /* Insert the element to the head of the link list. */
4277 struct relax_hint_id *tmp_id = malloc (sizeof (struct relax_hint_id));
4278 tmp_id->old_id = tmp;
4279 tmp_id->new_id = relax_hint_id_current;
4280 tmp_id->next = record_id_head;
4281 record_id_head = tmp_id;
4282 }
4283
4284 if (name && strcmp (name, "end") == 0)
4285 relax_hint_begin = 0;
4286 name = nds_itoa (relax_hint_id_current);
4287
4288 reordered_id:
4289
4290 /* Find relax hint entry for next instruction, and all member will be
4291 initialized at that time. */
4292 relocs = str_hash_find (nds32_hint_hash, name);
4293 if (relocs == NULL)
4294 {
4295 relocs = notes_calloc (1, sizeof (*relocs));
4296 str_hash_insert (nds32_hint_hash, name, relocs, 0);
4297 }
4298 else
4299 {
4300 while (relocs->next)
4301 relocs = relocs->next;
4302 relocs->next = notes_calloc (1, sizeof (*relocs));
4303 relocs = relocs->next;
4304 }
4305
4306 *input_line_pointer = saved_char;
4307 ignore_rest_of_line ();
4308
4309 /* Get the final one of relax hint series. */
4310
4311 /* It has to build this list because there are maybe more than one
4312 instructions relative to the same instruction. It to connect to
4313 next instruction after md_assemble. */
4314 new = XNEW (struct nds32_relocs_group);
4315 memset (new, 0, sizeof (struct nds32_relocs_group));
4316 new->pattern = relocs;
4317 new->next = NULL;
4318 group = nds32_relax_hint_current;
4319 if (!group)
4320 nds32_relax_hint_current = new;
4321 else
4322 {
4323 while (group->next != NULL)
4324 group = group->next;
4325 group->next = new;
4326 }
4327 relaxing = true;
4328 }
4329
4330 /* Decide the size of vector entries, only accepts 4 or 16 now. */
4331
4332 static void
4333 nds32_vec_size (int ignore ATTRIBUTE_UNUSED)
4334 {
4335 expressionS exp;
4336
4337 expression (&exp);
4338
4339 if (exp.X_op == O_constant)
4340 {
4341 if (exp.X_add_number == 4 || exp.X_add_number == 16)
4342 {
4343 if (vec_size == 0)
4344 vec_size = exp.X_add_number;
4345 else if (vec_size != exp.X_add_number)
4346 as_warn (_("Different arguments of .vec_size are found, "
4347 "previous %d, current %d"),
4348 (int) vec_size, (int) exp.X_add_number);
4349 }
4350 else
4351 as_warn (_("Argument of .vec_size is expected 4 or 16, actual: %d."),
4352 (int) exp.X_add_number);
4353 }
4354 else
4355 as_warn (_("Argument of .vec_size is not a constant."));
4356 }
4357
4358 /* The behavior of ".flag" directive varies depending on the target.
4359 In nds32 target, we use it to recognize whether this assembly content is
4360 generated by compiler. Other features can also be added in this function
4361 in the future. */
4362
4363 static void
4364 nds32_flag (int ignore ATTRIBUTE_UNUSED)
4365 {
4366 char *name;
4367 char saved_char;
4368 int i;
4369 const char *possible_flags[] = { "verbatim" };
4370
4371 /* Skip whitespaces. */
4372 name = input_line_pointer;
4373 while (*input_line_pointer && !ISSPACE (*input_line_pointer))
4374 input_line_pointer++;
4375 saved_char = *input_line_pointer;
4376 *input_line_pointer = 0;
4377
4378 for (i = 0; i < (int) ARRAY_SIZE (possible_flags); i++)
4379 {
4380 if (strcmp (name, possible_flags[i]) == 0)
4381 {
4382 switch (i)
4383 {
4384 case 0:
4385 /* flag: verbatim */
4386 verbatim = 1;
4387 break;
4388 default:
4389 break;
4390 }
4391 /* Already found the flag, no need to continue next loop. */
4392 break;
4393 }
4394 }
4395
4396 *input_line_pointer = saved_char;
4397 ignore_rest_of_line ();
4398 }
4399
4400 static void
4401 ict_model (int ignore ATTRIBUTE_UNUSED)
4402 {
4403 char *name;
4404 char saved_char;
4405 int i;
4406 const char *possible_flags[] = { "small", "large" };
4407
4408 /* Skip whitespaces. */
4409 name = input_line_pointer;
4410 while (*input_line_pointer && !ISSPACE (*input_line_pointer))
4411 input_line_pointer++;
4412 saved_char = *input_line_pointer;
4413 *input_line_pointer = 0;
4414
4415 for (i = 0; i < (int) ARRAY_SIZE (possible_flags); i++)
4416 {
4417 if (strcmp (name, possible_flags[i]) == 0)
4418 {
4419 switch (i)
4420 {
4421 case 0:
4422 /* flag: verbatim */
4423 ict_flag = ICT_SMALL;
4424 break;
4425 case 1:
4426 ict_flag = ICT_LARGE;
4427 break;
4428 default:
4429 break;
4430 }
4431 /* Already found the flag, no need to continue next loop. */
4432 break;
4433 }
4434 }
4435
4436 *input_line_pointer = saved_char;
4437 ignore_rest_of_line ();
4438 }
4439
4440 static void
4441 nds32_n12hc (int ignore ATTRIBUTE_UNUSED)
4442 {
4443 /* N1213HC core is used. */
4444 }
4445
4446
4447 /* The target specific pseudo-ops which we support. */
4448 const pseudo_typeS md_pseudo_table[] =
4449 {
4450 /* Forced alignment if declared these ways. */
4451 {"ascii", stringer, 8 + 0},
4452 {"asciz", stringer, 8 + 1},
4453 {"double", nds32_aligned_float_cons, 'd'},
4454 {"dword", nds32_aligned_cons, 3},
4455 {"float", nds32_aligned_float_cons, 'f'},
4456 {"half", nds32_aligned_cons, 1},
4457 {"hword", nds32_aligned_cons, 1},
4458 {"int", nds32_aligned_cons, 2},
4459 {"long", nds32_aligned_cons, 2},
4460 {"octa", nds32_aligned_cons, 4},
4461 {"quad", nds32_aligned_cons, 3},
4462 {"qword", nds32_aligned_cons, 4},
4463 {"short", nds32_aligned_cons, 1},
4464 {"byte", nds32_aligned_cons, 0},
4465 {"single", nds32_aligned_float_cons, 'f'},
4466 {"string", stringer, 8 + 1},
4467 {"word", nds32_aligned_cons, 2},
4468
4469 {"little", set_endian_little, 1},
4470 {"big", set_endian_little, 0},
4471 {"16bit_on", trigger_16bit, 1},
4472 {"16bit_off", trigger_16bit, 0},
4473 {"restore_16bit", restore_16bit, 0},
4474 {"off_16bit", off_16bit, 0},
4475
4476 {"sdata_d", nds32_seg, SDATA_D_SECTION},
4477 {"sdata_w", nds32_seg, SDATA_W_SECTION},
4478 {"sdata_h", nds32_seg, SDATA_H_SECTION},
4479 {"sdata_b", nds32_seg, SDATA_B_SECTION},
4480 {"sdata_f", nds32_seg, SDATA_F_SECTION},
4481
4482 {"sbss_d", nds32_seg, SBSS_D_SECTION},
4483 {"sbss_w", nds32_seg, SBSS_W_SECTION},
4484 {"sbss_h", nds32_seg, SBSS_H_SECTION},
4485 {"sbss_b", nds32_seg, SBSS_B_SECTION},
4486 {"sbss_f", nds32_seg, SBSS_F_SECTION},
4487
4488 {"pic", nds32_enable_pic, 0},
4489 {"n12_hc", nds32_n12hc, 0},
4490 {"abi_1", nds32_set_abi, E_NDS_ABI_V1},
4491 {"abi_2", nds32_set_abi, E_NDS_ABI_AABI},
4492 /* Obsolete. */
4493 {"abi_2fp", nds32_set_abi, E_NDS_ABI_V2FP},
4494 {"abi_2fp_plus", nds32_set_abi, E_NDS_ABI_V2FP_PLUS},
4495 {"relax", nds32_relax_relocs, 1},
4496 {"no_relax", nds32_relax_relocs, 0},
4497 {"hint_func_args", nds32_set_hint_func_args, 0}, /* Abandon?? */
4498 {"omit_fp_begin", nds32_omit_fp_begin, 1},
4499 {"omit_fp_end", nds32_omit_fp_begin, 0},
4500 {"vec_size", nds32_vec_size, 0},
4501 {"flag", nds32_flag, 0},
4502 {"innermost_loop_begin", nds32_loop_begin, 1},
4503 {"innermost_loop_end", nds32_loop_begin, 0},
4504 {"relax_hint", nds32_relax_hint, 0},
4505 {"ict_model", ict_model, 0},
4506 {NULL, NULL, 0}
4507 };
4508
4509 void
4510 nds32_pre_do_align (int n, char *fill, int len, int max)
4511 {
4512 /* Only make a frag if we HAVE to... */
4513 fragS *fragP;
4514 if (n != 0 && !need_pass_2)
4515 {
4516 if (fill == NULL)
4517 {
4518 if (subseg_text_p (now_seg))
4519 {
4520 dwarf2_emit_insn (0);
4521 fragP = frag_now;
4522 add_mapping_symbol_for_align (n, frag_now_fix (), 0);
4523 frag_align_code (n, max);
4524
4525 /* Tag this alignment when there is a label before it. */
4526 if (label_exist)
4527 {
4528 fragP->tc_frag_data.flag = NDS32_FRAG_LABEL;
4529 label_exist = 0;
4530 }
4531 }
4532 else
4533 frag_align (n, 0, max);
4534 }
4535 else if (len <= 1)
4536 frag_align (n, *fill, max);
4537 else
4538 frag_align_pattern (n, fill, len, max);
4539 }
4540 }
4541
4542 void
4543 nds32_do_align (int n)
4544 {
4545 /* Optimize for space and label exists. */
4546 expressionS exp;
4547
4548 /* FIXME:I think this will break debug info sections and except_table. */
4549 if (!enable_relax_relocs || !subseg_text_p (now_seg))
4550 return;
4551
4552 /* Create and attach a BFD_RELOC_NDS32_LABEL fixup
4553 the size of instruction may not be correct because
4554 it could be relaxable. */
4555 exp.X_op = O_symbol;
4556 exp.X_add_symbol = section_symbol (now_seg);
4557 exp.X_add_number = n;
4558 fix_new_exp (frag_now,
4559 frag_now_fix (), 0, &exp, 0, BFD_RELOC_NDS32_LABEL);
4560 }
4561
4562 /* Supported Andes machines. */
4563 struct nds32_machs
4564 {
4565 enum bfd_architecture bfd_mach;
4566 int mach_flags;
4567 };
4568
4569 /* This is the callback for nds32-asm.c to parse operands. */
4570
4571 int
4572 nds32_asm_parse_operand (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED,
4573 struct nds32_asm_insn *pinsn,
4574 char **pstr, int64_t *value)
4575 {
4576 char *hold;
4577 expressionS *pexp = pinsn->info;
4578
4579 hold = input_line_pointer;
4580 input_line_pointer = *pstr;
4581 expression (pexp);
4582 resolve_register (pexp);
4583 *pstr = input_line_pointer;
4584 input_line_pointer = hold;
4585
4586 switch (pexp->X_op)
4587 {
4588 case O_symbol:
4589 *value = 0;
4590 return NASM_R_SYMBOL;
4591 case O_constant:
4592 *value = pexp->X_add_number;
4593 return NASM_R_CONST;
4594 case O_illegal:
4595 case O_absent:
4596 case O_register:
4597 default:
4598 return NASM_R_ILLEGAL;
4599 }
4600 }
4601
4602 /* GAS will call this function at the start of the assembly, after the command
4603 line arguments have been parsed and all the machine independent
4604 initializations have been completed. */
4605
4606 void
4607 md_begin (void)
4608 {
4609 const struct nds32_keyword *k;
4610 relax_info_t *relax_info;
4611 int flags = 0;
4612
4613 bfd_set_arch_mach (stdoutput, TARGET_ARCH, nds32_baseline);
4614
4615 nds32_init_nds32_pseudo_opcodes ();
4616 asm_desc.parse_operand = nds32_asm_parse_operand;
4617 if (nds32_gpr16)
4618 flags |= NASM_OPEN_REDUCED_REG;
4619 nds32_asm_init (&asm_desc, flags);
4620
4621 /* Initial general purpose registers hash table. */
4622 nds32_gprs_hash = str_htab_create ();
4623 for (k = nds32_keyword_gpr; k->name; k++)
4624 str_hash_insert (nds32_gprs_hash, k->name, k, 0);
4625
4626 /* Initial branch hash table. */
4627 nds32_relax_info_hash = str_htab_create ();
4628 for (relax_info = relax_table; relax_info->opcode; relax_info++)
4629 str_hash_insert (nds32_relax_info_hash, relax_info->opcode, relax_info, 0);
4630
4631 /* Initial relax hint hash table. */
4632 nds32_hint_hash = str_htab_create ();
4633 enable_16bit = nds32_16bit_ext;
4634 }
4635
4636 /* HANDLE_ALIGN in write.c. */
4637
4638 void
4639 nds32_handle_align (fragS *fragp)
4640 {
4641 static const unsigned char nop16[] = { 0x92, 0x00 };
4642 static const unsigned char nop32[] = { 0x40, 0x00, 0x00, 0x09 };
4643 int bytes;
4644 char *p;
4645
4646 if (fragp->fr_type != rs_align_code)
4647 return;
4648
4649 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
4650 p = fragp->fr_literal + fragp->fr_fix;
4651
4652 if (bytes & 1)
4653 {
4654 *p++ = 0;
4655 bytes--;
4656 }
4657
4658 if (bytes & 2)
4659 {
4660 expressionS exp_t;
4661 exp_t.X_op = O_symbol;
4662 exp_t.X_add_symbol = abs_section_sym;
4663 exp_t.X_add_number = R_NDS32_INSN16_CONVERT_FLAG;
4664 fix_new_exp (fragp, fragp->fr_fix, 2, &exp_t, 0,
4665 BFD_RELOC_NDS32_INSN16);
4666 memcpy (p, nop16, 2);
4667 p += 2;
4668 bytes -= 2;
4669 }
4670
4671 while (bytes >= 4)
4672 {
4673 memcpy (p, nop32, 4);
4674 p += 4;
4675 bytes -= 4;
4676 }
4677
4678 bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
4679 fragp->fr_fix += bytes;
4680 }
4681
4682 /* md_flush_pending_output */
4683
4684 void
4685 nds32_flush_pending_output (void)
4686 {
4687 nds32_last_label = NULL;
4688 }
4689
4690 void
4691 nds32_frob_label (symbolS *label)
4692 {
4693 dwarf2_emit_label (label);
4694 }
4695
4696 /* TC_START_LABEL */
4697
4698 int
4699 nds32_start_label (int asmdone ATTRIBUTE_UNUSED, int secdone ATTRIBUTE_UNUSED)
4700 {
4701 if (optimize && subseg_text_p (now_seg))
4702 label_exist = 1;
4703 return 1;
4704 }
4705
4706 /* TARGET_FORMAT */
4707
4708 const char *
4709 nds32_target_format (void)
4710 {
4711 #ifdef TE_LINUX
4712 if (target_big_endian)
4713 return "elf32-nds32be-linux";
4714 else
4715 return "elf32-nds32le-linux";
4716 #else
4717 if (target_big_endian)
4718 return "elf32-nds32be";
4719 else
4720 return "elf32-nds32le";
4721 #endif
4722 }
4723
4724 static enum nds32_br_range
4725 get_range_type (const struct nds32_field *field)
4726 {
4727 gas_assert (field != NULL);
4728
4729 if (field->bitpos != 0)
4730 return BR_RANGE_U4G;
4731
4732 if (field->bitsize == 24 && field->shift == 1)
4733 return BR_RANGE_S16M;
4734 else if (field->bitsize == 16 && field->shift == 1)
4735 return BR_RANGE_S64K;
4736 else if (field->bitsize == 14 && field->shift == 1)
4737 return BR_RANGE_S16K;
4738 else if (field->bitsize == 8 && field->shift == 1)
4739 return BR_RANGE_S256;
4740 else
4741 return BR_RANGE_U4G;
4742 }
4743
4744 /* Save pseudo instruction relocation list. */
4745
4746 static struct nds32_relocs_pattern*
4747 nds32_elf_save_pseudo_pattern (fixS* fixP, struct nds32_asm_insn *insn,
4748 char *out, symbolS *sym,
4749 struct nds32_relocs_pattern *reloc_ptr,
4750 fragS *fragP)
4751 {
4752 struct nds32_opcode *opcode = insn->opcode;
4753 if (!reloc_ptr)
4754 reloc_ptr = XNEW (struct nds32_relocs_pattern);
4755 reloc_ptr->seg = now_seg;
4756 reloc_ptr->sym = sym;
4757 reloc_ptr->frag = fragP;
4758 reloc_ptr->frchain = frchain_now;
4759 reloc_ptr->fixP = fixP;
4760 reloc_ptr->opcode = opcode;
4761 reloc_ptr->where = out;
4762 reloc_ptr->insn = insn->insn;
4763 reloc_ptr->next = NULL;
4764 return reloc_ptr;
4765 }
4766
4767 /* Check X_md to transform relocation. */
4768
4769 static fixS*
4770 nds32_elf_record_fixup_exp (fragS *fragP, const char *str,
4771 const struct nds32_field *fld,
4772 expressionS *pexp, char* out,
4773 struct nds32_asm_insn *insn)
4774 {
4775 int reloc = -1;
4776 expressionS exp;
4777 fixS *fixP = NULL;
4778
4779 /* Handle instruction relocation. */
4780 if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_HI20))
4781 {
4782 /* Relocation for hi20 modifier. */
4783 switch (pexp->X_md)
4784 {
4785 case BFD_RELOC_NDS32_GOTOFF: /* @GOTOFF */
4786 reloc = BFD_RELOC_NDS32_GOTOFF_HI20;
4787 break;
4788 case BFD_RELOC_NDS32_GOT20: /* @GOT */
4789 reloc = BFD_RELOC_NDS32_GOT_HI20;
4790 break;
4791 case BFD_RELOC_NDS32_25_PLTREL: /* @PLT */
4792 if (!nds32_pic)
4793 as_bad (_("Invalid PIC expression."));
4794 else
4795 reloc = BFD_RELOC_NDS32_PLT_GOTREL_HI20;
4796 break;
4797 case BFD_RELOC_NDS32_GOTPC20: /* _GLOBAL_OFFSET_TABLE_ */
4798 reloc = BFD_RELOC_NDS32_GOTPC_HI20;
4799 break;
4800 case BFD_RELOC_NDS32_TPOFF: /* @TPOFF */
4801 reloc = BFD_RELOC_NDS32_TLS_LE_HI20;
4802 break;
4803 case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */
4804 reloc = nds32_pic ? BFD_RELOC_NDS32_TLS_IEGP_HI20 : BFD_RELOC_NDS32_TLS_IE_HI20;
4805 break;
4806 case BFD_RELOC_NDS32_TLS_DESC: /* @TLSDESC */
4807 reloc = BFD_RELOC_NDS32_TLS_DESC_HI20;
4808 break;
4809 default: /* No suffix */
4810 if (nds32_pic)
4811 /* When the file is pic, the address must be offset to gp.
4812 It may define another relocation or use GOTOFF. */
4813 reloc = BFD_RELOC_NDS32_PLT_GOTREL_HI20;
4814 else
4815 reloc = BFD_RELOC_NDS32_HI20;
4816 break;
4817 }
4818 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4819 insn->info, 0 /* pcrel */, reloc);
4820 }
4821 else if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_LO12))
4822 {
4823 /* Relocation for lo12 modifier. */
4824 if (fld->bitsize == 15 && fld->shift == 0)
4825 {
4826 /* [ls]bi || ori */
4827 switch (pexp->X_md)
4828 {
4829 case BFD_RELOC_NDS32_GOTOFF: /* @GOTOFF */
4830 reloc = BFD_RELOC_NDS32_GOTOFF_LO12;
4831 break;
4832 case BFD_RELOC_NDS32_GOT20: /* @GOT */
4833 reloc = BFD_RELOC_NDS32_GOT_LO12;
4834 break;
4835 case BFD_RELOC_NDS32_25_PLTREL: /* @PLT */
4836 if (!nds32_pic)
4837 as_bad (_("Invalid PIC expression."));
4838 else
4839 reloc = BFD_RELOC_NDS32_PLT_GOTREL_LO12;
4840 break;
4841 case BFD_RELOC_NDS32_GOTPC20: /* _GLOBAL_OFFSET_TABLE_ */
4842 reloc = BFD_RELOC_NDS32_GOTPC_LO12;
4843 break;
4844 case BFD_RELOC_NDS32_TPOFF: /* @TPOFF */
4845 reloc = BFD_RELOC_NDS32_TLS_LE_LO12;
4846 break;
4847 case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */
4848 reloc = nds32_pic ? BFD_RELOC_NDS32_TLS_IEGP_LO12 : BFD_RELOC_NDS32_TLS_IE_LO12;
4849 break;
4850 case BFD_RELOC_NDS32_TLS_DESC: /* @TLSDESC */
4851 reloc = BFD_RELOC_NDS32_TLS_DESC_LO12;
4852 break;
4853 default: /* No suffix */
4854 if (nds32_pic)
4855 /* When the file is pic, the address must be offset to gp.
4856 It may define another relocation or use GOTOFF. */
4857 reloc = BFD_RELOC_NDS32_PLT_GOTREL_LO12;
4858 else
4859 reloc = BFD_RELOC_NDS32_LO12S0;
4860 break;
4861 }
4862 }
4863 else if (fld->bitsize == 15 && fld->shift == 1)
4864 reloc = BFD_RELOC_NDS32_LO12S1; /* [ls]hi */
4865 else if (fld->bitsize == 15 && fld->shift == 2)
4866 {
4867 /* [ls]wi */
4868 switch (pexp->X_md)
4869 {
4870 case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */
4871 reloc = nds32_pic ? BFD_RELOC_NDS32_TLS_IEGP_LO12S2 : BFD_RELOC_NDS32_TLS_IE_LO12S2;
4872 break;
4873 default: /* No suffix */
4874 reloc = BFD_RELOC_NDS32_LO12S2;
4875 break;
4876 }
4877 }
4878 else if (fld->bitsize == 15 && fld->shift == 3)
4879 reloc = BFD_RELOC_NDS32_LO12S3; /* [ls]di */
4880 else if (fld->bitsize == 12 && fld->shift == 2)
4881 reloc = BFD_RELOC_NDS32_LO12S2_SP; /* f[ls][sd]i */
4882
4883 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4884 insn->info, 0 /* pcrel */, reloc);
4885 }
4886 else if (fld && fld->bitpos == 0 && insn->opcode->isize == 4
4887 && (insn->attr & NASM_ATTR_PCREL))
4888 {
4889 /* Relocation for 32-bit branch instructions. */
4890 if (fld->bitsize == 24 && fld->shift == 1)
4891 reloc = BFD_RELOC_NDS32_25_PCREL;
4892 else if (fld->bitsize == 16 && fld->shift == 1)
4893 reloc = BFD_RELOC_NDS32_17_PCREL;
4894 else if (fld->bitsize == 14 && fld->shift == 1)
4895 reloc = BFD_RELOC_NDS32_15_PCREL;
4896 else if (fld->bitsize == 8 && fld->shift == 1)
4897 reloc = BFD_RELOC_NDS32_WORD_9_PCREL;
4898 else
4899 abort ();
4900
4901 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4902 insn->info, 1 /* pcrel */, reloc);
4903 }
4904 else if (fld && fld->bitpos == 0 && insn->opcode->isize == 4
4905 && (insn->attr & NASM_ATTR_GPREL))
4906 {
4907 /* Relocation for 32-bit gp-relative instructions. */
4908 if (fld->bitsize == 19 && fld->shift == 0)
4909 reloc = BFD_RELOC_NDS32_SDA19S0;
4910 else if (fld->bitsize == 18 && fld->shift == 1)
4911 reloc = BFD_RELOC_NDS32_SDA18S1;
4912 else if (fld->bitsize == 17 && fld->shift == 2)
4913 reloc = BFD_RELOC_NDS32_SDA17S2;
4914 else
4915 abort ();
4916
4917 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4918 insn->info, 0 /* pcrel */, reloc);
4919 /* Insert INSN16 for converting fp_as_gp. */
4920 exp.X_op = O_symbol;
4921 exp.X_add_symbol = abs_section_sym;
4922 exp.X_add_number = 0;
4923 if (in_omit_fp && reloc == BFD_RELOC_NDS32_SDA17S2)
4924 fix_new_exp (fragP, out - fragP->fr_literal,
4925 insn->opcode->isize, &exp, 0 /* pcrel */,
4926 BFD_RELOC_NDS32_INSN16);
4927 }
4928 else if (fld && fld->bitpos == 0 && insn->opcode->isize == 2
4929 && (insn->attr & NASM_ATTR_PCREL))
4930 {
4931 /* Relocation for 16-bit branch instructions. */
4932 if (fld->bitsize == 8 && fld->shift == 1)
4933 reloc = BFD_RELOC_NDS32_9_PCREL;
4934 else
4935 abort ();
4936
4937 fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4938 insn->info, 1 /* pcrel */, reloc);
4939 }
4940 else if (fld)
4941 as_bad (_("Don't know how to handle this field. %s"), str);
4942
4943 return fixP;
4944 }
4945
4946 /* Build instruction pattern to relax. There are two type group pattern
4947 including pseudo instruction and relax hint. */
4948
4949 static void
4950 nds32_elf_build_relax_relation (fixS *fixP, expressionS *pexp, char* out,
4951 struct nds32_asm_insn *insn, fragS *fragP,
4952 const struct nds32_field *fld,
4953 bool pseudo_hint)
4954 {
4955 struct nds32_relocs_pattern *reloc_ptr;
4956 struct nds32_relocs_group *group;
4957 symbolS *sym = NULL;
4958
4959 /* The expression may be used uninitialized. */
4960 if (fld)
4961 sym = pexp->X_add_symbol;
4962
4963 if (pseudo_hint)
4964 {
4965 /* We cannot know how many instructions will be expanded for
4966 the pseudo instruction here. The first expanded instruction fills
4967 the memory created by relax_hint. The follower will created and link
4968 here. */
4969 group = nds32_relax_hint_current;
4970 while (group)
4971 {
4972 if (group->pattern->opcode == NULL)
4973 nds32_elf_save_pseudo_pattern (fixP, insn, out, sym,
4974 group->pattern, fragP);
4975 else
4976 {
4977 group->pattern->next =
4978 nds32_elf_save_pseudo_pattern (fixP, insn, out, sym,
4979 NULL, fragP);
4980 group->pattern = group->pattern->next;
4981 }
4982 group = group->next;
4983 }
4984 }
4985 else if (pseudo_opcode)
4986 {
4987 /* Save instruction relation for pseudo instruction expanding pattern. */
4988 reloc_ptr = nds32_elf_save_pseudo_pattern (fixP, insn, out, sym,
4989 NULL, fragP);
4990 if (!relocs_list)
4991 relocs_list = reloc_ptr;
4992 else
4993 {
4994 struct nds32_relocs_pattern *temp = relocs_list;
4995 while (temp->next)
4996 temp = temp->next;
4997 temp->next = reloc_ptr;
4998 }
4999 }
5000 else if (nds32_relax_hint_current)
5001 {
5002 /* Save instruction relation by relax hint. */
5003 group = nds32_relax_hint_current;
5004 while (group)
5005 {
5006 nds32_elf_save_pseudo_pattern (fixP, insn, out, sym,
5007 group->pattern, fragP);
5008 group = group->next;
5009 free (nds32_relax_hint_current);
5010 nds32_relax_hint_current = group;
5011 }
5012 }
5013
5014 /* Set relaxing false only for relax_hint trigger it. */
5015 if (!pseudo_opcode)
5016 relaxing = false;
5017 }
5018
5019 #define N32_MEM_EXT(insn) ((N32_OP6_MEM << 25) | insn)
5020
5021 /* Relax pattern for link time relaxation. */
5022 /* Relaxation types only! relocation types are not necessary. */
5023 /* Refer to nds32_elf_record_fixup_exp (). */
5024
5025 static struct nds32_relax_hint_table relax_ls_table[] =
5026 {
5027 {
5028 /* LA and Floating LSI. */
5029 .main_type = NDS32_RELAX_HINT_LA_FLSI,
5030 .relax_code_size = 12,
5031 .relax_code_seq =
5032 {
5033 OP6 (SETHI),
5034 OP6 (ORI),
5035 OP6 (LBI),
5036 },
5037 .relax_fixup =
5038 {
5039 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5040 {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
5041 {4, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5042 {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_LSI},
5043 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5044 {8, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5045 {0, 0, 0, 0}
5046 }
5047 },
5048 {
5049 /* Load Address / Load-Store (LALS). */
5050 .main_type = NDS32_RELAX_HINT_LALS,
5051 .relax_code_size = 12,
5052 .relax_code_seq =
5053 {
5054 OP6 (SETHI),
5055 OP6 (ORI),
5056 OP6 (LBI),
5057 },
5058 .relax_fixup =
5059 {
5060 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5061 {4, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5062 {8, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5063 {0, 0, 0, 0}
5064 }
5065 },
5066 {
5067 /* B(AL) symbol@PLT */
5068 .main_type = NDS32_RELAX_HINT_LA_PLT,
5069 .relax_code_size = 16,
5070 .relax_code_seq =
5071 {
5072 OP6 (SETHI),
5073 OP6 (ORI),
5074 OP6 (ALU1),
5075 OP6 (JREG),
5076 },
5077 .relax_fixup =
5078 {
5079 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5080 {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
5081 {8, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
5082 {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PLT_GOT_SUFF},
5083 {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5084 {12, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5085 {0, 0, 0, 0}
5086 }
5087 },
5088 {
5089 /* LA (@GOT). */
5090 .main_type = NDS32_RELAX_HINT_LA_GOT,
5091 .relax_code_size = 12,
5092 .relax_code_seq =
5093 {
5094 OP6 (SETHI),
5095 OP6 (ORI),
5096 OP6 (MEM),
5097 },
5098 .relax_fixup =
5099 {
5100 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5101 {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
5102 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5103 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_GOT_SUFF},
5104 {0, 0, 0, 0}
5105 }
5106 },
5107 {
5108 /* LA (@GOTOFF). */
5109 .main_type = NDS32_RELAX_HINT_LA_GOTOFF,
5110 .relax_code_size = 16,
5111 .relax_code_seq =
5112 {
5113 OP6 (SETHI),
5114 OP6 (ORI),
5115 OP6 (ALU1),
5116 OP6 (MEM),
5117 },
5118 .relax_fixup =
5119 {
5120 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5121 {4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
5122 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5123 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_GOTOFF_SUFF},
5124 {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5125 {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_GOTOFF_SUFF},
5126 {0, 0, 0, 0}
5127 }
5128 },
5129 {
5130 /* TLS LE LS|LA */
5131 .main_type = NDS32_RELAX_HINT_TLS_LE_LS,
5132 .relax_code_size = 16,
5133 .relax_code_seq =
5134 {
5135 OP6(SETHI),
5136 OP6(ORI),
5137 OP6(MEM),
5138 OP6(ALU1),
5139 },
5140 .relax_fixup =
5141 {
5142 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5143 {4, 4, NDS32_HINT | NDS32_PTR_MULTIPLE, BFD_RELOC_NDS32_PTR},
5144 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5145 {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_LE_LS},
5146 {12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5147 {12, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_LE_ADD},
5148 {0, 0, 0, 0}
5149 }
5150 },
5151 {
5152 /* TLS IE LA */
5153 .main_type = NDS32_RELAX_HINT_TLS_IE_LA,
5154 .relax_code_size = 8,
5155 .relax_code_seq =
5156 {
5157 OP6(SETHI),
5158 OP6(LBI),
5159 },
5160 .relax_fixup =
5161 {
5162 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5163 {4, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5164 {0, 0, 0, 0}
5165 }
5166 },
5167 {
5168 /* TLS IEGP LA */
5169 .main_type = NDS32_RELAX_HINT_TLS_IEGP_LA,
5170 .relax_code_size = 12,
5171 .relax_code_seq =
5172 {
5173 OP6 (SETHI),
5174 OP6 (ORI),
5175 OP6 (MEM),
5176 },
5177 .relax_fixup =
5178 {
5179 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5180 {4, 4, NDS32_HINT | NDS32_PTR_PATTERN, BFD_RELOC_NDS32_PTR},
5181 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5182 {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_IEGP_LW},
5183 {0, 0, 0, 0}
5184 }
5185 },
5186 {
5187 /* TLS DESC LS: */
5188 .main_type = NDS32_RELAX_HINT_TLS_DESC_LS,
5189 .relax_code_size = 24,
5190 .relax_code_seq =
5191 {
5192 OP6 (SETHI),
5193 OP6 (ORI),
5194 OP6 (ALU1),
5195 OP6 (LBI), /* load argument */
5196 OP6 (JREG),
5197 OP6 (MEM), /* load/store variable or load argument */
5198 },
5199 .relax_fixup =
5200 {
5201 {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5202 {4, 4, NDS32_HINT | NDS32_PTR_PATTERN, BFD_RELOC_NDS32_PTR},
5203 {8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5204 {8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_DESC_ADD},
5205 {12, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_DESC_FUNC},
5206 {16, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_DESC_CALL},
5207 {20, 4, NDS32_HINT | NDS32_SYM_DESC_MEM, BFD_RELOC_NDS32_TLS_DESC_MEM},
5208 {0, 0, 0, 0}
5209 }
5210 },
5211 {
5212 .main_type = 0,
5213 .relax_code_seq = {0},
5214 .relax_fixup = {{0, 0 , 0, 0}}
5215 }
5216 };
5217
5218 /* Since sethi loadstore relocation has to using next instruction to determine
5219 elimination itself or not, we have to return the next instruction range. */
5220
5221 static int
5222 nds32_elf_sethi_range (struct nds32_relocs_pattern *pattern)
5223 {
5224 int range = 0;
5225 while (pattern)
5226 {
5227 switch (pattern->opcode->value)
5228 {
5229 case INSN_LBI:
5230 case INSN_SBI:
5231 case INSN_LBSI:
5232 case N32_MEM_EXT (N32_MEM_LB):
5233 case N32_MEM_EXT (N32_MEM_LBS):
5234 case N32_MEM_EXT (N32_MEM_SB):
5235 range = NDS32_LOADSTORE_BYTE;
5236 break;
5237 case INSN_LHI:
5238 case INSN_SHI:
5239 case INSN_LHSI:
5240 case N32_MEM_EXT (N32_MEM_LH):
5241 case N32_MEM_EXT (N32_MEM_LHS):
5242 case N32_MEM_EXT (N32_MEM_SH):
5243 range = NDS32_LOADSTORE_HALF;
5244 break;
5245 case INSN_LWI:
5246 case INSN_SWI:
5247 case N32_MEM_EXT (N32_MEM_LW):
5248 case N32_MEM_EXT (N32_MEM_SW):
5249 range = NDS32_LOADSTORE_WORD;
5250 break;
5251 case INSN_FLSI:
5252 case INSN_FSSI:
5253 range = NDS32_LOADSTORE_FLOAT_S;
5254 break;
5255 case INSN_FLDI:
5256 case INSN_FSDI:
5257 range = NDS32_LOADSTORE_FLOAT_D;
5258 break;
5259 case INSN_ORI:
5260 range = NDS32_LOADSTORE_IMM;
5261 break;
5262 default:
5263 range = NDS32_LOADSTORE_NONE;
5264 break;
5265 }
5266 if (range != NDS32_LOADSTORE_NONE)
5267 break;
5268 pattern = pattern->next;
5269 }
5270 return range;
5271 }
5272
5273 /* The args means: instruction size, the 1st instruction is converted to 16 or
5274 not, optimize option, 16 bit instruction is enable. */
5275
5276 #define SET_ADDEND(size, convertible, optimize, insn16_on) \
5277 (((size) & 0xff) | ((convertible) ? 1u << 31 : 0) \
5278 | ((optimize) ? 1 << 30 : 0) | (insn16_on ? 1 << 29 : 0))
5279 #define MAC_COMBO (E_NDS32_HAS_FPU_MAC_INST|E_NDS32_HAS_MAC_DX_INST)
5280
5281 static void
5282 nds32_set_elf_flags_by_insn (struct nds32_asm_insn * insn)
5283 {
5284 static int skip_flags = NASM_ATTR_FPU_FMA
5285 | NASM_ATTR_BRANCH | NASM_ATTR_SATURATION_EXT
5286 | NASM_ATTR_GPREL | NASM_ATTR_DXREG
5287 | NASM_ATTR_ISA_V1 | NASM_ATTR_ISA_V2
5288 | NASM_ATTR_ISA_V3 | NASM_ATTR_ISA_V3M
5289 | NASM_ATTR_PCREL;
5290
5291 int new_flags = insn->opcode->attr & ~skip_flags;
5292 while (new_flags)
5293 {
5294 int next = 1 << (ffs (new_flags) - 1);
5295 new_flags &= ~next;
5296 switch (next)
5297 {
5298 case NASM_ATTR_PERF_EXT:
5299 {
5300 if (nds32_perf_ext)
5301 {
5302 nds32_elf_flags |= E_NDS32_HAS_EXT_INST;
5303 skip_flags |= NASM_ATTR_PERF_EXT;
5304 }
5305 else
5306 as_bad (_("instruction %s requires enabling performance "
5307 "extension"), insn->opcode->opcode);
5308 }
5309 break;
5310 case NASM_ATTR_PERF2_EXT:
5311 {
5312 if (nds32_perf_ext2)
5313 {
5314 nds32_elf_flags |= E_NDS32_HAS_EXT2_INST;
5315 skip_flags |= NASM_ATTR_PERF2_EXT;
5316 }
5317 else
5318 as_bad (_("instruction %s requires enabling performance "
5319 "extension II"), insn->opcode->opcode);
5320 }
5321 break;
5322 case NASM_ATTR_AUDIO_ISAEXT:
5323 {
5324 if (nds32_audio_ext)
5325 {
5326 nds32_elf_flags |= E_NDS32_HAS_AUDIO_INST;
5327 skip_flags |= NASM_ATTR_AUDIO_ISAEXT;
5328 }
5329 else
5330 as_bad (_("instruction %s requires enabling AUDIO extension"),
5331 insn->opcode->opcode);
5332 }
5333 break;
5334 case NASM_ATTR_STR_EXT:
5335 {
5336 if (nds32_string_ext)
5337 {
5338 nds32_elf_flags |= E_NDS32_HAS_STRING_INST;
5339 skip_flags |= NASM_ATTR_STR_EXT;
5340 }
5341 else
5342 as_bad (_("instruction %s requires enabling STRING extension"),
5343 insn->opcode->opcode);
5344 }
5345 break;
5346 case NASM_ATTR_DIV:
5347 {
5348 if (insn->opcode->attr & NASM_ATTR_DXREG)
5349 {
5350 if (nds32_div && nds32_dx_regs)
5351 {
5352 nds32_elf_flags |= E_NDS32_HAS_DIV_DX_INST;
5353 skip_flags |= NASM_ATTR_DIV;
5354 }
5355 else
5356 as_bad (_("instruction %s requires enabling DIV & DX_REGS "
5357 "extension"), insn->opcode->opcode);
5358 }
5359 }
5360 break;
5361 case NASM_ATTR_FPU:
5362 {
5363 if (nds32_fpu_sp_ext || nds32_fpu_dp_ext)
5364 {
5365 if (!(nds32_elf_flags
5366 & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST)))
5367 nds32_fpu_com = 1;
5368 skip_flags |= NASM_ATTR_FPU;
5369 }
5370 else
5371 as_bad (_("instruction %s requires enabling FPU extension"),
5372 insn->opcode->opcode);
5373 }
5374 break;
5375 case NASM_ATTR_FPU_SP_EXT:
5376 {
5377 if (nds32_fpu_sp_ext)
5378 {
5379 nds32_elf_flags |= E_NDS32_HAS_FPU_INST;
5380 skip_flags |= NASM_ATTR_FPU_SP_EXT;
5381 }
5382 else
5383 as_bad (_("instruction %s requires enabling FPU_SP extension"),
5384 insn->opcode->opcode);
5385 }
5386 break;
5387 case NASM_ATTR_FPU_DP_EXT:
5388 {
5389 if (nds32_fpu_dp_ext)
5390 {
5391 nds32_elf_flags |= E_NDS32_HAS_FPU_DP_INST;
5392 skip_flags |= NASM_ATTR_FPU_DP_EXT;
5393 }
5394 else
5395 as_bad (_("instruction %s requires enabling FPU_DP extension"),
5396 insn->opcode->opcode);
5397 }
5398 break;
5399 case NASM_ATTR_MAC:
5400 {
5401 if (insn->opcode->attr & NASM_ATTR_FPU_SP_EXT)
5402 {
5403 if (nds32_fpu_sp_ext && nds32_mac)
5404 nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST;
5405 else
5406 as_bad (_("instruction %s requires enabling FPU_MAC "
5407 "extension"), insn->opcode->opcode);
5408 }
5409 else if (insn->opcode->attr & NASM_ATTR_FPU_DP_EXT)
5410 {
5411 if (nds32_fpu_dp_ext && nds32_mac)
5412 nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST;
5413 else
5414 as_bad (_("instruction %s requires enabling FPU_MAC "
5415 "extension"), insn->opcode->opcode);
5416 }
5417 else if (insn->opcode->attr & NASM_ATTR_DXREG)
5418 {
5419 if (nds32_dx_regs && nds32_mac)
5420 nds32_elf_flags |= E_NDS32_HAS_MAC_DX_INST;
5421 else
5422 as_bad (_("instruction %s requires enabling DX_REGS "
5423 "extension"), insn->opcode->opcode);
5424 }
5425
5426 if (MAC_COMBO == (MAC_COMBO & nds32_elf_flags))
5427 skip_flags |= NASM_ATTR_MAC;
5428 }
5429 break;
5430 case NASM_ATTR_DSP_ISAEXT:
5431 {
5432 if (nds32_dsp_ext)
5433 {
5434 nds32_elf_flags |= E_NDS32_HAS_DSP_INST;
5435 skip_flags |= NASM_ATTR_DSP_ISAEXT;
5436 }
5437 else
5438 as_bad (_("instruction %s requires enabling dsp extension"),
5439 insn->opcode->opcode);
5440 }
5441 break;
5442 case NASM_ATTR_ZOL:
5443 {
5444 if (nds32_zol_ext)
5445 {
5446 nds32_elf_flags |= E_NDS32_HAS_ZOL;
5447 skip_flags |= NASM_ATTR_ZOL;
5448 }
5449 else
5450 as_bad (_("instruction %s requires enabling zol extension"),
5451 insn->opcode->opcode);
5452 }
5453 break;
5454 default:
5455 as_bad (_("internal error: unknown instruction attribute: 0x%08x"),
5456 next);
5457 }
5458 }
5459 }
5460
5461 /* Flag for analysis relaxation type. */
5462
5463 enum nds32_insn_type
5464 {
5465 N32_RELAX_SETHI = 1,
5466 N32_RELAX_BR = (1 << 1),
5467 N32_RELAX_LSI = (1 << 2),
5468 N32_RELAX_JUMP = (1 << 3),
5469 N32_RELAX_CALL = (1 << 4),
5470 N32_RELAX_ORI = (1 << 5),
5471 N32_RELAX_MEM = (1 << 6),
5472 N32_RELAX_MOVI = (1 << 7),
5473 N32_RELAX_ALU1 = (1 << 8),
5474 N32_RELAX_16BIT = (1 << 9),
5475 };
5476
5477 struct nds32_hint_map
5478 {
5479 /* the preamble relocation */
5480 bfd_reloc_code_real_type hi_type;
5481 /* mnemonic */
5482 const char *opc;
5483 /* relax pattern ID */
5484 enum nds32_relax_hint_type hint_type;
5485 /* range */
5486 enum nds32_br_range range;
5487 /* pattern character flags */
5488 enum nds32_insn_type insn_list;
5489 /* optional pattern character flags */
5490 enum nds32_insn_type option_list;
5491 };
5492
5493 /* Table to match instructions with hint and relax pattern. */
5494
5495 static struct nds32_hint_map hint_map [] =
5496 {
5497 {
5498 /* LONGCALL4. */
5499 BFD_RELOC_NDS32_HI20,
5500 "jal",
5501 NDS32_RELAX_HINT_NONE,
5502 BR_RANGE_U4G,
5503 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL,
5504 0,
5505 },
5506 {
5507 /* LONGCALL5. */
5508 _dummy_first_bfd_reloc_code_real,
5509 "bgezal",
5510 NDS32_RELAX_HINT_NONE,
5511 BR_RANGE_S16M,
5512 N32_RELAX_BR | N32_RELAX_CALL,
5513 0,
5514 },
5515 {
5516 /* LONGCALL6. */
5517 BFD_RELOC_NDS32_HI20,
5518 "bgezal",
5519 NDS32_RELAX_HINT_NONE,
5520 BR_RANGE_U4G,
5521 N32_RELAX_BR | N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL,
5522 0,
5523 },
5524 {
5525 /* LONGJUMP4. */
5526 BFD_RELOC_NDS32_HI20,
5527 "j",
5528 NDS32_RELAX_HINT_NONE,
5529 BR_RANGE_U4G,
5530 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_JUMP,
5531 0,
5532 },
5533 {
5534 /* LONGJUMP5. */
5535 /* There is two kinds of variation of LONGJUMP5. One of them
5536 generate EMPTY relocation for converted INSN16 if needed.
5537 But we don't distinguish them here. */
5538 _dummy_first_bfd_reloc_code_real,
5539 "beq",
5540 NDS32_RELAX_HINT_NONE,
5541 BR_RANGE_S16M,
5542 N32_RELAX_BR | N32_RELAX_JUMP,
5543 0,
5544 },
5545 {
5546 /* LONGJUMP6. */
5547 BFD_RELOC_NDS32_HI20,
5548 "beq",
5549 NDS32_RELAX_HINT_NONE,
5550 BR_RANGE_U4G,
5551 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_BR | N32_RELAX_JUMP,
5552 0,
5553 },
5554 {
5555 /* LONGJUMP7. */
5556 _dummy_first_bfd_reloc_code_real,
5557 "beqc",
5558 NDS32_RELAX_HINT_NONE,
5559 BR_RANGE_S16K,
5560 N32_RELAX_MOVI | N32_RELAX_BR,
5561 0,
5562 },
5563 {
5564 /* LONGCALL (BAL|JR|LA symbol@PLT). */
5565 BFD_RELOC_NDS32_PLT_GOTREL_HI20,
5566 NULL,
5567 NDS32_RELAX_HINT_LA_PLT,
5568 BR_RANGE_U4G,
5569 N32_RELAX_SETHI | N32_RELAX_ORI,
5570 N32_RELAX_ALU1 | N32_RELAX_CALL | N32_RELAX_JUMP,
5571 },
5572 /* relative issue: #12566 */
5573 {
5574 /* LA and Floating LSI. */
5575 BFD_RELOC_NDS32_HI20,
5576 NULL,
5577 NDS32_RELAX_HINT_LA_FLSI,
5578 BR_RANGE_U4G,
5579 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_LSI,
5580 0,
5581 },
5582 /* relative issue: #11685 #11602 */
5583 {
5584 /* load address / load-store (LALS). */
5585 BFD_RELOC_NDS32_HI20,
5586 NULL,
5587 NDS32_RELAX_HINT_LALS,
5588 BR_RANGE_U4G,
5589 N32_RELAX_SETHI,
5590 N32_RELAX_ORI | N32_RELAX_LSI,
5591 },
5592 {
5593 /* setup $GP (_GLOBAL_OFFSET_TABLE_) */
5594 BFD_RELOC_NDS32_GOTPC_HI20,
5595 NULL,
5596 NDS32_RELAX_HINT_LALS,
5597 BR_RANGE_U4G,
5598 N32_RELAX_SETHI | N32_RELAX_ORI,
5599 0,
5600 },
5601 {
5602 /* GOT LA/LS (symbol@GOT) */
5603 BFD_RELOC_NDS32_GOT_HI20,
5604 NULL,
5605 NDS32_RELAX_HINT_LA_GOT,
5606 BR_RANGE_U4G,
5607 N32_RELAX_SETHI | N32_RELAX_ORI,
5608 N32_RELAX_MEM,
5609 },
5610 {
5611 /* GOTOFF LA/LS (symbol@GOTOFF) */
5612 BFD_RELOC_NDS32_GOTOFF_HI20,
5613 NULL,
5614 NDS32_RELAX_HINT_LA_GOTOFF,
5615 BR_RANGE_U4G,
5616 N32_RELAX_SETHI | N32_RELAX_ORI,
5617 N32_RELAX_ALU1 | N32_RELAX_MEM, /* | N32_RELAX_LSI, */
5618 },
5619 {
5620 /* TLS LE LA|LS (@TPOFF) */
5621 BFD_RELOC_NDS32_TLS_LE_HI20,
5622 NULL,
5623 NDS32_RELAX_HINT_TLS_LE_LS,
5624 BR_RANGE_U4G,
5625 N32_RELAX_SETHI | N32_RELAX_ORI,
5626 N32_RELAX_ALU1 | N32_RELAX_MEM,
5627 },
5628 {
5629 /* TLS IE LA */
5630 BFD_RELOC_NDS32_TLS_IE_HI20,
5631 NULL,
5632 NDS32_RELAX_HINT_TLS_IE_LA,
5633 BR_RANGE_U4G,
5634 N32_RELAX_SETHI | N32_RELAX_LSI,
5635 0,
5636 },
5637 {
5638 /* TLS IE LS */
5639 BFD_RELOC_NDS32_TLS_IE_HI20,
5640 NULL,
5641 NDS32_RELAX_HINT_TLS_IE_LS,
5642 BR_RANGE_U4G,
5643 N32_RELAX_SETHI | N32_RELAX_LSI | N32_RELAX_MEM,
5644 0,
5645 },
5646 {
5647 /* TLS IEGP LA */
5648 BFD_RELOC_NDS32_TLS_IEGP_HI20,
5649 NULL,
5650 NDS32_RELAX_HINT_TLS_IEGP_LA,
5651 BR_RANGE_U4G,
5652 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_MEM,
5653 0,
5654 },
5655 {
5656 /* TLS DESC LS */
5657 BFD_RELOC_NDS32_TLS_DESC_HI20,
5658 NULL,
5659 NDS32_RELAX_HINT_TLS_DESC_LS,
5660 BR_RANGE_U4G,
5661 N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_ALU1 | N32_RELAX_CALL,
5662 N32_RELAX_LSI | N32_RELAX_MEM,
5663 },
5664 /* last one */
5665 {0, NULL, 0, 0 ,0, 0}
5666 };
5667
5668 /* Find the relaxation pattern according to instructions. */
5669
5670 static bool
5671 nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern,
5672 struct nds32_relax_hint_table *hint_info)
5673 {
5674 unsigned int opcode, seq_size;
5675 enum nds32_br_range range;
5676 struct nds32_relocs_pattern *pattern, *hi_pattern = NULL;
5677 const char *opc = NULL;
5678 relax_info_t *relax_info = NULL;
5679 nds32_relax_fixup_info_t *fixup_info, *hint_fixup;
5680 enum nds32_relax_hint_type hint_type = NDS32_RELAX_HINT_NONE;
5681 struct nds32_relax_hint_table *table_ptr;
5682 uint32_t *code_seq, *hint_code;
5683 enum nds32_insn_type relax_type = 0;
5684 struct nds32_hint_map *map_ptr = hint_map;
5685 unsigned int i;
5686 const char *check_insn[] =
5687 { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8" };
5688
5689 /* TODO: PLT GOT. */
5690 /* Traverse all pattern instruction and set flag. */
5691 pattern = relocs_pattern;
5692 while (pattern)
5693 {
5694 if (pattern->opcode->isize == 4)
5695 {
5696 /* 4 byte instruction. */
5697 opcode = N32_OP6 (pattern->opcode->value);
5698 switch (opcode)
5699 {
5700 case N32_OP6_SETHI:
5701 hi_pattern = pattern;
5702 relax_type |= N32_RELAX_SETHI;
5703 break;
5704 case N32_OP6_MEM:
5705 relax_type |= N32_RELAX_MEM;
5706 break;
5707 case N32_OP6_ALU1:
5708 relax_type |= N32_RELAX_ALU1;
5709 break;
5710 case N32_OP6_ORI:
5711 relax_type |= N32_RELAX_ORI;
5712 break;
5713 case N32_OP6_BR1:
5714 case N32_OP6_BR2:
5715 case N32_OP6_BR3:
5716 relax_type |= N32_RELAX_BR;
5717 break;
5718 case N32_OP6_MOVI:
5719 relax_type |= N32_RELAX_MOVI;
5720 break;
5721 case N32_OP6_LBI:
5722 case N32_OP6_SBI:
5723 case N32_OP6_LBSI:
5724 case N32_OP6_LHI:
5725 case N32_OP6_SHI:
5726 case N32_OP6_LHSI:
5727 case N32_OP6_LWI:
5728 case N32_OP6_SWI:
5729 case N32_OP6_LWC:
5730 case N32_OP6_SWC:
5731 case N32_OP6_LDC:
5732 case N32_OP6_SDC:
5733 relax_type |= N32_RELAX_LSI;
5734 break;
5735 case N32_OP6_JREG:
5736 if (__GF (pattern->opcode->value, 0, 1) == 1)
5737 relax_type |= N32_RELAX_CALL;
5738 else
5739 relax_type |= N32_RELAX_JUMP;
5740 break;
5741 case N32_OP6_JI:
5742 if (__GF (pattern->opcode->value, 24, 1) == 1)
5743 relax_type |= N32_RELAX_CALL;
5744 else
5745 relax_type |= N32_RELAX_JUMP;
5746 break;
5747 default:
5748 as_warn (_("relax hint unrecognized instruction: line %d."),
5749 pattern->frag->fr_line);
5750 return false;
5751 }
5752 }
5753 else
5754 {
5755 /* 2 byte instruction. Compare by opcode name because
5756 the opcode of 2byte instruction is not regular. */
5757 int is_matched = 0;
5758 for (i = 0; i < ARRAY_SIZE (check_insn); i++)
5759 {
5760 if (strcmp (pattern->opcode->opcode, check_insn[i]) == 0)
5761 {
5762 relax_type |= N32_RELAX_BR;
5763 is_matched += 1;
5764 break;
5765 }
5766 }
5767 if (!is_matched)
5768 relax_type |= N32_RELAX_16BIT;
5769 }
5770 pattern = pattern->next;
5771 }
5772
5773 /* Analysis instruction flag to choose relaxation table. */
5774 while (map_ptr->insn_list != 0)
5775 {
5776 struct nds32_hint_map *hint = map_ptr++;
5777 enum nds32_insn_type must = hint->insn_list;
5778 enum nds32_insn_type optional = hint->option_list;
5779 enum nds32_insn_type extra;
5780
5781 if (must != (must & relax_type))
5782 continue;
5783
5784 extra = relax_type ^ must;
5785 if (extra != (extra & optional))
5786 continue;
5787
5788 if (!hi_pattern
5789 || (hi_pattern->fixP
5790 && hi_pattern->fixP->fx_r_type == hint->hi_type))
5791 {
5792 opc = hint->opc;
5793 hint_type = hint->hint_type;
5794 range = hint->range;
5795 map_ptr = hint;
5796 break;
5797 }
5798 }
5799
5800 if (map_ptr->insn_list == 0)
5801 {
5802 if (!nds32_pic)
5803 as_warn (_("Can not find match relax hint. Line: %d"),
5804 relocs_pattern->frag->fr_line);
5805 return false;
5806 }
5807
5808 /* Get the match table. */
5809 if (opc)
5810 {
5811 /* Branch relax pattern. */
5812 relax_info = str_hash_find (nds32_relax_info_hash, opc);
5813 if (!relax_info)
5814 return false;
5815 fixup_info = relax_info->relax_fixup[range];
5816 code_seq = relax_info->relax_code_seq[range];
5817 seq_size = relax_info->relax_code_size[range];
5818 }
5819 else if (hint_type)
5820 {
5821 /* Load-store relax pattern. */
5822 table_ptr = relax_ls_table;
5823 while (table_ptr->main_type != 0)
5824 {
5825 if (table_ptr->main_type == hint_type)
5826 {
5827 fixup_info = table_ptr->relax_fixup;
5828 code_seq = table_ptr->relax_code_seq;
5829 seq_size = table_ptr->relax_code_size;
5830 break;
5831 }
5832 table_ptr++;
5833 }
5834 if (table_ptr->main_type == 0)
5835 return false;
5836 }
5837 else
5838 return false;
5839
5840 hint_fixup = hint_info->relax_fixup;
5841 hint_code = hint_info->relax_code_seq;
5842 hint_info->relax_code_size = seq_size;
5843
5844 while (fixup_info->size != 0)
5845 {
5846 if (fixup_info->ramp & NDS32_HINT)
5847 {
5848 memcpy (hint_fixup, fixup_info, sizeof (nds32_relax_fixup_info_t));
5849 hint_fixup++;
5850 }
5851 fixup_info++;
5852 }
5853 /* Clear final relocation. */
5854 memset (hint_fixup, 0, sizeof (nds32_relax_fixup_info_t));
5855 /* Copy code sequence. */
5856 memcpy (hint_code, code_seq, seq_size);
5857 return true;
5858 }
5859
5860 /* Because there are a lot of variant of load-store, check
5861 all these type here. */
5862
5863 #define CLEAN_REG(insn) ((insn) & 0xfe0003ff)
5864 #define GET_OPCODE(insn) ((insn) & 0xfe000000)
5865
5866 static bool
5867 nds32_match_hint_insn (struct nds32_opcode *opcode, uint32_t seq)
5868 {
5869 const char *check_insn[] =
5870 { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8", "jral5" };
5871 uint32_t insn = opcode->value;
5872 unsigned int i;
5873
5874 insn = CLEAN_REG (opcode->value);
5875 if (insn == seq)
5876 return true;
5877
5878 switch (seq)
5879 {
5880 case OP6 (LBI):
5881 /* In relocation_table, it regards instruction LBI as representation
5882 of all the NDS32_RELAX_HINT_LS pattern. */
5883 if (insn == OP6 (LBI) || insn == OP6 (SBI) || insn == OP6 (LBSI)
5884 || insn == OP6 (LHI) || insn == OP6 (SHI) || insn == OP6 (LHSI)
5885 || insn == OP6 (LWI) || insn == OP6 (SWI)
5886 || insn == OP6 (LWC) || insn == OP6 (SWC)
5887 || insn == OP6 (LDC) || insn == OP6 (SDC))
5888 return true;
5889 break;
5890 case OP6 (BR2):
5891 /* This is for LONGCALL5 and LONGCALL6. */
5892 if (insn == OP6 (BR2))
5893 return true;
5894 break;
5895 case OP6 (BR1):
5896 /* This is for LONGJUMP5 and LONGJUMP6. */
5897 if (opcode->isize == 4
5898 && (insn == OP6 (BR1) || insn == OP6 (BR2) || insn == OP6 (BR3)))
5899 return true;
5900 else if (opcode->isize == 2)
5901 {
5902 for (i = 0; i < ARRAY_SIZE (check_insn); i++)
5903 if (strcmp (opcode->opcode, check_insn[i]) == 0)
5904 return true;
5905 }
5906 break;
5907 case OP6 (MOVI):
5908 /* This is for LONGJUMP7. */
5909 if (opcode->isize == 2 && strcmp (opcode->opcode, "movi55") == 0)
5910 return true;
5911 break;
5912 case OP6 (MEM):
5913 if (OP6 (MEM) == GET_OPCODE (insn))
5914 return true;
5915 break;
5916 case OP6 (JREG):
5917 /* bit 24: N32_JI_JAL */ /* feed me! */
5918 if ((insn & ~(N32_BIT (24))) == JREG (JRAL))
5919 return true;
5920 break;
5921 default:
5922 if (opcode->isize == 2)
5923 {
5924 for (i = 0; i < ARRAY_SIZE (check_insn); i++)
5925 if (strcmp (opcode->opcode, check_insn[i]) == 0)
5926 return true;
5927
5928 if ((strcmp (opcode->opcode, "add5.pc") == 0) ||
5929 (strcmp (opcode->opcode, "add45") == 0))
5930 return true;
5931 }
5932 }
5933 return false;
5934 }
5935
5936 /* Append relax relocation for link time relaxing. */
5937
5938 static void
5939 nds32_elf_append_relax_relocs (const char *key, const void *value)
5940 {
5941 struct nds32_relocs_pattern *relocs_pattern =
5942 (struct nds32_relocs_pattern *) value;
5943 struct nds32_relocs_pattern *pattern_temp, *pattern_now;
5944 symbolS *sym, *hi_sym = NULL;
5945 expressionS exp;
5946 fragS *fragP;
5947 segT seg_bak = now_seg;
5948 frchainS *frchain_bak = frchain_now;
5949 struct nds32_relax_hint_table hint_info;
5950 nds32_relax_fixup_info_t *hint_fixup, *fixup_now;
5951 size_t fixup_size;
5952 offsetT branch_offset, hi_branch_offset = 0;
5953 fixS *fixP;
5954 int range, offset;
5955 unsigned int ptr_offset, hint_count, relax_code_size, count = 0;
5956 uint32_t *code_seq, code_insn;
5957 char *where;
5958 int pcrel;
5959
5960 if (!relocs_pattern)
5961 return;
5962
5963 if (!nds32_find_reloc_table (relocs_pattern, &hint_info))
5964 return;
5965
5966 /* Save symbol for some EMPTY relocation using. */
5967 pattern_now = relocs_pattern;
5968 while (pattern_now)
5969 {
5970 if (pattern_now->opcode->value == OP6 (SETHI))
5971 {
5972 hi_sym = pattern_now->sym;
5973 hi_branch_offset = pattern_now->fixP->fx_offset;
5974 break;
5975 }
5976 pattern_now = pattern_now->next;
5977 }
5978
5979 /* Inserting fix up must specify now_seg or frchain_now. */
5980 now_seg = relocs_pattern->seg;
5981 frchain_now = relocs_pattern->frchain;
5982 fragP = relocs_pattern->frag;
5983 branch_offset = fragP->fr_offset;
5984
5985 hint_fixup = hint_info.relax_fixup;
5986 code_seq = hint_info.relax_code_seq;
5987 relax_code_size = hint_info.relax_code_size;
5988 pattern_now = relocs_pattern;
5989
5990 #ifdef NDS32_LINUX_TOOLCHAIN
5991 /* prepare group relocation ID (number). */
5992 long group_id = 0;
5993 if (key)
5994 {
5995 /* convert .relax_hint key to number */
5996 errno = 0;
5997 group_id = strtol (key, NULL, 10);
5998 if ((errno == ERANGE && (group_id == LONG_MAX || group_id == LONG_MIN))
5999 || (errno != 0 && group_id == 0))
6000 {
6001 as_bad (_("Internal error: .relax_hint KEY is not a number!"));
6002 goto restore;
6003 }
6004 }
6005 #endif
6006
6007 /* Insert relaxation. */
6008 exp.X_op = O_symbol;
6009
6010 /* For each instruction in the hint group. */
6011 while (pattern_now)
6012 {
6013 if (count >= relax_code_size / 4)
6014 count = 0;
6015
6016 /* Choose the match fixup by instruction. */
6017 code_insn = CLEAN_REG (*(code_seq + count));
6018 if (!nds32_match_hint_insn (pattern_now->opcode, code_insn))
6019 {
6020 /* Try search from head again */
6021 count = 0;
6022 code_insn = CLEAN_REG (*(code_seq + count));
6023
6024 while (!nds32_match_hint_insn (pattern_now->opcode, code_insn))
6025 {
6026 count++;
6027 if (count >= relax_code_size / 4)
6028 {
6029 as_bad (_("Internal error: Relax hint (%s) error. %s: %s (%x)"),
6030 key,
6031 now_seg->name,
6032 pattern_now->opcode->opcode,
6033 pattern_now->opcode->value);
6034 goto restore;
6035 }
6036 code_insn = CLEAN_REG (*(code_seq + count));
6037 }
6038 }
6039 fragP = pattern_now->frag;
6040 sym = pattern_now->sym;
6041 branch_offset = fragP->fr_offset;
6042 offset = count * 4;
6043 where = pattern_now->where;
6044 /* Find the instruction map fix. */
6045 fixup_now = hint_fixup;
6046 while (fixup_now->offset != offset)
6047 {
6048 fixup_now++;
6049 if (fixup_now->size == 0)
6050 break;
6051 }
6052 /* This element is without relaxation relocation. */
6053 if (fixup_now->size == 0)
6054 {
6055 pattern_now = pattern_now->next;
6056 continue;
6057 }
6058 fixup_size = fixup_now->size;
6059
6060 /* Insert all fixup. */
6061 pcrel = 0;
6062 while (fixup_size != 0 && fixup_now->offset == offset)
6063 {
6064 /* Set the real instruction size in element. */
6065 fixup_size = pattern_now->opcode->isize;
6066 pcrel = ((fixup_now->ramp & NDS32_PCREL) != 0) ? 1 : 0;
6067 if (fixup_now->ramp & NDS32_FIX)
6068 {
6069 /* Convert original relocation. */
6070 pattern_now->fixP->fx_r_type = fixup_now->r_type ;
6071 fixup_size = 0;
6072 }
6073 else if ((fixup_now->ramp & NDS32_PTR) != 0)
6074 {
6075 /* This relocation has to point to another instruction. Make
6076 sure each resolved relocation has to be pointed. */
6077 pattern_temp = relocs_pattern;
6078 /* All instruction in relax_table should be 32-bit. */
6079 hint_count = hint_info.relax_code_size / 4;
6080 code_insn = CLEAN_REG (*(code_seq + hint_count - 1));
6081 while (pattern_temp)
6082 {
6083 /* Point to every resolved relocation. */
6084 if (nds32_match_hint_insn (pattern_temp->opcode, code_insn))
6085 {
6086 ptr_offset =
6087 pattern_temp->where - pattern_temp->frag->fr_literal;
6088 exp.X_add_symbol = symbol_temp_new (now_seg,
6089 pattern_temp->frag,
6090 ptr_offset);
6091 exp.X_add_number = 0;
6092 fixP =
6093 fix_new_exp (fragP, where - fragP->fr_literal,
6094 fixup_size, &exp, 0, fixup_now->r_type);
6095 fixP->fx_addnumber = fixP->fx_offset;
6096 }
6097 pattern_temp = pattern_temp->next;
6098 }
6099 fixup_size = 0;
6100 }
6101 else if (fixup_now->ramp & NDS32_ADDEND)
6102 {
6103 range = nds32_elf_sethi_range (relocs_pattern);
6104 if (range == NDS32_LOADSTORE_NONE)
6105 {
6106 as_bad (_("Internal error: Range error. %s"), now_seg->name);
6107 return;
6108 }
6109 exp.X_add_symbol = abs_section_sym;
6110 exp.X_add_number = SET_ADDEND (4, 0, optimize, enable_16bit);
6111 exp.X_add_number |= ((range & 0x3f) << 8);
6112 }
6113 else if ((fixup_now->ramp & NDS32_ABS) != 0)
6114 {
6115 /* This is a tag relocation. */
6116 exp.X_add_symbol = abs_section_sym;
6117 exp.X_add_number = 0;
6118 }
6119 else if ((fixup_now->ramp & NDS32_INSN16) != 0)
6120 {
6121 if (!enable_16bit)
6122 fixup_size = 0;
6123 /* This is a tag relocation. */
6124 exp.X_add_symbol = abs_section_sym;
6125 exp.X_add_number = 0;
6126 }
6127 else if ((fixup_now->ramp & NDS32_SYM) != 0)
6128 {
6129 /* For EMPTY relocation save the true symbol. */
6130 exp.X_add_symbol = hi_sym;
6131 exp.X_add_number = hi_branch_offset;
6132 }
6133 else if (NDS32_SYM_DESC_MEM & fixup_now->ramp)
6134 {
6135 /* Do the same as NDS32_SYM. */
6136 exp.X_add_symbol = hi_sym;
6137 exp.X_add_number = hi_branch_offset;
6138
6139 /* Extra to NDS32_SYM. */
6140 /* Detect if DESC_FUNC relax type do apply. */
6141 if ((REG_GP == N32_RA5 (pattern_now->insn))
6142 || (REG_GP == N32_RB5 (pattern_now->insn)))
6143 {
6144 fixP = fix_new_exp (fragP, where - fragP->fr_literal,
6145 fixup_size, &exp, pcrel,
6146 BFD_RELOC_NDS32_TLS_DESC_FUNC);
6147 fixP->fx_addnumber = fixP->fx_offset;
6148
6149 fixup_size = 0;
6150 }
6151 /* Else do as usual. */
6152 }
6153 else if (fixup_now->ramp & NDS32_PTR_PATTERN)
6154 {
6155 /* Find out PTR_RESOLVED code pattern. */
6156 nds32_relax_fixup_info_t *next_fixup = fixup_now + 1;
6157 uint32_t resolved_pattern = 0;
6158 while (next_fixup->offset)
6159 {
6160 if (next_fixup->r_type == BFD_RELOC_NDS32_PTR_RESOLVED)
6161 {
6162 uint32_t new_pattern = code_seq[next_fixup->offset >> 2];
6163 if (!resolved_pattern)
6164 resolved_pattern = new_pattern;
6165 else if (new_pattern != resolved_pattern)
6166 {
6167 as_warn (_("Multiple BFD_RELOC_NDS32_PTR_RESOLVED "
6168 "patterns are not supported yet!"));
6169 break;
6170 }
6171 }
6172 ++next_fixup;
6173 }
6174
6175 /* Find matched code and insert fix-ups. */
6176 struct nds32_relocs_pattern *next_pattern = pattern_now->next;
6177 /* This relocation has to point to another instruction.
6178 Make sure each resolved relocation has to be pointed. */
6179 /* All instruction in relax_table should be 32-bit. */
6180 while (next_pattern)
6181 {
6182 uint32_t cur_pattern = GET_OPCODE (next_pattern->opcode->value);
6183 if (cur_pattern == resolved_pattern)
6184 {
6185 ptr_offset = next_pattern->where
6186 - next_pattern->frag->fr_literal;
6187 exp.X_add_symbol = symbol_temp_new (now_seg,
6188 next_pattern->frag,
6189 ptr_offset);
6190 exp.X_add_number = 0;
6191 fixP = fix_new_exp (fragP, where - fragP->fr_literal,
6192 fixup_size, &exp, 0,
6193 fixup_now->r_type);
6194 fixP->fx_addnumber = fixP->fx_offset;
6195 }
6196 next_pattern = next_pattern->next;
6197 }
6198
6199 fixup_size = 0;
6200 }
6201 else if (fixup_now->ramp & NDS32_PTR_MULTIPLE)
6202 {
6203 /* Find each PTR_RESOLVED pattern after PTR. */
6204 nds32_relax_fixup_info_t *next_fixup = fixup_now + 1;
6205 while (next_fixup->offset)
6206 {
6207 if (next_fixup->r_type == BFD_RELOC_NDS32_PTR_RESOLVED)
6208 {
6209 uint32_t pattern = code_seq[next_fixup->offset >> 2];
6210 /* Find matched code to insert fix-ups. */
6211 struct nds32_relocs_pattern *next_insn = pattern_now->next;
6212 while (next_insn)
6213 {
6214 uint32_t insn_pattern = GET_OPCODE (next_insn->opcode->value);
6215 if (insn_pattern == pattern)
6216 {
6217 ptr_offset = next_insn->where
6218 - next_insn->frag->fr_literal;
6219 exp.X_add_symbol = symbol_temp_new (now_seg,
6220 next_insn->frag,
6221 ptr_offset);
6222 exp.X_add_number = 0;
6223 fixP = fix_new_exp (fragP,
6224 where - fragP->fr_literal,
6225 fixup_size, &exp, 0,
6226 fixup_now->r_type);
6227 fixP->fx_addnumber = fixP->fx_offset;
6228 }
6229 next_insn = next_insn->next;
6230 }
6231 }
6232 ++next_fixup;
6233 }
6234 fixup_size = 0;
6235 }
6236 else
6237 {
6238 exp.X_add_symbol = sym;
6239 exp.X_add_number = branch_offset;
6240 }
6241
6242 if (fixup_size != 0)
6243 {
6244 fixP = fix_new_exp (fragP, where - fragP->fr_literal, fixup_size,
6245 &exp, pcrel, fixup_now->r_type);
6246 fixP->fx_addnumber = fixP->fx_offset;
6247 }
6248 fixup_now++;
6249 fixup_size = fixup_now->size;
6250 }
6251
6252 #ifdef NDS32_LINUX_TOOLCHAIN
6253 /* Insert group relocation for each relax hint. */
6254 if (key)
6255 {
6256 exp.X_add_symbol = hi_sym; /* for eyes only */
6257 exp.X_add_number = group_id;
6258 fixP = fix_new_exp (fragP, where - fragP->fr_literal, fixup_size,
6259 &exp, pcrel, BFD_RELOC_NDS32_GROUP);
6260 fixP->fx_addnumber = fixP->fx_offset;
6261 }
6262 #endif
6263
6264 if (count < relax_code_size / 4)
6265 count++;
6266 pattern_now = pattern_now->next;
6267 }
6268
6269 restore:
6270 now_seg = seg_bak;
6271 frchain_now = frchain_bak;
6272 }
6273
6274 static int
6275 nds32_elf_append_relax_relocs_traverse (void **slot, void *arg ATTRIBUTE_UNUSED)
6276 {
6277 string_tuple_t *tuple = *((string_tuple_t **) slot);
6278 nds32_elf_append_relax_relocs (tuple->key, tuple->value);
6279 return 1;
6280 }
6281
6282
6283 static void
6284 nds32_str_tolower (const char *src, char *dest)
6285 {
6286 unsigned int i, len;
6287
6288 len = strlen (src);
6289
6290 for (i = 0; i < len; i++)
6291 *(dest + i) = TOLOWER (*(src + i));
6292
6293 *(dest + i) = '\0';
6294 }
6295
6296 /* Check instruction if it can be used for the baseline. */
6297
6298 static bool
6299 nds32_check_insn_available (struct nds32_asm_insn insn, const char *str)
6300 {
6301 int attr = insn.attr & ATTR_ALL;
6302 static int baseline_isa = 0;
6303 char *s;
6304
6305 s = xmalloc (strlen (str) + 1);
6306 nds32_str_tolower (str, s);
6307 if (verbatim
6308 && (((insn.opcode->value == ALU2 (MTUSR)
6309 || insn.opcode->value == ALU2 (MFUSR))
6310 && (strstr (s, "lc")
6311 || strstr (s, "le")
6312 || strstr (s, "lb")))
6313 || (insn.attr & NASM_ATTR_ZOL)))
6314 {
6315 as_bad (_("Not support instruction %s in verbatim."), str);
6316 return false;
6317 }
6318 free (s);
6319
6320 if (!enable_16bit && insn.opcode->isize == 2)
6321 {
6322 as_bad (_("16-bit instruction is disabled: %s."), str);
6323 return false;
6324 }
6325
6326 /* No isa setting or all isa can use. */
6327 if (attr == 0 || attr == ATTR_ALL)
6328 return true;
6329
6330 if (baseline_isa == 0)
6331 {
6332 /* Map option baseline and instruction attribute. */
6333 switch (nds32_baseline)
6334 {
6335 case ISA_V2:
6336 baseline_isa = ATTR (ISA_V2);
6337 break;
6338 case ISA_V3:
6339 baseline_isa = ATTR (ISA_V3);
6340 break;
6341 case ISA_V3M:
6342 baseline_isa = ATTR (ISA_V3M);
6343 break;
6344 }
6345 }
6346
6347 if ((baseline_isa & attr) == 0)
6348 {
6349 as_bad (_("Instruction %s not supported in the baseline."), str);
6350 return false;
6351 }
6352 return true;
6353 }
6354
6355 /* Stub of machine dependent. */
6356
6357 void
6358 md_assemble (char *str)
6359 {
6360 struct nds32_asm_insn insn;
6361 char *out;
6362 struct nds32_pseudo_opcode *popcode;
6363 const struct nds32_field *fld = NULL;
6364 fixS *fixP;
6365 uint16_t insn_16;
6366 struct nds32_relocs_pattern *relocs_temp;
6367 struct nds32_relocs_group *group_temp;
6368 fragS *fragP;
6369 int label = label_exist;
6370 static bool pseudo_hint = false;
6371
6372 popcode = nds32_lookup_pseudo_opcode (str);
6373 /* Note that we need to check 'verbatim' and
6374 'opcode->physical_op'. If the assembly content is generated by
6375 compiler and this opcode is a physical instruction, there is no
6376 need to perform pseudo instruction expansion/transformation. */
6377 if (popcode && !(verbatim && popcode->physical_op))
6378 {
6379 /* Pseudo instruction is with relax_hint. */
6380 if (relaxing)
6381 pseudo_hint = true;
6382 pseudo_opcode = true;
6383 nds32_pseudo_opcode_wrapper (str, popcode);
6384 pseudo_opcode = false;
6385 pseudo_hint = false;
6386 nds32_elf_append_relax_relocs (NULL, relocs_list);
6387
6388 /* Free relax_hint group list. */
6389 while (nds32_relax_hint_current)
6390 {
6391 group_temp = nds32_relax_hint_current->next;
6392 free (nds32_relax_hint_current);
6393 nds32_relax_hint_current = group_temp;
6394 }
6395
6396 /* Free pseudo list. */
6397 relocs_temp = relocs_list;
6398 while (relocs_temp)
6399 {
6400 relocs_list = relocs_list->next;
6401 free (relocs_temp);
6402 relocs_temp = relocs_list;
6403 }
6404
6405 return;
6406 }
6407
6408 label_exist = 0;
6409 insn.info = XNEW (expressionS);
6410 asm_desc.result = NASM_OK;
6411 nds32_assemble (&asm_desc, &insn, str);
6412
6413 switch (asm_desc.result)
6414 {
6415 case NASM_ERR_UNKNOWN_OP:
6416 as_bad (_("Unrecognized opcode, %s."), str);
6417 return;
6418 case NASM_ERR_SYNTAX:
6419 as_bad (_("Incorrect syntax, %s."), str);
6420 return;
6421 case NASM_ERR_OPERAND:
6422 as_bad (_("Unrecognized operand/register, %s."), str);
6423 return;
6424 case NASM_ERR_OUT_OF_RANGE:
6425 as_bad (_("Operand out of range, %s."), str);
6426 return;
6427 case NASM_ERR_REG_REDUCED:
6428 as_bad (_("Prohibited register used for reduced-register, %s."), str);
6429 return;
6430 case NASM_ERR_JUNK_EOL:
6431 as_bad (_("Junk at end of line, %s."), str);
6432 return;
6433 }
6434
6435 gas_assert (insn.opcode);
6436
6437 nds32_set_elf_flags_by_insn (&insn);
6438
6439 gas_assert (insn.opcode->isize == 4 || insn.opcode->isize == 2);
6440
6441 if (!nds32_check_insn_available (insn, str))
6442 return;
6443
6444 /* Make sure the beginning of text being 2-byte align. */
6445 nds32_adjust_label (1);
6446 add_mapping_symbol (MAP_CODE, 0, 0);
6447 fld = insn.field;
6448 /* Try to allocate the max size to guarantee relaxable same branch
6449 instructions in the same fragment. */
6450 frag_grow (NDS32_MAXCHAR);
6451 fragP = frag_now;
6452
6453 if (fld && (insn.attr & NASM_ATTR_BRANCH)
6454 && (pseudo_opcode || (insn.opcode->value != INSN_JAL
6455 && insn.opcode->value != INSN_J))
6456 && (!verbatim || pseudo_opcode))
6457 {
6458 /* User assembly code branch relax for it. */
6459 /* If fld is not NULL, it is a symbol. */
6460 /* Branch must relax to proper pattern in user assembly code exclude
6461 J and JAL. Keep these two in original type for users which wants
6462 to keep their size be fixed. In general, assembler does not convert
6463 instruction generated by compiler. But jump instruction may be
6464 truncated in text virtual model. For workaround, compiler generate
6465 pseudo jump to fix this issue currently. */
6466
6467 /* Get branch range type. */
6468 dwarf2_emit_insn (0);
6469 enum nds32_br_range range_type;
6470 expressionS *pexp = insn.info;
6471
6472 range_type = get_range_type (fld);
6473
6474 out = frag_var (rs_machine_dependent, NDS32_MAXCHAR,
6475 0, /* VAR is un-used. */
6476 range_type, /* SUBTYPE is used as range type. */
6477 pexp->X_add_symbol, pexp->X_add_number, 0);
6478
6479 fragP->fr_fix += insn.opcode->isize;
6480 fragP->tc_frag_data.opcode = insn.opcode;
6481 fragP->tc_frag_data.insn = insn.insn;
6482 if (insn.opcode->isize == 4)
6483 bfd_putb32 (insn.insn, out);
6484 else if (insn.opcode->isize == 2)
6485 bfd_putb16 (insn.insn, out);
6486 fragP->tc_frag_data.flag |= NDS32_FRAG_BRANCH;
6487
6488 free (insn.info);
6489 return;
6490 /* md_convert_frag will insert relocations. */
6491 }
6492 else if (!relaxing && enable_16bit && (optimize || optimize_for_space)
6493 && ((!fld && !verbatim && insn.opcode->isize == 4
6494 && nds32_convert_32_to_16 (stdoutput, insn.insn, &insn_16, NULL))
6495 || (insn.opcode->isize == 2
6496 && nds32_convert_16_to_32 (stdoutput, insn.insn, NULL))))
6497 {
6498 /* Record this one is relaxable. */
6499 expressionS *pexp = insn.info;
6500 dwarf2_emit_insn (0);
6501 if (fld)
6502 {
6503 out = frag_var (rs_machine_dependent,
6504 4, /* Max size is 32-bit instruction. */
6505 0, /* VAR is un-used. */
6506 0, pexp->X_add_symbol, pexp->X_add_number, 0);
6507 fragP->tc_frag_data.flag |= NDS32_FRAG_RELAXABLE_BRANCH;
6508 }
6509 else
6510 out = frag_var (rs_machine_dependent,
6511 4, /* Max size is 32-bit instruction. */
6512 0, /* VAR is un-used. */
6513 0, NULL, 0, NULL);
6514 fragP->tc_frag_data.flag |= NDS32_FRAG_RELAXABLE;
6515 fragP->tc_frag_data.opcode = insn.opcode;
6516 fragP->tc_frag_data.insn = insn.insn;
6517 fragP->fr_fix += 2;
6518
6519 /* In original, we don't relax the instruction with label on it,
6520 but this may cause some redundant nop16. Therefore, tag this
6521 relaxable instruction and relax it carefully. */
6522 if (label)
6523 fragP->tc_frag_data.flag |= NDS32_FRAG_LABEL;
6524
6525 if (insn.opcode->isize == 4)
6526 bfd_putb16 (insn_16, out);
6527 else if (insn.opcode->isize == 2)
6528 bfd_putb16 (insn.insn, out);
6529
6530 free (insn.info);
6531 return;
6532 }
6533 else if ((verbatim || !relaxing) && optimize && label)
6534 {
6535 /* This instruction is with label. */
6536 expressionS exp;
6537 out = frag_var (rs_machine_dependent, insn.opcode->isize,
6538 0, 0, NULL, 0, NULL);
6539 /* If this instruction is branch target, it is not relaxable. */
6540 fragP->tc_frag_data.flag = NDS32_FRAG_LABEL;
6541 fragP->tc_frag_data.opcode = insn.opcode;
6542 fragP->tc_frag_data.insn = insn.insn;
6543 fragP->fr_fix += insn.opcode->isize;
6544 if (insn.opcode->isize == 4)
6545 {
6546 exp.X_op = O_symbol;
6547 exp.X_add_symbol = abs_section_sym;
6548 exp.X_add_number = 0;
6549 fixP = fix_new_exp (fragP, fragP->fr_fix - 4, 0, &exp,
6550 0, BFD_RELOC_NDS32_LABEL);
6551 if (!verbatim)
6552 fragP->tc_frag_data.flag = NDS32_FRAG_ALIGN;
6553 }
6554 }
6555 else
6556 out = frag_more (insn.opcode->isize);
6557
6558 if (insn.opcode->isize == 4)
6559 bfd_putb32 (insn.insn, out);
6560 else if (insn.opcode->isize == 2)
6561 bfd_putb16 (insn.insn, out);
6562
6563 dwarf2_emit_insn (insn.opcode->isize);
6564
6565 /* Compiler generating code and user assembly pseudo load-store, insert
6566 fixup here. */
6567 expressionS *pexp = insn.info;
6568 fixP = nds32_elf_record_fixup_exp (fragP, str, fld, pexp, out, &insn);
6569 /* Build relaxation pattern when relaxing is enable. */
6570 if (relaxing)
6571 nds32_elf_build_relax_relation (fixP, pexp, out, &insn, fragP, fld,
6572 pseudo_hint);
6573
6574 free (insn.info);
6575 }
6576
6577 /* md_macro_start */
6578
6579 void
6580 nds32_macro_start (void)
6581 {
6582 }
6583
6584 /* md_macro_info */
6585
6586 void
6587 nds32_macro_info (void *info ATTRIBUTE_UNUSED)
6588 {
6589 }
6590
6591 /* md_macro_end */
6592
6593 void
6594 nds32_macro_end (void)
6595 {
6596 }
6597
6598 /* GAS will call this function with one argument, an expressionS pointer, for
6599 any expression that can not be recognized. When the function is called,
6600 input_line_pointer will point to the start of the expression. */
6601
6602 void
6603 md_operand (expressionS *expressionP)
6604 {
6605 if (*input_line_pointer == '#')
6606 {
6607 input_line_pointer++;
6608 expression (expressionP);
6609 }
6610 }
6611
6612 /* GAS will call this function for each section at the end of the assembly, to
6613 permit the CPU back end to adjust the alignment of a section. The function
6614 must take two arguments, a segT for the section and a valueT for the size of
6615 the section, and return a valueT for the rounded size. */
6616
6617 valueT
6618 md_section_align (segT segment, valueT size)
6619 {
6620 int align = bfd_section_alignment (segment);
6621
6622 return ((size + (1 << align) - 1) & ((valueT) -1 << align));
6623 }
6624
6625 /* GAS will call this function when a symbol table lookup fails, before it
6626 creates a new symbol. Typically this would be used to supply symbols whose
6627 name or value changes dynamically, possibly in a context sensitive way.
6628 Predefined symbols with fixed values, such as register names or condition
6629 codes, are typically entered directly into the symbol table when md_begin
6630 is called. One argument is passed, a char * for the symbol. */
6631
6632 symbolS *
6633 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
6634 {
6635 return NULL;
6636 }
6637
6638 static long
6639 nds32_calc_branch_offset (segT segment, fragS *fragP,
6640 long stretch ATTRIBUTE_UNUSED,
6641 relax_info_t *relax_info,
6642 enum nds32_br_range branch_range_type)
6643 {
6644 struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
6645 symbolS *branch_symbol = fragP->fr_symbol;
6646 offsetT branch_offset = fragP->fr_offset;
6647 offsetT branch_target_address;
6648 offsetT branch_insn_address;
6649 long offset = 0;
6650
6651 if ((S_GET_SEGMENT (branch_symbol) != segment)
6652 || S_IS_WEAK (branch_symbol))
6653 {
6654 /* The symbol is not in the SEGMENT. It could be far far away. */
6655 offset = 0x80000000;
6656 }
6657 else
6658 {
6659 /* Calculate symbol-to-instruction offset. */
6660 branch_target_address = S_GET_VALUE (branch_symbol) + branch_offset;
6661 /* If the destination symbol is beyond current frag address,
6662 STRETCH will take effect to symbol's position. */
6663 if (S_GET_VALUE (branch_symbol) > fragP->fr_address)
6664 branch_target_address += stretch;
6665
6666 branch_insn_address = fragP->fr_address + fragP->fr_fix;
6667 branch_insn_address -= opcode->isize;
6668
6669 /* Update BRANCH_INSN_ADDRESS to relaxed position. */
6670 branch_insn_address += (relax_info->relax_code_size[branch_range_type]
6671 - relax_info->relax_branch_isize[branch_range_type]);
6672
6673 offset = branch_target_address - branch_insn_address;
6674 }
6675
6676 return offset;
6677 }
6678
6679 static enum nds32_br_range
6680 nds32_convert_to_range_type (long offset)
6681 {
6682 enum nds32_br_range range_type;
6683
6684 if (-(0x100) <= offset && offset < 0x100) /* 256 bytes */
6685 range_type = BR_RANGE_S256;
6686 else if (-(0x4000) <= offset && offset < 0x4000) /* 16K bytes */
6687 range_type = BR_RANGE_S16K;
6688 else if (-(0x10000) <= offset && offset < 0x10000) /* 64K bytes */
6689 range_type = BR_RANGE_S64K;
6690 else if (-(0x1000000) <= offset && offset < 0x1000000) /* 16M bytes */
6691 range_type = BR_RANGE_S16M;
6692 else /* 4G bytes */
6693 range_type = BR_RANGE_U4G;
6694
6695 return range_type;
6696 }
6697
6698 /* Set instruction register mask. */
6699
6700 static void
6701 nds32_elf_get_set_cond (relax_info_t *relax_info, int offset, uint32_t *insn,
6702 uint32_t ori_insn, int range)
6703 {
6704 nds32_cond_field_t *cond_fields = relax_info->cond_field;
6705 nds32_cond_field_t *code_seq_cond = relax_info->relax_code_condition[range];
6706 uint32_t mask;
6707 int i = 0;
6708
6709 /* The instruction has conditions. Collect condition values. */
6710 while (code_seq_cond[i].bitmask != 0)
6711 {
6712 if (offset == code_seq_cond[i].offset)
6713 {
6714 mask = (ori_insn >> cond_fields[i].bitpos) & cond_fields[i].bitmask;
6715 /* Sign extend. */
6716 if (cond_fields[i].signed_extend)
6717 mask = (mask ^ ((cond_fields[i].bitmask + 1) >> 1)) -
6718 ((cond_fields[i].bitmask + 1) >> 1);
6719 *insn |= (mask & code_seq_cond[i].bitmask) << code_seq_cond[i].bitpos;
6720 }
6721 i++;
6722 }
6723 }
6724
6725 static int
6726 nds32_relax_branch_instructions (segT segment, fragS *fragP,
6727 long stretch ATTRIBUTE_UNUSED,
6728 int init)
6729 {
6730 enum nds32_br_range branch_range_type;
6731 struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
6732 long offset = 0;
6733 enum nds32_br_range real_range_type;
6734 int adjust = 0;
6735 relax_info_t *relax_info;
6736 int diff = 0;
6737 int i, j, k;
6738 int code_seq_size;
6739 uint32_t *code_seq;
6740 uint32_t insn;
6741 int insn_size;
6742 int code_seq_offset;
6743
6744 /* Replace with gas_assert (fragP->fr_symbol != NULL); */
6745 if (fragP->fr_symbol == NULL)
6746 return adjust;
6747
6748 /* If frag_var is not enough room, the previous frag is fr_full and with
6749 opcode. The new one is rs_dependent but without opcode. */
6750 if (opcode == NULL)
6751 return adjust;
6752
6753 /* Use U4G mode for b and bal in verbatim mode because lto may combine
6754 functions into a file. And order the file in the last when linking.
6755 Once there is multiple definition, the same function will be kicked.
6756 This may cause relocation truncated error. */
6757 if (verbatim && !nds32_pic
6758 && (strcmp (opcode->opcode, "j") == 0
6759 || strcmp (opcode->opcode, "jal") == 0))
6760 {
6761 fragP->fr_subtype = BR_RANGE_U4G;
6762 if (init)
6763 return 8;
6764 else
6765 return 0;
6766 }
6767
6768 relax_info = str_hash_find (nds32_relax_info_hash, opcode->opcode);
6769
6770 if (relax_info == NULL)
6771 return adjust;
6772
6773 if (init)
6774 {
6775 branch_range_type = relax_info->br_range;
6776 i = BR_RANGE_S256;
6777 }
6778 else
6779 {
6780 branch_range_type = fragP->fr_subtype;
6781 i = branch_range_type;
6782 }
6783
6784 offset = nds32_calc_branch_offset (segment, fragP, stretch,
6785 relax_info, branch_range_type);
6786
6787 real_range_type = nds32_convert_to_range_type (offset);
6788
6789 /* If actual range is equal to instruction jump range, do nothing. */
6790 if (real_range_type == branch_range_type)
6791 {
6792 fragP->fr_subtype = real_range_type;
6793 return adjust;
6794 }
6795
6796 /* Find out proper relaxation code sequence. */
6797 for (; i < BR_RANGE_NUM; i++)
6798 {
6799 if (real_range_type <= (unsigned int) i)
6800 {
6801 if (init)
6802 diff = relax_info->relax_code_size[i] - opcode->isize;
6803 else if (real_range_type < (unsigned int) i)
6804 diff = relax_info->relax_code_size[real_range_type]
6805 - relax_info->relax_code_size[branch_range_type];
6806 else
6807 diff = relax_info->relax_code_size[i]
6808 - relax_info->relax_code_size[branch_range_type];
6809
6810 /* If the instruction could be converted to 16-bits,
6811 minus the difference. */
6812 code_seq_offset = 0;
6813 j = 0;
6814 k = 0;
6815 code_seq_size = relax_info->relax_code_size[i];
6816 code_seq = relax_info->relax_code_seq[i];
6817 while (code_seq_offset < code_seq_size)
6818 {
6819 insn = code_seq[j];
6820 if (insn & 0x80000000) /* 16-bits instruction. */
6821 {
6822 insn_size = 2;
6823 }
6824 else /* 32-bits instruction. */
6825 {
6826 insn_size = 4;
6827
6828 while (relax_info->relax_fixup[i][k].size !=0
6829 && relax_info->relax_fixup[i][k].offset < code_seq_offset)
6830 k++;
6831 }
6832
6833 code_seq_offset += insn_size;
6834 j++;
6835 }
6836
6837 /* Update fr_subtype to new NDS32_BR_RANGE. */
6838 fragP->fr_subtype = real_range_type;
6839 break;
6840 }
6841 }
6842
6843 return diff + adjust;
6844 }
6845
6846 /* Adjust relaxable frag till current frag. */
6847
6848 static int
6849 nds32_adjust_relaxable_frag (fragS *startP, fragS *fragP)
6850 {
6851 int adj;
6852 if (startP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
6853 adj = -2;
6854 else
6855 adj = 2;
6856
6857 startP->tc_frag_data.flag ^= NDS32_FRAG_RELAXED;
6858
6859 while (startP)
6860 {
6861 startP = startP->fr_next;
6862 if (startP)
6863 {
6864 startP->fr_address += adj;
6865 if (startP == fragP)
6866 break;
6867 }
6868 }
6869 return adj;
6870 }
6871
6872 static addressT
6873 nds32_get_align (addressT address, int align)
6874 {
6875 addressT mask, new_address;
6876
6877 mask = ~((addressT) (~0) << align);
6878 new_address = (address + mask) & (~mask);
6879 return (new_address - address);
6880 }
6881
6882 /* Check the prev_frag is legal. */
6883 static void
6884 invalid_prev_frag (fragS * fragP, fragS **prev_frag, bool relax)
6885 {
6886 addressT address;
6887 fragS *frag_start = *prev_frag;
6888
6889 if (!frag_start || !relax)
6890 return;
6891
6892 if (frag_start->last_fr_address >= fragP->last_fr_address)
6893 {
6894 *prev_frag = NULL;
6895 return;
6896 }
6897
6898 fragS *frag_t = *prev_frag;
6899 while (frag_t != fragP)
6900 {
6901 if (frag_t->fr_type == rs_align
6902 || frag_t->fr_type == rs_align_code
6903 || frag_t->fr_type == rs_align_test)
6904 {
6905 /* Relax instruction can not walk across label. */
6906 if (frag_t->tc_frag_data.flag & NDS32_FRAG_LABEL)
6907 {
6908 prev_frag = NULL;
6909 return;
6910 }
6911 /* Relax previous relaxable to align rs_align frag. */
6912 address = frag_t->fr_address + frag_t->fr_fix;
6913 addressT offset = nds32_get_align (address, (int) frag_t->fr_offset);
6914 if (offset & 0x2)
6915 {
6916 /* If there is label on the prev_frag, check if it is aligned. */
6917 if (!((*prev_frag)->tc_frag_data.flag & NDS32_FRAG_LABEL)
6918 || (((*prev_frag)->fr_address + (*prev_frag)->fr_fix - 2 )
6919 & 0x2) == 0)
6920 nds32_adjust_relaxable_frag (*prev_frag, frag_t);
6921 }
6922 *prev_frag = NULL;
6923 return;
6924 }
6925 frag_t = frag_t->fr_next;
6926 }
6927
6928 if (fragP->tc_frag_data.flag & NDS32_FRAG_ALIGN)
6929 {
6930 address = fragP->fr_address;
6931 addressT offset = nds32_get_align (address, 2);
6932 if (offset & 0x2)
6933 {
6934 /* If there is label on the prev_frag, check if it is aligned. */
6935 if (!((*prev_frag)->tc_frag_data.flag & NDS32_FRAG_LABEL)
6936 || (((*prev_frag)->fr_address + (*prev_frag)->fr_fix - 2 )
6937 & 0x2) == 0)
6938 nds32_adjust_relaxable_frag (*prev_frag, fragP);
6939 }
6940 *prev_frag = NULL;
6941 return;
6942 }
6943 }
6944
6945 /* md_relax_frag */
6946
6947 int
6948 nds32_relax_frag (segT segment, fragS *fragP, long stretch ATTRIBUTE_UNUSED)
6949 {
6950 /* Currently, there are two kinds of relaxation in nds32 assembler.
6951 1. relax for branch
6952 2. relax for 32-bits to 16-bits */
6953
6954 static fragS *prev_frag = NULL;
6955 int adjust = 0;
6956
6957 invalid_prev_frag (fragP, &prev_frag, true);
6958
6959 if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
6960 adjust = nds32_relax_branch_instructions (segment, fragP, stretch, 0);
6961 if (fragP->tc_frag_data.flag & NDS32_FRAG_LABEL)
6962 prev_frag = NULL;
6963 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE
6964 && (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED) == 0)
6965 /* Here is considered relaxed case originally. But it may cause
6966 an endless loop when relaxing. Once the instruction is relaxed,
6967 it can not be undone. */
6968 prev_frag = fragP;
6969
6970 return adjust;
6971 }
6972
6973 /* This function returns an initial guess of the length by which a fragment
6974 must grow to hold a branch to reach its destination. Also updates
6975 fr_type/fr_subtype as necessary.
6976
6977 It is called just before doing relaxation. Any symbol that is now undefined
6978 will not become defined. The guess for fr_var is ACTUALLY the growth beyond
6979 fr_fix. Whatever we do to grow fr_fix or fr_var contributes to our returned
6980 value. Although it may not be explicit in the frag, pretend fr_var starts
6981 with a 0 value. */
6982
6983 int
6984 md_estimate_size_before_relax (fragS *fragP, segT segment)
6985 {
6986 /* Currently, there are two kinds of relaxation in nds32 assembler.
6987 1. relax for branch
6988 2. relax for 32-bits to 16-bits */
6989
6990 /* Save previous relaxable frag. */
6991 static fragS *prev_frag = NULL;
6992 int adjust = 0;
6993
6994 invalid_prev_frag (fragP, &prev_frag, false);
6995
6996 if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
6997 adjust = nds32_relax_branch_instructions (segment, fragP, 0, 1);
6998 if (fragP->tc_frag_data.flag & NDS32_FRAG_LABEL)
6999 prev_frag = NULL;
7000 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
7001 adjust = 2;
7002 else if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE)
7003 prev_frag = fragP;
7004
7005 return adjust;
7006 }
7007
7008 /* GAS will call this for each rs_machine_dependent fragment. The instruction
7009 is completed using the data from the relaxation pass. It may also create any
7010 necessary relocations.
7011
7012 *FRAGP has been relaxed to its final size, and now needs to have the bytes
7013 inside it modified to conform to the new size. It is called after relaxation
7014 is finished.
7015
7016 fragP->fr_type == rs_machine_dependent.
7017 fragP->fr_subtype is the subtype of what the address relaxed to. */
7018
7019 void
7020 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP)
7021 {
7022 /* Convert branch relaxation instructions. */
7023 symbolS *branch_symbol = fragP->fr_symbol;
7024 offsetT branch_offset = fragP->fr_offset;
7025 enum nds32_br_range branch_range_type = fragP->fr_subtype;
7026 struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
7027 uint32_t origin_insn = fragP->tc_frag_data.insn;
7028 relax_info_t *relax_info;
7029 char *fr_buffer;
7030 int fr_where;
7031 int addend ATTRIBUTE_UNUSED;
7032 offsetT branch_target_address, branch_insn_address;
7033 expressionS exp;
7034 fixS *fixP;
7035 uint32_t *code_seq;
7036 uint32_t insn;
7037 int code_size, insn_size, offset, fixup_size;
7038 int buf_offset, pcrel;
7039 int i, k;
7040 uint16_t insn_16;
7041 nds32_relax_fixup_info_t fixup_info[MAX_RELAX_FIX];
7042 /* Save the 1st instruction is converted to 16 bit or not. */
7043 unsigned int branch_size;
7044 enum bfd_reloc_code_real final_r_type;
7045
7046 /* Replace with gas_assert (branch_symbol != NULL); */
7047 if (branch_symbol == NULL && !(fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED))
7048 return;
7049
7050 /* If frag_var is not enough room, the previous frag is fr_full and with
7051 opcode. The new one is rs_dependent but without opcode. */
7052 if (opcode == NULL)
7053 return;
7054
7055 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE_BRANCH)
7056 {
7057 relax_info = str_hash_find (nds32_relax_info_hash, opcode->opcode);
7058
7059 if (relax_info == NULL)
7060 return;
7061
7062 i = BR_RANGE_S256;
7063 while (i < BR_RANGE_NUM
7064 && relax_info->relax_code_size[i]
7065 != (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED ? 4 : 2))
7066 i++;
7067
7068 if (i >= BR_RANGE_NUM)
7069 as_bad ("Internal error: Cannot find relocation of"
7070 "relaxable branch.");
7071
7072 exp.X_op = O_symbol;
7073 exp.X_add_symbol = branch_symbol;
7074 exp.X_add_number = branch_offset;
7075 pcrel = ((relax_info->relax_fixup[i][0].ramp & NDS32_PCREL) != 0) ? 1 : 0;
7076 fr_where = fragP->fr_fix - 2;
7077 fixP = fix_new_exp (fragP, fr_where, relax_info->relax_fixup[i][0].size,
7078 &exp, pcrel, relax_info->relax_fixup[i][0].r_type);
7079 fixP->fx_addnumber = fixP->fx_offset;
7080
7081 if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
7082 {
7083 insn_16 = fragP->tc_frag_data.insn;
7084 nds32_convert_16_to_32 (stdoutput, insn_16, &insn);
7085 fr_buffer = fragP->fr_literal + fr_where;
7086 fragP->fr_fix += 2;
7087 exp.X_op = O_symbol;
7088 exp.X_add_symbol = abs_section_sym;
7089 exp.X_add_number = 0;
7090 fix_new_exp (fragP, fr_where, 4,
7091 &exp, 0, BFD_RELOC_NDS32_INSN16);
7092 number_to_chars_bigendian (fr_buffer, insn, 4);
7093 }
7094 }
7095 else if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
7096 {
7097 if (fragP->tc_frag_data.opcode->isize == 2)
7098 {
7099 insn_16 = fragP->tc_frag_data.insn;
7100 nds32_convert_16_to_32 (stdoutput, insn_16, &insn);
7101 }
7102 else
7103 insn = fragP->tc_frag_data.insn;
7104 fragP->fr_fix += 2;
7105 fr_where = fragP->fr_fix - 4;
7106 fr_buffer = fragP->fr_literal + fr_where;
7107 exp.X_op = O_symbol;
7108 exp.X_add_symbol = abs_section_sym;
7109 exp.X_add_number = 0;
7110 fix_new_exp (fragP, fr_where, 4, &exp, 0,
7111 BFD_RELOC_NDS32_INSN16);
7112 number_to_chars_bigendian (fr_buffer, insn, 4);
7113 }
7114 else if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
7115 {
7116 /* Branch instruction adjust and append relocations. */
7117 relax_info = str_hash_find (nds32_relax_info_hash, opcode->opcode);
7118
7119 if (relax_info == NULL)
7120 return;
7121
7122 fr_where = fragP->fr_fix - opcode->isize;
7123 fr_buffer = fragP->fr_literal + fr_where;
7124
7125 if ((S_GET_SEGMENT (branch_symbol) != sec)
7126 || S_IS_WEAK (branch_symbol))
7127 {
7128 if (fragP->fr_offset & 3)
7129 as_warn (_("Addend to unresolved symbol is not on word boundary."));
7130 addend = 0;
7131 }
7132 else
7133 {
7134 /* Calculate symbol-to-instruction offset. */
7135 branch_target_address = S_GET_VALUE (branch_symbol) + branch_offset;
7136 branch_insn_address = fragP->fr_address + fr_where;
7137 addend = (branch_target_address - branch_insn_address) >> 1;
7138 }
7139
7140 code_size = relax_info->relax_code_size[branch_range_type];
7141 code_seq = relax_info->relax_code_seq[branch_range_type];
7142
7143 memcpy (fixup_info, relax_info->relax_fixup[branch_range_type],
7144 sizeof (fixup_info));
7145
7146 /* Fill in frag. */
7147 i = 0;
7148 k = 0;
7149 offset = 0; /* code_seq offset */
7150 buf_offset = 0; /* fr_buffer offset */
7151 while (offset < code_size)
7152 {
7153 insn = code_seq[i];
7154 if (insn & 0x80000000) /* 16-bits instruction. */
7155 {
7156 insn = (insn >> 16) & 0xFFFF;
7157 insn_size = 2;
7158 }
7159 else /* 32-bits instruction. */
7160 {
7161 insn_size = 4;
7162 }
7163
7164 nds32_elf_get_set_cond (relax_info, offset, &insn,
7165 origin_insn, branch_range_type);
7166
7167 /* Try to convert to 16-bits instruction. Currently, only the first
7168 instruction in pattern can be converted. EX: bnez sethi ori jr,
7169 only bnez can be converted to 16 bit and ori can't. */
7170
7171 while (fixup_info[k].size != 0
7172 && relax_info->relax_fixup[branch_range_type][k].offset < offset)
7173 k++;
7174
7175 number_to_chars_bigendian (fr_buffer + buf_offset, insn, insn_size);
7176 buf_offset += insn_size;
7177
7178 offset += insn_size;
7179 i++;
7180 }
7181
7182 /* Set up fixup. */
7183 exp.X_op = O_symbol;
7184
7185 for (i = 0; fixup_info[i].size != 0; i++)
7186 {
7187 fixup_size = fixup_info[i].size;
7188 pcrel = ((fixup_info[i].ramp & NDS32_PCREL) != 0) ? 1 : 0;
7189
7190 if ((fixup_info[i].ramp & NDS32_CREATE_LABEL) != 0)
7191 {
7192 /* This is a reverse branch. */
7193 exp.X_add_symbol = symbol_temp_new (sec, fragP->fr_next, 0);
7194 exp.X_add_number = 0;
7195 }
7196 else if ((fixup_info[i].ramp & NDS32_PTR) != 0)
7197 {
7198 /* This relocation has to point to another instruction. */
7199 branch_size = fr_where + code_size - 4;
7200 exp.X_add_symbol = symbol_temp_new (sec, fragP, branch_size);
7201 exp.X_add_number = 0;
7202 }
7203 else if ((fixup_info[i].ramp & NDS32_ABS) != 0)
7204 {
7205 /* This is a tag relocation. */
7206 exp.X_add_symbol = abs_section_sym;
7207 exp.X_add_number = 0;
7208 }
7209 else if ((fixup_info[i].ramp & NDS32_INSN16) != 0)
7210 {
7211 if (!enable_16bit)
7212 continue;
7213 /* This is a tag relocation. */
7214 exp.X_add_symbol = abs_section_sym;
7215 exp.X_add_number = 0;
7216 }
7217 else
7218 {
7219 exp.X_add_symbol = branch_symbol;
7220 exp.X_add_number = branch_offset;
7221 }
7222
7223 if (fixup_info[i].r_type != 0)
7224 {
7225 final_r_type = fixup_info[i].r_type;
7226 fixP = fix_new_exp (fragP, fr_where + fixup_info[i].offset,
7227 fixup_size, &exp, pcrel,
7228 final_r_type);
7229 fixP->fx_addnumber = fixP->fx_offset;
7230 }
7231 }
7232
7233 fragP->fr_fix = fr_where + buf_offset;
7234 }
7235 }
7236
7237 /* tc_frob_file_before_fix */
7238
7239 void
7240 nds32_frob_file_before_fix (void)
7241 {
7242 }
7243
7244 static bool
7245 nds32_relaxable_section (asection *sec)
7246 {
7247 return ((sec->flags & SEC_DEBUGGING) == 0
7248 && strcmp (sec->name, ".eh_frame") != 0);
7249 }
7250
7251 /* TC_FORCE_RELOCATION */
7252 int
7253 nds32_force_relocation (fixS * fix)
7254 {
7255 switch (fix->fx_r_type)
7256 {
7257 case BFD_RELOC_NDS32_INSN16:
7258 case BFD_RELOC_NDS32_LABEL:
7259 case BFD_RELOC_NDS32_LONGCALL1:
7260 case BFD_RELOC_NDS32_LONGCALL2:
7261 case BFD_RELOC_NDS32_LONGCALL3:
7262 case BFD_RELOC_NDS32_LONGJUMP1:
7263 case BFD_RELOC_NDS32_LONGJUMP2:
7264 case BFD_RELOC_NDS32_LONGJUMP3:
7265 case BFD_RELOC_NDS32_LOADSTORE:
7266 case BFD_RELOC_NDS32_9_FIXED:
7267 case BFD_RELOC_NDS32_15_FIXED:
7268 case BFD_RELOC_NDS32_17_FIXED:
7269 case BFD_RELOC_NDS32_25_FIXED:
7270 case BFD_RELOC_NDS32_9_PCREL:
7271 case BFD_RELOC_NDS32_15_PCREL:
7272 case BFD_RELOC_NDS32_17_PCREL:
7273 case BFD_RELOC_NDS32_WORD_9_PCREL:
7274 case BFD_RELOC_NDS32_10_UPCREL:
7275 case BFD_RELOC_NDS32_25_PCREL:
7276 case BFD_RELOC_NDS32_MINUEND:
7277 case BFD_RELOC_NDS32_SUBTRAHEND:
7278 return 1;
7279
7280 case BFD_RELOC_8:
7281 case BFD_RELOC_16:
7282 case BFD_RELOC_32:
7283 case BFD_RELOC_NDS32_DIFF_ULEB128:
7284 /* Linker should handle difference between two symbol. */
7285 return fix->fx_subsy != NULL
7286 && nds32_relaxable_section (S_GET_SEGMENT (fix->fx_addsy));
7287 case BFD_RELOC_64:
7288 if (fix->fx_subsy)
7289 as_bad ("Double word for difference between two symbols "
7290 "is not supported across relaxation.");
7291 default:
7292 ;
7293 }
7294
7295 if (generic_force_reloc (fix))
7296 return 1;
7297
7298 return fix->fx_pcrel;
7299 }
7300
7301 /* TC_VALIDATE_FIX_SUB */
7302
7303 int
7304 nds32_validate_fix_sub (fixS *fix, segT add_symbol_segment)
7305 {
7306 segT sub_symbol_segment;
7307
7308 /* This code is referred from Xtensa. Check their implementation for
7309 details. */
7310
7311 /* Make sure both symbols are in the same segment, and that segment is
7312 "normal" and relaxable. */
7313 sub_symbol_segment = S_GET_SEGMENT (fix->fx_subsy);
7314 return (sub_symbol_segment == add_symbol_segment
7315 && add_symbol_segment != undefined_section);
7316 }
7317
7318 void
7319 md_number_to_chars (char *buf, valueT val, int n)
7320 {
7321 if (target_big_endian)
7322 number_to_chars_bigendian (buf, val, n);
7323 else
7324 number_to_chars_littleendian (buf, val, n);
7325 }
7326
7327 /* This function is called to convert an ASCII string into a floating point
7328 value in format used by the CPU. */
7329
7330 const char *
7331 md_atof (int type, char *litP, int *sizeP)
7332 {
7333 int i;
7334 int prec;
7335 LITTLENUM_TYPE words[MAX_LITTLENUMS];
7336 char *t;
7337
7338 switch (type)
7339 {
7340 case 'f':
7341 case 'F':
7342 case 's':
7343 case 'S':
7344 prec = 2;
7345 break;
7346 case 'd':
7347 case 'D':
7348 case 'r':
7349 case 'R':
7350 prec = 4;
7351 break;
7352 default:
7353 *sizeP = 0;
7354 return _("Bad call to md_atof()");
7355 }
7356
7357 t = atof_ieee (input_line_pointer, type, words);
7358 if (t)
7359 input_line_pointer = t;
7360 *sizeP = prec * sizeof (LITTLENUM_TYPE);
7361
7362 if (target_big_endian)
7363 {
7364 for (i = 0; i < prec; i++)
7365 {
7366 md_number_to_chars (litP, (valueT) words[i],
7367 sizeof (LITTLENUM_TYPE));
7368 litP += sizeof (LITTLENUM_TYPE);
7369 }
7370 }
7371 else
7372 {
7373 for (i = prec - 1; i >= 0; i--)
7374 {
7375 md_number_to_chars (litP, (valueT) words[i],
7376 sizeof (LITTLENUM_TYPE));
7377 litP += sizeof (LITTLENUM_TYPE);
7378 }
7379 }
7380
7381 return 0;
7382 }
7383
7384 /* md_elf_section_change_hook */
7385
7386 void
7387 nds32_elf_section_change_hook (void)
7388 {
7389 }
7390
7391 /* md_cleanup */
7392
7393 void
7394 nds32_cleanup (void)
7395 {
7396 }
7397
7398 /* This function is used to scan leb128 subtraction expressions,
7399 and insert fixups for them.
7400
7401 e.g., .leb128 .L1 - .L0
7402
7403 These expressions are heavily used in debug information or
7404 exception tables. Because relaxation will change code size,
7405 we must resolve them in link time. */
7406
7407 static void
7408 nds32_insert_leb128_fixes (bfd *abfd ATTRIBUTE_UNUSED,
7409 asection *sec, void *xxx ATTRIBUTE_UNUSED)
7410 {
7411 segment_info_type *seginfo = seg_info (sec);
7412 struct frag *fragP;
7413
7414 subseg_set (sec, 0);
7415
7416 for (fragP = seginfo->frchainP->frch_root;
7417 fragP; fragP = fragP->fr_next)
7418 {
7419 expressionS *exp;
7420
7421 /* Only unsigned leb128 can be handle. */
7422 if (fragP->fr_type != rs_leb128 || fragP->fr_subtype != 0
7423 || fragP->fr_symbol == NULL)
7424 continue;
7425
7426 exp = symbol_get_value_expression (fragP->fr_symbol);
7427
7428 if (exp->X_op != O_subtract)
7429 continue;
7430
7431 fix_new_exp (fragP, fragP->fr_fix, 0,
7432 exp, 0, BFD_RELOC_NDS32_DIFF_ULEB128);
7433 }
7434 }
7435
7436 static void
7437 nds32_insert_relax_entry (bfd *abfd ATTRIBUTE_UNUSED, asection *sec,
7438 void *xxx ATTRIBUTE_UNUSED)
7439 {
7440 segment_info_type *seginfo;
7441 fragS *fragP;
7442 fixS *fixP;
7443 expressionS exp;
7444 fixS *fixp;
7445
7446 seginfo = seg_info (sec);
7447 if (!seginfo || !symbol_rootP || !subseg_text_p (sec) || sec->size == 0)
7448 return;
7449
7450 for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
7451 if (!fixp->fx_done)
7452 break;
7453
7454 if (!fixp && !verbatim && ict_flag == ICT_NONE)
7455 return;
7456
7457 subseg_change (sec, 0);
7458
7459 /* Set RELAX_ENTRY flags for linker. */
7460 fragP = seginfo->frchainP->frch_root;
7461 exp.X_op = O_symbol;
7462 exp.X_add_symbol = abs_section_sym;
7463 exp.X_add_number = 0;
7464 if (!enable_relax_relocs)
7465 exp.X_add_number |= R_NDS32_RELAX_ENTRY_DISABLE_RELAX_FLAG;
7466 else
7467 {
7468 /* These flags are only enabled when global relax is enabled.
7469 Maybe we can check DISABLE_RELAX_FLAG at link-time,
7470 so we set them anyway. */
7471 if (verbatim)
7472 exp.X_add_number |= R_NDS32_RELAX_ENTRY_VERBATIM_FLAG;
7473 if (ict_flag == ICT_SMALL)
7474 exp.X_add_number |= R_NDS32_RELAX_ENTRY_ICT_SMALL;
7475 else if (ict_flag == ICT_LARGE)
7476 exp.X_add_number |= R_NDS32_RELAX_ENTRY_ICT_LARGE;
7477 }
7478 if (optimize)
7479 exp.X_add_number |= R_NDS32_RELAX_ENTRY_OPTIMIZE_FLAG;
7480 if (optimize_for_space)
7481 exp.X_add_number |= R_NDS32_RELAX_ENTRY_OPTIMIZE_FOR_SPACE_FLAG;
7482
7483 fixP = fix_new_exp (fragP, 0, 0, &exp, 0, BFD_RELOC_NDS32_RELAX_ENTRY);
7484 fixP->fx_no_overflow = 1;
7485 }
7486
7487 /* Analysis relax hint and insert suitable relocation pattern. */
7488
7489 static void
7490 nds32_elf_analysis_relax_hint (void)
7491 {
7492 htab_traverse_noresize (nds32_hint_hash,
7493 nds32_elf_append_relax_relocs_traverse, NULL);
7494 }
7495
7496 static void
7497 nds32_elf_insert_final_frag (void)
7498 {
7499 struct frchain *frchainP;
7500 asection *s;
7501 fragS *fragP;
7502
7503 if (!optimize)
7504 return;
7505
7506 for (s = stdoutput->sections; s; s = s->next)
7507 {
7508 segment_info_type *seginfo = seg_info (s);
7509 if (!seginfo)
7510 continue;
7511
7512 for (frchainP = seginfo->frchainP; frchainP != NULL;
7513 frchainP = frchainP->frch_next)
7514 {
7515 subseg_set (s, frchainP->frch_subseg);
7516
7517 if (subseg_text_p (now_seg))
7518 {
7519 fragP = frag_now;
7520 frag_var (rs_machine_dependent, 2, /* Max size. */
7521 0, /* VAR is un-used. */ 0, NULL, 0, NULL);
7522 fragP->tc_frag_data.flag |= NDS32_FRAG_FINAL;
7523 }
7524 }
7525 }
7526 }
7527
7528 void
7529 md_finish (void)
7530 {
7531 nds32_elf_insert_final_frag ();
7532 nds32_elf_analysis_relax_hint ();
7533 bfd_map_over_sections (stdoutput, nds32_insert_leb128_fixes, NULL);
7534 }
7535
7536 /* Implement md_allow_local_subtract. */
7537
7538 bool
7539 nds32_allow_local_subtract (expressionS *expr_l ATTRIBUTE_UNUSED,
7540 expressionS *expr_r ATTRIBUTE_UNUSED,
7541 segT sec ATTRIBUTE_UNUSED)
7542 {
7543 /* Don't allow any subtraction, because relax may change the code. */
7544 return false;
7545 }
7546
7547 long
7548 nds32_pcrel_from_section (fixS *fixP, segT sec ATTRIBUTE_UNUSED)
7549 {
7550 if (fixP->fx_addsy == NULL || !S_IS_DEFINED (fixP->fx_addsy)
7551 || S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy))
7552 {
7553 /* Let linker resolve undefined symbols. */
7554 return 0;
7555 }
7556
7557 return fixP->fx_frag->fr_address + fixP->fx_where;
7558 }
7559
7560 /* md_post_relax_hook ()
7561 Insert relax entry relocation into sections. */
7562
7563 void
7564 nds32_post_relax_hook (void)
7565 {
7566 bfd_map_over_sections (stdoutput, nds32_insert_relax_entry, NULL);
7567 }
7568
7569 /* tc_fix_adjustable ()
7570
7571 Return whether this symbol (fixup) can be replaced with
7572 section symbols. */
7573
7574 bool
7575 nds32_fix_adjustable (fixS *fixP)
7576 {
7577 switch (fixP->fx_r_type)
7578 {
7579 case BFD_RELOC_NDS32_WORD_9_PCREL:
7580 case BFD_RELOC_NDS32_9_PCREL:
7581 case BFD_RELOC_NDS32_15_PCREL:
7582 case BFD_RELOC_NDS32_17_PCREL:
7583 case BFD_RELOC_NDS32_25_PCREL:
7584 case BFD_RELOC_NDS32_HI20:
7585 case BFD_RELOC_NDS32_LO12S0:
7586 case BFD_RELOC_8:
7587 case BFD_RELOC_16:
7588 case BFD_RELOC_32:
7589 case BFD_RELOC_NDS32_PTR:
7590 case BFD_RELOC_NDS32_LONGCALL4:
7591 case BFD_RELOC_NDS32_LONGCALL5:
7592 case BFD_RELOC_NDS32_LONGCALL6:
7593 case BFD_RELOC_NDS32_LONGJUMP4:
7594 case BFD_RELOC_NDS32_LONGJUMP5:
7595 case BFD_RELOC_NDS32_LONGJUMP6:
7596 case BFD_RELOC_NDS32_LONGJUMP7:
7597 return 1;
7598 default:
7599 return 0;
7600 }
7601 }
7602
7603 /* elf_tc_final_processing */
7604
7605 void
7606 elf_nds32_final_processing (void)
7607 {
7608 /* An FPU_COM instruction is found without previous non-FPU_COM
7609 instruction. */
7610 if (nds32_fpu_com
7611 && !(nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST)))
7612 {
7613 /* Since only FPU_COM instructions are used and no other FPU instructions
7614 are used. The nds32_elf_flags will be decided by the enabled options
7615 by command line or default configuration. */
7616 if (nds32_fpu_dp_ext || nds32_fpu_sp_ext)
7617 {
7618 nds32_elf_flags |= nds32_fpu_dp_ext ? E_NDS32_HAS_FPU_DP_INST : 0;
7619 nds32_elf_flags |= nds32_fpu_sp_ext ? E_NDS32_HAS_FPU_INST : 0;
7620 }
7621 else
7622 {
7623 /* Should never here. */
7624 as_bad (_("Used FPU instructions requires enabling FPU extension"));
7625 }
7626 }
7627
7628 if (nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST))
7629 {
7630 /* Single/double FPU has been used, set FPU register config. */
7631 /* We did not check the actual number of register used. We may
7632 want to do it while assemble. */
7633 nds32_elf_flags &= ~E_NDS32_FPU_REG_CONF;
7634 nds32_elf_flags |= (nds32_freg << E_NDS32_FPU_REG_CONF_SHIFT);
7635 }
7636
7637 if (nds32_pic)
7638 nds32_elf_flags |= E_NDS32_HAS_PIC;
7639
7640 if (nds32_gpr16)
7641 nds32_elf_flags |= E_NDS32_HAS_REDUCED_REGS;
7642
7643 nds32_elf_flags |= (E_NDS32_ELF_VER_1_4 | nds32_abi);
7644 elf_elfheader (stdoutput)->e_flags |= nds32_elf_flags;
7645 }
7646
7647 /* Implement md_apply_fix. Apply the fix-up or transform the fix-up for
7648 later relocation generation. */
7649
7650 void
7651 nds32_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
7652 {
7653 char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
7654 bfd_vma value = *valP;
7655
7656 if (fixP->fx_r_type < BFD_RELOC_UNUSED
7657 && fixP->fx_r_type > BFD_RELOC_NONE
7658 && fixP->fx_r_type != BFD_RELOC_NDS32_DIFF_ULEB128)
7659 {
7660 /* In our old nds32 binutils, it must convert relocations which is
7661 generated by CGEN. However, it does not have to consider this anymore.
7662 In current, it only deal with data relocations which enum
7663 is smaller than BFD_RELOC_NONE and BFD_RELOC_NDS32_DIFF_ULEB128.
7664 It is believed that we can construct a better mechanism to
7665 deal with the whole relocation issue in nds32 target
7666 without using CGEN. */
7667 fixP->fx_addnumber = value;
7668 fixP->tc_fix_data = NULL;
7669
7670 /* Transform specific relocations here for later relocation generation.
7671 Tag tls data for linker. */
7672 switch (fixP->fx_r_type)
7673 {
7674 case BFD_RELOC_NDS32_DATA:
7675 /* This reloc is obselete, we do not need it so far. */
7676 fixP->fx_done = 1;
7677 break;
7678 case BFD_RELOC_NDS32_TPOFF:
7679 case BFD_RELOC_NDS32_TLS_LE_HI20:
7680 case BFD_RELOC_NDS32_TLS_LE_LO12:
7681 case BFD_RELOC_NDS32_TLS_LE_ADD:
7682 case BFD_RELOC_NDS32_TLS_LE_LS:
7683 case BFD_RELOC_NDS32_GOTTPOFF:
7684 case BFD_RELOC_NDS32_TLS_IE_HI20:
7685 case BFD_RELOC_NDS32_TLS_IE_LO12S2:
7686 case BFD_RELOC_NDS32_TLS_DESC_HI20:
7687 case BFD_RELOC_NDS32_TLS_DESC_LO12:
7688 case BFD_RELOC_NDS32_TLS_IE_LO12:
7689 case BFD_RELOC_NDS32_TLS_IEGP_HI20:
7690 case BFD_RELOC_NDS32_TLS_IEGP_LO12:
7691 case BFD_RELOC_NDS32_TLS_IEGP_LO12S2:
7692 S_SET_THREAD_LOCAL (fixP->fx_addsy);
7693 break;
7694 default:
7695 break;
7696 }
7697 return;
7698 }
7699
7700 if (fixP->fx_addsy == (symbolS *) NULL)
7701 fixP->fx_done = 1;
7702
7703 if (fixP->fx_subsy != (symbolS *) NULL)
7704 {
7705 /* HOW DIFF RELOCATION WORKS.
7706
7707 First of all, this relocation is used to calculate the distance
7708 between two symbols in the SAME section. It is used for jump-
7709 table, debug information, exception table, et al. Therefore,
7710 it is a unsigned positive value. It is NOT used for general-
7711 purpose arithmetic.
7712
7713 Consider this example, the distance between .LEND and .LBEGIN
7714 is stored at the address of foo.
7715
7716 ---- >8 ---- >8 ---- >8 ---- >8 ----
7717 .data
7718 foo:
7719 .word .LBEGIN - .LEND
7720
7721 .text
7722 [before]
7723 .LBEGIN
7724 \
7725 [between] distance
7726 /
7727 .LEND
7728 [after]
7729 ---- 8< ---- 8< ---- 8< ---- 8< ----
7730
7731 We use a single relocation entry for this expression.
7732 * The initial distance value is stored directly in that location
7733 specified by r_offset (i.e., foo in this example.)
7734 * The begin of the region, i.e., .LBEGIN, is specified by
7735 r_info/R_SYM and r_addend, e.g., .text + 0x32.
7736 * The end of region, i.e., .LEND, is represented by
7737 .LBEGIN + distance instead of .LEND, so we only need
7738 a single relocation entry instead of two.
7739
7740 When an instruction is relaxed, we adjust the relocation entry
7741 depending on where the instruction locates. There are three
7742 cases, before, after and between the region.
7743 * between: Distance value is read from r_offset, adjusted and
7744 written back into r_offset.
7745 * before: Only r_addend is adjust.
7746 * after: We don't care about it.
7747
7748 Hereby, there are some limitation.
7749
7750 `(.LEND - 1) - .LBEGIN' and `(.LEND - .LBEGIN) - 1'
7751 are semantically different, and we cannot handle latter case
7752 when relaxation.
7753
7754 The latter expression means subtracting 1 from the distance
7755 between .LEND and .LBEGIN. And the former expression means
7756 the distance between (.LEND - 1) and .LBEGIN.
7757
7758 The nuance affects whether to adjust distance value when relax
7759 an instruction. In another words, whether the instruction
7760 locates in the region. Because we use a single relocation entry,
7761 there is no field left for .LEND and the subtrahend.
7762
7763 Since GCC-4.5, GCC may produce debug information in such expression
7764 .long .L1-1-.L0
7765 in order to describe register clobbering during an function-call.
7766 .L0:
7767 call foo
7768 .L1:
7769
7770 Check http://gcc.gnu.org/ml/gcc-patches/2009-06/msg01317.html
7771 for details. */
7772
7773 value -= S_GET_VALUE (fixP->fx_subsy);
7774 *valP = value;
7775 fixP->fx_subsy = NULL;
7776 fixP->fx_offset -= value;
7777
7778 switch (fixP->fx_r_type)
7779 {
7780 case BFD_RELOC_8:
7781 fixP->fx_r_type = BFD_RELOC_NDS32_DIFF8;
7782 md_number_to_chars (where, value, 1);
7783 break;
7784 case BFD_RELOC_16:
7785 fixP->fx_r_type = BFD_RELOC_NDS32_DIFF16;
7786 md_number_to_chars (where, value, 2);
7787 break;
7788 case BFD_RELOC_32:
7789 fixP->fx_r_type = BFD_RELOC_NDS32_DIFF32;
7790 md_number_to_chars (where, value, 4);
7791 break;
7792 case BFD_RELOC_NDS32_DIFF_ULEB128:
7793 /* cvt_frag_to_fill () has called output_leb128 () for us. */
7794 break;
7795 default:
7796 as_bad_subtract (fixP);
7797 return;
7798 }
7799 }
7800 else if (fixP->fx_done)
7801 {
7802 /* We're finished with this fixup. Install it because
7803 bfd_install_relocation won't be called to do it. */
7804 switch (fixP->fx_r_type)
7805 {
7806 case BFD_RELOC_8:
7807 md_number_to_chars (where, value, 1);
7808 break;
7809 case BFD_RELOC_16:
7810 md_number_to_chars (where, value, 2);
7811 break;
7812 case BFD_RELOC_32:
7813 md_number_to_chars (where, value, 4);
7814 break;
7815 case BFD_RELOC_64:
7816 md_number_to_chars (where, value, 8);
7817 break;
7818 default:
7819 as_bad_where (fixP->fx_file, fixP->fx_line,
7820 _("Internal error: Unknown fixup type %d (`%s')"),
7821 fixP->fx_r_type,
7822 bfd_get_reloc_code_name (fixP->fx_r_type));
7823 break;
7824 }
7825 }
7826 }
7827
7828 /* Implement tc_gen_reloc. Generate ELF relocation for a fix-up. */
7829
7830 arelent *
7831 tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
7832 {
7833 arelent *reloc;
7834 bfd_reloc_code_real_type code;
7835
7836 reloc = XNEW (arelent);
7837
7838 reloc->sym_ptr_ptr = XNEW (asymbol *);
7839 *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
7840 reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
7841
7842 code = fixP->fx_r_type;
7843
7844 reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
7845 if (reloc->howto == (reloc_howto_type *) NULL)
7846 {
7847 as_bad_where (fixP->fx_file, fixP->fx_line,
7848 _("internal error: can't export reloc type %d (`%s')"),
7849 fixP->fx_r_type, bfd_get_reloc_code_name (code));
7850 return NULL;
7851 }
7852
7853 /* Add relocation handling here. */
7854
7855 switch (fixP->fx_r_type)
7856 {
7857 default:
7858 /* In general, addend of a relocation is the offset to the
7859 associated symbol. */
7860 reloc->addend = fixP->fx_offset;
7861 break;
7862
7863 case BFD_RELOC_NDS32_DATA:
7864 /* Prevent linker from optimizing data in text sections.
7865 For example, jump table. */
7866 reloc->addend = fixP->fx_size;
7867 break;
7868 }
7869
7870 return reloc;
7871 }
7872
7873 static struct suffix_name suffix_table[] =
7874 {
7875 {"GOTOFF", BFD_RELOC_NDS32_GOTOFF},
7876 {"GOT", BFD_RELOC_NDS32_GOT20},
7877 {"TPOFF", BFD_RELOC_NDS32_TPOFF},
7878 {"PLT", BFD_RELOC_NDS32_25_PLTREL},
7879 {"GOTTPOFF", BFD_RELOC_NDS32_GOTTPOFF},
7880 {"TLSDESC", BFD_RELOC_NDS32_TLS_DESC},
7881 };
7882
7883 /* Implement md_parse_name. */
7884
7885 int
7886 nds32_parse_name (char const *name, expressionS *exprP,
7887 enum expr_mode mode ATTRIBUTE_UNUSED,
7888 char *nextcharP ATTRIBUTE_UNUSED)
7889 {
7890 segT segment;
7891
7892 exprP->X_op_symbol = NULL;
7893 exprP->X_md = BFD_RELOC_UNUSED;
7894
7895 exprP->X_add_symbol = symbol_find_or_make (name);
7896 exprP->X_op = O_symbol;
7897 exprP->X_add_number = 0;
7898
7899 /* Check the special name if a symbol. */
7900 segment = S_GET_SEGMENT (exprP->X_add_symbol);
7901 if ((segment != undefined_section) && (*nextcharP != '@'))
7902 return 0;
7903
7904 if (strcmp (name, GOT_NAME) == 0 && *nextcharP != '@')
7905 {
7906 /* Set for _GOT_OFFSET_TABLE_. */
7907 exprP->X_md = BFD_RELOC_NDS32_GOTPC20;
7908 }
7909 else if (*nextcharP == '@')
7910 {
7911 size_t i;
7912 char *next;
7913 for (i = 0; i < ARRAY_SIZE (suffix_table); i++)
7914 {
7915 next = input_line_pointer + 1 + strlen (suffix_table[i].suffix);
7916 if (strncasecmp (input_line_pointer + 1, suffix_table[i].suffix,
7917 strlen (suffix_table[i].suffix)) == 0
7918 && !is_part_of_name (*next))
7919 {
7920 exprP->X_md = suffix_table[i].reloc;
7921 *input_line_pointer = *nextcharP;
7922 input_line_pointer = next;
7923 *nextcharP = *input_line_pointer;
7924 *input_line_pointer = '\0';
7925 break;
7926 }
7927 }
7928 }
7929
7930 return 1;
7931 }
7932
7933 /* Implement tc_regname_to_dw2regnum. */
7934
7935 int
7936 tc_nds32_regname_to_dw2regnum (char *regname)
7937 {
7938 struct nds32_keyword *sym = str_hash_find (nds32_gprs_hash, regname);
7939
7940 if (!sym)
7941 return -1;
7942
7943 return sym->value;
7944 }
7945
7946 void
7947 tc_nds32_frame_initial_instructions (void)
7948 {
7949 /* CIE */
7950 /* Default cfa is register-31/sp. */
7951 cfi_add_CFA_def_cfa (31, 0);
7952 }
7953