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