tc-frv.c revision 1.1.1.3 1 1.1 skrll /* tc-frv.c -- Assembler for the Fujitsu FRV.
2 1.1.1.3 christos Copyright (C) 2002-2015 Free Software Foundation, Inc.
3 1.1 skrll
4 1.1 skrll This file is part of GAS, the GNU Assembler.
5 1.1 skrll
6 1.1 skrll GAS is free software; you can redistribute it and/or modify
7 1.1 skrll it under the terms of the GNU General Public License as published by
8 1.1 skrll the Free Software Foundation; either version 3, or (at your option)
9 1.1 skrll any later version.
10 1.1 skrll
11 1.1 skrll GAS is distributed in the hope that it will be useful,
12 1.1 skrll but WITHOUT ANY WARRANTY; without even the implied warranty of
13 1.1 skrll MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 1.1 skrll GNU General Public License for more details.
15 1.1 skrll
16 1.1 skrll You should have received a copy of the GNU General Public License
17 1.1 skrll along with GAS; see the file COPYING. If not, write to
18 1.1 skrll the Free Software Foundation, 51 Franklin Street - Fifth Floor,
19 1.1 skrll Boston, MA 02110-1301, USA. */
20 1.1 skrll
21 1.1 skrll #include "as.h"
22 1.1.1.3 christos #include "subsegs.h"
23 1.1 skrll #include "symcat.h"
24 1.1 skrll #include "opcodes/frv-desc.h"
25 1.1 skrll #include "opcodes/frv-opc.h"
26 1.1 skrll #include "cgen.h"
27 1.1 skrll #include "libbfd.h"
28 1.1 skrll #include "elf/common.h"
29 1.1 skrll #include "elf/frv.h"
30 1.1.1.2 christos #include "dwarf2dbg.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.1.3 christos /* 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.1.3 christos 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.1.3 christos 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.1.3 christos {
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.1.3 christos
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.1.3 christos 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.1.3 christos 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.1.3 christos 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.1.3 christos 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.1.3 christos /* 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.1.3 christos 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.1.3 christos 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.1.3 christos
740 1.1 skrll single_nop->next = second_part;
741 1.1 skrll
742 1.1.1.3 christos 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.1.3 christos second_part->next = vliw_to_split->next;
777 1.1 skrll frv_adjust_vliw_count (second_part);
778 1.1.1.3 christos
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.1.3 christos 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.1.3 christos 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.1.3 christos
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.1.3 christos 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.1.2 christos if (vliw1->insn_count == 2)
900 1.1 skrll {
901 1.1 skrll /* Check vliw1 for a label. */
902 1.1 skrll for (this_insn = vliw1->insn_list; this_insn; this_insn = this_insn->next)
903 1.1 skrll {
904 1.1 skrll if (this_insn->type == VLIW_LABEL_TYPE)
905 1.1 skrll {
906 1.1 skrll if ((temp_insn = frv_find_in_vliw (VLIW_BRANCH_TYPE, vliw2, this_insn->sym)) != NULL)
907 1.1 skrll {
908 1.1 skrll temp_insn->snop_frag->fr_subtype = NOP_KEEP;
909 1.1 skrll vliw1 = frv_tomcat_shuffle (VLIW_SINGLE_NOP, vliw2, this_insn);
910 1.1 skrll if (tomcat_stats)
911 1.1 skrll tomcat_singles++;
912 1.1 skrll }
913 1.1 skrll else
914 1.1 skrll vliw1 = vliw1->next;
915 1.1 skrll goto workaround_top;
916 1.1 skrll }
917 1.1 skrll }
918 1.1 skrll }
919 1.1 skrll /* Examine each insn in this VLIW. Look for the workaround criteria. */
920 1.1 skrll for (this_insn = vliw1->insn_list; this_insn; this_insn = this_insn->next)
921 1.1 skrll {
922 1.1 skrll /* Don't look at labels or nops. */
923 1.1 skrll while (this_insn
924 1.1 skrll && (this_insn->type == VLIW_LABEL_TYPE
925 1.1 skrll || this_insn->type == VLIW_NOP_TYPE
926 1.1 skrll || this_insn->type == VLIW_BRANCH_HAS_NOPS))
927 1.1 skrll this_insn = this_insn->next;
928 1.1 skrll
929 1.1 skrll if (!this_insn)
930 1.1 skrll {
931 1.1 skrll vliw1 = vliw2;
932 1.1 skrll goto workaround_top;
933 1.1 skrll }
934 1.1 skrll
935 1.1 skrll if (frv_is_branch_insn (this_insn->insn))
936 1.1 skrll {
937 1.1 skrll if ((temp_insn = frv_find_in_vliw (VLIW_LABEL_TYPE, vliw1, this_insn->sym)) != NULL)
938 1.1 skrll {
939 1.1 skrll /* Insert [nop/nop] [nop] before branch. */
940 1.1 skrll this_insn->snop_frag->fr_subtype = NOP_KEEP;
941 1.1 skrll this_insn->dnop_frag->fr_subtype = NOP_KEEP;
942 1.1 skrll vliw1 = frv_tomcat_shuffle (VLIW_DOUBLE_THEN_SINGLE_NOP, vliw1, this_insn);
943 1.1 skrll goto workaround_top;
944 1.1 skrll }
945 1.1 skrll }
946 1.1 skrll
947 1.1 skrll
948 1.1 skrll }
949 1.1 skrll /* This vliw insn checks out okay. Take a look at the next one. */
950 1.1 skrll vliw1 = vliw1->next;
951 1.1 skrll goto workaround_top;
952 1.1 skrll }
953 1.1 skrll
954 1.1 skrll void
955 1.1 skrll frv_tomcat_workaround (void)
956 1.1 skrll {
957 1.1 skrll if (frv_mach != bfd_mach_frvtomcat)
958 1.1 skrll return;
959 1.1 skrll
960 1.1 skrll if (tomcat_debug)
961 1.1 skrll frv_debug_tomcat (vliw_chain_top);
962 1.1 skrll
963 1.1 skrll frv_tomcat_analyze_vliw_chains ();
964 1.1 skrll
965 1.1 skrll if (tomcat_stats)
966 1.1 skrll {
967 1.1 skrll fprintf (stderr, "Inserted %d Single Nops\n", tomcat_singles);
968 1.1 skrll fprintf (stderr, "Inserted %d Double Nops\n", tomcat_doubles);
969 1.1 skrll }
970 1.1 skrll }
971 1.1 skrll
972 1.1 skrll static int
973 1.1 skrll fr550_check_insn_acc_range (frv_insn *insn, int low, int hi)
974 1.1 skrll {
975 1.1 skrll int acc;
976 1.1 skrll switch (CGEN_INSN_NUM (insn->insn))
977 1.1 skrll {
978 1.1 skrll case FRV_INSN_MADDACCS:
979 1.1 skrll case FRV_INSN_MSUBACCS:
980 1.1 skrll case FRV_INSN_MDADDACCS:
981 1.1 skrll case FRV_INSN_MDSUBACCS:
982 1.1 skrll case FRV_INSN_MASACCS:
983 1.1 skrll case FRV_INSN_MDASACCS:
984 1.1 skrll acc = insn->fields.f_ACC40Si;
985 1.1 skrll if (acc < low || acc > hi)
986 1.1 skrll return 1; /* out of range */
987 1.1 skrll acc = insn->fields.f_ACC40Sk;
988 1.1 skrll if (acc < low || acc > hi)
989 1.1 skrll return 1; /* out of range */
990 1.1 skrll break;
991 1.1 skrll case FRV_INSN_MMULHS:
992 1.1 skrll case FRV_INSN_MMULHU:
993 1.1 skrll case FRV_INSN_MMULXHS:
994 1.1 skrll case FRV_INSN_MMULXHU:
995 1.1 skrll case FRV_INSN_CMMULHS:
996 1.1 skrll case FRV_INSN_CMMULHU:
997 1.1 skrll case FRV_INSN_MQMULHS:
998 1.1 skrll case FRV_INSN_MQMULHU:
999 1.1 skrll case FRV_INSN_MQMULXHS:
1000 1.1 skrll case FRV_INSN_MQMULXHU:
1001 1.1 skrll case FRV_INSN_CMQMULHS:
1002 1.1 skrll case FRV_INSN_CMQMULHU:
1003 1.1.1.3 christos case FRV_INSN_MMACHS:
1004 1.1 skrll case FRV_INSN_MMRDHS:
1005 1.1 skrll case FRV_INSN_CMMACHS:
1006 1.1 skrll case FRV_INSN_MQMACHS:
1007 1.1 skrll case FRV_INSN_CMQMACHS:
1008 1.1 skrll case FRV_INSN_MQXMACHS:
1009 1.1 skrll case FRV_INSN_MQXMACXHS:
1010 1.1 skrll case FRV_INSN_MQMACXHS:
1011 1.1 skrll case FRV_INSN_MCPXRS:
1012 1.1 skrll case FRV_INSN_MCPXIS:
1013 1.1 skrll case FRV_INSN_CMCPXRS:
1014 1.1 skrll case FRV_INSN_CMCPXIS:
1015 1.1 skrll case FRV_INSN_MQCPXRS:
1016 1.1 skrll case FRV_INSN_MQCPXIS:
1017 1.1 skrll acc = insn->fields.f_ACC40Sk;
1018 1.1 skrll if (acc < low || acc > hi)
1019 1.1 skrll return 1; /* out of range */
1020 1.1 skrll break;
1021 1.1 skrll case FRV_INSN_MMACHU:
1022 1.1 skrll case FRV_INSN_MMRDHU:
1023 1.1 skrll case FRV_INSN_CMMACHU:
1024 1.1 skrll case FRV_INSN_MQMACHU:
1025 1.1 skrll case FRV_INSN_CMQMACHU:
1026 1.1 skrll case FRV_INSN_MCPXRU:
1027 1.1 skrll case FRV_INSN_MCPXIU:
1028 1.1 skrll case FRV_INSN_CMCPXRU:
1029 1.1 skrll case FRV_INSN_CMCPXIU:
1030 1.1 skrll case FRV_INSN_MQCPXRU:
1031 1.1 skrll case FRV_INSN_MQCPXIU:
1032 1.1 skrll acc = insn->fields.f_ACC40Uk;
1033 1.1 skrll if (acc < low || acc > hi)
1034 1.1 skrll return 1; /* out of range */
1035 1.1 skrll break;
1036 1.1 skrll default:
1037 1.1 skrll break;
1038 1.1 skrll }
1039 1.1 skrll return 0; /* all is ok */
1040 1.1 skrll }
1041 1.1.1.2 christos
1042 1.1 skrll static int
1043 1.1.1.2 christos fr550_check_acc_range (FRV_VLIW *vlw, frv_insn *insn)
1044 1.1 skrll {
1045 1.1 skrll switch ((*vlw->current_vliw)[vlw->next_slot - 1])
1046 1.1 skrll {
1047 1.1 skrll case UNIT_FM0:
1048 1.1 skrll case UNIT_FM2:
1049 1.1 skrll return fr550_check_insn_acc_range (insn, 0, 3);
1050 1.1 skrll case UNIT_FM1:
1051 1.1 skrll case UNIT_FM3:
1052 1.1 skrll return fr550_check_insn_acc_range (insn, 4, 7);
1053 1.1 skrll default:
1054 1.1 skrll break;
1055 1.1 skrll }
1056 1.1 skrll return 0; /* all is ok */
1057 1.1 skrll }
1058 1.1 skrll
1059 1.1 skrll /* Return true if the target implements instruction INSN. */
1060 1.1 skrll
1061 1.1 skrll static bfd_boolean
1062 1.1 skrll target_implements_insn_p (const CGEN_INSN *insn)
1063 1.1 skrll {
1064 1.1 skrll switch (frv_mach)
1065 1.1 skrll {
1066 1.1 skrll default:
1067 1.1 skrll /* bfd_mach_frv or generic. */
1068 1.1 skrll return TRUE;
1069 1.1 skrll
1070 1.1 skrll case bfd_mach_fr300:
1071 1.1 skrll case bfd_mach_frvsimple:
1072 1.1 skrll return CGEN_INSN_MACH_HAS_P (insn, MACH_SIMPLE);
1073 1.1 skrll
1074 1.1 skrll case bfd_mach_fr400:
1075 1.1 skrll return ((fr400_audio || !CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_AUDIO))
1076 1.1 skrll && CGEN_INSN_MACH_HAS_P (insn, MACH_FR400));
1077 1.1 skrll
1078 1.1 skrll case bfd_mach_fr450:
1079 1.1 skrll return CGEN_INSN_MACH_HAS_P (insn, MACH_FR450);
1080 1.1 skrll
1081 1.1 skrll case bfd_mach_fr500:
1082 1.1 skrll return CGEN_INSN_MACH_HAS_P (insn, MACH_FR500);
1083 1.1 skrll
1084 1.1 skrll case bfd_mach_fr550:
1085 1.1 skrll return CGEN_INSN_MACH_HAS_P (insn, MACH_FR550);
1086 1.1 skrll }
1087 1.1 skrll }
1088 1.1 skrll
1089 1.1 skrll void
1090 1.1 skrll md_assemble (char *str)
1091 1.1 skrll {
1092 1.1 skrll frv_insn insn;
1093 1.1 skrll char *errmsg;
1094 1.1 skrll int packing_constraint;
1095 1.1 skrll finished_insnS finished_insn;
1096 1.1 skrll fragS *double_nop_frag = NULL;
1097 1.1 skrll fragS *single_nop_frag = NULL;
1098 1.1 skrll struct vliw_insn_list *vliw_insn_list_entry = NULL;
1099 1.1 skrll
1100 1.1 skrll /* Initialize GAS's cgen interface for a new instruction. */
1101 1.1 skrll gas_cgen_init_parse ();
1102 1.1 skrll
1103 1.1 skrll memset (&insn, 0, sizeof (insn));
1104 1.1 skrll
1105 1.1.1.3 christos insn.insn = frv_cgen_assemble_insn
1106 1.1 skrll (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, &errmsg);
1107 1.1 skrll
1108 1.1.1.2 christos if (!insn.insn)
1109 1.1 skrll {
1110 1.1 skrll as_bad ("%s", errmsg);
1111 1.1.1.3 christos return;
1112 1.1 skrll }
1113 1.1 skrll
1114 1.1 skrll /* If the cpu is tomcat, then we need to insert nops to workaround
1115 1.1 skrll hardware limitations. We need to keep track of each vliw unit
1116 1.1 skrll and examine the length of the unit and the individual insns
1117 1.1 skrll within the unit to determine the number and location of the
1118 1.1 skrll required nops. */
1119 1.1 skrll if (frv_mach == bfd_mach_frvtomcat)
1120 1.1 skrll {
1121 1.1.1.3 christos /* If we've just finished a VLIW insn OR this is a branch,
1122 1.1 skrll then start up a new frag. Fill it with nops. We will get rid
1123 1.1 skrll of those that are not required after we've seen all of the
1124 1.1 skrll instructions but before we start resolving fixups. */
1125 1.1 skrll if ( !FRV_IS_NOP (insn)
1126 1.1 skrll && (frv_is_branch_insn (insn.insn) || insn.fields.f_pack))
1127 1.1 skrll {
1128 1.1 skrll char *buffer;
1129 1.1 skrll
1130 1.1 skrll frag_wane (frag_now);
1131 1.1 skrll frag_new (0);
1132 1.1 skrll double_nop_frag = frag_now;
1133 1.1 skrll buffer = frag_var (rs_machine_dependent, 8, 8, NOP_DELETE, NULL, 0, 0);
1134 1.1 skrll md_number_to_chars (buffer, FRV_NOP_PACK, 4);
1135 1.1 skrll md_number_to_chars (buffer+4, FRV_NOP_NOPACK, 4);
1136 1.1 skrll
1137 1.1 skrll frag_wane (frag_now);
1138 1.1 skrll frag_new (0);
1139 1.1 skrll single_nop_frag = frag_now;
1140 1.1 skrll buffer = frag_var (rs_machine_dependent, 4, 4, NOP_DELETE, NULL, 0, 0);
1141 1.1 skrll md_number_to_chars (buffer, FRV_NOP_NOPACK, 4);
1142 1.1 skrll }
1143 1.1 skrll
1144 1.1 skrll vliw_insn_list_entry = frv_insert_vliw_insn (DO_COUNT);
1145 1.1 skrll vliw_insn_list_entry->insn = insn.insn;
1146 1.1 skrll if (frv_is_branch_insn (insn.insn))
1147 1.1 skrll vliw_insn_list_entry->type = VLIW_BRANCH_TYPE;
1148 1.1 skrll
1149 1.1 skrll if ( !FRV_IS_NOP (insn)
1150 1.1 skrll && (frv_is_branch_insn (insn.insn) || insn.fields.f_pack))
1151 1.1 skrll {
1152 1.1 skrll vliw_insn_list_entry->snop_frag = single_nop_frag;
1153 1.1 skrll vliw_insn_list_entry->dnop_frag = double_nop_frag;
1154 1.1 skrll }
1155 1.1 skrll }
1156 1.1 skrll
1157 1.1 skrll /* Make sure that this insn does not violate the VLIW packing constraints. */
1158 1.1 skrll /* -mno-pack disallows any packing whatsoever. */
1159 1.1 skrll if (frv_flags & EF_FRV_NOPACK)
1160 1.1 skrll {
1161 1.1 skrll if (! insn.fields.f_pack)
1162 1.1 skrll {
1163 1.1 skrll as_bad (_("VLIW packing used for -mno-pack"));
1164 1.1 skrll return;
1165 1.1 skrll }
1166 1.1 skrll }
1167 1.1 skrll /* -mcpu=FRV is an idealized FR-V implementation that supports all of the
1168 1.1 skrll instructions, don't do vliw checking. */
1169 1.1 skrll else if (frv_mach != bfd_mach_frv)
1170 1.1 skrll {
1171 1.1 skrll if (!target_implements_insn_p (insn.insn))
1172 1.1 skrll {
1173 1.1 skrll as_bad (_("Instruction not supported by this architecture"));
1174 1.1 skrll return;
1175 1.1 skrll }
1176 1.1 skrll packing_constraint = frv_vliw_add_insn (& vliw, insn.insn);
1177 1.1 skrll if (frv_mach == bfd_mach_fr550 && ! packing_constraint)
1178 1.1 skrll packing_constraint = fr550_check_acc_range (& vliw, & insn);
1179 1.1 skrll if (insn.fields.f_pack)
1180 1.1 skrll frv_vliw_reset (& vliw, frv_mach, frv_flags);
1181 1.1 skrll if (packing_constraint)
1182 1.1 skrll {
1183 1.1 skrll as_bad (_("VLIW packing constraint violation"));
1184 1.1 skrll return;
1185 1.1 skrll }
1186 1.1 skrll }
1187 1.1 skrll
1188 1.1 skrll /* Doesn't really matter what we pass for RELAX_P here. */
1189 1.1 skrll gas_cgen_finish_insn (insn.insn, insn.buffer,
1190 1.1 skrll CGEN_FIELDS_BITSIZE (& insn.fields), 1, &finished_insn);
1191 1.1 skrll
1192 1.1 skrll
1193 1.1 skrll /* If the cpu is tomcat, then we need to insert nops to workaround
1194 1.1 skrll hardware limitations. We need to keep track of each vliw unit
1195 1.1 skrll and examine the length of the unit and the individual insns
1196 1.1 skrll within the unit to determine the number and location of the
1197 1.1 skrll required nops. */
1198 1.1 skrll if (frv_mach == bfd_mach_frvtomcat)
1199 1.1 skrll {
1200 1.1 skrll if (vliw_insn_list_entry)
1201 1.1 skrll vliw_insn_list_entry->address = finished_insn.addr;
1202 1.1 skrll else
1203 1.1 skrll abort();
1204 1.1 skrll
1205 1.1 skrll if (insn.fields.f_pack)
1206 1.1 skrll {
1207 1.1 skrll /* We've completed a VLIW insn. */
1208 1.1 skrll previous_vliw_chain = current_vliw_chain;
1209 1.1.1.3 christos current_vliw_chain = NULL;
1210 1.1 skrll current_vliw_insn = NULL;
1211 1.1 skrll }
1212 1.1 skrll }
1213 1.1 skrll }
1214 1.1 skrll
1215 1.1 skrll /* The syntax in the manual says constants begin with '#'.
1216 1.1.1.3 christos We just ignore it. */
1217 1.1 skrll
1218 1.1 skrll void
1219 1.1 skrll md_operand (expressionS *expressionP)
1220 1.1 skrll {
1221 1.1 skrll if (* input_line_pointer == '#')
1222 1.1 skrll {
1223 1.1 skrll input_line_pointer ++;
1224 1.1 skrll expression (expressionP);
1225 1.1 skrll }
1226 1.1 skrll }
1227 1.1 skrll
1228 1.1 skrll valueT
1229 1.1 skrll md_section_align (segT segment, valueT size)
1230 1.1.1.3 christos {
1231 1.1 skrll int align = bfd_get_section_alignment (stdoutput, segment);
1232 1.1 skrll return ((size + (1 << align) - 1) & -(1 << align));
1233 1.1 skrll }
1234 1.1 skrll
1235 1.1 skrll symbolS *
1236 1.1 skrll md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
1237 1.1 skrll {
1238 1.1 skrll return 0;
1239 1.1 skrll }
1240 1.1 skrll
1241 1.1 skrll /* Interface to relax_segment. */
1243 1.1 skrll
1244 1.1 skrll /* FIXME: Build table by hand, get it working, then machine generate. */
1245 1.1 skrll const relax_typeS md_relax_table[] =
1246 1.1 skrll {
1247 1.1 skrll {1, 1, 0, 0},
1248 1.1 skrll {511 - 2 - 2, -512 - 2 + 2, 0, 2 },
1249 1.1 skrll {0x2000000 - 1 - 2, -0x2000000 - 2, 2, 0 },
1250 1.1 skrll {0x2000000 - 1 - 2, -0x2000000 - 2, 4, 0 }
1251 1.1 skrll };
1252 1.1 skrll
1253 1.1 skrll long
1254 1.1 skrll frv_relax_frag (fragS *fragP ATTRIBUTE_UNUSED, long stretch ATTRIBUTE_UNUSED)
1255 1.1 skrll {
1256 1.1 skrll return 0;
1257 1.1 skrll }
1258 1.1 skrll
1259 1.1 skrll /* Return an initial guess of the length by which a fragment must grow to
1260 1.1 skrll hold a branch to reach its destination.
1261 1.1 skrll Also updates fr_type/fr_subtype as necessary.
1262 1.1 skrll
1263 1.1 skrll Called just before doing relaxation.
1264 1.1 skrll Any symbol that is now undefined will not become defined.
1265 1.1 skrll The guess for fr_var is ACTUALLY the growth beyond fr_fix.
1266 1.1 skrll Whatever we do to grow fr_fix or fr_var contributes to our returned value.
1267 1.1 skrll Although it may not be explicit in the frag, pretend fr_var starts with a
1268 1.1 skrll 0 value. */
1269 1.1 skrll
1270 1.1 skrll int
1271 1.1 skrll md_estimate_size_before_relax (fragS *fragP, segT segment ATTRIBUTE_UNUSED)
1272 1.1 skrll {
1273 1.1 skrll switch (fragP->fr_subtype)
1274 1.1 skrll {
1275 1.1 skrll case NOP_KEEP:
1276 1.1 skrll return fragP->fr_var;
1277 1.1 skrll
1278 1.1.1.3 christos default:
1279 1.1.1.3 christos case NOP_DELETE:
1280 1.1 skrll return 0;
1281 1.1 skrll }
1282 1.1 skrll }
1283 1.1 skrll
1284 1.1 skrll /* *fragP has been relaxed to its final size, and now needs to have
1285 1.1 skrll the bytes inside it modified to conform to the new size.
1286 1.1 skrll
1287 1.1 skrll Called after relaxation is finished.
1288 1.1 skrll fragP->fr_type == rs_machine_dependent.
1289 1.1 skrll fragP->fr_subtype is the subtype of what the address relaxed to. */
1290 1.1 skrll
1291 1.1 skrll void
1292 1.1 skrll md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
1293 1.1 skrll segT sec ATTRIBUTE_UNUSED,
1294 1.1 skrll fragS *fragP)
1295 1.1 skrll {
1296 1.1 skrll switch (fragP->fr_subtype)
1297 1.1 skrll {
1298 1.1 skrll default:
1299 1.1 skrll case NOP_DELETE:
1300 1.1 skrll return;
1301 1.1 skrll
1302 1.1.1.3 christos case NOP_KEEP:
1303 1.1 skrll fragP->fr_fix = fragP->fr_var;
1304 1.1 skrll fragP->fr_var = 0;
1305 1.1 skrll return;
1306 1.1 skrll }
1307 1.1 skrll }
1308 1.1 skrll
1309 1.1 skrll /* Functions concerning relocs. */
1311 1.1 skrll
1312 1.1 skrll /* The location from which a PC relative jump should be calculated,
1313 1.1 skrll given a PC relative reloc. */
1314 1.1 skrll
1315 1.1 skrll long
1316 1.1 skrll md_pcrel_from_section (fixS *fixP, segT sec)
1317 1.1 skrll {
1318 1.1 skrll if (TC_FORCE_RELOCATION (fixP)
1319 1.1 skrll || (fixP->fx_addsy != (symbolS *) NULL
1320 1.1 skrll && S_GET_SEGMENT (fixP->fx_addsy) != sec))
1321 1.1 skrll {
1322 1.1 skrll /* If we can't adjust this relocation, or if it references a
1323 1.1 skrll local symbol in a different section (which
1324 1.1 skrll TC_FORCE_RELOCATION can't check), let the linker figure it
1325 1.1 skrll out. */
1326 1.1 skrll return 0;
1327 1.1 skrll }
1328 1.1 skrll
1329 1.1 skrll return (fixP->fx_frag->fr_address + fixP->fx_where) & ~1;
1330 1.1 skrll }
1331 1.1 skrll
1332 1.1 skrll /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
1333 1.1 skrll Returns BFD_RELOC_NONE if no reloc type can be found.
1334 1.1 skrll *FIXP may be modified if desired. */
1335 1.1 skrll
1336 1.1 skrll bfd_reloc_code_real_type
1337 1.1 skrll md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
1338 1.1 skrll const CGEN_OPERAND *operand,
1339 1.1 skrll fixS *fixP)
1340 1.1 skrll {
1341 1.1 skrll switch (operand->type)
1342 1.1 skrll {
1343 1.1 skrll case FRV_OPERAND_LABEL16:
1344 1.1 skrll fixP->fx_pcrel = TRUE;
1345 1.1 skrll return BFD_RELOC_FRV_LABEL16;
1346 1.1 skrll
1347 1.1 skrll case FRV_OPERAND_LABEL24:
1348 1.1 skrll fixP->fx_pcrel = TRUE;
1349 1.1 skrll
1350 1.1 skrll if (fixP->fx_cgen.opinfo != 0)
1351 1.1 skrll return fixP->fx_cgen.opinfo;
1352 1.1 skrll
1353 1.1 skrll return BFD_RELOC_FRV_LABEL24;
1354 1.1 skrll
1355 1.1 skrll case FRV_OPERAND_UHI16:
1356 1.1 skrll case FRV_OPERAND_ULO16:
1357 1.1 skrll case FRV_OPERAND_SLO16:
1358 1.1 skrll case FRV_OPERAND_CALLANN:
1359 1.1 skrll case FRV_OPERAND_LDANN:
1360 1.1 skrll case FRV_OPERAND_LDDANN:
1361 1.1 skrll /* The relocation type should be recorded in opinfo */
1362 1.1 skrll if (fixP->fx_cgen.opinfo != 0)
1363 1.1 skrll return fixP->fx_cgen.opinfo;
1364 1.1 skrll break;
1365 1.1 skrll
1366 1.1 skrll case FRV_OPERAND_D12:
1367 1.1 skrll case FRV_OPERAND_S12:
1368 1.1 skrll if (fixP->fx_cgen.opinfo != 0)
1369 1.1 skrll return fixP->fx_cgen.opinfo;
1370 1.1 skrll
1371 1.1 skrll return BFD_RELOC_FRV_GPREL12;
1372 1.1.1.3 christos
1373 1.1 skrll case FRV_OPERAND_U12:
1374 1.1 skrll return BFD_RELOC_FRV_GPRELU12;
1375 1.1 skrll
1376 1.1 skrll default:
1377 1.1 skrll break;
1378 1.1 skrll }
1379 1.1 skrll return BFD_RELOC_NONE;
1380 1.1 skrll }
1381 1.1 skrll
1382 1.1 skrll
1383 1.1 skrll /* See whether we need to force a relocation into the output file.
1384 1.1 skrll This is used to force out switch and PC relative relocations when
1385 1.1 skrll relaxing. */
1386 1.1 skrll
1387 1.1 skrll int
1388 1.1 skrll frv_force_relocation (fixS *fix)
1389 1.1 skrll {
1390 1.1 skrll switch (fix->fx_r_type < BFD_RELOC_UNUSED
1391 1.1 skrll ? (int) fix->fx_r_type
1392 1.1 skrll : fix->fx_cgen.opinfo)
1393 1.1 skrll {
1394 1.1 skrll case BFD_RELOC_FRV_GPREL12:
1395 1.1 skrll case BFD_RELOC_FRV_GPRELU12:
1396 1.1 skrll case BFD_RELOC_FRV_GPREL32:
1397 1.1 skrll case BFD_RELOC_FRV_GPRELHI:
1398 1.1 skrll case BFD_RELOC_FRV_GPRELLO:
1399 1.1 skrll case BFD_RELOC_FRV_GOT12:
1400 1.1 skrll case BFD_RELOC_FRV_GOTHI:
1401 1.1 skrll case BFD_RELOC_FRV_GOTLO:
1402 1.1 skrll case BFD_RELOC_FRV_FUNCDESC_VALUE:
1403 1.1 skrll case BFD_RELOC_FRV_FUNCDESC_GOTOFF12:
1404 1.1 skrll case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI:
1405 1.1 skrll case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO:
1406 1.1 skrll case BFD_RELOC_FRV_GOTOFF12:
1407 1.1 skrll case BFD_RELOC_FRV_GOTOFFHI:
1408 1.1 skrll case BFD_RELOC_FRV_GOTOFFLO:
1409 1.1 skrll case BFD_RELOC_FRV_GETTLSOFF:
1410 1.1 skrll case BFD_RELOC_FRV_TLSDESC_VALUE:
1411 1.1 skrll case BFD_RELOC_FRV_GOTTLSDESC12:
1412 1.1 skrll case BFD_RELOC_FRV_GOTTLSDESCHI:
1413 1.1 skrll case BFD_RELOC_FRV_GOTTLSDESCLO:
1414 1.1 skrll case BFD_RELOC_FRV_TLSMOFF12:
1415 1.1 skrll case BFD_RELOC_FRV_TLSMOFFHI:
1416 1.1 skrll case BFD_RELOC_FRV_TLSMOFFLO:
1417 1.1 skrll case BFD_RELOC_FRV_GOTTLSOFF12:
1418 1.1 skrll case BFD_RELOC_FRV_GOTTLSOFFHI:
1419 1.1 skrll case BFD_RELOC_FRV_GOTTLSOFFLO:
1420 1.1 skrll case BFD_RELOC_FRV_TLSOFF:
1421 1.1 skrll case BFD_RELOC_FRV_TLSDESC_RELAX:
1422 1.1 skrll case BFD_RELOC_FRV_GETTLSOFF_RELAX:
1423 1.1 skrll case BFD_RELOC_FRV_TLSOFF_RELAX:
1424 1.1 skrll return 1;
1425 1.1 skrll
1426 1.1 skrll default:
1427 1.1 skrll break;
1428 1.1 skrll }
1429 1.1 skrll
1430 1.1 skrll return generic_force_reloc (fix);
1431 1.1 skrll }
1432 1.1 skrll
1433 1.1 skrll /* Apply a fixup that could be resolved within the assembler. */
1434 1.1 skrll
1435 1.1 skrll void
1436 1.1 skrll md_apply_fix (fixS *fixP, valueT *valP, segT seg)
1437 1.1 skrll {
1438 1.1 skrll if (fixP->fx_addsy == 0)
1439 1.1 skrll switch (fixP->fx_cgen.opinfo)
1440 1.1 skrll {
1441 1.1 skrll case BFD_RELOC_FRV_HI16:
1442 1.1 skrll *valP >>= 16;
1443 1.1 skrll /* Fall through. */
1444 1.1 skrll case BFD_RELOC_FRV_LO16:
1445 1.1 skrll *valP &= 0xffff;
1446 1.1 skrll break;
1447 1.1 skrll
1448 1.1 skrll /* We need relocations for these, even if their symbols reduce
1449 1.1 skrll to constants. */
1450 1.1 skrll case BFD_RELOC_FRV_GPREL12:
1451 1.1 skrll case BFD_RELOC_FRV_GPRELU12:
1452 1.1 skrll case BFD_RELOC_FRV_GPREL32:
1453 1.1 skrll case BFD_RELOC_FRV_GPRELHI:
1454 1.1 skrll case BFD_RELOC_FRV_GPRELLO:
1455 1.1 skrll case BFD_RELOC_FRV_GOT12:
1456 1.1 skrll case BFD_RELOC_FRV_GOTHI:
1457 1.1 skrll case BFD_RELOC_FRV_GOTLO:
1458 1.1 skrll case BFD_RELOC_FRV_FUNCDESC_VALUE:
1459 1.1 skrll case BFD_RELOC_FRV_FUNCDESC_GOTOFF12:
1460 1.1 skrll case BFD_RELOC_FRV_FUNCDESC_GOTOFFHI:
1461 1.1 skrll case BFD_RELOC_FRV_FUNCDESC_GOTOFFLO:
1462 1.1 skrll case BFD_RELOC_FRV_GOTOFF12:
1463 1.1 skrll case BFD_RELOC_FRV_GOTOFFHI:
1464 1.1 skrll case BFD_RELOC_FRV_GOTOFFLO:
1465 1.1 skrll case BFD_RELOC_FRV_GETTLSOFF:
1466 1.1 skrll case BFD_RELOC_FRV_TLSDESC_VALUE:
1467 1.1 skrll case BFD_RELOC_FRV_GOTTLSDESC12:
1468 1.1 skrll case BFD_RELOC_FRV_GOTTLSDESCHI:
1469 1.1 skrll case BFD_RELOC_FRV_GOTTLSDESCLO:
1470 1.1 skrll case BFD_RELOC_FRV_TLSMOFF12:
1471 1.1 skrll case BFD_RELOC_FRV_TLSMOFFHI:
1472 1.1 skrll case BFD_RELOC_FRV_TLSMOFFLO:
1473 1.1 skrll case BFD_RELOC_FRV_GOTTLSOFF12:
1474 1.1 skrll case BFD_RELOC_FRV_GOTTLSOFFHI:
1475 1.1 skrll case BFD_RELOC_FRV_GOTTLSOFFLO:
1476 1.1 skrll case BFD_RELOC_FRV_TLSOFF:
1477 1.1 skrll case BFD_RELOC_FRV_TLSDESC_RELAX:
1478 1.1 skrll case BFD_RELOC_FRV_GETTLSOFF_RELAX:
1479 1.1 skrll case BFD_RELOC_FRV_TLSOFF_RELAX:
1480 1.1 skrll fixP->fx_addsy = abs_section_sym;
1481 1.1 skrll break;
1482 1.1 skrll }
1483 1.1 skrll else
1484 1.1 skrll switch (fixP->fx_cgen.opinfo)
1485 1.1 skrll {
1486 1.1 skrll case BFD_RELOC_FRV_GETTLSOFF:
1487 1.1 skrll case BFD_RELOC_FRV_TLSDESC_VALUE:
1488 1.1 skrll case BFD_RELOC_FRV_GOTTLSDESC12:
1489 1.1 skrll case BFD_RELOC_FRV_GOTTLSDESCHI:
1490 1.1 skrll case BFD_RELOC_FRV_GOTTLSDESCLO:
1491 1.1 skrll case BFD_RELOC_FRV_TLSMOFF12:
1492 1.1 skrll case BFD_RELOC_FRV_TLSMOFFHI:
1493 1.1 skrll case BFD_RELOC_FRV_TLSMOFFLO:
1494 1.1 skrll case BFD_RELOC_FRV_GOTTLSOFF12:
1495 1.1 skrll case BFD_RELOC_FRV_GOTTLSOFFHI:
1496 1.1 skrll case BFD_RELOC_FRV_GOTTLSOFFLO:
1497 1.1 skrll case BFD_RELOC_FRV_TLSOFF:
1498 1.1 skrll case BFD_RELOC_FRV_TLSDESC_RELAX:
1499 1.1 skrll case BFD_RELOC_FRV_GETTLSOFF_RELAX:
1500 1.1 skrll case BFD_RELOC_FRV_TLSOFF_RELAX:
1501 1.1 skrll /* Mark TLS symbols as such. */
1502 1.1 skrll if (S_GET_SEGMENT (fixP->fx_addsy) != absolute_section)
1503 1.1 skrll S_SET_THREAD_LOCAL (fixP->fx_addsy);
1504 1.1 skrll break;
1505 1.1 skrll }
1506 1.1 skrll
1507 1.1 skrll gas_cgen_md_apply_fix (fixP, valP, seg);
1508 1.1 skrll return;
1509 1.1 skrll }
1510 1.1 skrll
1511 1.1 skrll
1512 1.1 skrll /* Write a value out to the object file, using the appropriate endianness. */
1514 1.1 skrll
1515 1.1 skrll void
1516 1.1 skrll frv_md_number_to_chars (char *buf, valueT val, int n)
1517 1.1 skrll {
1518 1.1 skrll number_to_chars_bigendian (buf, val, n);
1519 1.1 skrll }
1520 1.1 skrll
1521 1.1 skrll char *
1522 1.1 skrll md_atof (int type, char *litP, int *sizeP)
1523 1.1 skrll {
1524 1.1 skrll return ieee_md_atof (type, litP, sizeP, TRUE);
1525 1.1 skrll }
1526 1.1 skrll
1527 1.1 skrll bfd_boolean
1528 1.1 skrll frv_fix_adjustable (fixS *fixP)
1529 1.1 skrll {
1530 1.1 skrll bfd_reloc_code_real_type reloc_type;
1531 1.1 skrll
1532 1.1 skrll if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
1533 1.1 skrll {
1534 1.1 skrll const CGEN_INSN *insn = NULL;
1535 1.1 skrll int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
1536 1.1 skrll const CGEN_OPERAND *operand = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex);
1537 1.1 skrll reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
1538 1.1 skrll }
1539 1.1 skrll else
1540 1.1 skrll reloc_type = fixP->fx_r_type;
1541 1.1 skrll
1542 1.1 skrll /* We need the symbol name for the VTABLE entries */
1543 1.1 skrll if ( reloc_type == BFD_RELOC_VTABLE_INHERIT
1544 1.1 skrll || reloc_type == BFD_RELOC_VTABLE_ENTRY
1545 1.1 skrll || reloc_type == BFD_RELOC_FRV_GPREL12
1546 1.1 skrll || reloc_type == BFD_RELOC_FRV_GPRELU12)
1547 1.1 skrll return 0;
1548 1.1 skrll
1549 1.1 skrll return 1;
1550 1.1 skrll }
1551 1.1 skrll
1552 1.1 skrll /* Allow user to set flags bits. */
1553 1.1 skrll void
1554 1.1 skrll frv_set_flags (int arg ATTRIBUTE_UNUSED)
1555 1.1 skrll {
1556 1.1 skrll flagword new_flags = get_absolute_expression ();
1557 1.1 skrll flagword new_mask = ~ (flagword)0;
1558 1.1 skrll
1559 1.1 skrll frv_user_set_flags_p = 1;
1560 1.1 skrll if (*input_line_pointer == ',')
1561 1.1 skrll {
1562 1.1 skrll ++input_line_pointer;
1563 1.1 skrll new_mask = get_absolute_expression ();
1564 1.1 skrll }
1565 1.1 skrll
1566 1.1 skrll frv_flags = (frv_flags & ~new_mask) | (new_flags & new_mask);
1567 1.1 skrll bfd_set_private_flags (stdoutput, frv_flags);
1568 1.1 skrll }
1569 1.1 skrll
1570 1.1 skrll /* Frv specific function to handle 4 byte initializations for pointers that are
1571 1.1 skrll considered 'safe' for use with pic support. Until frv_frob_file{,_section}
1572 1.1 skrll is run, we encode it a BFD_RELOC_CTOR, and it is turned back into a normal
1573 1.1 skrll BFD_RELOC_32 at that time. */
1574 1.1 skrll
1575 1.1 skrll void
1576 1.1 skrll frv_pic_ptr (int nbytes)
1577 1.1 skrll {
1578 1.1 skrll expressionS exp;
1579 1.1 skrll char *p;
1580 1.1 skrll
1581 1.1 skrll if (nbytes != 4)
1582 1.1 skrll abort ();
1583 1.1 skrll
1584 1.1 skrll #ifdef md_flush_pending_output
1585 1.1 skrll md_flush_pending_output ();
1586 1.1 skrll #endif
1587 1.1 skrll
1588 1.1 skrll if (is_it_end_of_statement ())
1589 1.1 skrll {
1590 1.1 skrll demand_empty_rest_of_line ();
1591 1.1 skrll return;
1592 1.1 skrll }
1593 1.1 skrll
1594 1.1 skrll #ifdef md_cons_align
1595 1.1 skrll md_cons_align (nbytes);
1596 1.1.1.3 christos #endif
1597 1.1 skrll
1598 1.1 skrll do
1599 1.1 skrll {
1600 1.1 skrll bfd_reloc_code_real_type reloc_type = BFD_RELOC_CTOR;
1601 1.1 skrll
1602 1.1 skrll if (strncasecmp (input_line_pointer, "funcdesc(", 9) == 0)
1603 1.1 skrll {
1604 1.1 skrll input_line_pointer += 9;
1605 1.1 skrll expression (&exp);
1606 1.1 skrll if (*input_line_pointer == ')')
1607 1.1 skrll input_line_pointer++;
1608 1.1 skrll else
1609 1.1 skrll as_bad (_("missing ')'"));
1610 1.1 skrll reloc_type = BFD_RELOC_FRV_FUNCDESC;
1611 1.1 skrll }
1612 1.1 skrll else if (strncasecmp (input_line_pointer, "tlsmoff(", 8) == 0)
1613 1.1 skrll {
1614 1.1 skrll input_line_pointer += 8;
1615 1.1 skrll expression (&exp);
1616 1.1 skrll if (*input_line_pointer == ')')
1617 1.1 skrll input_line_pointer++;
1618 1.1 skrll else
1619 1.1 skrll as_bad (_("missing ')'"));
1620 1.1 skrll reloc_type = BFD_RELOC_FRV_TLSMOFF;
1621 1.1 skrll }
1622 1.1 skrll else
1623 1.1 skrll expression (&exp);
1624 1.1 skrll
1625 1.1 skrll p = frag_more (4);
1626 1.1 skrll memset (p, 0, 4);
1627 1.1 skrll fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &exp, 0,
1628 1.1 skrll reloc_type);
1629 1.1 skrll }
1630 1.1 skrll while (*input_line_pointer++ == ',');
1631 1.1 skrll
1632 1.1 skrll input_line_pointer--; /* Put terminator back into stream. */
1633 1.1 skrll demand_empty_rest_of_line ();
1634 1.1 skrll }
1635 1.1 skrll
1636 1.1 skrll
1637 1.1 skrll
1639 1.1 skrll #ifdef DEBUG
1640 1.1 skrll #define DPRINTF1(A) fprintf (stderr, A)
1641 1.1 skrll #define DPRINTF2(A,B) fprintf (stderr, A, B)
1642 1.1 skrll #define DPRINTF3(A,B,C) fprintf (stderr, A, B, C)
1643 1.1 skrll
1644 1.1 skrll #else
1645 1.1 skrll #define DPRINTF1(A)
1646 1.1 skrll #define DPRINTF2(A,B)
1647 1.1 skrll #define DPRINTF3(A,B,C)
1648 1.1 skrll #endif
1649 1.1 skrll
1650 1.1 skrll /* Go through a the sections looking for relocations that are problematical for
1651 1.1 skrll pic. If not pic, just note that this object can't be linked with pic. If
1652 1.1 skrll it is pic, see if it needs to be marked so that it will be fixed up, or if
1653 1.1 skrll not possible, issue an error. */
1654 1.1 skrll
1655 1.1 skrll static void
1656 1.1 skrll frv_frob_file_section (bfd *abfd, asection *sec, void *ptr ATTRIBUTE_UNUSED)
1657 1.1 skrll {
1658 1.1 skrll segment_info_type *seginfo = seg_info (sec);
1659 1.1 skrll fixS *fixp;
1660 1.1 skrll CGEN_CPU_DESC cd = gas_cgen_cpu_desc;
1661 1.1 skrll flagword flags = bfd_get_section_flags (abfd, sec);
1662 1.1 skrll
1663 1.1 skrll /* Skip relocations in known sections (.ctors, .dtors, and .gcc_except_table)
1664 1.1 skrll since we can fix those up by hand. */
1665 1.1 skrll int known_section_p = (sec->name
1666 1.1 skrll && sec->name[0] == '.'
1667 1.1 skrll && ((sec->name[1] == 'c'
1668 1.1 skrll && strcmp (sec->name, ".ctor") == 0)
1669 1.1 skrll || (sec->name[1] == 'd'
1670 1.1 skrll && strcmp (sec->name, ".dtor") == 0)
1671 1.1 skrll || (sec->name[1] == 'g'
1672 1.1 skrll && strcmp (sec->name, ".gcc_except_table") == 0)));
1673 1.1 skrll
1674 1.1 skrll DPRINTF3 ("\nFrv section %s%s\n", sec->name, (known_section_p) ? ", known section" : "");
1675 1.1 skrll if ((flags & SEC_ALLOC) == 0)
1676 1.1 skrll {
1677 1.1 skrll DPRINTF1 ("\tSkipping non-loaded section\n");
1678 1.1 skrll return;
1679 1.1 skrll }
1680 1.1 skrll
1681 1.1 skrll for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
1682 1.1 skrll {
1683 1.1 skrll symbolS *s = fixp->fx_addsy;
1684 1.1 skrll bfd_reloc_code_real_type reloc;
1685 1.1 skrll int non_pic_p;
1686 1.1 skrll int opindex;
1687 1.1 skrll const CGEN_OPERAND *operand;
1688 1.1 skrll const CGEN_INSN *insn = fixp->fx_cgen.insn;
1689 1.1 skrll
1690 1.1 skrll if (fixp->fx_done)
1691 1.1 skrll {
1692 1.1 skrll DPRINTF1 ("\tSkipping reloc that has already been done\n");
1693 1.1 skrll continue;
1694 1.1 skrll }
1695 1.1 skrll
1696 1.1 skrll if (fixp->fx_pcrel)
1697 1.1 skrll {
1698 1.1 skrll DPRINTF1 ("\tSkipping reloc that is PC relative\n");
1699 1.1 skrll continue;
1700 1.1 skrll }
1701 1.1 skrll
1702 1.1 skrll if (! s)
1703 1.1 skrll {
1704 1.1 skrll DPRINTF1 ("\tSkipping reloc without symbol\n");
1705 1.1 skrll continue;
1706 1.1 skrll }
1707 1.1 skrll
1708 1.1 skrll if (fixp->fx_r_type < BFD_RELOC_UNUSED)
1709 1.1 skrll {
1710 1.1 skrll opindex = -1;
1711 1.1 skrll reloc = fixp->fx_r_type;
1712 1.1 skrll }
1713 1.1 skrll else
1714 1.1 skrll {
1715 1.1 skrll opindex = (int) fixp->fx_r_type - (int) BFD_RELOC_UNUSED;
1716 1.1 skrll operand = cgen_operand_lookup_by_num (cd, opindex);
1717 1.1 skrll reloc = md_cgen_lookup_reloc (insn, operand, fixp);
1718 1.1 skrll }
1719 1.1 skrll
1720 1.1 skrll DPRINTF3 ("\treloc %s\t%s", bfd_get_reloc_code_name (reloc), S_GET_NAME (s));
1721 1.1 skrll
1722 1.1 skrll non_pic_p = 0;
1723 1.1 skrll switch (reloc)
1724 1.1 skrll {
1725 1.1 skrll default:
1726 1.1 skrll break;
1727 1.1 skrll
1728 1.1 skrll case BFD_RELOC_32:
1729 1.1 skrll /* Skip relocations in known sections (.ctors, .dtors, and
1730 1.1 skrll .gcc_except_table) since we can fix those up by hand. Also
1731 1.1 skrll skip forward references to constants. Also skip a difference
1732 1.1 skrll of two symbols, which still uses the BFD_RELOC_32 at this
1733 1.1 skrll point. */
1734 1.1 skrll if (! known_section_p
1735 1.1 skrll && S_GET_SEGMENT (s) != absolute_section
1736 1.1 skrll && !fixp->fx_subsy
1737 1.1 skrll && (flags & (SEC_READONLY | SEC_CODE)) == 0)
1738 1.1 skrll {
1739 1.1 skrll non_pic_p = 1;
1740 1.1 skrll }
1741 1.1 skrll break;
1742 1.1 skrll
1743 1.1 skrll /* FIXME -- should determine if any of the GP relocation really uses
1744 1.1 skrll gr16 (which is not pic safe) or not. Right now, assume if we
1745 1.1 skrll aren't being compiled with -mpic, the usage is non pic safe, but
1746 1.1 skrll is safe with -mpic. */
1747 1.1 skrll case BFD_RELOC_FRV_GPREL12:
1748 1.1 skrll case BFD_RELOC_FRV_GPRELU12:
1749 1.1 skrll case BFD_RELOC_FRV_GPREL32:
1750 1.1 skrll case BFD_RELOC_FRV_GPRELHI:
1751 1.1 skrll case BFD_RELOC_FRV_GPRELLO:
1752 1.1 skrll non_pic_p = ! frv_pic_p;
1753 1.1 skrll break;
1754 1.1 skrll
1755 1.1 skrll case BFD_RELOC_FRV_LO16:
1756 1.1 skrll case BFD_RELOC_FRV_HI16:
1757 1.1 skrll if (S_GET_SEGMENT (s) != absolute_section)
1758 1.1 skrll non_pic_p = 1;
1759 1.1 skrll break;
1760 1.1 skrll
1761 1.1 skrll case BFD_RELOC_VTABLE_INHERIT:
1762 1.1 skrll case BFD_RELOC_VTABLE_ENTRY:
1763 1.1 skrll non_pic_p = 1;
1764 1.1 skrll break;
1765 1.1 skrll
1766 1.1 skrll /* If this is a blessed BFD_RELOC_32, convert it back to the normal
1767 1.1 skrll relocation. */
1768 1.1 skrll case BFD_RELOC_CTOR:
1769 1.1 skrll fixp->fx_r_type = BFD_RELOC_32;
1770 1.1 skrll break;
1771 1.1 skrll }
1772 1.1 skrll
1773 1.1 skrll if (non_pic_p)
1774 1.1 skrll {
1775 1.1 skrll DPRINTF1 (" (Non-pic relocation)\n");
1776 1.1 skrll if (frv_pic_p)
1777 1.1 skrll as_warn_where (fixp->fx_file, fixp->fx_line,
1778 1.1 skrll _("Relocation %s is not safe for %s"),
1779 1.1 skrll bfd_get_reloc_code_name (reloc), frv_pic_flag);
1780 1.1 skrll
1781 1.1 skrll else if ((frv_flags & EF_FRV_NON_PIC_RELOCS) == 0)
1782 1.1 skrll {
1783 1.1 skrll frv_flags |= EF_FRV_NON_PIC_RELOCS;
1784 1.1 skrll bfd_set_private_flags (abfd, frv_flags);
1785 1.1 skrll }
1786 1.1 skrll }
1787 1.1 skrll #ifdef DEBUG
1788 1.1 skrll else
1789 1.1 skrll DPRINTF1 ("\n");
1790 1.1 skrll #endif
1791 1.1 skrll }
1792 1.1 skrll }
1793 1.1 skrll
1794 1.1 skrll /* After all of the symbols have been adjusted, go over the file looking
1795 1.1 skrll for any relocations that pic won't support. */
1796 1.1 skrll
1797 1.1 skrll void
1798 1.1 skrll frv_frob_file (void)
1799 1.1 skrll {
1800 1.1 skrll bfd_map_over_sections (stdoutput, frv_frob_file_section, (void *) 0);
1801 1.1 skrll }
1802 1.1.1.2 christos
1803 1.1 skrll void
1804 1.1 skrll frv_frob_label (symbolS *this_label)
1805 1.1 skrll {
1806 1.1 skrll struct vliw_insn_list *vliw_insn_list_entry;
1807 1.1 skrll
1808 1.1 skrll dwarf2_emit_label (this_label);
1809 1.1 skrll if (frv_mach != bfd_mach_frvtomcat)
1810 1.1 skrll return;
1811 1.1.1.3 christos
1812 1.1 skrll if (now_seg != text_section)
1813 1.1 skrll return;
1814 1.1 skrll
1815 1.1 skrll vliw_insn_list_entry = frv_insert_vliw_insn(DONT_COUNT);
1816 1.1 skrll vliw_insn_list_entry->type = VLIW_LABEL_TYPE;
1817 1.1 skrll vliw_insn_list_entry->sym = this_label;
1818 1.1 skrll }
1819 1.1 skrll
1820 1.1 skrll fixS *
1821 1.1 skrll frv_cgen_record_fixup_exp (fragS *frag,
1822 1.1 skrll int where,
1823 1.1 skrll const CGEN_INSN *insn,
1824 1.1 skrll int length,
1825 1.1 skrll const CGEN_OPERAND *operand,
1826 1.1 skrll int opinfo,
1827 1.1 skrll expressionS *exp)
1828 1.1 skrll {
1829 1.1 skrll fixS * fixP = gas_cgen_record_fixup_exp (frag, where, insn, length,
1830 1.1 skrll operand, opinfo, exp);
1831 1.1.1.3 christos
1832 1.1 skrll if (frv_mach == bfd_mach_frvtomcat
1833 1.1 skrll && current_vliw_insn
1834 && current_vliw_insn->type == VLIW_BRANCH_TYPE
1835 && exp != NULL)
1836 current_vliw_insn->sym = exp->X_add_symbol;
1837
1838 return fixP;
1839 }
1840