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