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