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