* mep.h (EF_MEP_COP_*): New.
[deliverable/binutils-gdb.git] / gas / config / tc-mep.c
CommitLineData
280d71bf 1/* tc-mep.c -- Assembler for the Toshiba Media Processor.
ec2655a6
NC
2 Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007
3 Free Software Foundation. Inc.
280d71bf
DB
4
5 This file is part of GAS, the GNU Assembler.
6
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
ec2655a6 9 the Free Software Foundation; either version 3, or (at your option)
280d71bf
DB
10 any later version.
11
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.
16
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. */
21
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"
34
35/* Structure to hold all of the different components describing
36 an individual instruction. */
37typedef struct
38{
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;
55
56static int mode = CORE; /* Start in core mode. */
57static int pluspresent = 0;
58static int allow_disabled_registers = 0;
59static int library_flag = 0;
60
61/* We're going to need to store all of the instructions along with
62 their fixups so that we can parallelization grouping rules. */
63
64static mep_insn saved_insns[MAX_SAVED_FIXUP_CHAINS];
65static int num_insns_saved = 0;
66
67const char comment_chars[] = "#";
68const char line_comment_chars[] = ";#";
69const char line_separator_chars[] = ";";
70const char EXP_CHARS[] = "eE";
71const char FLT_CHARS[] = "dD";
72
73static void mep_switch_to_vliw_mode (int);
74static void mep_switch_to_core_mode (int);
75static void mep_s_vtext (int);
76static void mep_noregerr (int);
77
78/* The target specific pseudo-ops which we support. */
79const pseudo_typeS md_pseudo_table[] =
80{
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 }
89};
90
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.
97
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. */
101
102struct mep_hi_fixup
103{
104 struct mep_hi_fixup * next; /* Next HI fixup. */
105 fixS * fixp; /* This fixup. */
106 segT seg; /* The section this fixup is in. */
107};
108
109/* The list of unmatched HI relocs. */
110static struct mep_hi_fixup * mep_hi_fixup_list;
111
112\f
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)
4d28413b
DD
139#define OPTION_UCI (OPTION_MD_BASE + 29)
140#define OPTION_NOUCI (OPTION_MD_BASE + 30)
141#define OPTION_DSP (OPTION_MD_BASE + 31)
142#define OPTION_NODSP (OPTION_MD_BASE + 32)
143#define OPTION_LIBRARY (OPTION_MD_BASE + 33)
280d71bf
DB
144
145struct option md_longopts[] = {
146 { "EB", no_argument, NULL, OPTION_EB},
147 { "EL", no_argument, NULL, OPTION_EL},
148 { "mconfig", required_argument, NULL, OPTION_CONFIG},
149 { "maverage", no_argument, NULL, OPTION_AVERAGE},
150 { "mno-average", no_argument, NULL, OPTION_NOAVERAGE},
151 { "mmult", no_argument, NULL, OPTION_MULT},
152 { "mno-mult", no_argument, NULL, OPTION_NOMULT},
153 { "mdiv", no_argument, NULL, OPTION_DIV},
154 { "mno-div", no_argument, NULL, OPTION_NODIV},
155 { "mbitops", no_argument, NULL, OPTION_BITOPS},
156 { "mno-bitops", no_argument, NULL, OPTION_NOBITOPS},
157 { "mleadz", no_argument, NULL, OPTION_LEADZ},
158 { "mno-leadz", no_argument, NULL, OPTION_NOLEADZ},
159 { "mabsdiff", no_argument, NULL, OPTION_ABSDIFF},
160 { "mno-absdiff", no_argument, NULL, OPTION_NOABSDIFF},
161 { "mminmax", no_argument, NULL, OPTION_MINMAX},
162 { "mno-minmax", no_argument, NULL, OPTION_NOMINMAX},
163 { "mclip", no_argument, NULL, OPTION_CLIP},
164 { "mno-clip", no_argument, NULL, OPTION_NOCLIP},
165 { "msatur", no_argument, NULL, OPTION_SATUR},
166 { "mno-satur", no_argument, NULL, OPTION_NOSATUR},
167 { "mcop32", no_argument, NULL, OPTION_COP32},
168 { "mdebug", no_argument, NULL, OPTION_DEBUG},
169 { "mno-debug", no_argument, NULL, OPTION_NODEBUG},
4d28413b
DD
170 { "muci", no_argument, NULL, OPTION_UCI},
171 { "mno-uci", no_argument, NULL, OPTION_NOUCI},
172 { "mdsp", no_argument, NULL, OPTION_DSP},
173 { "mno-dsp", no_argument, NULL, OPTION_NODSP},
280d71bf
DB
174 { "mlibrary", no_argument, NULL, OPTION_LIBRARY},
175 { NULL, 0, NULL, 0 } };
176size_t md_longopts_size = sizeof (md_longopts);
177
178const char * md_shortopts = "";
179static int optbits = 0;
180static int optbitset = 0;
181
182int
183md_parse_option (int c, char *arg ATTRIBUTE_UNUSED)
184{
185 int i, idx;
186 switch (c)
187 {
188 case OPTION_EB:
189 target_big_endian = 1;
190 break;
191 case OPTION_EL:
192 target_big_endian = 0;
193 break;
194 case OPTION_CONFIG:
195 idx = 0;
196 for (i=1; mep_config_map[i].name; i++)
197 if (strcmp (mep_config_map[i].name, arg) == 0)
198 {
199 idx = i;
200 break;
201 }
202 if (!idx)
203 {
204 fprintf (stderr, "Error: unknown configuration %s\n", arg);
205 return 0;
206 }
207 mep_config_index = idx;
208 target_big_endian = mep_config_map[idx].big_endian;
209 break;
210 case OPTION_AVERAGE:
211 optbits |= 1 << CGEN_INSN_OPTIONAL_AVE_INSN;
212 optbitset |= 1 << CGEN_INSN_OPTIONAL_AVE_INSN;
213 break;
214 case OPTION_NOAVERAGE:
215 optbits &= ~(1 << CGEN_INSN_OPTIONAL_AVE_INSN);
216 optbitset |= 1 << CGEN_INSN_OPTIONAL_AVE_INSN;
217 break;
218 case OPTION_MULT:
219 optbits |= 1 << CGEN_INSN_OPTIONAL_MUL_INSN;
220 optbitset |= 1 << CGEN_INSN_OPTIONAL_MUL_INSN;
221 break;
222 case OPTION_NOMULT:
223 optbits &= ~(1 << CGEN_INSN_OPTIONAL_MUL_INSN);
224 optbitset |= 1 << CGEN_INSN_OPTIONAL_MUL_INSN;
225 break;
226 case OPTION_DIV:
227 optbits |= 1 << CGEN_INSN_OPTIONAL_DIV_INSN;
228 optbitset |= 1 << CGEN_INSN_OPTIONAL_DIV_INSN;
229 break;
230 case OPTION_NODIV:
231 optbits &= ~(1 << CGEN_INSN_OPTIONAL_DIV_INSN);
232 optbitset |= 1 << CGEN_INSN_OPTIONAL_DIV_INSN;
233 break;
234 case OPTION_BITOPS:
235 optbits |= 1 << CGEN_INSN_OPTIONAL_BIT_INSN;
236 optbitset |= 1 << CGEN_INSN_OPTIONAL_BIT_INSN;
237 break;
238 case OPTION_NOBITOPS:
239 optbits &= ~(1 << CGEN_INSN_OPTIONAL_BIT_INSN);
240 optbitset |= 1 << CGEN_INSN_OPTIONAL_BIT_INSN;
241 break;
242 case OPTION_LEADZ:
243 optbits |= 1 << CGEN_INSN_OPTIONAL_LDZ_INSN;
244 optbitset |= 1 << CGEN_INSN_OPTIONAL_LDZ_INSN;
245 break;
246 case OPTION_NOLEADZ:
247 optbits &= ~(1 << CGEN_INSN_OPTIONAL_LDZ_INSN);
248 optbitset |= 1 << CGEN_INSN_OPTIONAL_LDZ_INSN;
249 break;
250 case OPTION_ABSDIFF:
251 optbits |= 1 << CGEN_INSN_OPTIONAL_ABS_INSN;
252 optbitset |= 1 << CGEN_INSN_OPTIONAL_ABS_INSN;
253 break;
254 case OPTION_NOABSDIFF:
255 optbits &= ~(1 << CGEN_INSN_OPTIONAL_ABS_INSN);
256 optbitset |= 1 << CGEN_INSN_OPTIONAL_ABS_INSN;
257 break;
258 case OPTION_MINMAX:
259 optbits |= 1 << CGEN_INSN_OPTIONAL_MINMAX_INSN;
260 optbitset |= 1 << CGEN_INSN_OPTIONAL_MINMAX_INSN;
261 break;
262 case OPTION_NOMINMAX:
263 optbits &= ~(1 << CGEN_INSN_OPTIONAL_MINMAX_INSN);
264 optbitset |= 1 << CGEN_INSN_OPTIONAL_MINMAX_INSN;
265 break;
266 case OPTION_CLIP:
267 optbits |= 1 << CGEN_INSN_OPTIONAL_CLIP_INSN;
268 optbitset |= 1 << CGEN_INSN_OPTIONAL_CLIP_INSN;
269 break;
270 case OPTION_NOCLIP:
271 optbits &= ~(1 << CGEN_INSN_OPTIONAL_CLIP_INSN);
272 optbitset |= 1 << CGEN_INSN_OPTIONAL_CLIP_INSN;
273 break;
274 case OPTION_SATUR:
275 optbits |= 1 << CGEN_INSN_OPTIONAL_SAT_INSN;
276 optbitset |= 1 << CGEN_INSN_OPTIONAL_SAT_INSN;
277 break;
278 case OPTION_NOSATUR:
279 optbits &= ~(1 << CGEN_INSN_OPTIONAL_SAT_INSN);
280 optbitset |= 1 << CGEN_INSN_OPTIONAL_SAT_INSN;
281 break;
282 case OPTION_COP32:
283 optbits |= 1 << CGEN_INSN_OPTIONAL_CP_INSN;
284 optbitset |= 1 << CGEN_INSN_OPTIONAL_CP_INSN;
285 break;
286 case OPTION_DEBUG:
287 optbits |= 1 << CGEN_INSN_OPTIONAL_DEBUG_INSN;
288 optbitset |= 1 << CGEN_INSN_OPTIONAL_DEBUG_INSN;
289 break;
290 case OPTION_NODEBUG:
291 optbits &= ~(1 << CGEN_INSN_OPTIONAL_DEBUG_INSN);
292 optbitset |= 1 << CGEN_INSN_OPTIONAL_DEBUG_INSN;
293 break;
4d28413b
DD
294 case OPTION_UCI:
295 optbits |= 1 << CGEN_INSN_OPTIONAL_UCI_INSN;
296 optbitset |= 1 << CGEN_INSN_OPTIONAL_UCI_INSN;
297 break;
298 case OPTION_NOUCI:
299 optbits &= ~(1 << CGEN_INSN_OPTIONAL_UCI_INSN);
300 optbitset |= 1 << CGEN_INSN_OPTIONAL_UCI_INSN;
301 break;
302 case OPTION_DSP:
303 optbits |= 1 << CGEN_INSN_OPTIONAL_DSP_INSN;
304 optbitset |= 1 << CGEN_INSN_OPTIONAL_DSP_INSN;
305 break;
306 case OPTION_NODSP:
307 optbits &= ~(1 << CGEN_INSN_OPTIONAL_DSP_INSN);
308 optbitset |= 1 << CGEN_INSN_OPTIONAL_DSP_INSN;
309 break;
280d71bf
DB
310 case OPTION_LIBRARY:
311 library_flag = EF_MEP_LIBRARY;
312 break;
313 case OPTION_REPEAT:
314 case OPTION_NOREPEAT:
315 break;
316 default:
317 return 0;
318 }
319 return 1;
320}
321
322void
323md_show_usage (FILE *stream)
324{
325 fprintf (stream, _("MeP specific command line options:\n\
4d28413b
DD
326 -EB assemble for a big endian system\n\
327 -EL assemble for a little endian system (default)\n\
280d71bf
DB
328 -mconfig=<name> specify a chip configuration to use\n\
329 -maverage -mno-average -mmult -mno-mult -mdiv -mno-div\n\
330 -mbitops -mno-bitops -mleadz -mno-leadz -mabsdiff -mno-absdiff\n\
331 -mminmax -mno-minmax -mclip -mno-clip -msatur -mno-satur -mcop32\n\
332 enable/disable the given opcodes\n\
333\n\
334 If -mconfig is given, the other -m options modify it. Otherwise,\n\
335 if no -m options are given, all core opcodes are enabled;\n\
336 if any enabling -m options are given, only those are enabled;\n\
337 if only disabling -m options are given, only those are disabled.\n\
338"));
339 if (mep_config_map[1].name)
340 {
341 int i;
342 fprintf (stream, " -mconfig=STR specify the configuration to use\n");
343 fprintf (stream, " Configurations:");
344 for (i=0; mep_config_map[i].name; i++)
345 fprintf (stream, " %s", mep_config_map[i].name);
346 fprintf (stream, "\n");
347 }
348}
349
350\f
351
352static void
353mep_check_for_disabled_registers (mep_insn *insn)
354{
355 static int initted = 0;
356 static int has_mul_div = 0;
357 static int has_cop = 0;
358 static int has_debug = 0;
359 unsigned int b, r;
360
361 if (allow_disabled_registers)
362 return;
363
364#if !CGEN_INT_INSN_P
365 if (target_big_endian)
366 b = insn->buffer[0] * 256 + insn->buffer[1];
367 else
368 b = insn->buffer[1] * 256 + insn->buffer[0];
369#else
370 b = insn->buffer[0];
371#endif
372
373 if ((b & 0xfffff00e) == 0x7008 /* stc */
374 || (b & 0xfffff00e) == 0x700a /* ldc */)
375 {
376 if (!initted)
377 {
378 initted = 1;
379 if ((MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_MUL_INSN))
380 || (MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_DIV_INSN)))
381 has_mul_div = 1;
382 if (MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_DEBUG_INSN))
383 has_debug = 1;
384 if (MEP_OMASK & (1 << CGEN_INSN_OPTIONAL_CP_INSN))
385 has_cop = 1;
386 }
387
388 r = ((b & 0x00f0) >> 4) | ((b & 0x0001) << 4);
389 switch (r)
390 {
391 case 7: /* $hi */
392 case 8: /* $lo */
393 if (!has_mul_div)
394 as_bad ("$hi and $lo are disabled when MUL and DIV are off");
395 break;
396 case 12: /* $mb0 */
397 case 13: /* $me0 */
398 case 14: /* $mb1 */
399 case 15: /* $me1 */
400 if (!has_cop)
401 as_bad ("$mb0, $me0, $mb1, and $me1 are disabled when COP is off");
402 break;
403 case 24: /* $dbg */
404 case 25: /* $depc */
405 if (!has_debug)
406 as_bad ("$dbg and $depc are disabled when DEBUG is off");
407 break;
408 }
409 }
410}
411
412static int
413mep_machine (void)
414{
415 switch (MEP_CPU)
416 {
417 default: break;
418 case EF_MEP_CPU_C2: return bfd_mach_mep;
419 case EF_MEP_CPU_C3: return bfd_mach_mep;
420 case EF_MEP_CPU_C4: return bfd_mach_mep;
4d28413b 421 case EF_MEP_CPU_C5: return bfd_mach_mep_c5;
280d71bf
DB
422 case EF_MEP_CPU_H1: return bfd_mach_mep_h1;
423 }
424
425 return bfd_mach_mep;
426}
427
428/* The MeP version of the cgen parse_operand function. The only difference
429 from the standard version is that we want to avoid treating '$foo' and
430 '($foo...)' as references to a symbol called '$foo'. The chances are
431 that '$foo' is really a misspelt register. */
432
433static const char *
434mep_parse_operand (CGEN_CPU_DESC cd, enum cgen_parse_operand_type want,
435 const char **strP, int opindex, int opinfo,
436 enum cgen_parse_operand_result *resultP, bfd_vma *valueP)
437{
438 if (want == CGEN_PARSE_OPERAND_INTEGER || want == CGEN_PARSE_OPERAND_ADDRESS)
439 {
440 const char *next;
441
442 next = *strP;
443 while (*next == '(')
444 next++;
445 if (*next == '$')
446 return "Not a valid literal";
447 }
448 return gas_cgen_parse_operand (cd, want, strP, opindex, opinfo,
449 resultP, valueP);
450}
451
452void
453md_begin ()
454{
455 /* Initialize the `cgen' interface. */
456
457 /* If the user specifies no options, we default to allowing
458 everything. If the user specifies any enabling options, we
459 default to allowing only what is specified. If the user
460 specifies only disabling options, we only disable what is
461 specified. If the user specifies options and a config, the
462 options modify the config. */
463 if (optbits && mep_config_index == 0)
464 MEP_OMASK = optbits;
465 else
466 MEP_OMASK = (MEP_OMASK & ~optbitset) | optbits;
467
468 /* Set the machine number and endian. */
469 gas_cgen_cpu_desc = mep_cgen_cpu_open (CGEN_CPU_OPEN_MACHS, 0,
470 CGEN_CPU_OPEN_ENDIAN,
471 target_big_endian
472 ? CGEN_ENDIAN_BIG
473 : CGEN_ENDIAN_LITTLE,
474 CGEN_CPU_OPEN_ISAS, 0,
475 CGEN_CPU_OPEN_END);
476 mep_cgen_init_asm (gas_cgen_cpu_desc);
477
478 /* This is a callback from cgen to gas to parse operands. */
479 cgen_set_parse_operand_fn (gas_cgen_cpu_desc, mep_parse_operand);
480
481 /* Identify the architecture. */
482 bfd_default_set_arch_mach (stdoutput, bfd_arch_mep, mep_machine ());
483
484 /* Store the configuration number and core. */
485 bfd_set_private_flags (stdoutput, MEP_CPU | MEP_CONFIG | library_flag);
486
487 /* Initialize the array we'll be using to store fixups. */
488 gas_cgen_initialize_saved_fixups_array();
489}
490
491/* Variant of mep_cgen_assemble_insn. Assemble insn STR of cpu CD as a
492 coprocessor instruction, if possible, into FIELDS, BUF, and INSN. */
493
494static const CGEN_INSN *
495mep_cgen_assemble_cop_insn (CGEN_CPU_DESC cd,
496 const char *str,
497 CGEN_FIELDS *fields,
498 CGEN_INSN_BYTES_PTR buf,
499 const struct cgen_insn *pinsn)
500{
501 const char *start;
502 CGEN_INSN_LIST *ilist;
503 const char *errmsg = NULL;
504
505 /* The instructions are stored in hashed lists. */
506 ilist = CGEN_ASM_LOOKUP_INSN (gas_cgen_cpu_desc,
507 CGEN_INSN_MNEMONIC (pinsn));
508
509 start = str;
510 for ( ; ilist != NULL ; ilist = CGEN_ASM_NEXT_INSN (ilist))
511 {
512 const CGEN_INSN *insn = ilist->insn;
513 if (strcmp (CGEN_INSN_MNEMONIC (ilist->insn),
514 CGEN_INSN_MNEMONIC (pinsn)) == 0
515 && MEP_INSN_COP_P (ilist->insn)
516 && mep_cgen_insn_supported (cd, insn))
517 {
518 str = start;
519
520 /* skip this insn if str doesn't look right lexically */
521 if (CGEN_INSN_RX (insn) != NULL &&
522 regexec ((regex_t *) CGEN_INSN_RX (insn), str, 0, NULL, 0) == REG_NOMATCH)
523 continue;
524
525 /* Allow parse/insert handlers to obtain length of insn. */
526 CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
527
528 errmsg = CGEN_PARSE_FN (cd, insn) (cd, insn, & str, fields);
529 if (errmsg != NULL)
530 continue;
531
532 errmsg = CGEN_INSERT_FN (cd, insn) (cd, insn, fields, buf,
533 (bfd_vma) 0);
534 if (errmsg != NULL)
535 continue;
536
537 return insn;
538 }
539 }
540 return pinsn;
541}
542
543static void
544mep_save_insn (mep_insn insn)
545{
546 /* Consider change MAX_SAVED_FIXUP_CHAINS to MAX_PARALLEL_INSNS. */
547 if (num_insns_saved < 0 || num_insns_saved >= MAX_SAVED_FIXUP_CHAINS)
548 {
549 as_fatal("index into saved_insns[] out of bounds.");
550 return;
551 }
552 saved_insns[num_insns_saved] = insn;
553 gas_cgen_save_fixups(num_insns_saved);
554 num_insns_saved++;
555}
556
557static void
558mep_check_parallel32_scheduling (void)
559{
560 int insn0iscopro, insn1iscopro, insn0length, insn1length;
561
562 /* More than two instructions means that either someone is referring to
563 an internally parallel core or an internally parallel coprocessor,
564 neither of which are supported at this time. */
565 if ( num_insns_saved > 2 )
566 as_fatal("Internally paralled cores and coprocessors not supported.");
567
568 /* If there are no insns saved, that's ok. Just return. This will
569 happen when mep_process_saved_insns is called when the end of the
570 source file is reached and there are no insns left to be processed. */
571 if (num_insns_saved == 0)
572 return;
573
574 /* Check some of the attributes of the first insn. */
575 insn0iscopro = MEP_INSN_COP_P (saved_insns[0].insn);
576 insn0length = CGEN_FIELDS_BITSIZE (& saved_insns[0].fields);
577
578 if (num_insns_saved == 2)
579 {
580 /* Check some of the attributes of the first insn. */
581 insn1iscopro = MEP_INSN_COP_P (saved_insns[1].insn);
582 insn1length = CGEN_FIELDS_BITSIZE (& saved_insns[1].fields);
583
584 if ((insn0iscopro && !insn1iscopro)
585 || (insn1iscopro && !insn0iscopro))
586 {
587 /* We have one core and one copro insn. If their sizes
588 add up to 32, then the combination is valid. */
589 if (insn0length + insn1length == 32)
590 return;
591 else
592 as_bad ("core and copro insn lengths must total 32 bits.");
593 }
594 else
595 as_bad ("vliw group must consist of 1 core and 1 copro insn.");
596 }
597 else
598 {
599 /* If we arrive here, we have one saved instruction. There are a
600 number of possible cases:
601
602 1. The instruction is a 32 bit core or coprocessor insn and
603 can be executed by itself. Valid.
604
605 2. The instrucion is a core instruction for which a cop nop
606 exists. In this case, insert the cop nop into the saved
607 insn array after the core insn and return. Valid.
608
609 3. The instruction is a coprocessor insn for which a core nop
610 exists. In this case, move the coprocessor insn to the
611 second element of the array and put the nop in the first
612 element then return. Valid.
613
614 4. The instruction is a core or coprocessor instruction for
615 which there is no matching coprocessor or core nop to use
616 to form a valid vliw insn combination. In this case, we
617 we have to abort. */
618
619 if (insn0length > 32)
620 as_fatal ("Cannot use 48- or 64-bit insns with a 32 bit datapath.");
621
622 if (insn0length == 32)
623 return;
624
625 /* Insn is smaller than datapath. If there are no matching
626 nops for this insn, then terminate assembly. */
627 if (CGEN_INSN_ATTR_VALUE (saved_insns[0].insn,
628 CGEN_INSN_VLIW32_NO_MATCHING_NOP))
629 as_fatal ("No valid nop.");
630
631 /* At this point we know that we have a single 16-bit insn that has
632 a matching nop. We have to assemble it and put it into the saved
633 insn and fixup chain arrays. */
634
635 if (insn0iscopro)
636 {
637 char *errmsg;
638 mep_insn insn;
639
640 /* Move the insn and it's fixups to the second element of the
641 saved insns arrary and insert a 16 bit core nope into the
642 first element. */
643 insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "nop",
644 &insn.fields, insn.buffer,
645 &errmsg);
646 if (!insn.insn)
647 {
648 as_bad ("%s", errmsg);
649 return;
650 }
651
652 /* Move the insn in element 0 to element 1 and insert the
653 nop into element 0. Move the fixups in element 0 to
654 element 1 and save the current fixups to element 0.
655 Really there aren't any fixups at this point because we're
656 inserting a nop but we might as well be general so that
657 if there's ever a need to insert a general insn, we'll
658 have an example. */
659 saved_insns[1] = saved_insns[0];
660 saved_insns[0] = insn;
661 num_insns_saved++;
662 gas_cgen_swap_fixups (0);
663 gas_cgen_save_fixups (1);
664 }
665 else
666 {
667 char * errmsg;
668 mep_insn insn;
669 int insn_num = saved_insns[0].insn->base->num;
670
671 /* Use 32 bit branches and skip the nop. */
672 if (insn_num == MEP_INSN_BSR12
673 || insn_num == MEP_INSN_BEQZ
674 || insn_num == MEP_INSN_BNEZ)
675 return;
676
677 /* Insert a 16-bit coprocessor nop. Note that at the time */
678 /* this was done, no 16-bit coprocessor nop was defined. */
679 insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop16",
680 &insn.fields, insn.buffer,
681 &errmsg);
682 if (!insn.insn)
683 {
684 as_bad ("%s", errmsg);
685 return;
686 }
687
688 /* Now put the insn and fixups into the arrays. */
689 mep_save_insn (insn);
690 }
691 }
692}
693
694static void
695mep_check_parallel64_scheduling (void)
696{
697 int insn0iscopro, insn1iscopro, insn0length, insn1length;
698
699 /* More than two instructions means that someone is referring to an
700 internally parallel core or an internally parallel coprocessor. */
701 /* These are not currently supported. */
702 if (num_insns_saved > 2)
703 as_fatal ("Internally parallel cores of coprocessors not supported.");
704
705 /* If there are no insns saved, that's ok. Just return. This will
706 happen when mep_process_saved_insns is called when the end of the
707 source file is reached and there are no insns left to be processed. */
708 if (num_insns_saved == 0)
709 return;
710
711 /* Check some of the attributes of the first insn. */
712 insn0iscopro = MEP_INSN_COP_P (saved_insns[0].insn);
713 insn0length = CGEN_FIELDS_BITSIZE (& saved_insns[0].fields);
714
715 if (num_insns_saved == 2)
716 {
717 /* Check some of the attributes of the first insn. */
718 insn1iscopro = MEP_INSN_COP_P (saved_insns[1].insn);
719 insn1length = CGEN_FIELDS_BITSIZE (& saved_insns[1].fields);
720
721 if ((insn0iscopro && !insn1iscopro)
722 || (insn1iscopro && !insn0iscopro))
723 {
724 /* We have one core and one copro insn. If their sizes
725 add up to 64, then the combination is valid. */
726 if (insn0length + insn1length == 64)
727 return;
728 else
729 as_bad ("core and copro insn lengths must total 64 bits.");
730 }
731 else
732 as_bad ("vliw group must consist of 1 core and 1 copro insn.");
733 }
734 else
735 {
736 /* If we arrive here, we have one saved instruction. There are a
737 number of possible cases:
738
739 1. The instruction is a 64 bit coprocessor insn and can be
740 executed by itself. Valid.
741
742 2. The instrucion is a core instruction for which a cop nop
743 exists. In this case, insert the cop nop into the saved
744 insn array after the core insn and return. Valid.
745
746 3. The instruction is a coprocessor insn for which a core nop
747 exists. In this case, move the coprocessor insn to the
748 second element of the array and put the nop in the first
749 element then return. Valid.
750
751 4. The instruction is a core or coprocessor instruction for
752 which there is no matching coprocessor or core nop to use
753 to form a valid vliw insn combination. In this case, we
754 we have to abort. */
755
756 /* If the insn is 64 bits long, it can run alone. The size check
757 is done indepependantly of whether the insn is core or copro
758 in case 64 bit coprocessor insns are added later. */
759 if (insn0length == 64)
760 return;
761
762 /* Insn is smaller than datapath. If there are no matching
763 nops for this insn, then terminate assembly. */
764 if (CGEN_INSN_ATTR_VALUE (saved_insns[0].insn,
765 CGEN_INSN_VLIW64_NO_MATCHING_NOP))
766 as_fatal ("No valid nop.");
767
768 if (insn0iscopro)
769 {
770 char *errmsg;
771 mep_insn insn;
772 int i;
773
774 /* Initialize the insn buffer. */
775 for (i = 0; i < 64; i++)
776 insn.buffer[i] = '\0';
777
778 /* We have a coprocessor insn. At this point in time there
779 are is 32-bit core nop. There is only a 16-bit core
780 nop. The idea is to allow for a relatively arbitrary
781 coprocessor to be specified. We aren't looking at
782 trying to cover future changes in the core at this time
783 since it is assumed that the core will remain fairly
784 static. If there ever are 32 or 48 bit core nops added,
785 they will require entries below. */
786
787 if (insn0length == 48)
788 {
789 /* Move the insn and fixups to the second element of the
790 arrays then assemble and insert a 16 bit core nop. */
791 insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "nop",
792 & insn.fields, insn.buffer,
793 & errmsg);
794 }
795 else
796 {
797 /* If this is reached, then we have a single coprocessor
798 insn that is not 48 bits long, but for which the assembler
799 thinks there is a matching core nop. If a 32-bit core
800 nop has been added, then make the necessary changes and
801 handle its assembly and insertion here. Otherwise,
802 go figure out why either:
803
804 1. The assembler thinks that there is a 32-bit core nop
805 to match a 32-bit coprocessor insn, or
806 2. The assembler thinks that there is a 48-bit core nop
807 to match a 16-bit coprocessor insn. */
808
809 as_fatal ("Assembler expects a non-existent core nop.");
810 }
811
812 if (!insn.insn)
813 {
814 as_bad ("%s", errmsg);
815 return;
816 }
817
818 /* Move the insn in element 0 to element 1 and insert the
819 nop into element 0. Move the fixups in element 0 to
820 element 1 and save the current fixups to element 0.
821 Really there aren't any fixups at this point because we're
822 inserting a nop but we might as well be general so that
823 if there's ever a need to insert a general insn, we'll
824 have an example. */
825
826 saved_insns[1] = saved_insns[0];
827 saved_insns[0] = insn;
828 num_insns_saved++;
829 gas_cgen_swap_fixups(0);
830 gas_cgen_save_fixups(1);
831
832 }
833 else
834 {
835 char * errmsg;
836 mep_insn insn;
837 int i;
838
839 /* Initialize the insn buffer */
840 for (i = 0; i < 64; i++)
841 insn.buffer[i] = '\0';
842
843 /* We have a core insn. We have to handle all possible nop
844 lengths. If a coprocessor doesn't have a nop of a certain
845 length but there exists core insns that when combined with
846 a nop of that length would fill the datapath, those core
847 insns will be flagged with the VLIW_NO_CORRESPONDING_NOP
848 attribute. That will ensure that when used in a way that
849 requires a nop to be inserted, assembly will terminate
850 before reaching this section of code. This guarantees
851 that cases below which would result in the attempted
852 insertion of nop that doesn't exist will never be entered. */
853 if (insn0length == 16)
854 {
855 /* Insert 48 bit coprocessor nop. */
856 /* Assemble it and put it into the arrays. */
857 insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop48",
858 &insn.fields, insn.buffer,
859 &errmsg);
860 }
861 else if (insn0length == 32)
862 {
863 /* Insert 32 bit coprocessor nop. */
864 insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop32",
865 &insn.fields, insn.buffer,
866 &errmsg);
867 }
868 else if (insn0length == 48)
869 {
870 /* Insert 16 bit coprocessor nop. */
871 insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, "cpnop16",
872 &insn.fields, insn.buffer,
873 &errmsg);
874 }
875 else
876 /* Core insn has an invalid length. Something has gone wrong. */
877 as_fatal ("Core insn has invalid length! Something is wrong!");
878
879 if (!insn.insn)
880 {
881 as_bad ("%s", errmsg);
882 return;
883 }
884
885 /* Now put the insn and fixups into the arrays. */
886 mep_save_insn (insn);
887 }
888 }
889}
890
891/* The scheduling functions are just filters for invalid combinations.
892 If there is a violation, they terminate assembly. Otherise they
893 just fall through. Succesful combinations cause no side effects
894 other than valid nop insertion. */
895
896static void
897mep_check_parallel_scheduling (void)
898{
899 /* This is where we will eventually read the config information
900 and choose which scheduling checking function to call. */
901 if (MEP_VLIW64)
902 mep_check_parallel64_scheduling ();
903 else
904 mep_check_parallel32_scheduling ();
905}
906
907static void
908mep_process_saved_insns (void)
909{
910 int i;
911
912 gas_cgen_save_fixups (MAX_SAVED_FIXUP_CHAINS - 1);
913
914 /* We have to check for valid scheduling here. */
915 mep_check_parallel_scheduling ();
916
917 /* If the last call didn't cause assembly to terminate, we have
918 a valid vliw insn/insn pair saved. Restore this instructions'
919 fixups and process the insns. */
920 for (i = 0;i<num_insns_saved;i++)
921 {
922 gas_cgen_restore_fixups (i);
923 gas_cgen_finish_insn (saved_insns[i].insn, saved_insns[i].buffer,
924 CGEN_FIELDS_BITSIZE (& saved_insns[i].fields),
925 1, NULL);
926 }
927 gas_cgen_restore_fixups (MAX_SAVED_FIXUP_CHAINS - 1);
928
929 /* Clear the fixups and reset the number insn saved to 0. */
930 gas_cgen_initialize_saved_fixups_array ();
931 num_insns_saved = 0;
932 listing_prev_line ();
933}
934
935void
936md_assemble (char * str)
937{
938 static CGEN_BITSET* isas = NULL;
939 char * errmsg;
940
941 /* Initialize GAS's cgen interface for a new instruction. */
942 gas_cgen_init_parse ();
943
944 /* There are two possible modes: core and vliw. We have to assemble
945 differently for each.
946
947 Core Mode: We assemble normally. All instructions are on a
948 single line and are made up of one mnemonic and one
949 set of operands.
950 VLIW Mode: Vliw combinations are indicated as follows:
951
952 core insn
953 + copro insn
954
955 We want to handle the general case where more than
956 one instruction can be preceeded by a +. This will
957 happen later if we add support for internally parallel
958 coprocessors. We'll make the parsing nice and general
959 so that it can handle an arbitrary number of insns
960 with leading +'s. The actual checking for valid
961 combinations is done elsewhere. */
962
963 /* Initialize the isa to refer to the core. */
964 if (isas == NULL)
965 isas = cgen_bitset_copy (& MEP_CORE_ISA);
966 else
967 {
968 cgen_bitset_clear (isas);
969 cgen_bitset_union (isas, & MEP_CORE_ISA, isas);
970 }
971 gas_cgen_cpu_desc->isas = isas;
972
973 if (mode == VLIW)
974 {
975 /* VLIW mode. */
976
977 int thisInsnIsCopro = 0;
978 mep_insn insn;
979 int i;
980
981 /* Initialize the insn buffer */
982
983 if (! CGEN_INT_INSN_P)
984 for (i=0; i < CGEN_MAX_INSN_SIZE; i++)
985 insn.buffer[i]='\0';
986
987 /* Can't tell core / copro insns apart at parse time! */
988 cgen_bitset_union (isas, & MEP_COP_ISA, isas);
989
990 /* Assemble the insn so we can examine its attributes. */
991 insn.insn = mep_cgen_assemble_insn (gas_cgen_cpu_desc, str,
992 &insn.fields, insn.buffer,
993 &errmsg);
994 if (!insn.insn)
995 {
996 as_bad ("%s", errmsg);
997 return;
998 }
999 mep_check_for_disabled_registers (&insn);
1000
1001 /* Check to see if it's a coprocessor instruction. */
1002 thisInsnIsCopro = MEP_INSN_COP_P (insn.insn);
1003
1004 if (!thisInsnIsCopro)
1005 {
1006 insn.insn = mep_cgen_assemble_cop_insn (gas_cgen_cpu_desc, str,
1007 &insn.fields, insn.buffer,
1008 insn.insn);
1009 thisInsnIsCopro = MEP_INSN_COP_P (insn.insn);
1010 mep_check_for_disabled_registers (&insn);
1011 }
1012
1013 if (pluspresent)
1014 {
1015 /* A plus was present. */
1016 /* Check for a + with a core insn and abort if found. */
1017 if (!thisInsnIsCopro)
1018 {
1019 as_fatal("A core insn cannot be preceeded by a +.\n");
1020 return;
1021 }
1022
1023 if (num_insns_saved > 0)
1024 {
1025 /* There are insns in the queue. Add this one. */
1026 mep_save_insn (insn);
1027 }
1028 else
1029 {
1030 /* There are no insns in the queue and a plus is present.
1031 This is a syntax error. Let's not tolerate this.
1032 We can relax this later if necessary. */
1033 as_bad (_("Invalid use of parallelization operator."));
1034 return;
1035 }
1036 }
1037 else
1038 {
1039 /* No plus was present. */
1040 if (num_insns_saved > 0)
1041 {
1042 /* There are insns saved and we came across an insn without a
1043 leading +. That's the signal to process the saved insns
1044 before proceeding then treat the current insn as the first
1045 in a new vliw group. */
1046 mep_process_saved_insns ();
1047 num_insns_saved = 0;
1048 /* mep_save_insn (insn); */
1049 }
1050 mep_save_insn (insn);
1051#if 0
1052 else
1053 {
1054
1055 /* Core Insn. Add it to the beginning of the queue. */
1056 mep_save_insn (insn);
1057 /* gas_cgen_save_fixups(num_insns_saved); */
1058 }
1059#endif
1060 }
1061
1062 pluspresent = 0;
1063 }
1064 else
1065 {
1066 /* Core mode. */
1067
1068 /* Only single instructions are assembled in core mode. */
1069 mep_insn insn;
1070
1071 /* If a leading '+' was present, issue an error.
1072 That's not allowed in core mode. */
1073 if (pluspresent)
1074 {
1075 as_bad (_("Leading plus sign not allowed in core mode"));
1076 return;
1077 }
1078
1079 insn.insn = mep_cgen_assemble_insn
1080 (gas_cgen_cpu_desc, str, & insn.fields, insn.buffer, & errmsg);
1081
1082 if (!insn.insn)
1083 {
1084 as_bad ("%s", errmsg);
1085 return;
1086 }
1087 gas_cgen_finish_insn (insn.insn, insn.buffer,
1088 CGEN_FIELDS_BITSIZE (& insn.fields), 1, NULL);
1089 mep_check_for_disabled_registers (&insn);
1090 }
1091}
1092
1093valueT
1094md_section_align (segT segment, valueT size)
1095{
1096 int align = bfd_get_section_alignment (stdoutput, segment);
1097 return ((size + (1 << align) - 1) & (-1 << align));
1098}
1099
1100
1101symbolS *
1102md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
1103{
1104 return 0;
1105}
1106\f
1107/* Interface to relax_segment. */
1108
1109
1110const relax_typeS md_relax_table[] =
1111{
1112 /* The fields are:
1113 1) most positive reach of this state,
1114 2) most negative reach of this state,
1115 3) how many bytes this mode will have in the variable part of the frag
1116 4) which index into the table to try if we can't fit into this one. */
1117 /* Note that we use "beq" because "jmp" has a peculiarity - it cannot
1118 jump to addresses with any bits 27..24 set. So, we use beq as a
1119 17-bit pc-relative branch to avoid using jmp, just in case. */
1120
1121 /* 0 */ { 0, 0, 0, 0 }, /* unused */
1122 /* 1 */ { 0, 0, 0, 0 }, /* marker for "don't know yet" */
1123
1124 /* 2 */ { 2047, -2048, 0, 3 }, /* bsr12 */
1125 /* 3 */ { 0, 0, 2, 0 }, /* bsr16 */
1126
1127 /* 4 */ { 2047, -2048, 0, 5 }, /* bra */
1128 /* 5 */ { 65535, -65536, 2, 6 }, /* beq $0,$0 */
1129 /* 6 */ { 0, 0, 2, 0 }, /* jmp24 */
1130
1131 /* 7 */ { 65535, -65536, 0, 8 }, /* beqi */
1132 /* 8 */ { 0, 0, 4, 0 }, /* bnei/jmp */
1133
1134 /* 9 */ { 127, -128, 0, 10 }, /* beqz */
1135 /* 10 */ { 65535, -65536, 2, 11 }, /* beqi */
1136 /* 11 */ { 0, 0, 4, 0 }, /* bnei/jmp */
1137
1138 /* 12 */ { 65535, -65536, 0, 13 }, /* bnei */
1139 /* 13 */ { 0, 0, 4, 0 }, /* beqi/jmp */
1140
1141 /* 14 */ { 127, -128, 0, 15 }, /* bnez */
1142 /* 15 */ { 65535, -65536, 2, 16 }, /* bnei */
1143 /* 16 */ { 0, 0, 4, 0 }, /* beqi/jmp */
1144
1145 /* 17 */ { 65535, -65536, 0, 13 }, /* bgei */
1146 /* 18 */ { 0, 0, 4, 0 },
1147 /* 19 */ { 65535, -65536, 0, 13 }, /* blti */
1148 /* 20 */ { 0, 0, 4, 0 },
1149 /* 19 */ { 65535, -65536, 0, 13 }, /* bcpeq */
1150 /* 20 */ { 0, 0, 4, 0 },
1151 /* 19 */ { 65535, -65536, 0, 13 }, /* bcpne */
1152 /* 20 */ { 0, 0, 4, 0 },
1153 /* 19 */ { 65535, -65536, 0, 13 }, /* bcpat */
1154 /* 20 */ { 0, 0, 4, 0 },
1155 /* 19 */ { 65535, -65536, 0, 13 }, /* bcpaf */
1156 /* 20 */ { 0, 0, 4, 0 }
1157};
1158
1159/* Pseudo-values for 64 bit "insns" which are combinations of two 32
1160 bit insns. */
1161typedef enum {
1162 MEP_PSEUDO64_NONE,
1163 MEP_PSEUDO64_16BITCC,
1164 MEP_PSEUDO64_32BITCC,
1165} MepPseudo64Values;
1166
1167static struct {
1168 int insn;
1169 int growth;
1170 int insn_for_extern;
1171} subtype_mappings[] = {
1172 { 0, 0, 0 },
1173 { 0, 0, 0 },
1174 { MEP_INSN_BSR12, 0, MEP_INSN_BSR24 },
1175 { MEP_INSN_BSR24, 2, MEP_INSN_BSR24 },
1176 { MEP_INSN_BRA, 0, MEP_INSN_BRA },
1177 { MEP_INSN_BEQ, 2, MEP_INSN_BEQ },
1178 { MEP_INSN_JMP, 2, MEP_INSN_JMP },
1179 { MEP_INSN_BEQI, 0, MEP_INSN_BEQI },
1180 { -1, 4, MEP_PSEUDO64_32BITCC },
1181 { MEP_INSN_BEQZ, 0, MEP_INSN_BEQZ },
1182 { MEP_INSN_BEQI, 2, MEP_INSN_BEQI },
1183 { -1, 4, MEP_PSEUDO64_16BITCC },
1184 { MEP_INSN_BNEI, 0, MEP_INSN_BNEI },
1185 { -1, 4, MEP_PSEUDO64_32BITCC },
1186 { MEP_INSN_BNEZ, 0, MEP_INSN_BNEZ },
1187 { MEP_INSN_BNEI, 2, MEP_INSN_BNEI },
1188 { -1, 4, MEP_PSEUDO64_16BITCC },
1189 { MEP_INSN_BGEI, 0, MEP_INSN_BGEI },
1190 { -1, 4, MEP_PSEUDO64_32BITCC },
1191 { MEP_INSN_BLTI, 0, MEP_INSN_BLTI },
1192 { -1, 4, MEP_PSEUDO64_32BITCC },
1193 { MEP_INSN_BCPEQ, 0, MEP_INSN_BCPEQ },
1194 { -1, 4, MEP_PSEUDO64_32BITCC },
1195 { MEP_INSN_BCPNE, 0, MEP_INSN_BCPNE },
1196 { -1, 4, MEP_PSEUDO64_32BITCC },
1197 { MEP_INSN_BCPAT, 0, MEP_INSN_BCPAT },
1198 { -1, 4, MEP_PSEUDO64_32BITCC },
1199 { MEP_INSN_BCPAF, 0, MEP_INSN_BCPAF },
1200 { -1, 4, MEP_PSEUDO64_32BITCC }
1201};
1202#define NUM_MAPPINGS (sizeof (subtype_mappings) / sizeof (subtype_mappings[0]))
1203
1204void
1205mep_prepare_relax_scan (fragS *fragP, offsetT *aim, relax_substateT this_state)
1206{
1207 symbolS *symbolP = fragP->fr_symbol;
1208 if (symbolP && !S_IS_DEFINED (symbolP))
1209 *aim = 0;
1210 /* Adjust for MeP pcrel not being relative to the next opcode. */
1211 *aim += 2 + md_relax_table[this_state].rlx_length;
1212}
1213
1214static int
1215insn_to_subtype (int insn)
1216{
1217 unsigned int i;
1218 for (i=0; i<NUM_MAPPINGS; i++)
1219 if (insn == subtype_mappings[i].insn)
1220 return i;
1221 abort ();
1222}
1223
1224/* Return an initial guess of the length by which a fragment must grow
1225 to hold a branch to reach its destination. Also updates fr_type
1226 and fr_subtype as necessary.
1227
1228 Called just before doing relaxation. Any symbol that is now
1229 undefined will not become defined. The guess for fr_var is
1230 ACTUALLY the growth beyond fr_fix. Whatever we do to grow fr_fix
1231 or fr_var contributes to our returned value. Although it may not
1232 be explicit in the frag, pretend fr_var starts with a 0 value. */
1233
1234int
1235md_estimate_size_before_relax (fragS * fragP, segT segment)
1236{
1237 if (fragP->fr_subtype == 1)
1238 fragP->fr_subtype = insn_to_subtype (fragP->fr_cgen.insn->base->num);
1239
1240 if (S_GET_SEGMENT (fragP->fr_symbol) != segment)
1241 {
1242 int new_insn;
1243
1244 new_insn = subtype_mappings[fragP->fr_subtype].insn_for_extern;
1245 fragP->fr_subtype = insn_to_subtype (new_insn);
1246 }
1247
1248 if (MEP_VLIW && ! MEP_VLIW64
1249 && (bfd_get_section_flags (stdoutput, segment) & SEC_MEP_VLIW))
1250 {
1251 /* Use 32 bit branches for vliw32 so the vliw word is not split. */
1252 switch (fragP->fr_cgen.insn->base->num)
1253 {
1254 case MEP_INSN_BSR12:
1255 fragP->fr_subtype = insn_to_subtype
1256 (subtype_mappings[fragP->fr_subtype].insn_for_extern);
1257 break;
1258 case MEP_INSN_BEQZ:
1259 fragP->fr_subtype ++;
1260 break;
1261 case MEP_INSN_BNEZ:
1262 fragP->fr_subtype ++;
1263 break;
1264 }
1265 }
1266
1267 if (fragP->fr_cgen.insn->base
1268 && fragP->fr_cgen.insn->base->num
1269 != subtype_mappings[fragP->fr_subtype].insn)
1270 {
1271 int new_insn= subtype_mappings[fragP->fr_subtype].insn;
1272 if (new_insn != -1)
1273 {
1274 fragP->fr_cgen.insn = (fragP->fr_cgen.insn
1275 - fragP->fr_cgen.insn->base->num
1276 + new_insn);
1277 }
1278 }
1279
1280 return subtype_mappings[fragP->fr_subtype].growth;
1281}
1282
1283/* *fragP has been relaxed to its final size, and now needs to have
1284 the bytes inside it modified to conform to the new size.
1285
1286 Called after relaxation is finished.
1287 fragP->fr_type == rs_machine_dependent.
1288 fragP->fr_subtype is the subtype of what the address relaxed to. */
1289
1290static int
1291target_address_for (fragS *frag)
1292{
1293 int rv = frag->fr_offset;
1294 symbolS *sym = frag->fr_symbol;
1295
1296 if (sym)
1297 rv += S_GET_VALUE (sym);
1298
1299 return rv;
1300}
1301
1302void
1303md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED,
1304 segT sec ATTRIBUTE_UNUSED,
1305 fragS *fragP)
1306{
1307 int addend, rn, bit = 0;
1308 int operand;
1309 int where = fragP->fr_opcode - fragP->fr_literal;
1310 int e = target_big_endian ? 0 : 1;
1311
1312 addend = target_address_for (fragP) - (fragP->fr_address + where);
1313
1314 if (subtype_mappings[fragP->fr_subtype].insn == -1)
1315 {
1316 fragP->fr_fix += subtype_mappings[fragP->fr_subtype].growth;
1317 switch (subtype_mappings[fragP->fr_subtype].insn_for_extern)
1318 {
1319 case MEP_PSEUDO64_16BITCC:
1320 fragP->fr_opcode[1^e] = ((fragP->fr_opcode[1^e] & 1) ^ 1) | 0x06;
1321 fragP->fr_opcode[2^e] = 0xd8;
1322 fragP->fr_opcode[3^e] = 0x08;
1323 fragP->fr_opcode[4^e] = 0;
1324 fragP->fr_opcode[5^e] = 0;
1325 where += 2;
1326 break;
1327 case MEP_PSEUDO64_32BITCC:
1328 if (fragP->fr_opcode[0^e] & 0x10)
1329 fragP->fr_opcode[1^e] ^= 0x01;
1330 else
1331 fragP->fr_opcode[1^e] ^= 0x04;
1332 fragP->fr_opcode[2^e] = 0;
1333 fragP->fr_opcode[3^e] = 4;
1334 fragP->fr_opcode[4^e] = 0xd8;
1335 fragP->fr_opcode[5^e] = 0x08;
1336 fragP->fr_opcode[6^e] = 0;
1337 fragP->fr_opcode[7^e] = 0;
1338 where += 4;
1339 break;
1340 default:
1341 abort ();
1342 }
1343 fragP->fr_cgen.insn = (fragP->fr_cgen.insn
1344 - fragP->fr_cgen.insn->base->num
1345 + MEP_INSN_JMP);
1346 operand = MEP_OPERAND_PCABS24A2;
1347 }
1348 else
1349 switch (fragP->fr_cgen.insn->base->num)
1350 {
1351 case MEP_INSN_BSR12:
1352 fragP->fr_opcode[0^e] = 0xb0 | ((addend >> 8) & 0x0f);
1353 fragP->fr_opcode[1^e] = 0x01 | (addend & 0xfe);
1354 operand = MEP_OPERAND_PCREL12A2;
1355 break;
1356
1357 case MEP_INSN_BSR24:
1358 fragP->fr_fix += 2;
1359 fragP->fr_opcode[0^e] = 0xd8 | ((addend >> 5) & 0x07);
1360 fragP->fr_opcode[1^e] = 0x09 | ((addend << 3) & 0xf0);
1361 fragP->fr_opcode[2^e] = 0x00 | ((addend >>16) & 0xff);
1362 fragP->fr_opcode[3^e] = 0x00 | ((addend >> 8) & 0xff);
1363 operand = MEP_OPERAND_PCREL24A2;
1364 break;
1365
1366 case MEP_INSN_BRA:
1367 fragP->fr_opcode[0^e] = 0xb0 | ((addend >> 8) & 0x0f);
1368 fragP->fr_opcode[1^e] = 0x00 | (addend & 0xfe);
1369 operand = MEP_OPERAND_PCREL12A2;
1370 break;
1371
1372 case MEP_INSN_BEQ:
1373 /* The default relax_frag doesn't change the state if there is no
1374 growth, so we must manually handle converting out-of-range BEQ
1375 instructions to JMP. */
1376 if (addend <= 65535 && addend >= -65536)
1377 {
1378 fragP->fr_fix += 2;
1379 fragP->fr_opcode[0^e] = 0xe0;
1380 fragP->fr_opcode[1^e] = 0x01;
1381 fragP->fr_opcode[2^e] = 0x00 | ((addend >> 9) & 0xff);
1382 fragP->fr_opcode[3^e] = 0x00 | ((addend >> 1) & 0xff);
1383 operand = MEP_OPERAND_PCREL17A2;
1384 break;
1385 }
1386 /* ...FALLTHROUGH... */
1387
1388 case MEP_INSN_JMP:
1389 addend = target_address_for (fragP);
1390 fragP->fr_fix += 2;
1391 fragP->fr_opcode[0^e] = 0xd8 | ((addend >> 5) & 0x07);
1392 fragP->fr_opcode[1^e] = 0x08 | ((addend << 3) & 0xf0);
1393 fragP->fr_opcode[2^e] = 0x00 | ((addend >>16) & 0xff);
1394 fragP->fr_opcode[3^e] = 0x00 | ((addend >> 8) & 0xff);
1395 operand = MEP_OPERAND_PCABS24A2;
1396 break;
1397
1398 case MEP_INSN_BNEZ:
1399 bit = 1;
1400 case MEP_INSN_BEQZ:
1401 fragP->fr_opcode[1^e] = bit | (addend & 0xfe);
1402 operand = MEP_OPERAND_PCREL8A2;
1403 break;
1404
1405 case MEP_INSN_BNEI:
1406 bit = 4;
1407 case MEP_INSN_BEQI:
1408 if (subtype_mappings[fragP->fr_subtype].growth)
1409 {
1410 fragP->fr_fix += subtype_mappings[fragP->fr_subtype].growth;
1411 rn = fragP->fr_opcode[0^e] & 0x0f;
1412 fragP->fr_opcode[0^e] = 0xe0 | rn;
1413 fragP->fr_opcode[1^e] = bit;
1414 }
1415 fragP->fr_opcode[2^e] = 0x00 | ((addend >> 9) & 0xff);
1416 fragP->fr_opcode[3^e] = 0x00 | ((addend >> 1) & 0xff);
1417 operand = MEP_OPERAND_PCREL17A2;
1418 break;
1419
1420 case MEP_INSN_BLTI:
1421 case MEP_INSN_BGEI:
1422 case MEP_INSN_BCPEQ:
1423 case MEP_INSN_BCPNE:
1424 case MEP_INSN_BCPAT:
1425 case MEP_INSN_BCPAF:
1426 /* No opcode change needed, just operand. */
1427 fragP->fr_opcode[2^e] = (addend >> 9) & 0xff;
1428 fragP->fr_opcode[3^e] = (addend >> 1) & 0xff;
1429 operand = MEP_OPERAND_PCREL17A2;
1430 break;
1431
1432 default:
1433 abort ();
1434 }
1435
1436 if (S_GET_SEGMENT (fragP->fr_symbol) != sec
1437 || operand == MEP_OPERAND_PCABS24A2)
1438 {
1439 assert (fragP->fr_cgen.insn != 0);
1440 gas_cgen_record_fixup (fragP,
1441 where,
1442 fragP->fr_cgen.insn,
1443 (fragP->fr_fix - where) * 8,
1444 cgen_operand_lookup_by_num (gas_cgen_cpu_desc,
1445 operand),
1446 fragP->fr_cgen.opinfo,
1447 fragP->fr_symbol, fragP->fr_offset);
1448 }
1449}
1450
1451\f
1452/* Functions concerning relocs. */
1453
1454void
1455mep_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
1456{
1457 /* If we already know the fixup value, adjust it in the same
1458 way that the linker would have done. */
1459 if (fixP->fx_addsy == 0)
1460 switch (fixP->fx_cgen.opinfo)
1461 {
1462 case BFD_RELOC_MEP_LOW16:
1463 *valP = ((long)(*valP & 0xffff)) << 16 >> 16;
1464 break;
1465 case BFD_RELOC_MEP_HI16U:
1466 *valP >>= 16;
1467 break;
1468 case BFD_RELOC_MEP_HI16S:
1469 *valP = (*valP + 0x8000) >> 16;
1470 break;
1471 }
1472
1473 /* Now call cgen's md_aply_fix. */
1474 gas_cgen_md_apply_fix (fixP, valP, seg);
1475}
1476
1477long
1478md_pcrel_from_section (fixS *fixP, segT sec)
1479{
1480 if (fixP->fx_addsy != (symbolS *) NULL
1481 && (! S_IS_DEFINED (fixP->fx_addsy)
1482 || S_GET_SEGMENT (fixP->fx_addsy) != sec))
1483 /* The symbol is undefined (or is defined but not in this section).
1484 Let the linker figure it out. */
1485 return 0;
1486
1487 /* Return the address of the opcode - cgen adjusts for opcode size
1488 itself, to be consistent with the disassembler, which must do
1489 so. */
1490 return fixP->fx_where + fixP->fx_frag->fr_address;
1491}
1492
1493/* Return the bfd reloc type for OPERAND of INSN at fixup FIXP.
1494 Returns BFD_RELOC_NONE if no reloc type can be found.
1495 *FIXP may be modified if desired. */
1496
1497#if defined (__STDC__) || defined (ALMOST_STDC) || defined (HAVE_STRINGIZE)
1498#define MAP(n) case MEP_OPERAND_##n: return BFD_RELOC_MEP_##n;
1499#else
1500#define MAP(n) case MEP_OPERAND_/**/n: return BFD_RELOC_MEP_/**/n;
1501#endif
1502
1503bfd_reloc_code_real_type
1504md_cgen_lookup_reloc (const CGEN_INSN *insn ATTRIBUTE_UNUSED,
1505 const CGEN_OPERAND *operand,
1506 fixS *fixP)
1507{
1508 enum bfd_reloc_code_real reloc = fixP->fx_cgen.opinfo;
1509 static char printed[MEP_OPERAND_MAX] = { 0 };
1510
1511 /* If there's a reloc here, it's because the parser saw a %foo() and
1512 is giving us the correct reloc to use, or because we converted to
1513 a different size reloc below and want to avoid "converting" more
1514 than once. */
1515 if (reloc && reloc != BFD_RELOC_NONE)
1516 return reloc;
1517
1518 switch (operand->type)
1519 {
1520 MAP (PCREL8A2); /* beqz */
1521 MAP (PCREL12A2); /* bsr16 */
1522 MAP (PCREL17A2); /* beqi */
1523 MAP (PCREL24A2); /* bsr24 */
1524 MAP (PCABS24A2); /* jmp */
1525 MAP (UIMM24); /* mov */
1526 MAP (ADDR24A4); /* sw/lw */
1527
1528 /* The rest of the relocs should be generated by the parser,
1529 for things such as %tprel(), etc. */
1530 case MEP_OPERAND_SIMM16:
1531#ifdef OBJ_COMPLEX_RELC
1532 /* coalescing this into RELOC_MEP_16 is actually a bug,
1533 since it's a signed operand. let the relc code handle it. */
1534 return BFD_RELOC_RELC;
1535#endif
1536
1537 case MEP_OPERAND_UIMM16:
1538 case MEP_OPERAND_SDISP16:
1539 case MEP_OPERAND_CODE16:
1540 fixP->fx_where += 2;
1541 /* to avoid doing the above add twice */
1542 fixP->fx_cgen.opinfo = BFD_RELOC_MEP_16;
1543 return BFD_RELOC_MEP_16;
1544
1545 default:
1546#ifdef OBJ_COMPLEX_RELC
1547 /* this is not an error, yet.
1548 pass it to the linker. */
1549 return BFD_RELOC_RELC;
1550#endif
1551 if (printed[operand->type])
1552 return BFD_RELOC_NONE;
1553 printed[operand->type] = 1;
1554
1555 as_bad_where (fixP->fx_file, fixP->fx_line,
1556 _("Don't know how to relocate plain operands of type %s"),
1557 operand->name);
1558
1559 /* Print some helpful hints for the user. */
1560 switch (operand->type)
1561 {
1562 case MEP_OPERAND_UDISP7:
1563 case MEP_OPERAND_UDISP7A2:
1564 case MEP_OPERAND_UDISP7A4:
1565 as_bad_where (fixP->fx_file, fixP->fx_line,
1566 _("Perhaps you are missing %%tpoff()?"));
1567 break;
1568 default:
1569 break;
1570 }
1571 return BFD_RELOC_NONE;
1572 }
1573}
1574
1575/* Called while parsing an instruction to create a fixup.
1576 We need to check for HI16 relocs and queue them up for later sorting. */
1577
1578fixS *
1579mep_cgen_record_fixup_exp (fragS *frag,
1580 int where,
1581 const CGEN_INSN *insn,
1582 int length,
1583 const CGEN_OPERAND *operand,
1584 int opinfo,
1585 expressionS *exp)
1586{
1587 fixS * fixP = gas_cgen_record_fixup_exp (frag, where, insn, length,
1588 operand, opinfo, exp);
1589 return fixP;
1590}
1591
1592/* Return BFD reloc type from opinfo field in a fixS.
1593 It's tricky using fx_r_type in mep_frob_file because the values
1594 are BFD_RELOC_UNUSED + operand number. */
1595#define FX_OPINFO_R_TYPE(f) ((f)->fx_cgen.opinfo)
1596
1597/* Sort any unmatched HI16 relocs so that they immediately precede
1598 the corresponding LO16 reloc. This is called before md_apply_fix and
1599 tc_gen_reloc. */
1600
1601void
1602mep_frob_file ()
1603{
1604 struct mep_hi_fixup * l;
1605
1606 for (l = mep_hi_fixup_list; l != NULL; l = l->next)
1607 {
1608 segment_info_type * seginfo;
1609 int pass;
1610
1611 assert (FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_HI16
1612 || FX_OPINFO_R_TYPE (l->fixp) == BFD_RELOC_LO16);
1613
1614 /* Check quickly whether the next fixup happens to be a matching low. */
1615 if (l->fixp->fx_next != NULL
1616 && FX_OPINFO_R_TYPE (l->fixp->fx_next) == BFD_RELOC_LO16
1617 && l->fixp->fx_addsy == l->fixp->fx_next->fx_addsy
1618 && l->fixp->fx_offset == l->fixp->fx_next->fx_offset)
1619 continue;
1620
1621 /* Look through the fixups for this segment for a matching
1622 `low'. When we find one, move the high just in front of it.
1623 We do this in two passes. In the first pass, we try to find
1624 a unique `low'. In the second pass, we permit multiple
1625 high's relocs for a single `low'. */
1626 seginfo = seg_info (l->seg);
1627 for (pass = 0; pass < 2; pass++)
1628 {
1629 fixS * f;
1630 fixS * prev;
1631
1632 prev = NULL;
1633 for (f = seginfo->fix_root; f != NULL; f = f->fx_next)
1634 {
1635 /* Check whether this is a `low' fixup which matches l->fixp. */
1636 if (FX_OPINFO_R_TYPE (f) == BFD_RELOC_LO16
1637 && f->fx_addsy == l->fixp->fx_addsy
1638 && f->fx_offset == l->fixp->fx_offset
1639 && (pass == 1
1640 || prev == NULL
1641 || (FX_OPINFO_R_TYPE (prev) != BFD_RELOC_HI16)
1642 || prev->fx_addsy != f->fx_addsy
1643 || prev->fx_offset != f->fx_offset))
1644 {
1645 fixS ** pf;
1646
1647 /* Move l->fixp before f. */
1648 for (pf = &seginfo->fix_root;
1649 * pf != l->fixp;
1650 pf = & (* pf)->fx_next)
1651 assert (* pf != NULL);
1652
1653 * pf = l->fixp->fx_next;
1654
1655 l->fixp->fx_next = f;
1656 if (prev == NULL)
1657 seginfo->fix_root = l->fixp;
1658 else
1659 prev->fx_next = l->fixp;
1660
1661 break;
1662 }
1663
1664 prev = f;
1665 }
1666
1667 if (f != NULL)
1668 break;
1669
1670 if (pass == 1)
1671 as_warn_where (l->fixp->fx_file, l->fixp->fx_line,
1672 _("Unmatched high relocation"));
1673 }
1674 }
1675}
1676
1677/* See whether we need to force a relocation into the output file. */
1678
1679int
1680mep_force_relocation (fixS *fixp)
1681{
1682 if ( fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
1683 || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
1684 return 1;
1685
1686 /* Allow branches to global symbols to be resolved at assembly time.
1687 This is consistent with way relaxable branches are handled, since
1688 branches to both global and local symbols are relaxed. It also
1689 corresponds to the assumptions made in md_pcrel_from_section. */
1690 return S_FORCE_RELOC (fixp->fx_addsy, !fixp->fx_pcrel);
1691}
1692\f
1693/* Write a value out to the object file, using the appropriate endianness. */
1694
1695void
1696md_number_to_chars (char *buf, valueT val, int n)
1697{
1698 if (target_big_endian)
1699 number_to_chars_bigendian (buf, val, n);
1700 else
1701 number_to_chars_littleendian (buf, val, n);
1702}
1703
280d71bf
DB
1704char *
1705md_atof (int type, char *litP, int *sizeP)
1706{
499ac353 1707 return ieee_md_atof (type, litP, sizeP, TRUE);
280d71bf
DB
1708}
1709
280d71bf
DB
1710bfd_boolean
1711mep_fix_adjustable (fixS *fixP)
1712{
1713 bfd_reloc_code_real_type reloc_type;
1714
1715 if ((int) fixP->fx_r_type >= (int) BFD_RELOC_UNUSED)
1716 {
1717 const CGEN_INSN *insn = NULL;
1718 int opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED;
1719 const CGEN_OPERAND *operand
1720 = cgen_operand_lookup_by_num(gas_cgen_cpu_desc, opindex);
1721 reloc_type = md_cgen_lookup_reloc (insn, operand, fixP);
1722 }
1723 else
1724 reloc_type = fixP->fx_r_type;
1725
1726 if (fixP->fx_addsy == NULL)
1727 return 1;
1728
1729 /* Prevent all adjustments to global symbols. */
1730 if (S_IS_EXTERNAL (fixP->fx_addsy))
1731 return 0;
1732
1733 if (S_IS_WEAK (fixP->fx_addsy))
1734 return 0;
1735
1736 /* We need the symbol name for the VTABLE entries */
1737 if (reloc_type == BFD_RELOC_VTABLE_INHERIT
1738 || reloc_type == BFD_RELOC_VTABLE_ENTRY)
1739 return 0;
1740
1741 return 1;
1742}
1743
01e1a5bc 1744bfd_vma
280d71bf
DB
1745mep_elf_section_letter (int letter, char **ptrmsg)
1746{
1747 if (letter == 'v')
1748 return SHF_MEP_VLIW;
1749
1750 *ptrmsg = _("Bad .section directive: want a,v,w,x,M,S in string");
1751 return 0;
1752}
1753
1754flagword
01e1a5bc 1755mep_elf_section_flags (flagword flags, bfd_vma attr, int type ATTRIBUTE_UNUSED)
280d71bf
DB
1756{
1757 if (attr & SHF_MEP_VLIW)
1758 flags |= SEC_MEP_VLIW;
1759 return flags;
1760}
1761
1762/* In vliw mode, the default section is .vtext. We have to be able
1763 to switch into .vtext using only the .vtext directive. */
1764
1765static segT
1766mep_vtext_section (void)
1767{
1768 static segT vtext_section;
1769
1770 if (! vtext_section)
1771 {
1772 flagword applicable = bfd_applicable_section_flags (stdoutput);
1773 vtext_section = subseg_new (VTEXT_SECTION_NAME, 0);
1774 bfd_set_section_flags (stdoutput, vtext_section,
1775 applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC
1776 | SEC_CODE | SEC_READONLY
1777 | SEC_MEP_VLIW));
1778 }
1779
1780 return vtext_section;
1781}
1782
1783static void
1784mep_s_vtext (int ignore ATTRIBUTE_UNUSED)
1785{
1786 int temp;
1787
1788 /* Record previous_section and previous_subsection. */
1789 obj_elf_section_change_hook ();
1790
1791 temp = get_absolute_expression ();
1792 subseg_set (mep_vtext_section (), (subsegT) temp);
1793 demand_empty_rest_of_line ();
1794}
1795
1796static void
1797mep_switch_to_core_mode (int dummy ATTRIBUTE_UNUSED)
1798{
1799 mep_process_saved_insns ();
1800 pluspresent = 0;
1801 mode = CORE;
1802}
1803
1804static void
1805mep_switch_to_vliw_mode (int dummy ATTRIBUTE_UNUSED)
1806{
1807 if (! MEP_VLIW)
1808 as_bad (_(".vliw unavailable when VLIW is disabled."));
1809 mode = VLIW;
1810 /* Switch into .vtext here too. */
1811 /* mep_s_vtext(); */
1812}
1813
1814/* This is an undocumented pseudo-op used to disable gas's
1815 "disabled_registers" check. Used for code which checks for those
1816 registers at runtime. */
1817static void
1818mep_noregerr (int i ATTRIBUTE_UNUSED)
1819{
1820 allow_disabled_registers = 1;
1821}
1822
1823/* mep_unrecognized_line: This is called when a line that can't be parsed
1824 is encountered. We use it to check for a leading '+' sign which indicates
1825 that the current instruction is a coprocessor instruction that is to be
1826 parallelized with a previous core insn. This function accepts the '+' and
1827 rejects all other characters that might indicate garbage at the beginning
1828 of the line. The '+' character gets lost as the calling loop continues,
1829 so we need to indicate that we saw it. */
1830
1831int
1832mep_unrecognized_line (int ch)
1833{
1834 switch (ch)
1835 {
1836 case '+':
1837 pluspresent = 1;
1838 return 1; /* '+' indicates an instruction to be parallelized. */
1839 default:
1840 return 0; /* If it's not a '+', the line can't be parsed. */
1841 }
1842}
1843
1844void
1845mep_cleanup (void)
1846{
1847 /* Take care of any insns left to be parallelized when the file ends.
1848 This is mainly here to handle the case where the file ends with an
1849 insn preceeded by a + or the file ends unexpectedly. */
1850 if (mode == VLIW)
1851 mep_process_saved_insns ();
1852}
1853
1854int
1855mep_flush_pending_output (void)
1856{
1857 if (mode == VLIW)
1858 {
1859 mep_process_saved_insns ();
1860 pluspresent = 0;
1861 }
1862
1863 return 1;
1864}
This page took 0.17789 seconds and 4 git commands to generate.