]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - cpu/mep.opc
[gdb/exp] Fix cast handling for indirection
[thirdparty/binutils-gdb.git] / cpu / mep.opc
CommitLineData
dc15e575
NC
1/* MeP opcode support. -*- C -*-
2 Copyright 2011 Free Software Foundation, Inc.
3
4 Contributed by Red Hat Inc;
5
6 This file is part of the GNU Binutils.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 MA 02110-1301, USA. */
22
23/* -- opc.h */
24
25#undef CGEN_DIS_HASH_SIZE
26#define CGEN_DIS_HASH_SIZE 1
27
28#undef CGEN_DIS_HASH
29#define CGEN_DIS_HASH(buffer, insn) 0
30
31#define CGEN_VERBOSE_ASSEMBLER_ERRORS
32
33typedef struct
34{
35 char * name;
36 int config_enum;
37 unsigned cpu_flag;
38 int big_endian;
39 int vliw_bits;
40 CGEN_ATTR_VALUE_BITSET_TYPE cop16_isa;
41 CGEN_ATTR_VALUE_BITSET_TYPE cop32_isa;
42 CGEN_ATTR_VALUE_BITSET_TYPE cop48_isa;
43 CGEN_ATTR_VALUE_BITSET_TYPE cop64_isa;
44 CGEN_ATTR_VALUE_BITSET_TYPE cop_isa;
45 CGEN_ATTR_VALUE_BITSET_TYPE core_isa;
46 unsigned int option_mask;
47} mep_config_map_struct;
48
49extern mep_config_map_struct mep_config_map[];
50extern int mep_config_index;
51
52extern void init_mep_all_core_isas_mask (void);
53extern void init_mep_all_cop_isas_mask (void);
54extern CGEN_ATTR_VALUE_BITSET_TYPE mep_cop_isa (void);
55
56#define MEP_CONFIG (mep_config_map[mep_config_index].config_enum)
57#define MEP_CPU (mep_config_map[mep_config_index].cpu_flag)
58#define MEP_OMASK (mep_config_map[mep_config_index].option_mask)
59#define MEP_VLIW (mep_config_map[mep_config_index].vliw_bits > 0)
60#define MEP_VLIW32 (mep_config_map[mep_config_index].vliw_bits == 32)
61#define MEP_VLIW64 (mep_config_map[mep_config_index].vliw_bits == 64)
62#define MEP_COP16_ISA (mep_config_map[mep_config_index].cop16_isa)
63#define MEP_COP32_ISA (mep_config_map[mep_config_index].cop32_isa)
64#define MEP_COP48_ISA (mep_config_map[mep_config_index].cop48_isa)
65#define MEP_COP64_ISA (mep_config_map[mep_config_index].cop64_isa)
66#define MEP_COP_ISA (mep_config_map[mep_config_index].cop_isa)
67#define MEP_CORE_ISA (mep_config_map[mep_config_index].core_isa)
68
69/* begin-cop-ip-supported-defines */
70#define MEP_IVC2_SUPPORTED 1
71/* end-cop-ip-supported-defines */
72
73extern int mep_insn_supported_by_isa (const CGEN_INSN *, CGEN_ATTR_VALUE_BITSET_TYPE *);
74
75/* A mask for all ISAs executed by the core. */
76#define MEP_ALL_CORE_ISAS_MASK mep_all_core_isas_mask
77extern CGEN_ATTR_VALUE_BITSET_TYPE mep_all_core_isas_mask;
78
79#define MEP_INSN_CORE_P(insn) ( \
80 init_mep_all_core_isas_mask (), \
81 mep_insn_supported_by_isa (insn, & MEP_ALL_CORE_ISAS_MASK) \
82)
83
84/* A mask for all ISAs executed by a VLIW coprocessor. */
3e8b13bf 85#define MEP_ALL_COP_ISAS_MASK mep_all_cop_isas_mask
dc15e575
NC
86extern CGEN_ATTR_VALUE_BITSET_TYPE mep_all_cop_isas_mask;
87
88#define MEP_INSN_COP_P(insn) ( \
89 init_mep_all_cop_isas_mask (), \
90 mep_insn_supported_by_isa (insn, & MEP_ALL_COP_ISAS_MASK) \
91)
92
93extern int mep_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
94extern int mep_cgen_insn_supported_asm (CGEN_CPU_DESC, const CGEN_INSN *);
95
96/* -- asm.c */
97
98#include "elf/mep.h"
99
100#define CGEN_VALIDATE_INSN_SUPPORTED
101#define mep_cgen_insn_supported mep_cgen_insn_supported_asm
102
103 const char * parse_csrn (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
104 const char * parse_tpreg (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
105 const char * parse_spreg (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
106 const char * parse_mep_align (CGEN_CPU_DESC, const char **, enum cgen_operand_type, long *);
107 const char * parse_mep_alignu (CGEN_CPU_DESC, const char **, enum cgen_operand_type, unsigned long *);
108static const char * parse_signed16 (CGEN_CPU_DESC, const char **, int, long *);
109static const char * parse_signed16_range (CGEN_CPU_DESC, const char **, int, long *) ATTRIBUTE_UNUSED;
110static const char * parse_unsigned16 (CGEN_CPU_DESC, const char **, int, unsigned long *);
111static const char * parse_unsigned16_range (CGEN_CPU_DESC, const char **, int, unsigned long *) ATTRIBUTE_UNUSED;
112static const char * parse_lo16 (CGEN_CPU_DESC, const char **, int, long *, long);
113static const char * parse_unsigned7 (CGEN_CPU_DESC, const char **, enum cgen_operand_type, unsigned long *);
114static const char * parse_zero (CGEN_CPU_DESC, const char **, int, long *);
115
116const char *
117parse_csrn (CGEN_CPU_DESC cd, const char **strp,
118 CGEN_KEYWORD *keyword_table, long *field)
119{
120 const char *err;
121 unsigned long value;
122
123 err = cgen_parse_keyword (cd, strp, keyword_table, field);
124 if (!err)
125 return NULL;
126
127 err = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CSRN_IDX, & value);
128 if (err)
129 return err;
130 *field = value;
131 return NULL;
132}
133
134/* begin-cop-ip-parse-handlers */
135static const char *
136parse_ivc2_cr (CGEN_CPU_DESC,
137 const char **,
138 CGEN_KEYWORD *,
139 long *) ATTRIBUTE_UNUSED;
140static const char *
141parse_ivc2_cr (CGEN_CPU_DESC cd,
142 const char **strp,
143 CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
144 long *field)
145{
146 return cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_cr_ivc2, field);
147}
148static const char *
149parse_ivc2_ccr (CGEN_CPU_DESC,
150 const char **,
151 CGEN_KEYWORD *,
152 long *) ATTRIBUTE_UNUSED;
153static const char *
154parse_ivc2_ccr (CGEN_CPU_DESC cd,
155 const char **strp,
156 CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
157 long *field)
158{
159 return cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_ccr_ivc2, field);
160}
161/* end-cop-ip-parse-handlers */
162
163const char *
164parse_tpreg (CGEN_CPU_DESC cd, const char ** strp,
165 CGEN_KEYWORD *keyword_table, long *field)
166{
167 const char *err;
168
169 err = cgen_parse_keyword (cd, strp, keyword_table, field);
170 if (err)
171 return err;
172 if (*field != 13)
173 return _("Only $tp or $13 allowed for this opcode");
174 return NULL;
175}
176
177const char *
178parse_spreg (CGEN_CPU_DESC cd, const char ** strp,
179 CGEN_KEYWORD *keyword_table, long *field)
180{
181 const char *err;
182
183 err = cgen_parse_keyword (cd, strp, keyword_table, field);
184 if (err)
185 return err;
186 if (*field != 15)
187 return _("Only $sp or $15 allowed for this opcode");
188 return NULL;
189}
190
191const char *
192parse_mep_align (CGEN_CPU_DESC cd, const char ** strp,
193 enum cgen_operand_type type, long *field)
194{
195 long lsbs = 0;
196 const char *err;
197
198 switch (type)
199 {
200 case MEP_OPERAND_PCREL8A2:
201 case MEP_OPERAND_PCREL12A2:
202 case MEP_OPERAND_PCREL17A2:
203 case MEP_OPERAND_PCREL24A2:
204 err = cgen_parse_signed_integer (cd, strp, type, field);
205 break;
206 case MEP_OPERAND_PCABS24A2:
207 case MEP_OPERAND_UDISP7:
208 case MEP_OPERAND_UDISP7A2:
209 case MEP_OPERAND_UDISP7A4:
210 case MEP_OPERAND_UIMM7A4:
211 case MEP_OPERAND_ADDR24A4:
212 err = cgen_parse_unsigned_integer (cd, strp, type, (unsigned long *) field);
213 break;
214 default:
215 abort();
216 }
217 if (err)
218 return err;
219 switch (type)
220 {
221 case MEP_OPERAND_UDISP7:
222 lsbs = 0;
223 break;
224 case MEP_OPERAND_PCREL8A2:
225 case MEP_OPERAND_PCREL12A2:
226 case MEP_OPERAND_PCREL17A2:
227 case MEP_OPERAND_PCREL24A2:
228 case MEP_OPERAND_PCABS24A2:
229 case MEP_OPERAND_UDISP7A2:
230 lsbs = *field & 1;
231 break;
232 case MEP_OPERAND_UDISP7A4:
233 case MEP_OPERAND_UIMM7A4:
234 case MEP_OPERAND_ADDR24A4:
235 lsbs = *field & 3;
236 break;
237 lsbs = *field & 7;
238 break;
239 default:
240 /* Safe assumption? */
241 abort ();
242 }
243 if (lsbs)
244 return "Value is not aligned enough";
245 return NULL;
246}
247
248const char *
249parse_mep_alignu (CGEN_CPU_DESC cd, const char ** strp,
250 enum cgen_operand_type type, unsigned long *field)
251{
252 return parse_mep_align (cd, strp, type, (long *) field);
253}
254
255
256/* Handle %lo(), %tpoff(), %sdaoff(), %hi(), and other signed
257 constants in a signed context. */
258
259static const char *
260parse_signed16 (CGEN_CPU_DESC cd,
261 const char **strp,
262 int opindex,
263 long *valuep)
264{
265 return parse_lo16 (cd, strp, opindex, valuep, 1);
266}
267
268static const char *
269parse_lo16 (CGEN_CPU_DESC cd,
270 const char **strp,
271 int opindex,
272 long *valuep,
273 long signedp)
274{
275 const char *errmsg;
276 enum cgen_parse_operand_result result_type;
277 bfd_vma value;
278
279 if (strncasecmp (*strp, "%lo(", 4) == 0)
280 {
281 *strp += 4;
282 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_LOW16,
283 & result_type, & value);
284 if (**strp != ')')
285 return _("missing `)'");
286 ++*strp;
287 if (errmsg == NULL
288 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
289 value &= 0xffff;
290 if (signedp)
291 *valuep = (long)(short) value;
292 else
293 *valuep = value;
294 return errmsg;
295 }
296
297 if (strncasecmp (*strp, "%hi(", 4) == 0)
298 {
299 *strp += 4;
300 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16S,
301 & result_type, & value);
302 if (**strp != ')')
303 return _("missing `)'");
304 ++*strp;
305 if (errmsg == NULL
306 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
307 value = (value + 0x8000) >> 16;
308 *valuep = value;
309 return errmsg;
310 }
311
312 if (strncasecmp (*strp, "%uhi(", 5) == 0)
313 {
314 *strp += 5;
315 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16U,
316 & result_type, & value);
317 if (**strp != ')')
318 return _("missing `)'");
319 ++*strp;
320 if (errmsg == NULL
321 && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
322 value = value >> 16;
323 *valuep = value;
324 return errmsg;
325 }
326
327 if (strncasecmp (*strp, "%sdaoff(", 8) == 0)
328 {
329 *strp += 8;
330 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_GPREL,
331 NULL, & value);
332 if (**strp != ')')
333 return _("missing `)'");
334 ++*strp;
335 *valuep = value;
336 return errmsg;
337 }
338
339 if (strncasecmp (*strp, "%tpoff(", 7) == 0)
340 {
341 *strp += 7;
342 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_TPREL,
343 NULL, & value);
344 if (**strp != ')')
345 return _("missing `)'");
346 ++*strp;
347 *valuep = value;
348 return errmsg;
349 }
350
351 if (**strp == '%')
f757c5ca 352 /* xgettext:no-c-format */
dc15e575
NC
353 return _("invalid %function() here");
354
355 return cgen_parse_signed_integer (cd, strp, opindex, valuep);
356}
357
358static const char *
359parse_unsigned16 (CGEN_CPU_DESC cd,
360 const char **strp,
361 int opindex,
362 unsigned long *valuep)
363{
364 return parse_lo16 (cd, strp, opindex, (long *) valuep, 0);
365}
366
367static const char *
368parse_signed16_range (CGEN_CPU_DESC cd,
369 const char **strp,
370 int opindex,
371 signed long *valuep)
372{
373 const char *errmsg = 0;
374 signed long value;
375
376 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
377 if (errmsg)
378 return errmsg;
379
380 if (value < -32768 || value > 32767)
381 return _("Immediate is out of range -32768 to 32767");
382
383 *valuep = value;
384 return 0;
385}
386
387static const char *
388parse_unsigned16_range (CGEN_CPU_DESC cd,
389 const char **strp,
390 int opindex,
391 unsigned long *valuep)
392{
393 const char *errmsg = 0;
394 unsigned long value;
395
396 errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
397 if (errmsg)
398 return errmsg;
399
400 if (value > 65535)
401 return _("Immediate is out of range 0 to 65535");
402
403 *valuep = value;
404 return 0;
405}
406
407/* A special case of parse_signed16 which accepts only the value zero. */
408
409static const char *
410parse_zero (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
411{
412 const char *errmsg;
413 enum cgen_parse_operand_result result_type;
414 bfd_vma value;
415
416 /*fprintf(stderr, "dj: signed parse opindex `%s'\n", *strp);*/
417
418 /* Prevent ($ry) from being attempted as an expression on 'sw $rx,($ry)'.
419 It will fail and cause ry to be listed as an undefined symbol in the
420 listing. */
421 if (strncmp (*strp, "($", 2) == 0)
422 return "not zero"; /* any string will do -- will never be seen. */
423
424 if (strncasecmp (*strp, "%lo(", 4) == 0)
425 {
426 *strp += 4;
427 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_LOW16,
428 &result_type, &value);
429 if (**strp != ')')
430 return "missing `)'";
431 ++*strp;
432 if (errmsg == NULL
433 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
434 return "not zero"; /* any string will do -- will never be seen. */
435 *valuep = value;
436 return errmsg;
437 }
438
439 if (strncasecmp (*strp, "%hi(", 4) == 0)
440 {
441 *strp += 4;
442 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16S,
443 &result_type, &value);
444 if (**strp != ')')
445 return "missing `)'";
446 ++*strp;
447 if (errmsg == NULL
448 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
449 return "not zero"; /* any string will do -- will never be seen. */
450 *valuep = value;
451 return errmsg;
452 }
453
454 if (strncasecmp (*strp, "%uhi(", 5) == 0)
455 {
456 *strp += 5;
457 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16U,
458 &result_type, &value);
459 if (**strp != ')')
460 return "missing `)'";
461 ++*strp;
462 if (errmsg == NULL
463 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
464 return "not zero"; /* any string will do -- will never be seen. */
465 *valuep = value;
466 return errmsg;
467 }
468
469 if (strncasecmp (*strp, "%sdaoff(", 8) == 0)
470 {
471 *strp += 8;
472 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_GPREL,
473 &result_type, &value);
474 if (**strp != ')')
475 return "missing `)'";
476 ++*strp;
477 if (errmsg == NULL
478 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
479 return "not zero"; /* any string will do -- will never be seen. */
480 *valuep = value;
481 return errmsg;
482 }
483
484 if (strncasecmp (*strp, "%tpoff(", 7) == 0)
485 {
486 *strp += 7;
487 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_TPREL,
488 &result_type, &value);
489 if (**strp != ')')
490 return "missing `)'";
491 ++*strp;
492 if (errmsg == NULL
493 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
494 return "not zero"; /* any string will do -- will never be seen. */
495 *valuep = value;
496 return errmsg;
497 }
498
499 if (**strp == '%')
500 return "invalid %function() here";
501
502 errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_NONE,
503 &result_type, &value);
504 if (errmsg == NULL
505 && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
506 return "not zero"; /* any string will do -- will never be seen. */
507
508 return errmsg;
509}
510
511static const char *
512parse_unsigned7 (CGEN_CPU_DESC cd, const char **strp,
513 enum cgen_operand_type opindex, unsigned long *valuep)
514{
515 const char *errmsg;
516 bfd_vma value;
517
518 /* fprintf(stderr, "dj: unsigned7 parse `%s'\n", *strp); */
519
520 if (strncasecmp (*strp, "%tpoff(", 7) == 0)
521 {
522 int reloc;
523 *strp += 7;
524 switch (opindex)
525 {
526 case MEP_OPERAND_UDISP7:
527 reloc = BFD_RELOC_MEP_TPREL7;
528 break;
529 case MEP_OPERAND_UDISP7A2:
530 reloc = BFD_RELOC_MEP_TPREL7A2;
531 break;
532 case MEP_OPERAND_UDISP7A4:
533 reloc = BFD_RELOC_MEP_TPREL7A4;
534 break;
535 default:
536 /* Safe assumption? */
3e8b13bf 537 abort ();
dc15e575
NC
538 }
539 errmsg = cgen_parse_address (cd, strp, opindex, reloc,
540 NULL, &value);
541 if (**strp != ')')
542 return "missing `)'";
543 ++*strp;
544 *valuep = value;
545 return errmsg;
546 }
547
548 if (**strp == '%')
f757c5ca 549 /* xgettext:no-c-format */
dc15e575
NC
550 return _("invalid %function() here");
551
552 return parse_mep_alignu (cd, strp, opindex, valuep);
553}
554
555static ATTRIBUTE_UNUSED const char *
556parse_cdisp10 (CGEN_CPU_DESC cd,
557 const char **strp,
558 int opindex,
559 long *valuep)
560{
561 const char *errmsg = 0;
562 signed long value;
563 long have_zero = 0;
564 int wide = 0;
565 int alignment;
566
567 switch (opindex)
568 {
569 case MEP_OPERAND_CDISP10A4:
570 alignment = 2;
571 break;
572 case MEP_OPERAND_CDISP10A2:
573 alignment = 1;
574 break;
575 case MEP_OPERAND_CDISP10:
576 default:
577 alignment = 0;
578 break;
579 }
580
581 if ((MEP_CPU & EF_MEP_CPU_MASK) == EF_MEP_CPU_C5)
582 wide = 1;
583
3e8b13bf 584 if (strncmp (*strp, "0x0", 3) == 0
dc15e575
NC
585 || (**strp == '0' && *(*strp + 1) != 'x'))
586 have_zero = 1;
587
588 errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
589 if (errmsg)
590 return errmsg;
591
592 if (wide)
593 {
594 if (value < -512 || value > 511)
595 return _("Immediate is out of range -512 to 511");
596 }
597 else
598 {
599 if (value < -128 || value > 127)
600 return _("Immediate is out of range -128 to 127");
601 }
602
603 if (value & ((1<<alignment)-1))
604 return _("Value is not aligned enough");
605
606 /* If this field may require a relocation then use larger dsp16. */
607 if (! have_zero && value == 0)
608 return (wide ? _("Immediate is out of range -512 to 511")
609 : _("Immediate is out of range -128 to 127"));
610
611 *valuep = value;
612 return 0;
613}
614
615/* BEGIN LIGHTWEIGHT MACRO PROCESSOR. */
616
617#define MAXARGS 9
618
619typedef struct
620{
621 char *name;
622 char *expansion;
623} macro;
624
625typedef struct
626{
627 const char *start;
628 int len;
629} arg;
630
4dcdbbd1 631static macro const macros[] =
dc15e575
NC
632{
633 { "sizeof", "(`1.end + (- `1))"},
634 { "startof", "(`1 | 0)" },
635 { "align4", "(`1&(~3))"},
636/*{ "hi", "(((`1+0x8000)>>16) & 0xffff)" }, */
637/*{ "lo", "(`1 & 0xffff)" }, */
638/*{ "sdaoff", "((`1-__sdabase) & 0x7f)"}, */
639/*{ "tpoff", "((`1-__tpbase) & 0x7f)"}, */
640 { 0,0 }
641};
642
643static char * expand_string (const char *, int);
644
645static const char *
646mep_cgen_expand_macros_and_parse_operand
647 (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
648
649static char *
650str_append (char *dest, const char *input, int len)
3e8b13bf 651{
dc15e575
NC
652 char *new_dest;
653 int oldlen;
654
655 if (len == 0)
656 return dest;
657 /* printf("str_append: <<%s>>, <<%s>>, %d\n", dest, input, len); */
658 oldlen = (dest ? strlen(dest) : 0);
659 new_dest = realloc (dest, oldlen + len + 1);
660 memset (new_dest + oldlen, 0, len + 1);
661 return strncat (new_dest, input, len);
662}
663
4dcdbbd1 664static const macro *
dc15e575
NC
665lookup_macro (const char *name)
666{
4dcdbbd1 667 const macro *m;
dc15e575
NC
668
669 for (m = macros; m->name; ++m)
670 if (strncmp (m->name, name, strlen(m->name)) == 0)
671 return m;
672
673 return 0;
674}
675
676static char *
4dcdbbd1 677expand_macro (arg *args, int narg, const macro *mac)
dc15e575
NC
678{
679 char *result = 0, *rescanned_result = 0;
680 char *e = mac->expansion;
681 char *mark = e;
682 int mac_arg = 0;
683
684 /* printf("expanding macro %s with %d args\n", mac->name, narg + 1); */
685 while (*e)
686 {
3e8b13bf
AM
687 if (*e == '`'
688 && (*e+1)
689 && ((*(e + 1) - '1') <= MAXARGS)
690 && ((*(e + 1) - '1') <= narg))
dc15e575
NC
691 {
692 result = str_append (result, mark, e - mark);
693 mac_arg = (*(e + 1) - '1');
694 /* printf("replacing `%d with %s\n", mac_arg+1, args[mac_arg].start); */
695 result = str_append (result, args[mac_arg].start, args[mac_arg].len);
696 ++e;
697 mark = e+1;
698 }
699 ++e;
700 }
701
702 if (mark != e)
703 result = str_append (result, mark, e - mark);
704
705 if (result)
706 {
707 rescanned_result = expand_string (result, 0);
708 free (result);
709 return rescanned_result;
710 }
3e8b13bf 711 else
dc15e575
NC
712 return result;
713}
714
715#define IN_TEXT 0
716#define IN_ARGS 1
717
718static char *
719expand_string (const char *in, int first_only)
720{
721 int num_expansions = 0;
722 int depth = 0;
723 int narg = -1;
724 arg args[MAXARGS];
725 int state = IN_TEXT;
726 const char *mark = in;
4dcdbbd1 727 const macro *pmacro = NULL;
dc15e575
NC
728 char *expansion = 0;
729 char *result = 0;
730
731 while (*in)
732 {
733 switch (state)
734 {
735 case IN_TEXT:
3e8b13bf
AM
736 if (*in == '%' && *(in + 1) && (!first_only || num_expansions == 0))
737 {
dc15e575
NC
738 pmacro = lookup_macro (in + 1);
739 if (pmacro)
740 {
741 /* printf("entering state %d at '%s'...\n", state, in); */
742 result = str_append (result, mark, in - mark);
743 mark = in;
744 in += 1 + strlen (pmacro->name);
745 while (*in == ' ') ++in;
746 if (*in != '(')
747 {
3e8b13bf 748 state = IN_TEXT;
dc15e575
NC
749 pmacro = NULL;
750 }
751 else
752 {
753 state = IN_ARGS;
754 narg = 0;
755 args[narg].start = in + 1;
756 args[narg].len = 0;
3e8b13bf 757 mark = in + 1;
dc15e575
NC
758 }
759 }
760 }
761 break;
762 case IN_ARGS:
763 if (depth == 0)
764 {
765 switch (*in)
766 {
767 case ',':
768 narg++;
769 args[narg].start = (in + 1);
770 args[narg].len = 0;
771 break;
772 case ')':
773 state = IN_TEXT;
774 /* printf("entering state %d at '%s'...\n", state, in); */
775 if (pmacro)
776 {
777 expansion = 0;
778 expansion = expand_macro (args, narg, pmacro);
779 num_expansions++;
780 if (expansion)
781 {
782 result = str_append (result, expansion, strlen (expansion));
783 free (expansion);
784 }
785 }
786 else
787 {
788 result = str_append (result, mark, in - mark);
789 }
790 pmacro = NULL;
791 mark = in + 1;
792 break;
793 case '(':
794 depth++;
b781683b 795 /* Fall through. */
dc15e575
NC
796 default:
797 args[narg].len++;
3e8b13bf 798 break;
dc15e575 799 }
3e8b13bf 800 }
dc15e575
NC
801 else
802 {
803 if (*in == ')')
804 depth--;
805 if (narg > -1)
806 args[narg].len++;
807 }
dc15e575
NC
808 }
809 ++in;
810 }
3e8b13bf 811
dc15e575
NC
812 if (mark != in)
813 result = str_append (result, mark, in - mark);
3e8b13bf 814
dc15e575
NC
815 return result;
816}
817
818#undef IN_ARGS
819#undef IN_TEXT
820#undef MAXARGS
821
822
823/* END LIGHTWEIGHT MACRO PROCESSOR. */
824
825const char * mep_cgen_parse_operand
826 (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
827
828const char *
829mep_cgen_expand_macros_and_parse_operand (CGEN_CPU_DESC cd, int opindex,
830 const char ** strp_in, CGEN_FIELDS * fields)
831{
832 const char * errmsg = NULL;
833 char *str = 0, *hold = 0;
834 const char **strp = 0;
835
836 /* Set up a new pointer to macro-expanded string. */
837 str = expand_string (*strp_in, 1);
838 /* fprintf (stderr, " expanded <<%s>> to <<%s>>\n", *strp_in, str); */
839
840 hold = str;
841 strp = (const char **)(&str);
842
843 errmsg = mep_cgen_parse_operand (cd, opindex, strp, fields);
844
845 /* Now work out the advance. */
846 if (strlen (str) == 0)
847 *strp_in += strlen (*strp_in);
848
849 else
850 {
851 if (strstr (*strp_in, str))
852 /* A macro-expansion was pulled off the front. */
3e8b13bf 853 *strp_in = strstr (*strp_in, str);
dc15e575
NC
854 else
855 /* A non-macro-expansion was pulled off the front. */
3e8b13bf 856 *strp_in += (str - hold);
dc15e575
NC
857 }
858
d96bf37b 859 free (hold);
dc15e575
NC
860
861 return errmsg;
862}
863
3e8b13bf 864#define CGEN_ASM_INIT_HOOK (cd->parse_operand = mep_cgen_expand_macros_and_parse_operand);
dc15e575
NC
865
866/* -- dis.c */
867
868#include "elf/mep.h"
869#include "elf-bfd.h"
870
871#define CGEN_VALIDATE_INSN_SUPPORTED
872
dc15e575 873static void
0dfdb523 874print_tpreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, void *dis_info,
dc15e575
NC
875 CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
876 unsigned int flags ATTRIBUTE_UNUSED)
877{
878 disassemble_info *info = (disassemble_info *) dis_info;
879
880 (*info->fprintf_func) (info->stream, "$tp");
881}
882
883static void
0dfdb523 884print_spreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, void *dis_info,
dc15e575
NC
885 CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
886 unsigned int flags ATTRIBUTE_UNUSED)
887{
888 disassemble_info *info = (disassemble_info *) dis_info;
889
890 (*info->fprintf_func) (info->stream, "$sp");
891}
892
893/* begin-cop-ip-print-handlers */
894static void
895print_ivc2_cr (CGEN_CPU_DESC,
896 void *,
897 CGEN_KEYWORD *,
898 long,
899 unsigned int) ATTRIBUTE_UNUSED;
900static void
901print_ivc2_cr (CGEN_CPU_DESC cd,
902 void *dis_info,
903 CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
904 long value,
905 unsigned int attrs)
906{
907 print_keyword (cd, dis_info, & mep_cgen_opval_h_cr_ivc2, value, attrs);
908}
909static void
910print_ivc2_ccr (CGEN_CPU_DESC,
911 void *,
912 CGEN_KEYWORD *,
913 long,
914 unsigned int) ATTRIBUTE_UNUSED;
915static void
916print_ivc2_ccr (CGEN_CPU_DESC cd,
917 void *dis_info,
918 CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
919 long value,
920 unsigned int attrs)
921{
922 print_keyword (cd, dis_info, & mep_cgen_opval_h_ccr_ivc2, value, attrs);
923}
924/* end-cop-ip-print-handlers */
925
926/************************************************************\
927*********************** Experimental *************************
928\************************************************************/
929
930#undef CGEN_PRINT_INSN
931#define CGEN_PRINT_INSN mep_print_insn
932
933static int
934mep_print_vliw_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info,
935 bfd_byte *buf, int corelength, int copro1length,
936 int copro2length ATTRIBUTE_UNUSED)
937{
938 int i;
939 int status = 0;
940 /* char insnbuf[CGEN_MAX_INSN_SIZE]; */
941 bfd_byte insnbuf[64];
942
943 /* If corelength > 0 then there is a core insn present. It
944 will be at the beginning of the buffer. After printing
945 the core insn, we need to print the + on the next line. */
946 if (corelength > 0)
947 {
948 int my_status = 0;
3e8b13bf 949
dc15e575
NC
950 for (i = 0; i < corelength; i++ )
951 insnbuf[i] = buf[i];
952 cd->isas = & MEP_CORE_ISA;
3e8b13bf 953
dc15e575
NC
954 my_status = print_insn (cd, pc, info, insnbuf, corelength);
955 if (my_status != corelength)
956 {
957 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
958 my_status = corelength;
959 }
960 status += my_status;
961
3e8b13bf
AM
962 /* Print the + to indicate that the following copro insn is
963 part of a vliw group. */
dc15e575 964 if (copro1length > 0)
3e8b13bf 965 (*info->fprintf_func) (info->stream, " + ");
dc15e575
NC
966 }
967
968 /* Now all that is left to be processed is the coprocessor insns
969 In vliw mode, there will always be one. Its positioning will
970 be from byte corelength to byte corelength+copro1length -1.
971 No need to check for existence. Also, the first vliw insn,
972 will, as spec'd, always be at least as long as the core insn
973 so we don't need to flush the buffer. */
974 if (copro1length > 0)
975 {
976 int my_status = 0;
3e8b13bf 977
dc15e575
NC
978 for (i = corelength; i < corelength + copro1length; i++ )
979 insnbuf[i - corelength] = buf[i];
980
981 switch (copro1length)
982 {
983 case 0:
984 break;
985 case 2:
986 cd->isas = & MEP_COP16_ISA;
987 break;
988 case 4:
989 cd->isas = & MEP_COP32_ISA;
990 break;
991 case 6:
992 cd->isas = & MEP_COP48_ISA;
993 break;
994 case 8:
995 cd->isas = & MEP_COP64_ISA;
3e8b13bf 996 break;
dc15e575
NC
997 default:
998 /* Shouldn't be anything but 16,32,48,64. */
999 break;
1000 }
1001
1002 my_status = print_insn (cd, pc, info, insnbuf, copro1length);
1003
1004 if (my_status != copro1length)
1005 {
1006 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
1007 my_status = copro1length;
1008 }
1009 status += my_status;
1010 }
1011
1012#if 0
1013 /* Now we need to process the second copro insn if it exists. We
1014 have no guarantee that the second copro insn will be longer
1015 than the first, so we have to flush the buffer if we are have
1016 a second copro insn to process. If present, this insn will
1017 be in the position from byte corelength+copro1length to byte
1018 corelength+copro1length+copro2length-1 (which better equal 8
1019 or else we're in big trouble. */
1020 if (copro2length > 0)
1021 {
1022 int my_status = 0;
1023
1024 for (i = 0; i < 64 ; i++)
1025 insnbuf[i] = 0;
1026
1027 for (i = corelength + copro1length; i < 64; i++)
1028 insnbuf[i - (corelength + copro1length)] = buf[i];
3e8b13bf 1029
dc15e575
NC
1030 switch (copro2length)
1031 {
1032 case 2:
1033 cd->isas = 1 << ISA_EXT_COP1_16;
1034 break;
1035 case 4:
1036 cd->isas = 1 << ISA_EXT_COP1_32;
1037 break;
1038 case 6:
1039 cd->isas = 1 << ISA_EXT_COP1_48;
1040 break;
1041 case 8:
3e8b13bf 1042 cd->isas = 1 << ISA_EXT_COP1_64;
dc15e575
NC
1043 break;
1044 default:
1045 /* Shouldn't be anything but 16,32,48,64. */
1046 break;
1047 }
1048
1049 my_status = print_insn (cd, pc, info, insnbuf, copro2length);
1050
1051 if (my_status != copro2length)
1052 {
1053 (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
1054 my_status = copro2length;
1055 }
1056
1057 status += my_status;
1058 }
1059#endif
1060
1061 /* Status should now be the number of bytes that were printed
1062 which should be 4 for VLIW32 mode and 64 for VLIW64 mode. */
1063
1064 if ((!MEP_VLIW64 && (status != 4)) || (MEP_VLIW64 && (status != 8)))
1065 return -1;
1066 else
1067 return status;
1068}
1069
3e8b13bf
AM
1070/* The two functions mep_examine_vliw[32,64]_insns are used find out
1071 which vliw combinaion (16 bit core with 48 bit copro, 32 bit core
1072 with 32 bit copro, etc.) is present. Later on, when internally
1073 parallel coprocessors are handled, only these functions should
1074 need to be changed.
1075
1076 At this time only the following combinations are supported:
dc15e575 1077
dc15e575
NC
1078 VLIW32 Mode:
1079 16 bit core insn (core) and 16 bit coprocessor insn (cop1)
1080 32 bit core insn (core)
1081 32 bit coprocessor insn (cop1)
1082 Note: As of this time, I do not believe we have enough information
1083 to distinguish a 32 bit core insn from a 32 bit cop insn. Also,
3e8b13bf 1084 no 16 bit coprocessor insns have been specified.
dc15e575
NC
1085
1086 VLIW64 Mode:
1087 16 bit core insn (core) and 48 bit coprocessor insn (cop1)
1088 32 bit core insn (core) and 32 bit coprocessor insn (cop1)
1089 64 bit coprocessor insn (cop1)
3e8b13bf 1090
dc15e575 1091 The framework for an internally parallel coprocessor is also
3e8b13bf 1092 present (2nd coprocessor insn is cop2), but at this time it
dc15e575
NC
1093 is not used. This only appears to be valid in VLIW64 mode. */
1094
1095static int
1096mep_examine_vliw32_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1097{
1098 int status;
1099 int buflength;
1100 int corebuflength;
1101 int cop1buflength;
1102 int cop2buflength;
3e8b13bf 1103 bfd_byte buf[CGEN_MAX_INSN_SIZE];
dc15e575 1104 char indicator16[1];
3e8b13bf 1105 char indicatorcop32[2];
dc15e575
NC
1106
1107 /* At this time we're not supporting internally parallel coprocessors,
1108 so cop2buflength will always be 0. */
1109 cop2buflength = 0;
1110
1111 /* Read in 32 bits. */
1112 buflength = 4; /* VLIW insn spans 4 bytes. */
1113 status = (*info->read_memory_func) (pc, buf, buflength, info);
1114
1115 if (status != 0)
1116 {
1117 (*info->memory_error_func) (status, pc, info);
1118 return -1;
1119 }
1120
1121 /* Put the big endian representation of the bytes to be examined
1122 in the temporary buffers for examination. */
1123
1124 if (info->endian == BFD_ENDIAN_BIG)
1125 {
1126 indicator16[0] = buf[0];
1127 indicatorcop32[0] = buf[0];
1128 indicatorcop32[1] = buf[1];
1129 }
1130 else
1131 {
1132 indicator16[0] = buf[1];
1133 indicatorcop32[0] = buf[1];
1134 indicatorcop32[1] = buf[0];
1135 }
1136
1137 /* If the two high order bits are 00, 01 or 10, we have a 16 bit
1138 core insn and a 48 bit copro insn. */
1139
1140 if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
1141 {
1142 if ((indicatorcop32[0] & 0xf0) == 0xf0 && (indicatorcop32[1] & 0x07) == 0x07)
1143 {
3e8b13bf
AM
1144 /* We have a 32 bit copro insn. */
1145 corebuflength = 0;
dc15e575 1146 /* All 4 4ytes are one copro insn. */
3e8b13bf 1147 cop1buflength = 4;
dc15e575
NC
1148 }
1149 else
1150 {
3e8b13bf
AM
1151 /* We have a 32 bit core. */
1152 corebuflength = 4;
1153 cop1buflength = 0;
dc15e575
NC
1154 }
1155 }
1156 else
1157 {
1158 /* We have a 16 bit core insn and a 16 bit copro insn. */
1159 corebuflength = 2;
1160 cop1buflength = 2;
1161 }
1162
1163 /* Now we have the distrubution set. Print them out. */
1164 status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
1165 cop1buflength, cop2buflength);
1166
1167 return status;
1168}
1169
1170static int
1171mep_examine_vliw64_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1172{
1173 int status;
1174 int buflength;
1175 int corebuflength;
1176 int cop1buflength;
1177 int cop2buflength;
1178 bfd_byte buf[CGEN_MAX_INSN_SIZE];
1179 char indicator16[1];
1180 char indicator64[4];
1181
1182 /* At this time we're not supporting internally parallel
1183 coprocessors, so cop2buflength will always be 0. */
1184 cop2buflength = 0;
1185
1186 /* Read in 64 bits. */
1187 buflength = 8; /* VLIW insn spans 8 bytes. */
1188 status = (*info->read_memory_func) (pc, buf, buflength, info);
1189
1190 if (status != 0)
1191 {
1192 (*info->memory_error_func) (status, pc, info);
1193 return -1;
1194 }
1195
1196 /* We have all 64 bits in the buffer now. We have to figure out
1197 what combination of instruction sizes are present. The two
1198 high order bits will indicate whether or not we have a 16 bit
1199 core insn or not. If not, then we have to look at the 7,8th
1200 bytes to tell whether we have 64 bit copro insn or a 32 bit
1201 core insn with a 32 bit copro insn. Endianness will make a
1202 difference here. */
1203
1204 /* Put the big endian representation of the bytes to be examined
1205 in the temporary buffers for examination. */
1206
1207 /* indicator16[0] = buf[0]; */
1208 if (info->endian == BFD_ENDIAN_BIG)
1209 {
1210 indicator16[0] = buf[0];
1211 indicator64[0] = buf[0];
1212 indicator64[1] = buf[1];
1213 indicator64[2] = buf[2];
1214 indicator64[3] = buf[3];
1215 }
1216 else
1217 {
1218 indicator16[0] = buf[1];
1219 indicator64[0] = buf[1];
1220 indicator64[1] = buf[0];
1221 indicator64[2] = buf[3];
1222 indicator64[3] = buf[2];
1223 }
1224
1225 /* If the two high order bits are 00, 01 or 10, we have a 16 bit
1226 core insn and a 48 bit copro insn. */
1227
1228 if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
1229 {
1230 if ((indicator64[0] & 0xf0) == 0xf0 && (indicator64[1] & 0x07) == 0x07
1231 && ((indicator64[2] & 0xfe) != 0xf0 || (indicator64[3] & 0xf4) != 0))
1232 {
3e8b13bf
AM
1233 /* We have a 64 bit copro insn. */
1234 corebuflength = 0;
dc15e575 1235 /* All 8 bytes are one copro insn. */
3e8b13bf 1236 cop1buflength = 8;
dc15e575
NC
1237 }
1238 else
1239 {
3e8b13bf
AM
1240 /* We have a 32 bit core insn and a 32 bit copro insn. */
1241 corebuflength = 4;
1242 cop1buflength = 4;
dc15e575
NC
1243 }
1244 }
1245 else
1246 {
1247 /* We have a 16 bit core insn and a 48 bit copro insn. */
1248 corebuflength = 2;
1249 cop1buflength = 6;
1250 }
1251
1252 /* Now we have the distrubution set. Print them out. */
1253 status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
1254 cop1buflength, cop2buflength);
1255
1256 return status;
1257}
1258
1259#ifdef MEP_IVC2_SUPPORTED
1260
1261static int
1262print_slot_insn (CGEN_CPU_DESC cd,
1263 bfd_vma pc,
1264 disassemble_info *info,
1265 SLOTS_ATTR slot,
1266 bfd_byte *buf)
1267{
1268 const CGEN_INSN_LIST *insn_list;
1269 CGEN_INSN_INT insn_value;
1270 CGEN_EXTRACT_INFO ex_info;
1271
e9bffec9 1272 insn_value = cgen_get_insn_value (cd, buf, 32, cd->insn_endian);
dc15e575
NC
1273
1274 /* Fill in ex_info fields like read_insn would. Don't actually call
1275 read_insn, since the incoming buffer is already read (and possibly
1276 modified a la m32r). */
1277 ex_info.valid = (1 << 8) - 1;
1278 ex_info.dis_info = info;
1279 ex_info.insn_bytes = buf;
1280
1281 /* The instructions are stored in hash lists.
1282 Pick the first one and keep trying until we find the right one. */
1283
1284 insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
1285 while (insn_list != NULL)
1286 {
1287 const CGEN_INSN *insn = insn_list->insn;
1288 CGEN_FIELDS fields;
1289 int length;
1290
1291 if ((CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG)
1292 && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG) != MEP_CONFIG)
1293 || ! (CGEN_ATTR_CGEN_INSN_SLOTS_VALUE (CGEN_INSN_ATTRS (insn)) & (1 << slot)))
3e8b13bf
AM
1294 {
1295 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
dc15e575 1296 continue;
3e8b13bf 1297 }
dc15e575
NC
1298
1299 if ((insn_value & CGEN_INSN_BASE_MASK (insn))
1300 == CGEN_INSN_BASE_VALUE (insn))
1301 {
1302 /* Printing is handled in two passes. The first pass parses the
1303 machine insn and extracts the fields. The second pass prints
1304 them. */
1305
1306 length = CGEN_EXTRACT_FN (cd, insn)
1307 (cd, insn, &ex_info, insn_value, &fields, pc);
1308
1309 /* Length < 0 -> error. */
1310 if (length < 0)
1311 return length;
1312 if (length > 0)
1313 {
1314 CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
1315 /* Length is in bits, result is in bytes. */
1316 return length / 8;
1317 }
1318 }
1319
1320 insn_list = CGEN_DIS_NEXT_INSN (insn_list);
1321 }
1322
1323 if (slot == SLOTS_P0S)
1324 (*info->fprintf_func) (info->stream, "*unknown-p0s*");
1325 else if (slot == SLOTS_P0)
1326 (*info->fprintf_func) (info->stream, "*unknown-p0*");
1327 else if (slot == SLOTS_P1)
1328 (*info->fprintf_func) (info->stream, "*unknown-p1*");
1329 else if (slot == SLOTS_C3)
1330 (*info->fprintf_func) (info->stream, "*unknown-c3*");
1331 return 0;
1332}
1333
1334static int
1335mep_examine_ivc2_insns (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, bfd_vma pc ATTRIBUTE_UNUSED, disassemble_info *info ATTRIBUTE_UNUSED)
1336{
1337 int status;
1338 int buflength;
1339 bfd_byte buf[8];
1340 bfd_byte insn[8];
1341 int e;
1342
1343 /* Read in 64 bits. */
1344 buflength = 8; /* VLIW insn spans 8 bytes. */
1345 status = (*info->read_memory_func) (pc, buf, buflength, info);
1346
1347 if (status != 0)
1348 {
1349 (*info->memory_error_func) (status, pc, info);
1350 return -1;
1351 }
1352
1353 if (info->endian == BFD_ENDIAN_LITTLE)
1354 e = 1;
1355 else
1356 e = 0;
1357
1358 if (((unsigned char)buf[0^e] & 0xf0) < 0xc0)
1359 {
1360 /* <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1361 /* V1 [-----core-----][--------p0s-------][------------p1------------] */
1362
1363 print_insn (cd, pc, info, buf, 2);
1364
1365 insn[0^e] = 0;
1366 insn[1^e] = buf[2^e];
1367 insn[2^e] = buf[3^e];
1368 insn[3^e] = buf[4^e] & 0xf0;
1369 (*info->fprintf_func) (info->stream, " + ");
1370 print_slot_insn (cd, pc, info, SLOTS_P0S, insn);
1371
1372 insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1373 insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1374 insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1375 insn[3^e] = buf[7^e] << 4;
1376 (*info->fprintf_func) (info->stream, " + ");
1377 print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1378 }
1379 else if ((buf[0^e] & 0xf0) == 0xf0 && (buf[1^e] & 0x0f) == 0x07)
1380 {
1381 /* <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1382 /* V3 1111[--p0--]0111[--------p0--------][------------p1------------] */
1383 /* 00000000111111112222222233333333 */
1384
1385 insn[0^e] = buf[0^e] << 4 | buf[1^e] >> 4;
1386 insn[1^e] = buf[2^e];
1387 insn[2^e] = buf[3^e];
1388 insn[3^e] = buf[4^e] & 0xf0;
1389 print_slot_insn (cd, pc, info, SLOTS_P0, insn);
1390
1391 insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1392 insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1393 insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1394 insn[3^e] = buf[7^e] << 4;
1395 (*info->fprintf_func) (info->stream, " + ");
1396 print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1397 }
1398 else
1399 {
1400 /* <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1401 /* V2 [-------------core-------------]xxxx[------------p1------------] */
1402 print_insn (cd, pc, info, buf, 4);
1403
1404 insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1405 insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1406 insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1407 insn[3^e] = buf[7^e] << 4;
1408 (*info->fprintf_func) (info->stream, " + ");
1409 print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1410 }
1411
1412 return 8;
1413}
1414
1415#endif /* MEP_IVC2_SUPPORTED */
1416
1417/* This is a hack. SID calls this to update the disassembler as the
1418 CPU changes modes. */
1419static int mep_ivc2_disassemble_p = 0;
1420static int mep_ivc2_vliw_disassemble_p = 0;
1421
1422void
1423mep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx);
1424void
1425mep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx)
1426{
1427 mep_ivc2_disassemble_p = ivc2_p;
1428 mep_ivc2_vliw_disassemble_p = vliw_p;
1429 mep_config_index = cfg_idx;
1430}
1431
1432static int
1433mep_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1434{
1435 int status;
1436 int cop_type;
1437 int ivc2 = 0;
1438 static CGEN_ATTR_VALUE_BITSET_TYPE *ivc2_core_isa = NULL;
1439
1440 if (ivc2_core_isa == NULL)
1441 {
1442 /* IVC2 has some core-only coprocessor instructions. We
1443 use COP32 to flag those, and COP64 for the VLIW ones,
1444 since they have the same names. */
1445 ivc2_core_isa = cgen_bitset_create (MAX_ISAS);
1446 }
1447
1448 /* Extract and adapt to configuration number, if available. */
1449 if (info->section && info->section->owner)
1450 {
1451 bfd *abfd = info->section->owner;
16089f32
TH
1452 if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
1453 {
1454 mep_config_index = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_INDEX_MASK;
1455 /* This instantly redefines MEP_CONFIG, MEP_OMASK, .... MEP_VLIW64 */
dc15e575 1456
71f646f2
NC
1457 /* mep_config_map is a variable sized array, so we do not know how big it is.
1458 The only safe way to check the index therefore is to iterate over the array.
1459 We do know that the last entry is all null. */
1460 int i;
1461 for (i = 0; i <= mep_config_index; i++)
1462 if (mep_config_map[i].name == NULL)
1463 break;
3e8b13bf 1464
71f646f2
NC
1465 if (i < mep_config_index)
1466 {
1467 opcodes_error_handler (_("illegal MEP INDEX setting '%x' in ELF header e_flags field"), mep_config_index);
1468 mep_config_index = 0;
1469 }
3e8b13bf 1470
16089f32
TH
1471 cop_type = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_COP_MASK;
1472 if (cop_type == EF_MEP_COP_IVC2)
1473 ivc2 = 1;
1474 }
dc15e575
NC
1475 }
1476
1477 /* Picking the right ISA bitmask for the current context is tricky. */
1478 if (info->section)
1479 {
1480 if (info->section->flags & SEC_MEP_VLIW)
1481 {
1482#ifdef MEP_IVC2_SUPPORTED
1483 if (ivc2)
1484 {
1485 /* ivc2 has its own way of selecting its functions. */
1486 cd->isas = & MEP_CORE_ISA;
1487 status = mep_examine_ivc2_insns (cd, pc, info);
1488 }
1489 else
1490#endif
1491 /* Are we in 32 or 64 bit vliw mode? */
1492 if (MEP_VLIW64)
1493 status = mep_examine_vliw64_insns (cd, pc, info);
1494 else
1495 status = mep_examine_vliw32_insns (cd, pc, info);
1496 /* Both the above branches set their own isa bitmasks. */
1497 }
1498 else
1499 {
1500 if (ivc2)
1501 {
1502 cgen_bitset_clear (ivc2_core_isa);
1503 cgen_bitset_union (ivc2_core_isa, &MEP_CORE_ISA, ivc2_core_isa);
1504 cgen_bitset_union (ivc2_core_isa, &MEP_COP32_ISA, ivc2_core_isa);
1505 cd->isas = ivc2_core_isa;
1506 }
1507 else
1508 cd->isas = & MEP_CORE_ISA;
1509 status = default_print_insn (cd, pc, info);
1510 }
1511 }
1512 else /* sid or gdb */
1513 {
1514#ifdef MEP_IVC2_SUPPORTED
1515 if (mep_ivc2_disassemble_p)
1516 {
1517 if (mep_ivc2_vliw_disassemble_p)
1518 {
1519 cd->isas = & MEP_CORE_ISA;
1520 status = mep_examine_ivc2_insns (cd, pc, info);
1521 return status;
1522 }
1523 else
1524 {
1525 if (ivc2)
1526 cd->isas = ivc2_core_isa;
1527 }
1528 }
1529#endif
1530
1531 status = default_print_insn (cd, pc, info);
1532 }
1533
1534 return status;
1535}
1536
1537
1538/* -- opc.c */
1539#include "elf/mep.h"
1540
1541/* A mask for all ISAs executed by the core. */
1542CGEN_ATTR_VALUE_BITSET_TYPE mep_all_core_isas_mask = {0, 0};
1543
1544void
1545init_mep_all_core_isas_mask (void)
1546{
1547 if (mep_all_core_isas_mask.length != 0)
1548 return;
1549 cgen_bitset_init (& mep_all_core_isas_mask, ISA_MAX);
1550 cgen_bitset_set (& mep_all_core_isas_mask, ISA_MEP);
1551 /* begin-all-core-isas */
1552 cgen_bitset_add (& mep_all_core_isas_mask, ISA_EXT_CORE1);
1553 /* end-all-core-isas */
1554}
1555
1556CGEN_ATTR_VALUE_BITSET_TYPE mep_all_cop_isas_mask = {0, 0};
1557
1558void
1559init_mep_all_cop_isas_mask (void)
1560{
1561 if (mep_all_cop_isas_mask.length != 0)
1562 return;
1563 cgen_bitset_init (& mep_all_cop_isas_mask, ISA_MAX);
1564 /* begin-all-cop-isas */
1565 cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_16);
1566 cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_32);
1567 cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_48);
1568 cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_64);
1569 /* end-all-cop-isas */
1570}
1571
1572int
1573mep_insn_supported_by_isa (const CGEN_INSN *insn, CGEN_ATTR_VALUE_BITSET_TYPE *isa_mask)
1574{
1575 CGEN_BITSET insn_isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
1576 return cgen_bitset_intersect_p (& insn_isas, isa_mask);
1577}
1578
1579#define OPTION_MASK \
1580 ( (1 << CGEN_INSN_OPTIONAL_BIT_INSN) \
1581 | (1 << CGEN_INSN_OPTIONAL_MUL_INSN) \
1582 | (1 << CGEN_INSN_OPTIONAL_DIV_INSN) \
1583 | (1 << CGEN_INSN_OPTIONAL_DEBUG_INSN) \
1584 | (1 << CGEN_INSN_OPTIONAL_LDZ_INSN) \
1585 | (1 << CGEN_INSN_OPTIONAL_ABS_INSN) \
1586 | (1 << CGEN_INSN_OPTIONAL_AVE_INSN) \
1587 | (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN) \
1588 | (1 << CGEN_INSN_OPTIONAL_CLIP_INSN) \
1589 | (1 << CGEN_INSN_OPTIONAL_SAT_INSN) \
1590 | (1 << CGEN_INSN_OPTIONAL_UCI_INSN) \
1591 | (1 << CGEN_INSN_OPTIONAL_DSP_INSN) \
1592 | (1 << CGEN_INSN_OPTIONAL_CP_INSN) \
1593 | (1 << CGEN_INSN_OPTIONAL_CP64_INSN) )
1594
1595
1596mep_config_map_struct mep_config_map[] =
1597{
1598 /* config-map-start */
1599 /* Default entry: first module, with all options enabled. */
1600 { "", 0, EF_MEP_COP_IVC2 | EF_MEP_CPU_C5,0, 64, { 1, "\x20" }, { 1, "\x10" }, { 1, "\x8" }, { 1, "\x4" }, { 1, "\x3c" }, { 1, "\xc0" }, OPTION_MASK | (1 << CGEN_INSN_OPTIONAL_DSP_INSN) | (1 << CGEN_INSN_OPTIONAL_UCI_INSN) },
1601 { "default", CONFIG_DEFAULT, EF_MEP_COP_IVC2 | EF_MEP_CPU_C5, 0, 64, { 1, "\x20" }, { 1, "\x10" }, { 1, "\x8" }, { 1, "\x4" }, { 1, "\x3c" }, { 1, "\xc0" },
1602 0
1603 | (1 << CGEN_INSN_OPTIONAL_CP_INSN)
1604 | (1 << CGEN_INSN_OPTIONAL_CP64_INSN)
1605 | (1 << CGEN_INSN_OPTIONAL_MUL_INSN)
1606 | (1 << CGEN_INSN_OPTIONAL_DIV_INSN)
1607 | (1 << CGEN_INSN_OPTIONAL_BIT_INSN)
1608 | (1 << CGEN_INSN_OPTIONAL_LDZ_INSN)
1609 | (1 << CGEN_INSN_OPTIONAL_ABS_INSN)
1610 | (1 << CGEN_INSN_OPTIONAL_AVE_INSN)
1611 | (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN)
1612 | (1 << CGEN_INSN_OPTIONAL_CLIP_INSN)
1613 | (1 << CGEN_INSN_OPTIONAL_SAT_INSN) },
1614 /* config-map-end */
1615 { 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 0 }
1616};
1617
1618int mep_config_index = 0;
1619
1620static int
1621check_configured_mach (int machs)
1622{
1623 /* All base insns are supported. */
1624 int mach = 1 << MACH_BASE;
1625 switch (MEP_CPU & EF_MEP_CPU_MASK)
1626 {
1627 case EF_MEP_CPU_C2:
1628 case EF_MEP_CPU_C3:
1629 mach |= (1 << MACH_MEP);
1630 break;
1631 case EF_MEP_CPU_H1:
1632 mach |= (1 << MACH_H1);
1633 break;
1634 case EF_MEP_CPU_C5:
1635 mach |= (1 << MACH_MEP);
1636 mach |= (1 << MACH_C5);
1637 break;
1638 default:
1639 break;
1640 }
1641 return machs & mach;
1642}
1643
1644int
1645mep_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
1646{
1647 int iconfig = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG);
1648 int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
1649 CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
1650 int ok1;
1651 int ok2;
1652 int ok3;
1653
1654 /* If the insn has an option bit set that we don't want,
1655 reject it. */
1656 if (CGEN_INSN_ATTRS (insn)->bool_ & OPTION_MASK & ~MEP_OMASK)
1657 return 0;
1658
1659 /* If attributes are absent, assume no restriction. */
1660 if (machs == 0)
1661 machs = ~0;
1662
1663 ok1 = ((machs & cd->machs) && cgen_bitset_intersect_p (& isas, cd->isas));
1664 /* If the insn is config-specific, make sure it matches. */
1665 ok2 = (iconfig == 0 || iconfig == MEP_CONFIG);
1666 /* Make sure the insn is supported by the configured mach */
1667 ok3 = check_configured_mach (machs);
1668
1669 return (ok1 && ok2 && ok3);
1670}
1671
1672int
1673mep_cgen_insn_supported_asm (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
1674{
1675#ifdef MEP_IVC2_SUPPORTED
1676 /* If we're assembling VLIW packets, ignore the 12-bit BSR as we
1677 can't relax that. The 24-bit BSR is matched instead. */
1678 if (insn->base->num == MEP_INSN_BSR12
1679 && cgen_bitset_contains (cd->isas, ISA_EXT_COP1_64))
1680 return 0;
1681#endif
1682
1683 return mep_cgen_insn_supported (cd, insn);
1684}