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