1440a403fSchristos /* tc-nds32.c -- Assemble for the nds32
2*b88e3e88Schristos    Copyright (C) 2012-2020 Free Software Foundation, Inc.
3440a403fSchristos    Contributed by Andes Technology Corporation.
4440a403fSchristos 
5440a403fSchristos    This file is part of GAS, the GNU Assembler.
6440a403fSchristos 
7440a403fSchristos    GAS is free software; you can redistribute it and/or modify
8440a403fSchristos    it under the terms of the GNU General Public License as published by
9440a403fSchristos    the Free Software Foundation; either version 3, or (at your option)
10440a403fSchristos    any later version.
11440a403fSchristos 
12440a403fSchristos    GAS is distributed in the hope that it will be useful,
13440a403fSchristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
14440a403fSchristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
15440a403fSchristos    GNU General Public License for more details.
16440a403fSchristos 
17440a403fSchristos    You should have received a copy of the GNU General Public License
18440a403fSchristos    along with GAS; see the file COPYING.  If not, write to the Free
19440a403fSchristos    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
20440a403fSchristos    02110-1301, USA.  */
21440a403fSchristos 
22440a403fSchristos #include "as.h"
23440a403fSchristos #include "safe-ctype.h"
24440a403fSchristos #include "subsegs.h"
25440a403fSchristos #include "symcat.h"
26440a403fSchristos #include "dwarf2dbg.h"
27440a403fSchristos #include "dw2gencfi.h"
28440a403fSchristos #include "opcodes/nds32-asm.h"
29440a403fSchristos #include "elf/nds32.h"
30440a403fSchristos #include "bfd/elf32-nds32.h"
31440a403fSchristos #include "hash.h"
32440a403fSchristos #include "sb.h"
33440a403fSchristos #include "macro.h"
34440a403fSchristos #include "opcode/nds32.h"
35440a403fSchristos 
36440a403fSchristos #include <stdio.h>
37*b88e3e88Schristos #include <errno.h>
38*b88e3e88Schristos #include <limits.h>
39440a403fSchristos 
40440a403fSchristos /* GAS definitions.  */
41440a403fSchristos 
42440a403fSchristos /* Characters which start a comment.  */
43440a403fSchristos const char comment_chars[] = "!";
44440a403fSchristos /* Characters which start a comment when they appear at the start of a line.  */
45440a403fSchristos const char line_comment_chars[] = "#!";
46440a403fSchristos /* Characters which separate lines (null and newline are by default).  */
47440a403fSchristos const char line_separator_chars[] = ";";
48440a403fSchristos /* Characters which may be used as the exponent character
49440a403fSchristos    in a floating point number.  */
50440a403fSchristos const char EXP_CHARS[] = "eE";
51440a403fSchristos /* Characters which may be used to indicate a floating point constant.  */
52440a403fSchristos const char FLT_CHARS[] = "dDfF";
53440a403fSchristos 
54440a403fSchristos static int enable_16bit = 1;
55440a403fSchristos /* Save for md_assemble to distinguish if this instruction is
56440a403fSchristos    expanded from the pseudo instruction.  */
57440a403fSchristos static bfd_boolean pseudo_opcode = FALSE;
58440a403fSchristos static struct nds32_relocs_pattern *relocs_list = NULL;
59440a403fSchristos /* Save instruction relation to inserting relaxation relocation.  */
60440a403fSchristos struct nds32_relocs_pattern
61440a403fSchristos {
62440a403fSchristos   segT seg;
63440a403fSchristos   fragS *frag;
64440a403fSchristos   frchainS *frchain;
65440a403fSchristos   symbolS *sym;
66440a403fSchristos   fixS* fixP;
67440a403fSchristos   struct nds32_opcode *opcode;
68440a403fSchristos   char *where;
69440a403fSchristos   struct nds32_relocs_pattern *next;
70*b88e3e88Schristos   /* Assembled instruction bytes.  */
71*b88e3e88Schristos   uint32_t insn;
72440a403fSchristos };
73440a403fSchristos 
74440a403fSchristos /* Suffix name and relocation.  */
75440a403fSchristos struct suffix_name
76440a403fSchristos {
77440a403fSchristos   const char *suffix;
78440a403fSchristos   short unsigned int reloc;
79440a403fSchristos };
80440a403fSchristos static int vec_size = 0;
81440a403fSchristos /* If the assembly code is generated by compiler, it is supposed to have
82440a403fSchristos    ".flag verbatim" at beginning of the content.  We have
83440a403fSchristos    'nds32_flag' to parse it and set this field to be non-zero.  */
84440a403fSchristos static int verbatim = 0;
85440a403fSchristos static struct hash_control *nds32_gprs_hash;
86440a403fSchristos static struct hash_control *nds32_hint_hash;
87440a403fSchristos #define TLS_REG "$r27"
88440a403fSchristos #define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
89440a403fSchristos 
90440a403fSchristos /* Generate relocation for relax or not, and the default is true.  */
91440a403fSchristos static int enable_relax_relocs = 1;
9206324dcfSchristos /* Save option -O for performance.  */
93440a403fSchristos static int optimize = 0;
94440a403fSchristos /* Save option -Os for code size.  */
95440a403fSchristos static int optimize_for_space = 0;
96440a403fSchristos /* Flag to save label exist.  */
97440a403fSchristos static int label_exist = 0;
98440a403fSchristos /* Flag to save state in omit_fp region.  */
99440a403fSchristos static int in_omit_fp = 0;
100440a403fSchristos extern struct nds32_keyword keyword_gpr[];
101440a403fSchristos /* Tag there is relax relocation having to link.  */
102440a403fSchristos static bfd_boolean relaxing = FALSE;
10306324dcfSchristos /* ICT model.  */
10406324dcfSchristos enum ict_option {
10506324dcfSchristos   ICT_NONE = 0,
10606324dcfSchristos   ICT_SMALL,
10706324dcfSchristos   ICT_LARGE
10806324dcfSchristos };
10906324dcfSchristos static enum ict_option ict_flag = ICT_NONE;
110440a403fSchristos 
111*b88e3e88Schristos 
112440a403fSchristos static struct hash_control *nds32_relax_info_hash;
113*b88e3e88Schristos 
114*b88e3e88Schristos /* Branch patterns.  */
115440a403fSchristos static relax_info_t relax_table[] =
116440a403fSchristos {
117440a403fSchristos   {
118*b88e3e88Schristos     .opcode = "jal",
119*b88e3e88Schristos     .br_range = BR_RANGE_S16M,
120*b88e3e88Schristos     .cond_field =
121440a403fSchristos       {
122*b88e3e88Schristos 	{0, 0, 0, FALSE}
123*b88e3e88Schristos       },
124*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S256] =
125440a403fSchristos       {
126440a403fSchristos 	INSN_JAL	/* jal label */
127*b88e3e88Schristos       },
128*b88e3e88Schristos     .relax_code_size[BR_RANGE_S256] = 4,
129*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S256] = 4,
130*b88e3e88Schristos     .relax_fixup[BR_RANGE_S256] =
131*b88e3e88Schristos       {
132*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
133*b88e3e88Schristos 	{0, 0, 0, 0}
134*b88e3e88Schristos       },
135*b88e3e88Schristos 
136*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16K] =
137440a403fSchristos       {
138440a403fSchristos 	INSN_JAL	/* jal label */
139*b88e3e88Schristos       },
140*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16K] = 4,
141*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16K] = 4,
142*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16K] =
143*b88e3e88Schristos       {
144*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
145*b88e3e88Schristos 	{0, 0, 0, 0}
146*b88e3e88Schristos       },
147*b88e3e88Schristos 
148*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S64K] =
149440a403fSchristos       {
150440a403fSchristos 	INSN_JAL	/* jal label */
151*b88e3e88Schristos       },
152*b88e3e88Schristos     .relax_code_size[BR_RANGE_S64K] = 4,
153*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S64K] = 4,
154*b88e3e88Schristos     .relax_fixup[BR_RANGE_S64K] =
155*b88e3e88Schristos       {
156*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
157*b88e3e88Schristos 	{0, 0, 0, 0}
158*b88e3e88Schristos       },
159*b88e3e88Schristos 
160*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16M] =
161440a403fSchristos       {
162440a403fSchristos 	INSN_JAL	/* jal label */
163*b88e3e88Schristos       },
164*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16M] = 4,
165*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16M] = 4,
166*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16M] =
167*b88e3e88Schristos       {
168*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
169*b88e3e88Schristos 	{0, 0, 0, 0}
170*b88e3e88Schristos       },
171*b88e3e88Schristos 
172*b88e3e88Schristos     .relax_code_seq[BR_RANGE_U4G] =
173440a403fSchristos       {
174440a403fSchristos 	INSN_SETHI_TA,	/* sethi $ta, label */
175440a403fSchristos 	INSN_ORI_TA,	/* ori $ta, $ta, label */
176*b88e3e88Schristos 	INSN_JRAL_TA	/* jral $ta */
177*b88e3e88Schristos       },
178*b88e3e88Schristos     .relax_code_size[BR_RANGE_U4G] = 12,
179*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_U4G] = 4,
180*b88e3e88Schristos     .relax_fixup[BR_RANGE_U4G] =
181440a403fSchristos       {
182440a403fSchristos 	{0, 4, 0, BFD_RELOC_NDS32_HI20},
183440a403fSchristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL4},
184440a403fSchristos 	{4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI},
185440a403fSchristos 	{4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
186440a403fSchristos 	{8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
187440a403fSchristos 	{8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
188440a403fSchristos 	{8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
189440a403fSchristos 	{0, 0, 0, 0}
190*b88e3e88Schristos       },
191440a403fSchristos   },
192440a403fSchristos   {
193*b88e3e88Schristos     .opcode = "bgezal",
194*b88e3e88Schristos     .br_range = BR_RANGE_S64K,
195*b88e3e88Schristos     .cond_field =
196440a403fSchristos       {
197440a403fSchristos 	{0, 20, 0x1F, FALSE},
198440a403fSchristos 	{0, 0, 0, FALSE}
199*b88e3e88Schristos       },
200*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S256] =
201440a403fSchristos       {
202*b88e3e88Schristos 	  INSN_BGEZAL	/* bgezal $rt, label */
203*b88e3e88Schristos       },
204*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S256] =
205440a403fSchristos       {
206*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
207*b88e3e88Schristos 	{0, 0, 0, FALSE},
208*b88e3e88Schristos       },
209*b88e3e88Schristos     .relax_code_size[BR_RANGE_S256] = 4,
210*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S256] = 4,
211*b88e3e88Schristos     .relax_fixup[BR_RANGE_S256] =
212440a403fSchristos       {
213*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
214*b88e3e88Schristos 	{0, 0, 0, 0}
215*b88e3e88Schristos       },
216*b88e3e88Schristos 
217*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16K] =
218440a403fSchristos       {
219*b88e3e88Schristos 	INSN_BGEZAL	/* bgezal $rt, label */
220*b88e3e88Schristos       },
221*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16K] =
222440a403fSchristos       {
223*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
224*b88e3e88Schristos 	{0, 0, 0, FALSE},
225*b88e3e88Schristos       },
226*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16K] = 4,
227*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16K] = 4,
228*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16K] =
229*b88e3e88Schristos       {
230*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
231*b88e3e88Schristos 	{0, 0, 0, 0}
232*b88e3e88Schristos       },
233*b88e3e88Schristos 
234*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S64K] =
235*b88e3e88Schristos       {
236*b88e3e88Schristos 	INSN_BGEZAL	/* bgezal $rt, label */
237*b88e3e88Schristos       },
238*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S64K] =
239*b88e3e88Schristos       {
240*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
241*b88e3e88Schristos 	{0, 0, 0, FALSE},
242*b88e3e88Schristos       },
243*b88e3e88Schristos     .relax_code_size[BR_RANGE_S64K] = 4,
244*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S64K] = 4,
245*b88e3e88Schristos     .relax_fixup[BR_RANGE_S64K] =
246*b88e3e88Schristos       {
247*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
248*b88e3e88Schristos 	{0, 0, 0, 0}
249*b88e3e88Schristos       },
250*b88e3e88Schristos 
251*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16M] =
252*b88e3e88Schristos       {
253*b88e3e88Schristos 	INSN_BLTZ,	/* bltz $rt, $1 */
254440a403fSchristos 	INSN_JAL	/* jal label */
255*b88e3e88Schristos       },
256*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16M] =
257440a403fSchristos       {
258440a403fSchristos 	{0, 20, 0x1F, FALSE},
259*b88e3e88Schristos 	{0, 0, 0, FALSE},
260*b88e3e88Schristos       },
261*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16M] = 8,
262*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16M] = 4,
263*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16M] =
264440a403fSchristos       {
265440a403fSchristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
266440a403fSchristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL5},
267440a403fSchristos 	{4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
268440a403fSchristos 	{0, 0, 0, 0}
269*b88e3e88Schristos       },
270*b88e3e88Schristos 
271*b88e3e88Schristos     .relax_code_seq[BR_RANGE_U4G] =
272*b88e3e88Schristos       {
273*b88e3e88Schristos 	INSN_BLTZ,	/* bltz $rt, $1 */
274*b88e3e88Schristos 	INSN_SETHI_TA,	/* sethi $ta, label */
275*b88e3e88Schristos 	INSN_ORI_TA,	/* ori $ta, $ta, label */
276*b88e3e88Schristos 	INSN_JRAL_TA	/* jral $ta */
277*b88e3e88Schristos       },
278*b88e3e88Schristos     .relax_code_condition[BR_RANGE_U4G] =
279*b88e3e88Schristos       {
280*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
281*b88e3e88Schristos 	{0, 0, 0, FALSE},
282*b88e3e88Schristos       },
283*b88e3e88Schristos     .relax_code_size[BR_RANGE_U4G] = 16,
284*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_U4G] = 4,
285*b88e3e88Schristos     .relax_fixup[BR_RANGE_U4G] =
286440a403fSchristos       {
287440a403fSchristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
288440a403fSchristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL6},
289440a403fSchristos 	{4, 4, 0, BFD_RELOC_NDS32_HI20},
290440a403fSchristos 	{4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
291440a403fSchristos 	{8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
292440a403fSchristos 	{8, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
293440a403fSchristos 	{12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
294440a403fSchristos 	{12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
295440a403fSchristos 	{12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
296440a403fSchristos 	{0, 0, 0, 0}
297*b88e3e88Schristos       },
298440a403fSchristos   },
299440a403fSchristos   {
300*b88e3e88Schristos     .opcode = "bltzal",
301*b88e3e88Schristos     .br_range = BR_RANGE_S64K,
302*b88e3e88Schristos     .cond_field =
303440a403fSchristos       {
304440a403fSchristos 	{0, 20, 0x1F, FALSE},
305440a403fSchristos 	{0, 0, 0, FALSE}
306*b88e3e88Schristos       },
307*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S256] =
308440a403fSchristos       {
309*b88e3e88Schristos 	  INSN_BLTZAL	/* bltzal $rt, label */
310*b88e3e88Schristos       },
311*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S256] =
312440a403fSchristos       {
313*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
314*b88e3e88Schristos 	{0, 0, 0, FALSE},
315*b88e3e88Schristos       },
316*b88e3e88Schristos     .relax_code_size[BR_RANGE_S256] = 4,
317*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S256] = 4,
318*b88e3e88Schristos     .relax_fixup[BR_RANGE_S256] =
319440a403fSchristos       {
320*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
321*b88e3e88Schristos 	{0, 0, 0, 0}
322*b88e3e88Schristos       },
323*b88e3e88Schristos 
324*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16K] =
325440a403fSchristos       {
326*b88e3e88Schristos 	INSN_BLTZAL	/* bltzal $rt, label */
327*b88e3e88Schristos       },
328*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16K] =
329440a403fSchristos       {
330*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
331*b88e3e88Schristos 	{0, 0, 0, FALSE},
332*b88e3e88Schristos       },
333*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16K] = 4,
334*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16K] = 4,
335*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16K] =
336*b88e3e88Schristos       {
337*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
338*b88e3e88Schristos 	{0, 0, 0, 0}
339*b88e3e88Schristos       },
340*b88e3e88Schristos 
341*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S64K] =
342*b88e3e88Schristos       {
343*b88e3e88Schristos 	INSN_BLTZAL	/* bltzal $rt, label */
344*b88e3e88Schristos       },
345*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S64K] =
346*b88e3e88Schristos       {
347*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
348*b88e3e88Schristos 	{0, 0, 0, FALSE},
349*b88e3e88Schristos       },
350*b88e3e88Schristos     .relax_code_size[BR_RANGE_S64K] = 4,
351*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S64K] = 4,
352*b88e3e88Schristos     .relax_fixup[BR_RANGE_S64K] =
353*b88e3e88Schristos       {
354*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
355*b88e3e88Schristos 	{0, 0, 0, 0}
356*b88e3e88Schristos       },
357*b88e3e88Schristos 
358*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16M] =
359*b88e3e88Schristos       {
360*b88e3e88Schristos 	INSN_BGEZ,	/* bgez $rt, $1 */
361440a403fSchristos 	INSN_JAL	/* jal label */
362*b88e3e88Schristos       },
363*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16M] =
364440a403fSchristos       {
365440a403fSchristos 	{0, 20, 0x1F, FALSE},
366*b88e3e88Schristos 	{0, 0, 0, FALSE},
367*b88e3e88Schristos       },
368*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16M] = 8,
369*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16M] = 4,
370*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16M] =
371440a403fSchristos       {
372440a403fSchristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
373440a403fSchristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL5},
374440a403fSchristos 	{4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
375440a403fSchristos 	{0, 0, 0, 0}
376*b88e3e88Schristos       },
377*b88e3e88Schristos 
378*b88e3e88Schristos     .relax_code_seq[BR_RANGE_U4G] =
379*b88e3e88Schristos       {
380*b88e3e88Schristos 	INSN_BGEZ,	/* bgez $rt, $1 */
381*b88e3e88Schristos 	INSN_SETHI_TA,	/* sethi $ta, label */
382*b88e3e88Schristos 	INSN_ORI_TA,	/* ori $ta, $ta, label */
383*b88e3e88Schristos 	INSN_JRAL_TA	/* jral $ta */
384*b88e3e88Schristos       },
385*b88e3e88Schristos     .relax_code_condition[BR_RANGE_U4G] =
386*b88e3e88Schristos       {
387*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
388*b88e3e88Schristos 	{0, 0, 0, FALSE},
389*b88e3e88Schristos       },
390*b88e3e88Schristos     .relax_code_size[BR_RANGE_U4G] = 16,
391*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_U4G] = 4,
392*b88e3e88Schristos     .relax_fixup[BR_RANGE_U4G] =
393440a403fSchristos       {
394440a403fSchristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
395440a403fSchristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL6},
396440a403fSchristos 	{4, 4, 0, BFD_RELOC_NDS32_HI20},
397440a403fSchristos 	{4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
398440a403fSchristos 	{8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
399440a403fSchristos 	{8, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
400440a403fSchristos 	{12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
401440a403fSchristos 	{12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
402440a403fSchristos 	{12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
403440a403fSchristos 	{0, 0, 0, 0}
404*b88e3e88Schristos       },
405440a403fSchristos   },
406440a403fSchristos   {
407*b88e3e88Schristos     .opcode = "j",
408*b88e3e88Schristos     .br_range = BR_RANGE_S16M,
409*b88e3e88Schristos     .cond_field =
410440a403fSchristos       {
411*b88e3e88Schristos 	{0, 0, 0, FALSE}
412*b88e3e88Schristos       },
413*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S256] =
414440a403fSchristos       {
415440a403fSchristos 	(INSN_J8 << 16)	/* j8 label */
416*b88e3e88Schristos       },
417*b88e3e88Schristos     .relax_code_size[BR_RANGE_S256] = 2,
418*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S256] = 2,
419*b88e3e88Schristos     .relax_fixup[BR_RANGE_S256] =
420*b88e3e88Schristos       {
421*b88e3e88Schristos 	{0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
422*b88e3e88Schristos 	{0, 0, 0, 0}
423*b88e3e88Schristos       },
424*b88e3e88Schristos 
425*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16K] =
426440a403fSchristos       {
427440a403fSchristos 	INSN_J		/* j label */
428*b88e3e88Schristos       },
429*b88e3e88Schristos     . relax_code_size[BR_RANGE_S16K] = 4,
430*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16K] = 4,
431*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16K] =
432*b88e3e88Schristos       {
433*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
434*b88e3e88Schristos 	{0, 0, 0, 0}
435*b88e3e88Schristos       },
436*b88e3e88Schristos 
437*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S64K] =
438440a403fSchristos       {
439440a403fSchristos 	INSN_J		/* j label */
440*b88e3e88Schristos       },
441*b88e3e88Schristos     .relax_code_size[BR_RANGE_S64K] = 4,
442*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S64K] = 4,
443*b88e3e88Schristos     .relax_fixup[BR_RANGE_S64K] =
444*b88e3e88Schristos       {
445*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
446*b88e3e88Schristos 	{0, 0, 0, 0}
447*b88e3e88Schristos       },
448*b88e3e88Schristos 
449*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16M] =
450440a403fSchristos       {
451440a403fSchristos 	INSN_J		/* j label */
452*b88e3e88Schristos       },
453*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16M] = 4,
454*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16M] = 4,
455*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16M] =
456*b88e3e88Schristos       {
457*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
458*b88e3e88Schristos 	{0, 0, 0, 0}
459*b88e3e88Schristos       },
460*b88e3e88Schristos 
461*b88e3e88Schristos     .relax_code_seq[BR_RANGE_U4G] =
462440a403fSchristos       {
463440a403fSchristos 	INSN_SETHI_TA,	/* sethi $ta, label */
464440a403fSchristos 	INSN_ORI_TA,	/* ori $ta, $ta, label */
465440a403fSchristos 	INSN_JR_TA	/* jr $ta */
466*b88e3e88Schristos       },
467*b88e3e88Schristos     .relax_code_size[BR_RANGE_U4G] = 12,
468*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_U4G] = 4,
469*b88e3e88Schristos     .relax_fixup[BR_RANGE_U4G] =
470440a403fSchristos       {
471440a403fSchristos 	{0, 4, 0, BFD_RELOC_NDS32_HI20},
472440a403fSchristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP4},
473440a403fSchristos 	{4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI},
474440a403fSchristos 	{4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
475440a403fSchristos 	{8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
476440a403fSchristos 	{8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
477440a403fSchristos 	{8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
478440a403fSchristos 	{0, 0, 0, 0}
479*b88e3e88Schristos       },
480440a403fSchristos   },
481440a403fSchristos   {
482*b88e3e88Schristos     .opcode = "j8",
483*b88e3e88Schristos     .br_range = BR_RANGE_S256,
484*b88e3e88Schristos     .cond_field =
485440a403fSchristos       {
486*b88e3e88Schristos 	{0, 0, 0, FALSE}
487*b88e3e88Schristos       },
488*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S256] =
489440a403fSchristos       {
490440a403fSchristos 	(INSN_J8 << 16)	/* j8 label */
491*b88e3e88Schristos       },
492*b88e3e88Schristos     .relax_code_size[BR_RANGE_S256] = 2,
493*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S256] = 2,
494*b88e3e88Schristos     .relax_fixup[BR_RANGE_S256] =
495*b88e3e88Schristos       {
496*b88e3e88Schristos 	{0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
497*b88e3e88Schristos 	{0, 0, 0, 0}
498*b88e3e88Schristos       },
499*b88e3e88Schristos 
500*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16K] =
501440a403fSchristos       {
502440a403fSchristos 	INSN_J		/* j label */
503*b88e3e88Schristos       },
504*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16K] = 4,
505*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16K] = 4,
506*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16K] =
507*b88e3e88Schristos       {
508*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
509*b88e3e88Schristos 	{0, 0, 0, 0}
510*b88e3e88Schristos       },
511*b88e3e88Schristos 
512*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S64K] =
513440a403fSchristos       {
514440a403fSchristos 	INSN_J		/* j label */
515*b88e3e88Schristos       },
516*b88e3e88Schristos     .relax_code_size[BR_RANGE_S64K] = 4,
517*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S64K] = 4,
518*b88e3e88Schristos     .relax_fixup[BR_RANGE_S64K] =
519*b88e3e88Schristos       {
520*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
521*b88e3e88Schristos 	{0, 0, 0, 0}
522*b88e3e88Schristos       },
523*b88e3e88Schristos 
524*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16M] =
525440a403fSchristos       {
526440a403fSchristos 	INSN_J		/* j label */
527*b88e3e88Schristos       },
528*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16M] = 4,
529*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16M] = 4,
530*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16M] =
531*b88e3e88Schristos       {
532*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
533*b88e3e88Schristos 	{0, 0, 0, 0}
534*b88e3e88Schristos       },
535*b88e3e88Schristos 
536*b88e3e88Schristos     .relax_code_seq[BR_RANGE_U4G] =
537440a403fSchristos       {
538440a403fSchristos 	INSN_SETHI_TA,	/* sethi $ta, label */
539440a403fSchristos 	INSN_ORI_TA,	/* ori $ta, $ta, label */
540440a403fSchristos 	INSN_JR_TA	/* jr $ta */
541*b88e3e88Schristos       },
542*b88e3e88Schristos     .relax_code_size[BR_RANGE_U4G] = 12,
543*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_U4G] = 4,
544*b88e3e88Schristos     .relax_fixup[BR_RANGE_U4G] =
545440a403fSchristos       {
546440a403fSchristos 	{0, 4, 0, BFD_RELOC_NDS32_HI20},
547440a403fSchristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP4},
548440a403fSchristos 	{4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI},
549440a403fSchristos 	{4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
550440a403fSchristos 	{8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
551440a403fSchristos 	{8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
552440a403fSchristos 	{8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
553440a403fSchristos 	{0, 0, 0, 0}
554*b88e3e88Schristos       },
555440a403fSchristos   },
556440a403fSchristos   {
557*b88e3e88Schristos     .opcode = "beqz",
558*b88e3e88Schristos     .br_range = BR_RANGE_S64K,
559*b88e3e88Schristos     .cond_field =
560440a403fSchristos       {
561440a403fSchristos 	{0, 20, 0x1F, FALSE},
562440a403fSchristos 	{0, 0, 0, FALSE}
563*b88e3e88Schristos       },
564*b88e3e88Schristos     /* We do not use beqz38 and beqzs8 here directly because we
565*b88e3e88Schristos        don't want to check register number for specail condition.  */
566*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S256] =
567440a403fSchristos       {
568440a403fSchristos 	  INSN_BEQZ	/* beqz $rt, label */
569*b88e3e88Schristos       },
570*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S256] =
571*b88e3e88Schristos       {
572*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
573*b88e3e88Schristos 	{0, 0, 0, FALSE},
574*b88e3e88Schristos       },
575*b88e3e88Schristos     .relax_code_size[BR_RANGE_S256] = 4,
576*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S256] = 4,
577*b88e3e88Schristos     .relax_fixup[BR_RANGE_S256] =
578*b88e3e88Schristos       {
579*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
580*b88e3e88Schristos 	{0, 4, NDS32_INSN16 , BFD_RELOC_NDS32_INSN16},
581*b88e3e88Schristos 	{0, 0, 0, 0}
582*b88e3e88Schristos       },
583*b88e3e88Schristos 
584*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16K] =
585440a403fSchristos       {
586440a403fSchristos 	INSN_BEQZ	/* beqz $rt, label */
587*b88e3e88Schristos       },
588*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16K] =
589*b88e3e88Schristos       {
590*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
591*b88e3e88Schristos 	{0, 0, 0, FALSE},
592*b88e3e88Schristos       },
593*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16K] = 4,
594*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16K] = 4,
595*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16K] =
596*b88e3e88Schristos       {
597*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
598*b88e3e88Schristos 	{0, 0, 0, 0}
599*b88e3e88Schristos       },
600*b88e3e88Schristos 
601*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S64K] =
602440a403fSchristos       {
603440a403fSchristos 	INSN_BEQZ	/* beqz $rt, label */
604*b88e3e88Schristos       },
605*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S64K] =
606*b88e3e88Schristos       {
607*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
608*b88e3e88Schristos 	{0, 0, 0, FALSE},
609*b88e3e88Schristos       },
610*b88e3e88Schristos     .relax_code_size[BR_RANGE_S64K] = 4,
611*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S64K] = 4,
612*b88e3e88Schristos     .relax_fixup[BR_RANGE_S64K] =
613*b88e3e88Schristos       {
614*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
615*b88e3e88Schristos 	{0, 0, 0, 0}
616*b88e3e88Schristos       },
617*b88e3e88Schristos 
618*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16M] =
619440a403fSchristos       {
620440a403fSchristos 	INSN_BNEZ,	/* bnez $rt, $1 */
621440a403fSchristos 	INSN_J		/* j label */
622*b88e3e88Schristos       },
623*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16M] =
624*b88e3e88Schristos       {
625*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
626*b88e3e88Schristos 	{0, 0, 0, FALSE},
627*b88e3e88Schristos       },
628*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16M] = 8,
629*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16M] = 4,
630*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16M] =
631*b88e3e88Schristos       {
632*b88e3e88Schristos 	/* bnez range is 17 pcrel, but it use 15 pcrel here since link time
633*b88e3e88Schristos 	   relaxtion.  If 17 pcrel can reach, it do not have to use S16M.
634*b88e3e88Schristos 	   Therefore, 15 pcrel is just for linker to distinguish LONGJUMP5
635*b88e3e88Schristos 	   and LONGJUMP6.  */
636*b88e3e88Schristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
637*b88e3e88Schristos 	{0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
638*b88e3e88Schristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
639*b88e3e88Schristos 	{4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
640*b88e3e88Schristos 	{4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
641*b88e3e88Schristos 	{0, 0, 0, 0}
642*b88e3e88Schristos       },
643*b88e3e88Schristos 
644*b88e3e88Schristos     .relax_code_seq[BR_RANGE_U4G] =
645440a403fSchristos       {
646440a403fSchristos 	INSN_BNEZ,	/* bnez $rt, $1 */
647440a403fSchristos 	INSN_SETHI_TA,	/* sethi $ta, label */
648440a403fSchristos 	INSN_ORI_TA,	/* ori $ta, $ta, label */
649440a403fSchristos 	INSN_JR_TA	/* jr $ta */
650*b88e3e88Schristos       },
651*b88e3e88Schristos     .relax_code_condition[BR_RANGE_U4G] =
652440a403fSchristos       {
653440a403fSchristos 	{0, 20, 0x1F, FALSE},
654*b88e3e88Schristos 	{0, 0, 0, FALSE},
655*b88e3e88Schristos       },
656*b88e3e88Schristos     .relax_code_size[BR_RANGE_U4G] = 16,
657*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_U4G] = 4,
658*b88e3e88Schristos     .relax_fixup[BR_RANGE_U4G] =
659440a403fSchristos       {
660440a403fSchristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
661440a403fSchristos 	{0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
662440a403fSchristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
663440a403fSchristos 	{4, 4, 0, BFD_RELOC_NDS32_HI20},
664440a403fSchristos 	{4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
665440a403fSchristos 	{8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
666440a403fSchristos 	{8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
667440a403fSchristos 	{12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
668440a403fSchristos 	{12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
669440a403fSchristos 	{12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
670440a403fSchristos 	{0, 0, 0, 0}
671*b88e3e88Schristos       },
672440a403fSchristos   },
673440a403fSchristos   {
674*b88e3e88Schristos     .opcode = "bgez",
675*b88e3e88Schristos     .br_range = BR_RANGE_S64K,
676*b88e3e88Schristos     .cond_field =
677440a403fSchristos       {
678440a403fSchristos 	{0, 20, 0x1F, FALSE},
679440a403fSchristos 	{0, 0, 0, FALSE}
680*b88e3e88Schristos       },
681*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S256] =
682440a403fSchristos       {
683440a403fSchristos 	INSN_BGEZ	/* bgez $rt, label */
684*b88e3e88Schristos       },
685*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S256] =
686*b88e3e88Schristos       {
687*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
688*b88e3e88Schristos 	{0, 0, 0, FALSE},
689*b88e3e88Schristos       },
690*b88e3e88Schristos     .relax_code_size[BR_RANGE_S256] = 4,
691*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S256] = 4,
692*b88e3e88Schristos     .relax_fixup[BR_RANGE_S256] =
693*b88e3e88Schristos       {
694*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
695*b88e3e88Schristos 	{0, 0, 0, 0}
696*b88e3e88Schristos       },
697*b88e3e88Schristos 
698*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16K] =
699440a403fSchristos       {
700440a403fSchristos 	INSN_BGEZ	/* bgez $rt, label */
701*b88e3e88Schristos       },
702*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16K] =
703*b88e3e88Schristos       {
704*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
705*b88e3e88Schristos 	{0, 0, 0, FALSE},
706*b88e3e88Schristos       },
707*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16K] = 4,
708*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16K] = 4,
709*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16K] =
710*b88e3e88Schristos       {
711*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
712*b88e3e88Schristos 	{0, 0, 0, 0}
713*b88e3e88Schristos       },
714*b88e3e88Schristos 
715*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S64K] =
716440a403fSchristos       {
717440a403fSchristos 	INSN_BGEZ	/* bgez $rt, label */
718*b88e3e88Schristos       },
719*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S64K] =
720*b88e3e88Schristos       {
721*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
722*b88e3e88Schristos 	{0, 0, 0, FALSE},
723*b88e3e88Schristos       },
724*b88e3e88Schristos     .relax_code_size[BR_RANGE_S64K] = 4,
725*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S64K] = 4,
726*b88e3e88Schristos     .relax_fixup[BR_RANGE_S64K] =
727*b88e3e88Schristos       {
728*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
729*b88e3e88Schristos 	{0, 0, 0, 0}
730*b88e3e88Schristos       },
731*b88e3e88Schristos 
732*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16M] =
733440a403fSchristos       {
734440a403fSchristos 	INSN_BLTZ,	/* bltz $rt, $1 */
735440a403fSchristos 	INSN_J		/* j label */
736*b88e3e88Schristos       },
737*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16M] =
738*b88e3e88Schristos       {
739*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
740*b88e3e88Schristos 	{0, 0, 0, FALSE},
741*b88e3e88Schristos       },
742*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16M] = 8,
743*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16M] = 4,
744*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16M] =
745*b88e3e88Schristos       {
746*b88e3e88Schristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
747*b88e3e88Schristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
748*b88e3e88Schristos 	{4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
749*b88e3e88Schristos 	{0, 0, 0, 0}
750*b88e3e88Schristos       },
751*b88e3e88Schristos     .relax_code_seq[BR_RANGE_U4G] =
752440a403fSchristos       {
753440a403fSchristos 	INSN_BLTZ,	/* bltz $rt, $1 */
754440a403fSchristos 	INSN_SETHI_TA,	/* sethi $ta, label */
755440a403fSchristos 	INSN_ORI_TA,	/* ori $ta, $ta, label */
756440a403fSchristos 	INSN_JR_TA	/* jr $ta */
757*b88e3e88Schristos       },
758*b88e3e88Schristos     .relax_code_condition[BR_RANGE_U4G] =
759440a403fSchristos       {
760440a403fSchristos 	{0, 20, 0x1F, FALSE},
761*b88e3e88Schristos 	{0, 0, 0, FALSE},
762*b88e3e88Schristos       },
763*b88e3e88Schristos     .relax_code_size[BR_RANGE_U4G] = 16,
764*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_U4G] = 4,
765*b88e3e88Schristos     .relax_fixup[BR_RANGE_U4G] =
766440a403fSchristos       {
767440a403fSchristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
768440a403fSchristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
769440a403fSchristos 	{4, 4, 0, BFD_RELOC_NDS32_HI20},
770440a403fSchristos 	{4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
771440a403fSchristos 	{8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
772440a403fSchristos 	{8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
773440a403fSchristos 	{12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
774440a403fSchristos 	{12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
775440a403fSchristos 	{12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
776440a403fSchristos 	{0, 0, 0, 0}
777*b88e3e88Schristos       },
778440a403fSchristos   },
779440a403fSchristos   {
780*b88e3e88Schristos     .opcode = "bnez",
781*b88e3e88Schristos     .br_range = BR_RANGE_S64K,
782*b88e3e88Schristos     .cond_field =
783440a403fSchristos       {
784440a403fSchristos 	{0, 20, 0x1F, FALSE},
785440a403fSchristos 	{0, 0, 0, FALSE}
786*b88e3e88Schristos       },
787*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S256] =
788440a403fSchristos       {
789440a403fSchristos 	INSN_BNEZ	/* bnez $rt, label */
790*b88e3e88Schristos       },
791*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S256] =
792*b88e3e88Schristos       {
793*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
794*b88e3e88Schristos 	{0, 0, 0, FALSE},
795*b88e3e88Schristos       },
796*b88e3e88Schristos     .relax_code_size[BR_RANGE_S256] = 4,
797*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S256] = 4,
798*b88e3e88Schristos     .relax_fixup[BR_RANGE_S256] =
799*b88e3e88Schristos       {
800*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
801*b88e3e88Schristos 	{0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
802*b88e3e88Schristos 	{0, 0, 0, 0}
803*b88e3e88Schristos       },
804*b88e3e88Schristos 
805*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16K] =
806440a403fSchristos       {
807440a403fSchristos 	INSN_BNEZ	/* bnez $rt, label */
808*b88e3e88Schristos       },
809*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16K] =
810*b88e3e88Schristos       {
811*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
812*b88e3e88Schristos 	{0, 0, 0, FALSE},
813*b88e3e88Schristos       },
814*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16K] = 4,
815*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16K] = 4,
816*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16K] =
817*b88e3e88Schristos       {
818*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
819*b88e3e88Schristos 	{0, 0, 0, 0}
820*b88e3e88Schristos       },
821*b88e3e88Schristos 
822*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S64K] =
823440a403fSchristos       {
824440a403fSchristos 	INSN_BNEZ	/* bnez $rt, label */
825*b88e3e88Schristos       },
826*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S64K] =
827*b88e3e88Schristos       {
828*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
829*b88e3e88Schristos 	{0, 0, 0, FALSE},
830*b88e3e88Schristos       },
831*b88e3e88Schristos     .relax_code_size[BR_RANGE_S64K] = 4,
832*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S64K] = 4,
833*b88e3e88Schristos     .relax_fixup[BR_RANGE_S64K] =
834*b88e3e88Schristos       {
835*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
836*b88e3e88Schristos 	{0, 0, 0, 0}
837*b88e3e88Schristos       },
838*b88e3e88Schristos 
839*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16M] =
840440a403fSchristos       {
841440a403fSchristos 	INSN_BEQZ,	/* beqz $rt, $1 */
842440a403fSchristos 	INSN_J		/* j label */
843*b88e3e88Schristos       },
844*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16M] =
845*b88e3e88Schristos       {
846*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
847*b88e3e88Schristos 	{0, 0, 0, FALSE},
848*b88e3e88Schristos       },
849*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16M] = 8,
850*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16M] = 4,
851*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16M] =
852*b88e3e88Schristos       {
853*b88e3e88Schristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
854*b88e3e88Schristos 	{0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
855*b88e3e88Schristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
856*b88e3e88Schristos 	{4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
857*b88e3e88Schristos 	{4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
858*b88e3e88Schristos 	{0, 0, 0, 0}
859*b88e3e88Schristos       },
860*b88e3e88Schristos 
861*b88e3e88Schristos     .relax_code_seq[BR_RANGE_U4G] =
862440a403fSchristos       {
863440a403fSchristos 	INSN_BEQZ,	/* beqz $rt, $1 */
864440a403fSchristos 	INSN_SETHI_TA,	/* sethi $ta, label */
865440a403fSchristos 	INSN_ORI_TA,	/* ori $ta, $ta, label */
866440a403fSchristos 	INSN_JR_TA	/* jr $ta */
867*b88e3e88Schristos       },
868*b88e3e88Schristos     .relax_code_condition[BR_RANGE_U4G] =
869440a403fSchristos       {
870440a403fSchristos 	{0, 20, 0x1F, FALSE},
871*b88e3e88Schristos 	{0, 0, 0, FALSE},
872*b88e3e88Schristos       },
873*b88e3e88Schristos     .relax_code_size[BR_RANGE_U4G] = 16,
874*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_U4G] = 4,
875*b88e3e88Schristos     .relax_fixup[BR_RANGE_U4G] =
876440a403fSchristos       {
877440a403fSchristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
878440a403fSchristos 	{0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
879440a403fSchristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
880440a403fSchristos 	{4, 4, 0, BFD_RELOC_NDS32_HI20},
881440a403fSchristos 	{4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
882440a403fSchristos 	{8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
883440a403fSchristos 	{8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
884440a403fSchristos 	{12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
885440a403fSchristos 	{12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
886440a403fSchristos 	{12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
887440a403fSchristos 	{0, 0, 0, 0}
888*b88e3e88Schristos       },
889440a403fSchristos   },
890440a403fSchristos   {
891*b88e3e88Schristos     .opcode = "bgtz",
892*b88e3e88Schristos     .br_range = BR_RANGE_S64K,
893*b88e3e88Schristos     .cond_field =
894440a403fSchristos       {
895440a403fSchristos 	{0, 20, 0x1F, FALSE},
896440a403fSchristos 	{0, 0, 0, FALSE}
897*b88e3e88Schristos       },
898*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S256] =
899440a403fSchristos       {
900440a403fSchristos 	INSN_BGTZ	/* bgtz $rt, label */
901*b88e3e88Schristos       },
902*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S256] =
903*b88e3e88Schristos       {
904*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
905*b88e3e88Schristos 	{0, 0, 0, FALSE},
906*b88e3e88Schristos       },
907*b88e3e88Schristos     .relax_code_size[BR_RANGE_S256] = 4,
908*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S256] = 4,
909*b88e3e88Schristos     .relax_fixup[BR_RANGE_S256] =
910*b88e3e88Schristos       {
911*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
912*b88e3e88Schristos 	{0, 0, 0, 0}
913*b88e3e88Schristos       },
914*b88e3e88Schristos 
915*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16K] =
916440a403fSchristos       {
917440a403fSchristos 	INSN_BGTZ	/* bgtz $rt, label */
918*b88e3e88Schristos       },
919*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16K] =
920*b88e3e88Schristos       {
921*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
922*b88e3e88Schristos 	{0, 0, 0, FALSE},
923*b88e3e88Schristos       },
924*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16K] = 4,
925*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16K] = 4,
926*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16K] =
927*b88e3e88Schristos       {
928*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
929*b88e3e88Schristos 	{0, 0, 0, 0}
930*b88e3e88Schristos       },
931*b88e3e88Schristos 
932*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S64K] =
933440a403fSchristos       {
934440a403fSchristos 	INSN_BGTZ	/* bgtz $rt, label */
935*b88e3e88Schristos       },
936*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S64K] =
937*b88e3e88Schristos       {
938*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
939*b88e3e88Schristos 	{0, 0, 0, FALSE},
940*b88e3e88Schristos       },
941*b88e3e88Schristos     .relax_code_size[BR_RANGE_S64K] = 4,
942*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S64K] = 4,
943*b88e3e88Schristos     .relax_fixup[BR_RANGE_S64K] =
944*b88e3e88Schristos       {
945*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
946*b88e3e88Schristos 	{0, 0, 0, 0}
947*b88e3e88Schristos       },
948*b88e3e88Schristos 
949*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16M] =
950440a403fSchristos       {
951440a403fSchristos 	INSN_BLEZ,	/* blez $rt, $1 */
952440a403fSchristos 	INSN_J		/* j label */
953*b88e3e88Schristos       },
954*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16M] =
955*b88e3e88Schristos       {
956*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
957*b88e3e88Schristos 	{0, 0, 0, FALSE},
958*b88e3e88Schristos       },
959*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16M] = 8,
960*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16M] = 4,
961*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16M] =
962*b88e3e88Schristos       {
963*b88e3e88Schristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
964*b88e3e88Schristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
965*b88e3e88Schristos 	{4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
966*b88e3e88Schristos 	{0, 0, 0, 0}
967*b88e3e88Schristos       },
968*b88e3e88Schristos 
969*b88e3e88Schristos     .relax_code_seq[BR_RANGE_U4G] =
970440a403fSchristos       {
971440a403fSchristos 	INSN_BLEZ,	/* blez $rt, $1 */
972440a403fSchristos 	INSN_SETHI_TA,	/* sethi $ta, label */
973440a403fSchristos 	INSN_ORI_TA,	/* ori $ta, $ta, label */
974440a403fSchristos 	INSN_JR_TA	/* jr $ta */
975*b88e3e88Schristos       },
976*b88e3e88Schristos     .relax_code_condition[BR_RANGE_U4G] =
977440a403fSchristos       {
978440a403fSchristos 	{0, 20, 0x1F, FALSE},
979*b88e3e88Schristos 	{0, 0, 0, FALSE},
980*b88e3e88Schristos       },
981*b88e3e88Schristos     .relax_code_size[BR_RANGE_U4G] = 16,
982*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_U4G] = 4,
983*b88e3e88Schristos     .relax_fixup[BR_RANGE_U4G] =
984440a403fSchristos       {
985440a403fSchristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
986440a403fSchristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
987440a403fSchristos 	{4, 4, 0, BFD_RELOC_NDS32_HI20},
988440a403fSchristos 	{4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
989440a403fSchristos 	{8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
990440a403fSchristos 	{8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
991440a403fSchristos 	{12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
992440a403fSchristos 	{12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
993440a403fSchristos 	{12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
994440a403fSchristos 	{0, 0, 0, 0}
995*b88e3e88Schristos       },
996440a403fSchristos   },
997440a403fSchristos   {
998*b88e3e88Schristos     .opcode = "blez",
999*b88e3e88Schristos     .br_range = BR_RANGE_S64K,
1000*b88e3e88Schristos     .cond_field =
1001440a403fSchristos       {
1002440a403fSchristos 	{0, 20, 0x1F, FALSE},
1003440a403fSchristos 	{0, 0, 0, FALSE}
1004*b88e3e88Schristos       },
1005*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S256] =
1006440a403fSchristos       {
1007440a403fSchristos 	INSN_BLEZ	/* blez $rt, label */
1008*b88e3e88Schristos       },
1009*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S256] =
1010*b88e3e88Schristos       {
1011*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1012*b88e3e88Schristos 	{0, 0, 0, FALSE},
1013*b88e3e88Schristos       },
1014*b88e3e88Schristos     .relax_code_size[BR_RANGE_S256] = 4,
1015*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S256] = 4,
1016*b88e3e88Schristos     .relax_fixup[BR_RANGE_S256] =
1017*b88e3e88Schristos       {
1018*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1019*b88e3e88Schristos 	{0, 0, 0, 0}
1020*b88e3e88Schristos       },
1021*b88e3e88Schristos 
1022*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16K] =
1023440a403fSchristos       {
1024440a403fSchristos 	INSN_BLEZ	/* blez $rt, label */
1025*b88e3e88Schristos       },
1026*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16K] =
1027*b88e3e88Schristos       {
1028*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1029*b88e3e88Schristos 	{0, 0, 0, FALSE},
1030*b88e3e88Schristos       },
1031*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16K] = 4,
1032*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16K] = 4,
1033*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16K] =
1034*b88e3e88Schristos       {
1035*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1036*b88e3e88Schristos 	{0, 0, 0, 0}
1037*b88e3e88Schristos       },
1038*b88e3e88Schristos 
1039*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S64K] =
1040440a403fSchristos       {
1041440a403fSchristos 	INSN_BLEZ	/* blez $rt, label */
1042*b88e3e88Schristos       },
1043*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S64K] =
1044*b88e3e88Schristos       {
1045*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1046*b88e3e88Schristos 	{0, 0, 0, FALSE},
1047*b88e3e88Schristos       },
1048*b88e3e88Schristos     .relax_code_size[BR_RANGE_S64K] = 4,
1049*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S64K] = 4,
1050*b88e3e88Schristos     .relax_fixup[BR_RANGE_S64K] =
1051*b88e3e88Schristos       {
1052*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1053*b88e3e88Schristos 	{0, 0, 0, 0}
1054*b88e3e88Schristos       },
1055*b88e3e88Schristos 
1056*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16M] =
1057440a403fSchristos       {
1058440a403fSchristos 	INSN_BGTZ,	/* bgtz $rt, $1 */
1059440a403fSchristos 	INSN_J		/* j label */
1060*b88e3e88Schristos       },
1061*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16M] =
1062*b88e3e88Schristos       {
1063*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1064*b88e3e88Schristos 	{0, 0, 0, FALSE},
1065*b88e3e88Schristos       },
1066*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16M] = 8,
1067*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16M] = 4,
1068*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16M] =
1069*b88e3e88Schristos       {
1070*b88e3e88Schristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1071*b88e3e88Schristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1072*b88e3e88Schristos 	{4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1073*b88e3e88Schristos 	{0, 0, 0, 0}
1074*b88e3e88Schristos       },
1075*b88e3e88Schristos 
1076*b88e3e88Schristos     .relax_code_seq[BR_RANGE_U4G] =
1077440a403fSchristos       {
1078440a403fSchristos 	INSN_BGTZ,	/* bgtz $rt, $1 */
1079440a403fSchristos 	INSN_SETHI_TA,	/* sethi $ta, label */
1080440a403fSchristos 	INSN_ORI_TA,	/* ori $ta, $ta, label */
1081440a403fSchristos 	INSN_JR_TA	/* jr $ta */
1082*b88e3e88Schristos       },
1083*b88e3e88Schristos     .relax_code_condition[BR_RANGE_U4G] =
1084440a403fSchristos       {
1085440a403fSchristos 	{0, 20, 0x1F, FALSE},
1086*b88e3e88Schristos 	{0, 0, 0, FALSE},
1087*b88e3e88Schristos       },
1088*b88e3e88Schristos     .relax_code_size[BR_RANGE_U4G] = 16,
1089*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_U4G] = 4,
1090*b88e3e88Schristos     .relax_fixup[BR_RANGE_U4G] =
1091440a403fSchristos       {
1092440a403fSchristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1093440a403fSchristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1094440a403fSchristos 	{4, 4, 0, BFD_RELOC_NDS32_HI20},
1095440a403fSchristos 	{4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1096440a403fSchristos 	{8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1097440a403fSchristos 	{8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1098440a403fSchristos 	{12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1099440a403fSchristos 	{12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1100440a403fSchristos 	{12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1101440a403fSchristos 	{0, 0, 0, 0}
1102*b88e3e88Schristos       },
1103440a403fSchristos   },
1104440a403fSchristos   {
1105*b88e3e88Schristos     .opcode = "bltz",
1106*b88e3e88Schristos     .br_range = BR_RANGE_S64K,
1107*b88e3e88Schristos     .cond_field =
1108440a403fSchristos       {
1109440a403fSchristos 	{0, 20, 0x1F, FALSE},
1110440a403fSchristos 	{0, 0, 0, FALSE}
1111*b88e3e88Schristos       },
1112*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S256] =
1113440a403fSchristos       {
1114440a403fSchristos 	INSN_BLTZ	/* bltz $rt, label */
1115*b88e3e88Schristos       },
1116*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S256] =
1117*b88e3e88Schristos       {
1118*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1119*b88e3e88Schristos 	{0, 0, 0, FALSE},
1120*b88e3e88Schristos       },
1121*b88e3e88Schristos     .relax_code_size[BR_RANGE_S256] = 4,
1122*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S256] = 4,
1123*b88e3e88Schristos     .relax_fixup[BR_RANGE_S256] =
1124*b88e3e88Schristos       {
1125*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1126*b88e3e88Schristos 	{0, 0, 0, 0}
1127*b88e3e88Schristos       },
1128*b88e3e88Schristos 
1129*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16K] =
1130440a403fSchristos       {
1131440a403fSchristos 	INSN_BLTZ	/* bltz $rt, label */
1132*b88e3e88Schristos       },
1133*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16K] =
1134*b88e3e88Schristos       {
1135*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1136*b88e3e88Schristos 	{0, 0, 0, FALSE},
1137*b88e3e88Schristos       },
1138*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16K] = 4,
1139*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16K] = 4,
1140*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16K] =
1141*b88e3e88Schristos       {
1142*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1143*b88e3e88Schristos 	{0, 0, 0, 0}
1144*b88e3e88Schristos       },
1145*b88e3e88Schristos 
1146*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S64K] =
1147440a403fSchristos       {
1148440a403fSchristos 	INSN_BLTZ	/* bltz $rt, label */
1149*b88e3e88Schristos       },
1150*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S64K] =
1151*b88e3e88Schristos       {
1152*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1153*b88e3e88Schristos 	{0, 0, 0, FALSE},
1154*b88e3e88Schristos       },
1155*b88e3e88Schristos     .relax_code_size[BR_RANGE_S64K] = 4,
1156*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S64K] = 4,
1157*b88e3e88Schristos     .relax_fixup[BR_RANGE_S64K] =
1158*b88e3e88Schristos       {
1159*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1160*b88e3e88Schristos 	{0, 0, 0, 0}
1161*b88e3e88Schristos       },
1162*b88e3e88Schristos 
1163*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16M] =
1164440a403fSchristos       {
1165440a403fSchristos 	INSN_BGEZ,	/* bgez $rt, $1 */
1166440a403fSchristos 	INSN_J		/* j label */
1167*b88e3e88Schristos       },
1168*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16M] =
1169*b88e3e88Schristos       {
1170*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1171*b88e3e88Schristos 	{0, 0, 0, FALSE},
1172*b88e3e88Schristos       },
1173*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16M] = 8,
1174*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16M] = 4,
1175*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16M] =
1176*b88e3e88Schristos       {
1177*b88e3e88Schristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1178*b88e3e88Schristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1179*b88e3e88Schristos 	{4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1180*b88e3e88Schristos 	{0, 0, 0, 0}
1181*b88e3e88Schristos       },
1182*b88e3e88Schristos 
1183*b88e3e88Schristos     .relax_code_seq[BR_RANGE_U4G] =
1184440a403fSchristos       {
1185440a403fSchristos 	INSN_BGEZ,	/* bgez $rt, $1 */
1186440a403fSchristos 	INSN_SETHI_TA,	/* sethi $ta, label */
1187440a403fSchristos 	INSN_ORI_TA,	/* ori $ta, $ta, label */
1188440a403fSchristos 	INSN_JR_TA	/* jr $ta */
1189*b88e3e88Schristos       },
1190*b88e3e88Schristos     .relax_code_condition[BR_RANGE_U4G] =
1191440a403fSchristos       {
1192440a403fSchristos 	{0, 20, 0x1F, FALSE},
1193*b88e3e88Schristos 	{0, 0, 0, FALSE},
1194*b88e3e88Schristos       },
1195*b88e3e88Schristos     .relax_code_size[BR_RANGE_U4G] = 16,
1196*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_U4G] = 4,
1197*b88e3e88Schristos     .relax_fixup[BR_RANGE_U4G] =
1198440a403fSchristos       {
1199440a403fSchristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1200440a403fSchristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1201440a403fSchristos 	{4, 4, 0, BFD_RELOC_NDS32_HI20},
1202440a403fSchristos 	{4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1203440a403fSchristos 	{8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1204440a403fSchristos 	{8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1205440a403fSchristos 	{12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1206440a403fSchristos 	{12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1207440a403fSchristos 	{12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1208440a403fSchristos 	{0, 0, 0, 0}
1209*b88e3e88Schristos       },
1210440a403fSchristos   },
1211440a403fSchristos   {
1212*b88e3e88Schristos     .opcode = "beq",
1213*b88e3e88Schristos     .br_range = BR_RANGE_S16K,
1214*b88e3e88Schristos     .cond_field =
1215440a403fSchristos       {
1216440a403fSchristos 	{0, 20, 0x1F, FALSE},
1217440a403fSchristos 	{0, 15, 0x1F, FALSE},
1218440a403fSchristos 	{0, 0, 0, FALSE}
1219*b88e3e88Schristos       },
1220*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S256] =
1221440a403fSchristos       {
1222440a403fSchristos 	INSN_BEQ	/* beq $rt, $ra, label */
1223*b88e3e88Schristos       },
1224*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S256] =
1225*b88e3e88Schristos       {
1226*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1227*b88e3e88Schristos 	{0, 15, 0x1F, FALSE},
1228*b88e3e88Schristos 	{0, 0, 0, FALSE}
1229*b88e3e88Schristos       },
1230*b88e3e88Schristos     .relax_code_size[BR_RANGE_S256] = 4,
1231*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S256] = 4,
1232*b88e3e88Schristos     .relax_fixup[BR_RANGE_S256] =
1233*b88e3e88Schristos       {
1234*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1235*b88e3e88Schristos 	{0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
1236*b88e3e88Schristos 	{0, 0, 0, 0}
1237*b88e3e88Schristos       },
1238*b88e3e88Schristos 
1239*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16K] =
1240440a403fSchristos       {
1241440a403fSchristos 	INSN_BEQ	/* beq $rt, $ra, label */
1242*b88e3e88Schristos       },
1243*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16K] =
1244*b88e3e88Schristos       {
1245*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1246*b88e3e88Schristos 	{0, 15, 0x1F, FALSE},
1247*b88e3e88Schristos 	{0, 0, 0, FALSE}
1248*b88e3e88Schristos       },
1249*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16K] = 4,
1250*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16K] = 4,
1251*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16K] =
1252*b88e3e88Schristos       {
1253*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1254*b88e3e88Schristos 	{0, 0, 0, 0}
1255*b88e3e88Schristos       },
1256*b88e3e88Schristos 
1257*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S64K] =
1258440a403fSchristos       {
1259440a403fSchristos 	INSN_BNE,	/* bne $rt, $ra, $1 */
1260440a403fSchristos 	INSN_J		/* j label */
1261*b88e3e88Schristos       },
1262*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S64K] =
1263*b88e3e88Schristos       {
1264*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1265*b88e3e88Schristos 	{0, 15, 0x1F, FALSE},
1266*b88e3e88Schristos 	{0, 0, 0, FALSE}
1267*b88e3e88Schristos       },
1268*b88e3e88Schristos     .relax_code_size[BR_RANGE_S64K] = 8,
1269*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S64K] = 4,
1270*b88e3e88Schristos     .relax_fixup[BR_RANGE_S64K] =
1271*b88e3e88Schristos       {
1272*b88e3e88Schristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1273*b88e3e88Schristos 	{0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1274*b88e3e88Schristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1275*b88e3e88Schristos 	{4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1276*b88e3e88Schristos 	{4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1277*b88e3e88Schristos 	{0, 0, 0, 0}
1278*b88e3e88Schristos       },
1279*b88e3e88Schristos 
1280*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16M] =
1281440a403fSchristos       {
1282440a403fSchristos 	INSN_BNE,	/* bne $rt, $ra, $1 */
1283440a403fSchristos 	INSN_J		/* j label */
1284*b88e3e88Schristos       },
1285*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16M] =
1286*b88e3e88Schristos       {
1287*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1288*b88e3e88Schristos 	{0, 15, 0x1F, FALSE},
1289*b88e3e88Schristos 	{0, 0, 0, FALSE}
1290*b88e3e88Schristos       },
1291*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16M] = 8,
1292*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16M] = 4,
1293*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16M] =
1294*b88e3e88Schristos       {
1295*b88e3e88Schristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1296*b88e3e88Schristos 	{0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1297*b88e3e88Schristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1298*b88e3e88Schristos 	{4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1299*b88e3e88Schristos 	{4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1300*b88e3e88Schristos 	{0, 0, 0, 0}
1301*b88e3e88Schristos       },
1302*b88e3e88Schristos 
1303*b88e3e88Schristos     .relax_code_seq[BR_RANGE_U4G] =
1304440a403fSchristos       {
1305440a403fSchristos 	INSN_BNE,	/* bne $rt, $ra, $1 */
1306440a403fSchristos 	INSN_SETHI_TA,	/* sethi $ta, label */
1307440a403fSchristos 	INSN_ORI_TA,	/* ori $ta, $ta, label */
1308440a403fSchristos 	INSN_JR_TA	/* jr $ta */
1309*b88e3e88Schristos       },
1310*b88e3e88Schristos     .relax_code_condition[BR_RANGE_U4G] =
1311440a403fSchristos       {
1312440a403fSchristos 	{0, 20, 0x1F, FALSE},
1313440a403fSchristos 	{0, 15, 0x1F, FALSE},
1314440a403fSchristos 	{0, 0, 0, FALSE}
1315*b88e3e88Schristos       },
1316*b88e3e88Schristos     .relax_code_size[BR_RANGE_U4G] = 16,
1317*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_U4G] = 4,
1318*b88e3e88Schristos     .relax_fixup[BR_RANGE_U4G] =
1319440a403fSchristos       {
1320440a403fSchristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1321440a403fSchristos 	{0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1322440a403fSchristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1323440a403fSchristos 	{4, 4, 0, BFD_RELOC_NDS32_HI20},
1324440a403fSchristos 	{4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1325440a403fSchristos 	{8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1326440a403fSchristos 	{8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1327440a403fSchristos 	{12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1328440a403fSchristos 	{12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1329440a403fSchristos 	{12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1330440a403fSchristos 	{0, 0, 0, 0}
1331*b88e3e88Schristos       },
1332440a403fSchristos   },
1333440a403fSchristos   {
1334*b88e3e88Schristos     .opcode = "bne",
1335*b88e3e88Schristos     .br_range = BR_RANGE_S16K,
1336*b88e3e88Schristos     .cond_field =
1337440a403fSchristos       {
1338440a403fSchristos 	{0, 20, 0x1F, FALSE},
1339440a403fSchristos 	{0, 15, 0x1F, FALSE},
1340440a403fSchristos 	{0, 0, 0, FALSE}
1341*b88e3e88Schristos       },
1342*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S256] =
1343440a403fSchristos       {
1344440a403fSchristos 	INSN_BNE	/* bne $rt, $ra, label */
1345*b88e3e88Schristos       },
1346*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S256] =
1347*b88e3e88Schristos       {
1348*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1349*b88e3e88Schristos 	{0, 15, 0x1F, FALSE},
1350*b88e3e88Schristos 	{0, 0, 0, FALSE}
1351*b88e3e88Schristos       },
1352*b88e3e88Schristos     .relax_code_size[BR_RANGE_S256] = 4,
1353*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S256] = 4,
1354*b88e3e88Schristos     .relax_fixup[BR_RANGE_S256] =
1355*b88e3e88Schristos       {
1356*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1357*b88e3e88Schristos 	{0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
1358*b88e3e88Schristos 	{0, 0, 0, 0}
1359*b88e3e88Schristos       },
1360*b88e3e88Schristos 
1361*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16K] =
1362440a403fSchristos       {
1363440a403fSchristos 	INSN_BNE	/* bne $rt, $ra, label */
1364*b88e3e88Schristos       },
1365*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16K] =
1366*b88e3e88Schristos       {
1367*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1368*b88e3e88Schristos 	{0, 15, 0x1F, FALSE},
1369*b88e3e88Schristos 	{0, 0, 0, FALSE}
1370*b88e3e88Schristos       },
1371*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16K] = 4,
1372*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16K] = 4,
1373*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16K] =
1374*b88e3e88Schristos       {
1375*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1376*b88e3e88Schristos 	{0, 0, 0, 0}
1377*b88e3e88Schristos       },
1378*b88e3e88Schristos 
1379*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S64K] =
1380440a403fSchristos       {
1381440a403fSchristos 	INSN_BEQ,	/* beq $rt, $ra, $1 */
1382440a403fSchristos 	INSN_J		/* j label */
1383*b88e3e88Schristos       },
1384*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S64K] =
1385*b88e3e88Schristos       {
1386*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1387*b88e3e88Schristos 	{0, 15, 0x1F, FALSE},
1388*b88e3e88Schristos 	{0, 0, 0, FALSE}
1389*b88e3e88Schristos       },
1390*b88e3e88Schristos     .relax_code_size[BR_RANGE_S64K] = 8,
1391*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S64K] = 4,
1392*b88e3e88Schristos     .relax_fixup[BR_RANGE_S64K] =
1393*b88e3e88Schristos       {
1394*b88e3e88Schristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1395*b88e3e88Schristos 	{0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1396*b88e3e88Schristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1397*b88e3e88Schristos 	{4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1398*b88e3e88Schristos 	{4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1399*b88e3e88Schristos 	{0, 0, 0, 0}
1400*b88e3e88Schristos       },
1401*b88e3e88Schristos 
1402*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16M] =
1403440a403fSchristos       {
1404440a403fSchristos 	INSN_BEQ,	/* beq $rt, $ra, $1 */
1405440a403fSchristos 	INSN_J		/* j label */
1406*b88e3e88Schristos       },
1407*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16M] =
1408*b88e3e88Schristos       {
1409*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1410*b88e3e88Schristos 	{0, 15, 0x1F, FALSE},
1411*b88e3e88Schristos 	{0, 0, 0, FALSE}
1412*b88e3e88Schristos       },
1413*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16M] = 8,
1414*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16M] = 4,
1415*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16M] =
1416*b88e3e88Schristos       {
1417*b88e3e88Schristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1418*b88e3e88Schristos 	{0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1419*b88e3e88Schristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1420*b88e3e88Schristos 	{4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1421*b88e3e88Schristos 	{4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1422*b88e3e88Schristos 	{0, 0, 0, 0}
1423*b88e3e88Schristos       },
1424*b88e3e88Schristos 
1425*b88e3e88Schristos     .relax_code_seq[BR_RANGE_U4G] =
1426440a403fSchristos       {
1427440a403fSchristos 	INSN_BEQ,	/* beq $rt, $ra, $1 */
1428440a403fSchristos 	INSN_SETHI_TA,	/* sethi $ta, label */
1429440a403fSchristos 	INSN_ORI_TA,	/* ori $ta, $ta, label */
1430440a403fSchristos 	INSN_JR_TA	/* jr $ta */
1431*b88e3e88Schristos       },
1432*b88e3e88Schristos     .relax_code_condition[BR_RANGE_U4G] =
1433440a403fSchristos       {
1434440a403fSchristos 	{0, 20, 0x1F, FALSE},
1435440a403fSchristos 	{0, 15, 0x1F, FALSE},
1436440a403fSchristos 	{0, 0, 0, FALSE}
1437*b88e3e88Schristos       },
1438*b88e3e88Schristos     .relax_code_size[BR_RANGE_U4G] = 16,
1439*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_U4G] = 4,
1440*b88e3e88Schristos     .relax_fixup[BR_RANGE_U4G] =
1441440a403fSchristos       {
1442440a403fSchristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1443440a403fSchristos 	{0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1444440a403fSchristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1445440a403fSchristos 	{4, 4, 0, BFD_RELOC_NDS32_HI20},
1446440a403fSchristos 	{4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1447440a403fSchristos 	{8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1448440a403fSchristos 	{8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1449440a403fSchristos 	{12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1450440a403fSchristos 	{12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1451440a403fSchristos 	{12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1452440a403fSchristos 	{0, 0, 0, 0}
1453*b88e3e88Schristos       },
1454440a403fSchristos   },
1455440a403fSchristos   {
1456*b88e3e88Schristos     .opcode = "beqz38",
1457*b88e3e88Schristos     .br_range = BR_RANGE_S256,
1458*b88e3e88Schristos     .cond_field =
1459440a403fSchristos       {
1460440a403fSchristos 	{0, 8, 0x7, FALSE},
1461440a403fSchristos 	{0, 0, 0, FALSE}
1462*b88e3e88Schristos       },
1463*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S256] =
1464440a403fSchristos       {
1465440a403fSchristos 	INSN_BEQZ38 << 16	/* beqz $rt, label */
1466*b88e3e88Schristos       },
1467*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S256] =
1468440a403fSchristos       {
1469440a403fSchristos 	{0, 8, 0x7, FALSE},
1470440a403fSchristos 	{0, 0, 0, FALSE}
1471*b88e3e88Schristos       },
1472*b88e3e88Schristos     .relax_code_size[BR_RANGE_S256] = 2,
1473*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S256] = 2,
1474*b88e3e88Schristos     .relax_fixup[BR_RANGE_S256] =
1475440a403fSchristos       {
1476440a403fSchristos 	{0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
1477440a403fSchristos 	{0, 0, 0, 0}
1478*b88e3e88Schristos       },
1479*b88e3e88Schristos 
1480*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16K] =
1481*b88e3e88Schristos       {
1482*b88e3e88Schristos 	INSN_BEQZ	/* beqz $rt, label */
1483*b88e3e88Schristos       },
1484*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16K] =
1485*b88e3e88Schristos       {
1486*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1487*b88e3e88Schristos 	{0, 0, 0, FALSE}
1488*b88e3e88Schristos       },
1489*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16K] = 4,
1490*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16K] = 4,
1491*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16K] =
1492440a403fSchristos       {
1493440a403fSchristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1494440a403fSchristos 	{0, 0, 0, 0}
1495*b88e3e88Schristos       },
1496*b88e3e88Schristos 
1497*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S64K] =
1498*b88e3e88Schristos       {
1499*b88e3e88Schristos 	INSN_BEQZ	/* beqz $rt, label */
1500*b88e3e88Schristos       },
1501*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S64K] =
1502*b88e3e88Schristos       {
1503*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1504*b88e3e88Schristos 	{0, 0, 0, FALSE}
1505*b88e3e88Schristos       },
1506*b88e3e88Schristos     .relax_code_size[BR_RANGE_S64K] = 4,
1507*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S64K] = 4,
1508*b88e3e88Schristos     .relax_fixup[BR_RANGE_S64K] =
1509440a403fSchristos       {
1510440a403fSchristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1511440a403fSchristos 	{0, 0, 0, 0}
1512*b88e3e88Schristos       },
1513*b88e3e88Schristos 
1514*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16M] =
1515*b88e3e88Schristos       {
1516*b88e3e88Schristos 	INSN_BNEZ,	/* bnez $rt, $1 */
1517*b88e3e88Schristos 	INSN_J		/* j label */
1518*b88e3e88Schristos       },
1519*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16M] =
1520*b88e3e88Schristos       {
1521*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1522*b88e3e88Schristos 	{0, 0, 0, FALSE}
1523*b88e3e88Schristos       },
1524*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16M] = 8,
1525*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16M] = 4,
1526*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16M] =
1527440a403fSchristos       {
1528440a403fSchristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1529440a403fSchristos 	{0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1530440a403fSchristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1531440a403fSchristos 	{4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1532440a403fSchristos 	{4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1533440a403fSchristos 	{0, 0, 0, 0}
1534*b88e3e88Schristos       },
1535*b88e3e88Schristos 
1536*b88e3e88Schristos     .relax_code_seq[BR_RANGE_U4G] =
1537*b88e3e88Schristos       {
1538*b88e3e88Schristos 	INSN_BNEZ,	/* bnez $rt, $1 */
1539*b88e3e88Schristos 	INSN_SETHI_TA,	/* sethi $ta, label */
1540*b88e3e88Schristos 	INSN_ORI_TA,	/* ori $ta, $ta, label */
1541*b88e3e88Schristos 	INSN_JR_TA	/* jr $ta */
1542*b88e3e88Schristos       },
1543*b88e3e88Schristos     .relax_code_condition[BR_RANGE_U4G] =
1544*b88e3e88Schristos       {
1545*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1546*b88e3e88Schristos 	{0, 0, 0, FALSE}
1547*b88e3e88Schristos       },
1548*b88e3e88Schristos     .relax_code_size[BR_RANGE_U4G] = 16,
1549*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_U4G] = 4,
1550*b88e3e88Schristos     .relax_fixup[BR_RANGE_U4G] =
1551440a403fSchristos       {
1552440a403fSchristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1553440a403fSchristos 	{0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1554440a403fSchristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1555440a403fSchristos 	{4, 4, 0, BFD_RELOC_NDS32_HI20},
1556440a403fSchristos 	{4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1557440a403fSchristos 	{8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1558440a403fSchristos 	{8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1559440a403fSchristos 	{12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1560440a403fSchristos 	{12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1561440a403fSchristos 	{12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1562440a403fSchristos 	{0, 0, 0, 0}
1563*b88e3e88Schristos       },
1564440a403fSchristos   },
1565440a403fSchristos   {
1566*b88e3e88Schristos     .opcode = "bnez38",
1567*b88e3e88Schristos     .br_range = BR_RANGE_S256,
1568*b88e3e88Schristos     .cond_field =
1569440a403fSchristos       {
1570440a403fSchristos 	{0, 8, 0x7, FALSE},
1571440a403fSchristos 	{0, 0, 0, FALSE}
1572*b88e3e88Schristos       },
1573*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S256] =
1574440a403fSchristos       {
1575440a403fSchristos 	INSN_BNEZ38 << 16	/* bnez $rt, label */
1576*b88e3e88Schristos       },
1577*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S256] =
1578440a403fSchristos       {
1579440a403fSchristos 	{0, 8, 0x7, FALSE},
1580440a403fSchristos 	{0, 0, 0, FALSE}
1581*b88e3e88Schristos       },
1582*b88e3e88Schristos     .relax_code_size[BR_RANGE_S256] = 2,
1583*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S256] = 2,
1584*b88e3e88Schristos     .relax_fixup[BR_RANGE_S256] =
1585440a403fSchristos       {
1586440a403fSchristos 	{0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
1587440a403fSchristos 	{0, 0, 0, 0}
1588*b88e3e88Schristos       },
1589*b88e3e88Schristos 
1590*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16K] =
1591*b88e3e88Schristos       {
1592*b88e3e88Schristos 	INSN_BNEZ	/* bnez $rt, label */
1593*b88e3e88Schristos       },
1594*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16K] =
1595*b88e3e88Schristos       {
1596*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1597*b88e3e88Schristos 	{0, 0, 0, FALSE}
1598*b88e3e88Schristos       },
1599*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16K] = 4,
1600*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16K] = 4,
1601*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16K] =
1602440a403fSchristos       {
1603440a403fSchristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1604440a403fSchristos 	{0, 0, 0, 0}
1605*b88e3e88Schristos       },
1606*b88e3e88Schristos 
1607*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S64K] =
1608*b88e3e88Schristos       {
1609*b88e3e88Schristos 	INSN_BNEZ	/* bnez $rt, label */
1610*b88e3e88Schristos       },
1611*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S64K] =
1612*b88e3e88Schristos       {
1613*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1614*b88e3e88Schristos 	{0, 0, 0, FALSE}
1615*b88e3e88Schristos       },
1616*b88e3e88Schristos     .relax_code_size[BR_RANGE_S64K] = 4,
1617*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S64K] = 4,
1618*b88e3e88Schristos     .relax_fixup[BR_RANGE_S64K] =
1619440a403fSchristos       {
1620440a403fSchristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1621440a403fSchristos 	{0, 0, 0, 0}
1622*b88e3e88Schristos       },
1623*b88e3e88Schristos 
1624*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16M] =
1625*b88e3e88Schristos       {
1626*b88e3e88Schristos 	INSN_BEQZ,	/* beqz $rt, $1 */
1627*b88e3e88Schristos 	INSN_J		/* j label */
1628*b88e3e88Schristos       },
1629*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16M] =
1630*b88e3e88Schristos       {
1631*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1632*b88e3e88Schristos 	{0, 0, 0, FALSE}
1633*b88e3e88Schristos       },
1634*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16M] = 8,
1635*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16M] = 4,
1636*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16M] =
1637440a403fSchristos       {
1638440a403fSchristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1639440a403fSchristos 	{0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1640440a403fSchristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1641440a403fSchristos 	{4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1642440a403fSchristos 	{4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1643440a403fSchristos 	{0, 0, 0, 0}
1644*b88e3e88Schristos       },
1645*b88e3e88Schristos 
1646*b88e3e88Schristos     .relax_code_seq[BR_RANGE_U4G] =
1647*b88e3e88Schristos       {
1648*b88e3e88Schristos 	INSN_BEQZ,	/* beqz $rt, $1 */
1649*b88e3e88Schristos 	INSN_SETHI_TA,	/* sethi $ta, label */
1650*b88e3e88Schristos 	INSN_ORI_TA,	/* ori $ta, $ta, label */
1651*b88e3e88Schristos 	INSN_JR_TA	/* jr $ta */
1652*b88e3e88Schristos       },
1653*b88e3e88Schristos     .relax_code_condition[BR_RANGE_U4G] =
1654*b88e3e88Schristos       {
1655*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1656*b88e3e88Schristos 	{0, 0, 0, FALSE}
1657*b88e3e88Schristos       },
1658*b88e3e88Schristos     .relax_code_size[BR_RANGE_U4G] = 16,
1659*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_U4G] = 4,
1660*b88e3e88Schristos     .relax_fixup[BR_RANGE_U4G] =
1661440a403fSchristos       {
1662440a403fSchristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1663440a403fSchristos 	{0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1664440a403fSchristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1665440a403fSchristos 	{4, 4, 0, BFD_RELOC_NDS32_HI20},
1666440a403fSchristos 	{4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1667440a403fSchristos 	{8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1668440a403fSchristos 	{8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1669440a403fSchristos 	{12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1670440a403fSchristos 	{12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1671440a403fSchristos 	{12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1672440a403fSchristos 	{0, 0, 0, 0}
1673*b88e3e88Schristos       },
1674440a403fSchristos   },
1675440a403fSchristos   {
1676*b88e3e88Schristos     .opcode = "beqzs8",
1677*b88e3e88Schristos     .br_range = BR_RANGE_S256,
1678*b88e3e88Schristos     .cond_field =
1679440a403fSchristos       {
1680*b88e3e88Schristos 	{0, 0, 0, FALSE}
1681*b88e3e88Schristos       },
1682*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S256] =
1683440a403fSchristos       {
1684440a403fSchristos 	INSN_BEQZS8 << 16	/* beqz $r15, label */
1685*b88e3e88Schristos       },
1686*b88e3e88Schristos     .relax_code_size[BR_RANGE_S256] = 2,
1687*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S256] = 2,
1688*b88e3e88Schristos     .relax_fixup[BR_RANGE_S256] =
1689440a403fSchristos       {
1690440a403fSchristos 	{0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
1691440a403fSchristos 	{0, 0, 0, 0}
1692*b88e3e88Schristos       },
1693*b88e3e88Schristos 
1694*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16K] =
1695*b88e3e88Schristos       {
1696*b88e3e88Schristos 	INSN_BEQZ_TA	/* beqz $r15, label */
1697*b88e3e88Schristos       },
1698*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16K] = 4,
1699*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16K] = 4,
1700*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16K] =
1701440a403fSchristos       {
1702440a403fSchristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1703440a403fSchristos 	{0, 0, 0, 0}
1704*b88e3e88Schristos       },
1705*b88e3e88Schristos 
1706*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S64K] =
1707*b88e3e88Schristos       {
1708*b88e3e88Schristos 	INSN_BEQZ_TA	/* beqz $r15, label */
1709*b88e3e88Schristos       },
1710*b88e3e88Schristos     .relax_code_size[BR_RANGE_S64K] = 4,
1711*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S64K] = 4,
1712*b88e3e88Schristos     .relax_fixup[BR_RANGE_S64K] =
1713440a403fSchristos       {
1714440a403fSchristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1715440a403fSchristos 	{0, 0, 0, 0}
1716*b88e3e88Schristos       },
1717*b88e3e88Schristos 
1718*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16M] =
1719*b88e3e88Schristos       {
1720*b88e3e88Schristos 	INSN_BNEZ_TA,	/* bnez $r15, $1 */
1721*b88e3e88Schristos 	INSN_J		/* j label */
1722*b88e3e88Schristos       },
1723*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16M] = 8,
1724*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16M] = 4,
1725*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16M] =
1726440a403fSchristos       {
1727440a403fSchristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1728440a403fSchristos 	{0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1729440a403fSchristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1730440a403fSchristos 	{4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1731440a403fSchristos 	{4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1732440a403fSchristos 	{0, 0, 0, 0}
1733*b88e3e88Schristos       },
1734*b88e3e88Schristos 
1735*b88e3e88Schristos     .relax_code_seq[BR_RANGE_U4G] =
1736*b88e3e88Schristos       {
1737*b88e3e88Schristos 	INSN_BNEZ_TA,	/* bnez $r15, $1 */
1738*b88e3e88Schristos 	INSN_SETHI_TA,	/* sethi $ta, label */
1739*b88e3e88Schristos 	INSN_ORI_TA,	/* ori $ta, $ta, label */
1740*b88e3e88Schristos 	INSN_JR_TA	/* jr $ta */
1741*b88e3e88Schristos       },
1742*b88e3e88Schristos     .relax_code_size[BR_RANGE_U4G] = 16,
1743*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_U4G] = 4,
1744*b88e3e88Schristos     .relax_fixup[BR_RANGE_U4G] =
1745440a403fSchristos       {
1746440a403fSchristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1747440a403fSchristos 	{0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1748440a403fSchristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1749440a403fSchristos 	{4, 4, 0, BFD_RELOC_NDS32_HI20},
1750440a403fSchristos 	{4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1751440a403fSchristos 	{8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1752440a403fSchristos 	{8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1753440a403fSchristos 	{12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1754440a403fSchristos 	{12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1755440a403fSchristos 	{12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1756440a403fSchristos 	{0, 0, 0, 0}
1757*b88e3e88Schristos       },
1758440a403fSchristos   },
1759440a403fSchristos   {
1760*b88e3e88Schristos     .opcode = "bnezs8",
1761*b88e3e88Schristos     .br_range = BR_RANGE_S256,
1762*b88e3e88Schristos     .cond_field =
1763440a403fSchristos       {
1764*b88e3e88Schristos 	{0, 0, 0, FALSE}
1765*b88e3e88Schristos       },
1766*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S256] =
1767440a403fSchristos       {
1768440a403fSchristos 	INSN_BNEZS8 << 16	/* bnez $r15, label */
1769*b88e3e88Schristos       },
1770*b88e3e88Schristos     .relax_code_size[BR_RANGE_S256] = 2,
1771*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S256] = 2,
1772*b88e3e88Schristos     .relax_fixup[BR_RANGE_S256] =
1773*b88e3e88Schristos       {
1774*b88e3e88Schristos 	{0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
1775*b88e3e88Schristos 	{0, 0, 0, 0}
1776*b88e3e88Schristos       },
1777*b88e3e88Schristos 
1778*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16K] =
1779440a403fSchristos       {
1780440a403fSchristos 	INSN_BNEZ_TA	/* bnez $r15, label */
1781*b88e3e88Schristos       },
1782*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16K] = 4,
1783*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16K] = 4,
1784*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16K] =
1785*b88e3e88Schristos       {
1786*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1787*b88e3e88Schristos 	{0, 0, 0, 0}
1788*b88e3e88Schristos       },
1789*b88e3e88Schristos 
1790*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S64K] =
1791440a403fSchristos       {
1792440a403fSchristos 	INSN_BNEZ_TA	/* bnez $r15, label */
1793*b88e3e88Schristos       },
1794*b88e3e88Schristos     .relax_code_size[BR_RANGE_S64K] = 4,
1795*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S64K] = 4,
1796*b88e3e88Schristos     .relax_fixup[BR_RANGE_S64K] =
1797*b88e3e88Schristos       {
1798*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
1799*b88e3e88Schristos 	{0, 0, 0, 0}
1800*b88e3e88Schristos       },
1801*b88e3e88Schristos 
1802*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16M] =
1803440a403fSchristos       {
1804440a403fSchristos 	INSN_BEQZ_TA,	/* beqz $r15, $1 */
1805440a403fSchristos 	INSN_J		/* j label */
1806*b88e3e88Schristos       },
1807*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16M] = 8,
1808*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16M] = 4,
1809*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16M] =
1810*b88e3e88Schristos       {
1811*b88e3e88Schristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1812*b88e3e88Schristos 	{0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1813*b88e3e88Schristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1814*b88e3e88Schristos 	{4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1815*b88e3e88Schristos 	{4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1816*b88e3e88Schristos 	{0, 0, 0, 0}
1817*b88e3e88Schristos       },
1818*b88e3e88Schristos 
1819*b88e3e88Schristos     .relax_code_seq[BR_RANGE_U4G] =
1820440a403fSchristos       {
1821440a403fSchristos 	INSN_BEQZ_TA,	/* beqz $r15, $1 */
1822440a403fSchristos 	INSN_SETHI_TA,	/* sethi $ta, label */
1823440a403fSchristos 	INSN_ORI_TA,	/* ori $ta, $ta, label */
1824440a403fSchristos 	INSN_JR_TA	/* jr $ta */
1825*b88e3e88Schristos       },
1826*b88e3e88Schristos     .relax_code_size[BR_RANGE_U4G] = 16,
1827*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_U4G] = 4,
1828*b88e3e88Schristos     .relax_fixup[BR_RANGE_U4G] =
1829440a403fSchristos       {
1830440a403fSchristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1831440a403fSchristos 	{0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1832440a403fSchristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1833440a403fSchristos 	{4, 4, 0, BFD_RELOC_NDS32_HI20},
1834440a403fSchristos 	{4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1835440a403fSchristos 	{8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1836440a403fSchristos 	{8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1837440a403fSchristos 	{12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1838440a403fSchristos 	{12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1839440a403fSchristos 	{12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1840440a403fSchristos 	{0, 0, 0, 0}
1841*b88e3e88Schristos       },
1842440a403fSchristos   },
1843440a403fSchristos   {
1844*b88e3e88Schristos     .opcode = "bnes38",
1845*b88e3e88Schristos     .br_range = BR_RANGE_S256,
1846*b88e3e88Schristos     .cond_field =
1847440a403fSchristos       {
1848440a403fSchristos 	{0, 8, 0x7, FALSE},
1849440a403fSchristos 	{0, 0, 0, FALSE}
1850*b88e3e88Schristos       },
1851*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S256] =
1852440a403fSchristos       {
1853*b88e3e88Schristos 	INSN_BNES38 << 16	/* bne $rt, $r5, label */
1854*b88e3e88Schristos       },
1855*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S256] =
1856440a403fSchristos       {
1857440a403fSchristos 	{0, 8, 0x7, FALSE},
1858440a403fSchristos 	{0, 0, 0, FALSE}
1859*b88e3e88Schristos       },
1860*b88e3e88Schristos     .relax_code_size[BR_RANGE_S256] = 2,
1861*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S256] = 2,
1862*b88e3e88Schristos     .relax_fixup[BR_RANGE_S256] =
1863440a403fSchristos       {
1864440a403fSchristos 	{0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
1865440a403fSchristos 	{0, 0, 0, 0}
1866*b88e3e88Schristos       },
1867*b88e3e88Schristos 
1868*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16K] =
1869*b88e3e88Schristos       {
1870*b88e3e88Schristos 	INSN_BNE_R5	/* bne $rt, $r5, label */
1871*b88e3e88Schristos       },
1872*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16K] =
1873*b88e3e88Schristos       {
1874*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1875*b88e3e88Schristos 	{0, 0, 0, FALSE}
1876*b88e3e88Schristos       },
1877*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16K] = 4,
1878*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16K] = 4,
1879*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16K] =
1880440a403fSchristos       {
1881440a403fSchristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1882440a403fSchristos 	{0, 0, 0, 0}
1883440a403fSchristos       },
1884*b88e3e88Schristos 
1885*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S64K] =
1886440a403fSchristos       {
1887*b88e3e88Schristos 	INSN_BEQ_R5,	/* beq $rt, $r5, $1 */
1888*b88e3e88Schristos 	INSN_J		/* j label */
1889*b88e3e88Schristos       },
1890*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S64K] =
1891440a403fSchristos       {
1892*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1893440a403fSchristos 	{0, 0, 0, FALSE}
1894*b88e3e88Schristos       },
1895*b88e3e88Schristos     .relax_code_size[BR_RANGE_S64K] = 8,
1896*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S64K] = 4,
1897*b88e3e88Schristos     .relax_fixup[BR_RANGE_S64K] =
1898440a403fSchristos       {
1899*b88e3e88Schristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1900*b88e3e88Schristos 	{0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1901*b88e3e88Schristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1902*b88e3e88Schristos 	{4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1903*b88e3e88Schristos 	{4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1904*b88e3e88Schristos 	{0, 0, 0, 0}
1905*b88e3e88Schristos       },
1906*b88e3e88Schristos 
1907*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16M] =
1908440a403fSchristos       {
1909*b88e3e88Schristos 	INSN_BEQ_R5,	/* beq $rt, $r5, $1 */
1910440a403fSchristos 	INSN_J		/* j label */
1911*b88e3e88Schristos       },
1912*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16M] =
1913440a403fSchristos       {
1914*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1915*b88e3e88Schristos 	{0, 0, 0, FALSE}
1916*b88e3e88Schristos       },
1917*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16M] = 8,
1918*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16M] = 4,
1919*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16M] =
1920440a403fSchristos       {
1921*b88e3e88Schristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1922*b88e3e88Schristos 	{0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1923*b88e3e88Schristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
1924*b88e3e88Schristos 	{4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
1925*b88e3e88Schristos 	{4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1926*b88e3e88Schristos 	{0, 0, 0, 0}
1927*b88e3e88Schristos       },
1928*b88e3e88Schristos 
1929*b88e3e88Schristos     .relax_code_seq[BR_RANGE_U4G] =
1930*b88e3e88Schristos       {
1931*b88e3e88Schristos 	INSN_BEQ_R5,	/* beq $rt, $r5, $1 */
1932440a403fSchristos 	INSN_SETHI_TA,	/* sethi $ta, label */
1933440a403fSchristos 	INSN_ORI_TA,	/* ori $ta, $ta, label */
1934440a403fSchristos 	INSN_JR_TA	/* jr $ta */
1935*b88e3e88Schristos       },
1936*b88e3e88Schristos     .relax_code_condition[BR_RANGE_U4G] =
1937440a403fSchristos       {
1938440a403fSchristos 	{0, 20, 0x1F, FALSE},
1939440a403fSchristos 	{0, 0, 0, FALSE}
1940*b88e3e88Schristos       },
1941*b88e3e88Schristos     .relax_code_size[BR_RANGE_U4G] = 16,
1942*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_U4G] = 4,
1943*b88e3e88Schristos     .relax_fixup[BR_RANGE_U4G] =
1944440a403fSchristos       {
1945440a403fSchristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1946440a403fSchristos 	{0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1947440a403fSchristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
1948440a403fSchristos 	{4, 4, 0, BFD_RELOC_NDS32_HI20},
1949440a403fSchristos 	{4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
1950440a403fSchristos 	{8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
1951440a403fSchristos 	{8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
1952440a403fSchristos 	{12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
1953440a403fSchristos 	{12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
1954440a403fSchristos 	{12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
1955440a403fSchristos 	{0, 0, 0, 0}
1956*b88e3e88Schristos       },
1957440a403fSchristos   },
1958440a403fSchristos   {
1959*b88e3e88Schristos     .opcode = "beqs38",
1960*b88e3e88Schristos     .br_range = BR_RANGE_S256,
1961*b88e3e88Schristos     .cond_field =
1962*b88e3e88Schristos       {
1963*b88e3e88Schristos 	{0, 8, 0x7, FALSE},
1964*b88e3e88Schristos 	{0, 0, 0, FALSE}
1965*b88e3e88Schristos       },
1966*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S256] =
1967*b88e3e88Schristos       {
1968*b88e3e88Schristos 	INSN_BEQS38 << 16	/* beq $rt, $r5, label */
1969*b88e3e88Schristos       },
1970*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S256] =
1971*b88e3e88Schristos       {
1972*b88e3e88Schristos 	{0, 8, 0x7, FALSE},
1973*b88e3e88Schristos 	{0, 0, 0, FALSE}
1974*b88e3e88Schristos       },
1975*b88e3e88Schristos     .relax_code_size[BR_RANGE_S256] = 2,
1976*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S256] = 2,
1977*b88e3e88Schristos     .relax_fixup[BR_RANGE_S256] =
1978*b88e3e88Schristos       {
1979*b88e3e88Schristos 	{0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
1980*b88e3e88Schristos 	{0, 0, 0, 0}
1981*b88e3e88Schristos       },
1982*b88e3e88Schristos 
1983*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16K] =
1984*b88e3e88Schristos       {
1985*b88e3e88Schristos 	INSN_BEQ_R5	/* beq $rt, $r5, label */
1986*b88e3e88Schristos       },
1987*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16K] =
1988*b88e3e88Schristos       {
1989*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
1990*b88e3e88Schristos 	{0, 0, 0, FALSE}
1991*b88e3e88Schristos       },
1992*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16K] = 4,
1993*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16K] = 4,
1994*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16K] =
1995*b88e3e88Schristos       {
1996*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
1997*b88e3e88Schristos 	{0, 0, 0, 0}
1998*b88e3e88Schristos       },
1999*b88e3e88Schristos 
2000*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S64K] =
2001*b88e3e88Schristos       {
2002*b88e3e88Schristos 	INSN_BNE_R5,	/* bne $rt, $r5, $1 */
2003*b88e3e88Schristos 	INSN_J		/* j label */
2004*b88e3e88Schristos       },
2005*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S64K] =
2006*b88e3e88Schristos       {
2007*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
2008*b88e3e88Schristos 	{0, 0, 0, FALSE}
2009*b88e3e88Schristos       },
2010*b88e3e88Schristos     .relax_code_size[BR_RANGE_S64K] = 8,
2011*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S64K] = 4,
2012*b88e3e88Schristos     .relax_fixup[BR_RANGE_S64K] =
2013*b88e3e88Schristos       {
2014*b88e3e88Schristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
2015*b88e3e88Schristos 	{0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
2016*b88e3e88Schristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
2017*b88e3e88Schristos 	{4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
2018*b88e3e88Schristos 	{4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
2019*b88e3e88Schristos 	{0, 0, 0, 0}
2020*b88e3e88Schristos       },
2021*b88e3e88Schristos 
2022*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16M] =
2023*b88e3e88Schristos       {
2024*b88e3e88Schristos 	INSN_BNE_R5,	/* bne $rt, $r5, $1 */
2025*b88e3e88Schristos 	INSN_J		/* j label */
2026*b88e3e88Schristos       },
2027*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16M] =
2028*b88e3e88Schristos       {
2029*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
2030*b88e3e88Schristos 	{0, 0, 0, FALSE}
2031*b88e3e88Schristos       },
2032*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16M] = 8,
2033*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16M] = 4,
2034*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16M] =
2035*b88e3e88Schristos       {
2036*b88e3e88Schristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
2037*b88e3e88Schristos 	{0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
2038*b88e3e88Schristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
2039*b88e3e88Schristos 	{4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
2040*b88e3e88Schristos 	{4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
2041*b88e3e88Schristos 	{0, 0, 0, 0}
2042*b88e3e88Schristos       },
2043*b88e3e88Schristos 
2044*b88e3e88Schristos     .relax_code_seq[BR_RANGE_U4G] =
2045*b88e3e88Schristos       {
2046*b88e3e88Schristos 	INSN_BNE_R5,	/* bne $rt, $r5, $1 */
2047*b88e3e88Schristos 	INSN_SETHI_TA,	/* sethi $ta, label */
2048*b88e3e88Schristos 	INSN_ORI_TA,	/* ori $ta, $ta, label */
2049*b88e3e88Schristos 	INSN_JR_TA	/* jr $ta */
2050*b88e3e88Schristos       },
2051*b88e3e88Schristos     .relax_code_condition[BR_RANGE_U4G] =
2052*b88e3e88Schristos       {
2053*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
2054*b88e3e88Schristos 	{0, 0, 0, FALSE}
2055*b88e3e88Schristos       },
2056*b88e3e88Schristos     .relax_code_size[BR_RANGE_U4G] = 16,
2057*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_U4G] = 4,
2058*b88e3e88Schristos     .relax_fixup[BR_RANGE_U4G] =
2059*b88e3e88Schristos       {
2060*b88e3e88Schristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
2061*b88e3e88Schristos 	{0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
2062*b88e3e88Schristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
2063*b88e3e88Schristos 	{4, 4, 0, BFD_RELOC_NDS32_HI20},
2064*b88e3e88Schristos 	{4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
2065*b88e3e88Schristos 	{8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
2066*b88e3e88Schristos 	{8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
2067*b88e3e88Schristos 	{12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
2068*b88e3e88Schristos 	{12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
2069*b88e3e88Schristos 	{12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
2070*b88e3e88Schristos 	{0, 0, 0, 0}
2071*b88e3e88Schristos       },
2072*b88e3e88Schristos   },
2073*b88e3e88Schristos   {
2074*b88e3e88Schristos     .opcode = "beqc",
2075*b88e3e88Schristos     .br_range = BR_RANGE_S256,
2076*b88e3e88Schristos     .cond_field =
2077440a403fSchristos       {
2078440a403fSchristos 	{0, 8, 0x7FF, TRUE},
2079440a403fSchristos 	{0, 20, 0x1F, FALSE},
2080440a403fSchristos 	{0, 0, 0, FALSE}
2081*b88e3e88Schristos       },
2082*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S256] =
2083440a403fSchristos       {
2084440a403fSchristos 	INSN_BEQC	/* beqc $rt, imm11s, label */
2085*b88e3e88Schristos       },
2086*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S256] =
2087*b88e3e88Schristos       {
2088*b88e3e88Schristos 	{0, 8, 0x7FF, FALSE},
2089*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
2090*b88e3e88Schristos 	{0, 0, 0, FALSE}
2091*b88e3e88Schristos       },
2092*b88e3e88Schristos     .relax_code_size[BR_RANGE_S256] = 4,
2093*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S256] = 4,
2094*b88e3e88Schristos     .relax_fixup[BR_RANGE_S256] =
2095*b88e3e88Schristos       {
2096*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
2097*b88e3e88Schristos 	{0, 0, 0, 0}
2098*b88e3e88Schristos       },
2099*b88e3e88Schristos 
2100*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16K] =
2101440a403fSchristos       {
2102440a403fSchristos 	INSN_MOVI_TA,	/* movi $ta, imm11s */
2103440a403fSchristos 	INSN_BEQ_TA	/* beq $rt, $ta, label */
2104*b88e3e88Schristos       },
2105*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16K] =
2106440a403fSchristos       {
2107440a403fSchristos 	{0, 0, 0xFFFFF, FALSE},
2108440a403fSchristos 	{4, 20, 0x1F, FALSE},
2109440a403fSchristos 	{0, 0, 0, FALSE}
2110*b88e3e88Schristos       },
2111*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16K] = 8,
2112*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16K] = 4,
2113*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16K] =
2114440a403fSchristos       {
2115440a403fSchristos 	{0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
2116440a403fSchristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP7},
2117440a403fSchristos 	{4, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
2118440a403fSchristos 	{0, 0, 0, 0}
2119*b88e3e88Schristos       },
2120*b88e3e88Schristos 
2121*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S64K] =
2122*b88e3e88Schristos       {
2123*b88e3e88Schristos 	INSN_BNEC,	/* bnec $rt, imm11s, $1 */
2124*b88e3e88Schristos 	INSN_J		/* j label */
2125*b88e3e88Schristos       },
2126*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S64K] =
2127*b88e3e88Schristos       {
2128*b88e3e88Schristos 	{0, 8, 0x7FF, FALSE},
2129*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
2130*b88e3e88Schristos 	{0, 0, 0, FALSE}
2131*b88e3e88Schristos       },
2132*b88e3e88Schristos     .relax_code_size[BR_RANGE_S64K] = 8,
2133*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S64K] = 4,
2134*b88e3e88Schristos     .relax_fixup[BR_RANGE_S64K] =
2135440a403fSchristos       {
2136440a403fSchristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
2137440a403fSchristos 	{4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
2138440a403fSchristos 	{0, 0, 0, 0}
2139*b88e3e88Schristos       },
2140*b88e3e88Schristos 
2141*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16M] =
2142*b88e3e88Schristos       {
2143*b88e3e88Schristos 	INSN_BNEC,	/* bnec $rt, imm11s, $1 */
2144*b88e3e88Schristos 	INSN_J		/* j label */
2145*b88e3e88Schristos       },
2146*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16M] =
2147*b88e3e88Schristos       {
2148*b88e3e88Schristos 	{0, 8, 0x7FF, FALSE},
2149*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
2150*b88e3e88Schristos 	{0, 0, 0, FALSE}
2151*b88e3e88Schristos       },
2152*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16M] = 8,
2153*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16M] = 4,
2154*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16M] =
2155440a403fSchristos       {
2156440a403fSchristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
2157440a403fSchristos 	{4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
2158440a403fSchristos 	{0, 0, 0, 0}
2159*b88e3e88Schristos       },
2160*b88e3e88Schristos 
2161*b88e3e88Schristos     .relax_code_seq[BR_RANGE_U4G] =
2162*b88e3e88Schristos       {
2163*b88e3e88Schristos 	INSN_BNEC,	/* bnec $rt, imm11s, $1 */
2164*b88e3e88Schristos 	INSN_SETHI_TA,	/* sethi $ta, label */
2165*b88e3e88Schristos 	INSN_ORI_TA,	/* ori $ta, $ta, label */
2166*b88e3e88Schristos 	INSN_JR_TA	/* jr $ta */
2167*b88e3e88Schristos       },
2168*b88e3e88Schristos     .relax_code_condition[BR_RANGE_U4G] =
2169*b88e3e88Schristos       {
2170*b88e3e88Schristos 	{0, 8, 0x7FF, FALSE},
2171*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
2172*b88e3e88Schristos 	{0, 0, 0, FALSE}
2173*b88e3e88Schristos       },
2174*b88e3e88Schristos     .relax_code_size[BR_RANGE_U4G] = 16,
2175*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_U4G] = 4,
2176*b88e3e88Schristos     .relax_fixup[BR_RANGE_U4G] =
2177440a403fSchristos       {
2178440a403fSchristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
2179440a403fSchristos 	{4, 4, 0, BFD_RELOC_NDS32_HI20},
2180440a403fSchristos 	{8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
2181440a403fSchristos 	{12, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
2182440a403fSchristos 	{0, 0, 0, 0}
2183*b88e3e88Schristos       },
2184440a403fSchristos   },
2185440a403fSchristos   {
2186*b88e3e88Schristos     .opcode = "bnec",
2187*b88e3e88Schristos     .br_range = BR_RANGE_S256,
2188*b88e3e88Schristos     .cond_field =
2189440a403fSchristos       {
2190440a403fSchristos 	{0, 8, 0x7FF, TRUE},
2191440a403fSchristos 	{0, 20, 0x1F, FALSE},
2192440a403fSchristos 	{0, 0, 0, FALSE}
2193*b88e3e88Schristos       },
2194*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S256] =
2195440a403fSchristos       {
2196440a403fSchristos 	  INSN_BNEC	/* bnec $rt, imm11s, label */
2197*b88e3e88Schristos       },
2198*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S256] =
2199*b88e3e88Schristos       {
2200*b88e3e88Schristos 	{0, 8, 0x7FF, FALSE},
2201*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
2202*b88e3e88Schristos 	{0, 0, 0, FALSE}
2203*b88e3e88Schristos       },
2204*b88e3e88Schristos     .relax_code_size[BR_RANGE_S256] = 4,
2205*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S256] = 4,
2206*b88e3e88Schristos     .relax_fixup[BR_RANGE_S256] =
2207*b88e3e88Schristos       {
2208*b88e3e88Schristos 	{0, 4, NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
2209*b88e3e88Schristos 	{0, 0, 0, 0}
2210*b88e3e88Schristos       },
2211*b88e3e88Schristos 
2212*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16K] =
2213440a403fSchristos       {
2214440a403fSchristos 	INSN_MOVI_TA,	/* movi $ta, imm11s */
2215440a403fSchristos 	INSN_BNE_TA	/* bne $rt, $ta, label */
2216*b88e3e88Schristos       },
2217*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16K] =
2218440a403fSchristos       {
2219440a403fSchristos 	{0, 0, 0xFFFFF, FALSE},
2220440a403fSchristos 	{4, 20, 0x1F, FALSE},
2221440a403fSchristos 	{0, 0, 0, FALSE}
2222*b88e3e88Schristos       },
2223*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16K] = 8,
2224*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16K] = 4,
2225*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16K] =
2226440a403fSchristos       {
2227440a403fSchristos 	{0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
2228440a403fSchristos 	{0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP7},
2229440a403fSchristos 	{4, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
2230440a403fSchristos 	{0, 0, 0, 0}
2231*b88e3e88Schristos       },
2232*b88e3e88Schristos 
2233*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S64K] =
2234*b88e3e88Schristos       {
2235*b88e3e88Schristos 	INSN_BEQC,	/* beqc $rt, imm11s, $1 */
2236*b88e3e88Schristos 	INSN_J		/* j label */
2237*b88e3e88Schristos       },
2238*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S64K] =
2239*b88e3e88Schristos       {
2240*b88e3e88Schristos 	{0, 8, 0x7FF, FALSE},
2241*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
2242*b88e3e88Schristos 	{0, 0, 0, FALSE}
2243*b88e3e88Schristos       },
2244*b88e3e88Schristos     .relax_code_size[BR_RANGE_S64K] = 8,
2245*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S64K] = 4,
2246*b88e3e88Schristos     .relax_fixup[BR_RANGE_S64K] =
2247440a403fSchristos       {
2248440a403fSchristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
2249440a403fSchristos 	{4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
2250440a403fSchristos 	{0, 0, 0, 0}
2251*b88e3e88Schristos       },
2252*b88e3e88Schristos 
2253*b88e3e88Schristos     .relax_code_seq[BR_RANGE_S16M] =
2254*b88e3e88Schristos       {
2255*b88e3e88Schristos 	INSN_BEQC,	/* beqc $rt, imm11s, $1 */
2256*b88e3e88Schristos 	INSN_J		/* j label */
2257*b88e3e88Schristos       },
2258*b88e3e88Schristos     .relax_code_condition[BR_RANGE_S16M] =
2259*b88e3e88Schristos       {
2260*b88e3e88Schristos 	{0, 8, 0x7FF, FALSE},
2261*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
2262*b88e3e88Schristos 	{0, 0, 0, FALSE}
2263*b88e3e88Schristos       },
2264*b88e3e88Schristos     .relax_code_size[BR_RANGE_S16M] = 8,
2265*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_S16M] = 4,
2266*b88e3e88Schristos     .relax_fixup[BR_RANGE_S16M] =
2267440a403fSchristos       {
2268440a403fSchristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
2269440a403fSchristos 	{4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
2270440a403fSchristos 	{0, 0, 0, 0}
2271*b88e3e88Schristos       },
2272*b88e3e88Schristos 
2273*b88e3e88Schristos     .relax_code_seq[BR_RANGE_U4G] =
2274*b88e3e88Schristos       {
2275*b88e3e88Schristos 	INSN_BEQC,	/* beqc $rt, imm11s, $1 */
2276*b88e3e88Schristos 	INSN_SETHI_TA,	/* sethi $ta, label */
2277*b88e3e88Schristos 	INSN_ORI_TA,	/* ori $ta, $ta, label */
2278*b88e3e88Schristos 	INSN_JR_TA	/* jr $ta */
2279*b88e3e88Schristos       },
2280*b88e3e88Schristos     .relax_code_condition[BR_RANGE_U4G] =
2281*b88e3e88Schristos       {
2282*b88e3e88Schristos 	{0, 8, 0x7FF, FALSE},
2283*b88e3e88Schristos 	{0, 20, 0x1F, FALSE},
2284*b88e3e88Schristos 	{0, 0, 0, FALSE}
2285*b88e3e88Schristos       },
2286*b88e3e88Schristos     .relax_code_size[BR_RANGE_U4G] = 16,
2287*b88e3e88Schristos     .relax_branch_isize[BR_RANGE_U4G] = 4,
2288*b88e3e88Schristos     .relax_fixup[BR_RANGE_U4G] =
2289440a403fSchristos       {
2290440a403fSchristos 	{0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
2291440a403fSchristos 	{4, 4, 0, BFD_RELOC_NDS32_HI20},
2292440a403fSchristos 	{8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
2293440a403fSchristos 	{12, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
2294440a403fSchristos 	{0, 0, 0, 0}
2295*b88e3e88Schristos       },
2296*b88e3e88Schristos   },
2297*b88e3e88Schristos   {
2298*b88e3e88Schristos     .opcode = NULL,
2299*b88e3e88Schristos   },
2300440a403fSchristos };
2301440a403fSchristos 
2302*b88e3e88Schristos 
2303440a403fSchristos /* GAS definitions for command-line options.  */
2304440a403fSchristos enum options
2305440a403fSchristos {
2306440a403fSchristos   OPTION_BIG = OPTION_MD_BASE,
2307440a403fSchristos   OPTION_LITTLE,
2308440a403fSchristos   OPTION_TURBO,
2309440a403fSchristos   OPTION_PIC,
2310440a403fSchristos   OPTION_RELAX_FP_AS_GP_OFF,
2311440a403fSchristos   OPTION_RELAX_B2BB_ON,
2312440a403fSchristos   OPTION_RELAX_ALL_OFF,
2313440a403fSchristos   OPTION_OPTIMIZE,
2314440a403fSchristos   OPTION_OPTIMIZE_SPACE
2315440a403fSchristos };
2316440a403fSchristos 
2317440a403fSchristos const char *md_shortopts = "m:O:";
2318440a403fSchristos struct option md_longopts[] =
2319440a403fSchristos {
2320440a403fSchristos   {"O1", no_argument, NULL, OPTION_OPTIMIZE},
2321440a403fSchristos   {"Os", no_argument, NULL, OPTION_OPTIMIZE_SPACE},
2322440a403fSchristos   {"big", no_argument, NULL, OPTION_BIG},
2323440a403fSchristos   {"little", no_argument, NULL, OPTION_LITTLE},
2324440a403fSchristos   {"EB", no_argument, NULL, OPTION_BIG},
2325440a403fSchristos   {"EL", no_argument, NULL, OPTION_LITTLE},
2326440a403fSchristos   {"meb", no_argument, NULL, OPTION_BIG},
2327440a403fSchristos   {"mel", no_argument, NULL, OPTION_LITTLE},
2328440a403fSchristos   {"mall-ext", no_argument, NULL, OPTION_TURBO},
2329440a403fSchristos   {"mext-all", no_argument, NULL, OPTION_TURBO},
2330440a403fSchristos   {"mpic", no_argument, NULL, OPTION_PIC},
2331440a403fSchristos   /* Relaxation related options.  */
2332440a403fSchristos   {"mno-fp-as-gp-relax", no_argument, NULL, OPTION_RELAX_FP_AS_GP_OFF},
2333440a403fSchristos   {"mb2bb", no_argument, NULL, OPTION_RELAX_B2BB_ON},
2334440a403fSchristos   {"mno-all-relax", no_argument, NULL, OPTION_RELAX_ALL_OFF},
2335440a403fSchristos   {NULL, no_argument, NULL, 0}
2336440a403fSchristos };
2337440a403fSchristos 
2338440a403fSchristos size_t md_longopts_size = sizeof (md_longopts);
2339440a403fSchristos 
2340440a403fSchristos struct nds32_parse_option_table
2341440a403fSchristos {
2342440a403fSchristos   const char *name;		/* Option string.  */
2343440a403fSchristos   const char *help;			/* Help description.  */
2344440a403fSchristos   int (*func) (const char *arg);	/* How to parse it.  */
2345440a403fSchristos };
2346440a403fSchristos 
2347440a403fSchristos 
2348440a403fSchristos /* The value `-1' represents this option has *NOT* been set.  */
2349440a403fSchristos #ifdef NDS32_DEFAULT_ARCH_NAME
2350440a403fSchristos static const char* nds32_arch_name = NDS32_DEFAULT_ARCH_NAME;
2351440a403fSchristos #else
2352440a403fSchristos static const char* nds32_arch_name = "v3";
2353440a403fSchristos #endif
2354440a403fSchristos static int nds32_baseline = -1;
2355440a403fSchristos static int nds32_gpr16 = -1;
2356440a403fSchristos static int nds32_fpu_sp_ext = -1;
2357440a403fSchristos static int nds32_fpu_dp_ext = -1;
2358440a403fSchristos static int nds32_freg = -1;
2359440a403fSchristos static int nds32_abi = -1;
2360440a403fSchristos 
2361440a403fSchristos /* Record ELF flags */
2362440a403fSchristos static int nds32_elf_flags = 0;
2363440a403fSchristos static int nds32_fpu_com = 0;
2364440a403fSchristos 
2365440a403fSchristos static int nds32_parse_arch (const char *str);
2366440a403fSchristos static int nds32_parse_baseline (const char *str);
2367440a403fSchristos static int nds32_parse_freg (const char *str);
2368440a403fSchristos static int nds32_parse_abi (const char *str);
2369*b88e3e88Schristos static void add_mapping_symbol (enum mstate state,
2370*b88e3e88Schristos 				unsigned int padding_byte,
2371*b88e3e88Schristos 				unsigned int align);
2372440a403fSchristos 
2373440a403fSchristos static struct nds32_parse_option_table parse_opts [] =
2374440a403fSchristos {
2375440a403fSchristos   {"arch=", N_("<arch name>\t  Assemble for architecture <arch name>\n\
2376440a403fSchristos 			  <arch name> could be\n\
2377440a403fSchristos 			  v3, v3j, v3m, v3f, v3s, "\
2378440a403fSchristos 			  "v2, v2j, v2f, v2s"), nds32_parse_arch},
2379440a403fSchristos   {"baseline=", N_("<baseline>\t  Assemble for baseline <baseline>\n\
2380440a403fSchristos 			  <baseline> could be v2, v3, v3m"),
2381440a403fSchristos 		  nds32_parse_baseline},
2382440a403fSchristos   {"fpu-freg=", N_("<freg>\t  Specify a FPU configuration\n\
2383440a403fSchristos 			  <freg>\n\
2384440a403fSchristos 			  0:     8 SP /  4 DP registers\n\
2385440a403fSchristos 			  1:    16 SP /  8 DP registers\n\
2386440a403fSchristos 			  2:    32 SP / 16 DP registers\n\
2387440a403fSchristos 			  3:    32 SP / 32 DP registers"), nds32_parse_freg},
2388440a403fSchristos   {"abi=", N_("<abi>\t          Specify a abi version\n\
2389440a403fSchristos 			  <abi> could be v1, v2, v2fp, v2fpp"), nds32_parse_abi},
2390440a403fSchristos   {NULL, NULL, NULL}
2391440a403fSchristos };
2392440a403fSchristos 
2393440a403fSchristos static int nds32_mac = 1;
2394440a403fSchristos static int nds32_div = 1;
2395440a403fSchristos static int nds32_16bit_ext = 1;
2396*b88e3e88Schristos static int nds32_dx_regs = NDS32_DEFAULT_DX_REGS;
2397*b88e3e88Schristos static int nds32_perf_ext = NDS32_DEFAULT_PERF_EXT;
2398*b88e3e88Schristos static int nds32_perf_ext2 = NDS32_DEFAULT_PERF_EXT2;
2399*b88e3e88Schristos static int nds32_string_ext = NDS32_DEFAULT_STRING_EXT;
2400*b88e3e88Schristos static int nds32_audio_ext = NDS32_DEFAULT_AUDIO_EXT;
2401*b88e3e88Schristos static int nds32_dsp_ext = NDS32_DEFAULT_DSP_EXT;
2402*b88e3e88Schristos static int nds32_zol_ext = NDS32_DEFAULT_ZOL_EXT;
2403440a403fSchristos static int nds32_fpu_fma = 0;
2404440a403fSchristos static int nds32_pic = 0;
2405440a403fSchristos static int nds32_relax_fp_as_gp = 1;
2406440a403fSchristos static int nds32_relax_b2bb = 0;
2407440a403fSchristos static int nds32_relax_all = 1;
2408440a403fSchristos struct nds32_set_option_table
2409440a403fSchristos {
2410440a403fSchristos   const char *name;		/* Option string.  */
2411440a403fSchristos   const char *help;			/* Help description.  */
2412440a403fSchristos   int *var;			/* Variable to be set.  */
2413440a403fSchristos   int value;			/* Value to set.  */
2414440a403fSchristos };
2415440a403fSchristos 
2416440a403fSchristos /* The option in this group has both Enable/Disable settings.
2417440a403fSchristos    Just list on here.  */
2418440a403fSchristos 
2419440a403fSchristos static struct nds32_set_option_table toggle_opts [] =
2420440a403fSchristos {
2421440a403fSchristos   {"mac", N_("Multiply instructions support"), &nds32_mac, 1},
2422440a403fSchristos   {"div", N_("Divide instructions support"), &nds32_div, 1},
2423440a403fSchristos   {"16bit-ext", N_("16-bit extension"), &nds32_16bit_ext, 1},
2424440a403fSchristos   {"dx-regs", N_("d0/d1 registers"), &nds32_dx_regs, 1},
2425440a403fSchristos   {"perf-ext", N_("Performance extension"), &nds32_perf_ext, 1},
2426440a403fSchristos   {"perf2-ext", N_("Performance extension 2"), &nds32_perf_ext2, 1},
2427440a403fSchristos   {"string-ext", N_("String extension"), &nds32_string_ext, 1},
2428440a403fSchristos   {"reduced-regs", N_("Reduced Register configuration (GPR16) option"), &nds32_gpr16, 1},
2429440a403fSchristos   {"audio-isa-ext", N_("AUDIO ISA extension"), &nds32_audio_ext, 1},
2430440a403fSchristos   {"fpu-sp-ext", N_("FPU SP extension"), &nds32_fpu_sp_ext, 1},
2431440a403fSchristos   {"fpu-dp-ext", N_("FPU DP extension"), &nds32_fpu_dp_ext, 1},
2432440a403fSchristos   {"fpu-fma", N_("FPU fused-multiply-add instructions"), &nds32_fpu_fma, 1},
2433*b88e3e88Schristos   {"dsp-ext", N_("DSP extension"), &nds32_dsp_ext, 1},
2434*b88e3e88Schristos   {"zol-ext", N_("hardware loop extension"), &nds32_zol_ext, 1},
2435440a403fSchristos   {NULL, NULL, NULL, 0}
2436440a403fSchristos };
2437440a403fSchristos 
2438440a403fSchristos 
2439440a403fSchristos /* GAS declarations.  */
2440440a403fSchristos 
2441440a403fSchristos /* This is the callback for nds32-asm.c to parse operands.  */
2442440a403fSchristos int
2443440a403fSchristos nds32_asm_parse_operand (struct nds32_asm_desc *pdesc,
2444440a403fSchristos 			 struct nds32_asm_insn *pinsn,
2445440a403fSchristos 			 char **pstr, int64_t *value);
2446440a403fSchristos 
2447440a403fSchristos 
2448*b88e3e88Schristos static struct nds32_asm_desc asm_desc;
2449440a403fSchristos 
2450440a403fSchristos /* md_after_parse_args ()
2451440a403fSchristos 
2452440a403fSchristos    GAS will call md_after_parse_args whenever it is defined.
2453440a403fSchristos    This function checks any conflicting options specified.  */
2454440a403fSchristos 
2455440a403fSchristos void
nds32_after_parse_args(void)2456440a403fSchristos nds32_after_parse_args (void)
2457440a403fSchristos {
2458440a403fSchristos   /* If -march option is not used in command-line, set the value of option
2459440a403fSchristos      variable according to NDS32_DEFAULT_ARCH_NAME.  */
2460440a403fSchristos   nds32_parse_arch (nds32_arch_name);
2461440a403fSchristos }
2462440a403fSchristos 
2463440a403fSchristos /* This function is called when printing usage message (--help).  */
2464440a403fSchristos 
2465440a403fSchristos void
md_show_usage(FILE * stream)2466440a403fSchristos md_show_usage (FILE *stream)
2467440a403fSchristos {
2468440a403fSchristos   struct nds32_parse_option_table *coarse_tune;
2469440a403fSchristos   struct nds32_set_option_table *fine_tune;
2470440a403fSchristos 
2471440a403fSchristos   fprintf (stream, _("\n NDS32-specific assembler options:\n"));
2472440a403fSchristos   fprintf (stream, _("\
2473440a403fSchristos   -O1,			  Optimize for performance\n\
2474440a403fSchristos   -Os			  Optimize for space\n"));
2475440a403fSchristos   fprintf (stream, _("\
2476440a403fSchristos   -EL, -mel or -little    Produce little endian output\n\
2477440a403fSchristos   -EB, -meb or -big       Produce big endian output\n\
2478440a403fSchristos   -mpic			  Generate PIC\n\
2479440a403fSchristos   -mno-fp-as-gp-relax	  Suppress fp-as-gp relaxation for this file\n\
2480440a403fSchristos   -mb2bb-relax		  Back-to-back branch optimization\n\
2481440a403fSchristos   -mno-all-relax	  Suppress all relaxation for this file\n"));
2482440a403fSchristos 
2483440a403fSchristos   for (coarse_tune = parse_opts; coarse_tune->name != NULL; coarse_tune++)
2484440a403fSchristos     {
2485440a403fSchristos       if (coarse_tune->help != NULL)
2486440a403fSchristos 	fprintf (stream, _("  -m%s%s\n"),
2487440a403fSchristos 		 coarse_tune->name, _(coarse_tune->help));
2488440a403fSchristos     }
2489440a403fSchristos 
2490440a403fSchristos   for (fine_tune = toggle_opts; fine_tune->name != NULL; fine_tune++)
2491440a403fSchristos     {
2492440a403fSchristos       if (fine_tune->help != NULL)
2493440a403fSchristos 	fprintf (stream, _("  -m[no-]%-17sEnable/Disable %s\n"),
2494440a403fSchristos 		 fine_tune->name, _(fine_tune->help));
2495440a403fSchristos     }
2496440a403fSchristos 
2497440a403fSchristos   fprintf (stream, _("\
2498440a403fSchristos   -mall-ext		  Turn on all extensions and instructions support\n"));
2499440a403fSchristos }
2500440a403fSchristos 
2501440a403fSchristos void
nds32_frag_init(fragS * fragp)2502440a403fSchristos nds32_frag_init (fragS *fragp)
2503440a403fSchristos {
2504440a403fSchristos   fragp->tc_frag_data.flag = 0;
2505440a403fSchristos   fragp->tc_frag_data.opcode = NULL;
2506440a403fSchristos   fragp->tc_frag_data.fixup = NULL;
2507440a403fSchristos }
2508440a403fSchristos 
2509440a403fSchristos 
2510440a403fSchristos 
2511440a403fSchristos /* This function reads an expression from a C string and returns a pointer past
2512440a403fSchristos    the end of the expression.  */
2513440a403fSchristos 
2514440a403fSchristos static char *
parse_expression(char * str,expressionS * exp)2515440a403fSchristos parse_expression (char *str, expressionS *exp)
2516440a403fSchristos {
2517440a403fSchristos   char *s;
2518440a403fSchristos   char *tmp;
2519440a403fSchristos 
2520440a403fSchristos   tmp = input_line_pointer;	/* Save line pointer.  */
2521440a403fSchristos   input_line_pointer = str;
2522440a403fSchristos   expression (exp);
2523440a403fSchristos   s = input_line_pointer;
2524440a403fSchristos   input_line_pointer = tmp;	/* Restore line pointer.  */
2525440a403fSchristos 
2526440a403fSchristos   return s;			/* Return pointer to where parsing stopped.  */
2527440a403fSchristos }
2528440a403fSchristos 
2529440a403fSchristos void
nds32_start_line_hook(void)2530440a403fSchristos nds32_start_line_hook (void)
2531440a403fSchristos {
2532440a403fSchristos }
2533440a403fSchristos 
2534440a403fSchristos /*
2535440a403fSchristos  * Pseudo opcodes
2536440a403fSchristos  */
2537440a403fSchristos 
253806324dcfSchristos typedef void (*nds32_pseudo_opcode_func) (int argc, char *argv[], unsigned int pv);
2539440a403fSchristos struct nds32_pseudo_opcode
2540440a403fSchristos {
2541440a403fSchristos   const char *opcode;
2542440a403fSchristos   int argc;
2543440a403fSchristos   nds32_pseudo_opcode_func proc;
254406324dcfSchristos   unsigned int pseudo_val;
2545440a403fSchristos 
2546440a403fSchristos   /* Some instructions are not pseudo opcode, but they might still be
2547440a403fSchristos      expanded or changed with other instruction combination for some
2548440a403fSchristos      conditions.  We also apply this structure to assist such work.
2549440a403fSchristos 
2550440a403fSchristos      For example, if the distance of branch target '.L0' is larger than
2551440a403fSchristos      imm8s<<1 range,
2552440a403fSchristos 
2553440a403fSchristos      the instruction:
2554440a403fSchristos 
2555440a403fSchristos          beqzs8 .L0
2556440a403fSchristos 
2557440a403fSchristos      will be transformed into:
2558440a403fSchristos 
2559440a403fSchristos          bnezs8  .LCB0
2560440a403fSchristos          j  .L0
2561440a403fSchristos        .LCB0:
2562440a403fSchristos 
2563440a403fSchristos      However, sometimes we do not want assembler to do such changes
2564440a403fSchristos      because compiler knows how to generate corresponding instruction sequence.
2565440a403fSchristos      Use this field to indicate that this opcode is also a physical instruction.
2566440a403fSchristos      If the flag 'verbatim' is nozero and this opcode
2567440a403fSchristos      is a physical instruction, we should not expand it.  */
2568440a403fSchristos   int physical_op;
2569440a403fSchristos };
2570440a403fSchristos #define PV_DONT_CARE 0
2571440a403fSchristos 
2572440a403fSchristos static struct hash_control *nds32_pseudo_opcode_hash = NULL;
2573440a403fSchristos 
2574440a403fSchristos static int
builtin_isreg(const char * s,const char * x ATTRIBUTE_UNUSED)2575440a403fSchristos builtin_isreg (const char *s, const char *x ATTRIBUTE_UNUSED)
2576440a403fSchristos {
2577440a403fSchristos   if (s [0] == '$' && hash_find (nds32_gprs_hash, (s + 1)))
2578440a403fSchristos     return 1;
2579440a403fSchristos   return 0;
2580440a403fSchristos }
2581440a403fSchristos 
2582440a403fSchristos static int
builtin_regnum(const char * s,const char * x ATTRIBUTE_UNUSED)2583440a403fSchristos builtin_regnum (const char *s, const char *x ATTRIBUTE_UNUSED)
2584440a403fSchristos {
2585440a403fSchristos   struct nds32_keyword *k;
2586440a403fSchristos   if (*s != '$')
2587440a403fSchristos     return -1;
2588440a403fSchristos   s++;
2589440a403fSchristos   k = hash_find (nds32_gprs_hash, s);
2590440a403fSchristos 
2591440a403fSchristos   if (k == NULL)
2592440a403fSchristos     return -1;
2593440a403fSchristos 
2594440a403fSchristos   return k->value;
2595440a403fSchristos }
2596440a403fSchristos 
2597440a403fSchristos static int
builtin_addend(const char * s,char * x ATTRIBUTE_UNUSED)2598440a403fSchristos builtin_addend (const char *s, char *x ATTRIBUTE_UNUSED)
2599440a403fSchristos {
2600440a403fSchristos   const char *ptr = s;
2601440a403fSchristos 
2602440a403fSchristos   while (*ptr != '+' && *ptr != '-' && *ptr)
2603440a403fSchristos     ++ptr;
2604440a403fSchristos 
2605440a403fSchristos   if (*ptr == 0)
2606440a403fSchristos     return 0;
2607440a403fSchristos   else
2608440a403fSchristos     return strtol (ptr, NULL, 0);
2609440a403fSchristos }
2610440a403fSchristos 
2611440a403fSchristos static void
md_assemblef(const char * format,...)2612440a403fSchristos md_assemblef (const char *format, ...)
2613440a403fSchristos {
2614440a403fSchristos   /* FIXME: hope this is long enough.  */
2615440a403fSchristos   char line[1024];
2616440a403fSchristos   va_list ap;
2617440a403fSchristos   unsigned int r;
2618440a403fSchristos 
2619440a403fSchristos   va_start (ap, format);
2620440a403fSchristos   r = vsnprintf (line, sizeof (line), format, ap);
2621440a403fSchristos   md_assemble (line);
2622440a403fSchristos 
2623440a403fSchristos   gas_assert (r < sizeof (line));
2624440a403fSchristos }
2625440a403fSchristos 
2626440a403fSchristos /* Some prototypes here, since some op may use another op.  */
2627440a403fSchristos static void do_pseudo_li_internal (const char *rt, int imm32s);
2628440a403fSchristos static void do_pseudo_move_reg_internal (char *dst, char *src);
2629440a403fSchristos 
2630440a403fSchristos static void
do_pseudo_b(int argc ATTRIBUTE_UNUSED,char * argv[],unsigned int pv ATTRIBUTE_UNUSED)263106324dcfSchristos do_pseudo_b (int argc ATTRIBUTE_UNUSED, char *argv[],
263206324dcfSchristos 	     unsigned int pv ATTRIBUTE_UNUSED)
2633440a403fSchristos {
2634440a403fSchristos   char *arg_label = argv[0];
2635440a403fSchristos   relaxing = TRUE;
2636440a403fSchristos   /* b   label */
2637*b88e3e88Schristos   if (nds32_pic)
2638440a403fSchristos     {
2639440a403fSchristos       md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2640440a403fSchristos       md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2641440a403fSchristos       md_assemble  ((char *) "add $ta,$ta,$gp");
2642440a403fSchristos       md_assemble  ((char *) "jr $ta");
2643440a403fSchristos     }
2644440a403fSchristos   else
2645440a403fSchristos     {
2646440a403fSchristos       md_assemblef ("j %s", arg_label);
2647440a403fSchristos     }
2648440a403fSchristos   relaxing = FALSE;
2649440a403fSchristos }
2650440a403fSchristos 
2651440a403fSchristos static void
do_pseudo_bal(int argc ATTRIBUTE_UNUSED,char * argv[],unsigned int pv ATTRIBUTE_UNUSED)265206324dcfSchristos do_pseudo_bal (int argc ATTRIBUTE_UNUSED, char *argv[],
265306324dcfSchristos 	       unsigned int pv ATTRIBUTE_UNUSED)
2654440a403fSchristos {
2655440a403fSchristos   char *arg_label = argv[0];
2656440a403fSchristos   relaxing = TRUE;
2657440a403fSchristos   /* bal|call  label */
2658*b88e3e88Schristos   if (nds32_pic)
2659440a403fSchristos     {
2660440a403fSchristos       md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2661440a403fSchristos       md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2662440a403fSchristos       md_assemble ((char *) "add $ta,$ta,$gp");
2663440a403fSchristos       md_assemble ((char *) "jral $ta");
2664440a403fSchristos     }
2665440a403fSchristos   else
2666440a403fSchristos     {
2667440a403fSchristos       md_assemblef ("jal %s", arg_label);
2668440a403fSchristos     }
2669440a403fSchristos   relaxing = FALSE;
2670440a403fSchristos }
2671440a403fSchristos 
2672440a403fSchristos static void
do_pseudo_bge(int argc ATTRIBUTE_UNUSED,char * argv[],unsigned int pv ATTRIBUTE_UNUSED)267306324dcfSchristos do_pseudo_bge (int argc ATTRIBUTE_UNUSED, char *argv[],
267406324dcfSchristos 	       unsigned int pv ATTRIBUTE_UNUSED)
2675440a403fSchristos {
2676440a403fSchristos   /* rt5, ra5, label */
2677440a403fSchristos   md_assemblef ("slt $ta,%s,%s", argv[0], argv[1]);
2678440a403fSchristos   md_assemblef ("beqz $ta,%s", argv[2]);
2679440a403fSchristos }
2680440a403fSchristos 
2681440a403fSchristos static void
do_pseudo_bges(int argc ATTRIBUTE_UNUSED,char * argv[],unsigned int pv ATTRIBUTE_UNUSED)268206324dcfSchristos do_pseudo_bges (int argc ATTRIBUTE_UNUSED, char *argv[],
268306324dcfSchristos 		unsigned int pv ATTRIBUTE_UNUSED)
2684440a403fSchristos {
2685440a403fSchristos   /* rt5, ra5, label */
2686440a403fSchristos   md_assemblef ("slts $ta,%s,%s", argv[0], argv[1]);
2687440a403fSchristos   md_assemblef ("beqz $ta,%s", argv[2]);
2688440a403fSchristos }
2689440a403fSchristos 
2690440a403fSchristos static void
do_pseudo_bgt(int argc ATTRIBUTE_UNUSED,char * argv[],unsigned int pv ATTRIBUTE_UNUSED)269106324dcfSchristos do_pseudo_bgt (int argc ATTRIBUTE_UNUSED, char *argv[],
269206324dcfSchristos 	       unsigned int pv ATTRIBUTE_UNUSED)
2693440a403fSchristos {
2694440a403fSchristos   /* bgt rt5, ra5, label */
2695440a403fSchristos   md_assemblef ("slt $ta,%s,%s", argv[1], argv[0]);
2696440a403fSchristos   md_assemblef ("bnez $ta,%s", argv[2]);
2697440a403fSchristos }
2698440a403fSchristos 
2699440a403fSchristos static void
do_pseudo_bgts(int argc ATTRIBUTE_UNUSED,char * argv[],unsigned int pv ATTRIBUTE_UNUSED)270006324dcfSchristos do_pseudo_bgts (int argc ATTRIBUTE_UNUSED, char *argv[],
270106324dcfSchristos 		unsigned int pv ATTRIBUTE_UNUSED)
2702440a403fSchristos {
2703440a403fSchristos   /* bgt rt5, ra5, label */
2704440a403fSchristos   md_assemblef ("slts $ta,%s,%s", argv[1], argv[0]);
2705440a403fSchristos   md_assemblef ("bnez $ta,%s", argv[2]);
2706440a403fSchristos }
2707440a403fSchristos 
2708440a403fSchristos static void
do_pseudo_ble(int argc ATTRIBUTE_UNUSED,char * argv[],unsigned int pv ATTRIBUTE_UNUSED)270906324dcfSchristos do_pseudo_ble (int argc ATTRIBUTE_UNUSED, char *argv[],
271006324dcfSchristos 	       unsigned int pv ATTRIBUTE_UNUSED)
2711440a403fSchristos {
2712440a403fSchristos   /* bgt rt5, ra5, label */
2713440a403fSchristos   md_assemblef ("slt $ta,%s,%s", argv[1], argv[0]);
2714440a403fSchristos   md_assemblef ("beqz $ta,%s", argv[2]);
2715440a403fSchristos }
2716440a403fSchristos 
2717440a403fSchristos static void
do_pseudo_bles(int argc ATTRIBUTE_UNUSED,char * argv[],unsigned int pv ATTRIBUTE_UNUSED)271806324dcfSchristos do_pseudo_bles (int argc ATTRIBUTE_UNUSED, char *argv[],
271906324dcfSchristos 		unsigned int pv ATTRIBUTE_UNUSED)
2720440a403fSchristos {
2721440a403fSchristos   /* bgt rt5, ra5, label */
2722440a403fSchristos   md_assemblef ("slts $ta,%s,%s", argv[1], argv[0]);
2723440a403fSchristos   md_assemblef ("beqz $ta,%s", argv[2]);
2724440a403fSchristos }
2725440a403fSchristos 
2726440a403fSchristos static void
do_pseudo_blt(int argc ATTRIBUTE_UNUSED,char * argv[],unsigned int pv ATTRIBUTE_UNUSED)272706324dcfSchristos do_pseudo_blt (int argc ATTRIBUTE_UNUSED, char *argv[],
272806324dcfSchristos 	       unsigned int pv ATTRIBUTE_UNUSED)
2729440a403fSchristos {
2730440a403fSchristos   /* rt5, ra5, label */
2731440a403fSchristos   md_assemblef ("slt $ta,%s,%s", argv[0], argv[1]);
2732440a403fSchristos   md_assemblef ("bnez $ta,%s", argv[2]);
2733440a403fSchristos }
2734440a403fSchristos 
2735440a403fSchristos static void
do_pseudo_blts(int argc ATTRIBUTE_UNUSED,char * argv[],unsigned int pv ATTRIBUTE_UNUSED)273606324dcfSchristos do_pseudo_blts (int argc ATTRIBUTE_UNUSED, char *argv[],
273706324dcfSchristos 		unsigned int pv ATTRIBUTE_UNUSED)
2738440a403fSchristos {
2739440a403fSchristos   /* rt5, ra5, label */
2740440a403fSchristos   md_assemblef ("slts $ta,%s,%s", argv[0], argv[1]);
2741440a403fSchristos   md_assemblef ("bnez $ta,%s", argv[2]);
2742440a403fSchristos }
2743440a403fSchristos 
2744440a403fSchristos static void
do_pseudo_br(int argc ATTRIBUTE_UNUSED,char * argv[],unsigned int pv ATTRIBUTE_UNUSED)274506324dcfSchristos do_pseudo_br (int argc ATTRIBUTE_UNUSED, char *argv[],
274606324dcfSchristos 	      unsigned int pv ATTRIBUTE_UNUSED)
2747440a403fSchristos {
2748440a403fSchristos   md_assemblef ("jr %s", argv[0]);
2749440a403fSchristos }
2750440a403fSchristos 
2751440a403fSchristos static void
do_pseudo_bral(int argc,char * argv[],unsigned int pv ATTRIBUTE_UNUSED)275206324dcfSchristos do_pseudo_bral (int argc, char *argv[],
275306324dcfSchristos 		unsigned int pv ATTRIBUTE_UNUSED)
2754440a403fSchristos {
2755440a403fSchristos   if (argc == 1)
2756440a403fSchristos     md_assemblef ("jral $lp,%s", argv[0]);
2757440a403fSchristos   else
2758440a403fSchristos     md_assemblef ("jral %s,%s", argv[0], argv[1]);
2759440a403fSchristos }
2760440a403fSchristos 
2761440a403fSchristos static void
do_pseudo_la_internal(const char * arg_reg,char * arg_label,const char * line)2762440a403fSchristos do_pseudo_la_internal (const char *arg_reg, char *arg_label,
2763440a403fSchristos 		       const char *line)
2764440a403fSchristos {
2765440a403fSchristos   expressionS exp;
2766440a403fSchristos 
2767440a403fSchristos   parse_expression (arg_label, &exp);
2768440a403fSchristos   if (exp.X_op != O_symbol)
2769440a403fSchristos     {
2770440a403fSchristos       as_bad (_("la must use with symbol. '%s'"), line);
2771440a403fSchristos       return;
2772440a403fSchristos     }
2773440a403fSchristos 
2774440a403fSchristos   relaxing = TRUE;
2775440a403fSchristos   /* rt, label */
2776440a403fSchristos   if (!nds32_pic && !strstr (arg_label, "@"))
2777440a403fSchristos     {
2778440a403fSchristos       md_assemblef ("sethi %s,hi20(%s)", arg_reg, arg_label);
2779440a403fSchristos       md_assemblef ("ori %s,%s,lo12(%s)", arg_reg, arg_reg, arg_label);
2780440a403fSchristos     }
2781440a403fSchristos   else if (strstr (arg_label, "@TPOFF"))
2782440a403fSchristos     {
2783440a403fSchristos       /* la $rt, sym@TPOFF  */
2784440a403fSchristos       md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2785440a403fSchristos       md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2786440a403fSchristos       md_assemblef ("add %s,$ta,%s", arg_reg, TLS_REG);
2787440a403fSchristos     }
2788440a403fSchristos   else if (strstr(arg_label, "@GOTTPOFF"))
2789440a403fSchristos     {
2790440a403fSchristos       /* la $rt, sym@GOTTPOFF*/
2791440a403fSchristos       md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2792440a403fSchristos       md_assemblef ("lwi $ta,[$ta+lo12(%s)]", arg_label);
2793440a403fSchristos       md_assemblef ("add %s,$ta,%s", arg_reg, TLS_REG);
2794440a403fSchristos     }
2795440a403fSchristos   else if (nds32_pic && ((strstr (arg_label, "@PLT")
2796440a403fSchristos 			  || strstr (arg_label, "@GOTOFF"))))
2797440a403fSchristos     {
2798440a403fSchristos       md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2799440a403fSchristos       md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2800440a403fSchristos       md_assemblef ("add %s,$ta,$gp", arg_reg);
2801440a403fSchristos     }
2802440a403fSchristos   else if (nds32_pic && strstr (arg_label, "@GOT"))
2803440a403fSchristos     {
2804440a403fSchristos       long addend = builtin_addend (arg_label, NULL);
2805440a403fSchristos 
2806440a403fSchristos       md_assemblef ("sethi $ta,hi20(%s)", arg_label);
2807440a403fSchristos       md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
2808440a403fSchristos       md_assemblef ("lw %s,[$gp+$ta]", arg_reg);
2809440a403fSchristos       if (addend != 0)
2810440a403fSchristos 	{
2811440a403fSchristos 	  if (addend < 0x4000 && addend >= -0x4000)
2812440a403fSchristos 	    {
2813440a403fSchristos 	      md_assemblef ("addi %s,%s,%d", arg_reg, arg_reg, addend);
2814440a403fSchristos 	    }
2815440a403fSchristos 	  else
2816440a403fSchristos 	    {
2817440a403fSchristos 	      do_pseudo_li_internal ("$ta", addend);
2818440a403fSchristos 	      md_assemblef ("add %s,$ta,%s", arg_reg, arg_reg);
2819440a403fSchristos 	    }
2820440a403fSchristos 	}
2821440a403fSchristos     }
2822440a403fSchristos    else
2823440a403fSchristos       as_bad (_("need PIC qualifier with symbol. '%s'"), line);
2824440a403fSchristos   relaxing = FALSE;
2825440a403fSchristos }
2826440a403fSchristos 
2827440a403fSchristos static void
do_pseudo_la(int argc ATTRIBUTE_UNUSED,char * argv[],unsigned int pv ATTRIBUTE_UNUSED)282806324dcfSchristos do_pseudo_la (int argc ATTRIBUTE_UNUSED, char *argv[],
282906324dcfSchristos 	      unsigned int pv ATTRIBUTE_UNUSED)
2830440a403fSchristos {
2831440a403fSchristos   do_pseudo_la_internal (argv[0], argv[1], argv[argc]);
2832440a403fSchristos }
2833440a403fSchristos 
2834440a403fSchristos static void
do_pseudo_li_internal(const char * rt,int imm32s)2835440a403fSchristos do_pseudo_li_internal (const char *rt, int imm32s)
2836440a403fSchristos {
2837440a403fSchristos   if (enable_16bit && imm32s <= 0xf && imm32s >= -0x10)
2838440a403fSchristos     md_assemblef ("movi55 %s,%d", rt, imm32s);
2839440a403fSchristos   else if (imm32s <= 0x7ffff && imm32s >= -0x80000)
2840440a403fSchristos     md_assemblef ("movi %s,%d", rt, imm32s);
2841440a403fSchristos   else if ((imm32s & 0xfff) == 0)
2842440a403fSchristos     md_assemblef ("sethi %s,hi20(%d)", rt, imm32s);
2843440a403fSchristos   else
2844440a403fSchristos     {
2845440a403fSchristos       md_assemblef ("sethi %s,hi20(%d)", rt, imm32s);
2846440a403fSchristos       md_assemblef ("ori %s,%s,lo12(%d)", rt, rt, imm32s);
2847440a403fSchristos     }
2848440a403fSchristos }
2849440a403fSchristos 
2850440a403fSchristos static void
do_pseudo_li(int argc ATTRIBUTE_UNUSED,char * argv[],unsigned int pv ATTRIBUTE_UNUSED)285106324dcfSchristos do_pseudo_li (int argc ATTRIBUTE_UNUSED, char *argv[],
285206324dcfSchristos 	      unsigned int pv ATTRIBUTE_UNUSED)
2853440a403fSchristos {
2854440a403fSchristos   /* Validate argv[1] for constant expression.  */
2855440a403fSchristos   expressionS exp;
2856440a403fSchristos 
2857440a403fSchristos   parse_expression (argv[1], &exp);
2858440a403fSchristos   if (exp.X_op != O_constant)
2859440a403fSchristos     {
2860440a403fSchristos       as_bad (_("Operand is not a constant. `%s'"), argv[argc]);
2861440a403fSchristos       return;
2862440a403fSchristos     }
2863440a403fSchristos 
2864440a403fSchristos   do_pseudo_li_internal (argv[0], exp.X_add_number);
2865440a403fSchristos }
2866440a403fSchristos 
2867440a403fSchristos static void
do_pseudo_ls_bhw(int argc ATTRIBUTE_UNUSED,char * argv[],unsigned int pv)286806324dcfSchristos do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED, char *argv[],
286906324dcfSchristos 		  unsigned int pv)
2870440a403fSchristos {
2871440a403fSchristos   char ls = 'r';
2872440a403fSchristos   char size = 'x';
2873440a403fSchristos   const char *sign = "";
2874440a403fSchristos 
2875440a403fSchristos   /* Prepare arguments for various load/store.  */
2876440a403fSchristos   sign = (pv & 0x10) ? "s" : "";
2877440a403fSchristos   ls = (pv & 0x80000000) ? 's' : 'l';
2878440a403fSchristos   switch (pv & 0x3)
2879440a403fSchristos     {
2880440a403fSchristos     case 0: size = 'b'; break;
2881440a403fSchristos     case 1: size = 'h'; break;
2882440a403fSchristos     case 2: size = 'w'; break;
2883440a403fSchristos     }
2884440a403fSchristos 
2885440a403fSchristos   if (ls == 's' || size == 'w')
2886440a403fSchristos     sign = "";
2887440a403fSchristos 
2888440a403fSchristos   if (builtin_isreg (argv[1], NULL))
2889440a403fSchristos     {
2890440a403fSchristos       /* lwi */
2891440a403fSchristos       md_assemblef ("%c%ci %s,[%s]", ls, size, argv[0], argv[1]);
2892440a403fSchristos     }
2893440a403fSchristos   else if (!nds32_pic)
2894440a403fSchristos     {
2895440a403fSchristos       relaxing = TRUE;
2896440a403fSchristos       if (strstr (argv[1], "@TPOFF"))
2897440a403fSchristos 	{
2898440a403fSchristos 	  /* ls.w $rt, sym@TPOFF  */
2899440a403fSchristos 	  md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2900440a403fSchristos 	  md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
2901440a403fSchristos 	  md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], TLS_REG);
2902440a403fSchristos 	}
2903440a403fSchristos       else if (strstr (argv[1], "@GOTTPOFF"))
2904440a403fSchristos 	{
2905440a403fSchristos 	  /* ls.w $rt, sym@GOTTPOFF  */
2906440a403fSchristos 	  md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2907440a403fSchristos 	  md_assemblef ("lwi $ta,[$ta+lo12(%s)]", argv[1]);
2908440a403fSchristos 	  md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], TLS_REG);
2909440a403fSchristos 	}
2910440a403fSchristos       else
2911440a403fSchristos 	{
2912440a403fSchristos 	  /* lwi */
2913440a403fSchristos 	  md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2914440a403fSchristos 	  md_assemblef ("%c%c%si %s,[$ta+lo12(%s)]", ls, size, sign, argv[0], argv[1]);
2915440a403fSchristos 	}
2916440a403fSchristos       relaxing = FALSE;
2917440a403fSchristos     }
2918440a403fSchristos   else
2919440a403fSchristos     {
2920440a403fSchristos       relaxing = TRUE;
2921440a403fSchristos       /* PIC code.  */
2922440a403fSchristos       if (strstr (argv[1], "@GOTOFF"))
2923440a403fSchristos 	{
2924440a403fSchristos 	  /* lw */
2925440a403fSchristos 	  md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2926440a403fSchristos 	  md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
2927440a403fSchristos 	  md_assemblef ("%c%c%s %s,[$ta+$gp]", ls, size, sign, argv[0]);
2928440a403fSchristos 	}
2929440a403fSchristos       else if (strstr (argv[1], "@GOT"))
2930440a403fSchristos 	{
2931440a403fSchristos 	  long addend = builtin_addend (argv[1], NULL);
2932440a403fSchristos 	  /* lw */
2933440a403fSchristos 	  md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
2934440a403fSchristos 	  md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
2935440a403fSchristos 	  md_assemble ((char *) "lw $ta,[$gp+$ta]");	/* Load address word.  */
2936440a403fSchristos 	  if (addend < 0x10000 && addend >= -0x10000)
2937440a403fSchristos 	    {
2938440a403fSchristos 	      md_assemblef ("%c%c%si %s,[$ta+(%d)]", ls, size, sign, argv[0], addend);
2939440a403fSchristos 	    }
2940440a403fSchristos 	  else
2941440a403fSchristos 	    {
2942440a403fSchristos 	      /* lw */
2943440a403fSchristos 	      do_pseudo_li_internal (argv[0], addend);
2944440a403fSchristos 	      md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], argv[0]);
2945440a403fSchristos 	    }
2946440a403fSchristos 	}
2947440a403fSchristos       else
2948440a403fSchristos 	{
2949440a403fSchristos 	  as_bad (_("needs @GOT or @GOTOFF. %s"), argv[argc]);
2950440a403fSchristos 	}
2951440a403fSchristos       relaxing = FALSE;
2952440a403fSchristos     }
2953440a403fSchristos }
2954440a403fSchristos 
2955440a403fSchristos static void
do_pseudo_ls_bhwp(int argc ATTRIBUTE_UNUSED,char * argv[],unsigned int pv)295606324dcfSchristos do_pseudo_ls_bhwp (int argc ATTRIBUTE_UNUSED, char *argv[],
295706324dcfSchristos 		   unsigned int pv)
2958440a403fSchristos {
2959440a403fSchristos   char *arg_rt = argv[0];
2960440a403fSchristos   char *arg_label = argv[1];
2961440a403fSchristos   char *arg_inc = argv[2];
2962440a403fSchristos   char ls = 'r';
2963440a403fSchristos   char size = 'x';
2964440a403fSchristos   const char *sign = "";
2965440a403fSchristos 
2966440a403fSchristos   /* Prepare arguments for various load/store.  */
2967440a403fSchristos   sign = (pv & 0x10) ? "s" : "";
2968440a403fSchristos   ls = (pv & 0x80000000) ? 's' : 'l';
2969440a403fSchristos   switch (pv & 0x3)
2970440a403fSchristos     {
2971440a403fSchristos     case 0: size = 'b'; break;
2972440a403fSchristos     case 1: size = 'h'; break;
2973440a403fSchristos     case 2: size = 'w'; break;
2974440a403fSchristos     }
2975440a403fSchristos 
2976440a403fSchristos   if (ls == 's' || size == 'w')
2977440a403fSchristos     sign = "";
2978440a403fSchristos 
2979440a403fSchristos   do_pseudo_la_internal ("$ta", arg_label, argv[argc]);
2980440a403fSchristos   md_assemblef ("%c%c%si.bi %s,[$ta],%s", ls, size, sign, arg_rt, arg_inc);
2981440a403fSchristos }
2982440a403fSchristos 
2983440a403fSchristos static void
do_pseudo_ls_bhwpc(int argc ATTRIBUTE_UNUSED,char * argv[],unsigned int pv)298406324dcfSchristos do_pseudo_ls_bhwpc (int argc ATTRIBUTE_UNUSED, char *argv[],
298506324dcfSchristos 		    unsigned int pv)
2986440a403fSchristos {
2987440a403fSchristos   char *arg_rt = argv[0];
2988440a403fSchristos   char *arg_inc = argv[1];
2989440a403fSchristos   char ls = 'r';
2990440a403fSchristos   char size = 'x';
2991440a403fSchristos   const char *sign = "";
2992440a403fSchristos 
2993440a403fSchristos   /* Prepare arguments for various load/store.  */
2994440a403fSchristos   sign = (pv & 0x10) ? "s" : "";
2995440a403fSchristos   ls = (pv & 0x80000000) ? 's' : 'l';
2996440a403fSchristos   switch (pv & 0x3)
2997440a403fSchristos     {
2998440a403fSchristos     case 0: size = 'b'; break;
2999440a403fSchristos     case 1: size = 'h'; break;
3000440a403fSchristos     case 2: size = 'w'; break;
3001440a403fSchristos     }
3002440a403fSchristos 
3003440a403fSchristos   if (ls == 's' || size == 'w')
3004440a403fSchristos     sign = "";
3005440a403fSchristos 
3006440a403fSchristos   md_assemblef ("%c%c%si.bi %s,[$ta],%s", ls, size, sign, arg_rt, arg_inc);
3007440a403fSchristos }
3008440a403fSchristos 
3009440a403fSchristos static void
do_pseudo_ls_bhwi(int argc ATTRIBUTE_UNUSED,char * argv[],unsigned int pv)301006324dcfSchristos do_pseudo_ls_bhwi (int argc ATTRIBUTE_UNUSED, char *argv[],
301106324dcfSchristos 		   unsigned int pv)
3012440a403fSchristos {
3013440a403fSchristos   char ls = 'r';
3014440a403fSchristos   char size = 'x';
3015440a403fSchristos   const char *sign = "";
3016440a403fSchristos 
3017440a403fSchristos   /* Prepare arguments for various load/store.  */
3018440a403fSchristos   sign = (pv & 0x10) ? "s" : "";
3019440a403fSchristos   ls = (pv & 0x80000000) ? 's' : 'l';
3020440a403fSchristos   switch (pv & 0x3)
3021440a403fSchristos     {
3022440a403fSchristos     case 0: size = 'b'; break;
3023440a403fSchristos     case 1: size = 'h'; break;
3024440a403fSchristos     case 2: size = 'w'; break;
3025440a403fSchristos     }
3026440a403fSchristos 
3027440a403fSchristos   if (ls == 's' || size == 'w')
3028440a403fSchristos     sign = "";
3029440a403fSchristos 
3030440a403fSchristos   md_assemblef ("%c%c%si.bi %s,%s,%s",
3031440a403fSchristos 		ls, size, sign, argv[0], argv[1], argv[2]);
3032440a403fSchristos }
3033440a403fSchristos 
3034440a403fSchristos static void
do_pseudo_move_reg_internal(char * dst,char * src)3035440a403fSchristos do_pseudo_move_reg_internal (char *dst, char *src)
3036440a403fSchristos {
3037440a403fSchristos   if (enable_16bit)
3038440a403fSchristos     md_assemblef ("mov55 %s,%s", dst, src);
3039440a403fSchristos   else
3040440a403fSchristos     md_assemblef ("ori %s,%s,0", dst, src);
3041440a403fSchristos }
3042440a403fSchristos 
3043440a403fSchristos static void
do_pseudo_move(int argc ATTRIBUTE_UNUSED,char * argv[],unsigned int pv ATTRIBUTE_UNUSED)304406324dcfSchristos do_pseudo_move (int argc ATTRIBUTE_UNUSED, char *argv[],
304506324dcfSchristos 		unsigned int pv ATTRIBUTE_UNUSED)
3046440a403fSchristos {
3047440a403fSchristos   expressionS exp;
3048440a403fSchristos 
3049440a403fSchristos   if (builtin_isreg (argv[1], NULL))
3050440a403fSchristos     do_pseudo_move_reg_internal (argv[0], argv[1]);
3051440a403fSchristos   else
3052440a403fSchristos     {
3053440a403fSchristos       parse_expression (argv[1], &exp);
3054440a403fSchristos       if (exp.X_op == O_constant)
3055440a403fSchristos 	/* move $rt, imm  -> li $rt, imm  */
3056440a403fSchristos 	do_pseudo_li_internal (argv[0], exp.X_add_number);
3057440a403fSchristos       else
3058440a403fSchristos 	/* l.w $rt, var  -> l.w $rt, var  */
3059440a403fSchristos 	do_pseudo_ls_bhw (argc, argv, 2);
3060440a403fSchristos     }
3061440a403fSchristos }
3062440a403fSchristos 
3063440a403fSchristos static void
do_pseudo_neg(int argc ATTRIBUTE_UNUSED,char * argv[],unsigned int pv ATTRIBUTE_UNUSED)306406324dcfSchristos do_pseudo_neg (int argc ATTRIBUTE_UNUSED, char *argv[],
306506324dcfSchristos 	       unsigned int pv ATTRIBUTE_UNUSED)
3066440a403fSchristos {
3067440a403fSchristos   /* Instead of "subri".  */
3068440a403fSchristos   md_assemblef ("subri %s,%s,0", argv[0], argv[1]);
3069440a403fSchristos }
3070440a403fSchristos 
3071440a403fSchristos static void
do_pseudo_not(int argc ATTRIBUTE_UNUSED,char * argv[],unsigned int pv ATTRIBUTE_UNUSED)307206324dcfSchristos do_pseudo_not (int argc ATTRIBUTE_UNUSED, char *argv[],
307306324dcfSchristos 	       unsigned int pv ATTRIBUTE_UNUSED)
3074440a403fSchristos {
3075440a403fSchristos   md_assemblef ("nor %s,%s,%s", argv[0], argv[1], argv[1]);
3076440a403fSchristos }
3077440a403fSchristos 
3078440a403fSchristos static void
do_pseudo_pushpopm(int argc,char * argv[],unsigned int pv ATTRIBUTE_UNUSED)307906324dcfSchristos do_pseudo_pushpopm (int argc, char *argv[],
308006324dcfSchristos 		    unsigned int pv ATTRIBUTE_UNUSED)
3081440a403fSchristos {
3082440a403fSchristos   /* posh/pop $ra, $rb */
3083440a403fSchristos   /* SMW.{b | a}{i | d}{m?} Rb, [Ra], Re, Enable4 */
3084440a403fSchristos   int rb, re, ra, en4;
3085440a403fSchristos   int i;
3086440a403fSchristos   const char *opc = "pushpopm";
3087440a403fSchristos 
3088440a403fSchristos   if (argc == 3)
3089440a403fSchristos     as_bad ("'pushm/popm $ra5, $rb5, $label' is deprecated.  "
3090440a403fSchristos 	    "Only 'pushm/popm $ra5' is supported now. %s", argv[argc]);
3091440a403fSchristos   else if (argc == 1)
3092440a403fSchristos     as_bad ("'pushm/popm $ra5, $rb5'. %s\n", argv[argc]);
3093440a403fSchristos 
3094440a403fSchristos   if (strstr (argv[argc], "pop") == argv[argc])
3095440a403fSchristos     opc = "lmw.bim";
3096440a403fSchristos   else if (strstr (argv[argc], "push") == argv[argc])
3097440a403fSchristos     opc = "smw.adm";
3098440a403fSchristos   else
3099440a403fSchristos     as_fatal ("nds32-as internal error. %s", argv[argc]);
3100440a403fSchristos 
3101440a403fSchristos   rb = builtin_regnum (argv[0], NULL);
3102440a403fSchristos   re = builtin_regnum (argv[1], NULL);
3103440a403fSchristos 
3104440a403fSchristos   if (re < rb)
3105440a403fSchristos     {
3106440a403fSchristos       as_warn ("$rb should not be smaller than $ra. %s", argv[argc]);
3107440a403fSchristos       /* Swap to right order.  */
3108440a403fSchristos       ra = re;
3109440a403fSchristos       re = rb;
3110440a403fSchristos       rb = ra;
3111440a403fSchristos     }
3112440a403fSchristos 
3113440a403fSchristos   /* Build enable4 mask.  */
3114440a403fSchristos   en4 = 0;
3115440a403fSchristos   if (re >= 28 || rb >= 28)
3116440a403fSchristos     {
3117440a403fSchristos       for (i = (rb >= 28? rb: 28); i <= re; i++)
3118440a403fSchristos 	en4 |= 1 << (3 - (i - 28));
3119440a403fSchristos     }
3120440a403fSchristos 
3121440a403fSchristos   /* Adjust $re, $rb.  */
3122440a403fSchristos   if (rb >= 28)
3123440a403fSchristos     rb = re = 31;
3124440a403fSchristos   else if (nds32_gpr16 != 1 && re >= 28)
3125440a403fSchristos     re = 27;
3126440a403fSchristos 
3127440a403fSchristos   /* Reduce register.  */
3128440a403fSchristos   if (nds32_gpr16 && re > 10 && !(rb == 31 && re == 31))
3129440a403fSchristos     {
3130440a403fSchristos       if (re >= 15 && strstr (opc, "smw") != NULL)
3131440a403fSchristos 	md_assemblef ("%s $r15,[$sp],$r15,%d", opc, en4);
3132440a403fSchristos       if (rb <= 10)
3133440a403fSchristos 	md_assemblef ("%s $r%d,[$sp],$r10, 0x0", opc, rb);
3134440a403fSchristos       if (re >= 15 && strstr (opc, "lmw") != NULL)
3135440a403fSchristos 	md_assemblef ("%s $r15,[$sp],$r15,%d", opc, en4);
3136440a403fSchristos     }
3137440a403fSchristos   else
3138440a403fSchristos     md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc, rb, re, en4);
3139440a403fSchristos }
3140440a403fSchristos 
3141440a403fSchristos static void
do_pseudo_pushpop(int argc,char * argv[],unsigned int pv ATTRIBUTE_UNUSED)314206324dcfSchristos do_pseudo_pushpop (int argc, char *argv[],
314306324dcfSchristos 		   unsigned int pv ATTRIBUTE_UNUSED)
3144440a403fSchristos {
3145440a403fSchristos   /* push/pop $ra5, $label=$sp */
3146440a403fSchristos   char *argvm[3];
3147440a403fSchristos 
3148440a403fSchristos   if (argc == 2)
3149440a403fSchristos     as_bad ("'push/pop $ra5, rb5' is deprecated.  "
3150440a403fSchristos 	    "Only 'push/pop $ra5' is supported now. %s", argv[argc]);
3151440a403fSchristos 
3152440a403fSchristos   argvm[0] = argv[0];
3153440a403fSchristos   argvm[1] = argv[0];
3154440a403fSchristos   argvm[2] = argv[argc];
3155440a403fSchristos   do_pseudo_pushpopm (2, argvm, PV_DONT_CARE);
3156440a403fSchristos }
3157440a403fSchristos 
3158440a403fSchristos static void
do_pseudo_v3push(int argc ATTRIBUTE_UNUSED,char * argv[],unsigned int pv ATTRIBUTE_UNUSED)315906324dcfSchristos do_pseudo_v3push (int argc ATTRIBUTE_UNUSED, char *argv[],
316006324dcfSchristos 		  unsigned int pv ATTRIBUTE_UNUSED)
3161440a403fSchristos {
3162440a403fSchristos   md_assemblef ("push25 %s,%s", argv[0], argv[1]);
3163440a403fSchristos }
3164440a403fSchristos 
3165440a403fSchristos static void
do_pseudo_v3pop(int argc ATTRIBUTE_UNUSED,char * argv[],unsigned int pv ATTRIBUTE_UNUSED)316606324dcfSchristos do_pseudo_v3pop (int argc ATTRIBUTE_UNUSED, char *argv[],
316706324dcfSchristos 		 unsigned int pv ATTRIBUTE_UNUSED)
3168440a403fSchristos {
3169440a403fSchristos   md_assemblef ("pop25 %s,%s", argv[0], argv[1]);
3170440a403fSchristos }
3171440a403fSchristos 
3172440a403fSchristos /* pv == 0, parsing "push.s" pseudo instruction operands.
3173440a403fSchristos    pv != 0, parsing "pop.s" pseudo instruction operands.  */
3174440a403fSchristos 
3175440a403fSchristos static void
do_pseudo_pushpop_stack(int argc,char * argv[],unsigned int pv)317606324dcfSchristos do_pseudo_pushpop_stack (int argc, char *argv[],
317706324dcfSchristos 			 unsigned int pv)
3178440a403fSchristos {
3179440a403fSchristos   /* push.s Rb,Re,{$fp $gp $lp $sp}  ==>  smw.adm Rb,[$sp],Re,Eable4  */
3180440a403fSchristos   /* pop.s Rb,Re,{$fp $gp $lp $sp}   ==>  lmw.bim Rb,[$sp],Re,Eable4  */
3181440a403fSchristos 
3182440a403fSchristos   int rb, re;
3183440a403fSchristos   int en4;
3184440a403fSchristos   int last_arg_index;
3185440a403fSchristos   const char *opc = (pv == 0) ? "smw.adm" : "lmw.bim";
3186440a403fSchristos 
3187440a403fSchristos   rb = re = 0;
3188440a403fSchristos 
3189440a403fSchristos   if (argc == 1)
3190440a403fSchristos     {
3191440a403fSchristos       /* argc=1, operands pattern: { $fp $gp $lp $sp }  */
3192440a403fSchristos 
3193440a403fSchristos       /* Set register number Rb = Re = $sp = $r31.  */
3194440a403fSchristos       rb = re = 31;
3195440a403fSchristos     }
3196440a403fSchristos   else if (argc == 2 || argc == 3)
3197440a403fSchristos     {
3198440a403fSchristos       /* argc=2, operands pattern: Rb, Re  */
3199440a403fSchristos       /* argc=3, operands pattern: Rb, Re, { $fp $gp $lp $sp }  */
3200440a403fSchristos 
3201440a403fSchristos       /* Get register number in integer.  */
3202440a403fSchristos       rb = builtin_regnum (argv[0], NULL);
3203440a403fSchristos       re = builtin_regnum (argv[1], NULL);
3204440a403fSchristos 
3205440a403fSchristos       /* Rb should be equal/less than Re.  */
3206440a403fSchristos       if (rb > re)
3207440a403fSchristos 	as_bad ("The first operand (%s) should be equal to or smaller than "
3208440a403fSchristos 		"second operand (%s).", argv[0], argv[1]);
3209440a403fSchristos 
3210440a403fSchristos       /* forbid using $fp|$gp|$lp|$sp in Rb or Re
3211440a403fSchristos 		      r28 r29 r30 r31  */
3212440a403fSchristos       if (rb >= 28)
3213440a403fSchristos 	as_bad ("Cannot use $fp, $gp, $lp, or $sp at first operand !!");
3214440a403fSchristos       if (re >= 28)
3215440a403fSchristos 	as_bad ("Cannot use $fp, $gp, $lp, or $sp at second operand !!");
3216440a403fSchristos     }
3217440a403fSchristos   else
3218440a403fSchristos     {
3219440a403fSchristos       as_bad ("Invalid operands pattern !!");
3220440a403fSchristos     }
3221440a403fSchristos 
3222440a403fSchristos   /* Build Enable4 mask.  */
3223440a403fSchristos   /* Using last_arg_index for argc=1|2|3 is safe, because $fp, $gp, $lp,
3224440a403fSchristos      and $sp only appear in argc=1 or argc=3 if argc=2, en4 remains 0,
3225440a403fSchristos      which is also valid for code generation.  */
3226440a403fSchristos   en4 = 0;
3227440a403fSchristos   last_arg_index = argc - 1;
3228440a403fSchristos   if (strstr (argv[last_arg_index], "$fp"))
3229440a403fSchristos     en4 |= 8;
3230440a403fSchristos   if (strstr (argv[last_arg_index], "$gp"))
3231440a403fSchristos     en4 |= 4;
3232440a403fSchristos   if (strstr (argv[last_arg_index], "$lp"))
3233440a403fSchristos     en4 |= 2;
3234440a403fSchristos   if (strstr (argv[last_arg_index], "$sp"))
3235440a403fSchristos     en4 |= 1;
3236440a403fSchristos 
3237440a403fSchristos   md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc, rb, re, en4);
3238440a403fSchristos }
3239440a403fSchristos 
3240440a403fSchristos static void
do_pseudo_push_bhwd(int argc ATTRIBUTE_UNUSED,char * argv[],unsigned int pv ATTRIBUTE_UNUSED)324106324dcfSchristos do_pseudo_push_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[],
324206324dcfSchristos 		     unsigned int pv ATTRIBUTE_UNUSED)
3243440a403fSchristos {
3244440a403fSchristos   char size = 'x';
3245440a403fSchristos   /* If users omit push location, use $sp as default value.  */
3246440a403fSchristos   char location[8] = "$sp";  /* 8 is enough for register name.  */
3247440a403fSchristos 
3248440a403fSchristos   switch (pv & 0x3)
3249440a403fSchristos     {
3250440a403fSchristos     case 0: size = 'b'; break;
3251440a403fSchristos     case 1: size = 'h'; break;
3252440a403fSchristos     case 2: size = 'w'; break;
3253440a403fSchristos     case 3: size = 'w'; break;
3254440a403fSchristos     }
3255440a403fSchristos 
3256440a403fSchristos   if (argc == 2)
3257440a403fSchristos     {
3258440a403fSchristos       strncpy (location, argv[1], 8);
3259440a403fSchristos       location[7] = '\0';
3260440a403fSchristos     }
3261440a403fSchristos 
3262440a403fSchristos   md_assemblef ("l.%c $ta,%s", size, argv[0]);
3263440a403fSchristos   md_assemblef ("smw.adm $ta,[%s],$ta", location);
3264440a403fSchristos 
3265440a403fSchristos   if ((pv & 0x3) == 0x3) /* double-word */
3266440a403fSchristos     {
3267440a403fSchristos       md_assemblef ("l.w $ta,%s+4", argv[0]);
3268440a403fSchristos       md_assemblef ("smw.adm $ta,[%s],$ta", location);
3269440a403fSchristos     }
3270440a403fSchristos }
3271440a403fSchristos 
3272440a403fSchristos static void
do_pseudo_pop_bhwd(int argc ATTRIBUTE_UNUSED,char * argv[],unsigned int pv ATTRIBUTE_UNUSED)327306324dcfSchristos do_pseudo_pop_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[],
327406324dcfSchristos 		    unsigned int pv ATTRIBUTE_UNUSED)
3275440a403fSchristos {
3276440a403fSchristos   char size = 'x';
3277440a403fSchristos   /* If users omit pop location, use $sp as default value.  */
3278440a403fSchristos   char location[8] = "$sp";  /* 8 is enough for register name.  */
3279440a403fSchristos 
3280440a403fSchristos   switch (pv & 0x3)
3281440a403fSchristos     {
3282440a403fSchristos     case 0: size = 'b'; break;
3283440a403fSchristos     case 1: size = 'h'; break;
3284440a403fSchristos     case 2: size = 'w'; break;
3285440a403fSchristos     case 3: size = 'w'; break;
3286440a403fSchristos     }
3287440a403fSchristos 
3288440a403fSchristos   if (argc == 3)
3289440a403fSchristos     {
3290440a403fSchristos       strncpy (location, argv[2], 8);
3291440a403fSchristos       location[7] = '\0';
3292440a403fSchristos     }
3293440a403fSchristos 
3294440a403fSchristos   if ((pv & 0x3) == 0x3) /* double-word */
3295440a403fSchristos     {
3296440a403fSchristos       md_assemblef ("lmw.bim %s,[%s],%s", argv[1], location, argv[1]);
3297440a403fSchristos       md_assemblef ("s.w %s,%s+4", argv[1], argv[0]);
3298440a403fSchristos     }
3299440a403fSchristos 
3300440a403fSchristos   md_assemblef ("lmw.bim %s,[%s],%s", argv[1], location, argv[1]);
3301440a403fSchristos   md_assemblef ("s.%c %s,%s", size, argv[1], argv[0]);
3302440a403fSchristos }
3303440a403fSchristos 
3304440a403fSchristos static void
do_pseudo_pusha(int argc ATTRIBUTE_UNUSED,char * argv[],unsigned int pv ATTRIBUTE_UNUSED)330506324dcfSchristos do_pseudo_pusha (int argc ATTRIBUTE_UNUSED, char *argv[],
330606324dcfSchristos 		 unsigned int pv ATTRIBUTE_UNUSED)
3307440a403fSchristos {
3308440a403fSchristos   /* If users omit push location, use $sp as default value.  */
3309440a403fSchristos   char location[8] = "$sp";  /* 8 is enough for register name.  */
3310440a403fSchristos 
3311440a403fSchristos   if (argc == 2)
3312440a403fSchristos     {
3313440a403fSchristos       strncpy (location, argv[1], 8);
3314440a403fSchristos       location[7] = '\0';
3315440a403fSchristos     }
3316440a403fSchristos 
3317440a403fSchristos   md_assemblef ("la $ta,%s", argv[0]);
3318440a403fSchristos   md_assemblef ("smw.adm $ta,[%s],$ta", location);
3319440a403fSchristos }
3320440a403fSchristos 
3321440a403fSchristos static void
do_pseudo_pushi(int argc ATTRIBUTE_UNUSED,char * argv[],unsigned int pv ATTRIBUTE_UNUSED)332206324dcfSchristos do_pseudo_pushi (int argc ATTRIBUTE_UNUSED, char *argv[],
332306324dcfSchristos 		 unsigned int pv ATTRIBUTE_UNUSED)
3324440a403fSchristos {
3325440a403fSchristos   /* If users omit push location, use $sp as default value.  */
3326440a403fSchristos   char location[8] = "$sp";  /* 8 is enough for register name.  */
3327440a403fSchristos 
3328440a403fSchristos   if (argc == 2)
3329440a403fSchristos     {
3330440a403fSchristos       strncpy (location, argv[1], 8);
3331440a403fSchristos       location[7] = '\0';
3332440a403fSchristos     }
3333440a403fSchristos 
3334440a403fSchristos   md_assemblef ("li $ta,%s", argv[0]);
3335440a403fSchristos   md_assemblef ("smw.adm $ta,[%s],$ta", location);
3336440a403fSchristos }
3337440a403fSchristos 
3338*b88e3e88Schristos static struct nds32_pseudo_opcode nds32_pseudo_opcode_table[] =
3339440a403fSchristos {
3340440a403fSchristos   {"b",      1, do_pseudo_b,      0, 0},
3341440a403fSchristos   {"bal",    1, do_pseudo_bal,    0, 0},
3342440a403fSchristos 
3343440a403fSchristos   {"bge",    3, do_pseudo_bge,    0, 0},
3344440a403fSchristos   {"bges",   3, do_pseudo_bges,   0, 0},
3345440a403fSchristos 
3346440a403fSchristos   {"bgt",    3, do_pseudo_bgt,    0, 0},
3347440a403fSchristos   {"bgts",   3, do_pseudo_bgts,   0, 0},
3348440a403fSchristos 
3349440a403fSchristos   {"ble",    3, do_pseudo_ble,    0, 0},
3350440a403fSchristos   {"bles",   3, do_pseudo_bles,   0, 0},
3351440a403fSchristos 
3352440a403fSchristos   {"blt",    3, do_pseudo_blt,    0, 0},
3353440a403fSchristos   {"blts",   3, do_pseudo_blts,   0, 0},
3354440a403fSchristos 
3355440a403fSchristos   {"br",     1, do_pseudo_br,     0, 0},
3356440a403fSchristos   {"bral",   1, do_pseudo_bral,   0, 0},
3357440a403fSchristos 
3358440a403fSchristos   {"call",   1, do_pseudo_bal,    0, 0},
3359440a403fSchristos 
3360440a403fSchristos   {"la",     2, do_pseudo_la, 0, 0},
3361440a403fSchristos   {"li",     2, do_pseudo_li, 0, 0},
3362440a403fSchristos 
3363440a403fSchristos   {"l.b",    2, do_pseudo_ls_bhw, 0, 0},
3364440a403fSchristos   {"l.h",    2, do_pseudo_ls_bhw, 1, 0},
3365440a403fSchristos   {"l.w",    2, do_pseudo_ls_bhw, 2, 0},
3366440a403fSchristos   {"l.bs",   2, do_pseudo_ls_bhw, 0 | 0x10, 0},
3367440a403fSchristos   {"l.hs",   2, do_pseudo_ls_bhw, 1 | 0x10, 0},
3368440a403fSchristos   {"s.b",    2, do_pseudo_ls_bhw, 0 | 0x80000000, 0},
3369440a403fSchristos   {"s.h",    2, do_pseudo_ls_bhw, 1 | 0x80000000, 0},
3370440a403fSchristos   {"s.w",    2, do_pseudo_ls_bhw, 2 | 0x80000000, 0},
3371440a403fSchristos 
3372440a403fSchristos   {"l.bp",   3, do_pseudo_ls_bhwp, 0, 0},
3373440a403fSchristos   {"l.bpc",  3, do_pseudo_ls_bhwpc, 0, 0},
3374440a403fSchristos   {"l.hp",   3, do_pseudo_ls_bhwp, 1, 0},
3375440a403fSchristos   {"l.hpc",  3, do_pseudo_ls_bhwpc, 1, 0},
3376440a403fSchristos   {"l.wp",   3, do_pseudo_ls_bhwp, 2, 0},
3377440a403fSchristos   {"l.wpc",  3, do_pseudo_ls_bhwpc, 2, 0},
3378440a403fSchristos   {"l.bsp",  3, do_pseudo_ls_bhwp, 0 | 0x10, 0},
3379440a403fSchristos   {"l.bspc", 3, do_pseudo_ls_bhwpc, 0 | 0x10, 0},
3380440a403fSchristos   {"l.hsp",  3, do_pseudo_ls_bhwp, 1 | 0x10, 0},
3381440a403fSchristos   {"l.hspc", 3, do_pseudo_ls_bhwpc, 1 | 0x10, 0},
3382440a403fSchristos   {"s.bp",   3, do_pseudo_ls_bhwp, 0 | 0x80000000, 0},
3383440a403fSchristos   {"s.bpc",   3, do_pseudo_ls_bhwpc, 0 | 0x80000000, 0},
3384440a403fSchristos   {"s.hp",   3, do_pseudo_ls_bhwp, 1 | 0x80000000, 0},
3385440a403fSchristos   {"s.hpc",   3, do_pseudo_ls_bhwpc, 1 | 0x80000000, 0},
3386440a403fSchristos   {"s.wp",   3, do_pseudo_ls_bhwp, 2 | 0x80000000, 0},
3387440a403fSchristos   {"s.wpc",   3, do_pseudo_ls_bhwpc, 2 | 0x80000000, 0},
3388440a403fSchristos   {"s.bsp",  3, do_pseudo_ls_bhwp, 0 | 0x80000000 | 0x10, 0},
3389440a403fSchristos   {"s.hsp",  3, do_pseudo_ls_bhwp, 1 | 0x80000000 | 0x10, 0},
3390440a403fSchristos 
3391440a403fSchristos   {"lbi.p",  3, do_pseudo_ls_bhwi, 0, 0},
3392440a403fSchristos   {"lhi.p",  3, do_pseudo_ls_bhwi, 1, 0},
3393440a403fSchristos   {"lwi.p",  3, do_pseudo_ls_bhwi, 2, 0},
3394440a403fSchristos   {"sbi.p",  3, do_pseudo_ls_bhwi, 0 | 0x80000000, 0},
3395440a403fSchristos   {"shi.p",  3, do_pseudo_ls_bhwi, 1 | 0x80000000, 0},
3396440a403fSchristos   {"swi.p",  3, do_pseudo_ls_bhwi, 2 | 0x80000000, 0},
3397440a403fSchristos   {"lbsi.p", 3, do_pseudo_ls_bhwi, 0 | 0x10, 0},
3398440a403fSchristos   {"lhsi.p", 3, do_pseudo_ls_bhwi, 1 | 0x10, 0},
3399440a403fSchristos   {"lwsi.p", 3, do_pseudo_ls_bhwi, 2 | 0x10, 0},
3400440a403fSchristos 
3401440a403fSchristos   {"move",   2, do_pseudo_move, 0, 0},
3402440a403fSchristos   {"neg",    2, do_pseudo_neg,  0, 0},
3403440a403fSchristos   {"not",    2, do_pseudo_not,  0, 0},
3404440a403fSchristos 
3405440a403fSchristos   {"pop",    2, do_pseudo_pushpop,   0, 0},
3406440a403fSchristos   {"push",   2, do_pseudo_pushpop,   0, 0},
3407440a403fSchristos   {"popm",   2, do_pseudo_pushpopm,  0, 0},
3408440a403fSchristos   {"pushm",   3, do_pseudo_pushpopm, 0, 0},
3409440a403fSchristos 
3410440a403fSchristos   {"v3push", 2, do_pseudo_v3push, 0, 0},
3411440a403fSchristos   {"v3pop",  2, do_pseudo_v3pop,  0, 0},
3412440a403fSchristos 
3413440a403fSchristos   /* Support pseudo instructions of pushing/poping registers into/from stack
3414440a403fSchristos      push.s  Rb, Re, { $fp $gp $lp $sp }  ==>  smw.adm  Rb,[$sp],Re,Enable4
3415440a403fSchristos      pop.s   Rb, Re, { $fp $gp $lp $sp }  ==>  lmw.bim  Rb,[$sp],Re,Enable4 */
3416440a403fSchristos   { "push.s", 3, do_pseudo_pushpop_stack, 0, 0 },
3417440a403fSchristos   { "pop.s", 3, do_pseudo_pushpop_stack, 1, 0 },
3418440a403fSchristos   { "push.b", 2, do_pseudo_push_bhwd, 0, 0 },
3419440a403fSchristos   { "push.h", 2, do_pseudo_push_bhwd, 1, 0 },
3420440a403fSchristos   { "push.w", 2, do_pseudo_push_bhwd, 2, 0 },
3421440a403fSchristos   { "push.d", 2, do_pseudo_push_bhwd, 3, 0 },
3422440a403fSchristos   { "pop.b", 3, do_pseudo_pop_bhwd, 0, 0 },
3423440a403fSchristos   { "pop.h", 3, do_pseudo_pop_bhwd, 1, 0 },
3424440a403fSchristos   { "pop.w", 3, do_pseudo_pop_bhwd, 2, 0 },
3425440a403fSchristos   { "pop.d", 3, do_pseudo_pop_bhwd, 3, 0 },
3426440a403fSchristos   { "pusha", 2, do_pseudo_pusha, 0, 0 },
3427440a403fSchristos   { "pushi", 2, do_pseudo_pushi, 0, 0 },
3428440a403fSchristos 
3429440a403fSchristos   {NULL, 0, NULL, 0, 0}
3430440a403fSchristos };
3431440a403fSchristos 
3432440a403fSchristos static void
nds32_init_nds32_pseudo_opcodes(void)3433440a403fSchristos nds32_init_nds32_pseudo_opcodes (void)
3434440a403fSchristos {
3435440a403fSchristos   struct nds32_pseudo_opcode *opcode = nds32_pseudo_opcode_table;
3436440a403fSchristos 
3437440a403fSchristos   nds32_pseudo_opcode_hash = hash_new ();
3438440a403fSchristos   for ( ; opcode->opcode; opcode++)
3439440a403fSchristos     {
3440440a403fSchristos       void *op;
3441440a403fSchristos 
3442440a403fSchristos       op = hash_find (nds32_pseudo_opcode_hash, opcode->opcode);
3443440a403fSchristos       if (op != NULL)
3444440a403fSchristos 	{
3445440a403fSchristos 	  as_warn (_("Duplicated pseudo-opcode %s."), opcode->opcode);
3446440a403fSchristos 	  continue;
3447440a403fSchristos 	}
3448440a403fSchristos       hash_insert (nds32_pseudo_opcode_hash, opcode->opcode, opcode);
3449440a403fSchristos     }
3450440a403fSchristos }
3451440a403fSchristos 
3452440a403fSchristos static struct nds32_pseudo_opcode *
nds32_lookup_pseudo_opcode(const char * str)3453440a403fSchristos nds32_lookup_pseudo_opcode (const char *str)
3454440a403fSchristos {
3455*b88e3e88Schristos   struct nds32_pseudo_opcode *result;
3456440a403fSchristos   int i = 0;
3457440a403fSchristos 
3458*b88e3e88Schristos   /* (*op) is the first word of current source line (*str)  */
3459*b88e3e88Schristos   int maxlen = strlen (str);
3460*b88e3e88Schristos   char *op = xmalloc (maxlen + 1);
3461*b88e3e88Schristos 
3462*b88e3e88Schristos   for (i = 0; i < maxlen; i++)
3463440a403fSchristos     {
3464440a403fSchristos       if (ISSPACE (op[i] = str[i]))
3465440a403fSchristos 	break;
3466440a403fSchristos     }
3467440a403fSchristos   op[i] = '\0';
3468440a403fSchristos 
3469*b88e3e88Schristos   result = hash_find (nds32_pseudo_opcode_hash, op);
3470*b88e3e88Schristos   free (op);
3471*b88e3e88Schristos   return result;
3472440a403fSchristos }
3473440a403fSchristos 
3474440a403fSchristos static void
nds32_pseudo_opcode_wrapper(char * line,struct nds32_pseudo_opcode * opcode)3475440a403fSchristos nds32_pseudo_opcode_wrapper (char *line, struct nds32_pseudo_opcode *opcode)
3476440a403fSchristos {
3477440a403fSchristos   int argc = 0;
3478440a403fSchristos   char *argv[8] = {NULL};
3479440a403fSchristos   char *s;
3480440a403fSchristos   char *str = xstrdup (line);
3481440a403fSchristos 
3482440a403fSchristos   /* Parse arguments for opcode.  */
3483440a403fSchristos   s = str + strlen (opcode->opcode);
3484440a403fSchristos 
3485440a403fSchristos   if (!s[0])
3486440a403fSchristos     goto end;
3487440a403fSchristos 
3488440a403fSchristos   /* Dummy comma to ease separate arguments as below.  */
3489440a403fSchristos   s[0] = ',';
3490440a403fSchristos   do
3491440a403fSchristos     {
3492440a403fSchristos       if (s[0] == ',')
3493440a403fSchristos 	{
3494440a403fSchristos 	  if (argc >= opcode->argc
3495440a403fSchristos 	      || (argc >= (int)ARRAY_SIZE (argv) - 1))
3496440a403fSchristos 	    as_bad (_("Too many argument. `%s'"), line);
3497440a403fSchristos 
3498440a403fSchristos 	  argv[argc] = s + 1;
3499440a403fSchristos 	  argc ++;
3500440a403fSchristos 	  s[0] = '\0';
3501440a403fSchristos 	}
3502440a403fSchristos       ++s;
3503440a403fSchristos     } while (s[0] != '\0');
3504440a403fSchristos end:
3505440a403fSchristos   /* Put the origin line for debugging.  */
3506440a403fSchristos   argv[argc] = line;
3507440a403fSchristos   opcode->proc (argc, argv, opcode->pseudo_val);
3508440a403fSchristos   free (str);
3509440a403fSchristos }
3510440a403fSchristos 
3511440a403fSchristos /* This function will be invoked from function `nds32_after_parse_args'.
3512440a403fSchristos    Thus, if the value of option has been set, keep the value the way it is.  */
3513440a403fSchristos 
3514440a403fSchristos static int
nds32_parse_arch(const char * str)3515440a403fSchristos nds32_parse_arch (const char *str)
3516440a403fSchristos {
3517440a403fSchristos   static const struct nds32_arch
3518440a403fSchristos   {
3519440a403fSchristos     const char *name;
3520440a403fSchristos     int baseline;
3521440a403fSchristos     int reduced_reg;
3522440a403fSchristos     int fpu_sp_ext;
3523440a403fSchristos     int fpu_dp_ext;
3524440a403fSchristos     int fpu_freg;
3525440a403fSchristos     int abi;
3526440a403fSchristos   } archs[] =
3527440a403fSchristos   {
3528440a403fSchristos     {"v3m", ISA_V3M, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3529440a403fSchristos     {"v3j", ISA_V3,  1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3530440a403fSchristos     {"v3s", ISA_V3,  0, 1, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3531440a403fSchristos     {"v3f", ISA_V3,  0, 1, 1, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3532440a403fSchristos     {"v3",  ISA_V3,  0, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3533440a403fSchristos     {"v2j", ISA_V2,  1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3534440a403fSchristos     {"v2s", ISA_V2,  0, 1, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3535440a403fSchristos     {"v2f", ISA_V2,  0, 1, 1, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
3536440a403fSchristos     {"v2",  ISA_V2,  0, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
3537440a403fSchristos   };
3538440a403fSchristos   size_t i;
3539440a403fSchristos 
3540440a403fSchristos   for (i = 0; i < ARRAY_SIZE (archs); i++)
3541440a403fSchristos     {
3542440a403fSchristos       if (strcmp (str, archs[i].name) != 0)
3543440a403fSchristos 	continue;
3544440a403fSchristos 
3545440a403fSchristos       /* The value `-1' represents this option has *NOT* been set.  */
3546440a403fSchristos       nds32_baseline = (-1 != nds32_baseline) ? nds32_baseline : archs[i].baseline;
3547440a403fSchristos       nds32_gpr16 = (-1 != nds32_gpr16) ? nds32_gpr16 : archs[i].reduced_reg;
3548440a403fSchristos       nds32_fpu_sp_ext = (-1 != nds32_fpu_sp_ext) ? nds32_fpu_sp_ext : archs[i].fpu_sp_ext;
3549440a403fSchristos       nds32_fpu_dp_ext = (-1 != nds32_fpu_dp_ext) ? nds32_fpu_dp_ext : archs[i].fpu_dp_ext;
3550440a403fSchristos       nds32_freg = (-1 != nds32_freg) ? nds32_freg : archs[i].fpu_freg;
3551440a403fSchristos       nds32_abi = (-1 != nds32_abi) ? nds32_abi : archs[i].abi;
3552440a403fSchristos 
3553440a403fSchristos       return 1;
3554440a403fSchristos     }
3555440a403fSchristos 
3556440a403fSchristos   /* Logic here rejects the input arch name.  */
3557440a403fSchristos   as_bad (_("unknown arch name `%s'\n"), str);
3558440a403fSchristos 
3559440a403fSchristos   return 1;
3560440a403fSchristos }
3561440a403fSchristos 
3562440a403fSchristos /* This function parses "baseline" specified.  */
3563440a403fSchristos 
3564440a403fSchristos static int
nds32_parse_baseline(const char * str)3565440a403fSchristos nds32_parse_baseline (const char *str)
3566440a403fSchristos {
3567440a403fSchristos   if (strcmp (str, "v3") == 0)
3568440a403fSchristos     nds32_baseline = ISA_V3;
3569440a403fSchristos   else if (strcmp (str, "v3m") == 0)
3570440a403fSchristos     nds32_baseline = ISA_V3M;
3571440a403fSchristos   else if (strcmp (str, "v2") == 0)
3572440a403fSchristos     nds32_baseline = ISA_V2;
3573440a403fSchristos   else
3574440a403fSchristos     {
3575440a403fSchristos       /* Logic here rejects the input baseline.  */
3576440a403fSchristos       as_bad (_("unknown baseline `%s'\n"), str);
3577440a403fSchristos       return 0;
3578440a403fSchristos     }
3579440a403fSchristos 
3580440a403fSchristos   return 1;
3581440a403fSchristos }
3582440a403fSchristos 
3583440a403fSchristos /* This function parses "fpu-freg" specified.  */
3584440a403fSchristos 
3585440a403fSchristos static int
nds32_parse_freg(const char * str)3586440a403fSchristos nds32_parse_freg (const char *str)
3587440a403fSchristos {
3588440a403fSchristos   if (strcmp (str, "2") == 0)
3589440a403fSchristos     nds32_freg = E_NDS32_FPU_REG_32SP_16DP;
3590440a403fSchristos   else if (strcmp (str, "3") == 0)
3591440a403fSchristos     nds32_freg = E_NDS32_FPU_REG_32SP_32DP;
3592440a403fSchristos   else if (strcmp (str, "1") == 0)
3593440a403fSchristos     nds32_freg = E_NDS32_FPU_REG_16SP_8DP;
3594440a403fSchristos   else if (strcmp (str, "0") == 0)
3595440a403fSchristos     nds32_freg = E_NDS32_FPU_REG_8SP_4DP;
3596440a403fSchristos   else
3597440a403fSchristos     {
3598440a403fSchristos       /* Logic here rejects the input FPU configuration.  */
3599440a403fSchristos       as_bad (_("unknown FPU configuration `%s'\n"), str);
3600440a403fSchristos       return 0;
3601440a403fSchristos     }
3602440a403fSchristos 
3603440a403fSchristos   return 1;
3604440a403fSchristos }
3605440a403fSchristos 
3606440a403fSchristos /* This function parse "abi=" specified.  */
3607440a403fSchristos 
3608440a403fSchristos static int
nds32_parse_abi(const char * str)3609440a403fSchristos nds32_parse_abi (const char *str)
3610440a403fSchristos {
3611440a403fSchristos   if (strcmp (str, "v2") == 0)
3612440a403fSchristos     nds32_abi = E_NDS_ABI_AABI;
3613440a403fSchristos   /* Obsolete.  */
3614440a403fSchristos   else if (strcmp (str, "v2fp") == 0)
3615440a403fSchristos     nds32_abi = E_NDS_ABI_V2FP;
3616440a403fSchristos   else if (strcmp (str, "v1") == 0)
3617440a403fSchristos     nds32_abi = E_NDS_ABI_V1;
3618440a403fSchristos   else if (strcmp (str,"v2fpp") == 0)
3619440a403fSchristos     nds32_abi = E_NDS_ABI_V2FP_PLUS;
3620440a403fSchristos   else
3621440a403fSchristos     {
3622440a403fSchristos       /* Logic here rejects the input abi version.  */
3623440a403fSchristos       as_bad (_("unknown ABI version`%s'\n"), str);
3624440a403fSchristos       return 0;
3625440a403fSchristos     }
3626440a403fSchristos 
3627440a403fSchristos   return 1;
3628440a403fSchristos }
3629440a403fSchristos 
3630440a403fSchristos /* This function turn on all extensions and instructions support.  */
3631440a403fSchristos 
3632440a403fSchristos static int
nds32_all_ext(void)3633440a403fSchristos nds32_all_ext (void)
3634440a403fSchristos {
3635440a403fSchristos   nds32_mac = 1;
3636440a403fSchristos   nds32_div = 1;
3637440a403fSchristos   nds32_dx_regs = 1;
3638440a403fSchristos   nds32_16bit_ext = 1;
3639440a403fSchristos   nds32_perf_ext = 1;
3640440a403fSchristos   nds32_perf_ext2 = 1;
3641440a403fSchristos   nds32_string_ext = 1;
3642440a403fSchristos   nds32_audio_ext = 1;
3643440a403fSchristos   nds32_fpu_fma = 1;
3644440a403fSchristos   nds32_fpu_sp_ext = 1;
3645440a403fSchristos   nds32_fpu_dp_ext = 1;
3646*b88e3e88Schristos   nds32_dsp_ext = 1;
3647*b88e3e88Schristos   nds32_zol_ext = 1;
3648*b88e3e88Schristos   /* Turn off reduced register.  */
3649*b88e3e88Schristos   nds32_gpr16 = 0;
3650440a403fSchristos 
3651440a403fSchristos   return 1;
3652440a403fSchristos }
3653440a403fSchristos 
3654440a403fSchristos /* GAS will call md_parse_option whenever getopt returns an unrecognized code,
3655440a403fSchristos    presumably indicating a special code value which appears in md_longopts.
3656440a403fSchristos    This function should return non-zero if it handled the option and zero
3657440a403fSchristos    otherwise.  There is no need to print a message about an option not being
3658440a403fSchristos    recognized.  This will be handled by the generic code.  */
3659440a403fSchristos 
3660440a403fSchristos int
nds32_parse_option(int c,const char * arg)3661440a403fSchristos nds32_parse_option (int c, const char *arg)
3662440a403fSchristos {
3663440a403fSchristos   struct nds32_parse_option_table *coarse_tune;
3664440a403fSchristos   struct nds32_set_option_table *fine_tune;
3665440a403fSchristos   const char *ptr_arg = NULL;
3666440a403fSchristos 
3667440a403fSchristos   switch (c)
3668440a403fSchristos     {
3669440a403fSchristos     case OPTION_OPTIMIZE:
3670440a403fSchristos       optimize = 1;
3671440a403fSchristos       optimize_for_space = 0;
3672440a403fSchristos       break;
3673440a403fSchristos     case OPTION_OPTIMIZE_SPACE:
3674440a403fSchristos       optimize = 0;
3675440a403fSchristos       optimize_for_space = 1;
3676440a403fSchristos       break;
3677440a403fSchristos     case OPTION_BIG:
3678440a403fSchristos       target_big_endian = 1;
3679440a403fSchristos       break;
3680440a403fSchristos     case OPTION_LITTLE:
3681440a403fSchristos       target_big_endian = 0;
3682440a403fSchristos       break;
3683440a403fSchristos     case OPTION_TURBO:
3684440a403fSchristos       nds32_all_ext ();
3685440a403fSchristos       break;
3686440a403fSchristos     case OPTION_PIC:
3687440a403fSchristos       nds32_pic = 1;
3688440a403fSchristos       break;
3689440a403fSchristos     case OPTION_RELAX_FP_AS_GP_OFF:
3690440a403fSchristos       nds32_relax_fp_as_gp = 0;
3691440a403fSchristos       break;
3692440a403fSchristos     case OPTION_RELAX_B2BB_ON:
3693440a403fSchristos       nds32_relax_b2bb = 1;
3694440a403fSchristos       break;
3695440a403fSchristos     case OPTION_RELAX_ALL_OFF:
3696440a403fSchristos       nds32_relax_all = 0;
3697440a403fSchristos       break;
3698440a403fSchristos     default:
3699440a403fSchristos       /* Determination of which option table to search for to save time.  */
3700440a403fSchristos       if (!arg)
3701440a403fSchristos 	return 0;
3702440a403fSchristos 
3703440a403fSchristos       ptr_arg = strchr (arg, '=');
3704440a403fSchristos 
3705440a403fSchristos       if (ptr_arg)
3706440a403fSchristos 	{
3707440a403fSchristos 	  /* Find the value after '='.  */
3708440a403fSchristos 	  if (ptr_arg != NULL)
3709440a403fSchristos 	    ptr_arg++;
3710440a403fSchristos 	  for (coarse_tune = parse_opts; coarse_tune->name != NULL; coarse_tune++)
3711440a403fSchristos 	    {
3712440a403fSchristos 	      if (strncmp (arg, coarse_tune->name, (ptr_arg - arg)) == 0)
3713440a403fSchristos 		{
3714440a403fSchristos 		  coarse_tune->func (ptr_arg);
3715440a403fSchristos 		  return 1;
3716440a403fSchristos 		}
3717440a403fSchristos 	    }
3718440a403fSchristos 	}
3719440a403fSchristos       else
3720440a403fSchristos 	{
3721440a403fSchristos 	  int disable = 0;
3722440a403fSchristos 
3723440a403fSchristos 	  /* Filter out the Disable option first.  */
3724440a403fSchristos 	  if (strncmp (arg, "no-", 3) == 0)
3725440a403fSchristos 	    {
3726440a403fSchristos 	      disable = 1;
3727440a403fSchristos 	      arg += 3;
3728440a403fSchristos 	    }
3729440a403fSchristos 
3730440a403fSchristos 	  for (fine_tune = toggle_opts; fine_tune->name != NULL; fine_tune++)
3731440a403fSchristos 	    {
3732440a403fSchristos 	      if (strcmp (arg, fine_tune->name) == 0)
3733440a403fSchristos 		{
3734440a403fSchristos 		  if (fine_tune->var != NULL)
3735440a403fSchristos 		    *fine_tune->var = (disable) ? 0 : 1;
3736440a403fSchristos 		  return 1;
3737440a403fSchristos 		}
3738440a403fSchristos 	    }
3739440a403fSchristos 	}
3740440a403fSchristos       /* Nothing match.  */
3741440a403fSchristos       return 0;
3742440a403fSchristos     }
3743440a403fSchristos 
3744440a403fSchristos   return 1;
3745440a403fSchristos }
3746440a403fSchristos 
3747440a403fSchristos /* tc_check_label  */
3748440a403fSchristos 
3749440a403fSchristos void
nds32_check_label(symbolS * label ATTRIBUTE_UNUSED)3750440a403fSchristos nds32_check_label (symbolS *label ATTRIBUTE_UNUSED)
3751440a403fSchristos {
3752440a403fSchristos   /* The code used to create BB is move to frob_label.
3753440a403fSchristos      They should go there.  */
3754440a403fSchristos }
3755440a403fSchristos 
3756440a403fSchristos static void
set_endian_little(int on)3757440a403fSchristos set_endian_little (int on)
3758440a403fSchristos {
3759440a403fSchristos   target_big_endian = !on;
3760440a403fSchristos }
3761440a403fSchristos 
3762440a403fSchristos /* These functions toggles the generation of 16-bit.  First encounter signals
3763440a403fSchristos    the beginning of not generating 16-bit instructions and next encounter
3764440a403fSchristos    signals the restoring back to default behavior.  */
3765440a403fSchristos 
3766440a403fSchristos static void
trigger_16bit(int trigger)3767440a403fSchristos trigger_16bit (int trigger)
3768440a403fSchristos {
3769440a403fSchristos   enable_16bit = trigger;
3770440a403fSchristos }
3771440a403fSchristos 
3772440a403fSchristos static int backup_16bit_mode;
3773440a403fSchristos static void
restore_16bit(int no_use ATTRIBUTE_UNUSED)3774440a403fSchristos restore_16bit (int no_use ATTRIBUTE_UNUSED)
3775440a403fSchristos {
3776440a403fSchristos   enable_16bit = backup_16bit_mode;
3777440a403fSchristos }
3778440a403fSchristos 
3779440a403fSchristos static void
off_16bit(int no_use ATTRIBUTE_UNUSED)3780440a403fSchristos off_16bit (int no_use ATTRIBUTE_UNUSED)
3781440a403fSchristos {
3782440a403fSchristos   backup_16bit_mode = enable_16bit;
3783440a403fSchristos   enable_16bit = 0;
3784440a403fSchristos }
3785440a403fSchristos 
3786440a403fSchristos /* Built-in segments for small object.  */
3787440a403fSchristos typedef struct nds32_seg_entryT
3788440a403fSchristos {
3789440a403fSchristos   segT s;
3790440a403fSchristos   const char *name;
3791440a403fSchristos   flagword flags;
3792440a403fSchristos } nds32_seg_entry;
3793440a403fSchristos 
3794440a403fSchristos nds32_seg_entry nds32_seg_table[] =
3795440a403fSchristos {
3796440a403fSchristos   {NULL, ".sdata_f", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3797440a403fSchristos 		     | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3798440a403fSchristos   {NULL, ".sdata_b", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3799440a403fSchristos 		     | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3800440a403fSchristos   {NULL, ".sdata_h", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3801440a403fSchristos 		     | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3802440a403fSchristos   {NULL, ".sdata_w", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3803440a403fSchristos 		     | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3804440a403fSchristos   {NULL, ".sdata_d", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
3805440a403fSchristos 		     | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
3806440a403fSchristos   {NULL, ".sbss_f", SEC_ALLOC | SEC_SMALL_DATA},
3807440a403fSchristos   {NULL, ".sbss_b", SEC_ALLOC | SEC_SMALL_DATA},
3808440a403fSchristos   {NULL, ".sbss_h", SEC_ALLOC | SEC_SMALL_DATA},
3809440a403fSchristos   {NULL, ".sbss_w", SEC_ALLOC | SEC_SMALL_DATA},
3810440a403fSchristos   {NULL, ".sbss_d", SEC_ALLOC | SEC_SMALL_DATA}
3811440a403fSchristos };
3812440a403fSchristos 
3813440a403fSchristos /* Indexes to nds32_seg_table[].  */
3814440a403fSchristos enum NDS32_SECTIONS_ENUM
3815440a403fSchristos {
3816440a403fSchristos   SDATA_F_SECTION = 0,
3817440a403fSchristos   SDATA_B_SECTION = 1,
3818440a403fSchristos   SDATA_H_SECTION = 2,
3819440a403fSchristos   SDATA_W_SECTION = 3,
3820440a403fSchristos   SDATA_D_SECTION = 4,
3821440a403fSchristos   SBSS_F_SECTION = 5,
3822440a403fSchristos   SBSS_B_SECTION = 6,
3823440a403fSchristos   SBSS_H_SECTION = 7,
3824440a403fSchristos   SBSS_W_SECTION = 8,
3825440a403fSchristos   SBSS_D_SECTION = 9
3826440a403fSchristos };
3827440a403fSchristos 
3828440a403fSchristos /* The following code is borrowed from v850_seg.  Revise this is needed.  */
3829440a403fSchristos 
3830440a403fSchristos static void
do_nds32_seg(int i,subsegT sub)3831440a403fSchristos do_nds32_seg (int i, subsegT sub)
3832440a403fSchristos {
3833440a403fSchristos   nds32_seg_entry *seg = nds32_seg_table + i;
3834440a403fSchristos 
3835440a403fSchristos   obj_elf_section_change_hook ();
3836440a403fSchristos 
3837440a403fSchristos   if (seg->s != NULL)
3838440a403fSchristos     subseg_set (seg->s, sub);
3839440a403fSchristos   else
3840440a403fSchristos     {
3841440a403fSchristos       seg->s = subseg_new (seg->name, sub);
3842440a403fSchristos       if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
3843440a403fSchristos 	{
3844*b88e3e88Schristos 	  bfd_set_section_flags (seg->s, seg->flags);
3845440a403fSchristos 	  if ((seg->flags & SEC_LOAD) == 0)
3846440a403fSchristos 	    seg_info (seg->s)->bss = 1;
3847440a403fSchristos 	}
3848440a403fSchristos     }
3849440a403fSchristos }
3850440a403fSchristos 
3851440a403fSchristos static void
nds32_seg(int i)3852440a403fSchristos nds32_seg (int i)
3853440a403fSchristos {
3854440a403fSchristos   subsegT sub = get_absolute_expression ();
3855440a403fSchristos 
3856440a403fSchristos   do_nds32_seg (i, sub);
3857440a403fSchristos   demand_empty_rest_of_line ();
3858440a403fSchristos }
3859440a403fSchristos 
3860440a403fSchristos /* Set if label adjustment is needed.  I should not adjust .xbyte in dwarf.  */
386106324dcfSchristos static symbolS *nds32_last_label;	/* Last label for alignment.  */
3862440a403fSchristos 
3863*b88e3e88Schristos static void
add_mapping_symbol_for_align(int shift,valueT addr,int is_data_align)3864*b88e3e88Schristos add_mapping_symbol_for_align (int shift, valueT addr, int is_data_align)
3865*b88e3e88Schristos {
3866*b88e3e88Schristos   if ((shift > 1) && (addr & 1))
3867*b88e3e88Schristos     {
3868*b88e3e88Schristos       int n = (1 << shift) - 1;
3869*b88e3e88Schristos       if (!is_data_align)
3870*b88e3e88Schristos 	add_mapping_symbol (MAP_CODE, 1, 0);
3871*b88e3e88Schristos       else if ((int) (addr & n) != n)
3872*b88e3e88Schristos 	add_mapping_symbol (MAP_CODE, 1, 0);
3873*b88e3e88Schristos     }
3874*b88e3e88Schristos   else if ((shift > 1) && ((int) (addr & 1) == 0))
3875*b88e3e88Schristos     add_mapping_symbol (MAP_CODE, 0, 0);
3876*b88e3e88Schristos }
3877*b88e3e88Schristos 
387806324dcfSchristos /* This code is referred from D30V for adjust label to be with pending
387906324dcfSchristos    alignment.  For example,
3880440a403fSchristos      LBYTE: .byte	0x12
3881440a403fSchristos      LHALF: .half	0x12
3882440a403fSchristos      LWORD: .word	0x12
388306324dcfSchristos    Without this, the above label will not attach to incoming data.  */
3884440a403fSchristos 
3885440a403fSchristos static void
nds32_adjust_label(int n)3886440a403fSchristos nds32_adjust_label (int n)
3887440a403fSchristos {
388806324dcfSchristos   /* FIXME: I think adjust label and alignment is
388906324dcfSchristos      the programmer's obligation.  Sadly, VLSI team doesn't
3890440a403fSchristos      properly use .align for their test cases.
3891440a403fSchristos      So I re-implement cons_align and auto adjust labels, again.
3892440a403fSchristos 
389306324dcfSchristos      I think d30v's implementation is simple and good enough.  */
3894440a403fSchristos 
3895440a403fSchristos   symbolS *label = nds32_last_label;
3896440a403fSchristos   nds32_last_label = NULL;
3897440a403fSchristos 
3898440a403fSchristos   /* SEC_ALLOC is used to eliminate .debug_ sections.
3899440a403fSchristos      SEC_CODE is used to include section for ILM.  */
3900440a403fSchristos   if (((now_seg->flags & SEC_ALLOC) == 0 && (now_seg->flags & SEC_CODE) == 0)
3901440a403fSchristos       || strcmp (now_seg->name, ".eh_frame") == 0
3902440a403fSchristos       || strcmp (now_seg->name, ".gcc_except_table") == 0)
3903440a403fSchristos     return;
3904440a403fSchristos 
3905440a403fSchristos   /* Only frag by alignment when needed.
3906440a403fSchristos      Otherwise, it will fail to optimize labels on 4-byte boundary.  (bug8454)
3907440a403fSchristos      See md_convert_frag () and RELAX_SET_RELAXABLE (frag) for details.  */
3908440a403fSchristos   if (frag_now_fix () & ((1 << n) -1 ))
3909440a403fSchristos     {
3910440a403fSchristos       if (subseg_text_p (now_seg))
3911*b88e3e88Schristos 	{
3912*b88e3e88Schristos 	  add_mapping_symbol_for_align (n, frag_now_fix (), 1);
3913440a403fSchristos 	  frag_align_code (n, 0);
3914*b88e3e88Schristos 	}
3915440a403fSchristos       else
3916440a403fSchristos 	frag_align (n, 0, 0);
3917440a403fSchristos 
3918440a403fSchristos       /* Record the minimum alignment for this segment.  */
3919440a403fSchristos       record_alignment (now_seg, n - OCTETS_PER_BYTE_POWER);
3920440a403fSchristos     }
3921440a403fSchristos 
3922440a403fSchristos   if (label != NULL)
3923440a403fSchristos     {
3924440a403fSchristos       symbolS *sym;
3925440a403fSchristos       int label_seen = FALSE;
3926440a403fSchristos       struct frag *old_frag;
3927440a403fSchristos       valueT old_value, new_value;
3928440a403fSchristos 
3929440a403fSchristos       gas_assert (S_GET_SEGMENT (label) == now_seg);
3930440a403fSchristos 
3931440a403fSchristos       old_frag  = symbol_get_frag (label);
3932440a403fSchristos       old_value = S_GET_VALUE (label);
3933440a403fSchristos       new_value = (valueT) frag_now_fix ();
3934440a403fSchristos 
3935440a403fSchristos       /* Multiple labels may be on the same address.  And the last symbol
3936440a403fSchristos 	 may not be a label at all, e.g., register name, external function names,
3937440a403fSchristos 	 so I have to track the last label in tc_frob_label instead of
3938440a403fSchristos 	 just using symbol_lastP.  */
3939440a403fSchristos       for (sym = symbol_lastP; sym != NULL; sym = symbol_previous (sym))
3940440a403fSchristos 	{
3941440a403fSchristos 	  if (symbol_get_frag (sym) == old_frag
3942440a403fSchristos 	      && S_GET_VALUE (sym) == old_value)
3943440a403fSchristos 	    {
3944440a403fSchristos 	      /* Warning HERE! */
3945440a403fSchristos 	      label_seen = TRUE;
3946440a403fSchristos 	      symbol_set_frag (sym, frag_now);
3947440a403fSchristos 	      S_SET_VALUE (sym, new_value);
3948440a403fSchristos 	    }
3949440a403fSchristos 	  else if (label_seen && symbol_get_frag (sym) != old_frag)
3950440a403fSchristos 	    break;
3951440a403fSchristos 	}
3952440a403fSchristos     }
3953440a403fSchristos }
3954440a403fSchristos 
3955440a403fSchristos void
nds32_cons_align(int size ATTRIBUTE_UNUSED)3956440a403fSchristos nds32_cons_align (int size ATTRIBUTE_UNUSED)
3957440a403fSchristos {
3958440a403fSchristos   /* Do nothing here.
3959440a403fSchristos      This is called before `md_flush_pending_output' is called by `cons'.
3960440a403fSchristos 
3961440a403fSchristos      There are two things should be done for auto-adjust-label.
3962440a403fSchristos      1. Align data/instructions and adjust label to be attached to them.
396306324dcfSchristos      2. Clear auto-adjust state, so incoming data/instructions will not
3964440a403fSchristos 	adjust the label.
3965440a403fSchristos 
3966440a403fSchristos      For example,
3967440a403fSchristos 	  .byte 0x1
3968440a403fSchristos 	.L0:
3969440a403fSchristos 	  .word 0x2
3970440a403fSchristos 	  .word 0x3
3971440a403fSchristos      in this case, '.word 0x2' will adjust the label, .L0, but '.word 0x3' should not.
3972440a403fSchristos 
3973440a403fSchristos      I think `md_flush_pending_output' is a good place to clear the auto-adjust state,
3974440a403fSchristos      but it is also called by `cons' before this function.
3975440a403fSchristos      To simplify the code, instead of overriding .zero, .fill, .space, etc,
3976440a403fSchristos      I think we should just adjust label in `nds32_aligned_X_cons' instead of here.  */
3977440a403fSchristos }
3978440a403fSchristos 
3979440a403fSchristos static void
make_mapping_symbol(enum mstate state,valueT value,fragS * frag,unsigned int align)3980*b88e3e88Schristos make_mapping_symbol (enum mstate state, valueT value, fragS * frag, unsigned int align)
3981*b88e3e88Schristos {
3982*b88e3e88Schristos   symbolS *symbol_p = NULL;
3983*b88e3e88Schristos   const char *symbol_name = NULL;
3984*b88e3e88Schristos   switch (state)
3985*b88e3e88Schristos     {
3986*b88e3e88Schristos     case MAP_DATA:
3987*b88e3e88Schristos       if (align == 0)
3988*b88e3e88Schristos 	symbol_name = "$d0";
3989*b88e3e88Schristos       else if (align == 1)
3990*b88e3e88Schristos 	symbol_name = "$d1";
3991*b88e3e88Schristos       else if (align == 2)
3992*b88e3e88Schristos 	symbol_name = "$d2";
3993*b88e3e88Schristos       else if (align == 3)
3994*b88e3e88Schristos 	symbol_name = "$d3";
3995*b88e3e88Schristos       else if (align == 4)
3996*b88e3e88Schristos 	symbol_name = "$d4";
3997*b88e3e88Schristos       break;
3998*b88e3e88Schristos     case MAP_CODE:
3999*b88e3e88Schristos       symbol_name = "$c";
4000*b88e3e88Schristos       break;
4001*b88e3e88Schristos     default:
4002*b88e3e88Schristos       abort ();
4003*b88e3e88Schristos     }
4004*b88e3e88Schristos 
4005*b88e3e88Schristos   symbol_p = symbol_new (symbol_name, now_seg, value, frag);
4006*b88e3e88Schristos   /* local scope attribute  */
4007*b88e3e88Schristos   symbol_get_bfdsym (symbol_p)->flags |= BSF_NO_FLAGS | BSF_LOCAL;
4008*b88e3e88Schristos }
4009*b88e3e88Schristos 
4010*b88e3e88Schristos static void
add_mapping_symbol(enum mstate state,unsigned int padding_byte,unsigned int align)4011*b88e3e88Schristos add_mapping_symbol (enum mstate state, unsigned int padding_byte,
4012*b88e3e88Schristos 		    unsigned int align)
4013*b88e3e88Schristos {
4014*b88e3e88Schristos   enum mstate current_mapping_state =
4015*b88e3e88Schristos     seg_info (now_seg)->tc_segment_info_data.mapstate;
4016*b88e3e88Schristos 
4017*b88e3e88Schristos   if (state == MAP_CODE
4018*b88e3e88Schristos       && current_mapping_state == state)
4019*b88e3e88Schristos     return;
4020*b88e3e88Schristos 
4021*b88e3e88Schristos   if (!SEG_NORMAL (now_seg)
4022*b88e3e88Schristos       || !subseg_text_p (now_seg))
4023*b88e3e88Schristos     return;
4024*b88e3e88Schristos 
4025*b88e3e88Schristos   /* start adding mapping symbol  */
4026*b88e3e88Schristos   seg_info (now_seg)->tc_segment_info_data.mapstate = state;
4027*b88e3e88Schristos   make_mapping_symbol (state, (valueT) frag_now_fix () + padding_byte,
4028*b88e3e88Schristos 		       frag_now, align);
4029*b88e3e88Schristos }
4030*b88e3e88Schristos 
4031*b88e3e88Schristos static void
nds32_aligned_cons(int idx)4032440a403fSchristos nds32_aligned_cons (int idx)
4033440a403fSchristos {
4034440a403fSchristos   nds32_adjust_label (idx);
4035*b88e3e88Schristos   add_mapping_symbol (MAP_DATA, 0, idx);
4036440a403fSchristos   /* Call default handler.  */
4037440a403fSchristos   cons (1 << idx);
4038440a403fSchristos   if (now_seg->flags & SEC_CODE
4039440a403fSchristos       && now_seg->flags & SEC_ALLOC && now_seg->flags & SEC_RELOC)
4040440a403fSchristos     {
4041*b88e3e88Schristos       /* Use BFD_RELOC_NDS32_DATA to avoid linker
4042*b88e3e88Schristos 	 optimization replacing data.  */
4043440a403fSchristos       expressionS exp;
4044440a403fSchristos 
4045440a403fSchristos       exp.X_add_number = 0;
4046440a403fSchristos       exp.X_op = O_constant;
4047440a403fSchristos       fix_new_exp (frag_now, frag_now_fix () - (1 << idx), 1 << idx,
4048440a403fSchristos 		   &exp, 0, BFD_RELOC_NDS32_DATA);
4049440a403fSchristos     }
4050440a403fSchristos }
4051440a403fSchristos 
4052440a403fSchristos /* `.double' directive.  */
4053440a403fSchristos 
4054440a403fSchristos static void
nds32_aligned_float_cons(int type)4055440a403fSchristos nds32_aligned_float_cons (int type)
4056440a403fSchristos {
4057440a403fSchristos   switch (type)
4058440a403fSchristos     {
4059440a403fSchristos     case 'f':
4060440a403fSchristos     case 'F':
4061440a403fSchristos     case 's':
4062440a403fSchristos     case 'S':
4063440a403fSchristos       nds32_adjust_label (2);
4064440a403fSchristos       break;
4065440a403fSchristos     case 'd':
4066440a403fSchristos     case 'D':
4067440a403fSchristos     case 'r':
4068440a403fSchristos     case 'R':
4069440a403fSchristos       nds32_adjust_label (4);
4070440a403fSchristos       break;
4071440a403fSchristos     default:
4072440a403fSchristos       as_bad ("Unrecognized float type, %c\n", (char)type);
4073440a403fSchristos     }
4074440a403fSchristos   /* Call default handler.  */
4075440a403fSchristos   float_cons (type);
4076440a403fSchristos }
4077440a403fSchristos 
4078440a403fSchristos static void
nds32_enable_pic(int ignore ATTRIBUTE_UNUSED)4079440a403fSchristos nds32_enable_pic (int ignore ATTRIBUTE_UNUSED)
4080440a403fSchristos {
4081440a403fSchristos   /* Another way to do -mpic.
4082440a403fSchristos      This is for GCC internal use and should always be first line
4083440a403fSchristos      of code, otherwise, the effect is not determined.  */
4084440a403fSchristos   nds32_pic = 1;
4085440a403fSchristos }
4086440a403fSchristos 
4087440a403fSchristos static void
nds32_set_abi(int ver)4088440a403fSchristos nds32_set_abi (int ver)
4089440a403fSchristos {
4090440a403fSchristos   nds32_abi = ver;
4091440a403fSchristos }
4092440a403fSchristos 
4093440a403fSchristos /* Relax directive to set relocation R_NDS32_RELAX_ENTRY value.  */
4094440a403fSchristos 
4095440a403fSchristos static void
nds32_relax_relocs(int relax)4096440a403fSchristos nds32_relax_relocs (int relax)
4097440a403fSchristos {
4098440a403fSchristos   char saved_char;
4099440a403fSchristos   char *name;
4100440a403fSchristos   int i;
4101440a403fSchristos   const char *subtype_relax[] =
4102*b88e3e88Schristos     {"", "",};
4103440a403fSchristos 
4104440a403fSchristos   name = input_line_pointer;
4105440a403fSchristos   while (*input_line_pointer && !ISSPACE (*input_line_pointer))
4106440a403fSchristos     input_line_pointer++;
4107440a403fSchristos   saved_char = *input_line_pointer;
4108440a403fSchristos   *input_line_pointer = 0;
4109440a403fSchristos 
4110440a403fSchristos   for (i = 0; i < (int) ARRAY_SIZE (subtype_relax); i++)
4111440a403fSchristos     {
4112440a403fSchristos       if (strcmp (name, subtype_relax[i]) == 0)
4113440a403fSchristos 	{
4114440a403fSchristos 	  switch (i)
4115440a403fSchristos 	    {
4116440a403fSchristos 	    case 0:
4117440a403fSchristos 	    case 1:
4118440a403fSchristos 	      enable_relax_relocs = relax & enable_relax_relocs;
4119440a403fSchristos 	      break;
4120440a403fSchristos 	    default:
4121440a403fSchristos 	      break;
4122440a403fSchristos 	    }
4123440a403fSchristos 	  break;
4124440a403fSchristos 	}
4125440a403fSchristos     }
4126440a403fSchristos   *input_line_pointer = saved_char;
4127440a403fSchristos   ignore_rest_of_line ();
4128440a403fSchristos }
4129440a403fSchristos 
4130440a403fSchristos /* Record which arguments register($r0 ~ $r5) is not used in callee.
4131440a403fSchristos    bit[i] for $ri  */
4132440a403fSchristos 
4133440a403fSchristos static void
nds32_set_hint_func_args(int ignore ATTRIBUTE_UNUSED)4134440a403fSchristos nds32_set_hint_func_args (int ignore ATTRIBUTE_UNUSED)
4135440a403fSchristos {
4136440a403fSchristos   ignore_rest_of_line ();
4137440a403fSchristos }
4138440a403fSchristos 
4139440a403fSchristos /* Insert relocations to mark the begin and end of a fp-omitted function,
4140440a403fSchristos    for further relaxation use.
4141440a403fSchristos    bit[i] for $ri  */
4142440a403fSchristos 
4143440a403fSchristos static void
nds32_omit_fp_begin(int mode)4144440a403fSchristos nds32_omit_fp_begin (int mode)
4145440a403fSchristos {
4146440a403fSchristos   expressionS exp;
4147440a403fSchristos 
4148440a403fSchristos   if (nds32_relax_fp_as_gp == 0)
4149440a403fSchristos     return;
4150440a403fSchristos   exp.X_op = O_symbol;
4151440a403fSchristos   exp.X_add_symbol = abs_section_sym;
4152440a403fSchristos   if (mode == 1)
4153440a403fSchristos     {
4154440a403fSchristos       in_omit_fp = 1;
4155440a403fSchristos       exp.X_add_number = R_NDS32_RELAX_REGION_OMIT_FP_FLAG;
4156440a403fSchristos       fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
4157440a403fSchristos 		   BFD_RELOC_NDS32_RELAX_REGION_BEGIN);
4158440a403fSchristos     }
4159440a403fSchristos   else
4160440a403fSchristos     {
4161440a403fSchristos       in_omit_fp = 0;
4162440a403fSchristos       exp.X_add_number = R_NDS32_RELAX_REGION_OMIT_FP_FLAG;
4163440a403fSchristos       fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
4164440a403fSchristos 		   BFD_RELOC_NDS32_RELAX_REGION_END);
4165440a403fSchristos     }
4166440a403fSchristos }
4167440a403fSchristos 
4168440a403fSchristos static void
nds32_loop_begin(int mode)4169440a403fSchristos nds32_loop_begin (int mode)
4170440a403fSchristos {
4171440a403fSchristos   /* Insert loop region relocation here.  */
4172440a403fSchristos   expressionS exp;
4173440a403fSchristos 
4174440a403fSchristos   exp.X_op = O_symbol;
4175440a403fSchristos   exp.X_add_symbol = abs_section_sym;
4176440a403fSchristos   if (mode == 1)
4177440a403fSchristos     {
4178440a403fSchristos       exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG;
4179440a403fSchristos       fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
4180440a403fSchristos 		   BFD_RELOC_NDS32_RELAX_REGION_BEGIN);
4181440a403fSchristos     }
4182440a403fSchristos   else
4183440a403fSchristos     {
4184440a403fSchristos       exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG;
4185440a403fSchristos       fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
4186440a403fSchristos 		   BFD_RELOC_NDS32_RELAX_REGION_END);
4187440a403fSchristos     }
4188440a403fSchristos }
4189440a403fSchristos 
4190440a403fSchristos struct nds32_relocs_group
4191440a403fSchristos {
4192440a403fSchristos   struct nds32_relocs_pattern *pattern;
4193440a403fSchristos   struct nds32_relocs_group *next;
4194440a403fSchristos };
4195440a403fSchristos 
4196440a403fSchristos static struct nds32_relocs_group *nds32_relax_hint_current = NULL;
4197*b88e3e88Schristos /* Used to reorder the id for ".relax_hint id".  */
4198*b88e3e88Schristos static int relax_hint_bias = 0;
4199*b88e3e88Schristos /* Record current relax hint id.  */
4200*b88e3e88Schristos static int relax_hint_id_current = -1;
4201*b88e3e88Schristos int reset_bias = 0;
4202*b88e3e88Schristos /* If ".relax_hint begin" is triggered?  */
4203*b88e3e88Schristos int relax_hint_begin = 0;
4204*b88e3e88Schristos 
4205*b88e3e88Schristos /* Record the reordered relax hint id.  */
4206*b88e3e88Schristos 
4207*b88e3e88Schristos struct relax_hint_id
4208*b88e3e88Schristos {
4209*b88e3e88Schristos   int old_id;
4210*b88e3e88Schristos   int new_id;
4211*b88e3e88Schristos   struct relax_hint_id *next;
4212*b88e3e88Schristos };
4213*b88e3e88Schristos 
4214*b88e3e88Schristos /* FIXME: Need to find somewhere to free the list.  */
4215*b88e3e88Schristos struct relax_hint_id *record_id_head = NULL;
4216*b88e3e88Schristos 
4217*b88e3e88Schristos /* Is the buffer large enough?  */
4218*b88e3e88Schristos #define MAX_BUFFER 12
4219*b88e3e88Schristos 
4220*b88e3e88Schristos static char *nds_itoa (int n);
4221*b88e3e88Schristos 
4222*b88e3e88Schristos static char *
nds_itoa(int n)4223*b88e3e88Schristos nds_itoa (int n)
4224*b88e3e88Schristos {
4225*b88e3e88Schristos   char *buf = xmalloc (MAX_BUFFER * sizeof (char));
4226*b88e3e88Schristos   snprintf (buf, MAX_BUFFER, "%d", n);
4227*b88e3e88Schristos   return buf;
4228*b88e3e88Schristos }
4229440a403fSchristos 
4230440a403fSchristos /* Insert a relax hint.  */
4231440a403fSchristos 
4232440a403fSchristos static void
nds32_relax_hint(int mode ATTRIBUTE_UNUSED)4233440a403fSchristos nds32_relax_hint (int mode ATTRIBUTE_UNUSED)
4234440a403fSchristos {
4235*b88e3e88Schristos   char *name = NULL;
4236440a403fSchristos   char saved_char;
4237440a403fSchristos   struct nds32_relocs_pattern *relocs = NULL;
4238440a403fSchristos   struct nds32_relocs_group *group, *new;
4239*b88e3e88Schristos   struct relax_hint_id *record_id;
4240440a403fSchristos 
4241440a403fSchristos   name = input_line_pointer;
4242440a403fSchristos   while (*input_line_pointer && !ISSPACE (*input_line_pointer))
4243440a403fSchristos     input_line_pointer++;
4244440a403fSchristos   saved_char = *input_line_pointer;
4245440a403fSchristos   *input_line_pointer = 0;
4246440a403fSchristos   name = strdup (name);
4247440a403fSchristos 
4248*b88e3e88Schristos   if (name && strcmp (name, "begin") == 0)
4249*b88e3e88Schristos     {
4250*b88e3e88Schristos       if (relax_hint_id_current == -1)
4251*b88e3e88Schristos 	reset_bias = 1;
4252*b88e3e88Schristos       relax_hint_bias++;
4253*b88e3e88Schristos       relax_hint_id_current++;
4254*b88e3e88Schristos       relax_hint_begin = 1;
4255*b88e3e88Schristos     }
4256*b88e3e88Schristos 
4257*b88e3e88Schristos   /* Original case ".relax_hint id".  It's id may need to be reordered. */
4258*b88e3e88Schristos   if (!relax_hint_begin)
4259*b88e3e88Schristos     {
4260*b88e3e88Schristos       int tmp = strtol (name, NULL, 10);
4261*b88e3e88Schristos       record_id = record_id_head;
4262*b88e3e88Schristos       while (record_id)
4263*b88e3e88Schristos 	{
4264*b88e3e88Schristos 	  if (record_id->old_id == tmp)
4265*b88e3e88Schristos 	    {
4266*b88e3e88Schristos 	      name = nds_itoa (record_id->new_id);
4267*b88e3e88Schristos 	      goto reordered_id;
4268*b88e3e88Schristos 	    }
4269*b88e3e88Schristos 	  record_id = record_id->next;
4270*b88e3e88Schristos 	}
4271*b88e3e88Schristos       if (reset_bias)
4272*b88e3e88Schristos 	{
4273*b88e3e88Schristos 	  relax_hint_bias = relax_hint_id_current - atoi (name) + 1;
4274*b88e3e88Schristos 	  reset_bias = 0;
4275*b88e3e88Schristos 	}
4276*b88e3e88Schristos       relax_hint_id_current = tmp + relax_hint_bias;
4277*b88e3e88Schristos 
4278*b88e3e88Schristos       /* Insert the element to the head of the link list.  */
4279*b88e3e88Schristos       struct relax_hint_id *tmp_id = malloc (sizeof (struct relax_hint_id));
4280*b88e3e88Schristos       tmp_id->old_id = tmp;
4281*b88e3e88Schristos       tmp_id->new_id = relax_hint_id_current;
4282*b88e3e88Schristos       tmp_id->next = record_id_head;
4283*b88e3e88Schristos       record_id_head = tmp_id;
4284*b88e3e88Schristos     }
4285*b88e3e88Schristos 
4286*b88e3e88Schristos   if (name && strcmp (name, "end") == 0)
4287*b88e3e88Schristos     relax_hint_begin = 0;
4288*b88e3e88Schristos   name = nds_itoa (relax_hint_id_current);
4289*b88e3e88Schristos 
4290*b88e3e88Schristos reordered_id:
4291*b88e3e88Schristos 
4292440a403fSchristos   /* Find relax hint entry for next instruction, and all member will be
4293440a403fSchristos      initialized at that time.  */
4294440a403fSchristos   relocs = hash_find (nds32_hint_hash, name);
4295440a403fSchristos   if (relocs == NULL)
4296440a403fSchristos     {
4297440a403fSchristos       relocs = XNEW (struct nds32_relocs_pattern);
4298*b88e3e88Schristos       memset (relocs, 0, sizeof (struct nds32_relocs_pattern));
4299440a403fSchristos       hash_insert (nds32_hint_hash, name, relocs);
4300440a403fSchristos     }
4301440a403fSchristos   else
4302440a403fSchristos     {
4303440a403fSchristos       while (relocs->next)
4304440a403fSchristos 	relocs=relocs->next;
4305440a403fSchristos       relocs->next = XNEW (struct nds32_relocs_pattern);
4306440a403fSchristos       relocs = relocs->next;
4307*b88e3e88Schristos       memset (relocs, 0, sizeof (struct nds32_relocs_pattern));
4308440a403fSchristos     }
4309440a403fSchristos 
4310440a403fSchristos   relocs->next = NULL;
4311440a403fSchristos   *input_line_pointer = saved_char;
4312440a403fSchristos   ignore_rest_of_line ();
4313440a403fSchristos 
4314440a403fSchristos   /* Get the final one of relax hint series.  */
4315440a403fSchristos 
4316440a403fSchristos   /* It has to build this list because there are maybe more than one
4317440a403fSchristos      instructions relative to the same instruction.  It to connect to
4318440a403fSchristos      next instruction after md_assemble.  */
4319440a403fSchristos   new = XNEW (struct nds32_relocs_group);
4320*b88e3e88Schristos   memset (new, 0, sizeof (struct nds32_relocs_group));
4321440a403fSchristos   new->pattern = relocs;
4322440a403fSchristos   new->next = NULL;
4323440a403fSchristos   group = nds32_relax_hint_current;
4324440a403fSchristos   if (!group)
4325440a403fSchristos     nds32_relax_hint_current = new;
4326440a403fSchristos   else
4327440a403fSchristos     {
4328440a403fSchristos       while (group->next != NULL)
4329440a403fSchristos 	group = group->next;
4330440a403fSchristos       group->next = new;
4331440a403fSchristos     }
4332440a403fSchristos   relaxing = TRUE;
4333440a403fSchristos }
4334440a403fSchristos 
4335440a403fSchristos /* Decide the size of vector entries, only accepts 4 or 16 now.  */
4336440a403fSchristos 
4337440a403fSchristos static void
nds32_vec_size(int ignore ATTRIBUTE_UNUSED)4338440a403fSchristos nds32_vec_size (int ignore ATTRIBUTE_UNUSED)
4339440a403fSchristos {
4340440a403fSchristos   expressionS exp;
4341440a403fSchristos 
4342440a403fSchristos   expression (&exp);
4343440a403fSchristos 
4344440a403fSchristos   if (exp.X_op == O_constant)
4345440a403fSchristos     {
4346440a403fSchristos       if (exp.X_add_number == 4 || exp.X_add_number == 16)
4347440a403fSchristos 	{
4348440a403fSchristos 	  if (vec_size == 0)
4349440a403fSchristos 	    vec_size = exp.X_add_number;
4350440a403fSchristos 	  else if (vec_size != exp.X_add_number)
4351440a403fSchristos 	    as_warn (_("Different arguments of .vec_size are found, "
4352440a403fSchristos 		       "previous %d, current %d"),
4353440a403fSchristos 		     (int) vec_size, (int) exp.X_add_number);
4354440a403fSchristos 	}
4355440a403fSchristos       else
4356440a403fSchristos 	as_warn (_("Argument of .vec_size is expected 4 or 16, actual: %d."),
4357440a403fSchristos 		 (int) exp.X_add_number);
4358440a403fSchristos     }
4359440a403fSchristos   else
4360440a403fSchristos     as_warn (_("Argument of .vec_size is not a constant."));
4361440a403fSchristos }
4362440a403fSchristos 
4363440a403fSchristos /* The behavior of ".flag" directive varies depending on the target.
4364440a403fSchristos    In nds32 target, we use it to recognize whether this assembly content is
4365440a403fSchristos    generated by compiler.  Other features can also be added in this function
4366440a403fSchristos    in the future.  */
4367440a403fSchristos 
4368440a403fSchristos static void
nds32_flag(int ignore ATTRIBUTE_UNUSED)4369440a403fSchristos nds32_flag (int ignore ATTRIBUTE_UNUSED)
4370440a403fSchristos {
4371440a403fSchristos   char *name;
4372440a403fSchristos   char saved_char;
4373440a403fSchristos   int i;
4374440a403fSchristos   const char *possible_flags[] = { "verbatim" };
4375440a403fSchristos 
4376440a403fSchristos   /* Skip whitespaces.  */
4377440a403fSchristos   name = input_line_pointer;
4378440a403fSchristos   while (*input_line_pointer && !ISSPACE (*input_line_pointer))
4379440a403fSchristos     input_line_pointer++;
4380440a403fSchristos   saved_char = *input_line_pointer;
4381440a403fSchristos   *input_line_pointer = 0;
4382440a403fSchristos 
4383440a403fSchristos   for (i = 0; i < (int) ARRAY_SIZE (possible_flags); i++)
4384440a403fSchristos     {
4385440a403fSchristos       if (strcmp (name, possible_flags[i]) == 0)
4386440a403fSchristos 	{
4387440a403fSchristos 	  switch (i)
4388440a403fSchristos 	    {
4389440a403fSchristos 	    case 0:
4390440a403fSchristos 	      /* flag: verbatim */
4391440a403fSchristos 	      verbatim = 1;
4392440a403fSchristos 	      break;
4393440a403fSchristos 	    default:
4394440a403fSchristos 	      break;
4395440a403fSchristos 	    }
4396440a403fSchristos 	  /* Already found the flag, no need to continue next loop.   */
4397440a403fSchristos 	  break;
4398440a403fSchristos 	}
4399440a403fSchristos     }
4400440a403fSchristos 
4401440a403fSchristos   *input_line_pointer = saved_char;
4402440a403fSchristos   ignore_rest_of_line ();
4403440a403fSchristos }
4404*b88e3e88Schristos 
440506324dcfSchristos static void
ict_model(int ignore ATTRIBUTE_UNUSED)440606324dcfSchristos ict_model (int ignore ATTRIBUTE_UNUSED)
440706324dcfSchristos {
440806324dcfSchristos   char *name;
440906324dcfSchristos   char saved_char;
441006324dcfSchristos   int i;
441106324dcfSchristos   const char *possible_flags[] = { "small", "large" };
441206324dcfSchristos 
441306324dcfSchristos   /* Skip whitespaces.  */
441406324dcfSchristos   name = input_line_pointer;
441506324dcfSchristos   while (*input_line_pointer && !ISSPACE (*input_line_pointer))
441606324dcfSchristos     input_line_pointer++;
441706324dcfSchristos   saved_char = *input_line_pointer;
441806324dcfSchristos   *input_line_pointer = 0;
441906324dcfSchristos 
442006324dcfSchristos   for (i = 0; i < (int) ARRAY_SIZE (possible_flags); i++)
442106324dcfSchristos     {
442206324dcfSchristos       if (strcmp (name, possible_flags[i]) == 0)
442306324dcfSchristos 	{
442406324dcfSchristos 	  switch (i)
442506324dcfSchristos 	    {
442606324dcfSchristos 	    case 0:
442706324dcfSchristos 	      /* flag: verbatim  */
442806324dcfSchristos 	      ict_flag = ICT_SMALL;
442906324dcfSchristos 	      break;
443006324dcfSchristos 	    case 1:
443106324dcfSchristos 	      ict_flag = ICT_LARGE;
443206324dcfSchristos 	      break;
443306324dcfSchristos 	    default:
443406324dcfSchristos 	      break;
443506324dcfSchristos 	    }
443606324dcfSchristos 	  /* Already found the flag, no need to continue next loop.   */
443706324dcfSchristos 	  break;
443806324dcfSchristos 	}
443906324dcfSchristos     }
444006324dcfSchristos 
444106324dcfSchristos   *input_line_pointer = saved_char;
444206324dcfSchristos   ignore_rest_of_line ();
444306324dcfSchristos }
4444440a403fSchristos 
4445440a403fSchristos static void
nds32_n12hc(int ignore ATTRIBUTE_UNUSED)4446440a403fSchristos nds32_n12hc (int ignore ATTRIBUTE_UNUSED)
4447440a403fSchristos {
4448440a403fSchristos   /* N1213HC core is used.  */
4449440a403fSchristos }
4450440a403fSchristos 
4451440a403fSchristos 
4452440a403fSchristos /* The target specific pseudo-ops which we support.  */
4453440a403fSchristos const pseudo_typeS md_pseudo_table[] =
4454440a403fSchristos {
4455440a403fSchristos   /* Forced alignment if declared these ways.  */
4456440a403fSchristos   {"ascii", stringer, 8 + 0},
4457440a403fSchristos   {"asciz", stringer, 8 + 1},
4458440a403fSchristos   {"double", nds32_aligned_float_cons, 'd'},
4459440a403fSchristos   {"dword", nds32_aligned_cons, 3},
4460440a403fSchristos   {"float", nds32_aligned_float_cons, 'f'},
4461440a403fSchristos   {"half", nds32_aligned_cons, 1},
4462440a403fSchristos   {"hword", nds32_aligned_cons, 1},
4463440a403fSchristos   {"int", nds32_aligned_cons, 2},
4464440a403fSchristos   {"long", nds32_aligned_cons, 2},
4465440a403fSchristos   {"octa", nds32_aligned_cons, 4},
4466440a403fSchristos   {"quad", nds32_aligned_cons, 3},
4467440a403fSchristos   {"qword", nds32_aligned_cons, 4},
4468440a403fSchristos   {"short", nds32_aligned_cons, 1},
4469440a403fSchristos   {"byte", nds32_aligned_cons, 0},
4470440a403fSchristos   {"single", nds32_aligned_float_cons, 'f'},
4471440a403fSchristos   {"string", stringer, 8 + 1},
4472440a403fSchristos   {"word", nds32_aligned_cons, 2},
4473440a403fSchristos 
4474440a403fSchristos   {"little", set_endian_little, 1},
4475440a403fSchristos   {"big", set_endian_little, 0},
4476440a403fSchristos   {"16bit_on", trigger_16bit, 1},
4477440a403fSchristos   {"16bit_off", trigger_16bit, 0},
4478440a403fSchristos   {"restore_16bit", restore_16bit, 0},
4479440a403fSchristos   {"off_16bit", off_16bit, 0},
4480440a403fSchristos 
4481440a403fSchristos   {"sdata_d", nds32_seg, SDATA_D_SECTION},
4482440a403fSchristos   {"sdata_w", nds32_seg, SDATA_W_SECTION},
4483440a403fSchristos   {"sdata_h", nds32_seg, SDATA_H_SECTION},
4484440a403fSchristos   {"sdata_b", nds32_seg, SDATA_B_SECTION},
4485440a403fSchristos   {"sdata_f", nds32_seg, SDATA_F_SECTION},
4486440a403fSchristos 
4487440a403fSchristos   {"sbss_d", nds32_seg, SBSS_D_SECTION},
4488440a403fSchristos   {"sbss_w", nds32_seg, SBSS_W_SECTION},
4489440a403fSchristos   {"sbss_h", nds32_seg, SBSS_H_SECTION},
4490440a403fSchristos   {"sbss_b", nds32_seg, SBSS_B_SECTION},
4491440a403fSchristos   {"sbss_f", nds32_seg, SBSS_F_SECTION},
4492440a403fSchristos 
4493440a403fSchristos   {"pic", nds32_enable_pic, 0},
4494440a403fSchristos   {"n12_hc", nds32_n12hc, 0},
4495440a403fSchristos   {"abi_1", nds32_set_abi, E_NDS_ABI_V1},
4496440a403fSchristos   {"abi_2", nds32_set_abi, E_NDS_ABI_AABI},
4497440a403fSchristos   /* Obsolete.  */
4498440a403fSchristos   {"abi_2fp", nds32_set_abi, E_NDS_ABI_V2FP},
4499440a403fSchristos   {"abi_2fp_plus", nds32_set_abi, E_NDS_ABI_V2FP_PLUS},
4500440a403fSchristos   {"relax", nds32_relax_relocs, 1},
4501440a403fSchristos   {"no_relax", nds32_relax_relocs, 0},
4502440a403fSchristos   {"hint_func_args", nds32_set_hint_func_args, 0}, /* Abandon??  */
4503440a403fSchristos   {"omit_fp_begin", nds32_omit_fp_begin, 1},
4504440a403fSchristos   {"omit_fp_end", nds32_omit_fp_begin, 0},
4505440a403fSchristos   {"vec_size", nds32_vec_size, 0},
4506440a403fSchristos   {"flag", nds32_flag, 0},
4507440a403fSchristos   {"innermost_loop_begin", nds32_loop_begin, 1},
4508440a403fSchristos   {"innermost_loop_end", nds32_loop_begin, 0},
4509440a403fSchristos   {"relax_hint", nds32_relax_hint, 0},
451006324dcfSchristos   {"ict_model", ict_model, 0},
4511440a403fSchristos   {NULL, NULL, 0}
4512440a403fSchristos };
4513440a403fSchristos 
4514440a403fSchristos void
nds32_pre_do_align(int n,char * fill,int len,int max)4515440a403fSchristos nds32_pre_do_align (int n, char *fill, int len, int max)
4516440a403fSchristos {
4517440a403fSchristos   /* Only make a frag if we HAVE to...  */
4518440a403fSchristos   fragS *fragP;
4519440a403fSchristos   if (n != 0 && !need_pass_2)
4520440a403fSchristos     {
4521440a403fSchristos       if (fill == NULL)
4522440a403fSchristos 	{
4523440a403fSchristos 	  if (subseg_text_p (now_seg))
4524440a403fSchristos 	    {
4525440a403fSchristos 	      dwarf2_emit_insn (0);
4526440a403fSchristos 	      fragP = frag_now;
4527*b88e3e88Schristos 	      add_mapping_symbol_for_align (n, frag_now_fix (), 0);
4528440a403fSchristos 	      frag_align_code (n, max);
4529440a403fSchristos 
453006324dcfSchristos 	      /* Tag this alignment when there is a label before it.  */
4531440a403fSchristos 	      if (label_exist)
4532440a403fSchristos 		{
4533440a403fSchristos 		  fragP->tc_frag_data.flag = NDS32_FRAG_LABEL;
4534440a403fSchristos 		  label_exist = 0;
4535440a403fSchristos 		}
4536440a403fSchristos 	    }
4537440a403fSchristos 	  else
4538440a403fSchristos 	    frag_align (n, 0, max);
4539440a403fSchristos 	}
4540440a403fSchristos       else if (len <= 1)
4541440a403fSchristos 	frag_align (n, *fill, max);
4542440a403fSchristos       else
4543440a403fSchristos 	frag_align_pattern (n, fill, len, max);
4544440a403fSchristos     }
4545440a403fSchristos }
4546440a403fSchristos 
4547440a403fSchristos void
nds32_do_align(int n)4548440a403fSchristos nds32_do_align (int n)
4549440a403fSchristos {
4550440a403fSchristos   /* Optimize for space and label exists.  */
4551440a403fSchristos   expressionS exp;
4552440a403fSchristos 
4553440a403fSchristos   /* FIXME:I think this will break debug info sections and except_table.  */
4554440a403fSchristos   if (!enable_relax_relocs || !subseg_text_p (now_seg))
4555440a403fSchristos     return;
4556440a403fSchristos 
4557440a403fSchristos   /* Create and attach a BFD_RELOC_NDS32_LABEL fixup
4558440a403fSchristos      the size of instruction may not be correct because
4559440a403fSchristos      it could be relaxable.  */
4560440a403fSchristos   exp.X_op = O_symbol;
4561440a403fSchristos   exp.X_add_symbol = section_symbol (now_seg);
4562440a403fSchristos   exp.X_add_number = n;
4563440a403fSchristos   fix_new_exp (frag_now,
4564440a403fSchristos 	       frag_now_fix (), 0, &exp, 0, BFD_RELOC_NDS32_LABEL);
4565440a403fSchristos }
4566440a403fSchristos 
4567440a403fSchristos /* Supported Andes machines.  */
4568440a403fSchristos struct nds32_machs
4569440a403fSchristos {
4570440a403fSchristos   enum bfd_architecture bfd_mach;
4571440a403fSchristos   int mach_flags;
4572440a403fSchristos };
4573440a403fSchristos 
4574440a403fSchristos /* This is the callback for nds32-asm.c to parse operands.  */
4575440a403fSchristos 
4576440a403fSchristos int
nds32_asm_parse_operand(struct nds32_asm_desc * pdesc ATTRIBUTE_UNUSED,struct nds32_asm_insn * pinsn,char ** pstr,int64_t * value)4577440a403fSchristos nds32_asm_parse_operand (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED,
4578440a403fSchristos 			 struct nds32_asm_insn *pinsn,
4579440a403fSchristos 			 char **pstr, int64_t *value)
4580440a403fSchristos {
4581440a403fSchristos   char *hold;
4582440a403fSchristos   expressionS *pexp = pinsn->info;
4583440a403fSchristos 
4584440a403fSchristos   hold = input_line_pointer;
4585440a403fSchristos   input_line_pointer = *pstr;
4586440a403fSchristos   expression (pexp);
4587440a403fSchristos   *pstr = input_line_pointer;
4588440a403fSchristos   input_line_pointer = hold;
4589440a403fSchristos 
4590440a403fSchristos   switch (pexp->X_op)
4591440a403fSchristos     {
4592440a403fSchristos     case O_symbol:
4593440a403fSchristos       *value = 0;
4594440a403fSchristos       return NASM_R_SYMBOL;
4595440a403fSchristos     case O_constant:
4596440a403fSchristos       *value = pexp->X_add_number;
4597440a403fSchristos       return NASM_R_CONST;
4598440a403fSchristos     case O_illegal:
4599440a403fSchristos     case O_absent:
4600440a403fSchristos     case O_register:
4601440a403fSchristos     default:
4602440a403fSchristos       return NASM_R_ILLEGAL;
4603440a403fSchristos     }
4604440a403fSchristos }
4605440a403fSchristos 
4606440a403fSchristos /* GAS will call this function at the start of the assembly, after the command
4607440a403fSchristos    line arguments have been parsed and all the machine independent
4608440a403fSchristos    initializations have been completed.  */
4609440a403fSchristos 
4610440a403fSchristos void
md_begin(void)4611440a403fSchristos md_begin (void)
4612440a403fSchristos {
4613440a403fSchristos   struct nds32_keyword *k;
4614*b88e3e88Schristos   relax_info_t *relax_info;
4615*b88e3e88Schristos   int flags = 0;
4616440a403fSchristos 
4617440a403fSchristos   bfd_set_arch_mach (stdoutput, TARGET_ARCH, nds32_baseline);
4618440a403fSchristos 
4619440a403fSchristos   nds32_init_nds32_pseudo_opcodes ();
4620440a403fSchristos   asm_desc.parse_operand = nds32_asm_parse_operand;
4621*b88e3e88Schristos   if (nds32_gpr16)
4622*b88e3e88Schristos     flags |= NASM_OPEN_REDUCED_REG;
4623*b88e3e88Schristos   nds32_asm_init (&asm_desc, flags);
4624440a403fSchristos 
462506324dcfSchristos   /* Initial general purpose registers hash table.  */
4626440a403fSchristos   nds32_gprs_hash = hash_new ();
4627440a403fSchristos   for (k = keyword_gpr; k->name; k++)
4628440a403fSchristos     hash_insert (nds32_gprs_hash, k->name, k);
4629440a403fSchristos 
4630440a403fSchristos   /* Initial branch hash table.  */
4631440a403fSchristos   nds32_relax_info_hash = hash_new ();
4632*b88e3e88Schristos   for (relax_info = relax_table; relax_info->opcode; relax_info++)
4633*b88e3e88Schristos     hash_insert (nds32_relax_info_hash, relax_info->opcode, relax_info);
4634440a403fSchristos 
4635440a403fSchristos   /* Initial relax hint hash table.  */
4636440a403fSchristos   nds32_hint_hash = hash_new ();
4637440a403fSchristos   enable_16bit = nds32_16bit_ext;
4638440a403fSchristos }
4639440a403fSchristos 
4640440a403fSchristos /* HANDLE_ALIGN in write.c.  */
4641440a403fSchristos 
4642440a403fSchristos void
nds32_handle_align(fragS * fragp)4643440a403fSchristos nds32_handle_align (fragS *fragp)
4644440a403fSchristos {
4645440a403fSchristos   static const unsigned char nop16[] = { 0x92, 0x00 };
4646440a403fSchristos   static const unsigned char nop32[] = { 0x40, 0x00, 0x00, 0x09 };
4647440a403fSchristos   int bytes;
4648440a403fSchristos   char *p;
4649440a403fSchristos 
4650440a403fSchristos   if (fragp->fr_type != rs_align_code)
4651440a403fSchristos     return;
4652440a403fSchristos 
4653440a403fSchristos   bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
4654440a403fSchristos   p = fragp->fr_literal + fragp->fr_fix;
4655440a403fSchristos 
4656440a403fSchristos   if (bytes & 1)
4657440a403fSchristos     {
4658440a403fSchristos       *p++ = 0;
4659440a403fSchristos       bytes--;
4660440a403fSchristos     }
4661440a403fSchristos 
4662440a403fSchristos   if (bytes & 2)
4663440a403fSchristos     {
4664440a403fSchristos       expressionS exp_t;
4665440a403fSchristos       exp_t.X_op = O_symbol;
4666440a403fSchristos       exp_t.X_add_symbol = abs_section_sym;
4667440a403fSchristos       exp_t.X_add_number = R_NDS32_INSN16_CONVERT_FLAG;
4668440a403fSchristos       fix_new_exp (fragp, fragp->fr_fix, 2, &exp_t, 0,
4669440a403fSchristos 		   BFD_RELOC_NDS32_INSN16);
4670440a403fSchristos       memcpy (p, nop16, 2);
4671440a403fSchristos       p += 2;
4672440a403fSchristos       bytes -= 2;
4673440a403fSchristos     }
4674440a403fSchristos 
4675440a403fSchristos   while (bytes >= 4)
4676440a403fSchristos     {
4677440a403fSchristos       memcpy (p, nop32, 4);
4678440a403fSchristos       p += 4;
4679440a403fSchristos       bytes -= 4;
4680440a403fSchristos     }
4681440a403fSchristos 
4682440a403fSchristos   bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
4683440a403fSchristos   fragp->fr_fix += bytes;
4684440a403fSchristos }
4685440a403fSchristos 
4686440a403fSchristos /* md_flush_pending_output  */
4687440a403fSchristos 
4688440a403fSchristos void
nds32_flush_pending_output(void)4689440a403fSchristos nds32_flush_pending_output (void)
4690440a403fSchristos {
4691440a403fSchristos   nds32_last_label = NULL;
4692440a403fSchristos }
4693440a403fSchristos 
4694440a403fSchristos void
nds32_frob_label(symbolS * label)4695440a403fSchristos nds32_frob_label (symbolS *label)
4696440a403fSchristos {
4697440a403fSchristos   dwarf2_emit_label (label);
4698440a403fSchristos }
4699440a403fSchristos 
4700440a403fSchristos /* TC_START_LABEL  */
4701440a403fSchristos 
4702440a403fSchristos int
nds32_start_label(int asmdone ATTRIBUTE_UNUSED,int secdone ATTRIBUTE_UNUSED)4703440a403fSchristos nds32_start_label (int asmdone ATTRIBUTE_UNUSED, int secdone ATTRIBUTE_UNUSED)
4704440a403fSchristos {
4705440a403fSchristos   if (optimize && subseg_text_p (now_seg))
4706440a403fSchristos     label_exist = 1;
4707440a403fSchristos   return 1;
4708440a403fSchristos }
4709440a403fSchristos 
4710440a403fSchristos /* TARGET_FORMAT  */
4711440a403fSchristos 
4712440a403fSchristos const char *
nds32_target_format(void)4713440a403fSchristos nds32_target_format (void)
4714440a403fSchristos {
4715440a403fSchristos #ifdef TE_LINUX
4716440a403fSchristos   if (target_big_endian)
4717440a403fSchristos     return "elf32-nds32be-linux";
4718440a403fSchristos   else
4719440a403fSchristos     return "elf32-nds32le-linux";
4720440a403fSchristos #else
4721440a403fSchristos   if (target_big_endian)
4722440a403fSchristos     return "elf32-nds32be";
4723440a403fSchristos   else
4724440a403fSchristos     return "elf32-nds32le";
4725440a403fSchristos #endif
4726440a403fSchristos }
4727440a403fSchristos 
4728440a403fSchristos static enum nds32_br_range
get_range_type(const struct nds32_field * field)4729440a403fSchristos get_range_type (const struct nds32_field *field)
4730440a403fSchristos {
4731440a403fSchristos   gas_assert (field != NULL);
4732440a403fSchristos 
4733440a403fSchristos   if (field->bitpos != 0)
4734440a403fSchristos     return BR_RANGE_U4G;
4735440a403fSchristos 
4736440a403fSchristos   if (field->bitsize == 24 && field->shift == 1)
4737440a403fSchristos     return BR_RANGE_S16M;
4738440a403fSchristos   else if (field->bitsize == 16 && field->shift == 1)
4739440a403fSchristos     return BR_RANGE_S64K;
4740440a403fSchristos   else if (field->bitsize == 14 && field->shift == 1)
4741440a403fSchristos     return BR_RANGE_S16K;
4742440a403fSchristos   else if (field->bitsize == 8 && field->shift == 1)
4743440a403fSchristos     return BR_RANGE_S256;
4744440a403fSchristos   else
4745440a403fSchristos     return BR_RANGE_U4G;
4746440a403fSchristos }
4747440a403fSchristos 
4748440a403fSchristos /* Save pseudo instruction relocation list.  */
4749440a403fSchristos 
4750440a403fSchristos static struct nds32_relocs_pattern*
nds32_elf_save_pseudo_pattern(fixS * fixP,struct nds32_asm_insn * insn,char * out,symbolS * sym,struct nds32_relocs_pattern * reloc_ptr,fragS * fragP)4751*b88e3e88Schristos nds32_elf_save_pseudo_pattern (fixS* fixP, struct nds32_asm_insn *insn,
4752440a403fSchristos 			       char *out, symbolS *sym,
4753440a403fSchristos 			       struct nds32_relocs_pattern *reloc_ptr,
4754440a403fSchristos 			       fragS *fragP)
4755440a403fSchristos {
4756*b88e3e88Schristos   struct nds32_opcode *opcode = insn->opcode;
4757440a403fSchristos   if (!reloc_ptr)
4758440a403fSchristos     reloc_ptr = XNEW (struct nds32_relocs_pattern);
4759440a403fSchristos   reloc_ptr->seg = now_seg;
4760440a403fSchristos   reloc_ptr->sym = sym;
4761440a403fSchristos   reloc_ptr->frag = fragP;
4762440a403fSchristos   reloc_ptr->frchain = frchain_now;
4763440a403fSchristos   reloc_ptr->fixP = fixP;
4764440a403fSchristos   reloc_ptr->opcode = opcode;
4765440a403fSchristos   reloc_ptr->where = out;
4766*b88e3e88Schristos   reloc_ptr->insn = insn->insn;
4767440a403fSchristos   reloc_ptr->next = NULL;
4768440a403fSchristos   return reloc_ptr;
4769440a403fSchristos }
4770440a403fSchristos 
4771440a403fSchristos /* Check X_md to transform relocation.  */
4772440a403fSchristos 
4773440a403fSchristos static fixS*
nds32_elf_record_fixup_exp(fragS * fragP,const char * str,const struct nds32_field * fld,expressionS * pexp,char * out,struct nds32_asm_insn * insn)4774440a403fSchristos nds32_elf_record_fixup_exp (fragS *fragP, const char *str,
4775440a403fSchristos 			    const struct nds32_field *fld,
4776440a403fSchristos 			    expressionS *pexp, char* out,
4777440a403fSchristos 			    struct nds32_asm_insn *insn)
4778440a403fSchristos {
4779440a403fSchristos   int reloc = -1;
4780440a403fSchristos   expressionS exp;
4781440a403fSchristos   fixS *fixP = NULL;
4782440a403fSchristos 
4783440a403fSchristos   /* Handle instruction relocation.  */
4784440a403fSchristos   if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_HI20))
4785440a403fSchristos     {
4786440a403fSchristos       /* Relocation for hi20 modifier.  */
4787440a403fSchristos       switch (pexp->X_md)
4788440a403fSchristos 	{
4789440a403fSchristos 	case BFD_RELOC_NDS32_GOTOFF:	/* @GOTOFF */
4790440a403fSchristos 	  reloc = BFD_RELOC_NDS32_GOTOFF_HI20;
4791440a403fSchristos 	  break;
4792440a403fSchristos 	case BFD_RELOC_NDS32_GOT20:	/* @GOT */
4793440a403fSchristos 	  reloc = BFD_RELOC_NDS32_GOT_HI20;
4794440a403fSchristos 	  break;
4795440a403fSchristos 	case BFD_RELOC_NDS32_25_PLTREL:	/* @PLT */
4796440a403fSchristos 	  if (!nds32_pic)
4797440a403fSchristos 	    as_bad (_("Invalid PIC expression."));
4798440a403fSchristos 	  else
4799440a403fSchristos 	    reloc = BFD_RELOC_NDS32_PLT_GOTREL_HI20;
4800440a403fSchristos 	  break;
4801440a403fSchristos 	case BFD_RELOC_NDS32_GOTPC20:	/* _GLOBAL_OFFSET_TABLE_ */
4802440a403fSchristos 	  reloc = BFD_RELOC_NDS32_GOTPC_HI20;
4803440a403fSchristos 	  break;
4804440a403fSchristos 	case BFD_RELOC_NDS32_TPOFF:	/* @TPOFF */
4805440a403fSchristos 	  reloc = BFD_RELOC_NDS32_TLS_LE_HI20;
4806440a403fSchristos 	  break;
4807440a403fSchristos 	case BFD_RELOC_NDS32_GOTTPOFF:	/* @GOTTPOFF */
4808*b88e3e88Schristos 	  reloc = nds32_pic ? BFD_RELOC_NDS32_TLS_IEGP_HI20 : BFD_RELOC_NDS32_TLS_IE_HI20;
4809440a403fSchristos 	  break;
4810*b88e3e88Schristos 	case BFD_RELOC_NDS32_TLS_DESC:	/* @TLSDESC */
4811*b88e3e88Schristos 	  reloc = BFD_RELOC_NDS32_TLS_DESC_HI20;
4812*b88e3e88Schristos 	  break;
4813*b88e3e88Schristos 	default:	/* No suffix */
4814*b88e3e88Schristos 	  if (nds32_pic)
4815*b88e3e88Schristos 	    /* When the file is pic, the address must be offset to gp.
4816*b88e3e88Schristos 	       It may define another relocation or use GOTOFF.  */
4817*b88e3e88Schristos 	    reloc = BFD_RELOC_NDS32_PLT_GOTREL_HI20;
4818*b88e3e88Schristos 	  else
4819440a403fSchristos 	    reloc = BFD_RELOC_NDS32_HI20;
4820440a403fSchristos 	  break;
4821440a403fSchristos 	}
4822440a403fSchristos       fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4823440a403fSchristos 			  insn->info, 0 /* pcrel */, reloc);
4824440a403fSchristos     }
4825440a403fSchristos   else if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_LO12))
4826440a403fSchristos     {
4827440a403fSchristos       /* Relocation for lo12 modifier.  */
4828440a403fSchristos       if (fld->bitsize == 15 && fld->shift == 0)
4829440a403fSchristos 	{
4830440a403fSchristos 	  /* [ls]bi || ori */
4831440a403fSchristos 	  switch (pexp->X_md)
4832440a403fSchristos 	    {
4833440a403fSchristos 	    case BFD_RELOC_NDS32_GOTOFF:	/* @GOTOFF */
4834440a403fSchristos 	      reloc = BFD_RELOC_NDS32_GOTOFF_LO12;
4835440a403fSchristos 	      break;
4836440a403fSchristos 	    case BFD_RELOC_NDS32_GOT20:		/* @GOT */
4837440a403fSchristos 	      reloc = BFD_RELOC_NDS32_GOT_LO12;
4838440a403fSchristos 	      break;
4839440a403fSchristos 	    case BFD_RELOC_NDS32_25_PLTREL:	/* @PLT */
4840440a403fSchristos 	      if (!nds32_pic)
4841440a403fSchristos 		as_bad (_("Invalid PIC expression."));
4842440a403fSchristos 	      else
4843440a403fSchristos 		reloc = BFD_RELOC_NDS32_PLT_GOTREL_LO12;
4844440a403fSchristos 	      break;
4845440a403fSchristos 	    case BFD_RELOC_NDS32_GOTPC20:	/* _GLOBAL_OFFSET_TABLE_ */
4846440a403fSchristos 	      reloc = BFD_RELOC_NDS32_GOTPC_LO12;
4847440a403fSchristos 	      break;
4848440a403fSchristos 	    case BFD_RELOC_NDS32_TPOFF:		/* @TPOFF */
4849440a403fSchristos 	      reloc = BFD_RELOC_NDS32_TLS_LE_LO12;
4850440a403fSchristos 	      break;
4851*b88e3e88Schristos 	    case BFD_RELOC_NDS32_GOTTPOFF:	/* @GOTTPOFF */
4852*b88e3e88Schristos 	      reloc = nds32_pic ? BFD_RELOC_NDS32_TLS_IEGP_LO12 : BFD_RELOC_NDS32_TLS_IE_LO12;
4853*b88e3e88Schristos 	      break;
4854*b88e3e88Schristos 	    case BFD_RELOC_NDS32_TLS_DESC:	/* @TLSDESC */
4855*b88e3e88Schristos 	      reloc = BFD_RELOC_NDS32_TLS_DESC_LO12;
4856*b88e3e88Schristos 	      break;
4857*b88e3e88Schristos 	    default:	/* No suffix */
4858*b88e3e88Schristos 	      if (nds32_pic)
4859*b88e3e88Schristos 		/* When the file is pic, the address must be offset to gp.
4860*b88e3e88Schristos 		   It may define another relocation or use GOTOFF.  */
4861*b88e3e88Schristos 		reloc = BFD_RELOC_NDS32_PLT_GOTREL_LO12;
4862*b88e3e88Schristos 	      else
4863440a403fSchristos 		reloc = BFD_RELOC_NDS32_LO12S0;
4864440a403fSchristos 	      break;
4865440a403fSchristos 	    }
4866440a403fSchristos 	}
4867440a403fSchristos       else if (fld->bitsize == 15 && fld->shift == 1)
4868440a403fSchristos 	reloc = BFD_RELOC_NDS32_LO12S1;		/* [ls]hi */
4869440a403fSchristos       else if (fld->bitsize == 15 && fld->shift == 2)
4870440a403fSchristos 	{
4871440a403fSchristos 	  /* [ls]wi */
4872440a403fSchristos 	  switch (pexp->X_md)
4873440a403fSchristos 	    {
4874440a403fSchristos 	    case BFD_RELOC_NDS32_GOTTPOFF:	/* @GOTTPOFF */
4875*b88e3e88Schristos 	      reloc = nds32_pic ? BFD_RELOC_NDS32_TLS_IEGP_LO12S2 : BFD_RELOC_NDS32_TLS_IE_LO12S2;
4876440a403fSchristos 	      break;
4877*b88e3e88Schristos 	    default:	/* No suffix */
4878440a403fSchristos 	      reloc = BFD_RELOC_NDS32_LO12S2;
4879440a403fSchristos 	      break;
4880440a403fSchristos 	    }
4881440a403fSchristos 	}
4882440a403fSchristos       else if (fld->bitsize == 15 && fld->shift == 3)
4883440a403fSchristos 	reloc = BFD_RELOC_NDS32_LO12S3;		/* [ls]di */
4884440a403fSchristos       else if (fld->bitsize == 12 && fld->shift == 2)
4885*b88e3e88Schristos 	reloc = BFD_RELOC_NDS32_LO12S2_SP;	/* f[ls][sd]i */
4886440a403fSchristos 
4887440a403fSchristos       fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4888440a403fSchristos 			  insn->info, 0 /* pcrel */, reloc);
4889440a403fSchristos     }
4890440a403fSchristos   else if (fld && fld->bitpos == 0 && insn->opcode->isize == 4
4891440a403fSchristos 	   && (insn->attr & NASM_ATTR_PCREL))
4892440a403fSchristos     {
4893440a403fSchristos       /* Relocation for 32-bit branch instructions.  */
4894440a403fSchristos       if (fld->bitsize == 24 && fld->shift == 1)
4895440a403fSchristos 	reloc = BFD_RELOC_NDS32_25_PCREL;
4896440a403fSchristos       else if (fld->bitsize == 16 && fld->shift == 1)
4897440a403fSchristos 	reloc = BFD_RELOC_NDS32_17_PCREL;
4898440a403fSchristos       else if (fld->bitsize == 14 && fld->shift == 1)
4899440a403fSchristos 	reloc = BFD_RELOC_NDS32_15_PCREL;
4900440a403fSchristos       else if (fld->bitsize == 8 && fld->shift == 1)
4901440a403fSchristos 	reloc = BFD_RELOC_NDS32_WORD_9_PCREL;
4902440a403fSchristos       else
4903440a403fSchristos 	abort ();
4904440a403fSchristos 
4905440a403fSchristos       fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4906440a403fSchristos 		   insn->info, 1 /* pcrel */, reloc);
4907440a403fSchristos     }
4908440a403fSchristos   else if (fld && fld->bitpos == 0 && insn->opcode->isize == 4
4909440a403fSchristos 	   && (insn->attr & NASM_ATTR_GPREL))
4910440a403fSchristos     {
4911440a403fSchristos       /* Relocation for 32-bit gp-relative instructions.  */
4912440a403fSchristos       if (fld->bitsize == 19 && fld->shift == 0)
4913440a403fSchristos 	reloc = BFD_RELOC_NDS32_SDA19S0;
4914440a403fSchristos       else if (fld->bitsize == 18 && fld->shift == 1)
4915440a403fSchristos 	reloc = BFD_RELOC_NDS32_SDA18S1;
4916440a403fSchristos       else if (fld->bitsize == 17 && fld->shift == 2)
4917440a403fSchristos 	reloc = BFD_RELOC_NDS32_SDA17S2;
4918440a403fSchristos       else
4919440a403fSchristos 	abort ();
4920440a403fSchristos 
4921440a403fSchristos       fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4922440a403fSchristos 		   insn->info, 0 /* pcrel */, reloc);
4923440a403fSchristos       /* Insert INSN16 for converting fp_as_gp.  */
4924440a403fSchristos       exp.X_op = O_symbol;
4925440a403fSchristos       exp.X_add_symbol = abs_section_sym;
4926440a403fSchristos       exp.X_add_number = 0;
4927440a403fSchristos       if (in_omit_fp && reloc == BFD_RELOC_NDS32_SDA17S2)
4928440a403fSchristos 	fix_new_exp (fragP, out - fragP->fr_literal,
4929440a403fSchristos 		     insn->opcode->isize, &exp, 0 /* pcrel */,
4930440a403fSchristos 		     BFD_RELOC_NDS32_INSN16);
4931440a403fSchristos     }
4932440a403fSchristos   else if (fld && fld->bitpos == 0 && insn->opcode->isize == 2
4933440a403fSchristos 	   && (insn->attr & NASM_ATTR_PCREL))
4934440a403fSchristos     {
4935440a403fSchristos       /* Relocation for 16-bit branch instructions.  */
4936440a403fSchristos       if (fld->bitsize == 8 && fld->shift == 1)
4937440a403fSchristos 	reloc = BFD_RELOC_NDS32_9_PCREL;
4938440a403fSchristos       else
4939440a403fSchristos 	abort ();
4940440a403fSchristos 
4941440a403fSchristos       fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
4942440a403fSchristos 		   insn->info, 1 /* pcrel */, reloc);
4943440a403fSchristos     }
4944440a403fSchristos   else if (fld)
4945440a403fSchristos     as_bad (_("Don't know how to handle this field. %s"), str);
4946440a403fSchristos 
4947440a403fSchristos   return fixP;
4948440a403fSchristos }
4949440a403fSchristos 
4950440a403fSchristos /* Build instruction pattern to relax.  There are two type group pattern
4951440a403fSchristos    including pseudo instruction and relax hint.  */
4952440a403fSchristos 
4953440a403fSchristos static void
nds32_elf_build_relax_relation(fixS * fixP,expressionS * pexp,char * out,struct nds32_asm_insn * insn,fragS * fragP,const struct nds32_field * fld,bfd_boolean pseudo_hint)4954440a403fSchristos nds32_elf_build_relax_relation (fixS *fixP, expressionS *pexp, char* out,
4955*b88e3e88Schristos 				struct nds32_asm_insn *insn, fragS *fragP,
4956*b88e3e88Schristos 				const struct nds32_field *fld,
4957*b88e3e88Schristos 				bfd_boolean pseudo_hint)
4958440a403fSchristos {
4959440a403fSchristos   struct nds32_relocs_pattern *reloc_ptr;
4960440a403fSchristos   struct nds32_relocs_group *group;
4961440a403fSchristos   symbolS *sym = NULL;
4962440a403fSchristos 
4963440a403fSchristos   /* The expression may be used uninitialized.  */
4964440a403fSchristos   if (fld)
4965440a403fSchristos     sym = pexp->X_add_symbol;
4966440a403fSchristos 
4967*b88e3e88Schristos   if (pseudo_hint)
4968*b88e3e88Schristos     {
4969*b88e3e88Schristos       /* We cannot know how many instructions will be expanded for
4970*b88e3e88Schristos 	 the pseudo instruction here.  The first expanded instruction fills
4971*b88e3e88Schristos 	 the memory created by relax_hint.  The follower will created and link
4972*b88e3e88Schristos 	 here.  */
4973*b88e3e88Schristos       group = nds32_relax_hint_current;
4974*b88e3e88Schristos       while (group)
4975*b88e3e88Schristos 	{
4976*b88e3e88Schristos 	  if (group->pattern->opcode == NULL)
4977*b88e3e88Schristos 	    nds32_elf_save_pseudo_pattern (fixP, insn, out, sym,
4978*b88e3e88Schristos 					   group->pattern, fragP);
4979*b88e3e88Schristos 	  else
4980*b88e3e88Schristos 	    {
4981*b88e3e88Schristos 	      group->pattern->next =
4982*b88e3e88Schristos 		nds32_elf_save_pseudo_pattern (fixP, insn, out, sym,
4983*b88e3e88Schristos 					       NULL, fragP);
4984*b88e3e88Schristos 	      group->pattern = group->pattern->next;
4985*b88e3e88Schristos 	    }
4986*b88e3e88Schristos 	  group = group->next;
4987*b88e3e88Schristos 	}
4988*b88e3e88Schristos     }
4989*b88e3e88Schristos   else if (pseudo_opcode)
4990440a403fSchristos     {
4991440a403fSchristos       /* Save instruction relation for pseudo instruction expanding pattern.  */
4992*b88e3e88Schristos       reloc_ptr = nds32_elf_save_pseudo_pattern (fixP, insn, out, sym,
4993440a403fSchristos 						 NULL, fragP);
4994440a403fSchristos       if (!relocs_list)
4995440a403fSchristos 	relocs_list = reloc_ptr;
4996440a403fSchristos       else
4997440a403fSchristos 	{
4998440a403fSchristos 	  struct nds32_relocs_pattern *temp = relocs_list;
4999440a403fSchristos 	  while (temp->next)
5000440a403fSchristos 	    temp = temp->next;
5001440a403fSchristos 	  temp->next = reloc_ptr;
5002440a403fSchristos 	}
5003440a403fSchristos     }
5004440a403fSchristos   else if (nds32_relax_hint_current)
5005440a403fSchristos     {
5006440a403fSchristos       /* Save instruction relation by relax hint.  */
5007440a403fSchristos       group = nds32_relax_hint_current;
5008440a403fSchristos       while (group)
5009440a403fSchristos 	{
5010*b88e3e88Schristos 	  nds32_elf_save_pseudo_pattern (fixP, insn, out, sym,
5011440a403fSchristos 					 group->pattern, fragP);
5012440a403fSchristos 	  group = group->next;
5013440a403fSchristos 	  free (nds32_relax_hint_current);
5014440a403fSchristos 	  nds32_relax_hint_current = group;
5015440a403fSchristos 	}
5016440a403fSchristos     }
5017440a403fSchristos 
5018440a403fSchristos   /* Set relaxing false only for relax_hint trigger it.  */
5019440a403fSchristos   if (!pseudo_opcode)
5020440a403fSchristos     relaxing = FALSE;
5021440a403fSchristos }
5022440a403fSchristos 
5023440a403fSchristos #define N32_MEM_EXT(insn) ((N32_OP6_MEM << 25) | insn)
5024440a403fSchristos 
5025440a403fSchristos /* Relax pattern for link time relaxation.  */
5026*b88e3e88Schristos /* Relaxation types only! relocation types are not necessary.  */
5027*b88e3e88Schristos /* Refer to nds32_elf_record_fixup_exp ().  */
5028440a403fSchristos 
5029440a403fSchristos static struct nds32_relax_hint_table relax_ls_table[] =
5030440a403fSchristos {
5031440a403fSchristos   {
5032*b88e3e88Schristos     /* LA and Floating LSI.  */
5033*b88e3e88Schristos     .main_type = NDS32_RELAX_HINT_LA_FLSI,
5034*b88e3e88Schristos     .relax_code_size = 12,
5035*b88e3e88Schristos     .relax_code_seq =
5036440a403fSchristos       {
5037440a403fSchristos 	OP6 (SETHI),
5038440a403fSchristos 	OP6 (ORI),
5039*b88e3e88Schristos 	OP6 (LBI),
5040*b88e3e88Schristos       },
5041*b88e3e88Schristos     .relax_fixup =
5042440a403fSchristos       {
5043440a403fSchristos 	{0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5044*b88e3e88Schristos 	{4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
5045*b88e3e88Schristos 	{4, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5046*b88e3e88Schristos 	{8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_LSI},
5047*b88e3e88Schristos 	{8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5048*b88e3e88Schristos 	{8, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5049*b88e3e88Schristos 	{0, 0, 0, 0}
5050*b88e3e88Schristos       }
5051440a403fSchristos   },
5052440a403fSchristos   {
5053*b88e3e88Schristos     /* Load Address / Load-Store (LALS).  */
5054*b88e3e88Schristos     .main_type = NDS32_RELAX_HINT_LALS,
5055*b88e3e88Schristos     .relax_code_size = 12,
5056*b88e3e88Schristos     .relax_code_seq =
5057*b88e3e88Schristos       {
5058*b88e3e88Schristos 	OP6 (SETHI),
5059*b88e3e88Schristos 	OP6 (ORI),
5060*b88e3e88Schristos 	OP6 (LBI),
5061*b88e3e88Schristos       },
5062*b88e3e88Schristos     .relax_fixup =
5063*b88e3e88Schristos       {
5064*b88e3e88Schristos 	{0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5065*b88e3e88Schristos 	{4, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5066*b88e3e88Schristos 	{8, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5067*b88e3e88Schristos 	{0, 0, 0, 0}
5068*b88e3e88Schristos       }
5069*b88e3e88Schristos   },
5070*b88e3e88Schristos   {
5071*b88e3e88Schristos     /* B(AL) symbol@PLT  */
5072*b88e3e88Schristos     .main_type = NDS32_RELAX_HINT_LA_PLT,
5073*b88e3e88Schristos     .relax_code_size = 16,
5074*b88e3e88Schristos     .relax_code_seq =
5075*b88e3e88Schristos       {
5076*b88e3e88Schristos 	OP6 (SETHI),
5077*b88e3e88Schristos 	OP6 (ORI),
5078*b88e3e88Schristos 	OP6 (ALU1),
5079*b88e3e88Schristos 	OP6 (JREG),
5080*b88e3e88Schristos       },
5081*b88e3e88Schristos     .relax_fixup =
5082*b88e3e88Schristos       {
5083*b88e3e88Schristos 	{0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5084*b88e3e88Schristos 	{4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
5085*b88e3e88Schristos 	{8, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
5086*b88e3e88Schristos 	{12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PLT_GOT_SUFF},
5087*b88e3e88Schristos 	{12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5088*b88e3e88Schristos 	{12, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5089*b88e3e88Schristos 	{0, 0, 0, 0}
5090*b88e3e88Schristos       }
5091*b88e3e88Schristos   },
5092*b88e3e88Schristos   {
5093*b88e3e88Schristos     /* LA (@GOT).  */
5094*b88e3e88Schristos     .main_type = NDS32_RELAX_HINT_LA_GOT,
5095*b88e3e88Schristos     .relax_code_size = 12,
5096*b88e3e88Schristos     .relax_code_seq =
5097*b88e3e88Schristos       {
5098*b88e3e88Schristos 	OP6 (SETHI),
5099*b88e3e88Schristos 	OP6 (ORI),
5100*b88e3e88Schristos 	OP6 (MEM),
5101*b88e3e88Schristos       },
5102*b88e3e88Schristos     .relax_fixup =
5103*b88e3e88Schristos       {
5104*b88e3e88Schristos 	{0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5105*b88e3e88Schristos 	{4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
5106*b88e3e88Schristos 	{8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5107*b88e3e88Schristos 	{8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_GOT_SUFF},
5108*b88e3e88Schristos 	{0, 0, 0, 0}
5109*b88e3e88Schristos       }
5110*b88e3e88Schristos   },
5111*b88e3e88Schristos   {
5112*b88e3e88Schristos     /* LA (@GOTOFF).  */
5113*b88e3e88Schristos     .main_type = NDS32_RELAX_HINT_LA_GOTOFF,
5114*b88e3e88Schristos     .relax_code_size = 16,
5115*b88e3e88Schristos     .relax_code_seq =
5116*b88e3e88Schristos       {
5117*b88e3e88Schristos 	OP6 (SETHI),
5118*b88e3e88Schristos 	OP6 (ORI),
5119*b88e3e88Schristos 	OP6 (ALU1),
5120*b88e3e88Schristos 	OP6 (MEM),
5121*b88e3e88Schristos       },
5122*b88e3e88Schristos     .relax_fixup =
5123*b88e3e88Schristos       {
5124*b88e3e88Schristos 	{0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5125*b88e3e88Schristos 	{4, 4, NDS32_HINT | NDS32_PTR, BFD_RELOC_NDS32_PTR},
5126*b88e3e88Schristos 	{8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5127*b88e3e88Schristos 	{8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_GOTOFF_SUFF},
5128*b88e3e88Schristos 	{12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5129*b88e3e88Schristos 	{12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_GOTOFF_SUFF},
5130*b88e3e88Schristos 	{0, 0, 0, 0}
5131*b88e3e88Schristos       }
5132*b88e3e88Schristos   },
5133*b88e3e88Schristos   {
5134*b88e3e88Schristos     /* TLS LE LS|LA */
5135*b88e3e88Schristos     .main_type = NDS32_RELAX_HINT_TLS_LE_LS,
5136*b88e3e88Schristos     .relax_code_size = 16,
5137*b88e3e88Schristos     .relax_code_seq =
5138*b88e3e88Schristos       {
5139*b88e3e88Schristos 	OP6(SETHI),
5140*b88e3e88Schristos 	OP6(ORI),
5141*b88e3e88Schristos 	OP6(MEM),
5142*b88e3e88Schristos 	OP6(ALU1),
5143*b88e3e88Schristos       },
5144*b88e3e88Schristos     .relax_fixup =
5145*b88e3e88Schristos       {
5146*b88e3e88Schristos 	{0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5147*b88e3e88Schristos 	{4, 4, NDS32_HINT | NDS32_PTR_MULTIPLE, BFD_RELOC_NDS32_PTR},
5148*b88e3e88Schristos 	{8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5149*b88e3e88Schristos 	{8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_LE_LS},
5150*b88e3e88Schristos 	{12, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5151*b88e3e88Schristos 	{12, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_LE_ADD},
5152*b88e3e88Schristos 	{0, 0, 0, 0}
5153*b88e3e88Schristos       }
5154*b88e3e88Schristos   },
5155*b88e3e88Schristos   {
5156*b88e3e88Schristos     /* TLS IE LA */
5157*b88e3e88Schristos     .main_type = NDS32_RELAX_HINT_TLS_IE_LA,
5158*b88e3e88Schristos     .relax_code_size = 8,
5159*b88e3e88Schristos     .relax_code_seq =
5160440a403fSchristos       {
5161440a403fSchristos 	OP6(SETHI),
5162440a403fSchristos 	OP6(LBI),
5163*b88e3e88Schristos       },
5164*b88e3e88Schristos     .relax_fixup =
5165440a403fSchristos       {
5166440a403fSchristos 	{0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5167*b88e3e88Schristos 	{4, 4, NDS32_HINT | NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
5168*b88e3e88Schristos 	{0, 0, 0, 0}
5169*b88e3e88Schristos       }
5170440a403fSchristos   },
5171440a403fSchristos   {
5172*b88e3e88Schristos     /* TLS IEGP LA */
5173*b88e3e88Schristos     .main_type = NDS32_RELAX_HINT_TLS_IEGP_LA,
5174*b88e3e88Schristos     .relax_code_size = 12,
5175*b88e3e88Schristos     .relax_code_seq =
5176*b88e3e88Schristos       {
5177*b88e3e88Schristos 	OP6 (SETHI),
5178*b88e3e88Schristos 	OP6 (ORI),
5179*b88e3e88Schristos 	OP6 (MEM),
5180*b88e3e88Schristos       },
5181*b88e3e88Schristos     .relax_fixup =
5182*b88e3e88Schristos       {
5183*b88e3e88Schristos 	{0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5184*b88e3e88Schristos 	{4, 4, NDS32_HINT | NDS32_PTR_PATTERN, BFD_RELOC_NDS32_PTR},
5185*b88e3e88Schristos 	{8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5186*b88e3e88Schristos 	{8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_IEGP_LW},
5187*b88e3e88Schristos 	{0, 0, 0, 0}
5188*b88e3e88Schristos       }
5189*b88e3e88Schristos   },
5190*b88e3e88Schristos   {
5191*b88e3e88Schristos     /* TLS DESC LS:  */
5192*b88e3e88Schristos     .main_type = NDS32_RELAX_HINT_TLS_DESC_LS,
5193*b88e3e88Schristos     .relax_code_size = 24,
5194*b88e3e88Schristos     .relax_code_seq =
5195*b88e3e88Schristos       {
5196*b88e3e88Schristos 	OP6 (SETHI),
5197*b88e3e88Schristos 	OP6 (ORI),
5198*b88e3e88Schristos 	OP6 (ALU1),
5199*b88e3e88Schristos 	OP6 (LBI),	/* load argument */
5200*b88e3e88Schristos 	OP6 (JREG),
5201*b88e3e88Schristos 	OP6 (MEM),	/* load/store variable or load argument */
5202*b88e3e88Schristos       },
5203*b88e3e88Schristos     .relax_fixup =
5204*b88e3e88Schristos       {
5205*b88e3e88Schristos 	{0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
5206*b88e3e88Schristos 	{4, 4, NDS32_HINT | NDS32_PTR_PATTERN, BFD_RELOC_NDS32_PTR},
5207*b88e3e88Schristos 	{8, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_PTR_RESOLVED},
5208*b88e3e88Schristos 	{8, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_DESC_ADD},
5209*b88e3e88Schristos 	{12, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_DESC_FUNC},
5210*b88e3e88Schristos 	{16, 4, NDS32_HINT | NDS32_SYM, BFD_RELOC_NDS32_TLS_DESC_CALL},
5211*b88e3e88Schristos 	{20, 4, NDS32_HINT | NDS32_SYM_DESC_MEM, BFD_RELOC_NDS32_TLS_DESC_MEM},
5212*b88e3e88Schristos 	{0, 0, 0, 0}
5213*b88e3e88Schristos       }
5214*b88e3e88Schristos   },
5215*b88e3e88Schristos   {
5216*b88e3e88Schristos     .main_type = 0,
5217*b88e3e88Schristos     .relax_code_seq = {0},
5218*b88e3e88Schristos     .relax_fixup = {{0, 0 , 0, 0}}
5219440a403fSchristos   }
5220440a403fSchristos };
5221440a403fSchristos 
5222440a403fSchristos /* Since sethi loadstore relocation has to using next instruction to determine
5223440a403fSchristos    elimination itself or not, we have to return the next instruction range.  */
5224440a403fSchristos 
5225440a403fSchristos static int
nds32_elf_sethi_range(struct nds32_relocs_pattern * pattern)5226440a403fSchristos nds32_elf_sethi_range (struct nds32_relocs_pattern *pattern)
5227440a403fSchristos {
5228440a403fSchristos   int range = 0;
5229440a403fSchristos   while (pattern)
5230440a403fSchristos     {
5231440a403fSchristos       switch (pattern->opcode->value)
5232440a403fSchristos 	{
5233440a403fSchristos 	case INSN_LBI:
5234440a403fSchristos 	case INSN_SBI:
5235440a403fSchristos 	case INSN_LBSI:
5236440a403fSchristos 	case N32_MEM_EXT (N32_MEM_LB):
5237440a403fSchristos 	case N32_MEM_EXT (N32_MEM_LBS):
5238440a403fSchristos 	case N32_MEM_EXT (N32_MEM_SB):
5239440a403fSchristos 	  range = NDS32_LOADSTORE_BYTE;
5240440a403fSchristos 	  break;
5241440a403fSchristos 	case INSN_LHI:
5242440a403fSchristos 	case INSN_SHI:
5243440a403fSchristos 	case INSN_LHSI:
5244440a403fSchristos 	case N32_MEM_EXT (N32_MEM_LH):
5245440a403fSchristos 	case N32_MEM_EXT (N32_MEM_LHS):
5246440a403fSchristos 	case N32_MEM_EXT (N32_MEM_SH):
5247440a403fSchristos 	  range = NDS32_LOADSTORE_HALF;
5248440a403fSchristos 	  break;
5249440a403fSchristos 	case INSN_LWI:
5250440a403fSchristos 	case INSN_SWI:
5251440a403fSchristos 	case N32_MEM_EXT (N32_MEM_LW):
5252440a403fSchristos 	case N32_MEM_EXT (N32_MEM_SW):
5253440a403fSchristos 	  range = NDS32_LOADSTORE_WORD;
5254440a403fSchristos 	  break;
5255440a403fSchristos 	case INSN_FLSI:
5256440a403fSchristos 	case INSN_FSSI:
5257440a403fSchristos 	  range = NDS32_LOADSTORE_FLOAT_S;
5258440a403fSchristos 	  break;
5259440a403fSchristos 	case INSN_FLDI:
5260440a403fSchristos 	case INSN_FSDI:
5261440a403fSchristos 	  range = NDS32_LOADSTORE_FLOAT_D;
5262440a403fSchristos 	  break;
5263440a403fSchristos 	case INSN_ORI:
5264440a403fSchristos 	  range = NDS32_LOADSTORE_IMM;
5265440a403fSchristos 	  break;
5266440a403fSchristos 	default:
5267440a403fSchristos 	  range = NDS32_LOADSTORE_NONE;
5268440a403fSchristos 	  break;
5269440a403fSchristos 	}
5270440a403fSchristos       if (range != NDS32_LOADSTORE_NONE)
5271440a403fSchristos 	break;
5272440a403fSchristos       pattern = pattern->next;
5273440a403fSchristos     }
5274440a403fSchristos   return range;
5275440a403fSchristos }
5276440a403fSchristos 
5277440a403fSchristos /* The args means: instruction size, the 1st instruction is converted to 16 or
5278440a403fSchristos    not, optimize option, 16 bit instruction is enable.  */
5279*b88e3e88Schristos 
5280440a403fSchristos #define SET_ADDEND(size, convertible, optimize, insn16_on) \
5281440a403fSchristos   (((size) & 0xff) | ((convertible) ? 1 << 31 : 0) \
5282440a403fSchristos    | ((optimize) ? 1<< 30 : 0) | (insn16_on ? 1 << 29 : 0))
5283*b88e3e88Schristos #define MAC_COMBO (E_NDS32_HAS_FPU_MAC_INST|E_NDS32_HAS_MAC_DX_INST)
5284440a403fSchristos 
5285440a403fSchristos static void
nds32_set_elf_flags_by_insn(struct nds32_asm_insn * insn)5286440a403fSchristos nds32_set_elf_flags_by_insn (struct nds32_asm_insn * insn)
5287440a403fSchristos {
5288*b88e3e88Schristos   static int skip_flags = NASM_ATTR_FPU_FMA
5289*b88e3e88Schristos     | NASM_ATTR_BRANCH | NASM_ATTR_SATURATION_EXT
5290*b88e3e88Schristos     | NASM_ATTR_GPREL | NASM_ATTR_DXREG
5291*b88e3e88Schristos     | NASM_ATTR_ISA_V1 | NASM_ATTR_ISA_V2
5292*b88e3e88Schristos     | NASM_ATTR_ISA_V3 | NASM_ATTR_ISA_V3M
5293*b88e3e88Schristos     | NASM_ATTR_PCREL;
5294*b88e3e88Schristos 
5295*b88e3e88Schristos   int new_flags = insn->opcode->attr & ~skip_flags;
5296*b88e3e88Schristos   while (new_flags)
5297*b88e3e88Schristos     {
5298*b88e3e88Schristos       int next = 1 << (ffs (new_flags) - 1);
5299*b88e3e88Schristos       new_flags &= ~next;
5300*b88e3e88Schristos       switch (next)
5301*b88e3e88Schristos 	{
5302*b88e3e88Schristos 	case NASM_ATTR_PERF_EXT:
5303440a403fSchristos 	  {
5304440a403fSchristos 	    if (nds32_perf_ext)
5305*b88e3e88Schristos 	      {
5306440a403fSchristos 		nds32_elf_flags |= E_NDS32_HAS_EXT_INST;
5307*b88e3e88Schristos 		skip_flags |= NASM_ATTR_PERF_EXT;
5308440a403fSchristos 	      }
5309*b88e3e88Schristos 	    else
5310*b88e3e88Schristos 	      as_bad (_("instruction %s requires enabling performance "
5311*b88e3e88Schristos 			"extension"), insn->opcode->opcode);
5312*b88e3e88Schristos 	  }
5313*b88e3e88Schristos 	  break;
5314*b88e3e88Schristos 	case NASM_ATTR_PERF2_EXT:
5315440a403fSchristos 	  {
5316440a403fSchristos 	    if (nds32_perf_ext2)
5317*b88e3e88Schristos 	      {
5318440a403fSchristos 		nds32_elf_flags |= E_NDS32_HAS_EXT2_INST;
5319*b88e3e88Schristos 		skip_flags |= NASM_ATTR_PERF2_EXT;
5320440a403fSchristos 	      }
5321*b88e3e88Schristos 	    else
5322*b88e3e88Schristos 	      as_bad (_("instruction %s requires enabling performance "
5323*b88e3e88Schristos 			"extension II"), insn->opcode->opcode);
5324*b88e3e88Schristos 	  }
5325*b88e3e88Schristos 	  break;
5326*b88e3e88Schristos 	case NASM_ATTR_AUDIO_ISAEXT:
5327440a403fSchristos 	  {
5328440a403fSchristos 	    if (nds32_audio_ext)
5329*b88e3e88Schristos 	      {
5330440a403fSchristos 		nds32_elf_flags |= E_NDS32_HAS_AUDIO_INST;
5331*b88e3e88Schristos 		skip_flags |= NASM_ATTR_AUDIO_ISAEXT;
5332*b88e3e88Schristos 	      }
5333440a403fSchristos 	    else
5334440a403fSchristos 	      as_bad (_("instruction %s requires enabling AUDIO extension"),
5335440a403fSchristos 		      insn->opcode->opcode);
5336440a403fSchristos 	  }
5337*b88e3e88Schristos 	  break;
5338*b88e3e88Schristos 	case NASM_ATTR_STR_EXT:
5339440a403fSchristos 	  {
5340440a403fSchristos 	    if (nds32_string_ext)
5341*b88e3e88Schristos 	      {
5342440a403fSchristos 		nds32_elf_flags |= E_NDS32_HAS_STRING_INST;
5343*b88e3e88Schristos 		skip_flags |= NASM_ATTR_STR_EXT;
5344*b88e3e88Schristos 	      }
5345440a403fSchristos 	    else
5346440a403fSchristos 	      as_bad (_("instruction %s requires enabling STRING extension"),
5347440a403fSchristos 		      insn->opcode->opcode);
5348440a403fSchristos 	  }
5349*b88e3e88Schristos 	  break;
5350*b88e3e88Schristos 	case NASM_ATTR_DIV:
5351*b88e3e88Schristos 	  {
5352*b88e3e88Schristos 	    if (insn->opcode->attr & NASM_ATTR_DXREG)
5353440a403fSchristos 	      {
5354440a403fSchristos 		if (nds32_div && nds32_dx_regs)
5355*b88e3e88Schristos 		  {
5356440a403fSchristos 		    nds32_elf_flags |= E_NDS32_HAS_DIV_DX_INST;
5357*b88e3e88Schristos 		    skip_flags |= NASM_ATTR_DIV;
5358440a403fSchristos 		  }
5359*b88e3e88Schristos 		else
5360*b88e3e88Schristos 		  as_bad (_("instruction %s requires enabling DIV & DX_REGS "
5361*b88e3e88Schristos 			    "extension"), insn->opcode->opcode);
5362*b88e3e88Schristos 	      }
5363*b88e3e88Schristos 	  }
5364*b88e3e88Schristos 	  break;
5365*b88e3e88Schristos 	case NASM_ATTR_FPU:
5366440a403fSchristos 	  {
5367440a403fSchristos 	    if (nds32_fpu_sp_ext || nds32_fpu_dp_ext)
5368440a403fSchristos 	      {
5369*b88e3e88Schristos 		if (!(nds32_elf_flags
5370*b88e3e88Schristos 		      & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST)))
5371440a403fSchristos 		  nds32_fpu_com = 1;
5372*b88e3e88Schristos 		skip_flags |= NASM_ATTR_FPU;
5373440a403fSchristos 	      }
5374440a403fSchristos 	    else
5375440a403fSchristos 	      as_bad (_("instruction %s requires enabling FPU extension"),
5376440a403fSchristos 		      insn->opcode->opcode);
5377440a403fSchristos 	  }
5378*b88e3e88Schristos 	  break;
5379*b88e3e88Schristos 	case NASM_ATTR_FPU_SP_EXT:
5380440a403fSchristos 	  {
5381440a403fSchristos 	    if (nds32_fpu_sp_ext)
5382*b88e3e88Schristos 	      {
5383440a403fSchristos 		nds32_elf_flags |= E_NDS32_HAS_FPU_INST;
5384*b88e3e88Schristos 		skip_flags |= NASM_ATTR_FPU_SP_EXT;
5385*b88e3e88Schristos 	      }
5386440a403fSchristos 	    else
5387440a403fSchristos 	      as_bad (_("instruction %s requires enabling FPU_SP extension"),
5388440a403fSchristos 		      insn->opcode->opcode);
5389440a403fSchristos 	  }
5390*b88e3e88Schristos 	  break;
5391*b88e3e88Schristos 	case NASM_ATTR_FPU_DP_EXT:
5392440a403fSchristos 	  {
5393440a403fSchristos 	    if (nds32_fpu_dp_ext)
5394*b88e3e88Schristos 	      {
5395440a403fSchristos 		nds32_elf_flags |= E_NDS32_HAS_FPU_DP_INST;
5396*b88e3e88Schristos 		skip_flags |= NASM_ATTR_FPU_DP_EXT;
5397*b88e3e88Schristos 	      }
5398440a403fSchristos 	    else
5399440a403fSchristos 	      as_bad (_("instruction %s requires enabling FPU_DP extension"),
5400440a403fSchristos 		      insn->opcode->opcode);
5401440a403fSchristos 	  }
5402*b88e3e88Schristos 	  break;
5403*b88e3e88Schristos 	case NASM_ATTR_MAC:
5404*b88e3e88Schristos 	  {
5405*b88e3e88Schristos 	    if (insn->opcode->attr & NASM_ATTR_FPU_SP_EXT)
5406*b88e3e88Schristos 	      {
5407*b88e3e88Schristos 		if (nds32_fpu_sp_ext && nds32_mac)
5408*b88e3e88Schristos 		  nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST;
5409*b88e3e88Schristos 		else
5410*b88e3e88Schristos 		  as_bad (_("instruction %s requires enabling FPU_MAC "
5411*b88e3e88Schristos 			    "extension"), insn->opcode->opcode);
5412*b88e3e88Schristos 	      }
5413*b88e3e88Schristos 	    else if (insn->opcode->attr & NASM_ATTR_FPU_DP_EXT)
5414440a403fSchristos 	      {
5415440a403fSchristos 		if (nds32_fpu_dp_ext && nds32_mac)
5416440a403fSchristos 		  nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST;
5417440a403fSchristos 		else
5418*b88e3e88Schristos 		  as_bad (_("instruction %s requires enabling FPU_MAC "
5419*b88e3e88Schristos 			    "extension"), insn->opcode->opcode);
5420440a403fSchristos 	      }
5421*b88e3e88Schristos 	    else if (insn->opcode->attr & NASM_ATTR_DXREG)
5422440a403fSchristos 	      {
5423*b88e3e88Schristos 		if (nds32_dx_regs && nds32_mac)
5424440a403fSchristos 		  nds32_elf_flags |= E_NDS32_HAS_MAC_DX_INST;
5425440a403fSchristos 		else
5426*b88e3e88Schristos 		  as_bad (_("instruction %s requires enabling DX_REGS "
5427*b88e3e88Schristos 			    "extension"), insn->opcode->opcode);
5428*b88e3e88Schristos 	      }
5429*b88e3e88Schristos 
5430*b88e3e88Schristos 	    if (MAC_COMBO == (MAC_COMBO & nds32_elf_flags))
5431*b88e3e88Schristos 	      skip_flags |= NASM_ATTR_MAC;
5432*b88e3e88Schristos 	  }
5433*b88e3e88Schristos 	  break;
5434*b88e3e88Schristos 	case NASM_ATTR_DSP_ISAEXT:
5435*b88e3e88Schristos 	  {
5436*b88e3e88Schristos 	    if (nds32_dsp_ext)
5437*b88e3e88Schristos 	      {
5438*b88e3e88Schristos 		nds32_elf_flags |= E_NDS32_HAS_DSP_INST;
5439*b88e3e88Schristos 		skip_flags |= NASM_ATTR_DSP_ISAEXT;
5440*b88e3e88Schristos 	      }
5441*b88e3e88Schristos 	    else
5442*b88e3e88Schristos 	      as_bad (_("instruction %s requires enabling dsp extension"),
5443440a403fSchristos 		      insn->opcode->opcode);
5444440a403fSchristos 	  }
5445*b88e3e88Schristos 	  break;
5446*b88e3e88Schristos 	case NASM_ATTR_ZOL:
5447440a403fSchristos 	  {
5448*b88e3e88Schristos 	    if (nds32_zol_ext)
5449*b88e3e88Schristos 	      {
5450*b88e3e88Schristos 		nds32_elf_flags |= E_NDS32_HAS_ZOL;
5451*b88e3e88Schristos 		skip_flags |= NASM_ATTR_ZOL;
5452440a403fSchristos 	      }
5453*b88e3e88Schristos 	    else
5454*b88e3e88Schristos 	      as_bad (_("instruction %s requires enabling zol extension"),
5455*b88e3e88Schristos 		      insn->opcode->opcode);
5456*b88e3e88Schristos 	  }
5457*b88e3e88Schristos 	  break;
5458*b88e3e88Schristos 	default:
5459*b88e3e88Schristos 	  as_bad (_("internal error: unknown instruction attribute: 0x%08x"),
5460*b88e3e88Schristos 		  next);
5461*b88e3e88Schristos 	}
5462*b88e3e88Schristos     }
5463440a403fSchristos }
5464440a403fSchristos 
5465440a403fSchristos /* Flag for analysis relaxation type.  */
5466440a403fSchristos 
5467440a403fSchristos enum nds32_insn_type
5468440a403fSchristos {
5469440a403fSchristos   N32_RELAX_SETHI = 1,
5470440a403fSchristos   N32_RELAX_BR = (1 << 1),
5471440a403fSchristos   N32_RELAX_LSI = (1 << 2),
5472440a403fSchristos   N32_RELAX_JUMP = (1 << 3),
5473440a403fSchristos   N32_RELAX_CALL = (1 << 4),
5474440a403fSchristos   N32_RELAX_ORI = (1 << 5),
5475440a403fSchristos   N32_RELAX_MEM = (1 << 6),
5476440a403fSchristos   N32_RELAX_MOVI = (1 << 7),
5477*b88e3e88Schristos   N32_RELAX_ALU1 = (1 << 8),
5478*b88e3e88Schristos   N32_RELAX_16BIT = (1 << 9),
5479440a403fSchristos };
5480440a403fSchristos 
5481440a403fSchristos struct nds32_hint_map
5482440a403fSchristos {
5483*b88e3e88Schristos   /* the preamble relocation */
5484440a403fSchristos   bfd_reloc_code_real_type hi_type;
5485*b88e3e88Schristos   /* mnemonic */
5486440a403fSchristos   const char *opc;
5487*b88e3e88Schristos   /* relax pattern ID */
5488440a403fSchristos   enum nds32_relax_hint_type hint_type;
5489*b88e3e88Schristos   /* range */
5490440a403fSchristos   enum nds32_br_range range;
5491*b88e3e88Schristos   /* pattern character flags */
5492440a403fSchristos   enum nds32_insn_type insn_list;
5493*b88e3e88Schristos   /* optional pattern character flags */
5494*b88e3e88Schristos   enum nds32_insn_type option_list;
5495440a403fSchristos };
5496440a403fSchristos 
5497440a403fSchristos /* Table to match instructions with hint and relax pattern.  */
5498440a403fSchristos 
5499440a403fSchristos static struct nds32_hint_map hint_map [] =
5500440a403fSchristos {
5501440a403fSchristos   {
5502440a403fSchristos     /* LONGCALL4.  */
5503440a403fSchristos     BFD_RELOC_NDS32_HI20,
5504440a403fSchristos     "jal",
5505440a403fSchristos     NDS32_RELAX_HINT_NONE,
5506440a403fSchristos     BR_RANGE_U4G,
5507*b88e3e88Schristos     N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL,
5508*b88e3e88Schristos     0,
5509440a403fSchristos   },
5510440a403fSchristos   {
5511440a403fSchristos     /* LONGCALL5.  */
5512440a403fSchristos     _dummy_first_bfd_reloc_code_real,
5513440a403fSchristos     "bgezal",
5514440a403fSchristos     NDS32_RELAX_HINT_NONE,
5515440a403fSchristos     BR_RANGE_S16M,
5516*b88e3e88Schristos     N32_RELAX_BR | N32_RELAX_CALL,
5517*b88e3e88Schristos     0,
5518440a403fSchristos   },
5519440a403fSchristos   {
5520440a403fSchristos     /* LONGCALL6.  */
5521440a403fSchristos     BFD_RELOC_NDS32_HI20,
5522440a403fSchristos     "bgezal",
5523440a403fSchristos     NDS32_RELAX_HINT_NONE,
5524440a403fSchristos     BR_RANGE_U4G,
5525*b88e3e88Schristos     N32_RELAX_BR | N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL,
5526*b88e3e88Schristos     0,
5527440a403fSchristos   },
5528440a403fSchristos   {
5529440a403fSchristos     /* LONGJUMP4.  */
5530440a403fSchristos     BFD_RELOC_NDS32_HI20,
5531440a403fSchristos     "j",
5532440a403fSchristos     NDS32_RELAX_HINT_NONE,
5533440a403fSchristos     BR_RANGE_U4G,
5534*b88e3e88Schristos     N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_JUMP,
5535*b88e3e88Schristos     0,
5536440a403fSchristos   },
5537440a403fSchristos   {
5538440a403fSchristos     /* LONGJUMP5.  */
5539*b88e3e88Schristos     /* There is two kinds of variation of LONGJUMP5.  One of them
5540440a403fSchristos        generate EMPTY relocation for converted INSN16 if needed.
5541440a403fSchristos        But we don't distinguish them here.  */
5542440a403fSchristos     _dummy_first_bfd_reloc_code_real,
5543440a403fSchristos     "beq",
5544440a403fSchristos     NDS32_RELAX_HINT_NONE,
5545440a403fSchristos     BR_RANGE_S16M,
5546*b88e3e88Schristos     N32_RELAX_BR | N32_RELAX_JUMP,
5547*b88e3e88Schristos     0,
5548440a403fSchristos   },
5549440a403fSchristos   {
5550440a403fSchristos     /* LONGJUMP6.  */
5551440a403fSchristos     BFD_RELOC_NDS32_HI20,
5552440a403fSchristos     "beq",
5553440a403fSchristos     NDS32_RELAX_HINT_NONE,
5554440a403fSchristos     BR_RANGE_U4G,
5555*b88e3e88Schristos     N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_BR | N32_RELAX_JUMP,
5556*b88e3e88Schristos     0,
5557440a403fSchristos   },
5558440a403fSchristos   {
5559440a403fSchristos     /* LONGJUMP7.  */
5560440a403fSchristos     _dummy_first_bfd_reloc_code_real,
5561440a403fSchristos     "beqc",
5562440a403fSchristos     NDS32_RELAX_HINT_NONE,
5563440a403fSchristos     BR_RANGE_S16K,
5564*b88e3e88Schristos     N32_RELAX_MOVI | N32_RELAX_BR,
5565*b88e3e88Schristos     0,
5566440a403fSchristos   },
5567440a403fSchristos   {
5568*b88e3e88Schristos     /* LONGCALL (BAL|JR|LA symbol@PLT).  */
5569*b88e3e88Schristos     BFD_RELOC_NDS32_PLT_GOTREL_HI20,
5570*b88e3e88Schristos     NULL,
5571*b88e3e88Schristos     NDS32_RELAX_HINT_LA_PLT,
5572*b88e3e88Schristos     BR_RANGE_U4G,
5573*b88e3e88Schristos     N32_RELAX_SETHI | N32_RELAX_ORI,
5574*b88e3e88Schristos     N32_RELAX_ALU1 | N32_RELAX_CALL | N32_RELAX_JUMP,
5575*b88e3e88Schristos   },
5576*b88e3e88Schristos   /* relative issue: #12566 */
5577*b88e3e88Schristos   {
5578*b88e3e88Schristos     /* LA and Floating LSI.  */
5579440a403fSchristos     BFD_RELOC_NDS32_HI20,
5580440a403fSchristos     NULL,
5581*b88e3e88Schristos     NDS32_RELAX_HINT_LA_FLSI,
5582440a403fSchristos     BR_RANGE_U4G,
5583*b88e3e88Schristos     N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_LSI,
5584*b88e3e88Schristos     0,
5585*b88e3e88Schristos   },
5586*b88e3e88Schristos   /* relative issue: #11685 #11602 */
5587*b88e3e88Schristos   {
5588*b88e3e88Schristos     /* load address / load-store (LALS).  */
5589*b88e3e88Schristos     BFD_RELOC_NDS32_HI20,
5590*b88e3e88Schristos     NULL,
5591*b88e3e88Schristos     NDS32_RELAX_HINT_LALS,
5592*b88e3e88Schristos     BR_RANGE_U4G,
5593*b88e3e88Schristos     N32_RELAX_SETHI,
5594*b88e3e88Schristos     N32_RELAX_ORI | N32_RELAX_LSI,
5595440a403fSchristos   },
5596440a403fSchristos   {
5597*b88e3e88Schristos     /* setup $GP (_GLOBAL_OFFSET_TABLE_)  */
5598*b88e3e88Schristos     BFD_RELOC_NDS32_GOTPC_HI20,
5599440a403fSchristos     NULL,
5600*b88e3e88Schristos     NDS32_RELAX_HINT_LALS,
5601440a403fSchristos     BR_RANGE_U4G,
5602*b88e3e88Schristos     N32_RELAX_SETHI | N32_RELAX_ORI,
5603*b88e3e88Schristos     0,
5604440a403fSchristos   },
5605*b88e3e88Schristos   {
5606*b88e3e88Schristos     /* GOT LA/LS (symbol@GOT)  */
5607*b88e3e88Schristos     BFD_RELOC_NDS32_GOT_HI20,
5608*b88e3e88Schristos     NULL,
5609*b88e3e88Schristos     NDS32_RELAX_HINT_LA_GOT,
5610*b88e3e88Schristos     BR_RANGE_U4G,
5611*b88e3e88Schristos     N32_RELAX_SETHI | N32_RELAX_ORI,
5612*b88e3e88Schristos     N32_RELAX_MEM,
5613*b88e3e88Schristos   },
5614*b88e3e88Schristos   {
5615*b88e3e88Schristos     /* GOTOFF LA/LS (symbol@GOTOFF)  */
5616*b88e3e88Schristos     BFD_RELOC_NDS32_GOTOFF_HI20,
5617*b88e3e88Schristos     NULL,
5618*b88e3e88Schristos     NDS32_RELAX_HINT_LA_GOTOFF,
5619*b88e3e88Schristos     BR_RANGE_U4G,
5620*b88e3e88Schristos     N32_RELAX_SETHI | N32_RELAX_ORI,
5621*b88e3e88Schristos     N32_RELAX_ALU1  | N32_RELAX_MEM, /* | N32_RELAX_LSI, */
5622*b88e3e88Schristos   },
5623*b88e3e88Schristos   {
5624*b88e3e88Schristos     /* TLS LE LA|LS (@TPOFF)  */
5625*b88e3e88Schristos     BFD_RELOC_NDS32_TLS_LE_HI20,
5626*b88e3e88Schristos     NULL,
5627*b88e3e88Schristos     NDS32_RELAX_HINT_TLS_LE_LS,
5628*b88e3e88Schristos     BR_RANGE_U4G,
5629*b88e3e88Schristos     N32_RELAX_SETHI | N32_RELAX_ORI,
5630*b88e3e88Schristos     N32_RELAX_ALU1 | N32_RELAX_MEM,
5631*b88e3e88Schristos   },
5632*b88e3e88Schristos   {
5633*b88e3e88Schristos     /* TLS IE LA */
5634*b88e3e88Schristos     BFD_RELOC_NDS32_TLS_IE_HI20,
5635*b88e3e88Schristos     NULL,
5636*b88e3e88Schristos     NDS32_RELAX_HINT_TLS_IE_LA,
5637*b88e3e88Schristos     BR_RANGE_U4G,
5638*b88e3e88Schristos     N32_RELAX_SETHI | N32_RELAX_LSI,
5639*b88e3e88Schristos     0,
5640*b88e3e88Schristos   },
5641*b88e3e88Schristos {
5642*b88e3e88Schristos     /* TLS IE LS */
5643*b88e3e88Schristos     BFD_RELOC_NDS32_TLS_IE_HI20,
5644*b88e3e88Schristos     NULL,
5645*b88e3e88Schristos     NDS32_RELAX_HINT_TLS_IE_LS,
5646*b88e3e88Schristos     BR_RANGE_U4G,
5647*b88e3e88Schristos     N32_RELAX_SETHI | N32_RELAX_LSI | N32_RELAX_MEM,
5648*b88e3e88Schristos     0,
5649*b88e3e88Schristos   },
5650*b88e3e88Schristos   {
5651*b88e3e88Schristos     /* TLS IEGP LA */
5652*b88e3e88Schristos     BFD_RELOC_NDS32_TLS_IEGP_HI20,
5653*b88e3e88Schristos     NULL,
5654*b88e3e88Schristos     NDS32_RELAX_HINT_TLS_IEGP_LA,
5655*b88e3e88Schristos     BR_RANGE_U4G,
5656*b88e3e88Schristos     N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_MEM,
5657*b88e3e88Schristos     0,
5658*b88e3e88Schristos   },
5659*b88e3e88Schristos   {
5660*b88e3e88Schristos     /* TLS DESC LS */
5661*b88e3e88Schristos     BFD_RELOC_NDS32_TLS_DESC_HI20,
5662*b88e3e88Schristos     NULL,
5663*b88e3e88Schristos     NDS32_RELAX_HINT_TLS_DESC_LS,
5664*b88e3e88Schristos     BR_RANGE_U4G,
5665*b88e3e88Schristos     N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_ALU1 | N32_RELAX_CALL,
5666*b88e3e88Schristos     N32_RELAX_LSI | N32_RELAX_MEM,
5667*b88e3e88Schristos   },
5668*b88e3e88Schristos   /* last one */
5669*b88e3e88Schristos   {0, NULL, 0, 0 ,0, 0}
5670440a403fSchristos };
5671440a403fSchristos 
5672440a403fSchristos /* Find the relaxation pattern according to instructions.  */
5673440a403fSchristos 
5674440a403fSchristos static bfd_boolean
nds32_find_reloc_table(struct nds32_relocs_pattern * relocs_pattern,struct nds32_relax_hint_table * hint_info)5675440a403fSchristos nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern,
5676440a403fSchristos 			struct nds32_relax_hint_table *hint_info)
5677440a403fSchristos {
5678440a403fSchristos   unsigned int opcode, seq_size;
5679440a403fSchristos   enum nds32_br_range range;
5680440a403fSchristos   struct nds32_relocs_pattern *pattern, *hi_pattern = NULL;
5681440a403fSchristos   const char *opc = NULL;
5682440a403fSchristos   relax_info_t *relax_info = NULL;
5683440a403fSchristos   nds32_relax_fixup_info_t *fixup_info, *hint_fixup;
5684440a403fSchristos   enum nds32_relax_hint_type hint_type = NDS32_RELAX_HINT_NONE;
5685440a403fSchristos   struct nds32_relax_hint_table *table_ptr;
5686440a403fSchristos   uint32_t *code_seq, *hint_code;
5687440a403fSchristos   enum nds32_insn_type relax_type = 0;
5688440a403fSchristos   struct nds32_hint_map *map_ptr = hint_map;
5689440a403fSchristos   unsigned int i;
5690440a403fSchristos   const char *check_insn[] =
5691440a403fSchristos     { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8" };
5692440a403fSchristos 
5693440a403fSchristos   /* TODO: PLT GOT.  */
5694440a403fSchristos   /* Traverse all pattern instruction and set flag.  */
5695440a403fSchristos   pattern = relocs_pattern;
5696440a403fSchristos   while (pattern)
5697440a403fSchristos     {
5698440a403fSchristos       if (pattern->opcode->isize == 4)
5699440a403fSchristos 	{
5700440a403fSchristos 	  /* 4 byte instruction.  */
5701440a403fSchristos 	  opcode = N32_OP6 (pattern->opcode->value);
5702440a403fSchristos 	  switch (opcode)
5703440a403fSchristos 	    {
5704440a403fSchristos 	    case N32_OP6_SETHI:
5705440a403fSchristos 	      hi_pattern = pattern;
5706440a403fSchristos 	      relax_type |= N32_RELAX_SETHI;
5707440a403fSchristos 	      break;
5708440a403fSchristos 	    case N32_OP6_MEM:
5709440a403fSchristos 	      relax_type |= N32_RELAX_MEM;
5710440a403fSchristos 	      break;
5711*b88e3e88Schristos 	    case N32_OP6_ALU1:
5712*b88e3e88Schristos 	      relax_type |= N32_RELAX_ALU1;
5713*b88e3e88Schristos 	      break;
5714440a403fSchristos 	    case N32_OP6_ORI:
5715440a403fSchristos 	      relax_type |= N32_RELAX_ORI;
5716440a403fSchristos 	      break;
5717440a403fSchristos 	    case N32_OP6_BR1:
5718440a403fSchristos 	    case N32_OP6_BR2:
5719440a403fSchristos 	    case N32_OP6_BR3:
5720440a403fSchristos 	      relax_type |= N32_RELAX_BR;
5721440a403fSchristos 	      break;
5722440a403fSchristos 	    case N32_OP6_MOVI:
5723440a403fSchristos 	      relax_type |= N32_RELAX_MOVI;
5724440a403fSchristos 	      break;
5725440a403fSchristos 	    case N32_OP6_LBI:
5726440a403fSchristos 	    case N32_OP6_SBI:
5727440a403fSchristos 	    case N32_OP6_LBSI:
5728440a403fSchristos 	    case N32_OP6_LHI:
5729440a403fSchristos 	    case N32_OP6_SHI:
5730440a403fSchristos 	    case N32_OP6_LHSI:
5731440a403fSchristos 	    case N32_OP6_LWI:
5732440a403fSchristos 	    case N32_OP6_SWI:
5733440a403fSchristos 	    case N32_OP6_LWC:
5734440a403fSchristos 	    case N32_OP6_SWC:
5735*b88e3e88Schristos 	    case N32_OP6_LDC:
5736*b88e3e88Schristos 	    case N32_OP6_SDC:
5737440a403fSchristos 	      relax_type |= N32_RELAX_LSI;
5738440a403fSchristos 	      break;
5739440a403fSchristos 	    case N32_OP6_JREG:
5740440a403fSchristos 	      if (__GF (pattern->opcode->value, 0, 1) == 1)
5741440a403fSchristos 		relax_type |= N32_RELAX_CALL;
5742440a403fSchristos 	      else
5743440a403fSchristos 		relax_type |= N32_RELAX_JUMP;
5744440a403fSchristos 	      break;
5745440a403fSchristos 	    case N32_OP6_JI:
5746440a403fSchristos 	      if (__GF (pattern->opcode->value, 24, 1) == 1)
5747440a403fSchristos 		relax_type |= N32_RELAX_CALL;
5748440a403fSchristos 	      else
5749440a403fSchristos 		relax_type |= N32_RELAX_JUMP;
5750440a403fSchristos 	      break;
5751440a403fSchristos 	    default:
5752440a403fSchristos 	      as_warn (_("relax hint unrecognized instruction: line %d."),
5753440a403fSchristos 		       pattern->frag->fr_line);
5754440a403fSchristos 	      return FALSE;
5755440a403fSchristos 	    }
5756440a403fSchristos 	}
5757440a403fSchristos       else
5758440a403fSchristos 	{
5759*b88e3e88Schristos 	  /* 2 byte instruction.  Compare by opcode name because
5760*b88e3e88Schristos 	     the opcode of 2byte instruction is not regular.  */
5761*b88e3e88Schristos 	  int is_matched = 0;
5762*b88e3e88Schristos 	  for (i = 0; i < ARRAY_SIZE (check_insn); i++)
5763440a403fSchristos 	    {
5764440a403fSchristos 	      if (strcmp (pattern->opcode->opcode, check_insn[i]) == 0)
5765440a403fSchristos 		{
5766440a403fSchristos 		  relax_type |= N32_RELAX_BR;
5767*b88e3e88Schristos 		  is_matched += 1;
5768440a403fSchristos 		  break;
5769440a403fSchristos 		}
5770440a403fSchristos 	    }
5771*b88e3e88Schristos 	  if (!is_matched)
5772*b88e3e88Schristos 	    relax_type |= N32_RELAX_16BIT;
5773440a403fSchristos 	}
5774440a403fSchristos       pattern = pattern->next;
5775440a403fSchristos     }
5776440a403fSchristos 
5777440a403fSchristos   /* Analysis instruction flag to choose relaxation table.  */
5778440a403fSchristos   while (map_ptr->insn_list != 0)
5779440a403fSchristos     {
5780*b88e3e88Schristos       struct nds32_hint_map *hint = map_ptr++;
5781*b88e3e88Schristos       enum nds32_insn_type must = hint->insn_list;
5782*b88e3e88Schristos       enum nds32_insn_type optional = hint->option_list;
5783*b88e3e88Schristos       enum nds32_insn_type extra;
5784*b88e3e88Schristos 
5785*b88e3e88Schristos       if (must != (must & relax_type))
5786*b88e3e88Schristos 	continue;
5787*b88e3e88Schristos 
5788*b88e3e88Schristos       extra = relax_type ^ must;
5789*b88e3e88Schristos       if (extra != (extra & optional))
5790*b88e3e88Schristos 	continue;
5791*b88e3e88Schristos 
5792*b88e3e88Schristos       if (!hi_pattern
5793440a403fSchristos 	  || (hi_pattern->fixP
5794*b88e3e88Schristos 	      && hi_pattern->fixP->fx_r_type == hint->hi_type))
5795440a403fSchristos 	{
5796*b88e3e88Schristos 	  opc = hint->opc;
5797*b88e3e88Schristos 	  hint_type = hint->hint_type;
5798*b88e3e88Schristos 	  range = hint->range;
5799*b88e3e88Schristos 	  map_ptr = hint;
5800440a403fSchristos 	  break;
5801440a403fSchristos 	}
5802440a403fSchristos     }
5803440a403fSchristos 
5804440a403fSchristos   if (map_ptr->insn_list == 0)
5805440a403fSchristos     {
5806*b88e3e88Schristos       if (!nds32_pic)
580706324dcfSchristos 	as_warn (_("Can not find match relax hint.  Line: %d"),
5808440a403fSchristos 		 relocs_pattern->frag->fr_line);
5809440a403fSchristos       return FALSE;
5810440a403fSchristos     }
5811440a403fSchristos 
5812440a403fSchristos   /* Get the match table.  */
5813440a403fSchristos   if (opc)
5814440a403fSchristos     {
5815440a403fSchristos       /* Branch relax pattern.  */
5816440a403fSchristos       relax_info = hash_find (nds32_relax_info_hash, opc);
5817440a403fSchristos       if (!relax_info)
5818440a403fSchristos 	return FALSE;
5819440a403fSchristos       fixup_info = relax_info->relax_fixup[range];
5820440a403fSchristos       code_seq = relax_info->relax_code_seq[range];
5821440a403fSchristos       seq_size = relax_info->relax_code_size[range];
5822440a403fSchristos     }
5823440a403fSchristos   else if (hint_type)
5824440a403fSchristos     {
5825440a403fSchristos       /* Load-store relax pattern.  */
5826440a403fSchristos       table_ptr = relax_ls_table;
5827440a403fSchristos       while (table_ptr->main_type != 0)
5828440a403fSchristos 	{
5829440a403fSchristos 	  if (table_ptr->main_type == hint_type)
5830440a403fSchristos 	    {
5831440a403fSchristos 	      fixup_info = table_ptr->relax_fixup;
5832440a403fSchristos 	      code_seq = table_ptr->relax_code_seq;
5833440a403fSchristos 	      seq_size = table_ptr->relax_code_size;
5834440a403fSchristos 	      break;
5835440a403fSchristos 	    }
5836440a403fSchristos 	  table_ptr++;
5837440a403fSchristos 	}
5838440a403fSchristos       if (table_ptr->main_type == 0)
5839440a403fSchristos 	return FALSE;
5840440a403fSchristos     }
5841440a403fSchristos   else
5842440a403fSchristos     return FALSE;
5843440a403fSchristos 
5844440a403fSchristos   hint_fixup = hint_info->relax_fixup;
5845440a403fSchristos   hint_code = hint_info->relax_code_seq;
5846440a403fSchristos   hint_info->relax_code_size = seq_size;
5847440a403fSchristos 
5848440a403fSchristos   while (fixup_info->size != 0)
5849440a403fSchristos     {
5850440a403fSchristos       if (fixup_info->ramp & NDS32_HINT)
5851440a403fSchristos 	{
5852440a403fSchristos 	  memcpy (hint_fixup, fixup_info, sizeof (nds32_relax_fixup_info_t));
5853440a403fSchristos 	  hint_fixup++;
5854440a403fSchristos 	}
5855440a403fSchristos       fixup_info++;
5856440a403fSchristos     }
5857440a403fSchristos   /* Clear final relocation.  */
5858440a403fSchristos   memset (hint_fixup, 0, sizeof (nds32_relax_fixup_info_t));
585906324dcfSchristos   /* Copy code sequence.  */
5860440a403fSchristos   memcpy (hint_code, code_seq, seq_size);
5861440a403fSchristos   return TRUE;
5862440a403fSchristos }
5863440a403fSchristos 
5864440a403fSchristos /* Because there are a lot of variant of load-store, check
5865440a403fSchristos    all these type here.  */
5866440a403fSchristos 
5867*b88e3e88Schristos #define CLEAN_REG(insn) ((insn) & 0xfe0003ff)
5868*b88e3e88Schristos #define GET_OPCODE(insn) ((insn) & 0xfe000000)
5869*b88e3e88Schristos 
5870440a403fSchristos static bfd_boolean
nds32_match_hint_insn(struct nds32_opcode * opcode,uint32_t seq)5871440a403fSchristos nds32_match_hint_insn (struct nds32_opcode *opcode, uint32_t seq)
5872440a403fSchristos {
5873440a403fSchristos   const char *check_insn[] =
5874*b88e3e88Schristos     { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8", "jral5" };
5875440a403fSchristos   uint32_t insn = opcode->value;
5876440a403fSchristos   unsigned int i;
5877440a403fSchristos 
5878440a403fSchristos   insn = CLEAN_REG (opcode->value);
5879440a403fSchristos   if (insn == seq)
5880440a403fSchristos     return TRUE;
5881440a403fSchristos 
5882440a403fSchristos   switch (seq)
5883440a403fSchristos     {
5884440a403fSchristos     case OP6 (LBI):
5885440a403fSchristos       /* In relocation_table, it regards instruction LBI as representation
5886440a403fSchristos 	 of all the NDS32_RELAX_HINT_LS pattern.  */
5887440a403fSchristos       if (insn == OP6 (LBI) || insn == OP6 (SBI) || insn == OP6 (LBSI)
5888440a403fSchristos 	  || insn == OP6 (LHI) || insn == OP6 (SHI) || insn == OP6 (LHSI)
5889440a403fSchristos 	  || insn == OP6 (LWI) || insn == OP6 (SWI)
5890*b88e3e88Schristos 	  || insn == OP6 (LWC) || insn == OP6 (SWC)
5891*b88e3e88Schristos 	  || insn == OP6 (LDC) || insn == OP6 (SDC))
5892440a403fSchristos 	return TRUE;
5893440a403fSchristos       break;
5894440a403fSchristos     case OP6 (BR2):
5895440a403fSchristos       /* This is for LONGCALL5 and LONGCALL6.  */
5896440a403fSchristos       if (insn == OP6 (BR2))
5897440a403fSchristos 	return TRUE;
5898440a403fSchristos       break;
5899440a403fSchristos     case OP6 (BR1):
5900440a403fSchristos       /* This is for LONGJUMP5 and LONGJUMP6.  */
5901440a403fSchristos       if (opcode->isize == 4
5902440a403fSchristos 	  && (insn == OP6 (BR1) || insn == OP6 (BR2) || insn == OP6 (BR3)))
5903440a403fSchristos 	return TRUE;
5904440a403fSchristos       else if (opcode->isize == 2)
5905440a403fSchristos 	{
5906*b88e3e88Schristos 	  for (i = 0; i < ARRAY_SIZE (check_insn); i++)
5907440a403fSchristos 	    if (strcmp (opcode->opcode, check_insn[i]) == 0)
5908440a403fSchristos 	      return TRUE;
5909440a403fSchristos 	}
5910440a403fSchristos       break;
5911440a403fSchristos     case OP6 (MOVI):
5912440a403fSchristos       /* This is for LONGJUMP7.  */
5913440a403fSchristos       if (opcode->isize == 2 && strcmp (opcode->opcode, "movi55") == 0)
5914440a403fSchristos 	return TRUE;
5915440a403fSchristos       break;
5916*b88e3e88Schristos     case OP6 (MEM):
5917*b88e3e88Schristos       if (OP6 (MEM) == GET_OPCODE (insn))
5918*b88e3e88Schristos 	return TRUE;
5919*b88e3e88Schristos       break;
5920*b88e3e88Schristos     case OP6 (JREG):
5921*b88e3e88Schristos       /* bit 24: N32_JI_JAL  */ /* feed me!  */
5922*b88e3e88Schristos       if ((insn & ~(N32_BIT (24))) == JREG (JRAL))
5923*b88e3e88Schristos 	return TRUE;
5924*b88e3e88Schristos       break;
5925*b88e3e88Schristos     default:
5926*b88e3e88Schristos       if (opcode->isize == 2)
5927*b88e3e88Schristos 	{
5928*b88e3e88Schristos 	  for (i = 0; i < ARRAY_SIZE (check_insn); i++)
5929*b88e3e88Schristos 	    if (strcmp (opcode->opcode, check_insn[i]) == 0)
5930*b88e3e88Schristos 	      return TRUE;
5931*b88e3e88Schristos 
5932*b88e3e88Schristos 	  if ((strcmp (opcode->opcode, "add5.pc") == 0) ||
5933*b88e3e88Schristos 	      (strcmp (opcode->opcode, "add45") == 0))
5934*b88e3e88Schristos 	    return TRUE;
5935*b88e3e88Schristos 	}
5936440a403fSchristos     }
5937440a403fSchristos   return FALSE;
5938440a403fSchristos }
5939440a403fSchristos 
5940440a403fSchristos /* Append relax relocation for link time relaxing.  */
5941440a403fSchristos 
5942440a403fSchristos static void
nds32_elf_append_relax_relocs(const char * key,void * value)5943*b88e3e88Schristos nds32_elf_append_relax_relocs (const char *key, void *value)
5944440a403fSchristos {
5945440a403fSchristos   struct nds32_relocs_pattern *relocs_pattern =
5946440a403fSchristos     (struct nds32_relocs_pattern *) value;
5947440a403fSchristos   struct nds32_relocs_pattern *pattern_temp, *pattern_now;
5948440a403fSchristos   symbolS *sym, *hi_sym = NULL;
5949440a403fSchristos   expressionS exp;
5950440a403fSchristos   fragS *fragP;
5951440a403fSchristos   segT seg_bak = now_seg;
5952440a403fSchristos   frchainS *frchain_bak = frchain_now;
5953440a403fSchristos   struct nds32_relax_hint_table hint_info;
5954440a403fSchristos   nds32_relax_fixup_info_t *hint_fixup, *fixup_now;
5955440a403fSchristos   size_t fixup_size;
5956*b88e3e88Schristos   offsetT branch_offset, hi_branch_offset = 0;
5957440a403fSchristos   fixS *fixP;
5958440a403fSchristos   int range, offset;
5959440a403fSchristos   unsigned int ptr_offset, hint_count, relax_code_size, count = 0;
5960440a403fSchristos   uint32_t *code_seq, code_insn;
5961440a403fSchristos   char *where;
5962440a403fSchristos   int pcrel;
5963440a403fSchristos 
5964440a403fSchristos   if (!relocs_pattern)
5965440a403fSchristos     return;
5966440a403fSchristos 
5967440a403fSchristos   if (!nds32_find_reloc_table (relocs_pattern, &hint_info))
5968440a403fSchristos     return;
5969440a403fSchristos 
5970440a403fSchristos   /* Save symbol for some EMPTY relocation using.  */
5971440a403fSchristos   pattern_now = relocs_pattern;
5972440a403fSchristos   while (pattern_now)
5973440a403fSchristos     {
5974440a403fSchristos       if (pattern_now->opcode->value == OP6 (SETHI))
5975440a403fSchristos 	{
5976440a403fSchristos 	  hi_sym = pattern_now->sym;
5977*b88e3e88Schristos 	  hi_branch_offset = pattern_now->fixP->fx_offset;
5978440a403fSchristos 	  break;
5979440a403fSchristos 	}
5980440a403fSchristos       pattern_now = pattern_now->next;
5981440a403fSchristos     }
5982440a403fSchristos 
5983440a403fSchristos   /* Inserting fix up must specify now_seg or frchain_now.  */
5984440a403fSchristos   now_seg = relocs_pattern->seg;
5985440a403fSchristos   frchain_now = relocs_pattern->frchain;
5986440a403fSchristos   fragP = relocs_pattern->frag;
5987440a403fSchristos   branch_offset = fragP->fr_offset;
5988440a403fSchristos 
5989440a403fSchristos   hint_fixup = hint_info.relax_fixup;
5990440a403fSchristos   code_seq = hint_info.relax_code_seq;
5991440a403fSchristos   relax_code_size = hint_info.relax_code_size;
5992440a403fSchristos   pattern_now = relocs_pattern;
5993440a403fSchristos 
5994*b88e3e88Schristos #ifdef NDS32_LINUX_TOOLCHAIN
5995*b88e3e88Schristos   /* prepare group relocation ID (number).  */
5996*b88e3e88Schristos   long group_id = 0;
5997*b88e3e88Schristos   if (key)
5998*b88e3e88Schristos     {
5999*b88e3e88Schristos       /* convert .relax_hint key to number */
6000*b88e3e88Schristos       errno = 0;
6001*b88e3e88Schristos       group_id = strtol (key, NULL, 10);
6002*b88e3e88Schristos       if ((errno == ERANGE && (group_id == LONG_MAX || group_id == LONG_MIN))
6003*b88e3e88Schristos 	  || (errno != 0 && group_id == 0))
6004*b88e3e88Schristos 	{
6005*b88e3e88Schristos 	  as_bad (_("Internal error: .relax_hint KEY is not a number!"));
6006*b88e3e88Schristos 	  goto restore;
6007*b88e3e88Schristos 	}
6008*b88e3e88Schristos     }
6009*b88e3e88Schristos #endif
6010*b88e3e88Schristos 
6011440a403fSchristos   /* Insert relaxation.  */
6012440a403fSchristos   exp.X_op = O_symbol;
6013440a403fSchristos 
6014*b88e3e88Schristos   /* For each instruction in the hint group.  */
6015440a403fSchristos   while (pattern_now)
6016440a403fSchristos     {
6017*b88e3e88Schristos       if (count >= relax_code_size / 4)
6018*b88e3e88Schristos 	count = 0;
6019*b88e3e88Schristos 
6020440a403fSchristos       /* Choose the match fixup by instruction.  */
6021440a403fSchristos       code_insn = CLEAN_REG (*(code_seq + count));
6022440a403fSchristos       if (!nds32_match_hint_insn (pattern_now->opcode, code_insn))
6023440a403fSchristos 	{
6024*b88e3e88Schristos 	  /* Try search from head again */
6025440a403fSchristos 	  count = 0;
6026440a403fSchristos 	  code_insn = CLEAN_REG (*(code_seq + count));
6027440a403fSchristos 
6028440a403fSchristos 	  while (!nds32_match_hint_insn (pattern_now->opcode, code_insn))
6029440a403fSchristos 	    {
6030440a403fSchristos 	      count++;
6031440a403fSchristos 	      if (count >= relax_code_size / 4)
6032440a403fSchristos 		{
6033*b88e3e88Schristos 		  as_bad (_("Internal error: Relax hint (%s) error. %s: %s (%x)"),
6034*b88e3e88Schristos 			  key,
6035*b88e3e88Schristos 			  now_seg->name,
6036*b88e3e88Schristos 			  pattern_now->opcode->opcode,
6037*b88e3e88Schristos 			  pattern_now->opcode->value);
6038440a403fSchristos 		  goto restore;
6039440a403fSchristos 		}
6040440a403fSchristos 	      code_insn = CLEAN_REG (*(code_seq + count));
6041440a403fSchristos 	    }
6042440a403fSchristos 	}
6043440a403fSchristos       fragP = pattern_now->frag;
6044440a403fSchristos       sym = pattern_now->sym;
6045440a403fSchristos       branch_offset = fragP->fr_offset;
6046440a403fSchristos       offset = count * 4;
6047440a403fSchristos       where = pattern_now->where;
6048440a403fSchristos       /* Find the instruction map fix.  */
6049440a403fSchristos       fixup_now = hint_fixup;
6050440a403fSchristos       while (fixup_now->offset != offset)
6051440a403fSchristos 	{
6052440a403fSchristos 	  fixup_now++;
6053440a403fSchristos 	  if (fixup_now->size == 0)
6054440a403fSchristos 	    break;
6055440a403fSchristos 	}
6056440a403fSchristos       /* This element is without relaxation relocation.  */
6057440a403fSchristos       if (fixup_now->size == 0)
6058440a403fSchristos 	{
6059440a403fSchristos 	  pattern_now = pattern_now->next;
6060440a403fSchristos 	  continue;
6061440a403fSchristos 	}
6062440a403fSchristos       fixup_size = fixup_now->size;
6063440a403fSchristos 
6064440a403fSchristos       /* Insert all fixup.  */
6065440a403fSchristos       while (fixup_size != 0 && fixup_now->offset == offset)
6066440a403fSchristos 	{
6067440a403fSchristos 	  /* Set the real instruction size in element.  */
6068440a403fSchristos 	  fixup_size = pattern_now->opcode->isize;
6069440a403fSchristos 	  pcrel = ((fixup_now->ramp & NDS32_PCREL) != 0) ? 1 : 0;
6070440a403fSchristos 	  if (fixup_now->ramp & NDS32_FIX)
6071440a403fSchristos 	    {
6072440a403fSchristos 	      /* Convert original relocation.  */
6073440a403fSchristos 	      pattern_now->fixP->fx_r_type = fixup_now->r_type ;
6074440a403fSchristos 	      fixup_size = 0;
6075440a403fSchristos 	    }
6076440a403fSchristos 	  else if ((fixup_now->ramp & NDS32_PTR) != 0)
6077440a403fSchristos 	    {
6078440a403fSchristos 	      /* This relocation has to point to another instruction.  Make
6079440a403fSchristos 		 sure each resolved relocation has to be pointed.  */
6080440a403fSchristos 	      pattern_temp = relocs_pattern;
6081440a403fSchristos 	      /* All instruction in relax_table should be 32-bit.  */
6082440a403fSchristos 	      hint_count = hint_info.relax_code_size / 4;
6083440a403fSchristos 	      code_insn = CLEAN_REG (*(code_seq + hint_count - 1));
6084440a403fSchristos 	      while (pattern_temp)
6085440a403fSchristos 		{
6086440a403fSchristos 		  /* Point to every resolved relocation.  */
6087440a403fSchristos 		  if (nds32_match_hint_insn (pattern_temp->opcode, code_insn))
6088440a403fSchristos 		    {
6089440a403fSchristos 		      ptr_offset =
6090440a403fSchristos 			pattern_temp->where - pattern_temp->frag->fr_literal;
6091440a403fSchristos 		      exp.X_add_symbol = symbol_temp_new (now_seg, ptr_offset,
6092440a403fSchristos 							  pattern_temp->frag);
6093440a403fSchristos 		      exp.X_add_number = 0;
6094440a403fSchristos 		      fixP =
6095440a403fSchristos 			fix_new_exp (fragP, where - fragP->fr_literal,
6096440a403fSchristos 				     fixup_size, &exp, 0, fixup_now->r_type);
6097440a403fSchristos 		      fixP->fx_addnumber = fixP->fx_offset;
6098440a403fSchristos 		    }
6099440a403fSchristos 		  pattern_temp = pattern_temp->next;
6100440a403fSchristos 		}
6101440a403fSchristos 	      fixup_size = 0;
6102440a403fSchristos 	    }
6103440a403fSchristos 	  else if (fixup_now->ramp & NDS32_ADDEND)
6104440a403fSchristos 	    {
6105440a403fSchristos 	      range = nds32_elf_sethi_range (relocs_pattern);
6106440a403fSchristos 	      if (range == NDS32_LOADSTORE_NONE)
6107440a403fSchristos 		{
6108440a403fSchristos 		  as_bad (_("Internal error: Range error. %s"), now_seg->name);
6109440a403fSchristos 		  return;
6110440a403fSchristos 		}
6111440a403fSchristos 	      exp.X_add_symbol = abs_section_sym;
6112440a403fSchristos 	      exp.X_add_number = SET_ADDEND (4, 0, optimize, enable_16bit);
6113440a403fSchristos 	      exp.X_add_number |= ((range & 0x3f) << 8);
6114440a403fSchristos 	    }
6115440a403fSchristos 	  else if ((fixup_now->ramp & NDS32_ABS) != 0)
6116440a403fSchristos 	    {
6117440a403fSchristos 	      /* This is a tag relocation.  */
6118440a403fSchristos 	      exp.X_add_symbol = abs_section_sym;
6119440a403fSchristos 	      exp.X_add_number = 0;
6120440a403fSchristos 	    }
6121440a403fSchristos 	  else if ((fixup_now->ramp & NDS32_INSN16) != 0)
6122440a403fSchristos 	    {
6123440a403fSchristos 	      if (!enable_16bit)
6124440a403fSchristos 		fixup_size = 0;
6125440a403fSchristos 	      /* This is a tag relocation.  */
6126440a403fSchristos 	      exp.X_add_symbol = abs_section_sym;
6127440a403fSchristos 	      exp.X_add_number = 0;
6128440a403fSchristos 	    }
6129440a403fSchristos 	  else if ((fixup_now->ramp & NDS32_SYM) != 0)
6130440a403fSchristos 	    {
6131440a403fSchristos 	      /* For EMPTY relocation save the true symbol.  */
6132440a403fSchristos 	      exp.X_add_symbol = hi_sym;
6133*b88e3e88Schristos 	      exp.X_add_number = hi_branch_offset;
6134*b88e3e88Schristos 	    }
6135*b88e3e88Schristos 	  else if (NDS32_SYM_DESC_MEM & fixup_now->ramp)
6136*b88e3e88Schristos 	    {
6137*b88e3e88Schristos 	      /* Do the same as NDS32_SYM.  */
6138*b88e3e88Schristos 	      exp.X_add_symbol = hi_sym;
6139*b88e3e88Schristos 	      exp.X_add_number = hi_branch_offset;
6140*b88e3e88Schristos 
6141*b88e3e88Schristos 	      /* Extra to NDS32_SYM.  */
6142*b88e3e88Schristos 	      /* Detect if DESC_FUNC relax type do apply.  */
6143*b88e3e88Schristos 	      if ((REG_GP == N32_RA5 (pattern_now->insn))
6144*b88e3e88Schristos 		  || (REG_GP == N32_RB5 (pattern_now->insn)))
6145*b88e3e88Schristos 		{
6146*b88e3e88Schristos 		  fixP = fix_new_exp (fragP, where - fragP->fr_literal,
6147*b88e3e88Schristos 				      fixup_size, &exp, pcrel,
6148*b88e3e88Schristos 				      BFD_RELOC_NDS32_TLS_DESC_FUNC);
6149*b88e3e88Schristos 		  fixP->fx_addnumber = fixP->fx_offset;
6150*b88e3e88Schristos 
6151*b88e3e88Schristos 		  fixup_size = 0;
6152*b88e3e88Schristos 		}
6153*b88e3e88Schristos 	      /* Else do as usual.  */
6154*b88e3e88Schristos 	    }
6155*b88e3e88Schristos 	  else if (fixup_now->ramp & NDS32_PTR_PATTERN)
6156*b88e3e88Schristos 	    {
6157*b88e3e88Schristos 	      /* Find out PTR_RESOLVED code pattern.  */
6158*b88e3e88Schristos 	      nds32_relax_fixup_info_t *next_fixup = fixup_now + 1;
6159*b88e3e88Schristos 	      uint32_t resolved_pattern = 0;
6160*b88e3e88Schristos 	      while (next_fixup->offset)
6161*b88e3e88Schristos 		{
6162*b88e3e88Schristos 		  if (next_fixup->r_type == BFD_RELOC_NDS32_PTR_RESOLVED)
6163*b88e3e88Schristos 		    {
6164*b88e3e88Schristos 		      uint32_t new_pattern = code_seq[next_fixup->offset >> 2];
6165*b88e3e88Schristos 		      if (!resolved_pattern)
6166*b88e3e88Schristos 			resolved_pattern = new_pattern;
6167*b88e3e88Schristos 		      else if (new_pattern != resolved_pattern)
6168*b88e3e88Schristos 			{
6169*b88e3e88Schristos 			  as_warn (_("Multiple BFD_RELOC_NDS32_PTR_RESOLVED "
6170*b88e3e88Schristos 				     "patterns are not supported yet!"));
6171*b88e3e88Schristos 			  break;
6172*b88e3e88Schristos 			}
6173*b88e3e88Schristos 		    }
6174*b88e3e88Schristos 		  ++next_fixup;
6175*b88e3e88Schristos 		}
6176*b88e3e88Schristos 
6177*b88e3e88Schristos 	      /* Find matched code and insert fix-ups.  */
6178*b88e3e88Schristos 	      struct nds32_relocs_pattern *next_pattern = pattern_now->next;
6179*b88e3e88Schristos 	      /* This relocation has to point to another instruction.
6180*b88e3e88Schristos 		 Make sure each resolved relocation has to be pointed.  */
6181*b88e3e88Schristos 	      /* All instruction in relax_table should be 32-bit.  */
6182*b88e3e88Schristos 	      while (next_pattern)
6183*b88e3e88Schristos 		{
6184*b88e3e88Schristos 		  uint32_t cur_pattern = GET_OPCODE (next_pattern->opcode->value);
6185*b88e3e88Schristos 		  if (cur_pattern == resolved_pattern)
6186*b88e3e88Schristos 		    {
6187*b88e3e88Schristos 		      ptr_offset = next_pattern->where
6188*b88e3e88Schristos 			- next_pattern->frag->fr_literal;
6189*b88e3e88Schristos 		      exp.X_add_symbol = symbol_temp_new (now_seg, ptr_offset,
6190*b88e3e88Schristos 							  next_pattern->frag);
6191*b88e3e88Schristos 		      exp.X_add_number = 0;
6192*b88e3e88Schristos 		      fixP = fix_new_exp (fragP, where - fragP->fr_literal,
6193*b88e3e88Schristos 					  fixup_size, &exp, 0,
6194*b88e3e88Schristos 					  fixup_now->r_type);
6195*b88e3e88Schristos 		      fixP->fx_addnumber = fixP->fx_offset;
6196*b88e3e88Schristos 		    }
6197*b88e3e88Schristos 		  next_pattern = next_pattern->next;
6198*b88e3e88Schristos 		}
6199*b88e3e88Schristos 
6200*b88e3e88Schristos 	      fixup_size = 0;
6201*b88e3e88Schristos 	    }
6202*b88e3e88Schristos 	  else if (fixup_now->ramp & NDS32_PTR_MULTIPLE)
6203*b88e3e88Schristos 	    {
6204*b88e3e88Schristos 	      /* Find each PTR_RESOLVED pattern after PTR.  */
6205*b88e3e88Schristos 	      nds32_relax_fixup_info_t *next_fixup = fixup_now + 1;
6206*b88e3e88Schristos 	      while (next_fixup->offset)
6207*b88e3e88Schristos 		{
6208*b88e3e88Schristos 		  if (next_fixup->r_type == BFD_RELOC_NDS32_PTR_RESOLVED)
6209*b88e3e88Schristos 		    {
6210*b88e3e88Schristos 		      uint32_t pattern = code_seq[next_fixup->offset >> 2];
6211*b88e3e88Schristos 		      /* Find matched code to insert fix-ups.  */
6212*b88e3e88Schristos 		      struct nds32_relocs_pattern *next_insn = pattern_now->next;
6213*b88e3e88Schristos 		      while (next_insn)
6214*b88e3e88Schristos 			{
6215*b88e3e88Schristos 			  uint32_t insn_pattern = GET_OPCODE (next_insn->opcode->value);
6216*b88e3e88Schristos 			  if (insn_pattern == pattern)
6217*b88e3e88Schristos 			    {
6218*b88e3e88Schristos 			      ptr_offset = next_insn->where
6219*b88e3e88Schristos 				- next_insn->frag->fr_literal;
6220*b88e3e88Schristos 			      exp.X_add_symbol = symbol_temp_new (now_seg,
6221*b88e3e88Schristos 								  ptr_offset,
6222*b88e3e88Schristos 								  next_insn->frag);
6223*b88e3e88Schristos 			      exp.X_add_number = 0;
6224*b88e3e88Schristos 			      fixP = fix_new_exp (fragP,
6225*b88e3e88Schristos 						  where - fragP->fr_literal,
6226*b88e3e88Schristos 						  fixup_size, &exp, 0,
6227*b88e3e88Schristos 						  fixup_now->r_type);
6228*b88e3e88Schristos 			      fixP->fx_addnumber = fixP->fx_offset;
6229*b88e3e88Schristos 			    }
6230*b88e3e88Schristos 			  next_insn = next_insn->next;
6231*b88e3e88Schristos 			}
6232*b88e3e88Schristos 		    }
6233*b88e3e88Schristos 		  ++next_fixup;
6234*b88e3e88Schristos 		}
6235*b88e3e88Schristos 	      fixup_size = 0;
6236440a403fSchristos 	    }
6237440a403fSchristos 	  else
6238440a403fSchristos 	    {
6239440a403fSchristos 	      exp.X_add_symbol = sym;
6240440a403fSchristos 	      exp.X_add_number = branch_offset;
6241440a403fSchristos 	    }
6242440a403fSchristos 
6243440a403fSchristos 	  if (fixup_size != 0)
6244440a403fSchristos 	    {
6245440a403fSchristos 	      fixP = fix_new_exp (fragP, where - fragP->fr_literal, fixup_size,
6246440a403fSchristos 				  &exp, pcrel, fixup_now->r_type);
6247440a403fSchristos 	      fixP->fx_addnumber = fixP->fx_offset;
6248440a403fSchristos 	    }
6249440a403fSchristos 	  fixup_now++;
6250440a403fSchristos 	  fixup_size = fixup_now->size;
6251440a403fSchristos 	}
6252*b88e3e88Schristos 
6253*b88e3e88Schristos #ifdef NDS32_LINUX_TOOLCHAIN
6254*b88e3e88Schristos       /* Insert group relocation for each relax hint.  */
6255*b88e3e88Schristos       if (key)
6256*b88e3e88Schristos 	{
6257*b88e3e88Schristos 	  exp.X_add_symbol = hi_sym; /* for eyes only */
6258*b88e3e88Schristos 	  exp.X_add_number = group_id;
6259*b88e3e88Schristos 	  fixP = fix_new_exp (fragP, where - fragP->fr_literal, fixup_size,
6260*b88e3e88Schristos 			      &exp, pcrel, BFD_RELOC_NDS32_GROUP);
6261*b88e3e88Schristos 	  fixP->fx_addnumber = fixP->fx_offset;
6262*b88e3e88Schristos 	}
6263*b88e3e88Schristos #endif
6264*b88e3e88Schristos 
6265440a403fSchristos       if (count < relax_code_size / 4)
6266440a403fSchristos 	count++;
6267440a403fSchristos       pattern_now = pattern_now->next;
6268440a403fSchristos     }
6269440a403fSchristos 
6270440a403fSchristos restore:
6271440a403fSchristos   now_seg = seg_bak;
6272440a403fSchristos   frchain_now = frchain_bak;
6273440a403fSchristos }
6274440a403fSchristos 
6275*b88e3e88Schristos static void
nds32_str_tolower(const char * src,char * dest)6276*b88e3e88Schristos nds32_str_tolower (const char *src, char *dest)
6277*b88e3e88Schristos {
6278*b88e3e88Schristos   unsigned int i, len;
6279*b88e3e88Schristos 
6280*b88e3e88Schristos   len = strlen (src);
6281*b88e3e88Schristos 
6282*b88e3e88Schristos   for (i = 0; i < len; i++)
6283*b88e3e88Schristos     *(dest + i) = TOLOWER (*(src + i));
6284*b88e3e88Schristos 
6285*b88e3e88Schristos   *(dest + i) = '\0';
6286*b88e3e88Schristos }
6287*b88e3e88Schristos 
6288440a403fSchristos /* Check instruction if it can be used for the baseline.  */
6289440a403fSchristos 
6290440a403fSchristos static bfd_boolean
nds32_check_insn_available(struct nds32_asm_insn insn,const char * str)6291440a403fSchristos nds32_check_insn_available (struct nds32_asm_insn insn, const char *str)
6292440a403fSchristos {
6293440a403fSchristos   int attr = insn.attr & ATTR_ALL;
6294440a403fSchristos   static int baseline_isa = 0;
6295*b88e3e88Schristos   char *s;
6296*b88e3e88Schristos 
6297*b88e3e88Schristos   s = xmalloc (strlen (str) + 1);
6298*b88e3e88Schristos   nds32_str_tolower (str, s);
6299*b88e3e88Schristos   if (verbatim
6300*b88e3e88Schristos       && (((insn.opcode->value == ALU2 (MTUSR)
6301*b88e3e88Schristos 	    || insn.opcode->value == ALU2 (MFUSR))
6302*b88e3e88Schristos 	   && (strstr (s, "lc")
6303*b88e3e88Schristos 	       || strstr (s, "le")
6304*b88e3e88Schristos 	       || strstr (s, "lb")))
6305*b88e3e88Schristos 	  || (insn.attr & NASM_ATTR_ZOL)))
6306*b88e3e88Schristos     {
6307*b88e3e88Schristos       as_bad (_("Not support instruction %s in verbatim."), str);
6308*b88e3e88Schristos       return FALSE;
6309*b88e3e88Schristos     }
6310*b88e3e88Schristos   free (s);
6311*b88e3e88Schristos 
6312*b88e3e88Schristos   if (!enable_16bit && insn.opcode->isize == 2)
6313*b88e3e88Schristos     {
6314*b88e3e88Schristos       as_bad (_("16-bit instruction is disabled: %s."), str);
6315*b88e3e88Schristos       return FALSE;
6316*b88e3e88Schristos     }
6317*b88e3e88Schristos 
6318440a403fSchristos   /* No isa setting or all isa can use.  */
6319440a403fSchristos   if (attr == 0 || attr == ATTR_ALL)
6320440a403fSchristos     return TRUE;
6321440a403fSchristos 
6322440a403fSchristos   if (baseline_isa == 0)
6323440a403fSchristos     {
6324440a403fSchristos       /* Map option baseline and instruction attribute.  */
6325440a403fSchristos       switch (nds32_baseline)
6326440a403fSchristos 	{
6327440a403fSchristos 	case ISA_V2:
6328440a403fSchristos 	  baseline_isa = ATTR (ISA_V2);
6329440a403fSchristos 	  break;
6330440a403fSchristos 	case ISA_V3:
6331440a403fSchristos 	  baseline_isa = ATTR (ISA_V3);
6332440a403fSchristos 	  break;
6333440a403fSchristos 	case ISA_V3M:
6334440a403fSchristos 	  baseline_isa = ATTR (ISA_V3M);
6335440a403fSchristos 	  break;
6336440a403fSchristos 	}
6337440a403fSchristos     }
6338440a403fSchristos 
6339440a403fSchristos   if  ((baseline_isa & attr) == 0)
6340440a403fSchristos     {
634106324dcfSchristos       as_bad (_("Instruction %s not supported in the baseline."), str);
6342440a403fSchristos       return FALSE;
6343440a403fSchristos     }
6344440a403fSchristos   return TRUE;
6345440a403fSchristos }
6346440a403fSchristos 
6347440a403fSchristos /* Stub of machine dependent.  */
6348440a403fSchristos 
6349440a403fSchristos void
md_assemble(char * str)6350440a403fSchristos md_assemble (char *str)
6351440a403fSchristos {
6352440a403fSchristos   struct nds32_asm_insn insn;
6353440a403fSchristos   char *out;
6354440a403fSchristos   struct nds32_pseudo_opcode *popcode;
6355440a403fSchristos   const struct nds32_field *fld = NULL;
6356440a403fSchristos   fixS *fixP;
6357440a403fSchristos   uint16_t insn_16;
6358440a403fSchristos   struct nds32_relocs_pattern *relocs_temp;
6359*b88e3e88Schristos   struct nds32_relocs_group *group_temp;
6360440a403fSchristos   fragS *fragP;
6361440a403fSchristos   int label = label_exist;
6362*b88e3e88Schristos   static bfd_boolean pseudo_hint = FALSE;
6363440a403fSchristos 
6364440a403fSchristos   popcode = nds32_lookup_pseudo_opcode (str);
6365440a403fSchristos   /* Note that we need to check 'verbatim' and
6366440a403fSchristos      'opcode->physical_op'.  If the assembly content is generated by
6367440a403fSchristos      compiler and this opcode is a physical instruction, there is no
6368440a403fSchristos      need to perform pseudo instruction expansion/transformation.  */
6369440a403fSchristos   if (popcode && !(verbatim && popcode->physical_op))
6370440a403fSchristos     {
6371*b88e3e88Schristos       /* Pseudo instruction is with relax_hint.  */
6372*b88e3e88Schristos       if (relaxing)
6373*b88e3e88Schristos 	pseudo_hint = TRUE;
6374440a403fSchristos       pseudo_opcode = TRUE;
6375440a403fSchristos       nds32_pseudo_opcode_wrapper (str, popcode);
6376440a403fSchristos       pseudo_opcode = FALSE;
6377*b88e3e88Schristos       pseudo_hint = FALSE;
6378440a403fSchristos       nds32_elf_append_relax_relocs (NULL, relocs_list);
6379440a403fSchristos 
6380*b88e3e88Schristos       /* Free relax_hint group list.  */
6381*b88e3e88Schristos       while (nds32_relax_hint_current)
6382*b88e3e88Schristos 	{
6383*b88e3e88Schristos 	  group_temp = nds32_relax_hint_current->next;
6384*b88e3e88Schristos 	  free (nds32_relax_hint_current);
6385*b88e3e88Schristos 	  nds32_relax_hint_current = group_temp;
6386*b88e3e88Schristos 	}
6387*b88e3e88Schristos 
6388440a403fSchristos       /* Free pseudo list.  */
6389440a403fSchristos       relocs_temp = relocs_list;
6390440a403fSchristos       while (relocs_temp)
6391440a403fSchristos 	{
6392440a403fSchristos 	  relocs_list = relocs_list->next;
6393440a403fSchristos 	  free (relocs_temp);
6394440a403fSchristos 	  relocs_temp = relocs_list;
6395440a403fSchristos 	}
6396440a403fSchristos 
6397440a403fSchristos       return;
6398440a403fSchristos     }
6399440a403fSchristos 
6400440a403fSchristos   label_exist = 0;
6401*b88e3e88Schristos   insn.info = XNEW (expressionS);
6402440a403fSchristos   asm_desc.result = NASM_OK;
6403440a403fSchristos   nds32_assemble (&asm_desc, &insn, str);
6404440a403fSchristos 
6405440a403fSchristos   switch (asm_desc.result)
6406440a403fSchristos     {
6407440a403fSchristos     case NASM_ERR_UNKNOWN_OP:
6408440a403fSchristos       as_bad (_("Unrecognized opcode, %s."), str);
6409440a403fSchristos       return;
6410440a403fSchristos     case NASM_ERR_SYNTAX:
6411440a403fSchristos       as_bad (_("Incorrect syntax, %s."), str);
6412440a403fSchristos       return;
6413440a403fSchristos     case NASM_ERR_OPERAND:
6414440a403fSchristos       as_bad (_("Unrecognized operand/register, %s."), str);
6415440a403fSchristos       return;
6416440a403fSchristos     case NASM_ERR_OUT_OF_RANGE:
6417440a403fSchristos       as_bad (_("Operand out of range, %s."), str);
6418440a403fSchristos       return;
6419440a403fSchristos     case NASM_ERR_REG_REDUCED:
6420440a403fSchristos       as_bad (_("Prohibited register used for reduced-register, %s."), str);
6421440a403fSchristos       return;
6422440a403fSchristos     case NASM_ERR_JUNK_EOL:
6423440a403fSchristos       as_bad (_("Junk at end of line, %s."), str);
6424440a403fSchristos       return;
6425440a403fSchristos     }
6426440a403fSchristos 
6427440a403fSchristos   gas_assert (insn.opcode);
6428440a403fSchristos 
6429440a403fSchristos   nds32_set_elf_flags_by_insn (&insn);
6430440a403fSchristos 
6431440a403fSchristos   gas_assert (insn.opcode->isize == 4 || insn.opcode->isize == 2);
6432440a403fSchristos 
6433440a403fSchristos   if (!nds32_check_insn_available (insn, str))
6434440a403fSchristos     return;
6435440a403fSchristos 
643606324dcfSchristos   /* Make sure the beginning of text being 2-byte align.  */
6437440a403fSchristos   nds32_adjust_label (1);
6438*b88e3e88Schristos   add_mapping_symbol (MAP_CODE, 0, 0);
6439440a403fSchristos   fld = insn.field;
6440440a403fSchristos   /* Try to allocate the max size to guarantee relaxable same branch
6441440a403fSchristos      instructions in the same fragment.  */
6442440a403fSchristos   frag_grow (NDS32_MAXCHAR);
6443440a403fSchristos   fragP = frag_now;
6444*b88e3e88Schristos 
6445440a403fSchristos   if (fld && (insn.attr & NASM_ATTR_BRANCH)
6446440a403fSchristos       && (pseudo_opcode || (insn.opcode->value != INSN_JAL
6447440a403fSchristos 			    && insn.opcode->value != INSN_J))
6448440a403fSchristos       && (!verbatim || pseudo_opcode))
6449440a403fSchristos     {
6450440a403fSchristos       /* User assembly code branch relax for it.  */
6451440a403fSchristos       /* If fld is not NULL, it is a symbol.  */
645206324dcfSchristos       /* Branch must relax to proper pattern in user assembly code exclude
6453440a403fSchristos 	 J and JAL.  Keep these two in original type for users which wants
6454440a403fSchristos 	 to keep their size be fixed.  In general, assembler does not convert
6455440a403fSchristos 	 instruction generated by compiler.  But jump instruction may be
6456440a403fSchristos 	 truncated in text virtual model.  For workaround, compiler generate
6457440a403fSchristos 	 pseudo jump to fix this issue currently.  */
6458440a403fSchristos 
6459440a403fSchristos       /* Get branch range type.  */
6460440a403fSchristos       dwarf2_emit_insn (0);
6461440a403fSchristos       enum nds32_br_range range_type;
6462*b88e3e88Schristos       expressionS *pexp = insn.info;
6463440a403fSchristos 
6464440a403fSchristos       range_type = get_range_type (fld);
6465440a403fSchristos 
6466440a403fSchristos       out = frag_var (rs_machine_dependent, NDS32_MAXCHAR,
6467440a403fSchristos 		      0, /* VAR is un-used.  */
6468440a403fSchristos 		      range_type, /* SUBTYPE is used as range type.  */
6469440a403fSchristos 		      pexp->X_add_symbol, pexp->X_add_number, 0);
6470440a403fSchristos 
6471440a403fSchristos       fragP->fr_fix += insn.opcode->isize;
6472440a403fSchristos       fragP->tc_frag_data.opcode = insn.opcode;
6473440a403fSchristos       fragP->tc_frag_data.insn = insn.insn;
6474440a403fSchristos       if (insn.opcode->isize == 4)
6475440a403fSchristos 	bfd_putb32 (insn.insn, out);
6476440a403fSchristos       else if (insn.opcode->isize == 2)
6477440a403fSchristos 	bfd_putb16 (insn.insn, out);
6478440a403fSchristos       fragP->tc_frag_data.flag |= NDS32_FRAG_BRANCH;
6479*b88e3e88Schristos 
6480*b88e3e88Schristos       free (insn.info);
6481440a403fSchristos       return;
6482440a403fSchristos       /* md_convert_frag will insert relocations.  */
6483440a403fSchristos     }
6484440a403fSchristos   else if (!relaxing && enable_16bit && (optimize || optimize_for_space)
6485440a403fSchristos 	   && ((!fld && !verbatim && insn.opcode->isize == 4
6486440a403fSchristos 		&& nds32_convert_32_to_16 (stdoutput, insn.insn, &insn_16, NULL))
6487440a403fSchristos 	       || (insn.opcode->isize == 2
6488440a403fSchristos 		   && nds32_convert_16_to_32 (stdoutput, insn.insn, NULL))))
6489440a403fSchristos     {
6490440a403fSchristos       /* Record this one is relaxable.  */
6491*b88e3e88Schristos       expressionS *pexp = insn.info;
6492440a403fSchristos       dwarf2_emit_insn (0);
6493440a403fSchristos       if (fld)
6494440a403fSchristos 	{
6495440a403fSchristos 	  out = frag_var (rs_machine_dependent,
6496440a403fSchristos 			  4, /* Max size is 32-bit instruction.  */
6497440a403fSchristos 			  0, /* VAR is un-used.  */
6498440a403fSchristos 			  0, pexp->X_add_symbol, pexp->X_add_number, 0);
6499440a403fSchristos 	  fragP->tc_frag_data.flag |= NDS32_FRAG_RELAXABLE_BRANCH;
6500440a403fSchristos 	}
6501440a403fSchristos       else
6502440a403fSchristos 	out = frag_var (rs_machine_dependent,
6503440a403fSchristos 			4, /* Max size is 32-bit instruction.  */
6504440a403fSchristos 			0, /* VAR is un-used.  */
6505440a403fSchristos 			0, NULL, 0, NULL);
6506440a403fSchristos       fragP->tc_frag_data.flag |= NDS32_FRAG_RELAXABLE;
6507440a403fSchristos       fragP->tc_frag_data.opcode = insn.opcode;
6508440a403fSchristos       fragP->tc_frag_data.insn = insn.insn;
6509440a403fSchristos       fragP->fr_fix += 2;
6510440a403fSchristos 
651106324dcfSchristos       /* In original, we don't relax the instruction with label on it,
6512440a403fSchristos 	 but this may cause some redundant nop16.  Therefore, tag this
6513440a403fSchristos 	 relaxable instruction and relax it carefully.  */
6514440a403fSchristos       if (label)
6515440a403fSchristos 	fragP->tc_frag_data.flag |= NDS32_FRAG_LABEL;
6516440a403fSchristos 
6517440a403fSchristos       if (insn.opcode->isize == 4)
6518440a403fSchristos 	bfd_putb16 (insn_16, out);
6519440a403fSchristos       else if (insn.opcode->isize == 2)
6520440a403fSchristos 	bfd_putb16 (insn.insn, out);
6521*b88e3e88Schristos 
6522*b88e3e88Schristos       free (insn.info);
6523440a403fSchristos       return;
6524440a403fSchristos     }
6525440a403fSchristos   else if ((verbatim || !relaxing) && optimize && label)
6526440a403fSchristos     {
6527440a403fSchristos       /* This instruction is with label.  */
6528440a403fSchristos       expressionS exp;
6529440a403fSchristos       out = frag_var (rs_machine_dependent, insn.opcode->isize,
6530440a403fSchristos 		      0, 0, NULL, 0, NULL);
653106324dcfSchristos       /* If this instruction is branch target, it is not relaxable.  */
6532440a403fSchristos       fragP->tc_frag_data.flag = NDS32_FRAG_LABEL;
6533440a403fSchristos       fragP->tc_frag_data.opcode = insn.opcode;
6534440a403fSchristos       fragP->tc_frag_data.insn = insn.insn;
6535440a403fSchristos       fragP->fr_fix += insn.opcode->isize;
6536440a403fSchristos       if (insn.opcode->isize == 4)
6537440a403fSchristos 	{
6538440a403fSchristos 	  exp.X_op = O_symbol;
6539440a403fSchristos 	  exp.X_add_symbol = abs_section_sym;
6540440a403fSchristos 	  exp.X_add_number = 0;
6541440a403fSchristos 	  fixP = fix_new_exp (fragP, fragP->fr_fix - 4, 0, &exp,
6542440a403fSchristos 			      0, BFD_RELOC_NDS32_LABEL);
6543440a403fSchristos 	  if (!verbatim)
6544440a403fSchristos 	    fragP->tc_frag_data.flag = NDS32_FRAG_ALIGN;
6545440a403fSchristos 	}
6546440a403fSchristos     }
6547440a403fSchristos   else
6548440a403fSchristos     out = frag_more (insn.opcode->isize);
6549440a403fSchristos 
6550440a403fSchristos   if (insn.opcode->isize == 4)
6551440a403fSchristos     bfd_putb32 (insn.insn, out);
6552*b88e3e88Schristos   else if (insn.opcode->isize == 2)
6553440a403fSchristos     bfd_putb16 (insn.insn, out);
6554440a403fSchristos 
6555440a403fSchristos   dwarf2_emit_insn (insn.opcode->isize);
6556440a403fSchristos 
6557440a403fSchristos   /* Compiler generating code and user assembly pseudo load-store, insert
6558440a403fSchristos      fixup here.  */
6559*b88e3e88Schristos   expressionS *pexp = insn.info;
6560440a403fSchristos   fixP = nds32_elf_record_fixup_exp (fragP, str, fld, pexp, out, &insn);
6561440a403fSchristos   /* Build relaxation pattern when relaxing is enable.  */
6562440a403fSchristos   if (relaxing)
6563*b88e3e88Schristos     nds32_elf_build_relax_relation (fixP, pexp, out, &insn, fragP, fld,
6564*b88e3e88Schristos 				    pseudo_hint);
6565*b88e3e88Schristos 
6566*b88e3e88Schristos   free (insn.info);
6567440a403fSchristos }
6568440a403fSchristos 
6569440a403fSchristos /* md_macro_start  */
6570440a403fSchristos 
6571440a403fSchristos void
nds32_macro_start(void)6572440a403fSchristos nds32_macro_start (void)
6573440a403fSchristos {
6574440a403fSchristos }
6575440a403fSchristos 
6576440a403fSchristos /* md_macro_info  */
6577440a403fSchristos 
6578440a403fSchristos void
nds32_macro_info(void * info ATTRIBUTE_UNUSED)6579440a403fSchristos nds32_macro_info (void *info ATTRIBUTE_UNUSED)
6580440a403fSchristos {
6581440a403fSchristos }
6582440a403fSchristos 
6583440a403fSchristos /* md_macro_end  */
6584440a403fSchristos 
6585440a403fSchristos void
nds32_macro_end(void)6586440a403fSchristos nds32_macro_end (void)
6587440a403fSchristos {
6588440a403fSchristos }
6589440a403fSchristos 
6590440a403fSchristos /* GAS will call this function with one argument, an expressionS pointer, for
6591440a403fSchristos    any expression that can not be recognized.  When the function is called,
6592440a403fSchristos    input_line_pointer will point to the start of the expression.  */
6593440a403fSchristos 
6594440a403fSchristos void
md_operand(expressionS * expressionP)6595440a403fSchristos md_operand (expressionS *expressionP)
6596440a403fSchristos {
6597440a403fSchristos   if (*input_line_pointer == '#')
6598440a403fSchristos     {
6599440a403fSchristos       input_line_pointer++;
6600440a403fSchristos       expression (expressionP);
6601440a403fSchristos     }
6602440a403fSchristos }
6603440a403fSchristos 
6604440a403fSchristos /* GAS will call this function for each section at the end of the assembly, to
6605440a403fSchristos    permit the CPU back end to adjust the alignment of a section.  The function
6606440a403fSchristos    must take two arguments, a segT for the section and a valueT for the size of
6607440a403fSchristos    the section, and return a valueT for the rounded size.  */
6608440a403fSchristos 
6609440a403fSchristos valueT
md_section_align(segT segment,valueT size)6610440a403fSchristos md_section_align (segT segment, valueT size)
6611440a403fSchristos {
6612*b88e3e88Schristos   int align = bfd_section_alignment (segment);
6613440a403fSchristos 
6614*b88e3e88Schristos   return ((size + (1 << align) - 1) & ((valueT) -1 << align));
6615440a403fSchristos }
6616440a403fSchristos 
6617440a403fSchristos /* GAS will call this function when a symbol table lookup fails, before it
6618440a403fSchristos    creates a new symbol.  Typically this would be used to supply symbols whose
6619440a403fSchristos    name or value changes dynamically, possibly in a context sensitive way.
6620440a403fSchristos    Predefined symbols with fixed values, such as register names or condition
6621440a403fSchristos    codes, are typically entered directly into the symbol table when md_begin
6622440a403fSchristos    is called.  One argument is passed, a char * for the symbol.  */
6623440a403fSchristos 
6624440a403fSchristos symbolS *
md_undefined_symbol(char * name ATTRIBUTE_UNUSED)6625440a403fSchristos md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
6626440a403fSchristos {
6627440a403fSchristos   return NULL;
6628440a403fSchristos }
6629440a403fSchristos 
6630440a403fSchristos 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)6631440a403fSchristos nds32_calc_branch_offset (segT segment, fragS *fragP,
6632440a403fSchristos 			  long stretch ATTRIBUTE_UNUSED,
6633440a403fSchristos 			  relax_info_t *relax_info,
6634440a403fSchristos 			  enum nds32_br_range branch_range_type)
6635440a403fSchristos {
6636440a403fSchristos   struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
6637440a403fSchristos   symbolS *branch_symbol = fragP->fr_symbol;
6638440a403fSchristos   offsetT branch_offset = fragP->fr_offset;
6639440a403fSchristos   offsetT branch_target_address;
6640440a403fSchristos   offsetT branch_insn_address;
6641440a403fSchristos   long offset = 0;
6642440a403fSchristos 
6643440a403fSchristos   if ((S_GET_SEGMENT (branch_symbol) != segment)
6644440a403fSchristos       || S_IS_WEAK (branch_symbol))
6645440a403fSchristos     {
6646440a403fSchristos       /* The symbol is not in the SEGMENT.  It could be far far away.  */
6647440a403fSchristos       offset = 0x80000000;
6648440a403fSchristos     }
6649440a403fSchristos   else
6650440a403fSchristos     {
6651440a403fSchristos       /* Calculate symbol-to-instruction offset.  */
6652440a403fSchristos       branch_target_address = S_GET_VALUE (branch_symbol) + branch_offset;
6653440a403fSchristos       /* If the destination symbol is beyond current frag address,
6654440a403fSchristos 	 STRETCH will take effect to symbol's position.  */
6655440a403fSchristos       if (S_GET_VALUE (branch_symbol) > fragP->fr_address)
6656440a403fSchristos 	branch_target_address += stretch;
6657440a403fSchristos 
6658440a403fSchristos       branch_insn_address = fragP->fr_address + fragP->fr_fix;
6659440a403fSchristos       branch_insn_address -= opcode->isize;
6660440a403fSchristos 
6661440a403fSchristos       /* Update BRANCH_INSN_ADDRESS to relaxed position.  */
6662440a403fSchristos       branch_insn_address += (relax_info->relax_code_size[branch_range_type]
6663440a403fSchristos 			      - relax_info->relax_branch_isize[branch_range_type]);
6664440a403fSchristos 
6665440a403fSchristos       offset = branch_target_address - branch_insn_address;
6666440a403fSchristos     }
6667440a403fSchristos 
6668440a403fSchristos   return offset;
6669440a403fSchristos }
6670440a403fSchristos 
6671440a403fSchristos static enum nds32_br_range
nds32_convert_to_range_type(long offset)6672440a403fSchristos nds32_convert_to_range_type (long offset)
6673440a403fSchristos {
6674440a403fSchristos   enum nds32_br_range range_type;
6675440a403fSchristos 
6676440a403fSchristos   if (-(0x100) <= offset && offset < 0x100) /* 256 bytes */
6677440a403fSchristos     range_type = BR_RANGE_S256;
6678440a403fSchristos   else if (-(0x4000) <= offset && offset < 0x4000) /* 16K bytes */
6679440a403fSchristos     range_type = BR_RANGE_S16K;
6680440a403fSchristos   else if (-(0x10000) <= offset && offset < 0x10000) /* 64K bytes */
6681440a403fSchristos     range_type = BR_RANGE_S64K;
6682440a403fSchristos   else if (-(0x1000000) <= offset && offset < 0x1000000) /* 16M bytes */
6683440a403fSchristos     range_type = BR_RANGE_S16M;
6684440a403fSchristos   else /* 4G bytes */
6685440a403fSchristos     range_type = BR_RANGE_U4G;
6686440a403fSchristos 
6687440a403fSchristos   return range_type;
6688440a403fSchristos }
6689440a403fSchristos 
669006324dcfSchristos /* Set instruction register mask.  */
6691440a403fSchristos 
6692440a403fSchristos static void
nds32_elf_get_set_cond(relax_info_t * relax_info,int offset,uint32_t * insn,uint32_t ori_insn,int range)6693440a403fSchristos nds32_elf_get_set_cond (relax_info_t *relax_info, int offset, uint32_t *insn,
6694440a403fSchristos 			uint32_t ori_insn, int range)
6695440a403fSchristos {
6696440a403fSchristos   nds32_cond_field_t *cond_fields = relax_info->cond_field;
6697440a403fSchristos   nds32_cond_field_t *code_seq_cond = relax_info->relax_code_condition[range];
6698440a403fSchristos   uint32_t mask;
6699440a403fSchristos   int i = 0;
6700440a403fSchristos 
6701440a403fSchristos   /* The instruction has conditions.  Collect condition values.  */
6702440a403fSchristos   while (code_seq_cond[i].bitmask != 0)
6703440a403fSchristos     {
6704440a403fSchristos       if (offset == code_seq_cond[i].offset)
6705440a403fSchristos 	{
6706440a403fSchristos 	  mask = (ori_insn >> cond_fields[i].bitpos) & cond_fields[i].bitmask;
6707440a403fSchristos 	  /* Sign extend.  */
6708440a403fSchristos 	  if (cond_fields[i].signed_extend)
6709440a403fSchristos 	    mask = (mask ^ ((cond_fields[i].bitmask + 1) >> 1)) -
6710440a403fSchristos 	      ((cond_fields[i].bitmask + 1) >> 1);
6711440a403fSchristos 	  *insn |= (mask & code_seq_cond[i].bitmask) << code_seq_cond[i].bitpos;
6712440a403fSchristos 	}
6713440a403fSchristos       i++;
6714440a403fSchristos     }
6715440a403fSchristos }
6716440a403fSchristos 
6717440a403fSchristos static int
nds32_relax_branch_instructions(segT segment,fragS * fragP,long stretch ATTRIBUTE_UNUSED,int init)6718440a403fSchristos nds32_relax_branch_instructions (segT segment, fragS *fragP,
6719440a403fSchristos 				 long stretch ATTRIBUTE_UNUSED,
6720440a403fSchristos 				 int init)
6721440a403fSchristos {
6722440a403fSchristos   enum nds32_br_range branch_range_type;
6723440a403fSchristos   struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
6724440a403fSchristos   long offset = 0;
6725440a403fSchristos   enum nds32_br_range real_range_type;
6726440a403fSchristos   int adjust = 0;
6727440a403fSchristos   relax_info_t *relax_info;
6728440a403fSchristos   int diff = 0;
6729440a403fSchristos   int i, j, k;
6730440a403fSchristos   int code_seq_size;
6731440a403fSchristos   uint32_t *code_seq;
6732440a403fSchristos   uint32_t insn;
6733440a403fSchristos   int insn_size;
6734440a403fSchristos   int code_seq_offset;
6735440a403fSchristos 
6736440a403fSchristos   /* Replace with gas_assert (fragP->fr_symbol != NULL); */
6737440a403fSchristos   if (fragP->fr_symbol == NULL)
6738440a403fSchristos     return adjust;
6739440a403fSchristos 
674006324dcfSchristos   /* If frag_var is not enough room, the previous frag is fr_full and with
6741440a403fSchristos      opcode.  The new one is rs_dependent but without opcode.  */
6742440a403fSchristos   if (opcode == NULL)
6743440a403fSchristos     return adjust;
6744440a403fSchristos 
6745*b88e3e88Schristos   /* Use U4G mode for b and bal in verbatim mode because lto may combine
6746*b88e3e88Schristos      functions into a file.  And order the file in the last when linking.
6747*b88e3e88Schristos      Once there is multiple definition, the same function will be kicked.
6748*b88e3e88Schristos      This may cause relocation truncated error.  */
6749*b88e3e88Schristos   if (verbatim && !nds32_pic
6750*b88e3e88Schristos       && (strcmp (opcode->opcode, "j") == 0
6751*b88e3e88Schristos 	  || strcmp (opcode->opcode, "jal") == 0))
6752*b88e3e88Schristos     {
6753*b88e3e88Schristos       fragP->fr_subtype = BR_RANGE_U4G;
6754*b88e3e88Schristos       if (init)
6755*b88e3e88Schristos 	return 8;
6756*b88e3e88Schristos       else
6757*b88e3e88Schristos 	return 0;
6758*b88e3e88Schristos     }
6759*b88e3e88Schristos 
6760440a403fSchristos   relax_info = hash_find (nds32_relax_info_hash, opcode->opcode);
6761440a403fSchristos 
6762440a403fSchristos   if (relax_info == NULL)
6763440a403fSchristos     return adjust;
6764440a403fSchristos 
6765440a403fSchristos   if (init)
6766*b88e3e88Schristos     {
6767440a403fSchristos       branch_range_type = relax_info->br_range;
6768*b88e3e88Schristos       i = BR_RANGE_S256;
6769*b88e3e88Schristos     }
6770440a403fSchristos   else
6771*b88e3e88Schristos     {
6772440a403fSchristos       branch_range_type = fragP->fr_subtype;
6773*b88e3e88Schristos       i = branch_range_type;
6774*b88e3e88Schristos     }
6775440a403fSchristos 
6776440a403fSchristos   offset = nds32_calc_branch_offset (segment, fragP, stretch,
6777440a403fSchristos 				     relax_info, branch_range_type);
6778440a403fSchristos 
6779440a403fSchristos   real_range_type = nds32_convert_to_range_type (offset);
6780440a403fSchristos 
6781440a403fSchristos   /* If actual range is equal to instruction jump range, do nothing.  */
6782440a403fSchristos   if (real_range_type == branch_range_type)
6783*b88e3e88Schristos     {
6784*b88e3e88Schristos       fragP->fr_subtype = real_range_type;
6785440a403fSchristos       return adjust;
6786*b88e3e88Schristos     }
6787440a403fSchristos 
6788440a403fSchristos   /* Find out proper relaxation code sequence.  */
6789*b88e3e88Schristos   for (; i < BR_RANGE_NUM; i++)
6790440a403fSchristos     {
6791440a403fSchristos       if (real_range_type <= (unsigned int) i)
6792440a403fSchristos 	{
6793440a403fSchristos 	  if (init)
6794440a403fSchristos 	    diff = relax_info->relax_code_size[i] - opcode->isize;
6795*b88e3e88Schristos 	  else if (real_range_type < (unsigned int) i)
6796*b88e3e88Schristos 	    diff = relax_info->relax_code_size[real_range_type]
6797*b88e3e88Schristos 	      - relax_info->relax_code_size[branch_range_type];
6798440a403fSchristos 	  else
6799440a403fSchristos 	    diff = relax_info->relax_code_size[i]
6800440a403fSchristos 	      - relax_info->relax_code_size[branch_range_type];
6801440a403fSchristos 
6802440a403fSchristos 	  /* If the instruction could be converted to 16-bits,
6803440a403fSchristos 	     minus the difference.  */
6804440a403fSchristos 	  code_seq_offset = 0;
6805440a403fSchristos 	  j = 0;
6806440a403fSchristos 	  k = 0;
6807440a403fSchristos 	  code_seq_size = relax_info->relax_code_size[i];
6808440a403fSchristos 	  code_seq = relax_info->relax_code_seq[i];
6809440a403fSchristos 	  while (code_seq_offset < code_seq_size)
6810440a403fSchristos 	    {
6811440a403fSchristos 	      insn = code_seq[j];
6812440a403fSchristos 	      if (insn & 0x80000000) /* 16-bits instruction.  */
6813440a403fSchristos 		{
6814440a403fSchristos 		  insn_size = 2;
6815440a403fSchristos 		}
6816440a403fSchristos 	      else /* 32-bits instruction.  */
6817440a403fSchristos 		{
6818440a403fSchristos 		  insn_size = 4;
6819440a403fSchristos 
6820440a403fSchristos 		  while (relax_info->relax_fixup[i][k].size !=0
6821440a403fSchristos 			 && relax_info->relax_fixup[i][k].offset < code_seq_offset)
6822440a403fSchristos 		    k++;
6823440a403fSchristos 		}
6824440a403fSchristos 
6825440a403fSchristos 	      code_seq_offset += insn_size;
6826440a403fSchristos 	      j++;
6827440a403fSchristos 	    }
6828440a403fSchristos 
6829440a403fSchristos 	  /* Update fr_subtype to new NDS32_BR_RANGE.  */
6830*b88e3e88Schristos 	  fragP->fr_subtype = real_range_type;
6831440a403fSchristos 	  break;
6832440a403fSchristos 	}
6833440a403fSchristos     }
6834440a403fSchristos 
6835440a403fSchristos   return diff + adjust;
6836440a403fSchristos }
6837440a403fSchristos 
6838440a403fSchristos /* Adjust relaxable frag till current frag.  */
6839440a403fSchristos 
6840440a403fSchristos static int
nds32_adjust_relaxable_frag(fragS * startP,fragS * fragP)6841440a403fSchristos nds32_adjust_relaxable_frag (fragS *startP, fragS *fragP)
6842440a403fSchristos {
6843440a403fSchristos   int adj;
6844440a403fSchristos   if (startP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
6845440a403fSchristos     adj = -2;
6846440a403fSchristos   else
6847440a403fSchristos     adj = 2;
6848440a403fSchristos 
6849440a403fSchristos   startP->tc_frag_data.flag ^= NDS32_FRAG_RELAXED;
6850440a403fSchristos 
6851440a403fSchristos   while (startP)
6852440a403fSchristos     {
6853440a403fSchristos       startP = startP->fr_next;
6854440a403fSchristos       if (startP)
6855440a403fSchristos 	{
6856440a403fSchristos 	  startP->fr_address += adj;
6857440a403fSchristos 	  if (startP == fragP)
6858440a403fSchristos 	    break;
6859440a403fSchristos 	}
6860440a403fSchristos     }
6861440a403fSchristos   return adj;
6862440a403fSchristos }
6863440a403fSchristos 
6864440a403fSchristos static addressT
nds32_get_align(addressT address,int align)6865440a403fSchristos nds32_get_align (addressT address, int align)
6866440a403fSchristos {
6867440a403fSchristos   addressT mask, new_address;
6868440a403fSchristos 
6869*b88e3e88Schristos   mask = ~((addressT) (~0) << align);
6870440a403fSchristos   new_address = (address + mask) & (~mask);
6871440a403fSchristos   return (new_address - address);
6872440a403fSchristos }
6873440a403fSchristos 
6874440a403fSchristos /* Check the prev_frag is legal.  */
6875440a403fSchristos static void
invalid_prev_frag(fragS * fragP,fragS ** prev_frag,bfd_boolean relax)6876*b88e3e88Schristos invalid_prev_frag (fragS * fragP, fragS **prev_frag, bfd_boolean relax)
6877440a403fSchristos {
6878440a403fSchristos   addressT address;
6879440a403fSchristos   fragS *frag_start = *prev_frag;
6880440a403fSchristos 
6881*b88e3e88Schristos   if (!frag_start || !relax)
6882440a403fSchristos     return;
6883440a403fSchristos 
6884440a403fSchristos   if (frag_start->last_fr_address >= fragP->last_fr_address)
6885440a403fSchristos     {
6886440a403fSchristos       *prev_frag = NULL;
6887440a403fSchristos       return;
6888440a403fSchristos     }
6889440a403fSchristos 
6890440a403fSchristos   fragS *frag_t = *prev_frag;
6891440a403fSchristos   while (frag_t != fragP)
6892440a403fSchristos     {
6893440a403fSchristos       if (frag_t->fr_type == rs_align
6894440a403fSchristos 	  || frag_t->fr_type == rs_align_code
6895440a403fSchristos 	  || frag_t->fr_type == rs_align_test)
6896440a403fSchristos 	{
689706324dcfSchristos 	  /* Relax instruction can not walk across label.  */
6898440a403fSchristos 	  if (frag_t->tc_frag_data.flag & NDS32_FRAG_LABEL)
6899440a403fSchristos 	    {
6900440a403fSchristos 	      prev_frag = NULL;
6901440a403fSchristos 	      return;
6902440a403fSchristos 	    }
690306324dcfSchristos 	  /* Relax previous relaxable to align rs_align frag.  */
6904440a403fSchristos 	  address = frag_t->fr_address + frag_t->fr_fix;
6905440a403fSchristos 	  addressT offset = nds32_get_align (address, (int) frag_t->fr_offset);
6906440a403fSchristos 	  if (offset & 0x2)
6907440a403fSchristos 	    {
6908440a403fSchristos 	      /* If there is label on the prev_frag, check if it is aligned.  */
6909440a403fSchristos 	      if (!((*prev_frag)->tc_frag_data.flag & NDS32_FRAG_LABEL)
6910440a403fSchristos 		  || (((*prev_frag)->fr_address + (*prev_frag)->fr_fix  - 2 )
6911440a403fSchristos 		      & 0x2) == 0)
6912440a403fSchristos 		nds32_adjust_relaxable_frag (*prev_frag, frag_t);
6913440a403fSchristos 	    }
6914440a403fSchristos 	  *prev_frag = NULL;
6915440a403fSchristos 	  return;
6916440a403fSchristos 	}
6917440a403fSchristos       frag_t = frag_t->fr_next;
6918440a403fSchristos     }
6919440a403fSchristos 
6920440a403fSchristos   if (fragP->tc_frag_data.flag & NDS32_FRAG_ALIGN)
6921440a403fSchristos     {
6922440a403fSchristos       address = fragP->fr_address;
6923440a403fSchristos       addressT offset = nds32_get_align (address, 2);
6924440a403fSchristos       if (offset & 0x2)
6925440a403fSchristos 	{
6926440a403fSchristos 	  /* If there is label on the prev_frag, check if it is aligned.  */
6927440a403fSchristos 	  if (!((*prev_frag)->tc_frag_data.flag & NDS32_FRAG_LABEL)
6928440a403fSchristos 	      || (((*prev_frag)->fr_address + (*prev_frag)->fr_fix  - 2 )
6929440a403fSchristos 		  & 0x2) == 0)
6930440a403fSchristos 	    nds32_adjust_relaxable_frag (*prev_frag, fragP);
6931440a403fSchristos 	}
6932440a403fSchristos       *prev_frag = NULL;
6933440a403fSchristos       return;
6934440a403fSchristos     }
6935440a403fSchristos }
6936440a403fSchristos 
6937440a403fSchristos /* md_relax_frag  */
6938440a403fSchristos 
6939440a403fSchristos int
nds32_relax_frag(segT segment,fragS * fragP,long stretch ATTRIBUTE_UNUSED)6940440a403fSchristos nds32_relax_frag (segT segment, fragS *fragP, long stretch ATTRIBUTE_UNUSED)
6941440a403fSchristos {
6942440a403fSchristos   /* Currently, there are two kinds of relaxation in nds32 assembler.
6943440a403fSchristos      1. relax for branch
6944440a403fSchristos      2. relax for 32-bits to 16-bits  */
6945440a403fSchristos 
6946440a403fSchristos   static fragS *prev_frag = NULL;
6947440a403fSchristos   int adjust = 0;
6948440a403fSchristos 
6949*b88e3e88Schristos   invalid_prev_frag (fragP, &prev_frag, TRUE);
6950440a403fSchristos 
6951440a403fSchristos   if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
6952440a403fSchristos     adjust = nds32_relax_branch_instructions (segment, fragP, stretch, 0);
6953440a403fSchristos   if (fragP->tc_frag_data.flag & NDS32_FRAG_LABEL)
6954440a403fSchristos     prev_frag = NULL;
6955440a403fSchristos   if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE
6956440a403fSchristos       && (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED) == 0)
6957440a403fSchristos     /* Here is considered relaxed case originally.  But it may cause
695806324dcfSchristos        an endless loop when relaxing.  Once the instruction is relaxed,
695906324dcfSchristos        it can not be undone.  */
6960440a403fSchristos     prev_frag = fragP;
6961440a403fSchristos 
6962440a403fSchristos   return adjust;
6963440a403fSchristos }
6964440a403fSchristos 
6965440a403fSchristos /* This function returns an initial guess of the length by which a fragment
6966440a403fSchristos    must grow to hold a branch to reach its destination.  Also updates
6967440a403fSchristos    fr_type/fr_subtype as necessary.
6968440a403fSchristos 
6969440a403fSchristos    It is called just before doing relaxation.  Any symbol that is now undefined
6970440a403fSchristos    will not become defined.  The guess for fr_var is ACTUALLY the growth beyond
6971440a403fSchristos    fr_fix.  Whatever we do to grow fr_fix or fr_var contributes to our returned
6972440a403fSchristos    value.  Although it may not be explicit in the frag, pretend fr_var starts
6973440a403fSchristos    with a 0 value.  */
6974440a403fSchristos 
6975440a403fSchristos int
md_estimate_size_before_relax(fragS * fragP,segT segment)6976440a403fSchristos md_estimate_size_before_relax (fragS *fragP, segT segment)
6977440a403fSchristos {
6978440a403fSchristos   /* Currently, there are two kinds of relaxation in nds32 assembler.
6979440a403fSchristos      1. relax for branch
6980440a403fSchristos      2. relax for 32-bits to 16-bits  */
6981440a403fSchristos 
698206324dcfSchristos   /* Save previous relaxable frag.  */
6983440a403fSchristos   static fragS *prev_frag = NULL;
6984440a403fSchristos   int adjust = 0;
6985440a403fSchristos 
6986*b88e3e88Schristos   invalid_prev_frag (fragP, &prev_frag, FALSE);
6987440a403fSchristos 
6988440a403fSchristos   if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
6989440a403fSchristos     adjust = nds32_relax_branch_instructions (segment, fragP, 0, 1);
6990440a403fSchristos   if (fragP->tc_frag_data.flag & NDS32_FRAG_LABEL)
6991440a403fSchristos     prev_frag = NULL;
6992440a403fSchristos   if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
6993440a403fSchristos     adjust = 2;
6994440a403fSchristos   else if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE)
6995440a403fSchristos     prev_frag = fragP;
6996440a403fSchristos 
6997440a403fSchristos   return adjust;
6998440a403fSchristos }
6999440a403fSchristos 
7000440a403fSchristos /* GAS will call this for each rs_machine_dependent fragment.  The instruction
7001440a403fSchristos    is completed using the data from the relaxation pass.  It may also create any
7002440a403fSchristos    necessary relocations.
7003440a403fSchristos 
7004440a403fSchristos    *FRAGP has been relaxed to its final size, and now needs to have the bytes
7005440a403fSchristos    inside it modified to conform to the new size.  It is called after relaxation
7006440a403fSchristos    is finished.
7007440a403fSchristos 
7008440a403fSchristos    fragP->fr_type == rs_machine_dependent.
7009440a403fSchristos    fragP->fr_subtype is the subtype of what the address relaxed to.  */
7010440a403fSchristos 
7011440a403fSchristos void
md_convert_frag(bfd * abfd ATTRIBUTE_UNUSED,segT sec,fragS * fragP)7012440a403fSchristos md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP)
7013440a403fSchristos {
7014440a403fSchristos   /* Convert branch relaxation instructions.  */
7015440a403fSchristos   symbolS *branch_symbol = fragP->fr_symbol;
7016440a403fSchristos   offsetT branch_offset = fragP->fr_offset;
7017440a403fSchristos   enum nds32_br_range branch_range_type = fragP->fr_subtype;
7018440a403fSchristos   struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
7019440a403fSchristos   uint32_t origin_insn = fragP->tc_frag_data.insn;
7020440a403fSchristos   relax_info_t *relax_info;
7021440a403fSchristos   char *fr_buffer;
7022440a403fSchristos   int fr_where;
7023440a403fSchristos   int addend ATTRIBUTE_UNUSED;
7024440a403fSchristos   offsetT branch_target_address, branch_insn_address;
7025440a403fSchristos   expressionS exp;
7026440a403fSchristos   fixS *fixP;
7027440a403fSchristos   uint32_t *code_seq;
7028440a403fSchristos   uint32_t insn;
7029440a403fSchristos   int code_size, insn_size, offset, fixup_size;
7030440a403fSchristos   int buf_offset, pcrel;
7031440a403fSchristos   int i, k;
7032440a403fSchristos   uint16_t insn_16;
7033440a403fSchristos   nds32_relax_fixup_info_t fixup_info[MAX_RELAX_FIX];
7034440a403fSchristos   /* Save the 1st instruction is converted to 16 bit or not.  */
7035440a403fSchristos   unsigned int branch_size;
7036*b88e3e88Schristos   enum bfd_reloc_code_real final_r_type;
7037440a403fSchristos 
7038440a403fSchristos   /* Replace with gas_assert (branch_symbol != NULL); */
7039440a403fSchristos   if (branch_symbol == NULL && !(fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED))
7040440a403fSchristos     return;
7041440a403fSchristos 
704206324dcfSchristos   /* If frag_var is not enough room, the previous frag is fr_full and with
7043440a403fSchristos      opcode.  The new one is rs_dependent but without opcode.  */
7044440a403fSchristos   if (opcode == NULL)
7045440a403fSchristos     return;
7046440a403fSchristos 
7047440a403fSchristos   if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE_BRANCH)
7048440a403fSchristos     {
7049440a403fSchristos       relax_info = hash_find (nds32_relax_info_hash, opcode->opcode);
7050440a403fSchristos 
7051440a403fSchristos       if (relax_info == NULL)
7052440a403fSchristos 	return;
7053440a403fSchristos 
7054440a403fSchristos       i = BR_RANGE_S256;
7055440a403fSchristos       while (i < BR_RANGE_NUM
7056440a403fSchristos 	     && relax_info->relax_code_size[i]
7057440a403fSchristos 	     != (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED ? 4 : 2))
7058440a403fSchristos 	i++;
7059440a403fSchristos 
7060440a403fSchristos       if (i >= BR_RANGE_NUM)
7061440a403fSchristos 	as_bad ("Internal error: Cannot find relocation of"
7062440a403fSchristos 		"relaxable branch.");
7063440a403fSchristos 
7064440a403fSchristos       exp.X_op = O_symbol;
7065440a403fSchristos       exp.X_add_symbol = branch_symbol;
7066440a403fSchristos       exp.X_add_number = branch_offset;
7067440a403fSchristos       pcrel = ((relax_info->relax_fixup[i][0].ramp & NDS32_PCREL) != 0) ? 1 : 0;
7068440a403fSchristos       fr_where = fragP->fr_fix - 2;
7069440a403fSchristos       fixP = fix_new_exp (fragP, fr_where, relax_info->relax_fixup[i][0].size,
7070440a403fSchristos 			  &exp, pcrel, relax_info->relax_fixup[i][0].r_type);
7071440a403fSchristos       fixP->fx_addnumber = fixP->fx_offset;
7072440a403fSchristos 
7073440a403fSchristos       if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
7074440a403fSchristos 	{
7075440a403fSchristos 	  insn_16 = fragP->tc_frag_data.insn;
7076440a403fSchristos 	  nds32_convert_16_to_32 (stdoutput, insn_16, &insn);
7077440a403fSchristos 	  fr_buffer = fragP->fr_literal + fr_where;
7078440a403fSchristos 	  fragP->fr_fix += 2;
7079440a403fSchristos 	  exp.X_op = O_symbol;
7080440a403fSchristos 	  exp.X_add_symbol = abs_section_sym;
7081440a403fSchristos 	  exp.X_add_number = 0;
7082440a403fSchristos 	  fix_new_exp (fragP, fr_where, 4,
7083440a403fSchristos 		       &exp, 0, BFD_RELOC_NDS32_INSN16);
7084440a403fSchristos 	  number_to_chars_bigendian (fr_buffer, insn, 4);
7085440a403fSchristos 	}
7086440a403fSchristos     }
7087440a403fSchristos   else if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
7088440a403fSchristos     {
7089440a403fSchristos       if (fragP->tc_frag_data.opcode->isize == 2)
7090440a403fSchristos 	{
7091440a403fSchristos 	  insn_16 = fragP->tc_frag_data.insn;
7092440a403fSchristos 	  nds32_convert_16_to_32 (stdoutput, insn_16, &insn);
7093440a403fSchristos 	}
7094440a403fSchristos       else
7095440a403fSchristos 	insn = fragP->tc_frag_data.insn;
7096440a403fSchristos       fragP->fr_fix += 2;
7097440a403fSchristos       fr_where = fragP->fr_fix - 4;
7098440a403fSchristos       fr_buffer = fragP->fr_literal + fr_where;
7099440a403fSchristos       exp.X_op = O_symbol;
7100440a403fSchristos       exp.X_add_symbol = abs_section_sym;
7101440a403fSchristos       exp.X_add_number = 0;
7102440a403fSchristos       fix_new_exp (fragP, fr_where, 4, &exp, 0,
7103440a403fSchristos 		   BFD_RELOC_NDS32_INSN16);
7104440a403fSchristos       number_to_chars_bigendian (fr_buffer, insn, 4);
7105440a403fSchristos     }
7106440a403fSchristos   else if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
7107440a403fSchristos     {
7108440a403fSchristos       /* Branch instruction adjust and append relocations.  */
7109440a403fSchristos       relax_info = hash_find (nds32_relax_info_hash, opcode->opcode);
7110440a403fSchristos 
7111440a403fSchristos       if (relax_info == NULL)
7112440a403fSchristos 	return;
7113440a403fSchristos 
7114440a403fSchristos       fr_where = fragP->fr_fix - opcode->isize;
7115440a403fSchristos       fr_buffer = fragP->fr_literal + fr_where;
7116440a403fSchristos 
7117440a403fSchristos       if ((S_GET_SEGMENT (branch_symbol) != sec)
7118440a403fSchristos 	  || S_IS_WEAK (branch_symbol))
7119440a403fSchristos 	{
7120440a403fSchristos 	  if (fragP->fr_offset & 3)
7121440a403fSchristos 	    as_warn (_("Addend to unresolved symbol is not on word boundary."));
7122440a403fSchristos 	  addend = 0;
7123440a403fSchristos 	}
7124440a403fSchristos       else
7125440a403fSchristos 	{
7126440a403fSchristos 	  /* Calculate symbol-to-instruction offset.  */
7127440a403fSchristos 	  branch_target_address = S_GET_VALUE (branch_symbol) + branch_offset;
7128440a403fSchristos 	  branch_insn_address = fragP->fr_address + fr_where;
7129440a403fSchristos 	  addend = (branch_target_address - branch_insn_address) >> 1;
7130440a403fSchristos 	}
7131440a403fSchristos 
7132440a403fSchristos       code_size = relax_info->relax_code_size[branch_range_type];
7133440a403fSchristos       code_seq = relax_info->relax_code_seq[branch_range_type];
7134440a403fSchristos 
7135440a403fSchristos       memcpy (fixup_info, relax_info->relax_fixup[branch_range_type],
7136440a403fSchristos 	      sizeof (fixup_info));
7137440a403fSchristos 
7138440a403fSchristos       /* Fill in frag.  */
7139440a403fSchristos       i = 0;
7140440a403fSchristos       k = 0;
7141440a403fSchristos       offset = 0; /* code_seq offset */
7142440a403fSchristos       buf_offset = 0; /* fr_buffer offset */
7143440a403fSchristos       while (offset < code_size)
7144440a403fSchristos 	{
7145440a403fSchristos 	  insn = code_seq[i];
7146440a403fSchristos 	  if (insn & 0x80000000) /* 16-bits instruction.  */
7147440a403fSchristos 	    {
7148440a403fSchristos 	      insn = (insn >> 16) & 0xFFFF;
7149440a403fSchristos 	      insn_size = 2;
7150440a403fSchristos 	    }
7151440a403fSchristos 	  else /* 32-bits instruction.  */
7152440a403fSchristos 	    {
7153440a403fSchristos 	      insn_size = 4;
7154440a403fSchristos 	    }
7155440a403fSchristos 
7156440a403fSchristos 	  nds32_elf_get_set_cond (relax_info, offset, &insn,
7157440a403fSchristos 				  origin_insn, branch_range_type);
7158440a403fSchristos 
7159440a403fSchristos 	  /* Try to convert to 16-bits instruction.  Currently, only the first
716006324dcfSchristos 	     instruction in pattern can be converted.  EX: bnez sethi ori jr,
7161440a403fSchristos 	     only bnez can be converted to 16 bit and ori can't.  */
7162440a403fSchristos 
7163440a403fSchristos 	  while (fixup_info[k].size != 0
7164440a403fSchristos 		 && relax_info->relax_fixup[branch_range_type][k].offset < offset)
7165440a403fSchristos 	    k++;
7166440a403fSchristos 
7167440a403fSchristos 	  number_to_chars_bigendian (fr_buffer + buf_offset, insn, insn_size);
7168440a403fSchristos 	  buf_offset += insn_size;
7169440a403fSchristos 
7170440a403fSchristos 	  offset += insn_size;
7171440a403fSchristos 	  i++;
7172440a403fSchristos 	}
7173440a403fSchristos 
7174440a403fSchristos       /* Set up fixup.  */
7175440a403fSchristos       exp.X_op = O_symbol;
7176440a403fSchristos 
7177440a403fSchristos       for (i = 0; fixup_info[i].size != 0; i++)
7178440a403fSchristos 	{
7179440a403fSchristos 	  fixup_size = fixup_info[i].size;
7180440a403fSchristos 	  pcrel = ((fixup_info[i].ramp & NDS32_PCREL) != 0) ? 1 : 0;
7181440a403fSchristos 
7182440a403fSchristos 	  if ((fixup_info[i].ramp & NDS32_CREATE_LABEL) != 0)
7183440a403fSchristos 	    {
7184440a403fSchristos 	      /* This is a reverse branch.  */
7185440a403fSchristos 	      exp.X_add_symbol = symbol_temp_new (sec, 0, fragP->fr_next);
7186440a403fSchristos 	      exp.X_add_number = 0;
7187440a403fSchristos 	    }
7188440a403fSchristos 	  else if ((fixup_info[i].ramp & NDS32_PTR) != 0)
7189440a403fSchristos 	    {
7190440a403fSchristos 	      /* This relocation has to point to another instruction.  */
7191440a403fSchristos 	      branch_size = fr_where + code_size - 4;
7192440a403fSchristos 	      exp.X_add_symbol = symbol_temp_new (sec, branch_size, fragP);
7193440a403fSchristos 	      exp.X_add_number = 0;
7194440a403fSchristos 	    }
7195440a403fSchristos 	  else if ((fixup_info[i].ramp & NDS32_ABS) != 0)
7196440a403fSchristos 	    {
7197440a403fSchristos 	      /* This is a tag relocation.  */
7198440a403fSchristos 	      exp.X_add_symbol = abs_section_sym;
7199440a403fSchristos 	      exp.X_add_number = 0;
7200440a403fSchristos 	    }
7201440a403fSchristos 	  else if ((fixup_info[i].ramp & NDS32_INSN16) != 0)
7202440a403fSchristos 	    {
7203440a403fSchristos 	      if (!enable_16bit)
7204440a403fSchristos 		continue;
7205440a403fSchristos 	      /* This is a tag relocation.  */
7206440a403fSchristos 	      exp.X_add_symbol = abs_section_sym;
7207440a403fSchristos 	      exp.X_add_number = 0;
7208440a403fSchristos 	    }
7209440a403fSchristos 	  else
7210440a403fSchristos 	    {
7211440a403fSchristos 	      exp.X_add_symbol = branch_symbol;
7212440a403fSchristos 	      exp.X_add_number = branch_offset;
7213440a403fSchristos 	    }
7214440a403fSchristos 
7215440a403fSchristos 	  if (fixup_info[i].r_type != 0)
7216440a403fSchristos 	    {
7217*b88e3e88Schristos 	      final_r_type = fixup_info[i].r_type;
7218440a403fSchristos 	      fixP = fix_new_exp (fragP, fr_where + fixup_info[i].offset,
7219440a403fSchristos 				  fixup_size, &exp, pcrel,
7220*b88e3e88Schristos 				  final_r_type);
7221440a403fSchristos 	      fixP->fx_addnumber = fixP->fx_offset;
7222440a403fSchristos 	    }
7223440a403fSchristos 	}
7224440a403fSchristos 
7225440a403fSchristos       fragP->fr_fix = fr_where + buf_offset;
7226440a403fSchristos     }
7227440a403fSchristos }
7228440a403fSchristos 
7229440a403fSchristos /* tc_frob_file_before_fix  */
7230440a403fSchristos 
7231440a403fSchristos void
nds32_frob_file_before_fix(void)7232440a403fSchristos nds32_frob_file_before_fix (void)
7233440a403fSchristos {
7234440a403fSchristos }
7235440a403fSchristos 
7236440a403fSchristos static bfd_boolean
nds32_relaxable_section(asection * sec)7237440a403fSchristos nds32_relaxable_section (asection *sec)
7238440a403fSchristos {
7239440a403fSchristos   return ((sec->flags & SEC_DEBUGGING) == 0
7240440a403fSchristos 	  && strcmp (sec->name, ".eh_frame") != 0);
7241440a403fSchristos }
7242440a403fSchristos 
7243440a403fSchristos /* TC_FORCE_RELOCATION */
7244440a403fSchristos int
nds32_force_relocation(fixS * fix)7245440a403fSchristos nds32_force_relocation (fixS * fix)
7246440a403fSchristos {
7247440a403fSchristos   switch (fix->fx_r_type)
7248440a403fSchristos     {
7249440a403fSchristos     case BFD_RELOC_NDS32_INSN16:
7250440a403fSchristos     case BFD_RELOC_NDS32_LABEL:
7251440a403fSchristos     case BFD_RELOC_NDS32_LONGCALL1:
7252440a403fSchristos     case BFD_RELOC_NDS32_LONGCALL2:
7253440a403fSchristos     case BFD_RELOC_NDS32_LONGCALL3:
7254440a403fSchristos     case BFD_RELOC_NDS32_LONGJUMP1:
7255440a403fSchristos     case BFD_RELOC_NDS32_LONGJUMP2:
7256440a403fSchristos     case BFD_RELOC_NDS32_LONGJUMP3:
7257440a403fSchristos     case BFD_RELOC_NDS32_LOADSTORE:
7258440a403fSchristos     case BFD_RELOC_NDS32_9_FIXED:
7259440a403fSchristos     case BFD_RELOC_NDS32_15_FIXED:
7260440a403fSchristos     case BFD_RELOC_NDS32_17_FIXED:
7261440a403fSchristos     case BFD_RELOC_NDS32_25_FIXED:
7262440a403fSchristos     case BFD_RELOC_NDS32_9_PCREL:
7263440a403fSchristos     case BFD_RELOC_NDS32_15_PCREL:
7264440a403fSchristos     case BFD_RELOC_NDS32_17_PCREL:
7265440a403fSchristos     case BFD_RELOC_NDS32_WORD_9_PCREL:
7266440a403fSchristos     case BFD_RELOC_NDS32_10_UPCREL:
7267440a403fSchristos     case BFD_RELOC_NDS32_25_PCREL:
7268440a403fSchristos     case BFD_RELOC_NDS32_MINUEND:
7269440a403fSchristos     case BFD_RELOC_NDS32_SUBTRAHEND:
7270440a403fSchristos       return 1;
7271440a403fSchristos 
7272440a403fSchristos     case BFD_RELOC_8:
7273440a403fSchristos     case BFD_RELOC_16:
7274440a403fSchristos     case BFD_RELOC_32:
7275440a403fSchristos     case BFD_RELOC_NDS32_DIFF_ULEB128:
7276440a403fSchristos       /* Linker should handle difference between two symbol.  */
7277440a403fSchristos       return fix->fx_subsy != NULL
7278440a403fSchristos 	&& nds32_relaxable_section (S_GET_SEGMENT (fix->fx_addsy));
7279440a403fSchristos     case BFD_RELOC_64:
7280440a403fSchristos       if (fix->fx_subsy)
7281440a403fSchristos 	as_bad ("Double word for difference between two symbols "
7282440a403fSchristos 		"is not supported across relaxation.");
7283440a403fSchristos     default:
7284440a403fSchristos       ;
7285440a403fSchristos     }
7286440a403fSchristos 
7287440a403fSchristos   if (generic_force_reloc (fix))
7288440a403fSchristos     return 1;
7289440a403fSchristos 
7290440a403fSchristos   return fix->fx_pcrel;
7291440a403fSchristos }
7292440a403fSchristos 
7293440a403fSchristos /* TC_VALIDATE_FIX_SUB  */
7294440a403fSchristos 
7295440a403fSchristos int
nds32_validate_fix_sub(fixS * fix,segT add_symbol_segment)7296440a403fSchristos nds32_validate_fix_sub (fixS *fix, segT add_symbol_segment)
7297440a403fSchristos {
7298440a403fSchristos   segT sub_symbol_segment;
7299440a403fSchristos 
7300440a403fSchristos   /* This code is referred from Xtensa.  Check their implementation for
7301440a403fSchristos      details.  */
7302440a403fSchristos 
7303440a403fSchristos   /* Make sure both symbols are in the same segment, and that segment is
7304440a403fSchristos      "normal" and relaxable.  */
7305440a403fSchristos   sub_symbol_segment = S_GET_SEGMENT (fix->fx_subsy);
7306440a403fSchristos   return (sub_symbol_segment == add_symbol_segment
7307440a403fSchristos 	  && add_symbol_segment != undefined_section);
7308440a403fSchristos }
7309440a403fSchristos 
7310440a403fSchristos void
md_number_to_chars(char * buf,valueT val,int n)7311440a403fSchristos md_number_to_chars (char *buf, valueT val, int n)
7312440a403fSchristos {
7313440a403fSchristos   if (target_big_endian)
7314440a403fSchristos     number_to_chars_bigendian (buf, val, n);
7315440a403fSchristos   else
7316440a403fSchristos     number_to_chars_littleendian (buf, val, n);
7317440a403fSchristos }
7318440a403fSchristos 
7319440a403fSchristos /* This function is called to convert an ASCII string into a floating point
7320440a403fSchristos    value in format used by the CPU.  */
7321440a403fSchristos 
7322440a403fSchristos const char *
md_atof(int type,char * litP,int * sizeP)7323440a403fSchristos md_atof (int type, char *litP, int *sizeP)
7324440a403fSchristos {
7325440a403fSchristos   int i;
7326440a403fSchristos   int prec;
7327440a403fSchristos   LITTLENUM_TYPE words[MAX_LITTLENUMS];
7328440a403fSchristos   char *t;
7329440a403fSchristos 
7330440a403fSchristos   switch (type)
7331440a403fSchristos     {
7332440a403fSchristos     case 'f':
7333440a403fSchristos     case 'F':
7334440a403fSchristos     case 's':
7335440a403fSchristos     case 'S':
7336440a403fSchristos       prec = 2;
7337440a403fSchristos       break;
7338440a403fSchristos     case 'd':
7339440a403fSchristos     case 'D':
7340440a403fSchristos     case 'r':
7341440a403fSchristos     case 'R':
7342440a403fSchristos       prec = 4;
7343440a403fSchristos       break;
7344440a403fSchristos     default:
7345440a403fSchristos       *sizeP = 0;
7346440a403fSchristos       return _("Bad call to md_atof()");
7347440a403fSchristos     }
7348440a403fSchristos 
7349440a403fSchristos   t = atof_ieee (input_line_pointer, type, words);
7350440a403fSchristos   if (t)
7351440a403fSchristos     input_line_pointer = t;
7352440a403fSchristos   *sizeP = prec * sizeof (LITTLENUM_TYPE);
7353440a403fSchristos 
7354440a403fSchristos   if (target_big_endian)
7355440a403fSchristos     {
7356440a403fSchristos       for (i = 0; i < prec; i++)
7357440a403fSchristos 	{
7358440a403fSchristos 	  md_number_to_chars (litP, (valueT) words[i],
7359440a403fSchristos 			      sizeof (LITTLENUM_TYPE));
7360440a403fSchristos 	  litP += sizeof (LITTLENUM_TYPE);
7361440a403fSchristos 	}
7362440a403fSchristos     }
7363440a403fSchristos   else
7364440a403fSchristos     {
7365440a403fSchristos       for (i = prec - 1; i >= 0; i--)
7366440a403fSchristos 	{
7367440a403fSchristos 	  md_number_to_chars (litP, (valueT) words[i],
7368440a403fSchristos 			      sizeof (LITTLENUM_TYPE));
7369440a403fSchristos 	  litP += sizeof (LITTLENUM_TYPE);
7370440a403fSchristos 	}
7371440a403fSchristos     }
7372440a403fSchristos 
7373440a403fSchristos   return 0;
7374440a403fSchristos }
7375440a403fSchristos 
7376440a403fSchristos /* md_elf_section_change_hook  */
7377440a403fSchristos 
7378440a403fSchristos void
nds32_elf_section_change_hook(void)7379440a403fSchristos nds32_elf_section_change_hook (void)
7380440a403fSchristos {
7381440a403fSchristos }
7382440a403fSchristos 
7383440a403fSchristos /* md_cleanup  */
7384440a403fSchristos 
7385440a403fSchristos void
nds32_cleanup(void)7386440a403fSchristos nds32_cleanup (void)
7387440a403fSchristos {
7388440a403fSchristos }
7389440a403fSchristos 
7390440a403fSchristos /* This function is used to scan leb128 subtraction expressions,
7391440a403fSchristos    and insert fixups for them.
7392440a403fSchristos 
7393440a403fSchristos       e.g., .leb128  .L1 - .L0
7394440a403fSchristos 
7395440a403fSchristos    These expressions are heavily used in debug information or
7396440a403fSchristos    exception tables.  Because relaxation will change code size,
7397440a403fSchristos    we must resolve them in link time.  */
7398440a403fSchristos 
7399440a403fSchristos static void
nds32_insert_leb128_fixes(bfd * abfd ATTRIBUTE_UNUSED,asection * sec,void * xxx ATTRIBUTE_UNUSED)7400440a403fSchristos nds32_insert_leb128_fixes (bfd *abfd ATTRIBUTE_UNUSED,
7401440a403fSchristos 			   asection *sec, void *xxx ATTRIBUTE_UNUSED)
7402440a403fSchristos {
7403440a403fSchristos   segment_info_type *seginfo = seg_info (sec);
7404440a403fSchristos   struct frag *fragP;
7405440a403fSchristos 
7406440a403fSchristos   subseg_set (sec, 0);
7407440a403fSchristos 
7408440a403fSchristos   for (fragP = seginfo->frchainP->frch_root;
7409440a403fSchristos        fragP; fragP = fragP->fr_next)
7410440a403fSchristos     {
7411440a403fSchristos       expressionS *exp;
7412440a403fSchristos 
7413440a403fSchristos       /* Only unsigned leb128 can be handle.  */
7414440a403fSchristos       if (fragP->fr_type != rs_leb128 || fragP->fr_subtype != 0
7415440a403fSchristos 	  || fragP->fr_symbol == NULL)
7416440a403fSchristos 	continue;
7417440a403fSchristos 
7418440a403fSchristos       exp = symbol_get_value_expression (fragP->fr_symbol);
7419440a403fSchristos 
7420440a403fSchristos       if (exp->X_op != O_subtract)
7421440a403fSchristos 	continue;
7422440a403fSchristos 
7423440a403fSchristos       fix_new_exp (fragP, fragP->fr_fix, 0,
7424440a403fSchristos 		   exp, 0, BFD_RELOC_NDS32_DIFF_ULEB128);
7425440a403fSchristos     }
7426440a403fSchristos }
7427440a403fSchristos 
7428440a403fSchristos static void
nds32_insert_relax_entry(bfd * abfd ATTRIBUTE_UNUSED,asection * sec,void * xxx ATTRIBUTE_UNUSED)7429440a403fSchristos nds32_insert_relax_entry (bfd *abfd ATTRIBUTE_UNUSED, asection *sec,
7430440a403fSchristos 			  void *xxx ATTRIBUTE_UNUSED)
7431440a403fSchristos {
7432440a403fSchristos   segment_info_type *seginfo;
7433440a403fSchristos   fragS *fragP;
7434440a403fSchristos   fixS *fixP;
7435440a403fSchristos   expressionS exp;
7436440a403fSchristos   fixS *fixp;
7437440a403fSchristos 
7438440a403fSchristos   seginfo = seg_info (sec);
7439440a403fSchristos   if (!seginfo || !symbol_rootP || !subseg_text_p (sec) || sec->size == 0)
7440440a403fSchristos     return;
7441*b88e3e88Schristos 
7442440a403fSchristos   for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
7443440a403fSchristos     if (!fixp->fx_done)
7444440a403fSchristos       break;
7445*b88e3e88Schristos 
7446*b88e3e88Schristos   if (!fixp && !verbatim && ict_flag == ICT_NONE)
7447440a403fSchristos     return;
7448440a403fSchristos 
7449440a403fSchristos   subseg_change (sec, 0);
7450440a403fSchristos 
7451440a403fSchristos   /* Set RELAX_ENTRY flags for linker.  */
7452440a403fSchristos   fragP = seginfo->frchainP->frch_root;
7453440a403fSchristos   exp.X_op = O_symbol;
7454*b88e3e88Schristos   exp.X_add_symbol = abs_section_sym;
7455440a403fSchristos   exp.X_add_number = 0;
7456440a403fSchristos   if (!enable_relax_relocs)
7457440a403fSchristos     exp.X_add_number |= R_NDS32_RELAX_ENTRY_DISABLE_RELAX_FLAG;
7458440a403fSchristos   else
7459440a403fSchristos     {
7460440a403fSchristos       /* These flags are only enabled when global relax is enabled.
746106324dcfSchristos 	 Maybe we can check DISABLE_RELAX_FLAG at link-time,
7462440a403fSchristos 	 so we set them anyway.  */
7463440a403fSchristos       if (verbatim)
7464440a403fSchristos 	exp.X_add_number |= R_NDS32_RELAX_ENTRY_VERBATIM_FLAG;
746506324dcfSchristos       if (ict_flag == ICT_SMALL)
746606324dcfSchristos 	exp.X_add_number |= R_NDS32_RELAX_ENTRY_ICT_SMALL;
746706324dcfSchristos       else if (ict_flag == ICT_LARGE)
746806324dcfSchristos 	exp.X_add_number |= R_NDS32_RELAX_ENTRY_ICT_LARGE;
7469440a403fSchristos     }
7470440a403fSchristos   if (optimize)
7471440a403fSchristos     exp.X_add_number |= R_NDS32_RELAX_ENTRY_OPTIMIZE_FLAG;
7472440a403fSchristos   if (optimize_for_space)
7473440a403fSchristos     exp.X_add_number |= R_NDS32_RELAX_ENTRY_OPTIMIZE_FOR_SPACE_FLAG;
7474440a403fSchristos 
7475440a403fSchristos   fixP = fix_new_exp (fragP, 0, 0, &exp, 0, BFD_RELOC_NDS32_RELAX_ENTRY);
7476440a403fSchristos   fixP->fx_no_overflow = 1;
7477440a403fSchristos }
7478440a403fSchristos 
7479440a403fSchristos /* Analysis relax hint and insert suitable relocation pattern.  */
7480440a403fSchristos 
7481440a403fSchristos static void
nds32_elf_analysis_relax_hint(void)7482440a403fSchristos nds32_elf_analysis_relax_hint (void)
7483440a403fSchristos {
7484440a403fSchristos   hash_traverse (nds32_hint_hash, nds32_elf_append_relax_relocs);
7485440a403fSchristos }
7486440a403fSchristos 
7487440a403fSchristos static void
nds32_elf_insert_final_frag(void)7488440a403fSchristos nds32_elf_insert_final_frag (void)
7489440a403fSchristos {
7490440a403fSchristos   struct frchain *frchainP;
7491440a403fSchristos   asection *s;
7492440a403fSchristos   fragS *fragP;
7493440a403fSchristos 
7494440a403fSchristos   if (!optimize)
7495440a403fSchristos     return;
7496440a403fSchristos 
7497440a403fSchristos   for (s = stdoutput->sections; s; s = s->next)
7498440a403fSchristos     {
7499440a403fSchristos       segment_info_type *seginfo = seg_info (s);
7500440a403fSchristos       if (!seginfo)
7501440a403fSchristos 	continue;
7502440a403fSchristos 
7503440a403fSchristos       for (frchainP = seginfo->frchainP; frchainP != NULL;
7504440a403fSchristos 	   frchainP = frchainP->frch_next)
7505440a403fSchristos 	{
7506440a403fSchristos 	  subseg_set (s, frchainP->frch_subseg);
7507440a403fSchristos 
7508440a403fSchristos 	  if (subseg_text_p (now_seg))
7509440a403fSchristos 	    {
7510440a403fSchristos 	      fragP = frag_now;
7511440a403fSchristos 	      frag_var (rs_machine_dependent, 2, /* Max size.  */
7512440a403fSchristos 			0, /* VAR is un-used.  */ 0, NULL, 0, NULL);
7513440a403fSchristos 	      fragP->tc_frag_data.flag |= NDS32_FRAG_FINAL;
7514440a403fSchristos 	    }
7515440a403fSchristos 	}
7516440a403fSchristos     }
7517440a403fSchristos }
7518440a403fSchristos 
7519440a403fSchristos void
md_end(void)7520440a403fSchristos md_end (void)
7521440a403fSchristos {
7522440a403fSchristos   nds32_elf_insert_final_frag ();
7523440a403fSchristos   nds32_elf_analysis_relax_hint ();
7524440a403fSchristos   bfd_map_over_sections (stdoutput, nds32_insert_leb128_fixes, NULL);
7525440a403fSchristos }
7526440a403fSchristos 
7527440a403fSchristos /* Implement md_allow_local_subtract.  */
7528440a403fSchristos 
7529440a403fSchristos bfd_boolean
nds32_allow_local_subtract(expressionS * expr_l ATTRIBUTE_UNUSED,expressionS * expr_r ATTRIBUTE_UNUSED,segT sec ATTRIBUTE_UNUSED)7530440a403fSchristos nds32_allow_local_subtract (expressionS *expr_l ATTRIBUTE_UNUSED,
7531440a403fSchristos 			    expressionS *expr_r ATTRIBUTE_UNUSED,
7532440a403fSchristos 			    segT sec ATTRIBUTE_UNUSED)
7533440a403fSchristos {
7534440a403fSchristos   /* Don't allow any subtraction, because relax may change the code.  */
7535440a403fSchristos   return FALSE;
7536440a403fSchristos }
7537440a403fSchristos 
7538440a403fSchristos /* Sort relocation by address.
7539440a403fSchristos 
7540440a403fSchristos    We didn't use qsort () in stdlib, because quick-sort is not a stable
7541440a403fSchristos    sorting algorithm.  Relocations at the same address (r_offset) must keep
7542440a403fSchristos    their relative order.  For example, RELAX_ENTRY must be the very first
7543440a403fSchristos    relocation entry.
7544440a403fSchristos 
7545440a403fSchristos    Currently, this function implements insertion-sort.  */
7546440a403fSchristos 
7547440a403fSchristos static int
compar_relent(const void * lhs,const void * rhs)7548440a403fSchristos compar_relent (const void *lhs, const void *rhs)
7549440a403fSchristos {
7550440a403fSchristos   const arelent **l = (const arelent **) lhs;
7551440a403fSchristos   const arelent **r = (const arelent **) rhs;
7552440a403fSchristos 
7553440a403fSchristos   if ((*l)->address > (*r)->address)
7554440a403fSchristos     return 1;
7555440a403fSchristos   else if ((*l)->address == (*r)->address)
7556440a403fSchristos     return 0;
7557440a403fSchristos   else
7558440a403fSchristos     return -1;
7559440a403fSchristos }
7560440a403fSchristos 
7561440a403fSchristos /* SET_SECTION_RELOCS ()
7562440a403fSchristos 
7563440a403fSchristos    Although this macro is originally used to set a relocation for each section,
7564440a403fSchristos    we use it to sort relocations in the same section by the address of the
7565440a403fSchristos    relocation.  */
7566440a403fSchristos 
7567440a403fSchristos void
nds32_set_section_relocs(asection * sec ATTRIBUTE_UNUSED,arelent ** relocs,unsigned int n)7568*b88e3e88Schristos nds32_set_section_relocs (asection *sec ATTRIBUTE_UNUSED,
7569*b88e3e88Schristos 			  arelent **relocs, unsigned int n)
7570440a403fSchristos {
7571*b88e3e88Schristos   if (n <= 1)
7572*b88e3e88Schristos     return;
7573*b88e3e88Schristos 
7574*b88e3e88Schristos   nds32_insertion_sort (relocs, n, sizeof (*relocs), compar_relent);
7575440a403fSchristos }
7576440a403fSchristos 
7577440a403fSchristos long
nds32_pcrel_from_section(fixS * fixP,segT sec ATTRIBUTE_UNUSED)7578440a403fSchristos nds32_pcrel_from_section (fixS *fixP, segT sec ATTRIBUTE_UNUSED)
7579440a403fSchristos {
7580440a403fSchristos   if (fixP->fx_addsy == NULL || !S_IS_DEFINED (fixP->fx_addsy)
7581440a403fSchristos       || S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy))
7582440a403fSchristos     {
7583440a403fSchristos       /* Let linker resolve undefined symbols.  */
7584440a403fSchristos       return 0;
7585440a403fSchristos     }
7586440a403fSchristos 
7587440a403fSchristos   return fixP->fx_frag->fr_address + fixP->fx_where;
7588440a403fSchristos }
7589440a403fSchristos 
7590440a403fSchristos /* md_post_relax_hook ()
7591440a403fSchristos    Insert relax entry relocation into sections.  */
7592440a403fSchristos 
7593440a403fSchristos void
nds32_post_relax_hook(void)7594440a403fSchristos nds32_post_relax_hook (void)
7595440a403fSchristos {
7596440a403fSchristos   bfd_map_over_sections (stdoutput, nds32_insert_relax_entry, NULL);
7597440a403fSchristos }
7598440a403fSchristos 
7599440a403fSchristos /* tc_fix_adjustable ()
7600440a403fSchristos 
7601440a403fSchristos    Return whether this symbol (fixup) can be replaced with
7602440a403fSchristos    section symbols.  */
7603440a403fSchristos 
7604440a403fSchristos bfd_boolean
nds32_fix_adjustable(fixS * fixP)7605440a403fSchristos nds32_fix_adjustable (fixS *fixP)
7606440a403fSchristos {
7607440a403fSchristos   switch (fixP->fx_r_type)
7608440a403fSchristos     {
7609440a403fSchristos     case BFD_RELOC_NDS32_WORD_9_PCREL:
7610440a403fSchristos     case BFD_RELOC_NDS32_9_PCREL:
7611440a403fSchristos     case BFD_RELOC_NDS32_15_PCREL:
7612440a403fSchristos     case BFD_RELOC_NDS32_17_PCREL:
7613440a403fSchristos     case BFD_RELOC_NDS32_25_PCREL:
7614440a403fSchristos     case BFD_RELOC_NDS32_HI20:
7615440a403fSchristos     case BFD_RELOC_NDS32_LO12S0:
7616440a403fSchristos     case BFD_RELOC_8:
7617440a403fSchristos     case BFD_RELOC_16:
7618440a403fSchristos     case BFD_RELOC_32:
7619440a403fSchristos     case BFD_RELOC_NDS32_PTR:
7620440a403fSchristos     case BFD_RELOC_NDS32_LONGCALL4:
7621440a403fSchristos     case BFD_RELOC_NDS32_LONGCALL5:
7622440a403fSchristos     case BFD_RELOC_NDS32_LONGCALL6:
7623440a403fSchristos     case BFD_RELOC_NDS32_LONGJUMP4:
7624440a403fSchristos     case BFD_RELOC_NDS32_LONGJUMP5:
7625440a403fSchristos     case BFD_RELOC_NDS32_LONGJUMP6:
7626440a403fSchristos     case BFD_RELOC_NDS32_LONGJUMP7:
7627440a403fSchristos       return 1;
7628440a403fSchristos     default:
7629440a403fSchristos       return 0;
7630440a403fSchristos     }
7631440a403fSchristos }
7632440a403fSchristos 
7633440a403fSchristos /* elf_tc_final_processing  */
7634440a403fSchristos 
7635440a403fSchristos void
elf_nds32_final_processing(void)7636440a403fSchristos elf_nds32_final_processing (void)
7637440a403fSchristos {
7638440a403fSchristos   /* An FPU_COM instruction is found without previous non-FPU_COM
7639440a403fSchristos      instruction.  */
7640440a403fSchristos   if (nds32_fpu_com
7641440a403fSchristos       && !(nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST)))
7642440a403fSchristos     {
7643440a403fSchristos       /* Since only FPU_COM instructions are used and no other FPU instructions
7644440a403fSchristos 	 are used.  The nds32_elf_flags will be decided by the enabled options
7645440a403fSchristos 	 by command line or default configuration.  */
7646440a403fSchristos       if (nds32_fpu_dp_ext || nds32_fpu_sp_ext)
7647440a403fSchristos 	{
7648440a403fSchristos 	  nds32_elf_flags |= nds32_fpu_dp_ext ? E_NDS32_HAS_FPU_DP_INST : 0;
7649440a403fSchristos 	  nds32_elf_flags |= nds32_fpu_sp_ext ? E_NDS32_HAS_FPU_INST : 0;
7650440a403fSchristos 	}
7651440a403fSchristos       else
7652440a403fSchristos 	{
7653440a403fSchristos 	  /* Should never here.  */
7654440a403fSchristos 	  as_bad (_("Used FPU instructions requires enabling FPU extension"));
7655440a403fSchristos 	}
7656440a403fSchristos     }
7657440a403fSchristos 
7658440a403fSchristos   if (nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST))
7659440a403fSchristos     {
7660440a403fSchristos       /* Single/double FPU has been used, set FPU register config.  */
7661440a403fSchristos       /* We did not check the actual number of register used.  We may
7662440a403fSchristos 	 want to do it while assemble.  */
7663440a403fSchristos       nds32_elf_flags &= ~E_NDS32_FPU_REG_CONF;
7664440a403fSchristos       nds32_elf_flags |= (nds32_freg << E_NDS32_FPU_REG_CONF_SHIFT);
7665440a403fSchristos     }
7666440a403fSchristos 
7667440a403fSchristos   if (nds32_pic)
7668440a403fSchristos     nds32_elf_flags |= E_NDS32_HAS_PIC;
7669440a403fSchristos 
7670440a403fSchristos   if (nds32_gpr16)
7671440a403fSchristos     nds32_elf_flags |= E_NDS32_HAS_REDUCED_REGS;
7672440a403fSchristos 
7673440a403fSchristos   nds32_elf_flags |= (E_NDS32_ELF_VER_1_4 | nds32_abi);
7674440a403fSchristos   elf_elfheader (stdoutput)->e_flags |= nds32_elf_flags;
7675440a403fSchristos }
7676440a403fSchristos 
767706324dcfSchristos /* Implement md_apply_fix.  Apply the fix-up or transform the fix-up for
7678440a403fSchristos    later relocation generation.  */
7679440a403fSchristos 
7680440a403fSchristos void
nds32_apply_fix(fixS * fixP,valueT * valP,segT seg ATTRIBUTE_UNUSED)7681440a403fSchristos nds32_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
7682440a403fSchristos {
7683440a403fSchristos   char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
7684440a403fSchristos   bfd_vma value = *valP;
7685440a403fSchristos 
7686440a403fSchristos   if (fixP->fx_r_type < BFD_RELOC_UNUSED
7687440a403fSchristos       && fixP->fx_r_type > BFD_RELOC_NONE
7688440a403fSchristos       && fixP->fx_r_type != BFD_RELOC_NDS32_DIFF_ULEB128)
7689440a403fSchristos     {
7690440a403fSchristos       /* In our old nds32 binutils, it must convert relocations which is
7691440a403fSchristos 	 generated by CGEN.  However, it does not have to consider this anymore.
7692440a403fSchristos 	 In current, it only deal with data relocations which enum
7693440a403fSchristos 	 is smaller than BFD_RELOC_NONE and BFD_RELOC_NDS32_DIFF_ULEB128.
7694440a403fSchristos 	 It is believed that we can construct a better mechanism to
7695440a403fSchristos 	 deal with the whole relocation issue in nds32 target
7696440a403fSchristos 	 without using CGEN.  */
7697440a403fSchristos       fixP->fx_addnumber = value;
7698440a403fSchristos       fixP->tc_fix_data = NULL;
7699440a403fSchristos 
770006324dcfSchristos       /* Transform specific relocations here for later relocation generation.
7701*b88e3e88Schristos 	 Tag tls data for linker.  */
7702440a403fSchristos       switch (fixP->fx_r_type)
7703440a403fSchristos 	{
7704440a403fSchristos 	case BFD_RELOC_NDS32_DATA:
7705*b88e3e88Schristos 	  /* This reloc is obselete, we do not need it so far.  */
7706440a403fSchristos 	  fixP->fx_done = 1;
7707440a403fSchristos 	  break;
7708440a403fSchristos 	case BFD_RELOC_NDS32_TPOFF:
7709440a403fSchristos 	case BFD_RELOC_NDS32_TLS_LE_HI20:
7710440a403fSchristos 	case BFD_RELOC_NDS32_TLS_LE_LO12:
7711440a403fSchristos 	case BFD_RELOC_NDS32_TLS_LE_ADD:
7712440a403fSchristos 	case BFD_RELOC_NDS32_TLS_LE_LS:
7713440a403fSchristos 	case BFD_RELOC_NDS32_GOTTPOFF:
7714440a403fSchristos 	case BFD_RELOC_NDS32_TLS_IE_HI20:
7715440a403fSchristos 	case BFD_RELOC_NDS32_TLS_IE_LO12S2:
7716*b88e3e88Schristos 	case BFD_RELOC_NDS32_TLS_DESC_HI20:
7717*b88e3e88Schristos 	case BFD_RELOC_NDS32_TLS_DESC_LO12:
7718*b88e3e88Schristos 	case BFD_RELOC_NDS32_TLS_IE_LO12:
7719*b88e3e88Schristos 	case BFD_RELOC_NDS32_TLS_IEGP_HI20:
7720*b88e3e88Schristos 	case BFD_RELOC_NDS32_TLS_IEGP_LO12:
7721*b88e3e88Schristos 	case BFD_RELOC_NDS32_TLS_IEGP_LO12S2:
7722440a403fSchristos 	  S_SET_THREAD_LOCAL (fixP->fx_addsy);
7723440a403fSchristos 	  break;
7724440a403fSchristos 	default:
7725440a403fSchristos 	  break;
7726440a403fSchristos 	}
7727440a403fSchristos       return;
7728440a403fSchristos     }
7729440a403fSchristos 
7730440a403fSchristos   if (fixP->fx_addsy == (symbolS *) NULL)
7731440a403fSchristos     fixP->fx_done = 1;
7732440a403fSchristos 
7733440a403fSchristos   if (fixP->fx_subsy != (symbolS *) NULL)
7734440a403fSchristos     {
7735440a403fSchristos       /* HOW DIFF RELOCATION WORKS.
7736440a403fSchristos 
7737440a403fSchristos 	 First of all, this relocation is used to calculate the distance
7738440a403fSchristos 	 between two symbols in the SAME section.  It is used for  jump-
7739440a403fSchristos 	 table, debug information, exception table, et al.    Therefore,
7740440a403fSchristos 	 it is a unsigned positive value.   It is NOT used for  general-
7741440a403fSchristos 	 purpose arithmetic.
7742440a403fSchristos 
7743440a403fSchristos 	 Consider this example,  the distance between  .LEND and .LBEGIN
7744440a403fSchristos 	 is stored at the address of foo.
7745440a403fSchristos 
7746440a403fSchristos 	 ---- >8 ---- >8 ---- >8 ---- >8 ----
7747440a403fSchristos 	  .data
7748440a403fSchristos 	  foo:
7749440a403fSchristos 	    .word	.LBEGIN - .LEND
7750440a403fSchristos 
7751440a403fSchristos 	  .text
7752440a403fSchristos 	     [before]
7753440a403fSchristos 	  .LBEGIN
7754440a403fSchristos 			 \
7755440a403fSchristos 	     [between]    distance
7756440a403fSchristos 			 /
7757440a403fSchristos 	  .LEND
7758440a403fSchristos 	     [after]
7759440a403fSchristos 	 ---- 8< ---- 8< ---- 8< ---- 8< ----
7760440a403fSchristos 
7761440a403fSchristos 	 We use a single relocation entry for this expression.
776206324dcfSchristos 	 * The initial distance value is stored directly in that location
7763440a403fSchristos 	   specified by r_offset (i.e., foo in this example.)
7764440a403fSchristos 	 * The begin of the region, i.e., .LBEGIN, is specified by
7765440a403fSchristos 	   r_info/R_SYM and r_addend, e.g., .text + 0x32.
7766440a403fSchristos 	 * The end of region, i.e., .LEND, is represented by
7767440a403fSchristos 	   .LBEGIN + distance instead of .LEND, so we only need
7768440a403fSchristos 	   a single relocation entry instead of two.
7769440a403fSchristos 
7770440a403fSchristos 	 When an instruction is relaxed, we adjust the relocation entry
7771440a403fSchristos 	 depending on where the instruction locates.    There are three
7772440a403fSchristos 	 cases, before, after and between the region.
7773440a403fSchristos 	 * between: Distance value is read from r_offset,  adjusted and
7774440a403fSchristos 	   written back into r_offset.
7775440a403fSchristos 	 * before: Only r_addend is adjust.
7776440a403fSchristos 	 * after: We don't care about it.
7777440a403fSchristos 
7778440a403fSchristos 	 Hereby, there are some limitation.
7779440a403fSchristos 
7780440a403fSchristos 	 `(.LEND - 1) - .LBEGIN' and `(.LEND - .LBEGIN) - 1'
7781440a403fSchristos 	 are semantically different, and we cannot handle latter case
7782440a403fSchristos 	 when relaxation.
7783440a403fSchristos 
7784440a403fSchristos 	 The latter expression means subtracting 1 from the distance
7785440a403fSchristos 	 between .LEND and .LBEGIN.  And the former expression means
7786440a403fSchristos 	 the distance between (.LEND - 1) and .LBEGIN.
7787440a403fSchristos 
7788440a403fSchristos 	 The nuance affects whether to adjust distance value when relax
7789440a403fSchristos 	 an instruction.  In another words, whether the instruction
7790440a403fSchristos 	 locates in the region.  Because we use a single relocation entry,
7791440a403fSchristos 	 there is no field left for .LEND and the subtrahend.
7792440a403fSchristos 
7793440a403fSchristos 	 Since GCC-4.5, GCC may produce debug information in such expression
7794440a403fSchristos 	     .long  .L1-1-.L0
7795440a403fSchristos 	 in order to describe register clobbering during an function-call.
7796440a403fSchristos 	     .L0:
7797440a403fSchristos 		call foo
7798440a403fSchristos 	     .L1:
7799440a403fSchristos 
7800440a403fSchristos 	 Check http://gcc.gnu.org/ml/gcc-patches/2009-06/msg01317.html
7801440a403fSchristos 	 for details.  */
7802440a403fSchristos 
7803440a403fSchristos       value -= S_GET_VALUE (fixP->fx_subsy);
7804440a403fSchristos       *valP = value;
7805440a403fSchristos       fixP->fx_subsy = NULL;
7806440a403fSchristos       fixP->fx_offset -= value;
7807440a403fSchristos 
7808440a403fSchristos       switch (fixP->fx_r_type)
7809440a403fSchristos 	{
7810440a403fSchristos 	case BFD_RELOC_8:
7811440a403fSchristos 	  fixP->fx_r_type = BFD_RELOC_NDS32_DIFF8;
7812440a403fSchristos 	  md_number_to_chars (where, value, 1);
7813440a403fSchristos 	  break;
7814440a403fSchristos 	case BFD_RELOC_16:
7815440a403fSchristos 	  fixP->fx_r_type = BFD_RELOC_NDS32_DIFF16;
7816440a403fSchristos 	  md_number_to_chars (where, value, 2);
7817440a403fSchristos 	  break;
7818440a403fSchristos 	case BFD_RELOC_32:
7819440a403fSchristos 	  fixP->fx_r_type = BFD_RELOC_NDS32_DIFF32;
7820440a403fSchristos 	  md_number_to_chars (where, value, 4);
7821440a403fSchristos 	  break;
7822440a403fSchristos 	case BFD_RELOC_NDS32_DIFF_ULEB128:
7823440a403fSchristos 	  /* cvt_frag_to_fill () has called output_leb128 () for us.  */
7824440a403fSchristos 	  break;
7825440a403fSchristos 	default:
7826440a403fSchristos 	  as_bad_where (fixP->fx_file, fixP->fx_line,
7827440a403fSchristos 			_("expression too complex"));
7828440a403fSchristos 	  return;
7829440a403fSchristos 	}
7830440a403fSchristos     }
7831440a403fSchristos   else if (fixP->fx_done)
7832440a403fSchristos     {
7833440a403fSchristos       /* We're finished with this fixup.  Install it because
7834440a403fSchristos 	 bfd_install_relocation won't be called to do it.  */
7835440a403fSchristos       switch (fixP->fx_r_type)
7836440a403fSchristos 	{
7837440a403fSchristos 	case BFD_RELOC_8:
7838440a403fSchristos 	  md_number_to_chars (where, value, 1);
7839440a403fSchristos 	  break;
7840440a403fSchristos 	case BFD_RELOC_16:
7841440a403fSchristos 	  md_number_to_chars (where, value, 2);
7842440a403fSchristos 	  break;
7843440a403fSchristos 	case BFD_RELOC_32:
7844440a403fSchristos 	  md_number_to_chars (where, value, 4);
7845440a403fSchristos 	  break;
7846440a403fSchristos 	case BFD_RELOC_64:
7847440a403fSchristos 	  md_number_to_chars (where, value, 8);
784806324dcfSchristos 	  break;
7849440a403fSchristos 	default:
7850440a403fSchristos 	  as_bad_where (fixP->fx_file, fixP->fx_line,
7851440a403fSchristos 			_("Internal error: Unknown fixup type %d (`%s')"),
7852440a403fSchristos 			fixP->fx_r_type,
7853440a403fSchristos 			bfd_get_reloc_code_name (fixP->fx_r_type));
7854440a403fSchristos 	  break;
7855440a403fSchristos 	}
7856440a403fSchristos     }
7857440a403fSchristos }
7858440a403fSchristos 
7859440a403fSchristos /* Implement tc_gen_reloc.  Generate ELF relocation for a fix-up.  */
7860440a403fSchristos 
7861440a403fSchristos arelent *
tc_gen_reloc(asection * section ATTRIBUTE_UNUSED,fixS * fixP)7862440a403fSchristos tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
7863440a403fSchristos {
7864440a403fSchristos   arelent *reloc;
7865440a403fSchristos   bfd_reloc_code_real_type code;
7866440a403fSchristos 
7867440a403fSchristos   reloc = XNEW (arelent);
7868440a403fSchristos 
7869440a403fSchristos   reloc->sym_ptr_ptr = XNEW (asymbol *);
7870440a403fSchristos   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
7871440a403fSchristos   reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
7872440a403fSchristos 
7873440a403fSchristos   code = fixP->fx_r_type;
7874440a403fSchristos 
7875440a403fSchristos   reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
7876440a403fSchristos   if (reloc->howto == (reloc_howto_type *) NULL)
7877440a403fSchristos     {
7878440a403fSchristos       as_bad_where (fixP->fx_file, fixP->fx_line,
7879440a403fSchristos 		    _("internal error: can't export reloc type %d (`%s')"),
7880440a403fSchristos 		    fixP->fx_r_type, bfd_get_reloc_code_name (code));
7881440a403fSchristos       return NULL;
7882440a403fSchristos     }
7883440a403fSchristos 
7884440a403fSchristos   /* Add relocation handling here.  */
7885440a403fSchristos 
7886440a403fSchristos   switch (fixP->fx_r_type)
7887440a403fSchristos     {
7888440a403fSchristos     default:
7889440a403fSchristos       /* In general, addend of a relocation is the offset to the
7890440a403fSchristos 	 associated symbol.  */
7891440a403fSchristos       reloc->addend = fixP->fx_offset;
7892440a403fSchristos       break;
7893440a403fSchristos 
7894440a403fSchristos     case BFD_RELOC_NDS32_DATA:
7895440a403fSchristos       /* Prevent linker from optimizing data in text sections.
7896440a403fSchristos 	 For example, jump table.  */
7897440a403fSchristos       reloc->addend = fixP->fx_size;
7898440a403fSchristos       break;
7899440a403fSchristos     }
7900440a403fSchristos 
7901440a403fSchristos   return reloc;
7902440a403fSchristos }
7903440a403fSchristos 
7904*b88e3e88Schristos static struct suffix_name suffix_table[] =
7905440a403fSchristos {
7906*b88e3e88Schristos   {"GOTOFF",	BFD_RELOC_NDS32_GOTOFF},
7907*b88e3e88Schristos   {"GOT",	BFD_RELOC_NDS32_GOT20},
7908*b88e3e88Schristos   {"TPOFF",	BFD_RELOC_NDS32_TPOFF},
7909*b88e3e88Schristos   {"PLT",	BFD_RELOC_NDS32_25_PLTREL},
7910*b88e3e88Schristos   {"GOTTPOFF",	BFD_RELOC_NDS32_GOTTPOFF},
7911*b88e3e88Schristos   {"TLSDESC",  BFD_RELOC_NDS32_TLS_DESC},
7912440a403fSchristos };
7913440a403fSchristos 
7914440a403fSchristos /* Implement md_parse_name.  */
7915440a403fSchristos 
7916440a403fSchristos int
nds32_parse_name(char const * name,expressionS * exprP,enum expr_mode mode ATTRIBUTE_UNUSED,char * nextcharP ATTRIBUTE_UNUSED)7917440a403fSchristos nds32_parse_name (char const *name, expressionS *exprP,
7918440a403fSchristos 		  enum expr_mode mode ATTRIBUTE_UNUSED,
7919440a403fSchristos 		  char *nextcharP ATTRIBUTE_UNUSED)
7920440a403fSchristos {
7921440a403fSchristos   segT segment;
7922440a403fSchristos 
7923440a403fSchristos   exprP->X_op_symbol = NULL;
7924440a403fSchristos   exprP->X_md = BFD_RELOC_UNUSED;
7925440a403fSchristos 
7926440a403fSchristos   exprP->X_add_symbol = symbol_find_or_make (name);
7927440a403fSchristos   exprP->X_op = O_symbol;
7928440a403fSchristos   exprP->X_add_number = 0;
7929440a403fSchristos 
793006324dcfSchristos   /* Check the special name if a symbol.  */
7931440a403fSchristos   segment = S_GET_SEGMENT (exprP->X_add_symbol);
7932*b88e3e88Schristos   if ((segment != undefined_section) && (*nextcharP != '@'))
7933440a403fSchristos     return 0;
7934440a403fSchristos 
7935440a403fSchristos   if (strcmp (name, GOT_NAME) == 0 && *nextcharP != '@')
7936440a403fSchristos     {
7937440a403fSchristos       /* Set for _GOT_OFFSET_TABLE_.  */
7938440a403fSchristos       exprP->X_md = BFD_RELOC_NDS32_GOTPC20;
7939440a403fSchristos     }
7940440a403fSchristos   else if (*nextcharP == '@')
7941440a403fSchristos     {
7942440a403fSchristos       size_t i;
7943440a403fSchristos       char *next;
7944440a403fSchristos       for (i = 0; i < ARRAY_SIZE (suffix_table); i++)
7945440a403fSchristos 	{
7946440a403fSchristos 	  next = input_line_pointer + 1 + strlen (suffix_table[i].suffix);
7947440a403fSchristos 	  if (strncasecmp (input_line_pointer + 1, suffix_table[i].suffix,
7948440a403fSchristos 			   strlen (suffix_table[i].suffix)) == 0
7949440a403fSchristos 	      && !is_part_of_name (*next))
7950440a403fSchristos 	    {
7951440a403fSchristos 	      exprP->X_md = suffix_table[i].reloc;
7952440a403fSchristos 	      *input_line_pointer = *nextcharP;
7953440a403fSchristos 	      input_line_pointer = next;
7954440a403fSchristos 	      *nextcharP = *input_line_pointer;
7955440a403fSchristos 	      *input_line_pointer = '\0';
7956440a403fSchristos 	      break;
7957440a403fSchristos 	    }
7958440a403fSchristos 	}
7959440a403fSchristos     }
7960*b88e3e88Schristos 
7961440a403fSchristos   return 1;
7962440a403fSchristos }
7963440a403fSchristos 
7964440a403fSchristos /* Implement tc_regname_to_dw2regnum.  */
7965440a403fSchristos 
7966440a403fSchristos int
tc_nds32_regname_to_dw2regnum(char * regname)7967440a403fSchristos tc_nds32_regname_to_dw2regnum (char *regname)
7968440a403fSchristos {
7969440a403fSchristos   struct nds32_keyword *sym = hash_find (nds32_gprs_hash, regname);
7970440a403fSchristos 
7971440a403fSchristos   if (!sym)
7972440a403fSchristos     return -1;
7973440a403fSchristos 
7974440a403fSchristos   return sym->value;
7975440a403fSchristos }
7976440a403fSchristos 
7977440a403fSchristos void
tc_nds32_frame_initial_instructions(void)7978440a403fSchristos tc_nds32_frame_initial_instructions (void)
7979440a403fSchristos {
7980440a403fSchristos   /* CIE */
7981440a403fSchristos   /* Default cfa is register-31/sp.  */
7982440a403fSchristos   cfi_add_CFA_def_cfa (31, 0);
7983440a403fSchristos }
7984