tc-arc.c revision 1.1.1.3 1 1.1 skrll /* tc-arc.c -- Assembler for the ARC
2 1.1.1.3 christos Copyright (C) 1994-2015 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 skrll #include "safe-ctype.h"
28 1.1.1.3 christos
29 1.1 skrll #include "opcode/arc.h"
30 1.1 skrll #include "elf/arc.h"
31 1.1 skrll
32 1.1.1.3 christos /* Defines section. */
33 1.1 skrll
34 1.1.1.3 christos #define MAX_FLAG_NAME_LENGHT 3
35 1.1.1.3 christos #define MAX_INSN_FIXUPS 2
36 1.1.1.3 christos #define MAX_CONSTR_STR 20
37 1.1.1.3 christos
38 1.1.1.3 christos #ifdef DEBUG
39 1.1.1.3 christos # define pr_debug(fmt, args...) fprintf (stderr, fmt, ##args)
40 1.1.1.3 christos #else
41 1.1.1.3 christos # define pr_debug(fmt, args...)
42 1.1.1.3 christos #endif
43 1.1.1.3 christos
44 1.1.1.3 christos #define MAJOR_OPCODE(x) (((x) & 0xF8000000) >> 27)
45 1.1.1.3 christos #define SUB_OPCODE(x) (((x) & 0x003F0000) >> 16)
46 1.1.1.3 christos #define LP_INSN(x) ((MAJOR_OPCODE (x) == 0x4) && \
47 1.1.1.3 christos (SUB_OPCODE (x) == 0x28))
48 1.1.1.3 christos
49 1.1.1.3 christos /* Equal to MAX_PRECISION in atof-ieee.c. */
50 1.1.1.3 christos #define MAX_LITTLENUMS 6
51 1.1.1.3 christos
52 1.1.1.3 christos /* Macros section. */
53 1.1.1.3 christos
54 1.1.1.3 christos #define regno(x) ((x) & 0x3F)
55 1.1.1.3 christos #define is_ir_num(x) (((x) & ~0x3F) == 0)
56 1.1.1.3 christos #define is_code_density_p(op) (((op)->subclass == CD1 || (op)->subclass == CD2))
57 1.1.1.3 christos #define is_br_jmp_insn_p(op) (((op)->class == BRANCH || (op)->class == JUMP))
58 1.1.1.3 christos #define is_kernel_insn_p(op) (((op)->class == KERNEL))
59 1.1 skrll
60 1.1.1.3 christos /* Generic assembler global variables which must be defined by all
61 1.1.1.3 christos targets. */
62 1.1 skrll
63 1.1.1.3 christos /* Characters which always start a comment. */
64 1.1 skrll const char comment_chars[] = "#;";
65 1.1 skrll
66 1.1.1.3 christos /* Characters which start a comment at the beginning of a line. */
67 1.1 skrll const char line_comment_chars[] = "#";
68 1.1 skrll
69 1.1.1.3 christos /* Characters which may be used to separate multiple commands on a
70 1.1.1.3 christos single line. */
71 1.1.1.3 christos const char line_separator_chars[] = "`";
72 1.1 skrll
73 1.1.1.3 christos /* Characters which are used to indicate an exponent in a floating
74 1.1.1.3 christos point number. */
75 1.1 skrll const char EXP_CHARS[] = "eE";
76 1.1 skrll
77 1.1 skrll /* Chars that mean this number is a floating point constant
78 1.1 skrll As in 0f12.456 or 0d1.2345e12. */
79 1.1 skrll const char FLT_CHARS[] = "rRsSfFdD";
80 1.1 skrll
81 1.1 skrll /* Byte order. */
82 1.1 skrll extern int target_big_endian;
83 1.1 skrll const char *arc_target_format = DEFAULT_TARGET_FORMAT;
84 1.1 skrll static int byte_order = DEFAULT_BYTE_ORDER;
85 1.1 skrll
86 1.1.1.3 christos extern int arc_get_mach (char *);
87 1.1 skrll
88 1.1.1.3 christos /* Forward declaration. */
89 1.1.1.3 christos static void arc_lcomm (int);
90 1.1.1.3 christos static void arc_option (int);
91 1.1.1.3 christos static void arc_extra_reloc (int);
92 1.1 skrll
93 1.1.1.3 christos const pseudo_typeS md_pseudo_table[] =
94 1.1.1.3 christos {
95 1.1.1.3 christos /* Make sure that .word is 32 bits. */
96 1.1.1.3 christos { "word", cons, 4 },
97 1.1 skrll
98 1.1.1.3 christos { "align", s_align_bytes, 0 }, /* Defaulting is invalid (0). */
99 1.1.1.3 christos { "lcomm", arc_lcomm, 0 },
100 1.1.1.3 christos { "lcommon", arc_lcomm, 0 },
101 1.1.1.3 christos { "cpu", arc_option, 0 },
102 1.1.1.3 christos
103 1.1.1.3 christos { "tls_gd_ld", arc_extra_reloc, BFD_RELOC_ARC_TLS_GD_LD },
104 1.1.1.3 christos { "tls_gd_call", arc_extra_reloc, BFD_RELOC_ARC_TLS_GD_CALL },
105 1.1.1.3 christos
106 1.1.1.3 christos { NULL, NULL, 0 }
107 1.1.1.3 christos };
108 1.1 skrll
109 1.1 skrll const char *md_shortopts = "";
110 1.1 skrll
111 1.1 skrll enum options
112 1.1 skrll {
113 1.1 skrll OPTION_EB = OPTION_MD_BASE,
114 1.1 skrll OPTION_EL,
115 1.1.1.3 christos
116 1.1.1.3 christos OPTION_ARC600,
117 1.1.1.3 christos OPTION_ARC601,
118 1.1.1.3 christos OPTION_ARC700,
119 1.1.1.3 christos OPTION_ARCEM,
120 1.1.1.3 christos OPTION_ARCHS,
121 1.1.1.3 christos
122 1.1.1.3 christos OPTION_MCPU,
123 1.1.1.3 christos OPTION_CD,
124 1.1.1.3 christos
125 1.1.1.3 christos /* The following options are deprecated and provided here only for
126 1.1.1.3 christos compatibility reasons. */
127 1.1.1.3 christos OPTION_USER_MODE,
128 1.1.1.3 christos OPTION_LD_EXT_MASK,
129 1.1.1.3 christos OPTION_SWAP,
130 1.1.1.3 christos OPTION_NORM,
131 1.1.1.3 christos OPTION_BARREL_SHIFT,
132 1.1.1.3 christos OPTION_MIN_MAX,
133 1.1.1.3 christos OPTION_NO_MPY,
134 1.1.1.3 christos OPTION_EA,
135 1.1.1.3 christos OPTION_MUL64,
136 1.1.1.3 christos OPTION_SIMD,
137 1.1.1.3 christos OPTION_SPFP,
138 1.1.1.3 christos OPTION_DPFP,
139 1.1.1.3 christos OPTION_XMAC_D16,
140 1.1.1.3 christos OPTION_XMAC_24,
141 1.1.1.3 christos OPTION_DSP_PACKA,
142 1.1.1.3 christos OPTION_CRC,
143 1.1.1.3 christos OPTION_DVBF,
144 1.1.1.3 christos OPTION_TELEPHONY,
145 1.1.1.3 christos OPTION_XYMEMORY,
146 1.1.1.3 christos OPTION_LOCK,
147 1.1.1.3 christos OPTION_SWAPE,
148 1.1.1.3 christos OPTION_RTSC,
149 1.1.1.3 christos OPTION_FPUDA
150 1.1 skrll };
151 1.1 skrll
152 1.1 skrll struct option md_longopts[] =
153 1.1 skrll {
154 1.1.1.3 christos { "EB", no_argument, NULL, OPTION_EB },
155 1.1.1.3 christos { "EL", no_argument, NULL, OPTION_EL },
156 1.1.1.3 christos { "mcpu", required_argument, NULL, OPTION_MCPU },
157 1.1.1.3 christos { "mA6", no_argument, NULL, OPTION_ARC600 },
158 1.1.1.3 christos { "mARC600", no_argument, NULL, OPTION_ARC600 },
159 1.1.1.3 christos { "mARC601", no_argument, NULL, OPTION_ARC601 },
160 1.1.1.3 christos { "mARC700", no_argument, NULL, OPTION_ARC700 },
161 1.1.1.3 christos { "mA7", no_argument, NULL, OPTION_ARC700 },
162 1.1.1.3 christos { "mEM", no_argument, NULL, OPTION_ARCEM },
163 1.1.1.3 christos { "mHS", no_argument, NULL, OPTION_ARCHS },
164 1.1.1.3 christos { "mcode-density", no_argument, NULL, OPTION_CD },
165 1.1.1.3 christos
166 1.1.1.3 christos /* The following options are deprecated and provided here only for
167 1.1.1.3 christos compatibility reasons. */
168 1.1.1.3 christos { "mav2em", no_argument, NULL, OPTION_ARCEM },
169 1.1.1.3 christos { "mav2hs", no_argument, NULL, OPTION_ARCHS },
170 1.1.1.3 christos { "muser-mode-only", no_argument, NULL, OPTION_USER_MODE },
171 1.1.1.3 christos { "mld-extension-reg-mask", required_argument, NULL, OPTION_LD_EXT_MASK },
172 1.1.1.3 christos { "mswap", no_argument, NULL, OPTION_SWAP },
173 1.1.1.3 christos { "mnorm", no_argument, NULL, OPTION_NORM },
174 1.1.1.3 christos { "mbarrel-shifter", no_argument, NULL, OPTION_BARREL_SHIFT },
175 1.1.1.3 christos { "mbarrel_shifter", no_argument, NULL, OPTION_BARREL_SHIFT },
176 1.1.1.3 christos { "mmin-max", no_argument, NULL, OPTION_MIN_MAX },
177 1.1.1.3 christos { "mmin_max", no_argument, NULL, OPTION_MIN_MAX },
178 1.1.1.3 christos { "mno-mpy", no_argument, NULL, OPTION_NO_MPY },
179 1.1.1.3 christos { "mea", no_argument, NULL, OPTION_EA },
180 1.1.1.3 christos { "mEA", no_argument, NULL, OPTION_EA },
181 1.1.1.3 christos { "mmul64", no_argument, NULL, OPTION_MUL64 },
182 1.1.1.3 christos { "msimd", no_argument, NULL, OPTION_SIMD},
183 1.1.1.3 christos { "mspfp", no_argument, NULL, OPTION_SPFP},
184 1.1.1.3 christos { "mspfp-compact", no_argument, NULL, OPTION_SPFP},
185 1.1.1.3 christos { "mspfp_compact", no_argument, NULL, OPTION_SPFP},
186 1.1.1.3 christos { "mspfp-fast", no_argument, NULL, OPTION_SPFP},
187 1.1.1.3 christos { "mspfp_fast", no_argument, NULL, OPTION_SPFP},
188 1.1.1.3 christos { "mdpfp", no_argument, NULL, OPTION_DPFP},
189 1.1.1.3 christos { "mdpfp-compact", no_argument, NULL, OPTION_DPFP},
190 1.1.1.3 christos { "mdpfp_compact", no_argument, NULL, OPTION_DPFP},
191 1.1.1.3 christos { "mdpfp-fast", no_argument, NULL, OPTION_DPFP},
192 1.1.1.3 christos { "mdpfp_fast", no_argument, NULL, OPTION_DPFP},
193 1.1.1.3 christos { "mmac-d16", no_argument, NULL, OPTION_XMAC_D16},
194 1.1.1.3 christos { "mmac_d16", no_argument, NULL, OPTION_XMAC_D16},
195 1.1.1.3 christos { "mmac-24", no_argument, NULL, OPTION_XMAC_24},
196 1.1.1.3 christos { "mmac_24", no_argument, NULL, OPTION_XMAC_24},
197 1.1.1.3 christos { "mdsp-packa", no_argument, NULL, OPTION_DSP_PACKA},
198 1.1.1.3 christos { "mdsp_packa", no_argument, NULL, OPTION_DSP_PACKA},
199 1.1.1.3 christos { "mcrc", no_argument, NULL, OPTION_CRC},
200 1.1.1.3 christos { "mdvbf", no_argument, NULL, OPTION_DVBF},
201 1.1.1.3 christos { "mtelephony", no_argument, NULL, OPTION_TELEPHONY},
202 1.1.1.3 christos { "mxy", no_argument, NULL, OPTION_XYMEMORY},
203 1.1.1.3 christos { "mlock", no_argument, NULL, OPTION_LOCK},
204 1.1.1.3 christos { "mswape", no_argument, NULL, OPTION_SWAPE},
205 1.1.1.3 christos { "mrtsc", no_argument, NULL, OPTION_RTSC},
206 1.1.1.3 christos { "mfpuda", no_argument, NULL, OPTION_FPUDA},
207 1.1.1.3 christos
208 1.1.1.3 christos { NULL, no_argument, NULL, 0 }
209 1.1 skrll };
210 1.1.1.3 christos
211 1.1 skrll size_t md_longopts_size = sizeof (md_longopts);
212 1.1 skrll
213 1.1.1.3 christos /* Local data and data types. */
214 1.1.1.3 christos
215 1.1.1.3 christos /* Used since new relocation types are introduced in this
216 1.1.1.3 christos file (DUMMY_RELOC_LITUSE_*). */
217 1.1.1.3 christos typedef int extended_bfd_reloc_code_real_type;
218 1.1.1.3 christos
219 1.1.1.3 christos struct arc_fixup
220 1.1.1.3 christos {
221 1.1.1.3 christos expressionS exp;
222 1.1 skrll
223 1.1.1.3 christos extended_bfd_reloc_code_real_type reloc;
224 1.1 skrll
225 1.1.1.3 christos /* index into arc_operands. */
226 1.1.1.3 christos unsigned int opindex;
227 1.1 skrll
228 1.1.1.3 christos /* PC-relative, used by internals fixups. */
229 1.1.1.3 christos unsigned char pcrel;
230 1.1.1.3 christos
231 1.1.1.3 christos /* TRUE if this fixup is for LIMM operand. */
232 1.1.1.3 christos bfd_boolean islong;
233 1.1.1.3 christos };
234 1.1.1.3 christos
235 1.1.1.3 christos struct arc_insn
236 1.1 skrll {
237 1.1.1.3 christos unsigned int insn;
238 1.1.1.3 christos int nfixups;
239 1.1.1.3 christos struct arc_fixup fixups[MAX_INSN_FIXUPS];
240 1.1.1.3 christos long limm;
241 1.1.1.3 christos bfd_boolean short_insn; /* Boolean value: TRUE if current insn is
242 1.1.1.3 christos short. */
243 1.1.1.3 christos bfd_boolean has_limm; /* Boolean value: TRUE if limm field is
244 1.1.1.3 christos valid. */
245 1.1.1.3 christos };
246 1.1 skrll
247 1.1.1.3 christos /* Structure to hold any last two instructions. */
248 1.1.1.3 christos static struct arc_last_insn
249 1.1 skrll {
250 1.1.1.3 christos /* Saved instruction opcode. */
251 1.1.1.3 christos const struct arc_opcode *opcode;
252 1.1 skrll
253 1.1.1.3 christos /* Boolean value: TRUE if current insn is short. */
254 1.1.1.3 christos bfd_boolean has_limm;
255 1.1 skrll
256 1.1.1.3 christos /* Boolean value: TRUE if current insn has delay slot. */
257 1.1.1.3 christos bfd_boolean has_delay_slot;
258 1.1.1.3 christos } arc_last_insns[2];
259 1.1.1.3 christos
260 1.1.1.3 christos /* The cpu for which we are generating code. */
261 1.1.1.3 christos static unsigned arc_target = ARC_OPCODE_BASE;
262 1.1.1.3 christos static const char *arc_target_name = "<all>";
263 1.1.1.3 christos static unsigned arc_features = 0x00;
264 1.1 skrll
265 1.1.1.3 christos /* The default architecture. */
266 1.1.1.3 christos static int arc_mach_type = bfd_mach_arc_arcv2;
267 1.1 skrll
268 1.1.1.3 christos /* Non-zero if the cpu type has been explicitly specified. */
269 1.1.1.3 christos static int mach_type_specified_p = 0;
270 1.1 skrll
271 1.1.1.3 christos /* The hash table of instruction opcodes. */
272 1.1.1.3 christos static struct hash_control *arc_opcode_hash;
273 1.1 skrll
274 1.1.1.3 christos /* The hash table of register symbols. */
275 1.1.1.3 christos static struct hash_control *arc_reg_hash;
276 1.1.1.3 christos
277 1.1.1.3 christos /* A table of CPU names and opcode sets. */
278 1.1.1.3 christos static const struct cpu_type
279 1.1 skrll {
280 1.1.1.3 christos const char *name;
281 1.1.1.3 christos unsigned flags;
282 1.1.1.3 christos int mach;
283 1.1.1.3 christos unsigned eflags;
284 1.1.1.3 christos unsigned features;
285 1.1.1.3 christos }
286 1.1.1.3 christos cpu_types[] =
287 1.1.1.3 christos {
288 1.1.1.3 christos { "arc600", ARC_OPCODE_ARC600, bfd_mach_arc_arc600,
289 1.1.1.3 christos E_ARC_MACH_ARC600, 0x00},
290 1.1.1.3 christos { "arc700", ARC_OPCODE_ARC700, bfd_mach_arc_arc700,
291 1.1.1.3 christos E_ARC_MACH_ARC700, 0x00},
292 1.1.1.3 christos { "arcem", ARC_OPCODE_ARCv2EM, bfd_mach_arc_arcv2,
293 1.1.1.3 christos EF_ARC_CPU_ARCV2EM, 0x00},
294 1.1.1.3 christos { "archs", ARC_OPCODE_ARCv2HS, bfd_mach_arc_arcv2,
295 1.1.1.3 christos EF_ARC_CPU_ARCV2HS, ARC_CD},
296 1.1.1.3 christos { "all", ARC_OPCODE_BASE, bfd_mach_arc_arcv2,
297 1.1.1.3 christos 0x00, 0x00 },
298 1.1.1.3 christos { 0, 0, 0, 0, 0 }
299 1.1.1.3 christos };
300 1.1 skrll
301 1.1.1.3 christos struct arc_flags
302 1.1.1.3 christos {
303 1.1.1.3 christos /* Name of the parsed flag. */
304 1.1.1.3 christos char name[MAX_FLAG_NAME_LENGHT+1];
305 1.1 skrll
306 1.1.1.3 christos /* The code of the parsed flag. Valid when is not zero. */
307 1.1.1.3 christos unsigned char code;
308 1.1.1.3 christos };
309 1.1 skrll
310 1.1.1.3 christos /* Used by the arc_reloc_op table. Order is important. */
311 1.1.1.3 christos #define O_gotoff O_md1 /* @gotoff relocation. */
312 1.1.1.3 christos #define O_gotpc O_md2 /* @gotpc relocation. */
313 1.1.1.3 christos #define O_plt O_md3 /* @plt relocation. */
314 1.1.1.3 christos #define O_sda O_md4 /* @sda relocation. */
315 1.1.1.3 christos #define O_pcl O_md5 /* @pcl relocation. */
316 1.1.1.3 christos #define O_tlsgd O_md6 /* @tlsgd relocation. */
317 1.1.1.3 christos #define O_tlsie O_md7 /* @tlsie relocation. */
318 1.1.1.3 christos #define O_tpoff9 O_md8 /* @tpoff9 relocation. */
319 1.1.1.3 christos #define O_tpoff O_md9 /* @tpoff relocation. */
320 1.1.1.3 christos #define O_dtpoff9 O_md10 /* @dtpoff9 relocation. */
321 1.1.1.3 christos #define O_dtpoff O_md11 /* @dtpoff relocation. */
322 1.1.1.3 christos #define O_last O_dtpoff
323 1.1.1.3 christos
324 1.1.1.3 christos /* Used to define a bracket as operand in tokens. */
325 1.1.1.3 christos #define O_bracket O_md32
326 1.1.1.3 christos
327 1.1.1.3 christos /* Dummy relocation, to be sorted out. */
328 1.1.1.3 christos #define DUMMY_RELOC_ARC_ENTRY (BFD_RELOC_UNUSED + 1)
329 1.1.1.3 christos
330 1.1.1.3 christos #define USER_RELOC_P(R) ((R) >= O_gotoff && (R) <= O_last)
331 1.1.1.3 christos
332 1.1.1.3 christos /* A table to map the spelling of a relocation operand into an appropriate
333 1.1.1.3 christos bfd_reloc_code_real_type type. The table is assumed to be ordered such
334 1.1.1.3 christos that op-O_literal indexes into it. */
335 1.1.1.3 christos #define ARC_RELOC_TABLE(op) \
336 1.1.1.3 christos (&arc_reloc_op[ ((!USER_RELOC_P (op)) \
337 1.1.1.3 christos ? (abort (), 0) \
338 1.1.1.3 christos : (int) (op) - (int) O_gotoff) ])
339 1.1.1.3 christos
340 1.1.1.3 christos #define DEF(NAME, RELOC, REQ) \
341 1.1.1.3 christos { #NAME, sizeof (#NAME)-1, O_##NAME, RELOC, REQ}
342 1.1.1.3 christos
343 1.1.1.3 christos static const struct arc_reloc_op_tag
344 1.1.1.3 christos {
345 1.1.1.3 christos /* String to lookup. */
346 1.1.1.3 christos const char *name;
347 1.1.1.3 christos /* Size of the string. */
348 1.1.1.3 christos size_t length;
349 1.1.1.3 christos /* Which operator to use. */
350 1.1.1.3 christos operatorT op;
351 1.1.1.3 christos extended_bfd_reloc_code_real_type reloc;
352 1.1.1.3 christos /* Allows complex relocation expression like identifier@reloc +
353 1.1.1.3 christos const. */
354 1.1.1.3 christos unsigned int complex_expr : 1;
355 1.1.1.3 christos }
356 1.1.1.3 christos arc_reloc_op[] =
357 1.1.1.3 christos {
358 1.1.1.3 christos DEF (gotoff, BFD_RELOC_ARC_GOTOFF, 1),
359 1.1.1.3 christos DEF (gotpc, BFD_RELOC_ARC_GOTPC32, 0),
360 1.1.1.3 christos DEF (plt, BFD_RELOC_ARC_PLT32, 0),
361 1.1.1.3 christos DEF (sda, DUMMY_RELOC_ARC_ENTRY, 1),
362 1.1.1.3 christos DEF (pcl, BFD_RELOC_ARC_PC32, 1),
363 1.1.1.3 christos DEF (tlsgd, BFD_RELOC_ARC_TLS_GD_GOT, 0),
364 1.1.1.3 christos DEF (tlsie, BFD_RELOC_ARC_TLS_IE_GOT, 0),
365 1.1.1.3 christos DEF (tpoff9, BFD_RELOC_ARC_TLS_LE_S9, 0),
366 1.1.1.3 christos DEF (tpoff, BFD_RELOC_ARC_TLS_LE_32, 0),
367 1.1.1.3 christos DEF (dtpoff9, BFD_RELOC_ARC_TLS_DTPOFF_S9, 0),
368 1.1.1.3 christos DEF (dtpoff, BFD_RELOC_ARC_TLS_DTPOFF, 0),
369 1.1.1.3 christos };
370 1.1 skrll
371 1.1.1.3 christos static const int arc_num_reloc_op
372 1.1.1.3 christos = sizeof (arc_reloc_op) / sizeof (*arc_reloc_op);
373 1.1.1.3 christos
374 1.1.1.3 christos /* Flags to set in the elf header. */
375 1.1.1.3 christos static flagword arc_eflag = 0x00;
376 1.1 skrll
377 1.1.1.3 christos /* Pre-defined "_GLOBAL_OFFSET_TABLE_". */
378 1.1.1.3 christos symbolS * GOT_symbol = 0;
379 1.1 skrll
380 1.1.1.3 christos /* Set to TRUE when we assemble instructions. */
381 1.1.1.3 christos static bfd_boolean assembling_insn = FALSE;
382 1.1.1.3 christos
383 1.1.1.3 christos /* Functions declaration. */
384 1.1.1.3 christos
385 1.1.1.3 christos static void assemble_tokens (const char *, expressionS *, int,
386 1.1.1.3 christos struct arc_flags *, int);
387 1.1.1.3 christos static const struct arc_opcode *find_opcode_match (const struct arc_opcode *,
388 1.1.1.3 christos expressionS *, int *,
389 1.1.1.3 christos struct arc_flags *,
390 1.1.1.3 christos int, int *);
391 1.1.1.3 christos static void assemble_insn (const struct arc_opcode *, const expressionS *,
392 1.1.1.3 christos int, const struct arc_flags *, int,
393 1.1.1.3 christos struct arc_insn *);
394 1.1.1.3 christos static void emit_insn (struct arc_insn *);
395 1.1.1.3 christos static unsigned insert_operand (unsigned, const struct arc_operand *,
396 1.1.1.3 christos offsetT, char *, unsigned);
397 1.1.1.3 christos static const struct arc_opcode *find_special_case_flag (const char *,
398 1.1.1.3 christos int *,
399 1.1.1.3 christos struct arc_flags *);
400 1.1.1.3 christos static const struct arc_opcode *find_special_case (const char *,
401 1.1.1.3 christos int *,
402 1.1.1.3 christos struct arc_flags *,
403 1.1.1.3 christos expressionS *, int *);
404 1.1.1.3 christos static const struct arc_opcode *find_special_case_pseudo (const char *,
405 1.1.1.3 christos int *,
406 1.1.1.3 christos expressionS *,
407 1.1.1.3 christos int *,
408 1.1.1.3 christos struct arc_flags *);
409 1.1.1.3 christos
410 1.1.1.3 christos /* Functions implementation. */
411 1.1.1.3 christos
412 1.1.1.3 christos /* Like md_number_to_chars but used for limms. The 4-byte limm value,
413 1.1.1.3 christos is encoded as 'middle-endian' for a little-endian target. FIXME!
414 1.1.1.3 christos this function is used for regular 4 byte instructions as well. */
415 1.1 skrll
416 1.1.1.3 christos static void
417 1.1.1.3 christos md_number_to_chars_midend (char *buf, valueT val, int n)
418 1.1.1.3 christos {
419 1.1.1.3 christos if (n == 4)
420 1.1 skrll {
421 1.1.1.3 christos md_number_to_chars (buf, (val & 0xffff0000) >> 16, 2);
422 1.1.1.3 christos md_number_to_chars (buf + 2, (val & 0xffff), 2);
423 1.1.1.3 christos }
424 1.1.1.3 christos else
425 1.1 skrll {
426 1.1.1.3 christos md_number_to_chars (buf, val, n);
427 1.1.1.3 christos }
428 1.1.1.3 christos }
429 1.1 skrll
430 1.1.1.3 christos /* Here ends all the ARCompact extension instruction assembling
431 1.1.1.3 christos stuff. */
432 1.1 skrll
433 1.1.1.3 christos static void
434 1.1.1.3 christos arc_extra_reloc (int r_type)
435 1.1.1.3 christos {
436 1.1.1.3 christos char *sym_name, c;
437 1.1.1.3 christos symbolS *sym, *lab = NULL;
438 1.1 skrll
439 1.1.1.3 christos if (*input_line_pointer == '@')
440 1.1.1.3 christos input_line_pointer++;
441 1.1.1.3 christos c = get_symbol_name (&sym_name);
442 1.1.1.3 christos sym = symbol_find_or_make (sym_name);
443 1.1.1.3 christos restore_line_pointer (c);
444 1.1.1.3 christos if (c == ',' && r_type == BFD_RELOC_ARC_TLS_GD_LD)
445 1.1.1.3 christos {
446 1.1.1.3 christos ++input_line_pointer;
447 1.1.1.3 christos char *lab_name;
448 1.1.1.3 christos c = get_symbol_name (&lab_name);
449 1.1.1.3 christos lab = symbol_find_or_make (lab_name);
450 1.1.1.3 christos restore_line_pointer (c);
451 1.1.1.3 christos }
452 1.1.1.3 christos fixS *fixP
453 1.1.1.3 christos = fix_new (frag_now, /* Which frag? */
454 1.1.1.3 christos frag_now_fix (), /* Where in that frag? */
455 1.1.1.3 christos 2, /* size: 1, 2, or 4 usually. */
456 1.1.1.3 christos sym, /* X_add_symbol. */
457 1.1.1.3 christos 0, /* X_add_number. */
458 1.1.1.3 christos FALSE, /* TRUE if PC-relative relocation. */
459 1.1.1.3 christos r_type /* Relocation type. */);
460 1.1.1.3 christos fixP->fx_subsy = lab;
461 1.1.1.3 christos }
462 1.1.1.3 christos
463 1.1.1.3 christos static symbolS *
464 1.1.1.3 christos arc_lcomm_internal (int ignore ATTRIBUTE_UNUSED,
465 1.1.1.3 christos symbolS *symbolP, addressT size)
466 1.1.1.3 christos {
467 1.1.1.3 christos addressT align = 0;
468 1.1.1.3 christos SKIP_WHITESPACE ();
469 1.1 skrll
470 1.1.1.3 christos if (*input_line_pointer == ',')
471 1.1 skrll {
472 1.1.1.3 christos align = parse_align (1);
473 1.1 skrll
474 1.1.1.3 christos if (align == (addressT) -1)
475 1.1.1.3 christos return NULL;
476 1.1 skrll }
477 1.1 skrll else
478 1.1.1.3 christos {
479 1.1.1.3 christos if (size >= 8)
480 1.1.1.3 christos align = 3;
481 1.1.1.3 christos else if (size >= 4)
482 1.1.1.3 christos align = 2;
483 1.1.1.3 christos else if (size >= 2)
484 1.1.1.3 christos align = 1;
485 1.1.1.3 christos else
486 1.1.1.3 christos align = 0;
487 1.1.1.3 christos }
488 1.1 skrll
489 1.1.1.3 christos bss_alloc (symbolP, size, align);
490 1.1.1.3 christos S_CLEAR_EXTERNAL (symbolP);
491 1.1 skrll
492 1.1.1.3 christos return symbolP;
493 1.1.1.3 christos }
494 1.1 skrll
495 1.1.1.3 christos static void
496 1.1.1.3 christos arc_lcomm (int ignore)
497 1.1 skrll {
498 1.1.1.3 christos symbolS *symbolP = s_comm_internal (ignore, arc_lcomm_internal);
499 1.1 skrll
500 1.1.1.3 christos if (symbolP)
501 1.1.1.3 christos symbol_get_bfdsym (symbolP)->flags |= BSF_OBJECT;
502 1.1.1.3 christos }
503 1.1 skrll
504 1.1.1.3 christos /* Select the cpu we're assembling for. */
505 1.1 skrll
506 1.1.1.3 christos static void
507 1.1.1.3 christos arc_option (int ignore ATTRIBUTE_UNUSED)
508 1.1.1.3 christos {
509 1.1.1.3 christos int mach = -1;
510 1.1.1.3 christos char c;
511 1.1.1.3 christos char *cpu;
512 1.1 skrll
513 1.1.1.3 christos c = get_symbol_name (&cpu);
514 1.1.1.3 christos mach = arc_get_mach (cpu);
515 1.1.1.3 christos restore_line_pointer (c);
516 1.1 skrll
517 1.1.1.3 christos if (mach == -1)
518 1.1.1.3 christos goto bad_cpu;
519 1.1 skrll
520 1.1.1.3 christos if (!mach_type_specified_p)
521 1.1 skrll {
522 1.1.1.3 christos arc_mach_type = mach;
523 1.1.1.3 christos if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, mach))
524 1.1.1.3 christos as_fatal ("could not set architecture and machine");
525 1.1 skrll
526 1.1.1.3 christos mach_type_specified_p = 1;
527 1.1 skrll }
528 1.1 skrll else
529 1.1.1.3 christos if (arc_mach_type != mach)
530 1.1.1.3 christos as_warn ("Command-line value overrides \".cpu\" directive");
531 1.1 skrll
532 1.1.1.3 christos demand_empty_rest_of_line ();
533 1.1.1.3 christos
534 1.1.1.3 christos return;
535 1.1 skrll
536 1.1.1.3 christos bad_cpu:
537 1.1.1.3 christos as_bad ("invalid identifier for \".cpu\"");
538 1.1.1.3 christos ignore_rest_of_line ();
539 1.1.1.3 christos }
540 1.1 skrll
541 1.1.1.3 christos /* Smartly print an expression. */
542 1.1 skrll
543 1.1.1.3 christos static void
544 1.1.1.3 christos debug_exp (expressionS *t)
545 1.1.1.3 christos {
546 1.1.1.3 christos const char *name ATTRIBUTE_UNUSED;
547 1.1.1.3 christos const char *namemd ATTRIBUTE_UNUSED;
548 1.1 skrll
549 1.1.1.3 christos pr_debug ("debug_exp: ");
550 1.1 skrll
551 1.1.1.3 christos switch (t->X_op)
552 1.1 skrll {
553 1.1.1.3 christos default: name = "unknown"; break;
554 1.1.1.3 christos case O_illegal: name = "O_illegal"; break;
555 1.1.1.3 christos case O_absent: name = "O_absent"; break;
556 1.1.1.3 christos case O_constant: name = "O_constant"; break;
557 1.1.1.3 christos case O_symbol: name = "O_symbol"; break;
558 1.1.1.3 christos case O_symbol_rva: name = "O_symbol_rva"; break;
559 1.1.1.3 christos case O_register: name = "O_register"; break;
560 1.1.1.3 christos case O_big: name = "O_big"; break;
561 1.1.1.3 christos case O_uminus: name = "O_uminus"; break;
562 1.1.1.3 christos case O_bit_not: name = "O_bit_not"; break;
563 1.1.1.3 christos case O_logical_not: name = "O_logical_not"; break;
564 1.1.1.3 christos case O_multiply: name = "O_multiply"; break;
565 1.1.1.3 christos case O_divide: name = "O_divide"; break;
566 1.1.1.3 christos case O_modulus: name = "O_modulus"; break;
567 1.1.1.3 christos case O_left_shift: name = "O_left_shift"; break;
568 1.1.1.3 christos case O_right_shift: name = "O_right_shift"; break;
569 1.1.1.3 christos case O_bit_inclusive_or: name = "O_bit_inclusive_or"; break;
570 1.1.1.3 christos case O_bit_or_not: name = "O_bit_or_not"; break;
571 1.1.1.3 christos case O_bit_exclusive_or: name = "O_bit_exclusive_or"; break;
572 1.1.1.3 christos case O_bit_and: name = "O_bit_and"; break;
573 1.1.1.3 christos case O_add: name = "O_add"; break;
574 1.1.1.3 christos case O_subtract: name = "O_subtract"; break;
575 1.1.1.3 christos case O_eq: name = "O_eq"; break;
576 1.1.1.3 christos case O_ne: name = "O_ne"; break;
577 1.1.1.3 christos case O_lt: name = "O_lt"; break;
578 1.1.1.3 christos case O_le: name = "O_le"; break;
579 1.1.1.3 christos case O_ge: name = "O_ge"; break;
580 1.1.1.3 christos case O_gt: name = "O_gt"; break;
581 1.1.1.3 christos case O_logical_and: name = "O_logical_and"; break;
582 1.1.1.3 christos case O_logical_or: name = "O_logical_or"; break;
583 1.1.1.3 christos case O_index: name = "O_index"; break;
584 1.1.1.3 christos case O_bracket: name = "O_bracket"; break;
585 1.1.1.3 christos }
586 1.1.1.3 christos
587 1.1.1.3 christos switch (t->X_md)
588 1.1.1.3 christos {
589 1.1.1.3 christos default: namemd = "unknown"; break;
590 1.1.1.3 christos case O_gotoff: namemd = "O_gotoff"; break;
591 1.1.1.3 christos case O_gotpc: namemd = "O_gotpc"; break;
592 1.1.1.3 christos case O_plt: namemd = "O_plt"; break;
593 1.1.1.3 christos case O_sda: namemd = "O_sda"; break;
594 1.1.1.3 christos case O_pcl: namemd = "O_pcl"; break;
595 1.1.1.3 christos case O_tlsgd: namemd = "O_tlsgd"; break;
596 1.1.1.3 christos case O_tlsie: namemd = "O_tlsie"; break;
597 1.1.1.3 christos case O_tpoff9: namemd = "O_tpoff9"; break;
598 1.1.1.3 christos case O_tpoff: namemd = "O_tpoff"; break;
599 1.1.1.3 christos case O_dtpoff9: namemd = "O_dtpoff9"; break;
600 1.1.1.3 christos case O_dtpoff: namemd = "O_dtpoff"; break;
601 1.1.1.3 christos }
602 1.1.1.3 christos
603 1.1.1.3 christos pr_debug ("%s (%s, %s, %d, %s)", name,
604 1.1.1.3 christos (t->X_add_symbol) ? S_GET_NAME (t->X_add_symbol) : "--",
605 1.1.1.3 christos (t->X_op_symbol) ? S_GET_NAME (t->X_op_symbol) : "--",
606 1.1.1.3 christos (int) t->X_add_number,
607 1.1.1.3 christos (t->X_md) ? namemd : "--");
608 1.1.1.3 christos pr_debug ("\n");
609 1.1.1.3 christos fflush (stderr);
610 1.1.1.3 christos }
611 1.1 skrll
612 1.1.1.3 christos /* Parse the arguments to an opcode. */
613 1.1 skrll
614 1.1.1.3 christos static int
615 1.1.1.3 christos tokenize_arguments (char *str,
616 1.1.1.3 christos expressionS *tok,
617 1.1.1.3 christos int ntok)
618 1.1.1.3 christos {
619 1.1.1.3 christos char *old_input_line_pointer;
620 1.1.1.3 christos bfd_boolean saw_comma = FALSE;
621 1.1.1.3 christos bfd_boolean saw_arg = FALSE;
622 1.1.1.3 christos int brk_lvl = 0;
623 1.1.1.3 christos int num_args = 0;
624 1.1.1.3 christos int i;
625 1.1.1.3 christos size_t len;
626 1.1.1.3 christos const struct arc_reloc_op_tag *r;
627 1.1.1.3 christos expressionS tmpE;
628 1.1.1.3 christos char *reloc_name, c;
629 1.1.1.3 christos
630 1.1.1.3 christos memset (tok, 0, sizeof (*tok) * ntok);
631 1.1.1.3 christos
632 1.1.1.3 christos /* Save and restore input_line_pointer around this function. */
633 1.1.1.3 christos old_input_line_pointer = input_line_pointer;
634 1.1.1.3 christos input_line_pointer = str;
635 1.1 skrll
636 1.1.1.3 christos while (*input_line_pointer)
637 1.1 skrll {
638 1.1 skrll SKIP_WHITESPACE ();
639 1.1.1.3 christos switch (*input_line_pointer)
640 1.1 skrll {
641 1.1.1.3 christos case '\0':
642 1.1.1.3 christos goto fini;
643 1.1 skrll
644 1.1.1.3 christos case ',':
645 1.1.1.3 christos input_line_pointer++;
646 1.1.1.3 christos if (saw_comma || !saw_arg)
647 1.1.1.3 christos goto err;
648 1.1.1.3 christos saw_comma = TRUE;
649 1.1.1.3 christos break;
650 1.1 skrll
651 1.1.1.3 christos case '}':
652 1.1.1.3 christos case ']':
653 1.1.1.3 christos ++input_line_pointer;
654 1.1.1.3 christos --brk_lvl;
655 1.1.1.3 christos if (!saw_arg)
656 1.1.1.3 christos goto err;
657 1.1.1.3 christos tok->X_op = O_bracket;
658 1.1.1.3 christos ++tok;
659 1.1.1.3 christos ++num_args;
660 1.1.1.3 christos break;
661 1.1.1.3 christos
662 1.1.1.3 christos case '{':
663 1.1.1.3 christos case '[':
664 1.1.1.3 christos input_line_pointer++;
665 1.1.1.3 christos if (brk_lvl)
666 1.1.1.3 christos goto err;
667 1.1.1.3 christos ++brk_lvl;
668 1.1.1.3 christos tok->X_op = O_bracket;
669 1.1.1.3 christos ++tok;
670 1.1.1.3 christos ++num_args;
671 1.1.1.3 christos break;
672 1.1.1.3 christos
673 1.1.1.3 christos case '@':
674 1.1.1.3 christos /* We have labels, function names and relocations, all
675 1.1.1.3 christos starting with @ symbol. Sort them out. */
676 1.1.1.3 christos if (saw_arg && !saw_comma)
677 1.1.1.3 christos goto err;
678 1.1.1.3 christos
679 1.1.1.3 christos /* Parse @label. */
680 1.1.1.3 christos tok->X_op = O_symbol;
681 1.1.1.3 christos tok->X_md = O_absent;
682 1.1.1.3 christos expression (tok);
683 1.1.1.3 christos if (*input_line_pointer != '@')
684 1.1.1.3 christos goto normalsymbol; /* This is not a relocation. */
685 1.1.1.3 christos
686 1.1.1.3 christos relocationsym:
687 1.1.1.3 christos
688 1.1.1.3 christos /* A relocation opernad has the following form
689 1.1.1.3 christos @identifier@relocation_type. The identifier is already
690 1.1.1.3 christos in tok! */
691 1.1.1.3 christos if (tok->X_op != O_symbol)
692 1.1 skrll {
693 1.1.1.3 christos as_bad (_("No valid label relocation operand"));
694 1.1.1.3 christos goto err;
695 1.1 skrll }
696 1.1.1.3 christos
697 1.1.1.3 christos /* Parse @relocation_type. */
698 1.1.1.3 christos input_line_pointer++;
699 1.1.1.3 christos c = get_symbol_name (&reloc_name);
700 1.1.1.3 christos len = input_line_pointer - reloc_name;
701 1.1.1.3 christos if (len == 0)
702 1.1 skrll {
703 1.1.1.3 christos as_bad (_("No relocation operand"));
704 1.1.1.3 christos goto err;
705 1.1 skrll }
706 1.1.1.3 christos
707 1.1.1.3 christos /* Go through known relocation and try to find a match. */
708 1.1.1.3 christos r = &arc_reloc_op[0];
709 1.1.1.3 christos for (i = arc_num_reloc_op - 1; i >= 0; i--, r++)
710 1.1.1.3 christos if (len == r->length
711 1.1.1.3 christos && memcmp (reloc_name, r->name, len) == 0)
712 1.1.1.3 christos break;
713 1.1.1.3 christos if (i < 0)
714 1.1 skrll {
715 1.1.1.3 christos as_bad (_("Unknown relocation operand: @%s"), reloc_name);
716 1.1.1.3 christos goto err;
717 1.1 skrll }
718 1.1 skrll
719 1.1.1.3 christos *input_line_pointer = c;
720 1.1.1.3 christos SKIP_WHITESPACE_AFTER_NAME ();
721 1.1.1.3 christos /* Extra check for TLS: base. */
722 1.1.1.3 christos if (*input_line_pointer == '@')
723 1.1 skrll {
724 1.1.1.3 christos symbolS *base;
725 1.1.1.3 christos if (tok->X_op_symbol != NULL
726 1.1.1.3 christos || tok->X_op != O_symbol)
727 1.1.1.3 christos {
728 1.1.1.3 christos as_bad (_("Unable to parse TLS base: %s"),
729 1.1.1.3 christos input_line_pointer);
730 1.1.1.3 christos goto err;
731 1.1.1.3 christos }
732 1.1.1.3 christos input_line_pointer++;
733 1.1.1.3 christos char *sym_name;
734 1.1.1.3 christos c = get_symbol_name (&sym_name);
735 1.1.1.3 christos base = symbol_find_or_make (sym_name);
736 1.1.1.3 christos tok->X_op = O_subtract;
737 1.1.1.3 christos tok->X_op_symbol = base;
738 1.1.1.3 christos restore_line_pointer (c);
739 1.1.1.3 christos tmpE.X_add_number = 0;
740 1.1.1.3 christos }
741 1.1.1.3 christos else if ((*input_line_pointer != '+')
742 1.1.1.3 christos && (*input_line_pointer != '-'))
743 1.1.1.3 christos {
744 1.1.1.3 christos tmpE.X_add_number = 0;
745 1.1 skrll }
746 1.1 skrll else
747 1.1 skrll {
748 1.1.1.3 christos /* Parse the constant of a complex relocation expression
749 1.1.1.3 christos like @identifier@reloc +/- const. */
750 1.1.1.3 christos if (! r->complex_expr)
751 1.1 skrll {
752 1.1.1.3 christos as_bad (_("@%s is not a complex relocation."), r->name);
753 1.1.1.3 christos goto err;
754 1.1 skrll }
755 1.1.1.3 christos expression (&tmpE);
756 1.1.1.3 christos if (tmpE.X_op != O_constant)
757 1.1 skrll {
758 1.1.1.3 christos as_bad (_("Bad expression: @%s + %s."),
759 1.1.1.3 christos r->name, input_line_pointer);
760 1.1.1.3 christos goto err;
761 1.1 skrll }
762 1.1 skrll }
763 1.1 skrll
764 1.1.1.3 christos tok->X_md = r->op;
765 1.1.1.3 christos tok->X_add_number = tmpE.X_add_number;
766 1.1 skrll
767 1.1.1.3 christos debug_exp (tok);
768 1.1 skrll
769 1.1.1.3 christos saw_comma = FALSE;
770 1.1.1.3 christos saw_arg = TRUE;
771 1.1.1.3 christos tok++;
772 1.1.1.3 christos num_args++;
773 1.1.1.3 christos break;
774 1.1 skrll
775 1.1.1.3 christos case '%':
776 1.1.1.3 christos /* Can be a register. */
777 1.1.1.3 christos ++input_line_pointer;
778 1.1.1.3 christos /* Fall through. */
779 1.1.1.3 christos default:
780 1.1.1.3 christos
781 1.1.1.3 christos if (saw_arg && !saw_comma)
782 1.1.1.3 christos goto err;
783 1.1.1.3 christos
784 1.1.1.3 christos tok->X_op = O_absent;
785 1.1.1.3 christos tok->X_md = O_absent;
786 1.1.1.3 christos expression (tok);
787 1.1.1.3 christos
788 1.1.1.3 christos /* Legacy: There are cases when we have
789 1.1.1.3 christos identifier@relocation_type, if it is the case parse the
790 1.1.1.3 christos relocation type as well. */
791 1.1.1.3 christos if (*input_line_pointer == '@')
792 1.1.1.3 christos goto relocationsym;
793 1.1.1.3 christos
794 1.1.1.3 christos normalsymbol:
795 1.1.1.3 christos debug_exp (tok);
796 1.1.1.3 christos
797 1.1.1.3 christos if (tok->X_op == O_illegal || tok->X_op == O_absent)
798 1.1.1.3 christos goto err;
799 1.1.1.3 christos
800 1.1.1.3 christos saw_comma = FALSE;
801 1.1.1.3 christos saw_arg = TRUE;
802 1.1.1.3 christos tok++;
803 1.1.1.3 christos num_args++;
804 1.1.1.3 christos break;
805 1.1 skrll }
806 1.1 skrll }
807 1.1 skrll
808 1.1.1.3 christos fini:
809 1.1.1.3 christos if (saw_comma || brk_lvl)
810 1.1.1.3 christos goto err;
811 1.1.1.3 christos input_line_pointer = old_input_line_pointer;
812 1.1.1.3 christos
813 1.1.1.3 christos return num_args;
814 1.1.1.3 christos
815 1.1.1.3 christos err:
816 1.1.1.3 christos if (brk_lvl)
817 1.1.1.3 christos as_bad (_("Brackets in operand field incorrect"));
818 1.1.1.3 christos else if (saw_comma)
819 1.1.1.3 christos as_bad (_("extra comma"));
820 1.1.1.3 christos else if (!saw_arg)
821 1.1.1.3 christos as_bad (_("missing argument"));
822 1.1.1.3 christos else
823 1.1.1.3 christos as_bad (_("missing comma or colon"));
824 1.1.1.3 christos input_line_pointer = old_input_line_pointer;
825 1.1.1.3 christos return -1;
826 1.1.1.3 christos }
827 1.1 skrll
828 1.1.1.3 christos /* Parse the flags to a structure. */
829 1.1 skrll
830 1.1.1.3 christos static int
831 1.1.1.3 christos tokenize_flags (const char *str,
832 1.1.1.3 christos struct arc_flags flags[],
833 1.1.1.3 christos int nflg)
834 1.1.1.3 christos {
835 1.1.1.3 christos char *old_input_line_pointer;
836 1.1.1.3 christos bfd_boolean saw_flg = FALSE;
837 1.1.1.3 christos bfd_boolean saw_dot = FALSE;
838 1.1.1.3 christos int num_flags = 0;
839 1.1.1.3 christos size_t flgnamelen;
840 1.1.1.3 christos
841 1.1.1.3 christos memset (flags, 0, sizeof (*flags) * nflg);
842 1.1.1.3 christos
843 1.1.1.3 christos /* Save and restore input_line_pointer around this function. */
844 1.1.1.3 christos old_input_line_pointer = input_line_pointer;
845 1.1.1.3 christos input_line_pointer = (char *) str;
846 1.1.1.3 christos
847 1.1.1.3 christos while (*input_line_pointer)
848 1.1.1.3 christos {
849 1.1.1.3 christos switch (*input_line_pointer)
850 1.1.1.3 christos {
851 1.1.1.3 christos case ' ':
852 1.1.1.3 christos case '\0':
853 1.1.1.3 christos goto fini;
854 1.1.1.3 christos
855 1.1.1.3 christos case '.':
856 1.1.1.3 christos input_line_pointer++;
857 1.1.1.3 christos if (saw_dot)
858 1.1.1.3 christos goto err;
859 1.1.1.3 christos saw_dot = TRUE;
860 1.1.1.3 christos saw_flg = FALSE;
861 1.1.1.3 christos break;
862 1.1 skrll
863 1.1.1.3 christos default:
864 1.1.1.3 christos if (saw_flg && !saw_dot)
865 1.1.1.3 christos goto err;
866 1.1 skrll
867 1.1.1.3 christos if (num_flags >= nflg)
868 1.1.1.3 christos goto err;
869 1.1 skrll
870 1.1.1.3 christos flgnamelen = strspn (input_line_pointer, "abcdefghilmnopqrstvwxz");
871 1.1.1.3 christos if (flgnamelen > MAX_FLAG_NAME_LENGHT)
872 1.1.1.3 christos goto err;
873 1.1.1.3 christos
874 1.1.1.3 christos memcpy (flags->name, input_line_pointer, flgnamelen);
875 1.1.1.3 christos
876 1.1.1.3 christos input_line_pointer += flgnamelen;
877 1.1.1.3 christos flags++;
878 1.1.1.3 christos saw_dot = FALSE;
879 1.1.1.3 christos saw_flg = TRUE;
880 1.1.1.3 christos num_flags++;
881 1.1.1.3 christos break;
882 1.1.1.3 christos }
883 1.1 skrll }
884 1.1 skrll
885 1.1.1.3 christos fini:
886 1.1.1.3 christos input_line_pointer = old_input_line_pointer;
887 1.1.1.3 christos return num_flags;
888 1.1.1.3 christos
889 1.1.1.3 christos err:
890 1.1.1.3 christos if (saw_dot)
891 1.1.1.3 christos as_bad (_("extra dot"));
892 1.1.1.3 christos else if (!saw_flg)
893 1.1.1.3 christos as_bad (_("unrecognized flag"));
894 1.1.1.3 christos else
895 1.1.1.3 christos as_bad (_("failed to parse flags"));
896 1.1.1.3 christos input_line_pointer = old_input_line_pointer;
897 1.1.1.3 christos return -1;
898 1.1 skrll }
899 1.1 skrll
900 1.1.1.3 christos /* The public interface to the instruction assembler. */
901 1.1.1.3 christos
902 1.1.1.3 christos void
903 1.1.1.3 christos md_assemble (char *str)
904 1.1 skrll {
905 1.1.1.3 christos char *opname;
906 1.1.1.3 christos expressionS tok[MAX_INSN_ARGS];
907 1.1.1.3 christos int ntok, nflg;
908 1.1.1.3 christos size_t opnamelen;
909 1.1.1.3 christos struct arc_flags flags[MAX_INSN_FLGS];
910 1.1.1.3 christos
911 1.1.1.3 christos /* Split off the opcode. */
912 1.1.1.3 christos opnamelen = strspn (str, "abcdefghijklmnopqrstuvwxyz_0123468");
913 1.1.1.3 christos opname = xmalloc (opnamelen + 1);
914 1.1.1.3 christos memcpy (opname, str, opnamelen);
915 1.1.1.3 christos opname[opnamelen] = '\0';
916 1.1 skrll
917 1.1.1.3 christos /* Signalize we are assmbling the instructions. */
918 1.1.1.3 christos assembling_insn = TRUE;
919 1.1 skrll
920 1.1.1.3 christos /* Tokenize the flags. */
921 1.1.1.3 christos if ((nflg = tokenize_flags (str + opnamelen, flags, MAX_INSN_FLGS)) == -1)
922 1.1 skrll {
923 1.1.1.3 christos as_bad (_("syntax error"));
924 1.1 skrll return;
925 1.1 skrll }
926 1.1 skrll
927 1.1.1.3 christos /* Scan up to the end of the mnemonic which must end in space or end
928 1.1.1.3 christos of string. */
929 1.1.1.3 christos str += opnamelen;
930 1.1.1.3 christos for (; *str != '\0'; str++)
931 1.1.1.3 christos if (*str == ' ')
932 1.1.1.3 christos break;
933 1.1 skrll
934 1.1.1.3 christos /* Tokenize the rest of the line. */
935 1.1.1.3 christos if ((ntok = tokenize_arguments (str, tok, MAX_INSN_ARGS)) < 0)
936 1.1 skrll {
937 1.1.1.3 christos as_bad (_("syntax error"));
938 1.1 skrll return;
939 1.1 skrll }
940 1.1 skrll
941 1.1.1.3 christos /* Finish it off. */
942 1.1.1.3 christos assemble_tokens (opname, tok, ntok, flags, nflg);
943 1.1.1.3 christos assembling_insn = FALSE;
944 1.1.1.3 christos }
945 1.1 skrll
946 1.1.1.3 christos /* Callback to insert a register into the hash table. */
947 1.1 skrll
948 1.1 skrll static void
949 1.1.1.3 christos declare_register (char *name, int number)
950 1.1 skrll {
951 1.1.1.3 christos const char *err;
952 1.1.1.3 christos symbolS *regS = symbol_create (name, reg_section,
953 1.1.1.3 christos number, &zero_address_frag);
954 1.1 skrll
955 1.1.1.3 christos err = hash_insert (arc_reg_hash, S_GET_NAME (regS), (void *) regS);
956 1.1.1.3 christos if (err)
957 1.1.1.3 christos as_fatal ("Inserting \"%s\" into register table failed: %s",
958 1.1.1.3 christos name, err);
959 1.1.1.3 christos }
960 1.1 skrll
961 1.1.1.3 christos /* Construct symbols for each of the general registers. */
962 1.1 skrll
963 1.1.1.3 christos static void
964 1.1.1.3 christos declare_register_set (void)
965 1.1.1.3 christos {
966 1.1.1.3 christos int i;
967 1.1.1.3 christos for (i = 0; i < 32; ++i)
968 1.1 skrll {
969 1.1.1.3 christos char name[7];
970 1.1 skrll
971 1.1.1.3 christos sprintf (name, "r%d", i);
972 1.1.1.3 christos declare_register (name, i);
973 1.1.1.3 christos if ((i & 0x01) == 0)
974 1.1 skrll {
975 1.1.1.3 christos sprintf (name, "r%dr%d", i, i+1);
976 1.1.1.3 christos declare_register (name, i);
977 1.1 skrll }
978 1.1 skrll }
979 1.1.1.3 christos }
980 1.1 skrll
981 1.1.1.3 christos /* Port-specific assembler initialization. This function is called
982 1.1.1.3 christos once, at assembler startup time. */
983 1.1 skrll
984 1.1.1.3 christos void
985 1.1.1.3 christos md_begin (void)
986 1.1.1.3 christos {
987 1.1.1.3 christos unsigned int i;
988 1.1 skrll
989 1.1.1.3 christos /* The endianness can be chosen "at the factory". */
990 1.1.1.3 christos target_big_endian = byte_order == BIG_ENDIAN;
991 1.1 skrll
992 1.1.1.3 christos if (!bfd_set_arch_mach (stdoutput, bfd_arch_arc, arc_mach_type))
993 1.1.1.3 christos as_warn (_("could not set architecture and machine"));
994 1.1 skrll
995 1.1.1.3 christos /* Set elf header flags. */
996 1.1.1.3 christos bfd_set_private_flags (stdoutput, arc_eflag);
997 1.1 skrll
998 1.1.1.3 christos /* Set up a hash table for the instructions. */
999 1.1.1.3 christos arc_opcode_hash = hash_new ();
1000 1.1.1.3 christos if (arc_opcode_hash == NULL)
1001 1.1.1.3 christos as_fatal (_("Virtual memory exhausted"));
1002 1.1.1.3 christos
1003 1.1.1.3 christos /* Initialize the hash table with the insns. */
1004 1.1.1.3 christos for (i = 0; i < arc_num_opcodes;)
1005 1.1.1.3 christos {
1006 1.1.1.3 christos const char *name, *retval;
1007 1.1.1.3 christos
1008 1.1.1.3 christos name = arc_opcodes[i].name;
1009 1.1.1.3 christos retval = hash_insert (arc_opcode_hash, name, (void *) &arc_opcodes[i]);
1010 1.1.1.3 christos if (retval)
1011 1.1.1.3 christos as_fatal (_("internal error: can't hash opcode '%s': %s"),
1012 1.1.1.3 christos name, retval);
1013 1.1.1.3 christos
1014 1.1.1.3 christos while (++i < arc_num_opcodes
1015 1.1.1.3 christos && (arc_opcodes[i].name == name
1016 1.1.1.3 christos || !strcmp (arc_opcodes[i].name, name)))
1017 1.1.1.3 christos continue;
1018 1.1 skrll }
1019 1.1 skrll
1020 1.1.1.3 christos /* Register declaration. */
1021 1.1.1.3 christos arc_reg_hash = hash_new ();
1022 1.1.1.3 christos if (arc_reg_hash == NULL)
1023 1.1.1.3 christos as_fatal (_("Virtual memory exhausted"));
1024 1.1.1.3 christos
1025 1.1.1.3 christos declare_register_set ();
1026 1.1.1.3 christos declare_register ("gp", 26);
1027 1.1.1.3 christos declare_register ("fp", 27);
1028 1.1.1.3 christos declare_register ("sp", 28);
1029 1.1.1.3 christos declare_register ("ilink", 29);
1030 1.1.1.3 christos declare_register ("ilink1", 29);
1031 1.1.1.3 christos declare_register ("ilink2", 30);
1032 1.1.1.3 christos declare_register ("blink", 31);
1033 1.1.1.3 christos
1034 1.1.1.3 christos declare_register ("mlo", 57);
1035 1.1.1.3 christos declare_register ("mmid", 58);
1036 1.1.1.3 christos declare_register ("mhi", 59);
1037 1.1 skrll
1038 1.1.1.3 christos declare_register ("acc1", 56);
1039 1.1.1.3 christos declare_register ("acc2", 57);
1040 1.1 skrll
1041 1.1.1.3 christos declare_register ("lp_count", 60);
1042 1.1.1.3 christos declare_register ("pcl", 63);
1043 1.1.1.3 christos
1044 1.1.1.3 christos /* Initialize the last instructions. */
1045 1.1.1.3 christos memset (&arc_last_insns[0], 0, sizeof (arc_last_insns));
1046 1.1 skrll }
1047 1.1 skrll
1048 1.1 skrll /* Write a value out to the object file, using the appropriate
1049 1.1 skrll endianness. */
1050 1.1 skrll
1051 1.1 skrll void
1052 1.1.1.3 christos md_number_to_chars (char *buf,
1053 1.1.1.3 christos valueT val,
1054 1.1.1.3 christos int n)
1055 1.1 skrll {
1056 1.1 skrll if (target_big_endian)
1057 1.1 skrll number_to_chars_bigendian (buf, val, n);
1058 1.1 skrll else
1059 1.1 skrll number_to_chars_littleendian (buf, val, n);
1060 1.1 skrll }
1061 1.1 skrll
1062 1.1 skrll /* Round up a section size to the appropriate boundary. */
1063 1.1 skrll
1064 1.1 skrll valueT
1065 1.1.1.3 christos md_section_align (segT segment,
1066 1.1.1.3 christos valueT size)
1067 1.1 skrll {
1068 1.1 skrll int align = bfd_get_section_alignment (stdoutput, segment);
1069 1.1 skrll
1070 1.1.1.3 christos return ((size + (1 << align) - 1) & -(1 << align));
1071 1.1 skrll }
1072 1.1 skrll
1073 1.1.1.3 christos /* The location from which a PC relative jump should be calculated,
1074 1.1.1.3 christos given a PC relative reloc. */
1075 1.1 skrll
1076 1.1.1.3 christos long
1077 1.1.1.3 christos md_pcrel_from_section (fixS *fixP,
1078 1.1.1.3 christos segT sec)
1079 1.1 skrll {
1080 1.1.1.3 christos offsetT base = fixP->fx_where + fixP->fx_frag->fr_address;
1081 1.1 skrll
1082 1.1.1.3 christos pr_debug ("pcrel_from_section, fx_offset = %d\n", (int) fixP->fx_offset);
1083 1.1 skrll
1084 1.1.1.3 christos if (fixP->fx_addsy != (symbolS *) NULL
1085 1.1.1.3 christos && (!S_IS_DEFINED (fixP->fx_addsy)
1086 1.1.1.3 christos || S_GET_SEGMENT (fixP->fx_addsy) != sec))
1087 1.1 skrll {
1088 1.1.1.3 christos pr_debug ("Unknown pcrel symbol: %s\n", S_GET_NAME (fixP->fx_addsy));
1089 1.1 skrll
1090 1.1.1.3 christos /* The symbol is undefined (or is defined but not in this section).
1091 1.1.1.3 christos Let the linker figure it out. */
1092 1.1.1.3 christos return 0;
1093 1.1 skrll }
1094 1.1 skrll
1095 1.1.1.3 christos if ((int) fixP->fx_r_type < 0)
1096 1.1 skrll {
1097 1.1.1.3 christos /* These are the "internal" relocations. Align them to
1098 1.1.1.3 christos 32 bit boundary (PCL), for the moment. */
1099 1.1.1.3 christos base &= ~3;
1100 1.1 skrll }
1101 1.1 skrll else
1102 1.1 skrll {
1103 1.1.1.3 christos switch (fixP->fx_r_type)
1104 1.1 skrll {
1105 1.1.1.3 christos case BFD_RELOC_ARC_PC32:
1106 1.1.1.3 christos /* The hardware calculates relative to the start of the
1107 1.1.1.3 christos insn, but this relocation is relative to location of the
1108 1.1.1.3 christos LIMM, compensate. TIP: the base always needs to be
1109 1.1.1.3 christos substracted by 4 as we do not support this type of PCrel
1110 1.1.1.3 christos relocation for short instructions. */
1111 1.1.1.3 christos base -= fixP->fx_where - fixP->fx_dot_value;
1112 1.1.1.3 christos gas_assert ((fixP->fx_where - fixP->fx_dot_value) == 4);
1113 1.1.1.3 christos /* Fall through. */
1114 1.1.1.3 christos case BFD_RELOC_ARC_PLT32:
1115 1.1.1.3 christos case BFD_RELOC_ARC_S25H_PCREL_PLT:
1116 1.1.1.3 christos case BFD_RELOC_ARC_S21H_PCREL_PLT:
1117 1.1.1.3 christos case BFD_RELOC_ARC_S25W_PCREL_PLT:
1118 1.1.1.3 christos case BFD_RELOC_ARC_S21W_PCREL_PLT:
1119 1.1.1.3 christos
1120 1.1.1.3 christos case BFD_RELOC_ARC_S21H_PCREL:
1121 1.1.1.3 christos case BFD_RELOC_ARC_S25H_PCREL:
1122 1.1.1.3 christos case BFD_RELOC_ARC_S13_PCREL:
1123 1.1.1.3 christos case BFD_RELOC_ARC_S21W_PCREL:
1124 1.1.1.3 christos case BFD_RELOC_ARC_S25W_PCREL:
1125 1.1.1.3 christos base &= ~3;
1126 1.1.1.3 christos break;
1127 1.1.1.3 christos default:
1128 1.1.1.3 christos as_bad_where (fixP->fx_file, fixP->fx_line,
1129 1.1.1.3 christos _("unhandled reloc %s in md_pcrel_from_section"),
1130 1.1.1.3 christos bfd_get_reloc_code_name (fixP->fx_r_type));
1131 1.1.1.3 christos break;
1132 1.1 skrll }
1133 1.1 skrll }
1134 1.1 skrll
1135 1.1.1.3 christos pr_debug ("pcrel from %x + %lx = %x, symbol: %s (%x)\n",
1136 1.1.1.3 christos fixP->fx_frag->fr_address, fixP->fx_where, base,
1137 1.1.1.3 christos fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : "(null)",
1138 1.1.1.3 christos fixP->fx_addsy ? S_GET_VALUE (fixP->fx_addsy) : 0);
1139 1.1 skrll
1140 1.1.1.3 christos return base;
1141 1.1 skrll }
1142 1.1 skrll
1143 1.1.1.3 christos /* Given a BFD relocation find the coresponding operand. */
1144 1.1 skrll
1145 1.1.1.3 christos static const struct arc_operand *
1146 1.1.1.3 christos find_operand_for_reloc (extended_bfd_reloc_code_real_type reloc)
1147 1.1 skrll {
1148 1.1.1.3 christos unsigned i;
1149 1.1 skrll
1150 1.1.1.3 christos for (i = 0; i < arc_num_operands; i++)
1151 1.1.1.3 christos if (arc_operands[i].default_reloc == reloc)
1152 1.1.1.3 christos return &arc_operands[i];
1153 1.1.1.3 christos return NULL;
1154 1.1 skrll }
1155 1.1 skrll
1156 1.1.1.3 christos /* Apply a fixup to the object code. At this point all symbol values
1157 1.1.1.3 christos should be fully resolved, and we attempt to completely resolve the
1158 1.1.1.3 christos reloc. If we can not do that, we determine the correct reloc code
1159 1.1.1.3 christos and put it back in the fixup. To indicate that a fixup has been
1160 1.1.1.3 christos eliminated, set fixP->fx_done. */
1161 1.1 skrll
1162 1.1 skrll void
1163 1.1.1.3 christos md_apply_fix (fixS *fixP,
1164 1.1.1.3 christos valueT *valP,
1165 1.1.1.3 christos segT seg)
1166 1.1.1.3 christos {
1167 1.1.1.3 christos char * const fixpos = fixP->fx_frag->fr_literal + fixP->fx_where;
1168 1.1.1.3 christos valueT value = *valP;
1169 1.1.1.3 christos unsigned insn = 0;
1170 1.1.1.3 christos symbolS *fx_addsy, *fx_subsy;
1171 1.1.1.3 christos offsetT fx_offset;
1172 1.1.1.3 christos segT add_symbol_segment = absolute_section;
1173 1.1.1.3 christos segT sub_symbol_segment = absolute_section;
1174 1.1.1.3 christos const struct arc_operand *operand = NULL;
1175 1.1.1.3 christos extended_bfd_reloc_code_real_type reloc;
1176 1.1.1.3 christos
1177 1.1.1.3 christos pr_debug ("%s:%u: apply_fix: r_type=%d (%s) value=0x%lX offset=0x%lX\n",
1178 1.1.1.3 christos fixP->fx_file, fixP->fx_line, fixP->fx_r_type,
1179 1.1.1.3 christos ((int) fixP->fx_r_type < 0) ? "Internal":
1180 1.1.1.3 christos bfd_get_reloc_code_name (fixP->fx_r_type), value,
1181 1.1.1.3 christos fixP->fx_offset);
1182 1.1.1.3 christos
1183 1.1.1.3 christos fx_addsy = fixP->fx_addsy;
1184 1.1.1.3 christos fx_subsy = fixP->fx_subsy;
1185 1.1.1.3 christos fx_offset = 0;
1186 1.1.1.3 christos
1187 1.1.1.3 christos if (fx_addsy)
1188 1.1.1.3 christos {
1189 1.1.1.3 christos add_symbol_segment = S_GET_SEGMENT (fx_addsy);
1190 1.1.1.3 christos }
1191 1.1.1.3 christos
1192 1.1.1.3 christos if (fx_subsy
1193 1.1.1.3 christos && fixP->fx_r_type != BFD_RELOC_ARC_TLS_DTPOFF
1194 1.1.1.3 christos && fixP->fx_r_type != BFD_RELOC_ARC_TLS_DTPOFF_S9
1195 1.1.1.3 christos && fixP->fx_r_type != BFD_RELOC_ARC_TLS_GD_LD)
1196 1.1.1.3 christos {
1197 1.1.1.3 christos resolve_symbol_value (fx_subsy);
1198 1.1.1.3 christos sub_symbol_segment = S_GET_SEGMENT (fx_subsy);
1199 1.1.1.3 christos
1200 1.1.1.3 christos if (sub_symbol_segment == absolute_section)
1201 1.1.1.3 christos {
1202 1.1.1.3 christos /* The symbol is really a constant. */
1203 1.1.1.3 christos fx_offset -= S_GET_VALUE (fx_subsy);
1204 1.1.1.3 christos fx_subsy = NULL;
1205 1.1.1.3 christos }
1206 1.1.1.3 christos else
1207 1.1.1.3 christos {
1208 1.1.1.3 christos as_bad_where (fixP->fx_file, fixP->fx_line,
1209 1.1.1.3 christos _("can't resolve `%s' {%s section} - `%s' {%s section}"),
1210 1.1.1.3 christos fx_addsy ? S_GET_NAME (fx_addsy) : "0",
1211 1.1.1.3 christos segment_name (add_symbol_segment),
1212 1.1.1.3 christos S_GET_NAME (fx_subsy),
1213 1.1.1.3 christos segment_name (sub_symbol_segment));
1214 1.1.1.3 christos return;
1215 1.1.1.3 christos }
1216 1.1 skrll }
1217 1.1.1.3 christos
1218 1.1.1.3 christos if (fx_addsy
1219 1.1.1.3 christos && !S_IS_WEAK (fx_addsy))
1220 1.1 skrll {
1221 1.1.1.3 christos if (add_symbol_segment == seg
1222 1.1.1.3 christos && fixP->fx_pcrel)
1223 1.1.1.3 christos {
1224 1.1.1.3 christos value += S_GET_VALUE (fx_addsy);
1225 1.1.1.3 christos value -= md_pcrel_from_section (fixP, seg);
1226 1.1.1.3 christos fx_addsy = NULL;
1227 1.1.1.3 christos fixP->fx_pcrel = FALSE;
1228 1.1.1.3 christos }
1229 1.1.1.3 christos else if (add_symbol_segment == absolute_section)
1230 1.1.1.3 christos {
1231 1.1.1.3 christos value = fixP->fx_offset;
1232 1.1.1.3 christos fx_offset += S_GET_VALUE (fixP->fx_addsy);
1233 1.1.1.3 christos fx_addsy = NULL;
1234 1.1.1.3 christos fixP->fx_pcrel = FALSE;
1235 1.1.1.3 christos }
1236 1.1 skrll }
1237 1.1 skrll
1238 1.1.1.3 christos if (!fx_addsy)
1239 1.1.1.3 christos fixP->fx_done = TRUE;
1240 1.1 skrll
1241 1.1.1.3 christos if (fixP->fx_pcrel)
1242 1.1.1.3 christos {
1243 1.1.1.3 christos if (fx_addsy
1244 1.1.1.3 christos && ((S_IS_DEFINED (fx_addsy)
1245 1.1.1.3 christos && S_GET_SEGMENT (fx_addsy) != seg)
1246 1.1.1.3 christos || S_IS_WEAK (fx_addsy)))
1247 1.1.1.3 christos value += md_pcrel_from_section (fixP, seg);
1248 1.1.1.3 christos
1249 1.1.1.3 christos switch (fixP->fx_r_type)
1250 1.1.1.3 christos {
1251 1.1.1.3 christos case BFD_RELOC_ARC_32_ME:
1252 1.1.1.3 christos /* This is a pc-relative value in a LIMM. Adjust it to the
1253 1.1.1.3 christos address of the instruction not to the address of the
1254 1.1.1.3 christos LIMM. Note: it is not anylonger valid this afirmation as
1255 1.1.1.3 christos the linker consider ARC_PC32 a fixup to entire 64 bit
1256 1.1.1.3 christos insn. */
1257 1.1.1.3 christos fixP->fx_offset += fixP->fx_frag->fr_address;
1258 1.1.1.3 christos /* Fall through. */
1259 1.1.1.3 christos case BFD_RELOC_32:
1260 1.1.1.3 christos fixP->fx_r_type = BFD_RELOC_ARC_PC32;
1261 1.1.1.3 christos /* Fall through. */
1262 1.1.1.3 christos case BFD_RELOC_ARC_PC32:
1263 1.1.1.3 christos /* fixP->fx_offset += fixP->fx_where - fixP->fx_dot_value; */
1264 1.1.1.3 christos break;
1265 1.1.1.3 christos default:
1266 1.1.1.3 christos if ((int) fixP->fx_r_type < 0)
1267 1.1.1.3 christos as_fatal (_("PC relative relocation not allowed for (internal) type %d"),
1268 1.1.1.3 christos fixP->fx_r_type);
1269 1.1.1.3 christos break;
1270 1.1.1.3 christos }
1271 1.1.1.3 christos }
1272 1.1 skrll
1273 1.1.1.3 christos pr_debug ("%s:%u: apply_fix: r_type=%d (%s) value=0x%lX offset=0x%lX\n",
1274 1.1.1.3 christos fixP->fx_file, fixP->fx_line, fixP->fx_r_type,
1275 1.1.1.3 christos ((int) fixP->fx_r_type < 0) ? "Internal":
1276 1.1.1.3 christos bfd_get_reloc_code_name (fixP->fx_r_type), value,
1277 1.1.1.3 christos fixP->fx_offset);
1278 1.1.1.3 christos
1279 1.1.1.3 christos
1280 1.1.1.3 christos /* Now check for TLS relocations. */
1281 1.1.1.3 christos reloc = fixP->fx_r_type;
1282 1.1.1.3 christos switch (reloc)
1283 1.1.1.3 christos {
1284 1.1.1.3 christos case BFD_RELOC_ARC_TLS_DTPOFF:
1285 1.1.1.3 christos case BFD_RELOC_ARC_TLS_LE_32:
1286 1.1.1.3 christos fixP->fx_offset = 0;
1287 1.1.1.3 christos /* Fall through. */
1288 1.1.1.3 christos case BFD_RELOC_ARC_TLS_GD_GOT:
1289 1.1.1.3 christos case BFD_RELOC_ARC_TLS_IE_GOT:
1290 1.1.1.3 christos S_SET_THREAD_LOCAL (fixP->fx_addsy);
1291 1.1.1.3 christos break;
1292 1.1 skrll
1293 1.1.1.3 christos case BFD_RELOC_ARC_TLS_GD_LD:
1294 1.1.1.3 christos gas_assert (!fixP->fx_offset);
1295 1.1.1.3 christos if (fixP->fx_subsy)
1296 1.1.1.3 christos fixP->fx_offset
1297 1.1.1.3 christos = (S_GET_VALUE (fixP->fx_subsy)
1298 1.1.1.3 christos - fixP->fx_frag->fr_address- fixP->fx_where);
1299 1.1.1.3 christos fixP->fx_subsy = NULL;
1300 1.1.1.3 christos /* Fall through. */
1301 1.1.1.3 christos case BFD_RELOC_ARC_TLS_GD_CALL:
1302 1.1.1.3 christos /* These two relocs are there just to allow ld to change the tls
1303 1.1.1.3 christos model for this symbol, by patching the code. The offset -
1304 1.1.1.3 christos and scale, if any - will be installed by the linker. */
1305 1.1.1.3 christos S_SET_THREAD_LOCAL (fixP->fx_addsy);
1306 1.1.1.3 christos break;
1307 1.1.1.3 christos
1308 1.1.1.3 christos case BFD_RELOC_ARC_TLS_LE_S9:
1309 1.1.1.3 christos case BFD_RELOC_ARC_TLS_DTPOFF_S9:
1310 1.1.1.3 christos as_bad (_("TLS_*_S9 relocs are not supported yet"));
1311 1.1.1.3 christos break;
1312 1.1 skrll
1313 1.1.1.3 christos default:
1314 1.1.1.3 christos break;
1315 1.1.1.3 christos }
1316 1.1 skrll
1317 1.1.1.3 christos if (!fixP->fx_done)
1318 1.1 skrll {
1319 1.1.1.3 christos return;
1320 1.1 skrll }
1321 1.1 skrll
1322 1.1.1.3 christos /* Addjust the value if we have a constant. */
1323 1.1.1.3 christos value += fx_offset;
1324 1.1 skrll
1325 1.1.1.3 christos /* For hosts with longs bigger than 32-bits make sure that the top
1326 1.1.1.3 christos bits of a 32-bit negative value read in by the parser are set,
1327 1.1.1.3 christos so that the correct comparisons are made. */
1328 1.1.1.3 christos if (value & 0x80000000)
1329 1.1.1.3 christos value |= (-1L << 31);
1330 1.1.1.3 christos
1331 1.1.1.3 christos reloc = fixP->fx_r_type;
1332 1.1.1.3 christos switch (reloc)
1333 1.1.1.3 christos {
1334 1.1.1.3 christos case BFD_RELOC_8:
1335 1.1.1.3 christos case BFD_RELOC_16:
1336 1.1.1.3 christos case BFD_RELOC_24:
1337 1.1.1.3 christos case BFD_RELOC_32:
1338 1.1.1.3 christos case BFD_RELOC_64:
1339 1.1.1.3 christos case BFD_RELOC_ARC_32_PCREL:
1340 1.1.1.3 christos md_number_to_chars (fixpos, value, fixP->fx_size);
1341 1.1.1.3 christos return;
1342 1.1 skrll
1343 1.1.1.3 christos case BFD_RELOC_ARC_GOTPC32:
1344 1.1.1.3 christos /* I cannot fix an GOTPC relocation because I need to relax it
1345 1.1.1.3 christos from ld rx,[pcl,@sym@gotpc] to add rx,pcl,@sym@gotpc. */
1346 1.1.1.3 christos as_bad (_("Unsupported operation on reloc"));
1347 1.1.1.3 christos return;
1348 1.1.1.3 christos case BFD_RELOC_ARC_GOTOFF:
1349 1.1.1.3 christos case BFD_RELOC_ARC_32_ME:
1350 1.1.1.3 christos case BFD_RELOC_ARC_PC32:
1351 1.1.1.3 christos md_number_to_chars_midend (fixpos, value, fixP->fx_size);
1352 1.1.1.3 christos return;
1353 1.1 skrll
1354 1.1.1.3 christos case BFD_RELOC_ARC_PLT32:
1355 1.1.1.3 christos md_number_to_chars_midend (fixpos, value, fixP->fx_size);
1356 1.1.1.3 christos return;
1357 1.1 skrll
1358 1.1.1.3 christos case BFD_RELOC_ARC_S25H_PCREL_PLT:
1359 1.1.1.3 christos reloc = BFD_RELOC_ARC_S25W_PCREL;
1360 1.1.1.3 christos goto solve_plt;
1361 1.1.1.3 christos
1362 1.1.1.3 christos case BFD_RELOC_ARC_S21H_PCREL_PLT:
1363 1.1.1.3 christos reloc = BFD_RELOC_ARC_S21H_PCREL;
1364 1.1.1.3 christos goto solve_plt;
1365 1.1.1.3 christos
1366 1.1.1.3 christos case BFD_RELOC_ARC_S25W_PCREL_PLT:
1367 1.1.1.3 christos reloc = BFD_RELOC_ARC_S25W_PCREL;
1368 1.1.1.3 christos goto solve_plt;
1369 1.1.1.3 christos
1370 1.1.1.3 christos case BFD_RELOC_ARC_S21W_PCREL_PLT:
1371 1.1.1.3 christos reloc = BFD_RELOC_ARC_S21W_PCREL;
1372 1.1.1.3 christos
1373 1.1.1.3 christos case BFD_RELOC_ARC_S25W_PCREL:
1374 1.1.1.3 christos case BFD_RELOC_ARC_S21W_PCREL:
1375 1.1.1.3 christos case BFD_RELOC_ARC_S21H_PCREL:
1376 1.1.1.3 christos case BFD_RELOC_ARC_S25H_PCREL:
1377 1.1.1.3 christos case BFD_RELOC_ARC_S13_PCREL:
1378 1.1.1.3 christos solve_plt:
1379 1.1.1.3 christos operand = find_operand_for_reloc (reloc);
1380 1.1.1.3 christos gas_assert (operand);
1381 1.1.1.3 christos break;
1382 1.1 skrll
1383 1.1.1.3 christos default:
1384 1.1.1.3 christos {
1385 1.1.1.3 christos if ((int) fixP->fx_r_type >= 0)
1386 1.1.1.3 christos as_fatal (_("unhandled relocation type %s"),
1387 1.1.1.3 christos bfd_get_reloc_code_name (fixP->fx_r_type));
1388 1.1 skrll
1389 1.1.1.3 christos /* The rest of these fixups needs to be completely resolved as
1390 1.1.1.3 christos constants. */
1391 1.1.1.3 christos if (fixP->fx_addsy != 0
1392 1.1.1.3 christos && S_GET_SEGMENT (fixP->fx_addsy) != absolute_section)
1393 1.1.1.3 christos as_bad_where (fixP->fx_file, fixP->fx_line,
1394 1.1.1.3 christos _("non-absolute expression in constant field"));
1395 1.1.1.3 christos
1396 1.1.1.3 christos gas_assert (-(int) fixP->fx_r_type < (int) arc_num_operands);
1397 1.1.1.3 christos operand = &arc_operands[-(int) fixP->fx_r_type];
1398 1.1.1.3 christos break;
1399 1.1.1.3 christos }
1400 1.1.1.3 christos }
1401 1.1.1.3 christos
1402 1.1.1.3 christos if (target_big_endian)
1403 1.1.1.3 christos {
1404 1.1.1.3 christos switch (fixP->fx_size)
1405 1.1 skrll {
1406 1.1.1.3 christos case 4:
1407 1.1.1.3 christos insn = bfd_getb32 (fixpos);
1408 1.1.1.3 christos break;
1409 1.1.1.3 christos case 2:
1410 1.1.1.3 christos insn = bfd_getb16 (fixpos);
1411 1.1.1.3 christos break;
1412 1.1.1.3 christos default:
1413 1.1 skrll as_bad_where (fixP->fx_file, fixP->fx_line,
1414 1.1.1.3 christos _("unknown fixup size"));
1415 1.1 skrll }
1416 1.1 skrll }
1417 1.1 skrll else
1418 1.1 skrll {
1419 1.1.1.3 christos insn = 0;
1420 1.1.1.3 christos switch (fixP->fx_size)
1421 1.1 skrll {
1422 1.1.1.3 christos case 4:
1423 1.1.1.3 christos insn = bfd_getl16 (fixpos) << 16 | bfd_getl16 (fixpos + 2);
1424 1.1 skrll break;
1425 1.1.1.3 christos case 2:
1426 1.1.1.3 christos insn = bfd_getl16 (fixpos);
1427 1.1 skrll break;
1428 1.1 skrll default:
1429 1.1.1.3 christos as_bad_where (fixP->fx_file, fixP->fx_line,
1430 1.1.1.3 christos _("unknown fixup size"));
1431 1.1 skrll }
1432 1.1 skrll }
1433 1.1 skrll
1434 1.1.1.3 christos insn = insert_operand (insn, operand, (offsetT) value,
1435 1.1.1.3 christos fixP->fx_file, fixP->fx_line);
1436 1.1.1.3 christos
1437 1.1.1.3 christos md_number_to_chars_midend (fixpos, insn, fixP->fx_size);
1438 1.1.1.3 christos }
1439 1.1.1.3 christos
1440 1.1.1.3 christos /* Prepare machine-dependent frags for relaxation.
1441 1.1.1.3 christos
1442 1.1.1.3 christos Called just before relaxation starts. Any symbol that is now undefined
1443 1.1.1.3 christos will not become defined.
1444 1.1.1.3 christos
1445 1.1.1.3 christos Return the correct fr_subtype in the frag.
1446 1.1.1.3 christos
1447 1.1.1.3 christos Return the initial "guess for fr_var" to caller. The guess for fr_var
1448 1.1.1.3 christos is *actually* the growth beyond fr_fix. Whatever we do to grow fr_fix
1449 1.1.1.3 christos or fr_var contributes to our returned value.
1450 1.1.1.3 christos
1451 1.1.1.3 christos Although it may not be explicit in the frag, pretend
1452 1.1.1.3 christos fr_var starts with a value. */
1453 1.1.1.3 christos
1454 1.1.1.3 christos int
1455 1.1.1.3 christos md_estimate_size_before_relax (fragS *fragP ATTRIBUTE_UNUSED,
1456 1.1.1.3 christos segT segment ATTRIBUTE_UNUSED)
1457 1.1.1.3 christos {
1458 1.1.1.3 christos int growth = 4;
1459 1.1.1.3 christos
1460 1.1.1.3 christos fragP->fr_var = 4;
1461 1.1.1.3 christos pr_debug ("%s:%d: md_estimate_size_before_relax: %d\n",
1462 1.1.1.3 christos fragP->fr_file, fragP->fr_line, growth);
1463 1.1.1.3 christos
1464 1.1.1.3 christos as_fatal (_("md_estimate_size_before_relax\n"));
1465 1.1.1.3 christos return growth;
1466 1.1.1.3 christos }
1467 1.1.1.3 christos
1468 1.1.1.3 christos /* Translate internal representation of relocation info to BFD target
1469 1.1.1.3 christos format. */
1470 1.1 skrll
1471 1.1 skrll arelent *
1472 1.1 skrll tc_gen_reloc (asection *section ATTRIBUTE_UNUSED,
1473 1.1 skrll fixS *fixP)
1474 1.1 skrll {
1475 1.1 skrll arelent *reloc;
1476 1.1.1.3 christos bfd_reloc_code_real_type code;
1477 1.1 skrll
1478 1.1.1.3 christos reloc = (arelent *) xmalloc (sizeof (* reloc));
1479 1.1.1.2 christos reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
1480 1.1 skrll *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
1481 1.1 skrll reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
1482 1.1.1.3 christos
1483 1.1.1.3 christos /* Make sure none of our internal relocations make it this far.
1484 1.1.1.3 christos They'd better have been fully resolved by this point. */
1485 1.1.1.3 christos gas_assert ((int) fixP->fx_r_type > 0);
1486 1.1.1.3 christos
1487 1.1.1.3 christos code = fixP->fx_r_type;
1488 1.1.1.3 christos
1489 1.1.1.3 christos /* if we have something like add gp, pcl,
1490 1.1.1.3 christos _GLOBAL_OFFSET_TABLE_@gotpc. */
1491 1.1.1.3 christos if (code == BFD_RELOC_ARC_GOTPC32
1492 1.1.1.3 christos && GOT_symbol
1493 1.1.1.3 christos && fixP->fx_addsy == GOT_symbol)
1494 1.1.1.3 christos code = BFD_RELOC_ARC_GOTPC;
1495 1.1.1.3 christos
1496 1.1.1.3 christos reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
1497 1.1.1.3 christos if (reloc->howto == NULL)
1498 1.1 skrll {
1499 1.1 skrll as_bad_where (fixP->fx_file, fixP->fx_line,
1500 1.1.1.3 christos _("cannot represent `%s' relocation in object file"),
1501 1.1.1.3 christos bfd_get_reloc_code_name (code));
1502 1.1 skrll return NULL;
1503 1.1 skrll }
1504 1.1 skrll
1505 1.1.1.3 christos if (!fixP->fx_pcrel != !reloc->howto->pc_relative)
1506 1.1.1.3 christos as_fatal (_("internal error? cannot generate `%s' relocation"),
1507 1.1.1.3 christos bfd_get_reloc_code_name (code));
1508 1.1 skrll
1509 1.1.1.3 christos gas_assert (!fixP->fx_pcrel == !reloc->howto->pc_relative);
1510 1.1 skrll
1511 1.1.1.3 christos if (code == BFD_RELOC_ARC_TLS_DTPOFF
1512 1.1.1.3 christos || code == BFD_RELOC_ARC_TLS_DTPOFF_S9)
1513 1.1.1.3 christos {
1514 1.1.1.3 christos asymbol *sym
1515 1.1.1.3 christos = fixP->fx_subsy ? symbol_get_bfdsym (fixP->fx_subsy) : NULL;
1516 1.1.1.3 christos /* We just want to store a 24 bit index, but we have to wait
1517 1.1.1.3 christos till after write_contents has been called via
1518 1.1.1.3 christos bfd_map_over_sections before we can get the index from
1519 1.1.1.3 christos _bfd_elf_symbol_from_bfd_symbol. Thus, the write_relocs
1520 1.1.1.3 christos function is elf32-arc.c has to pick up the slack.
1521 1.1.1.3 christos Unfortunately, this leads to problems with hosts that have
1522 1.1.1.3 christos pointers wider than long (bfd_vma). There would be various
1523 1.1.1.3 christos ways to handle this, all error-prone :-( */
1524 1.1.1.3 christos reloc->addend = (bfd_vma) sym;
1525 1.1.1.3 christos if ((asymbol *) reloc->addend != sym)
1526 1.1.1.3 christos {
1527 1.1.1.3 christos as_bad ("Can't store pointer\n");
1528 1.1.1.3 christos return NULL;
1529 1.1.1.3 christos }
1530 1.1.1.3 christos }
1531 1.1.1.3 christos else
1532 1.1.1.3 christos reloc->addend = fixP->fx_offset;
1533 1.1 skrll
1534 1.1 skrll return reloc;
1535 1.1 skrll }
1536 1.1 skrll
1537 1.1.1.3 christos /* Perform post-processing of machine-dependent frags after relaxation.
1538 1.1.1.3 christos Called after relaxation is finished.
1539 1.1.1.3 christos In: Address of frag.
1540 1.1.1.3 christos fr_type == rs_machine_dependent.
1541 1.1.1.3 christos fr_subtype is what the address relaxed to.
1542 1.1.1.3 christos
1543 1.1.1.3 christos Out: Any fixS:s and constants are set up. */
1544 1.1.1.3 christos
1545 1.1.1.3 christos void
1546 1.1.1.3 christos md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
1547 1.1.1.3 christos segT segment ATTRIBUTE_UNUSED,
1548 1.1.1.3 christos fragS *fragP ATTRIBUTE_UNUSED)
1549 1.1 skrll {
1550 1.1.1.3 christos pr_debug ("%s:%d: md_convert_frag, subtype: %d, fix: %d, var: %d\n",
1551 1.1.1.3 christos fragP->fr_file, fragP->fr_line,
1552 1.1.1.3 christos fragP->fr_subtype, fragP->fr_fix, fragP->fr_var);
1553 1.1.1.3 christos abort ();
1554 1.1.1.3 christos }
1555 1.1.1.3 christos
1556 1.1.1.3 christos /* We have no need to default values of symbols. We could catch
1557 1.1.1.3 christos register names here, but that is handled by inserting them all in
1558 1.1.1.3 christos the symbol table to begin with. */
1559 1.1.1.3 christos
1560 1.1.1.3 christos symbolS *
1561 1.1.1.3 christos md_undefined_symbol (char *name)
1562 1.1.1.3 christos {
1563 1.1.1.3 christos /* The arc abi demands that a GOT[0] should be referencible as
1564 1.1.1.3 christos [pc+_DYNAMIC@gotpc]. Hence we convert a _DYNAMIC@gotpc to a
1565 1.1.1.3 christos GOTPC reference to _GLOBAL_OFFSET_TABLE_. */
1566 1.1.1.3 christos if (((*name == '_')
1567 1.1.1.3 christos && (*(name+1) == 'G')
1568 1.1.1.3 christos && (strcmp (name, GLOBAL_OFFSET_TABLE_NAME) == 0))
1569 1.1.1.3 christos || ((*name == '_')
1570 1.1.1.3 christos && (*(name+1) == 'D')
1571 1.1.1.3 christos && (strcmp (name, DYNAMIC_STRUCT_NAME) == 0)))
1572 1.1.1.3 christos {
1573 1.1.1.3 christos if (!GOT_symbol)
1574 1.1.1.3 christos {
1575 1.1.1.3 christos if (symbol_find (name))
1576 1.1.1.3 christos as_bad ("GOT already in symbol table");
1577 1.1.1.3 christos
1578 1.1.1.3 christos GOT_symbol = symbol_new (GLOBAL_OFFSET_TABLE_NAME, undefined_section,
1579 1.1.1.3 christos (valueT) 0, &zero_address_frag);
1580 1.1.1.3 christos };
1581 1.1.1.3 christos return GOT_symbol;
1582 1.1.1.3 christos }
1583 1.1.1.3 christos return NULL;
1584 1.1.1.3 christos }
1585 1.1.1.3 christos
1586 1.1.1.3 christos /* Turn a string in input_line_pointer into a floating point constant
1587 1.1.1.3 christos of type type, and store the appropriate bytes in *litP. The number
1588 1.1.1.3 christos of LITTLENUMS emitted is stored in *sizeP. An error message is
1589 1.1.1.3 christos returned, or NULL on OK. */
1590 1.1 skrll
1591 1.1.1.3 christos char *
1592 1.1.1.3 christos md_atof (int type, char *litP, int *sizeP)
1593 1.1.1.3 christos {
1594 1.1.1.3 christos return ieee_md_atof (type, litP, sizeP, target_big_endian);
1595 1.1.1.3 christos }
1596 1.1.1.3 christos
1597 1.1.1.3 christos /* Called for any expression that can not be recognized. When the
1598 1.1.1.3 christos function is called, `input_line_pointer' will point to the start of
1599 1.1.1.3 christos the expression. */
1600 1.1 skrll
1601 1.1 skrll void
1602 1.1.1.3 christos md_operand (expressionS *expressionP ATTRIBUTE_UNUSED)
1603 1.1 skrll {
1604 1.1.1.3 christos char *p = input_line_pointer;
1605 1.1.1.3 christos if (*p == '@')
1606 1.1.1.3 christos {
1607 1.1.1.3 christos input_line_pointer++;
1608 1.1.1.3 christos expressionP->X_op = O_symbol;
1609 1.1.1.3 christos expression (expressionP);
1610 1.1.1.3 christos }
1611 1.1.1.3 christos }
1612 1.1 skrll
1613 1.1.1.3 christos /* This function is called from the function 'expression', it attempts
1614 1.1.1.3 christos to parse special names (in our case register names). It fills in
1615 1.1.1.3 christos the expression with the identified register. It returns TRUE if
1616 1.1.1.3 christos it is a register and FALSE otherwise. */
1617 1.1.1.3 christos
1618 1.1.1.3 christos bfd_boolean
1619 1.1.1.3 christos arc_parse_name (const char *name,
1620 1.1.1.3 christos struct expressionS *e)
1621 1.1.1.3 christos {
1622 1.1.1.3 christos struct symbol *sym;
1623 1.1.1.3 christos
1624 1.1.1.3 christos if (!assembling_insn)
1625 1.1.1.3 christos return FALSE;
1626 1.1.1.3 christos
1627 1.1.1.3 christos /* Handle only registers. */
1628 1.1.1.3 christos if (e->X_op != O_absent)
1629 1.1.1.3 christos return FALSE;
1630 1.1.1.3 christos
1631 1.1.1.3 christos sym = hash_find (arc_reg_hash, name);
1632 1.1.1.3 christos if (sym)
1633 1.1.1.3 christos {
1634 1.1.1.3 christos e->X_op = O_register;
1635 1.1.1.3 christos e->X_add_number = S_GET_VALUE (sym);
1636 1.1.1.3 christos return TRUE;
1637 1.1.1.3 christos }
1638 1.1.1.3 christos return FALSE;
1639 1.1.1.3 christos }
1640 1.1.1.3 christos
1641 1.1.1.3 christos /* md_parse_option
1642 1.1.1.3 christos Invocation line includes a switch not recognized by the base assembler.
1643 1.1.1.3 christos See if it's a processor-specific option.
1644 1.1.1.3 christos
1645 1.1.1.3 christos New options (supported) are:
1646 1.1.1.3 christos
1647 1.1.1.3 christos -mcpu=<cpu name> Assemble for selected processor
1648 1.1.1.3 christos -EB/-mbig-endian Big-endian
1649 1.1.1.3 christos -EL/-mlittle-endian Little-endian
1650 1.1.1.3 christos
1651 1.1.1.3 christos The following CPU names are recognized:
1652 1.1.1.3 christos arc700, av2em, av2hs. */
1653 1.1.1.3 christos
1654 1.1.1.3 christos int
1655 1.1.1.3 christos md_parse_option (int c, char *arg ATTRIBUTE_UNUSED)
1656 1.1.1.3 christos {
1657 1.1.1.3 christos int cpu_flags = EF_ARC_CPU_GENERIC;
1658 1.1.1.3 christos
1659 1.1.1.3 christos switch (c)
1660 1.1.1.3 christos {
1661 1.1.1.3 christos case OPTION_ARC600:
1662 1.1.1.3 christos case OPTION_ARC601:
1663 1.1.1.3 christos return md_parse_option (OPTION_MCPU, "arc600");
1664 1.1.1.3 christos
1665 1.1.1.3 christos case OPTION_ARC700:
1666 1.1.1.3 christos return md_parse_option (OPTION_MCPU, "arc700");
1667 1.1.1.3 christos
1668 1.1.1.3 christos case OPTION_ARCEM:
1669 1.1.1.3 christos return md_parse_option (OPTION_MCPU, "arcem");
1670 1.1.1.3 christos
1671 1.1.1.3 christos case OPTION_ARCHS:
1672 1.1.1.3 christos return md_parse_option (OPTION_MCPU, "archs");
1673 1.1.1.3 christos
1674 1.1.1.3 christos case OPTION_MCPU:
1675 1.1.1.3 christos {
1676 1.1.1.3 christos int i;
1677 1.1.1.3 christos char *s = alloca (strlen (arg) + 1);
1678 1.1 skrll
1679 1.1 skrll {
1680 1.1.1.3 christos char *t = s;
1681 1.1.1.3 christos char *arg1 = arg;
1682 1.1 skrll
1683 1.1.1.3 christos do
1684 1.1.1.3 christos *t = TOLOWER (*arg1++);
1685 1.1.1.3 christos while (*t++);
1686 1.1.1.3 christos }
1687 1.1.1.3 christos
1688 1.1.1.3 christos for (i = 0; cpu_types[i].name; ++i)
1689 1.1.1.3 christos {
1690 1.1.1.3 christos if (!strcmp (cpu_types[i].name, s))
1691 1.1.1.3 christos {
1692 1.1.1.3 christos arc_target = cpu_types[i].flags;
1693 1.1.1.3 christos arc_target_name = cpu_types[i].name;
1694 1.1.1.3 christos arc_features = cpu_types[i].features;
1695 1.1.1.3 christos arc_mach_type = cpu_types[i].mach;
1696 1.1.1.3 christos cpu_flags = cpu_types[i].eflags;
1697 1.1.1.3 christos
1698 1.1.1.3 christos mach_type_specified_p = 1;
1699 1.1 skrll break;
1700 1.1.1.3 christos }
1701 1.1.1.3 christos }
1702 1.1 skrll
1703 1.1.1.3 christos if (!cpu_types[i].name)
1704 1.1.1.3 christos {
1705 1.1.1.3 christos as_fatal (_("unknown architecture: %s\n"), arg);
1706 1.1.1.3 christos }
1707 1.1.1.3 christos break;
1708 1.1.1.3 christos }
1709 1.1 skrll
1710 1.1.1.3 christos case OPTION_EB:
1711 1.1.1.3 christos arc_target_format = "elf32-bigarc";
1712 1.1.1.3 christos byte_order = BIG_ENDIAN;
1713 1.1.1.3 christos break;
1714 1.1 skrll
1715 1.1.1.3 christos case OPTION_EL:
1716 1.1.1.3 christos arc_target_format = "elf32-littlearc";
1717 1.1.1.3 christos byte_order = LITTLE_ENDIAN;
1718 1.1.1.3 christos break;
1719 1.1 skrll
1720 1.1.1.3 christos case OPTION_CD:
1721 1.1.1.3 christos /* This option has an effect only on ARC EM. */
1722 1.1.1.3 christos if (arc_target & ARC_OPCODE_ARCv2EM)
1723 1.1.1.3 christos arc_features |= ARC_CD;
1724 1.1.1.3 christos break;
1725 1.1 skrll
1726 1.1.1.3 christos case OPTION_USER_MODE:
1727 1.1.1.3 christos case OPTION_LD_EXT_MASK:
1728 1.1.1.3 christos case OPTION_SWAP:
1729 1.1.1.3 christos case OPTION_NORM:
1730 1.1.1.3 christos case OPTION_BARREL_SHIFT:
1731 1.1.1.3 christos case OPTION_MIN_MAX:
1732 1.1.1.3 christos case OPTION_NO_MPY:
1733 1.1.1.3 christos case OPTION_EA:
1734 1.1.1.3 christos case OPTION_MUL64:
1735 1.1.1.3 christos case OPTION_SIMD:
1736 1.1.1.3 christos case OPTION_SPFP:
1737 1.1.1.3 christos case OPTION_DPFP:
1738 1.1.1.3 christos case OPTION_XMAC_D16:
1739 1.1.1.3 christos case OPTION_XMAC_24:
1740 1.1.1.3 christos case OPTION_DSP_PACKA:
1741 1.1.1.3 christos case OPTION_CRC:
1742 1.1.1.3 christos case OPTION_DVBF:
1743 1.1.1.3 christos case OPTION_TELEPHONY:
1744 1.1.1.3 christos case OPTION_XYMEMORY:
1745 1.1.1.3 christos case OPTION_LOCK:
1746 1.1.1.3 christos case OPTION_SWAPE:
1747 1.1.1.3 christos case OPTION_RTSC:
1748 1.1.1.3 christos case OPTION_FPUDA:
1749 1.1.1.3 christos /* Dummy options. */
1750 1.1 skrll
1751 1.1.1.3 christos default:
1752 1.1.1.3 christos return 0;
1753 1.1.1.3 christos }
1754 1.1 skrll
1755 1.1.1.3 christos if (cpu_flags != EF_ARC_CPU_GENERIC)
1756 1.1.1.3 christos arc_eflag = (arc_eflag & ~EF_ARC_MACH_MSK) | cpu_flags;
1757 1.1 skrll
1758 1.1.1.3 christos return 1;
1759 1.1.1.3 christos }
1760 1.1.1.3 christos
1761 1.1.1.3 christos void
1762 1.1.1.3 christos md_show_usage (FILE *stream)
1763 1.1.1.3 christos {
1764 1.1.1.3 christos fprintf (stream, _("ARC-specific assembler options:\n"));
1765 1.1.1.3 christos
1766 1.1.1.3 christos fprintf (stream, " -mcpu=<cpu name>\t assemble for CPU <cpu name>\n");
1767 1.1.1.3 christos fprintf (stream,
1768 1.1.1.3 christos " -mcode-density\t enable code density option for ARC EM\n");
1769 1.1.1.3 christos
1770 1.1.1.3 christos fprintf (stream, _("\
1771 1.1.1.3 christos -EB assemble code for a big-endian cpu\n"));
1772 1.1.1.3 christos fprintf (stream, _("\
1773 1.1.1.3 christos -EL assemble code for a little-endian cpu\n"));
1774 1.1.1.3 christos }
1775 1.1.1.3 christos
1776 1.1.1.3 christos static void
1777 1.1.1.3 christos preprocess_operands (const struct arc_opcode *opcode,
1778 1.1.1.3 christos expressionS *tok,
1779 1.1.1.3 christos int ntok)
1780 1.1.1.3 christos {
1781 1.1.1.3 christos int i;
1782 1.1.1.3 christos size_t len;
1783 1.1.1.3 christos const char *p;
1784 1.1.1.3 christos unsigned j;
1785 1.1.1.3 christos const struct arc_aux_reg *auxr;
1786 1.1.1.3 christos
1787 1.1.1.3 christos for (i = 0; i < ntok; i++)
1788 1.1.1.3 christos {
1789 1.1.1.3 christos switch (tok[i].X_op)
1790 1.1.1.3 christos {
1791 1.1.1.3 christos case O_illegal:
1792 1.1.1.3 christos case O_absent:
1793 1.1.1.3 christos break; /* Throw and error. */
1794 1.1.1.3 christos
1795 1.1.1.3 christos case O_symbol:
1796 1.1.1.3 christos if (opcode->class != AUXREG)
1797 1.1.1.3 christos break;
1798 1.1.1.3 christos /* Convert the symbol to a constant if possible. */
1799 1.1.1.3 christos p = S_GET_NAME (tok[i].X_add_symbol);
1800 1.1.1.3 christos len = strlen (p);
1801 1.1.1.3 christos
1802 1.1.1.3 christos auxr = &arc_aux_regs[0];
1803 1.1.1.3 christos for (j = 0; j < arc_num_aux_regs; j++, auxr++)
1804 1.1.1.3 christos if (len == auxr->length
1805 1.1.1.3 christos && strcasecmp (auxr->name, p) == 0)
1806 1.1.1.3 christos {
1807 1.1.1.3 christos tok[i].X_op = O_constant;
1808 1.1.1.3 christos tok[i].X_add_number = auxr->address;
1809 1.1.1.3 christos break;
1810 1.1.1.3 christos }
1811 1.1.1.3 christos break;
1812 1.1.1.3 christos default:
1813 1.1.1.3 christos break;
1814 1.1 skrll }
1815 1.1.1.3 christos }
1816 1.1.1.3 christos }
1817 1.1.1.3 christos
1818 1.1.1.3 christos /* Given an opcode name, pre-tockenized set of argumenst and the
1819 1.1.1.3 christos opcode flags, take it all the way through emission. */
1820 1.1.1.3 christos
1821 1.1.1.3 christos static void
1822 1.1.1.3 christos assemble_tokens (const char *opname,
1823 1.1.1.3 christos expressionS *tok,
1824 1.1.1.3 christos int ntok,
1825 1.1.1.3 christos struct arc_flags *pflags,
1826 1.1.1.3 christos int nflgs)
1827 1.1.1.3 christos {
1828 1.1.1.3 christos bfd_boolean found_something = FALSE;
1829 1.1.1.3 christos const struct arc_opcode *opcode;
1830 1.1.1.3 christos int cpumatch = 1;
1831 1.1.1.3 christos
1832 1.1.1.3 christos /* Search opcodes. */
1833 1.1.1.3 christos opcode = (const struct arc_opcode *) hash_find (arc_opcode_hash, opname);
1834 1.1.1.3 christos
1835 1.1.1.3 christos /* Couldn't find opcode conventional way, try special cases. */
1836 1.1.1.3 christos if (!opcode)
1837 1.1.1.3 christos opcode = find_special_case (opname, &nflgs, pflags, tok, &ntok);
1838 1.1 skrll
1839 1.1.1.3 christos if (opcode)
1840 1.1.1.3 christos {
1841 1.1.1.3 christos pr_debug ("%s:%d: assemble_tokens: %s trying opcode 0x%08X\n",
1842 1.1.1.3 christos frag_now->fr_file, frag_now->fr_line, opcode->name,
1843 1.1.1.3 christos opcode->opcode);
1844 1.1.1.3 christos
1845 1.1.1.3 christos preprocess_operands (opcode, tok, ntok);
1846 1.1.1.3 christos
1847 1.1.1.3 christos found_something = TRUE;
1848 1.1.1.3 christos opcode = find_opcode_match (opcode, tok, &ntok, pflags, nflgs, &cpumatch);
1849 1.1.1.3 christos if (opcode)
1850 1.1 skrll {
1851 1.1.1.3 christos struct arc_insn insn;
1852 1.1.1.3 christos assemble_insn (opcode, tok, ntok, pflags, nflgs, &insn);
1853 1.1.1.3 christos emit_insn (&insn);
1854 1.1.1.3 christos return;
1855 1.1.1.3 christos }
1856 1.1.1.3 christos }
1857 1.1.1.3 christos
1858 1.1.1.3 christos if (found_something)
1859 1.1.1.3 christos {
1860 1.1.1.3 christos if (cpumatch)
1861 1.1.1.3 christos as_bad (_("inappropriate arguments for opcode '%s'"), opname);
1862 1.1.1.3 christos else
1863 1.1.1.3 christos as_bad (_("opcode '%s' not supported for target %s"), opname,
1864 1.1.1.3 christos arc_target_name);
1865 1.1.1.3 christos }
1866 1.1.1.3 christos else
1867 1.1.1.3 christos as_bad (_("unknown opcode '%s'"), opname);
1868 1.1.1.3 christos }
1869 1.1 skrll
1870 1.1.1.3 christos /* Used to find special case opcode. */
1871 1.1 skrll
1872 1.1.1.3 christos static const struct arc_opcode *
1873 1.1.1.3 christos find_special_case (const char *opname,
1874 1.1.1.3 christos int *nflgs,
1875 1.1.1.3 christos struct arc_flags *pflags,
1876 1.1.1.3 christos expressionS *tok,
1877 1.1.1.3 christos int *ntok)
1878 1.1.1.3 christos {
1879 1.1.1.3 christos const struct arc_opcode *opcode;
1880 1.1 skrll
1881 1.1.1.3 christos opcode = find_special_case_pseudo (opname, ntok, tok, nflgs, pflags);
1882 1.1 skrll
1883 1.1.1.3 christos if (opcode == NULL)
1884 1.1.1.3 christos opcode = find_special_case_flag (opname, nflgs, pflags);
1885 1.1 skrll
1886 1.1.1.3 christos return opcode;
1887 1.1.1.3 christos }
1888 1.1 skrll
1889 1.1.1.3 christos /* Swap operand tokens. */
1890 1.1 skrll
1891 1.1.1.3 christos static void
1892 1.1.1.3 christos swap_operand (expressionS *operand_array,
1893 1.1.1.3 christos unsigned source,
1894 1.1.1.3 christos unsigned destination)
1895 1.1.1.3 christos {
1896 1.1.1.3 christos expressionS cpy_operand;
1897 1.1.1.3 christos expressionS *src_operand;
1898 1.1.1.3 christos expressionS *dst_operand;
1899 1.1.1.3 christos size_t size;
1900 1.1 skrll
1901 1.1.1.3 christos if (source == destination)
1902 1.1.1.3 christos return;
1903 1.1.1.3 christos
1904 1.1.1.3 christos src_operand = &operand_array[source];
1905 1.1.1.3 christos dst_operand = &operand_array[destination];
1906 1.1.1.3 christos size = sizeof (expressionS);
1907 1.1.1.3 christos
1908 1.1.1.3 christos /* Make copy of operand to swap with and swap. */
1909 1.1.1.3 christos memcpy (&cpy_operand, dst_operand, size);
1910 1.1.1.3 christos memcpy (dst_operand, src_operand, size);
1911 1.1.1.3 christos memcpy (src_operand, &cpy_operand, size);
1912 1.1.1.3 christos }
1913 1.1 skrll
1914 1.1.1.3 christos /* Check if *op matches *tok type.
1915 1.1.1.3 christos Returns FALSE if they don't match, TRUE if they match. */
1916 1.1.1.3 christos
1917 1.1.1.3 christos static bfd_boolean
1918 1.1.1.3 christos pseudo_operand_match (const expressionS *tok,
1919 1.1.1.3 christos const struct arc_operand_operation *op)
1920 1.1.1.3 christos {
1921 1.1.1.3 christos offsetT min, max, val;
1922 1.1.1.3 christos bfd_boolean ret;
1923 1.1.1.3 christos const struct arc_operand *operand_real = &arc_operands[op->operand_idx];
1924 1.1.1.3 christos
1925 1.1.1.3 christos ret = FALSE;
1926 1.1.1.3 christos switch (tok->X_op)
1927 1.1.1.3 christos {
1928 1.1.1.3 christos case O_constant:
1929 1.1.1.3 christos if (operand_real->bits == 32 && (operand_real->flags & ARC_OPERAND_LIMM))
1930 1.1.1.3 christos ret = 1;
1931 1.1.1.3 christos else if (!(operand_real->flags & ARC_OPERAND_IR))
1932 1.1.1.3 christos {
1933 1.1.1.3 christos val = tok->X_add_number;
1934 1.1.1.3 christos if (operand_real->flags & ARC_OPERAND_SIGNED)
1935 1.1 skrll {
1936 1.1.1.3 christos max = (1 << (operand_real->bits - 1)) - 1;
1937 1.1.1.3 christos min = -(1 << (operand_real->bits - 1));
1938 1.1 skrll }
1939 1.1 skrll else
1940 1.1 skrll {
1941 1.1.1.3 christos max = (1 << operand_real->bits) - 1;
1942 1.1.1.3 christos min = 0;
1943 1.1 skrll }
1944 1.1.1.3 christos if (min <= val && val <= max)
1945 1.1.1.3 christos ret = TRUE;
1946 1.1.1.3 christos }
1947 1.1.1.3 christos break;
1948 1.1 skrll
1949 1.1.1.3 christos case O_symbol:
1950 1.1.1.3 christos /* Handle all symbols as long immediates or signed 9. */
1951 1.1.1.3 christos if (operand_real->flags & ARC_OPERAND_LIMM ||
1952 1.1.1.3 christos ((operand_real->flags & ARC_OPERAND_SIGNED) && operand_real->bits == 9))
1953 1.1.1.3 christos ret = TRUE;
1954 1.1.1.3 christos break;
1955 1.1 skrll
1956 1.1.1.3 christos case O_register:
1957 1.1.1.3 christos if (operand_real->flags & ARC_OPERAND_IR)
1958 1.1.1.3 christos ret = TRUE;
1959 1.1.1.3 christos break;
1960 1.1.1.3 christos
1961 1.1.1.3 christos case O_bracket:
1962 1.1.1.3 christos if (operand_real->flags & ARC_OPERAND_BRAKET)
1963 1.1.1.3 christos ret = TRUE;
1964 1.1.1.3 christos break;
1965 1.1.1.3 christos
1966 1.1.1.3 christos default:
1967 1.1.1.3 christos /* Unknown. */
1968 1.1.1.3 christos break;
1969 1.1.1.3 christos }
1970 1.1.1.3 christos return ret;
1971 1.1.1.3 christos }
1972 1.1.1.3 christos
1973 1.1.1.3 christos /* Find pseudo instruction in array. */
1974 1.1.1.3 christos
1975 1.1.1.3 christos static const struct arc_pseudo_insn *
1976 1.1.1.3 christos find_pseudo_insn (const char *opname,
1977 1.1.1.3 christos int ntok,
1978 1.1.1.3 christos const expressionS *tok)
1979 1.1.1.3 christos {
1980 1.1.1.3 christos const struct arc_pseudo_insn *pseudo_insn = NULL;
1981 1.1.1.3 christos const struct arc_operand_operation *op;
1982 1.1.1.3 christos unsigned int i;
1983 1.1.1.3 christos int j;
1984 1.1.1.3 christos
1985 1.1.1.3 christos for (i = 0; i < arc_num_pseudo_insn; ++i)
1986 1.1.1.3 christos {
1987 1.1.1.3 christos pseudo_insn = &arc_pseudo_insns[i];
1988 1.1.1.3 christos if (strcmp (pseudo_insn->mnemonic_p, opname) == 0)
1989 1.1.1.3 christos {
1990 1.1.1.3 christos op = pseudo_insn->operand;
1991 1.1.1.3 christos for (j = 0; j < ntok; ++j)
1992 1.1.1.3 christos if (!pseudo_operand_match (&tok[j], &op[j]))
1993 1.1.1.3 christos break;
1994 1.1.1.3 christos
1995 1.1.1.3 christos /* Found the right instruction. */
1996 1.1.1.3 christos if (j == ntok)
1997 1.1.1.3 christos return pseudo_insn;
1998 1.1 skrll }
1999 1.1 skrll }
2000 1.1.1.3 christos return NULL;
2001 1.1.1.3 christos }
2002 1.1 skrll
2003 1.1.1.3 christos /* Assumes the expressionS *tok is of sufficient size. */
2004 1.1.1.3 christos
2005 1.1.1.3 christos static const struct arc_opcode *
2006 1.1.1.3 christos find_special_case_pseudo (const char *opname,
2007 1.1.1.3 christos int *ntok,
2008 1.1.1.3 christos expressionS *tok,
2009 1.1.1.3 christos int *nflgs,
2010 1.1.1.3 christos struct arc_flags *pflags)
2011 1.1.1.3 christos {
2012 1.1.1.3 christos const struct arc_pseudo_insn *pseudo_insn = NULL;
2013 1.1.1.3 christos const struct arc_operand_operation *operand_pseudo;
2014 1.1.1.3 christos const struct arc_operand *operand_real;
2015 1.1.1.3 christos unsigned i;
2016 1.1.1.3 christos char construct_operand[MAX_CONSTR_STR];
2017 1.1.1.3 christos
2018 1.1.1.3 christos /* Find whether opname is in pseudo instruction array. */
2019 1.1.1.3 christos pseudo_insn = find_pseudo_insn (opname, *ntok, tok);
2020 1.1.1.3 christos
2021 1.1.1.3 christos if (pseudo_insn == NULL)
2022 1.1.1.3 christos return NULL;
2023 1.1.1.3 christos
2024 1.1.1.3 christos /* Handle flag, Limited to one flag at the moment. */
2025 1.1.1.3 christos if (pseudo_insn->flag_r != NULL)
2026 1.1.1.3 christos *nflgs += tokenize_flags (pseudo_insn->flag_r, &pflags[*nflgs],
2027 1.1.1.3 christos MAX_INSN_FLGS - *nflgs);
2028 1.1.1.3 christos
2029 1.1.1.3 christos /* Handle operand operations. */
2030 1.1.1.3 christos for (i = 0; i < pseudo_insn->operand_cnt; ++i)
2031 1.1.1.3 christos {
2032 1.1.1.3 christos operand_pseudo = &pseudo_insn->operand[i];
2033 1.1.1.3 christos operand_real = &arc_operands[operand_pseudo->operand_idx];
2034 1.1.1.3 christos
2035 1.1.1.3 christos if (operand_real->flags & ARC_OPERAND_BRAKET &&
2036 1.1.1.3 christos !operand_pseudo->needs_insert)
2037 1.1.1.3 christos continue;
2038 1.1.1.3 christos
2039 1.1.1.3 christos /* Has to be inserted (i.e. this token does not exist yet). */
2040 1.1.1.3 christos if (operand_pseudo->needs_insert)
2041 1.1.1.3 christos {
2042 1.1.1.3 christos if (operand_real->flags & ARC_OPERAND_BRAKET)
2043 1.1.1.3 christos {
2044 1.1.1.3 christos tok[i].X_op = O_bracket;
2045 1.1.1.3 christos ++(*ntok);
2046 1.1.1.3 christos continue;
2047 1.1.1.3 christos }
2048 1.1.1.3 christos
2049 1.1.1.3 christos /* Check if operand is a register or constant and handle it
2050 1.1.1.3 christos by type. */
2051 1.1.1.3 christos if (operand_real->flags & ARC_OPERAND_IR)
2052 1.1.1.3 christos snprintf (construct_operand, MAX_CONSTR_STR, "r%d",
2053 1.1.1.3 christos operand_pseudo->count);
2054 1.1.1.3 christos else
2055 1.1.1.3 christos snprintf (construct_operand, MAX_CONSTR_STR, "%d",
2056 1.1.1.3 christos operand_pseudo->count);
2057 1.1.1.3 christos
2058 1.1.1.3 christos tokenize_arguments (construct_operand, &tok[i], 1);
2059 1.1.1.3 christos ++(*ntok);
2060 1.1.1.3 christos }
2061 1.1.1.3 christos
2062 1.1.1.3 christos else if (operand_pseudo->count)
2063 1.1.1.3 christos {
2064 1.1.1.3 christos /* Operand number has to be adjusted accordingly (by operand
2065 1.1.1.3 christos type). */
2066 1.1.1.3 christos switch (tok[i].X_op)
2067 1.1.1.3 christos {
2068 1.1.1.3 christos case O_constant:
2069 1.1.1.3 christos tok[i].X_add_number += operand_pseudo->count;
2070 1.1.1.3 christos break;
2071 1.1.1.3 christos
2072 1.1.1.3 christos case O_symbol:
2073 1.1.1.3 christos break;
2074 1.1.1.3 christos
2075 1.1.1.3 christos default:
2076 1.1.1.3 christos /* Ignored. */
2077 1.1.1.3 christos break;
2078 1.1.1.3 christos }
2079 1.1.1.3 christos }
2080 1.1.1.3 christos }
2081 1.1.1.3 christos
2082 1.1.1.3 christos /* Swap operands if necessary. Only supports one swap at the
2083 1.1.1.3 christos moment. */
2084 1.1.1.3 christos for (i = 0; i < pseudo_insn->operand_cnt; ++i)
2085 1.1.1.3 christos {
2086 1.1.1.3 christos operand_pseudo = &pseudo_insn->operand[i];
2087 1.1.1.3 christos
2088 1.1.1.3 christos if (operand_pseudo->swap_operand_idx == i)
2089 1.1.1.3 christos continue;
2090 1.1.1.3 christos
2091 1.1.1.3 christos swap_operand (tok, i, operand_pseudo->swap_operand_idx);
2092 1.1.1.3 christos
2093 1.1.1.3 christos /* Prevent a swap back later by breaking out. */
2094 1.1.1.3 christos break;
2095 1.1.1.3 christos }
2096 1.1.1.3 christos
2097 1.1.1.3 christos return (const struct arc_opcode *)
2098 1.1.1.3 christos hash_find (arc_opcode_hash, pseudo_insn->mnemonic_r);
2099 1.1.1.3 christos }
2100 1.1.1.3 christos
2101 1.1.1.3 christos static const struct arc_opcode *
2102 1.1.1.3 christos find_special_case_flag (const char *opname,
2103 1.1.1.3 christos int *nflgs,
2104 1.1.1.3 christos struct arc_flags *pflags)
2105 1.1.1.3 christos {
2106 1.1.1.3 christos unsigned int i;
2107 1.1.1.3 christos const char *flagnm;
2108 1.1.1.3 christos unsigned flag_idx, flag_arr_idx;
2109 1.1.1.3 christos size_t flaglen, oplen;
2110 1.1.1.3 christos const struct arc_flag_special *arc_flag_special_opcode;
2111 1.1.1.3 christos const struct arc_opcode *opcode;
2112 1.1.1.3 christos
2113 1.1.1.3 christos /* Search for special case instruction. */
2114 1.1.1.3 christos for (i = 0; i < arc_num_flag_special; i++)
2115 1.1.1.3 christos {
2116 1.1.1.3 christos arc_flag_special_opcode = &arc_flag_special_cases[i];
2117 1.1.1.3 christos oplen = strlen (arc_flag_special_opcode->name);
2118 1.1.1.3 christos
2119 1.1.1.3 christos if (strncmp (opname, arc_flag_special_opcode->name, oplen) != 0)
2120 1.1.1.3 christos continue;
2121 1.1.1.3 christos
2122 1.1.1.3 christos /* Found a potential special case instruction, now test for
2123 1.1.1.3 christos flags. */
2124 1.1.1.3 christos for (flag_arr_idx = 0;; ++flag_arr_idx)
2125 1.1.1.3 christos {
2126 1.1.1.3 christos flag_idx = arc_flag_special_opcode->flags[flag_arr_idx];
2127 1.1.1.3 christos if (flag_idx == 0)
2128 1.1.1.3 christos break; /* End of array, nothing found. */
2129 1.1.1.3 christos
2130 1.1.1.3 christos flagnm = arc_flag_operands[flag_idx].name;
2131 1.1.1.3 christos flaglen = strlen (flagnm);
2132 1.1.1.3 christos if (strcmp (opname + oplen, flagnm) == 0)
2133 1.1.1.3 christos {
2134 1.1.1.3 christos opcode = (const struct arc_opcode *)
2135 1.1.1.3 christos hash_find (arc_opcode_hash,
2136 1.1.1.3 christos arc_flag_special_opcode->name);
2137 1.1.1.3 christos
2138 1.1.1.3 christos if (*nflgs + 1 > MAX_INSN_FLGS)
2139 1.1.1.3 christos break;
2140 1.1.1.3 christos memcpy (pflags[*nflgs].name, flagnm, flaglen);
2141 1.1.1.3 christos pflags[*nflgs].name[flaglen] = '\0';
2142 1.1.1.3 christos (*nflgs)++;
2143 1.1.1.3 christos return opcode;
2144 1.1.1.3 christos }
2145 1.1.1.3 christos }
2146 1.1.1.3 christos }
2147 1.1.1.3 christos return NULL;
2148 1.1.1.3 christos }
2149 1.1.1.3 christos
2150 1.1.1.3 christos /* Check whether a symbol involves a register. */
2151 1.1.1.3 christos
2152 1.1.1.3 christos static int
2153 1.1.1.3 christos contains_register (symbolS *sym)
2154 1.1.1.3 christos {
2155 1.1.1.3 christos if (sym)
2156 1.1.1.3 christos {
2157 1.1.1.3 christos expressionS *ex = symbol_get_value_expression (sym);
2158 1.1.1.3 christos return ((O_register == ex->X_op)
2159 1.1.1.3 christos && !contains_register (ex->X_add_symbol)
2160 1.1.1.3 christos && !contains_register (ex->X_op_symbol));
2161 1.1.1.3 christos }
2162 1.1.1.3 christos else
2163 1.1.1.3 christos return 0;
2164 1.1.1.3 christos }
2165 1.1.1.3 christos
2166 1.1.1.3 christos /* Returns the register number within a symbol. */
2167 1.1.1.3 christos
2168 1.1.1.3 christos static int
2169 1.1.1.3 christos get_register (symbolS *sym)
2170 1.1.1.3 christos {
2171 1.1.1.3 christos if (!contains_register (sym))
2172 1.1.1.3 christos return -1;
2173 1.1.1.3 christos
2174 1.1.1.3 christos expressionS *ex = symbol_get_value_expression (sym);
2175 1.1.1.3 christos return regno (ex->X_add_number);
2176 1.1.1.3 christos }
2177 1.1.1.3 christos
2178 1.1.1.3 christos /* Allocates a tok entry. */
2179 1.1.1.3 christos
2180 1.1.1.3 christos static int
2181 1.1.1.3 christos allocate_tok (expressionS *tok, int ntok, int cidx)
2182 1.1.1.3 christos {
2183 1.1.1.3 christos if (ntok > MAX_INSN_ARGS - 2)
2184 1.1.1.3 christos return 0; /* No space left. */
2185 1.1.1.3 christos
2186 1.1.1.3 christos if (cidx > ntok)
2187 1.1.1.3 christos return 0; /* Incorect args. */
2188 1.1.1.3 christos
2189 1.1.1.3 christos memcpy (&tok[ntok+1], &tok[ntok], sizeof (*tok));
2190 1.1.1.3 christos
2191 1.1.1.3 christos if (cidx == ntok)
2192 1.1.1.3 christos return 1; /* Success. */
2193 1.1.1.3 christos return allocate_tok (tok, ntok - 1, cidx);
2194 1.1.1.3 christos }
2195 1.1.1.3 christos
2196 1.1.1.3 christos /* Return true if a RELOC is generic. A generic reloc is PC-rel of a
2197 1.1.1.3 christos simple ME relocation (e.g. RELOC_ARC_32_ME, BFD_RELOC_ARC_PC32. */
2198 1.1.1.3 christos
2199 1.1.1.3 christos static bfd_boolean
2200 1.1.1.3 christos generic_reloc_p (extended_bfd_reloc_code_real_type reloc)
2201 1.1.1.3 christos {
2202 1.1.1.3 christos if (!reloc)
2203 1.1.1.3 christos return FALSE;
2204 1.1.1.3 christos
2205 1.1.1.3 christos switch (reloc)
2206 1.1.1.3 christos {
2207 1.1.1.3 christos case BFD_RELOC_ARC_SDA_LDST:
2208 1.1.1.3 christos case BFD_RELOC_ARC_SDA_LDST1:
2209 1.1.1.3 christos case BFD_RELOC_ARC_SDA_LDST2:
2210 1.1.1.3 christos case BFD_RELOC_ARC_SDA16_LD:
2211 1.1.1.3 christos case BFD_RELOC_ARC_SDA16_LD1:
2212 1.1.1.3 christos case BFD_RELOC_ARC_SDA16_LD2:
2213 1.1.1.3 christos case BFD_RELOC_ARC_SDA16_ST2:
2214 1.1.1.3 christos case BFD_RELOC_ARC_SDA32_ME:
2215 1.1.1.3 christos return FALSE;
2216 1.1.1.3 christos default:
2217 1.1.1.3 christos break;
2218 1.1.1.3 christos }
2219 1.1.1.3 christos return TRUE;
2220 1.1.1.3 christos }
2221 1.1.1.3 christos
2222 1.1.1.3 christos /* Search forward through all variants of an opcode looking for a
2223 1.1.1.3 christos syntax match. */
2224 1.1.1.3 christos
2225 1.1.1.3 christos static const struct arc_opcode *
2226 1.1.1.3 christos find_opcode_match (const struct arc_opcode *first_opcode,
2227 1.1.1.3 christos expressionS *tok,
2228 1.1.1.3 christos int *pntok,
2229 1.1.1.3 christos struct arc_flags *first_pflag,
2230 1.1.1.3 christos int nflgs,
2231 1.1.1.3 christos int *pcpumatch)
2232 1.1.1.3 christos {
2233 1.1.1.3 christos const struct arc_opcode *opcode = first_opcode;
2234 1.1.1.3 christos int ntok = *pntok;
2235 1.1.1.3 christos int got_cpu_match = 0;
2236 1.1.1.3 christos expressionS bktok[MAX_INSN_ARGS];
2237 1.1.1.3 christos int bkntok;
2238 1.1.1.3 christos expressionS emptyE;
2239 1.1.1.3 christos
2240 1.1.1.3 christos memset (&emptyE, 0, sizeof (emptyE));
2241 1.1.1.3 christos memcpy (bktok, tok, MAX_INSN_ARGS * sizeof (*tok));
2242 1.1.1.3 christos bkntok = ntok;
2243 1.1.1.3 christos
2244 1.1.1.3 christos do
2245 1.1.1.3 christos {
2246 1.1.1.3 christos const unsigned char *opidx;
2247 1.1.1.3 christos const unsigned char *flgidx;
2248 1.1.1.3 christos int tokidx = 0;
2249 1.1.1.3 christos const expressionS *t = &emptyE;
2250 1.1.1.3 christos
2251 1.1.1.3 christos pr_debug ("%s:%d: find_opcode_match: trying opcode 0x%08X ",
2252 1.1.1.3 christos frag_now->fr_file, frag_now->fr_line, opcode->opcode);
2253 1.1.1.3 christos
2254 1.1.1.3 christos /* Don't match opcodes that don't exist on this
2255 1.1.1.3 christos architecture. */
2256 1.1.1.3 christos if (!(opcode->cpu & arc_target))
2257 1.1.1.3 christos goto match_failed;
2258 1.1.1.3 christos
2259 1.1.1.3 christos if (is_code_density_p (opcode) && !(arc_features & ARC_CD))
2260 1.1.1.3 christos goto match_failed;
2261 1.1.1.3 christos
2262 1.1.1.3 christos got_cpu_match = 1;
2263 1.1.1.3 christos pr_debug ("cpu ");
2264 1.1.1.3 christos
2265 1.1.1.3 christos /* Check the operands. */
2266 1.1.1.3 christos for (opidx = opcode->operands; *opidx; ++opidx)
2267 1.1.1.3 christos {
2268 1.1.1.3 christos const struct arc_operand *operand = &arc_operands[*opidx];
2269 1.1.1.3 christos
2270 1.1.1.3 christos /* Only take input from real operands. */
2271 1.1.1.3 christos if ((operand->flags & ARC_OPERAND_FAKE)
2272 1.1.1.3 christos && !(operand->flags & ARC_OPERAND_BRAKET))
2273 1.1.1.3 christos continue;
2274 1.1.1.3 christos
2275 1.1.1.3 christos /* When we expect input, make sure we have it. */
2276 1.1.1.3 christos if (tokidx >= ntok)
2277 1.1.1.3 christos goto match_failed;
2278 1.1.1.3 christos
2279 1.1.1.3 christos /* Match operand type with expression type. */
2280 1.1.1.3 christos switch (operand->flags & ARC_OPERAND_TYPECHECK_MASK)
2281 1.1.1.3 christos {
2282 1.1.1.3 christos case ARC_OPERAND_IR:
2283 1.1.1.3 christos /* Check to be a register. */
2284 1.1.1.3 christos if ((tok[tokidx].X_op != O_register
2285 1.1.1.3 christos || !is_ir_num (tok[tokidx].X_add_number))
2286 1.1.1.3 christos && !(operand->flags & ARC_OPERAND_IGNORE))
2287 1.1.1.3 christos goto match_failed;
2288 1.1.1.3 christos
2289 1.1.1.3 christos /* If expect duplicate, make sure it is duplicate. */
2290 1.1.1.3 christos if (operand->flags & ARC_OPERAND_DUPLICATE)
2291 1.1.1.3 christos {
2292 1.1.1.3 christos /* Check for duplicate. */
2293 1.1.1.3 christos if (t->X_op != O_register
2294 1.1.1.3 christos || !is_ir_num (t->X_add_number)
2295 1.1.1.3 christos || (regno (t->X_add_number) !=
2296 1.1.1.3 christos regno (tok[tokidx].X_add_number)))
2297 1.1.1.3 christos goto match_failed;
2298 1.1.1.3 christos }
2299 1.1.1.3 christos
2300 1.1.1.3 christos /* Special handling? */
2301 1.1.1.3 christos if (operand->insert)
2302 1.1.1.3 christos {
2303 1.1.1.3 christos const char *errmsg = NULL;
2304 1.1.1.3 christos (*operand->insert)(0,
2305 1.1.1.3 christos regno (tok[tokidx].X_add_number),
2306 1.1.1.3 christos &errmsg);
2307 1.1.1.3 christos if (errmsg)
2308 1.1.1.3 christos {
2309 1.1.1.3 christos if (operand->flags & ARC_OPERAND_IGNORE)
2310 1.1.1.3 christos {
2311 1.1.1.3 christos /* Missing argument, create one. */
2312 1.1.1.3 christos if (!allocate_tok (tok, ntok - 1, tokidx))
2313 1.1.1.3 christos goto match_failed;
2314 1.1.1.3 christos
2315 1.1.1.3 christos tok[tokidx].X_op = O_absent;
2316 1.1.1.3 christos ++ntok;
2317 1.1.1.3 christos }
2318 1.1.1.3 christos else
2319 1.1.1.3 christos goto match_failed;
2320 1.1.1.3 christos }
2321 1.1.1.3 christos }
2322 1.1.1.3 christos
2323 1.1.1.3 christos t = &tok[tokidx];
2324 1.1.1.3 christos break;
2325 1.1.1.3 christos
2326 1.1.1.3 christos case ARC_OPERAND_BRAKET:
2327 1.1.1.3 christos /* Check if bracket is also in opcode table as
2328 1.1.1.3 christos operand. */
2329 1.1.1.3 christos if (tok[tokidx].X_op != O_bracket)
2330 1.1.1.3 christos goto match_failed;
2331 1.1.1.3 christos break;
2332 1.1.1.3 christos
2333 1.1.1.3 christos case ARC_OPERAND_LIMM:
2334 1.1.1.3 christos case ARC_OPERAND_SIGNED:
2335 1.1.1.3 christos case ARC_OPERAND_UNSIGNED:
2336 1.1.1.3 christos switch (tok[tokidx].X_op)
2337 1.1.1.3 christos {
2338 1.1.1.3 christos case O_illegal:
2339 1.1.1.3 christos case O_absent:
2340 1.1.1.3 christos case O_register:
2341 1.1.1.3 christos goto match_failed;
2342 1.1.1.3 christos
2343 1.1.1.3 christos case O_bracket:
2344 1.1.1.3 christos /* Got an (too) early bracket, check if it is an
2345 1.1.1.3 christos ignored operand. N.B. This procedure works only
2346 1.1.1.3 christos when bracket is the last operand! */
2347 1.1.1.3 christos if (!(operand->flags & ARC_OPERAND_IGNORE))
2348 1.1.1.3 christos goto match_failed;
2349 1.1.1.3 christos /* Insert the missing operand. */
2350 1.1.1.3 christos if (!allocate_tok (tok, ntok - 1, tokidx))
2351 1.1.1.3 christos goto match_failed;
2352 1.1.1.3 christos
2353 1.1.1.3 christos tok[tokidx].X_op = O_absent;
2354 1.1.1.3 christos ++ntok;
2355 1.1.1.3 christos break;
2356 1.1.1.3 christos
2357 1.1.1.3 christos case O_constant:
2358 1.1.1.3 christos /* Check the range. */
2359 1.1.1.3 christos if (operand->bits != 32
2360 1.1.1.3 christos && !(operand->flags & ARC_OPERAND_NCHK))
2361 1.1.1.3 christos {
2362 1.1.1.3 christos offsetT min, max, val;
2363 1.1.1.3 christos val = tok[tokidx].X_add_number;
2364 1.1.1.3 christos
2365 1.1.1.3 christos if (operand->flags & ARC_OPERAND_SIGNED)
2366 1.1.1.3 christos {
2367 1.1.1.3 christos max = (1 << (operand->bits - 1)) - 1;
2368 1.1.1.3 christos min = -(1 << (operand->bits - 1));
2369 1.1.1.3 christos }
2370 1.1.1.3 christos else
2371 1.1.1.3 christos {
2372 1.1.1.3 christos max = (1 << operand->bits) - 1;
2373 1.1.1.3 christos min = 0;
2374 1.1.1.3 christos }
2375 1.1.1.3 christos
2376 1.1.1.3 christos if (val < min || val > max)
2377 1.1.1.3 christos goto match_failed;
2378 1.1.1.3 christos
2379 1.1.1.3 christos /* Check alignmets. */
2380 1.1.1.3 christos if ((operand->flags & ARC_OPERAND_ALIGNED32)
2381 1.1.1.3 christos && (val & 0x03))
2382 1.1.1.3 christos goto match_failed;
2383 1.1.1.3 christos
2384 1.1.1.3 christos if ((operand->flags & ARC_OPERAND_ALIGNED16)
2385 1.1.1.3 christos && (val & 0x01))
2386 1.1.1.3 christos goto match_failed;
2387 1.1.1.3 christos }
2388 1.1.1.3 christos else if (operand->flags & ARC_OPERAND_NCHK)
2389 1.1.1.3 christos {
2390 1.1.1.3 christos if (operand->insert)
2391 1.1.1.3 christos {
2392 1.1.1.3 christos const char *errmsg = NULL;
2393 1.1.1.3 christos (*operand->insert)(0,
2394 1.1.1.3 christos tok[tokidx].X_add_number,
2395 1.1.1.3 christos &errmsg);
2396 1.1.1.3 christos if (errmsg)
2397 1.1.1.3 christos goto match_failed;
2398 1.1.1.3 christos }
2399 1.1.1.3 christos else
2400 1.1.1.3 christos goto match_failed;
2401 1.1.1.3 christos }
2402 1.1.1.3 christos break;
2403 1.1.1.3 christos
2404 1.1.1.3 christos case O_subtract:
2405 1.1.1.3 christos /* Check if it is register range. */
2406 1.1.1.3 christos if ((tok[tokidx].X_add_number == 0)
2407 1.1.1.3 christos && contains_register (tok[tokidx].X_add_symbol)
2408 1.1.1.3 christos && contains_register (tok[tokidx].X_op_symbol))
2409 1.1.1.3 christos {
2410 1.1.1.3 christos int regs;
2411 1.1.1.3 christos
2412 1.1.1.3 christos regs = get_register (tok[tokidx].X_add_symbol);
2413 1.1.1.3 christos regs <<= 16;
2414 1.1.1.3 christos regs |= get_register (tok[tokidx].X_op_symbol);
2415 1.1.1.3 christos if (operand->insert)
2416 1.1.1.3 christos {
2417 1.1.1.3 christos const char *errmsg = NULL;
2418 1.1.1.3 christos (*operand->insert)(0,
2419 1.1.1.3 christos regs,
2420 1.1.1.3 christos &errmsg);
2421 1.1.1.3 christos if (errmsg)
2422 1.1.1.3 christos goto match_failed;
2423 1.1.1.3 christos }
2424 1.1.1.3 christos else
2425 1.1.1.3 christos goto match_failed;
2426 1.1.1.3 christos break;
2427 1.1.1.3 christos }
2428 1.1.1.3 christos default:
2429 1.1.1.3 christos if (operand->default_reloc == 0)
2430 1.1.1.3 christos goto match_failed; /* The operand needs relocation. */
2431 1.1.1.3 christos
2432 1.1.1.3 christos /* Relocs requiring long immediate. FIXME! make it
2433 1.1.1.3 christos generic and move it to a function. */
2434 1.1.1.3 christos switch (tok[tokidx].X_md)
2435 1.1.1.3 christos {
2436 1.1.1.3 christos case O_gotoff:
2437 1.1.1.3 christos case O_gotpc:
2438 1.1.1.3 christos case O_pcl:
2439 1.1.1.3 christos case O_tpoff:
2440 1.1.1.3 christos case O_dtpoff:
2441 1.1.1.3 christos case O_tlsgd:
2442 1.1.1.3 christos case O_tlsie:
2443 1.1.1.3 christos if (!(operand->flags & ARC_OPERAND_LIMM))
2444 1.1.1.3 christos goto match_failed;
2445 1.1.1.3 christos case O_absent:
2446 1.1.1.3 christos if (!generic_reloc_p (operand->default_reloc))
2447 1.1.1.3 christos goto match_failed;
2448 1.1.1.3 christos default:
2449 1.1.1.3 christos break;
2450 1.1.1.3 christos }
2451 1.1.1.3 christos break;
2452 1.1.1.3 christos }
2453 1.1.1.3 christos /* If expect duplicate, make sure it is duplicate. */
2454 1.1.1.3 christos if (operand->flags & ARC_OPERAND_DUPLICATE)
2455 1.1.1.3 christos {
2456 1.1.1.3 christos if (t->X_op == O_illegal
2457 1.1.1.3 christos || t->X_op == O_absent
2458 1.1.1.3 christos || t->X_op == O_register
2459 1.1.1.3 christos || (t->X_add_number != tok[tokidx].X_add_number))
2460 1.1.1.3 christos goto match_failed;
2461 1.1.1.3 christos }
2462 1.1.1.3 christos t = &tok[tokidx];
2463 1.1.1.3 christos break;
2464 1.1.1.3 christos
2465 1.1.1.3 christos default:
2466 1.1.1.3 christos /* Everything else should have been fake. */
2467 1.1.1.3 christos abort ();
2468 1.1.1.3 christos }
2469 1.1.1.3 christos
2470 1.1.1.3 christos ++tokidx;
2471 1.1.1.3 christos }
2472 1.1.1.3 christos pr_debug ("opr ");
2473 1.1.1.3 christos
2474 1.1.1.3 christos /* Check the flags. Iterate over the valid flag classes. */
2475 1.1.1.3 christos int lnflg = nflgs;
2476 1.1.1.3 christos
2477 1.1.1.3 christos for (flgidx = opcode->flags; *flgidx && lnflg; ++flgidx)
2478 1.1.1.3 christos {
2479 1.1.1.3 christos /* Get a valid flag class. */
2480 1.1.1.3 christos const struct arc_flag_class *cl_flags = &arc_flag_classes[*flgidx];
2481 1.1.1.3 christos const unsigned *flgopridx;
2482 1.1.1.3 christos
2483 1.1.1.3 christos for (flgopridx = cl_flags->flags; *flgopridx; ++flgopridx)
2484 1.1.1.3 christos {
2485 1.1.1.3 christos const struct arc_flag_operand *flg_operand;
2486 1.1.1.3 christos struct arc_flags *pflag = first_pflag;
2487 1.1.1.3 christos int i;
2488 1.1.1.3 christos
2489 1.1.1.3 christos flg_operand = &arc_flag_operands[*flgopridx];
2490 1.1.1.3 christos for (i = 0; i < nflgs; i++, pflag++)
2491 1.1.1.3 christos {
2492 1.1.1.3 christos /* Match against the parsed flags. */
2493 1.1.1.3 christos if (!strcmp (flg_operand->name, pflag->name))
2494 1.1.1.3 christos {
2495 1.1.1.3 christos /*TODO: Check if it is duplicated. */
2496 1.1.1.3 christos pflag->code = *flgopridx;
2497 1.1.1.3 christos lnflg--;
2498 1.1.1.3 christos break; /* goto next flag class and parsed flag. */
2499 1.1.1.3 christos }
2500 1.1.1.3 christos }
2501 1.1.1.3 christos }
2502 1.1.1.3 christos }
2503 1.1.1.3 christos /* Did I check all the parsed flags? */
2504 1.1.1.3 christos if (lnflg)
2505 1.1.1.3 christos goto match_failed;
2506 1.1.1.3 christos
2507 1.1.1.3 christos pr_debug ("flg");
2508 1.1.1.3 christos /* Possible match -- did we use all of our input? */
2509 1.1.1.3 christos if (tokidx == ntok)
2510 1.1.1.3 christos {
2511 1.1.1.3 christos *pntok = ntok;
2512 1.1.1.3 christos pr_debug ("\n");
2513 1.1.1.3 christos return opcode;
2514 1.1.1.3 christos }
2515 1.1.1.3 christos
2516 1.1.1.3 christos match_failed:;
2517 1.1.1.3 christos pr_debug ("\n");
2518 1.1.1.3 christos /* Restore the original parameters. */
2519 1.1.1.3 christos memcpy (tok, bktok, MAX_INSN_ARGS * sizeof (*tok));
2520 1.1.1.3 christos ntok = bkntok;
2521 1.1.1.3 christos }
2522 1.1.1.3 christos while (++opcode - arc_opcodes < (int) arc_num_opcodes
2523 1.1.1.3 christos && !strcmp (opcode->name, first_opcode->name));
2524 1.1.1.3 christos
2525 1.1.1.3 christos if (*pcpumatch)
2526 1.1.1.3 christos *pcpumatch = got_cpu_match;
2527 1.1.1.3 christos
2528 1.1.1.3 christos return NULL;
2529 1.1.1.3 christos }
2530 1.1.1.3 christos
2531 1.1.1.3 christos /* Find the proper relocation for the given opcode. */
2532 1.1.1.3 christos
2533 1.1.1.3 christos static extended_bfd_reloc_code_real_type
2534 1.1.1.3 christos find_reloc (const char *name,
2535 1.1.1.3 christos const char *opcodename,
2536 1.1.1.3 christos const struct arc_flags *pflags,
2537 1.1.1.3 christos int nflg,
2538 1.1.1.3 christos extended_bfd_reloc_code_real_type reloc)
2539 1.1.1.3 christos {
2540 1.1.1.3 christos unsigned int i;
2541 1.1.1.3 christos int j;
2542 1.1.1.3 christos bfd_boolean found_flag;
2543 1.1.1.3 christos extended_bfd_reloc_code_real_type ret = BFD_RELOC_UNUSED;
2544 1.1.1.3 christos
2545 1.1.1.3 christos for (i = 0; i < arc_num_equiv_tab; i++)
2546 1.1.1.3 christos {
2547 1.1.1.3 christos const struct arc_reloc_equiv_tab *r = &arc_reloc_equiv[i];
2548 1.1.1.3 christos
2549 1.1.1.3 christos /* Find the entry. */
2550 1.1.1.3 christos if (strcmp (name, r->name))
2551 1.1.1.3 christos continue;
2552 1.1.1.3 christos if (r->mnemonic && (strcmp (r->mnemonic, opcodename)))
2553 1.1.1.3 christos continue;
2554 1.1.1.3 christos if (r->flagcode)
2555 1.1.1.3 christos {
2556 1.1.1.3 christos if (!nflg)
2557 1.1.1.3 christos continue;
2558 1.1.1.3 christos found_flag = FALSE;
2559 1.1.1.3 christos for (j = 0; j < nflg; j++)
2560 1.1.1.3 christos if (pflags[i].code == r->flagcode)
2561 1.1.1.3 christos {
2562 1.1.1.3 christos found_flag = TRUE;
2563 1.1.1.3 christos break;
2564 1.1.1.3 christos }
2565 1.1.1.3 christos if (!found_flag)
2566 1.1.1.3 christos continue;
2567 1.1.1.3 christos }
2568 1.1.1.3 christos
2569 1.1.1.3 christos if (reloc != r->oldreloc)
2570 1.1.1.3 christos continue;
2571 1.1.1.3 christos /* Found it. */
2572 1.1.1.3 christos ret = r->newreloc;
2573 1.1.1.3 christos break;
2574 1.1.1.3 christos }
2575 1.1.1.3 christos
2576 1.1.1.3 christos if (ret == BFD_RELOC_UNUSED)
2577 1.1.1.3 christos as_bad (_("Unable to find %s relocation for instruction %s"),
2578 1.1.1.3 christos name, opcodename);
2579 1.1.1.3 christos return ret;
2580 1.1.1.3 christos }
2581 1.1.1.3 christos
2582 1.1.1.3 christos /* Turn an opcode description and a set of arguments into
2583 1.1.1.3 christos an instruction and a fixup. */
2584 1.1.1.3 christos
2585 1.1.1.3 christos static void
2586 1.1.1.3 christos assemble_insn (const struct arc_opcode *opcode,
2587 1.1.1.3 christos const expressionS *tok,
2588 1.1.1.3 christos int ntok,
2589 1.1.1.3 christos const struct arc_flags *pflags,
2590 1.1.1.3 christos int nflg,
2591 1.1.1.3 christos struct arc_insn *insn)
2592 1.1.1.3 christos {
2593 1.1.1.3 christos const expressionS *reloc_exp = NULL;
2594 1.1.1.3 christos unsigned image;
2595 1.1.1.3 christos const unsigned char *argidx;
2596 1.1.1.3 christos int i;
2597 1.1.1.3 christos int tokidx = 0;
2598 1.1.1.3 christos unsigned char pcrel = 0;
2599 1.1.1.3 christos bfd_boolean needGOTSymbol;
2600 1.1.1.3 christos bfd_boolean has_delay_slot = FALSE;
2601 1.1.1.3 christos extended_bfd_reloc_code_real_type reloc = BFD_RELOC_UNUSED;
2602 1.1.1.3 christos
2603 1.1.1.3 christos memset (insn, 0, sizeof (*insn));
2604 1.1.1.3 christos image = opcode->opcode;
2605 1.1.1.3 christos
2606 1.1.1.3 christos pr_debug ("%s:%d: assemble_insn: %s using opcode %x\n",
2607 1.1.1.3 christos frag_now->fr_file, frag_now->fr_line, opcode->name,
2608 1.1.1.3 christos opcode->opcode);
2609 1.1.1.3 christos
2610 1.1.1.3 christos /* Handle operands. */
2611 1.1.1.3 christos for (argidx = opcode->operands; *argidx; ++argidx)
2612 1.1.1.3 christos {
2613 1.1.1.3 christos const struct arc_operand *operand = &arc_operands[*argidx];
2614 1.1.1.3 christos const expressionS *t = (const expressionS *) 0;
2615 1.1.1.3 christos
2616 1.1.1.3 christos if ((operand->flags & ARC_OPERAND_FAKE)
2617 1.1.1.3 christos && !(operand->flags & ARC_OPERAND_BRAKET))
2618 1.1.1.3 christos continue;
2619 1.1.1.3 christos
2620 1.1.1.3 christos if (operand->flags & ARC_OPERAND_DUPLICATE)
2621 1.1.1.3 christos {
2622 1.1.1.3 christos /* Duplicate operand, already inserted. */
2623 1.1.1.3 christos tokidx ++;
2624 1.1.1.3 christos continue;
2625 1.1.1.3 christos }
2626 1.1.1.3 christos
2627 1.1.1.3 christos if (tokidx >= ntok)
2628 1.1.1.3 christos {
2629 1.1.1.3 christos abort ();
2630 1.1.1.3 christos }
2631 1.1.1.3 christos else
2632 1.1.1.3 christos t = &tok[tokidx++];
2633 1.1.1.3 christos
2634 1.1.1.3 christos /* Regardless if we have a reloc or not mark the instruction
2635 1.1.1.3 christos limm if it is the case. */
2636 1.1.1.3 christos if (operand->flags & ARC_OPERAND_LIMM)
2637 1.1.1.3 christos insn->has_limm = TRUE;
2638 1.1.1.3 christos
2639 1.1.1.3 christos switch (t->X_op)
2640 1.1.1.3 christos {
2641 1.1.1.3 christos case O_register:
2642 1.1.1.3 christos image = insert_operand (image, operand, regno (t->X_add_number),
2643 1.1.1.3 christos NULL, 0);
2644 1.1.1.3 christos break;
2645 1.1.1.3 christos
2646 1.1.1.3 christos case O_constant:
2647 1.1.1.3 christos image = insert_operand (image, operand, t->X_add_number, NULL, 0);
2648 1.1.1.3 christos reloc_exp = t;
2649 1.1.1.3 christos if (operand->flags & ARC_OPERAND_LIMM)
2650 1.1.1.3 christos insn->limm = t->X_add_number;
2651 1.1.1.3 christos break;
2652 1.1.1.3 christos
2653 1.1.1.3 christos case O_bracket:
2654 1.1.1.3 christos /* Ignore brackets. */
2655 1.1.1.3 christos break;
2656 1.1.1.3 christos
2657 1.1.1.3 christos case O_absent:
2658 1.1.1.3 christos gas_assert (operand->flags & ARC_OPERAND_IGNORE);
2659 1.1.1.3 christos break;
2660 1.1.1.3 christos
2661 1.1.1.3 christos case O_subtract:
2662 1.1.1.3 christos /* Maybe register range. */
2663 1.1.1.3 christos if ((t->X_add_number == 0)
2664 1.1.1.3 christos && contains_register (t->X_add_symbol)
2665 1.1.1.3 christos && contains_register (t->X_op_symbol))
2666 1.1.1.3 christos {
2667 1.1.1.3 christos int regs;
2668 1.1.1.3 christos
2669 1.1.1.3 christos regs = get_register (t->X_add_symbol);
2670 1.1.1.3 christos regs <<= 16;
2671 1.1.1.3 christos regs |= get_register (t->X_op_symbol);
2672 1.1.1.3 christos image = insert_operand (image, operand, regs, NULL, 0);
2673 1.1.1.3 christos break;
2674 1.1.1.3 christos }
2675 1.1.1.3 christos
2676 1.1.1.3 christos default:
2677 1.1.1.3 christos /* This operand needs a relocation. */
2678 1.1.1.3 christos needGOTSymbol = FALSE;
2679 1.1.1.3 christos
2680 1.1.1.3 christos switch (t->X_md)
2681 1.1.1.3 christos {
2682 1.1.1.3 christos case O_plt:
2683 1.1.1.3 christos needGOTSymbol = TRUE;
2684 1.1.1.3 christos reloc = find_reloc ("plt", opcode->name,
2685 1.1.1.3 christos pflags, nflg,
2686 1.1.1.3 christos operand->default_reloc);
2687 1.1.1.3 christos break;
2688 1.1.1.3 christos
2689 1.1.1.3 christos case O_gotoff:
2690 1.1.1.3 christos case O_gotpc:
2691 1.1.1.3 christos needGOTSymbol = TRUE;
2692 1.1.1.3 christos reloc = ARC_RELOC_TABLE (t->X_md)->reloc;
2693 1.1.1.3 christos break;
2694 1.1.1.3 christos case O_pcl:
2695 1.1.1.3 christos reloc = ARC_RELOC_TABLE (t->X_md)->reloc;
2696 1.1.1.3 christos if (ARC_SHORT (opcode->mask))
2697 1.1.1.3 christos as_bad_where (frag_now->fr_file, frag_now->fr_line,
2698 1.1.1.3 christos _("Unable to use @pcl relocation for insn %s"),
2699 1.1.1.3 christos opcode->name);
2700 1.1.1.3 christos break;
2701 1.1.1.3 christos case O_sda:
2702 1.1.1.3 christos reloc = find_reloc ("sda", opcode->name,
2703 1.1.1.3 christos pflags, nflg,
2704 1.1.1.3 christos operand->default_reloc);
2705 1.1.1.3 christos break;
2706 1.1.1.3 christos case O_tlsgd:
2707 1.1.1.3 christos case O_tlsie:
2708 1.1.1.3 christos needGOTSymbol = TRUE;
2709 1.1.1.3 christos /* Fall-through. */
2710 1.1.1.3 christos
2711 1.1.1.3 christos case O_tpoff:
2712 1.1.1.3 christos case O_dtpoff:
2713 1.1.1.3 christos reloc = ARC_RELOC_TABLE (t->X_md)->reloc;
2714 1.1.1.3 christos break;
2715 1.1.1.3 christos
2716 1.1.1.3 christos case O_tpoff9: /*FIXME! Check for the conditionality of
2717 1.1.1.3 christos the insn. */
2718 1.1.1.3 christos case O_dtpoff9: /*FIXME! Check for the conditionality of
2719 1.1.1.3 christos the insn. */
2720 1.1.1.3 christos as_bad (_("TLS_*_S9 relocs are not supported yet"));
2721 1.1.1.3 christos break;
2722 1.1.1.3 christos
2723 1.1.1.3 christos default:
2724 1.1.1.3 christos /* Just consider the default relocation. */
2725 1.1.1.3 christos reloc = operand->default_reloc;
2726 1.1.1.3 christos break;
2727 1.1.1.3 christos }
2728 1.1.1.3 christos
2729 1.1.1.3 christos if (needGOTSymbol && (GOT_symbol == NULL))
2730 1.1.1.3 christos GOT_symbol = symbol_find_or_make (GLOBAL_OFFSET_TABLE_NAME);
2731 1.1.1.3 christos
2732 1.1.1.3 christos reloc_exp = t;
2733 1.1.1.3 christos
2734 1.1.1.3 christos #if 0
2735 1.1.1.3 christos if (reloc > 0)
2736 1.1.1.3 christos {
2737 1.1.1.3 christos /* sanity checks. */
2738 1.1.1.3 christos reloc_howto_type *reloc_howto
2739 1.1.1.3 christos = bfd_reloc_type_lookup (stdoutput,
2740 1.1.1.3 christos (bfd_reloc_code_real_type) reloc);
2741 1.1.1.3 christos unsigned reloc_bitsize = reloc_howto->bitsize;
2742 1.1.1.3 christos if (reloc_howto->rightshift)
2743 1.1.1.3 christos reloc_bitsize -= reloc_howto->rightshift;
2744 1.1.1.3 christos if (reloc_bitsize != operand->bits)
2745 1.1.1.3 christos {
2746 1.1.1.3 christos as_bad (_("invalid relocation %s for field"),
2747 1.1.1.3 christos bfd_get_reloc_code_name (reloc));
2748 1.1.1.3 christos return;
2749 1.1.1.3 christos }
2750 1.1.1.3 christos }
2751 1.1.1.3 christos #endif
2752 1.1.1.3 christos if (insn->nfixups >= MAX_INSN_FIXUPS)
2753 1.1.1.3 christos as_fatal (_("too many fixups"));
2754 1.1.1.3 christos
2755 1.1.1.3 christos struct arc_fixup *fixup;
2756 1.1.1.3 christos fixup = &insn->fixups[insn->nfixups++];
2757 1.1.1.3 christos fixup->exp = *t;
2758 1.1.1.3 christos fixup->reloc = reloc;
2759 1.1.1.3 christos pcrel = (operand->flags & ARC_OPERAND_PCREL) ? 1 : 0;
2760 1.1.1.3 christos fixup->pcrel = pcrel;
2761 1.1.1.3 christos fixup->islong = (operand->flags & ARC_OPERAND_LIMM) ?
2762 1.1.1.3 christos TRUE : FALSE;
2763 1.1.1.3 christos break;
2764 1.1.1.3 christos }
2765 1.1.1.3 christos }
2766 1.1.1.3 christos
2767 1.1.1.3 christos /* Handle flags. */
2768 1.1.1.3 christos for (i = 0; i < nflg; i++)
2769 1.1.1.3 christos {
2770 1.1.1.3 christos const struct arc_flag_operand *flg_operand =
2771 1.1.1.3 christos &arc_flag_operands[pflags[i].code];
2772 1.1.1.3 christos
2773 1.1.1.3 christos /* Check if the instruction has a delay slot. */
2774 1.1.1.3 christos if (!strcmp (flg_operand->name, "d"))
2775 1.1.1.3 christos has_delay_slot = TRUE;
2776 1.1.1.3 christos
2777 1.1.1.3 christos /* There is an exceptional case when we cannot insert a flag
2778 1.1.1.3 christos just as it is. The .T flag must be handled in relation with
2779 1.1.1.3 christos the relative address. */
2780 1.1.1.3 christos if (!strcmp (flg_operand->name, "t")
2781 1.1.1.3 christos || !strcmp (flg_operand->name, "nt"))
2782 1.1.1.3 christos {
2783 1.1.1.3 christos unsigned bitYoperand = 0;
2784 1.1.1.3 christos /* FIXME! move selection bbit/brcc in arc-opc.c. */
2785 1.1.1.3 christos if (!strcmp (flg_operand->name, "t"))
2786 1.1.1.3 christos if (!strcmp (opcode->name, "bbit0")
2787 1.1.1.3 christos || !strcmp (opcode->name, "bbit1"))
2788 1.1.1.3 christos bitYoperand = arc_NToperand;
2789 1.1.1.3 christos else
2790 1.1.1.3 christos bitYoperand = arc_Toperand;
2791 1.1.1.3 christos else
2792 1.1.1.3 christos if (!strcmp (opcode->name, "bbit0")
2793 1.1.1.3 christos || !strcmp (opcode->name, "bbit1"))
2794 1.1.1.3 christos bitYoperand = arc_Toperand;
2795 1.1.1.3 christos else
2796 1.1.1.3 christos bitYoperand = arc_NToperand;
2797 1.1.1.3 christos
2798 1.1.1.3 christos gas_assert (reloc_exp != NULL);
2799 1.1.1.3 christos if (reloc_exp->X_op == O_constant)
2800 1.1.1.3 christos {
2801 1.1.1.3 christos /* Check if we have a constant and solved it
2802 1.1.1.3 christos immediately. */
2803 1.1.1.3 christos offsetT val = reloc_exp->X_add_number;
2804 1.1.1.3 christos image |= insert_operand (image, &arc_operands[bitYoperand],
2805 1.1.1.3 christos val, NULL, 0);
2806 1.1.1.3 christos }
2807 1.1.1.3 christos else
2808 1.1.1.3 christos {
2809 1.1.1.3 christos struct arc_fixup *fixup;
2810 1.1.1.3 christos
2811 1.1.1.3 christos if (insn->nfixups >= MAX_INSN_FIXUPS)
2812 1.1.1.3 christos as_fatal (_("too many fixups"));
2813 1.1.1.3 christos
2814 1.1.1.3 christos fixup = &insn->fixups[insn->nfixups++];
2815 1.1.1.3 christos fixup->exp = *reloc_exp;
2816 1.1.1.3 christos fixup->reloc = -bitYoperand;
2817 1.1.1.3 christos fixup->pcrel = pcrel;
2818 1.1.1.3 christos fixup->islong = FALSE;
2819 1.1.1.3 christos }
2820 1.1.1.3 christos }
2821 1.1.1.3 christos else
2822 1.1.1.3 christos image |= (flg_operand->code & ((1 << flg_operand->bits) - 1))
2823 1.1.1.3 christos << flg_operand->shift;
2824 1.1.1.3 christos }
2825 1.1.1.3 christos
2826 1.1.1.3 christos /* Short instruction? */
2827 1.1.1.3 christos insn->short_insn = ARC_SHORT (opcode->mask) ? TRUE : FALSE;
2828 1.1.1.3 christos
2829 1.1.1.3 christos insn->insn = image;
2830 1.1.1.3 christos
2831 1.1.1.3 christos /* Update last insn status. */
2832 1.1.1.3 christos arc_last_insns[1] = arc_last_insns[0];
2833 1.1.1.3 christos arc_last_insns[0].opcode = opcode;
2834 1.1.1.3 christos arc_last_insns[0].has_limm = insn->has_limm;
2835 1.1.1.3 christos arc_last_insns[0].has_delay_slot = has_delay_slot;
2836 1.1.1.3 christos
2837 1.1.1.3 christos /* Check if the current instruction is legally used. */
2838 1.1.1.3 christos if (arc_last_insns[1].has_delay_slot
2839 1.1.1.3 christos && is_br_jmp_insn_p (arc_last_insns[0].opcode))
2840 1.1.1.3 christos as_bad_where (frag_now->fr_file, frag_now->fr_line,
2841 1.1.1.3 christos _("A jump/branch instruction in delay slot."));
2842 1.1.1.3 christos }
2843 1.1.1.3 christos
2844 1.1.1.3 christos /* Actually output an instruction with its fixup. */
2845 1.1.1.3 christos
2846 1.1.1.3 christos static void
2847 1.1.1.3 christos emit_insn (struct arc_insn *insn)
2848 1.1.1.3 christos {
2849 1.1.1.3 christos char *f;
2850 1.1.1.3 christos int i;
2851 1.1.1.3 christos
2852 1.1.1.3 christos pr_debug ("Emit insn : 0x%x\n", insn->insn);
2853 1.1.1.3 christos pr_debug ("\tShort : 0x%d\n", insn->short_insn);
2854 1.1.1.3 christos pr_debug ("\tLong imm: 0x%lx\n", insn->limm);
2855 1.1.1.3 christos
2856 1.1.1.3 christos /* Write out the instruction. */
2857 1.1.1.3 christos if (insn->short_insn)
2858 1.1.1.3 christos {
2859 1.1.1.3 christos if (insn->has_limm)
2860 1.1.1.3 christos {
2861 1.1.1.3 christos f = frag_more (6);
2862 1.1.1.3 christos md_number_to_chars (f, insn->insn, 2);
2863 1.1.1.3 christos md_number_to_chars_midend (f + 2, insn->limm, 4);
2864 1.1.1.3 christos dwarf2_emit_insn (6);
2865 1.1.1.3 christos }
2866 1.1.1.3 christos else
2867 1.1.1.3 christos {
2868 1.1.1.3 christos f = frag_more (2);
2869 1.1.1.3 christos md_number_to_chars (f, insn->insn, 2);
2870 1.1.1.3 christos dwarf2_emit_insn (2);
2871 1.1.1.3 christos }
2872 1.1.1.3 christos }
2873 1.1.1.3 christos else
2874 1.1.1.3 christos {
2875 1.1.1.3 christos if (insn->has_limm)
2876 1.1.1.3 christos {
2877 1.1.1.3 christos f = frag_more (8);
2878 1.1.1.3 christos md_number_to_chars_midend (f, insn->insn, 4);
2879 1.1.1.3 christos md_number_to_chars_midend (f + 4, insn->limm, 4);
2880 1.1.1.3 christos dwarf2_emit_insn (8);
2881 1.1.1.3 christos }
2882 1.1.1.3 christos else
2883 1.1.1.3 christos {
2884 1.1.1.3 christos f = frag_more (4);
2885 1.1.1.3 christos md_number_to_chars_midend (f, insn->insn, 4);
2886 1.1.1.3 christos dwarf2_emit_insn (4);
2887 1.1.1.3 christos }
2888 1.1.1.3 christos }
2889 1.1.1.3 christos
2890 1.1.1.3 christos /* Apply the fixups in order. */
2891 1.1.1.3 christos for (i = 0; i < insn->nfixups; i++)
2892 1.1.1.3 christos {
2893 1.1.1.3 christos struct arc_fixup *fixup = &insn->fixups[i];
2894 1.1.1.3 christos int size, pcrel, offset = 0;
2895 1.1.1.3 christos
2896 1.1.1.3 christos /*FIXME! the reloc size is wrong in the BFD file. When it will
2897 1.1.1.3 christos be fixed please delete me. */
2898 1.1.1.3 christos size = (insn->short_insn && !fixup->islong) ? 2 : 4;
2899 1.1.1.3 christos
2900 1.1.1.3 christos if (fixup->islong)
2901 1.1.1.3 christos offset = (insn->short_insn) ? 2 : 4;
2902 1.1.1.3 christos
2903 1.1.1.3 christos /* Some fixups are only used internally, thus no howto. */
2904 1.1.1.3 christos if ((int) fixup->reloc < 0)
2905 1.1.1.3 christos {
2906 1.1.1.3 christos /*FIXME! the reloc size is wrong in the BFD file. When it
2907 1.1.1.3 christos will be fixed please enable me.
2908 1.1.1.3 christos size = (insn->short_insn && !fixup->islong) ? 2 : 4; */
2909 1.1.1.3 christos pcrel = fixup->pcrel;
2910 1.1.1.3 christos }
2911 1.1.1.3 christos else
2912 1.1.1.3 christos {
2913 1.1.1.3 christos reloc_howto_type *reloc_howto =
2914 1.1.1.3 christos bfd_reloc_type_lookup (stdoutput,
2915 1.1.1.3 christos (bfd_reloc_code_real_type) fixup->reloc);
2916 1.1.1.3 christos gas_assert (reloc_howto);
2917 1.1.1.3 christos /*FIXME! the reloc size is wrong in the BFD file. When it
2918 1.1.1.3 christos will be fixed please enable me.
2919 1.1.1.3 christos size = bfd_get_reloc_size (reloc_howto); */
2920 1.1.1.3 christos pcrel = reloc_howto->pc_relative;
2921 1.1.1.3 christos }
2922 1.1.1.3 christos
2923 1.1.1.3 christos pr_debug ("%s:%d: emit_insn: new %s fixup (PCrel:%s) of size %d @ offset %d\n",
2924 1.1.1.3 christos frag_now->fr_file, frag_now->fr_line,
2925 1.1.1.3 christos (fixup->reloc < 0) ? "Internal" :
2926 1.1.1.3 christos bfd_get_reloc_code_name (fixup->reloc),
2927 1.1.1.3 christos pcrel ? "Y" : "N",
2928 1.1.1.3 christos size, offset);
2929 1.1.1.3 christos fix_new_exp (frag_now, f - frag_now->fr_literal + offset,
2930 1.1.1.3 christos size, &fixup->exp, pcrel, fixup->reloc);
2931 1.1.1.3 christos
2932 1.1.1.3 christos /* Check for ZOLs, and update symbol info if any. */
2933 1.1.1.3 christos if (LP_INSN (insn->insn))
2934 1.1.1.3 christos {
2935 1.1.1.3 christos gas_assert (fixup->exp.X_add_symbol);
2936 1.1.1.3 christos ARC_SET_FLAG (fixup->exp.X_add_symbol, ARC_FLAG_ZOL);
2937 1.1.1.3 christos }
2938 1.1.1.3 christos }
2939 1.1.1.3 christos }
2940 1.1.1.3 christos
2941 1.1.1.3 christos /* Insert an operand value into an instruction. */
2942 1.1.1.3 christos
2943 1.1.1.3 christos static unsigned
2944 1.1.1.3 christos insert_operand (unsigned insn,
2945 1.1.1.3 christos const struct arc_operand *operand,
2946 1.1.1.3 christos offsetT val,
2947 1.1.1.3 christos char *file,
2948 1.1.1.3 christos unsigned line)
2949 1.1.1.3 christos {
2950 1.1.1.3 christos offsetT min = 0, max = 0;
2951 1.1.1.3 christos
2952 1.1.1.3 christos if (operand->bits != 32
2953 1.1.1.3 christos && !(operand->flags & ARC_OPERAND_NCHK)
2954 1.1.1.3 christos && !(operand->flags & ARC_OPERAND_FAKE))
2955 1.1.1.3 christos {
2956 1.1.1.3 christos if (operand->flags & ARC_OPERAND_SIGNED)
2957 1.1.1.3 christos {
2958 1.1.1.3 christos max = (1 << (operand->bits - 1)) - 1;
2959 1.1.1.3 christos min = -(1 << (operand->bits - 1));
2960 1.1.1.3 christos }
2961 1.1.1.3 christos else
2962 1.1.1.3 christos {
2963 1.1.1.3 christos max = (1 << operand->bits) - 1;
2964 1.1.1.3 christos min = 0;
2965 1.1.1.3 christos }
2966 1.1.1.3 christos
2967 1.1.1.3 christos if (val < min || val > max)
2968 1.1.1.3 christos as_bad_value_out_of_range (_("operand"),
2969 1.1.1.3 christos val, min, max, file, line);
2970 1.1.1.3 christos }
2971 1.1.1.3 christos
2972 1.1.1.3 christos pr_debug ("insert field: %ld <= %ld <= %ld in 0x%08x\n",
2973 1.1.1.3 christos min, val, max, insn);
2974 1.1.1.3 christos
2975 1.1.1.3 christos if ((operand->flags & ARC_OPERAND_ALIGNED32)
2976 1.1.1.3 christos && (val & 0x03))
2977 1.1.1.3 christos as_bad_where (file, line,
2978 1.1.1.3 christos _("Unaligned operand. Needs to be 32bit aligned"));
2979 1.1.1.3 christos
2980 1.1.1.3 christos if ((operand->flags & ARC_OPERAND_ALIGNED16)
2981 1.1.1.3 christos && (val & 0x01))
2982 1.1.1.3 christos as_bad_where (file, line,
2983 1.1.1.3 christos _("Unaligned operand. Needs to be 16bit aligned"));
2984 1.1.1.3 christos
2985 1.1.1.3 christos if (operand->insert)
2986 1.1.1.3 christos {
2987 1.1.1.3 christos const char *errmsg = NULL;
2988 1.1.1.3 christos
2989 1.1.1.3 christos insn = (*operand->insert) (insn, val, &errmsg);
2990 1.1.1.3 christos if (errmsg)
2991 1.1.1.3 christos as_warn_where (file, line, "%s", errmsg);
2992 1.1.1.3 christos }
2993 1.1.1.3 christos else
2994 1.1.1.3 christos {
2995 1.1.1.3 christos if (operand->flags & ARC_OPERAND_TRUNCATE)
2996 1.1.1.3 christos {
2997 1.1.1.3 christos if (operand->flags & ARC_OPERAND_ALIGNED32)
2998 1.1.1.3 christos val >>= 2;
2999 1.1.1.3 christos if (operand->flags & ARC_OPERAND_ALIGNED16)
3000 1.1.1.3 christos val >>= 1;
3001 1.1.1.3 christos }
3002 1.1.1.3 christos insn |= ((val & ((1 << operand->bits) - 1)) << operand->shift);
3003 1.1.1.3 christos }
3004 1.1.1.3 christos return insn;
3005 1.1.1.3 christos }
3006 1.1.1.3 christos
3007 1.1.1.3 christos void
3008 1.1.1.3 christos arc_handle_align (fragS* fragP)
3009 1.1.1.3 christos {
3010 1.1.1.3 christos if ((fragP)->fr_type == rs_align_code)
3011 1.1.1.3 christos {
3012 1.1.1.3 christos char *dest = (fragP)->fr_literal + (fragP)->fr_fix;
3013 1.1.1.3 christos valueT count = ((fragP)->fr_next->fr_address
3014 1.1.1.3 christos - (fragP)->fr_address - (fragP)->fr_fix);
3015 1.1.1.3 christos
3016 1.1.1.3 christos (fragP)->fr_var = 2;
3017 1.1.1.3 christos
3018 1.1.1.3 christos if (count & 1)/* Padding in the gap till the next 2-byte
3019 1.1.1.3 christos boundary with 0s. */
3020 1.1.1.3 christos {
3021 1.1.1.3 christos (fragP)->fr_fix++;
3022 1.1.1.3 christos *dest++ = 0;
3023 1.1.1.3 christos }
3024 1.1.1.3 christos /* Writing nop_s. */
3025 1.1.1.3 christos md_number_to_chars (dest, NOP_OPCODE_S, 2);
3026 1.1.1.3 christos }
3027 1.1.1.3 christos }
3028 1.1.1.3 christos
3029 1.1.1.3 christos /* Here we decide which fixups can be adjusted to make them relative
3030 1.1.1.3 christos to the beginning of the section instead of the symbol. Basically
3031 1.1.1.3 christos we need to make sure that the dynamic relocations are done
3032 1.1.1.3 christos correctly, so in some cases we force the original symbol to be
3033 1.1.1.3 christos used. */
3034 1.1.1.3 christos
3035 1.1.1.3 christos int
3036 1.1.1.3 christos tc_arc_fix_adjustable (fixS *fixP)
3037 1.1.1.3 christos {
3038 1.1.1.3 christos
3039 1.1.1.3 christos /* Prevent all adjustments to global symbols. */
3040 1.1.1.3 christos if (S_IS_EXTERNAL (fixP->fx_addsy))
3041 1.1.1.3 christos return 0;
3042 1.1.1.3 christos if (S_IS_WEAK (fixP->fx_addsy))
3043 1.1.1.3 christos return 0;
3044 1.1.1.3 christos
3045 1.1.1.3 christos /* Adjust_reloc_syms doesn't know about the GOT. */
3046 1.1.1.3 christos switch (fixP->fx_r_type)
3047 1.1.1.3 christos {
3048 1.1.1.3 christos case BFD_RELOC_ARC_GOTPC32:
3049 1.1.1.3 christos case BFD_RELOC_ARC_PLT32:
3050 1.1.1.3 christos case BFD_RELOC_ARC_S25H_PCREL_PLT:
3051 1.1.1.3 christos case BFD_RELOC_ARC_S21H_PCREL_PLT:
3052 1.1.1.3 christos case BFD_RELOC_ARC_S25W_PCREL_PLT:
3053 1.1.1.3 christos case BFD_RELOC_ARC_S21W_PCREL_PLT:
3054 1.1.1.3 christos return 0;
3055 1.1.1.3 christos
3056 1.1.1.3 christos default:
3057 1.1.1.3 christos break;
3058 1.1.1.3 christos }
3059 1.1.1.3 christos
3060 1.1.1.3 christos return 0; /* FIXME! return 1, fix it in the linker. */
3061 1.1.1.3 christos }
3062 1.1.1.3 christos
3063 1.1.1.3 christos /* Compute the reloc type of an expression EXP. */
3064 1.1.1.3 christos
3065 1.1.1.3 christos static void
3066 1.1.1.3 christos arc_check_reloc (expressionS *exp,
3067 1.1.1.3 christos bfd_reloc_code_real_type *r_type_p)
3068 1.1.1.3 christos {
3069 1.1.1.3 christos if (*r_type_p == BFD_RELOC_32
3070 1.1.1.3 christos && exp->X_op == O_subtract
3071 1.1.1.3 christos && exp->X_op_symbol != NULL
3072 1.1.1.3 christos && exp->X_op_symbol->bsym->section == now_seg)
3073 1.1.1.3 christos *r_type_p = BFD_RELOC_ARC_32_PCREL;
3074 1.1.1.3 christos }
3075 1.1.1.3 christos
3076 1.1.1.3 christos
3077 1.1.1.3 christos /* Add expression EXP of SIZE bytes to offset OFF of fragment FRAG. */
3078 1.1.1.3 christos
3079 1.1.1.3 christos void
3080 1.1.1.3 christos arc_cons_fix_new (fragS *frag,
3081 1.1.1.3 christos int off,
3082 1.1.1.3 christos int size,
3083 1.1.1.3 christos expressionS *exp,
3084 1.1.1.3 christos bfd_reloc_code_real_type r_type)
3085 1.1.1.3 christos {
3086 1.1.1.3 christos r_type = BFD_RELOC_UNUSED;
3087 1.1.1.3 christos
3088 1.1.1.3 christos switch (size)
3089 1.1.1.3 christos {
3090 1.1.1.3 christos case 1:
3091 1.1.1.3 christos r_type = BFD_RELOC_8;
3092 1.1.1.3 christos break;
3093 1.1.1.3 christos
3094 1.1.1.3 christos case 2:
3095 1.1.1.3 christos r_type = BFD_RELOC_16;
3096 1.1.1.3 christos break;
3097 1.1.1.3 christos
3098 1.1.1.3 christos case 3:
3099 1.1.1.3 christos r_type = BFD_RELOC_24;
3100 1.1.1.3 christos break;
3101 1.1.1.3 christos
3102 1.1.1.3 christos case 4:
3103 1.1.1.3 christos r_type = BFD_RELOC_32;
3104 1.1.1.3 christos arc_check_reloc (exp, &r_type);
3105 1.1.1.3 christos break;
3106 1.1.1.3 christos
3107 1.1.1.3 christos case 8:
3108 1.1.1.3 christos r_type = BFD_RELOC_64;
3109 1.1.1.3 christos break;
3110 1.1.1.3 christos
3111 1.1.1.3 christos default:
3112 1.1.1.3 christos as_bad (_("unsupported BFD relocation size %u"), size);
3113 1.1.1.3 christos r_type = BFD_RELOC_UNUSED;
3114 1.1.1.3 christos }
3115 1.1.1.3 christos
3116 1.1.1.3 christos fix_new_exp (frag, off, size, exp, 0, r_type);
3117 1.1.1.3 christos }
3118 1.1.1.3 christos
3119 1.1.1.3 christos /* The actual routine that checks the ZOL conditions. */
3120 1.1.1.3 christos
3121 1.1.1.3 christos static void
3122 1.1.1.3 christos check_zol (symbolS *s)
3123 1.1.1.3 christos {
3124 1.1.1.3 christos switch (arc_mach_type)
3125 1.1.1.3 christos {
3126 1.1.1.3 christos case bfd_mach_arc_arcv2:
3127 1.1.1.3 christos if (arc_target & ARC_OPCODE_ARCv2EM)
3128 1.1.1.3 christos return;
3129 1.1.1.3 christos
3130 1.1.1.3 christos if (is_br_jmp_insn_p (arc_last_insns[0].opcode)
3131 1.1.1.3 christos || arc_last_insns[1].has_delay_slot)
3132 1.1.1.3 christos as_bad (_("Jump/Branch instruction detected at the end of the ZOL label @%s"),
3133 1.1.1.3 christos S_GET_NAME (s));
3134 1.1.1.3 christos
3135 1.1.1.3 christos break;
3136 1.1.1.3 christos case bfd_mach_arc_arc600:
3137 1.1.1.3 christos
3138 1.1.1.3 christos if (is_kernel_insn_p (arc_last_insns[0].opcode))
3139 1.1.1.3 christos as_bad (_("Kernel instruction detected at the end of the ZOL label @%s"),
3140 1.1.1.3 christos S_GET_NAME (s));
3141 1.1.1.3 christos
3142 1.1.1.3 christos if (arc_last_insns[0].has_limm
3143 1.1.1.3 christos && is_br_jmp_insn_p (arc_last_insns[0].opcode))
3144 1.1.1.3 christos as_bad (_("A jump instruction with long immediate detected at the \
3145 1.1.1.3 christos end of the ZOL label @%s"), S_GET_NAME (s));
3146 1.1.1.3 christos
3147 1.1.1.3 christos /* Fall through. */
3148 1.1.1.3 christos case bfd_mach_arc_arc700:
3149 1.1.1.3 christos if (arc_last_insns[0].has_delay_slot)
3150 1.1.1.3 christos as_bad (_("An illegal use of delay slot detected at the end of the ZOL label @%s"),
3151 1.1.1.3 christos S_GET_NAME (s));
3152 1.1.1.3 christos
3153 1.1.1.3 christos break;
3154 1.1.1.3 christos default:
3155 1.1.1.3 christos break;
3156 1.1.1.3 christos }
3157 1.1.1.3 christos }
3158 1.1.1.3 christos
3159 1.1.1.3 christos /* If ZOL end check the last two instruction for illegals. */
3160 1.1.1.3 christos void
3161 1.1.1.3 christos arc_frob_label (symbolS * sym)
3162 1.1.1.3 christos {
3163 1.1.1.3 christos if (ARC_GET_FLAG (sym) & ARC_FLAG_ZOL)
3164 1.1.1.3 christos check_zol (sym);
3165 1.1.1.3 christos
3166 1.1.1.3 christos dwarf2_emit_label (sym);
3167 1.1 skrll }
3168