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