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