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