xref: /netbsd-src/external/gpl3/binutils/dist/cpu/mep.opc (revision cb63e24e8d6aae7ddac1859a9015f48b1d8bd90e)
1883529b6Schristos/* MeP opcode support.  -*- C -*-
2883529b6Schristos   Copyright 2011 Free Software Foundation, Inc.
3883529b6Schristos
4883529b6Schristos   Contributed by Red Hat Inc;
5883529b6Schristos
6883529b6Schristos   This file is part of the GNU Binutils.
7883529b6Schristos
8883529b6Schristos   This program is free software; you can redistribute it and/or modify
9883529b6Schristos   it under the terms of the GNU General Public License as published by
10883529b6Schristos   the Free Software Foundation; either version 3 of the License, or
11883529b6Schristos   (at your option) any later version.
12883529b6Schristos
13883529b6Schristos   This program is distributed in the hope that it will be useful,
14883529b6Schristos   but WITHOUT ANY WARRANTY; without even the implied warranty of
15883529b6Schristos   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16883529b6Schristos   GNU General Public License for more details.
17883529b6Schristos
18883529b6Schristos   You should have received a copy of the GNU General Public License
19883529b6Schristos   along with this program; if not, write to the Free Software
20883529b6Schristos   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21883529b6Schristos   MA 02110-1301, USA.  */
22883529b6Schristos
23883529b6Schristos/* -- opc.h */
24883529b6Schristos
25883529b6Schristos#undef  CGEN_DIS_HASH_SIZE
26883529b6Schristos#define CGEN_DIS_HASH_SIZE 1
27883529b6Schristos
28883529b6Schristos#undef  CGEN_DIS_HASH
29883529b6Schristos#define CGEN_DIS_HASH(buffer, insn) 0
30883529b6Schristos
31883529b6Schristos#define CGEN_VERBOSE_ASSEMBLER_ERRORS
32883529b6Schristos
33883529b6Schristostypedef struct
34883529b6Schristos{
35883529b6Schristos  char * name;
36883529b6Schristos  int    config_enum;
37883529b6Schristos  unsigned cpu_flag;
38883529b6Schristos  int    big_endian;
39883529b6Schristos  int    vliw_bits;
40883529b6Schristos  CGEN_ATTR_VALUE_BITSET_TYPE cop16_isa;
41883529b6Schristos  CGEN_ATTR_VALUE_BITSET_TYPE cop32_isa;
42883529b6Schristos  CGEN_ATTR_VALUE_BITSET_TYPE cop48_isa;
43883529b6Schristos  CGEN_ATTR_VALUE_BITSET_TYPE cop64_isa;
44883529b6Schristos  CGEN_ATTR_VALUE_BITSET_TYPE cop_isa;
45883529b6Schristos  CGEN_ATTR_VALUE_BITSET_TYPE core_isa;
46883529b6Schristos  unsigned int option_mask;
47883529b6Schristos} mep_config_map_struct;
48883529b6Schristos
49883529b6Schristosextern mep_config_map_struct mep_config_map[];
50883529b6Schristosextern int mep_config_index;
51883529b6Schristos
52883529b6Schristosextern void init_mep_all_core_isas_mask (void);
53883529b6Schristosextern void init_mep_all_cop_isas_mask  (void);
54883529b6Schristosextern CGEN_ATTR_VALUE_BITSET_TYPE mep_cop_isa  (void);
55883529b6Schristos
56883529b6Schristos#define MEP_CONFIG     (mep_config_map[mep_config_index].config_enum)
57883529b6Schristos#define MEP_CPU        (mep_config_map[mep_config_index].cpu_flag)
58883529b6Schristos#define MEP_OMASK      (mep_config_map[mep_config_index].option_mask)
59883529b6Schristos#define MEP_VLIW       (mep_config_map[mep_config_index].vliw_bits > 0)
60883529b6Schristos#define MEP_VLIW32     (mep_config_map[mep_config_index].vliw_bits == 32)
61883529b6Schristos#define MEP_VLIW64     (mep_config_map[mep_config_index].vliw_bits == 64)
62883529b6Schristos#define MEP_COP16_ISA  (mep_config_map[mep_config_index].cop16_isa)
63883529b6Schristos#define MEP_COP32_ISA  (mep_config_map[mep_config_index].cop32_isa)
64883529b6Schristos#define MEP_COP48_ISA  (mep_config_map[mep_config_index].cop48_isa)
65883529b6Schristos#define MEP_COP64_ISA  (mep_config_map[mep_config_index].cop64_isa)
66883529b6Schristos#define MEP_COP_ISA    (mep_config_map[mep_config_index].cop_isa)
67883529b6Schristos#define MEP_CORE_ISA   (mep_config_map[mep_config_index].core_isa)
68883529b6Schristos
69883529b6Schristos/* begin-cop-ip-supported-defines */
70883529b6Schristos#define MEP_IVC2_SUPPORTED 1
71883529b6Schristos/* end-cop-ip-supported-defines */
72883529b6Schristos
73883529b6Schristosextern int mep_insn_supported_by_isa (const CGEN_INSN *, CGEN_ATTR_VALUE_BITSET_TYPE *);
74883529b6Schristos
75883529b6Schristos/* A mask for all ISAs executed by the core.  */
76883529b6Schristos#define MEP_ALL_CORE_ISAS_MASK mep_all_core_isas_mask
77883529b6Schristosextern CGEN_ATTR_VALUE_BITSET_TYPE mep_all_core_isas_mask;
78883529b6Schristos
79883529b6Schristos#define MEP_INSN_CORE_P(insn) ( \
80883529b6Schristos  init_mep_all_core_isas_mask (), \
81883529b6Schristos  mep_insn_supported_by_isa (insn, & MEP_ALL_CORE_ISAS_MASK) \
82883529b6Schristos)
83883529b6Schristos
84883529b6Schristos/* A mask for all ISAs executed by a VLIW coprocessor.  */
85883529b6Schristos#define MEP_ALL_COP_ISAS_MASK mep_all_cop_isas_mask
86883529b6Schristosextern CGEN_ATTR_VALUE_BITSET_TYPE mep_all_cop_isas_mask;
87883529b6Schristos
88883529b6Schristos#define MEP_INSN_COP_P(insn) ( \
89883529b6Schristos  init_mep_all_cop_isas_mask (), \
90883529b6Schristos  mep_insn_supported_by_isa (insn, & MEP_ALL_COP_ISAS_MASK) \
91883529b6Schristos)
92883529b6Schristos
93883529b6Schristosextern int mep_cgen_insn_supported (CGEN_CPU_DESC, const CGEN_INSN *);
94883529b6Schristosextern int mep_cgen_insn_supported_asm (CGEN_CPU_DESC, const CGEN_INSN *);
95883529b6Schristos
96883529b6Schristos/* -- asm.c */
97883529b6Schristos
98883529b6Schristos#include "elf/mep.h"
99883529b6Schristos
100883529b6Schristos#define CGEN_VALIDATE_INSN_SUPPORTED
101883529b6Schristos#define mep_cgen_insn_supported mep_cgen_insn_supported_asm
102883529b6Schristos
103883529b6Schristos       const char * parse_csrn       (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
104883529b6Schristos       const char * parse_tpreg      (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
105883529b6Schristos       const char * parse_spreg      (CGEN_CPU_DESC, const char **, CGEN_KEYWORD *, long *);
106883529b6Schristos       const char * parse_mep_align  (CGEN_CPU_DESC, const char **, enum cgen_operand_type, long *);
107883529b6Schristos       const char * parse_mep_alignu (CGEN_CPU_DESC, const char **, enum cgen_operand_type, unsigned long *);
108883529b6Schristosstatic const char * parse_signed16   (CGEN_CPU_DESC, const char **, int, long *);
109883529b6Schristosstatic const char * parse_signed16_range   (CGEN_CPU_DESC, const char **, int, long *) ATTRIBUTE_UNUSED;
110883529b6Schristosstatic const char * parse_unsigned16 (CGEN_CPU_DESC, const char **, int, unsigned long *);
111883529b6Schristosstatic const char * parse_unsigned16_range (CGEN_CPU_DESC, const char **, int, unsigned long *) ATTRIBUTE_UNUSED;
112883529b6Schristosstatic const char * parse_lo16       (CGEN_CPU_DESC, const char **, int, long *, long);
113883529b6Schristosstatic const char * parse_unsigned7  (CGEN_CPU_DESC, const char **, enum cgen_operand_type, unsigned long *);
114883529b6Schristosstatic const char * parse_zero       (CGEN_CPU_DESC, const char **, int, long *);
115883529b6Schristos
116883529b6Schristosconst char *
117883529b6Schristosparse_csrn (CGEN_CPU_DESC cd, const char **strp,
118883529b6Schristos	    CGEN_KEYWORD *keyword_table, long *field)
119883529b6Schristos{
120883529b6Schristos  const char *err;
121883529b6Schristos  unsigned long value;
122883529b6Schristos
123883529b6Schristos  err = cgen_parse_keyword (cd, strp, keyword_table, field);
124883529b6Schristos  if (!err)
125883529b6Schristos    return NULL;
126883529b6Schristos
127883529b6Schristos  err = cgen_parse_unsigned_integer (cd, strp, MEP_OPERAND_CSRN_IDX, & value);
128883529b6Schristos  if (err)
129883529b6Schristos    return err;
130883529b6Schristos  *field = value;
131883529b6Schristos  return NULL;
132883529b6Schristos}
133883529b6Schristos
134883529b6Schristos/* begin-cop-ip-parse-handlers */
135883529b6Schristosstatic const char *
136883529b6Schristosparse_ivc2_cr (CGEN_CPU_DESC,
137883529b6Schristos	const char **,
138883529b6Schristos	CGEN_KEYWORD *,
139883529b6Schristos	long *) ATTRIBUTE_UNUSED;
140883529b6Schristosstatic const char *
141883529b6Schristosparse_ivc2_cr (CGEN_CPU_DESC cd,
142883529b6Schristos	const char **strp,
143883529b6Schristos	CGEN_KEYWORD *keyword_table  ATTRIBUTE_UNUSED,
144883529b6Schristos	long *field)
145883529b6Schristos{
146883529b6Schristos  return cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_cr_ivc2, field);
147883529b6Schristos}
148883529b6Schristosstatic const char *
149883529b6Schristosparse_ivc2_ccr (CGEN_CPU_DESC,
150883529b6Schristos	const char **,
151883529b6Schristos	CGEN_KEYWORD *,
152883529b6Schristos	long *) ATTRIBUTE_UNUSED;
153883529b6Schristosstatic const char *
154883529b6Schristosparse_ivc2_ccr (CGEN_CPU_DESC cd,
155883529b6Schristos	const char **strp,
156883529b6Schristos	CGEN_KEYWORD *keyword_table  ATTRIBUTE_UNUSED,
157883529b6Schristos	long *field)
158883529b6Schristos{
159883529b6Schristos  return cgen_parse_keyword (cd, strp, & mep_cgen_opval_h_ccr_ivc2, field);
160883529b6Schristos}
161883529b6Schristos/* end-cop-ip-parse-handlers */
162883529b6Schristos
163883529b6Schristosconst char *
164883529b6Schristosparse_tpreg (CGEN_CPU_DESC cd, const char ** strp,
165883529b6Schristos	     CGEN_KEYWORD *keyword_table, long *field)
166883529b6Schristos{
167883529b6Schristos  const char *err;
168883529b6Schristos
169883529b6Schristos  err = cgen_parse_keyword (cd, strp, keyword_table, field);
170883529b6Schristos  if (err)
171883529b6Schristos    return err;
172883529b6Schristos  if (*field != 13)
173883529b6Schristos    return _("Only $tp or $13 allowed for this opcode");
174883529b6Schristos  return NULL;
175883529b6Schristos}
176883529b6Schristos
177883529b6Schristosconst char *
178883529b6Schristosparse_spreg (CGEN_CPU_DESC cd, const char ** strp,
179883529b6Schristos	     CGEN_KEYWORD *keyword_table, long *field)
180883529b6Schristos{
181883529b6Schristos  const char *err;
182883529b6Schristos
183883529b6Schristos  err = cgen_parse_keyword (cd, strp, keyword_table, field);
184883529b6Schristos  if (err)
185883529b6Schristos    return err;
186883529b6Schristos  if (*field != 15)
187883529b6Schristos    return _("Only $sp or $15 allowed for this opcode");
188883529b6Schristos  return NULL;
189883529b6Schristos}
190883529b6Schristos
191883529b6Schristosconst char *
192883529b6Schristosparse_mep_align (CGEN_CPU_DESC cd, const char ** strp,
193883529b6Schristos		 enum cgen_operand_type type, long *field)
194883529b6Schristos{
195883529b6Schristos  long lsbs = 0;
196883529b6Schristos  const char *err;
197883529b6Schristos
198883529b6Schristos  switch (type)
199883529b6Schristos    {
200883529b6Schristos    case MEP_OPERAND_PCREL8A2:
201883529b6Schristos    case MEP_OPERAND_PCREL12A2:
202883529b6Schristos    case MEP_OPERAND_PCREL17A2:
203883529b6Schristos    case MEP_OPERAND_PCREL24A2:
204883529b6Schristos      err = cgen_parse_signed_integer   (cd, strp, type, field);
205883529b6Schristos      break;
206883529b6Schristos    case MEP_OPERAND_PCABS24A2:
207883529b6Schristos    case MEP_OPERAND_UDISP7:
208883529b6Schristos    case MEP_OPERAND_UDISP7A2:
209883529b6Schristos    case MEP_OPERAND_UDISP7A4:
210883529b6Schristos    case MEP_OPERAND_UIMM7A4:
211883529b6Schristos    case MEP_OPERAND_ADDR24A4:
212883529b6Schristos      err = cgen_parse_unsigned_integer (cd, strp, type, (unsigned long *) field);
213883529b6Schristos      break;
214883529b6Schristos    default:
215883529b6Schristos      abort();
216883529b6Schristos    }
217883529b6Schristos  if (err)
218883529b6Schristos    return err;
219883529b6Schristos  switch (type)
220883529b6Schristos    {
221883529b6Schristos    case MEP_OPERAND_UDISP7:
222883529b6Schristos      lsbs = 0;
223883529b6Schristos      break;
224883529b6Schristos    case MEP_OPERAND_PCREL8A2:
225883529b6Schristos    case MEP_OPERAND_PCREL12A2:
226883529b6Schristos    case MEP_OPERAND_PCREL17A2:
227883529b6Schristos    case MEP_OPERAND_PCREL24A2:
228883529b6Schristos    case MEP_OPERAND_PCABS24A2:
229883529b6Schristos    case MEP_OPERAND_UDISP7A2:
230883529b6Schristos      lsbs = *field & 1;
231883529b6Schristos      break;
232883529b6Schristos    case MEP_OPERAND_UDISP7A4:
233883529b6Schristos    case MEP_OPERAND_UIMM7A4:
234883529b6Schristos    case MEP_OPERAND_ADDR24A4:
235883529b6Schristos      lsbs = *field & 3;
236883529b6Schristos      break;
237883529b6Schristos      lsbs = *field & 7;
238883529b6Schristos      break;
239883529b6Schristos    default:
240883529b6Schristos      /* Safe assumption?  */
241883529b6Schristos      abort ();
242883529b6Schristos    }
243883529b6Schristos  if (lsbs)
244883529b6Schristos    return "Value is not aligned enough";
245883529b6Schristos  return NULL;
246883529b6Schristos}
247883529b6Schristos
248883529b6Schristosconst char *
249883529b6Schristosparse_mep_alignu (CGEN_CPU_DESC cd, const char ** strp,
250883529b6Schristos		 enum cgen_operand_type type, unsigned long *field)
251883529b6Schristos{
252883529b6Schristos  return parse_mep_align (cd, strp, type, (long *) field);
253883529b6Schristos}
254883529b6Schristos
255883529b6Schristos
256883529b6Schristos/* Handle %lo(), %tpoff(), %sdaoff(), %hi(), and other signed
257883529b6Schristos   constants in a signed context.  */
258883529b6Schristos
259883529b6Schristosstatic const char *
260883529b6Schristosparse_signed16 (CGEN_CPU_DESC cd,
261883529b6Schristos		const char **strp,
262883529b6Schristos		int opindex,
263883529b6Schristos		long *valuep)
264883529b6Schristos{
265883529b6Schristos  return parse_lo16 (cd, strp, opindex, valuep, 1);
266883529b6Schristos}
267883529b6Schristos
268883529b6Schristosstatic const char *
269883529b6Schristosparse_lo16 (CGEN_CPU_DESC cd,
270883529b6Schristos	    const char **strp,
271883529b6Schristos	    int opindex,
272883529b6Schristos	    long *valuep,
273883529b6Schristos	    long signedp)
274883529b6Schristos{
275883529b6Schristos  const char *errmsg;
276883529b6Schristos  enum cgen_parse_operand_result result_type;
277883529b6Schristos  bfd_vma value;
278883529b6Schristos
279883529b6Schristos  if (strncasecmp (*strp, "%lo(", 4) == 0)
280883529b6Schristos    {
281883529b6Schristos      *strp += 4;
282883529b6Schristos      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_LOW16,
283883529b6Schristos				   & result_type, & value);
284883529b6Schristos      if (**strp != ')')
285883529b6Schristos	return _("missing `)'");
286883529b6Schristos      ++*strp;
287883529b6Schristos      if (errmsg == NULL
288883529b6Schristos	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
289883529b6Schristos	value &= 0xffff;
290883529b6Schristos      if (signedp)
291883529b6Schristos	*valuep = (long)(short) value;
292883529b6Schristos      else
293883529b6Schristos	*valuep = value;
294883529b6Schristos      return errmsg;
295883529b6Schristos    }
296883529b6Schristos
297883529b6Schristos  if (strncasecmp (*strp, "%hi(", 4) == 0)
298883529b6Schristos    {
299883529b6Schristos      *strp += 4;
300883529b6Schristos      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16S,
301883529b6Schristos				   & result_type, & value);
302883529b6Schristos      if (**strp != ')')
303883529b6Schristos	return _("missing `)'");
304883529b6Schristos      ++*strp;
305883529b6Schristos      if (errmsg == NULL
306883529b6Schristos	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
307883529b6Schristos	value = (value + 0x8000) >> 16;
308883529b6Schristos      *valuep = value;
309883529b6Schristos      return errmsg;
310883529b6Schristos    }
311883529b6Schristos
312883529b6Schristos  if (strncasecmp (*strp, "%uhi(", 5) == 0)
313883529b6Schristos    {
314883529b6Schristos      *strp += 5;
315883529b6Schristos      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16U,
316883529b6Schristos				   & result_type, & value);
317883529b6Schristos      if (**strp != ')')
318883529b6Schristos	return _("missing `)'");
319883529b6Schristos      ++*strp;
320883529b6Schristos      if (errmsg == NULL
321883529b6Schristos	  && result_type == CGEN_PARSE_OPERAND_RESULT_NUMBER)
322883529b6Schristos	value = value >> 16;
323883529b6Schristos      *valuep = value;
324883529b6Schristos      return errmsg;
325883529b6Schristos    }
326883529b6Schristos
327883529b6Schristos  if (strncasecmp (*strp, "%sdaoff(", 8) == 0)
328883529b6Schristos    {
329883529b6Schristos      *strp += 8;
330883529b6Schristos      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_GPREL,
331883529b6Schristos				   NULL, & value);
332883529b6Schristos      if (**strp != ')')
333883529b6Schristos	return _("missing `)'");
334883529b6Schristos      ++*strp;
335883529b6Schristos      *valuep = value;
336883529b6Schristos      return errmsg;
337883529b6Schristos    }
338883529b6Schristos
339883529b6Schristos  if (strncasecmp (*strp, "%tpoff(", 7) == 0)
340883529b6Schristos    {
341883529b6Schristos      *strp += 7;
342883529b6Schristos      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_TPREL,
343883529b6Schristos				   NULL, & value);
344883529b6Schristos      if (**strp != ')')
345883529b6Schristos	return _("missing `)'");
346883529b6Schristos      ++*strp;
347883529b6Schristos      *valuep = value;
348883529b6Schristos      return errmsg;
349883529b6Schristos    }
350883529b6Schristos
351883529b6Schristos  if (**strp == '%')
352883529b6Schristos    return _("invalid %function() here");
353883529b6Schristos
354883529b6Schristos  return cgen_parse_signed_integer (cd, strp, opindex, valuep);
355883529b6Schristos}
356883529b6Schristos
357883529b6Schristosstatic const char *
358883529b6Schristosparse_unsigned16 (CGEN_CPU_DESC cd,
359883529b6Schristos		  const char **strp,
360883529b6Schristos		  int opindex,
361883529b6Schristos		  unsigned long *valuep)
362883529b6Schristos{
363883529b6Schristos  return parse_lo16 (cd, strp, opindex, (long *) valuep, 0);
364883529b6Schristos}
365883529b6Schristos
366883529b6Schristosstatic const char *
367883529b6Schristosparse_signed16_range (CGEN_CPU_DESC cd,
368883529b6Schristos		      const char **strp,
369883529b6Schristos		      int opindex,
370883529b6Schristos		      signed long *valuep)
371883529b6Schristos{
372883529b6Schristos  const char *errmsg = 0;
373883529b6Schristos  signed long value;
374883529b6Schristos
375883529b6Schristos  errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
376883529b6Schristos  if (errmsg)
377883529b6Schristos    return errmsg;
378883529b6Schristos
379883529b6Schristos  if (value < -32768 || value > 32767)
380883529b6Schristos    return _("Immediate is out of range -32768 to 32767");
381883529b6Schristos
382883529b6Schristos  *valuep = value;
383883529b6Schristos  return 0;
384883529b6Schristos}
385883529b6Schristos
386883529b6Schristosstatic const char *
387883529b6Schristosparse_unsigned16_range (CGEN_CPU_DESC cd,
388883529b6Schristos			const char **strp,
389883529b6Schristos			int opindex,
390883529b6Schristos			unsigned long *valuep)
391883529b6Schristos{
392883529b6Schristos  const char *errmsg = 0;
393883529b6Schristos  unsigned long value;
394883529b6Schristos
395883529b6Schristos  errmsg = cgen_parse_unsigned_integer (cd, strp, opindex, & value);
396883529b6Schristos  if (errmsg)
397883529b6Schristos    return errmsg;
398883529b6Schristos
399883529b6Schristos  if (value > 65535)
400883529b6Schristos    return _("Immediate is out of range 0 to 65535");
401883529b6Schristos
402883529b6Schristos  *valuep = value;
403883529b6Schristos  return 0;
404883529b6Schristos}
405883529b6Schristos
406883529b6Schristos/* A special case of parse_signed16 which accepts only the value zero.  */
407883529b6Schristos
408883529b6Schristosstatic const char *
409883529b6Schristosparse_zero (CGEN_CPU_DESC cd, const char **strp, int opindex, long *valuep)
410883529b6Schristos{
411883529b6Schristos  const char *errmsg;
412883529b6Schristos  enum cgen_parse_operand_result result_type;
413883529b6Schristos  bfd_vma value;
414883529b6Schristos
415883529b6Schristos  /*fprintf(stderr, "dj: signed parse opindex `%s'\n", *strp);*/
416883529b6Schristos
417883529b6Schristos  /* Prevent ($ry) from being attempted as an expression on 'sw $rx,($ry)'.
418883529b6Schristos     It will fail and cause ry to be listed as an undefined symbol in the
419883529b6Schristos     listing.  */
420883529b6Schristos  if (strncmp (*strp, "($", 2) == 0)
421883529b6Schristos    return "not zero"; /* any string will do -- will never be seen.  */
422883529b6Schristos
423883529b6Schristos  if (strncasecmp (*strp, "%lo(", 4) == 0)
424883529b6Schristos    {
425883529b6Schristos      *strp += 4;
426883529b6Schristos      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_LOW16,
427883529b6Schristos				   &result_type, &value);
428883529b6Schristos      if (**strp != ')')
429883529b6Schristos	return "missing `)'";
430883529b6Schristos      ++*strp;
431883529b6Schristos      if (errmsg == NULL
432883529b6Schristos	  && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
433883529b6Schristos	return "not zero"; /* any string will do -- will never be seen.  */
434883529b6Schristos      *valuep = value;
435883529b6Schristos      return errmsg;
436883529b6Schristos    }
437883529b6Schristos
438883529b6Schristos  if (strncasecmp (*strp, "%hi(", 4) == 0)
439883529b6Schristos    {
440883529b6Schristos      *strp += 4;
441883529b6Schristos      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16S,
442883529b6Schristos				   &result_type, &value);
443883529b6Schristos      if (**strp != ')')
444883529b6Schristos	return "missing `)'";
445883529b6Schristos      ++*strp;
446883529b6Schristos      if (errmsg == NULL
447883529b6Schristos	  && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
448883529b6Schristos	return "not zero"; /* any string will do -- will never be seen.  */
449883529b6Schristos      *valuep = value;
450883529b6Schristos      return errmsg;
451883529b6Schristos    }
452883529b6Schristos
453883529b6Schristos  if (strncasecmp (*strp, "%uhi(", 5) == 0)
454883529b6Schristos    {
455883529b6Schristos      *strp += 5;
456883529b6Schristos      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_HI16U,
457883529b6Schristos				   &result_type, &value);
458883529b6Schristos      if (**strp != ')')
459883529b6Schristos	return "missing `)'";
460883529b6Schristos      ++*strp;
461883529b6Schristos      if (errmsg == NULL
462883529b6Schristos	  && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
463883529b6Schristos	return "not zero"; /* any string will do -- will never be seen.  */
464883529b6Schristos      *valuep = value;
465883529b6Schristos      return errmsg;
466883529b6Schristos    }
467883529b6Schristos
468883529b6Schristos  if (strncasecmp (*strp, "%sdaoff(", 8) == 0)
469883529b6Schristos    {
470883529b6Schristos      *strp += 8;
471883529b6Schristos      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_GPREL,
472883529b6Schristos				   &result_type, &value);
473883529b6Schristos      if (**strp != ')')
474883529b6Schristos	return "missing `)'";
475883529b6Schristos      ++*strp;
476883529b6Schristos      if (errmsg == NULL
477883529b6Schristos	  && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
478883529b6Schristos	return "not zero"; /* any string will do -- will never be seen.  */
479883529b6Schristos      *valuep = value;
480883529b6Schristos      return errmsg;
481883529b6Schristos    }
482883529b6Schristos
483883529b6Schristos  if (strncasecmp (*strp, "%tpoff(", 7) == 0)
484883529b6Schristos    {
485883529b6Schristos      *strp += 7;
486883529b6Schristos      errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_MEP_TPREL,
487883529b6Schristos				   &result_type, &value);
488883529b6Schristos      if (**strp != ')')
489883529b6Schristos	return "missing `)'";
490883529b6Schristos      ++*strp;
491883529b6Schristos      if (errmsg == NULL
492883529b6Schristos	  && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
493883529b6Schristos	return "not zero"; /* any string will do -- will never be seen.  */
494883529b6Schristos      *valuep = value;
495883529b6Schristos      return errmsg;
496883529b6Schristos    }
497883529b6Schristos
498883529b6Schristos  if (**strp == '%')
499883529b6Schristos    return "invalid %function() here";
500883529b6Schristos
501883529b6Schristos  errmsg = cgen_parse_address (cd, strp, opindex, BFD_RELOC_NONE,
502883529b6Schristos			       &result_type, &value);
503883529b6Schristos  if (errmsg == NULL
504883529b6Schristos      && (result_type != CGEN_PARSE_OPERAND_RESULT_NUMBER || value != 0))
505883529b6Schristos    return "not zero"; /* any string will do -- will never be seen.  */
506883529b6Schristos
507883529b6Schristos  return errmsg;
508883529b6Schristos}
509883529b6Schristos
510883529b6Schristosstatic const char *
511883529b6Schristosparse_unsigned7 (CGEN_CPU_DESC cd, const char **strp,
512883529b6Schristos		 enum cgen_operand_type opindex, unsigned long *valuep)
513883529b6Schristos{
514883529b6Schristos  const char *errmsg;
515883529b6Schristos  bfd_vma value;
516883529b6Schristos
517883529b6Schristos  /* fprintf(stderr, "dj: unsigned7 parse `%s'\n", *strp); */
518883529b6Schristos
519883529b6Schristos  if (strncasecmp (*strp, "%tpoff(", 7) == 0)
520883529b6Schristos    {
521883529b6Schristos      int reloc;
522883529b6Schristos      *strp += 7;
523883529b6Schristos      switch (opindex)
524883529b6Schristos	{
525883529b6Schristos	case MEP_OPERAND_UDISP7:
526883529b6Schristos	  reloc = BFD_RELOC_MEP_TPREL7;
527883529b6Schristos	  break;
528883529b6Schristos	case MEP_OPERAND_UDISP7A2:
529883529b6Schristos	  reloc = BFD_RELOC_MEP_TPREL7A2;
530883529b6Schristos	  break;
531883529b6Schristos	case MEP_OPERAND_UDISP7A4:
532883529b6Schristos	  reloc = BFD_RELOC_MEP_TPREL7A4;
533883529b6Schristos	  break;
534883529b6Schristos	default:
535883529b6Schristos	  /* Safe assumption?  */
536883529b6Schristos	  abort ();
537883529b6Schristos	}
538883529b6Schristos      errmsg = cgen_parse_address (cd, strp, opindex, reloc,
539883529b6Schristos				   NULL, &value);
540883529b6Schristos      if (**strp != ')')
541883529b6Schristos	return "missing `)'";
542883529b6Schristos      ++*strp;
543883529b6Schristos      *valuep = value;
544883529b6Schristos      return errmsg;
545883529b6Schristos    }
546883529b6Schristos
547883529b6Schristos  if (**strp == '%')
548883529b6Schristos    return _("invalid %function() here");
549883529b6Schristos
550883529b6Schristos  return parse_mep_alignu (cd, strp, opindex, valuep);
551883529b6Schristos}
552883529b6Schristos
553883529b6Schristosstatic ATTRIBUTE_UNUSED const char *
554883529b6Schristosparse_cdisp10 (CGEN_CPU_DESC cd,
555883529b6Schristos	       const char **strp,
556883529b6Schristos	       int opindex,
557883529b6Schristos	       long *valuep)
558883529b6Schristos{
559883529b6Schristos  const char *errmsg = 0;
560883529b6Schristos  signed long value;
561883529b6Schristos  long have_zero = 0;
562883529b6Schristos  int wide = 0;
563883529b6Schristos  int alignment;
564883529b6Schristos
565883529b6Schristos  switch (opindex)
566883529b6Schristos    {
567883529b6Schristos    case MEP_OPERAND_CDISP10A4:
568883529b6Schristos      alignment = 2;
569883529b6Schristos      break;
570883529b6Schristos    case MEP_OPERAND_CDISP10A2:
571883529b6Schristos      alignment = 1;
572883529b6Schristos      break;
573883529b6Schristos    case MEP_OPERAND_CDISP10:
574883529b6Schristos    default:
575883529b6Schristos      alignment = 0;
576883529b6Schristos      break;
577883529b6Schristos    }
578883529b6Schristos
579883529b6Schristos  if ((MEP_CPU & EF_MEP_CPU_MASK) == EF_MEP_CPU_C5)
580883529b6Schristos    wide = 1;
581883529b6Schristos
582883529b6Schristos  if (strncmp (*strp, "0x0", 3) == 0
583883529b6Schristos      || (**strp == '0' && *(*strp + 1) != 'x'))
584883529b6Schristos    have_zero = 1;
585883529b6Schristos
586883529b6Schristos  errmsg = cgen_parse_signed_integer (cd, strp, opindex, & value);
587883529b6Schristos  if (errmsg)
588883529b6Schristos    return errmsg;
589883529b6Schristos
590883529b6Schristos  if (wide)
591883529b6Schristos    {
592883529b6Schristos      if (value < -512 || value > 511)
593883529b6Schristos	return _("Immediate is out of range -512 to 511");
594883529b6Schristos    }
595883529b6Schristos  else
596883529b6Schristos    {
597883529b6Schristos      if (value < -128 || value > 127)
598883529b6Schristos	return _("Immediate is out of range -128 to 127");
599883529b6Schristos    }
600883529b6Schristos
601883529b6Schristos  if (value & ((1<<alignment)-1))
602883529b6Schristos    return _("Value is not aligned enough");
603883529b6Schristos
604883529b6Schristos  /* If this field may require a relocation then use larger dsp16.  */
605883529b6Schristos  if (! have_zero && value == 0)
606883529b6Schristos    return (wide ? _("Immediate is out of range -512 to 511")
607883529b6Schristos	    : _("Immediate is out of range -128 to 127"));
608883529b6Schristos
609883529b6Schristos  *valuep = value;
610883529b6Schristos  return 0;
611883529b6Schristos}
612883529b6Schristos
613883529b6Schristos/* BEGIN LIGHTWEIGHT MACRO PROCESSOR.  */
614883529b6Schristos
615883529b6Schristos#define MAXARGS 9
616883529b6Schristos
617883529b6Schristostypedef struct
618883529b6Schristos{
619883529b6Schristos  char *name;
620883529b6Schristos  char *expansion;
621883529b6Schristos}  macro;
622883529b6Schristos
623883529b6Schristostypedef struct
624883529b6Schristos{
625883529b6Schristos  const char *start;
626883529b6Schristos  int len;
627883529b6Schristos} arg;
628883529b6Schristos
6294f645668Schristosstatic macro const macros[] =
630883529b6Schristos{
631883529b6Schristos  { "sizeof", "(`1.end + (- `1))"},
632883529b6Schristos  { "startof", "(`1 | 0)" },
633883529b6Schristos  { "align4", "(`1&(~3))"},
634883529b6Schristos/*{ "hi", "(((`1+0x8000)>>16) & 0xffff)" },  */
635883529b6Schristos/*{ "lo", "(`1 & 0xffff)" },  */
636883529b6Schristos/*{ "sdaoff", "((`1-__sdabase) & 0x7f)"},  */
637883529b6Schristos/*{ "tpoff", "((`1-__tpbase) & 0x7f)"},  */
638883529b6Schristos  { 0,0 }
639883529b6Schristos};
640883529b6Schristos
641883529b6Schristosstatic char  * expand_string    (const char *, int);
642883529b6Schristos
643883529b6Schristosstatic const char *
644883529b6Schristosmep_cgen_expand_macros_and_parse_operand
645883529b6Schristos  (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
646883529b6Schristos
647883529b6Schristosstatic char *
648883529b6Schristosstr_append (char *dest, const char *input, int len)
649883529b6Schristos{
650883529b6Schristos  char *new_dest;
651883529b6Schristos  int oldlen;
652883529b6Schristos
653883529b6Schristos  if (len == 0)
654883529b6Schristos    return dest;
655883529b6Schristos  /* printf("str_append: <<%s>>, <<%s>>, %d\n", dest, input, len); */
656883529b6Schristos  oldlen = (dest ? strlen(dest) : 0);
657883529b6Schristos  new_dest = realloc (dest, oldlen + len + 1);
658883529b6Schristos  memset (new_dest + oldlen, 0, len + 1);
659883529b6Schristos  return strncat (new_dest, input, len);
660883529b6Schristos}
661883529b6Schristos
6624f645668Schristosstatic const macro *
663883529b6Schristoslookup_macro (const char *name)
664883529b6Schristos{
6654f645668Schristos  const macro *m;
666883529b6Schristos
667883529b6Schristos  for (m = macros; m->name; ++m)
668883529b6Schristos    if (strncmp (m->name, name, strlen(m->name)) == 0)
669883529b6Schristos      return m;
670883529b6Schristos
671883529b6Schristos  return 0;
672883529b6Schristos}
673883529b6Schristos
674883529b6Schristosstatic char *
6754f645668Schristosexpand_macro (arg *args, int narg, const macro *mac)
676883529b6Schristos{
677883529b6Schristos  char *result = 0, *rescanned_result = 0;
678883529b6Schristos  char *e = mac->expansion;
679883529b6Schristos  char *mark = e;
680883529b6Schristos  int mac_arg = 0;
681883529b6Schristos
682883529b6Schristos  /*  printf("expanding macro %s with %d args\n", mac->name, narg + 1); */
683883529b6Schristos  while (*e)
684883529b6Schristos    {
685*cb63e24eSchristos      if (*e == '`'
686*cb63e24eSchristos	  && (*e+1)
687*cb63e24eSchristos	  && ((*(e + 1) - '1') <= MAXARGS)
688*cb63e24eSchristos	  && ((*(e + 1) - '1') <= narg))
689883529b6Schristos	{
690883529b6Schristos	  result = str_append (result, mark, e - mark);
691883529b6Schristos	  mac_arg = (*(e + 1) - '1');
692883529b6Schristos	  /* printf("replacing `%d with %s\n", mac_arg+1, args[mac_arg].start); */
693883529b6Schristos	  result = str_append (result, args[mac_arg].start, args[mac_arg].len);
694883529b6Schristos	  ++e;
695883529b6Schristos	  mark = e+1;
696883529b6Schristos	}
697883529b6Schristos      ++e;
698883529b6Schristos    }
699883529b6Schristos
700883529b6Schristos  if (mark != e)
701883529b6Schristos    result = str_append (result, mark, e - mark);
702883529b6Schristos
703883529b6Schristos  if (result)
704883529b6Schristos    {
705883529b6Schristos      rescanned_result = expand_string (result, 0);
706883529b6Schristos      free (result);
707883529b6Schristos      return rescanned_result;
708883529b6Schristos    }
709883529b6Schristos  else
710883529b6Schristos    return result;
711883529b6Schristos}
712883529b6Schristos
713883529b6Schristos#define IN_TEXT 0
714883529b6Schristos#define IN_ARGS 1
715883529b6Schristos
716883529b6Schristosstatic char *
717883529b6Schristosexpand_string (const char *in, int first_only)
718883529b6Schristos{
719883529b6Schristos  int num_expansions = 0;
720883529b6Schristos  int depth = 0;
721883529b6Schristos  int narg = -1;
722883529b6Schristos  arg args[MAXARGS];
723883529b6Schristos  int state = IN_TEXT;
724883529b6Schristos  const char *mark = in;
7254f645668Schristos  const macro *pmacro = NULL;
726883529b6Schristos  char *expansion = 0;
727883529b6Schristos  char *result = 0;
728883529b6Schristos
729883529b6Schristos  while (*in)
730883529b6Schristos    {
731883529b6Schristos      switch (state)
732883529b6Schristos	{
733883529b6Schristos	case IN_TEXT:
734883529b6Schristos	  if (*in == '%' && *(in + 1) && (!first_only || num_expansions == 0))
735883529b6Schristos	    {
736883529b6Schristos	      pmacro = lookup_macro (in + 1);
737883529b6Schristos	      if (pmacro)
738883529b6Schristos		{
739883529b6Schristos		  /* printf("entering state %d at '%s'...\n", state, in); */
740883529b6Schristos		  result = str_append (result, mark, in - mark);
741883529b6Schristos		  mark = in;
742883529b6Schristos		  in += 1 + strlen (pmacro->name);
743883529b6Schristos		  while (*in == ' ') ++in;
744883529b6Schristos		  if (*in != '(')
745883529b6Schristos		    {
746883529b6Schristos		      state = IN_TEXT;
747883529b6Schristos		      pmacro = NULL;
748883529b6Schristos		    }
749883529b6Schristos		  else
750883529b6Schristos		    {
751883529b6Schristos		      state = IN_ARGS;
752883529b6Schristos		      narg = 0;
753883529b6Schristos		      args[narg].start = in + 1;
754883529b6Schristos		      args[narg].len = 0;
755883529b6Schristos		      mark = in + 1;
756883529b6Schristos		    }
757883529b6Schristos		}
758883529b6Schristos	    }
759883529b6Schristos	  break;
760883529b6Schristos	case IN_ARGS:
761883529b6Schristos	  if (depth == 0)
762883529b6Schristos	    {
763883529b6Schristos	      switch (*in)
764883529b6Schristos		{
765883529b6Schristos		case ',':
766883529b6Schristos		  narg++;
767883529b6Schristos		  args[narg].start = (in + 1);
768883529b6Schristos		  args[narg].len = 0;
769883529b6Schristos		  break;
770883529b6Schristos		case ')':
771883529b6Schristos		  state = IN_TEXT;
772883529b6Schristos		  /* printf("entering state %d at '%s'...\n", state, in); */
773883529b6Schristos		  if (pmacro)
774883529b6Schristos		    {
775883529b6Schristos		      expansion = 0;
776883529b6Schristos		      expansion = expand_macro (args, narg, pmacro);
777883529b6Schristos		      num_expansions++;
778883529b6Schristos		      if (expansion)
779883529b6Schristos			{
780883529b6Schristos			  result = str_append (result, expansion, strlen (expansion));
781883529b6Schristos			  free (expansion);
782883529b6Schristos			}
783883529b6Schristos		    }
784883529b6Schristos		  else
785883529b6Schristos		    {
786883529b6Schristos		      result = str_append (result, mark, in - mark);
787883529b6Schristos		    }
788883529b6Schristos		  pmacro = NULL;
789883529b6Schristos		  mark = in + 1;
790883529b6Schristos		  break;
791883529b6Schristos		case '(':
792883529b6Schristos		  depth++;
793fc4f4269Schristos		  /* Fall through.  */
794883529b6Schristos		default:
795883529b6Schristos		  args[narg].len++;
796883529b6Schristos		  break;
797883529b6Schristos		}
798883529b6Schristos	    }
799883529b6Schristos	  else
800883529b6Schristos	    {
801883529b6Schristos	      if (*in == ')')
802883529b6Schristos		depth--;
803883529b6Schristos	      if (narg > -1)
804883529b6Schristos		args[narg].len++;
805883529b6Schristos	    }
806883529b6Schristos	}
807883529b6Schristos      ++in;
808883529b6Schristos    }
809883529b6Schristos
810883529b6Schristos  if (mark != in)
811883529b6Schristos    result = str_append (result, mark, in - mark);
812883529b6Schristos
813883529b6Schristos  return result;
814883529b6Schristos}
815883529b6Schristos
816883529b6Schristos#undef IN_ARGS
817883529b6Schristos#undef IN_TEXT
818883529b6Schristos#undef MAXARGS
819883529b6Schristos
820883529b6Schristos
821883529b6Schristos/* END LIGHTWEIGHT MACRO PROCESSOR.  */
822883529b6Schristos
823883529b6Schristosconst char * mep_cgen_parse_operand
824883529b6Schristos  (CGEN_CPU_DESC, int, const char **, CGEN_FIELDS *);
825883529b6Schristos
826883529b6Schristosconst char *
827883529b6Schristosmep_cgen_expand_macros_and_parse_operand (CGEN_CPU_DESC cd, int opindex,
828883529b6Schristos					  const char ** strp_in, CGEN_FIELDS * fields)
829883529b6Schristos{
830883529b6Schristos  const char * errmsg = NULL;
831883529b6Schristos  char *str = 0, *hold = 0;
832883529b6Schristos  const char **strp = 0;
833883529b6Schristos
834883529b6Schristos  /* Set up a new pointer to macro-expanded string.  */
835883529b6Schristos  str = expand_string (*strp_in, 1);
836883529b6Schristos  /* fprintf (stderr, " expanded <<%s>> to <<%s>>\n", *strp_in, str); */
837883529b6Schristos
838883529b6Schristos  hold = str;
839883529b6Schristos  strp = (const char **)(&str);
840883529b6Schristos
841883529b6Schristos  errmsg = mep_cgen_parse_operand (cd, opindex, strp, fields);
842883529b6Schristos
843883529b6Schristos  /* Now work out the advance.  */
844883529b6Schristos  if (strlen (str) == 0)
845883529b6Schristos    *strp_in += strlen (*strp_in);
846883529b6Schristos
847883529b6Schristos  else
848883529b6Schristos    {
849883529b6Schristos      if (strstr (*strp_in, str))
850883529b6Schristos	/* A macro-expansion was pulled off the front.  */
851883529b6Schristos	*strp_in = strstr (*strp_in, str);
852883529b6Schristos      else
853883529b6Schristos	/* A non-macro-expansion was pulled off the front.  */
854883529b6Schristos	*strp_in += (str - hold);
855883529b6Schristos    }
856883529b6Schristos
857883529b6Schristos  free (hold);
858883529b6Schristos
859883529b6Schristos  return errmsg;
860883529b6Schristos}
861883529b6Schristos
862883529b6Schristos#define CGEN_ASM_INIT_HOOK (cd->parse_operand = mep_cgen_expand_macros_and_parse_operand);
863883529b6Schristos
864883529b6Schristos/* -- dis.c */
865883529b6Schristos
866883529b6Schristos#include "elf/mep.h"
867883529b6Schristos#include "elf-bfd.h"
868883529b6Schristos
869883529b6Schristos#define CGEN_VALIDATE_INSN_SUPPORTED
870883529b6Schristos
871883529b6Schristosstatic void
8724f645668Schristosprint_tpreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, void *dis_info,
873883529b6Schristos	     CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
874883529b6Schristos	     unsigned int flags ATTRIBUTE_UNUSED)
875883529b6Schristos{
876883529b6Schristos  disassemble_info *info = (disassemble_info *) dis_info;
877883529b6Schristos
878883529b6Schristos  (*info->fprintf_func) (info->stream, "$tp");
879883529b6Schristos}
880883529b6Schristos
881883529b6Schristosstatic void
8824f645668Schristosprint_spreg (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, void *dis_info,
883883529b6Schristos	     CGEN_KEYWORD *table ATTRIBUTE_UNUSED, long val ATTRIBUTE_UNUSED,
884883529b6Schristos	     unsigned int flags ATTRIBUTE_UNUSED)
885883529b6Schristos{
886883529b6Schristos  disassemble_info *info = (disassemble_info *) dis_info;
887883529b6Schristos
888883529b6Schristos  (*info->fprintf_func) (info->stream, "$sp");
889883529b6Schristos}
890883529b6Schristos
891883529b6Schristos/* begin-cop-ip-print-handlers */
892883529b6Schristosstatic void
893883529b6Schristosprint_ivc2_cr (CGEN_CPU_DESC,
894883529b6Schristos	void *,
895883529b6Schristos	CGEN_KEYWORD *,
896883529b6Schristos	long,
897883529b6Schristos	unsigned int) ATTRIBUTE_UNUSED;
898883529b6Schristosstatic void
899883529b6Schristosprint_ivc2_cr (CGEN_CPU_DESC cd,
900883529b6Schristos	void *dis_info,
901883529b6Schristos	CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
902883529b6Schristos	long value,
903883529b6Schristos	unsigned int attrs)
904883529b6Schristos{
905883529b6Schristos  print_keyword (cd, dis_info, & mep_cgen_opval_h_cr_ivc2, value, attrs);
906883529b6Schristos}
907883529b6Schristosstatic void
908883529b6Schristosprint_ivc2_ccr (CGEN_CPU_DESC,
909883529b6Schristos	void *,
910883529b6Schristos	CGEN_KEYWORD *,
911883529b6Schristos	long,
912883529b6Schristos	unsigned int) ATTRIBUTE_UNUSED;
913883529b6Schristosstatic void
914883529b6Schristosprint_ivc2_ccr (CGEN_CPU_DESC cd,
915883529b6Schristos	void *dis_info,
916883529b6Schristos	CGEN_KEYWORD *keyword_table ATTRIBUTE_UNUSED,
917883529b6Schristos	long value,
918883529b6Schristos	unsigned int attrs)
919883529b6Schristos{
920883529b6Schristos  print_keyword (cd, dis_info, & mep_cgen_opval_h_ccr_ivc2, value, attrs);
921883529b6Schristos}
922883529b6Schristos/* end-cop-ip-print-handlers */
923883529b6Schristos
924883529b6Schristos/************************************************************\
925883529b6Schristos*********************** Experimental *************************
926883529b6Schristos\************************************************************/
927883529b6Schristos
928883529b6Schristos#undef  CGEN_PRINT_INSN
929883529b6Schristos#define CGEN_PRINT_INSN mep_print_insn
930883529b6Schristos
931883529b6Schristosstatic int
932883529b6Schristosmep_print_vliw_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info,
933883529b6Schristos		      bfd_byte *buf, int corelength, int copro1length,
934883529b6Schristos		      int copro2length ATTRIBUTE_UNUSED)
935883529b6Schristos{
936883529b6Schristos  int i;
937883529b6Schristos  int status = 0;
938883529b6Schristos  /* char insnbuf[CGEN_MAX_INSN_SIZE]; */
939883529b6Schristos  bfd_byte insnbuf[64];
940883529b6Schristos
941883529b6Schristos  /* If corelength > 0 then there is a core insn present. It
942883529b6Schristos     will be at the beginning of the buffer.  After printing
943883529b6Schristos     the core insn, we need to print the + on the next line.  */
944883529b6Schristos  if (corelength > 0)
945883529b6Schristos    {
946883529b6Schristos      int my_status = 0;
947883529b6Schristos
948883529b6Schristos      for (i = 0; i < corelength; i++ )
949883529b6Schristos	insnbuf[i] = buf[i];
950883529b6Schristos      cd->isas = & MEP_CORE_ISA;
951883529b6Schristos
952883529b6Schristos      my_status = print_insn (cd, pc, info, insnbuf, corelength);
953883529b6Schristos      if (my_status != corelength)
954883529b6Schristos	{
955883529b6Schristos	  (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
956883529b6Schristos	  my_status = corelength;
957883529b6Schristos	}
958883529b6Schristos      status += my_status;
959883529b6Schristos
960*cb63e24eSchristos      /* Print the + to indicate that the following copro insn is
961*cb63e24eSchristos	 part of a vliw group.  */
962883529b6Schristos      if (copro1length > 0)
963883529b6Schristos	(*info->fprintf_func) (info->stream, " + ");
964883529b6Schristos    }
965883529b6Schristos
966883529b6Schristos  /* Now all that is left to be processed is the coprocessor insns
967883529b6Schristos     In vliw mode, there will always be one.  Its positioning will
968883529b6Schristos     be from byte corelength to byte corelength+copro1length -1.
969883529b6Schristos     No need to check for existence.   Also, the first vliw insn,
970883529b6Schristos     will, as spec'd, always be at least as long as the core insn
971883529b6Schristos     so we don't need to flush the buffer.  */
972883529b6Schristos  if (copro1length > 0)
973883529b6Schristos    {
974883529b6Schristos      int my_status = 0;
975883529b6Schristos
976883529b6Schristos      for (i = corelength; i < corelength + copro1length; i++ )
977883529b6Schristos	insnbuf[i - corelength] = buf[i];
978883529b6Schristos
979883529b6Schristos      switch (copro1length)
980883529b6Schristos	{
981883529b6Schristos	case 0:
982883529b6Schristos	  break;
983883529b6Schristos	case 2:
984883529b6Schristos	  cd->isas = & MEP_COP16_ISA;
985883529b6Schristos	  break;
986883529b6Schristos	case 4:
987883529b6Schristos	  cd->isas = & MEP_COP32_ISA;
988883529b6Schristos	  break;
989883529b6Schristos	case 6:
990883529b6Schristos	  cd->isas = & MEP_COP48_ISA;
991883529b6Schristos	  break;
992883529b6Schristos	case 8:
993883529b6Schristos	  cd->isas = & MEP_COP64_ISA;
994883529b6Schristos	  break;
995883529b6Schristos	default:
996883529b6Schristos	  /* Shouldn't be anything but 16,32,48,64.  */
997883529b6Schristos	  break;
998883529b6Schristos	}
999883529b6Schristos
1000883529b6Schristos      my_status = print_insn (cd, pc, info, insnbuf, copro1length);
1001883529b6Schristos
1002883529b6Schristos      if (my_status != copro1length)
1003883529b6Schristos	{
1004883529b6Schristos	  (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
1005883529b6Schristos	  my_status = copro1length;
1006883529b6Schristos	}
1007883529b6Schristos      status += my_status;
1008883529b6Schristos    }
1009883529b6Schristos
1010883529b6Schristos#if 0
1011883529b6Schristos  /* Now we need to process the second copro insn if it exists. We
1012883529b6Schristos     have no guarantee that the second copro insn will be longer
1013883529b6Schristos     than the first, so we have to flush the buffer if we are have
1014883529b6Schristos     a second copro insn to process.  If present, this insn will
1015883529b6Schristos     be in the position from byte corelength+copro1length to byte
1016883529b6Schristos     corelength+copro1length+copro2length-1 (which better equal 8
1017883529b6Schristos     or else we're in big trouble.  */
1018883529b6Schristos  if (copro2length > 0)
1019883529b6Schristos    {
1020883529b6Schristos      int my_status = 0;
1021883529b6Schristos
1022883529b6Schristos      for (i = 0; i < 64 ; i++)
1023883529b6Schristos	insnbuf[i] = 0;
1024883529b6Schristos
1025883529b6Schristos      for (i = corelength + copro1length; i < 64; i++)
1026883529b6Schristos	insnbuf[i - (corelength + copro1length)] = buf[i];
1027883529b6Schristos
1028883529b6Schristos      switch (copro2length)
1029883529b6Schristos	{
1030883529b6Schristos	case 2:
1031883529b6Schristos	  cd->isas = 1 << ISA_EXT_COP1_16;
1032883529b6Schristos	  break;
1033883529b6Schristos	case 4:
1034883529b6Schristos	  cd->isas = 1 << ISA_EXT_COP1_32;
1035883529b6Schristos	  break;
1036883529b6Schristos	case 6:
1037883529b6Schristos	  cd->isas = 1 << ISA_EXT_COP1_48;
1038883529b6Schristos	  break;
1039883529b6Schristos	case 8:
1040883529b6Schristos	  cd->isas = 1 << ISA_EXT_COP1_64;
1041883529b6Schristos	  break;
1042883529b6Schristos	default:
1043883529b6Schristos	  /* Shouldn't be anything but 16,32,48,64.  */
1044883529b6Schristos	  break;
1045883529b6Schristos	}
1046883529b6Schristos
1047883529b6Schristos      my_status = print_insn (cd, pc, info, insnbuf, copro2length);
1048883529b6Schristos
1049883529b6Schristos      if (my_status != copro2length)
1050883529b6Schristos	{
1051883529b6Schristos	  (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
1052883529b6Schristos	  my_status = copro2length;
1053883529b6Schristos	}
1054883529b6Schristos
1055883529b6Schristos      status += my_status;
1056883529b6Schristos    }
1057883529b6Schristos#endif
1058883529b6Schristos
1059883529b6Schristos  /* Status should now be the number of bytes that were printed
1060883529b6Schristos     which should be 4 for VLIW32 mode and 64 for VLIW64 mode.  */
1061883529b6Schristos
1062883529b6Schristos  if ((!MEP_VLIW64 && (status != 4)) || (MEP_VLIW64 && (status != 8)))
1063883529b6Schristos    return -1;
1064883529b6Schristos  else
1065883529b6Schristos    return status;
1066883529b6Schristos}
1067883529b6Schristos
1068883529b6Schristos/* The two functions mep_examine_vliw[32,64]_insns are used find out
1069883529b6Schristos   which vliw combinaion (16 bit core with 48 bit copro, 32 bit core
1070883529b6Schristos   with 32 bit copro, etc.) is present.  Later on, when internally
1071883529b6Schristos   parallel coprocessors are handled, only these functions should
1072883529b6Schristos   need to be changed.
1073883529b6Schristos
1074883529b6Schristos   At this time only the following combinations are supported:
1075883529b6Schristos
1076883529b6Schristos   VLIW32 Mode:
1077883529b6Schristos   16 bit core insn (core) and 16 bit coprocessor insn (cop1)
1078883529b6Schristos   32 bit core insn (core)
1079883529b6Schristos   32 bit coprocessor insn (cop1)
1080883529b6Schristos   Note: As of this time, I do not believe we have enough information
1081883529b6Schristos         to distinguish a 32 bit core insn from a 32 bit cop insn. Also,
1082883529b6Schristos         no 16 bit coprocessor insns have been specified.
1083883529b6Schristos
1084883529b6Schristos   VLIW64 Mode:
1085883529b6Schristos   16 bit core insn (core) and 48 bit coprocessor insn (cop1)
1086883529b6Schristos   32 bit core insn (core) and 32 bit coprocessor insn (cop1)
1087883529b6Schristos   64 bit coprocessor insn (cop1)
1088883529b6Schristos
1089883529b6Schristos   The framework for an internally parallel coprocessor is also
1090883529b6Schristos   present (2nd coprocessor insn is cop2), but at this time it
1091883529b6Schristos   is not used.  This only appears to be valid in VLIW64 mode.  */
1092883529b6Schristos
1093883529b6Schristosstatic int
1094883529b6Schristosmep_examine_vliw32_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1095883529b6Schristos{
1096883529b6Schristos  int status;
1097883529b6Schristos  int buflength;
1098883529b6Schristos  int corebuflength;
1099883529b6Schristos  int cop1buflength;
1100883529b6Schristos  int cop2buflength;
1101883529b6Schristos  bfd_byte buf[CGEN_MAX_INSN_SIZE];
1102883529b6Schristos  char indicator16[1];
1103883529b6Schristos  char indicatorcop32[2];
1104883529b6Schristos
1105883529b6Schristos  /* At this time we're not supporting internally parallel coprocessors,
1106883529b6Schristos     so cop2buflength will always be 0.  */
1107883529b6Schristos  cop2buflength = 0;
1108883529b6Schristos
1109883529b6Schristos  /* Read in 32 bits.  */
1110883529b6Schristos  buflength = 4; /* VLIW insn spans 4 bytes.  */
1111883529b6Schristos  status = (*info->read_memory_func) (pc, buf, buflength, info);
1112883529b6Schristos
1113883529b6Schristos  if (status != 0)
1114883529b6Schristos    {
1115883529b6Schristos      (*info->memory_error_func) (status, pc, info);
1116883529b6Schristos      return -1;
1117883529b6Schristos    }
1118883529b6Schristos
1119883529b6Schristos  /* Put the big endian representation of the bytes to be examined
1120883529b6Schristos     in the temporary buffers for examination.  */
1121883529b6Schristos
1122883529b6Schristos  if (info->endian == BFD_ENDIAN_BIG)
1123883529b6Schristos    {
1124883529b6Schristos      indicator16[0] = buf[0];
1125883529b6Schristos      indicatorcop32[0] = buf[0];
1126883529b6Schristos      indicatorcop32[1] = buf[1];
1127883529b6Schristos    }
1128883529b6Schristos  else
1129883529b6Schristos    {
1130883529b6Schristos      indicator16[0] = buf[1];
1131883529b6Schristos      indicatorcop32[0] = buf[1];
1132883529b6Schristos      indicatorcop32[1] = buf[0];
1133883529b6Schristos    }
1134883529b6Schristos
1135883529b6Schristos  /* If the two high order bits are 00, 01 or 10, we have a 16 bit
1136883529b6Schristos     core insn and a 48 bit copro insn.  */
1137883529b6Schristos
1138883529b6Schristos  if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
1139883529b6Schristos    {
1140883529b6Schristos      if ((indicatorcop32[0] & 0xf0) == 0xf0 && (indicatorcop32[1] & 0x07) == 0x07)
1141883529b6Schristos	{
1142883529b6Schristos	  /* We have a 32 bit copro insn.  */
1143883529b6Schristos	  corebuflength = 0;
1144883529b6Schristos	  /* All 4 4ytes are one copro insn. */
1145883529b6Schristos	  cop1buflength = 4;
1146883529b6Schristos	}
1147883529b6Schristos      else
1148883529b6Schristos	{
1149883529b6Schristos	  /* We have a 32 bit core.  */
1150883529b6Schristos	  corebuflength = 4;
1151883529b6Schristos	  cop1buflength = 0;
1152883529b6Schristos	}
1153883529b6Schristos    }
1154883529b6Schristos  else
1155883529b6Schristos    {
1156883529b6Schristos      /* We have a 16 bit core insn and a 16 bit copro insn.  */
1157883529b6Schristos      corebuflength = 2;
1158883529b6Schristos      cop1buflength = 2;
1159883529b6Schristos    }
1160883529b6Schristos
1161883529b6Schristos  /* Now we have the distrubution set.  Print them out.  */
1162883529b6Schristos  status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
1163883529b6Schristos				 cop1buflength, cop2buflength);
1164883529b6Schristos
1165883529b6Schristos  return status;
1166883529b6Schristos}
1167883529b6Schristos
1168883529b6Schristosstatic int
1169883529b6Schristosmep_examine_vliw64_insns (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1170883529b6Schristos{
1171883529b6Schristos  int status;
1172883529b6Schristos  int buflength;
1173883529b6Schristos  int corebuflength;
1174883529b6Schristos  int cop1buflength;
1175883529b6Schristos  int cop2buflength;
1176883529b6Schristos  bfd_byte buf[CGEN_MAX_INSN_SIZE];
1177883529b6Schristos  char indicator16[1];
1178883529b6Schristos  char indicator64[4];
1179883529b6Schristos
1180883529b6Schristos  /* At this time we're not supporting internally parallel
1181883529b6Schristos     coprocessors, so cop2buflength will always be 0.  */
1182883529b6Schristos  cop2buflength = 0;
1183883529b6Schristos
1184883529b6Schristos  /* Read in 64 bits.  */
1185883529b6Schristos  buflength = 8; /* VLIW insn spans 8 bytes.  */
1186883529b6Schristos  status = (*info->read_memory_func) (pc, buf, buflength, info);
1187883529b6Schristos
1188883529b6Schristos  if (status != 0)
1189883529b6Schristos    {
1190883529b6Schristos      (*info->memory_error_func) (status, pc, info);
1191883529b6Schristos      return -1;
1192883529b6Schristos    }
1193883529b6Schristos
1194883529b6Schristos  /* We have all 64 bits in the buffer now.  We have to figure out
1195883529b6Schristos     what combination of instruction sizes are present.  The two
1196883529b6Schristos     high order bits will indicate whether or not we have a 16 bit
1197883529b6Schristos     core insn or not.  If not, then we have to look at the 7,8th
1198883529b6Schristos     bytes to tell whether we have 64 bit copro insn or a 32 bit
1199883529b6Schristos     core insn with a 32 bit copro insn.  Endianness will make a
1200883529b6Schristos     difference here.  */
1201883529b6Schristos
1202883529b6Schristos  /* Put the big endian representation of the bytes to be examined
1203883529b6Schristos     in the temporary buffers for examination.  */
1204883529b6Schristos
1205883529b6Schristos  /* indicator16[0] = buf[0];  */
1206883529b6Schristos  if (info->endian == BFD_ENDIAN_BIG)
1207883529b6Schristos    {
1208883529b6Schristos      indicator16[0] = buf[0];
1209883529b6Schristos      indicator64[0] = buf[0];
1210883529b6Schristos      indicator64[1] = buf[1];
1211883529b6Schristos      indicator64[2] = buf[2];
1212883529b6Schristos      indicator64[3] = buf[3];
1213883529b6Schristos    }
1214883529b6Schristos  else
1215883529b6Schristos    {
1216883529b6Schristos      indicator16[0] = buf[1];
1217883529b6Schristos      indicator64[0] = buf[1];
1218883529b6Schristos      indicator64[1] = buf[0];
1219883529b6Schristos      indicator64[2] = buf[3];
1220883529b6Schristos      indicator64[3] = buf[2];
1221883529b6Schristos    }
1222883529b6Schristos
1223883529b6Schristos  /* If the two high order bits are 00, 01 or 10, we have a 16 bit
1224883529b6Schristos     core insn and a 48 bit copro insn.  */
1225883529b6Schristos
1226883529b6Schristos  if ((indicator16[0] & 0x80) && (indicator16[0] & 0x40))
1227883529b6Schristos    {
1228883529b6Schristos      if ((indicator64[0] & 0xf0) == 0xf0 && (indicator64[1] & 0x07) == 0x07
1229883529b6Schristos	  && ((indicator64[2] & 0xfe) != 0xf0 || (indicator64[3] & 0xf4) != 0))
1230883529b6Schristos	{
1231883529b6Schristos	  /* We have a 64 bit copro insn.  */
1232883529b6Schristos	  corebuflength = 0;
1233883529b6Schristos	  /* All 8 bytes are one copro insn.  */
1234883529b6Schristos	  cop1buflength = 8;
1235883529b6Schristos	}
1236883529b6Schristos      else
1237883529b6Schristos	{
1238883529b6Schristos	  /* We have a 32 bit core insn and a 32 bit copro insn.  */
1239883529b6Schristos	  corebuflength = 4;
1240883529b6Schristos	  cop1buflength = 4;
1241883529b6Schristos	}
1242883529b6Schristos    }
1243883529b6Schristos  else
1244883529b6Schristos    {
1245883529b6Schristos      /* We have a 16 bit core insn and a 48 bit copro insn.  */
1246883529b6Schristos      corebuflength = 2;
1247883529b6Schristos      cop1buflength = 6;
1248883529b6Schristos    }
1249883529b6Schristos
1250883529b6Schristos  /* Now we have the distrubution set.  Print them out. */
1251883529b6Schristos  status = mep_print_vliw_insns (cd, pc, info, buf, corebuflength,
1252883529b6Schristos				 cop1buflength, cop2buflength);
1253883529b6Schristos
1254883529b6Schristos  return status;
1255883529b6Schristos}
1256883529b6Schristos
1257883529b6Schristos#ifdef MEP_IVC2_SUPPORTED
1258883529b6Schristos
1259883529b6Schristosstatic int
1260883529b6Schristosprint_slot_insn (CGEN_CPU_DESC cd,
1261883529b6Schristos		 bfd_vma pc,
1262883529b6Schristos		 disassemble_info *info,
1263883529b6Schristos		 SLOTS_ATTR slot,
1264883529b6Schristos		 bfd_byte *buf)
1265883529b6Schristos{
1266883529b6Schristos  const CGEN_INSN_LIST *insn_list;
1267883529b6Schristos  CGEN_INSN_INT insn_value;
1268883529b6Schristos  CGEN_EXTRACT_INFO ex_info;
1269883529b6Schristos
12704f645668Schristos  insn_value = cgen_get_insn_value (cd, buf, 32, cd->insn_endian);
1271883529b6Schristos
1272883529b6Schristos  /* Fill in ex_info fields like read_insn would.  Don't actually call
1273883529b6Schristos     read_insn, since the incoming buffer is already read (and possibly
1274883529b6Schristos     modified a la m32r).  */
1275883529b6Schristos  ex_info.valid = (1 << 8) - 1;
1276883529b6Schristos  ex_info.dis_info = info;
1277883529b6Schristos  ex_info.insn_bytes = buf;
1278883529b6Schristos
1279883529b6Schristos  /* The instructions are stored in hash lists.
1280883529b6Schristos     Pick the first one and keep trying until we find the right one.  */
1281883529b6Schristos
1282883529b6Schristos  insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
1283883529b6Schristos  while (insn_list != NULL)
1284883529b6Schristos    {
1285883529b6Schristos      const CGEN_INSN *insn = insn_list->insn;
1286883529b6Schristos      CGEN_FIELDS fields;
1287883529b6Schristos      int length;
1288883529b6Schristos
1289883529b6Schristos      if ((CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG)
1290883529b6Schristos	   && CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG) != MEP_CONFIG)
1291883529b6Schristos	  || ! (CGEN_ATTR_CGEN_INSN_SLOTS_VALUE (CGEN_INSN_ATTRS (insn)) & (1 << slot)))
1292883529b6Schristos	{
1293883529b6Schristos	  insn_list = CGEN_DIS_NEXT_INSN (insn_list);
1294883529b6Schristos	  continue;
1295883529b6Schristos	}
1296883529b6Schristos
1297883529b6Schristos      if ((insn_value & CGEN_INSN_BASE_MASK (insn))
1298883529b6Schristos	  == CGEN_INSN_BASE_VALUE (insn))
1299883529b6Schristos	{
1300883529b6Schristos	  /* Printing is handled in two passes.  The first pass parses the
1301883529b6Schristos	     machine insn and extracts the fields.  The second pass prints
1302883529b6Schristos	     them.  */
1303883529b6Schristos
1304883529b6Schristos	  length = CGEN_EXTRACT_FN (cd, insn)
1305883529b6Schristos	    (cd, insn, &ex_info, insn_value, &fields, pc);
1306883529b6Schristos
1307883529b6Schristos	  /* Length < 0 -> error.  */
1308883529b6Schristos	  if (length < 0)
1309883529b6Schristos	    return length;
1310883529b6Schristos	  if (length > 0)
1311883529b6Schristos	    {
1312883529b6Schristos	      CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
1313883529b6Schristos	      /* Length is in bits, result is in bytes.  */
1314883529b6Schristos	      return length / 8;
1315883529b6Schristos	    }
1316883529b6Schristos	}
1317883529b6Schristos
1318883529b6Schristos      insn_list = CGEN_DIS_NEXT_INSN (insn_list);
1319883529b6Schristos    }
1320883529b6Schristos
1321883529b6Schristos  if (slot == SLOTS_P0S)
1322883529b6Schristos    (*info->fprintf_func) (info->stream, "*unknown-p0s*");
1323883529b6Schristos  else if (slot == SLOTS_P0)
1324883529b6Schristos    (*info->fprintf_func) (info->stream, "*unknown-p0*");
1325883529b6Schristos  else if (slot == SLOTS_P1)
1326883529b6Schristos    (*info->fprintf_func) (info->stream, "*unknown-p1*");
1327883529b6Schristos  else if (slot == SLOTS_C3)
1328883529b6Schristos    (*info->fprintf_func) (info->stream, "*unknown-c3*");
1329883529b6Schristos  return 0;
1330883529b6Schristos}
1331883529b6Schristos
1332883529b6Schristosstatic int
1333883529b6Schristosmep_examine_ivc2_insns (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED, bfd_vma pc ATTRIBUTE_UNUSED, disassemble_info *info ATTRIBUTE_UNUSED)
1334883529b6Schristos{
1335883529b6Schristos  int status;
1336883529b6Schristos  int buflength;
1337883529b6Schristos  bfd_byte buf[8];
1338883529b6Schristos  bfd_byte insn[8];
1339883529b6Schristos  int e;
1340883529b6Schristos
1341883529b6Schristos  /* Read in 64 bits.  */
1342883529b6Schristos  buflength = 8; /* VLIW insn spans 8 bytes.  */
1343883529b6Schristos  status = (*info->read_memory_func) (pc, buf, buflength, info);
1344883529b6Schristos
1345883529b6Schristos  if (status != 0)
1346883529b6Schristos    {
1347883529b6Schristos      (*info->memory_error_func) (status, pc, info);
1348883529b6Schristos      return -1;
1349883529b6Schristos    }
1350883529b6Schristos
1351883529b6Schristos  if (info->endian == BFD_ENDIAN_LITTLE)
1352883529b6Schristos    e = 1;
1353883529b6Schristos  else
1354883529b6Schristos    e = 0;
1355883529b6Schristos
1356883529b6Schristos  if (((unsigned char)buf[0^e] & 0xf0) < 0xc0)
1357883529b6Schristos    {
1358883529b6Schristos      /*      <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1359883529b6Schristos      /* V1   [-----core-----][--------p0s-------][------------p1------------] */
1360883529b6Schristos
1361883529b6Schristos      print_insn (cd, pc, info, buf, 2);
1362883529b6Schristos
1363883529b6Schristos      insn[0^e] = 0;
1364883529b6Schristos      insn[1^e] = buf[2^e];
1365883529b6Schristos      insn[2^e] = buf[3^e];
1366883529b6Schristos      insn[3^e] = buf[4^e] & 0xf0;
1367883529b6Schristos      (*info->fprintf_func) (info->stream, " + ");
1368883529b6Schristos      print_slot_insn (cd, pc, info, SLOTS_P0S, insn);
1369883529b6Schristos
1370883529b6Schristos      insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1371883529b6Schristos      insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1372883529b6Schristos      insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1373883529b6Schristos      insn[3^e] = buf[7^e] << 4;
1374883529b6Schristos      (*info->fprintf_func) (info->stream, " + ");
1375883529b6Schristos      print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1376883529b6Schristos    }
1377883529b6Schristos  else if ((buf[0^e] & 0xf0) == 0xf0 && (buf[1^e] & 0x0f) == 0x07)
1378883529b6Schristos    {
1379883529b6Schristos      /*      <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1380883529b6Schristos      /* V3   1111[--p0--]0111[--------p0--------][------------p1------------] */
1381883529b6Schristos      /*                                          00000000111111112222222233333333 */
1382883529b6Schristos
1383883529b6Schristos      insn[0^e] = buf[0^e] << 4 | buf[1^e] >> 4;
1384883529b6Schristos      insn[1^e] = buf[2^e];
1385883529b6Schristos      insn[2^e] = buf[3^e];
1386883529b6Schristos      insn[3^e] = buf[4^e] & 0xf0;
1387883529b6Schristos      print_slot_insn (cd, pc, info, SLOTS_P0, insn);
1388883529b6Schristos
1389883529b6Schristos      insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1390883529b6Schristos      insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1391883529b6Schristos      insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1392883529b6Schristos      insn[3^e] = buf[7^e] << 4;
1393883529b6Schristos      (*info->fprintf_func) (info->stream, " + ");
1394883529b6Schristos      print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1395883529b6Schristos    }
1396883529b6Schristos  else
1397883529b6Schristos    {
1398883529b6Schristos      /*      <--00--><--11--><--22--><--33--><--44--><--55--><--66--><--77--> */
1399883529b6Schristos      /* V2   [-------------core-------------]xxxx[------------p1------------] */
1400883529b6Schristos      print_insn (cd, pc, info, buf, 4);
1401883529b6Schristos
1402883529b6Schristos      insn[0^e] = buf[4^e] << 4 | buf[5^e] >> 4;
1403883529b6Schristos      insn[1^e] = buf[5^e] << 4 | buf[6^e] >> 4;
1404883529b6Schristos      insn[2^e] = buf[6^e] << 4 | buf[7^e] >> 4;
1405883529b6Schristos      insn[3^e] = buf[7^e] << 4;
1406883529b6Schristos      (*info->fprintf_func) (info->stream, " + ");
1407883529b6Schristos      print_slot_insn (cd, pc, info, SLOTS_P1, insn);
1408883529b6Schristos    }
1409883529b6Schristos
1410883529b6Schristos  return 8;
1411883529b6Schristos}
1412883529b6Schristos
1413883529b6Schristos#endif /* MEP_IVC2_SUPPORTED */
1414883529b6Schristos
1415883529b6Schristos/* This is a hack.  SID calls this to update the disassembler as the
1416883529b6Schristos   CPU changes modes.  */
1417883529b6Schristosstatic int mep_ivc2_disassemble_p = 0;
1418883529b6Schristosstatic int mep_ivc2_vliw_disassemble_p = 0;
1419883529b6Schristos
1420883529b6Schristosvoid
1421883529b6Schristosmep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx);
1422883529b6Schristosvoid
1423883529b6Schristosmep_print_insn_set_ivc2_mode (int ivc2_p, int vliw_p, int cfg_idx)
1424883529b6Schristos{
1425883529b6Schristos  mep_ivc2_disassemble_p = ivc2_p;
1426883529b6Schristos  mep_ivc2_vliw_disassemble_p = vliw_p;
1427883529b6Schristos  mep_config_index = cfg_idx;
1428883529b6Schristos}
1429883529b6Schristos
1430883529b6Schristosstatic int
1431883529b6Schristosmep_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
1432883529b6Schristos{
1433883529b6Schristos  int status;
1434883529b6Schristos  int cop_type;
1435883529b6Schristos  int ivc2 = 0;
1436883529b6Schristos  static CGEN_ATTR_VALUE_BITSET_TYPE *ivc2_core_isa = NULL;
1437883529b6Schristos
1438883529b6Schristos  if (ivc2_core_isa == NULL)
1439883529b6Schristos    {
1440883529b6Schristos      /* IVC2 has some core-only coprocessor instructions.  We
1441883529b6Schristos	 use COP32 to flag those, and COP64 for the VLIW ones,
1442883529b6Schristos	 since they have the same names.  */
1443883529b6Schristos      ivc2_core_isa = cgen_bitset_create (MAX_ISAS);
1444883529b6Schristos    }
1445883529b6Schristos
1446883529b6Schristos  /* Extract and adapt to configuration number, if available. */
1447883529b6Schristos  if (info->section && info->section->owner)
1448883529b6Schristos    {
1449883529b6Schristos      bfd *abfd = info->section->owner;
14504f645668Schristos      if (bfd_get_flavour (abfd) == bfd_target_elf_flavour)
14514f645668Schristos	{
1452883529b6Schristos	  mep_config_index = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_INDEX_MASK;
1453883529b6Schristos	  /* This instantly redefines MEP_CONFIG, MEP_OMASK, .... MEP_VLIW64 */
1454883529b6Schristos
1455*cb63e24eSchristos	  /* mep_config_map is a variable sized array, so we do not know how big it is.
1456*cb63e24eSchristos	     The only safe way to check the index therefore is to iterate over the array.
1457*cb63e24eSchristos	     We do know that the last entry is all null.  */
1458*cb63e24eSchristos	  int i;
1459*cb63e24eSchristos	  for (i = 0; i <= mep_config_index; i++)
1460*cb63e24eSchristos	    if (mep_config_map[i].name == NULL)
1461*cb63e24eSchristos	      break;
1462*cb63e24eSchristos
1463*cb63e24eSchristos	  if (i < mep_config_index)
1464*cb63e24eSchristos	    {
1465*cb63e24eSchristos	      opcodes_error_handler (_("illegal MEP INDEX setting '%x' in ELF header e_flags field"), mep_config_index);
1466*cb63e24eSchristos	      mep_config_index = 0;
1467*cb63e24eSchristos	    }
1468*cb63e24eSchristos
1469883529b6Schristos	  cop_type = abfd->tdata.elf_obj_data->elf_header->e_flags & EF_MEP_COP_MASK;
1470883529b6Schristos	  if (cop_type == EF_MEP_COP_IVC2)
1471883529b6Schristos	    ivc2 = 1;
1472883529b6Schristos	}
14734f645668Schristos    }
1474883529b6Schristos
1475883529b6Schristos  /* Picking the right ISA bitmask for the current context is tricky.  */
1476883529b6Schristos  if (info->section)
1477883529b6Schristos    {
1478883529b6Schristos      if (info->section->flags & SEC_MEP_VLIW)
1479883529b6Schristos	{
1480883529b6Schristos#ifdef MEP_IVC2_SUPPORTED
1481883529b6Schristos	  if (ivc2)
1482883529b6Schristos	    {
1483883529b6Schristos	      /* ivc2 has its own way of selecting its functions.  */
1484883529b6Schristos	      cd->isas = & MEP_CORE_ISA;
1485883529b6Schristos	      status = mep_examine_ivc2_insns (cd, pc, info);
1486883529b6Schristos	    }
1487883529b6Schristos	  else
1488883529b6Schristos#endif
1489883529b6Schristos	    /* Are we in 32 or 64 bit vliw mode?  */
1490883529b6Schristos	    if (MEP_VLIW64)
1491883529b6Schristos	      status = mep_examine_vliw64_insns (cd, pc, info);
1492883529b6Schristos	    else
1493883529b6Schristos	      status = mep_examine_vliw32_insns (cd, pc, info);
1494883529b6Schristos	  /* Both the above branches set their own isa bitmasks.  */
1495883529b6Schristos	}
1496883529b6Schristos      else
1497883529b6Schristos	{
1498883529b6Schristos	  if (ivc2)
1499883529b6Schristos	    {
1500883529b6Schristos	      cgen_bitset_clear (ivc2_core_isa);
1501883529b6Schristos	      cgen_bitset_union (ivc2_core_isa, &MEP_CORE_ISA, ivc2_core_isa);
1502883529b6Schristos	      cgen_bitset_union (ivc2_core_isa, &MEP_COP32_ISA, ivc2_core_isa);
1503883529b6Schristos	      cd->isas = ivc2_core_isa;
1504883529b6Schristos	    }
1505883529b6Schristos	  else
1506883529b6Schristos	    cd->isas = & MEP_CORE_ISA;
1507883529b6Schristos	  status = default_print_insn (cd, pc, info);
1508883529b6Schristos	}
1509883529b6Schristos    }
1510883529b6Schristos  else /* sid or gdb */
1511883529b6Schristos    {
1512883529b6Schristos#ifdef MEP_IVC2_SUPPORTED
1513883529b6Schristos      if (mep_ivc2_disassemble_p)
1514883529b6Schristos	{
1515883529b6Schristos	  if (mep_ivc2_vliw_disassemble_p)
1516883529b6Schristos	    {
1517883529b6Schristos	      cd->isas = & MEP_CORE_ISA;
1518883529b6Schristos	      status = mep_examine_ivc2_insns (cd, pc, info);
1519883529b6Schristos	      return status;
1520883529b6Schristos	    }
1521883529b6Schristos	  else
1522883529b6Schristos	    {
1523883529b6Schristos	      if (ivc2)
1524883529b6Schristos		cd->isas = ivc2_core_isa;
1525883529b6Schristos	    }
1526883529b6Schristos	}
1527883529b6Schristos#endif
1528883529b6Schristos
1529883529b6Schristos      status = default_print_insn (cd, pc, info);
1530883529b6Schristos    }
1531883529b6Schristos
1532883529b6Schristos  return status;
1533883529b6Schristos}
1534883529b6Schristos
1535883529b6Schristos
1536883529b6Schristos/* -- opc.c */
1537883529b6Schristos#include "elf/mep.h"
1538883529b6Schristos
1539883529b6Schristos/* A mask for all ISAs executed by the core. */
1540883529b6SchristosCGEN_ATTR_VALUE_BITSET_TYPE mep_all_core_isas_mask = {0, 0};
1541883529b6Schristos
1542883529b6Schristosvoid
1543883529b6Schristosinit_mep_all_core_isas_mask (void)
1544883529b6Schristos{
1545883529b6Schristos  if (mep_all_core_isas_mask.length != 0)
1546883529b6Schristos    return;
1547883529b6Schristos  cgen_bitset_init (& mep_all_core_isas_mask, ISA_MAX);
1548883529b6Schristos  cgen_bitset_set (& mep_all_core_isas_mask, ISA_MEP);
1549883529b6Schristos  /* begin-all-core-isas */
1550883529b6Schristos  cgen_bitset_add (& mep_all_core_isas_mask, ISA_EXT_CORE1);
1551883529b6Schristos  /* end-all-core-isas */
1552883529b6Schristos}
1553883529b6Schristos
1554883529b6SchristosCGEN_ATTR_VALUE_BITSET_TYPE mep_all_cop_isas_mask = {0, 0};
1555883529b6Schristos
1556883529b6Schristosvoid
1557883529b6Schristosinit_mep_all_cop_isas_mask (void)
1558883529b6Schristos{
1559883529b6Schristos  if (mep_all_cop_isas_mask.length != 0)
1560883529b6Schristos    return;
1561883529b6Schristos  cgen_bitset_init (& mep_all_cop_isas_mask, ISA_MAX);
1562883529b6Schristos  /* begin-all-cop-isas */
1563883529b6Schristos  cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_16);
1564883529b6Schristos  cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_32);
1565883529b6Schristos  cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_48);
1566883529b6Schristos  cgen_bitset_add (& mep_all_cop_isas_mask, ISA_EXT_COP1_64);
1567883529b6Schristos  /* end-all-cop-isas */
1568883529b6Schristos}
1569883529b6Schristos
1570883529b6Schristosint
1571883529b6Schristosmep_insn_supported_by_isa (const CGEN_INSN *insn, CGEN_ATTR_VALUE_BITSET_TYPE *isa_mask)
1572883529b6Schristos{
1573883529b6Schristos  CGEN_BITSET insn_isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
1574883529b6Schristos  return cgen_bitset_intersect_p (& insn_isas, isa_mask);
1575883529b6Schristos}
1576883529b6Schristos
1577883529b6Schristos#define OPTION_MASK \
1578883529b6Schristos	( (1 << CGEN_INSN_OPTIONAL_BIT_INSN) \
1579883529b6Schristos	| (1 << CGEN_INSN_OPTIONAL_MUL_INSN) \
1580883529b6Schristos	| (1 << CGEN_INSN_OPTIONAL_DIV_INSN) \
1581883529b6Schristos	| (1 << CGEN_INSN_OPTIONAL_DEBUG_INSN) \
1582883529b6Schristos	| (1 << CGEN_INSN_OPTIONAL_LDZ_INSN) \
1583883529b6Schristos	| (1 << CGEN_INSN_OPTIONAL_ABS_INSN) \
1584883529b6Schristos	| (1 << CGEN_INSN_OPTIONAL_AVE_INSN) \
1585883529b6Schristos	| (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN) \
1586883529b6Schristos	| (1 << CGEN_INSN_OPTIONAL_CLIP_INSN) \
1587883529b6Schristos	| (1 << CGEN_INSN_OPTIONAL_SAT_INSN) \
1588883529b6Schristos	| (1 << CGEN_INSN_OPTIONAL_UCI_INSN) \
1589883529b6Schristos	| (1 << CGEN_INSN_OPTIONAL_DSP_INSN) \
1590883529b6Schristos	| (1 << CGEN_INSN_OPTIONAL_CP_INSN) \
1591883529b6Schristos	| (1 << CGEN_INSN_OPTIONAL_CP64_INSN) )
1592883529b6Schristos
1593883529b6Schristos
1594883529b6Schristosmep_config_map_struct mep_config_map[] =
1595883529b6Schristos{
1596883529b6Schristos  /* config-map-start */
1597883529b6Schristos  /* Default entry: first module, with all options enabled. */
1598883529b6Schristos  { "", 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) },
1599883529b6Schristos  { "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" },
1600883529b6Schristos	  0
1601883529b6Schristos	| (1 << CGEN_INSN_OPTIONAL_CP_INSN)
1602883529b6Schristos	| (1 << CGEN_INSN_OPTIONAL_CP64_INSN)
1603883529b6Schristos	| (1 << CGEN_INSN_OPTIONAL_MUL_INSN)
1604883529b6Schristos	| (1 << CGEN_INSN_OPTIONAL_DIV_INSN)
1605883529b6Schristos	| (1 << CGEN_INSN_OPTIONAL_BIT_INSN)
1606883529b6Schristos	| (1 << CGEN_INSN_OPTIONAL_LDZ_INSN)
1607883529b6Schristos	| (1 << CGEN_INSN_OPTIONAL_ABS_INSN)
1608883529b6Schristos	| (1 << CGEN_INSN_OPTIONAL_AVE_INSN)
1609883529b6Schristos	| (1 << CGEN_INSN_OPTIONAL_MINMAX_INSN)
1610883529b6Schristos	| (1 << CGEN_INSN_OPTIONAL_CLIP_INSN)
1611883529b6Schristos	| (1 << CGEN_INSN_OPTIONAL_SAT_INSN) },
1612883529b6Schristos  /* config-map-end */
1613883529b6Schristos  { 0, 0, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, 0 }
1614883529b6Schristos};
1615883529b6Schristos
1616883529b6Schristosint mep_config_index = 0;
1617883529b6Schristos
1618883529b6Schristosstatic int
1619883529b6Schristoscheck_configured_mach (int machs)
1620883529b6Schristos{
1621883529b6Schristos  /* All base insns are supported.  */
1622883529b6Schristos  int mach = 1 << MACH_BASE;
1623883529b6Schristos  switch (MEP_CPU & EF_MEP_CPU_MASK)
1624883529b6Schristos    {
1625883529b6Schristos    case EF_MEP_CPU_C2:
1626883529b6Schristos    case EF_MEP_CPU_C3:
1627883529b6Schristos      mach |= (1 << MACH_MEP);
1628883529b6Schristos      break;
1629883529b6Schristos    case EF_MEP_CPU_H1:
1630883529b6Schristos      mach |= (1 << MACH_H1);
1631883529b6Schristos      break;
1632883529b6Schristos    case EF_MEP_CPU_C5:
1633883529b6Schristos      mach |= (1 << MACH_MEP);
1634883529b6Schristos      mach |= (1 << MACH_C5);
1635883529b6Schristos      break;
1636883529b6Schristos    default:
1637883529b6Schristos      break;
1638883529b6Schristos    }
1639883529b6Schristos  return machs & mach;
1640883529b6Schristos}
1641883529b6Schristos
1642883529b6Schristosint
1643883529b6Schristosmep_cgen_insn_supported (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
1644883529b6Schristos{
1645883529b6Schristos  int iconfig = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_CONFIG);
1646883529b6Schristos  int machs = CGEN_INSN_ATTR_VALUE (insn, CGEN_INSN_MACH);
1647883529b6Schristos  CGEN_BITSET isas = CGEN_INSN_BITSET_ATTR_VALUE (insn, CGEN_INSN_ISA);
1648883529b6Schristos  int ok1;
1649883529b6Schristos  int ok2;
1650883529b6Schristos  int ok3;
1651883529b6Schristos
1652883529b6Schristos  /* If the insn has an option bit set that we don't want,
1653883529b6Schristos     reject it.  */
1654883529b6Schristos  if (CGEN_INSN_ATTRS (insn)->bool_ & OPTION_MASK & ~MEP_OMASK)
1655883529b6Schristos    return 0;
1656883529b6Schristos
1657883529b6Schristos  /* If attributes are absent, assume no restriction. */
1658883529b6Schristos  if (machs == 0)
1659883529b6Schristos    machs = ~0;
1660883529b6Schristos
1661883529b6Schristos  ok1 = ((machs & cd->machs) && cgen_bitset_intersect_p (& isas, cd->isas));
1662883529b6Schristos  /* If the insn is config-specific, make sure it matches.  */
1663883529b6Schristos  ok2 =  (iconfig == 0 || iconfig == MEP_CONFIG);
1664883529b6Schristos  /* Make sure the insn is supported by the configured mach  */
1665883529b6Schristos  ok3 = check_configured_mach (machs);
1666883529b6Schristos
1667883529b6Schristos  return (ok1 && ok2 && ok3);
1668883529b6Schristos}
1669883529b6Schristos
1670883529b6Schristosint
1671883529b6Schristosmep_cgen_insn_supported_asm (CGEN_CPU_DESC cd, const CGEN_INSN *insn)
1672883529b6Schristos{
1673883529b6Schristos#ifdef MEP_IVC2_SUPPORTED
1674883529b6Schristos  /* If we're assembling VLIW packets, ignore the 12-bit BSR as we
1675883529b6Schristos     can't relax that.  The 24-bit BSR is matched instead.  */
1676883529b6Schristos  if (insn->base->num == MEP_INSN_BSR12
1677883529b6Schristos      && cgen_bitset_contains (cd->isas, ISA_EXT_COP1_64))
1678883529b6Schristos    return 0;
1679883529b6Schristos#endif
1680883529b6Schristos
1681883529b6Schristos  return mep_cgen_insn_supported (cd, insn);
1682883529b6Schristos}
1683