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