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