tc-frv.c revision 1.1.1.7 1 1.1 skrll /* tc-frv.c -- Assembler for the Fujitsu FRV.
2 1.1.1.7 christos Copyright (C) 2002-2022 Free Software Foundation, Inc.
3 1.1 skrll
4 1.1 skrll This file is part of GAS, the GNU Assembler.
5 1.1 skrll
6 1.1 skrll GAS is free software; you can redistribute it and/or modify
7 1.1 skrll it under the terms of the GNU General Public License as published by
8 1.1 skrll the Free Software Foundation; either version 3, or (at your option)
9 1.1 skrll any later version.
10 1.1 skrll
11 1.1 skrll GAS is distributed in the hope that it will be useful,
12 1.1 skrll but WITHOUT ANY WARRANTY; without even the implied warranty of
13 1.1 skrll MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 1.1 skrll GNU General Public License for more details.
15 1.1 skrll
16 1.1 skrll You should have received a copy of the GNU General Public License
17 1.1 skrll along with GAS; see the file COPYING. If not, write to
18 1.1 skrll the Free Software Foundation, 51 Franklin Street - Fifth Floor,
19 1.1 skrll Boston, MA 02110-1301, USA. */
20 1.1 skrll
21 1.1 skrll #include "as.h"
22 1.1.1.3 christos #include "subsegs.h"
23 1.1 skrll #include "symcat.h"
24 1.1 skrll #include "opcodes/frv-desc.h"
25 1.1 skrll #include "opcodes/frv-opc.h"
26 1.1 skrll #include "cgen.h"
27 1.1 skrll #include "elf/common.h"
28 1.1 skrll #include "elf/frv.h"
29 1.1.1.2 christos #include "dwarf2dbg.h"
30 1.1 skrll
31 1.1 skrll /* Structure to hold all of the different components describing
32 1.1 skrll an individual instruction. */
33 1.1 skrll typedef struct
34 1.1 skrll {
35 1.1 skrll const CGEN_INSN * insn;
36 1.1 skrll const CGEN_INSN * orig_insn;
37 1.1 skrll CGEN_FIELDS fields;
38 1.1 skrll #if CGEN_INT_INSN_P
39 1.1 skrll CGEN_INSN_INT buffer [1];
40 1.1 skrll #define INSN_VALUE(buf) (*(buf))
41 1.1 skrll #else
42 1.1 skrll unsigned char buffer [CGEN_MAX_INSN_SIZE];
43 1.1 skrll #define INSN_VALUE(buf) (buf)
44 1.1 skrll #endif
45 1.1 skrll char * addr;
46 1.1 skrll fragS * frag;
47 1.1 skrll int num_fixups;
48 1.1 skrll fixS * fixups [GAS_CGEN_MAX_FIXUPS];
49 1.1 skrll int indices [MAX_OPERAND_INSTANCES];
50 1.1 skrll }
51 1.1 skrll frv_insn;
52 1.1 skrll
53 1.1 skrll enum vliw_insn_type
54 1.1 skrll {
55 1.1 skrll VLIW_GENERIC_TYPE, /* Don't care about this insn. */
56 1.1 skrll VLIW_BRANCH_TYPE, /* A Branch. */
57 1.1 skrll VLIW_LABEL_TYPE, /* A Label. */
58 1.1 skrll VLIW_NOP_TYPE, /* A NOP. */
59 1.1 skrll VLIW_BRANCH_HAS_NOPS /* A Branch that requires NOPS. */
60 1.1 skrll };
61 1.1 skrll
62 1.1.1.3 christos /* We're going to use these in the fr_subtype field to mark
63 1.1 skrll whether to keep inserted nops. */
64 1.1 skrll
65 1.1 skrll #define NOP_KEEP 1 /* Keep these NOPS. */
66 1.1 skrll #define NOP_DELETE 2 /* Delete these NOPS. */
67 1.1 skrll
68 1.1.1.7 christos #define DO_COUNT true
69 1.1.1.7 christos #define DONT_COUNT false
70 1.1 skrll
71 1.1 skrll /* A list of insns within a VLIW insn. */
72 1.1 skrll struct vliw_insn_list
73 1.1 skrll {
74 1.1 skrll /* The type of this insn. */
75 1.1 skrll enum vliw_insn_type type;
76 1.1 skrll
77 1.1 skrll /* The corresponding gas insn information. */
78 1.1 skrll const CGEN_INSN *insn;
79 1.1 skrll
80 1.1 skrll /* For branches and labels, the symbol that is referenced. */
81 1.1 skrll symbolS *sym;
82 1.1 skrll
83 1.1 skrll /* For branches, the frag containing the single nop that was generated. */
84 1.1 skrll fragS *snop_frag;
85 1.1 skrll
86 1.1 skrll /* For branches, the frag containing the double nop that was generated. */
87 1.1 skrll fragS *dnop_frag;
88 1.1 skrll
89 1.1 skrll /* Pointer to raw data for this insn. */
90 1.1 skrll char *address;
91 1.1 skrll
92 1.1 skrll /* Next insn in list. */
93 1.1 skrll struct vliw_insn_list *next;
94 1.1 skrll };
95 1.1 skrll
96 1.1 skrll static struct vliw_insn_list single_nop_insn = {
97 1.1 skrll VLIW_NOP_TYPE, NULL, NULL, NULL, NULL, NULL, NULL };
98 1.1 skrll
99 1.1 skrll static struct vliw_insn_list double_nop_insn = {
100 1.1 skrll VLIW_NOP_TYPE, NULL, NULL, NULL, NULL, NULL, NULL };
101 1.1 skrll
102 1.1 skrll struct vliw_chain
103 1.1 skrll {
104 1.1 skrll int num;
105 1.1 skrll int insn_count;
106 1.1 skrll struct vliw_insn_list *insn_list;
107 1.1 skrll struct vliw_chain *next;
108 1.1 skrll };
109 1.1 skrll
110 1.1 skrll static struct vliw_chain *vliw_chain_top;
111 1.1 skrll static struct vliw_chain *current_vliw_chain;
112 1.1 skrll static struct vliw_chain *previous_vliw_chain;
113 1.1 skrll static struct vliw_insn_list *current_vliw_insn;
114 1.1 skrll
115 1.1 skrll const char comment_chars[] = ";";
116 1.1 skrll const char line_comment_chars[] = "#";
117 1.1.1.3 christos const char line_separator_chars[] = "!";
118 1.1 skrll const char EXP_CHARS[] = "eE";
119 1.1 skrll const char FLT_CHARS[] = "dD";
120 1.1 skrll
121 1.1 skrll static FRV_VLIW vliw;
122 1.1 skrll
123 1.1 skrll /* Default machine */
124 1.1 skrll
125 1.1 skrll #ifdef DEFAULT_CPU_FRV
126 1.1 skrll #define DEFAULT_MACHINE bfd_mach_frv
127 1.1 skrll #define DEFAULT_FLAGS EF_FRV_CPU_GENERIC
128 1.1 skrll
129 1.1 skrll #else
130 1.1 skrll #ifdef DEFAULT_CPU_FR300
131 1.1 skrll #define DEFAULT_MACHINE bfd_mach_fr300
132 1.1 skrll #define DEFAULT_FLAGS EF_FRV_CPU_FR300
133 1.1 skrll
134 1.1 skrll #else
135 1.1 skrll #ifdef DEFAULT_CPU_SIMPLE
136 1.1 skrll #define DEFAULT_MACHINE bfd_mach_frvsimple
137 1.1 skrll #define DEFAULT_FLAGS EF_FRV_CPU_SIMPLE
138 1.1 skrll
139 1.1 skrll #else
140 1.1 skrll #ifdef DEFAULT_CPU_TOMCAT
141 1.1 skrll #define DEFAULT_MACHINE bfd_mach_frvtomcat
142 1.1 skrll #define DEFAULT_FLAGS EF_FRV_CPU_TOMCAT
143 1.1 skrll
144 1.1 skrll #else
145 1.1 skrll #ifdef DEFAULT_CPU_FR400
146 1.1 skrll #define DEFAULT_MACHINE bfd_mach_fr400
147 1.1 skrll #define DEFAULT_FLAGS EF_FRV_CPU_FR400
148 1.1 skrll
149 1.1 skrll #else
150 1.1 skrll #ifdef DEFAULT_CPU_FR550
151 1.1 skrll #define DEFAULT_MACHINE bfd_mach_fr550
152 1.1 skrll #define DEFAULT_FLAGS EF_FRV_CPU_FR550
153 1.1 skrll
154 1.1 skrll #else
155 1.1 skrll #define DEFAULT_MACHINE bfd_mach_fr500
156 1.1 skrll #define DEFAULT_FLAGS EF_FRV_CPU_FR500
157 1.1 skrll #endif
158 1.1 skrll #endif
159 1.1 skrll #endif
160 1.1 skrll #endif
161 1.1 skrll #endif
162 1.1 skrll #endif
163 1.1 skrll
164 1.1 skrll #ifdef TE_LINUX
165 1.1 skrll # define DEFAULT_FDPIC EF_FRV_FDPIC
166 1.1 skrll #else
167 1.1 skrll # define DEFAULT_FDPIC 0
168 1.1 skrll #endif
169 1.1 skrll
170 1.1 skrll static unsigned long frv_mach = bfd_mach_frv;
171 1.1.1.7 christos static bool fr400_audio;
172 1.1 skrll
173 1.1 skrll /* Flags to set in the elf header */
174 1.1 skrll static flagword frv_flags = DEFAULT_FLAGS | DEFAULT_FDPIC;
175 1.1 skrll
176 1.1 skrll static int frv_user_set_flags_p = 0;
177 1.1 skrll static int frv_pic_p = 0;
178 1.1 skrll static const char *frv_pic_flag = DEFAULT_FDPIC ? "-mfdpic" : (const char *)0;
179 1.1 skrll
180 1.1 skrll /* Print tomcat-specific debugging info. */
181 1.1 skrll static int tomcat_debug = 0;
182 1.1 skrll
183 1.1 skrll /* Tomcat-specific NOP statistics. */
184 1.1 skrll static int tomcat_stats = 0;
185 1.1 skrll static int tomcat_doubles = 0;
186 1.1 skrll static int tomcat_singles = 0;
187 1.1 skrll
188 1.1 skrll /* Forward reference to static functions */
189 1.1 skrll static void frv_set_flags (int);
190 1.1 skrll static void frv_pic_ptr (int);
191 1.1 skrll
192 1.1 skrll /* The target specific pseudo-ops which we support. */
193 1.1 skrll const pseudo_typeS md_pseudo_table[] =
194 1.1 skrll {
195 1.1 skrll { "eflags", frv_set_flags, 0 },
196 1.1 skrll { "word", cons, 4 },
197 1.1 skrll { "picptr", frv_pic_ptr, 4 },
198 1.1 skrll { NULL, NULL, 0 }
199 1.1 skrll };
200 1.1 skrll
201 1.1 skrll
202 1.1 skrll #define FRV_SHORTOPTS "G:"
204 1.1 skrll const char * md_shortopts = FRV_SHORTOPTS;
205 1.1 skrll
206 1.1 skrll #define OPTION_GPR_32 (OPTION_MD_BASE)
207 1.1 skrll #define OPTION_GPR_64 (OPTION_MD_BASE + 1)
208 1.1 skrll #define OPTION_FPR_32 (OPTION_MD_BASE + 2)
209 1.1 skrll #define OPTION_FPR_64 (OPTION_MD_BASE + 3)
210 1.1 skrll #define OPTION_SOFT_FLOAT (OPTION_MD_BASE + 4)
211 1.1 skrll #define OPTION_DWORD_YES (OPTION_MD_BASE + 5)
212 1.1 skrll #define OPTION_DWORD_NO (OPTION_MD_BASE + 6)
213 1.1 skrll #define OPTION_DOUBLE (OPTION_MD_BASE + 7)
214 1.1 skrll #define OPTION_NO_DOUBLE (OPTION_MD_BASE + 8)
215 1.1 skrll #define OPTION_MEDIA (OPTION_MD_BASE + 9)
216 1.1 skrll #define OPTION_NO_MEDIA (OPTION_MD_BASE + 10)
217 1.1 skrll #define OPTION_CPU (OPTION_MD_BASE + 11)
218 1.1 skrll #define OPTION_PIC (OPTION_MD_BASE + 12)
219 1.1 skrll #define OPTION_BIGPIC (OPTION_MD_BASE + 13)
220 1.1 skrll #define OPTION_LIBPIC (OPTION_MD_BASE + 14)
221 1.1 skrll #define OPTION_MULADD (OPTION_MD_BASE + 15)
222 1.1 skrll #define OPTION_NO_MULADD (OPTION_MD_BASE + 16)
223 1.1 skrll #define OPTION_TOMCAT_DEBUG (OPTION_MD_BASE + 17)
224 1.1 skrll #define OPTION_TOMCAT_STATS (OPTION_MD_BASE + 18)
225 1.1 skrll #define OPTION_PACK (OPTION_MD_BASE + 19)
226 1.1 skrll #define OPTION_NO_PACK (OPTION_MD_BASE + 20)
227 1.1 skrll #define OPTION_FDPIC (OPTION_MD_BASE + 21)
228 1.1 skrll #define OPTION_NOPIC (OPTION_MD_BASE + 22)
229 1.1 skrll
230 1.1 skrll struct option md_longopts[] =
231 1.1 skrll {
232 1.1 skrll { "mgpr-32", no_argument, NULL, OPTION_GPR_32 },
233 1.1 skrll { "mgpr-64", no_argument, NULL, OPTION_GPR_64 },
234 1.1 skrll { "mfpr-32", no_argument, NULL, OPTION_FPR_32 },
235 1.1 skrll { "mfpr-64", no_argument, NULL, OPTION_FPR_64 },
236 1.1 skrll { "mhard-float", no_argument, NULL, OPTION_FPR_64 },
237 1.1 skrll { "msoft-float", no_argument, NULL, OPTION_SOFT_FLOAT },
238 1.1 skrll { "mdword", no_argument, NULL, OPTION_DWORD_YES },
239 1.1 skrll { "mno-dword", no_argument, NULL, OPTION_DWORD_NO },
240 1.1 skrll { "mdouble", no_argument, NULL, OPTION_DOUBLE },
241 1.1 skrll { "mno-double", no_argument, NULL, OPTION_NO_DOUBLE },
242 1.1 skrll { "mmedia", no_argument, NULL, OPTION_MEDIA },
243 1.1 skrll { "mno-media", no_argument, NULL, OPTION_NO_MEDIA },
244 1.1 skrll { "mcpu", required_argument, NULL, OPTION_CPU },
245 1.1 skrll { "mpic", no_argument, NULL, OPTION_PIC },
246 1.1 skrll { "mPIC", no_argument, NULL, OPTION_BIGPIC },
247 1.1 skrll { "mlibrary-pic", no_argument, NULL, OPTION_LIBPIC },
248 1.1 skrll { "mmuladd", no_argument, NULL, OPTION_MULADD },
249 1.1 skrll { "mno-muladd", no_argument, NULL, OPTION_NO_MULADD },
250 1.1 skrll { "mtomcat-debug", no_argument, NULL, OPTION_TOMCAT_DEBUG },
251 1.1 skrll { "mtomcat-stats", no_argument, NULL, OPTION_TOMCAT_STATS },
252 1.1 skrll { "mpack", no_argument, NULL, OPTION_PACK },
253 1.1 skrll { "mno-pack", no_argument, NULL, OPTION_NO_PACK },
254 1.1 skrll { "mfdpic", no_argument, NULL, OPTION_FDPIC },
255 1.1 skrll { "mnopic", no_argument, NULL, OPTION_NOPIC },
256 1.1 skrll { NULL, no_argument, NULL, 0 },
257 1.1 skrll };
258 1.1 skrll
259 1.1 skrll size_t md_longopts_size = sizeof (md_longopts);
260 1.1 skrll
261 1.1 skrll /* What value to give to bfd_set_gp_size. */
262 1.1 skrll static int g_switch_value = 8;
263 1.1 skrll
264 1.1.1.4 christos int
265 1.1 skrll md_parse_option (int c, const char *arg)
266 1.1 skrll {
267 1.1 skrll switch (c)
268 1.1 skrll {
269 1.1 skrll default:
270 1.1 skrll return 0;
271 1.1 skrll
272 1.1 skrll case 'G':
273 1.1 skrll g_switch_value = atoi (arg);
274 1.1 skrll if (! g_switch_value)
275 1.1 skrll frv_flags |= EF_FRV_G0;
276 1.1 skrll break;
277 1.1 skrll
278 1.1 skrll case OPTION_GPR_32:
279 1.1 skrll frv_flags = (frv_flags & ~EF_FRV_GPR_MASK) | EF_FRV_GPR_32;
280 1.1 skrll break;
281 1.1 skrll
282 1.1 skrll case OPTION_GPR_64:
283 1.1 skrll frv_flags = (frv_flags & ~EF_FRV_GPR_MASK) | EF_FRV_GPR_64;
284 1.1 skrll break;
285 1.1 skrll
286 1.1 skrll case OPTION_FPR_32:
287 1.1 skrll frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_32;
288 1.1 skrll break;
289 1.1 skrll
290 1.1 skrll case OPTION_FPR_64:
291 1.1 skrll frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_64;
292 1.1 skrll break;
293 1.1 skrll
294 1.1 skrll case OPTION_SOFT_FLOAT:
295 1.1 skrll frv_flags = (frv_flags & ~EF_FRV_FPR_MASK) | EF_FRV_FPR_NONE;
296 1.1 skrll break;
297 1.1 skrll
298 1.1 skrll case OPTION_DWORD_YES:
299 1.1 skrll frv_flags = (frv_flags & ~EF_FRV_DWORD_MASK) | EF_FRV_DWORD_YES;
300 1.1 skrll break;
301 1.1 skrll
302 1.1 skrll case OPTION_DWORD_NO:
303 1.1 skrll frv_flags = (frv_flags & ~EF_FRV_DWORD_MASK) | EF_FRV_DWORD_NO;
304 1.1 skrll break;
305 1.1 skrll
306 1.1 skrll case OPTION_DOUBLE:
307 1.1 skrll frv_flags |= EF_FRV_DOUBLE;
308 1.1 skrll break;
309 1.1 skrll
310 1.1 skrll case OPTION_NO_DOUBLE:
311 1.1 skrll frv_flags &= ~EF_FRV_DOUBLE;
312 1.1 skrll break;
313 1.1 skrll
314 1.1 skrll case OPTION_MEDIA:
315 1.1 skrll frv_flags |= EF_FRV_MEDIA;
316 1.1 skrll break;
317 1.1 skrll
318 1.1 skrll case OPTION_NO_MEDIA:
319 1.1 skrll frv_flags &= ~EF_FRV_MEDIA;
320 1.1 skrll break;
321 1.1 skrll
322 1.1 skrll case OPTION_MULADD:
323 1.1 skrll frv_flags |= EF_FRV_MULADD;
324 1.1 skrll break;
325 1.1 skrll
326 1.1 skrll case OPTION_NO_MULADD:
327 1.1 skrll frv_flags &= ~EF_FRV_MULADD;
328 1.1 skrll break;
329 1.1 skrll
330 1.1 skrll case OPTION_PACK:
331 1.1 skrll frv_flags &= ~EF_FRV_NOPACK;
332 1.1 skrll break;
333 1.1 skrll
334 1.1 skrll case OPTION_NO_PACK:
335 1.1 skrll frv_flags |= EF_FRV_NOPACK;
336 1.1 skrll break;
337 1.1 skrll
338 1.1 skrll case OPTION_CPU:
339 1.1.1.4 christos {
340 1.1 skrll const char *p;
341 1.1 skrll int cpu_flags = EF_FRV_CPU_GENERIC;
342 1.1 skrll
343 1.1 skrll /* Identify the processor type */
344 1.1 skrll p = arg;
345 1.1 skrll if (strcmp (p, "frv") == 0)
346 1.1 skrll {
347 1.1 skrll cpu_flags = EF_FRV_CPU_GENERIC;
348 1.1 skrll frv_mach = bfd_mach_frv;
349 1.1 skrll }
350 1.1 skrll
351 1.1 skrll else if (strcmp (p, "fr500") == 0)
352 1.1 skrll {
353 1.1 skrll cpu_flags = EF_FRV_CPU_FR500;
354 1.1 skrll frv_mach = bfd_mach_fr500;
355 1.1 skrll }
356 1.1 skrll
357 1.1 skrll else if (strcmp (p, "fr550") == 0)
358 1.1 skrll {
359 1.1 skrll cpu_flags = EF_FRV_CPU_FR550;
360 1.1 skrll frv_mach = bfd_mach_fr550;
361 1.1 skrll }
362 1.1 skrll
363 1.1 skrll else if (strcmp (p, "fr450") == 0)
364 1.1 skrll {
365 1.1 skrll cpu_flags = EF_FRV_CPU_FR450;
366 1.1 skrll frv_mach = bfd_mach_fr450;
367 1.1 skrll }
368 1.1 skrll
369 1.1 skrll else if (strcmp (p, "fr405") == 0)
370 1.1 skrll {
371 1.1 skrll cpu_flags = EF_FRV_CPU_FR405;
372 1.1.1.7 christos frv_mach = bfd_mach_fr400;
373 1.1 skrll fr400_audio = true;
374 1.1 skrll }
375 1.1 skrll
376 1.1 skrll else if (strcmp (p, "fr400") == 0)
377 1.1 skrll {
378 1.1 skrll cpu_flags = EF_FRV_CPU_FR400;
379 1.1.1.7 christos frv_mach = bfd_mach_fr400;
380 1.1 skrll fr400_audio = false;
381 1.1 skrll }
382 1.1 skrll
383 1.1 skrll else if (strcmp (p, "fr300") == 0)
384 1.1 skrll {
385 1.1 skrll cpu_flags = EF_FRV_CPU_FR300;
386 1.1 skrll frv_mach = bfd_mach_fr300;
387 1.1 skrll }
388 1.1 skrll
389 1.1 skrll else if (strcmp (p, "simple") == 0)
390 1.1 skrll {
391 1.1 skrll cpu_flags = EF_FRV_CPU_SIMPLE;
392 1.1 skrll frv_mach = bfd_mach_frvsimple;
393 1.1 skrll frv_flags |= EF_FRV_NOPACK;
394 1.1 skrll }
395 1.1 skrll
396 1.1 skrll else if (strcmp (p, "tomcat") == 0)
397 1.1 skrll {
398 1.1 skrll cpu_flags = EF_FRV_CPU_TOMCAT;
399 1.1 skrll frv_mach = bfd_mach_frvtomcat;
400 1.1 skrll }
401 1.1 skrll
402 1.1 skrll else
403 1.1 skrll {
404 1.1 skrll as_fatal (_("Unknown cpu -mcpu=%s"), arg);
405 1.1 skrll return 0;
406 1.1 skrll }
407 1.1 skrll
408 1.1 skrll frv_flags = (frv_flags & ~EF_FRV_CPU_MASK) | cpu_flags;
409 1.1 skrll }
410 1.1 skrll break;
411 1.1 skrll
412 1.1 skrll case OPTION_PIC:
413 1.1 skrll frv_flags |= EF_FRV_PIC;
414 1.1 skrll frv_pic_p = 1;
415 1.1 skrll frv_pic_flag = "-fpic";
416 1.1 skrll break;
417 1.1 skrll
418 1.1 skrll case OPTION_BIGPIC:
419 1.1 skrll frv_flags |= EF_FRV_BIGPIC;
420 1.1 skrll frv_pic_p = 1;
421 1.1 skrll frv_pic_flag = "-fPIC";
422 1.1 skrll break;
423 1.1 skrll
424 1.1 skrll case OPTION_LIBPIC:
425 1.1 skrll frv_flags |= (EF_FRV_LIBPIC | EF_FRV_G0);
426 1.1 skrll frv_pic_p = 1;
427 1.1 skrll frv_pic_flag = "-mlibrary-pic";
428 1.1 skrll g_switch_value = 0;
429 1.1 skrll break;
430 1.1 skrll
431 1.1 skrll case OPTION_FDPIC:
432 1.1 skrll frv_flags |= EF_FRV_FDPIC;
433 1.1 skrll frv_pic_flag = "-mfdpic";
434 1.1 skrll break;
435 1.1 skrll
436 1.1 skrll case OPTION_NOPIC:
437 1.1 skrll frv_flags &= ~(EF_FRV_FDPIC | EF_FRV_PIC
438 1.1 skrll | EF_FRV_BIGPIC | EF_FRV_LIBPIC);
439 1.1 skrll frv_pic_flag = 0;
440 1.1 skrll break;
441 1.1 skrll
442 1.1 skrll case OPTION_TOMCAT_DEBUG:
443 1.1 skrll tomcat_debug = 1;
444 1.1 skrll break;
445 1.1 skrll
446 1.1 skrll case OPTION_TOMCAT_STATS:
447 1.1 skrll tomcat_stats = 1;
448 1.1 skrll break;
449 1.1 skrll }
450 1.1 skrll
451 1.1 skrll return 1;
452 1.1 skrll }
453 1.1 skrll
454 1.1 skrll void
455 1.1 skrll md_show_usage (FILE * stream)
456 1.1 skrll {
457 1.1 skrll fprintf (stream, _("FRV specific command line options:\n"));
458 1.1 skrll fprintf (stream, _("-G n Put data <= n bytes in the small data area\n"));
459 1.1 skrll fprintf (stream, _("-mgpr-32 Mark generated file as only using 32 GPRs\n"));
460 1.1 skrll fprintf (stream, _("-mgpr-64 Mark generated file as using all 64 GPRs\n"));
461 1.1 skrll fprintf (stream, _("-mfpr-32 Mark generated file as only using 32 FPRs\n"));
462 1.1 skrll fprintf (stream, _("-mfpr-64 Mark generated file as using all 64 FPRs\n"));
463 1.1 skrll fprintf (stream, _("-msoft-float Mark generated file as using software FP\n"));
464 1.1 skrll fprintf (stream, _("-mdword Mark generated file as using a 8-byte stack alignment\n"));
465 1.1 skrll fprintf (stream, _("-mno-dword Mark generated file as using a 4-byte stack alignment\n"));
466 1.1 skrll fprintf (stream, _("-mdouble Mark generated file as using double precision FP insns\n"));
467 1.1 skrll fprintf (stream, _("-mmedia Mark generated file as using media insns\n"));
468 1.1 skrll fprintf (stream, _("-mmuladd Mark generated file as using multiply add/subtract insns\n"));
469 1.1 skrll fprintf (stream, _("-mpack Allow instructions to be packed\n"));
470 1.1 skrll fprintf (stream, _("-mno-pack Do not allow instructions to be packed\n"));
471 1.1 skrll fprintf (stream, _("-mpic Mark generated file as using small position independent code\n"));
472 1.1.1.5 christos fprintf (stream, _("-mPIC Mark generated file as using large position independent code\n"));
473 1.1 skrll fprintf (stream, _("-mlibrary-pic Mark generated file as using position independent code for libraries\n"));
474 1.1 skrll fprintf (stream, _("-mfdpic Assemble for the FDPIC ABI\n"));
475 1.1 skrll fprintf (stream, _("-mnopic Disable -mpic, -mPIC, -mlibrary-pic and -mfdpic\n"));
476 1.1 skrll fprintf (stream, _("-mcpu={fr500|fr550|fr400|fr405|fr450|fr300|frv|simple|tomcat}\n"));
477 1.1 skrll fprintf (stream, _(" Record the cpu type\n"));
478 1.1 skrll fprintf (stream, _("-mtomcat-stats Print out stats for tomcat workarounds\n"));
479 1.1.1.3 christos fprintf (stream, _("-mtomcat-debug Debug tomcat workarounds\n"));
480 1.1 skrll }
481 1.1 skrll
482 1.1 skrll
483 1.1 skrll void
485 1.1 skrll md_begin (void)
486 1.1.1.3 christos {
487 1.1 skrll /* Initialize the `cgen' interface. */
488 1.1 skrll
489 1.1 skrll /* Set the machine number and endian. */
490 1.1 skrll gas_cgen_cpu_desc = frv_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0,
491 1.1 skrll CGEN_CPU_OPEN_ENDIAN,
492 1.1 skrll CGEN_ENDIAN_BIG,
493 1.1 skrll CGEN_CPU_OPEN_END);
494 1.1 skrll frv_cgen_init_asm (gas_cgen_cpu_desc);
495 1.1 skrll
496 1.1 skrll /* This is a callback from cgen to gas to parse operands. */
497 1.1 skrll cgen_set_parse_operand_fn (gas_cgen_cpu_desc, gas_cgen_parse_operand);
498 1.1 skrll
499 1.1 skrll /* Set the ELF flags if desired. */
500 1.1 skrll if (frv_flags)
501 1.1 skrll bfd_set_private_flags (stdoutput, frv_flags);
502 1.1 skrll
503 1.1 skrll /* Set the machine type */
504 1.1 skrll bfd_default_set_arch_mach (stdoutput, bfd_arch_frv, frv_mach);
505 1.1 skrll
506 1.1 skrll /* Set up gp size so we can put local common items in .sbss */
507 1.1 skrll bfd_set_gp_size (stdoutput, g_switch_value);
508 1.1 skrll
509 1.1 skrll frv_vliw_reset (& vliw, frv_mach, frv_flags);
510 1.1.1.7 christos }
511 1.1 skrll
512 1.1 skrll bool
513 1.1 skrll frv_md_fdpic_enabled (void)
514 1.1 skrll {
515 1.1 skrll return (frv_flags & EF_FRV_FDPIC) != 0;
516 1.1 skrll }
517 1.1 skrll
518 1.1 skrll int chain_num = 0;
519 1.1.1.7 christos
520 1.1 skrll static struct vliw_insn_list *
521 1.1 skrll frv_insert_vliw_insn (bool count)
522 1.1 skrll {
523 1.1 skrll struct vliw_insn_list *vliw_insn_list_entry;
524 1.1 skrll struct vliw_chain *vliw_chain_entry;
525 1.1 skrll
526 1.1.1.4 christos if (current_vliw_chain == NULL)
527 1.1 skrll {
528 1.1 skrll vliw_chain_entry = XNEW (struct vliw_chain);
529 1.1 skrll vliw_chain_entry->insn_count = 0;
530 1.1 skrll vliw_chain_entry->insn_list = NULL;
531 1.1 skrll vliw_chain_entry->next = NULL;
532 1.1 skrll vliw_chain_entry->num = chain_num++;
533 1.1 skrll
534 1.1 skrll if (!vliw_chain_top)
535 1.1 skrll vliw_chain_top = vliw_chain_entry;
536 1.1 skrll current_vliw_chain = vliw_chain_entry;
537 1.1 skrll if (previous_vliw_chain)
538 1.1 skrll previous_vliw_chain->next = vliw_chain_entry;
539 1.1.1.4 christos }
540 1.1 skrll
541 1.1 skrll vliw_insn_list_entry = XNEW (struct vliw_insn_list);
542 1.1 skrll vliw_insn_list_entry->type = VLIW_GENERIC_TYPE;
543 1.1 skrll vliw_insn_list_entry->insn = NULL;
544 1.1 skrll vliw_insn_list_entry->sym = NULL;
545 1.1 skrll vliw_insn_list_entry->snop_frag = NULL;
546 1.1 skrll vliw_insn_list_entry->dnop_frag = NULL;
547 1.1 skrll vliw_insn_list_entry->next = NULL;
548 1.1 skrll
549 1.1 skrll if (count)
550 1.1 skrll current_vliw_chain->insn_count++;
551 1.1 skrll
552 1.1 skrll if (current_vliw_insn)
553 1.1 skrll current_vliw_insn->next = vliw_insn_list_entry;
554 1.1 skrll current_vliw_insn = vliw_insn_list_entry;
555 1.1 skrll
556 1.1 skrll if (!current_vliw_chain->insn_list)
557 1.1 skrll current_vliw_chain->insn_list = current_vliw_insn;
558 1.1 skrll
559 1.1 skrll return vliw_insn_list_entry;
560 1.1 skrll }
561 1.1.1.3 christos
562 1.1 skrll /* Identify the following cases:
563 1.1 skrll
564 1.1 skrll 1) A VLIW insn that contains both a branch and the branch destination.
565 1.1 skrll This requires the insertion of two vliw instructions before the
566 1.1.1.3 christos branch. The first consists of two nops. The second consists of
567 1.1 skrll a single nop.
568 1.1 skrll
569 1.1 skrll 2) A single instruction VLIW insn which is the destination of a branch
570 1.1.1.3 christos that is in the next VLIW insn. This requires the insertion of a vliw
571 1.1 skrll insn containing two nops before the branch.
572 1.1 skrll
573 1.1 skrll 3) A double instruction VLIW insn which contains the destination of a
574 1.1.1.3 christos branch that is in the next VLIW insn. This requires the insertion of
575 1.1 skrll a VLIW insn containing a single nop before the branch.
576 1.1 skrll
577 1.1 skrll 4) A single instruction VLIW insn which contains branch destination (x),
578 1.1 skrll followed by a single instruction VLIW insn which does not contain
579 1.1 skrll the branch to (x), followed by a VLIW insn which does contain the branch
580 1.1.1.3 christos to (x). This requires the insertion of a VLIW insn containing a single
581 1.1 skrll nop before the VLIW instruction containing the branch.
582 1.1 skrll
583 1.1 skrll */
584 1.1 skrll #define FRV_IS_NOP(insn) (insn.buffer[0] == FRV_NOP_PACK || insn.buffer[0] == FRV_NOP_NOPACK)
585 1.1 skrll #define FRV_NOP_PACK 0x00880000 /* ori.p gr0,0,gr0 */
586 1.1 skrll #define FRV_NOP_NOPACK 0x80880000 /* ori gr0,0,gr0 */
587 1.1 skrll
588 1.1 skrll /* Check a vliw insn for an insn of type containing the sym passed in label_sym. */
589 1.1 skrll
590 1.1 skrll static struct vliw_insn_list *
591 1.1 skrll frv_find_in_vliw (enum vliw_insn_type vliw_insn_type,
592 1.1 skrll struct vliw_chain *this_chain,
593 1.1 skrll symbolS *label_sym)
594 1.1 skrll {
595 1.1 skrll
596 1.1 skrll struct vliw_insn_list *the_insn;
597 1.1 skrll
598 1.1 skrll if (!this_chain)
599 1.1 skrll return NULL;
600 1.1 skrll
601 1.1 skrll for (the_insn = this_chain->insn_list; the_insn; the_insn = the_insn->next)
602 1.1 skrll {
603 1.1 skrll if (the_insn->type == vliw_insn_type
604 1.1 skrll && the_insn->sym == label_sym)
605 1.1 skrll return the_insn;
606 1.1 skrll }
607 1.1 skrll
608 1.1 skrll return NULL;
609 1.1 skrll }
610 1.1 skrll
611 1.1 skrll enum vliw_nop_type
612 1.1 skrll {
613 1.1.1.3 christos /* A Vliw insn containing a single nop insn. */
614 1.1 skrll VLIW_SINGLE_NOP,
615 1.1 skrll
616 1.1 skrll /* A Vliw insn containing two nop insns. */
617 1.1.1.3 christos VLIW_DOUBLE_NOP,
618 1.1 skrll
619 1.1 skrll /* Two vliw insns. The first containing two nop insns.
620 1.1 skrll The second contain a single nop insn. */
621 1.1 skrll VLIW_DOUBLE_THEN_SINGLE_NOP
622 1.1 skrll };
623 1.1 skrll
624 1.1 skrll static void
625 1.1 skrll frv_debug_tomcat (struct vliw_chain *start_chain)
626 1.1 skrll {
627 1.1 skrll struct vliw_chain *this_chain;
628 1.1 skrll struct vliw_insn_list *this_insn;
629 1.1 skrll int i = 1;
630 1.1 skrll
631 1.1 skrll for (this_chain = start_chain; this_chain; this_chain = this_chain->next, i++)
632 1.1 skrll {
633 1.1 skrll fprintf (stderr, "\nVliw Insn #%d, #insns: %d\n", i, this_chain->insn_count);
634 1.1 skrll
635 1.1 skrll for (this_insn = this_chain->insn_list; this_insn; this_insn = this_insn->next)
636 1.1 skrll {
637 1.1 skrll if (this_insn->type == VLIW_LABEL_TYPE)
638 1.1 skrll fprintf (stderr, "Label Value: %p\n", this_insn->sym);
639 1.1 skrll else if (this_insn->type == VLIW_BRANCH_TYPE)
640 1.1 skrll fprintf (stderr, "%s to %p\n", this_insn->insn->base->name, this_insn->sym);
641 1.1 skrll else if (this_insn->type == VLIW_BRANCH_HAS_NOPS)
642 1.1 skrll fprintf (stderr, "nop'd %s to %p\n", this_insn->insn->base->name, this_insn->sym);
643 1.1 skrll else if (this_insn->type == VLIW_NOP_TYPE)
644 1.1 skrll fprintf (stderr, "Nop\n");
645 1.1 skrll else
646 1.1 skrll fprintf (stderr, " %s\n", this_insn->insn->base->name);
647 1.1 skrll }
648 1.1 skrll }
649 1.1 skrll }
650 1.1 skrll
651 1.1 skrll static void
652 1.1 skrll frv_adjust_vliw_count (struct vliw_chain *this_chain)
653 1.1 skrll {
654 1.1 skrll struct vliw_insn_list *this_insn;
655 1.1 skrll
656 1.1 skrll this_chain->insn_count = 0;
657 1.1 skrll
658 1.1 skrll for (this_insn = this_chain->insn_list;
659 1.1 skrll this_insn;
660 1.1 skrll this_insn = this_insn->next)
661 1.1 skrll {
662 1.1 skrll if (this_insn->type != VLIW_LABEL_TYPE)
663 1.1 skrll this_chain->insn_count++;
664 1.1 skrll }
665 1.1 skrll
666 1.1 skrll }
667 1.1 skrll
668 1.1 skrll /* Insert the desired nop combination in the vliw chain before insert_before_insn.
669 1.1 skrll Rechain the vliw insn. */
670 1.1 skrll
671 1.1 skrll static struct vliw_chain *
672 1.1 skrll frv_tomcat_shuffle (enum vliw_nop_type this_nop_type,
673 1.1 skrll struct vliw_chain *vliw_to_split,
674 1.1 skrll struct vliw_insn_list *insert_before_insn)
675 1.1.1.7 christos {
676 1.1 skrll
677 1.1 skrll bool pack_prev = false;
678 1.1 skrll struct vliw_chain *return_me = NULL;
679 1.1 skrll struct vliw_insn_list *prev_insn = NULL;
680 1.1.1.4 christos struct vliw_insn_list *curr_insn = vliw_to_split->insn_list;
681 1.1.1.4 christos
682 1.1.1.4 christos struct vliw_chain *double_nop = XNEW (struct vliw_chain);
683 1.1 skrll struct vliw_chain *single_nop = XNEW (struct vliw_chain);
684 1.1 skrll struct vliw_chain *second_part = XNEW (struct vliw_chain);
685 1.1 skrll struct vliw_chain *curr_vliw = vliw_chain_top;
686 1.1 skrll struct vliw_chain *prev_vliw = NULL;
687 1.1 skrll
688 1.1 skrll while (curr_insn && curr_insn != insert_before_insn)
689 1.1 skrll {
690 1.1 skrll /* We can't set the packing bit on a label. If we have the case
691 1.1 skrll label 1:
692 1.1 skrll label 2:
693 1.1 skrll label 3:
694 1.1 skrll branch that needs nops
695 1.1 skrll Then don't set pack bit later. */
696 1.1.1.7 christos
697 1.1 skrll if (curr_insn->type != VLIW_LABEL_TYPE)
698 1.1 skrll pack_prev = true;
699 1.1.1.3 christos prev_insn = curr_insn;
700 1.1 skrll curr_insn = curr_insn->next;
701 1.1 skrll }
702 1.1 skrll
703 1.1 skrll while (curr_vliw && curr_vliw != vliw_to_split)
704 1.1 skrll {
705 1.1 skrll prev_vliw = curr_vliw;
706 1.1 skrll curr_vliw = curr_vliw->next;
707 1.1 skrll }
708 1.1 skrll
709 1.1 skrll switch (this_nop_type)
710 1.1 skrll {
711 1.1 skrll case VLIW_SINGLE_NOP:
712 1.1 skrll if (!prev_insn)
713 1.1 skrll {
714 1.1 skrll /* Branch is first, Insert the NOP prior to this vliw insn. */
715 1.1 skrll if (prev_vliw)
716 1.1 skrll prev_vliw->next = single_nop;
717 1.1 skrll else
718 1.1 skrll vliw_chain_top = single_nop;
719 1.1 skrll single_nop->next = vliw_to_split;
720 1.1 skrll vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS;
721 1.1 skrll return_me = vliw_to_split;
722 1.1 skrll }
723 1.1 skrll else
724 1.1 skrll {
725 1.1 skrll /* Set the packing bit on the previous insn. */
726 1.1 skrll if (pack_prev)
727 1.1 skrll {
728 1.1 skrll char *buffer = prev_insn->address;
729 1.1 skrll buffer[0] |= 0x80;
730 1.1.1.5 christos }
731 1.1 skrll /* The branch is in the middle. Split this vliw insn into first
732 1.1 skrll and second parts. Insert the NOP between. */
733 1.1 skrll
734 1.1 skrll second_part->insn_list = insert_before_insn;
735 1.1 skrll second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS;
736 1.1 skrll second_part->next = vliw_to_split->next;
737 1.1 skrll frv_adjust_vliw_count (second_part);
738 1.1.1.3 christos
739 1.1 skrll single_nop->next = second_part;
740 1.1 skrll
741 1.1.1.3 christos vliw_to_split->next = single_nop;
742 1.1 skrll prev_insn->next = NULL;
743 1.1 skrll
744 1.1 skrll return_me = second_part;
745 1.1 skrll frv_adjust_vliw_count (vliw_to_split);
746 1.1 skrll }
747 1.1 skrll break;
748 1.1 skrll
749 1.1 skrll case VLIW_DOUBLE_NOP:
750 1.1 skrll if (!prev_insn)
751 1.1 skrll {
752 1.1 skrll /* Branch is first, Insert the NOP prior to this vliw insn. */
753 1.1 skrll if (prev_vliw)
754 1.1 skrll prev_vliw->next = double_nop;
755 1.1 skrll else
756 1.1 skrll vliw_chain_top = double_nop;
757 1.1 skrll
758 1.1 skrll double_nop->next = vliw_to_split;
759 1.1 skrll return_me = vliw_to_split;
760 1.1 skrll vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS;
761 1.1 skrll }
762 1.1 skrll else
763 1.1 skrll {
764 1.1 skrll /* Set the packing bit on the previous insn. */
765 1.1 skrll if (pack_prev)
766 1.1 skrll {
767 1.1 skrll char *buffer = prev_insn->address;
768 1.1 skrll buffer[0] |= 0x80;
769 1.1 skrll }
770 1.1.1.5 christos
771 1.1 skrll /* The branch is in the middle. Split this vliw insn into first
772 1.1 skrll and second parts. Insert the NOP in between. */
773 1.1 skrll second_part->insn_list = insert_before_insn;
774 1.1 skrll second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS;
775 1.1.1.3 christos second_part->next = vliw_to_split->next;
776 1.1 skrll frv_adjust_vliw_count (second_part);
777 1.1.1.3 christos
778 1.1 skrll double_nop->next = second_part;
779 1.1 skrll
780 1.1 skrll vliw_to_split->next = single_nop;
781 1.1.1.3 christos prev_insn->next = NULL;
782 1.1 skrll frv_adjust_vliw_count (vliw_to_split);
783 1.1 skrll
784 1.1 skrll return_me = second_part;
785 1.1 skrll }
786 1.1 skrll break;
787 1.1 skrll
788 1.1 skrll case VLIW_DOUBLE_THEN_SINGLE_NOP:
789 1.1 skrll double_nop->next = single_nop;
790 1.1 skrll double_nop->insn_count = 2;
791 1.1 skrll double_nop->insn_list = &double_nop_insn;
792 1.1 skrll single_nop->insn_count = 1;
793 1.1 skrll single_nop->insn_list = &single_nop_insn;
794 1.1 skrll
795 1.1 skrll if (!prev_insn)
796 1.1 skrll {
797 1.1 skrll /* The branch is the first insn in this vliw. Don't split the vliw. Insert
798 1.1 skrll the nops prior to this vliw. */
799 1.1 skrll if (prev_vliw)
800 1.1 skrll prev_vliw->next = double_nop;
801 1.1.1.3 christos else
802 1.1 skrll vliw_chain_top = double_nop;
803 1.1 skrll
804 1.1 skrll single_nop->next = vliw_to_split;
805 1.1 skrll return_me = vliw_to_split;
806 1.1 skrll vliw_to_split->insn_list->type = VLIW_BRANCH_HAS_NOPS;
807 1.1 skrll }
808 1.1 skrll else
809 1.1 skrll {
810 1.1 skrll /* Set the packing bit on the previous insn. */
811 1.1 skrll if (pack_prev)
812 1.1 skrll {
813 1.1 skrll char *buffer = prev_insn->address;
814 1.1 skrll buffer[0] |= 0x80;
815 1.1 skrll }
816 1.1.1.3 christos
817 1.1 skrll /* The branch is in the middle of this vliw insn. Split into first and
818 1.1 skrll second parts. Insert the nop vliws in between. */
819 1.1 skrll second_part->insn_list = insert_before_insn;
820 1.1 skrll second_part->insn_list->type = VLIW_BRANCH_HAS_NOPS;
821 1.1 skrll second_part->next = vliw_to_split->next;
822 1.1 skrll frv_adjust_vliw_count (second_part);
823 1.1 skrll
824 1.1 skrll single_nop->next = second_part;
825 1.1 skrll
826 1.1 skrll vliw_to_split->next = double_nop;
827 1.1 skrll prev_insn->next = NULL;
828 1.1 skrll frv_adjust_vliw_count (vliw_to_split);
829 1.1 skrll
830 1.1 skrll return_me = second_part;
831 1.1 skrll }
832 1.1 skrll break;
833 1.1 skrll }
834 1.1 skrll
835 1.1 skrll return return_me;
836 1.1 skrll }
837 1.1 skrll
838 1.1 skrll static void
839 1.1 skrll frv_tomcat_analyze_vliw_chains (void)
840 1.1 skrll {
841 1.1 skrll struct vliw_chain *vliw1 = NULL;
842 1.1 skrll struct vliw_chain *vliw2 = NULL;
843 1.1 skrll struct vliw_chain *vliw3 = NULL;
844 1.1 skrll
845 1.1 skrll struct vliw_insn_list *this_insn = NULL;
846 1.1 skrll struct vliw_insn_list *temp_insn = NULL;
847 1.1 skrll
848 1.1 skrll /* We potentially need to look at three VLIW insns to determine if the
849 1.1 skrll workaround is required. Set them up. Ignore existing nops during analysis. */
850 1.1 skrll
851 1.1 skrll #define FRV_SET_VLIW_WINDOW(VLIW1, VLIW2, VLIW3) \
852 1.1 skrll if (VLIW1 && VLIW1->next) \
853 1.1 skrll VLIW2 = VLIW1->next; \
854 1.1 skrll else \
855 1.1 skrll VLIW2 = NULL; \
856 1.1 skrll if (VLIW2 && VLIW2->next) \
857 1.1 skrll VLIW3 = VLIW2->next; \
858 1.1 skrll else \
859 1.1 skrll VLIW3 = NULL
860 1.1 skrll
861 1.1.1.7 christos vliw1 = vliw_chain_top;
862 1.1 skrll
863 1.1 skrll workaround_top:
864 1.1 skrll
865 1.1 skrll FRV_SET_VLIW_WINDOW (vliw1, vliw2, vliw3);
866 1.1 skrll
867 1.1 skrll if (!vliw1)
868 1.1 skrll return;
869 1.1 skrll
870 1.1 skrll if (vliw1->insn_count == 1)
871 1.1 skrll {
872 1.1 skrll /* check vliw1 for a label. */
873 1.1 skrll if (vliw1->insn_list->type == VLIW_LABEL_TYPE)
874 1.1 skrll {
875 1.1 skrll temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw2, vliw1->insn_list->sym);
876 1.1 skrll if (temp_insn)
877 1.1 skrll {
878 1.1 skrll vliw1 = frv_tomcat_shuffle (VLIW_DOUBLE_NOP, vliw2, vliw1->insn_list);
879 1.1 skrll temp_insn->dnop_frag->fr_subtype = NOP_KEEP;
880 1.1 skrll vliw1 = vliw1->next;
881 1.1 skrll if (tomcat_stats)
882 1.1 skrll tomcat_doubles++;
883 1.1.1.3 christos goto workaround_top;
884 1.1 skrll }
885 1.1 skrll else if (vliw2
886 1.1 skrll && vliw2->insn_count == 1
887 1.1 skrll && (temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw3, vliw1->insn_list->sym)) != NULL)
888 1.1 skrll {
889 1.1 skrll temp_insn->snop_frag->fr_subtype = NOP_KEEP;
890 1.1 skrll vliw1 = frv_tomcat_shuffle (VLIW_SINGLE_NOP, vliw3, vliw3->insn_list);
891 1.1 skrll if (tomcat_stats)
892 1.1 skrll tomcat_singles++;
893 1.1 skrll goto workaround_top;
894 1.1 skrll }
895 1.1 skrll }
896 1.1 skrll }
897 1.1 skrll
898 1.1.1.2 christos if (vliw1->insn_count == 2)
899 1.1 skrll {
900 1.1 skrll /* Check vliw1 for a label. */
901 1.1 skrll for (this_insn = vliw1->insn_list; this_insn; this_insn = this_insn->next)
902 1.1 skrll {
903 1.1 skrll if (this_insn->type == VLIW_LABEL_TYPE)
904 1.1 skrll {
905 1.1 skrll if ((temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw2, this_insn->sym)) != NULL)
906 1.1 skrll {
907 1.1 skrll temp_insn->snop_frag->fr_subtype = NOP_KEEP;
908 1.1 skrll vliw1 = frv_tomcat_shuffle (VLIW_SINGLE_NOP, vliw2, this_insn);
909 1.1 skrll if (tomcat_stats)
910 1.1 skrll tomcat_singles++;
911 1.1 skrll }
912 1.1 skrll else
913 1.1 skrll vliw1 = vliw1->next;
914 1.1 skrll goto workaround_top;
915 1.1 skrll }
916 1.1 skrll }
917 1.1 skrll }
918 1.1 skrll /* Examine each insn in this VLIW. Look for the workaround criteria. */
919 1.1 skrll for (this_insn = vliw1->insn_list; this_insn; this_insn = this_insn->next)
920 1.1 skrll {
921 1.1 skrll /* Don't look at labels or nops. */
922 1.1 skrll while (this_insn
923 1.1 skrll && (this_insn->type == VLIW_LABEL_TYPE
924 1.1 skrll || this_insn->type == VLIW_NOP_TYPE
925 1.1 skrll || this_insn->type == VLIW_BRANCH_HAS_NOPS))
926 1.1 skrll this_insn = this_insn->next;
927 1.1 skrll
928 1.1 skrll if (!this_insn)
929 1.1 skrll {
930 1.1 skrll vliw1 = vliw2;
931 1.1 skrll goto workaround_top;
932 1.1 skrll }
933 1.1 skrll
934 1.1 skrll if (frv_is_branch_insn (this_insn->insn))
935 1.1 skrll {
936 1.1 skrll if ((temp_insn = frv_find_in_vliw (VLIW_LABEL_TYPE, vliw1, this_insn->sym)) != NULL)
937 1.1 skrll {
938 1.1 skrll /* Insert [nop/nop] [nop] before branch. */
939 1.1 skrll this_insn->snop_frag->fr_subtype = NOP_KEEP;
940 1.1 skrll this_insn->dnop_frag->fr_subtype = NOP_KEEP;
941 1.1 skrll vliw1 = frv_tomcat_shuffle (VLIW_DOUBLE_THEN_SINGLE_NOP, vliw1, this_insn);
942 1.1 skrll goto workaround_top;
943 1.1 skrll }
944 1.1 skrll }
945 1.1 skrll
946 1.1 skrll
947 1.1 skrll }
948 1.1 skrll /* This vliw insn checks out okay. Take a look at the next one. */
949 1.1 skrll vliw1 = vliw1->next;
950 1.1 skrll goto workaround_top;
951 1.1 skrll }
952 1.1 skrll
953 1.1 skrll void
954 1.1 skrll frv_tomcat_workaround (void)
955 1.1 skrll {
956 1.1 skrll if (frv_mach != bfd_mach_frvtomcat)
957 1.1 skrll return;
958 1.1 skrll
959 1.1 skrll if (tomcat_debug)
960 1.1 skrll frv_debug_tomcat (vliw_chain_top);
961 1.1 skrll
962 1.1 skrll frv_tomcat_analyze_vliw_chains ();
963 1.1 skrll
964 1.1 skrll if (tomcat_stats)
965 1.1 skrll {
966 1.1 skrll fprintf (stderr, "Inserted %d Single Nops\n", tomcat_singles);
967 1.1 skrll fprintf (stderr, "Inserted %d Double Nops\n", tomcat_doubles);
968 1.1 skrll }
969 1.1 skrll }
970 1.1 skrll
971 1.1 skrll static int
972 1.1 skrll fr550_check_insn_acc_range (frv_insn *insn, int low, int hi)
973 1.1 skrll {
974 1.1 skrll int acc;
975 1.1 skrll switch (CGEN_INSN_NUM (insn->insn))
976 1.1 skrll {
977 1.1 skrll case FRV_INSN_MADDACCS:
978 1.1 skrll case FRV_INSN_MSUBACCS:
979 1.1 skrll case FRV_INSN_MDADDACCS:
980 1.1 skrll case FRV_INSN_MDSUBACCS:
981 1.1 skrll case FRV_INSN_MASACCS:
982 1.1 skrll case FRV_INSN_MDASACCS:
983 1.1 skrll acc = insn->fields.f_ACC40Si;
984 1.1 skrll if (acc < low || acc > hi)
985 1.1 skrll return 1; /* out of range */
986 1.1 skrll acc = insn->fields.f_ACC40Sk;
987 1.1 skrll if (acc < low || acc > hi)
988 1.1 skrll return 1; /* out of range */
989 1.1 skrll break;
990 1.1 skrll case FRV_INSN_MMULHS:
991 1.1 skrll case FRV_INSN_MMULHU:
992 1.1 skrll case FRV_INSN_MMULXHS:
993 1.1 skrll case FRV_INSN_MMULXHU:
994 1.1 skrll case FRV_INSN_CMMULHS:
995 1.1 skrll case FRV_INSN_CMMULHU:
996 1.1 skrll case FRV_INSN_MQMULHS:
997 1.1 skrll case FRV_INSN_MQMULHU:
998 1.1 skrll case FRV_INSN_MQMULXHS:
999 1.1 skrll case FRV_INSN_MQMULXHU:
1000 1.1 skrll case FRV_INSN_CMQMULHS:
1001 1.1 skrll case FRV_INSN_CMQMULHU:
1002 1.1.1.3 christos case FRV_INSN_MMACHS:
1003 1.1 skrll case FRV_INSN_MMRDHS:
1004 1.1 skrll case FRV_INSN_CMMACHS:
1005 1.1 skrll case FRV_INSN_MQMACHS:
1006 1.1 skrll case FRV_INSN_CMQMACHS:
1007 1.1 skrll case FRV_INSN_MQXMACHS:
1008 1.1 skrll case FRV_INSN_MQXMACXHS:
1009 1.1 skrll case FRV_INSN_MQMACXHS:
1010 1.1 skrll case FRV_INSN_MCPXRS:
1011 1.1 skrll case FRV_INSN_MCPXIS:
1012 1.1 skrll case FRV_INSN_CMCPXRS:
1013 1.1 skrll case FRV_INSN_CMCPXIS:
1014 1.1 skrll case FRV_INSN_MQCPXRS:
1015 1.1 skrll case FRV_INSN_MQCPXIS:
1016 1.1 skrll acc = insn->fields.f_ACC40Sk;
1017 1.1 skrll if (acc < low || acc > hi)
1018 1.1 skrll return 1; /* out of range */
1019 1.1 skrll break;
1020 1.1 skrll case FRV_INSN_MMACHU:
1021 1.1 skrll case FRV_INSN_MMRDHU:
1022 1.1 skrll case FRV_INSN_CMMACHU:
1023 1.1 skrll case FRV_INSN_MQMACHU:
1024 1.1 skrll case FRV_INSN_CMQMACHU:
1025 1.1 skrll case FRV_INSN_MCPXRU:
1026 1.1 skrll case FRV_INSN_MCPXIU:
1027 1.1 skrll case FRV_INSN_CMCPXRU:
1028 1.1 skrll case FRV_INSN_CMCPXIU:
1029 1.1 skrll case FRV_INSN_MQCPXRU:
1030 1.1 skrll case FRV_INSN_MQCPXIU:
1031 1.1 skrll acc = insn->fields.f_ACC40Uk;
1032 1.1 skrll if (acc < low || acc > hi)
1033 1.1 skrll return 1; /* out of range */
1034 1.1 skrll break;
1035 1.1 skrll default:
1036 1.1 skrll break;
1037 1.1 skrll }
1038 1.1 skrll return 0; /* all is ok */
1039 1.1 skrll }
1040 1.1.1.2 christos
1041 1.1 skrll static int
1042 1.1.1.2 christos fr550_check_acc_range (FRV_VLIW *vlw, frv_insn *insn)
1043 1.1 skrll {
1044 1.1 skrll switch ((*vlw->current_vliw)[vlw->next_slot - 1])
1045 1.1 skrll {
1046 1.1 skrll case UNIT_FM0:
1047 1.1 skrll case UNIT_FM2:
1048 1.1 skrll return fr550_check_insn_acc_range (insn, 0, 3);
1049 1.1 skrll case UNIT_FM1:
1050 1.1 skrll case UNIT_FM3:
1051 1.1 skrll return fr550_check_insn_acc_range (insn, 4, 7);
1052 1.1 skrll default:
1053 1.1 skrll break;
1054 1.1 skrll }
1055 1.1 skrll return 0; /* all is ok */
1056 1.1 skrll }
1057 1.1 skrll
1058 1.1.1.7 christos /* Return true if the target implements instruction INSN. */
1059 1.1 skrll
1060 1.1 skrll static bool
1061 1.1 skrll target_implements_insn_p (const CGEN_INSN *insn)
1062 1.1 skrll {
1063 1.1 skrll switch (frv_mach)
1064 1.1 skrll {
1065 1.1.1.7 christos default:
1066 1.1 skrll /* bfd_mach_frv or generic. */
1067 1.1 skrll return true;
1068 1.1 skrll
1069 1.1 skrll case bfd_mach_fr300:
1070 1.1 skrll case bfd_mach_frvsimple:
1071 1.1 skrll return CGEN_INSN_MACH_HAS_P (insn, MACH_SIMPLE);
1072 1.1 skrll
1073 1.1 skrll case bfd_mach_fr400:
1074 1.1 skrll return ((fr400_audio || !CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_AUDIO))
1075 1.1 skrll && CGEN_INSN_MACH_HAS_P (insn, MACH_FR400));
1076 1.1 skrll
1077 1.1 skrll case bfd_mach_fr450:
1078 1.1 skrll return CGEN_INSN_MACH_HAS_P (insn, MACH_FR450);
1079 1.1 skrll
1080 1.1 skrll case bfd_mach_fr500:
1081 1.1 skrll return CGEN_INSN_MACH_HAS_P (insn, MACH_FR500);
1082 1.1 skrll
1083 1.1 skrll case bfd_mach_fr550:
1084 1.1 skrll return CGEN_INSN_MACH_HAS_P (insn, MACH_FR550);
1085 1.1 skrll }
1086 1.1 skrll }
1087 1.1 skrll
1088 1.1 skrll void
1089 1.1 skrll md_assemble (char *str)
1090 1.1 skrll {
1091 1.1 skrll frv_insn insn;
1092 1.1 skrll char *errmsg;
1093 1.1 skrll int packing_constraint;
1094 1.1 skrll finished_insnS finished_insn;
1095 1.1 skrll fragS *double_nop_frag = NULL;
1096 1.1 skrll fragS *single_nop_frag = NULL;
1097 1.1 skrll struct vliw_insn_list *vliw_insn_list_entry = NULL;
1098 1.1 skrll
1099 1.1 skrll /* Initialize GAS's cgen interface for a new instruction. */
1100 1.1 skrll gas_cgen_init_parse ();
1101 1.1 skrll
1102 1.1 skrll memset (&insn, 0, sizeof (insn));
1103 1.1 skrll
1104 1.1.1.3 christos insn.insn = frv_cgen_assemble_insn
1105 1.1 skrll (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, &errmsg);
1106 1.1 skrll
1107 1.1.1.2 christos if (!insn.insn)
1108 1.1 skrll {
1109 1.1 skrll as_bad ("%s", errmsg);
1110 1.1.1.3 christos return;
1111 1.1 skrll }
1112 1.1 skrll
1113 1.1 skrll /* If the cpu is tomcat, then we need to insert nops to workaround
1114 1.1 skrll hardware limitations. We need to keep track of each vliw unit
1115 1.1 skrll and examine the length of the unit and the individual insns
1116 1.1 skrll within the unit to determine the number and location of the
1117 1.1 skrll required nops. */
1118 1.1 skrll if (frv_mach == bfd_mach_frvtomcat)
1119 1.1 skrll {
1120 1.1.1.3 christos /* If we've just finished a VLIW insn OR this is a branch,
1121 1.1 skrll then start up a new frag. Fill it with nops. We will get rid
1122 1.1 skrll of those that are not required after we've seen all of the
1123 1.1 skrll instructions but before we start resolving fixups. */
1124 1.1 skrll if ( !FRV_IS_NOP (insn)
1125 1.1 skrll && (frv_is_branch_insn (insn.insn) || insn.fields.f_pack))
1126 1.1 skrll {
1127 1.1 skrll char *buffer;
1128 1.1 skrll
1129 1.1 skrll frag_wane (frag_now);
1130 1.1 skrll frag_new (0);
1131 1.1 skrll double_nop_frag = frag_now;
1132 1.1 skrll buffer = frag_var (rs_machine_dependent, 8, 8, NOP_DELETE, NULL, 0, 0);
1133 1.1 skrll md_number_to_chars (buffer, FRV_NOP_PACK, 4);
1134 1.1 skrll md_number_to_chars (buffer+4, FRV_NOP_NOPACK, 4);
1135 1.1 skrll
1136 1.1 skrll frag_wane (frag_now);
1137 1.1 skrll frag_new (0);
1138 1.1 skrll single_nop_frag = frag_now;
1139 1.1 skrll buffer = frag_var (rs_machine_dependent, 4, 4, NOP_DELETE, NULL, 0, 0);
1140 1.1 skrll md_number_to_chars (buffer, FRV_NOP_NOPACK, 4);
1141 1.1 skrll }
1142 1.1 skrll
1143 1.1 skrll vliw_insn_list_entry = frv_insert_vliw_insn (DO_COUNT);
1144 1.1 skrll vliw_insn_list_entry->insn = insn.insn;
1145 1.1 skrll if (frv_is_branch_insn (insn.insn))
1146 1.1 skrll vliw_insn_list_entry->type = VLIW_BRANCH_TYPE;
1147 1.1 skrll
1148 1.1 skrll if ( !FRV_IS_NOP (insn)
1149 1.1 skrll && (frv_is_branch_insn (insn.insn) || insn.fields.f_pack))
1150 1.1 skrll {
1151 1.1 skrll vliw_insn_list_entry->snop_frag = single_nop_frag;
1152 1.1 skrll vliw_insn_list_entry->dnop_frag = double_nop_frag;
1153 1.1 skrll }
1154 1.1 skrll }
1155 1.1 skrll
1156 1.1 skrll /* Make sure that this insn does not violate the VLIW packing constraints. */
1157 1.1 skrll /* -mno-pack disallows any packing whatsoever. */
1158 1.1 skrll if (frv_flags & EF_FRV_NOPACK)
1159 1.1 skrll {
1160 1.1 skrll if (! insn.fields.f_pack)
1161 1.1 skrll {
1162 1.1 skrll as_bad (_("VLIW packing used for -mno-pack"));
1163 1.1 skrll return;
1164 1.1 skrll }
1165 1.1 skrll }
1166 1.1 skrll /* -mcpu=FRV is an idealized FR-V implementation that supports all of the
1167 1.1 skrll instructions, don't do vliw checking. */
1168 1.1 skrll else if (frv_mach != bfd_mach_frv)
1169 1.1 skrll {
1170 1.1 skrll if (!target_implements_insn_p (insn.insn))
1171 1.1 skrll {
1172 1.1 skrll as_bad (_("Instruction not supported by this architecture"));
1173 1.1 skrll return;
1174 1.1 skrll }
1175 1.1 skrll packing_constraint = frv_vliw_add_insn (& vliw, insn.insn);
1176 1.1 skrll if (frv_mach == bfd_mach_fr550 && ! packing_constraint)
1177 1.1 skrll packing_constraint = fr550_check_acc_range (& vliw, & insn);
1178 1.1 skrll if (insn.fields.f_pack)
1179 1.1 skrll frv_vliw_reset (& vliw, frv_mach, frv_flags);
1180 1.1 skrll if (packing_constraint)
1181 1.1 skrll {
1182 1.1 skrll as_bad (_("VLIW packing constraint violation"));
1183 1.1 skrll return;
1184 1.1 skrll }
1185 1.1 skrll }
1186 1.1 skrll
1187 1.1 skrll /* Doesn't really matter what we pass for RELAX_P here. */
1188 1.1 skrll gas_cgen_finish_insn (insn.insn, insn.buffer,
1189 1.1 skrll CGEN_FIELDS_BITSIZE (& insn.fields), 1, &finished_insn);
1190 1.1 skrll
1191 1.1 skrll
1192 1.1 skrll /* If the cpu is tomcat, then we need to insert nops to workaround
1193 1.1 skrll hardware limitations. We need to keep track of each vliw unit
1194 1.1 skrll and examine the length of the unit and the individual insns
1195 1.1 skrll within the unit to determine the number and location of the
1196 1.1 skrll required nops. */
1197 1.1 skrll if (frv_mach == bfd_mach_frvtomcat)
1198 1.1 skrll {
1199 1.1 skrll if (vliw_insn_list_entry)
1200 1.1 skrll vliw_insn_list_entry->address = finished_insn.addr;
1201 1.1 skrll else
1202 1.1 skrll abort();
1203 1.1 skrll
1204 1.1 skrll if (insn.fields.f_pack)
1205 1.1 skrll {
1206 1.1 skrll /* We've completed a VLIW insn. */
1207 1.1 skrll previous_vliw_chain = current_vliw_chain;
1208 1.1.1.3 christos current_vliw_chain = NULL;
1209 1.1 skrll current_vliw_insn = NULL;
1210 1.1 skrll }
1211 1.1 skrll }
1212 1.1 skrll }
1213 1.1 skrll
1214 1.1 skrll /* The syntax in the manual says constants begin with '#'.
1215 1.1.1.3 christos We just ignore it. */
1216 1.1 skrll
1217 1.1 skrll void
1218 1.1 skrll md_operand (expressionS *expressionP)
1219 1.1 skrll {
1220 1.1 skrll if (* input_line_pointer == '#')
1221 1.1 skrll {
1222 1.1 skrll input_line_pointer ++;
1223 1.1 skrll expression (expressionP);
1224 1.1 skrll }
1225 1.1 skrll }
1226 1.1 skrll
1227 1.1 skrll valueT
1228 1.1.1.6 christos md_section_align (segT segment, valueT size)
1229 1.1.1.3 christos {
1230 1.1 skrll int align = bfd_section_alignment (segment);
1231 1.1 skrll return ((size + (1 << align) - 1) & -(1 << align));
1232 1.1 skrll }
1233 1.1 skrll
1234 1.1 skrll symbolS *
1235 1.1 skrll md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
1236 1.1 skrll {
1237 1.1 skrll return 0;
1238 1.1 skrll }
1239 1.1 skrll
1240 1.1 skrll /* Interface to relax_segment. */
1242 1.1 skrll
1243 1.1 skrll /* FIXME: Build table by hand, get it working, then machine generate. */
1244 1.1 skrll const relax_typeS md_relax_table[] =
1245 1.1 skrll {
1246 1.1 skrll {1, 1, 0, 0},
1247 1.1 skrll {511 - 2 - 2, -512 - 2 + 2, 0, 2 },
1248 1.1 skrll {0x2000000 - 1 - 2, -0x2000000 - 2, 2, 0 },
1249 1.1 skrll {0x2000000 - 1 - 2, -0x2000000 - 2, 4, 0 }
1250 1.1 skrll };
1251 1.1 skrll
1252 1.1 skrll long
1253 1.1 skrll frv_relax_frag (fragS *fragP ATTRIBUTE_UNUSED, long stretch ATTRIBUTE_UNUSED)
1254 1.1 skrll {
1255 1.1 skrll return 0;
1256 1.1 skrll }
1257 1.1 skrll
1258 1.1 skrll /* Return an initial guess of the length by which a fragment must grow to
1259 1.1 skrll hold a branch to reach its destination.
1260 1.1 skrll Also updates fr_type/fr_subtype as necessary.
1261 1.1 skrll
1262 1.1 skrll Called just before doing relaxation.
1263 1.1 skrll Any symbol that is now undefined will not become defined.
1264 1.1 skrll The guess for fr_var is ACTUALLY the growth beyond fr_fix.
1265 1.1 skrll Whatever we do to grow fr_fix or fr_var contributes to our returned value.
1266 1.1 skrll Although it may not be explicit in the frag, pretend fr_var starts with a
1267 1.1 skrll 0 value. */
1268 1.1 skrll
1269 1.1 skrll int
1270 1.1 skrll md_estimate_size_before_relax (fragS *fragP, segT segment ATTRIBUTE_UNUSED)
1271 1.1 skrll {
1272 1.1 skrll switch (fragP->fr_subtype)
1273 1.1 skrll {
1274 1.1 skrll case NOP_KEEP:
1275 1.1 skrll return fragP->fr_var;
1276 1.1 skrll
1277 1.1.1.3 christos default:
1278 1.1.1.3 christos case NOP_DELETE:
1279 1.1 skrll return 0;
1280 1.1 skrll }
1281 1.1 skrll }
1282 1.1 skrll
1283 1.1 skrll /* *fragP has been relaxed to its final size, and now needs to have
1284 1.1 skrll the bytes inside it modified to conform to the new size.
1285 1.1 skrll
1286 1.1 skrll Called after relaxation is finished.
1287 1.1 skrll fragP->fr_type == rs_machine_dependent.
1288 1.1 skrll fragP->fr_subtype is the subtype of what the address relaxed to. */
1289 1.1 skrll
1290 1.1 skrll void
1291 1.1 skrll md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
1292 1.1 skrll segT sec ATTRIBUTE_UNUSED,
1293 1.1 skrll fragS *fragP)
1294 1.1 skrll {
1295 1.1 skrll switch (fragP->fr_subtype)
1296 1.1 skrll {
1297 1.1 skrll default:
1298 1.1 skrll case NOP_DELETE:
1299 1.1 skrll return;
1300 1.1 skrll
1301 1.1.1.3 christos case NOP_KEEP:
1302 1.1 skrll fragP->fr_fix = fragP->fr_var;
1303 1.1 skrll fragP->fr_var = 0;
1304 1.1 skrll return;
1305 1.1 skrll }
1306 1.1 skrll }
1307 1.1 skrll
1308 1.1 skrll /* Functions concerning relocs. */
1310 1.1 skrll
1311 1.1 skrll /* The location from which a PC relative jump should be calculated,
1312 1.1 skrll given a PC relative reloc. */
1313 1.1 skrll
1314 1.1 skrll long
1315 1.1 skrll md_pcrel_from_section (fixS *fixP, segT sec)
1316 1.1 skrll {
1317 1.1 skrll if (TC_FORCE_RELOCATION (fixP)
1318 1.1 skrll || (fixP->fx_addsy != (symbolS *) NULL
1319 1.1 skrll && S_GET_SEGMENT (fixP->fx_addsy) != sec))
1320 1.1 skrll {
1321 1.1 skrll /* If we can't adjust this relocation, or if it references a
1322 1.1 skrll local symbol in a different section (which
1323 1.1 skrll TC_FORCE_RELOCATION can't check), let the linker figure it
1324 1.1 skrll out. */
1325 1.1 skrll return 0;
1326 1.1 skrll }
1327 1.1 skrll
1328 1.1 skrll return (fixP->fx_frag->fr_address + fixP->fx_where) & ~1;
1329 1.1 skrll }
1330 1.1 skrll
1331 1.1 skrll /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
1332 1.1 skrll Returns BFD_RELOC_NONE if no reloc type can be found.
1333 1.1 skrll *FIXP may be modified if desired. */
1334 1.1 skrll
1335 1.1 skrll bfd_reloc_code_real_type
1336 1.1 skrll md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
1337 1.1 skrll const CGEN_OPERAND *operand,
1338 1.1 skrll fixS *fixP)
1339 1.1.1.7 christos {
1340 1.1 skrll switch (operand->type)
1341 1.1 skrll {
1342 1.1 skrll case FRV_OPERAND_LABEL16:
1343 1.1.1.7 christos fixP->fx_pcrel = true;
1344 1.1 skrll return BFD_RELOC_FRV_LABEL16;
1345 1.1 skrll
1346 1.1 skrll case FRV_OPERAND_LABEL24:
1347 1.1 skrll fixP->fx_pcrel = true;
1348 1.1 skrll
1349 1.1 skrll if (fixP->fx_cgen.opinfo != 0)
1350 1.1 skrll return fixP->fx_cgen.opinfo;
1351 1.1 skrll
1352 1.1 skrll return BFD_RELOC_FRV_LABEL24;
1353 1.1 skrll
1354 1.1 skrll case FRV_OPERAND_UHI16:
1355 1.1 skrll case FRV_OPERAND_ULO16:
1356 1.1 skrll case FRV_OPERAND_SLO16:
1357 1.1 skrll case FRV_OPERAND_CALLANN:
1358 1.1 skrll case FRV_OPERAND_LDANN:
1359 1.1 skrll case FRV_OPERAND_LDDANN:
1360 1.1 skrll /* The relocation type should be recorded in opinfo */
1361 1.1 skrll if (fixP->fx_cgen.opinfo != 0)
1362 1.1 skrll return fixP->fx_cgen.opinfo;
1363 1.1 skrll break;
1364 1.1 skrll
1365 1.1 skrll case FRV_OPERAND_D12:
1366 1.1 skrll case FRV_OPERAND_S12:
1367 1.1 skrll if (fixP->fx_cgen.opinfo != 0)
1368 1.1 skrll return fixP->fx_cgen.opinfo;
1369 1.1 skrll
1370 1.1 skrll return BFD_RELOC_FRV_GPREL12;
1371 1.1.1.3 christos
1372 1.1 skrll case FRV_OPERAND_U12:
1373 1.1 skrll return BFD_RELOC_FRV_GPRELU12;
1374 1.1 skrll
1375 1.1 skrll default:
1376 1.1 skrll break;
1377 1.1 skrll }
1378 1.1 skrll return BFD_RELOC_NONE;
1379 1.1 skrll }
1380 1.1 skrll
1381 1.1 skrll
1382 1.1 skrll /* See whether we need to force a relocation into the output file.
1383 1.1 skrll This is used to force out switch and PC relative relocations when
1384 1.1 skrll relaxing. */
1385 1.1 skrll
1386 1.1 skrll int
1387 1.1 skrll frv_force_relocation (fixS *fix)
1388 1.1 skrll {
1389 1.1 skrll switch (fix->fx_r_type < BFD_RELOC_UNUSED
1390 1.1 skrll ? (int) fix->fx_r_type
1391 1.1 skrll : fix->fx_cgen.opinfo)
1392 1.1 skrll {
1393 1.1 skrll case BFD_RELOC_FRV_GPREL12:
1394 1.1 skrll case BFD_RELOC_FRV_GPRELU12:
1395 1.1 skrll case BFD_RELOC_FRV_GPREL32:
1396 1.1 skrll case BFD_RELOC_FRV_GPRELHI:
1397 1.1 skrll case BFD_RELOC_FRV_GPRELLO:
1398 1.1 skrll case BFD_RELOC_FRV_GOT12:
1399 1.1 skrll case BFD_RELOC_FRV_GOTHI:
1400 1.1 skrll case BFD_RELOC_FRV_GOTLO:
1401 1.1 skrll case BFD_RELOC_FRV_FUNCDESC_VALUE:
1402 1.1 skrll case BFD_RELOC_FRV_FUNCDESC_GOTOFF12:
1403 1.1 skrll case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI:
1404 1.1 skrll case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO:
1405 1.1 skrll case BFD_RELOC_FRV_GOTOFF12:
1406 1.1 skrll case BFD_RELOC_FRV_GOTOFFHI:
1407 1.1 skrll case BFD_RELOC_FRV_GOTOFFLO:
1408 1.1 skrll case BFD_RELOC_FRV_GETTLSOFF:
1409 1.1 skrll case BFD_RELOC_FRV_TLSDESC_VALUE:
1410 1.1 skrll case BFD_RELOC_FRV_GOTTLSDESC12:
1411 1.1 skrll case BFD_RELOC_FRV_GOTTLSDESCHI:
1412 1.1 skrll case BFD_RELOC_FRV_GOTTLSDESCLO:
1413 1.1 skrll case BFD_RELOC_FRV_TLSMOFF12:
1414 1.1 skrll case BFD_RELOC_FRV_TLSMOFFHI:
1415 1.1 skrll case BFD_RELOC_FRV_TLSMOFFLO:
1416 1.1 skrll case BFD_RELOC_FRV_GOTTLSOFF12:
1417 1.1 skrll case BFD_RELOC_FRV_GOTTLSOFFHI:
1418 1.1 skrll case BFD_RELOC_FRV_GOTTLSOFFLO:
1419 1.1 skrll case BFD_RELOC_FRV_TLSOFF:
1420 1.1 skrll case BFD_RELOC_FRV_TLSDESC_RELAX:
1421 1.1 skrll case BFD_RELOC_FRV_GETTLSOFF_RELAX:
1422 1.1 skrll case BFD_RELOC_FRV_TLSOFF_RELAX:
1423 1.1 skrll return 1;
1424 1.1 skrll
1425 1.1 skrll default:
1426 1.1 skrll break;
1427 1.1 skrll }
1428 1.1 skrll
1429 1.1 skrll return generic_force_reloc (fix);
1430 1.1 skrll }
1431 1.1 skrll
1432 1.1 skrll /* Apply a fixup that could be resolved within the assembler. */
1433 1.1 skrll
1434 1.1 skrll void
1435 1.1 skrll md_apply_fix (fixS *fixP, valueT *valP, segT seg)
1436 1.1 skrll {
1437 1.1 skrll if (fixP->fx_addsy == 0)
1438 1.1 skrll switch (fixP->fx_cgen.opinfo)
1439 1.1 skrll {
1440 1.1 skrll case BFD_RELOC_FRV_HI16:
1441 1.1 skrll *valP >>= 16;
1442 1.1 skrll /* Fall through. */
1443 1.1 skrll case BFD_RELOC_FRV_LO16:
1444 1.1 skrll *valP &= 0xffff;
1445 1.1 skrll break;
1446 1.1 skrll
1447 1.1 skrll /* We need relocations for these, even if their symbols reduce
1448 1.1 skrll to constants. */
1449 1.1 skrll case BFD_RELOC_FRV_GPREL12:
1450 1.1 skrll case BFD_RELOC_FRV_GPRELU12:
1451 1.1 skrll case BFD_RELOC_FRV_GPREL32:
1452 1.1 skrll case BFD_RELOC_FRV_GPRELHI:
1453 1.1 skrll case BFD_RELOC_FRV_GPRELLO:
1454 1.1 skrll case BFD_RELOC_FRV_GOT12:
1455 1.1 skrll case BFD_RELOC_FRV_GOTHI:
1456 1.1 skrll case BFD_RELOC_FRV_GOTLO:
1457 1.1 skrll case BFD_RELOC_FRV_FUNCDESC_VALUE:
1458 1.1 skrll case BFD_RELOC_FRV_FUNCDESC_GOTOFF12:
1459 1.1 skrll case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI:
1460 1.1 skrll case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO:
1461 1.1 skrll case BFD_RELOC_FRV_GOTOFF12:
1462 1.1 skrll case BFD_RELOC_FRV_GOTOFFHI:
1463 1.1 skrll case BFD_RELOC_FRV_GOTOFFLO:
1464 1.1 skrll case BFD_RELOC_FRV_GETTLSOFF:
1465 1.1 skrll case BFD_RELOC_FRV_TLSDESC_VALUE:
1466 1.1 skrll case BFD_RELOC_FRV_GOTTLSDESC12:
1467 1.1 skrll case BFD_RELOC_FRV_GOTTLSDESCHI:
1468 1.1 skrll case BFD_RELOC_FRV_GOTTLSDESCLO:
1469 1.1 skrll case BFD_RELOC_FRV_TLSMOFF12:
1470 1.1 skrll case BFD_RELOC_FRV_TLSMOFFHI:
1471 1.1 skrll case BFD_RELOC_FRV_TLSMOFFLO:
1472 1.1 skrll case BFD_RELOC_FRV_GOTTLSOFF12:
1473 1.1 skrll case BFD_RELOC_FRV_GOTTLSOFFHI:
1474 1.1 skrll case BFD_RELOC_FRV_GOTTLSOFFLO:
1475 1.1 skrll case BFD_RELOC_FRV_TLSOFF:
1476 1.1 skrll case BFD_RELOC_FRV_TLSDESC_RELAX:
1477 1.1 skrll case BFD_RELOC_FRV_GETTLSOFF_RELAX:
1478 1.1 skrll case BFD_RELOC_FRV_TLSOFF_RELAX:
1479 1.1 skrll fixP->fx_addsy = abs_section_sym;
1480 1.1 skrll break;
1481 1.1 skrll }
1482 1.1 skrll else
1483 1.1 skrll switch (fixP->fx_cgen.opinfo)
1484 1.1 skrll {
1485 1.1 skrll case BFD_RELOC_FRV_GETTLSOFF:
1486 1.1 skrll case BFD_RELOC_FRV_TLSDESC_VALUE:
1487 1.1 skrll case BFD_RELOC_FRV_GOTTLSDESC12:
1488 1.1 skrll case BFD_RELOC_FRV_GOTTLSDESCHI:
1489 1.1 skrll case BFD_RELOC_FRV_GOTTLSDESCLO:
1490 1.1 skrll case BFD_RELOC_FRV_TLSMOFF12:
1491 1.1 skrll case BFD_RELOC_FRV_TLSMOFFHI:
1492 1.1 skrll case BFD_RELOC_FRV_TLSMOFFLO:
1493 1.1 skrll case BFD_RELOC_FRV_GOTTLSOFF12:
1494 1.1 skrll case BFD_RELOC_FRV_GOTTLSOFFHI:
1495 1.1 skrll case BFD_RELOC_FRV_GOTTLSOFFLO:
1496 1.1 skrll case BFD_RELOC_FRV_TLSOFF:
1497 1.1 skrll case BFD_RELOC_FRV_TLSDESC_RELAX:
1498 1.1 skrll case BFD_RELOC_FRV_GETTLSOFF_RELAX:
1499 1.1 skrll case BFD_RELOC_FRV_TLSOFF_RELAX:
1500 1.1 skrll /* Mark TLS symbols as such. */
1501 1.1 skrll if (S_GET_SEGMENT (fixP->fx_addsy) != absolute_section)
1502 1.1 skrll S_SET_THREAD_LOCAL (fixP->fx_addsy);
1503 1.1 skrll break;
1504 1.1 skrll }
1505 1.1 skrll
1506 1.1 skrll gas_cgen_md_apply_fix (fixP, valP, seg);
1507 1.1 skrll return;
1508 1.1 skrll }
1509 1.1 skrll
1510 1.1 skrll
1511 1.1 skrll /* Write a value out to the object file, using the appropriate endianness. */
1513 1.1 skrll
1514 1.1 skrll void
1515 1.1.1.4 christos frv_md_number_to_chars (char *buf, valueT val, int n)
1516 1.1 skrll {
1517 1.1 skrll number_to_chars_bigendian (buf, val, n);
1518 1.1.1.7 christos }
1519 1.1 skrll
1520 1.1 skrll const char *
1521 1.1.1.7 christos md_atof (int type, char *litP, int *sizeP)
1522 1.1 skrll {
1523 1.1 skrll return ieee_md_atof (type, litP, sizeP, true);
1524 1.1 skrll }
1525 1.1 skrll
1526 1.1 skrll bool
1527 1.1 skrll frv_fix_adjustable (fixS *fixP)
1528 1.1 skrll {
1529 1.1 skrll bfd_reloc_code_real_type reloc_type;
1530 1.1 skrll
1531 1.1 skrll if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
1532 1.1 skrll {
1533 1.1 skrll const CGEN_INSN *insn = NULL;
1534 1.1 skrll int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
1535 1.1 skrll const CGEN_OPERAND *operand = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex);
1536 1.1 skrll reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
1537 1.1 skrll }
1538 1.1 skrll else
1539 1.1 skrll reloc_type = fixP->fx_r_type;
1540 1.1 skrll
1541 1.1 skrll /* We need the symbol name for the VTABLE entries */
1542 1.1 skrll if ( reloc_type == BFD_RELOC_VTABLE_INHERIT
1543 1.1 skrll || reloc_type == BFD_RELOC_VTABLE_ENTRY
1544 1.1 skrll || reloc_type == BFD_RELOC_FRV_GPREL12
1545 1.1 skrll || reloc_type == BFD_RELOC_FRV_GPRELU12)
1546 1.1 skrll return 0;
1547 1.1 skrll
1548 1.1 skrll return 1;
1549 1.1 skrll }
1550 1.1 skrll
1551 1.1 skrll /* Allow user to set flags bits. */
1552 1.1 skrll void
1553 1.1 skrll frv_set_flags (int arg ATTRIBUTE_UNUSED)
1554 1.1 skrll {
1555 1.1 skrll flagword new_flags = get_absolute_expression ();
1556 1.1 skrll flagword new_mask = ~ (flagword)0;
1557 1.1 skrll
1558 1.1 skrll frv_user_set_flags_p = 1;
1559 1.1 skrll if (*input_line_pointer == ',')
1560 1.1 skrll {
1561 1.1 skrll ++input_line_pointer;
1562 1.1 skrll new_mask = get_absolute_expression ();
1563 1.1 skrll }
1564 1.1 skrll
1565 1.1 skrll frv_flags = (frv_flags & ~new_mask) | (new_flags & new_mask);
1566 1.1 skrll bfd_set_private_flags (stdoutput, frv_flags);
1567 1.1 skrll }
1568 1.1 skrll
1569 1.1 skrll /* Frv specific function to handle 4 byte initializations for pointers that are
1570 1.1 skrll considered 'safe' for use with pic support. Until frv_frob_file{,_section}
1571 1.1 skrll is run, we encode it a BFD_RELOC_CTOR, and it is turned back into a normal
1572 1.1 skrll BFD_RELOC_32 at that time. */
1573 1.1 skrll
1574 1.1 skrll void
1575 1.1 skrll frv_pic_ptr (int nbytes)
1576 1.1 skrll {
1577 1.1 skrll expressionS exp;
1578 1.1 skrll char *p;
1579 1.1 skrll
1580 1.1 skrll if (nbytes != 4)
1581 1.1 skrll abort ();
1582 1.1 skrll
1583 1.1 skrll #ifdef md_flush_pending_output
1584 1.1 skrll md_flush_pending_output ();
1585 1.1 skrll #endif
1586 1.1 skrll
1587 1.1 skrll if (is_it_end_of_statement ())
1588 1.1 skrll {
1589 1.1 skrll demand_empty_rest_of_line ();
1590 1.1 skrll return;
1591 1.1 skrll }
1592 1.1 skrll
1593 1.1 skrll #ifdef md_cons_align
1594 1.1 skrll md_cons_align (nbytes);
1595 1.1.1.3 christos #endif
1596 1.1 skrll
1597 1.1 skrll do
1598 1.1 skrll {
1599 1.1 skrll bfd_reloc_code_real_type reloc_type = BFD_RELOC_CTOR;
1600 1.1 skrll
1601 1.1 skrll if (strncasecmp (input_line_pointer, "funcdesc(", 9) == 0)
1602 1.1 skrll {
1603 1.1 skrll input_line_pointer += 9;
1604 1.1 skrll expression (&exp);
1605 1.1 skrll if (*input_line_pointer == ')')
1606 1.1 skrll input_line_pointer++;
1607 1.1 skrll else
1608 1.1 skrll as_bad (_("missing ')'"));
1609 1.1 skrll reloc_type = BFD_RELOC_FRV_FUNCDESC;
1610 1.1 skrll }
1611 1.1 skrll else if (strncasecmp (input_line_pointer, "tlsmoff(", 8) == 0)
1612 1.1 skrll {
1613 1.1 skrll input_line_pointer += 8;
1614 1.1 skrll expression (&exp);
1615 1.1 skrll if (*input_line_pointer == ')')
1616 1.1 skrll input_line_pointer++;
1617 1.1 skrll else
1618 1.1 skrll as_bad (_("missing ')'"));
1619 1.1 skrll reloc_type = BFD_RELOC_FRV_TLSMOFF;
1620 1.1 skrll }
1621 1.1 skrll else
1622 1.1 skrll expression (&exp);
1623 1.1 skrll
1624 1.1 skrll p = frag_more (4);
1625 1.1 skrll memset (p, 0, 4);
1626 1.1 skrll fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &exp, 0,
1627 1.1 skrll reloc_type);
1628 1.1 skrll }
1629 1.1 skrll while (*input_line_pointer++ == ',');
1630 1.1 skrll
1631 1.1 skrll input_line_pointer--; /* Put terminator back into stream. */
1632 1.1 skrll demand_empty_rest_of_line ();
1633 1.1 skrll }
1634 1.1 skrll
1635 1.1 skrll
1636 1.1 skrll
1638 1.1 skrll #ifdef DEBUG
1639 1.1 skrll #define DPRINTF1(A) fprintf (stderr, A)
1640 1.1 skrll #define DPRINTF2(A,B) fprintf (stderr, A, B)
1641 1.1 skrll #define DPRINTF3(A,B,C) fprintf (stderr, A, B, C)
1642 1.1 skrll
1643 1.1 skrll #else
1644 1.1 skrll #define DPRINTF1(A)
1645 1.1 skrll #define DPRINTF2(A,B)
1646 1.1 skrll #define DPRINTF3(A,B,C)
1647 1.1 skrll #endif
1648 1.1 skrll
1649 1.1 skrll /* Go through a the sections looking for relocations that are problematical for
1650 1.1 skrll pic. If not pic, just note that this object can't be linked with pic. If
1651 1.1 skrll it is pic, see if it needs to be marked so that it will be fixed up, or if
1652 1.1 skrll not possible, issue an error. */
1653 1.1 skrll
1654 1.1.1.6 christos static void
1655 1.1 skrll frv_frob_file_section (bfd *abfd, asection *sec, void *ptr ATTRIBUTE_UNUSED)
1656 1.1 skrll {
1657 1.1 skrll segment_info_type *seginfo = seg_info (sec);
1658 1.1 skrll fixS *fixp;
1659 1.1 skrll CGEN_CPU_DESC cd = gas_cgen_cpu_desc;
1660 1.1 skrll flagword flags = bfd_section_flags (sec);
1661 1.1 skrll
1662 1.1 skrll /* Skip relocations in known sections (.ctors, .dtors, and .gcc_except_table)
1663 1.1 skrll since we can fix those up by hand. */
1664 1.1 skrll int known_section_p = (sec->name
1665 1.1 skrll && sec->name[0] == '.'
1666 1.1 skrll && ((sec->name[1] == 'c'
1667 1.1 skrll && strcmp (sec->name, ".ctor") == 0)
1668 1.1 skrll || (sec->name[1] == 'd'
1669 1.1 skrll && strcmp (sec->name, ".dtor") == 0)
1670 1.1 skrll || (sec->name[1] == 'g'
1671 1.1 skrll && strcmp (sec->name, ".gcc_except_table") == 0)));
1672 1.1 skrll
1673 1.1 skrll DPRINTF3 ("\nFrv section %s%s\n", sec->name, (known_section_p) ? ", known section" : "");
1674 1.1 skrll if ((flags & SEC_ALLOC) == 0)
1675 1.1 skrll {
1676 1.1 skrll DPRINTF1 ("\tSkipping non-loaded section\n");
1677 1.1 skrll return;
1678 1.1 skrll }
1679 1.1 skrll
1680 1.1 skrll for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
1681 1.1 skrll {
1682 1.1 skrll symbolS *s = fixp->fx_addsy;
1683 1.1 skrll bfd_reloc_code_real_type reloc;
1684 1.1 skrll int non_pic_p;
1685 1.1 skrll int opindex;
1686 1.1 skrll const CGEN_OPERAND *operand;
1687 1.1 skrll const CGEN_INSN *insn = fixp->fx_cgen.insn;
1688 1.1 skrll
1689 1.1 skrll if (fixp->fx_done)
1690 1.1 skrll {
1691 1.1 skrll DPRINTF1 ("\tSkipping reloc that has already been done\n");
1692 1.1 skrll continue;
1693 1.1 skrll }
1694 1.1 skrll
1695 1.1 skrll if (fixp->fx_pcrel)
1696 1.1 skrll {
1697 1.1 skrll DPRINTF1 ("\tSkipping reloc that is PC relative\n");
1698 1.1 skrll continue;
1699 1.1 skrll }
1700 1.1 skrll
1701 1.1 skrll if (! s)
1702 1.1 skrll {
1703 1.1 skrll DPRINTF1 ("\tSkipping reloc without symbol\n");
1704 1.1 skrll continue;
1705 1.1 skrll }
1706 1.1 skrll
1707 1.1 skrll if (fixp->fx_r_type < BFD_RELOC_UNUSED)
1708 1.1 skrll {
1709 1.1 skrll opindex = -1;
1710 1.1 skrll reloc = fixp->fx_r_type;
1711 1.1 skrll }
1712 1.1 skrll else
1713 1.1 skrll {
1714 1.1 skrll opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED;
1715 1.1 skrll operand = cgen_operand_lookup_by_num (cd, opindex);
1716 1.1 skrll reloc = md_cgen_lookup_reloc (insn, operand, fixp);
1717 1.1 skrll }
1718 1.1 skrll
1719 1.1 skrll DPRINTF3 ("\treloc %s\t%s", bfd_get_reloc_code_name (reloc), S_GET_NAME (s));
1720 1.1 skrll
1721 1.1 skrll non_pic_p = 0;
1722 1.1 skrll switch (reloc)
1723 1.1 skrll {
1724 1.1 skrll default:
1725 1.1 skrll break;
1726 1.1 skrll
1727 1.1 skrll case BFD_RELOC_32:
1728 1.1 skrll /* Skip relocations in known sections (.ctors, .dtors, and
1729 1.1 skrll .gcc_except_table) since we can fix those up by hand. Also
1730 1.1 skrll skip forward references to constants. Also skip a difference
1731 1.1 skrll of two symbols, which still uses the BFD_RELOC_32 at this
1732 1.1 skrll point. */
1733 1.1 skrll if (! known_section_p
1734 1.1 skrll && S_GET_SEGMENT (s) != absolute_section
1735 1.1 skrll && !fixp->fx_subsy
1736 1.1 skrll && (flags & (SEC_READONLY | SEC_CODE)) == 0)
1737 1.1 skrll {
1738 1.1 skrll non_pic_p = 1;
1739 1.1 skrll }
1740 1.1 skrll break;
1741 1.1 skrll
1742 1.1 skrll /* FIXME -- should determine if any of the GP relocation really uses
1743 1.1 skrll gr16 (which is not pic safe) or not. Right now, assume if we
1744 1.1 skrll aren't being compiled with -mpic, the usage is non pic safe, but
1745 1.1 skrll is safe with -mpic. */
1746 1.1 skrll case BFD_RELOC_FRV_GPREL12:
1747 1.1 skrll case BFD_RELOC_FRV_GPRELU12:
1748 1.1 skrll case BFD_RELOC_FRV_GPREL32:
1749 1.1 skrll case BFD_RELOC_FRV_GPRELHI:
1750 1.1 skrll case BFD_RELOC_FRV_GPRELLO:
1751 1.1 skrll non_pic_p = ! frv_pic_p;
1752 1.1 skrll break;
1753 1.1 skrll
1754 1.1 skrll case BFD_RELOC_FRV_LO16:
1755 1.1 skrll case BFD_RELOC_FRV_HI16:
1756 1.1 skrll if (S_GET_SEGMENT (s) != absolute_section)
1757 1.1 skrll non_pic_p = 1;
1758 1.1 skrll break;
1759 1.1 skrll
1760 1.1 skrll case BFD_RELOC_VTABLE_INHERIT:
1761 1.1 skrll case BFD_RELOC_VTABLE_ENTRY:
1762 1.1 skrll non_pic_p = 1;
1763 1.1 skrll break;
1764 1.1 skrll
1765 1.1 skrll /* If this is a blessed BFD_RELOC_32, convert it back to the normal
1766 1.1 skrll relocation. */
1767 1.1 skrll case BFD_RELOC_CTOR:
1768 1.1 skrll fixp->fx_r_type = BFD_RELOC_32;
1769 1.1 skrll break;
1770 1.1 skrll }
1771 1.1 skrll
1772 1.1 skrll if (non_pic_p)
1773 1.1 skrll {
1774 1.1 skrll DPRINTF1 (" (Non-pic relocation)\n");
1775 1.1 skrll if (frv_pic_p)
1776 1.1 skrll as_warn_where (fixp->fx_file, fixp->fx_line,
1777 1.1 skrll _("Relocation %s is not safe for %s"),
1778 1.1 skrll bfd_get_reloc_code_name (reloc), frv_pic_flag);
1779 1.1 skrll
1780 1.1 skrll else if ((frv_flags & EF_FRV_NON_PIC_RELOCS) == 0)
1781 1.1 skrll {
1782 1.1 skrll frv_flags |= EF_FRV_NON_PIC_RELOCS;
1783 1.1 skrll bfd_set_private_flags (abfd, frv_flags);
1784 1.1 skrll }
1785 1.1 skrll }
1786 1.1 skrll #ifdef DEBUG
1787 1.1 skrll else
1788 1.1 skrll DPRINTF1 ("\n");
1789 1.1 skrll #endif
1790 1.1 skrll }
1791 1.1 skrll }
1792 1.1 skrll
1793 1.1 skrll /* After all of the symbols have been adjusted, go over the file looking
1794 1.1 skrll for any relocations that pic won't support. */
1795 1.1 skrll
1796 1.1 skrll void
1797 1.1 skrll frv_frob_file (void)
1798 1.1 skrll {
1799 1.1 skrll bfd_map_over_sections (stdoutput, frv_frob_file_section, (void *) 0);
1800 1.1 skrll }
1801 1.1.1.2 christos
1802 1.1 skrll void
1803 1.1 skrll frv_frob_label (symbolS *this_label)
1804 1.1 skrll {
1805 1.1 skrll struct vliw_insn_list *vliw_insn_list_entry;
1806 1.1 skrll
1807 1.1 skrll dwarf2_emit_label (this_label);
1808 1.1 skrll if (frv_mach != bfd_mach_frvtomcat)
1809 1.1 skrll return;
1810 1.1.1.3 christos
1811 1.1 skrll if (now_seg != text_section)
1812 1.1 skrll return;
1813 1.1 skrll
1814 1.1 skrll vliw_insn_list_entry = frv_insert_vliw_insn(DONT_COUNT);
1815 1.1 skrll vliw_insn_list_entry->type = VLIW_LABEL_TYPE;
1816 1.1 skrll vliw_insn_list_entry->sym = this_label;
1817 1.1 skrll }
1818 1.1 skrll
1819 1.1 skrll fixS *
1820 1.1 skrll frv_cgen_record_fixup_exp (fragS *frag,
1821 1.1 skrll int where,
1822 1.1 skrll const CGEN_INSN *insn,
1823 1.1 skrll int length,
1824 1.1 skrll const CGEN_OPERAND *operand,
1825 1.1 skrll int opinfo,
1826 1.1 skrll expressionS *exp)
1827 1.1 skrll {
1828 1.1 skrll fixS * fixP = gas_cgen_record_fixup_exp (frag, where, insn, length,
1829 1.1 skrll operand, opinfo, exp);
1830 1.1.1.3 christos
1831 1.1 skrll if (frv_mach == bfd_mach_frvtomcat
1832 1.1 skrll && current_vliw_insn
1833 && current_vliw_insn->type == VLIW_BRANCH_TYPE
1834 && exp != NULL)
1835 current_vliw_insn->sym = exp->X_add_symbol;
1836
1837 return fixP;
1838 }
1839