tc-arc.c revision 1.1.1.3.2.2 1 1.1 skrll /* tc-arc.c -- Assembler for the ARC
2 1.1.1.3.2.2 pgoyette Copyright (C) 1994-2016 Free Software Foundation, Inc.
3 1.1.1.3 christos
4 1.1.1.3 christos Contributor: Claudiu Zissulescu <claziss (at) synopsys.com>
5 1.1 skrll
6 1.1 skrll This file is part of GAS, the GNU Assembler.
7 1.1 skrll
8 1.1 skrll GAS is free software; you can redistribute it and/or modify
9 1.1 skrll it under the terms of the GNU General Public License as published by
10 1.1 skrll the Free Software Foundation; either version 3, or (at your option)
11 1.1 skrll any later version.
12 1.1 skrll
13 1.1 skrll GAS is distributed in the hope that it will be useful,
14 1.1 skrll but WITHOUT ANY WARRANTY; without even the implied warranty of
15 1.1 skrll MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 1.1 skrll GNU General Public License for more details.
17 1.1 skrll
18 1.1 skrll You should have received a copy of the GNU General Public License
19 1.1 skrll along with GAS; see the file COPYING. If not, write to the Free
20 1.1 skrll Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
21 1.1 skrll 02110-1301, USA. */
22 1.1 skrll
23 1.1 skrll #include "as.h"
24 1.1.1.3 christos #include "subsegs.h"
25 1.1 skrll #include "struc-symbol.h"
26 1.1.1.3 christos #include "dwarf2dbg.h"
27 1.1.1.3.2.2 pgoyette #include "dw2gencfi.h"
28 1.1 skrll #include "safe-ctype.h"
29 1.1.1.3 christos
30 1.1 skrll #include "opcode/arc.h"
31 1.1 skrll #include "elf/arc.h"
32 1.1.1.3.2.2 pgoyette #include "../opcodes/arc-ext.h"
33 1.1 skrll
34 1.1.1.3 christos /* Defines section. */
35 1.1 skrll
36 1.1.1.3 christos #define MAX_INSN_FIXUPS 2
37 1.1.1.3 christos #define MAX_CONSTR_STR 20
38 1.1.1.3.2.2 pgoyette #define FRAG_MAX_GROWTH 8
39 1.1.1.3 christos
40 1.1.1.3 christos #ifdef DEBUG
41 1.1.1.3 christos # define pr_debug(fmt, args...) fprintf (stderr, fmt, ##args)
42 1.1.1.3 christos #else
43 1.1.1.3 christos # define pr_debug(fmt, args...)
44 1.1.1.3 christos #endif
45 1.1.1.3 christos
46 1.1.1.3 christos #define MAJOR_OPCODE(x) (((x) & 0xF8000000) >> 27)
47 1.1.1.3 christos #define SUB_OPCODE(x) (((x) & 0x003F0000) >> 16)
48 1.1.1.3.2.2 pgoyette #define LP_INSN(x) ((MAJOR_OPCODE (x) == 0x4) && \
49 1.1.1.3 christos (SUB_OPCODE (x) == 0x28))
50 1.1.1.3 christos
51 1.1.1.3 christos /* Equal to MAX_PRECISION in atof-ieee.c. */
52 1.1.1.3 christos #define MAX_LITTLENUMS 6
53 1.1.1.3 christos
54 1.1.1.3.2.2 pgoyette #ifndef TARGET_WITH_CPU
55 1.1.1.3.2.2 pgoyette #define TARGET_WITH_CPU "arc700"
56 1.1.1.3.2.2 pgoyette #endif /* TARGET_WITH_CPU */
57 1.1.1.3.2.2 pgoyette
58 1.1.1.3.2.2 pgoyette /* Enum used to enumerate the relaxable ins operands. */
59 1.1.1.3.2.2 pgoyette enum rlx_operand_type
60 1.1.1.3.2.2 pgoyette {
61 1.1.1.3.2.2 pgoyette EMPTY = 0,
62 1.1.1.3.2.2 pgoyette REGISTER,
63 1.1.1.3.2.2 pgoyette REGISTER_S, /* Register for short instruction(s). */
64 1.1.1.3.2.2 pgoyette REGISTER_NO_GP, /* Is a register but not gp register specifically. */
65 1.1.1.3.2.2 pgoyette REGISTER_DUP, /* Duplication of previous operand of type register. */
66 1.1.1.3.2.2 pgoyette IMMEDIATE,
67 1.1.1.3.2.2 pgoyette BRACKET
68 1.1.1.3.2.2 pgoyette };
69 1.1.1.3.2.2 pgoyette
70 1.1.1.3.2.2 pgoyette enum arc_rlx_types
71 1.1.1.3.2.2 pgoyette {
72 1.1.1.3.2.2 pgoyette ARC_RLX_NONE = 0,
73 1.1.1.3.2.2 pgoyette ARC_RLX_BL_S,
74 1.1.1.3.2.2 pgoyette ARC_RLX_BL,
75 1.1.1.3.2.2 pgoyette ARC_RLX_B_S,
76 1.1.1.3.2.2 pgoyette ARC_RLX_B,
77 1.1.1.3.2.2 pgoyette ARC_RLX_ADD_U3,
78 1.1.1.3.2.2 pgoyette ARC_RLX_ADD_U6,
79 1.1.1.3.2.2 pgoyette ARC_RLX_ADD_LIMM,
80 1.1.1.3.2.2 pgoyette ARC_RLX_LD_U7,
81 1.1.1.3.2.2 pgoyette ARC_RLX_LD_S9,
82 1.1.1.3.2.2 pgoyette ARC_RLX_LD_LIMM,
83 1.1.1.3.2.2 pgoyette ARC_RLX_MOV_U8,
84 1.1.1.3.2.2 pgoyette ARC_RLX_MOV_S12,
85 1.1.1.3.2.2 pgoyette ARC_RLX_MOV_LIMM,
86 1.1.1.3.2.2 pgoyette ARC_RLX_SUB_U3,
87 1.1.1.3.2.2 pgoyette ARC_RLX_SUB_U6,
88 1.1.1.3.2.2 pgoyette ARC_RLX_SUB_LIMM,
89 1.1.1.3.2.2 pgoyette ARC_RLX_MPY_U6,
90 1.1.1.3.2.2 pgoyette ARC_RLX_MPY_LIMM,
91 1.1.1.3.2.2 pgoyette ARC_RLX_MOV_RU6,
92 1.1.1.3.2.2 pgoyette ARC_RLX_MOV_RLIMM,
93 1.1.1.3.2.2 pgoyette ARC_RLX_ADD_RRU6,
94 1.1.1.3.2.2 pgoyette ARC_RLX_ADD_RRLIMM,
95 1.1.1.3.2.2 pgoyette };
96 1.1.1.3.2.2 pgoyette
97 1.1.1.3 christos /* Macros section. */
98 1.1.1.3 christos
99 1.1.1.3 christos #define regno(x) ((x) & 0x3F)
100 1.1.1.3 christos #define is_ir_num(x) (((x) & ~0x3F) == 0)
101 1.1.1.3.2.2 pgoyette #define is_code_density_p(sc) (((sc) == CD1 || (sc) == CD2))
102 1.1.1.3.2.2 pgoyette #define is_spfp_p(op) (((sc) == SPX))
103 1.1.1.3.2.2 pgoyette #define is_dpfp_p(op) (((sc) == DPX))
104 1.1.1.3.2.2 pgoyette #define is_fpuda_p(op) (((sc) == DPA))
105 1.1.1.3.2.2 pgoyette #define is_br_jmp_insn_p(op) (((op)->insn_class == BRANCH || (op)->insn_class == JUMP))
106 1.1.1.3.2.2 pgoyette #define is_kernel_insn_p(op) (((op)->insn_class == KERNEL))
107 1.1.1.3.2.2 pgoyette #define is_nps400_p(op) (((sc) == NPS400))
108 1.1 skrll
109 1.1.1.3 christos /* Generic assembler global variables which must be defined by all
110 1.1.1.3 christos targets. */
111 1.1 skrll
112 1.1.1.3 christos /* Characters which always start a comment. */
113 1.1 skrll const char comment_chars[] = "#;";
114 1.1 skrll
115 1.1.1.3 christos /* Characters which start a comment at the beginning of a line. */
116 1.1 skrll const char line_comment_chars[] = "#";
117 1.1 skrll
118 1.1.1.3 christos /* Characters which may be used to separate multiple commands on a
119 1.1.1.3 christos single line. */
120 1.1.1.3 christos const char line_separator_chars[] = "`";
121 1.1 skrll
122 1.1.1.3 christos /* Characters which are used to indicate an exponent in a floating
123 1.1.1.3 christos point number. */
124 1.1 skrll const char EXP_CHARS[] = "eE";
125 1.1 skrll
126 1.1 skrll /* Chars that mean this number is a floating point constant
127 1.1 skrll As in 0f12.456 or 0d1.2345e12. */
128 1.1 skrll const char FLT_CHARS[] = "rRsSfFdD";
129 1.1 skrll
130 1.1 skrll /* Byte order. */
131 1.1 skrll extern int target_big_endian;
132 1.1 skrll const char *arc_target_format = DEFAULT_TARGET_FORMAT;
133 1.1 skrll static int byte_order = DEFAULT_BYTE_ORDER;
134 1.1 skrll
135 1.1.1.3.2.2 pgoyette /* Arc extension section. */
136 1.1.1.3.2.2 pgoyette static segT arcext_section;
137 1.1.1.3.2.2 pgoyette
138 1.1.1.3.2.2 pgoyette /* By default relaxation is disabled. */
139 1.1.1.3.2.2 pgoyette static int relaxation_state = 0;
140 1.1.1.3.2.2 pgoyette
141 1.1.1.3 christos extern int arc_get_mach (char *);
142 1.1 skrll
143 1.1.1.3.2.2 pgoyette /* Forward declarations. */
144 1.1.1.3 christos static void arc_lcomm (int);
145 1.1.1.3 christos static void arc_option (int);
146 1.1.1.3 christos static void arc_extra_reloc (int);
147 1.1.1.3.2.2 pgoyette static void arc_extinsn (int);
148 1.1.1.3.2.2 pgoyette static void arc_extcorereg (int);
149 1.1 skrll
150 1.1.1.3 christos const pseudo_typeS md_pseudo_table[] =
151 1.1.1.3 christos {
152 1.1.1.3 christos /* Make sure that .word is 32 bits. */
153 1.1.1.3 christos { "word", cons, 4 },
154 1.1 skrll
155 1.1.1.3 christos { "align", s_align_bytes, 0 }, /* Defaulting is invalid (0). */
156 1.1.1.3 christos { "lcomm", arc_lcomm, 0 },
157 1.1.1.3 christos { "lcommon", arc_lcomm, 0 },
158 1.1.1.3 christos { "cpu", arc_option, 0 },
159 1.1.1.3 christos
160 1.1.1.3.2.2 pgoyette { "extinstruction", arc_extinsn, 0 },
161 1.1.1.3.2.2 pgoyette { "extcoreregister", arc_extcorereg, EXT_CORE_REGISTER },
162 1.1.1.3.2.2 pgoyette { "extauxregister", arc_extcorereg, EXT_AUX_REGISTER },
163 1.1.1.3.2.2 pgoyette { "extcondcode", arc_extcorereg, EXT_COND_CODE },
164 1.1.1.3.2.2 pgoyette
165 1.1.1.3 christos { "tls_gd_ld", arc_extra_reloc, BFD_RELOC_ARC_TLS_GD_LD },
166 1.1.1.3 christos { "tls_gd_call", arc_extra_reloc, BFD_RELOC_ARC_TLS_GD_CALL },
167 1.1.1.3 christos
168 1.1.1.3 christos { NULL, NULL, 0 }
169 1.1.1.3 christos };
170 1.1 skrll
171 1.1 skrll const char *md_shortopts = "";
172 1.1 skrll
173 1.1 skrll enum options
174 1.1 skrll {
175 1.1 skrll OPTION_EB = OPTION_MD_BASE,
176 1.1 skrll OPTION_EL,
177 1.1.1.3 christos
178 1.1.1.3 christos OPTION_ARC600,
179 1.1.1.3 christos OPTION_ARC601,
180 1.1.1.3 christos OPTION_ARC700,
181 1.1.1.3 christos OPTION_ARCEM,
182 1.1.1.3 christos OPTION_ARCHS,
183 1.1.1.3 christos
184 1.1.1.3 christos OPTION_MCPU,
185 1.1.1.3 christos OPTION_CD,
186 1.1.1.3.2.2 pgoyette OPTION_RELAX,
187 1.1.1.3.2.2 pgoyette OPTION_NPS400,
188 1.1.1.3.2.2 pgoyette
189 1.1.1.3.2.2 pgoyette OPTION_SPFP,
190 1.1.1.3.2.2 pgoyette OPTION_DPFP,
191 1.1.1.3.2.2 pgoyette OPTION_FPUDA,
192 1.1.1.3 christos
193 1.1.1.3 christos /* The following options are deprecated and provided here only for
194 1.1.1.3 christos compatibility reasons. */
195 1.1.1.3 christos OPTION_USER_MODE,
196 1.1.1.3 christos OPTION_LD_EXT_MASK,
197 1.1.1.3 christos OPTION_SWAP,
198 1.1.1.3 christos OPTION_NORM,
199 1.1.1.3 christos OPTION_BARREL_SHIFT,
200 1.1.1.3 christos OPTION_MIN_MAX,
201 1.1.1.3 christos OPTION_NO_MPY,
202 1.1.1.3 christos OPTION_EA,
203 1.1.1.3 christos OPTION_MUL64,
204 1.1.1.3 christos OPTION_SIMD,
205 1.1.1.3 christos OPTION_XMAC_D16,
206 1.1.1.3 christos OPTION_XMAC_24,
207 1.1.1.3 christos OPTION_DSP_PACKA,
208 1.1.1.3 christos OPTION_CRC,
209 1.1.1.3 christos OPTION_DVBF,
210 1.1.1.3 christos OPTION_TELEPHONY,
211 1.1.1.3 christos OPTION_XYMEMORY,
212 1.1.1.3 christos OPTION_LOCK,
213 1.1.1.3 christos OPTION_SWAPE,
214 1.1.1.3.2.2 pgoyette OPTION_RTSC
215 1.1 skrll };
216 1.1 skrll
217 1.1 skrll struct option md_longopts[] =
218 1.1 skrll {
219 1.1.1.3 christos { "EB", no_argument, NULL, OPTION_EB },
220 1.1.1.3 christos { "EL", no_argument, NULL, OPTION_EL },
221 1.1.1.3 christos { "mcpu", required_argument, NULL, OPTION_MCPU },
222 1.1.1.3 christos { "mA6", no_argument, NULL, OPTION_ARC600 },
223 1.1.1.3.2.2 pgoyette { "mARC600", no_argument, NULL, OPTION_ARC600 },
224 1.1.1.3.2.2 pgoyette { "mARC601", no_argument, NULL, OPTION_ARC601 },
225 1.1.1.3.2.2 pgoyette { "mARC700", no_argument, NULL, OPTION_ARC700 },
226 1.1.1.3 christos { "mA7", no_argument, NULL, OPTION_ARC700 },
227 1.1.1.3 christos { "mEM", no_argument, NULL, OPTION_ARCEM },
228 1.1.1.3 christos { "mHS", no_argument, NULL, OPTION_ARCHS },
229 1.1.1.3 christos { "mcode-density", no_argument, NULL, OPTION_CD },
230 1.1.1.3.2.2 pgoyette { "mrelax", no_argument, NULL, OPTION_RELAX },
231 1.1.1.3.2.2 pgoyette { "mnps400", no_argument, NULL, OPTION_NPS400 },
232 1.1.1.3.2.2 pgoyette
233 1.1.1.3.2.2 pgoyette /* Floating point options */
234 1.1.1.3.2.2 pgoyette { "mspfp", no_argument, NULL, OPTION_SPFP},
235 1.1.1.3.2.2 pgoyette { "mspfp-compact", no_argument, NULL, OPTION_SPFP},
236 1.1.1.3.2.2 pgoyette { "mspfp_compact", no_argument, NULL, OPTION_SPFP},
237 1.1.1.3.2.2 pgoyette { "mspfp-fast", no_argument, NULL, OPTION_SPFP},
238 1.1.1.3.2.2 pgoyette { "mspfp_fast", no_argument, NULL, OPTION_SPFP},
239 1.1.1.3.2.2 pgoyette { "mdpfp", no_argument, NULL, OPTION_DPFP},
240 1.1.1.3.2.2 pgoyette { "mdpfp-compact", no_argument, NULL, OPTION_DPFP},
241 1.1.1.3.2.2 pgoyette { "mdpfp_compact", no_argument, NULL, OPTION_DPFP},
242 1.1.1.3.2.2 pgoyette { "mdpfp-fast", no_argument, NULL, OPTION_DPFP},
243 1.1.1.3.2.2 pgoyette { "mdpfp_fast", no_argument, NULL, OPTION_DPFP},
244 1.1.1.3.2.2 pgoyette { "mfpuda", no_argument, NULL, OPTION_FPUDA},
245 1.1.1.3 christos
246 1.1.1.3 christos /* The following options are deprecated and provided here only for
247 1.1.1.3 christos compatibility reasons. */
248 1.1.1.3 christos { "mav2em", no_argument, NULL, OPTION_ARCEM },
249 1.1.1.3 christos { "mav2hs", no_argument, NULL, OPTION_ARCHS },
250 1.1.1.3 christos { "muser-mode-only", no_argument, NULL, OPTION_USER_MODE },
251 1.1.1.3 christos { "mld-extension-reg-mask", required_argument, NULL, OPTION_LD_EXT_MASK },
252 1.1.1.3 christos { "mswap", no_argument, NULL, OPTION_SWAP },
253 1.1.1.3 christos { "mnorm", no_argument, NULL, OPTION_NORM },
254 1.1.1.3 christos { "mbarrel-shifter", no_argument, NULL, OPTION_BARREL_SHIFT },
255 1.1.1.3 christos { "mbarrel_shifter", no_argument, NULL, OPTION_BARREL_SHIFT },
256 1.1.1.3 christos { "mmin-max", no_argument, NULL, OPTION_MIN_MAX },
257 1.1.1.3 christos { "mmin_max", no_argument, NULL, OPTION_MIN_MAX },
258 1.1.1.3 christos { "mno-mpy", no_argument, NULL, OPTION_NO_MPY },
259 1.1.1.3 christos { "mea", no_argument, NULL, OPTION_EA },
260 1.1.1.3 christos { "mEA", no_argument, NULL, OPTION_EA },
261 1.1.1.3 christos { "mmul64", no_argument, NULL, OPTION_MUL64 },
262 1.1.1.3 christos { "msimd", no_argument, NULL, OPTION_SIMD},
263 1.1.1.3 christos { "mmac-d16", no_argument, NULL, OPTION_XMAC_D16},
264 1.1.1.3 christos { "mmac_d16", no_argument, NULL, OPTION_XMAC_D16},
265 1.1.1.3 christos { "mmac-24", no_argument, NULL, OPTION_XMAC_24},
266 1.1.1.3 christos { "mmac_24", no_argument, NULL, OPTION_XMAC_24},
267 1.1.1.3 christos { "mdsp-packa", no_argument, NULL, OPTION_DSP_PACKA},
268 1.1.1.3 christos { "mdsp_packa", no_argument, NULL, OPTION_DSP_PACKA},
269 1.1.1.3 christos { "mcrc", no_argument, NULL, OPTION_CRC},
270 1.1.1.3 christos { "mdvbf", no_argument, NULL, OPTION_DVBF},
271 1.1.1.3 christos { "mtelephony", no_argument, NULL, OPTION_TELEPHONY},
272 1.1.1.3 christos { "mxy", no_argument, NULL, OPTION_XYMEMORY},
273 1.1.1.3 christos { "mlock", no_argument, NULL, OPTION_LOCK},
274 1.1.1.3 christos { "mswape", no_argument, NULL, OPTION_SWAPE},
275 1.1.1.3 christos { "mrtsc", no_argument, NULL, OPTION_RTSC},
276 1.1.1.3 christos
277 1.1.1.3 christos { NULL, no_argument, NULL, 0 }
278 1.1 skrll };
279 1.1.1.3 christos
280 1.1 skrll size_t md_longopts_size = sizeof (md_longopts);
281 1.1 skrll
282 1.1.1.3 christos /* Local data and data types. */
283 1.1.1.3 christos
284 1.1.1.3 christos /* Used since new relocation types are introduced in this
285 1.1.1.3 christos file (DUMMY_RELOC_LITUSE_*). */
286 1.1.1.3 christos typedef int extended_bfd_reloc_code_real_type;
287 1.1.1.3 christos
288 1.1.1.3 christos struct arc_fixup
289 1.1.1.3 christos {
290 1.1.1.3 christos expressionS exp;
291 1.1 skrll
292 1.1.1.3 christos extended_bfd_reloc_code_real_type reloc;
293 1.1 skrll
294 1.1.1.3 christos /* index into arc_operands. */
295 1.1.1.3 christos unsigned int opindex;
296 1.1 skrll
297 1.1.1.3 christos /* PC-relative, used by internals fixups. */
298 1.1.1.3 christos unsigned char pcrel;
299 1.1.1.3 christos
300 1.1.1.3 christos /* TRUE if this fixup is for LIMM operand. */
301 1.1.1.3 christos bfd_boolean islong;
302 1.1.1.3 christos };
303 1.1.1.3 christos
304 1.1.1.3 christos struct arc_insn
305 1.1 skrll {
306 1.1.1.3 christos unsigned int insn;
307 1.1.1.3 christos int nfixups;
308 1.1.1.3 christos struct arc_fixup fixups[MAX_INSN_FIXUPS];
309 1.1.1.3 christos long limm;
310 1.1.1.3 christos bfd_boolean short_insn; /* Boolean value: TRUE if current insn is
311 1.1.1.3 christos short. */
312 1.1.1.3 christos bfd_boolean has_limm; /* Boolean value: TRUE if limm field is
313 1.1.1.3 christos valid. */
314 1.1.1.3.2.2 pgoyette bfd_boolean relax; /* Boolean value: TRUE if needs
315 1.1.1.3.2.2 pgoyette relaxation. */
316 1.1.1.3 christos };
317 1.1 skrll
318 1.1.1.3 christos /* Structure to hold any last two instructions. */
319 1.1.1.3 christos static struct arc_last_insn
320 1.1 skrll {
321 1.1.1.3 christos /* Saved instruction opcode. */
322 1.1.1.3 christos const struct arc_opcode *opcode;
323 1.1 skrll
324 1.1.1.3 christos /* Boolean value: TRUE if current insn is short. */
325 1.1.1.3 christos bfd_boolean has_limm;
326 1.1 skrll
327 1.1.1.3 christos /* Boolean value: TRUE if current insn has delay slot. */
328 1.1.1.3 christos bfd_boolean has_delay_slot;
329 1.1.1.3 christos } arc_last_insns[2];
330 1.1.1.3 christos
331 1.1.1.3.2.2 pgoyette /* Extension instruction suffix classes. */
332 1.1.1.3.2.2 pgoyette typedef struct
333 1.1.1.3.2.2 pgoyette {
334 1.1.1.3.2.2 pgoyette const char *name;
335 1.1.1.3.2.2 pgoyette int len;
336 1.1.1.3.2.2 pgoyette int attr_class;
337 1.1.1.3.2.2 pgoyette } attributes_t;
338 1.1.1.3.2.2 pgoyette
339 1.1.1.3.2.2 pgoyette static const attributes_t suffixclass[] =
340 1.1.1.3.2.2 pgoyette {
341 1.1.1.3.2.2 pgoyette { "SUFFIX_FLAG", 11, ARC_SUFFIX_FLAG },
342 1.1.1.3.2.2 pgoyette { "SUFFIX_COND", 11, ARC_SUFFIX_COND },
343 1.1.1.3.2.2 pgoyette { "SUFFIX_NONE", 11, ARC_SUFFIX_NONE }
344 1.1.1.3.2.2 pgoyette };
345 1.1.1.3.2.2 pgoyette
346 1.1.1.3.2.2 pgoyette /* Extension instruction syntax classes. */
347 1.1.1.3.2.2 pgoyette static const attributes_t syntaxclass[] =
348 1.1.1.3.2.2 pgoyette {
349 1.1.1.3.2.2 pgoyette { "SYNTAX_3OP", 10, ARC_SYNTAX_3OP },
350 1.1.1.3.2.2 pgoyette { "SYNTAX_2OP", 10, ARC_SYNTAX_2OP },
351 1.1.1.3.2.2 pgoyette { "SYNTAX_1OP", 10, ARC_SYNTAX_1OP },
352 1.1.1.3.2.2 pgoyette { "SYNTAX_NOP", 10, ARC_SYNTAX_NOP }
353 1.1.1.3.2.2 pgoyette };
354 1.1.1.3.2.2 pgoyette
355 1.1.1.3.2.2 pgoyette /* Extension instruction syntax classes modifiers. */
356 1.1.1.3.2.2 pgoyette static const attributes_t syntaxclassmod[] =
357 1.1.1.3.2.2 pgoyette {
358 1.1.1.3.2.2 pgoyette { "OP1_IMM_IMPLIED" , 15, ARC_OP1_IMM_IMPLIED },
359 1.1.1.3.2.2 pgoyette { "OP1_MUST_BE_IMM" , 15, ARC_OP1_MUST_BE_IMM }
360 1.1.1.3.2.2 pgoyette };
361 1.1.1.3.2.2 pgoyette
362 1.1.1.3.2.2 pgoyette /* Extension register type. */
363 1.1.1.3.2.2 pgoyette typedef struct
364 1.1.1.3.2.2 pgoyette {
365 1.1.1.3.2.2 pgoyette char *name;
366 1.1.1.3.2.2 pgoyette int number;
367 1.1.1.3.2.2 pgoyette int imode;
368 1.1.1.3.2.2 pgoyette } extRegister_t;
369 1.1.1.3.2.2 pgoyette
370 1.1.1.3.2.2 pgoyette /* A structure to hold the additional conditional codes. */
371 1.1.1.3.2.2 pgoyette static struct
372 1.1.1.3.2.2 pgoyette {
373 1.1.1.3.2.2 pgoyette struct arc_flag_operand *arc_ext_condcode;
374 1.1.1.3.2.2 pgoyette int size;
375 1.1.1.3.2.2 pgoyette } ext_condcode = { NULL, 0 };
376 1.1.1.3.2.2 pgoyette
377 1.1.1.3.2.2 pgoyette /* Structure to hold an entry in ARC_OPCODE_HASH. */
378 1.1.1.3.2.2 pgoyette struct arc_opcode_hash_entry
379 1.1.1.3.2.2 pgoyette {
380 1.1.1.3.2.2 pgoyette /* The number of pointers in the OPCODE list. */
381 1.1.1.3.2.2 pgoyette size_t count;
382 1.1.1.3.2.2 pgoyette
383 1.1.1.3.2.2 pgoyette /* Points to a list of opcode pointers. */
384 1.1.1.3.2.2 pgoyette const struct arc_opcode **opcode;
385 1.1.1.3.2.2 pgoyette };
386 1.1.1.3.2.2 pgoyette
387 1.1.1.3.2.2 pgoyette /* Structure used for iterating through an arc_opcode_hash_entry. */
388 1.1.1.3.2.2 pgoyette struct arc_opcode_hash_entry_iterator
389 1.1.1.3.2.2 pgoyette {
390 1.1.1.3.2.2 pgoyette /* Index into the OPCODE element of the arc_opcode_hash_entry. */
391 1.1.1.3.2.2 pgoyette size_t index;
392 1.1.1.3.2.2 pgoyette
393 1.1.1.3.2.2 pgoyette /* The specific ARC_OPCODE from the ARC_OPCODES table that was last
394 1.1.1.3.2.2 pgoyette returned by this iterator. */
395 1.1.1.3.2.2 pgoyette const struct arc_opcode *opcode;
396 1.1.1.3.2.2 pgoyette };
397 1.1.1.3.2.2 pgoyette
398 1.1.1.3.2.2 pgoyette /* Forward declaration. */
399 1.1.1.3.2.2 pgoyette static void assemble_insn
400 1.1.1.3.2.2 pgoyette (const struct arc_opcode *, const expressionS *, int,
401 1.1.1.3.2.2 pgoyette const struct arc_flags *, int, struct arc_insn *);
402 1.1.1.3.2.2 pgoyette
403 1.1.1.3 christos /* The cpu for which we are generating code. */
404 1.1.1.3.2.2 pgoyette static unsigned arc_target;
405 1.1.1.3.2.2 pgoyette static const char *arc_target_name;
406 1.1.1.3.2.2 pgoyette static unsigned arc_features;
407 1.1 skrll
408 1.1.1.3 christos /* The default architecture. */
409 1.1.1.3.2.2 pgoyette static int arc_mach_type;
410 1.1 skrll
411 1.1.1.3.2.2 pgoyette /* TRUE if the cpu type has been explicitly specified. */
412 1.1.1.3.2.2 pgoyette static bfd_boolean mach_type_specified_p = FALSE;
413 1.1 skrll
414 1.1.1.3 christos /* The hash table of instruction opcodes. */
415 1.1.1.3 christos static struct hash_control *arc_opcode_hash;
416 1.1 skrll
417 1.1.1.3 christos /* The hash table of register symbols. */
418 1.1.1.3 christos static struct hash_control *arc_reg_hash;
419 1.1.1.3 christos
420 1.1.1.3.2.2 pgoyette /* The hash table of aux register symbols. */
421 1.1.1.3.2.2 pgoyette static struct hash_control *arc_aux_hash;
422 1.1.1.3.2.2 pgoyette
423 1.1.1.3 christos /* A table of CPU names and opcode sets. */
424 1.1.1.3 christos static const struct cpu_type
425 1.1 skrll {
426 1.1.1.3 christos const char *name;
427 1.1.1.3 christos unsigned flags;
428 1.1.1.3 christos int mach;
429 1.1.1.3 christos unsigned eflags;
430 1.1.1.3 christos unsigned features;
431 1.1.1.3 christos }
432 1.1.1.3 christos cpu_types[] =
433 1.1.1.3 christos {
434 1.1.1.3 christos { "arc600", ARC_OPCODE_ARC600, bfd_mach_arc_arc600,
435 1.1.1.3 christos E_ARC_MACH_ARC600, 0x00},
436 1.1.1.3 christos { "arc700", ARC_OPCODE_ARC700, bfd_mach_arc_arc700,
437 1.1.1.3 christos E_ARC_MACH_ARC700, 0x00},
438 1.1.1.3.2.2 pgoyette { "nps400", ARC_OPCODE_ARC700 , bfd_mach_arc_arc700,
439 1.1.1.3.2.2 pgoyette E_ARC_MACH_ARC700, ARC_NPS400},
440 1.1.1.3 christos { "arcem", ARC_OPCODE_ARCv2EM, bfd_mach_arc_arcv2,
441 1.1.1.3 christos EF_ARC_CPU_ARCV2EM, 0x00},
442 1.1.1.3 christos { "archs", ARC_OPCODE_ARCv2HS, bfd_mach_arc_arcv2,
443 1.1.1.3 christos EF_ARC_CPU_ARCV2HS, ARC_CD},
444 1.1.1.3 christos { 0, 0, 0, 0, 0 }
445 1.1.1.3 christos };
446 1.1 skrll
447 1.1.1.3 christos /* Used by the arc_reloc_op table. Order is important. */
448 1.1.1.3 christos #define O_gotoff O_md1 /* @gotoff relocation. */
449 1.1.1.3 christos #define O_gotpc O_md2 /* @gotpc relocation. */
450 1.1.1.3 christos #define O_plt O_md3 /* @plt relocation. */
451 1.1.1.3 christos #define O_sda O_md4 /* @sda relocation. */
452 1.1.1.3 christos #define O_pcl O_md5 /* @pcl relocation. */
453 1.1.1.3 christos #define O_tlsgd O_md6 /* @tlsgd relocation. */
454 1.1.1.3 christos #define O_tlsie O_md7 /* @tlsie relocation. */
455 1.1.1.3 christos #define O_tpoff9 O_md8 /* @tpoff9 relocation. */
456 1.1.1.3 christos #define O_tpoff O_md9 /* @tpoff relocation. */
457 1.1.1.3 christos #define O_dtpoff9 O_md10 /* @dtpoff9 relocation. */
458 1.1.1.3 christos #define O_dtpoff O_md11 /* @dtpoff relocation. */
459 1.1.1.3 christos #define O_last O_dtpoff
460 1.1.1.3 christos
461 1.1.1.3 christos /* Used to define a bracket as operand in tokens. */
462 1.1.1.3 christos #define O_bracket O_md32
463 1.1.1.3 christos
464 1.1.1.3 christos /* Dummy relocation, to be sorted out. */
465 1.1.1.3 christos #define DUMMY_RELOC_ARC_ENTRY (BFD_RELOC_UNUSED + 1)
466 1.1.1.3 christos
467 1.1.1.3 christos #define USER_RELOC_P(R) ((R) >= O_gotoff && (R) <= O_last)
468 1.1.1.3 christos
469 1.1.1.3 christos /* A table to map the spelling of a relocation operand into an appropriate
470 1.1.1.3 christos bfd_reloc_code_real_type type. The table is assumed to be ordered such
471 1.1.1.3 christos that op-O_literal indexes into it. */
472 1.1.1.3 christos #define ARC_RELOC_TABLE(op) \
473 1.1.1.3 christos (&arc_reloc_op[ ((!USER_RELOC_P (op)) \
474 1.1.1.3 christos ? (abort (), 0) \
475 1.1.1.3 christos : (int) (op) - (int) O_gotoff) ])
476 1.1.1.3 christos
477 1.1.1.3 christos #define DEF(NAME, RELOC, REQ) \
478 1.1.1.3 christos { #NAME, sizeof (#NAME)-1, O_##NAME, RELOC, REQ}
479 1.1.1.3 christos
480 1.1.1.3 christos static const struct arc_reloc_op_tag
481 1.1.1.3 christos {
482 1.1.1.3 christos /* String to lookup. */
483 1.1.1.3 christos const char *name;
484 1.1.1.3 christos /* Size of the string. */
485 1.1.1.3 christos size_t length;
486 1.1.1.3 christos /* Which operator to use. */
487 1.1.1.3 christos operatorT op;
488 1.1.1.3 christos extended_bfd_reloc_code_real_type reloc;
489 1.1.1.3 christos /* Allows complex relocation expression like identifier@reloc +
490 1.1.1.3 christos const. */
491 1.1.1.3 christos unsigned int complex_expr : 1;
492 1.1.1.3 christos }
493 1.1.1.3 christos arc_reloc_op[] =
494 1.1.1.3 christos {
495 1.1.1.3 christos DEF (gotoff, BFD_RELOC_ARC_GOTOFF, 1),
496 1.1.1.3 christos DEF (gotpc, BFD_RELOC_ARC_GOTPC32, 0),
497 1.1.1.3 christos DEF (plt, BFD_RELOC_ARC_PLT32, 0),
498 1.1.1.3 christos DEF (sda, DUMMY_RELOC_ARC_ENTRY, 1),
499 1.1.1.3 christos DEF (pcl, BFD_RELOC_ARC_PC32, 1),
500 1.1.1.3 christos DEF (tlsgd, BFD_RELOC_ARC_TLS_GD_GOT, 0),
501 1.1.1.3 christos DEF (tlsie, BFD_RELOC_ARC_TLS_IE_GOT, 0),
502 1.1.1.3 christos DEF (tpoff9, BFD_RELOC_ARC_TLS_LE_S9, 0),
503 1.1.1.3.2.2 pgoyette DEF (tpoff, BFD_RELOC_ARC_TLS_LE_32, 1),
504 1.1.1.3 christos DEF (dtpoff9, BFD_RELOC_ARC_TLS_DTPOFF_S9, 0),
505 1.1.1.3 christos DEF (dtpoff, BFD_RELOC_ARC_TLS_DTPOFF, 0),
506 1.1.1.3 christos };
507 1.1 skrll
508 1.1.1.3 christos static const int arc_num_reloc_op
509 1.1.1.3 christos = sizeof (arc_reloc_op) / sizeof (*arc_reloc_op);
510 1.1.1.3 christos
511 1.1.1.3.2.2 pgoyette /* Structure for relaxable instruction that have to be swapped with a
512 1.1.1.3.2.2 pgoyette smaller alternative instruction. */
513 1.1.1.3.2.2 pgoyette struct arc_relaxable_ins
514 1.1.1.3.2.2 pgoyette {
515 1.1.1.3.2.2 pgoyette /* Mnemonic that should be checked. */
516 1.1.1.3.2.2 pgoyette const char *mnemonic_r;
517 1.1.1.3.2.2 pgoyette
518 1.1.1.3.2.2 pgoyette /* Operands that should be checked.
519 1.1.1.3.2.2 pgoyette Indexes of operands from operand array. */
520 1.1.1.3.2.2 pgoyette enum rlx_operand_type operands[6];
521 1.1.1.3.2.2 pgoyette
522 1.1.1.3.2.2 pgoyette /* Flags that should be checked. */
523 1.1.1.3.2.2 pgoyette unsigned flag_classes[5];
524 1.1.1.3.2.2 pgoyette
525 1.1.1.3.2.2 pgoyette /* Mnemonic (smaller) alternative to be used later for relaxation. */
526 1.1.1.3.2.2 pgoyette const char *mnemonic_alt;
527 1.1.1.3.2.2 pgoyette
528 1.1.1.3.2.2 pgoyette /* Index of operand that generic relaxation has to check. */
529 1.1.1.3.2.2 pgoyette unsigned opcheckidx;
530 1.1.1.3.2.2 pgoyette
531 1.1.1.3.2.2 pgoyette /* Base subtype index used. */
532 1.1.1.3.2.2 pgoyette enum arc_rlx_types subtype;
533 1.1.1.3.2.2 pgoyette };
534 1.1.1.3.2.2 pgoyette
535 1.1.1.3.2.2 pgoyette #define RELAX_TABLE_ENTRY(BITS, ISSIGNED, SIZE, NEXT) \
536 1.1.1.3.2.2 pgoyette { (ISSIGNED) ? ((1 << ((BITS) - 1)) - 1) : ((1 << (BITS)) - 1), \
537 1.1.1.3.2.2 pgoyette (ISSIGNED) ? -(1 << ((BITS) - 1)) : 0, \
538 1.1.1.3.2.2 pgoyette (SIZE), \
539 1.1.1.3.2.2 pgoyette (NEXT) } \
540 1.1.1.3.2.2 pgoyette
541 1.1.1.3.2.2 pgoyette #define RELAX_TABLE_ENTRY_MAX(ISSIGNED, SIZE, NEXT) \
542 1.1.1.3.2.2 pgoyette { (ISSIGNED) ? 0x7FFFFFFF : 0xFFFFFFFF, \
543 1.1.1.3.2.2 pgoyette (ISSIGNED) ? -(0x7FFFFFFF) : 0, \
544 1.1.1.3.2.2 pgoyette (SIZE), \
545 1.1.1.3.2.2 pgoyette (NEXT) } \
546 1.1.1.3.2.2 pgoyette
547 1.1.1.3.2.2 pgoyette
548 1.1.1.3.2.2 pgoyette /* ARC relaxation table. */
549 1.1.1.3.2.2 pgoyette const relax_typeS md_relax_table[] =
550 1.1.1.3.2.2 pgoyette {
551 1.1.1.3.2.2 pgoyette /* Fake entry. */
552 1.1.1.3.2.2 pgoyette {0, 0, 0, 0},
553 1.1.1.3.2.2 pgoyette
554 1.1.1.3.2.2 pgoyette /* BL_S s13 ->
555 1.1.1.3.2.2 pgoyette BL s25. */
556 1.1.1.3.2.2 pgoyette RELAX_TABLE_ENTRY(13, 1, 2, ARC_RLX_BL),
557 1.1.1.3.2.2 pgoyette RELAX_TABLE_ENTRY(25, 1, 4, ARC_RLX_NONE),
558 1.1.1.3.2.2 pgoyette
559 1.1.1.3.2.2 pgoyette /* B_S s10 ->
560 1.1.1.3.2.2 pgoyette B s25. */
561 1.1.1.3.2.2 pgoyette RELAX_TABLE_ENTRY(10, 1, 2, ARC_RLX_B),
562 1.1.1.3.2.2 pgoyette RELAX_TABLE_ENTRY(25, 1, 4, ARC_RLX_NONE),
563 1.1.1.3.2.2 pgoyette
564 1.1.1.3.2.2 pgoyette /* ADD_S c,b, u3 ->
565 1.1.1.3.2.2 pgoyette ADD<.f> a,b,u6 ->
566 1.1.1.3.2.2 pgoyette ADD<.f> a,b,limm. */
567 1.1.1.3.2.2 pgoyette RELAX_TABLE_ENTRY(3, 0, 2, ARC_RLX_ADD_U6),
568 1.1.1.3.2.2 pgoyette RELAX_TABLE_ENTRY(6, 0, 4, ARC_RLX_ADD_LIMM),
569 1.1.1.3.2.2 pgoyette RELAX_TABLE_ENTRY_MAX(0, 8, ARC_RLX_NONE),
570 1.1.1.3.2.2 pgoyette
571 1.1.1.3.2.2 pgoyette /* LD_S a, [b, u7] ->
572 1.1.1.3.2.2 pgoyette LD<zz><.x><.aa><.di> a, [b, s9] ->
573 1.1.1.3.2.2 pgoyette LD<zz><.x><.aa><.di> a, [b, limm] */
574 1.1.1.3.2.2 pgoyette RELAX_TABLE_ENTRY(7, 0, 2, ARC_RLX_LD_S9),
575 1.1.1.3.2.2 pgoyette RELAX_TABLE_ENTRY(9, 1, 4, ARC_RLX_LD_LIMM),
576 1.1.1.3.2.2 pgoyette RELAX_TABLE_ENTRY_MAX(1, 8, ARC_RLX_NONE),
577 1.1.1.3.2.2 pgoyette
578 1.1.1.3.2.2 pgoyette /* MOV_S b, u8 ->
579 1.1.1.3.2.2 pgoyette MOV<.f> b, s12 ->
580 1.1.1.3.2.2 pgoyette MOV<.f> b, limm. */
581 1.1.1.3.2.2 pgoyette RELAX_TABLE_ENTRY(8, 0, 2, ARC_RLX_MOV_S12),
582 1.1.1.3.2.2 pgoyette RELAX_TABLE_ENTRY(8, 0, 4, ARC_RLX_MOV_LIMM),
583 1.1.1.3.2.2 pgoyette RELAX_TABLE_ENTRY_MAX(0, 8, ARC_RLX_NONE),
584 1.1.1.3.2.2 pgoyette
585 1.1.1.3.2.2 pgoyette /* SUB_S c, b, u3 ->
586 1.1.1.3.2.2 pgoyette SUB<.f> a, b, u6 ->
587 1.1.1.3.2.2 pgoyette SUB<.f> a, b, limm. */
588 1.1.1.3.2.2 pgoyette RELAX_TABLE_ENTRY(3, 0, 2, ARC_RLX_SUB_U6),
589 1.1.1.3.2.2 pgoyette RELAX_TABLE_ENTRY(6, 0, 4, ARC_RLX_SUB_LIMM),
590 1.1.1.3.2.2 pgoyette RELAX_TABLE_ENTRY_MAX(0, 8, ARC_RLX_NONE),
591 1.1.1.3.2.2 pgoyette
592 1.1.1.3.2.2 pgoyette /* MPY<.f> a, b, u6 ->
593 1.1.1.3.2.2 pgoyette MPY<.f> a, b, limm. */
594 1.1.1.3.2.2 pgoyette RELAX_TABLE_ENTRY(6, 0, 4, ARC_RLX_MPY_LIMM),
595 1.1.1.3.2.2 pgoyette RELAX_TABLE_ENTRY_MAX(0, 8, ARC_RLX_NONE),
596 1.1.1.3.2.2 pgoyette
597 1.1.1.3.2.2 pgoyette /* MOV<.f><.cc> b, u6 ->
598 1.1.1.3.2.2 pgoyette MOV<.f><.cc> b, limm. */
599 1.1.1.3.2.2 pgoyette RELAX_TABLE_ENTRY(6, 0, 4, ARC_RLX_MOV_RLIMM),
600 1.1.1.3.2.2 pgoyette RELAX_TABLE_ENTRY_MAX(0, 8, ARC_RLX_NONE),
601 1.1.1.3.2.2 pgoyette
602 1.1.1.3.2.2 pgoyette /* ADD<.f><.cc> b, b, u6 ->
603 1.1.1.3.2.2 pgoyette ADD<.f><.cc> b, b, limm. */
604 1.1.1.3.2.2 pgoyette RELAX_TABLE_ENTRY(6, 0, 4, ARC_RLX_ADD_RRLIMM),
605 1.1.1.3.2.2 pgoyette RELAX_TABLE_ENTRY_MAX(0, 8, ARC_RLX_NONE),
606 1.1.1.3.2.2 pgoyette };
607 1.1.1.3.2.2 pgoyette
608 1.1.1.3.2.2 pgoyette /* Order of this table's entries matters! */
609 1.1.1.3.2.2 pgoyette const struct arc_relaxable_ins arc_relaxable_insns[] =
610 1.1.1.3.2.2 pgoyette {
611 1.1.1.3.2.2 pgoyette { "bl", { IMMEDIATE }, { 0 }, "bl_s", 0, ARC_RLX_BL_S },
612 1.1.1.3.2.2 pgoyette { "b", { IMMEDIATE }, { 0 }, "b_s", 0, ARC_RLX_B_S },
613 1.1.1.3.2.2 pgoyette { "add", { REGISTER, REGISTER_DUP, IMMEDIATE }, { 5, 1, 0 }, "add",
614 1.1.1.3.2.2 pgoyette 2, ARC_RLX_ADD_RRU6},
615 1.1.1.3.2.2 pgoyette { "add", { REGISTER_S, REGISTER_S, IMMEDIATE }, { 0 }, "add_s", 2,
616 1.1.1.3.2.2 pgoyette ARC_RLX_ADD_U3 },
617 1.1.1.3.2.2 pgoyette { "add", { REGISTER, REGISTER, IMMEDIATE }, { 5, 0 }, "add", 2,
618 1.1.1.3.2.2 pgoyette ARC_RLX_ADD_U6 },
619 1.1.1.3.2.2 pgoyette { "ld", { REGISTER_S, BRACKET, REGISTER_S, IMMEDIATE, BRACKET },
620 1.1.1.3.2.2 pgoyette { 0 }, "ld_s", 3, ARC_RLX_LD_U7 },
621 1.1.1.3.2.2 pgoyette { "ld", { REGISTER, BRACKET, REGISTER_NO_GP, IMMEDIATE, BRACKET },
622 1.1.1.3.2.2 pgoyette { 11, 4, 14, 17, 0 }, "ld", 3, ARC_RLX_LD_S9 },
623 1.1.1.3.2.2 pgoyette { "mov", { REGISTER_S, IMMEDIATE }, { 0 }, "mov_s", 1, ARC_RLX_MOV_U8 },
624 1.1.1.3.2.2 pgoyette { "mov", { REGISTER, IMMEDIATE }, { 5, 0 }, "mov", 1, ARC_RLX_MOV_S12 },
625 1.1.1.3.2.2 pgoyette { "mov", { REGISTER, IMMEDIATE }, { 5, 1, 0 },"mov", 1, ARC_RLX_MOV_RU6 },
626 1.1.1.3.2.2 pgoyette { "sub", { REGISTER_S, REGISTER_S, IMMEDIATE }, { 0 }, "sub_s", 2,
627 1.1.1.3.2.2 pgoyette ARC_RLX_SUB_U3 },
628 1.1.1.3.2.2 pgoyette { "sub", { REGISTER, REGISTER, IMMEDIATE }, { 5, 0 }, "sub", 2,
629 1.1.1.3.2.2 pgoyette ARC_RLX_SUB_U6 },
630 1.1.1.3.2.2 pgoyette { "mpy", { REGISTER, REGISTER, IMMEDIATE }, { 5, 0 }, "mpy", 2,
631 1.1.1.3.2.2 pgoyette ARC_RLX_MPY_U6 },
632 1.1.1.3.2.2 pgoyette };
633 1.1.1.3.2.2 pgoyette
634 1.1.1.3.2.2 pgoyette const unsigned arc_num_relaxable_ins = ARRAY_SIZE (arc_relaxable_insns);
635 1.1.1.3.2.2 pgoyette
636 1.1.1.3 christos /* Flags to set in the elf header. */
637 1.1.1.3 christos static flagword arc_eflag = 0x00;
638 1.1 skrll
639 1.1.1.3 christos /* Pre-defined "_GLOBAL_OFFSET_TABLE_". */
640 1.1.1.3 christos symbolS * GOT_symbol = 0;
641 1.1 skrll
642 1.1.1.3 christos /* Set to TRUE when we assemble instructions. */
643 1.1.1.3 christos static bfd_boolean assembling_insn = FALSE;
644 1.1.1.3 christos
645 1.1.1.3.2.2 pgoyette /* Functions implementation. */
646 1.1.1.3 christos
647 1.1.1.3.2.2 pgoyette /* Return a pointer to ARC_OPCODE_HASH_ENTRY that identifies all
648 1.1.1.3.2.2 pgoyette ARC_OPCODE entries in ARC_OPCODE_HASH that match NAME, or NULL if there
649 1.1.1.3.2.2 pgoyette are no matching entries in ARC_OPCODE_HASH. */
650 1.1.1.3.2.2 pgoyette
651 1.1.1.3.2.2 pgoyette static const struct arc_opcode_hash_entry *
652 1.1.1.3.2.2 pgoyette arc_find_opcode (const char *name)
653 1.1.1.3.2.2 pgoyette {
654 1.1.1.3.2.2 pgoyette const struct arc_opcode_hash_entry *entry;
655 1.1.1.3.2.2 pgoyette
656 1.1.1.3.2.2 pgoyette entry = hash_find (arc_opcode_hash, name);
657 1.1.1.3.2.2 pgoyette return entry;
658 1.1.1.3.2.2 pgoyette }
659 1.1.1.3.2.2 pgoyette
660 1.1.1.3.2.2 pgoyette /* Initialise the iterator ITER. */
661 1.1.1.3.2.2 pgoyette
662 1.1.1.3.2.2 pgoyette static void
663 1.1.1.3.2.2 pgoyette arc_opcode_hash_entry_iterator_init (struct arc_opcode_hash_entry_iterator *iter)
664 1.1.1.3.2.2 pgoyette {
665 1.1.1.3.2.2 pgoyette iter->index = 0;
666 1.1.1.3.2.2 pgoyette iter->opcode = NULL;
667 1.1.1.3.2.2 pgoyette }
668 1.1.1.3.2.2 pgoyette
669 1.1.1.3.2.2 pgoyette /* Return the next ARC_OPCODE from ENTRY, using ITER to hold state between
670 1.1.1.3.2.2 pgoyette calls to this function. Return NULL when all ARC_OPCODE entries have
671 1.1.1.3.2.2 pgoyette been returned. */
672 1.1.1.3.2.2 pgoyette
673 1.1.1.3.2.2 pgoyette static const struct arc_opcode *
674 1.1.1.3.2.2 pgoyette arc_opcode_hash_entry_iterator_next (const struct arc_opcode_hash_entry *entry,
675 1.1.1.3.2.2 pgoyette struct arc_opcode_hash_entry_iterator *iter)
676 1.1.1.3.2.2 pgoyette {
677 1.1.1.3.2.2 pgoyette if (iter->opcode == NULL && iter->index == 0)
678 1.1.1.3.2.2 pgoyette {
679 1.1.1.3.2.2 pgoyette gas_assert (entry->count > 0);
680 1.1.1.3.2.2 pgoyette iter->opcode = entry->opcode[iter->index];
681 1.1.1.3.2.2 pgoyette }
682 1.1.1.3.2.2 pgoyette else if (iter->opcode != NULL)
683 1.1.1.3.2.2 pgoyette {
684 1.1.1.3.2.2 pgoyette const char *old_name = iter->opcode->name;
685 1.1.1.3.2.2 pgoyette
686 1.1.1.3.2.2 pgoyette iter->opcode++;
687 1.1.1.3.2.2 pgoyette if (iter->opcode->name == NULL
688 1.1.1.3.2.2 pgoyette || strcmp (old_name, iter->opcode->name) != 0)
689 1.1.1.3.2.2 pgoyette {
690 1.1.1.3.2.2 pgoyette iter->index++;
691 1.1.1.3.2.2 pgoyette if (iter->index == entry->count)
692 1.1.1.3.2.2 pgoyette iter->opcode = NULL;
693 1.1.1.3.2.2 pgoyette else
694 1.1.1.3.2.2 pgoyette iter->opcode = entry->opcode[iter->index];
695 1.1.1.3.2.2 pgoyette }
696 1.1.1.3.2.2 pgoyette }
697 1.1.1.3.2.2 pgoyette
698 1.1.1.3.2.2 pgoyette return iter->opcode;
699 1.1.1.3.2.2 pgoyette }
700 1.1.1.3.2.2 pgoyette
701 1.1.1.3.2.2 pgoyette /* Insert an opcode into opcode hash structure. */
702 1.1.1.3.2.2 pgoyette
703 1.1.1.3.2.2 pgoyette static void
704 1.1.1.3.2.2 pgoyette arc_insert_opcode (const struct arc_opcode *opcode)
705 1.1.1.3.2.2 pgoyette {
706 1.1.1.3.2.2 pgoyette const char *name, *retval;
707 1.1.1.3.2.2 pgoyette struct arc_opcode_hash_entry *entry;
708 1.1.1.3.2.2 pgoyette name = opcode->name;
709 1.1.1.3.2.2 pgoyette
710 1.1.1.3.2.2 pgoyette entry = hash_find (arc_opcode_hash, name);
711 1.1.1.3.2.2 pgoyette if (entry == NULL)
712 1.1.1.3.2.2 pgoyette {
713 1.1.1.3.2.2 pgoyette entry = XNEW (struct arc_opcode_hash_entry);
714 1.1.1.3.2.2 pgoyette entry->count = 0;
715 1.1.1.3.2.2 pgoyette entry->opcode = NULL;
716 1.1.1.3.2.2 pgoyette
717 1.1.1.3.2.2 pgoyette retval = hash_insert (arc_opcode_hash, name, (void *) entry);
718 1.1.1.3.2.2 pgoyette if (retval)
719 1.1.1.3.2.2 pgoyette as_fatal (_("internal error: can't hash opcode '%s': %s"),
720 1.1.1.3.2.2 pgoyette name, retval);
721 1.1.1.3.2.2 pgoyette }
722 1.1.1.3.2.2 pgoyette
723 1.1.1.3.2.2 pgoyette entry->opcode = XRESIZEVEC (const struct arc_opcode *, entry->opcode,
724 1.1.1.3.2.2 pgoyette entry->count + 1);
725 1.1.1.3.2.2 pgoyette
726 1.1.1.3.2.2 pgoyette if (entry->opcode == NULL)
727 1.1.1.3.2.2 pgoyette as_fatal (_("Virtual memory exhausted"));
728 1.1.1.3.2.2 pgoyette
729 1.1.1.3.2.2 pgoyette entry->opcode[entry->count] = opcode;
730 1.1.1.3.2.2 pgoyette entry->count++;
731 1.1.1.3.2.2 pgoyette }
732 1.1.1.3 christos
733 1.1.1.3 christos
734 1.1.1.3 christos /* Like md_number_to_chars but used for limms. The 4-byte limm value,
735 1.1.1.3 christos is encoded as 'middle-endian' for a little-endian target. FIXME!
736 1.1.1.3 christos this function is used for regular 4 byte instructions as well. */
737 1.1 skrll
738 1.1.1.3 christos static void
739 1.1.1.3 christos md_number_to_chars_midend (char *buf, valueT val, int n)
740 1.1.1.3 christos {
741 1.1.1.3 christos if (n == 4)
742 1.1 skrll {
743 1.1.1.3 christos md_number_to_chars (buf, (val & 0xffff0000) >> 16, 2);
744 1.1.1.3 christos md_number_to_chars (buf + 2, (val & 0xffff), 2);
745 1.1.1.3 christos }
746 1.1.1.3 christos else
747 1.1 skrll {
748 1.1.1.3 christos md_number_to_chars (buf, val, n);
749 1.1.1.3 christos }
750 1.1.1.3 christos }
751 1.1 skrll
752 1.1.1.3.2.2 pgoyette /* Select an appropriate entry from CPU_TYPES based on ARG and initialise
753 1.1.1.3.2.2 pgoyette the relevant static global variables. */
754 1.1.1.3.2.2 pgoyette
755 1.1.1.3.2.2 pgoyette static void
756 1.1.1.3.2.2 pgoyette arc_select_cpu (const char *arg)
757 1.1.1.3.2.2 pgoyette {
758 1.1.1.3.2.2 pgoyette int cpu_flags = 0;
759 1.1.1.3.2.2 pgoyette int i;
760 1.1.1.3.2.2 pgoyette
761 1.1.1.3.2.2 pgoyette for (i = 0; cpu_types[i].name; ++i)
762 1.1.1.3.2.2 pgoyette {
763 1.1.1.3.2.2 pgoyette if (!strcasecmp (cpu_types[i].name, arg))
764 1.1.1.3.2.2 pgoyette {
765 1.1.1.3.2.2 pgoyette arc_target = cpu_types[i].flags;
766 1.1.1.3.2.2 pgoyette arc_target_name = cpu_types[i].name;
767 1.1.1.3.2.2 pgoyette arc_features = cpu_types[i].features;
768 1.1.1.3.2.2 pgoyette arc_mach_type = cpu_types[i].mach;
769 1.1.1.3.2.2 pgoyette cpu_flags = cpu_types[i].eflags;
770 1.1.1.3.2.2 pgoyette break;
771 1.1.1.3.2.2 pgoyette }
772 1.1.1.3.2.2 pgoyette }
773 1.1.1.3.2.2 pgoyette
774 1.1.1.3.2.2 pgoyette if (!cpu_types[i].name)
775 1.1.1.3.2.2 pgoyette as_fatal (_("unknown architecture: %s\n"), arg);
776 1.1.1.3.2.2 pgoyette gas_assert (cpu_flags != 0);
777 1.1.1.3.2.2 pgoyette arc_eflag = (arc_eflag & ~EF_ARC_MACH_MSK) | cpu_flags;
778 1.1.1.3.2.2 pgoyette }
779 1.1.1.3.2.2 pgoyette
780 1.1.1.3 christos /* Here ends all the ARCompact extension instruction assembling
781 1.1.1.3 christos stuff. */
782 1.1 skrll
783 1.1.1.3 christos static void
784 1.1.1.3 christos arc_extra_reloc (int r_type)
785 1.1.1.3 christos {
786 1.1.1.3 christos char *sym_name, c;
787 1.1.1.3 christos symbolS *sym, *lab = NULL;
788 1.1 skrll
789 1.1.1.3 christos if (*input_line_pointer == '@')
790 1.1.1.3 christos input_line_pointer++;
791 1.1.1.3 christos c = get_symbol_name (&sym_name);
792 1.1.1.3 christos sym = symbol_find_or_make (sym_name);
793 1.1.1.3 christos restore_line_pointer (c);
794 1.1.1.3 christos if (c == ',' && r_type == BFD_RELOC_ARC_TLS_GD_LD)
795 1.1.1.3 christos {
796 1.1.1.3 christos ++input_line_pointer;
797 1.1.1.3 christos char *lab_name;
798 1.1.1.3 christos c = get_symbol_name (&lab_name);
799 1.1.1.3 christos lab = symbol_find_or_make (lab_name);
800 1.1.1.3 christos restore_line_pointer (c);
801 1.1.1.3 christos }
802 1.1.1.3.2.2 pgoyette
803 1.1.1.3.2.2 pgoyette /* These relocations exist as a mechanism for the compiler to tell the
804 1.1.1.3.2.2 pgoyette linker how to patch the code if the tls model is optimised. However,
805 1.1.1.3.2.2 pgoyette the relocation itself does not require any space within the assembler
806 1.1.1.3.2.2 pgoyette fragment, and so we pass a size of 0.
807 1.1.1.3.2.2 pgoyette
808 1.1.1.3.2.2 pgoyette The lines that generate these relocations look like this:
809 1.1.1.3.2.2 pgoyette
810 1.1.1.3.2.2 pgoyette .tls_gd_ld @.tdata`bl __tls_get_addr@plt
811 1.1.1.3.2.2 pgoyette
812 1.1.1.3.2.2 pgoyette The '.tls_gd_ld @.tdata' is processed first and generates the
813 1.1.1.3.2.2 pgoyette additional relocation, while the 'bl __tls_get_addr@plt' is processed
814 1.1.1.3.2.2 pgoyette second and generates the additional branch.
815 1.1.1.3.2.2 pgoyette
816 1.1.1.3.2.2 pgoyette It is possible that the additional relocation generated by the
817 1.1.1.3.2.2 pgoyette '.tls_gd_ld @.tdata' will be attached at the very end of one fragment,
818 1.1.1.3.2.2 pgoyette while the 'bl __tls_get_addr@plt' will be generated as the first thing
819 1.1.1.3.2.2 pgoyette in the next fragment. This will be fine; both relocations will still
820 1.1.1.3.2.2 pgoyette appear to be at the same address in the generated object file.
821 1.1.1.3.2.2 pgoyette However, this only works as the additional relocation is generated
822 1.1.1.3.2.2 pgoyette with size of 0 bytes. */
823 1.1.1.3 christos fixS *fixP
824 1.1.1.3 christos = fix_new (frag_now, /* Which frag? */
825 1.1.1.3 christos frag_now_fix (), /* Where in that frag? */
826 1.1.1.3.2.2 pgoyette 0, /* size: 1, 2, or 4 usually. */
827 1.1.1.3 christos sym, /* X_add_symbol. */
828 1.1.1.3 christos 0, /* X_add_number. */
829 1.1.1.3 christos FALSE, /* TRUE if PC-relative relocation. */
830 1.1.1.3 christos r_type /* Relocation type. */);
831 1.1.1.3 christos fixP->fx_subsy = lab;
832 1.1.1.3 christos }
833 1.1.1.3 christos
834 1.1.1.3 christos static symbolS *
835 1.1.1.3 christos arc_lcomm_internal (int ignore ATTRIBUTE_UNUSED,
836 1.1.1.3 christos symbolS *symbolP, addressT size)
837 1.1.1.3 christos {
838 1.1.1.3 christos addressT align = 0;
839 1.1.1.3 christos SKIP_WHITESPACE ();
840 1.1 skrll
841 1.1.1.3 christos if (*input_line_pointer == ',')
842 1.1 skrll {
843 1.1.1.3 christos align = parse_align (1);
844 1.1 skrll
845 1.1.1.3 christos if (align == (addressT) -1)
846 1.1.1.3 christos return NULL;
847 1.1 skrll }
848 1.1 skrll else
849 1.1.1.3 christos {
850 1.1.1.3 christos if (size >= 8)
851 1.1.1.3 christos align = 3;
852 1.1.1.3 christos else if (size >= 4)
853 1.1.1.3 christos align = 2;
854 1.1.1.3 christos else if (size >= 2)
855 1.1.1.3 christos align = 1;
856 1.1.1.3 christos else
857 1.1.1.3 christos align = 0;
858 1.1.1.3 christos }
859 1.1 skrll
860 1.1.1.3 christos bss_alloc (symbolP, size, align);
861 1.1.1.3 christos S_CLEAR_EXTERNAL (symbolP);
862 1.1 skrll
863 1.1.1.3 christos return symbolP;
864 1.1.1.3 christos }
865 1.1 skrll
866 1.1.1.3 christos static void
867 1.1.1.3 christos arc_lcomm (int ignore)
868 1.1 skrll {
869 1.1.1.3 christos symbolS *symbolP = s_comm_internal (ignore, arc_lcomm_internal);
870 1.1 skrll
871 1.1.1.3 christos if (symbolP)
872 1.1.1.3 christos symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
873 1.1.1.3 christos }
874 1.1 skrll
875 1.1.1.3 christos /* Select the cpu we're assembling for. */
876 1.1 skrll
877 1.1.1.3 christos static void
878 1.1.1.3 christos arc_option (int ignore ATTRIBUTE_UNUSED)
879 1.1.1.3 christos {
880 1.1.1.3 christos int mach = -1;
881 1.1.1.3 christos char c;
882 1.1.1.3 christos char *cpu;
883 1.1 skrll
884 1.1.1.3 christos c = get_symbol_name (&cpu);
885 1.1.1.3 christos mach = arc_get_mach (cpu);
886 1.1 skrll
887 1.1.1.3 christos if (mach == -1)
888 1.1.1.3 christos goto bad_cpu;
889 1.1 skrll
890 1.1.1.3 christos if (!mach_type_specified_p)
891 1.1 skrll {
892 1.1.1.3.2.2 pgoyette if ((!strcmp ("ARC600", cpu))
893 1.1.1.3.2.2 pgoyette || (!strcmp ("ARC601", cpu))
894 1.1.1.3.2.2 pgoyette || (!strcmp ("A6", cpu)))
895 1.1.1.3.2.2 pgoyette {
896 1.1.1.3.2.2 pgoyette md_parse_option (OPTION_MCPU, "arc600");
897 1.1.1.3.2.2 pgoyette }
898 1.1.1.3.2.2 pgoyette else if ((!strcmp ("ARC700", cpu))
899 1.1.1.3.2.2 pgoyette || (!strcmp ("A7", cpu)))
900 1.1.1.3.2.2 pgoyette {
901 1.1.1.3.2.2 pgoyette md_parse_option (OPTION_MCPU, "arc700");
902 1.1.1.3.2.2 pgoyette }
903 1.1.1.3.2.2 pgoyette else if (!strcmp ("EM", cpu))
904 1.1.1.3.2.2 pgoyette {
905 1.1.1.3.2.2 pgoyette md_parse_option (OPTION_MCPU, "arcem");
906 1.1.1.3.2.2 pgoyette }
907 1.1.1.3.2.2 pgoyette else if (!strcmp ("HS", cpu))
908 1.1.1.3.2.2 pgoyette {
909 1.1.1.3.2.2 pgoyette md_parse_option (OPTION_MCPU, "archs");
910 1.1.1.3.2.2 pgoyette }
911 1.1.1.3.2.2 pgoyette else if (!strcmp ("NPS400", cpu))
912 1.1.1.3.2.2 pgoyette {
913 1.1.1.3.2.2 pgoyette md_parse_option (OPTION_MCPU, "nps400");
914 1.1.1.3.2.2 pgoyette }
915 1.1.1.3.2.2 pgoyette else
916 1.1.1.3.2.2 pgoyette as_fatal (_("could not find the architecture"));
917 1.1.1.3.2.2 pgoyette
918 1.1.1.3 christos if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, mach))
919 1.1.1.3.2.2 pgoyette as_fatal (_("could not set architecture and machine"));
920 1.1 skrll
921 1.1.1.3.2.2 pgoyette /* Set elf header flags. */
922 1.1.1.3.2.2 pgoyette bfd_set_private_flags (stdoutput, arc_eflag);
923 1.1 skrll }
924 1.1 skrll else
925 1.1.1.3 christos if (arc_mach_type != mach)
926 1.1.1.3.2.2 pgoyette as_warn (_("Command-line value overrides \".cpu\" directive"));
927 1.1 skrll
928 1.1.1.3.2.2 pgoyette restore_line_pointer (c);
929 1.1.1.3 christos demand_empty_rest_of_line ();
930 1.1.1.3 christos return;
931 1.1 skrll
932 1.1.1.3 christos bad_cpu:
933 1.1.1.3.2.2 pgoyette restore_line_pointer (c);
934 1.1.1.3.2.2 pgoyette as_bad (_("invalid identifier for \".cpu\""));
935 1.1.1.3 christos ignore_rest_of_line ();
936 1.1.1.3 christos }
937 1.1 skrll
938 1.1.1.3 christos /* Smartly print an expression. */
939 1.1 skrll
940 1.1.1.3 christos static void
941 1.1.1.3 christos debug_exp (expressionS *t)
942 1.1.1.3 christos {
943 1.1.1.3 christos const char *name ATTRIBUTE_UNUSED;
944 1.1.1.3 christos const char *namemd ATTRIBUTE_UNUSED;
945 1.1 skrll
946 1.1.1.3 christos pr_debug ("debug_exp: ");
947 1.1 skrll
948 1.1.1.3 christos switch (t->X_op)
949 1.1 skrll {
950 1.1.1.3 christos default: name = "unknown"; break;
951 1.1.1.3 christos case O_illegal: name = "O_illegal"; break;
952 1.1.1.3 christos case O_absent: name = "O_absent"; break;
953 1.1.1.3 christos case O_constant: name = "O_constant"; break;
954 1.1.1.3 christos case O_symbol: name = "O_symbol"; break;
955 1.1.1.3 christos case O_symbol_rva: name = "O_symbol_rva"; break;
956 1.1.1.3 christos case O_register: name = "O_register"; break;
957 1.1.1.3 christos case O_big: name = "O_big"; break;
958 1.1.1.3 christos case O_uminus: name = "O_uminus"; break;
959 1.1.1.3 christos case O_bit_not: name = "O_bit_not"; break;
960 1.1.1.3 christos case O_logical_not: name = "O_logical_not"; break;
961 1.1.1.3 christos case O_multiply: name = "O_multiply"; break;
962 1.1.1.3 christos case O_divide: name = "O_divide"; break;
963 1.1.1.3 christos case O_modulus: name = "O_modulus"; break;
964 1.1.1.3 christos case O_left_shift: name = "O_left_shift"; break;
965 1.1.1.3 christos case O_right_shift: name = "O_right_shift"; break;
966 1.1.1.3 christos case O_bit_inclusive_or: name = "O_bit_inclusive_or"; break;
967 1.1.1.3 christos case O_bit_or_not: name = "O_bit_or_not"; break;
968 1.1.1.3 christos case O_bit_exclusive_or: name = "O_bit_exclusive_or"; break;
969 1.1.1.3 christos case O_bit_and: name = "O_bit_and"; break;
970 1.1.1.3 christos case O_add: name = "O_add"; break;
971 1.1.1.3 christos case O_subtract: name = "O_subtract"; break;
972 1.1.1.3 christos case O_eq: name = "O_eq"; break;
973 1.1.1.3 christos case O_ne: name = "O_ne"; break;
974 1.1.1.3 christos case O_lt: name = "O_lt"; break;
975 1.1.1.3 christos case O_le: name = "O_le"; break;
976 1.1.1.3 christos case O_ge: name = "O_ge"; break;
977 1.1.1.3 christos case O_gt: name = "O_gt"; break;
978 1.1.1.3 christos case O_logical_and: name = "O_logical_and"; break;
979 1.1.1.3 christos case O_logical_or: name = "O_logical_or"; break;
980 1.1.1.3 christos case O_index: name = "O_index"; break;
981 1.1.1.3 christos case O_bracket: name = "O_bracket"; break;
982 1.1.1.3 christos }
983 1.1.1.3 christos
984 1.1.1.3 christos switch (t->X_md)
985 1.1.1.3 christos {
986 1.1.1.3 christos default: namemd = "unknown"; break;
987 1.1.1.3 christos case O_gotoff: namemd = "O_gotoff"; break;
988 1.1.1.3 christos case O_gotpc: namemd = "O_gotpc"; break;
989 1.1.1.3 christos case O_plt: namemd = "O_plt"; break;
990 1.1.1.3 christos case O_sda: namemd = "O_sda"; break;
991 1.1.1.3 christos case O_pcl: namemd = "O_pcl"; break;
992 1.1.1.3 christos case O_tlsgd: namemd = "O_tlsgd"; break;
993 1.1.1.3 christos case O_tlsie: namemd = "O_tlsie"; break;
994 1.1.1.3 christos case O_tpoff9: namemd = "O_tpoff9"; break;
995 1.1.1.3 christos case O_tpoff: namemd = "O_tpoff"; break;
996 1.1.1.3 christos case O_dtpoff9: namemd = "O_dtpoff9"; break;
997 1.1.1.3 christos case O_dtpoff: namemd = "O_dtpoff"; break;
998 1.1.1.3 christos }
999 1.1.1.3 christos
1000 1.1.1.3 christos pr_debug ("%s (%s, %s, %d, %s)", name,
1001 1.1.1.3 christos (t->X_add_symbol) ? S_GET_NAME (t->X_add_symbol) : "--",
1002 1.1.1.3 christos (t->X_op_symbol) ? S_GET_NAME (t->X_op_symbol) : "--",
1003 1.1.1.3 christos (int) t->X_add_number,
1004 1.1.1.3 christos (t->X_md) ? namemd : "--");
1005 1.1.1.3 christos pr_debug ("\n");
1006 1.1.1.3 christos fflush (stderr);
1007 1.1.1.3 christos }
1008 1.1 skrll
1009 1.1.1.3 christos /* Parse the arguments to an opcode. */
1010 1.1 skrll
1011 1.1.1.3 christos static int
1012 1.1.1.3 christos tokenize_arguments (char *str,
1013 1.1.1.3 christos expressionS *tok,
1014 1.1.1.3 christos int ntok)
1015 1.1.1.3 christos {
1016 1.1.1.3 christos char *old_input_line_pointer;
1017 1.1.1.3 christos bfd_boolean saw_comma = FALSE;
1018 1.1.1.3 christos bfd_boolean saw_arg = FALSE;
1019 1.1.1.3 christos int brk_lvl = 0;
1020 1.1.1.3 christos int num_args = 0;
1021 1.1.1.3 christos int i;
1022 1.1.1.3 christos size_t len;
1023 1.1.1.3 christos const struct arc_reloc_op_tag *r;
1024 1.1.1.3 christos expressionS tmpE;
1025 1.1.1.3 christos char *reloc_name, c;
1026 1.1.1.3 christos
1027 1.1.1.3 christos memset (tok, 0, sizeof (*tok) * ntok);
1028 1.1.1.3 christos
1029 1.1.1.3 christos /* Save and restore input_line_pointer around this function. */
1030 1.1.1.3 christos old_input_line_pointer = input_line_pointer;
1031 1.1.1.3 christos input_line_pointer = str;
1032 1.1 skrll
1033 1.1.1.3 christos while (*input_line_pointer)
1034 1.1 skrll {
1035 1.1 skrll SKIP_WHITESPACE ();
1036 1.1.1.3 christos switch (*input_line_pointer)
1037 1.1 skrll {
1038 1.1.1.3 christos case '\0':
1039 1.1.1.3 christos goto fini;
1040 1.1 skrll
1041 1.1.1.3 christos case ',':
1042 1.1.1.3 christos input_line_pointer++;
1043 1.1.1.3 christos if (saw_comma || !saw_arg)
1044 1.1.1.3 christos goto err;
1045 1.1.1.3 christos saw_comma = TRUE;
1046 1.1.1.3 christos break;
1047 1.1 skrll
1048 1.1.1.3 christos case '}':
1049 1.1.1.3 christos case ']':
1050 1.1.1.3 christos ++input_line_pointer;
1051 1.1.1.3 christos --brk_lvl;
1052 1.1.1.3.2.2 pgoyette if (!saw_arg || num_args == ntok)
1053 1.1.1.3 christos goto err;
1054 1.1.1.3 christos tok->X_op = O_bracket;
1055 1.1.1.3 christos ++tok;
1056 1.1.1.3 christos ++num_args;
1057 1.1.1.3 christos break;
1058 1.1.1.3 christos
1059 1.1.1.3 christos case '{':
1060 1.1.1.3 christos case '[':
1061 1.1.1.3 christos input_line_pointer++;
1062 1.1.1.3.2.2 pgoyette if (brk_lvl || num_args == ntok)
1063 1.1.1.3 christos goto err;
1064 1.1.1.3 christos ++brk_lvl;
1065 1.1.1.3 christos tok->X_op = O_bracket;
1066 1.1.1.3 christos ++tok;
1067 1.1.1.3 christos ++num_args;
1068 1.1.1.3 christos break;
1069 1.1.1.3 christos
1070 1.1.1.3 christos case '@':
1071 1.1.1.3 christos /* We have labels, function names and relocations, all
1072 1.1.1.3 christos starting with @ symbol. Sort them out. */
1073 1.1.1.3.2.2 pgoyette if ((saw_arg && !saw_comma) || num_args == ntok)
1074 1.1.1.3 christos goto err;
1075 1.1.1.3 christos
1076 1.1.1.3 christos /* Parse @label. */
1077 1.1.1.3 christos tok->X_op = O_symbol;
1078 1.1.1.3 christos tok->X_md = O_absent;
1079 1.1.1.3 christos expression (tok);
1080 1.1.1.3 christos if (*input_line_pointer != '@')
1081 1.1.1.3 christos goto normalsymbol; /* This is not a relocation. */
1082 1.1.1.3 christos
1083 1.1.1.3 christos relocationsym:
1084 1.1.1.3 christos
1085 1.1.1.3 christos /* A relocation opernad has the following form
1086 1.1.1.3 christos @identifier@relocation_type. The identifier is already
1087 1.1.1.3 christos in tok! */
1088 1.1.1.3 christos if (tok->X_op != O_symbol)
1089 1.1 skrll {
1090 1.1.1.3 christos as_bad (_("No valid label relocation operand"));
1091 1.1.1.3 christos goto err;
1092 1.1 skrll }
1093 1.1.1.3 christos
1094 1.1.1.3 christos /* Parse @relocation_type. */
1095 1.1.1.3 christos input_line_pointer++;
1096 1.1.1.3 christos c = get_symbol_name (&reloc_name);
1097 1.1.1.3 christos len = input_line_pointer - reloc_name;
1098 1.1.1.3 christos if (len == 0)
1099 1.1 skrll {
1100 1.1.1.3 christos as_bad (_("No relocation operand"));
1101 1.1.1.3 christos goto err;
1102 1.1 skrll }
1103 1.1.1.3 christos
1104 1.1.1.3 christos /* Go through known relocation and try to find a match. */
1105 1.1.1.3 christos r = &arc_reloc_op[0];
1106 1.1.1.3 christos for (i = arc_num_reloc_op - 1; i >= 0; i--, r++)
1107 1.1.1.3 christos if (len == r->length
1108 1.1.1.3 christos && memcmp (reloc_name, r->name, len) == 0)
1109 1.1.1.3 christos break;
1110 1.1.1.3 christos if (i < 0)
1111 1.1 skrll {
1112 1.1.1.3 christos as_bad (_("Unknown relocation operand: @%s"), reloc_name);
1113 1.1.1.3 christos goto err;
1114 1.1 skrll }
1115 1.1 skrll
1116 1.1.1.3 christos *input_line_pointer = c;
1117 1.1.1.3 christos SKIP_WHITESPACE_AFTER_NAME ();
1118 1.1.1.3 christos /* Extra check for TLS: base. */
1119 1.1.1.3 christos if (*input_line_pointer == '@')
1120 1.1 skrll {
1121 1.1.1.3 christos symbolS *base;
1122 1.1.1.3 christos if (tok->X_op_symbol != NULL
1123 1.1.1.3 christos || tok->X_op != O_symbol)
1124 1.1.1.3 christos {
1125 1.1.1.3 christos as_bad (_("Unable to parse TLS base: %s"),
1126 1.1.1.3 christos input_line_pointer);
1127 1.1.1.3 christos goto err;
1128 1.1.1.3 christos }
1129 1.1.1.3 christos input_line_pointer++;
1130 1.1.1.3 christos char *sym_name;
1131 1.1.1.3 christos c = get_symbol_name (&sym_name);
1132 1.1.1.3 christos base = symbol_find_or_make (sym_name);
1133 1.1.1.3 christos tok->X_op = O_subtract;
1134 1.1.1.3 christos tok->X_op_symbol = base;
1135 1.1.1.3 christos restore_line_pointer (c);
1136 1.1.1.3 christos tmpE.X_add_number = 0;
1137 1.1.1.3 christos }
1138 1.1.1.3 christos else if ((*input_line_pointer != '+')
1139 1.1.1.3 christos && (*input_line_pointer != '-'))
1140 1.1.1.3 christos {
1141 1.1.1.3 christos tmpE.X_add_number = 0;
1142 1.1 skrll }
1143 1.1 skrll else
1144 1.1 skrll {
1145 1.1.1.3 christos /* Parse the constant of a complex relocation expression
1146 1.1.1.3 christos like @identifier@reloc +/- const. */
1147 1.1.1.3 christos if (! r->complex_expr)
1148 1.1 skrll {
1149 1.1.1.3 christos as_bad (_("@%s is not a complex relocation."), r->name);
1150 1.1.1.3 christos goto err;
1151 1.1 skrll }
1152 1.1.1.3 christos expression (&tmpE);
1153 1.1.1.3 christos if (tmpE.X_op != O_constant)
1154 1.1 skrll {
1155 1.1.1.3 christos as_bad (_("Bad expression: @%s + %s."),
1156 1.1.1.3 christos r->name, input_line_pointer);
1157 1.1.1.3 christos goto err;
1158 1.1 skrll }
1159 1.1 skrll }
1160 1.1 skrll
1161 1.1.1.3 christos tok->X_md = r->op;
1162 1.1.1.3 christos tok->X_add_number = tmpE.X_add_number;
1163 1.1 skrll
1164 1.1.1.3 christos debug_exp (tok);
1165 1.1 skrll
1166 1.1.1.3 christos saw_comma = FALSE;
1167 1.1.1.3 christos saw_arg = TRUE;
1168 1.1.1.3 christos tok++;
1169 1.1.1.3 christos num_args++;
1170 1.1.1.3 christos break;
1171 1.1 skrll
1172 1.1.1.3 christos case '%':
1173 1.1.1.3 christos /* Can be a register. */
1174 1.1.1.3 christos ++input_line_pointer;
1175 1.1.1.3 christos /* Fall through. */
1176 1.1.1.3 christos default:
1177 1.1.1.3 christos
1178 1.1.1.3.2.2 pgoyette if ((saw_arg && !saw_comma) || num_args == ntok)
1179 1.1.1.3 christos goto err;
1180 1.1.1.3 christos
1181 1.1.1.3 christos tok->X_op = O_absent;
1182 1.1.1.3 christos tok->X_md = O_absent;
1183 1.1.1.3 christos expression (tok);
1184 1.1.1.3 christos
1185 1.1.1.3 christos /* Legacy: There are cases when we have
1186 1.1.1.3 christos identifier@relocation_type, if it is the case parse the
1187 1.1.1.3 christos relocation type as well. */
1188 1.1.1.3 christos if (*input_line_pointer == '@')
1189 1.1.1.3 christos goto relocationsym;
1190 1.1.1.3 christos
1191 1.1.1.3 christos normalsymbol:
1192 1.1.1.3 christos debug_exp (tok);
1193 1.1.1.3 christos
1194 1.1.1.3.2.2 pgoyette if (tok->X_op == O_illegal
1195 1.1.1.3.2.2 pgoyette || tok->X_op == O_absent
1196 1.1.1.3.2.2 pgoyette || num_args == ntok)
1197 1.1.1.3 christos goto err;
1198 1.1.1.3 christos
1199 1.1.1.3 christos saw_comma = FALSE;
1200 1.1.1.3 christos saw_arg = TRUE;
1201 1.1.1.3 christos tok++;
1202 1.1.1.3 christos num_args++;
1203 1.1.1.3 christos break;
1204 1.1 skrll }
1205 1.1 skrll }
1206 1.1 skrll
1207 1.1.1.3 christos fini:
1208 1.1.1.3 christos if (saw_comma || brk_lvl)
1209 1.1.1.3 christos goto err;
1210 1.1.1.3 christos input_line_pointer = old_input_line_pointer;
1211 1.1.1.3 christos
1212 1.1.1.3 christos return num_args;
1213 1.1.1.3 christos
1214 1.1.1.3 christos err:
1215 1.1.1.3 christos if (brk_lvl)
1216 1.1.1.3 christos as_bad (_("Brackets in operand field incorrect"));
1217 1.1.1.3 christos else if (saw_comma)
1218 1.1.1.3 christos as_bad (_("extra comma"));
1219 1.1.1.3 christos else if (!saw_arg)
1220 1.1.1.3 christos as_bad (_("missing argument"));
1221 1.1.1.3 christos else
1222 1.1.1.3 christos as_bad (_("missing comma or colon"));
1223 1.1.1.3 christos input_line_pointer = old_input_line_pointer;
1224 1.1.1.3 christos return -1;
1225 1.1.1.3 christos }
1226 1.1 skrll
1227 1.1.1.3 christos /* Parse the flags to a structure. */
1228 1.1 skrll
1229 1.1.1.3 christos static int
1230 1.1.1.3 christos tokenize_flags (const char *str,
1231 1.1.1.3 christos struct arc_flags flags[],
1232 1.1.1.3 christos int nflg)
1233 1.1.1.3 christos {
1234 1.1.1.3 christos char *old_input_line_pointer;
1235 1.1.1.3 christos bfd_boolean saw_flg = FALSE;
1236 1.1.1.3 christos bfd_boolean saw_dot = FALSE;
1237 1.1.1.3 christos int num_flags = 0;
1238 1.1.1.3 christos size_t flgnamelen;
1239 1.1.1.3 christos
1240 1.1.1.3 christos memset (flags, 0, sizeof (*flags) * nflg);
1241 1.1.1.3 christos
1242 1.1.1.3 christos /* Save and restore input_line_pointer around this function. */
1243 1.1.1.3 christos old_input_line_pointer = input_line_pointer;
1244 1.1.1.3 christos input_line_pointer = (char *) str;
1245 1.1.1.3 christos
1246 1.1.1.3 christos while (*input_line_pointer)
1247 1.1.1.3 christos {
1248 1.1.1.3 christos switch (*input_line_pointer)
1249 1.1.1.3 christos {
1250 1.1.1.3 christos case ' ':
1251 1.1.1.3 christos case '\0':
1252 1.1.1.3 christos goto fini;
1253 1.1.1.3 christos
1254 1.1.1.3 christos case '.':
1255 1.1.1.3 christos input_line_pointer++;
1256 1.1.1.3 christos if (saw_dot)
1257 1.1.1.3 christos goto err;
1258 1.1.1.3 christos saw_dot = TRUE;
1259 1.1.1.3 christos saw_flg = FALSE;
1260 1.1.1.3 christos break;
1261 1.1 skrll
1262 1.1.1.3 christos default:
1263 1.1.1.3 christos if (saw_flg && !saw_dot)
1264 1.1.1.3 christos goto err;
1265 1.1 skrll
1266 1.1.1.3 christos if (num_flags >= nflg)
1267 1.1.1.3 christos goto err;
1268 1.1 skrll
1269 1.1.1.3.2.2 pgoyette flgnamelen = strspn (input_line_pointer,
1270 1.1.1.3.2.2 pgoyette "abcdefghijklmnopqrstuvwxyz0123456789");
1271 1.1.1.3.2.2 pgoyette if (flgnamelen > MAX_FLAG_NAME_LENGTH)
1272 1.1.1.3 christos goto err;
1273 1.1.1.3 christos
1274 1.1.1.3 christos memcpy (flags->name, input_line_pointer, flgnamelen);
1275 1.1.1.3 christos
1276 1.1.1.3 christos input_line_pointer += flgnamelen;
1277 1.1.1.3 christos flags++;
1278 1.1.1.3 christos saw_dot = FALSE;
1279 1.1.1.3 christos saw_flg = TRUE;
1280 1.1.1.3 christos num_flags++;
1281 1.1.1.3 christos break;
1282 1.1.1.3 christos }
1283 1.1 skrll }
1284 1.1 skrll
1285 1.1.1.3 christos fini:
1286 1.1.1.3 christos input_line_pointer = old_input_line_pointer;
1287 1.1.1.3 christos return num_flags;
1288 1.1.1.3 christos
1289 1.1.1.3 christos err:
1290 1.1.1.3 christos if (saw_dot)
1291 1.1.1.3 christos as_bad (_("extra dot"));
1292 1.1.1.3 christos else if (!saw_flg)
1293 1.1.1.3 christos as_bad (_("unrecognized flag"));
1294 1.1.1.3 christos else
1295 1.1.1.3 christos as_bad (_("failed to parse flags"));
1296 1.1.1.3 christos input_line_pointer = old_input_line_pointer;
1297 1.1.1.3 christos return -1;
1298 1.1 skrll }
1299 1.1 skrll
1300 1.1.1.3.2.2 pgoyette /* Apply the fixups in order. */
1301 1.1.1.3 christos
1302 1.1.1.3.2.2 pgoyette static void
1303 1.1.1.3.2.2 pgoyette apply_fixups (struct arc_insn *insn, fragS *fragP, int fix)
1304 1.1 skrll {
1305 1.1.1.3.2.2 pgoyette int i;
1306 1.1 skrll
1307 1.1.1.3.2.2 pgoyette for (i = 0; i < insn->nfixups; i++)
1308 1.1 skrll {
1309 1.1.1.3.2.2 pgoyette struct arc_fixup *fixup = &insn->fixups[i];
1310 1.1.1.3.2.2 pgoyette int size, pcrel, offset = 0;
1311 1.1 skrll
1312 1.1.1.3.2.2 pgoyette /* FIXME! the reloc size is wrong in the BFD file.
1313 1.1.1.3.2.2 pgoyette When it is fixed please delete me. */
1314 1.1.1.3.2.2 pgoyette size = (insn->short_insn && !fixup->islong) ? 2 : 4;
1315 1.1 skrll
1316 1.1.1.3.2.2 pgoyette if (fixup->islong)
1317 1.1.1.3.2.2 pgoyette offset = (insn->short_insn) ? 2 : 4;
1318 1.1 skrll
1319 1.1.1.3.2.2 pgoyette /* Some fixups are only used internally, thus no howto. */
1320 1.1.1.3.2.2 pgoyette if ((int) fixup->reloc == 0)
1321 1.1.1.3.2.2 pgoyette as_fatal (_("Unhandled reloc type"));
1322 1.1 skrll
1323 1.1.1.3.2.2 pgoyette if ((int) fixup->reloc < 0)
1324 1.1.1.3.2.2 pgoyette {
1325 1.1.1.3.2.2 pgoyette /* FIXME! the reloc size is wrong in the BFD file.
1326 1.1.1.3.2.2 pgoyette When it is fixed please enable me.
1327 1.1.1.3.2.2 pgoyette size = (insn->short_insn && !fixup->islong) ? 2 : 4; */
1328 1.1.1.3.2.2 pgoyette pcrel = fixup->pcrel;
1329 1.1.1.3.2.2 pgoyette }
1330 1.1.1.3.2.2 pgoyette else
1331 1.1.1.3.2.2 pgoyette {
1332 1.1.1.3.2.2 pgoyette reloc_howto_type *reloc_howto =
1333 1.1.1.3.2.2 pgoyette bfd_reloc_type_lookup (stdoutput,
1334 1.1.1.3.2.2 pgoyette (bfd_reloc_code_real_type) fixup->reloc);
1335 1.1.1.3.2.2 pgoyette gas_assert (reloc_howto);
1336 1.1 skrll
1337 1.1.1.3.2.2 pgoyette /* FIXME! the reloc size is wrong in the BFD file.
1338 1.1.1.3.2.2 pgoyette When it is fixed please enable me.
1339 1.1.1.3.2.2 pgoyette size = bfd_get_reloc_size (reloc_howto); */
1340 1.1.1.3.2.2 pgoyette pcrel = reloc_howto->pc_relative;
1341 1.1.1.3.2.2 pgoyette }
1342 1.1 skrll
1343 1.1.1.3.2.2 pgoyette pr_debug ("%s:%d: apply_fixups: new %s fixup (PCrel:%s) of size %d @ \
1344 1.1.1.3.2.2 pgoyette offset %d + %d\n",
1345 1.1.1.3.2.2 pgoyette fragP->fr_file, fragP->fr_line,
1346 1.1.1.3.2.2 pgoyette (fixup->reloc < 0) ? "Internal" :
1347 1.1.1.3.2.2 pgoyette bfd_get_reloc_code_name (fixup->reloc),
1348 1.1.1.3.2.2 pgoyette pcrel ? "Y" : "N",
1349 1.1.1.3.2.2 pgoyette size, fix, offset);
1350 1.1.1.3.2.2 pgoyette fix_new_exp (fragP, fix + offset,
1351 1.1.1.3.2.2 pgoyette size, &fixup->exp, pcrel, fixup->reloc);
1352 1.1 skrll
1353 1.1.1.3.2.2 pgoyette /* Check for ZOLs, and update symbol info if any. */
1354 1.1.1.3.2.2 pgoyette if (LP_INSN (insn->insn))
1355 1.1 skrll {
1356 1.1.1.3.2.2 pgoyette gas_assert (fixup->exp.X_add_symbol);
1357 1.1.1.3.2.2 pgoyette ARC_SET_FLAG (fixup->exp.X_add_symbol, ARC_FLAG_ZOL);
1358 1.1 skrll }
1359 1.1 skrll }
1360 1.1.1.3 christos }
1361 1.1 skrll
1362 1.1.1.3.2.2 pgoyette /* Actually output an instruction with its fixup. */
1363 1.1 skrll
1364 1.1.1.3.2.2 pgoyette static void
1365 1.1.1.3.2.2 pgoyette emit_insn0 (struct arc_insn *insn, char *where, bfd_boolean relax)
1366 1.1.1.3 christos {
1367 1.1.1.3.2.2 pgoyette char *f = where;
1368 1.1 skrll
1369 1.1.1.3.2.2 pgoyette pr_debug ("Emit insn : 0x%x\n", insn->insn);
1370 1.1.1.3.2.2 pgoyette pr_debug ("\tShort : 0x%d\n", insn->short_insn);
1371 1.1.1.3.2.2 pgoyette pr_debug ("\tLong imm: 0x%lx\n", insn->limm);
1372 1.1 skrll
1373 1.1.1.3.2.2 pgoyette /* Write out the instruction. */
1374 1.1.1.3.2.2 pgoyette if (insn->short_insn)
1375 1.1.1.3 christos {
1376 1.1.1.3.2.2 pgoyette if (insn->has_limm)
1377 1.1.1.3.2.2 pgoyette {
1378 1.1.1.3.2.2 pgoyette if (!relax)
1379 1.1.1.3.2.2 pgoyette f = frag_more (6);
1380 1.1.1.3.2.2 pgoyette md_number_to_chars (f, insn->insn, 2);
1381 1.1.1.3.2.2 pgoyette md_number_to_chars_midend (f + 2, insn->limm, 4);
1382 1.1.1.3.2.2 pgoyette dwarf2_emit_insn (6);
1383 1.1.1.3.2.2 pgoyette }
1384 1.1.1.3.2.2 pgoyette else
1385 1.1.1.3.2.2 pgoyette {
1386 1.1.1.3.2.2 pgoyette if (!relax)
1387 1.1.1.3.2.2 pgoyette f = frag_more (2);
1388 1.1.1.3.2.2 pgoyette md_number_to_chars (f, insn->insn, 2);
1389 1.1.1.3.2.2 pgoyette dwarf2_emit_insn (2);
1390 1.1.1.3.2.2 pgoyette }
1391 1.1.1.3.2.2 pgoyette }
1392 1.1.1.3.2.2 pgoyette else
1393 1.1.1.3.2.2 pgoyette {
1394 1.1.1.3.2.2 pgoyette if (insn->has_limm)
1395 1.1.1.3.2.2 pgoyette {
1396 1.1.1.3.2.2 pgoyette if (!relax)
1397 1.1.1.3.2.2 pgoyette f = frag_more (8);
1398 1.1.1.3.2.2 pgoyette md_number_to_chars_midend (f, insn->insn, 4);
1399 1.1.1.3.2.2 pgoyette md_number_to_chars_midend (f + 4, insn->limm, 4);
1400 1.1.1.3.2.2 pgoyette dwarf2_emit_insn (8);
1401 1.1.1.3.2.2 pgoyette }
1402 1.1.1.3.2.2 pgoyette else
1403 1.1.1.3.2.2 pgoyette {
1404 1.1.1.3.2.2 pgoyette if (!relax)
1405 1.1.1.3.2.2 pgoyette f = frag_more (4);
1406 1.1.1.3.2.2 pgoyette md_number_to_chars_midend (f, insn->insn, 4);
1407 1.1.1.3.2.2 pgoyette dwarf2_emit_insn (4);
1408 1.1.1.3.2.2 pgoyette }
1409 1.1 skrll }
1410 1.1 skrll
1411 1.1.1.3.2.2 pgoyette if (!relax)
1412 1.1.1.3.2.2 pgoyette apply_fixups (insn, frag_now, (f - frag_now->fr_literal));
1413 1.1.1.3.2.2 pgoyette }
1414 1.1.1.3 christos
1415 1.1.1.3.2.2 pgoyette static void
1416 1.1.1.3.2.2 pgoyette emit_insn1 (struct arc_insn *insn)
1417 1.1.1.3.2.2 pgoyette {
1418 1.1.1.3.2.2 pgoyette /* How frag_var's args are currently configured:
1419 1.1.1.3.2.2 pgoyette - rs_machine_dependent, to dictate it's a relaxation frag.
1420 1.1.1.3.2.2 pgoyette - FRAG_MAX_GROWTH, maximum size of instruction
1421 1.1.1.3.2.2 pgoyette - 0, variable size that might grow...unused by generic relaxation.
1422 1.1.1.3.2.2 pgoyette - frag_now->fr_subtype, fr_subtype starting value, set previously.
1423 1.1.1.3.2.2 pgoyette - s, opand expression.
1424 1.1.1.3.2.2 pgoyette - 0, offset but it's unused.
1425 1.1.1.3.2.2 pgoyette - 0, opcode but it's unused. */
1426 1.1.1.3.2.2 pgoyette symbolS *s = make_expr_symbol (&insn->fixups[0].exp);
1427 1.1.1.3.2.2 pgoyette frag_now->tc_frag_data.pcrel = insn->fixups[0].pcrel;
1428 1.1.1.3.2.2 pgoyette
1429 1.1.1.3.2.2 pgoyette if (frag_room () < FRAG_MAX_GROWTH)
1430 1.1.1.3.2.2 pgoyette {
1431 1.1.1.3.2.2 pgoyette /* Handle differently when frag literal memory is exhausted.
1432 1.1.1.3.2.2 pgoyette This is used because when there's not enough memory left in
1433 1.1.1.3.2.2 pgoyette the current frag, a new frag is created and the information
1434 1.1.1.3.2.2 pgoyette we put into frag_now->tc_frag_data is disregarded. */
1435 1.1.1.3.2.2 pgoyette
1436 1.1.1.3.2.2 pgoyette struct arc_relax_type relax_info_copy;
1437 1.1.1.3.2.2 pgoyette relax_substateT subtype = frag_now->fr_subtype;
1438 1.1.1.3.2.2 pgoyette
1439 1.1.1.3.2.2 pgoyette memcpy (&relax_info_copy, &frag_now->tc_frag_data,
1440 1.1.1.3.2.2 pgoyette sizeof (struct arc_relax_type));
1441 1.1 skrll
1442 1.1.1.3.2.2 pgoyette frag_wane (frag_now);
1443 1.1.1.3.2.2 pgoyette frag_grow (FRAG_MAX_GROWTH);
1444 1.1 skrll
1445 1.1.1.3.2.2 pgoyette memcpy (&frag_now->tc_frag_data, &relax_info_copy,
1446 1.1.1.3.2.2 pgoyette sizeof (struct arc_relax_type));
1447 1.1.1.3 christos
1448 1.1.1.3.2.2 pgoyette frag_var (rs_machine_dependent, FRAG_MAX_GROWTH, 0,
1449 1.1.1.3.2.2 pgoyette subtype, s, 0, 0);
1450 1.1.1.3.2.2 pgoyette }
1451 1.1.1.3.2.2 pgoyette else
1452 1.1.1.3.2.2 pgoyette frag_var (rs_machine_dependent, FRAG_MAX_GROWTH, 0,
1453 1.1.1.3.2.2 pgoyette frag_now->fr_subtype, s, 0, 0);
1454 1.1 skrll }
1455 1.1 skrll
1456 1.1.1.3.2.2 pgoyette static void
1457 1.1.1.3.2.2 pgoyette emit_insn (struct arc_insn *insn)
1458 1.1 skrll {
1459 1.1.1.3.2.2 pgoyette if (insn->relax)
1460 1.1.1.3.2.2 pgoyette emit_insn1 (insn);
1461 1.1 skrll else
1462 1.1.1.3.2.2 pgoyette emit_insn0 (insn, NULL, FALSE);
1463 1.1 skrll }
1464 1.1 skrll
1465 1.1.1.3.2.2 pgoyette /* Check whether a symbol involves a register. */
1466 1.1 skrll
1467 1.1.1.3.2.2 pgoyette static bfd_boolean
1468 1.1.1.3.2.2 pgoyette contains_register (symbolS *sym)
1469 1.1 skrll {
1470 1.1.1.3.2.2 pgoyette if (sym)
1471 1.1.1.3.2.2 pgoyette {
1472 1.1.1.3.2.2 pgoyette expressionS *ex = symbol_get_value_expression (sym);
1473 1.1.1.3.2.2 pgoyette
1474 1.1.1.3.2.2 pgoyette return ((O_register == ex->X_op)
1475 1.1.1.3.2.2 pgoyette && !contains_register (ex->X_add_symbol)
1476 1.1.1.3.2.2 pgoyette && !contains_register (ex->X_op_symbol));
1477 1.1.1.3.2.2 pgoyette }
1478 1.1 skrll
1479 1.1.1.3.2.2 pgoyette return FALSE;
1480 1.1 skrll }
1481 1.1 skrll
1482 1.1.1.3.2.2 pgoyette /* Returns the register number within a symbol. */
1483 1.1 skrll
1484 1.1.1.3.2.2 pgoyette static int
1485 1.1.1.3.2.2 pgoyette get_register (symbolS *sym)
1486 1.1 skrll {
1487 1.1.1.3.2.2 pgoyette if (!contains_register (sym))
1488 1.1.1.3.2.2 pgoyette return -1;
1489 1.1 skrll
1490 1.1.1.3.2.2 pgoyette expressionS *ex = symbol_get_value_expression (sym);
1491 1.1.1.3.2.2 pgoyette return regno (ex->X_add_number);
1492 1.1.1.3.2.2 pgoyette }
1493 1.1 skrll
1494 1.1.1.3.2.2 pgoyette /* Return true if a RELOC is generic. A generic reloc is PC-rel of a
1495 1.1.1.3.2.2 pgoyette simple ME relocation (e.g. RELOC_ARC_32_ME, BFD_RELOC_ARC_PC32. */
1496 1.1 skrll
1497 1.1.1.3.2.2 pgoyette static bfd_boolean
1498 1.1.1.3.2.2 pgoyette generic_reloc_p (extended_bfd_reloc_code_real_type reloc)
1499 1.1.1.3.2.2 pgoyette {
1500 1.1.1.3.2.2 pgoyette if (!reloc)
1501 1.1.1.3.2.2 pgoyette return FALSE;
1502 1.1 skrll
1503 1.1.1.3.2.2 pgoyette switch (reloc)
1504 1.1 skrll {
1505 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_SDA_LDST:
1506 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_SDA_LDST1:
1507 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_SDA_LDST2:
1508 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_SDA16_LD:
1509 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_SDA16_LD1:
1510 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_SDA16_LD2:
1511 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_SDA16_ST2:
1512 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_SDA32_ME:
1513 1.1.1.3.2.2 pgoyette return FALSE;
1514 1.1.1.3.2.2 pgoyette default:
1515 1.1.1.3.2.2 pgoyette return TRUE;
1516 1.1 skrll }
1517 1.1 skrll }
1518 1.1 skrll
1519 1.1.1.3.2.2 pgoyette /* Allocates a tok entry. */
1520 1.1 skrll
1521 1.1.1.3.2.2 pgoyette static int
1522 1.1.1.3.2.2 pgoyette allocate_tok (expressionS *tok, int ntok, int cidx)
1523 1.1 skrll {
1524 1.1.1.3.2.2 pgoyette if (ntok > MAX_INSN_ARGS - 2)
1525 1.1.1.3.2.2 pgoyette return 0; /* No space left. */
1526 1.1 skrll
1527 1.1.1.3.2.2 pgoyette if (cidx > ntok)
1528 1.1.1.3.2.2 pgoyette return 0; /* Incorect args. */
1529 1.1.1.3.2.2 pgoyette
1530 1.1.1.3.2.2 pgoyette memcpy (&tok[ntok+1], &tok[ntok], sizeof (*tok));
1531 1.1.1.3.2.2 pgoyette
1532 1.1.1.3.2.2 pgoyette if (cidx == ntok)
1533 1.1.1.3.2.2 pgoyette return 1; /* Success. */
1534 1.1.1.3.2.2 pgoyette return allocate_tok (tok, ntok - 1, cidx);
1535 1.1 skrll }
1536 1.1 skrll
1537 1.1.1.3.2.2 pgoyette /* Check if an particular ARC feature is enabled. */
1538 1.1 skrll
1539 1.1.1.3.2.2 pgoyette static bfd_boolean
1540 1.1.1.3.2.2 pgoyette check_cpu_feature (insn_subclass_t sc)
1541 1.1.1.3 christos {
1542 1.1.1.3.2.2 pgoyette if (is_code_density_p (sc) && !(arc_features & ARC_CD))
1543 1.1.1.3.2.2 pgoyette return FALSE;
1544 1.1.1.3 christos
1545 1.1.1.3.2.2 pgoyette if (is_spfp_p (sc) && !(arc_features & ARC_SPFP))
1546 1.1.1.3.2.2 pgoyette return FALSE;
1547 1.1.1.3 christos
1548 1.1.1.3.2.2 pgoyette if (is_dpfp_p (sc) && !(arc_features & ARC_DPFP))
1549 1.1.1.3.2.2 pgoyette return FALSE;
1550 1.1.1.3 christos
1551 1.1.1.3.2.2 pgoyette if (is_fpuda_p (sc) && !(arc_features & ARC_FPUDA))
1552 1.1.1.3.2.2 pgoyette return FALSE;
1553 1.1.1.3 christos
1554 1.1.1.3.2.2 pgoyette if (is_nps400_p (sc) && !(arc_features & ARC_NPS400))
1555 1.1.1.3.2.2 pgoyette return FALSE;
1556 1.1.1.3 christos
1557 1.1.1.3.2.2 pgoyette return TRUE;
1558 1.1.1.3.2.2 pgoyette }
1559 1.1.1.3.2.2 pgoyette
1560 1.1.1.3.2.2 pgoyette /* Parse the flags described by FIRST_PFLAG and NFLGS against the flag
1561 1.1.1.3.2.2 pgoyette operands in OPCODE. Stores the matching OPCODES into the FIRST_PFLAG
1562 1.1.1.3.2.2 pgoyette array and returns TRUE if the flag operands all match, otherwise,
1563 1.1.1.3.2.2 pgoyette returns FALSE, in which case the FIRST_PFLAG array may have been
1564 1.1.1.3.2.2 pgoyette modified. */
1565 1.1.1.3.2.2 pgoyette
1566 1.1.1.3.2.2 pgoyette static bfd_boolean
1567 1.1.1.3.2.2 pgoyette parse_opcode_flags (const struct arc_opcode *opcode,
1568 1.1.1.3.2.2 pgoyette int nflgs,
1569 1.1.1.3.2.2 pgoyette struct arc_flags *first_pflag)
1570 1.1.1.3.2.2 pgoyette {
1571 1.1.1.3.2.2 pgoyette int lnflg, i;
1572 1.1.1.3.2.2 pgoyette const unsigned char *flgidx;
1573 1.1.1.3.2.2 pgoyette
1574 1.1.1.3.2.2 pgoyette lnflg = nflgs;
1575 1.1.1.3.2.2 pgoyette for (i = 0; i < nflgs; i++)
1576 1.1.1.3.2.2 pgoyette first_pflag[i].flgp = NULL;
1577 1.1.1.3.2.2 pgoyette
1578 1.1.1.3.2.2 pgoyette /* Check the flags. Iterate over the valid flag classes. */
1579 1.1.1.3.2.2 pgoyette for (flgidx = opcode->flags; *flgidx; ++flgidx)
1580 1.1.1.3.2.2 pgoyette {
1581 1.1.1.3.2.2 pgoyette /* Get a valid flag class. */
1582 1.1.1.3.2.2 pgoyette const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
1583 1.1.1.3.2.2 pgoyette const unsigned *flgopridx;
1584 1.1.1.3.2.2 pgoyette int cl_matches = 0;
1585 1.1.1.3.2.2 pgoyette struct arc_flags *pflag = NULL;
1586 1.1.1.3.2.2 pgoyette
1587 1.1.1.3.2.2 pgoyette /* Check for extension conditional codes. */
1588 1.1.1.3.2.2 pgoyette if (ext_condcode.arc_ext_condcode
1589 1.1.1.3.2.2 pgoyette && cl_flags->flag_class & F_CLASS_EXTEND)
1590 1.1.1.3.2.2 pgoyette {
1591 1.1.1.3.2.2 pgoyette struct arc_flag_operand *pf = ext_condcode.arc_ext_condcode;
1592 1.1.1.3.2.2 pgoyette while (pf->name)
1593 1.1.1.3.2.2 pgoyette {
1594 1.1.1.3.2.2 pgoyette pflag = first_pflag;
1595 1.1.1.3.2.2 pgoyette for (i = 0; i < nflgs; i++, pflag++)
1596 1.1.1.3.2.2 pgoyette {
1597 1.1.1.3.2.2 pgoyette if (!strcmp (pf->name, pflag->name))
1598 1.1.1.3.2.2 pgoyette {
1599 1.1.1.3.2.2 pgoyette if (pflag->flgp != NULL)
1600 1.1.1.3.2.2 pgoyette return FALSE;
1601 1.1.1.3.2.2 pgoyette /* Found it. */
1602 1.1.1.3.2.2 pgoyette cl_matches++;
1603 1.1.1.3.2.2 pgoyette pflag->flgp = pf;
1604 1.1.1.3.2.2 pgoyette lnflg--;
1605 1.1.1.3.2.2 pgoyette break;
1606 1.1.1.3.2.2 pgoyette }
1607 1.1.1.3.2.2 pgoyette }
1608 1.1.1.3.2.2 pgoyette pf++;
1609 1.1.1.3.2.2 pgoyette }
1610 1.1.1.3.2.2 pgoyette }
1611 1.1.1.3.2.2 pgoyette
1612 1.1.1.3.2.2 pgoyette for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
1613 1.1.1.3.2.2 pgoyette {
1614 1.1.1.3.2.2 pgoyette const struct arc_flag_operand *flg_operand;
1615 1.1.1.3.2.2 pgoyette
1616 1.1.1.3.2.2 pgoyette pflag = first_pflag;
1617 1.1.1.3.2.2 pgoyette flg_operand = &arc_flag_operands[*flgopridx];
1618 1.1.1.3.2.2 pgoyette for (i = 0; i < nflgs; i++, pflag++)
1619 1.1.1.3.2.2 pgoyette {
1620 1.1.1.3.2.2 pgoyette /* Match against the parsed flags. */
1621 1.1.1.3.2.2 pgoyette if (!strcmp (flg_operand->name, pflag->name))
1622 1.1.1.3.2.2 pgoyette {
1623 1.1.1.3.2.2 pgoyette if (pflag->flgp != NULL)
1624 1.1.1.3.2.2 pgoyette return FALSE;
1625 1.1.1.3.2.2 pgoyette cl_matches++;
1626 1.1.1.3.2.2 pgoyette pflag->flgp = flg_operand;
1627 1.1.1.3.2.2 pgoyette lnflg--;
1628 1.1.1.3.2.2 pgoyette break; /* goto next flag class and parsed flag. */
1629 1.1.1.3.2.2 pgoyette }
1630 1.1.1.3.2.2 pgoyette }
1631 1.1.1.3.2.2 pgoyette }
1632 1.1.1.3.2.2 pgoyette
1633 1.1.1.3.2.2 pgoyette if ((cl_flags->flag_class & F_CLASS_REQUIRED) && cl_matches == 0)
1634 1.1.1.3.2.2 pgoyette return FALSE;
1635 1.1.1.3.2.2 pgoyette if ((cl_flags->flag_class & F_CLASS_OPTIONAL) && cl_matches > 1)
1636 1.1.1.3.2.2 pgoyette return FALSE;
1637 1.1 skrll }
1638 1.1.1.3 christos
1639 1.1.1.3.2.2 pgoyette /* Did I check all the parsed flags? */
1640 1.1.1.3.2.2 pgoyette return lnflg ? FALSE : TRUE;
1641 1.1.1.3.2.2 pgoyette }
1642 1.1.1.3.2.2 pgoyette
1643 1.1.1.3.2.2 pgoyette
1644 1.1.1.3.2.2 pgoyette /* Search forward through all variants of an opcode looking for a
1645 1.1.1.3.2.2 pgoyette syntax match. */
1646 1.1.1.3.2.2 pgoyette
1647 1.1.1.3.2.2 pgoyette static const struct arc_opcode *
1648 1.1.1.3.2.2 pgoyette find_opcode_match (const struct arc_opcode_hash_entry *entry,
1649 1.1.1.3.2.2 pgoyette expressionS *tok,
1650 1.1.1.3.2.2 pgoyette int *pntok,
1651 1.1.1.3.2.2 pgoyette struct arc_flags *first_pflag,
1652 1.1.1.3.2.2 pgoyette int nflgs,
1653 1.1.1.3.2.2 pgoyette int *pcpumatch)
1654 1.1.1.3.2.2 pgoyette {
1655 1.1.1.3.2.2 pgoyette const struct arc_opcode *opcode;
1656 1.1.1.3.2.2 pgoyette struct arc_opcode_hash_entry_iterator iter;
1657 1.1.1.3.2.2 pgoyette int ntok = *pntok;
1658 1.1.1.3.2.2 pgoyette int got_cpu_match = 0;
1659 1.1.1.3.2.2 pgoyette expressionS bktok[MAX_INSN_ARGS];
1660 1.1.1.3.2.2 pgoyette int bkntok;
1661 1.1.1.3.2.2 pgoyette expressionS emptyE;
1662 1.1.1.3.2.2 pgoyette
1663 1.1.1.3.2.2 pgoyette arc_opcode_hash_entry_iterator_init (&iter);
1664 1.1.1.3.2.2 pgoyette memset (&emptyE, 0, sizeof (emptyE));
1665 1.1.1.3.2.2 pgoyette memcpy (bktok, tok, MAX_INSN_ARGS * sizeof (*tok));
1666 1.1.1.3.2.2 pgoyette bkntok = ntok;
1667 1.1.1.3.2.2 pgoyette
1668 1.1.1.3.2.2 pgoyette for (opcode = arc_opcode_hash_entry_iterator_next (entry, &iter);
1669 1.1.1.3.2.2 pgoyette opcode != NULL;
1670 1.1.1.3.2.2 pgoyette opcode = arc_opcode_hash_entry_iterator_next (entry, &iter))
1671 1.1 skrll {
1672 1.1.1.3.2.2 pgoyette const unsigned char *opidx;
1673 1.1.1.3.2.2 pgoyette int tokidx = 0;
1674 1.1.1.3.2.2 pgoyette const expressionS *t = &emptyE;
1675 1.1.1.3.2.2 pgoyette
1676 1.1.1.3.2.2 pgoyette pr_debug ("%s:%d: find_opcode_match: trying opcode 0x%08X ",
1677 1.1.1.3.2.2 pgoyette frag_now->fr_file, frag_now->fr_line, opcode->opcode);
1678 1.1.1.3.2.2 pgoyette
1679 1.1.1.3.2.2 pgoyette /* Don't match opcodes that don't exist on this
1680 1.1.1.3.2.2 pgoyette architecture. */
1681 1.1.1.3.2.2 pgoyette if (!(opcode->cpu & arc_target))
1682 1.1.1.3.2.2 pgoyette goto match_failed;
1683 1.1.1.3.2.2 pgoyette
1684 1.1.1.3.2.2 pgoyette if (!check_cpu_feature (opcode->subclass))
1685 1.1.1.3.2.2 pgoyette goto match_failed;
1686 1.1.1.3.2.2 pgoyette
1687 1.1.1.3.2.2 pgoyette got_cpu_match = 1;
1688 1.1.1.3.2.2 pgoyette pr_debug ("cpu ");
1689 1.1.1.3.2.2 pgoyette
1690 1.1.1.3.2.2 pgoyette /* Check the operands. */
1691 1.1.1.3.2.2 pgoyette for (opidx = opcode->operands; *opidx; ++opidx)
1692 1.1.1.3 christos {
1693 1.1.1.3.2.2 pgoyette const struct arc_operand *operand = &arc_operands[*opidx];
1694 1.1.1.3.2.2 pgoyette
1695 1.1.1.3.2.2 pgoyette /* Only take input from real operands. */
1696 1.1.1.3.2.2 pgoyette if ((operand->flags & ARC_OPERAND_FAKE)
1697 1.1.1.3.2.2 pgoyette && !(operand->flags & ARC_OPERAND_BRAKET))
1698 1.1.1.3.2.2 pgoyette continue;
1699 1.1.1.3.2.2 pgoyette
1700 1.1.1.3.2.2 pgoyette /* When we expect input, make sure we have it. */
1701 1.1.1.3.2.2 pgoyette if (tokidx >= ntok)
1702 1.1.1.3.2.2 pgoyette goto match_failed;
1703 1.1.1.3.2.2 pgoyette
1704 1.1.1.3.2.2 pgoyette /* Match operand type with expression type. */
1705 1.1.1.3.2.2 pgoyette switch (operand->flags & ARC_OPERAND_TYPECHECK_MASK)
1706 1.1.1.3.2.2 pgoyette {
1707 1.1.1.3.2.2 pgoyette case ARC_OPERAND_IR:
1708 1.1.1.3.2.2 pgoyette /* Check to be a register. */
1709 1.1.1.3.2.2 pgoyette if ((tok[tokidx].X_op != O_register
1710 1.1.1.3.2.2 pgoyette || !is_ir_num (tok[tokidx].X_add_number))
1711 1.1.1.3.2.2 pgoyette && !(operand->flags & ARC_OPERAND_IGNORE))
1712 1.1.1.3.2.2 pgoyette goto match_failed;
1713 1.1.1.3.2.2 pgoyette
1714 1.1.1.3.2.2 pgoyette /* If expect duplicate, make sure it is duplicate. */
1715 1.1.1.3.2.2 pgoyette if (operand->flags & ARC_OPERAND_DUPLICATE)
1716 1.1.1.3.2.2 pgoyette {
1717 1.1.1.3.2.2 pgoyette /* Check for duplicate. */
1718 1.1.1.3.2.2 pgoyette if (t->X_op != O_register
1719 1.1.1.3.2.2 pgoyette || !is_ir_num (t->X_add_number)
1720 1.1.1.3.2.2 pgoyette || (regno (t->X_add_number) !=
1721 1.1.1.3.2.2 pgoyette regno (tok[tokidx].X_add_number)))
1722 1.1.1.3.2.2 pgoyette goto match_failed;
1723 1.1.1.3.2.2 pgoyette }
1724 1.1.1.3.2.2 pgoyette
1725 1.1.1.3.2.2 pgoyette /* Special handling? */
1726 1.1.1.3.2.2 pgoyette if (operand->insert)
1727 1.1.1.3.2.2 pgoyette {
1728 1.1.1.3.2.2 pgoyette const char *errmsg = NULL;
1729 1.1.1.3.2.2 pgoyette (*operand->insert)(0,
1730 1.1.1.3.2.2 pgoyette regno (tok[tokidx].X_add_number),
1731 1.1.1.3.2.2 pgoyette &errmsg);
1732 1.1.1.3.2.2 pgoyette if (errmsg)
1733 1.1.1.3.2.2 pgoyette {
1734 1.1.1.3.2.2 pgoyette if (operand->flags & ARC_OPERAND_IGNORE)
1735 1.1.1.3.2.2 pgoyette {
1736 1.1.1.3.2.2 pgoyette /* Missing argument, create one. */
1737 1.1.1.3.2.2 pgoyette if (!allocate_tok (tok, ntok - 1, tokidx))
1738 1.1.1.3.2.2 pgoyette goto match_failed;
1739 1.1.1.3.2.2 pgoyette
1740 1.1.1.3.2.2 pgoyette tok[tokidx].X_op = O_absent;
1741 1.1.1.3.2.2 pgoyette ++ntok;
1742 1.1.1.3.2.2 pgoyette }
1743 1.1.1.3.2.2 pgoyette else
1744 1.1.1.3.2.2 pgoyette goto match_failed;
1745 1.1.1.3.2.2 pgoyette }
1746 1.1.1.3.2.2 pgoyette }
1747 1.1.1.3.2.2 pgoyette
1748 1.1.1.3.2.2 pgoyette t = &tok[tokidx];
1749 1.1.1.3.2.2 pgoyette break;
1750 1.1.1.3.2.2 pgoyette
1751 1.1.1.3.2.2 pgoyette case ARC_OPERAND_BRAKET:
1752 1.1.1.3.2.2 pgoyette /* Check if bracket is also in opcode table as
1753 1.1.1.3.2.2 pgoyette operand. */
1754 1.1.1.3.2.2 pgoyette if (tok[tokidx].X_op != O_bracket)
1755 1.1.1.3.2.2 pgoyette goto match_failed;
1756 1.1.1.3.2.2 pgoyette break;
1757 1.1.1.3.2.2 pgoyette
1758 1.1.1.3.2.2 pgoyette case ARC_OPERAND_LIMM:
1759 1.1.1.3.2.2 pgoyette case ARC_OPERAND_SIGNED:
1760 1.1.1.3.2.2 pgoyette case ARC_OPERAND_UNSIGNED:
1761 1.1.1.3.2.2 pgoyette switch (tok[tokidx].X_op)
1762 1.1.1.3.2.2 pgoyette {
1763 1.1.1.3.2.2 pgoyette case O_illegal:
1764 1.1.1.3.2.2 pgoyette case O_absent:
1765 1.1.1.3.2.2 pgoyette case O_register:
1766 1.1.1.3.2.2 pgoyette goto match_failed;
1767 1.1.1.3.2.2 pgoyette
1768 1.1.1.3.2.2 pgoyette case O_bracket:
1769 1.1.1.3.2.2 pgoyette /* Got an (too) early bracket, check if it is an
1770 1.1.1.3.2.2 pgoyette ignored operand. N.B. This procedure works only
1771 1.1.1.3.2.2 pgoyette when bracket is the last operand! */
1772 1.1.1.3.2.2 pgoyette if (!(operand->flags & ARC_OPERAND_IGNORE))
1773 1.1.1.3.2.2 pgoyette goto match_failed;
1774 1.1.1.3.2.2 pgoyette /* Insert the missing operand. */
1775 1.1.1.3.2.2 pgoyette if (!allocate_tok (tok, ntok - 1, tokidx))
1776 1.1.1.3.2.2 pgoyette goto match_failed;
1777 1.1.1.3.2.2 pgoyette
1778 1.1.1.3.2.2 pgoyette tok[tokidx].X_op = O_absent;
1779 1.1.1.3.2.2 pgoyette ++ntok;
1780 1.1.1.3.2.2 pgoyette break;
1781 1.1.1.3.2.2 pgoyette
1782 1.1.1.3.2.2 pgoyette case O_symbol:
1783 1.1.1.3.2.2 pgoyette {
1784 1.1.1.3.2.2 pgoyette const char *p;
1785 1.1.1.3.2.2 pgoyette const struct arc_aux_reg *auxr;
1786 1.1.1.3.2.2 pgoyette
1787 1.1.1.3.2.2 pgoyette if (opcode->insn_class != AUXREG)
1788 1.1.1.3.2.2 pgoyette goto de_fault;
1789 1.1.1.3.2.2 pgoyette p = S_GET_NAME (tok[tokidx].X_add_symbol);
1790 1.1.1.3.2.2 pgoyette
1791 1.1.1.3.2.2 pgoyette auxr = hash_find (arc_aux_hash, p);
1792 1.1.1.3.2.2 pgoyette if (auxr)
1793 1.1.1.3.2.2 pgoyette {
1794 1.1.1.3.2.2 pgoyette /* We modify the token array here, safe in the
1795 1.1.1.3.2.2 pgoyette knowledge, that if this was the wrong
1796 1.1.1.3.2.2 pgoyette choice then the original contents will be
1797 1.1.1.3.2.2 pgoyette restored from BKTOK. */
1798 1.1.1.3.2.2 pgoyette tok[tokidx].X_op = O_constant;
1799 1.1.1.3.2.2 pgoyette tok[tokidx].X_add_number = auxr->address;
1800 1.1.1.3.2.2 pgoyette ARC_SET_FLAG (tok[tokidx].X_add_symbol, ARC_FLAG_AUX);
1801 1.1.1.3.2.2 pgoyette }
1802 1.1.1.3.2.2 pgoyette
1803 1.1.1.3.2.2 pgoyette if (tok[tokidx].X_op != O_constant)
1804 1.1.1.3.2.2 pgoyette goto de_fault;
1805 1.1.1.3.2.2 pgoyette }
1806 1.1.1.3.2.2 pgoyette /* Fall-through */
1807 1.1.1.3.2.2 pgoyette case O_constant:
1808 1.1.1.3.2.2 pgoyette /* Check the range. */
1809 1.1.1.3.2.2 pgoyette if (operand->bits != 32
1810 1.1.1.3.2.2 pgoyette && !(operand->flags & ARC_OPERAND_NCHK))
1811 1.1.1.3.2.2 pgoyette {
1812 1.1.1.3.2.2 pgoyette offsetT min, max, val;
1813 1.1.1.3.2.2 pgoyette val = tok[tokidx].X_add_number;
1814 1.1.1.3.2.2 pgoyette
1815 1.1.1.3.2.2 pgoyette if (operand->flags & ARC_OPERAND_SIGNED)
1816 1.1.1.3.2.2 pgoyette {
1817 1.1.1.3.2.2 pgoyette max = (1 << (operand->bits - 1)) - 1;
1818 1.1.1.3.2.2 pgoyette min = -(1 << (operand->bits - 1));
1819 1.1.1.3.2.2 pgoyette }
1820 1.1.1.3.2.2 pgoyette else
1821 1.1.1.3.2.2 pgoyette {
1822 1.1.1.3.2.2 pgoyette max = (1 << operand->bits) - 1;
1823 1.1.1.3.2.2 pgoyette min = 0;
1824 1.1.1.3.2.2 pgoyette }
1825 1.1.1.3.2.2 pgoyette
1826 1.1.1.3.2.2 pgoyette if (val < min || val > max)
1827 1.1.1.3.2.2 pgoyette goto match_failed;
1828 1.1.1.3.2.2 pgoyette
1829 1.1.1.3.2.2 pgoyette /* Check alignmets. */
1830 1.1.1.3.2.2 pgoyette if ((operand->flags & ARC_OPERAND_ALIGNED32)
1831 1.1.1.3.2.2 pgoyette && (val & 0x03))
1832 1.1.1.3.2.2 pgoyette goto match_failed;
1833 1.1.1.3.2.2 pgoyette
1834 1.1.1.3.2.2 pgoyette if ((operand->flags & ARC_OPERAND_ALIGNED16)
1835 1.1.1.3.2.2 pgoyette && (val & 0x01))
1836 1.1.1.3.2.2 pgoyette goto match_failed;
1837 1.1.1.3.2.2 pgoyette }
1838 1.1.1.3.2.2 pgoyette else if (operand->flags & ARC_OPERAND_NCHK)
1839 1.1.1.3.2.2 pgoyette {
1840 1.1.1.3.2.2 pgoyette if (operand->insert)
1841 1.1.1.3.2.2 pgoyette {
1842 1.1.1.3.2.2 pgoyette const char *errmsg = NULL;
1843 1.1.1.3.2.2 pgoyette (*operand->insert)(0,
1844 1.1.1.3.2.2 pgoyette tok[tokidx].X_add_number,
1845 1.1.1.3.2.2 pgoyette &errmsg);
1846 1.1.1.3.2.2 pgoyette if (errmsg)
1847 1.1.1.3.2.2 pgoyette goto match_failed;
1848 1.1.1.3.2.2 pgoyette }
1849 1.1.1.3.2.2 pgoyette else if (!(operand->flags & ARC_OPERAND_IGNORE))
1850 1.1.1.3.2.2 pgoyette goto match_failed;
1851 1.1.1.3.2.2 pgoyette }
1852 1.1.1.3.2.2 pgoyette break;
1853 1.1.1.3.2.2 pgoyette
1854 1.1.1.3.2.2 pgoyette case O_subtract:
1855 1.1.1.3.2.2 pgoyette /* Check if it is register range. */
1856 1.1.1.3.2.2 pgoyette if ((tok[tokidx].X_add_number == 0)
1857 1.1.1.3.2.2 pgoyette && contains_register (tok[tokidx].X_add_symbol)
1858 1.1.1.3.2.2 pgoyette && contains_register (tok[tokidx].X_op_symbol))
1859 1.1.1.3.2.2 pgoyette {
1860 1.1.1.3.2.2 pgoyette int regs;
1861 1.1.1.3.2.2 pgoyette
1862 1.1.1.3.2.2 pgoyette regs = get_register (tok[tokidx].X_add_symbol);
1863 1.1.1.3.2.2 pgoyette regs <<= 16;
1864 1.1.1.3.2.2 pgoyette regs |= get_register (tok[tokidx].X_op_symbol);
1865 1.1.1.3.2.2 pgoyette if (operand->insert)
1866 1.1.1.3.2.2 pgoyette {
1867 1.1.1.3.2.2 pgoyette const char *errmsg = NULL;
1868 1.1.1.3.2.2 pgoyette (*operand->insert)(0,
1869 1.1.1.3.2.2 pgoyette regs,
1870 1.1.1.3.2.2 pgoyette &errmsg);
1871 1.1.1.3.2.2 pgoyette if (errmsg)
1872 1.1.1.3.2.2 pgoyette goto match_failed;
1873 1.1.1.3.2.2 pgoyette }
1874 1.1.1.3.2.2 pgoyette else
1875 1.1.1.3.2.2 pgoyette goto match_failed;
1876 1.1.1.3.2.2 pgoyette break;
1877 1.1.1.3.2.2 pgoyette }
1878 1.1.1.3.2.2 pgoyette default:
1879 1.1.1.3.2.2 pgoyette de_fault:
1880 1.1.1.3.2.2 pgoyette if (operand->default_reloc == 0)
1881 1.1.1.3.2.2 pgoyette goto match_failed; /* The operand needs relocation. */
1882 1.1.1.3.2.2 pgoyette
1883 1.1.1.3.2.2 pgoyette /* Relocs requiring long immediate. FIXME! make it
1884 1.1.1.3.2.2 pgoyette generic and move it to a function. */
1885 1.1.1.3.2.2 pgoyette switch (tok[tokidx].X_md)
1886 1.1.1.3.2.2 pgoyette {
1887 1.1.1.3.2.2 pgoyette case O_gotoff:
1888 1.1.1.3.2.2 pgoyette case O_gotpc:
1889 1.1.1.3.2.2 pgoyette case O_pcl:
1890 1.1.1.3.2.2 pgoyette case O_tpoff:
1891 1.1.1.3.2.2 pgoyette case O_dtpoff:
1892 1.1.1.3.2.2 pgoyette case O_tlsgd:
1893 1.1.1.3.2.2 pgoyette case O_tlsie:
1894 1.1.1.3.2.2 pgoyette if (!(operand->flags & ARC_OPERAND_LIMM))
1895 1.1.1.3.2.2 pgoyette goto match_failed;
1896 1.1.1.3.2.2 pgoyette case O_absent:
1897 1.1.1.3.2.2 pgoyette if (!generic_reloc_p (operand->default_reloc))
1898 1.1.1.3.2.2 pgoyette goto match_failed;
1899 1.1.1.3.2.2 pgoyette default:
1900 1.1.1.3.2.2 pgoyette break;
1901 1.1.1.3.2.2 pgoyette }
1902 1.1.1.3.2.2 pgoyette break;
1903 1.1.1.3.2.2 pgoyette }
1904 1.1.1.3.2.2 pgoyette /* If expect duplicate, make sure it is duplicate. */
1905 1.1.1.3.2.2 pgoyette if (operand->flags & ARC_OPERAND_DUPLICATE)
1906 1.1.1.3.2.2 pgoyette {
1907 1.1.1.3.2.2 pgoyette if (t->X_op == O_illegal
1908 1.1.1.3.2.2 pgoyette || t->X_op == O_absent
1909 1.1.1.3.2.2 pgoyette || t->X_op == O_register
1910 1.1.1.3.2.2 pgoyette || (t->X_add_number != tok[tokidx].X_add_number))
1911 1.1.1.3.2.2 pgoyette goto match_failed;
1912 1.1.1.3.2.2 pgoyette }
1913 1.1.1.3.2.2 pgoyette t = &tok[tokidx];
1914 1.1.1.3.2.2 pgoyette break;
1915 1.1.1.3.2.2 pgoyette
1916 1.1.1.3.2.2 pgoyette default:
1917 1.1.1.3.2.2 pgoyette /* Everything else should have been fake. */
1918 1.1.1.3.2.2 pgoyette abort ();
1919 1.1.1.3.2.2 pgoyette }
1920 1.1.1.3.2.2 pgoyette
1921 1.1.1.3.2.2 pgoyette ++tokidx;
1922 1.1.1.3 christos }
1923 1.1.1.3.2.2 pgoyette pr_debug ("opr ");
1924 1.1.1.3.2.2 pgoyette
1925 1.1.1.3.2.2 pgoyette /* Setup ready for flag parsing. */
1926 1.1.1.3.2.2 pgoyette if (!parse_opcode_flags (opcode, nflgs, first_pflag))
1927 1.1.1.3.2.2 pgoyette goto match_failed;
1928 1.1.1.3.2.2 pgoyette
1929 1.1.1.3.2.2 pgoyette pr_debug ("flg");
1930 1.1.1.3.2.2 pgoyette /* Possible match -- did we use all of our input? */
1931 1.1.1.3.2.2 pgoyette if (tokidx == ntok)
1932 1.1.1.3 christos {
1933 1.1.1.3.2.2 pgoyette *pntok = ntok;
1934 1.1.1.3.2.2 pgoyette pr_debug ("\n");
1935 1.1.1.3.2.2 pgoyette return opcode;
1936 1.1.1.3 christos }
1937 1.1.1.3.2.2 pgoyette
1938 1.1.1.3.2.2 pgoyette match_failed:;
1939 1.1.1.3.2.2 pgoyette pr_debug ("\n");
1940 1.1.1.3.2.2 pgoyette /* Restore the original parameters. */
1941 1.1.1.3.2.2 pgoyette memcpy (tok, bktok, MAX_INSN_ARGS * sizeof (*tok));
1942 1.1.1.3.2.2 pgoyette ntok = bkntok;
1943 1.1 skrll }
1944 1.1 skrll
1945 1.1.1.3.2.2 pgoyette if (*pcpumatch)
1946 1.1.1.3.2.2 pgoyette *pcpumatch = got_cpu_match;
1947 1.1 skrll
1948 1.1.1.3.2.2 pgoyette return NULL;
1949 1.1.1.3.2.2 pgoyette }
1950 1.1.1.3 christos
1951 1.1.1.3.2.2 pgoyette /* Swap operand tokens. */
1952 1.1 skrll
1953 1.1.1.3.2.2 pgoyette static void
1954 1.1.1.3.2.2 pgoyette swap_operand (expressionS *operand_array,
1955 1.1.1.3.2.2 pgoyette unsigned source,
1956 1.1.1.3.2.2 pgoyette unsigned destination)
1957 1.1.1.3.2.2 pgoyette {
1958 1.1.1.3.2.2 pgoyette expressionS cpy_operand;
1959 1.1.1.3.2.2 pgoyette expressionS *src_operand;
1960 1.1.1.3.2.2 pgoyette expressionS *dst_operand;
1961 1.1.1.3.2.2 pgoyette size_t size;
1962 1.1.1.3 christos
1963 1.1.1.3.2.2 pgoyette if (source == destination)
1964 1.1.1.3.2.2 pgoyette return;
1965 1.1.1.3 christos
1966 1.1.1.3.2.2 pgoyette src_operand = &operand_array[source];
1967 1.1.1.3.2.2 pgoyette dst_operand = &operand_array[destination];
1968 1.1.1.3.2.2 pgoyette size = sizeof (expressionS);
1969 1.1.1.3.2.2 pgoyette
1970 1.1.1.3.2.2 pgoyette /* Make copy of operand to swap with and swap. */
1971 1.1.1.3.2.2 pgoyette memcpy (&cpy_operand, dst_operand, size);
1972 1.1.1.3.2.2 pgoyette memcpy (dst_operand, src_operand, size);
1973 1.1.1.3.2.2 pgoyette memcpy (src_operand, &cpy_operand, size);
1974 1.1.1.3.2.2 pgoyette }
1975 1.1.1.3.2.2 pgoyette
1976 1.1.1.3.2.2 pgoyette /* Check if *op matches *tok type.
1977 1.1.1.3.2.2 pgoyette Returns FALSE if they don't match, TRUE if they match. */
1978 1.1.1.3.2.2 pgoyette
1979 1.1.1.3.2.2 pgoyette static bfd_boolean
1980 1.1.1.3.2.2 pgoyette pseudo_operand_match (const expressionS *tok,
1981 1.1.1.3.2.2 pgoyette const struct arc_operand_operation *op)
1982 1.1.1.3.2.2 pgoyette {
1983 1.1.1.3.2.2 pgoyette offsetT min, max, val;
1984 1.1.1.3.2.2 pgoyette bfd_boolean ret;
1985 1.1.1.3.2.2 pgoyette const struct arc_operand *operand_real = &arc_operands[op->operand_idx];
1986 1.1.1.3.2.2 pgoyette
1987 1.1.1.3.2.2 pgoyette ret = FALSE;
1988 1.1.1.3.2.2 pgoyette switch (tok->X_op)
1989 1.1.1.3 christos {
1990 1.1.1.3.2.2 pgoyette case O_constant:
1991 1.1.1.3.2.2 pgoyette if (operand_real->bits == 32 && (operand_real->flags & ARC_OPERAND_LIMM))
1992 1.1.1.3.2.2 pgoyette ret = 1;
1993 1.1.1.3.2.2 pgoyette else if (!(operand_real->flags & ARC_OPERAND_IR))
1994 1.1.1.3.2.2 pgoyette {
1995 1.1.1.3.2.2 pgoyette val = tok->X_add_number + op->count;
1996 1.1.1.3.2.2 pgoyette if (operand_real->flags & ARC_OPERAND_SIGNED)
1997 1.1.1.3.2.2 pgoyette {
1998 1.1.1.3.2.2 pgoyette max = (1 << (operand_real->bits - 1)) - 1;
1999 1.1.1.3.2.2 pgoyette min = -(1 << (operand_real->bits - 1));
2000 1.1.1.3.2.2 pgoyette }
2001 1.1.1.3.2.2 pgoyette else
2002 1.1.1.3.2.2 pgoyette {
2003 1.1.1.3.2.2 pgoyette max = (1 << operand_real->bits) - 1;
2004 1.1.1.3.2.2 pgoyette min = 0;
2005 1.1.1.3.2.2 pgoyette }
2006 1.1.1.3.2.2 pgoyette if (min <= val && val <= max)
2007 1.1.1.3.2.2 pgoyette ret = TRUE;
2008 1.1.1.3.2.2 pgoyette }
2009 1.1.1.3.2.2 pgoyette break;
2010 1.1.1.3.2.2 pgoyette
2011 1.1.1.3.2.2 pgoyette case O_symbol:
2012 1.1.1.3.2.2 pgoyette /* Handle all symbols as long immediates or signed 9. */
2013 1.1.1.3.2.2 pgoyette if (operand_real->flags & ARC_OPERAND_LIMM ||
2014 1.1.1.3.2.2 pgoyette ((operand_real->flags & ARC_OPERAND_SIGNED) && operand_real->bits == 9))
2015 1.1.1.3.2.2 pgoyette ret = TRUE;
2016 1.1.1.3 christos break;
2017 1.1 skrll
2018 1.1.1.3.2.2 pgoyette case O_register:
2019 1.1.1.3.2.2 pgoyette if (operand_real->flags & ARC_OPERAND_IR)
2020 1.1.1.3.2.2 pgoyette ret = TRUE;
2021 1.1.1.3 christos break;
2022 1.1.1.3 christos
2023 1.1.1.3.2.2 pgoyette case O_bracket:
2024 1.1.1.3.2.2 pgoyette if (operand_real->flags & ARC_OPERAND_BRAKET)
2025 1.1.1.3.2.2 pgoyette ret = TRUE;
2026 1.1.1.3 christos break;
2027 1.1 skrll
2028 1.1.1.3 christos default:
2029 1.1.1.3.2.2 pgoyette /* Unknown. */
2030 1.1.1.3 christos break;
2031 1.1.1.3 christos }
2032 1.1.1.3.2.2 pgoyette return ret;
2033 1.1.1.3.2.2 pgoyette }
2034 1.1 skrll
2035 1.1.1.3.2.2 pgoyette /* Find pseudo instruction in array. */
2036 1.1.1.3.2.2 pgoyette
2037 1.1.1.3.2.2 pgoyette static const struct arc_pseudo_insn *
2038 1.1.1.3.2.2 pgoyette find_pseudo_insn (const char *opname,
2039 1.1.1.3.2.2 pgoyette int ntok,
2040 1.1.1.3.2.2 pgoyette const expressionS *tok)
2041 1.1.1.3.2.2 pgoyette {
2042 1.1.1.3.2.2 pgoyette const struct arc_pseudo_insn *pseudo_insn = NULL;
2043 1.1.1.3.2.2 pgoyette const struct arc_operand_operation *op;
2044 1.1.1.3.2.2 pgoyette unsigned int i;
2045 1.1.1.3.2.2 pgoyette int j;
2046 1.1.1.3.2.2 pgoyette
2047 1.1.1.3.2.2 pgoyette for (i = 0; i < arc_num_pseudo_insn; ++i)
2048 1.1 skrll {
2049 1.1.1.3.2.2 pgoyette pseudo_insn = &arc_pseudo_insns[i];
2050 1.1.1.3.2.2 pgoyette if (strcmp (pseudo_insn->mnemonic_p, opname) == 0)
2051 1.1.1.3.2.2 pgoyette {
2052 1.1.1.3.2.2 pgoyette op = pseudo_insn->operand;
2053 1.1.1.3.2.2 pgoyette for (j = 0; j < ntok; ++j)
2054 1.1.1.3.2.2 pgoyette if (!pseudo_operand_match (&tok[j], &op[j]))
2055 1.1.1.3.2.2 pgoyette break;
2056 1.1.1.3.2.2 pgoyette
2057 1.1.1.3.2.2 pgoyette /* Found the right instruction. */
2058 1.1.1.3.2.2 pgoyette if (j == ntok)
2059 1.1.1.3.2.2 pgoyette return pseudo_insn;
2060 1.1.1.3.2.2 pgoyette }
2061 1.1 skrll }
2062 1.1.1.3.2.2 pgoyette return NULL;
2063 1.1.1.3.2.2 pgoyette }
2064 1.1 skrll
2065 1.1.1.3.2.2 pgoyette /* Assumes the expressionS *tok is of sufficient size. */
2066 1.1 skrll
2067 1.1.1.3.2.2 pgoyette static const struct arc_opcode_hash_entry *
2068 1.1.1.3.2.2 pgoyette find_special_case_pseudo (const char *opname,
2069 1.1.1.3.2.2 pgoyette int *ntok,
2070 1.1.1.3.2.2 pgoyette expressionS *tok,
2071 1.1.1.3.2.2 pgoyette int *nflgs,
2072 1.1.1.3.2.2 pgoyette struct arc_flags *pflags)
2073 1.1.1.3.2.2 pgoyette {
2074 1.1.1.3.2.2 pgoyette const struct arc_pseudo_insn *pseudo_insn = NULL;
2075 1.1.1.3.2.2 pgoyette const struct arc_operand_operation *operand_pseudo;
2076 1.1.1.3.2.2 pgoyette const struct arc_operand *operand_real;
2077 1.1.1.3.2.2 pgoyette unsigned i;
2078 1.1.1.3.2.2 pgoyette char construct_operand[MAX_CONSTR_STR];
2079 1.1.1.3 christos
2080 1.1.1.3.2.2 pgoyette /* Find whether opname is in pseudo instruction array. */
2081 1.1.1.3.2.2 pgoyette pseudo_insn = find_pseudo_insn (opname, *ntok, tok);
2082 1.1 skrll
2083 1.1.1.3.2.2 pgoyette if (pseudo_insn == NULL)
2084 1.1.1.3.2.2 pgoyette return NULL;
2085 1.1 skrll
2086 1.1.1.3.2.2 pgoyette /* Handle flag, Limited to one flag at the moment. */
2087 1.1.1.3.2.2 pgoyette if (pseudo_insn->flag_r != NULL)
2088 1.1.1.3.2.2 pgoyette *nflgs += tokenize_flags (pseudo_insn->flag_r, &pflags[*nflgs],
2089 1.1.1.3.2.2 pgoyette MAX_INSN_FLGS - *nflgs);
2090 1.1 skrll
2091 1.1.1.3.2.2 pgoyette /* Handle operand operations. */
2092 1.1.1.3.2.2 pgoyette for (i = 0; i < pseudo_insn->operand_cnt; ++i)
2093 1.1.1.3.2.2 pgoyette {
2094 1.1.1.3.2.2 pgoyette operand_pseudo = &pseudo_insn->operand[i];
2095 1.1.1.3.2.2 pgoyette operand_real = &arc_operands[operand_pseudo->operand_idx];
2096 1.1.1.3 christos
2097 1.1.1.3.2.2 pgoyette if (operand_real->flags & ARC_OPERAND_BRAKET &&
2098 1.1.1.3.2.2 pgoyette !operand_pseudo->needs_insert)
2099 1.1.1.3.2.2 pgoyette continue;
2100 1.1.1.3 christos
2101 1.1.1.3.2.2 pgoyette /* Has to be inserted (i.e. this token does not exist yet). */
2102 1.1.1.3.2.2 pgoyette if (operand_pseudo->needs_insert)
2103 1.1.1.3.2.2 pgoyette {
2104 1.1.1.3.2.2 pgoyette if (operand_real->flags & ARC_OPERAND_BRAKET)
2105 1.1.1.3.2.2 pgoyette {
2106 1.1.1.3.2.2 pgoyette tok[i].X_op = O_bracket;
2107 1.1.1.3.2.2 pgoyette ++(*ntok);
2108 1.1.1.3.2.2 pgoyette continue;
2109 1.1.1.3.2.2 pgoyette }
2110 1.1.1.3 christos
2111 1.1.1.3.2.2 pgoyette /* Check if operand is a register or constant and handle it
2112 1.1.1.3.2.2 pgoyette by type. */
2113 1.1.1.3.2.2 pgoyette if (operand_real->flags & ARC_OPERAND_IR)
2114 1.1.1.3.2.2 pgoyette snprintf (construct_operand, MAX_CONSTR_STR, "r%d",
2115 1.1.1.3.2.2 pgoyette operand_pseudo->count);
2116 1.1.1.3.2.2 pgoyette else
2117 1.1.1.3.2.2 pgoyette snprintf (construct_operand, MAX_CONSTR_STR, "%d",
2118 1.1.1.3.2.2 pgoyette operand_pseudo->count);
2119 1.1.1.3 christos
2120 1.1.1.3.2.2 pgoyette tokenize_arguments (construct_operand, &tok[i], 1);
2121 1.1.1.3.2.2 pgoyette ++(*ntok);
2122 1.1.1.3.2.2 pgoyette }
2123 1.1 skrll
2124 1.1.1.3.2.2 pgoyette else if (operand_pseudo->count)
2125 1.1.1.3.2.2 pgoyette {
2126 1.1.1.3.2.2 pgoyette /* Operand number has to be adjusted accordingly (by operand
2127 1.1.1.3.2.2 pgoyette type). */
2128 1.1.1.3.2.2 pgoyette switch (tok[i].X_op)
2129 1.1.1.3.2.2 pgoyette {
2130 1.1.1.3.2.2 pgoyette case O_constant:
2131 1.1.1.3.2.2 pgoyette tok[i].X_add_number += operand_pseudo->count;
2132 1.1.1.3.2.2 pgoyette break;
2133 1.1 skrll
2134 1.1.1.3.2.2 pgoyette case O_symbol:
2135 1.1.1.3.2.2 pgoyette break;
2136 1.1.1.3 christos
2137 1.1.1.3.2.2 pgoyette default:
2138 1.1.1.3.2.2 pgoyette /* Ignored. */
2139 1.1.1.3.2.2 pgoyette break;
2140 1.1.1.3.2.2 pgoyette }
2141 1.1.1.3.2.2 pgoyette }
2142 1.1.1.3 christos }
2143 1.1.1.3 christos
2144 1.1.1.3.2.2 pgoyette /* Swap operands if necessary. Only supports one swap at the
2145 1.1.1.3.2.2 pgoyette moment. */
2146 1.1.1.3.2.2 pgoyette for (i = 0; i < pseudo_insn->operand_cnt; ++i)
2147 1.1.1.3 christos {
2148 1.1.1.3.2.2 pgoyette operand_pseudo = &pseudo_insn->operand[i];
2149 1.1.1.3.2.2 pgoyette
2150 1.1.1.3.2.2 pgoyette if (operand_pseudo->swap_operand_idx == i)
2151 1.1.1.3.2.2 pgoyette continue;
2152 1.1.1.3.2.2 pgoyette
2153 1.1.1.3.2.2 pgoyette swap_operand (tok, i, operand_pseudo->swap_operand_idx);
2154 1.1.1.3.2.2 pgoyette
2155 1.1.1.3.2.2 pgoyette /* Prevent a swap back later by breaking out. */
2156 1.1.1.3.2.2 pgoyette break;
2157 1.1 skrll }
2158 1.1.1.3.2.2 pgoyette
2159 1.1.1.3.2.2 pgoyette return arc_find_opcode (pseudo_insn->mnemonic_r);
2160 1.1.1.3.2.2 pgoyette }
2161 1.1.1.3.2.2 pgoyette
2162 1.1.1.3.2.2 pgoyette static const struct arc_opcode_hash_entry *
2163 1.1.1.3.2.2 pgoyette find_special_case_flag (const char *opname,
2164 1.1.1.3.2.2 pgoyette int *nflgs,
2165 1.1.1.3.2.2 pgoyette struct arc_flags *pflags)
2166 1.1.1.3.2.2 pgoyette {
2167 1.1.1.3.2.2 pgoyette unsigned int i;
2168 1.1.1.3.2.2 pgoyette const char *flagnm;
2169 1.1.1.3.2.2 pgoyette unsigned flag_idx, flag_arr_idx;
2170 1.1.1.3.2.2 pgoyette size_t flaglen, oplen;
2171 1.1.1.3.2.2 pgoyette const struct arc_flag_special *arc_flag_special_opcode;
2172 1.1.1.3.2.2 pgoyette const struct arc_opcode_hash_entry *entry;
2173 1.1.1.3.2.2 pgoyette
2174 1.1.1.3.2.2 pgoyette /* Search for special case instruction. */
2175 1.1.1.3.2.2 pgoyette for (i = 0; i < arc_num_flag_special; i++)
2176 1.1 skrll {
2177 1.1.1.3.2.2 pgoyette arc_flag_special_opcode = &arc_flag_special_cases[i];
2178 1.1.1.3.2.2 pgoyette oplen = strlen (arc_flag_special_opcode->name);
2179 1.1.1.3.2.2 pgoyette
2180 1.1.1.3.2.2 pgoyette if (strncmp (opname, arc_flag_special_opcode->name, oplen) != 0)
2181 1.1.1.3.2.2 pgoyette continue;
2182 1.1.1.3.2.2 pgoyette
2183 1.1.1.3.2.2 pgoyette /* Found a potential special case instruction, now test for
2184 1.1.1.3.2.2 pgoyette flags. */
2185 1.1.1.3.2.2 pgoyette for (flag_arr_idx = 0;; ++flag_arr_idx)
2186 1.1 skrll {
2187 1.1.1.3.2.2 pgoyette flag_idx = arc_flag_special_opcode->flags[flag_arr_idx];
2188 1.1.1.3.2.2 pgoyette if (flag_idx == 0)
2189 1.1.1.3.2.2 pgoyette break; /* End of array, nothing found. */
2190 1.1.1.3.2.2 pgoyette
2191 1.1.1.3.2.2 pgoyette flagnm = arc_flag_operands[flag_idx].name;
2192 1.1.1.3.2.2 pgoyette flaglen = strlen (flagnm);
2193 1.1.1.3.2.2 pgoyette if (strcmp (opname + oplen, flagnm) == 0)
2194 1.1.1.3.2.2 pgoyette {
2195 1.1.1.3.2.2 pgoyette entry = arc_find_opcode (arc_flag_special_opcode->name);
2196 1.1.1.3.2.2 pgoyette
2197 1.1.1.3.2.2 pgoyette if (*nflgs + 1 > MAX_INSN_FLGS)
2198 1.1.1.3.2.2 pgoyette break;
2199 1.1.1.3.2.2 pgoyette memcpy (pflags[*nflgs].name, flagnm, flaglen);
2200 1.1.1.3.2.2 pgoyette pflags[*nflgs].name[flaglen] = '\0';
2201 1.1.1.3.2.2 pgoyette (*nflgs)++;
2202 1.1.1.3.2.2 pgoyette return entry;
2203 1.1.1.3.2.2 pgoyette }
2204 1.1 skrll }
2205 1.1 skrll }
2206 1.1.1.3.2.2 pgoyette return NULL;
2207 1.1.1.3.2.2 pgoyette }
2208 1.1 skrll
2209 1.1.1.3.2.2 pgoyette /* The long instructions are not stored in a hash (there's not many of
2210 1.1.1.3.2.2 pgoyette them) and so there's no arc_opcode_hash_entry structure to return. This
2211 1.1.1.3.2.2 pgoyette helper function for find_special_case_long_opcode takes an arc_opcode
2212 1.1.1.3.2.2 pgoyette result and places it into a fake arc_opcode_hash_entry that points to
2213 1.1.1.3.2.2 pgoyette the single arc_opcode OPCODE, which is then returned. */
2214 1.1.1.3.2.2 pgoyette
2215 1.1.1.3.2.2 pgoyette static const struct arc_opcode_hash_entry *
2216 1.1.1.3.2.2 pgoyette build_fake_opcode_hash_entry (const struct arc_opcode *opcode)
2217 1.1.1.3.2.2 pgoyette {
2218 1.1.1.3.2.2 pgoyette static struct arc_opcode_hash_entry entry;
2219 1.1.1.3.2.2 pgoyette static struct arc_opcode tmp[2];
2220 1.1.1.3.2.2 pgoyette static const struct arc_opcode *ptr[2];
2221 1.1.1.3.2.2 pgoyette
2222 1.1.1.3.2.2 pgoyette memcpy (&tmp[0], opcode, sizeof (struct arc_opcode));
2223 1.1.1.3.2.2 pgoyette memset (&tmp[1], 0, sizeof (struct arc_opcode));
2224 1.1.1.3.2.2 pgoyette entry.count = 1;
2225 1.1.1.3.2.2 pgoyette entry.opcode = ptr;
2226 1.1.1.3.2.2 pgoyette ptr[0] = tmp;
2227 1.1.1.3.2.2 pgoyette ptr[1] = NULL;
2228 1.1.1.3.2.2 pgoyette return &entry;
2229 1.1.1.3 christos }
2230 1.1.1.3 christos
2231 1.1.1.3 christos
2232 1.1.1.3.2.2 pgoyette /* Used by the assembler to match the list of tokens against a long (48 or
2233 1.1.1.3.2.2 pgoyette 64 bits) instruction. If a matching long instruction is found, then
2234 1.1.1.3.2.2 pgoyette some of the tokens are consumed in this function and converted into a
2235 1.1.1.3.2.2 pgoyette single LIMM value, which is then added to the end of the token list,
2236 1.1.1.3.2.2 pgoyette where it will be consumed by a LIMM operand that exists in the base
2237 1.1.1.3.2.2 pgoyette opcode of the long instruction. */
2238 1.1.1.3.2.2 pgoyette
2239 1.1.1.3.2.2 pgoyette static const struct arc_opcode_hash_entry *
2240 1.1.1.3.2.2 pgoyette find_special_case_long_opcode (const char *opname,
2241 1.1.1.3.2.2 pgoyette int *ntok ATTRIBUTE_UNUSED,
2242 1.1.1.3.2.2 pgoyette expressionS *tok ATTRIBUTE_UNUSED,
2243 1.1.1.3.2.2 pgoyette int *nflgs,
2244 1.1.1.3.2.2 pgoyette struct arc_flags *pflags)
2245 1.1.1.3.2.2 pgoyette {
2246 1.1.1.3.2.2 pgoyette unsigned i;
2247 1.1.1.3 christos
2248 1.1.1.3.2.2 pgoyette if (*ntok == MAX_INSN_ARGS)
2249 1.1.1.3.2.2 pgoyette return NULL;
2250 1.1.1.3 christos
2251 1.1.1.3.2.2 pgoyette for (i = 0; i < arc_num_long_opcodes; ++i)
2252 1.1.1.3.2.2 pgoyette {
2253 1.1.1.3.2.2 pgoyette struct arc_opcode fake_opcode;
2254 1.1.1.3.2.2 pgoyette const struct arc_opcode *opcode;
2255 1.1.1.3.2.2 pgoyette struct arc_insn insn;
2256 1.1.1.3.2.2 pgoyette expressionS *limm_token;
2257 1.1.1.3 christos
2258 1.1.1.3.2.2 pgoyette opcode = &arc_long_opcodes[i].base_opcode;
2259 1.1.1.3 christos
2260 1.1.1.3.2.2 pgoyette if (!(opcode->cpu & arc_target))
2261 1.1.1.3.2.2 pgoyette continue;
2262 1.1.1.3 christos
2263 1.1.1.3.2.2 pgoyette if (!check_cpu_feature (opcode->subclass))
2264 1.1.1.3.2.2 pgoyette continue;
2265 1.1.1.3 christos
2266 1.1.1.3.2.2 pgoyette if (strcmp (opname, opcode->name) != 0)
2267 1.1.1.3.2.2 pgoyette continue;
2268 1.1.1.3.2.2 pgoyette
2269 1.1.1.3.2.2 pgoyette /* Check that the flags are a match. */
2270 1.1.1.3.2.2 pgoyette if (!parse_opcode_flags (opcode, *nflgs, pflags))
2271 1.1.1.3.2.2 pgoyette continue;
2272 1.1.1.3.2.2 pgoyette
2273 1.1.1.3.2.2 pgoyette /* Parse the LIMM operands into the LIMM template. */
2274 1.1.1.3.2.2 pgoyette memset (&fake_opcode, 0, sizeof (fake_opcode));
2275 1.1.1.3.2.2 pgoyette fake_opcode.name = "fake limm";
2276 1.1.1.3.2.2 pgoyette fake_opcode.opcode = arc_long_opcodes[i].limm_template;
2277 1.1.1.3.2.2 pgoyette fake_opcode.mask = arc_long_opcodes[i].limm_mask;
2278 1.1.1.3.2.2 pgoyette fake_opcode.cpu = opcode->cpu;
2279 1.1.1.3.2.2 pgoyette fake_opcode.insn_class = opcode->insn_class;
2280 1.1.1.3.2.2 pgoyette fake_opcode.subclass = opcode->subclass;
2281 1.1.1.3.2.2 pgoyette memcpy (&fake_opcode.operands[0],
2282 1.1.1.3.2.2 pgoyette &arc_long_opcodes[i].operands,
2283 1.1.1.3.2.2 pgoyette MAX_INSN_ARGS);
2284 1.1.1.3.2.2 pgoyette /* Leave fake_opcode.flags as zero. */
2285 1.1.1.3.2.2 pgoyette
2286 1.1.1.3.2.2 pgoyette pr_debug ("Calling assemble_insn to build fake limm value\n");
2287 1.1.1.3.2.2 pgoyette assemble_insn (&fake_opcode, tok, *ntok,
2288 1.1.1.3.2.2 pgoyette NULL, 0, &insn);
2289 1.1.1.3.2.2 pgoyette pr_debug (" got limm value: 0x%x\n", insn.insn);
2290 1.1.1.3.2.2 pgoyette
2291 1.1.1.3.2.2 pgoyette /* Now create a new token at the end of the token array (We know this
2292 1.1.1.3.2.2 pgoyette is safe as the token array is always created with enough space for
2293 1.1.1.3.2.2 pgoyette MAX_INSN_ARGS, and we check at the start at the start of this
2294 1.1.1.3.2.2 pgoyette function that we're not there yet). This new token will
2295 1.1.1.3.2.2 pgoyette correspond to a LIMM operand that will be contained in the
2296 1.1.1.3.2.2 pgoyette base_opcode of the arc_long_opcode. */
2297 1.1.1.3.2.2 pgoyette limm_token = &tok[(*ntok)];
2298 1.1.1.3.2.2 pgoyette (*ntok)++;
2299 1.1.1.3.2.2 pgoyette
2300 1.1.1.3.2.2 pgoyette /* Modify the LIMM token to hold the constant. */
2301 1.1.1.3.2.2 pgoyette limm_token->X_op = O_constant;
2302 1.1.1.3.2.2 pgoyette limm_token->X_add_number = insn.insn;
2303 1.1.1.3.2.2 pgoyette
2304 1.1.1.3.2.2 pgoyette /* Return the base opcode. */
2305 1.1.1.3.2.2 pgoyette return build_fake_opcode_hash_entry (opcode);
2306 1.1.1.3.2.2 pgoyette }
2307 1.1.1.3.2.2 pgoyette
2308 1.1.1.3.2.2 pgoyette return NULL;
2309 1.1.1.3 christos }
2310 1.1.1.3 christos
2311 1.1.1.3.2.2 pgoyette /* Used to find special case opcode. */
2312 1.1 skrll
2313 1.1.1.3.2.2 pgoyette static const struct arc_opcode_hash_entry *
2314 1.1.1.3.2.2 pgoyette find_special_case (const char *opname,
2315 1.1.1.3.2.2 pgoyette int *nflgs,
2316 1.1.1.3.2.2 pgoyette struct arc_flags *pflags,
2317 1.1.1.3.2.2 pgoyette expressionS *tok,
2318 1.1.1.3.2.2 pgoyette int *ntok)
2319 1.1 skrll {
2320 1.1.1.3.2.2 pgoyette const struct arc_opcode_hash_entry *entry;
2321 1.1 skrll
2322 1.1.1.3.2.2 pgoyette entry = find_special_case_pseudo (opname, ntok, tok, nflgs, pflags);
2323 1.1.1.3 christos
2324 1.1.1.3.2.2 pgoyette if (entry == NULL)
2325 1.1.1.3.2.2 pgoyette entry = find_special_case_flag (opname, nflgs, pflags);
2326 1.1.1.3 christos
2327 1.1.1.3.2.2 pgoyette if (entry == NULL)
2328 1.1.1.3.2.2 pgoyette entry = find_special_case_long_opcode (opname, ntok, tok, nflgs, pflags);
2329 1.1.1.3 christos
2330 1.1.1.3.2.2 pgoyette return entry;
2331 1.1.1.3.2.2 pgoyette }
2332 1.1.1.3 christos
2333 1.1.1.3.2.2 pgoyette /* Given an opcode name, pre-tockenized set of argumenst and the
2334 1.1.1.3.2.2 pgoyette opcode flags, take it all the way through emission. */
2335 1.1 skrll
2336 1.1.1.3.2.2 pgoyette static void
2337 1.1.1.3.2.2 pgoyette assemble_tokens (const char *opname,
2338 1.1.1.3.2.2 pgoyette expressionS *tok,
2339 1.1.1.3.2.2 pgoyette int ntok,
2340 1.1.1.3.2.2 pgoyette struct arc_flags *pflags,
2341 1.1.1.3.2.2 pgoyette int nflgs)
2342 1.1.1.3.2.2 pgoyette {
2343 1.1.1.3.2.2 pgoyette bfd_boolean found_something = FALSE;
2344 1.1.1.3.2.2 pgoyette const struct arc_opcode_hash_entry *entry;
2345 1.1.1.3.2.2 pgoyette int cpumatch = 1;
2346 1.1 skrll
2347 1.1.1.3.2.2 pgoyette /* Search opcodes. */
2348 1.1.1.3.2.2 pgoyette entry = arc_find_opcode (opname);
2349 1.1 skrll
2350 1.1.1.3.2.2 pgoyette /* Couldn't find opcode conventional way, try special cases. */
2351 1.1.1.3.2.2 pgoyette if (entry == NULL)
2352 1.1.1.3.2.2 pgoyette entry = find_special_case (opname, &nflgs, pflags, tok, &ntok);
2353 1.1.1.3.2.2 pgoyette
2354 1.1.1.3.2.2 pgoyette if (entry != NULL)
2355 1.1.1.3 christos {
2356 1.1.1.3.2.2 pgoyette const struct arc_opcode *opcode;
2357 1.1.1.3.2.2 pgoyette
2358 1.1.1.3.2.2 pgoyette pr_debug ("%s:%d: assemble_tokens: %s\n",
2359 1.1.1.3.2.2 pgoyette frag_now->fr_file, frag_now->fr_line, opname);
2360 1.1.1.3.2.2 pgoyette found_something = TRUE;
2361 1.1.1.3.2.2 pgoyette opcode = find_opcode_match (entry, tok, &ntok, pflags,
2362 1.1.1.3.2.2 pgoyette nflgs, &cpumatch);
2363 1.1.1.3.2.2 pgoyette if (opcode != NULL)
2364 1.1.1.3 christos {
2365 1.1.1.3.2.2 pgoyette struct arc_insn insn;
2366 1.1.1.3.2.2 pgoyette
2367 1.1.1.3.2.2 pgoyette assemble_insn (opcode, tok, ntok, pflags, nflgs, &insn);
2368 1.1.1.3.2.2 pgoyette emit_insn (&insn);
2369 1.1.1.3.2.2 pgoyette return;
2370 1.1.1.3 christos }
2371 1.1.1.3 christos }
2372 1.1 skrll
2373 1.1.1.3.2.2 pgoyette if (found_something)
2374 1.1.1.3.2.2 pgoyette {
2375 1.1.1.3.2.2 pgoyette if (cpumatch)
2376 1.1.1.3.2.2 pgoyette as_bad (_("inappropriate arguments for opcode '%s'"), opname);
2377 1.1.1.3.2.2 pgoyette else
2378 1.1.1.3.2.2 pgoyette as_bad (_("opcode '%s' not supported for target %s"), opname,
2379 1.1.1.3.2.2 pgoyette arc_target_name);
2380 1.1.1.3.2.2 pgoyette }
2381 1.1.1.3.2.2 pgoyette else
2382 1.1.1.3.2.2 pgoyette as_bad (_("unknown opcode '%s'"), opname);
2383 1.1 skrll }
2384 1.1 skrll
2385 1.1.1.3.2.2 pgoyette /* The public interface to the instruction assembler. */
2386 1.1.1.3 christos
2387 1.1.1.3 christos void
2388 1.1.1.3.2.2 pgoyette md_assemble (char *str)
2389 1.1 skrll {
2390 1.1.1.3.2.2 pgoyette char *opname;
2391 1.1.1.3.2.2 pgoyette expressionS tok[MAX_INSN_ARGS];
2392 1.1.1.3.2.2 pgoyette int ntok, nflg;
2393 1.1.1.3.2.2 pgoyette size_t opnamelen;
2394 1.1.1.3.2.2 pgoyette struct arc_flags flags[MAX_INSN_FLGS];
2395 1.1.1.3 christos
2396 1.1.1.3.2.2 pgoyette /* Split off the opcode. */
2397 1.1.1.3.2.2 pgoyette opnamelen = strspn (str, "abcdefghijklmnopqrstuvwxyz_0123468");
2398 1.1.1.3.2.2 pgoyette opname = xmemdup0 (str, opnamelen);
2399 1.1.1.3 christos
2400 1.1.1.3.2.2 pgoyette /* Signalize we are assmbling the instructions. */
2401 1.1.1.3.2.2 pgoyette assembling_insn = TRUE;
2402 1.1.1.3 christos
2403 1.1.1.3.2.2 pgoyette /* Tokenize the flags. */
2404 1.1.1.3.2.2 pgoyette if ((nflg = tokenize_flags (str + opnamelen, flags, MAX_INSN_FLGS)) == -1)
2405 1.1.1.3.2.2 pgoyette {
2406 1.1.1.3.2.2 pgoyette as_bad (_("syntax error"));
2407 1.1.1.3.2.2 pgoyette return;
2408 1.1.1.3 christos }
2409 1.1.1.3 christos
2410 1.1.1.3.2.2 pgoyette /* Scan up to the end of the mnemonic which must end in space or end
2411 1.1.1.3.2.2 pgoyette of string. */
2412 1.1.1.3.2.2 pgoyette str += opnamelen;
2413 1.1.1.3.2.2 pgoyette for (; *str != '\0'; str++)
2414 1.1.1.3.2.2 pgoyette if (*str == ' ')
2415 1.1.1.3.2.2 pgoyette break;
2416 1.1 skrll
2417 1.1.1.3.2.2 pgoyette /* Tokenize the rest of the line. */
2418 1.1.1.3.2.2 pgoyette if ((ntok = tokenize_arguments (str, tok, MAX_INSN_ARGS)) < 0)
2419 1.1.1.3 christos {
2420 1.1.1.3.2.2 pgoyette as_bad (_("syntax error"));
2421 1.1.1.3.2.2 pgoyette return;
2422 1.1.1.3 christos }
2423 1.1.1.3.2.2 pgoyette
2424 1.1.1.3.2.2 pgoyette /* Finish it off. */
2425 1.1.1.3.2.2 pgoyette assemble_tokens (opname, tok, ntok, flags, nflg);
2426 1.1.1.3.2.2 pgoyette assembling_insn = FALSE;
2427 1.1.1.3 christos }
2428 1.1 skrll
2429 1.1.1.3.2.2 pgoyette /* Callback to insert a register into the hash table. */
2430 1.1.1.3 christos
2431 1.1.1.3.2.2 pgoyette static void
2432 1.1.1.3.2.2 pgoyette declare_register (const char *name, int number)
2433 1.1.1.3 christos {
2434 1.1.1.3.2.2 pgoyette const char *err;
2435 1.1.1.3.2.2 pgoyette symbolS *regS = symbol_create (name, reg_section,
2436 1.1.1.3.2.2 pgoyette number, &zero_address_frag);
2437 1.1.1.3 christos
2438 1.1.1.3.2.2 pgoyette err = hash_insert (arc_reg_hash, S_GET_NAME (regS), (void *) regS);
2439 1.1.1.3.2.2 pgoyette if (err)
2440 1.1.1.3.2.2 pgoyette as_fatal (_("Inserting \"%s\" into register table failed: %s"),
2441 1.1.1.3.2.2 pgoyette name, err);
2442 1.1.1.3.2.2 pgoyette }
2443 1.1.1.3 christos
2444 1.1.1.3.2.2 pgoyette /* Construct symbols for each of the general registers. */
2445 1.1.1.3 christos
2446 1.1.1.3.2.2 pgoyette static void
2447 1.1.1.3.2.2 pgoyette declare_register_set (void)
2448 1.1.1.3.2.2 pgoyette {
2449 1.1.1.3.2.2 pgoyette int i;
2450 1.1.1.3.2.2 pgoyette for (i = 0; i < 64; ++i)
2451 1.1.1.3 christos {
2452 1.1.1.3.2.2 pgoyette char name[7];
2453 1.1.1.3.2.2 pgoyette
2454 1.1.1.3.2.2 pgoyette sprintf (name, "r%d", i);
2455 1.1.1.3.2.2 pgoyette declare_register (name, i);
2456 1.1.1.3.2.2 pgoyette if ((i & 0x01) == 0)
2457 1.1.1.3.2.2 pgoyette {
2458 1.1.1.3.2.2 pgoyette sprintf (name, "r%dr%d", i, i+1);
2459 1.1.1.3.2.2 pgoyette declare_register (name, i);
2460 1.1.1.3.2.2 pgoyette }
2461 1.1.1.3 christos }
2462 1.1.1.3 christos }
2463 1.1.1.3 christos
2464 1.1.1.3.2.2 pgoyette /* Port-specific assembler initialization. This function is called
2465 1.1.1.3.2.2 pgoyette once, at assembler startup time. */
2466 1.1.1.3.2.2 pgoyette
2467 1.1.1.3.2.2 pgoyette void
2468 1.1.1.3.2.2 pgoyette md_begin (void)
2469 1.1.1.3.2.2 pgoyette {
2470 1.1.1.3.2.2 pgoyette const struct arc_opcode *opcode = arc_opcodes;
2471 1.1.1.3.2.2 pgoyette
2472 1.1.1.3.2.2 pgoyette if (!mach_type_specified_p)
2473 1.1.1.3.2.2 pgoyette arc_select_cpu (TARGET_WITH_CPU);
2474 1.1.1.3 christos
2475 1.1.1.3.2.2 pgoyette /* The endianness can be chosen "at the factory". */
2476 1.1.1.3.2.2 pgoyette target_big_endian = byte_order == BIG_ENDIAN;
2477 1.1.1.3 christos
2478 1.1.1.3.2.2 pgoyette if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, arc_mach_type))
2479 1.1.1.3.2.2 pgoyette as_warn (_("could not set architecture and machine"));
2480 1.1.1.3 christos
2481 1.1.1.3.2.2 pgoyette /* Set elf header flags. */
2482 1.1.1.3.2.2 pgoyette bfd_set_private_flags (stdoutput, arc_eflag);
2483 1.1.1.3 christos
2484 1.1.1.3.2.2 pgoyette /* Set up a hash table for the instructions. */
2485 1.1.1.3.2.2 pgoyette arc_opcode_hash = hash_new ();
2486 1.1.1.3.2.2 pgoyette if (arc_opcode_hash == NULL)
2487 1.1.1.3.2.2 pgoyette as_fatal (_("Virtual memory exhausted"));
2488 1.1.1.3 christos
2489 1.1.1.3.2.2 pgoyette /* Initialize the hash table with the insns. */
2490 1.1.1.3.2.2 pgoyette do
2491 1.1.1.3 christos {
2492 1.1.1.3.2.2 pgoyette const char *name = opcode->name;
2493 1.1.1.3 christos
2494 1.1.1.3.2.2 pgoyette arc_insert_opcode (opcode);
2495 1.1.1.3 christos
2496 1.1.1.3.2.2 pgoyette while (++opcode && opcode->name
2497 1.1.1.3.2.2 pgoyette && (opcode->name == name
2498 1.1.1.3.2.2 pgoyette || !strcmp (opcode->name, name)))
2499 1.1.1.3.2.2 pgoyette continue;
2500 1.1.1.3.2.2 pgoyette }while (opcode->name);
2501 1.1.1.3 christos
2502 1.1.1.3.2.2 pgoyette /* Register declaration. */
2503 1.1.1.3.2.2 pgoyette arc_reg_hash = hash_new ();
2504 1.1.1.3.2.2 pgoyette if (arc_reg_hash == NULL)
2505 1.1.1.3.2.2 pgoyette as_fatal (_("Virtual memory exhausted"));
2506 1.1.1.3 christos
2507 1.1.1.3.2.2 pgoyette declare_register_set ();
2508 1.1.1.3.2.2 pgoyette declare_register ("gp", 26);
2509 1.1.1.3.2.2 pgoyette declare_register ("fp", 27);
2510 1.1.1.3.2.2 pgoyette declare_register ("sp", 28);
2511 1.1.1.3.2.2 pgoyette declare_register ("ilink", 29);
2512 1.1.1.3.2.2 pgoyette declare_register ("ilink1", 29);
2513 1.1.1.3.2.2 pgoyette declare_register ("ilink2", 30);
2514 1.1.1.3.2.2 pgoyette declare_register ("blink", 31);
2515 1.1 skrll
2516 1.1.1.3.2.2 pgoyette /* XY memory registers. */
2517 1.1.1.3.2.2 pgoyette declare_register ("x0_u0", 32);
2518 1.1.1.3.2.2 pgoyette declare_register ("x0_u1", 33);
2519 1.1.1.3.2.2 pgoyette declare_register ("x1_u0", 34);
2520 1.1.1.3.2.2 pgoyette declare_register ("x1_u1", 35);
2521 1.1.1.3.2.2 pgoyette declare_register ("x2_u0", 36);
2522 1.1.1.3.2.2 pgoyette declare_register ("x2_u1", 37);
2523 1.1.1.3.2.2 pgoyette declare_register ("x3_u0", 38);
2524 1.1.1.3.2.2 pgoyette declare_register ("x3_u1", 39);
2525 1.1.1.3.2.2 pgoyette declare_register ("y0_u0", 40);
2526 1.1.1.3.2.2 pgoyette declare_register ("y0_u1", 41);
2527 1.1.1.3.2.2 pgoyette declare_register ("y1_u0", 42);
2528 1.1.1.3.2.2 pgoyette declare_register ("y1_u1", 43);
2529 1.1.1.3.2.2 pgoyette declare_register ("y2_u0", 44);
2530 1.1.1.3.2.2 pgoyette declare_register ("y2_u1", 45);
2531 1.1.1.3.2.2 pgoyette declare_register ("y3_u0", 46);
2532 1.1.1.3.2.2 pgoyette declare_register ("y3_u1", 47);
2533 1.1.1.3.2.2 pgoyette declare_register ("x0_nu", 48);
2534 1.1.1.3.2.2 pgoyette declare_register ("x1_nu", 49);
2535 1.1.1.3.2.2 pgoyette declare_register ("x2_nu", 50);
2536 1.1.1.3.2.2 pgoyette declare_register ("x3_nu", 51);
2537 1.1.1.3.2.2 pgoyette declare_register ("y0_nu", 52);
2538 1.1.1.3.2.2 pgoyette declare_register ("y1_nu", 53);
2539 1.1.1.3.2.2 pgoyette declare_register ("y2_nu", 54);
2540 1.1.1.3.2.2 pgoyette declare_register ("y3_nu", 55);
2541 1.1 skrll
2542 1.1.1.3.2.2 pgoyette declare_register ("mlo", 57);
2543 1.1.1.3.2.2 pgoyette declare_register ("mmid", 58);
2544 1.1.1.3.2.2 pgoyette declare_register ("mhi", 59);
2545 1.1.1.3 christos
2546 1.1.1.3.2.2 pgoyette declare_register ("acc1", 56);
2547 1.1.1.3.2.2 pgoyette declare_register ("acc2", 57);
2548 1.1.1.3 christos
2549 1.1.1.3.2.2 pgoyette declare_register ("lp_count", 60);
2550 1.1.1.3.2.2 pgoyette declare_register ("pcl", 63);
2551 1.1 skrll
2552 1.1.1.3.2.2 pgoyette /* Initialize the last instructions. */
2553 1.1.1.3.2.2 pgoyette memset (&arc_last_insns[0], 0, sizeof (arc_last_insns));
2554 1.1 skrll
2555 1.1.1.3.2.2 pgoyette /* Aux register declaration. */
2556 1.1.1.3.2.2 pgoyette arc_aux_hash = hash_new ();
2557 1.1.1.3.2.2 pgoyette if (arc_aux_hash == NULL)
2558 1.1.1.3.2.2 pgoyette as_fatal (_("Virtual memory exhausted"));
2559 1.1 skrll
2560 1.1.1.3.2.2 pgoyette const struct arc_aux_reg *auxr = &arc_aux_regs[0];
2561 1.1.1.3.2.2 pgoyette unsigned int i;
2562 1.1.1.3.2.2 pgoyette for (i = 0; i < arc_num_aux_regs; i++, auxr++)
2563 1.1.1.3.2.2 pgoyette {
2564 1.1.1.3.2.2 pgoyette const char *retval;
2565 1.1 skrll
2566 1.1.1.3.2.2 pgoyette if (!(auxr->cpu & arc_target))
2567 1.1.1.3.2.2 pgoyette continue;
2568 1.1 skrll
2569 1.1.1.3.2.2 pgoyette if ((auxr->subclass != NONE)
2570 1.1.1.3.2.2 pgoyette && !check_cpu_feature (auxr->subclass))
2571 1.1.1.3.2.2 pgoyette continue;
2572 1.1 skrll
2573 1.1.1.3.2.2 pgoyette retval = hash_insert (arc_aux_hash, auxr->name, (void *) auxr);
2574 1.1.1.3.2.2 pgoyette if (retval)
2575 1.1.1.3.2.2 pgoyette as_fatal (_("internal error: can't hash aux register '%s': %s"),
2576 1.1.1.3.2.2 pgoyette auxr->name, retval);
2577 1.1.1.3 christos }
2578 1.1.1.3 christos }
2579 1.1.1.3 christos
2580 1.1.1.3.2.2 pgoyette /* Write a value out to the object file, using the appropriate
2581 1.1.1.3.2.2 pgoyette endianness. */
2582 1.1.1.3.2.2 pgoyette
2583 1.1.1.3 christos void
2584 1.1.1.3.2.2 pgoyette md_number_to_chars (char *buf,
2585 1.1.1.3.2.2 pgoyette valueT val,
2586 1.1.1.3.2.2 pgoyette int n)
2587 1.1.1.3 christos {
2588 1.1.1.3.2.2 pgoyette if (target_big_endian)
2589 1.1.1.3.2.2 pgoyette number_to_chars_bigendian (buf, val, n);
2590 1.1.1.3.2.2 pgoyette else
2591 1.1.1.3.2.2 pgoyette number_to_chars_littleendian (buf, val, n);
2592 1.1.1.3.2.2 pgoyette }
2593 1.1.1.3 christos
2594 1.1.1.3.2.2 pgoyette /* Round up a section size to the appropriate boundary. */
2595 1.1.1.3 christos
2596 1.1.1.3.2.2 pgoyette valueT
2597 1.1.1.3.2.2 pgoyette md_section_align (segT segment,
2598 1.1.1.3.2.2 pgoyette valueT size)
2599 1.1.1.3.2.2 pgoyette {
2600 1.1.1.3.2.2 pgoyette int align = bfd_get_section_alignment (stdoutput, segment);
2601 1.1.1.3.2.2 pgoyette
2602 1.1.1.3.2.2 pgoyette return ((size + (1 << align) - 1) & (-((valueT) 1 << align)));
2603 1.1.1.3 christos }
2604 1.1.1.3 christos
2605 1.1.1.3.2.2 pgoyette /* The location from which a PC relative jump should be calculated,
2606 1.1.1.3.2.2 pgoyette given a PC relative reloc. */
2607 1.1.1.3.2.2 pgoyette
2608 1.1.1.3.2.2 pgoyette long
2609 1.1.1.3.2.2 pgoyette md_pcrel_from_section (fixS *fixP,
2610 1.1.1.3.2.2 pgoyette segT sec)
2611 1.1.1.3 christos {
2612 1.1.1.3.2.2 pgoyette offsetT base = fixP->fx_where + fixP->fx_frag->fr_address;
2613 1.1.1.3.2.2 pgoyette
2614 1.1.1.3.2.2 pgoyette pr_debug ("pcrel_from_section, fx_offset = %d\n", (int) fixP->fx_offset);
2615 1.1.1.3.2.2 pgoyette
2616 1.1.1.3.2.2 pgoyette if (fixP->fx_addsy != (symbolS *) NULL
2617 1.1.1.3.2.2 pgoyette && (!S_IS_DEFINED (fixP->fx_addsy)
2618 1.1.1.3.2.2 pgoyette || S_GET_SEGMENT (fixP->fx_addsy) != sec))
2619 1.1.1.3.2.2 pgoyette {
2620 1.1.1.3.2.2 pgoyette pr_debug ("Unknown pcrel symbol: %s\n", S_GET_NAME (fixP->fx_addsy));
2621 1.1.1.3.2.2 pgoyette
2622 1.1.1.3.2.2 pgoyette /* The symbol is undefined (or is defined but not in this section).
2623 1.1.1.3.2.2 pgoyette Let the linker figure it out. */
2624 1.1.1.3.2.2 pgoyette return 0;
2625 1.1.1.3.2.2 pgoyette }
2626 1.1.1.3 christos
2627 1.1.1.3.2.2 pgoyette if ((int) fixP->fx_r_type < 0)
2628 1.1.1.3.2.2 pgoyette {
2629 1.1.1.3.2.2 pgoyette /* These are the "internal" relocations. Align them to
2630 1.1.1.3.2.2 pgoyette 32 bit boundary (PCL), for the moment. */
2631 1.1.1.3.2.2 pgoyette base &= ~3;
2632 1.1.1.3.2.2 pgoyette }
2633 1.1.1.3.2.2 pgoyette else
2634 1.1.1.3 christos {
2635 1.1.1.3.2.2 pgoyette switch (fixP->fx_r_type)
2636 1.1.1.3 christos {
2637 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_PC32:
2638 1.1.1.3.2.2 pgoyette /* The hardware calculates relative to the start of the
2639 1.1.1.3.2.2 pgoyette insn, but this relocation is relative to location of the
2640 1.1.1.3.2.2 pgoyette LIMM, compensate. The base always needs to be
2641 1.1.1.3.2.2 pgoyette substracted by 4 as we do not support this type of PCrel
2642 1.1.1.3.2.2 pgoyette relocation for short instructions. */
2643 1.1.1.3.2.2 pgoyette base -= 4;
2644 1.1.1.3.2.2 pgoyette /* Fall through. */
2645 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_PLT32:
2646 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_S25H_PCREL_PLT:
2647 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_S21H_PCREL_PLT:
2648 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_S25W_PCREL_PLT:
2649 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_S21W_PCREL_PLT:
2650 1.1.1.3 christos
2651 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_S21H_PCREL:
2652 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_S25H_PCREL:
2653 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_S13_PCREL:
2654 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_S21W_PCREL:
2655 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_S25W_PCREL:
2656 1.1.1.3.2.2 pgoyette base &= ~3;
2657 1.1.1.3 christos break;
2658 1.1.1.3 christos default:
2659 1.1.1.3.2.2 pgoyette as_bad_where (fixP->fx_file, fixP->fx_line,
2660 1.1.1.3.2.2 pgoyette _("unhandled reloc %s in md_pcrel_from_section"),
2661 1.1.1.3.2.2 pgoyette bfd_get_reloc_code_name (fixP->fx_r_type));
2662 1.1.1.3 christos break;
2663 1.1 skrll }
2664 1.1.1.3 christos }
2665 1.1.1.3.2.2 pgoyette
2666 1.1.1.3.2.2 pgoyette pr_debug ("pcrel from %"BFD_VMA_FMT"x + %lx = %"BFD_VMA_FMT"x, "
2667 1.1.1.3.2.2 pgoyette "symbol: %s (%"BFD_VMA_FMT"x)\n",
2668 1.1.1.3.2.2 pgoyette fixP->fx_frag->fr_address, fixP->fx_where, base,
2669 1.1.1.3.2.2 pgoyette fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : "(null)",
2670 1.1.1.3.2.2 pgoyette fixP->fx_addsy ? S_GET_VALUE (fixP->fx_addsy) : 0);
2671 1.1.1.3.2.2 pgoyette
2672 1.1.1.3.2.2 pgoyette return base;
2673 1.1.1.3 christos }
2674 1.1.1.3 christos
2675 1.1.1.3.2.2 pgoyette /* Given a BFD relocation find the coresponding operand. */
2676 1.1.1.3 christos
2677 1.1.1.3.2.2 pgoyette static const struct arc_operand *
2678 1.1.1.3.2.2 pgoyette find_operand_for_reloc (extended_bfd_reloc_code_real_type reloc)
2679 1.1.1.3 christos {
2680 1.1.1.3.2.2 pgoyette unsigned i;
2681 1.1.1.3 christos
2682 1.1.1.3.2.2 pgoyette for (i = 0; i < arc_num_operands; i++)
2683 1.1.1.3.2.2 pgoyette if (arc_operands[i].default_reloc == reloc)
2684 1.1.1.3.2.2 pgoyette return &arc_operands[i];
2685 1.1.1.3.2.2 pgoyette return NULL;
2686 1.1.1.3.2.2 pgoyette }
2687 1.1 skrll
2688 1.1.1.3.2.2 pgoyette /* Insert an operand value into an instruction. */
2689 1.1.1.3 christos
2690 1.1.1.3.2.2 pgoyette static unsigned
2691 1.1.1.3.2.2 pgoyette insert_operand (unsigned insn,
2692 1.1.1.3.2.2 pgoyette const struct arc_operand *operand,
2693 1.1.1.3.2.2 pgoyette offsetT val,
2694 1.1.1.3.2.2 pgoyette const char *file,
2695 1.1.1.3.2.2 pgoyette unsigned line)
2696 1.1.1.3.2.2 pgoyette {
2697 1.1.1.3.2.2 pgoyette offsetT min = 0, max = 0;
2698 1.1.1.3 christos
2699 1.1.1.3.2.2 pgoyette if (operand->bits != 32
2700 1.1.1.3.2.2 pgoyette && !(operand->flags & ARC_OPERAND_NCHK)
2701 1.1.1.3.2.2 pgoyette && !(operand->flags & ARC_OPERAND_FAKE))
2702 1.1.1.3.2.2 pgoyette {
2703 1.1.1.3.2.2 pgoyette if (operand->flags & ARC_OPERAND_SIGNED)
2704 1.1 skrll {
2705 1.1.1.3.2.2 pgoyette max = (1 << (operand->bits - 1)) - 1;
2706 1.1.1.3.2.2 pgoyette min = -(1 << (operand->bits - 1));
2707 1.1.1.3 christos }
2708 1.1.1.3 christos else
2709 1.1.1.3.2.2 pgoyette {
2710 1.1.1.3.2.2 pgoyette max = (1 << operand->bits) - 1;
2711 1.1.1.3.2.2 pgoyette min = 0;
2712 1.1.1.3.2.2 pgoyette }
2713 1.1.1.3.2.2 pgoyette
2714 1.1.1.3.2.2 pgoyette if (val < min || val > max)
2715 1.1.1.3.2.2 pgoyette as_bad_value_out_of_range (_("operand"),
2716 1.1.1.3.2.2 pgoyette val, min, max, file, line);
2717 1.1.1.3 christos }
2718 1.1 skrll
2719 1.1.1.3.2.2 pgoyette pr_debug ("insert field: %ld <= %ld <= %ld in 0x%08x\n",
2720 1.1.1.3.2.2 pgoyette min, val, max, insn);
2721 1.1 skrll
2722 1.1.1.3.2.2 pgoyette if ((operand->flags & ARC_OPERAND_ALIGNED32)
2723 1.1.1.3.2.2 pgoyette && (val & 0x03))
2724 1.1.1.3.2.2 pgoyette as_bad_where (file, line,
2725 1.1.1.3.2.2 pgoyette _("Unaligned operand. Needs to be 32bit aligned"));
2726 1.1 skrll
2727 1.1.1.3.2.2 pgoyette if ((operand->flags & ARC_OPERAND_ALIGNED16)
2728 1.1.1.3.2.2 pgoyette && (val & 0x01))
2729 1.1.1.3.2.2 pgoyette as_bad_where (file, line,
2730 1.1.1.3.2.2 pgoyette _("Unaligned operand. Needs to be 16bit aligned"));
2731 1.1 skrll
2732 1.1.1.3.2.2 pgoyette if (operand->insert)
2733 1.1.1.3.2.2 pgoyette {
2734 1.1.1.3.2.2 pgoyette const char *errmsg = NULL;
2735 1.1 skrll
2736 1.1.1.3.2.2 pgoyette insn = (*operand->insert) (insn, val, &errmsg);
2737 1.1.1.3.2.2 pgoyette if (errmsg)
2738 1.1.1.3.2.2 pgoyette as_warn_where (file, line, "%s", errmsg);
2739 1.1.1.3.2.2 pgoyette }
2740 1.1.1.3.2.2 pgoyette else
2741 1.1.1.3.2.2 pgoyette {
2742 1.1.1.3.2.2 pgoyette if (operand->flags & ARC_OPERAND_TRUNCATE)
2743 1.1.1.3.2.2 pgoyette {
2744 1.1.1.3.2.2 pgoyette if (operand->flags & ARC_OPERAND_ALIGNED32)
2745 1.1.1.3.2.2 pgoyette val >>= 2;
2746 1.1.1.3.2.2 pgoyette if (operand->flags & ARC_OPERAND_ALIGNED16)
2747 1.1.1.3.2.2 pgoyette val >>= 1;
2748 1.1.1.3.2.2 pgoyette }
2749 1.1.1.3.2.2 pgoyette insn |= ((val & ((1 << operand->bits) - 1)) << operand->shift);
2750 1.1.1.3.2.2 pgoyette }
2751 1.1.1.3.2.2 pgoyette return insn;
2752 1.1.1.3 christos }
2753 1.1 skrll
2754 1.1.1.3.2.2 pgoyette /* Apply a fixup to the object code. At this point all symbol values
2755 1.1.1.3.2.2 pgoyette should be fully resolved, and we attempt to completely resolve the
2756 1.1.1.3.2.2 pgoyette reloc. If we can not do that, we determine the correct reloc code
2757 1.1.1.3.2.2 pgoyette and put it back in the fixup. To indicate that a fixup has been
2758 1.1.1.3.2.2 pgoyette eliminated, set fixP->fx_done. */
2759 1.1 skrll
2760 1.1.1.3.2.2 pgoyette void
2761 1.1.1.3.2.2 pgoyette md_apply_fix (fixS *fixP,
2762 1.1.1.3.2.2 pgoyette valueT *valP,
2763 1.1.1.3.2.2 pgoyette segT seg)
2764 1.1.1.3 christos {
2765 1.1.1.3.2.2 pgoyette char * const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where;
2766 1.1.1.3.2.2 pgoyette valueT value = *valP;
2767 1.1.1.3.2.2 pgoyette unsigned insn = 0;
2768 1.1.1.3.2.2 pgoyette symbolS *fx_addsy, *fx_subsy;
2769 1.1.1.3.2.2 pgoyette offsetT fx_offset;
2770 1.1.1.3.2.2 pgoyette segT add_symbol_segment = absolute_section;
2771 1.1.1.3.2.2 pgoyette segT sub_symbol_segment = absolute_section;
2772 1.1.1.3.2.2 pgoyette const struct arc_operand *operand = NULL;
2773 1.1.1.3.2.2 pgoyette extended_bfd_reloc_code_real_type reloc;
2774 1.1 skrll
2775 1.1.1.3.2.2 pgoyette pr_debug ("%s:%u: apply_fix: r_type=%d (%s) value=0x%lX offset=0x%lX\n",
2776 1.1.1.3.2.2 pgoyette fixP->fx_file, fixP->fx_line, fixP->fx_r_type,
2777 1.1.1.3.2.2 pgoyette ((int) fixP->fx_r_type < 0) ? "Internal":
2778 1.1.1.3.2.2 pgoyette bfd_get_reloc_code_name (fixP->fx_r_type), value,
2779 1.1.1.3.2.2 pgoyette fixP->fx_offset);
2780 1.1.1.3 christos
2781 1.1.1.3.2.2 pgoyette fx_addsy = fixP->fx_addsy;
2782 1.1.1.3.2.2 pgoyette fx_subsy = fixP->fx_subsy;
2783 1.1.1.3.2.2 pgoyette fx_offset = 0;
2784 1.1.1.3 christos
2785 1.1.1.3.2.2 pgoyette if (fx_addsy)
2786 1.1.1.3.2.2 pgoyette {
2787 1.1.1.3.2.2 pgoyette add_symbol_segment = S_GET_SEGMENT (fx_addsy);
2788 1.1.1.3.2.2 pgoyette }
2789 1.1 skrll
2790 1.1.1.3.2.2 pgoyette if (fx_subsy
2791 1.1.1.3.2.2 pgoyette && fixP->fx_r_type != BFD_RELOC_ARC_TLS_DTPOFF
2792 1.1.1.3.2.2 pgoyette && fixP->fx_r_type != BFD_RELOC_ARC_TLS_DTPOFF_S9
2793 1.1.1.3.2.2 pgoyette && fixP->fx_r_type != BFD_RELOC_ARC_TLS_GD_LD)
2794 1.1.1.3.2.2 pgoyette {
2795 1.1.1.3.2.2 pgoyette resolve_symbol_value (fx_subsy);
2796 1.1.1.3.2.2 pgoyette sub_symbol_segment = S_GET_SEGMENT (fx_subsy);
2797 1.1.1.3 christos
2798 1.1.1.3.2.2 pgoyette if (sub_symbol_segment == absolute_section)
2799 1.1.1.3.2.2 pgoyette {
2800 1.1.1.3.2.2 pgoyette /* The symbol is really a constant. */
2801 1.1.1.3.2.2 pgoyette fx_offset -= S_GET_VALUE (fx_subsy);
2802 1.1.1.3.2.2 pgoyette fx_subsy = NULL;
2803 1.1.1.3.2.2 pgoyette }
2804 1.1.1.3.2.2 pgoyette else
2805 1.1.1.3.2.2 pgoyette {
2806 1.1.1.3.2.2 pgoyette as_bad_where (fixP->fx_file, fixP->fx_line,
2807 1.1.1.3.2.2 pgoyette _("can't resolve `%s' {%s section} - `%s' {%s section}"),
2808 1.1.1.3.2.2 pgoyette fx_addsy ? S_GET_NAME (fx_addsy) : "0",
2809 1.1.1.3.2.2 pgoyette segment_name (add_symbol_segment),
2810 1.1.1.3.2.2 pgoyette S_GET_NAME (fx_subsy),
2811 1.1.1.3.2.2 pgoyette segment_name (sub_symbol_segment));
2812 1.1.1.3.2.2 pgoyette return;
2813 1.1.1.3.2.2 pgoyette }
2814 1.1.1.3.2.2 pgoyette }
2815 1.1.1.3 christos
2816 1.1.1.3.2.2 pgoyette if (fx_addsy
2817 1.1.1.3.2.2 pgoyette && !S_IS_WEAK (fx_addsy))
2818 1.1.1.3 christos {
2819 1.1.1.3.2.2 pgoyette if (add_symbol_segment == seg
2820 1.1.1.3.2.2 pgoyette && fixP->fx_pcrel)
2821 1.1.1.3 christos {
2822 1.1.1.3.2.2 pgoyette value += S_GET_VALUE (fx_addsy);
2823 1.1.1.3.2.2 pgoyette value -= md_pcrel_from_section (fixP, seg);
2824 1.1.1.3.2.2 pgoyette fx_addsy = NULL;
2825 1.1.1.3.2.2 pgoyette fixP->fx_pcrel = FALSE;
2826 1.1.1.3 christos }
2827 1.1.1.3.2.2 pgoyette else if (add_symbol_segment == absolute_section)
2828 1.1.1.3.2.2 pgoyette {
2829 1.1.1.3.2.2 pgoyette value = fixP->fx_offset;
2830 1.1.1.3.2.2 pgoyette fx_offset += S_GET_VALUE (fixP->fx_addsy);
2831 1.1.1.3.2.2 pgoyette fx_addsy = NULL;
2832 1.1.1.3.2.2 pgoyette fixP->fx_pcrel = FALSE;
2833 1.1.1.3.2.2 pgoyette }
2834 1.1.1.3.2.2 pgoyette }
2835 1.1 skrll
2836 1.1.1.3.2.2 pgoyette if (!fx_addsy)
2837 1.1.1.3.2.2 pgoyette fixP->fx_done = TRUE;
2838 1.1.1.3 christos
2839 1.1.1.3.2.2 pgoyette if (fixP->fx_pcrel)
2840 1.1.1.3.2.2 pgoyette {
2841 1.1.1.3.2.2 pgoyette if (fx_addsy
2842 1.1.1.3.2.2 pgoyette && ((S_IS_DEFINED (fx_addsy)
2843 1.1.1.3.2.2 pgoyette && S_GET_SEGMENT (fx_addsy) != seg)
2844 1.1.1.3.2.2 pgoyette || S_IS_WEAK (fx_addsy)))
2845 1.1.1.3.2.2 pgoyette value += md_pcrel_from_section (fixP, seg);
2846 1.1.1.3 christos
2847 1.1.1.3.2.2 pgoyette switch (fixP->fx_r_type)
2848 1.1.1.3.2.2 pgoyette {
2849 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_32_ME:
2850 1.1.1.3.2.2 pgoyette /* This is a pc-relative value in a LIMM. Adjust it to the
2851 1.1.1.3.2.2 pgoyette address of the instruction not to the address of the
2852 1.1.1.3.2.2 pgoyette LIMM. Note: it is not anylonger valid this afirmation as
2853 1.1.1.3.2.2 pgoyette the linker consider ARC_PC32 a fixup to entire 64 bit
2854 1.1.1.3.2.2 pgoyette insn. */
2855 1.1.1.3.2.2 pgoyette fixP->fx_offset += fixP->fx_frag->fr_address;
2856 1.1.1.3.2.2 pgoyette /* Fall through. */
2857 1.1.1.3.2.2 pgoyette case BFD_RELOC_32:
2858 1.1.1.3.2.2 pgoyette fixP->fx_r_type = BFD_RELOC_ARC_PC32;
2859 1.1.1.3.2.2 pgoyette /* Fall through. */
2860 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_PC32:
2861 1.1.1.3.2.2 pgoyette /* fixP->fx_offset += fixP->fx_where - fixP->fx_dot_value; */
2862 1.1.1.3.2.2 pgoyette break;
2863 1.1.1.3.2.2 pgoyette default:
2864 1.1.1.3.2.2 pgoyette if ((int) fixP->fx_r_type < 0)
2865 1.1.1.3.2.2 pgoyette as_fatal (_("PC relative relocation not allowed for (internal) type %d"),
2866 1.1.1.3.2.2 pgoyette fixP->fx_r_type);
2867 1.1.1.3.2.2 pgoyette break;
2868 1.1.1.3.2.2 pgoyette }
2869 1.1.1.3 christos }
2870 1.1.1.3 christos
2871 1.1.1.3.2.2 pgoyette pr_debug ("%s:%u: apply_fix: r_type=%d (%s) value=0x%lX offset=0x%lX\n",
2872 1.1.1.3.2.2 pgoyette fixP->fx_file, fixP->fx_line, fixP->fx_r_type,
2873 1.1.1.3.2.2 pgoyette ((int) fixP->fx_r_type < 0) ? "Internal":
2874 1.1.1.3.2.2 pgoyette bfd_get_reloc_code_name (fixP->fx_r_type), value,
2875 1.1.1.3.2.2 pgoyette fixP->fx_offset);
2876 1.1.1.3 christos
2877 1.1.1.3 christos
2878 1.1.1.3.2.2 pgoyette /* Now check for TLS relocations. */
2879 1.1.1.3.2.2 pgoyette reloc = fixP->fx_r_type;
2880 1.1.1.3.2.2 pgoyette switch (reloc)
2881 1.1.1.3 christos {
2882 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_TLS_DTPOFF:
2883 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_TLS_LE_32:
2884 1.1.1.3.2.2 pgoyette if (fixP->fx_done)
2885 1.1.1.3.2.2 pgoyette break;
2886 1.1.1.3.2.2 pgoyette /* Fall through. */
2887 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_TLS_GD_GOT:
2888 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_TLS_IE_GOT:
2889 1.1.1.3.2.2 pgoyette S_SET_THREAD_LOCAL (fixP->fx_addsy);
2890 1.1.1.3.2.2 pgoyette break;
2891 1.1.1.3 christos
2892 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_TLS_GD_LD:
2893 1.1.1.3.2.2 pgoyette gas_assert (!fixP->fx_offset);
2894 1.1.1.3.2.2 pgoyette if (fixP->fx_subsy)
2895 1.1.1.3.2.2 pgoyette fixP->fx_offset
2896 1.1.1.3.2.2 pgoyette = (S_GET_VALUE (fixP->fx_subsy)
2897 1.1.1.3.2.2 pgoyette - fixP->fx_frag->fr_address- fixP->fx_where);
2898 1.1.1.3.2.2 pgoyette fixP->fx_subsy = NULL;
2899 1.1.1.3.2.2 pgoyette /* Fall through. */
2900 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_TLS_GD_CALL:
2901 1.1.1.3.2.2 pgoyette /* These two relocs are there just to allow ld to change the tls
2902 1.1.1.3.2.2 pgoyette model for this symbol, by patching the code. The offset -
2903 1.1.1.3.2.2 pgoyette and scale, if any - will be installed by the linker. */
2904 1.1.1.3.2.2 pgoyette S_SET_THREAD_LOCAL (fixP->fx_addsy);
2905 1.1.1.3.2.2 pgoyette break;
2906 1.1 skrll
2907 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_TLS_LE_S9:
2908 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_TLS_DTPOFF_S9:
2909 1.1.1.3.2.2 pgoyette as_bad (_("TLS_*_S9 relocs are not supported yet"));
2910 1.1.1.3.2.2 pgoyette break;
2911 1.1.1.3 christos
2912 1.1.1.3.2.2 pgoyette default:
2913 1.1.1.3.2.2 pgoyette break;
2914 1.1.1.3.2.2 pgoyette }
2915 1.1.1.3 christos
2916 1.1.1.3.2.2 pgoyette if (!fixP->fx_done)
2917 1.1.1.3.2.2 pgoyette {
2918 1.1.1.3.2.2 pgoyette return;
2919 1.1.1.3.2.2 pgoyette }
2920 1.1.1.3 christos
2921 1.1.1.3.2.2 pgoyette /* Addjust the value if we have a constant. */
2922 1.1.1.3.2.2 pgoyette value += fx_offset;
2923 1.1.1.3 christos
2924 1.1.1.3.2.2 pgoyette /* For hosts with longs bigger than 32-bits make sure that the top
2925 1.1.1.3.2.2 pgoyette bits of a 32-bit negative value read in by the parser are set,
2926 1.1.1.3.2.2 pgoyette so that the correct comparisons are made. */
2927 1.1.1.3.2.2 pgoyette if (value & 0x80000000)
2928 1.1.1.3.2.2 pgoyette value |= (-1UL << 31);
2929 1.1.1.3 christos
2930 1.1.1.3.2.2 pgoyette reloc = fixP->fx_r_type;
2931 1.1.1.3.2.2 pgoyette switch (reloc)
2932 1.1.1.3 christos {
2933 1.1.1.3.2.2 pgoyette case BFD_RELOC_8:
2934 1.1.1.3.2.2 pgoyette case BFD_RELOC_16:
2935 1.1.1.3.2.2 pgoyette case BFD_RELOC_24:
2936 1.1.1.3.2.2 pgoyette case BFD_RELOC_32:
2937 1.1.1.3.2.2 pgoyette case BFD_RELOC_64:
2938 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_32_PCREL:
2939 1.1.1.3.2.2 pgoyette md_number_to_chars (fixpos, value, fixP->fx_size);
2940 1.1.1.3.2.2 pgoyette return;
2941 1.1.1.3 christos
2942 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_GOTPC32:
2943 1.1.1.3.2.2 pgoyette /* I cannot fix an GOTPC relocation because I need to relax it
2944 1.1.1.3.2.2 pgoyette from ld rx,[pcl,@sym@gotpc] to add rx,pcl,@sym@gotpc. */
2945 1.1.1.3.2.2 pgoyette as_bad (_("Unsupported operation on reloc"));
2946 1.1.1.3.2.2 pgoyette return;
2947 1.1.1.3 christos
2948 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_TLS_DTPOFF:
2949 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_TLS_LE_32:
2950 1.1.1.3.2.2 pgoyette gas_assert (!fixP->fx_addsy);
2951 1.1.1.3.2.2 pgoyette gas_assert (!fixP->fx_subsy);
2952 1.1.1.3 christos
2953 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_GOTOFF:
2954 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_32_ME:
2955 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_PC32:
2956 1.1.1.3.2.2 pgoyette md_number_to_chars_midend (fixpos, value, fixP->fx_size);
2957 1.1.1.3.2.2 pgoyette return;
2958 1.1.1.3 christos
2959 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_PLT32:
2960 1.1.1.3.2.2 pgoyette md_number_to_chars_midend (fixpos, value, fixP->fx_size);
2961 1.1.1.3.2.2 pgoyette return;
2962 1.1.1.3 christos
2963 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_S25H_PCREL_PLT:
2964 1.1.1.3.2.2 pgoyette reloc = BFD_RELOC_ARC_S25W_PCREL;
2965 1.1.1.3.2.2 pgoyette goto solve_plt;
2966 1.1.1.3 christos
2967 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_S21H_PCREL_PLT:
2968 1.1.1.3.2.2 pgoyette reloc = BFD_RELOC_ARC_S21H_PCREL;
2969 1.1.1.3.2.2 pgoyette goto solve_plt;
2970 1.1.1.3 christos
2971 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_S25W_PCREL_PLT:
2972 1.1.1.3.2.2 pgoyette reloc = BFD_RELOC_ARC_S25W_PCREL;
2973 1.1.1.3.2.2 pgoyette goto solve_plt;
2974 1.1.1.3 christos
2975 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_S21W_PCREL_PLT:
2976 1.1.1.3.2.2 pgoyette reloc = BFD_RELOC_ARC_S21W_PCREL;
2977 1.1.1.3 christos
2978 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_S25W_PCREL:
2979 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_S21W_PCREL:
2980 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_S21H_PCREL:
2981 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_S25H_PCREL:
2982 1.1.1.3.2.2 pgoyette case BFD_RELOC_ARC_S13_PCREL:
2983 1.1.1.3.2.2 pgoyette solve_plt:
2984 1.1.1.3.2.2 pgoyette operand = find_operand_for_reloc (reloc);
2985 1.1.1.3.2.2 pgoyette gas_assert (operand);
2986 1.1.1.3.2.2 pgoyette break;
2987 1.1.1.3 christos
2988 1.1.1.3.2.2 pgoyette default:
2989 1.1.1.3.2.2 pgoyette {
2990 1.1.1.3.2.2 pgoyette if ((int) fixP->fx_r_type >= 0)
2991 1.1.1.3.2.2 pgoyette as_fatal (_("unhandled relocation type %s"),
2992 1.1.1.3.2.2 pgoyette bfd_get_reloc_code_name (fixP->fx_r_type));
2993 1.1.1.3 christos
2994 1.1.1.3.2.2 pgoyette /* The rest of these fixups needs to be completely resolved as
2995 1.1.1.3.2.2 pgoyette constants. */
2996 1.1.1.3.2.2 pgoyette if (fixP->fx_addsy != 0
2997 1.1.1.3.2.2 pgoyette && S_GET_SEGMENT (fixP->fx_addsy) != absolute_section)
2998 1.1.1.3.2.2 pgoyette as_bad_where (fixP->fx_file, fixP->fx_line,
2999 1.1.1.3.2.2 pgoyette _("non-absolute expression in constant field"));
3000 1.1.1.3.2.2 pgoyette
3001 1.1.1.3.2.2 pgoyette gas_assert (-(int) fixP->fx_r_type < (int) arc_num_operands);
3002 1.1.1.3.2.2 pgoyette operand = &arc_operands[-(int) fixP->fx_r_type];
3003 1.1.1.3.2.2 pgoyette break;
3004 1.1.1.3.2.2 pgoyette }
3005 1.1.1.3 christos }
3006 1.1.1.3 christos
3007 1.1.1.3.2.2 pgoyette if (target_big_endian)
3008 1.1.1.3.2.2 pgoyette {
3009 1.1.1.3.2.2 pgoyette switch (fixP->fx_size)
3010 1.1.1.3.2.2 pgoyette {
3011 1.1.1.3.2.2 pgoyette case 4:
3012 1.1.1.3.2.2 pgoyette insn = bfd_getb32 (fixpos);
3013 1.1.1.3.2.2 pgoyette break;
3014 1.1.1.3.2.2 pgoyette case 2:
3015 1.1.1.3.2.2 pgoyette insn = bfd_getb16 (fixpos);
3016 1.1.1.3.2.2 pgoyette break;
3017 1.1.1.3.2.2 pgoyette default:
3018 1.1.1.3.2.2 pgoyette as_bad_where (fixP->fx_file, fixP->fx_line,
3019 1.1.1.3.2.2 pgoyette _("unknown fixup size"));
3020 1.1.1.3.2.2 pgoyette }
3021 1.1.1.3.2.2 pgoyette }
3022 1.1.1.3.2.2 pgoyette else
3023 1.1.1.3.2.2 pgoyette {
3024 1.1.1.3.2.2 pgoyette insn = 0;
3025 1.1.1.3.2.2 pgoyette switch (fixP->fx_size)
3026 1.1.1.3.2.2 pgoyette {
3027 1.1.1.3.2.2 pgoyette case 4:
3028 1.1.1.3.2.2 pgoyette insn = bfd_getl16 (fixpos) << 16 | bfd_getl16 (fixpos + 2);
3029 1.1.1.3.2.2 pgoyette break;
3030 1.1.1.3.2.2 pgoyette case 2:
3031 1.1.1.3.2.2 pgoyette insn = bfd_getl16 (fixpos);
3032 1.1.1.3.2.2 pgoyette break;
3033 1.1.1.3.2.2 pgoyette default:
3034 1.1.1.3.2.2 pgoyette as_bad_where (fixP->fx_file, fixP->fx_line,
3035 1.1.1.3.2.2 pgoyette _("unknown fixup size"));
3036 1.1.1.3.2.2 pgoyette }
3037 1.1.1.3.2.2 pgoyette }
3038 1.1.1.3 christos
3039 1.1.1.3.2.2 pgoyette insn = insert_operand (insn, operand, (offsetT) value,
3040 1.1.1.3.2.2 pgoyette fixP->fx_file, fixP->fx_line);
3041 1.1.1.3 christos
3042 1.1.1.3.2.2 pgoyette md_number_to_chars_midend (fixpos, insn, fixP->fx_size);
3043 1.1.1.3.2.2 pgoyette }
3044 1.1.1.3 christos
3045 1.1.1.3.2.2 pgoyette /* Prepare machine-dependent frags for relaxation.
3046 1.1.1.3 christos
3047 1.1.1.3.2.2 pgoyette Called just before relaxation starts. Any symbol that is now undefined
3048 1.1.1.3.2.2 pgoyette will not become defined.
3049 1.1.1.3 christos
3050 1.1.1.3.2.2 pgoyette Return the correct fr_subtype in the frag.
3051 1.1.1.3 christos
3052 1.1.1.3.2.2 pgoyette Return the initial "guess for fr_var" to caller. The guess for fr_var
3053 1.1.1.3.2.2 pgoyette is *actually* the growth beyond fr_fix. Whatever we do to grow fr_fix
3054 1.1.1.3.2.2 pgoyette or fr_var contributes to our returned value.
3055 1.1.1.3 christos
3056 1.1.1.3.2.2 pgoyette Although it may not be explicit in the frag, pretend
3057 1.1.1.3.2.2 pgoyette fr_var starts with a value. */
3058 1.1.1.3 christos
3059 1.1.1.3.2.2 pgoyette int
3060 1.1.1.3.2.2 pgoyette md_estimate_size_before_relax (fragS *fragP,
3061 1.1.1.3.2.2 pgoyette segT segment)
3062 1.1.1.3 christos {
3063 1.1.1.3.2.2 pgoyette int growth;
3064 1.1.1.3.2.2 pgoyette
3065 1.1.1.3.2.2 pgoyette /* If the symbol is not located within the same section AND it's not
3066 1.1.1.3.2.2 pgoyette an absolute section, use the maximum. OR if the symbol is a
3067 1.1.1.3.2.2 pgoyette constant AND the insn is by nature not pc-rel, use the maximum.
3068 1.1.1.3.2.2 pgoyette OR if the symbol is being equated against another symbol, use the
3069 1.1.1.3.2.2 pgoyette maximum. OR if the symbol is weak use the maximum. */
3070 1.1.1.3.2.2 pgoyette if ((S_GET_SEGMENT (fragP->fr_symbol) != segment
3071 1.1.1.3.2.2 pgoyette && S_GET_SEGMENT (fragP->fr_symbol) != absolute_section)
3072 1.1.1.3.2.2 pgoyette || (symbol_constant_p (fragP->fr_symbol)
3073 1.1.1.3.2.2 pgoyette && !fragP->tc_frag_data.pcrel)
3074 1.1.1.3.2.2 pgoyette || symbol_equated_p (fragP->fr_symbol)
3075 1.1.1.3.2.2 pgoyette || S_IS_WEAK (fragP->fr_symbol))
3076 1.1.1.3.2.2 pgoyette {
3077 1.1.1.3.2.2 pgoyette while (md_relax_table[fragP->fr_subtype].rlx_more != ARC_RLX_NONE)
3078 1.1.1.3.2.2 pgoyette ++fragP->fr_subtype;
3079 1.1.1.3.2.2 pgoyette }
3080 1.1.1.3 christos
3081 1.1.1.3.2.2 pgoyette growth = md_relax_table[fragP->fr_subtype].rlx_length;
3082 1.1.1.3.2.2 pgoyette fragP->fr_var = growth;
3083 1.1.1.3 christos
3084 1.1.1.3.2.2 pgoyette pr_debug ("%s:%d: md_estimate_size_before_relax: %d\n",
3085 1.1.1.3.2.2 pgoyette fragP->fr_file, fragP->fr_line, growth);
3086 1.1.1.3 christos
3087 1.1.1.3.2.2 pgoyette return growth;
3088 1.1.1.3 christos }
3089 1.1.1.3 christos
3090 1.1.1.3.2.2 pgoyette /* Translate internal representation of relocation info to BFD target
3091 1.1.1.3.2.2 pgoyette format. */
3092 1.1.1.3 christos
3093 1.1.1.3.2.2 pgoyette arelent *
3094 1.1.1.3.2.2 pgoyette tc_gen_reloc (asection *section ATTRIBUTE_UNUSED,
3095 1.1.1.3.2.2 pgoyette fixS *fixP)
3096 1.1.1.3 christos {
3097 1.1.1.3.2.2 pgoyette arelent *reloc;
3098 1.1.1.3.2.2 pgoyette bfd_reloc_code_real_type code;
3099 1.1.1.3 christos
3100 1.1.1.3.2.2 pgoyette reloc = XNEW (arelent);
3101 1.1.1.3.2.2 pgoyette reloc->sym_ptr_ptr = XNEW (asymbol *);
3102 1.1.1.3.2.2 pgoyette *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
3103 1.1.1.3.2.2 pgoyette reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
3104 1.1.1.3 christos
3105 1.1.1.3.2.2 pgoyette /* Make sure none of our internal relocations make it this far.
3106 1.1.1.3.2.2 pgoyette They'd better have been fully resolved by this point. */
3107 1.1.1.3.2.2 pgoyette gas_assert ((int) fixP->fx_r_type > 0);
3108 1.1.1.3 christos
3109 1.1.1.3.2.2 pgoyette code = fixP->fx_r_type;
3110 1.1.1.3 christos
3111 1.1.1.3.2.2 pgoyette /* if we have something like add gp, pcl,
3112 1.1.1.3.2.2 pgoyette _GLOBAL_OFFSET_TABLE_@gotpc. */
3113 1.1.1.3.2.2 pgoyette if (code == BFD_RELOC_ARC_GOTPC32
3114 1.1.1.3.2.2 pgoyette && GOT_symbol
3115 1.1.1.3.2.2 pgoyette && fixP->fx_addsy == GOT_symbol)
3116 1.1.1.3.2.2 pgoyette code = BFD_RELOC_ARC_GOTPC;
3117 1.1.1.3 christos
3118 1.1.1.3.2.2 pgoyette reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
3119 1.1.1.3.2.2 pgoyette if (reloc->howto == NULL)
3120 1.1.1.3.2.2 pgoyette {
3121 1.1.1.3.2.2 pgoyette as_bad_where (fixP->fx_file, fixP->fx_line,
3122 1.1.1.3.2.2 pgoyette _("cannot represent `%s' relocation in object file"),
3123 1.1.1.3.2.2 pgoyette bfd_get_reloc_code_name (code));
3124 1.1.1.3.2.2 pgoyette return NULL;
3125 1.1.1.3.2.2 pgoyette }
3126 1.1.1.3 christos
3127 1.1.1.3.2.2 pgoyette if (!fixP->fx_pcrel != !reloc->howto->pc_relative)
3128 1.1.1.3.2.2 pgoyette as_fatal (_("internal error? cannot generate `%s' relocation"),
3129 1.1.1.3.2.2 pgoyette bfd_get_reloc_code_name (code));
3130 1.1.1.3.2.2 pgoyette
3131 1.1.1.3.2.2 pgoyette gas_assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
3132 1.1.1.3.2.2 pgoyette
3133 1.1.1.3.2.2 pgoyette if (code == BFD_RELOC_ARC_TLS_DTPOFF
3134 1.1.1.3.2.2 pgoyette || code == BFD_RELOC_ARC_TLS_DTPOFF_S9)
3135 1.1.1.3 christos {
3136 1.1.1.3.2.2 pgoyette asymbol *sym
3137 1.1.1.3.2.2 pgoyette = fixP->fx_subsy ? symbol_get_bfdsym (fixP->fx_subsy) : NULL;
3138 1.1.1.3.2.2 pgoyette /* We just want to store a 24 bit index, but we have to wait
3139 1.1.1.3.2.2 pgoyette till after write_contents has been called via
3140 1.1.1.3.2.2 pgoyette bfd_map_over_sections before we can get the index from
3141 1.1.1.3.2.2 pgoyette _bfd_elf_symbol_from_bfd_symbol. Thus, the write_relocs
3142 1.1.1.3.2.2 pgoyette function is elf32-arc.c has to pick up the slack.
3143 1.1.1.3.2.2 pgoyette Unfortunately, this leads to problems with hosts that have
3144 1.1.1.3.2.2 pgoyette pointers wider than long (bfd_vma). There would be various
3145 1.1.1.3.2.2 pgoyette ways to handle this, all error-prone :-( */
3146 1.1.1.3.2.2 pgoyette reloc->addend = (bfd_vma) sym;
3147 1.1.1.3.2.2 pgoyette if ((asymbol *) reloc->addend != sym)
3148 1.1.1.3.2.2 pgoyette {
3149 1.1.1.3.2.2 pgoyette as_bad ("Can't store pointer\n");
3150 1.1.1.3.2.2 pgoyette return NULL;
3151 1.1.1.3.2.2 pgoyette }
3152 1.1.1.3 christos }
3153 1.1.1.3.2.2 pgoyette else
3154 1.1.1.3.2.2 pgoyette reloc->addend = fixP->fx_offset;
3155 1.1.1.3.2.2 pgoyette
3156 1.1.1.3.2.2 pgoyette return reloc;
3157 1.1.1.3 christos }
3158 1.1.1.3 christos
3159 1.1.1.3.2.2 pgoyette /* Perform post-processing of machine-dependent frags after relaxation.
3160 1.1.1.3.2.2 pgoyette Called after relaxation is finished.
3161 1.1.1.3.2.2 pgoyette In: Address of frag.
3162 1.1.1.3.2.2 pgoyette fr_type == rs_machine_dependent.
3163 1.1.1.3.2.2 pgoyette fr_subtype is what the address relaxed to.
3164 1.1.1.3 christos
3165 1.1.1.3.2.2 pgoyette Out: Any fixS:s and constants are set up. */
3166 1.1.1.3.2.2 pgoyette
3167 1.1.1.3.2.2 pgoyette void
3168 1.1.1.3.2.2 pgoyette md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
3169 1.1.1.3.2.2 pgoyette segT segment ATTRIBUTE_UNUSED,
3170 1.1.1.3.2.2 pgoyette fragS *fragP)
3171 1.1.1.3 christos {
3172 1.1.1.3.2.2 pgoyette const relax_typeS *table_entry;
3173 1.1.1.3.2.2 pgoyette char *dest;
3174 1.1.1.3.2.2 pgoyette const struct arc_opcode *opcode;
3175 1.1.1.3.2.2 pgoyette struct arc_insn insn;
3176 1.1.1.3.2.2 pgoyette int size, fix;
3177 1.1.1.3.2.2 pgoyette struct arc_relax_type *relax_arg = &fragP->tc_frag_data;
3178 1.1.1.3.2.2 pgoyette
3179 1.1.1.3.2.2 pgoyette fix = (fragP->fr_fix < 0 ? 0 : fragP->fr_fix);
3180 1.1.1.3.2.2 pgoyette dest = fragP->fr_literal + fix;
3181 1.1.1.3.2.2 pgoyette table_entry = TC_GENERIC_RELAX_TABLE + fragP->fr_subtype;
3182 1.1.1.3 christos
3183 1.1.1.3.2.2 pgoyette pr_debug ("%s:%d: md_convert_frag, subtype: %d, fix: %d, "
3184 1.1.1.3.2.2 pgoyette "var: %"BFD_VMA_FMT"d\n",
3185 1.1.1.3.2.2 pgoyette fragP->fr_file, fragP->fr_line,
3186 1.1.1.3.2.2 pgoyette fragP->fr_subtype, fix, fragP->fr_var);
3187 1.1.1.3 christos
3188 1.1.1.3.2.2 pgoyette if (fragP->fr_subtype <= 0
3189 1.1.1.3.2.2 pgoyette && fragP->fr_subtype >= arc_num_relax_opcodes)
3190 1.1.1.3.2.2 pgoyette as_fatal (_("no relaxation found for this instruction."));
3191 1.1.1.3 christos
3192 1.1.1.3.2.2 pgoyette opcode = &arc_relax_opcodes[fragP->fr_subtype];
3193 1.1.1.3 christos
3194 1.1.1.3.2.2 pgoyette assemble_insn (opcode, relax_arg->tok, relax_arg->ntok, relax_arg->pflags,
3195 1.1.1.3.2.2 pgoyette relax_arg->nflg, &insn);
3196 1.1.1.3 christos
3197 1.1.1.3.2.2 pgoyette apply_fixups (&insn, fragP, fix);
3198 1.1.1.3 christos
3199 1.1.1.3.2.2 pgoyette size = insn.short_insn ? (insn.has_limm ? 6 : 2) : (insn.has_limm ? 8 : 4);
3200 1.1.1.3.2.2 pgoyette gas_assert (table_entry->rlx_length == size);
3201 1.1.1.3.2.2 pgoyette emit_insn0 (&insn, dest, TRUE);
3202 1.1.1.3 christos
3203 1.1.1.3.2.2 pgoyette fragP->fr_fix += table_entry->rlx_length;
3204 1.1.1.3.2.2 pgoyette fragP->fr_var = 0;
3205 1.1.1.3.2.2 pgoyette }
3206 1.1.1.3.2.2 pgoyette
3207 1.1.1.3.2.2 pgoyette /* We have no need to default values of symbols. We could catch
3208 1.1.1.3.2.2 pgoyette register names here, but that is handled by inserting them all in
3209 1.1.1.3.2.2 pgoyette the symbol table to begin with. */
3210 1.1.1.3.2.2 pgoyette
3211 1.1.1.3.2.2 pgoyette symbolS *
3212 1.1.1.3.2.2 pgoyette md_undefined_symbol (char *name)
3213 1.1.1.3.2.2 pgoyette {
3214 1.1.1.3.2.2 pgoyette /* The arc abi demands that a GOT[0] should be referencible as
3215 1.1.1.3.2.2 pgoyette [pc+_DYNAMIC@gotpc]. Hence we convert a _DYNAMIC@gotpc to a
3216 1.1.1.3.2.2 pgoyette GOTPC reference to _GLOBAL_OFFSET_TABLE_. */
3217 1.1.1.3.2.2 pgoyette if (((*name == '_')
3218 1.1.1.3.2.2 pgoyette && (*(name+1) == 'G')
3219 1.1.1.3.2.2 pgoyette && (strcmp (name, GLOBAL_OFFSET_TABLE_NAME) == 0))
3220 1.1.1.3.2.2 pgoyette || ((*name == '_')
3221 1.1.1.3.2.2 pgoyette && (*(name+1) == 'D')
3222 1.1.1.3.2.2 pgoyette && (strcmp (name, DYNAMIC_STRUCT_NAME) == 0)))
3223 1.1.1.3.2.2 pgoyette {
3224 1.1.1.3.2.2 pgoyette if (!GOT_symbol)
3225 1.1.1.3 christos {
3226 1.1.1.3.2.2 pgoyette if (symbol_find (name))
3227 1.1.1.3.2.2 pgoyette as_bad ("GOT already in symbol table");
3228 1.1.1.3 christos
3229 1.1.1.3.2.2 pgoyette GOT_symbol = symbol_new (GLOBAL_OFFSET_TABLE_NAME, undefined_section,
3230 1.1.1.3.2.2 pgoyette (valueT) 0, &zero_address_frag);
3231 1.1.1.3.2.2 pgoyette };
3232 1.1.1.3.2.2 pgoyette return GOT_symbol;
3233 1.1.1.3.2.2 pgoyette }
3234 1.1.1.3.2.2 pgoyette return NULL;
3235 1.1.1.3.2.2 pgoyette }
3236 1.1.1.3 christos
3237 1.1.1.3.2.2 pgoyette /* Turn a string in input_line_pointer into a floating point constant
3238 1.1.1.3.2.2 pgoyette of type type, and store the appropriate bytes in *litP. The number
3239 1.1.1.3.2.2 pgoyette of LITTLENUMS emitted is stored in *sizeP. An error message is
3240 1.1.1.3.2.2 pgoyette returned, or NULL on OK. */
3241 1.1.1.3 christos
3242 1.1.1.3.2.2 pgoyette const char *
3243 1.1.1.3.2.2 pgoyette md_atof (int type, char *litP, int *sizeP)
3244 1.1.1.3.2.2 pgoyette {
3245 1.1.1.3.2.2 pgoyette return ieee_md_atof (type, litP, sizeP, target_big_endian);
3246 1.1.1.3.2.2 pgoyette }
3247 1.1.1.3 christos
3248 1.1.1.3.2.2 pgoyette /* Called for any expression that can not be recognized. When the
3249 1.1.1.3.2.2 pgoyette function is called, `input_line_pointer' will point to the start of
3250 1.1.1.3.2.2 pgoyette the expression. */
3251 1.1.1.3 christos
3252 1.1.1.3.2.2 pgoyette void
3253 1.1.1.3.2.2 pgoyette md_operand (expressionS *expressionP ATTRIBUTE_UNUSED)
3254 1.1.1.3.2.2 pgoyette {
3255 1.1.1.3.2.2 pgoyette char *p = input_line_pointer;
3256 1.1.1.3.2.2 pgoyette if (*p == '@')
3257 1.1.1.3.2.2 pgoyette {
3258 1.1.1.3.2.2 pgoyette input_line_pointer++;
3259 1.1.1.3.2.2 pgoyette expressionP->X_op = O_symbol;
3260 1.1.1.3.2.2 pgoyette expression (expressionP);
3261 1.1.1.3.2.2 pgoyette }
3262 1.1.1.3.2.2 pgoyette }
3263 1.1.1.3 christos
3264 1.1.1.3.2.2 pgoyette /* This function is called from the function 'expression', it attempts
3265 1.1.1.3.2.2 pgoyette to parse special names (in our case register names). It fills in
3266 1.1.1.3.2.2 pgoyette the expression with the identified register. It returns TRUE if
3267 1.1.1.3.2.2 pgoyette it is a register and FALSE otherwise. */
3268 1.1.1.3.2.2 pgoyette
3269 1.1.1.3.2.2 pgoyette bfd_boolean
3270 1.1.1.3.2.2 pgoyette arc_parse_name (const char *name,
3271 1.1.1.3.2.2 pgoyette struct expressionS *e)
3272 1.1.1.3.2.2 pgoyette {
3273 1.1.1.3.2.2 pgoyette struct symbol *sym;
3274 1.1.1.3.2.2 pgoyette
3275 1.1.1.3.2.2 pgoyette if (!assembling_insn)
3276 1.1.1.3.2.2 pgoyette return FALSE;
3277 1.1.1.3 christos
3278 1.1.1.3.2.2 pgoyette /* Handle only registers. */
3279 1.1.1.3.2.2 pgoyette if (e->X_op != O_absent)
3280 1.1.1.3.2.2 pgoyette return FALSE;
3281 1.1.1.3 christos
3282 1.1.1.3.2.2 pgoyette sym = hash_find (arc_reg_hash, name);
3283 1.1.1.3.2.2 pgoyette if (sym)
3284 1.1.1.3.2.2 pgoyette {
3285 1.1.1.3.2.2 pgoyette e->X_op = O_register;
3286 1.1.1.3.2.2 pgoyette e->X_add_number = S_GET_VALUE (sym);
3287 1.1.1.3.2.2 pgoyette return TRUE;
3288 1.1.1.3.2.2 pgoyette }
3289 1.1.1.3.2.2 pgoyette return FALSE;
3290 1.1.1.3.2.2 pgoyette }
3291 1.1.1.3 christos
3292 1.1.1.3.2.2 pgoyette /* md_parse_option
3293 1.1.1.3.2.2 pgoyette Invocation line includes a switch not recognized by the base assembler.
3294 1.1.1.3.2.2 pgoyette See if it's a processor-specific option.
3295 1.1.1.3 christos
3296 1.1.1.3.2.2 pgoyette New options (supported) are:
3297 1.1.1.3 christos
3298 1.1.1.3.2.2 pgoyette -mcpu=<cpu name> Assemble for selected processor
3299 1.1.1.3.2.2 pgoyette -EB/-mbig-endian Big-endian
3300 1.1.1.3.2.2 pgoyette -EL/-mlittle-endian Little-endian
3301 1.1.1.3.2.2 pgoyette -mrelax Enable relaxation
3302 1.1.1.3 christos
3303 1.1.1.3.2.2 pgoyette The following CPU names are recognized:
3304 1.1.1.3.2.2 pgoyette arc600, arc700, arcem, archs, nps400. */
3305 1.1.1.3 christos
3306 1.1.1.3.2.2 pgoyette int
3307 1.1.1.3.2.2 pgoyette md_parse_option (int c, const char *arg ATTRIBUTE_UNUSED)
3308 1.1.1.3.2.2 pgoyette {
3309 1.1.1.3.2.2 pgoyette switch (c)
3310 1.1.1.3.2.2 pgoyette {
3311 1.1.1.3.2.2 pgoyette case OPTION_ARC600:
3312 1.1.1.3.2.2 pgoyette case OPTION_ARC601:
3313 1.1.1.3.2.2 pgoyette return md_parse_option (OPTION_MCPU, "arc600");
3314 1.1.1.3 christos
3315 1.1.1.3.2.2 pgoyette case OPTION_ARC700:
3316 1.1.1.3.2.2 pgoyette return md_parse_option (OPTION_MCPU, "arc700");
3317 1.1.1.3 christos
3318 1.1.1.3.2.2 pgoyette case OPTION_ARCEM:
3319 1.1.1.3.2.2 pgoyette return md_parse_option (OPTION_MCPU, "arcem");
3320 1.1.1.3 christos
3321 1.1.1.3.2.2 pgoyette case OPTION_ARCHS:
3322 1.1.1.3.2.2 pgoyette return md_parse_option (OPTION_MCPU, "archs");
3323 1.1.1.3 christos
3324 1.1.1.3.2.2 pgoyette case OPTION_MCPU:
3325 1.1.1.3.2.2 pgoyette {
3326 1.1.1.3.2.2 pgoyette arc_select_cpu (arg);
3327 1.1.1.3.2.2 pgoyette mach_type_specified_p = TRUE;
3328 1.1.1.3.2.2 pgoyette break;
3329 1.1.1.3.2.2 pgoyette }
3330 1.1.1.3 christos
3331 1.1.1.3.2.2 pgoyette case OPTION_EB:
3332 1.1.1.3.2.2 pgoyette arc_target_format = "elf32-bigarc";
3333 1.1.1.3.2.2 pgoyette byte_order = BIG_ENDIAN;
3334 1.1.1.3.2.2 pgoyette break;
3335 1.1.1.3 christos
3336 1.1.1.3.2.2 pgoyette case OPTION_EL:
3337 1.1.1.3.2.2 pgoyette arc_target_format = "elf32-littlearc";
3338 1.1.1.3.2.2 pgoyette byte_order = LITTLE_ENDIAN;
3339 1.1.1.3.2.2 pgoyette break;
3340 1.1.1.3 christos
3341 1.1.1.3.2.2 pgoyette case OPTION_CD:
3342 1.1.1.3.2.2 pgoyette /* This option has an effect only on ARC EM. */
3343 1.1.1.3.2.2 pgoyette if (arc_target & ARC_OPCODE_ARCv2EM)
3344 1.1.1.3.2.2 pgoyette arc_features |= ARC_CD;
3345 1.1.1.3.2.2 pgoyette else
3346 1.1.1.3.2.2 pgoyette as_warn (_("Code density option invalid for selected CPU"));
3347 1.1.1.3.2.2 pgoyette break;
3348 1.1.1.3 christos
3349 1.1.1.3.2.2 pgoyette case OPTION_RELAX:
3350 1.1.1.3.2.2 pgoyette relaxation_state = 1;
3351 1.1.1.3.2.2 pgoyette break;
3352 1.1.1.3 christos
3353 1.1.1.3.2.2 pgoyette case OPTION_NPS400:
3354 1.1.1.3.2.2 pgoyette arc_features |= ARC_NPS400;
3355 1.1.1.3.2.2 pgoyette break;
3356 1.1.1.3 christos
3357 1.1.1.3.2.2 pgoyette case OPTION_SPFP:
3358 1.1.1.3.2.2 pgoyette arc_features |= ARC_SPFP;
3359 1.1.1.3.2.2 pgoyette break;
3360 1.1.1.3 christos
3361 1.1.1.3.2.2 pgoyette case OPTION_DPFP:
3362 1.1.1.3.2.2 pgoyette arc_features |= ARC_DPFP;
3363 1.1.1.3.2.2 pgoyette break;
3364 1.1.1.3 christos
3365 1.1.1.3.2.2 pgoyette case OPTION_FPUDA:
3366 1.1.1.3.2.2 pgoyette /* This option has an effect only on ARC EM. */
3367 1.1.1.3.2.2 pgoyette if (arc_target & ARC_OPCODE_ARCv2EM)
3368 1.1.1.3.2.2 pgoyette arc_features |= ARC_FPUDA;
3369 1.1.1.3.2.2 pgoyette else
3370 1.1.1.3.2.2 pgoyette as_warn (_("FPUDA invalid for selected CPU"));
3371 1.1.1.3.2.2 pgoyette break;
3372 1.1.1.3 christos
3373 1.1.1.3.2.2 pgoyette /* Dummy options are accepted but have no effect. */
3374 1.1.1.3.2.2 pgoyette case OPTION_USER_MODE:
3375 1.1.1.3.2.2 pgoyette case OPTION_LD_EXT_MASK:
3376 1.1.1.3.2.2 pgoyette case OPTION_SWAP:
3377 1.1.1.3.2.2 pgoyette case OPTION_NORM:
3378 1.1.1.3.2.2 pgoyette case OPTION_BARREL_SHIFT:
3379 1.1.1.3.2.2 pgoyette case OPTION_MIN_MAX:
3380 1.1.1.3.2.2 pgoyette case OPTION_NO_MPY:
3381 1.1.1.3.2.2 pgoyette case OPTION_EA:
3382 1.1.1.3.2.2 pgoyette case OPTION_MUL64:
3383 1.1.1.3.2.2 pgoyette case OPTION_SIMD:
3384 1.1.1.3.2.2 pgoyette case OPTION_XMAC_D16:
3385 1.1.1.3.2.2 pgoyette case OPTION_XMAC_24:
3386 1.1.1.3.2.2 pgoyette case OPTION_DSP_PACKA:
3387 1.1.1.3.2.2 pgoyette case OPTION_CRC:
3388 1.1.1.3.2.2 pgoyette case OPTION_DVBF:
3389 1.1.1.3.2.2 pgoyette case OPTION_TELEPHONY:
3390 1.1.1.3.2.2 pgoyette case OPTION_XYMEMORY:
3391 1.1.1.3.2.2 pgoyette case OPTION_LOCK:
3392 1.1.1.3.2.2 pgoyette case OPTION_SWAPE:
3393 1.1.1.3.2.2 pgoyette case OPTION_RTSC:
3394 1.1.1.3.2.2 pgoyette break;
3395 1.1.1.3 christos
3396 1.1.1.3.2.2 pgoyette default:
3397 1.1.1.3.2.2 pgoyette return 0;
3398 1.1.1.3 christos }
3399 1.1.1.3 christos
3400 1.1.1.3.2.2 pgoyette return 1;
3401 1.1.1.3.2.2 pgoyette }
3402 1.1.1.3.2.2 pgoyette
3403 1.1.1.3.2.2 pgoyette void
3404 1.1.1.3.2.2 pgoyette md_show_usage (FILE *stream)
3405 1.1.1.3.2.2 pgoyette {
3406 1.1.1.3.2.2 pgoyette fprintf (stream, _("ARC-specific assembler options:\n"));
3407 1.1.1.3.2.2 pgoyette
3408 1.1.1.3.2.2 pgoyette fprintf (stream, " -mcpu=<cpu name>\t assemble for CPU <cpu name> "
3409 1.1.1.3.2.2 pgoyette "(default: %s)\n", TARGET_WITH_CPU);
3410 1.1.1.3.2.2 pgoyette fprintf (stream, " -mcpu=nps400\t\t same as -mcpu=arc700 -mnps400\n");
3411 1.1.1.3.2.2 pgoyette fprintf (stream, " -mA6/-mARC600/-mARC601 same as -mcpu=arc600\n");
3412 1.1.1.3.2.2 pgoyette fprintf (stream, " -mA7/-mARC700\t\t same as -mcpu=arc700\n");
3413 1.1.1.3.2.2 pgoyette fprintf (stream, " -mEM\t\t\t same as -mcpu=arcem\n");
3414 1.1.1.3.2.2 pgoyette fprintf (stream, " -mHS\t\t\t same as -mcpu=archs\n");
3415 1.1.1.3.2.2 pgoyette
3416 1.1.1.3.2.2 pgoyette fprintf (stream, " -mnps400\t\t enable NPS-400 extended instructions\n");
3417 1.1.1.3.2.2 pgoyette fprintf (stream, " -mspfp\t\t enable single-precision floating point instructions\n");
3418 1.1.1.3.2.2 pgoyette fprintf (stream, " -mdpfp\t\t enable double-precision floating point instructions\n");
3419 1.1.1.3.2.2 pgoyette fprintf (stream, " -mfpuda\t\t enable double-precision assist floating "
3420 1.1.1.3.2.2 pgoyette "point\n\t\t\t instructions for ARC EM\n");
3421 1.1.1.3.2.2 pgoyette
3422 1.1.1.3.2.2 pgoyette fprintf (stream,
3423 1.1.1.3.2.2 pgoyette " -mcode-density\t enable code density option for ARC EM\n");
3424 1.1.1.3.2.2 pgoyette
3425 1.1.1.3.2.2 pgoyette fprintf (stream, _("\
3426 1.1.1.3.2.2 pgoyette -EB assemble code for a big-endian cpu\n"));
3427 1.1.1.3.2.2 pgoyette fprintf (stream, _("\
3428 1.1.1.3.2.2 pgoyette -EL assemble code for a little-endian cpu\n"));
3429 1.1.1.3.2.2 pgoyette fprintf (stream, _("\
3430 1.1.1.3.2.2 pgoyette -mrelax enable relaxation\n"));
3431 1.1.1.3.2.2 pgoyette
3432 1.1.1.3.2.2 pgoyette fprintf (stream, _("The following ARC-specific assembler options are "
3433 1.1.1.3.2.2 pgoyette "deprecated and are accepted\nfor compatibility only:\n"));
3434 1.1.1.3 christos
3435 1.1.1.3.2.2 pgoyette fprintf (stream, _(" -mEA\n"
3436 1.1.1.3.2.2 pgoyette " -mbarrel-shifter\n"
3437 1.1.1.3.2.2 pgoyette " -mbarrel_shifter\n"
3438 1.1.1.3.2.2 pgoyette " -mcrc\n"
3439 1.1.1.3.2.2 pgoyette " -mdsp-packa\n"
3440 1.1.1.3.2.2 pgoyette " -mdsp_packa\n"
3441 1.1.1.3.2.2 pgoyette " -mdvbf\n"
3442 1.1.1.3.2.2 pgoyette " -mld-extension-reg-mask\n"
3443 1.1.1.3.2.2 pgoyette " -mlock\n"
3444 1.1.1.3.2.2 pgoyette " -mmac-24\n"
3445 1.1.1.3.2.2 pgoyette " -mmac-d16\n"
3446 1.1.1.3.2.2 pgoyette " -mmac_24\n"
3447 1.1.1.3.2.2 pgoyette " -mmac_d16\n"
3448 1.1.1.3.2.2 pgoyette " -mmin-max\n"
3449 1.1.1.3.2.2 pgoyette " -mmin_max\n"
3450 1.1.1.3.2.2 pgoyette " -mmul64\n"
3451 1.1.1.3.2.2 pgoyette " -mno-mpy\n"
3452 1.1.1.3.2.2 pgoyette " -mnorm\n"
3453 1.1.1.3.2.2 pgoyette " -mrtsc\n"
3454 1.1.1.3.2.2 pgoyette " -msimd\n"
3455 1.1.1.3.2.2 pgoyette " -mswap\n"
3456 1.1.1.3.2.2 pgoyette " -mswape\n"
3457 1.1.1.3.2.2 pgoyette " -mtelephony\n"
3458 1.1.1.3.2.2 pgoyette " -muser-mode-only\n"
3459 1.1.1.3.2.2 pgoyette " -mxy\n"));
3460 1.1.1.3 christos }
3461 1.1.1.3 christos
3462 1.1.1.3 christos /* Find the proper relocation for the given opcode. */
3463 1.1.1.3 christos
3464 1.1.1.3 christos static extended_bfd_reloc_code_real_type
3465 1.1.1.3 christos find_reloc (const char *name,
3466 1.1.1.3 christos const char *opcodename,
3467 1.1.1.3 christos const struct arc_flags *pflags,
3468 1.1.1.3 christos int nflg,
3469 1.1.1.3 christos extended_bfd_reloc_code_real_type reloc)
3470 1.1.1.3 christos {
3471 1.1.1.3 christos unsigned int i;
3472 1.1.1.3 christos int j;
3473 1.1.1.3.2.2 pgoyette bfd_boolean found_flag, tmp;
3474 1.1.1.3 christos extended_bfd_reloc_code_real_type ret = BFD_RELOC_UNUSED;
3475 1.1.1.3 christos
3476 1.1.1.3 christos for (i = 0; i < arc_num_equiv_tab; i++)
3477 1.1.1.3 christos {
3478 1.1.1.3 christos const struct arc_reloc_equiv_tab *r = &arc_reloc_equiv[i];
3479 1.1.1.3 christos
3480 1.1.1.3 christos /* Find the entry. */
3481 1.1.1.3 christos if (strcmp (name, r->name))
3482 1.1.1.3 christos continue;
3483 1.1.1.3 christos if (r->mnemonic && (strcmp (r->mnemonic, opcodename)))
3484 1.1.1.3 christos continue;
3485 1.1.1.3.2.2 pgoyette if (r->flags[0])
3486 1.1.1.3 christos {
3487 1.1.1.3 christos if (!nflg)
3488 1.1.1.3 christos continue;
3489 1.1.1.3 christos found_flag = FALSE;
3490 1.1.1.3.2.2 pgoyette unsigned * psflg = (unsigned *)r->flags;
3491 1.1.1.3.2.2 pgoyette do
3492 1.1.1.3.2.2 pgoyette {
3493 1.1.1.3.2.2 pgoyette tmp = FALSE;
3494 1.1.1.3.2.2 pgoyette for (j = 0; j < nflg; j++)
3495 1.1.1.3.2.2 pgoyette if (!strcmp (pflags[j].name,
3496 1.1.1.3.2.2 pgoyette arc_flag_operands[*psflg].name))
3497 1.1.1.3.2.2 pgoyette {
3498 1.1.1.3.2.2 pgoyette tmp = TRUE;
3499 1.1.1.3.2.2 pgoyette break;
3500 1.1.1.3.2.2 pgoyette }
3501 1.1.1.3.2.2 pgoyette if (!tmp)
3502 1.1.1.3.2.2 pgoyette {
3503 1.1.1.3.2.2 pgoyette found_flag = FALSE;
3504 1.1.1.3.2.2 pgoyette break;
3505 1.1.1.3.2.2 pgoyette }
3506 1.1.1.3.2.2 pgoyette else
3507 1.1.1.3.2.2 pgoyette {
3508 1.1.1.3.2.2 pgoyette found_flag = TRUE;
3509 1.1.1.3.2.2 pgoyette }
3510 1.1.1.3.2.2 pgoyette ++ psflg;
3511 1.1.1.3.2.2 pgoyette } while (*psflg);
3512 1.1.1.3.2.2 pgoyette
3513 1.1.1.3 christos if (!found_flag)
3514 1.1.1.3 christos continue;
3515 1.1.1.3 christos }
3516 1.1.1.3 christos
3517 1.1.1.3 christos if (reloc != r->oldreloc)
3518 1.1.1.3 christos continue;
3519 1.1.1.3 christos /* Found it. */
3520 1.1.1.3 christos ret = r->newreloc;
3521 1.1.1.3 christos break;
3522 1.1.1.3 christos }
3523 1.1.1.3 christos
3524 1.1.1.3 christos if (ret == BFD_RELOC_UNUSED)
3525 1.1.1.3 christos as_bad (_("Unable to find %s relocation for instruction %s"),
3526 1.1.1.3 christos name, opcodename);
3527 1.1.1.3 christos return ret;
3528 1.1.1.3 christos }
3529 1.1.1.3 christos
3530 1.1.1.3.2.2 pgoyette /* All the symbol types that are allowed to be used for
3531 1.1.1.3.2.2 pgoyette relaxation. */
3532 1.1.1.3.2.2 pgoyette
3533 1.1.1.3.2.2 pgoyette static bfd_boolean
3534 1.1.1.3.2.2 pgoyette may_relax_expr (expressionS tok)
3535 1.1.1.3.2.2 pgoyette {
3536 1.1.1.3.2.2 pgoyette /* Check if we have unrelaxable relocs. */
3537 1.1.1.3.2.2 pgoyette switch (tok.X_md)
3538 1.1.1.3.2.2 pgoyette {
3539 1.1.1.3.2.2 pgoyette default:
3540 1.1.1.3.2.2 pgoyette break;
3541 1.1.1.3.2.2 pgoyette case O_plt:
3542 1.1.1.3.2.2 pgoyette return FALSE;
3543 1.1.1.3.2.2 pgoyette }
3544 1.1.1.3.2.2 pgoyette
3545 1.1.1.3.2.2 pgoyette switch (tok.X_op)
3546 1.1.1.3.2.2 pgoyette {
3547 1.1.1.3.2.2 pgoyette case O_symbol:
3548 1.1.1.3.2.2 pgoyette case O_multiply:
3549 1.1.1.3.2.2 pgoyette case O_divide:
3550 1.1.1.3.2.2 pgoyette case O_modulus:
3551 1.1.1.3.2.2 pgoyette case O_add:
3552 1.1.1.3.2.2 pgoyette case O_subtract:
3553 1.1.1.3.2.2 pgoyette break;
3554 1.1.1.3.2.2 pgoyette
3555 1.1.1.3.2.2 pgoyette default:
3556 1.1.1.3.2.2 pgoyette return FALSE;
3557 1.1.1.3.2.2 pgoyette }
3558 1.1.1.3.2.2 pgoyette return TRUE;
3559 1.1.1.3.2.2 pgoyette }
3560 1.1.1.3.2.2 pgoyette
3561 1.1.1.3.2.2 pgoyette /* Checks if flags are in line with relaxable insn. */
3562 1.1.1.3.2.2 pgoyette
3563 1.1.1.3.2.2 pgoyette static bfd_boolean
3564 1.1.1.3.2.2 pgoyette relaxable_flag (const struct arc_relaxable_ins *ins,
3565 1.1.1.3.2.2 pgoyette const struct arc_flags *pflags,
3566 1.1.1.3.2.2 pgoyette int nflgs)
3567 1.1.1.3.2.2 pgoyette {
3568 1.1.1.3.2.2 pgoyette unsigned flag_class,
3569 1.1.1.3.2.2 pgoyette flag,
3570 1.1.1.3.2.2 pgoyette flag_class_idx = 0,
3571 1.1.1.3.2.2 pgoyette flag_idx = 0;
3572 1.1.1.3.2.2 pgoyette
3573 1.1.1.3.2.2 pgoyette const struct arc_flag_operand *flag_opand;
3574 1.1.1.3.2.2 pgoyette int i, counttrue = 0;
3575 1.1.1.3.2.2 pgoyette
3576 1.1.1.3.2.2 pgoyette /* Iterate through flags classes. */
3577 1.1.1.3.2.2 pgoyette while ((flag_class = ins->flag_classes[flag_class_idx]) != 0)
3578 1.1.1.3.2.2 pgoyette {
3579 1.1.1.3.2.2 pgoyette /* Iterate through flags in flag class. */
3580 1.1.1.3.2.2 pgoyette while ((flag = arc_flag_classes[flag_class].flags[flag_idx])
3581 1.1.1.3.2.2 pgoyette != 0)
3582 1.1.1.3.2.2 pgoyette {
3583 1.1.1.3.2.2 pgoyette flag_opand = &arc_flag_operands[flag];
3584 1.1.1.3.2.2 pgoyette /* Iterate through flags in ins to compare. */
3585 1.1.1.3.2.2 pgoyette for (i = 0; i < nflgs; ++i)
3586 1.1.1.3.2.2 pgoyette {
3587 1.1.1.3.2.2 pgoyette if (strcmp (flag_opand->name, pflags[i].name) == 0)
3588 1.1.1.3.2.2 pgoyette ++counttrue;
3589 1.1.1.3.2.2 pgoyette }
3590 1.1.1.3.2.2 pgoyette
3591 1.1.1.3.2.2 pgoyette ++flag_idx;
3592 1.1.1.3.2.2 pgoyette }
3593 1.1.1.3.2.2 pgoyette
3594 1.1.1.3.2.2 pgoyette ++flag_class_idx;
3595 1.1.1.3.2.2 pgoyette flag_idx = 0;
3596 1.1.1.3.2.2 pgoyette }
3597 1.1.1.3.2.2 pgoyette
3598 1.1.1.3.2.2 pgoyette /* If counttrue == nflgs, then all flags have been found. */
3599 1.1.1.3.2.2 pgoyette return (counttrue == nflgs ? TRUE : FALSE);
3600 1.1.1.3.2.2 pgoyette }
3601 1.1.1.3.2.2 pgoyette
3602 1.1.1.3.2.2 pgoyette /* Checks if operands are in line with relaxable insn. */
3603 1.1.1.3.2.2 pgoyette
3604 1.1.1.3.2.2 pgoyette static bfd_boolean
3605 1.1.1.3.2.2 pgoyette relaxable_operand (const struct arc_relaxable_ins *ins,
3606 1.1.1.3.2.2 pgoyette const expressionS *tok,
3607 1.1.1.3.2.2 pgoyette int ntok)
3608 1.1.1.3.2.2 pgoyette {
3609 1.1.1.3.2.2 pgoyette const enum rlx_operand_type *operand = &ins->operands[0];
3610 1.1.1.3.2.2 pgoyette int i = 0;
3611 1.1.1.3.2.2 pgoyette
3612 1.1.1.3.2.2 pgoyette while (*operand != EMPTY)
3613 1.1.1.3.2.2 pgoyette {
3614 1.1.1.3.2.2 pgoyette const expressionS *epr = &tok[i];
3615 1.1.1.3.2.2 pgoyette
3616 1.1.1.3.2.2 pgoyette if (i != 0 && i >= ntok)
3617 1.1.1.3.2.2 pgoyette return FALSE;
3618 1.1.1.3.2.2 pgoyette
3619 1.1.1.3.2.2 pgoyette switch (*operand)
3620 1.1.1.3.2.2 pgoyette {
3621 1.1.1.3.2.2 pgoyette case IMMEDIATE:
3622 1.1.1.3.2.2 pgoyette if (!(epr->X_op == O_multiply
3623 1.1.1.3.2.2 pgoyette || epr->X_op == O_divide
3624 1.1.1.3.2.2 pgoyette || epr->X_op == O_modulus
3625 1.1.1.3.2.2 pgoyette || epr->X_op == O_add
3626 1.1.1.3.2.2 pgoyette || epr->X_op == O_subtract
3627 1.1.1.3.2.2 pgoyette || epr->X_op == O_symbol))
3628 1.1.1.3.2.2 pgoyette return FALSE;
3629 1.1.1.3.2.2 pgoyette break;
3630 1.1.1.3.2.2 pgoyette
3631 1.1.1.3.2.2 pgoyette case REGISTER_DUP:
3632 1.1.1.3.2.2 pgoyette if ((i <= 0)
3633 1.1.1.3.2.2 pgoyette || (epr->X_add_number != tok[i - 1].X_add_number))
3634 1.1.1.3.2.2 pgoyette return FALSE;
3635 1.1.1.3.2.2 pgoyette /* Fall through. */
3636 1.1.1.3.2.2 pgoyette case REGISTER:
3637 1.1.1.3.2.2 pgoyette if (epr->X_op != O_register)
3638 1.1.1.3.2.2 pgoyette return FALSE;
3639 1.1.1.3.2.2 pgoyette break;
3640 1.1.1.3.2.2 pgoyette
3641 1.1.1.3.2.2 pgoyette case REGISTER_S:
3642 1.1.1.3.2.2 pgoyette if (epr->X_op != O_register)
3643 1.1.1.3.2.2 pgoyette return FALSE;
3644 1.1.1.3.2.2 pgoyette
3645 1.1.1.3.2.2 pgoyette switch (epr->X_add_number)
3646 1.1.1.3.2.2 pgoyette {
3647 1.1.1.3.2.2 pgoyette case 0: case 1: case 2: case 3:
3648 1.1.1.3.2.2 pgoyette case 12: case 13: case 14: case 15:
3649 1.1.1.3.2.2 pgoyette break;
3650 1.1.1.3.2.2 pgoyette default:
3651 1.1.1.3.2.2 pgoyette return FALSE;
3652 1.1.1.3.2.2 pgoyette }
3653 1.1.1.3.2.2 pgoyette break;
3654 1.1.1.3.2.2 pgoyette
3655 1.1.1.3.2.2 pgoyette case REGISTER_NO_GP:
3656 1.1.1.3.2.2 pgoyette if ((epr->X_op != O_register)
3657 1.1.1.3.2.2 pgoyette || (epr->X_add_number == 26)) /* 26 is the gp register. */
3658 1.1.1.3.2.2 pgoyette return FALSE;
3659 1.1.1.3.2.2 pgoyette break;
3660 1.1.1.3.2.2 pgoyette
3661 1.1.1.3.2.2 pgoyette case BRACKET:
3662 1.1.1.3.2.2 pgoyette if (epr->X_op != O_bracket)
3663 1.1.1.3.2.2 pgoyette return FALSE;
3664 1.1.1.3.2.2 pgoyette break;
3665 1.1.1.3.2.2 pgoyette
3666 1.1.1.3.2.2 pgoyette default:
3667 1.1.1.3.2.2 pgoyette /* Don't understand, bail out. */
3668 1.1.1.3.2.2 pgoyette return FALSE;
3669 1.1.1.3.2.2 pgoyette break;
3670 1.1.1.3.2.2 pgoyette }
3671 1.1.1.3.2.2 pgoyette
3672 1.1.1.3.2.2 pgoyette ++i;
3673 1.1.1.3.2.2 pgoyette operand = &ins->operands[i];
3674 1.1.1.3.2.2 pgoyette }
3675 1.1.1.3.2.2 pgoyette
3676 1.1.1.3.2.2 pgoyette return (i == ntok ? TRUE : FALSE);
3677 1.1.1.3.2.2 pgoyette }
3678 1.1.1.3.2.2 pgoyette
3679 1.1.1.3.2.2 pgoyette /* Return TRUE if this OPDCODE is a candidate for relaxation. */
3680 1.1.1.3.2.2 pgoyette
3681 1.1.1.3.2.2 pgoyette static bfd_boolean
3682 1.1.1.3.2.2 pgoyette relax_insn_p (const struct arc_opcode *opcode,
3683 1.1.1.3.2.2 pgoyette const expressionS *tok,
3684 1.1.1.3.2.2 pgoyette int ntok,
3685 1.1.1.3.2.2 pgoyette const struct arc_flags *pflags,
3686 1.1.1.3.2.2 pgoyette int nflg)
3687 1.1.1.3.2.2 pgoyette {
3688 1.1.1.3.2.2 pgoyette unsigned i;
3689 1.1.1.3.2.2 pgoyette bfd_boolean rv = FALSE;
3690 1.1.1.3.2.2 pgoyette
3691 1.1.1.3.2.2 pgoyette /* Check the relaxation table. */
3692 1.1.1.3.2.2 pgoyette for (i = 0; i < arc_num_relaxable_ins && relaxation_state; ++i)
3693 1.1.1.3.2.2 pgoyette {
3694 1.1.1.3.2.2 pgoyette const struct arc_relaxable_ins *arc_rlx_ins = &arc_relaxable_insns[i];
3695 1.1.1.3.2.2 pgoyette
3696 1.1.1.3.2.2 pgoyette if ((strcmp (opcode->name, arc_rlx_ins->mnemonic_r) == 0)
3697 1.1.1.3.2.2 pgoyette && may_relax_expr (tok[arc_rlx_ins->opcheckidx])
3698 1.1.1.3.2.2 pgoyette && relaxable_operand (arc_rlx_ins, tok, ntok)
3699 1.1.1.3.2.2 pgoyette && relaxable_flag (arc_rlx_ins, pflags, nflg))
3700 1.1.1.3.2.2 pgoyette {
3701 1.1.1.3.2.2 pgoyette rv = TRUE;
3702 1.1.1.3.2.2 pgoyette frag_now->fr_subtype = arc_relaxable_insns[i].subtype;
3703 1.1.1.3.2.2 pgoyette memcpy (&frag_now->tc_frag_data.tok, tok,
3704 1.1.1.3.2.2 pgoyette sizeof (expressionS) * ntok);
3705 1.1.1.3.2.2 pgoyette memcpy (&frag_now->tc_frag_data.pflags, pflags,
3706 1.1.1.3.2.2 pgoyette sizeof (struct arc_flags) * nflg);
3707 1.1.1.3.2.2 pgoyette frag_now->tc_frag_data.nflg = nflg;
3708 1.1.1.3.2.2 pgoyette frag_now->tc_frag_data.ntok = ntok;
3709 1.1.1.3.2.2 pgoyette break;
3710 1.1.1.3.2.2 pgoyette }
3711 1.1.1.3.2.2 pgoyette }
3712 1.1.1.3.2.2 pgoyette
3713 1.1.1.3.2.2 pgoyette return rv;
3714 1.1.1.3.2.2 pgoyette }
3715 1.1.1.3.2.2 pgoyette
3716 1.1.1.3 christos /* Turn an opcode description and a set of arguments into
3717 1.1.1.3 christos an instruction and a fixup. */
3718 1.1.1.3 christos
3719 1.1.1.3 christos static void
3720 1.1.1.3 christos assemble_insn (const struct arc_opcode *opcode,
3721 1.1.1.3 christos const expressionS *tok,
3722 1.1.1.3 christos int ntok,
3723 1.1.1.3 christos const struct arc_flags *pflags,
3724 1.1.1.3 christos int nflg,
3725 1.1.1.3 christos struct arc_insn *insn)
3726 1.1.1.3 christos {
3727 1.1.1.3 christos const expressionS *reloc_exp = NULL;
3728 1.1.1.3 christos unsigned image;
3729 1.1.1.3 christos const unsigned char *argidx;
3730 1.1.1.3 christos int i;
3731 1.1.1.3 christos int tokidx = 0;
3732 1.1.1.3 christos unsigned char pcrel = 0;
3733 1.1.1.3 christos bfd_boolean needGOTSymbol;
3734 1.1.1.3 christos bfd_boolean has_delay_slot = FALSE;
3735 1.1.1.3 christos extended_bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
3736 1.1.1.3 christos
3737 1.1.1.3 christos memset (insn, 0, sizeof (*insn));
3738 1.1.1.3 christos image = opcode->opcode;
3739 1.1.1.3 christos
3740 1.1.1.3 christos pr_debug ("%s:%d: assemble_insn: %s using opcode %x\n",
3741 1.1.1.3 christos frag_now->fr_file, frag_now->fr_line, opcode->name,
3742 1.1.1.3 christos opcode->opcode);
3743 1.1.1.3 christos
3744 1.1.1.3 christos /* Handle operands. */
3745 1.1.1.3 christos for (argidx = opcode->operands; *argidx; ++argidx)
3746 1.1.1.3 christos {
3747 1.1.1.3 christos const struct arc_operand *operand = &arc_operands[*argidx];
3748 1.1.1.3 christos const expressionS *t = (const expressionS *) 0;
3749 1.1.1.3 christos
3750 1.1.1.3 christos if ((operand->flags & ARC_OPERAND_FAKE)
3751 1.1.1.3 christos && !(operand->flags & ARC_OPERAND_BRAKET))
3752 1.1.1.3 christos continue;
3753 1.1.1.3 christos
3754 1.1.1.3 christos if (operand->flags & ARC_OPERAND_DUPLICATE)
3755 1.1.1.3 christos {
3756 1.1.1.3 christos /* Duplicate operand, already inserted. */
3757 1.1.1.3 christos tokidx ++;
3758 1.1.1.3 christos continue;
3759 1.1.1.3 christos }
3760 1.1.1.3 christos
3761 1.1.1.3 christos if (tokidx >= ntok)
3762 1.1.1.3 christos {
3763 1.1.1.3 christos abort ();
3764 1.1.1.3 christos }
3765 1.1.1.3 christos else
3766 1.1.1.3 christos t = &tok[tokidx++];
3767 1.1.1.3 christos
3768 1.1.1.3 christos /* Regardless if we have a reloc or not mark the instruction
3769 1.1.1.3 christos limm if it is the case. */
3770 1.1.1.3 christos if (operand->flags & ARC_OPERAND_LIMM)
3771 1.1.1.3 christos insn->has_limm = TRUE;
3772 1.1.1.3 christos
3773 1.1.1.3 christos switch (t->X_op)
3774 1.1.1.3 christos {
3775 1.1.1.3 christos case O_register:
3776 1.1.1.3 christos image = insert_operand (image, operand, regno (t->X_add_number),
3777 1.1.1.3 christos NULL, 0);
3778 1.1.1.3 christos break;
3779 1.1.1.3 christos
3780 1.1.1.3 christos case O_constant:
3781 1.1.1.3 christos image = insert_operand (image, operand, t->X_add_number, NULL, 0);
3782 1.1.1.3 christos reloc_exp = t;
3783 1.1.1.3 christos if (operand->flags & ARC_OPERAND_LIMM)
3784 1.1.1.3 christos insn->limm = t->X_add_number;
3785 1.1.1.3 christos break;
3786 1.1.1.3 christos
3787 1.1.1.3 christos case O_bracket:
3788 1.1.1.3 christos /* Ignore brackets. */
3789 1.1.1.3 christos break;
3790 1.1.1.3 christos
3791 1.1.1.3 christos case O_absent:
3792 1.1.1.3 christos gas_assert (operand->flags & ARC_OPERAND_IGNORE);
3793 1.1.1.3 christos break;
3794 1.1.1.3 christos
3795 1.1.1.3 christos case O_subtract:
3796 1.1.1.3 christos /* Maybe register range. */
3797 1.1.1.3 christos if ((t->X_add_number == 0)
3798 1.1.1.3 christos && contains_register (t->X_add_symbol)
3799 1.1.1.3 christos && contains_register (t->X_op_symbol))
3800 1.1.1.3 christos {
3801 1.1.1.3 christos int regs;
3802 1.1.1.3 christos
3803 1.1.1.3 christos regs = get_register (t->X_add_symbol);
3804 1.1.1.3 christos regs <<= 16;
3805 1.1.1.3 christos regs |= get_register (t->X_op_symbol);
3806 1.1.1.3 christos image = insert_operand (image, operand, regs, NULL, 0);
3807 1.1.1.3 christos break;
3808 1.1.1.3 christos }
3809 1.1.1.3 christos
3810 1.1.1.3 christos default:
3811 1.1.1.3 christos /* This operand needs a relocation. */
3812 1.1.1.3 christos needGOTSymbol = FALSE;
3813 1.1.1.3 christos
3814 1.1.1.3 christos switch (t->X_md)
3815 1.1.1.3 christos {
3816 1.1.1.3 christos case O_plt:
3817 1.1.1.3.2.2 pgoyette if (opcode->insn_class == JUMP)
3818 1.1.1.3.2.2 pgoyette as_bad_where (frag_now->fr_file, frag_now->fr_line,
3819 1.1.1.3.2.2 pgoyette _("Unable to use @plt relocatio for insn %s"),
3820 1.1.1.3.2.2 pgoyette opcode->name);
3821 1.1.1.3 christos needGOTSymbol = TRUE;
3822 1.1.1.3 christos reloc = find_reloc ("plt", opcode->name,
3823 1.1.1.3 christos pflags, nflg,
3824 1.1.1.3 christos operand->default_reloc);
3825 1.1.1.3 christos break;
3826 1.1.1.3 christos
3827 1.1.1.3 christos case O_gotoff:
3828 1.1.1.3 christos case O_gotpc:
3829 1.1.1.3 christos needGOTSymbol = TRUE;
3830 1.1.1.3 christos reloc = ARC_RELOC_TABLE (t->X_md)->reloc;
3831 1.1.1.3 christos break;
3832 1.1.1.3 christos case O_pcl:
3833 1.1.1.3 christos reloc = ARC_RELOC_TABLE (t->X_md)->reloc;
3834 1.1.1.3.2.2 pgoyette if (ARC_SHORT (opcode->mask) || opcode->insn_class == JUMP)
3835 1.1.1.3 christos as_bad_where (frag_now->fr_file, frag_now->fr_line,
3836 1.1.1.3 christos _("Unable to use @pcl relocation for insn %s"),
3837 1.1.1.3 christos opcode->name);
3838 1.1.1.3 christos break;
3839 1.1.1.3 christos case O_sda:
3840 1.1.1.3 christos reloc = find_reloc ("sda", opcode->name,
3841 1.1.1.3 christos pflags, nflg,
3842 1.1.1.3 christos operand->default_reloc);
3843 1.1.1.3 christos break;
3844 1.1.1.3 christos case O_tlsgd:
3845 1.1.1.3 christos case O_tlsie:
3846 1.1.1.3 christos needGOTSymbol = TRUE;
3847 1.1.1.3 christos /* Fall-through. */
3848 1.1.1.3 christos
3849 1.1.1.3 christos case O_tpoff:
3850 1.1.1.3 christos case O_dtpoff:
3851 1.1.1.3 christos reloc = ARC_RELOC_TABLE (t->X_md)->reloc;
3852 1.1.1.3 christos break;
3853 1.1.1.3 christos
3854 1.1.1.3 christos case O_tpoff9: /*FIXME! Check for the conditionality of
3855 1.1.1.3 christos the insn. */
3856 1.1.1.3 christos case O_dtpoff9: /*FIXME! Check for the conditionality of
3857 1.1.1.3 christos the insn. */
3858 1.1.1.3 christos as_bad (_("TLS_*_S9 relocs are not supported yet"));
3859 1.1.1.3 christos break;
3860 1.1.1.3 christos
3861 1.1.1.3 christos default:
3862 1.1.1.3 christos /* Just consider the default relocation. */
3863 1.1.1.3 christos reloc = operand->default_reloc;
3864 1.1.1.3 christos break;
3865 1.1.1.3 christos }
3866 1.1.1.3 christos
3867 1.1.1.3 christos if (needGOTSymbol && (GOT_symbol == NULL))
3868 1.1.1.3 christos GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME);
3869 1.1.1.3 christos
3870 1.1.1.3 christos reloc_exp = t;
3871 1.1.1.3 christos
3872 1.1.1.3 christos #if 0
3873 1.1.1.3 christos if (reloc > 0)
3874 1.1.1.3 christos {
3875 1.1.1.3 christos /* sanity checks. */
3876 1.1.1.3 christos reloc_howto_type *reloc_howto
3877 1.1.1.3 christos = bfd_reloc_type_lookup (stdoutput,
3878 1.1.1.3 christos (bfd_reloc_code_real_type) reloc);
3879 1.1.1.3 christos unsigned reloc_bitsize = reloc_howto->bitsize;
3880 1.1.1.3 christos if (reloc_howto->rightshift)
3881 1.1.1.3 christos reloc_bitsize -= reloc_howto->rightshift;
3882 1.1.1.3 christos if (reloc_bitsize != operand->bits)
3883 1.1.1.3 christos {
3884 1.1.1.3 christos as_bad (_("invalid relocation %s for field"),
3885 1.1.1.3 christos bfd_get_reloc_code_name (reloc));
3886 1.1.1.3 christos return;
3887 1.1.1.3 christos }
3888 1.1.1.3 christos }
3889 1.1.1.3 christos #endif
3890 1.1.1.3 christos if (insn->nfixups >= MAX_INSN_FIXUPS)
3891 1.1.1.3 christos as_fatal (_("too many fixups"));
3892 1.1.1.3 christos
3893 1.1.1.3 christos struct arc_fixup *fixup;
3894 1.1.1.3 christos fixup = &insn->fixups[insn->nfixups++];
3895 1.1.1.3 christos fixup->exp = *t;
3896 1.1.1.3 christos fixup->reloc = reloc;
3897 1.1.1.3 christos pcrel = (operand->flags & ARC_OPERAND_PCREL) ? 1 : 0;
3898 1.1.1.3 christos fixup->pcrel = pcrel;
3899 1.1.1.3 christos fixup->islong = (operand->flags & ARC_OPERAND_LIMM) ?
3900 1.1.1.3 christos TRUE : FALSE;
3901 1.1.1.3 christos break;
3902 1.1.1.3 christos }
3903 1.1.1.3 christos }
3904 1.1.1.3 christos
3905 1.1.1.3 christos /* Handle flags. */
3906 1.1.1.3 christos for (i = 0; i < nflg; i++)
3907 1.1.1.3 christos {
3908 1.1.1.3.2.2 pgoyette const struct arc_flag_operand *flg_operand = pflags[i].flgp;
3909 1.1.1.3 christos
3910 1.1.1.3 christos /* Check if the instruction has a delay slot. */
3911 1.1.1.3 christos if (!strcmp (flg_operand->name, "d"))
3912 1.1.1.3 christos has_delay_slot = TRUE;
3913 1.1.1.3 christos
3914 1.1.1.3 christos /* There is an exceptional case when we cannot insert a flag
3915 1.1.1.3 christos just as it is. The .T flag must be handled in relation with
3916 1.1.1.3 christos the relative address. */
3917 1.1.1.3 christos if (!strcmp (flg_operand->name, "t")
3918 1.1.1.3 christos || !strcmp (flg_operand->name, "nt"))
3919 1.1.1.3 christos {
3920 1.1.1.3 christos unsigned bitYoperand = 0;
3921 1.1.1.3 christos /* FIXME! move selection bbit/brcc in arc-opc.c. */
3922 1.1.1.3 christos if (!strcmp (flg_operand->name, "t"))
3923 1.1.1.3 christos if (!strcmp (opcode->name, "bbit0")
3924 1.1.1.3 christos || !strcmp (opcode->name, "bbit1"))
3925 1.1.1.3 christos bitYoperand = arc_NToperand;
3926 1.1.1.3 christos else
3927 1.1.1.3 christos bitYoperand = arc_Toperand;
3928 1.1.1.3 christos else
3929 1.1.1.3 christos if (!strcmp (opcode->name, "bbit0")
3930 1.1.1.3 christos || !strcmp (opcode->name, "bbit1"))
3931 1.1.1.3 christos bitYoperand = arc_Toperand;
3932 1.1.1.3 christos else
3933 1.1.1.3 christos bitYoperand = arc_NToperand;
3934 1.1.1.3 christos
3935 1.1.1.3 christos gas_assert (reloc_exp != NULL);
3936 1.1.1.3 christos if (reloc_exp->X_op == O_constant)
3937 1.1.1.3 christos {
3938 1.1.1.3 christos /* Check if we have a constant and solved it
3939 1.1.1.3 christos immediately. */
3940 1.1.1.3 christos offsetT val = reloc_exp->X_add_number;
3941 1.1.1.3 christos image |= insert_operand (image, &arc_operands[bitYoperand],
3942 1.1.1.3 christos val, NULL, 0);
3943 1.1.1.3 christos }
3944 1.1.1.3 christos else
3945 1.1.1.3 christos {
3946 1.1.1.3 christos struct arc_fixup *fixup;
3947 1.1.1.3 christos
3948 1.1.1.3 christos if (insn->nfixups >= MAX_INSN_FIXUPS)
3949 1.1.1.3 christos as_fatal (_("too many fixups"));
3950 1.1.1.3 christos
3951 1.1.1.3 christos fixup = &insn->fixups[insn->nfixups++];
3952 1.1.1.3 christos fixup->exp = *reloc_exp;
3953 1.1.1.3 christos fixup->reloc = -bitYoperand;
3954 1.1.1.3 christos fixup->pcrel = pcrel;
3955 1.1.1.3 christos fixup->islong = FALSE;
3956 1.1.1.3 christos }
3957 1.1.1.3 christos }
3958 1.1.1.3 christos else
3959 1.1.1.3 christos image |= (flg_operand->code & ((1 << flg_operand->bits) - 1))
3960 1.1.1.3 christos << flg_operand->shift;
3961 1.1.1.3 christos }
3962 1.1.1.3 christos
3963 1.1.1.3.2.2 pgoyette insn->relax = relax_insn_p (opcode, tok, ntok, pflags, nflg);
3964 1.1.1.3.2.2 pgoyette
3965 1.1.1.3.2.2 pgoyette /* Short instruction? */
3966 1.1.1.3.2.2 pgoyette insn->short_insn = ARC_SHORT (opcode->mask) ? TRUE : FALSE;
3967 1.1.1.3.2.2 pgoyette
3968 1.1.1.3.2.2 pgoyette insn->insn = image;
3969 1.1.1.3.2.2 pgoyette
3970 1.1.1.3.2.2 pgoyette /* Update last insn status. */
3971 1.1.1.3.2.2 pgoyette arc_last_insns[1] = arc_last_insns[0];
3972 1.1.1.3.2.2 pgoyette arc_last_insns[0].opcode = opcode;
3973 1.1.1.3.2.2 pgoyette arc_last_insns[0].has_limm = insn->has_limm;
3974 1.1.1.3.2.2 pgoyette arc_last_insns[0].has_delay_slot = has_delay_slot;
3975 1.1.1.3.2.2 pgoyette
3976 1.1.1.3.2.2 pgoyette /* Check if the current instruction is legally used. */
3977 1.1.1.3.2.2 pgoyette if (arc_last_insns[1].has_delay_slot
3978 1.1.1.3.2.2 pgoyette && is_br_jmp_insn_p (arc_last_insns[0].opcode))
3979 1.1.1.3.2.2 pgoyette as_bad_where (frag_now->fr_file, frag_now->fr_line,
3980 1.1.1.3.2.2 pgoyette _("A jump/branch instruction in delay slot."));
3981 1.1.1.3 christos }
3982 1.1.1.3 christos
3983 1.1.1.3 christos void
3984 1.1.1.3 christos arc_handle_align (fragS* fragP)
3985 1.1.1.3 christos {
3986 1.1.1.3 christos if ((fragP)->fr_type == rs_align_code)
3987 1.1.1.3 christos {
3988 1.1.1.3 christos char *dest = (fragP)->fr_literal + (fragP)->fr_fix;
3989 1.1.1.3 christos valueT count = ((fragP)->fr_next->fr_address
3990 1.1.1.3 christos - (fragP)->fr_address - (fragP)->fr_fix);
3991 1.1.1.3 christos
3992 1.1.1.3 christos (fragP)->fr_var = 2;
3993 1.1.1.3 christos
3994 1.1.1.3 christos if (count & 1)/* Padding in the gap till the next 2-byte
3995 1.1.1.3 christos boundary with 0s. */
3996 1.1.1.3 christos {
3997 1.1.1.3 christos (fragP)->fr_fix++;
3998 1.1.1.3 christos *dest++ = 0;
3999 1.1.1.3 christos }
4000 1.1.1.3 christos /* Writing nop_s. */
4001 1.1.1.3 christos md_number_to_chars (dest, NOP_OPCODE_S, 2);
4002 1.1.1.3 christos }
4003 1.1.1.3 christos }
4004 1.1.1.3 christos
4005 1.1.1.3 christos /* Here we decide which fixups can be adjusted to make them relative
4006 1.1.1.3 christos to the beginning of the section instead of the symbol. Basically
4007 1.1.1.3 christos we need to make sure that the dynamic relocations are done
4008 1.1.1.3 christos correctly, so in some cases we force the original symbol to be
4009 1.1.1.3 christos used. */
4010 1.1.1.3 christos
4011 1.1.1.3 christos int
4012 1.1.1.3 christos tc_arc_fix_adjustable (fixS *fixP)
4013 1.1.1.3 christos {
4014 1.1.1.3 christos
4015 1.1.1.3 christos /* Prevent all adjustments to global symbols. */
4016 1.1.1.3 christos if (S_IS_EXTERNAL (fixP->fx_addsy))
4017 1.1.1.3 christos return 0;
4018 1.1.1.3 christos if (S_IS_WEAK (fixP->fx_addsy))
4019 1.1.1.3 christos return 0;
4020 1.1.1.3 christos
4021 1.1.1.3 christos /* Adjust_reloc_syms doesn't know about the GOT. */
4022 1.1.1.3 christos switch (fixP->fx_r_type)
4023 1.1.1.3 christos {
4024 1.1.1.3 christos case BFD_RELOC_ARC_GOTPC32:
4025 1.1.1.3 christos case BFD_RELOC_ARC_PLT32:
4026 1.1.1.3 christos case BFD_RELOC_ARC_S25H_PCREL_PLT:
4027 1.1.1.3 christos case BFD_RELOC_ARC_S21H_PCREL_PLT:
4028 1.1.1.3 christos case BFD_RELOC_ARC_S25W_PCREL_PLT:
4029 1.1.1.3 christos case BFD_RELOC_ARC_S21W_PCREL_PLT:
4030 1.1.1.3 christos return 0;
4031 1.1.1.3 christos
4032 1.1.1.3 christos default:
4033 1.1.1.3 christos break;
4034 1.1.1.3 christos }
4035 1.1.1.3 christos
4036 1.1.1.3.2.2 pgoyette return 1;
4037 1.1.1.3 christos }
4038 1.1.1.3 christos
4039 1.1.1.3 christos /* Compute the reloc type of an expression EXP. */
4040 1.1.1.3 christos
4041 1.1.1.3 christos static void
4042 1.1.1.3 christos arc_check_reloc (expressionS *exp,
4043 1.1.1.3 christos bfd_reloc_code_real_type *r_type_p)
4044 1.1.1.3 christos {
4045 1.1.1.3 christos if (*r_type_p == BFD_RELOC_32
4046 1.1.1.3 christos && exp->X_op == O_subtract
4047 1.1.1.3 christos && exp->X_op_symbol != NULL
4048 1.1.1.3 christos && exp->X_op_symbol->bsym->section == now_seg)
4049 1.1.1.3 christos *r_type_p = BFD_RELOC_ARC_32_PCREL;
4050 1.1.1.3 christos }
4051 1.1.1.3 christos
4052 1.1.1.3 christos
4053 1.1.1.3 christos /* Add expression EXP of SIZE bytes to offset OFF of fragment FRAG. */
4054 1.1.1.3 christos
4055 1.1.1.3 christos void
4056 1.1.1.3 christos arc_cons_fix_new (fragS *frag,
4057 1.1.1.3 christos int off,
4058 1.1.1.3 christos int size,
4059 1.1.1.3 christos expressionS *exp,
4060 1.1.1.3 christos bfd_reloc_code_real_type r_type)
4061 1.1.1.3 christos {
4062 1.1.1.3 christos r_type = BFD_RELOC_UNUSED;
4063 1.1.1.3 christos
4064 1.1.1.3 christos switch (size)
4065 1.1.1.3 christos {
4066 1.1.1.3 christos case 1:
4067 1.1.1.3 christos r_type = BFD_RELOC_8;
4068 1.1.1.3 christos break;
4069 1.1.1.3 christos
4070 1.1.1.3 christos case 2:
4071 1.1.1.3 christos r_type = BFD_RELOC_16;
4072 1.1.1.3 christos break;
4073 1.1.1.3 christos
4074 1.1.1.3 christos case 3:
4075 1.1.1.3 christos r_type = BFD_RELOC_24;
4076 1.1.1.3 christos break;
4077 1.1.1.3 christos
4078 1.1.1.3 christos case 4:
4079 1.1.1.3 christos r_type = BFD_RELOC_32;
4080 1.1.1.3 christos arc_check_reloc (exp, &r_type);
4081 1.1.1.3 christos break;
4082 1.1.1.3 christos
4083 1.1.1.3 christos case 8:
4084 1.1.1.3 christos r_type = BFD_RELOC_64;
4085 1.1.1.3 christos break;
4086 1.1.1.3 christos
4087 1.1.1.3 christos default:
4088 1.1.1.3 christos as_bad (_("unsupported BFD relocation size %u"), size);
4089 1.1.1.3 christos r_type = BFD_RELOC_UNUSED;
4090 1.1.1.3 christos }
4091 1.1.1.3 christos
4092 1.1.1.3 christos fix_new_exp (frag, off, size, exp, 0, r_type);
4093 1.1.1.3 christos }
4094 1.1.1.3 christos
4095 1.1.1.3 christos /* The actual routine that checks the ZOL conditions. */
4096 1.1.1.3 christos
4097 1.1.1.3 christos static void
4098 1.1.1.3 christos check_zol (symbolS *s)
4099 1.1.1.3 christos {
4100 1.1.1.3 christos switch (arc_mach_type)
4101 1.1.1.3 christos {
4102 1.1.1.3 christos case bfd_mach_arc_arcv2:
4103 1.1.1.3 christos if (arc_target & ARC_OPCODE_ARCv2EM)
4104 1.1.1.3 christos return;
4105 1.1.1.3 christos
4106 1.1.1.3 christos if (is_br_jmp_insn_p (arc_last_insns[0].opcode)
4107 1.1.1.3 christos || arc_last_insns[1].has_delay_slot)
4108 1.1.1.3 christos as_bad (_("Jump/Branch instruction detected at the end of the ZOL label @%s"),
4109 1.1.1.3 christos S_GET_NAME (s));
4110 1.1.1.3 christos
4111 1.1.1.3 christos break;
4112 1.1.1.3 christos case bfd_mach_arc_arc600:
4113 1.1.1.3 christos
4114 1.1.1.3 christos if (is_kernel_insn_p (arc_last_insns[0].opcode))
4115 1.1.1.3 christos as_bad (_("Kernel instruction detected at the end of the ZOL label @%s"),
4116 1.1.1.3 christos S_GET_NAME (s));
4117 1.1.1.3 christos
4118 1.1.1.3 christos if (arc_last_insns[0].has_limm
4119 1.1.1.3 christos && is_br_jmp_insn_p (arc_last_insns[0].opcode))
4120 1.1.1.3 christos as_bad (_("A jump instruction with long immediate detected at the \
4121 1.1.1.3 christos end of the ZOL label @%s"), S_GET_NAME (s));
4122 1.1.1.3 christos
4123 1.1.1.3 christos /* Fall through. */
4124 1.1.1.3 christos case bfd_mach_arc_arc700:
4125 1.1.1.3 christos if (arc_last_insns[0].has_delay_slot)
4126 1.1.1.3 christos as_bad (_("An illegal use of delay slot detected at the end of the ZOL label @%s"),
4127 1.1.1.3 christos S_GET_NAME (s));
4128 1.1.1.3 christos
4129 1.1.1.3 christos break;
4130 1.1.1.3 christos default:
4131 1.1.1.3 christos break;
4132 1.1.1.3 christos }
4133 1.1.1.3 christos }
4134 1.1.1.3 christos
4135 1.1.1.3 christos /* If ZOL end check the last two instruction for illegals. */
4136 1.1.1.3 christos void
4137 1.1.1.3 christos arc_frob_label (symbolS * sym)
4138 1.1.1.3 christos {
4139 1.1.1.3 christos if (ARC_GET_FLAG (sym) & ARC_FLAG_ZOL)
4140 1.1.1.3 christos check_zol (sym);
4141 1.1.1.3 christos
4142 1.1.1.3 christos dwarf2_emit_label (sym);
4143 1.1 skrll }
4144 1.1.1.3.2.2 pgoyette
4145 1.1.1.3.2.2 pgoyette /* Used because generic relaxation assumes a pc-rel value whilst we
4146 1.1.1.3.2.2 pgoyette also relax instructions that use an absolute value resolved out of
4147 1.1.1.3.2.2 pgoyette relative values (if that makes any sense). An example: 'add r1,
4148 1.1.1.3.2.2 pgoyette r2, @.L2 - .' The symbols . and @.L2 are relative to the section
4149 1.1.1.3.2.2 pgoyette but if they're in the same section we can subtract the section
4150 1.1.1.3.2.2 pgoyette offset relocation which ends up in a resolved value. So if @.L2 is
4151 1.1.1.3.2.2 pgoyette .text + 0x50 and . is .text + 0x10, we can say that .text + 0x50 -
4152 1.1.1.3.2.2 pgoyette .text + 0x40 = 0x10. */
4153 1.1.1.3.2.2 pgoyette int
4154 1.1.1.3.2.2 pgoyette arc_pcrel_adjust (fragS *fragP)
4155 1.1.1.3.2.2 pgoyette {
4156 1.1.1.3.2.2 pgoyette if (!fragP->tc_frag_data.pcrel)
4157 1.1.1.3.2.2 pgoyette return fragP->fr_address + fragP->fr_fix;
4158 1.1.1.3.2.2 pgoyette
4159 1.1.1.3.2.2 pgoyette return 0;
4160 1.1.1.3.2.2 pgoyette }
4161 1.1.1.3.2.2 pgoyette
4162 1.1.1.3.2.2 pgoyette /* Initialize the DWARF-2 unwind information for this procedure. */
4163 1.1.1.3.2.2 pgoyette
4164 1.1.1.3.2.2 pgoyette void
4165 1.1.1.3.2.2 pgoyette tc_arc_frame_initial_instructions (void)
4166 1.1.1.3.2.2 pgoyette {
4167 1.1.1.3.2.2 pgoyette /* Stack pointer is register 28. */
4168 1.1.1.3.2.2 pgoyette cfi_add_CFA_def_cfa (28, 0);
4169 1.1.1.3.2.2 pgoyette }
4170 1.1.1.3.2.2 pgoyette
4171 1.1.1.3.2.2 pgoyette int
4172 1.1.1.3.2.2 pgoyette tc_arc_regname_to_dw2regnum (char *regname)
4173 1.1.1.3.2.2 pgoyette {
4174 1.1.1.3.2.2 pgoyette struct symbol *sym;
4175 1.1.1.3.2.2 pgoyette
4176 1.1.1.3.2.2 pgoyette sym = hash_find (arc_reg_hash, regname);
4177 1.1.1.3.2.2 pgoyette if (sym)
4178 1.1.1.3.2.2 pgoyette return S_GET_VALUE (sym);
4179 1.1.1.3.2.2 pgoyette
4180 1.1.1.3.2.2 pgoyette return -1;
4181 1.1.1.3.2.2 pgoyette }
4182 1.1.1.3.2.2 pgoyette
4183 1.1.1.3.2.2 pgoyette /* Adjust the symbol table. Delete found AUX register symbols. */
4184 1.1.1.3.2.2 pgoyette
4185 1.1.1.3.2.2 pgoyette void
4186 1.1.1.3.2.2 pgoyette arc_adjust_symtab (void)
4187 1.1.1.3.2.2 pgoyette {
4188 1.1.1.3.2.2 pgoyette symbolS * sym;
4189 1.1.1.3.2.2 pgoyette
4190 1.1.1.3.2.2 pgoyette for (sym = symbol_rootP; sym != NULL; sym = symbol_next (sym))
4191 1.1.1.3.2.2 pgoyette {
4192 1.1.1.3.2.2 pgoyette /* I've created a symbol during parsing process. Now, remove
4193 1.1.1.3.2.2 pgoyette the symbol as it is found to be an AUX register. */
4194 1.1.1.3.2.2 pgoyette if (ARC_GET_FLAG (sym) & ARC_FLAG_AUX)
4195 1.1.1.3.2.2 pgoyette symbol_remove (sym, &symbol_rootP, &symbol_lastP);
4196 1.1.1.3.2.2 pgoyette }
4197 1.1.1.3.2.2 pgoyette
4198 1.1.1.3.2.2 pgoyette /* Now do generic ELF adjustments. */
4199 1.1.1.3.2.2 pgoyette elf_adjust_symtab ();
4200 1.1.1.3.2.2 pgoyette }
4201 1.1.1.3.2.2 pgoyette
4202 1.1.1.3.2.2 pgoyette static void
4203 1.1.1.3.2.2 pgoyette tokenize_extinsn (extInstruction_t *einsn)
4204 1.1.1.3.2.2 pgoyette {
4205 1.1.1.3.2.2 pgoyette char *p, c;
4206 1.1.1.3.2.2 pgoyette char *insn_name;
4207 1.1.1.3.2.2 pgoyette unsigned char major_opcode;
4208 1.1.1.3.2.2 pgoyette unsigned char sub_opcode;
4209 1.1.1.3.2.2 pgoyette unsigned char syntax_class = 0;
4210 1.1.1.3.2.2 pgoyette unsigned char syntax_class_modifiers = 0;
4211 1.1.1.3.2.2 pgoyette unsigned char suffix_class = 0;
4212 1.1.1.3.2.2 pgoyette unsigned int i;
4213 1.1.1.3.2.2 pgoyette
4214 1.1.1.3.2.2 pgoyette SKIP_WHITESPACE ();
4215 1.1.1.3.2.2 pgoyette
4216 1.1.1.3.2.2 pgoyette /* 1st: get instruction name. */
4217 1.1.1.3.2.2 pgoyette p = input_line_pointer;
4218 1.1.1.3.2.2 pgoyette c = get_symbol_name (&p);
4219 1.1.1.3.2.2 pgoyette
4220 1.1.1.3.2.2 pgoyette insn_name = xstrdup (p);
4221 1.1.1.3.2.2 pgoyette restore_line_pointer (c);
4222 1.1.1.3.2.2 pgoyette
4223 1.1.1.3.2.2 pgoyette /* 2nd: get major opcode. */
4224 1.1.1.3.2.2 pgoyette if (*input_line_pointer != ',')
4225 1.1.1.3.2.2 pgoyette {
4226 1.1.1.3.2.2 pgoyette as_bad (_("expected comma after instruction name"));
4227 1.1.1.3.2.2 pgoyette ignore_rest_of_line ();
4228 1.1.1.3.2.2 pgoyette return;
4229 1.1.1.3.2.2 pgoyette }
4230 1.1.1.3.2.2 pgoyette input_line_pointer++;
4231 1.1.1.3.2.2 pgoyette major_opcode = get_absolute_expression ();
4232 1.1.1.3.2.2 pgoyette
4233 1.1.1.3.2.2 pgoyette /* 3rd: get sub-opcode. */
4234 1.1.1.3.2.2 pgoyette SKIP_WHITESPACE ();
4235 1.1.1.3.2.2 pgoyette
4236 1.1.1.3.2.2 pgoyette if (*input_line_pointer != ',')
4237 1.1.1.3.2.2 pgoyette {
4238 1.1.1.3.2.2 pgoyette as_bad (_("expected comma after major opcode"));
4239 1.1.1.3.2.2 pgoyette ignore_rest_of_line ();
4240 1.1.1.3.2.2 pgoyette return;
4241 1.1.1.3.2.2 pgoyette }
4242 1.1.1.3.2.2 pgoyette input_line_pointer++;
4243 1.1.1.3.2.2 pgoyette sub_opcode = get_absolute_expression ();
4244 1.1.1.3.2.2 pgoyette
4245 1.1.1.3.2.2 pgoyette /* 4th: get suffix class. */
4246 1.1.1.3.2.2 pgoyette SKIP_WHITESPACE ();
4247 1.1.1.3.2.2 pgoyette
4248 1.1.1.3.2.2 pgoyette if (*input_line_pointer != ',')
4249 1.1.1.3.2.2 pgoyette {
4250 1.1.1.3.2.2 pgoyette as_bad ("expected comma after sub opcode");
4251 1.1.1.3.2.2 pgoyette ignore_rest_of_line ();
4252 1.1.1.3.2.2 pgoyette return;
4253 1.1.1.3.2.2 pgoyette }
4254 1.1.1.3.2.2 pgoyette input_line_pointer++;
4255 1.1.1.3.2.2 pgoyette
4256 1.1.1.3.2.2 pgoyette while (1)
4257 1.1.1.3.2.2 pgoyette {
4258 1.1.1.3.2.2 pgoyette SKIP_WHITESPACE ();
4259 1.1.1.3.2.2 pgoyette
4260 1.1.1.3.2.2 pgoyette for (i = 0; i < ARRAY_SIZE (suffixclass); i++)
4261 1.1.1.3.2.2 pgoyette {
4262 1.1.1.3.2.2 pgoyette if (!strncmp (suffixclass[i].name, input_line_pointer,
4263 1.1.1.3.2.2 pgoyette suffixclass[i].len))
4264 1.1.1.3.2.2 pgoyette {
4265 1.1.1.3.2.2 pgoyette suffix_class |= suffixclass[i].attr_class;
4266 1.1.1.3.2.2 pgoyette input_line_pointer += suffixclass[i].len;
4267 1.1.1.3.2.2 pgoyette break;
4268 1.1.1.3.2.2 pgoyette }
4269 1.1.1.3.2.2 pgoyette }
4270 1.1.1.3.2.2 pgoyette
4271 1.1.1.3.2.2 pgoyette if (i == ARRAY_SIZE (suffixclass))
4272 1.1.1.3.2.2 pgoyette {
4273 1.1.1.3.2.2 pgoyette as_bad ("invalid suffix class");
4274 1.1.1.3.2.2 pgoyette ignore_rest_of_line ();
4275 1.1.1.3.2.2 pgoyette return;
4276 1.1.1.3.2.2 pgoyette }
4277 1.1.1.3.2.2 pgoyette
4278 1.1.1.3.2.2 pgoyette SKIP_WHITESPACE ();
4279 1.1.1.3.2.2 pgoyette
4280 1.1.1.3.2.2 pgoyette if (*input_line_pointer == '|')
4281 1.1.1.3.2.2 pgoyette input_line_pointer++;
4282 1.1.1.3.2.2 pgoyette else
4283 1.1.1.3.2.2 pgoyette break;
4284 1.1.1.3.2.2 pgoyette }
4285 1.1.1.3.2.2 pgoyette
4286 1.1.1.3.2.2 pgoyette /* 5th: get syntax class and syntax class modifiers. */
4287 1.1.1.3.2.2 pgoyette if (*input_line_pointer != ',')
4288 1.1.1.3.2.2 pgoyette {
4289 1.1.1.3.2.2 pgoyette as_bad ("expected comma after suffix class");
4290 1.1.1.3.2.2 pgoyette ignore_rest_of_line ();
4291 1.1.1.3.2.2 pgoyette return;
4292 1.1.1.3.2.2 pgoyette }
4293 1.1.1.3.2.2 pgoyette input_line_pointer++;
4294 1.1.1.3.2.2 pgoyette
4295 1.1.1.3.2.2 pgoyette while (1)
4296 1.1.1.3.2.2 pgoyette {
4297 1.1.1.3.2.2 pgoyette SKIP_WHITESPACE ();
4298 1.1.1.3.2.2 pgoyette
4299 1.1.1.3.2.2 pgoyette for (i = 0; i < ARRAY_SIZE (syntaxclassmod); i++)
4300 1.1.1.3.2.2 pgoyette {
4301 1.1.1.3.2.2 pgoyette if (!strncmp (syntaxclassmod[i].name,
4302 1.1.1.3.2.2 pgoyette input_line_pointer,
4303 1.1.1.3.2.2 pgoyette syntaxclassmod[i].len))
4304 1.1.1.3.2.2 pgoyette {
4305 1.1.1.3.2.2 pgoyette syntax_class_modifiers |= syntaxclassmod[i].attr_class;
4306 1.1.1.3.2.2 pgoyette input_line_pointer += syntaxclassmod[i].len;
4307 1.1.1.3.2.2 pgoyette break;
4308 1.1.1.3.2.2 pgoyette }
4309 1.1.1.3.2.2 pgoyette }
4310 1.1.1.3.2.2 pgoyette
4311 1.1.1.3.2.2 pgoyette if (i == ARRAY_SIZE (syntaxclassmod))
4312 1.1.1.3.2.2 pgoyette {
4313 1.1.1.3.2.2 pgoyette for (i = 0; i < ARRAY_SIZE (syntaxclass); i++)
4314 1.1.1.3.2.2 pgoyette {
4315 1.1.1.3.2.2 pgoyette if (!strncmp (syntaxclass[i].name,
4316 1.1.1.3.2.2 pgoyette input_line_pointer,
4317 1.1.1.3.2.2 pgoyette syntaxclass[i].len))
4318 1.1.1.3.2.2 pgoyette {
4319 1.1.1.3.2.2 pgoyette syntax_class |= syntaxclass[i].attr_class;
4320 1.1.1.3.2.2 pgoyette input_line_pointer += syntaxclass[i].len;
4321 1.1.1.3.2.2 pgoyette break;
4322 1.1.1.3.2.2 pgoyette }
4323 1.1.1.3.2.2 pgoyette }
4324 1.1.1.3.2.2 pgoyette
4325 1.1.1.3.2.2 pgoyette if (i == ARRAY_SIZE (syntaxclass))
4326 1.1.1.3.2.2 pgoyette {
4327 1.1.1.3.2.2 pgoyette as_bad ("missing syntax class");
4328 1.1.1.3.2.2 pgoyette ignore_rest_of_line ();
4329 1.1.1.3.2.2 pgoyette return;
4330 1.1.1.3.2.2 pgoyette }
4331 1.1.1.3.2.2 pgoyette }
4332 1.1.1.3.2.2 pgoyette
4333 1.1.1.3.2.2 pgoyette SKIP_WHITESPACE ();
4334 1.1.1.3.2.2 pgoyette
4335 1.1.1.3.2.2 pgoyette if (*input_line_pointer == '|')
4336 1.1.1.3.2.2 pgoyette input_line_pointer++;
4337 1.1.1.3.2.2 pgoyette else
4338 1.1.1.3.2.2 pgoyette break;
4339 1.1.1.3.2.2 pgoyette }
4340 1.1.1.3.2.2 pgoyette
4341 1.1.1.3.2.2 pgoyette demand_empty_rest_of_line ();
4342 1.1.1.3.2.2 pgoyette
4343 1.1.1.3.2.2 pgoyette einsn->name = insn_name;
4344 1.1.1.3.2.2 pgoyette einsn->major = major_opcode;
4345 1.1.1.3.2.2 pgoyette einsn->minor = sub_opcode;
4346 1.1.1.3.2.2 pgoyette einsn->syntax = syntax_class;
4347 1.1.1.3.2.2 pgoyette einsn->modsyn = syntax_class_modifiers;
4348 1.1.1.3.2.2 pgoyette einsn->suffix = suffix_class;
4349 1.1.1.3.2.2 pgoyette einsn->flags = syntax_class
4350 1.1.1.3.2.2 pgoyette | (syntax_class_modifiers & ARC_OP1_IMM_IMPLIED ? 0x10 : 0);
4351 1.1.1.3.2.2 pgoyette }
4352 1.1.1.3.2.2 pgoyette
4353 1.1.1.3.2.2 pgoyette /* Generate an extension section. */
4354 1.1.1.3.2.2 pgoyette
4355 1.1.1.3.2.2 pgoyette static int
4356 1.1.1.3.2.2 pgoyette arc_set_ext_seg (void)
4357 1.1.1.3.2.2 pgoyette {
4358 1.1.1.3.2.2 pgoyette if (!arcext_section)
4359 1.1.1.3.2.2 pgoyette {
4360 1.1.1.3.2.2 pgoyette arcext_section = subseg_new (".arcextmap", 0);
4361 1.1.1.3.2.2 pgoyette bfd_set_section_flags (stdoutput, arcext_section,
4362 1.1.1.3.2.2 pgoyette SEC_READONLY | SEC_HAS_CONTENTS);
4363 1.1.1.3.2.2 pgoyette }
4364 1.1.1.3.2.2 pgoyette else
4365 1.1.1.3.2.2 pgoyette subseg_set (arcext_section, 0);
4366 1.1.1.3.2.2 pgoyette return 1;
4367 1.1.1.3.2.2 pgoyette }
4368 1.1.1.3.2.2 pgoyette
4369 1.1.1.3.2.2 pgoyette /* Create an extension instruction description in the arc extension
4370 1.1.1.3.2.2 pgoyette section of the output file.
4371 1.1.1.3.2.2 pgoyette The structure for an instruction is like this:
4372 1.1.1.3.2.2 pgoyette [0]: Length of the record.
4373 1.1.1.3.2.2 pgoyette [1]: Type of the record.
4374 1.1.1.3.2.2 pgoyette
4375 1.1.1.3.2.2 pgoyette [2]: Major opcode.
4376 1.1.1.3.2.2 pgoyette [3]: Sub-opcode.
4377 1.1.1.3.2.2 pgoyette [4]: Syntax (flags).
4378 1.1.1.3.2.2 pgoyette [5]+ Name instruction.
4379 1.1.1.3.2.2 pgoyette
4380 1.1.1.3.2.2 pgoyette The sequence is terminated by an empty entry. */
4381 1.1.1.3.2.2 pgoyette
4382 1.1.1.3.2.2 pgoyette static void
4383 1.1.1.3.2.2 pgoyette create_extinst_section (extInstruction_t *einsn)
4384 1.1.1.3.2.2 pgoyette {
4385 1.1.1.3.2.2 pgoyette
4386 1.1.1.3.2.2 pgoyette segT old_sec = now_seg;
4387 1.1.1.3.2.2 pgoyette int old_subsec = now_subseg;
4388 1.1.1.3.2.2 pgoyette char *p;
4389 1.1.1.3.2.2 pgoyette int name_len = strlen (einsn->name);
4390 1.1.1.3.2.2 pgoyette
4391 1.1.1.3.2.2 pgoyette arc_set_ext_seg ();
4392 1.1.1.3.2.2 pgoyette
4393 1.1.1.3.2.2 pgoyette p = frag_more (1);
4394 1.1.1.3.2.2 pgoyette *p = 5 + name_len + 1;
4395 1.1.1.3.2.2 pgoyette p = frag_more (1);
4396 1.1.1.3.2.2 pgoyette *p = EXT_INSTRUCTION;
4397 1.1.1.3.2.2 pgoyette p = frag_more (1);
4398 1.1.1.3.2.2 pgoyette *p = einsn->major;
4399 1.1.1.3.2.2 pgoyette p = frag_more (1);
4400 1.1.1.3.2.2 pgoyette *p = einsn->minor;
4401 1.1.1.3.2.2 pgoyette p = frag_more (1);
4402 1.1.1.3.2.2 pgoyette *p = einsn->flags;
4403 1.1.1.3.2.2 pgoyette p = frag_more (name_len + 1);
4404 1.1.1.3.2.2 pgoyette strcpy (p, einsn->name);
4405 1.1.1.3.2.2 pgoyette
4406 1.1.1.3.2.2 pgoyette subseg_set (old_sec, old_subsec);
4407 1.1.1.3.2.2 pgoyette }
4408 1.1.1.3.2.2 pgoyette
4409 1.1.1.3.2.2 pgoyette /* Handler .extinstruction pseudo-op. */
4410 1.1.1.3.2.2 pgoyette
4411 1.1.1.3.2.2 pgoyette static void
4412 1.1.1.3.2.2 pgoyette arc_extinsn (int ignore ATTRIBUTE_UNUSED)
4413 1.1.1.3.2.2 pgoyette {
4414 1.1.1.3.2.2 pgoyette extInstruction_t einsn;
4415 1.1.1.3.2.2 pgoyette struct arc_opcode *arc_ext_opcodes;
4416 1.1.1.3.2.2 pgoyette const char *errmsg = NULL;
4417 1.1.1.3.2.2 pgoyette unsigned char moplow, mophigh;
4418 1.1.1.3.2.2 pgoyette
4419 1.1.1.3.2.2 pgoyette memset (&einsn, 0, sizeof (einsn));
4420 1.1.1.3.2.2 pgoyette tokenize_extinsn (&einsn);
4421 1.1.1.3.2.2 pgoyette
4422 1.1.1.3.2.2 pgoyette /* Check if the name is already used. */
4423 1.1.1.3.2.2 pgoyette if (arc_find_opcode (einsn.name))
4424 1.1.1.3.2.2 pgoyette as_warn (_("Pseudocode already used %s"), einsn.name);
4425 1.1.1.3.2.2 pgoyette
4426 1.1.1.3.2.2 pgoyette /* Check the opcode ranges. */
4427 1.1.1.3.2.2 pgoyette moplow = 0x05;
4428 1.1.1.3.2.2 pgoyette mophigh = (arc_target & (ARC_OPCODE_ARCv2EM
4429 1.1.1.3.2.2 pgoyette | ARC_OPCODE_ARCv2HS)) ? 0x07 : 0x0a;
4430 1.1.1.3.2.2 pgoyette
4431 1.1.1.3.2.2 pgoyette if ((einsn.major > mophigh) || (einsn.major < moplow))
4432 1.1.1.3.2.2 pgoyette as_fatal (_("major opcode not in range [0x%02x - 0x%02x]"), moplow, mophigh);
4433 1.1.1.3.2.2 pgoyette
4434 1.1.1.3.2.2 pgoyette if ((einsn.minor > 0x3f) && (einsn.major != 0x0a)
4435 1.1.1.3.2.2 pgoyette && (einsn.major != 5) && (einsn.major != 9))
4436 1.1.1.3.2.2 pgoyette as_fatal (_("minor opcode not in range [0x00 - 0x3f]"));
4437 1.1.1.3.2.2 pgoyette
4438 1.1.1.3.2.2 pgoyette switch (einsn.syntax & ARC_SYNTAX_MASK)
4439 1.1.1.3.2.2 pgoyette {
4440 1.1.1.3.2.2 pgoyette case ARC_SYNTAX_3OP:
4441 1.1.1.3.2.2 pgoyette if (einsn.modsyn & ARC_OP1_IMM_IMPLIED)
4442 1.1.1.3.2.2 pgoyette as_fatal (_("Improper use of OP1_IMM_IMPLIED"));
4443 1.1.1.3.2.2 pgoyette break;
4444 1.1.1.3.2.2 pgoyette case ARC_SYNTAX_2OP:
4445 1.1.1.3.2.2 pgoyette case ARC_SYNTAX_1OP:
4446 1.1.1.3.2.2 pgoyette case ARC_SYNTAX_NOP:
4447 1.1.1.3.2.2 pgoyette if (einsn.modsyn & ARC_OP1_MUST_BE_IMM)
4448 1.1.1.3.2.2 pgoyette as_fatal (_("Improper use of OP1_MUST_BE_IMM"));
4449 1.1.1.3.2.2 pgoyette break;
4450 1.1.1.3.2.2 pgoyette default:
4451 1.1.1.3.2.2 pgoyette break;
4452 1.1.1.3.2.2 pgoyette }
4453 1.1.1.3.2.2 pgoyette
4454 1.1.1.3.2.2 pgoyette arc_ext_opcodes = arcExtMap_genOpcode (&einsn, arc_target, &errmsg);
4455 1.1.1.3.2.2 pgoyette if (arc_ext_opcodes == NULL)
4456 1.1.1.3.2.2 pgoyette {
4457 1.1.1.3.2.2 pgoyette if (errmsg)
4458 1.1.1.3.2.2 pgoyette as_fatal ("%s", errmsg);
4459 1.1.1.3.2.2 pgoyette else
4460 1.1.1.3.2.2 pgoyette as_fatal (_("Couldn't generate extension instruction opcodes"));
4461 1.1.1.3.2.2 pgoyette }
4462 1.1.1.3.2.2 pgoyette else if (errmsg)
4463 1.1.1.3.2.2 pgoyette as_warn ("%s", errmsg);
4464 1.1.1.3.2.2 pgoyette
4465 1.1.1.3.2.2 pgoyette /* Insert the extension instruction. */
4466 1.1.1.3.2.2 pgoyette arc_insert_opcode ((const struct arc_opcode *) arc_ext_opcodes);
4467 1.1.1.3.2.2 pgoyette
4468 1.1.1.3.2.2 pgoyette create_extinst_section (&einsn);
4469 1.1.1.3.2.2 pgoyette }
4470 1.1.1.3.2.2 pgoyette
4471 1.1.1.3.2.2 pgoyette static void
4472 1.1.1.3.2.2 pgoyette tokenize_extregister (extRegister_t *ereg, int opertype)
4473 1.1.1.3.2.2 pgoyette {
4474 1.1.1.3.2.2 pgoyette char *name;
4475 1.1.1.3.2.2 pgoyette char *mode;
4476 1.1.1.3.2.2 pgoyette char c;
4477 1.1.1.3.2.2 pgoyette char *p;
4478 1.1.1.3.2.2 pgoyette int number, imode = 0;
4479 1.1.1.3.2.2 pgoyette bfd_boolean isCore_p = (opertype == EXT_CORE_REGISTER) ? TRUE : FALSE;
4480 1.1.1.3.2.2 pgoyette bfd_boolean isReg_p = (opertype == EXT_CORE_REGISTER
4481 1.1.1.3.2.2 pgoyette || opertype == EXT_AUX_REGISTER) ? TRUE : FALSE;
4482 1.1.1.3.2.2 pgoyette
4483 1.1.1.3.2.2 pgoyette /* 1st: get register name. */
4484 1.1.1.3.2.2 pgoyette SKIP_WHITESPACE ();
4485 1.1.1.3.2.2 pgoyette p = input_line_pointer;
4486 1.1.1.3.2.2 pgoyette c = get_symbol_name (&p);
4487 1.1.1.3.2.2 pgoyette
4488 1.1.1.3.2.2 pgoyette name = xstrdup (p);
4489 1.1.1.3.2.2 pgoyette restore_line_pointer (c);
4490 1.1.1.3.2.2 pgoyette
4491 1.1.1.3.2.2 pgoyette /* 2nd: get register number. */
4492 1.1.1.3.2.2 pgoyette SKIP_WHITESPACE ();
4493 1.1.1.3.2.2 pgoyette
4494 1.1.1.3.2.2 pgoyette if (*input_line_pointer != ',')
4495 1.1.1.3.2.2 pgoyette {
4496 1.1.1.3.2.2 pgoyette as_bad (_("expected comma after register name"));
4497 1.1.1.3.2.2 pgoyette ignore_rest_of_line ();
4498 1.1.1.3.2.2 pgoyette free (name);
4499 1.1.1.3.2.2 pgoyette return;
4500 1.1.1.3.2.2 pgoyette }
4501 1.1.1.3.2.2 pgoyette input_line_pointer++;
4502 1.1.1.3.2.2 pgoyette number = get_absolute_expression ();
4503 1.1.1.3.2.2 pgoyette
4504 1.1.1.3.2.2 pgoyette if (number < 0)
4505 1.1.1.3.2.2 pgoyette {
4506 1.1.1.3.2.2 pgoyette as_bad (_("negative operand number %d"), number);
4507 1.1.1.3.2.2 pgoyette ignore_rest_of_line ();
4508 1.1.1.3.2.2 pgoyette free (name);
4509 1.1.1.3.2.2 pgoyette return;
4510 1.1.1.3.2.2 pgoyette }
4511 1.1.1.3.2.2 pgoyette
4512 1.1.1.3.2.2 pgoyette if (isReg_p)
4513 1.1.1.3.2.2 pgoyette {
4514 1.1.1.3.2.2 pgoyette /* 3rd: get register mode. */
4515 1.1.1.3.2.2 pgoyette SKIP_WHITESPACE ();
4516 1.1.1.3.2.2 pgoyette
4517 1.1.1.3.2.2 pgoyette if (*input_line_pointer != ',')
4518 1.1.1.3.2.2 pgoyette {
4519 1.1.1.3.2.2 pgoyette as_bad (_("expected comma after register number"));
4520 1.1.1.3.2.2 pgoyette ignore_rest_of_line ();
4521 1.1.1.3.2.2 pgoyette free (name);
4522 1.1.1.3.2.2 pgoyette return;
4523 1.1.1.3.2.2 pgoyette }
4524 1.1.1.3.2.2 pgoyette
4525 1.1.1.3.2.2 pgoyette input_line_pointer++;
4526 1.1.1.3.2.2 pgoyette mode = input_line_pointer;
4527 1.1.1.3.2.2 pgoyette
4528 1.1.1.3.2.2 pgoyette if (!strncmp (mode, "r|w", 3))
4529 1.1.1.3.2.2 pgoyette {
4530 1.1.1.3.2.2 pgoyette imode = 0;
4531 1.1.1.3.2.2 pgoyette input_line_pointer += 3;
4532 1.1.1.3.2.2 pgoyette }
4533 1.1.1.3.2.2 pgoyette else if (!strncmp (mode, "r", 1))
4534 1.1.1.3.2.2 pgoyette {
4535 1.1.1.3.2.2 pgoyette imode = ARC_REGISTER_READONLY;
4536 1.1.1.3.2.2 pgoyette input_line_pointer += 1;
4537 1.1.1.3.2.2 pgoyette }
4538 1.1.1.3.2.2 pgoyette else if (strncmp (mode, "w", 1))
4539 1.1.1.3.2.2 pgoyette {
4540 1.1.1.3.2.2 pgoyette as_bad (_("invalid mode"));
4541 1.1.1.3.2.2 pgoyette ignore_rest_of_line ();
4542 1.1.1.3.2.2 pgoyette free (name);
4543 1.1.1.3.2.2 pgoyette return;
4544 1.1.1.3.2.2 pgoyette }
4545 1.1.1.3.2.2 pgoyette else
4546 1.1.1.3.2.2 pgoyette {
4547 1.1.1.3.2.2 pgoyette imode = ARC_REGISTER_WRITEONLY;
4548 1.1.1.3.2.2 pgoyette input_line_pointer += 1;
4549 1.1.1.3.2.2 pgoyette }
4550 1.1.1.3.2.2 pgoyette }
4551 1.1.1.3.2.2 pgoyette
4552 1.1.1.3.2.2 pgoyette if (isCore_p)
4553 1.1.1.3.2.2 pgoyette {
4554 1.1.1.3.2.2 pgoyette /* 4th: get core register shortcut. */
4555 1.1.1.3.2.2 pgoyette SKIP_WHITESPACE ();
4556 1.1.1.3.2.2 pgoyette if (*input_line_pointer != ',')
4557 1.1.1.3.2.2 pgoyette {
4558 1.1.1.3.2.2 pgoyette as_bad (_("expected comma after register mode"));
4559 1.1.1.3.2.2 pgoyette ignore_rest_of_line ();
4560 1.1.1.3.2.2 pgoyette free (name);
4561 1.1.1.3.2.2 pgoyette return;
4562 1.1.1.3.2.2 pgoyette }
4563 1.1.1.3.2.2 pgoyette
4564 1.1.1.3.2.2 pgoyette input_line_pointer++;
4565 1.1.1.3.2.2 pgoyette
4566 1.1.1.3.2.2 pgoyette if (!strncmp (input_line_pointer, "cannot_shortcut", 15))
4567 1.1.1.3.2.2 pgoyette {
4568 1.1.1.3.2.2 pgoyette imode |= ARC_REGISTER_NOSHORT_CUT;
4569 1.1.1.3.2.2 pgoyette input_line_pointer += 15;
4570 1.1.1.3.2.2 pgoyette }
4571 1.1.1.3.2.2 pgoyette else if (strncmp (input_line_pointer, "can_shortcut", 12))
4572 1.1.1.3.2.2 pgoyette {
4573 1.1.1.3.2.2 pgoyette as_bad (_("shortcut designator invalid"));
4574 1.1.1.3.2.2 pgoyette ignore_rest_of_line ();
4575 1.1.1.3.2.2 pgoyette free (name);
4576 1.1.1.3.2.2 pgoyette return;
4577 1.1.1.3.2.2 pgoyette }
4578 1.1.1.3.2.2 pgoyette else
4579 1.1.1.3.2.2 pgoyette {
4580 1.1.1.3.2.2 pgoyette input_line_pointer += 12;
4581 1.1.1.3.2.2 pgoyette }
4582 1.1.1.3.2.2 pgoyette }
4583 1.1.1.3.2.2 pgoyette demand_empty_rest_of_line ();
4584 1.1.1.3.2.2 pgoyette
4585 1.1.1.3.2.2 pgoyette ereg->name = name;
4586 1.1.1.3.2.2 pgoyette ereg->number = number;
4587 1.1.1.3.2.2 pgoyette ereg->imode = imode;
4588 1.1.1.3.2.2 pgoyette }
4589 1.1.1.3.2.2 pgoyette
4590 1.1.1.3.2.2 pgoyette /* Create an extension register/condition description in the arc
4591 1.1.1.3.2.2 pgoyette extension section of the output file.
4592 1.1.1.3.2.2 pgoyette
4593 1.1.1.3.2.2 pgoyette The structure for an instruction is like this:
4594 1.1.1.3.2.2 pgoyette [0]: Length of the record.
4595 1.1.1.3.2.2 pgoyette [1]: Type of the record.
4596 1.1.1.3.2.2 pgoyette
4597 1.1.1.3.2.2 pgoyette For core regs and condition codes:
4598 1.1.1.3.2.2 pgoyette [2]: Value.
4599 1.1.1.3.2.2 pgoyette [3]+ Name.
4600 1.1.1.3.2.2 pgoyette
4601 1.1.1.3.2.2 pgoyette For auxilirary registers:
4602 1.1.1.3.2.2 pgoyette [2..5]: Value.
4603 1.1.1.3.2.2 pgoyette [6]+ Name
4604 1.1.1.3.2.2 pgoyette
4605 1.1.1.3.2.2 pgoyette The sequence is terminated by an empty entry. */
4606 1.1.1.3.2.2 pgoyette
4607 1.1.1.3.2.2 pgoyette static void
4608 1.1.1.3.2.2 pgoyette create_extcore_section (extRegister_t *ereg, int opertype)
4609 1.1.1.3.2.2 pgoyette {
4610 1.1.1.3.2.2 pgoyette segT old_sec = now_seg;
4611 1.1.1.3.2.2 pgoyette int old_subsec = now_subseg;
4612 1.1.1.3.2.2 pgoyette char *p;
4613 1.1.1.3.2.2 pgoyette int name_len = strlen (ereg->name);
4614 1.1.1.3.2.2 pgoyette
4615 1.1.1.3.2.2 pgoyette arc_set_ext_seg ();
4616 1.1.1.3.2.2 pgoyette
4617 1.1.1.3.2.2 pgoyette switch (opertype)
4618 1.1.1.3.2.2 pgoyette {
4619 1.1.1.3.2.2 pgoyette case EXT_COND_CODE:
4620 1.1.1.3.2.2 pgoyette case EXT_CORE_REGISTER:
4621 1.1.1.3.2.2 pgoyette p = frag_more (1);
4622 1.1.1.3.2.2 pgoyette *p = 3 + name_len + 1;
4623 1.1.1.3.2.2 pgoyette p = frag_more (1);
4624 1.1.1.3.2.2 pgoyette *p = opertype;
4625 1.1.1.3.2.2 pgoyette p = frag_more (1);
4626 1.1.1.3.2.2 pgoyette *p = ereg->number;
4627 1.1.1.3.2.2 pgoyette break;
4628 1.1.1.3.2.2 pgoyette case EXT_AUX_REGISTER:
4629 1.1.1.3.2.2 pgoyette p = frag_more (1);
4630 1.1.1.3.2.2 pgoyette *p = 6 + name_len + 1;
4631 1.1.1.3.2.2 pgoyette p = frag_more (1);
4632 1.1.1.3.2.2 pgoyette *p = EXT_AUX_REGISTER;
4633 1.1.1.3.2.2 pgoyette p = frag_more (1);
4634 1.1.1.3.2.2 pgoyette *p = (ereg->number >> 24) & 0xff;
4635 1.1.1.3.2.2 pgoyette p = frag_more (1);
4636 1.1.1.3.2.2 pgoyette *p = (ereg->number >> 16) & 0xff;
4637 1.1.1.3.2.2 pgoyette p = frag_more (1);
4638 1.1.1.3.2.2 pgoyette *p = (ereg->number >> 8) & 0xff;
4639 1.1.1.3.2.2 pgoyette p = frag_more (1);
4640 1.1.1.3.2.2 pgoyette *p = (ereg->number) & 0xff;
4641 1.1.1.3.2.2 pgoyette break;
4642 1.1.1.3.2.2 pgoyette default:
4643 1.1.1.3.2.2 pgoyette break;
4644 1.1.1.3.2.2 pgoyette }
4645 1.1.1.3.2.2 pgoyette
4646 1.1.1.3.2.2 pgoyette p = frag_more (name_len + 1);
4647 1.1.1.3.2.2 pgoyette strcpy (p, ereg->name);
4648 1.1.1.3.2.2 pgoyette
4649 1.1.1.3.2.2 pgoyette subseg_set (old_sec, old_subsec);
4650 1.1.1.3.2.2 pgoyette }
4651 1.1.1.3.2.2 pgoyette
4652 1.1.1.3.2.2 pgoyette /* Handler .extCoreRegister pseudo-op. */
4653 1.1.1.3.2.2 pgoyette
4654 1.1.1.3.2.2 pgoyette static void
4655 1.1.1.3.2.2 pgoyette arc_extcorereg (int opertype)
4656 1.1.1.3.2.2 pgoyette {
4657 1.1.1.3.2.2 pgoyette extRegister_t ereg;
4658 1.1.1.3.2.2 pgoyette struct arc_aux_reg *auxr;
4659 1.1.1.3.2.2 pgoyette const char *retval;
4660 1.1.1.3.2.2 pgoyette struct arc_flag_operand *ccode;
4661 1.1.1.3.2.2 pgoyette
4662 1.1.1.3.2.2 pgoyette memset (&ereg, 0, sizeof (ereg));
4663 1.1.1.3.2.2 pgoyette tokenize_extregister (&ereg, opertype);
4664 1.1.1.3.2.2 pgoyette
4665 1.1.1.3.2.2 pgoyette switch (opertype)
4666 1.1.1.3.2.2 pgoyette {
4667 1.1.1.3.2.2 pgoyette case EXT_CORE_REGISTER:
4668 1.1.1.3.2.2 pgoyette /* Core register. */
4669 1.1.1.3.2.2 pgoyette if (ereg.number > 60)
4670 1.1.1.3.2.2 pgoyette as_bad (_("core register %s value (%d) too large"), ereg.name,
4671 1.1.1.3.2.2 pgoyette ereg.number);
4672 1.1.1.3.2.2 pgoyette declare_register (ereg.name, ereg.number);
4673 1.1.1.3.2.2 pgoyette break;
4674 1.1.1.3.2.2 pgoyette case EXT_AUX_REGISTER:
4675 1.1.1.3.2.2 pgoyette /* Auxiliary register. */
4676 1.1.1.3.2.2 pgoyette auxr = XNEW (struct arc_aux_reg);
4677 1.1.1.3.2.2 pgoyette auxr->name = ereg.name;
4678 1.1.1.3.2.2 pgoyette auxr->cpu = arc_target;
4679 1.1.1.3.2.2 pgoyette auxr->subclass = NONE;
4680 1.1.1.3.2.2 pgoyette auxr->address = ereg.number;
4681 1.1.1.3.2.2 pgoyette retval = hash_insert (arc_aux_hash, auxr->name, (void *) auxr);
4682 1.1.1.3.2.2 pgoyette if (retval)
4683 1.1.1.3.2.2 pgoyette as_fatal (_("internal error: can't hash aux register '%s': %s"),
4684 1.1.1.3.2.2 pgoyette auxr->name, retval);
4685 1.1.1.3.2.2 pgoyette break;
4686 1.1.1.3.2.2 pgoyette case EXT_COND_CODE:
4687 1.1.1.3.2.2 pgoyette /* Condition code. */
4688 1.1.1.3.2.2 pgoyette if (ereg.number > 31)
4689 1.1.1.3.2.2 pgoyette as_bad (_("condition code %s value (%d) too large"), ereg.name,
4690 1.1.1.3.2.2 pgoyette ereg.number);
4691 1.1.1.3.2.2 pgoyette ext_condcode.size ++;
4692 1.1.1.3.2.2 pgoyette ext_condcode.arc_ext_condcode =
4693 1.1.1.3.2.2 pgoyette XRESIZEVEC (struct arc_flag_operand, ext_condcode.arc_ext_condcode,
4694 1.1.1.3.2.2 pgoyette ext_condcode.size + 1);
4695 1.1.1.3.2.2 pgoyette if (ext_condcode.arc_ext_condcode == NULL)
4696 1.1.1.3.2.2 pgoyette as_fatal (_("Virtual memory exhausted"));
4697 1.1.1.3.2.2 pgoyette
4698 1.1.1.3.2.2 pgoyette ccode = ext_condcode.arc_ext_condcode + ext_condcode.size - 1;
4699 1.1.1.3.2.2 pgoyette ccode->name = ereg.name;
4700 1.1.1.3.2.2 pgoyette ccode->code = ereg.number;
4701 1.1.1.3.2.2 pgoyette ccode->bits = 5;
4702 1.1.1.3.2.2 pgoyette ccode->shift = 0;
4703 1.1.1.3.2.2 pgoyette ccode->favail = 0; /* not used. */
4704 1.1.1.3.2.2 pgoyette ccode++;
4705 1.1.1.3.2.2 pgoyette memset (ccode, 0, sizeof (struct arc_flag_operand));
4706 1.1.1.3.2.2 pgoyette break;
4707 1.1.1.3.2.2 pgoyette default:
4708 1.1.1.3.2.2 pgoyette as_bad (_("Unknown extension"));
4709 1.1.1.3.2.2 pgoyette break;
4710 1.1.1.3.2.2 pgoyette }
4711 1.1.1.3.2.2 pgoyette create_extcore_section (&ereg, opertype);
4712 1.1.1.3.2.2 pgoyette }
4713 1.1.1.3.2.2 pgoyette
4714 1.1.1.3.2.2 pgoyette /* Local variables:
4715 1.1.1.3.2.2 pgoyette eval: (c-set-style "gnu")
4716 1.1.1.3.2.2 pgoyette indent-tabs-mode: t
4717 1.1.1.3.2.2 pgoyette End: */
4718