Banish PARAMS and PTR. Convert to ISO C.
[binutils.git] / gas / config / tc-mep.c
blob26080192c999e1f4a90cfdc1bdd66e2dc2202674
1 /* tc-mep.c -- Assembler for the Toshiba Media Processor.
2 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007
3 Free Software Foundation. Inc.
5 This file is part of GAS, the GNU Assembler.
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to
19 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
22 #include <stdio.h>
23 #include "as.h"
24 #include "dwarf2dbg.h"
25 #include "subsegs.h"
26 #include "symcat.h"
27 #include "opcodes/mep-desc.h"
28 #include "opcodes/mep-opc.h"
29 #include "cgen.h"
30 #include "elf/common.h"
31 #include "elf/mep.h"
32 #include "libbfd.h"
33 #include "xregex.h"
35 /* Structure to hold all of the different components describing
36 an individual instruction. */
37 typedef struct
39 const CGEN_INSN * insn;
40 const CGEN_INSN * orig_insn;
41 CGEN_FIELDS fields;
42 #if CGEN_INT_INSN_P
43 CGEN_INSN_INT buffer [1];
44 #define INSN_VALUE(buf) (*(buf))
45 #else
46 unsigned char buffer [CGEN_MAX_INSN_SIZE];
47 #define INSN_VALUE(buf) (buf)
48 #endif
49 char * addr;
50 fragS * frag;
51 int num_fixups;
52 fixS * fixups [GAS_CGEN_MAX_FIXUPS];
53 int indices [MAX_OPERAND_INSTANCES];
54 } mep_insn;
56 static int mode = CORE; /* Start in core mode. */
57 static int pluspresent = 0;
58 static int allow_disabled_registers = 0;
59 static int library_flag = 0;
61 /* We're going to need to store all of the instructions along with
62 their fixups so that we can parallelization grouping rules. */
64 static mep_insn saved_insns[MAX_SAVED_FIXUP_CHAINS];
65 static int num_insns_saved = 0;
67 const char comment_chars[] = "#";
68 const char line_comment_chars[] = ";#";
69 const char line_separator_chars[] = ";";
70 const char EXP_CHARS[] = "eE";
71 const char FLT_CHARS[] = "dD";
73 static void mep_switch_to_vliw_mode (int);
74 static void mep_switch_to_core_mode (int);
75 static void mep_s_vtext (int);
76 static void mep_noregerr (int);
78 /* The target specific pseudo-ops which we support. */
79 const pseudo_typeS md_pseudo_table[] =
81 { "word", cons, 4 },
82 { "file", (void (*) (int)) dwarf2_directive_file, 0 },
83 { "loc", dwarf2_directive_loc, 0 },
84 { "vliw", mep_switch_to_vliw_mode, 0 },
85 { "core", mep_switch_to_core_mode, 0 },
86 { "vtext", mep_s_vtext, 0 },
87 { "noregerr", mep_noregerr, 0 },
88 { NULL, NULL, 0 }
91 /* Relocations against symbols are done in two
92 parts, with a HI relocation and a LO relocation. Each relocation
93 has only 16 bits of space to store an addend. This means that in
94 order for the linker to handle carries correctly, it must be able
95 to locate both the HI and the LO relocation. This means that the
96 relocations must appear in order in the relocation table.
98 In order to implement this, we keep track of each unmatched HI
99 relocation. We then sort them so that they immediately precede the
100 corresponding LO relocation. */
102 struct mep_hi_fixup
104 struct mep_hi_fixup * next; /* Next HI fixup. */
105 fixS * fixp; /* This fixup. */
106 segT seg; /* The section this fixup is in. */
109 /* The list of unmatched HI relocs. */
110 static struct mep_hi_fixup * mep_hi_fixup_list;
113 #define OPTION_EB (OPTION_MD_BASE + 0)
114 #define OPTION_EL (OPTION_MD_BASE + 1)
115 #define OPTION_CONFIG (OPTION_MD_BASE + 2)
116 #define OPTION_AVERAGE (OPTION_MD_BASE + 3)
117 #define OPTION_NOAVERAGE (OPTION_MD_BASE + 4)
118 #define OPTION_MULT (OPTION_MD_BASE + 5)
119 #define OPTION_NOMULT (OPTION_MD_BASE + 6)
120 #define OPTION_DIV (OPTION_MD_BASE + 7)
121 #define OPTION_NODIV (OPTION_MD_BASE + 8)
122 #define OPTION_BITOPS (OPTION_MD_BASE + 9)
123 #define OPTION_NOBITOPS (OPTION_MD_BASE + 10)
124 #define OPTION_LEADZ (OPTION_MD_BASE + 11)
125 #define OPTION_NOLEADZ (OPTION_MD_BASE + 12)
126 #define OPTION_ABSDIFF (OPTION_MD_BASE + 13)
127 #define OPTION_NOABSDIFF (OPTION_MD_BASE + 14)
128 #define OPTION_MINMAX (OPTION_MD_BASE + 15)
129 #define OPTION_NOMINMAX (OPTION_MD_BASE + 16)
130 #define OPTION_CLIP (OPTION_MD_BASE + 17)
131 #define OPTION_NOCLIP (OPTION_MD_BASE + 18)
132 #define OPTION_SATUR (OPTION_MD_BASE + 19)
133 #define OPTION_NOSATUR (OPTION_MD_BASE + 20)
134 #define OPTION_COP32 (OPTION_MD_BASE + 21)
135 #define OPTION_REPEAT (OPTION_MD_BASE + 25)
136 #define OPTION_NOREPEAT (OPTION_MD_BASE + 26)
137 #define OPTION_DEBUG (OPTION_MD_BASE + 27)
138 #define OPTION_NODEBUG (OPTION_MD_BASE + 28)
139 #define OPTION_LIBRARY (OPTION_MD_BASE + 29)
141 struct option md_longopts[] = {
142 { "EB", no_argument, NULL, OPTION_EB},
143 { "EL", no_argument, NULL, OPTION_EL},
144 { "mconfig", required_argument, NULL, OPTION_CONFIG},
145 { "maverage", no_argument, NULL, OPTION_AVERAGE},
146 { "mno-average", no_argument, NULL, OPTION_NOAVERAGE},
147 { "mmult", no_argument, NULL, OPTION_MULT},
148 { "mno-mult", no_argument, NULL, OPTION_NOMULT},
149 { "mdiv", no_argument, NULL, OPTION_DIV},
150 { "mno-div", no_argument, NULL, OPTION_NODIV},
151 { "mbitops", no_argument, NULL, OPTION_BITOPS},
152 { "mno-bitops", no_argument, NULL, OPTION_NOBITOPS},
153 { "mleadz", no_argument, NULL, OPTION_LEADZ},
154 { "mno-leadz", no_argument, NULL, OPTION_NOLEADZ},
155 { "mabsdiff", no_argument, NULL, OPTION_ABSDIFF},
156 { "mno-absdiff", no_argument, NULL, OPTION_NOABSDIFF},
157 { "mminmax", no_argument, NULL, OPTION_MINMAX},
158 { "mno-minmax", no_argument, NULL, OPTION_NOMINMAX},
159 { "mclip", no_argument, NULL, OPTION_CLIP},
160 { "mno-clip", no_argument, NULL, OPTION_NOCLIP},
161 { "msatur", no_argument, NULL, OPTION_SATUR},
162 { "mno-satur", no_argument, NULL, OPTION_NOSATUR},
163 { "mcop32", no_argument, NULL, OPTION_COP32},
164 { "mdebug", no_argument, NULL, OPTION_DEBUG},
165 { "mno-debug", no_argument, NULL, OPTION_NODEBUG},
166 { "mlibrary", no_argument, NULL, OPTION_LIBRARY},
167 { NULL, 0, NULL, 0 } };
168 size_t md_longopts_size = sizeof (md_longopts);
170 const char * md_shortopts = "";
171 static int optbits = 0;
172 static int optbitset = 0;
175 md_parse_option (int c, char *arg ATTRIBUTE_UNUSED)
177 int i, idx;
178 switch (c)
180 case OPTION_EB:
181 target_big_endian = 1;
182 break;
183 case OPTION_EL:
184 target_big_endian = 0;
185 break;
186 case OPTION_CONFIG:
187 idx = 0;
188 for (i=1; mep_config_map[i].name; i++)
189 if (strcmp (mep_config_map[i].name, arg) == 0)
191 idx = i;
192 break;
194 if (!idx)
196 fprintf (stderr, "Error: unknown configuration %s\n", arg);
197 return 0;
199 mep_config_index = idx;
200 target_big_endian = mep_config_map[idx].big_endian;
201 break;
202 case OPTION_AVERAGE:
203 optbits |= 1 << CGEN_INSN_OPTIONAL_AVE_INSN;
204 optbitset |= 1 << CGEN_INSN_OPTIONAL_AVE_INSN;
205 break;
206 case OPTION_NOAVERAGE:
207 optbits &= ~(1 << CGEN_INSN_OPTIONAL_AVE_INSN);
208 optbitset |= 1 << CGEN_INSN_OPTIONAL_AVE_INSN;
209 break;
210 case OPTION_MULT:
211 optbits |= 1 << CGEN_INSN_OPTIONAL_MUL_INSN;
212 optbitset |= 1 << CGEN_INSN_OPTIONAL_MUL_INSN;
213 break;
214 case OPTION_NOMULT:
215 optbits &= ~(1 << CGEN_INSN_OPTIONAL_MUL_INSN);
216 optbitset |= 1 << CGEN_INSN_OPTIONAL_MUL_INSN;
217 break;
218 case OPTION_DIV:
219 optbits |= 1 << CGEN_INSN_OPTIONAL_DIV_INSN;
220 optbitset |= 1 << CGEN_INSN_OPTIONAL_DIV_INSN;
221 break;
222 case OPTION_NODIV:
223 optbits &= ~(1 << CGEN_INSN_OPTIONAL_DIV_INSN);
224 optbitset |= 1 << CGEN_INSN_OPTIONAL_DIV_INSN;
225 break;
226 case OPTION_BITOPS:
227 optbits |= 1 << CGEN_INSN_OPTIONAL_BIT_INSN;
228 optbitset |= 1 << CGEN_INSN_OPTIONAL_BIT_INSN;
229 break;
230 case OPTION_NOBITOPS:
231 optbits &= ~(1 << CGEN_INSN_OPTIONAL_BIT_INSN);
232 optbitset |= 1 << CGEN_INSN_OPTIONAL_BIT_INSN;
233 break;
234 case OPTION_LEADZ:
235 optbits |= 1 << CGEN_INSN_OPTIONAL_LDZ_INSN;
236 optbitset |= 1 << CGEN_INSN_OPTIONAL_LDZ_INSN;
237 break;
238 case OPTION_NOLEADZ:
239 optbits &= ~(1 << CGEN_INSN_OPTIONAL_LDZ_INSN);
240 optbitset |= 1 << CGEN_INSN_OPTIONAL_LDZ_INSN;
241 break;
242 case OPTION_ABSDIFF:
243 optbits |= 1 << CGEN_INSN_OPTIONAL_ABS_INSN;
244 optbitset |= 1 << CGEN_INSN_OPTIONAL_ABS_INSN;
245 break;
246 case OPTION_NOABSDIFF:
247 optbits &= ~(1 << CGEN_INSN_OPTIONAL_ABS_INSN);
248 optbitset |= 1 << CGEN_INSN_OPTIONAL_ABS_INSN;
249 break;
250 case OPTION_MINMAX:
251 optbits |= 1 << CGEN_INSN_OPTIONAL_MINMAX_INSN;
252 optbitset |= 1 << CGEN_INSN_OPTIONAL_MINMAX_INSN;
253 break;
254 case OPTION_NOMINMAX:
255 optbits &= ~(1 << CGEN_INSN_OPTIONAL_MINMAX_INSN);
256 optbitset |= 1 << CGEN_INSN_OPTIONAL_MINMAX_INSN;
257 break;
258 case OPTION_CLIP:
259 optbits |= 1 << CGEN_INSN_OPTIONAL_CLIP_INSN;
260 optbitset |= 1 << CGEN_INSN_OPTIONAL_CLIP_INSN;
261 break;
262 case OPTION_NOCLIP:
263 optbits &= ~(1 << CGEN_INSN_OPTIONAL_CLIP_INSN);
264 optbitset |= 1 << CGEN_INSN_OPTIONAL_CLIP_INSN;
265 break;
266 case OPTION_SATUR:
267 optbits |= 1 << CGEN_INSN_OPTIONAL_SAT_INSN;
268 optbitset |= 1 << CGEN_INSN_OPTIONAL_SAT_INSN;
269 break;
270 case OPTION_NOSATUR:
271 optbits &= ~(1 << CGEN_INSN_OPTIONAL_SAT_INSN);
272 optbitset |= 1 << CGEN_INSN_OPTIONAL_SAT_INSN;
273 break;
274 case OPTION_COP32:
275 optbits |= 1 << CGEN_INSN_OPTIONAL_CP_INSN;
276 optbitset |= 1 << CGEN_INSN_OPTIONAL_CP_INSN;
277 break;
278 case OPTION_DEBUG:
279 optbits |= 1 << CGEN_INSN_OPTIONAL_DEBUG_INSN;
280 optbitset |= 1 << CGEN_INSN_OPTIONAL_DEBUG_INSN;
281 break;
282 case OPTION_NODEBUG:
283 optbits &= ~(1 << CGEN_INSN_OPTIONAL_DEBUG_INSN);
284 optbitset |= 1 << CGEN_INSN_OPTIONAL_DEBUG_INSN;
285 break;
286 case OPTION_LIBRARY:
287 library_flag = EF_MEP_LIBRARY;
288 break;
289 case OPTION_REPEAT:
290 case OPTION_NOREPEAT:
291 break;
292 default:
293 return 0;
295 return 1;
298 void
299 md_show_usage (FILE *stream)
301 fprintf (stream, _("MeP specific command line options:\n\
302 -EB assemble for a big endian system (default)\n\
303 -EL assemble for a little endian system\n\
304 -mconfig=<name> specify a chip configuration to use\n\
305 -maverage -mno-average -mmult -mno-mult -mdiv -mno-div\n\
306 -mbitops -mno-bitops -mleadz -mno-leadz -mabsdiff -mno-absdiff\n\
307 -mminmax -mno-minmax -mclip -mno-clip -msatur -mno-satur -mcop32\n\
308 enable/disable the given opcodes\n\
310 If -mconfig is given, the other -m options modify it. Otherwise,\n\
311 if no -m options are given, all core opcodes are enabled;\n\
312 if any enabling -m options are given, only those are enabled;\n\
313 if only disabling -m options are given, only those are disabled.\n\
314 "));
315 if (mep_config_map[1].name)
317 int i;
318 fprintf (stream, " -mconfig=STR specify the configuration to use\n");
319 fprintf (stream, " Configurations:");
320 for (i=0; mep_config_map[i].name; i++)
321 fprintf (stream, " %s", mep_config_map[i].name);
322 fprintf (stream, "\n");
328 static void
329 mep_check_for_disabled_registers (mep_insn *insn)
331 static int initted = 0;
332 static int has_mul_div = 0;
333 static int has_cop = 0;
334 static int has_debug = 0;
335 unsigned int b, r;
337 if (allow_disabled_registers)
338 return;
340 #if !CGEN_INT_INSN_P
341 if (target_big_endian)
342 b = insn->buffer[0] * 256 + insn->buffer[1];
343 else
344 b = insn->buffer[1] * 256 + insn->buffer[0];
345 #else
346 b = insn->buffer[0];
347 #endif
349 if ((b & 0xfffff00e) == 0x7008 /* stc */
350 || (b & 0xfffff00e) == 0x700a /* ldc */)
352 if (!initted)
354 initted = 1;
355 if ((MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_MUL_INSN))
356 || (MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_DIV_INSN)))
357 has_mul_div = 1;
358 if (MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_DEBUG_INSN))
359 has_debug = 1;
360 if (MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_CP_INSN))
361 has_cop = 1;
364 r = ((b & 0x00f0) >> 4) | ((b & 0x0001) << 4);
365 switch (r)
367 case 7: /* $hi */
368 case 8: /* $lo */
369 if (!has_mul_div)
370 as_bad ("$hi and $lo are disabled when MUL and DIV are off");
371 break;
372 case 12: /* $mb0 */
373 case 13: /* $me0 */
374 case 14: /* $mb1 */
375 case 15: /* $me1 */
376 if (!has_cop)
377 as_bad ("$mb0, $me0, $mb1, and $me1 are disabled when COP is off");
378 break;
379 case 24: /* $dbg */
380 case 25: /* $depc */
381 if (!has_debug)
382 as_bad ("$dbg and $depc are disabled when DEBUG is off");
383 break;
388 static int
389 mep_machine (void)
391 switch (MEP_CPU)
393 default: break;
394 case EF_MEP_CPU_C2: return bfd_mach_mep;
395 case EF_MEP_CPU_C3: return bfd_mach_mep;
396 case EF_MEP_CPU_C4: return bfd_mach_mep;
397 case EF_MEP_CPU_H1: return bfd_mach_mep_h1;
400 return bfd_mach_mep;
403 /* The MeP version of the cgen parse_operand function. The only difference
404 from the standard version is that we want to avoid treating '$foo' and
405 '($foo...)' as references to a symbol called '$foo'. The chances are
406 that '$foo' is really a misspelt register. */
408 static const char *
409 mep_parse_operand (CGEN_CPU_DESC cd, enum cgen_parse_operand_type want,
410 const char **strP, int opindex, int opinfo,
411 enum cgen_parse_operand_result *resultP, bfd_vma *valueP)
413 if (want == CGEN_PARSE_OPERAND_INTEGER || want == CGEN_PARSE_OPERAND_ADDRESS)
415 const char *next;
417 next = *strP;
418 while (*next == '(')
419 next++;
420 if (*next == '$')
421 return "Not a valid literal";
423 return gas_cgen_parse_operand (cd, want, strP, opindex, opinfo,
424 resultP, valueP);
427 void
428 md_begin ()
430 /* Initialize the `cgen' interface. */
432 /* If the user specifies no options, we default to allowing
433 everything. If the user specifies any enabling options, we
434 default to allowing only what is specified. If the user
435 specifies only disabling options, we only disable what is
436 specified. If the user specifies options and a config, the
437 options modify the config. */
438 if (optbits && mep_config_index == 0)
439 MEP_OMASK = optbits;
440 else
441 MEP_OMASK = (MEP_OMASK & ~optbitset) | optbits;
443 /* Set the machine number and endian. */
444 gas_cgen_cpu_desc = mep_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0,
445 CGEN_CPU_OPEN_ENDIAN,
446 target_big_endian
447 ? CGEN_ENDIAN_BIG
448 : CGEN_ENDIAN_LITTLE,
449 CGEN_CPU_OPEN_ISAS, 0,
450 CGEN_CPU_OPEN_END);
451 mep_cgen_init_asm (gas_cgen_cpu_desc);
453 /* This is a callback from cgen to gas to parse operands. */
454 cgen_set_parse_operand_fn (gas_cgen_cpu_desc, mep_parse_operand);
456 /* Identify the architecture. */
457 bfd_default_set_arch_mach (stdoutput, bfd_arch_mep, mep_machine ());
459 /* Store the configuration number and core. */
460 bfd_set_private_flags (stdoutput, MEP_CPU | MEP_CONFIG | library_flag);
462 /* Initialize the array we'll be using to store fixups. */
463 gas_cgen_initialize_saved_fixups_array();
466 /* Variant of mep_cgen_assemble_insn. Assemble insn STR of cpu CD as a
467 coprocessor instruction, if possible, into FIELDS, BUF, and INSN. */
469 static const CGEN_INSN *
470 mep_cgen_assemble_cop_insn (CGEN_CPU_DESC cd,
471 const char *str,
472 CGEN_FIELDS *fields,
473 CGEN_INSN_BYTES_PTR buf,
474 const struct cgen_insn *pinsn)
476 const char *start;
477 CGEN_INSN_LIST *ilist;
478 const char *errmsg = NULL;
480 /* The instructions are stored in hashed lists. */
481 ilist = CGEN_ASM_LOOKUP_INSN (gas_cgen_cpu_desc,
482 CGEN_INSN_MNEMONIC (pinsn));
484 start = str;
485 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
487 const CGEN_INSN *insn = ilist->insn;
488 if (strcmp (CGEN_INSN_MNEMONIC (ilist->insn),
489 CGEN_INSN_MNEMONIC (pinsn)) == 0
490 && MEP_INSN_COP_P (ilist->insn)
491 && mep_cgen_insn_supported (cd, insn))
493 str = start;
495 /* skip this insn if str doesn't look right lexically */
496 if (CGEN_INSN_RX (insn) != NULL &&
497 regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
498 continue;
500 /* Allow parse/insert handlers to obtain length of insn. */
501 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
503 errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
504 if (errmsg != NULL)
505 continue;
507 errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
508 (bfd_vma) 0);
509 if (errmsg != NULL)
510 continue;
512 return insn;
515 return pinsn;
518 static void
519 mep_save_insn (mep_insn insn)
521 /* Consider change MAX_SAVED_FIXUP_CHAINS to MAX_PARALLEL_INSNS. */
522 if (num_insns_saved < 0 || num_insns_saved >= MAX_SAVED_FIXUP_CHAINS)
524 as_fatal("index into saved_insns[] out of bounds.");
525 return;
527 saved_insns[num_insns_saved] = insn;
528 gas_cgen_save_fixups(num_insns_saved);
529 num_insns_saved++;
532 static void
533 mep_check_parallel32_scheduling (void)
535 int insn0iscopro, insn1iscopro, insn0length, insn1length;
537 /* More than two instructions means that either someone is referring to
538 an internally parallel core or an internally parallel coprocessor,
539 neither of which are supported at this time. */
540 if ( num_insns_saved > 2 )
541 as_fatal("Internally paralled cores and coprocessors not supported.");
543 /* If there are no insns saved, that's ok. Just return. This will
544 happen when mep_process_saved_insns is called when the end of the
545 source file is reached and there are no insns left to be processed. */
546 if (num_insns_saved == 0)
547 return;
549 /* Check some of the attributes of the first insn. */
550 insn0iscopro = MEP_INSN_COP_P (saved_insns[0].insn);
551 insn0length = CGEN_FIELDS_BITSIZE (& saved_insns[0].fields);
553 if (num_insns_saved == 2)
555 /* Check some of the attributes of the first insn. */
556 insn1iscopro = MEP_INSN_COP_P (saved_insns[1].insn);
557 insn1length = CGEN_FIELDS_BITSIZE (& saved_insns[1].fields);
559 if ((insn0iscopro && !insn1iscopro)
560 || (insn1iscopro && !insn0iscopro))
562 /* We have one core and one copro insn. If their sizes
563 add up to 32, then the combination is valid. */
564 if (insn0length + insn1length == 32)
565 return;
566 else
567 as_bad ("core and copro insn lengths must total 32 bits.");
569 else
570 as_bad ("vliw group must consist of 1 core and 1 copro insn.");
572 else
574 /* If we arrive here, we have one saved instruction. There are a
575 number of possible cases:
577 1. The instruction is a 32 bit core or coprocessor insn and
578 can be executed by itself. Valid.
580 2. The instrucion is a core instruction for which a cop nop
581 exists. In this case, insert the cop nop into the saved
582 insn array after the core insn and return. Valid.
584 3. The instruction is a coprocessor insn for which a core nop
585 exists. In this case, move the coprocessor insn to the
586 second element of the array and put the nop in the first
587 element then return. Valid.
589 4. The instruction is a core or coprocessor instruction for
590 which there is no matching coprocessor or core nop to use
591 to form a valid vliw insn combination. In this case, we
592 we have to abort. */
594 if (insn0length > 32)
595 as_fatal ("Cannot use 48- or 64-bit insns with a 32 bit datapath.");
597 if (insn0length == 32)
598 return;
600 /* Insn is smaller than datapath. If there are no matching
601 nops for this insn, then terminate assembly. */
602 if (CGEN_INSN_ATTR_VALUE (saved_insns[0].insn,
603 CGEN_INSN_VLIW32_NO_MATCHING_NOP))
604 as_fatal ("No valid nop.");
606 /* At this point we know that we have a single 16-bit insn that has
607 a matching nop. We have to assemble it and put it into the saved
608 insn and fixup chain arrays. */
610 if (insn0iscopro)
612 char *errmsg;
613 mep_insn insn;
615 /* Move the insn and it's fixups to the second element of the
616 saved insns arrary and insert a 16 bit core nope into the
617 first element. */
618 insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "nop",
619 &insn.fields, insn.buffer,
620 &errmsg);
621 if (!insn.insn)
623 as_bad ("%s", errmsg);
624 return;
627 /* Move the insn in element 0 to element 1 and insert the
628 nop into element 0. Move the fixups in element 0 to
629 element 1 and save the current fixups to element 0.
630 Really there aren't any fixups at this point because we're
631 inserting a nop but we might as well be general so that
632 if there's ever a need to insert a general insn, we'll
633 have an example. */
634 saved_insns[1] = saved_insns[0];
635 saved_insns[0] = insn;
636 num_insns_saved++;
637 gas_cgen_swap_fixups (0);
638 gas_cgen_save_fixups (1);
640 else
642 char * errmsg;
643 mep_insn insn;
644 int insn_num = saved_insns[0].insn->base->num;
646 /* Use 32 bit branches and skip the nop. */
647 if (insn_num == MEP_INSN_BSR12
648 || insn_num == MEP_INSN_BEQZ
649 || insn_num == MEP_INSN_BNEZ)
650 return;
652 /* Insert a 16-bit coprocessor nop. Note that at the time */
653 /* this was done, no 16-bit coprocessor nop was defined. */
654 insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop16",
655 &insn.fields, insn.buffer,
656 &errmsg);
657 if (!insn.insn)
659 as_bad ("%s", errmsg);
660 return;
663 /* Now put the insn and fixups into the arrays. */
664 mep_save_insn (insn);
669 static void
670 mep_check_parallel64_scheduling (void)
672 int insn0iscopro, insn1iscopro, insn0length, insn1length;
674 /* More than two instructions means that someone is referring to an
675 internally parallel core or an internally parallel coprocessor. */
676 /* These are not currently supported. */
677 if (num_insns_saved > 2)
678 as_fatal ("Internally parallel cores of coprocessors not supported.");
680 /* If there are no insns saved, that's ok. Just return. This will
681 happen when mep_process_saved_insns is called when the end of the
682 source file is reached and there are no insns left to be processed. */
683 if (num_insns_saved == 0)
684 return;
686 /* Check some of the attributes of the first insn. */
687 insn0iscopro = MEP_INSN_COP_P (saved_insns[0].insn);
688 insn0length = CGEN_FIELDS_BITSIZE (& saved_insns[0].fields);
690 if (num_insns_saved == 2)
692 /* Check some of the attributes of the first insn. */
693 insn1iscopro = MEP_INSN_COP_P (saved_insns[1].insn);
694 insn1length = CGEN_FIELDS_BITSIZE (& saved_insns[1].fields);
696 if ((insn0iscopro && !insn1iscopro)
697 || (insn1iscopro && !insn0iscopro))
699 /* We have one core and one copro insn. If their sizes
700 add up to 64, then the combination is valid. */
701 if (insn0length + insn1length == 64)
702 return;
703 else
704 as_bad ("core and copro insn lengths must total 64 bits.");
706 else
707 as_bad ("vliw group must consist of 1 core and 1 copro insn.");
709 else
711 /* If we arrive here, we have one saved instruction. There are a
712 number of possible cases:
714 1. The instruction is a 64 bit coprocessor insn and can be
715 executed by itself. Valid.
717 2. The instrucion is a core instruction for which a cop nop
718 exists. In this case, insert the cop nop into the saved
719 insn array after the core insn and return. Valid.
721 3. The instruction is a coprocessor insn for which a core nop
722 exists. In this case, move the coprocessor insn to the
723 second element of the array and put the nop in the first
724 element then return. Valid.
726 4. The instruction is a core or coprocessor instruction for
727 which there is no matching coprocessor or core nop to use
728 to form a valid vliw insn combination. In this case, we
729 we have to abort. */
731 /* If the insn is 64 bits long, it can run alone. The size check
732 is done indepependantly of whether the insn is core or copro
733 in case 64 bit coprocessor insns are added later. */
734 if (insn0length == 64)
735 return;
737 /* Insn is smaller than datapath. If there are no matching
738 nops for this insn, then terminate assembly. */
739 if (CGEN_INSN_ATTR_VALUE (saved_insns[0].insn,
740 CGEN_INSN_VLIW64_NO_MATCHING_NOP))
741 as_fatal ("No valid nop.");
743 if (insn0iscopro)
745 char *errmsg;
746 mep_insn insn;
747 int i;
749 /* Initialize the insn buffer. */
750 for (i = 0; i < 64; i++)
751 insn.buffer[i] = '\0';
753 /* We have a coprocessor insn. At this point in time there
754 are is 32-bit core nop. There is only a 16-bit core
755 nop. The idea is to allow for a relatively arbitrary
756 coprocessor to be specified. We aren't looking at
757 trying to cover future changes in the core at this time
758 since it is assumed that the core will remain fairly
759 static. If there ever are 32 or 48 bit core nops added,
760 they will require entries below. */
762 if (insn0length == 48)
764 /* Move the insn and fixups to the second element of the
765 arrays then assemble and insert a 16 bit core nop. */
766 insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "nop",
767 & insn.fields, insn.buffer,
768 & errmsg);
770 else
772 /* If this is reached, then we have a single coprocessor
773 insn that is not 48 bits long, but for which the assembler
774 thinks there is a matching core nop. If a 32-bit core
775 nop has been added, then make the necessary changes and
776 handle its assembly and insertion here. Otherwise,
777 go figure out why either:
779 1. The assembler thinks that there is a 32-bit core nop
780 to match a 32-bit coprocessor insn, or
781 2. The assembler thinks that there is a 48-bit core nop
782 to match a 16-bit coprocessor insn. */
784 as_fatal ("Assembler expects a non-existent core nop.");
787 if (!insn.insn)
789 as_bad ("%s", errmsg);
790 return;
793 /* Move the insn in element 0 to element 1 and insert the
794 nop into element 0. Move the fixups in element 0 to
795 element 1 and save the current fixups to element 0.
796 Really there aren't any fixups at this point because we're
797 inserting a nop but we might as well be general so that
798 if there's ever a need to insert a general insn, we'll
799 have an example. */
801 saved_insns[1] = saved_insns[0];
802 saved_insns[0] = insn;
803 num_insns_saved++;
804 gas_cgen_swap_fixups(0);
805 gas_cgen_save_fixups(1);
808 else
810 char * errmsg;
811 mep_insn insn;
812 int i;
814 /* Initialize the insn buffer */
815 for (i = 0; i < 64; i++)
816 insn.buffer[i] = '\0';
818 /* We have a core insn. We have to handle all possible nop
819 lengths. If a coprocessor doesn't have a nop of a certain
820 length but there exists core insns that when combined with
821 a nop of that length would fill the datapath, those core
822 insns will be flagged with the VLIW_NO_CORRESPONDING_NOP
823 attribute. That will ensure that when used in a way that
824 requires a nop to be inserted, assembly will terminate
825 before reaching this section of code. This guarantees
826 that cases below which would result in the attempted
827 insertion of nop that doesn't exist will never be entered. */
828 if (insn0length == 16)
830 /* Insert 48 bit coprocessor nop. */
831 /* Assemble it and put it into the arrays. */
832 insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop48",
833 &insn.fields, insn.buffer,
834 &errmsg);
836 else if (insn0length == 32)
838 /* Insert 32 bit coprocessor nop. */
839 insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop32",
840 &insn.fields, insn.buffer,
841 &errmsg);
843 else if (insn0length == 48)
845 /* Insert 16 bit coprocessor nop. */
846 insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop16",
847 &insn.fields, insn.buffer,
848 &errmsg);
850 else
851 /* Core insn has an invalid length. Something has gone wrong. */
852 as_fatal ("Core insn has invalid length! Something is wrong!");
854 if (!insn.insn)
856 as_bad ("%s", errmsg);
857 return;
860 /* Now put the insn and fixups into the arrays. */
861 mep_save_insn (insn);
866 /* The scheduling functions are just filters for invalid combinations.
867 If there is a violation, they terminate assembly. Otherise they
868 just fall through. Succesful combinations cause no side effects
869 other than valid nop insertion. */
871 static void
872 mep_check_parallel_scheduling (void)
874 /* This is where we will eventually read the config information
875 and choose which scheduling checking function to call. */
876 if (MEP_VLIW64)
877 mep_check_parallel64_scheduling ();
878 else
879 mep_check_parallel32_scheduling ();
882 static void
883 mep_process_saved_insns (void)
885 int i;
887 gas_cgen_save_fixups (MAX_SAVED_FIXUP_CHAINS - 1);
889 /* We have to check for valid scheduling here. */
890 mep_check_parallel_scheduling ();
892 /* If the last call didn't cause assembly to terminate, we have
893 a valid vliw insn/insn pair saved. Restore this instructions'
894 fixups and process the insns. */
895 for (i = 0;i<num_insns_saved;i++)
897 gas_cgen_restore_fixups (i);
898 gas_cgen_finish_insn (saved_insns[i].insn, saved_insns[i].buffer,
899 CGEN_FIELDS_BITSIZE (& saved_insns[i].fields),
900 1, NULL);
902 gas_cgen_restore_fixups (MAX_SAVED_FIXUP_CHAINS - 1);
904 /* Clear the fixups and reset the number insn saved to 0. */
905 gas_cgen_initialize_saved_fixups_array ();
906 num_insns_saved = 0;
907 listing_prev_line ();
910 void
911 md_assemble (char * str)
913 static CGEN_BITSET* isas = NULL;
914 char * errmsg;
916 /* Initialize GAS's cgen interface for a new instruction. */
917 gas_cgen_init_parse ();
919 /* There are two possible modes: core and vliw. We have to assemble
920 differently for each.
922 Core Mode: We assemble normally. All instructions are on a
923 single line and are made up of one mnemonic and one
924 set of operands.
925 VLIW Mode: Vliw combinations are indicated as follows:
927 core insn
928 + copro insn
930 We want to handle the general case where more than
931 one instruction can be preceeded by a +. This will
932 happen later if we add support for internally parallel
933 coprocessors. We'll make the parsing nice and general
934 so that it can handle an arbitrary number of insns
935 with leading +'s. The actual checking for valid
936 combinations is done elsewhere. */
938 /* Initialize the isa to refer to the core. */
939 if (isas == NULL)
940 isas = cgen_bitset_copy (& MEP_CORE_ISA);
941 else
943 cgen_bitset_clear (isas);
944 cgen_bitset_union (isas, & MEP_CORE_ISA, isas);
946 gas_cgen_cpu_desc->isas = isas;
948 if (mode == VLIW)
950 /* VLIW mode. */
952 int thisInsnIsCopro = 0;
953 mep_insn insn;
954 int i;
956 /* Initialize the insn buffer */
958 if (! CGEN_INT_INSN_P)
959 for (i=0; i < CGEN_MAX_INSN_SIZE; i++)
960 insn.buffer[i]='\0';
962 /* Can't tell core / copro insns apart at parse time! */
963 cgen_bitset_union (isas, & MEP_COP_ISA, isas);
965 /* Assemble the insn so we can examine its attributes. */
966 insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, str,
967 &insn.fields, insn.buffer,
968 &errmsg);
969 if (!insn.insn)
971 as_bad ("%s", errmsg);
972 return;
974 mep_check_for_disabled_registers (&insn);
976 /* Check to see if it's a coprocessor instruction. */
977 thisInsnIsCopro = MEP_INSN_COP_P (insn.insn);
979 if (!thisInsnIsCopro)
981 insn.insn = mep_cgen_assemble_cop_insn (gas_cgen_cpu_desc, str,
982 &insn.fields, insn.buffer,
983 insn.insn);
984 thisInsnIsCopro = MEP_INSN_COP_P (insn.insn);
985 mep_check_for_disabled_registers (&insn);
988 if (pluspresent)
990 /* A plus was present. */
991 /* Check for a + with a core insn and abort if found. */
992 if (!thisInsnIsCopro)
994 as_fatal("A core insn cannot be preceeded by a +.\n");
995 return;
998 if (num_insns_saved > 0)
1000 /* There are insns in the queue. Add this one. */
1001 mep_save_insn (insn);
1003 else
1005 /* There are no insns in the queue and a plus is present.
1006 This is a syntax error. Let's not tolerate this.
1007 We can relax this later if necessary. */
1008 as_bad (_("Invalid use of parallelization operator."));
1009 return;
1012 else
1014 /* No plus was present. */
1015 if (num_insns_saved > 0)
1017 /* There are insns saved and we came across an insn without a
1018 leading +. That's the signal to process the saved insns
1019 before proceeding then treat the current insn as the first
1020 in a new vliw group. */
1021 mep_process_saved_insns ();
1022 num_insns_saved = 0;
1023 /* mep_save_insn (insn); */
1025 mep_save_insn (insn);
1026 #if 0
1027 else
1030 /* Core Insn. Add it to the beginning of the queue. */
1031 mep_save_insn (insn);
1032 /* gas_cgen_save_fixups(num_insns_saved); */
1034 #endif
1037 pluspresent = 0;
1039 else
1041 /* Core mode. */
1043 /* Only single instructions are assembled in core mode. */
1044 mep_insn insn;
1046 /* If a leading '+' was present, issue an error.
1047 That's not allowed in core mode. */
1048 if (pluspresent)
1050 as_bad (_("Leading plus sign not allowed in core mode"));
1051 return;
1054 insn.insn = mep_cgen_assemble_insn
1055 (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);
1057 if (!insn.insn)
1059 as_bad ("%s", errmsg);
1060 return;
1062 gas_cgen_finish_insn (insn.insn, insn.buffer,
1063 CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL);
1064 mep_check_for_disabled_registers (&insn);
1068 valueT
1069 md_section_align (segT segment, valueT size)
1071 int align = bfd_get_section_alignment (stdoutput, segment);
1072 return ((size + (1 << align) - 1) & (-1 << align));
1076 symbolS *
1077 md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
1079 return 0;
1082 /* Interface to relax_segment. */
1085 const relax_typeS md_relax_table[] =
1087 /* The fields are:
1088 1) most positive reach of this state,
1089 2) most negative reach of this state,
1090 3) how many bytes this mode will have in the variable part of the frag
1091 4) which index into the table to try if we can't fit into this one. */
1092 /* Note that we use "beq" because "jmp" has a peculiarity - it cannot
1093 jump to addresses with any bits 27..24 set. So, we use beq as a
1094 17-bit pc-relative branch to avoid using jmp, just in case. */
1096 /* 0 */ { 0, 0, 0, 0 }, /* unused */
1097 /* 1 */ { 0, 0, 0, 0 }, /* marker for "don't know yet" */
1099 /* 2 */ { 2047, -2048, 0, 3 }, /* bsr12 */
1100 /* 3 */ { 0, 0, 2, 0 }, /* bsr16 */
1102 /* 4 */ { 2047, -2048, 0, 5 }, /* bra */
1103 /* 5 */ { 65535, -65536, 2, 6 }, /* beq $0,$0 */
1104 /* 6 */ { 0, 0, 2, 0 }, /* jmp24 */
1106 /* 7 */ { 65535, -65536, 0, 8 }, /* beqi */
1107 /* 8 */ { 0, 0, 4, 0 }, /* bnei/jmp */
1109 /* 9 */ { 127, -128, 0, 10 }, /* beqz */
1110 /* 10 */ { 65535, -65536, 2, 11 }, /* beqi */
1111 /* 11 */ { 0, 0, 4, 0 }, /* bnei/jmp */
1113 /* 12 */ { 65535, -65536, 0, 13 }, /* bnei */
1114 /* 13 */ { 0, 0, 4, 0 }, /* beqi/jmp */
1116 /* 14 */ { 127, -128, 0, 15 }, /* bnez */
1117 /* 15 */ { 65535, -65536, 2, 16 }, /* bnei */
1118 /* 16 */ { 0, 0, 4, 0 }, /* beqi/jmp */
1120 /* 17 */ { 65535, -65536, 0, 13 }, /* bgei */
1121 /* 18 */ { 0, 0, 4, 0 },
1122 /* 19 */ { 65535, -65536, 0, 13 }, /* blti */
1123 /* 20 */ { 0, 0, 4, 0 },
1124 /* 19 */ { 65535, -65536, 0, 13 }, /* bcpeq */
1125 /* 20 */ { 0, 0, 4, 0 },
1126 /* 19 */ { 65535, -65536, 0, 13 }, /* bcpne */
1127 /* 20 */ { 0, 0, 4, 0 },
1128 /* 19 */ { 65535, -65536, 0, 13 }, /* bcpat */
1129 /* 20 */ { 0, 0, 4, 0 },
1130 /* 19 */ { 65535, -65536, 0, 13 }, /* bcpaf */
1131 /* 20 */ { 0, 0, 4, 0 }
1134 /* Pseudo-values for 64 bit "insns" which are combinations of two 32
1135 bit insns. */
1136 typedef enum {
1137 MEP_PSEUDO64_NONE,
1138 MEP_PSEUDO64_16BITCC,
1139 MEP_PSEUDO64_32BITCC,
1140 } MepPseudo64Values;
1142 static struct {
1143 int insn;
1144 int growth;
1145 int insn_for_extern;
1146 } subtype_mappings[] = {
1147 { 0, 0, 0 },
1148 { 0, 0, 0 },
1149 { MEP_INSN_BSR12, 0, MEP_INSN_BSR24 },
1150 { MEP_INSN_BSR24, 2, MEP_INSN_BSR24 },
1151 { MEP_INSN_BRA, 0, MEP_INSN_BRA },
1152 { MEP_INSN_BEQ, 2, MEP_INSN_BEQ },
1153 { MEP_INSN_JMP, 2, MEP_INSN_JMP },
1154 { MEP_INSN_BEQI, 0, MEP_INSN_BEQI },
1155 { -1, 4, MEP_PSEUDO64_32BITCC },
1156 { MEP_INSN_BEQZ, 0, MEP_INSN_BEQZ },
1157 { MEP_INSN_BEQI, 2, MEP_INSN_BEQI },
1158 { -1, 4, MEP_PSEUDO64_16BITCC },
1159 { MEP_INSN_BNEI, 0, MEP_INSN_BNEI },
1160 { -1, 4, MEP_PSEUDO64_32BITCC },
1161 { MEP_INSN_BNEZ, 0, MEP_INSN_BNEZ },
1162 { MEP_INSN_BNEI, 2, MEP_INSN_BNEI },
1163 { -1, 4, MEP_PSEUDO64_16BITCC },
1164 { MEP_INSN_BGEI, 0, MEP_INSN_BGEI },
1165 { -1, 4, MEP_PSEUDO64_32BITCC },
1166 { MEP_INSN_BLTI, 0, MEP_INSN_BLTI },
1167 { -1, 4, MEP_PSEUDO64_32BITCC },
1168 { MEP_INSN_BCPEQ, 0, MEP_INSN_BCPEQ },
1169 { -1, 4, MEP_PSEUDO64_32BITCC },
1170 { MEP_INSN_BCPNE, 0, MEP_INSN_BCPNE },
1171 { -1, 4, MEP_PSEUDO64_32BITCC },
1172 { MEP_INSN_BCPAT, 0, MEP_INSN_BCPAT },
1173 { -1, 4, MEP_PSEUDO64_32BITCC },
1174 { MEP_INSN_BCPAF, 0, MEP_INSN_BCPAF },
1175 { -1, 4, MEP_PSEUDO64_32BITCC }
1177 #define NUM_MAPPINGS (sizeof (subtype_mappings) / sizeof (subtype_mappings[0]))
1179 void
1180 mep_prepare_relax_scan (fragS *fragP, offsetT *aim, relax_substateT this_state)
1182 symbolS *symbolP = fragP->fr_symbol;
1183 if (symbolP && !S_IS_DEFINED (symbolP))
1184 *aim = 0;
1185 /* Adjust for MeP pcrel not being relative to the next opcode. */
1186 *aim += 2 + md_relax_table[this_state].rlx_length;
1189 static int
1190 insn_to_subtype (int insn)
1192 unsigned int i;
1193 for (i=0; i<NUM_MAPPINGS; i++)
1194 if (insn == subtype_mappings[i].insn)
1195 return i;
1196 abort ();
1199 /* Return an initial guess of the length by which a fragment must grow
1200 to hold a branch to reach its destination. Also updates fr_type
1201 and fr_subtype as necessary.
1203 Called just before doing relaxation. Any symbol that is now
1204 undefined will not become defined. The guess for fr_var is
1205 ACTUALLY the growth beyond fr_fix. Whatever we do to grow fr_fix
1206 or fr_var contributes to our returned value. Although it may not
1207 be explicit in the frag, pretend fr_var starts with a 0 value. */
1210 md_estimate_size_before_relax (fragS * fragP, segT segment)
1212 if (fragP->fr_subtype == 1)
1213 fragP->fr_subtype = insn_to_subtype (fragP->fr_cgen.insn->base->num);
1215 if (S_GET_SEGMENT (fragP->fr_symbol) != segment)
1217 int new_insn;
1219 new_insn = subtype_mappings[fragP->fr_subtype].insn_for_extern;
1220 fragP->fr_subtype = insn_to_subtype (new_insn);
1223 if (MEP_VLIW && ! MEP_VLIW64
1224 && (bfd_get_section_flags (stdoutput, segment) & SEC_MEP_VLIW))
1226 /* Use 32 bit branches for vliw32 so the vliw word is not split. */
1227 switch (fragP->fr_cgen.insn->base->num)
1229 case MEP_INSN_BSR12:
1230 fragP->fr_subtype = insn_to_subtype
1231 (subtype_mappings[fragP->fr_subtype].insn_for_extern);
1232 break;
1233 case MEP_INSN_BEQZ:
1234 fragP->fr_subtype ++;
1235 break;
1236 case MEP_INSN_BNEZ:
1237 fragP->fr_subtype ++;
1238 break;
1242 if (fragP->fr_cgen.insn->base
1243 && fragP->fr_cgen.insn->base->num
1244 != subtype_mappings[fragP->fr_subtype].insn)
1246 int new_insn= subtype_mappings[fragP->fr_subtype].insn;
1247 if (new_insn != -1)
1249 fragP->fr_cgen.insn = (fragP->fr_cgen.insn
1250 - fragP->fr_cgen.insn->base->num
1251 + new_insn);
1255 return subtype_mappings[fragP->fr_subtype].growth;
1258 /* *fragP has been relaxed to its final size, and now needs to have
1259 the bytes inside it modified to conform to the new size.
1261 Called after relaxation is finished.
1262 fragP->fr_type == rs_machine_dependent.
1263 fragP->fr_subtype is the subtype of what the address relaxed to. */
1265 static int
1266 target_address_for (fragS *frag)
1268 int rv = frag->fr_offset;
1269 symbolS *sym = frag->fr_symbol;
1271 if (sym)
1272 rv += S_GET_VALUE (sym);
1274 return rv;
1277 void
1278 md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
1279 segT sec ATTRIBUTE_UNUSED,
1280 fragS *fragP)
1282 int addend, rn, bit = 0;
1283 int operand;
1284 int where = fragP->fr_opcode - fragP->fr_literal;
1285 int e = target_big_endian ? 0 : 1;
1287 addend = target_address_for (fragP) - (fragP->fr_address + where);
1289 if (subtype_mappings[fragP->fr_subtype].insn == -1)
1291 fragP->fr_fix += subtype_mappings[fragP->fr_subtype].growth;
1292 switch (subtype_mappings[fragP->fr_subtype].insn_for_extern)
1294 case MEP_PSEUDO64_16BITCC:
1295 fragP->fr_opcode[1^e] = ((fragP->fr_opcode[1^e] & 1) ^ 1) | 0x06;
1296 fragP->fr_opcode[2^e] = 0xd8;
1297 fragP->fr_opcode[3^e] = 0x08;
1298 fragP->fr_opcode[4^e] = 0;
1299 fragP->fr_opcode[5^e] = 0;
1300 where += 2;
1301 break;
1302 case MEP_PSEUDO64_32BITCC:
1303 if (fragP->fr_opcode[0^e] & 0x10)
1304 fragP->fr_opcode[1^e] ^= 0x01;
1305 else
1306 fragP->fr_opcode[1^e] ^= 0x04;
1307 fragP->fr_opcode[2^e] = 0;
1308 fragP->fr_opcode[3^e] = 4;
1309 fragP->fr_opcode[4^e] = 0xd8;
1310 fragP->fr_opcode[5^e] = 0x08;
1311 fragP->fr_opcode[6^e] = 0;
1312 fragP->fr_opcode[7^e] = 0;
1313 where += 4;
1314 break;
1315 default:
1316 abort ();
1318 fragP->fr_cgen.insn = (fragP->fr_cgen.insn
1319 - fragP->fr_cgen.insn->base->num
1320 + MEP_INSN_JMP);
1321 operand = MEP_OPERAND_PCABS24A2;
1323 else
1324 switch (fragP->fr_cgen.insn->base->num)
1326 case MEP_INSN_BSR12:
1327 fragP->fr_opcode[0^e] = 0xb0 | ((addend >> 8) & 0x0f);
1328 fragP->fr_opcode[1^e] = 0x01 | (addend & 0xfe);
1329 operand = MEP_OPERAND_PCREL12A2;
1330 break;
1332 case MEP_INSN_BSR24:
1333 fragP->fr_fix += 2;
1334 fragP->fr_opcode[0^e] = 0xd8 | ((addend >> 5) & 0x07);
1335 fragP->fr_opcode[1^e] = 0x09 | ((addend << 3) & 0xf0);
1336 fragP->fr_opcode[2^e] = 0x00 | ((addend >>16) & 0xff);
1337 fragP->fr_opcode[3^e] = 0x00 | ((addend >> 8) & 0xff);
1338 operand = MEP_OPERAND_PCREL24A2;
1339 break;
1341 case MEP_INSN_BRA:
1342 fragP->fr_opcode[0^e] = 0xb0 | ((addend >> 8) & 0x0f);
1343 fragP->fr_opcode[1^e] = 0x00 | (addend & 0xfe);
1344 operand = MEP_OPERAND_PCREL12A2;
1345 break;
1347 case MEP_INSN_BEQ:
1348 /* The default relax_frag doesn't change the state if there is no
1349 growth, so we must manually handle converting out-of-range BEQ
1350 instructions to JMP. */
1351 if (addend <= 65535 && addend >= -65536)
1353 fragP->fr_fix += 2;
1354 fragP->fr_opcode[0^e] = 0xe0;
1355 fragP->fr_opcode[1^e] = 0x01;
1356 fragP->fr_opcode[2^e] = 0x00 | ((addend >> 9) & 0xff);
1357 fragP->fr_opcode[3^e] = 0x00 | ((addend >> 1) & 0xff);
1358 operand = MEP_OPERAND_PCREL17A2;
1359 break;
1361 /* ...FALLTHROUGH... */
1363 case MEP_INSN_JMP:
1364 addend = target_address_for (fragP);
1365 fragP->fr_fix += 2;
1366 fragP->fr_opcode[0^e] = 0xd8 | ((addend >> 5) & 0x07);
1367 fragP->fr_opcode[1^e] = 0x08 | ((addend << 3) & 0xf0);
1368 fragP->fr_opcode[2^e] = 0x00 | ((addend >>16) & 0xff);
1369 fragP->fr_opcode[3^e] = 0x00 | ((addend >> 8) & 0xff);
1370 operand = MEP_OPERAND_PCABS24A2;
1371 break;
1373 case MEP_INSN_BNEZ:
1374 bit = 1;
1375 case MEP_INSN_BEQZ:
1376 fragP->fr_opcode[1^e] = bit | (addend & 0xfe);
1377 operand = MEP_OPERAND_PCREL8A2;
1378 break;
1380 case MEP_INSN_BNEI:
1381 bit = 4;
1382 case MEP_INSN_BEQI:
1383 if (subtype_mappings[fragP->fr_subtype].growth)
1385 fragP->fr_fix += subtype_mappings[fragP->fr_subtype].growth;
1386 rn = fragP->fr_opcode[0^e] & 0x0f;
1387 fragP->fr_opcode[0^e] = 0xe0 | rn;
1388 fragP->fr_opcode[1^e] = bit;
1390 fragP->fr_opcode[2^e] = 0x00 | ((addend >> 9) & 0xff);
1391 fragP->fr_opcode[3^e] = 0x00 | ((addend >> 1) & 0xff);
1392 operand = MEP_OPERAND_PCREL17A2;
1393 break;
1395 case MEP_INSN_BLTI:
1396 case MEP_INSN_BGEI:
1397 case MEP_INSN_BCPEQ:
1398 case MEP_INSN_BCPNE:
1399 case MEP_INSN_BCPAT:
1400 case MEP_INSN_BCPAF:
1401 /* No opcode change needed, just operand. */
1402 fragP->fr_opcode[2^e] = (addend >> 9) & 0xff;
1403 fragP->fr_opcode[3^e] = (addend >> 1) & 0xff;
1404 operand = MEP_OPERAND_PCREL17A2;
1405 break;
1407 default:
1408 abort ();
1411 if (S_GET_SEGMENT (fragP->fr_symbol) != sec
1412 || operand == MEP_OPERAND_PCABS24A2)
1414 assert (fragP->fr_cgen.insn != 0);
1415 gas_cgen_record_fixup (fragP,
1416 where,
1417 fragP->fr_cgen.insn,
1418 (fragP->fr_fix - where) * 8,
1419 cgen_operand_lookup_by_num (gas_cgen_cpu_desc,
1420 operand),
1421 fragP->fr_cgen.opinfo,
1422 fragP->fr_symbol, fragP->fr_offset);
1427 /* Functions concerning relocs. */
1429 void
1430 mep_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
1432 /* If we already know the fixup value, adjust it in the same
1433 way that the linker would have done. */
1434 if (fixP->fx_addsy == 0)
1435 switch (fixP->fx_cgen.opinfo)
1437 case BFD_RELOC_MEP_LOW16:
1438 *valP = ((long)(*valP & 0xffff)) << 16 >> 16;
1439 break;
1440 case BFD_RELOC_MEP_HI16U:
1441 *valP >>= 16;
1442 break;
1443 case BFD_RELOC_MEP_HI16S:
1444 *valP = (*valP + 0x8000) >> 16;
1445 break;
1448 /* Now call cgen's md_aply_fix. */
1449 gas_cgen_md_apply_fix (fixP, valP, seg);
1452 long
1453 md_pcrel_from_section (fixS *fixP, segT sec)
1455 if (fixP->fx_addsy != (symbolS *) NULL
1456 && (! S_IS_DEFINED (fixP->fx_addsy)
1457 || S_GET_SEGMENT (fixP->fx_addsy) != sec))
1458 /* The symbol is undefined (or is defined but not in this section).
1459 Let the linker figure it out. */
1460 return 0;
1462 /* Return the address of the opcode - cgen adjusts for opcode size
1463 itself, to be consistent with the disassembler, which must do
1464 so. */
1465 return fixP->fx_where + fixP->fx_frag->fr_address;
1468 /* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
1469 Returns BFD_RELOC_NONE if no reloc type can be found.
1470 *FIXP may be modified if desired. */
1472 #if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
1473 #define MAP(n) case MEP_OPERAND_##n: return BFD_RELOC_MEP_##n;
1474 #else
1475 #define MAP(n) case MEP_OPERAND_/**/n: return BFD_RELOC_MEP_/**/n;
1476 #endif
1478 bfd_reloc_code_real_type
1479 md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
1480 const CGEN_OPERAND *operand,
1481 fixS *fixP)
1483 enum bfd_reloc_code_real reloc = fixP->fx_cgen.opinfo;
1484 static char printed[MEP_OPERAND_MAX] = { 0 };
1486 /* If there's a reloc here, it's because the parser saw a %foo() and
1487 is giving us the correct reloc to use, or because we converted to
1488 a different size reloc below and want to avoid "converting" more
1489 than once. */
1490 if (reloc && reloc != BFD_RELOC_NONE)
1491 return reloc;
1493 switch (operand->type)
1495 MAP (PCREL8A2); /* beqz */
1496 MAP (PCREL12A2); /* bsr16 */
1497 MAP (PCREL17A2); /* beqi */
1498 MAP (PCREL24A2); /* bsr24 */
1499 MAP (PCABS24A2); /* jmp */
1500 MAP (UIMM24); /* mov */
1501 MAP (ADDR24A4); /* sw/lw */
1503 /* The rest of the relocs should be generated by the parser,
1504 for things such as %tprel(), etc. */
1505 case MEP_OPERAND_SIMM16:
1506 #ifdef OBJ_COMPLEX_RELC
1507 /* coalescing this into RELOC_MEP_16 is actually a bug,
1508 since it's a signed operand. let the relc code handle it. */
1509 return BFD_RELOC_RELC;
1510 #endif
1512 case MEP_OPERAND_UIMM16:
1513 case MEP_OPERAND_SDISP16:
1514 case MEP_OPERAND_CODE16:
1515 fixP->fx_where += 2;
1516 /* to avoid doing the above add twice */
1517 fixP->fx_cgen.opinfo = BFD_RELOC_MEP_16;
1518 return BFD_RELOC_MEP_16;
1520 default:
1521 #ifdef OBJ_COMPLEX_RELC
1522 /* this is not an error, yet.
1523 pass it to the linker. */
1524 return BFD_RELOC_RELC;
1525 #endif
1526 if (printed[operand->type])
1527 return BFD_RELOC_NONE;
1528 printed[operand->type] = 1;
1530 as_bad_where (fixP->fx_file, fixP->fx_line,
1531 _("Don't know how to relocate plain operands of type %s"),
1532 operand->name);
1534 /* Print some helpful hints for the user. */
1535 switch (operand->type)
1537 case MEP_OPERAND_UDISP7:
1538 case MEP_OPERAND_UDISP7A2:
1539 case MEP_OPERAND_UDISP7A4:
1540 as_bad_where (fixP->fx_file, fixP->fx_line,
1541 _("Perhaps you are missing %%tpoff()?"));
1542 break;
1543 default:
1544 break;
1546 return BFD_RELOC_NONE;
1550 /* Called while parsing an instruction to create a fixup.
1551 We need to check for HI16 relocs and queue them up for later sorting. */
1553 fixS *
1554 mep_cgen_record_fixup_exp (fragS *frag,
1555 int where,
1556 const CGEN_INSN *insn,
1557 int length,
1558 const CGEN_OPERAND *operand,
1559 int opinfo,
1560 expressionS *exp)
1562 fixS * fixP = gas_cgen_record_fixup_exp (frag, where, insn, length,
1563 operand, opinfo, exp);
1564 return fixP;
1567 /* Return BFD reloc type from opinfo field in a fixS.
1568 It's tricky using fx_r_type in mep_frob_file because the values
1569 are BFD_RELOC_UNUSED + operand number. */
1570 #define FX_OPINFO_R_TYPE(f) ((f)->fx_cgen.opinfo)
1572 /* Sort any unmatched HI16 relocs so that they immediately precede
1573 the corresponding LO16 reloc. This is called before md_apply_fix and
1574 tc_gen_reloc. */
1576 void
1577 mep_frob_file ()
1579 struct mep_hi_fixup * l;
1581 for (l = mep_hi_fixup_list; l != NULL; l = l->next)
1583 segment_info_type * seginfo;
1584 int pass;
1586 assert (FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_HI16
1587 || FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_LO16);
1589 /* Check quickly whether the next fixup happens to be a matching low. */
1590 if (l->fixp->fx_next != NULL
1591 && FX_OPINFO_R_TYPE (l->fixp->fx_next) == BFD_RELOC_LO16
1592 && l->fixp->fx_addsy == l->fixp->fx_next->fx_addsy
1593 && l->fixp->fx_offset == l->fixp->fx_next->fx_offset)
1594 continue;
1596 /* Look through the fixups for this segment for a matching
1597 `low'. When we find one, move the high just in front of it.
1598 We do this in two passes. In the first pass, we try to find
1599 a unique `low'. In the second pass, we permit multiple
1600 high's relocs for a single `low'. */
1601 seginfo = seg_info (l->seg);
1602 for (pass = 0; pass < 2; pass++)
1604 fixS * f;
1605 fixS * prev;
1607 prev = NULL;
1608 for (f = seginfo->fix_root; f != NULL; f = f->fx_next)
1610 /* Check whether this is a `low' fixup which matches l->fixp. */
1611 if (FX_OPINFO_R_TYPE (f) == BFD_RELOC_LO16
1612 && f->fx_addsy == l->fixp->fx_addsy
1613 && f->fx_offset == l->fixp->fx_offset
1614 && (pass == 1
1615 || prev == NULL
1616 || (FX_OPINFO_R_TYPE (prev) != BFD_RELOC_HI16)
1617 || prev->fx_addsy != f->fx_addsy
1618 || prev->fx_offset != f->fx_offset))
1620 fixS ** pf;
1622 /* Move l->fixp before f. */
1623 for (pf = &seginfo->fix_root;
1624 * pf != l->fixp;
1625 pf = & (* pf)->fx_next)
1626 assert (* pf != NULL);
1628 * pf = l->fixp->fx_next;
1630 l->fixp->fx_next = f;
1631 if (prev == NULL)
1632 seginfo->fix_root = l->fixp;
1633 else
1634 prev->fx_next = l->fixp;
1636 break;
1639 prev = f;
1642 if (f != NULL)
1643 break;
1645 if (pass == 1)
1646 as_warn_where (l->fixp->fx_file, l->fixp->fx_line,
1647 _("Unmatched high relocation"));
1652 /* See whether we need to force a relocation into the output file. */
1655 mep_force_relocation (fixS *fixp)
1657 if ( fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
1658 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
1659 return 1;
1661 /* Allow branches to global symbols to be resolved at assembly time.
1662 This is consistent with way relaxable branches are handled, since
1663 branches to both global and local symbols are relaxed. It also
1664 corresponds to the assumptions made in md_pcrel_from_section. */
1665 return S_FORCE_RELOC (fixp->fx_addsy, !fixp->fx_pcrel);
1668 /* Write a value out to the object file, using the appropriate endianness. */
1670 void
1671 md_number_to_chars (char *buf, valueT val, int n)
1673 if (target_big_endian)
1674 number_to_chars_bigendian (buf, val, n);
1675 else
1676 number_to_chars_littleendian (buf, val, n);
1679 char *
1680 md_atof (int type, char *litP, int *sizeP)
1682 return ieee_md_atof (type, litP, sizeP, TRUE);
1685 bfd_boolean
1686 mep_fix_adjustable (fixS *fixP)
1688 bfd_reloc_code_real_type reloc_type;
1690 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
1692 const CGEN_INSN *insn = NULL;
1693 int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
1694 const CGEN_OPERAND *operand
1695 = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex);
1696 reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
1698 else
1699 reloc_type = fixP->fx_r_type;
1701 if (fixP->fx_addsy == NULL)
1702 return 1;
1704 /* Prevent all adjustments to global symbols. */
1705 if (S_IS_EXTERNAL (fixP->fx_addsy))
1706 return 0;
1708 if (S_IS_WEAK (fixP->fx_addsy))
1709 return 0;
1711 /* We need the symbol name for the VTABLE entries */
1712 if (reloc_type == BFD_RELOC_VTABLE_INHERIT
1713 || reloc_type == BFD_RELOC_VTABLE_ENTRY)
1714 return 0;
1716 return 1;
1720 mep_elf_section_letter (int letter, char **ptrmsg)
1722 if (letter == 'v')
1723 return SHF_MEP_VLIW;
1725 *ptrmsg = _("Bad .section directive: want a,v,w,x,M,S in string");
1726 return 0;
1729 flagword
1730 mep_elf_section_flags (flagword flags, int attr, int type ATTRIBUTE_UNUSED)
1732 if (attr & SHF_MEP_VLIW)
1733 flags |= SEC_MEP_VLIW;
1734 return flags;
1737 /* In vliw mode, the default section is .vtext. We have to be able
1738 to switch into .vtext using only the .vtext directive. */
1740 static segT
1741 mep_vtext_section (void)
1743 static segT vtext_section;
1745 if (! vtext_section)
1747 flagword applicable = bfd_applicable_section_flags (stdoutput);
1748 vtext_section = subseg_new (VTEXT_SECTION_NAME, 0);
1749 bfd_set_section_flags (stdoutput, vtext_section,
1750 applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC
1751 | SEC_CODE | SEC_READONLY
1752 | SEC_MEP_VLIW));
1755 return vtext_section;
1758 static void
1759 mep_s_vtext (int ignore ATTRIBUTE_UNUSED)
1761 int temp;
1763 /* Record previous_section and previous_subsection. */
1764 obj_elf_section_change_hook ();
1766 temp = get_absolute_expression ();
1767 subseg_set (mep_vtext_section (), (subsegT) temp);
1768 demand_empty_rest_of_line ();
1771 static void
1772 mep_switch_to_core_mode (int dummy ATTRIBUTE_UNUSED)
1774 mep_process_saved_insns ();
1775 pluspresent = 0;
1776 mode = CORE;
1779 static void
1780 mep_switch_to_vliw_mode (int dummy ATTRIBUTE_UNUSED)
1782 if (! MEP_VLIW)
1783 as_bad (_(".vliw unavailable when VLIW is disabled."));
1784 mode = VLIW;
1785 /* Switch into .vtext here too. */
1786 /* mep_s_vtext(); */
1789 /* This is an undocumented pseudo-op used to disable gas's
1790 "disabled_registers" check. Used for code which checks for those
1791 registers at runtime. */
1792 static void
1793 mep_noregerr (int i ATTRIBUTE_UNUSED)
1795 allow_disabled_registers = 1;
1798 /* mep_unrecognized_line: This is called when a line that can't be parsed
1799 is encountered. We use it to check for a leading '+' sign which indicates
1800 that the current instruction is a coprocessor instruction that is to be
1801 parallelized with a previous core insn. This function accepts the '+' and
1802 rejects all other characters that might indicate garbage at the beginning
1803 of the line. The '+' character gets lost as the calling loop continues,
1804 so we need to indicate that we saw it. */
1807 mep_unrecognized_line (int ch)
1809 switch (ch)
1811 case '+':
1812 pluspresent = 1;
1813 return 1; /* '+' indicates an instruction to be parallelized. */
1814 default:
1815 return 0; /* If it's not a '+', the line can't be parsed. */
1819 void
1820 mep_cleanup (void)
1822 /* Take care of any insns left to be parallelized when the file ends.
1823 This is mainly here to handle the case where the file ends with an
1824 insn preceeded by a + or the file ends unexpectedly. */
1825 if (mode == VLIW)
1826 mep_process_saved_insns ();
1830 mep_flush_pending_output (void)
1832 if (mode == VLIW)
1834 mep_process_saved_insns ();
1835 pluspresent = 0;
1838 return 1;