xref: /openbsd-src/gnu/usr.bin/binutils/opcodes/iq2000-ibld.c (revision cf2f2c5620d6d9a4fd01930983c4b9a1f76d7aa3)
1d2201f2fSdrahn /* Instruction building/extraction support for iq2000. -*- C -*-
2d2201f2fSdrahn 
3d2201f2fSdrahn THIS FILE IS MACHINE GENERATED WITH CGEN: Cpu tools GENerator.
4d2201f2fSdrahn - the resultant file is machine generated, cgen-ibld.in isn't
5d2201f2fSdrahn 
6d2201f2fSdrahn Copyright 1996, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
7d2201f2fSdrahn 
8d2201f2fSdrahn This file is part of the GNU Binutils and GDB, the GNU debugger.
9d2201f2fSdrahn 
10d2201f2fSdrahn This program is free software; you can redistribute it and/or modify
11d2201f2fSdrahn it under the terms of the GNU General Public License as published by
12d2201f2fSdrahn the Free Software Foundation; either version 2, or (at your option)
13d2201f2fSdrahn any later version.
14d2201f2fSdrahn 
15d2201f2fSdrahn This program is distributed in the hope that it will be useful,
16d2201f2fSdrahn but WITHOUT ANY WARRANTY; without even the implied warranty of
17d2201f2fSdrahn MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18d2201f2fSdrahn GNU General Public License for more details.
19d2201f2fSdrahn 
20d2201f2fSdrahn You should have received a copy of the GNU General Public License
21d2201f2fSdrahn along with this program; if not, write to the Free Software Foundation, Inc.,
22d2201f2fSdrahn 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
23d2201f2fSdrahn 
24d2201f2fSdrahn /* ??? Eventually more and more of this stuff can go to cpu-independent files.
25d2201f2fSdrahn    Keep that in mind.  */
26d2201f2fSdrahn 
27d2201f2fSdrahn #include "sysdep.h"
28d2201f2fSdrahn #include <stdio.h>
29d2201f2fSdrahn #include "ansidecl.h"
30d2201f2fSdrahn #include "dis-asm.h"
31d2201f2fSdrahn #include "bfd.h"
32d2201f2fSdrahn #include "symcat.h"
33d2201f2fSdrahn #include "iq2000-desc.h"
34d2201f2fSdrahn #include "iq2000-opc.h"
35d2201f2fSdrahn #include "opintl.h"
36d2201f2fSdrahn #include "safe-ctype.h"
37d2201f2fSdrahn 
38d2201f2fSdrahn #undef min
39d2201f2fSdrahn #define min(a,b) ((a) < (b) ? (a) : (b))
40d2201f2fSdrahn #undef max
41d2201f2fSdrahn #define max(a,b) ((a) > (b) ? (a) : (b))
42d2201f2fSdrahn 
43d2201f2fSdrahn /* Used by the ifield rtx function.  */
44d2201f2fSdrahn #define FLD(f) (fields->f)
45d2201f2fSdrahn 
46d2201f2fSdrahn static const char * insert_normal
47*cf2f2c56Smiod   (CGEN_CPU_DESC, long, unsigned int, unsigned int, unsigned int,
48*cf2f2c56Smiod    unsigned int, unsigned int, unsigned int, CGEN_INSN_BYTES_PTR);
49d2201f2fSdrahn static const char * insert_insn_normal
50*cf2f2c56Smiod   (CGEN_CPU_DESC, const CGEN_INSN *,
51*cf2f2c56Smiod    CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma);
52d2201f2fSdrahn static int extract_normal
53*cf2f2c56Smiod   (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
54d2201f2fSdrahn    unsigned int, unsigned int, unsigned int, unsigned int,
55*cf2f2c56Smiod    unsigned int, unsigned int, bfd_vma, long *);
56d2201f2fSdrahn static int extract_insn_normal
57*cf2f2c56Smiod   (CGEN_CPU_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *,
58*cf2f2c56Smiod    CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma);
59d2201f2fSdrahn #if CGEN_INT_INSN_P
60d2201f2fSdrahn static void put_insn_int_value
61*cf2f2c56Smiod   (CGEN_CPU_DESC, CGEN_INSN_BYTES_PTR, int, int, CGEN_INSN_INT);
62d2201f2fSdrahn #endif
63d2201f2fSdrahn #if ! CGEN_INT_INSN_P
64d2201f2fSdrahn static CGEN_INLINE void insert_1
65*cf2f2c56Smiod   (CGEN_CPU_DESC, unsigned long, int, int, int, unsigned char *);
66d2201f2fSdrahn static CGEN_INLINE int fill_cache
67*cf2f2c56Smiod   (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *,  int, int, bfd_vma);
68d2201f2fSdrahn static CGEN_INLINE long extract_1
69*cf2f2c56Smiod   (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, int, unsigned char *, bfd_vma);
70d2201f2fSdrahn #endif
71d2201f2fSdrahn 
72d2201f2fSdrahn /* Operand insertion.  */
73d2201f2fSdrahn 
74d2201f2fSdrahn #if ! CGEN_INT_INSN_P
75d2201f2fSdrahn 
76d2201f2fSdrahn /* Subroutine of insert_normal.  */
77d2201f2fSdrahn 
78d2201f2fSdrahn static CGEN_INLINE void
insert_1(CGEN_CPU_DESC cd,unsigned long value,int start,int length,int word_length,unsigned char * bufp)79*cf2f2c56Smiod insert_1 (CGEN_CPU_DESC cd,
80*cf2f2c56Smiod 	  unsigned long value,
81*cf2f2c56Smiod 	  int start,
82*cf2f2c56Smiod 	  int length,
83*cf2f2c56Smiod 	  int word_length,
84*cf2f2c56Smiod 	  unsigned char *bufp)
85d2201f2fSdrahn {
86d2201f2fSdrahn   unsigned long x,mask;
87d2201f2fSdrahn   int shift;
88d2201f2fSdrahn 
89d2201f2fSdrahn   x = cgen_get_insn_value (cd, bufp, word_length);
90d2201f2fSdrahn 
91d2201f2fSdrahn   /* Written this way to avoid undefined behaviour.  */
92d2201f2fSdrahn   mask = (((1L << (length - 1)) - 1) << 1) | 1;
93d2201f2fSdrahn   if (CGEN_INSN_LSB0_P)
94d2201f2fSdrahn     shift = (start + 1) - length;
95d2201f2fSdrahn   else
96d2201f2fSdrahn     shift = (word_length - (start + length));
97d2201f2fSdrahn   x = (x & ~(mask << shift)) | ((value & mask) << shift);
98d2201f2fSdrahn 
99d2201f2fSdrahn   cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x);
100d2201f2fSdrahn }
101d2201f2fSdrahn 
102d2201f2fSdrahn #endif /* ! CGEN_INT_INSN_P */
103d2201f2fSdrahn 
104d2201f2fSdrahn /* Default insertion routine.
105d2201f2fSdrahn 
106d2201f2fSdrahn    ATTRS is a mask of the boolean attributes.
107d2201f2fSdrahn    WORD_OFFSET is the offset in bits from the start of the insn of the value.
108d2201f2fSdrahn    WORD_LENGTH is the length of the word in bits in which the value resides.
109d2201f2fSdrahn    START is the starting bit number in the word, architecture origin.
110d2201f2fSdrahn    LENGTH is the length of VALUE in bits.
111d2201f2fSdrahn    TOTAL_LENGTH is the total length of the insn in bits.
112d2201f2fSdrahn 
113d2201f2fSdrahn    The result is an error message or NULL if success.  */
114d2201f2fSdrahn 
115d2201f2fSdrahn /* ??? This duplicates functionality with bfd's howto table and
116d2201f2fSdrahn    bfd_install_relocation.  */
117d2201f2fSdrahn /* ??? This doesn't handle bfd_vma's.  Create another function when
118d2201f2fSdrahn    necessary.  */
119d2201f2fSdrahn 
120d2201f2fSdrahn static const char *
insert_normal(CGEN_CPU_DESC cd,long value,unsigned int attrs,unsigned int word_offset,unsigned int start,unsigned int length,unsigned int word_length,unsigned int total_length,CGEN_INSN_BYTES_PTR buffer)121*cf2f2c56Smiod insert_normal (CGEN_CPU_DESC cd,
122*cf2f2c56Smiod 	       long value,
123*cf2f2c56Smiod 	       unsigned int attrs,
124*cf2f2c56Smiod 	       unsigned int word_offset,
125*cf2f2c56Smiod 	       unsigned int start,
126*cf2f2c56Smiod 	       unsigned int length,
127*cf2f2c56Smiod 	       unsigned int word_length,
128*cf2f2c56Smiod 	       unsigned int total_length,
129*cf2f2c56Smiod 	       CGEN_INSN_BYTES_PTR buffer)
130d2201f2fSdrahn {
131d2201f2fSdrahn   static char errbuf[100];
132d2201f2fSdrahn   /* Written this way to avoid undefined behaviour.  */
133d2201f2fSdrahn   unsigned long mask = (((1L << (length - 1)) - 1) << 1) | 1;
134d2201f2fSdrahn 
135d2201f2fSdrahn   /* If LENGTH is zero, this operand doesn't contribute to the value.  */
136d2201f2fSdrahn   if (length == 0)
137d2201f2fSdrahn     return NULL;
138d2201f2fSdrahn 
139d2201f2fSdrahn #if 0
140d2201f2fSdrahn   if (CGEN_INT_INSN_P
141d2201f2fSdrahn       && word_offset != 0)
142d2201f2fSdrahn     abort ();
143d2201f2fSdrahn #endif
144d2201f2fSdrahn 
145d2201f2fSdrahn   if (word_length > 32)
146d2201f2fSdrahn     abort ();
147d2201f2fSdrahn 
148d2201f2fSdrahn   /* For architectures with insns smaller than the base-insn-bitsize,
149d2201f2fSdrahn      word_length may be too big.  */
150d2201f2fSdrahn   if (cd->min_insn_bitsize < cd->base_insn_bitsize)
151d2201f2fSdrahn     {
152d2201f2fSdrahn       if (word_offset == 0
153d2201f2fSdrahn 	  && word_length > total_length)
154d2201f2fSdrahn 	word_length = total_length;
155d2201f2fSdrahn     }
156d2201f2fSdrahn 
157d2201f2fSdrahn   /* Ensure VALUE will fit.  */
158d2201f2fSdrahn   if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGN_OPT))
159d2201f2fSdrahn     {
160d2201f2fSdrahn       long minval = - (1L << (length - 1));
161d2201f2fSdrahn       unsigned long maxval = mask;
162d2201f2fSdrahn 
163d2201f2fSdrahn       if ((value > 0 && (unsigned long) value > maxval)
164d2201f2fSdrahn 	  || value < minval)
165d2201f2fSdrahn 	{
166d2201f2fSdrahn 	  /* xgettext:c-format */
167d2201f2fSdrahn 	  sprintf (errbuf,
168d2201f2fSdrahn 		   _("operand out of range (%ld not between %ld and %lu)"),
169d2201f2fSdrahn 		   value, minval, maxval);
170d2201f2fSdrahn 	  return errbuf;
171d2201f2fSdrahn 	}
172d2201f2fSdrahn     }
173d2201f2fSdrahn   else if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED))
174d2201f2fSdrahn     {
175d2201f2fSdrahn       unsigned long maxval = mask;
176d2201f2fSdrahn 
177d2201f2fSdrahn       if ((unsigned long) value > maxval)
178d2201f2fSdrahn 	{
179d2201f2fSdrahn 	  /* xgettext:c-format */
180d2201f2fSdrahn 	  sprintf (errbuf,
181d2201f2fSdrahn 		   _("operand out of range (%lu not between 0 and %lu)"),
182d2201f2fSdrahn 		   value, maxval);
183d2201f2fSdrahn 	  return errbuf;
184d2201f2fSdrahn 	}
185d2201f2fSdrahn     }
186d2201f2fSdrahn   else
187d2201f2fSdrahn     {
188d2201f2fSdrahn       if (! cgen_signed_overflow_ok_p (cd))
189d2201f2fSdrahn 	{
190d2201f2fSdrahn 	  long minval = - (1L << (length - 1));
191d2201f2fSdrahn 	  long maxval =   (1L << (length - 1)) - 1;
192d2201f2fSdrahn 
193d2201f2fSdrahn 	  if (value < minval || value > maxval)
194d2201f2fSdrahn 	    {
195d2201f2fSdrahn 	      sprintf
196d2201f2fSdrahn 		/* xgettext:c-format */
197d2201f2fSdrahn 		(errbuf, _("operand out of range (%ld not between %ld and %ld)"),
198d2201f2fSdrahn 		 value, minval, maxval);
199d2201f2fSdrahn 	      return errbuf;
200d2201f2fSdrahn 	    }
201d2201f2fSdrahn 	}
202d2201f2fSdrahn     }
203d2201f2fSdrahn 
204d2201f2fSdrahn #if CGEN_INT_INSN_P
205d2201f2fSdrahn 
206d2201f2fSdrahn   {
207d2201f2fSdrahn     int shift;
208d2201f2fSdrahn 
209d2201f2fSdrahn     if (CGEN_INSN_LSB0_P)
210d2201f2fSdrahn       shift = (word_offset + start + 1) - length;
211d2201f2fSdrahn     else
212d2201f2fSdrahn       shift = total_length - (word_offset + start + length);
213d2201f2fSdrahn     *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
214d2201f2fSdrahn   }
215d2201f2fSdrahn 
216d2201f2fSdrahn #else /* ! CGEN_INT_INSN_P */
217d2201f2fSdrahn 
218d2201f2fSdrahn   {
219d2201f2fSdrahn     unsigned char *bufp = (unsigned char *) buffer + word_offset / 8;
220d2201f2fSdrahn 
221d2201f2fSdrahn     insert_1 (cd, value, start, length, word_length, bufp);
222d2201f2fSdrahn   }
223d2201f2fSdrahn 
224d2201f2fSdrahn #endif /* ! CGEN_INT_INSN_P */
225d2201f2fSdrahn 
226d2201f2fSdrahn   return NULL;
227d2201f2fSdrahn }
228d2201f2fSdrahn 
229d2201f2fSdrahn /* Default insn builder (insert handler).
230d2201f2fSdrahn    The instruction is recorded in CGEN_INT_INSN_P byte order (meaning
231d2201f2fSdrahn    that if CGEN_INSN_BYTES_PTR is an int * and thus, the value is
232d2201f2fSdrahn    recorded in host byte order, otherwise BUFFER is an array of bytes
233d2201f2fSdrahn    and the value is recorded in target byte order).
234d2201f2fSdrahn    The result is an error message or NULL if success.  */
235d2201f2fSdrahn 
236d2201f2fSdrahn static const char *
insert_insn_normal(CGEN_CPU_DESC cd,const CGEN_INSN * insn,CGEN_FIELDS * fields,CGEN_INSN_BYTES_PTR buffer,bfd_vma pc)237*cf2f2c56Smiod insert_insn_normal (CGEN_CPU_DESC cd,
238*cf2f2c56Smiod 		    const CGEN_INSN * insn,
239*cf2f2c56Smiod 		    CGEN_FIELDS * fields,
240*cf2f2c56Smiod 		    CGEN_INSN_BYTES_PTR buffer,
241*cf2f2c56Smiod 		    bfd_vma pc)
242d2201f2fSdrahn {
243d2201f2fSdrahn   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
244d2201f2fSdrahn   unsigned long value;
245d2201f2fSdrahn   const CGEN_SYNTAX_CHAR_TYPE * syn;
246d2201f2fSdrahn 
247d2201f2fSdrahn   CGEN_INIT_INSERT (cd);
248d2201f2fSdrahn   value = CGEN_INSN_BASE_VALUE (insn);
249d2201f2fSdrahn 
250d2201f2fSdrahn   /* If we're recording insns as numbers (rather than a string of bytes),
251d2201f2fSdrahn      target byte order handling is deferred until later.  */
252d2201f2fSdrahn 
253d2201f2fSdrahn #if CGEN_INT_INSN_P
254d2201f2fSdrahn 
255d2201f2fSdrahn   put_insn_int_value (cd, buffer, cd->base_insn_bitsize,
256d2201f2fSdrahn 		      CGEN_FIELDS_BITSIZE (fields), value);
257d2201f2fSdrahn 
258d2201f2fSdrahn #else
259d2201f2fSdrahn 
260d2201f2fSdrahn   cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
261d2201f2fSdrahn 					(unsigned) CGEN_FIELDS_BITSIZE (fields)),
262d2201f2fSdrahn 		       value);
263d2201f2fSdrahn 
264d2201f2fSdrahn #endif /* ! CGEN_INT_INSN_P */
265d2201f2fSdrahn 
266d2201f2fSdrahn   /* ??? It would be better to scan the format's fields.
267d2201f2fSdrahn      Still need to be able to insert a value based on the operand though;
268d2201f2fSdrahn      e.g. storing a branch displacement that got resolved later.
269d2201f2fSdrahn      Needs more thought first.  */
270d2201f2fSdrahn 
271d2201f2fSdrahn   for (syn = CGEN_SYNTAX_STRING (syntax); * syn; ++ syn)
272d2201f2fSdrahn     {
273d2201f2fSdrahn       const char *errmsg;
274d2201f2fSdrahn 
275d2201f2fSdrahn       if (CGEN_SYNTAX_CHAR_P (* syn))
276d2201f2fSdrahn 	continue;
277d2201f2fSdrahn 
278d2201f2fSdrahn       errmsg = (* cd->insert_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
279d2201f2fSdrahn 				       fields, buffer, pc);
280d2201f2fSdrahn       if (errmsg)
281d2201f2fSdrahn 	return errmsg;
282d2201f2fSdrahn     }
283d2201f2fSdrahn 
284d2201f2fSdrahn   return NULL;
285d2201f2fSdrahn }
286d2201f2fSdrahn 
287d2201f2fSdrahn #if CGEN_INT_INSN_P
288d2201f2fSdrahn /* Cover function to store an insn value into an integral insn.  Must go here
289d2201f2fSdrahn  because it needs <prefix>-desc.h for CGEN_INT_INSN_P.  */
290d2201f2fSdrahn 
291d2201f2fSdrahn static void
put_insn_int_value(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,CGEN_INSN_BYTES_PTR buf,int length,int insn_length,CGEN_INSN_INT value)292*cf2f2c56Smiod put_insn_int_value (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
293*cf2f2c56Smiod 		    CGEN_INSN_BYTES_PTR buf,
294*cf2f2c56Smiod 		    int length,
295*cf2f2c56Smiod 		    int insn_length,
296*cf2f2c56Smiod 		    CGEN_INSN_INT value)
297d2201f2fSdrahn {
298d2201f2fSdrahn   /* For architectures with insns smaller than the base-insn-bitsize,
299d2201f2fSdrahn      length may be too big.  */
300d2201f2fSdrahn   if (length > insn_length)
301d2201f2fSdrahn     *buf = value;
302d2201f2fSdrahn   else
303d2201f2fSdrahn     {
304d2201f2fSdrahn       int shift = insn_length - length;
305d2201f2fSdrahn       /* Written this way to avoid undefined behaviour.  */
306d2201f2fSdrahn       CGEN_INSN_INT mask = (((1L << (length - 1)) - 1) << 1) | 1;
307d2201f2fSdrahn       *buf = (*buf & ~(mask << shift)) | ((value & mask) << shift);
308d2201f2fSdrahn     }
309d2201f2fSdrahn }
310d2201f2fSdrahn #endif
311d2201f2fSdrahn 
312d2201f2fSdrahn /* Operand extraction.  */
313d2201f2fSdrahn 
314d2201f2fSdrahn #if ! CGEN_INT_INSN_P
315d2201f2fSdrahn 
316d2201f2fSdrahn /* Subroutine of extract_normal.
317d2201f2fSdrahn    Ensure sufficient bytes are cached in EX_INFO.
318d2201f2fSdrahn    OFFSET is the offset in bytes from the start of the insn of the value.
319d2201f2fSdrahn    BYTES is the length of the needed value.
320d2201f2fSdrahn    Returns 1 for success, 0 for failure.  */
321d2201f2fSdrahn 
322d2201f2fSdrahn static CGEN_INLINE int
fill_cache(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,CGEN_EXTRACT_INFO * ex_info,int offset,int bytes,bfd_vma pc)323*cf2f2c56Smiod fill_cache (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
324*cf2f2c56Smiod 	    CGEN_EXTRACT_INFO *ex_info,
325*cf2f2c56Smiod 	    int offset,
326*cf2f2c56Smiod 	    int bytes,
327*cf2f2c56Smiod 	    bfd_vma pc)
328d2201f2fSdrahn {
329d2201f2fSdrahn   /* It's doubtful that the middle part has already been fetched so
330d2201f2fSdrahn      we don't optimize that case.  kiss.  */
331d2201f2fSdrahn   unsigned int mask;
332d2201f2fSdrahn   disassemble_info *info = (disassemble_info *) ex_info->dis_info;
333d2201f2fSdrahn 
334d2201f2fSdrahn   /* First do a quick check.  */
335d2201f2fSdrahn   mask = (1 << bytes) - 1;
336d2201f2fSdrahn   if (((ex_info->valid >> offset) & mask) == mask)
337d2201f2fSdrahn     return 1;
338d2201f2fSdrahn 
339d2201f2fSdrahn   /* Search for the first byte we need to read.  */
340d2201f2fSdrahn   for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
341d2201f2fSdrahn     if (! (mask & ex_info->valid))
342d2201f2fSdrahn       break;
343d2201f2fSdrahn 
344d2201f2fSdrahn   if (bytes)
345d2201f2fSdrahn     {
346d2201f2fSdrahn       int status;
347d2201f2fSdrahn 
348d2201f2fSdrahn       pc += offset;
349d2201f2fSdrahn       status = (*info->read_memory_func)
350d2201f2fSdrahn 	(pc, ex_info->insn_bytes + offset, bytes, info);
351d2201f2fSdrahn 
352d2201f2fSdrahn       if (status != 0)
353d2201f2fSdrahn 	{
354d2201f2fSdrahn 	  (*info->memory_error_func) (status, pc, info);
355d2201f2fSdrahn 	  return 0;
356d2201f2fSdrahn 	}
357d2201f2fSdrahn 
358d2201f2fSdrahn       ex_info->valid |= ((1 << bytes) - 1) << offset;
359d2201f2fSdrahn     }
360d2201f2fSdrahn 
361d2201f2fSdrahn   return 1;
362d2201f2fSdrahn }
363d2201f2fSdrahn 
364d2201f2fSdrahn /* Subroutine of extract_normal.  */
365d2201f2fSdrahn 
366d2201f2fSdrahn static CGEN_INLINE long
extract_1(CGEN_CPU_DESC cd,CGEN_EXTRACT_INFO * ex_info ATTRIBUTE_UNUSED,int start,int length,int word_length,unsigned char * bufp,bfd_vma pc ATTRIBUTE_UNUSED)367*cf2f2c56Smiod extract_1 (CGEN_CPU_DESC cd,
368*cf2f2c56Smiod 	   CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
369*cf2f2c56Smiod 	   int start,
370*cf2f2c56Smiod 	   int length,
371*cf2f2c56Smiod 	   int word_length,
372*cf2f2c56Smiod 	   unsigned char *bufp,
373*cf2f2c56Smiod 	   bfd_vma pc ATTRIBUTE_UNUSED)
374d2201f2fSdrahn {
375d2201f2fSdrahn   unsigned long x;
376d2201f2fSdrahn   int shift;
377d2201f2fSdrahn #if 0
378d2201f2fSdrahn   int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG;
379d2201f2fSdrahn #endif
380d2201f2fSdrahn   x = cgen_get_insn_value (cd, bufp, word_length);
381d2201f2fSdrahn 
382d2201f2fSdrahn   if (CGEN_INSN_LSB0_P)
383d2201f2fSdrahn     shift = (start + 1) - length;
384d2201f2fSdrahn   else
385d2201f2fSdrahn     shift = (word_length - (start + length));
386d2201f2fSdrahn   return x >> shift;
387d2201f2fSdrahn }
388d2201f2fSdrahn 
389d2201f2fSdrahn #endif /* ! CGEN_INT_INSN_P */
390d2201f2fSdrahn 
391d2201f2fSdrahn /* Default extraction routine.
392d2201f2fSdrahn 
393d2201f2fSdrahn    INSN_VALUE is the first base_insn_bitsize bits of the insn in host order,
394d2201f2fSdrahn    or sometimes less for cases like the m32r where the base insn size is 32
395d2201f2fSdrahn    but some insns are 16 bits.
396d2201f2fSdrahn    ATTRS is a mask of the boolean attributes.  We only need `SIGNED',
397d2201f2fSdrahn    but for generality we take a bitmask of all of them.
398d2201f2fSdrahn    WORD_OFFSET is the offset in bits from the start of the insn of the value.
399d2201f2fSdrahn    WORD_LENGTH is the length of the word in bits in which the value resides.
400d2201f2fSdrahn    START is the starting bit number in the word, architecture origin.
401d2201f2fSdrahn    LENGTH is the length of VALUE in bits.
402d2201f2fSdrahn    TOTAL_LENGTH is the total length of the insn in bits.
403d2201f2fSdrahn 
404d2201f2fSdrahn    Returns 1 for success, 0 for failure.  */
405d2201f2fSdrahn 
406d2201f2fSdrahn /* ??? The return code isn't properly used.  wip.  */
407d2201f2fSdrahn 
408d2201f2fSdrahn /* ??? This doesn't handle bfd_vma's.  Create another function when
409d2201f2fSdrahn    necessary.  */
410d2201f2fSdrahn 
411d2201f2fSdrahn static int
extract_normal(CGEN_CPU_DESC cd,CGEN_EXTRACT_INFO * ex_info,CGEN_INSN_INT insn_value,unsigned int attrs,unsigned int word_offset,unsigned int start,unsigned int length,unsigned int word_length,unsigned int total_length,bfd_vma pc,long * valuep)412*cf2f2c56Smiod extract_normal (CGEN_CPU_DESC cd,
413d2201f2fSdrahn #if ! CGEN_INT_INSN_P
414*cf2f2c56Smiod 		CGEN_EXTRACT_INFO *ex_info,
415d2201f2fSdrahn #else
416*cf2f2c56Smiod 		CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
417d2201f2fSdrahn #endif
418*cf2f2c56Smiod 		CGEN_INSN_INT insn_value,
419*cf2f2c56Smiod 		unsigned int attrs,
420*cf2f2c56Smiod 		unsigned int word_offset,
421*cf2f2c56Smiod 		unsigned int start,
422*cf2f2c56Smiod 		unsigned int length,
423*cf2f2c56Smiod 		unsigned int word_length,
424*cf2f2c56Smiod 		unsigned int total_length,
425d2201f2fSdrahn #if ! CGEN_INT_INSN_P
426*cf2f2c56Smiod 		bfd_vma pc,
427d2201f2fSdrahn #else
428*cf2f2c56Smiod 		bfd_vma pc ATTRIBUTE_UNUSED,
429d2201f2fSdrahn #endif
430*cf2f2c56Smiod 		long *valuep)
431d2201f2fSdrahn {
432d2201f2fSdrahn   long value, mask;
433d2201f2fSdrahn 
434d2201f2fSdrahn   /* If LENGTH is zero, this operand doesn't contribute to the value
435d2201f2fSdrahn      so give it a standard value of zero.  */
436d2201f2fSdrahn   if (length == 0)
437d2201f2fSdrahn     {
438d2201f2fSdrahn       *valuep = 0;
439d2201f2fSdrahn       return 1;
440d2201f2fSdrahn     }
441d2201f2fSdrahn 
442d2201f2fSdrahn #if 0
443d2201f2fSdrahn   if (CGEN_INT_INSN_P
444d2201f2fSdrahn       && word_offset != 0)
445d2201f2fSdrahn     abort ();
446d2201f2fSdrahn #endif
447d2201f2fSdrahn 
448d2201f2fSdrahn   if (word_length > 32)
449d2201f2fSdrahn     abort ();
450d2201f2fSdrahn 
451d2201f2fSdrahn   /* For architectures with insns smaller than the insn-base-bitsize,
452d2201f2fSdrahn      word_length may be too big.  */
453d2201f2fSdrahn   if (cd->min_insn_bitsize < cd->base_insn_bitsize)
454d2201f2fSdrahn     {
455d2201f2fSdrahn       if (word_offset == 0
456d2201f2fSdrahn 	  && word_length > total_length)
457d2201f2fSdrahn 	word_length = total_length;
458d2201f2fSdrahn     }
459d2201f2fSdrahn 
460d2201f2fSdrahn   /* Does the value reside in INSN_VALUE, and at the right alignment?  */
461d2201f2fSdrahn 
462d2201f2fSdrahn   if (CGEN_INT_INSN_P || (word_offset == 0 && word_length == total_length))
463d2201f2fSdrahn     {
464d2201f2fSdrahn       if (CGEN_INSN_LSB0_P)
465d2201f2fSdrahn 	value = insn_value >> ((word_offset + start + 1) - length);
466d2201f2fSdrahn       else
467d2201f2fSdrahn 	value = insn_value >> (total_length - ( word_offset + start + length));
468d2201f2fSdrahn     }
469d2201f2fSdrahn 
470d2201f2fSdrahn #if ! CGEN_INT_INSN_P
471d2201f2fSdrahn 
472d2201f2fSdrahn   else
473d2201f2fSdrahn     {
474d2201f2fSdrahn       unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;
475d2201f2fSdrahn 
476d2201f2fSdrahn       if (word_length > 32)
477d2201f2fSdrahn 	abort ();
478d2201f2fSdrahn 
479d2201f2fSdrahn       if (fill_cache (cd, ex_info, word_offset / 8, word_length / 8, pc) == 0)
480d2201f2fSdrahn 	return 0;
481d2201f2fSdrahn 
482d2201f2fSdrahn       value = extract_1 (cd, ex_info, start, length, word_length, bufp, pc);
483d2201f2fSdrahn     }
484d2201f2fSdrahn 
485d2201f2fSdrahn #endif /* ! CGEN_INT_INSN_P */
486d2201f2fSdrahn 
487d2201f2fSdrahn   /* Written this way to avoid undefined behaviour.  */
488d2201f2fSdrahn   mask = (((1L << (length - 1)) - 1) << 1) | 1;
489d2201f2fSdrahn 
490d2201f2fSdrahn   value &= mask;
491d2201f2fSdrahn   /* sign extend? */
492d2201f2fSdrahn   if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)
493d2201f2fSdrahn       && (value & (1L << (length - 1))))
494d2201f2fSdrahn     value |= ~mask;
495d2201f2fSdrahn 
496d2201f2fSdrahn   *valuep = value;
497d2201f2fSdrahn 
498d2201f2fSdrahn   return 1;
499d2201f2fSdrahn }
500d2201f2fSdrahn 
501d2201f2fSdrahn /* Default insn extractor.
502d2201f2fSdrahn 
503d2201f2fSdrahn    INSN_VALUE is the first base_insn_bitsize bits, translated to host order.
504d2201f2fSdrahn    The extracted fields are stored in FIELDS.
505d2201f2fSdrahn    EX_INFO is used to handle reading variable length insns.
506d2201f2fSdrahn    Return the length of the insn in bits, or 0 if no match,
507d2201f2fSdrahn    or -1 if an error occurs fetching data (memory_error_func will have
508d2201f2fSdrahn    been called).  */
509d2201f2fSdrahn 
510d2201f2fSdrahn static int
extract_insn_normal(CGEN_CPU_DESC cd,const CGEN_INSN * insn,CGEN_EXTRACT_INFO * ex_info,CGEN_INSN_INT insn_value,CGEN_FIELDS * fields,bfd_vma pc)511*cf2f2c56Smiod extract_insn_normal (CGEN_CPU_DESC cd,
512*cf2f2c56Smiod 		     const CGEN_INSN *insn,
513*cf2f2c56Smiod 		     CGEN_EXTRACT_INFO *ex_info,
514*cf2f2c56Smiod 		     CGEN_INSN_INT insn_value,
515*cf2f2c56Smiod 		     CGEN_FIELDS *fields,
516*cf2f2c56Smiod 		     bfd_vma pc)
517d2201f2fSdrahn {
518d2201f2fSdrahn   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
519d2201f2fSdrahn   const CGEN_SYNTAX_CHAR_TYPE *syn;
520d2201f2fSdrahn 
521d2201f2fSdrahn   CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
522d2201f2fSdrahn 
523d2201f2fSdrahn   CGEN_INIT_EXTRACT (cd);
524d2201f2fSdrahn 
525d2201f2fSdrahn   for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
526d2201f2fSdrahn     {
527d2201f2fSdrahn       int length;
528d2201f2fSdrahn 
529d2201f2fSdrahn       if (CGEN_SYNTAX_CHAR_P (*syn))
530d2201f2fSdrahn 	continue;
531d2201f2fSdrahn 
532d2201f2fSdrahn       length = (* cd->extract_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
533d2201f2fSdrahn 					ex_info, insn_value, fields, pc);
534d2201f2fSdrahn       if (length <= 0)
535d2201f2fSdrahn 	return length;
536d2201f2fSdrahn     }
537d2201f2fSdrahn 
538d2201f2fSdrahn   /* We recognized and successfully extracted this insn.  */
539d2201f2fSdrahn   return CGEN_INSN_BITSIZE (insn);
540d2201f2fSdrahn }
541d2201f2fSdrahn 
542d2201f2fSdrahn /* machine generated code added here */
543d2201f2fSdrahn 
544d2201f2fSdrahn const char * iq2000_cgen_insert_operand
545d2201f2fSdrahn   PARAMS ((CGEN_CPU_DESC, int, CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma));
546d2201f2fSdrahn 
547d2201f2fSdrahn /* Main entry point for operand insertion.
548d2201f2fSdrahn 
549d2201f2fSdrahn    This function is basically just a big switch statement.  Earlier versions
550d2201f2fSdrahn    used tables to look up the function to use, but
551d2201f2fSdrahn    - if the table contains both assembler and disassembler functions then
552d2201f2fSdrahn      the disassembler contains much of the assembler and vice-versa,
553d2201f2fSdrahn    - there's a lot of inlining possibilities as things grow,
554d2201f2fSdrahn    - using a switch statement avoids the function call overhead.
555d2201f2fSdrahn 
556d2201f2fSdrahn    This function could be moved into `parse_insn_normal', but keeping it
557d2201f2fSdrahn    separate makes clear the interface between `parse_insn_normal' and each of
558d2201f2fSdrahn    the handlers.  It's also needed by GAS to insert operands that couldn't be
559d2201f2fSdrahn    resolved during parsing.  */
560d2201f2fSdrahn 
561d2201f2fSdrahn const char *
iq2000_cgen_insert_operand(cd,opindex,fields,buffer,pc)562d2201f2fSdrahn iq2000_cgen_insert_operand (cd, opindex, fields, buffer, pc)
563d2201f2fSdrahn      CGEN_CPU_DESC cd;
564d2201f2fSdrahn      int opindex;
565d2201f2fSdrahn      CGEN_FIELDS * fields;
566d2201f2fSdrahn      CGEN_INSN_BYTES_PTR buffer;
567d2201f2fSdrahn      bfd_vma pc ATTRIBUTE_UNUSED;
568d2201f2fSdrahn {
569d2201f2fSdrahn   const char * errmsg = NULL;
570d2201f2fSdrahn   unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
571d2201f2fSdrahn 
572d2201f2fSdrahn   switch (opindex)
573d2201f2fSdrahn     {
574d2201f2fSdrahn     case IQ2000_OPERAND_BASE :
575d2201f2fSdrahn       errmsg = insert_normal (cd, fields->f_rs, 0, 0, 25, 5, 32, total_length, buffer);
576d2201f2fSdrahn       break;
577d2201f2fSdrahn     case IQ2000_OPERAND_BASEOFF :
578d2201f2fSdrahn       errmsg = insert_normal (cd, fields->f_imm, 0, 0, 15, 16, 32, total_length, buffer);
579d2201f2fSdrahn       break;
580d2201f2fSdrahn     case IQ2000_OPERAND_BITNUM :
581d2201f2fSdrahn       errmsg = insert_normal (cd, fields->f_rt, 0, 0, 20, 5, 32, total_length, buffer);
582d2201f2fSdrahn       break;
583d2201f2fSdrahn     case IQ2000_OPERAND_BYTECOUNT :
584d2201f2fSdrahn       errmsg = insert_normal (cd, fields->f_bytecount, 0, 0, 7, 8, 32, total_length, buffer);
585d2201f2fSdrahn       break;
586d2201f2fSdrahn     case IQ2000_OPERAND_CAM_Y :
587d2201f2fSdrahn       errmsg = insert_normal (cd, fields->f_cam_y, 0, 0, 2, 3, 32, total_length, buffer);
588d2201f2fSdrahn       break;
589d2201f2fSdrahn     case IQ2000_OPERAND_CAM_Z :
590d2201f2fSdrahn       errmsg = insert_normal (cd, fields->f_cam_z, 0, 0, 5, 3, 32, total_length, buffer);
591d2201f2fSdrahn       break;
592d2201f2fSdrahn     case IQ2000_OPERAND_CM_3FUNC :
593d2201f2fSdrahn       errmsg = insert_normal (cd, fields->f_cm_3func, 0, 0, 5, 3, 32, total_length, buffer);
594d2201f2fSdrahn       break;
595d2201f2fSdrahn     case IQ2000_OPERAND_CM_3Z :
596d2201f2fSdrahn       errmsg = insert_normal (cd, fields->f_cm_3z, 0, 0, 1, 2, 32, total_length, buffer);
597d2201f2fSdrahn       break;
598d2201f2fSdrahn     case IQ2000_OPERAND_CM_4FUNC :
599d2201f2fSdrahn       errmsg = insert_normal (cd, fields->f_cm_4func, 0, 0, 5, 4, 32, total_length, buffer);
600d2201f2fSdrahn       break;
601d2201f2fSdrahn     case IQ2000_OPERAND_CM_4Z :
602d2201f2fSdrahn       errmsg = insert_normal (cd, fields->f_cm_4z, 0, 0, 2, 3, 32, total_length, buffer);
603d2201f2fSdrahn       break;
604d2201f2fSdrahn     case IQ2000_OPERAND_COUNT :
605d2201f2fSdrahn       errmsg = insert_normal (cd, fields->f_count, 0, 0, 15, 7, 32, total_length, buffer);
606d2201f2fSdrahn       break;
607d2201f2fSdrahn     case IQ2000_OPERAND_EXECODE :
608d2201f2fSdrahn       errmsg = insert_normal (cd, fields->f_excode, 0, 0, 25, 20, 32, total_length, buffer);
609d2201f2fSdrahn       break;
610*cf2f2c56Smiod     case IQ2000_OPERAND_F_INDEX :
611*cf2f2c56Smiod       errmsg = insert_normal (cd, fields->f_index, 0, 0, 8, 9, 32, total_length, buffer);
612*cf2f2c56Smiod       break;
613d2201f2fSdrahn     case IQ2000_OPERAND_HI16 :
614d2201f2fSdrahn       errmsg = insert_normal (cd, fields->f_imm, 0, 0, 15, 16, 32, total_length, buffer);
615d2201f2fSdrahn       break;
616d2201f2fSdrahn     case IQ2000_OPERAND_IMM :
617d2201f2fSdrahn       errmsg = insert_normal (cd, fields->f_imm, 0, 0, 15, 16, 32, total_length, buffer);
618d2201f2fSdrahn       break;
619d2201f2fSdrahn     case IQ2000_OPERAND_JMPTARG :
620d2201f2fSdrahn       {
621d2201f2fSdrahn         long value = fields->f_jtarg;
622d2201f2fSdrahn         value = ((unsigned int) (((value) & (262143))) >> (2));
623d2201f2fSdrahn         errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 15, 16, 32, total_length, buffer);
624d2201f2fSdrahn       }
625d2201f2fSdrahn       break;
626d2201f2fSdrahn     case IQ2000_OPERAND_JMPTARGQ10 :
627d2201f2fSdrahn       {
628d2201f2fSdrahn         long value = fields->f_jtargq10;
629d2201f2fSdrahn         value = ((unsigned int) (((value) & (8388607))) >> (2));
630d2201f2fSdrahn         errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 20, 21, 32, total_length, buffer);
631d2201f2fSdrahn       }
632d2201f2fSdrahn       break;
633d2201f2fSdrahn     case IQ2000_OPERAND_LO16 :
634d2201f2fSdrahn       errmsg = insert_normal (cd, fields->f_imm, 0, 0, 15, 16, 32, total_length, buffer);
635d2201f2fSdrahn       break;
636d2201f2fSdrahn     case IQ2000_OPERAND_MASK :
637d2201f2fSdrahn       errmsg = insert_normal (cd, fields->f_mask, 0, 0, 9, 4, 32, total_length, buffer);
638d2201f2fSdrahn       break;
639d2201f2fSdrahn     case IQ2000_OPERAND_MASKL :
640d2201f2fSdrahn       errmsg = insert_normal (cd, fields->f_maskl, 0, 0, 4, 5, 32, total_length, buffer);
641d2201f2fSdrahn       break;
642d2201f2fSdrahn     case IQ2000_OPERAND_MASKQ10 :
643d2201f2fSdrahn       errmsg = insert_normal (cd, fields->f_maskq10, 0, 0, 10, 5, 32, total_length, buffer);
644d2201f2fSdrahn       break;
645d2201f2fSdrahn     case IQ2000_OPERAND_MASKR :
646d2201f2fSdrahn       errmsg = insert_normal (cd, fields->f_rs, 0, 0, 25, 5, 32, total_length, buffer);
647d2201f2fSdrahn       break;
648d2201f2fSdrahn     case IQ2000_OPERAND_MLO16 :
649d2201f2fSdrahn       errmsg = insert_normal (cd, fields->f_imm, 0, 0, 15, 16, 32, total_length, buffer);
650d2201f2fSdrahn       break;
651d2201f2fSdrahn     case IQ2000_OPERAND_OFFSET :
652d2201f2fSdrahn       {
653d2201f2fSdrahn         long value = fields->f_offset;
654d2201f2fSdrahn         value = ((int) (((value) - (pc))) >> (2));
655d2201f2fSdrahn         errmsg = insert_normal (cd, value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 15, 16, 32, total_length, buffer);
656d2201f2fSdrahn       }
657d2201f2fSdrahn       break;
658d2201f2fSdrahn     case IQ2000_OPERAND_RD :
659d2201f2fSdrahn       errmsg = insert_normal (cd, fields->f_rd, 0, 0, 15, 5, 32, total_length, buffer);
660d2201f2fSdrahn       break;
661d2201f2fSdrahn     case IQ2000_OPERAND_RD_RS :
662d2201f2fSdrahn       {
663d2201f2fSdrahn {
664d2201f2fSdrahn   FLD (f_rd) = FLD (f_rd_rs);
665d2201f2fSdrahn   FLD (f_rs) = FLD (f_rd_rs);
666d2201f2fSdrahn }
667d2201f2fSdrahn         errmsg = insert_normal (cd, fields->f_rd, 0, 0, 15, 5, 32, total_length, buffer);
668d2201f2fSdrahn         if (errmsg)
669d2201f2fSdrahn           break;
670d2201f2fSdrahn         errmsg = insert_normal (cd, fields->f_rs, 0, 0, 25, 5, 32, total_length, buffer);
671d2201f2fSdrahn         if (errmsg)
672d2201f2fSdrahn           break;
673d2201f2fSdrahn       }
674d2201f2fSdrahn       break;
675d2201f2fSdrahn     case IQ2000_OPERAND_RD_RT :
676d2201f2fSdrahn       {
677d2201f2fSdrahn {
678d2201f2fSdrahn   FLD (f_rd) = FLD (f_rd_rt);
679d2201f2fSdrahn   FLD (f_rt) = FLD (f_rd_rt);
680d2201f2fSdrahn }
681d2201f2fSdrahn         errmsg = insert_normal (cd, fields->f_rd, 0, 0, 15, 5, 32, total_length, buffer);
682d2201f2fSdrahn         if (errmsg)
683d2201f2fSdrahn           break;
684d2201f2fSdrahn         errmsg = insert_normal (cd, fields->f_rt, 0, 0, 20, 5, 32, total_length, buffer);
685d2201f2fSdrahn         if (errmsg)
686d2201f2fSdrahn           break;
687d2201f2fSdrahn       }
688d2201f2fSdrahn       break;
689d2201f2fSdrahn     case IQ2000_OPERAND_RS :
690d2201f2fSdrahn       errmsg = insert_normal (cd, fields->f_rs, 0, 0, 25, 5, 32, total_length, buffer);
691d2201f2fSdrahn       break;
692d2201f2fSdrahn     case IQ2000_OPERAND_RT :
693d2201f2fSdrahn       errmsg = insert_normal (cd, fields->f_rt, 0, 0, 20, 5, 32, total_length, buffer);
694d2201f2fSdrahn       break;
695d2201f2fSdrahn     case IQ2000_OPERAND_RT_RS :
696d2201f2fSdrahn       {
697d2201f2fSdrahn {
698d2201f2fSdrahn   FLD (f_rt) = FLD (f_rt_rs);
699d2201f2fSdrahn   FLD (f_rs) = FLD (f_rt_rs);
700d2201f2fSdrahn }
701d2201f2fSdrahn         errmsg = insert_normal (cd, fields->f_rt, 0, 0, 20, 5, 32, total_length, buffer);
702d2201f2fSdrahn         if (errmsg)
703d2201f2fSdrahn           break;
704d2201f2fSdrahn         errmsg = insert_normal (cd, fields->f_rs, 0, 0, 25, 5, 32, total_length, buffer);
705d2201f2fSdrahn         if (errmsg)
706d2201f2fSdrahn           break;
707d2201f2fSdrahn       }
708d2201f2fSdrahn       break;
709d2201f2fSdrahn     case IQ2000_OPERAND_SHAMT :
710d2201f2fSdrahn       errmsg = insert_normal (cd, fields->f_shamt, 0, 0, 10, 5, 32, total_length, buffer);
711d2201f2fSdrahn       break;
712d2201f2fSdrahn 
713d2201f2fSdrahn     default :
714d2201f2fSdrahn       /* xgettext:c-format */
715d2201f2fSdrahn       fprintf (stderr, _("Unrecognized field %d while building insn.\n"),
716d2201f2fSdrahn 	       opindex);
717d2201f2fSdrahn       abort ();
718d2201f2fSdrahn   }
719d2201f2fSdrahn 
720d2201f2fSdrahn   return errmsg;
721d2201f2fSdrahn }
722d2201f2fSdrahn 
723d2201f2fSdrahn int iq2000_cgen_extract_operand
724d2201f2fSdrahn   PARAMS ((CGEN_CPU_DESC, int, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
725d2201f2fSdrahn            CGEN_FIELDS *, bfd_vma));
726d2201f2fSdrahn 
727d2201f2fSdrahn /* Main entry point for operand extraction.
728d2201f2fSdrahn    The result is <= 0 for error, >0 for success.
729d2201f2fSdrahn    ??? Actual values aren't well defined right now.
730d2201f2fSdrahn 
731d2201f2fSdrahn    This function is basically just a big switch statement.  Earlier versions
732d2201f2fSdrahn    used tables to look up the function to use, but
733d2201f2fSdrahn    - if the table contains both assembler and disassembler functions then
734d2201f2fSdrahn      the disassembler contains much of the assembler and vice-versa,
735d2201f2fSdrahn    - there's a lot of inlining possibilities as things grow,
736d2201f2fSdrahn    - using a switch statement avoids the function call overhead.
737d2201f2fSdrahn 
738d2201f2fSdrahn    This function could be moved into `print_insn_normal', but keeping it
739d2201f2fSdrahn    separate makes clear the interface between `print_insn_normal' and each of
740d2201f2fSdrahn    the handlers.  */
741d2201f2fSdrahn 
742d2201f2fSdrahn int
iq2000_cgen_extract_operand(cd,opindex,ex_info,insn_value,fields,pc)743d2201f2fSdrahn iq2000_cgen_extract_operand (cd, opindex, ex_info, insn_value, fields, pc)
744d2201f2fSdrahn      CGEN_CPU_DESC cd;
745d2201f2fSdrahn      int opindex;
746d2201f2fSdrahn      CGEN_EXTRACT_INFO *ex_info;
747d2201f2fSdrahn      CGEN_INSN_INT insn_value;
748d2201f2fSdrahn      CGEN_FIELDS * fields;
749d2201f2fSdrahn      bfd_vma pc;
750d2201f2fSdrahn {
751d2201f2fSdrahn   /* Assume success (for those operands that are nops).  */
752d2201f2fSdrahn   int length = 1;
753d2201f2fSdrahn   unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
754d2201f2fSdrahn 
755d2201f2fSdrahn   switch (opindex)
756d2201f2fSdrahn     {
757d2201f2fSdrahn     case IQ2000_OPERAND_BASE :
758d2201f2fSdrahn       length = extract_normal (cd, ex_info, insn_value, 0, 0, 25, 5, 32, total_length, pc, & fields->f_rs);
759d2201f2fSdrahn       break;
760d2201f2fSdrahn     case IQ2000_OPERAND_BASEOFF :
761d2201f2fSdrahn       length = extract_normal (cd, ex_info, insn_value, 0, 0, 15, 16, 32, total_length, pc, & fields->f_imm);
762d2201f2fSdrahn       break;
763d2201f2fSdrahn     case IQ2000_OPERAND_BITNUM :
764d2201f2fSdrahn       length = extract_normal (cd, ex_info, insn_value, 0, 0, 20, 5, 32, total_length, pc, & fields->f_rt);
765d2201f2fSdrahn       break;
766d2201f2fSdrahn     case IQ2000_OPERAND_BYTECOUNT :
767d2201f2fSdrahn       length = extract_normal (cd, ex_info, insn_value, 0, 0, 7, 8, 32, total_length, pc, & fields->f_bytecount);
768d2201f2fSdrahn       break;
769d2201f2fSdrahn     case IQ2000_OPERAND_CAM_Y :
770d2201f2fSdrahn       length = extract_normal (cd, ex_info, insn_value, 0, 0, 2, 3, 32, total_length, pc, & fields->f_cam_y);
771d2201f2fSdrahn       break;
772d2201f2fSdrahn     case IQ2000_OPERAND_CAM_Z :
773d2201f2fSdrahn       length = extract_normal (cd, ex_info, insn_value, 0, 0, 5, 3, 32, total_length, pc, & fields->f_cam_z);
774d2201f2fSdrahn       break;
775d2201f2fSdrahn     case IQ2000_OPERAND_CM_3FUNC :
776d2201f2fSdrahn       length = extract_normal (cd, ex_info, insn_value, 0, 0, 5, 3, 32, total_length, pc, & fields->f_cm_3func);
777d2201f2fSdrahn       break;
778d2201f2fSdrahn     case IQ2000_OPERAND_CM_3Z :
779d2201f2fSdrahn       length = extract_normal (cd, ex_info, insn_value, 0, 0, 1, 2, 32, total_length, pc, & fields->f_cm_3z);
780d2201f2fSdrahn       break;
781d2201f2fSdrahn     case IQ2000_OPERAND_CM_4FUNC :
782d2201f2fSdrahn       length = extract_normal (cd, ex_info, insn_value, 0, 0, 5, 4, 32, total_length, pc, & fields->f_cm_4func);
783d2201f2fSdrahn       break;
784d2201f2fSdrahn     case IQ2000_OPERAND_CM_4Z :
785d2201f2fSdrahn       length = extract_normal (cd, ex_info, insn_value, 0, 0, 2, 3, 32, total_length, pc, & fields->f_cm_4z);
786d2201f2fSdrahn       break;
787d2201f2fSdrahn     case IQ2000_OPERAND_COUNT :
788d2201f2fSdrahn       length = extract_normal (cd, ex_info, insn_value, 0, 0, 15, 7, 32, total_length, pc, & fields->f_count);
789d2201f2fSdrahn       break;
790d2201f2fSdrahn     case IQ2000_OPERAND_EXECODE :
791d2201f2fSdrahn       length = extract_normal (cd, ex_info, insn_value, 0, 0, 25, 20, 32, total_length, pc, & fields->f_excode);
792d2201f2fSdrahn       break;
793*cf2f2c56Smiod     case IQ2000_OPERAND_F_INDEX :
794*cf2f2c56Smiod       length = extract_normal (cd, ex_info, insn_value, 0, 0, 8, 9, 32, total_length, pc, & fields->f_index);
795*cf2f2c56Smiod       break;
796d2201f2fSdrahn     case IQ2000_OPERAND_HI16 :
797d2201f2fSdrahn       length = extract_normal (cd, ex_info, insn_value, 0, 0, 15, 16, 32, total_length, pc, & fields->f_imm);
798d2201f2fSdrahn       break;
799d2201f2fSdrahn     case IQ2000_OPERAND_IMM :
800d2201f2fSdrahn       length = extract_normal (cd, ex_info, insn_value, 0, 0, 15, 16, 32, total_length, pc, & fields->f_imm);
801d2201f2fSdrahn       break;
802d2201f2fSdrahn     case IQ2000_OPERAND_JMPTARG :
803d2201f2fSdrahn       {
804d2201f2fSdrahn         long value;
805d2201f2fSdrahn         length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 15, 16, 32, total_length, pc, & value);
806d2201f2fSdrahn         value = ((((pc) & (0xf0000000))) | (((value) << (2))));
807d2201f2fSdrahn         fields->f_jtarg = value;
808d2201f2fSdrahn       }
809d2201f2fSdrahn       break;
810d2201f2fSdrahn     case IQ2000_OPERAND_JMPTARGQ10 :
811d2201f2fSdrahn       {
812d2201f2fSdrahn         long value;
813d2201f2fSdrahn         length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 20, 21, 32, total_length, pc, & value);
814d2201f2fSdrahn         value = ((((pc) & (0xf0000000))) | (((value) << (2))));
815d2201f2fSdrahn         fields->f_jtargq10 = value;
816d2201f2fSdrahn       }
817d2201f2fSdrahn       break;
818d2201f2fSdrahn     case IQ2000_OPERAND_LO16 :
819d2201f2fSdrahn       length = extract_normal (cd, ex_info, insn_value, 0, 0, 15, 16, 32, total_length, pc, & fields->f_imm);
820d2201f2fSdrahn       break;
821d2201f2fSdrahn     case IQ2000_OPERAND_MASK :
822d2201f2fSdrahn       length = extract_normal (cd, ex_info, insn_value, 0, 0, 9, 4, 32, total_length, pc, & fields->f_mask);
823d2201f2fSdrahn       break;
824d2201f2fSdrahn     case IQ2000_OPERAND_MASKL :
825d2201f2fSdrahn       length = extract_normal (cd, ex_info, insn_value, 0, 0, 4, 5, 32, total_length, pc, & fields->f_maskl);
826d2201f2fSdrahn       break;
827d2201f2fSdrahn     case IQ2000_OPERAND_MASKQ10 :
828d2201f2fSdrahn       length = extract_normal (cd, ex_info, insn_value, 0, 0, 10, 5, 32, total_length, pc, & fields->f_maskq10);
829d2201f2fSdrahn       break;
830d2201f2fSdrahn     case IQ2000_OPERAND_MASKR :
831d2201f2fSdrahn       length = extract_normal (cd, ex_info, insn_value, 0, 0, 25, 5, 32, total_length, pc, & fields->f_rs);
832d2201f2fSdrahn       break;
833d2201f2fSdrahn     case IQ2000_OPERAND_MLO16 :
834d2201f2fSdrahn       length = extract_normal (cd, ex_info, insn_value, 0, 0, 15, 16, 32, total_length, pc, & fields->f_imm);
835d2201f2fSdrahn       break;
836d2201f2fSdrahn     case IQ2000_OPERAND_OFFSET :
837d2201f2fSdrahn       {
838d2201f2fSdrahn         long value;
839d2201f2fSdrahn         length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_SIGNED)|(1<<CGEN_IFLD_PCREL_ADDR), 0, 15, 16, 32, total_length, pc, & value);
840d2201f2fSdrahn         value = ((((value) << (2))) + (((pc) + (4))));
841d2201f2fSdrahn         fields->f_offset = value;
842d2201f2fSdrahn       }
843d2201f2fSdrahn       break;
844d2201f2fSdrahn     case IQ2000_OPERAND_RD :
845d2201f2fSdrahn       length = extract_normal (cd, ex_info, insn_value, 0, 0, 15, 5, 32, total_length, pc, & fields->f_rd);
846d2201f2fSdrahn       break;
847d2201f2fSdrahn     case IQ2000_OPERAND_RD_RS :
848d2201f2fSdrahn       {
849d2201f2fSdrahn         length = extract_normal (cd, ex_info, insn_value, 0, 0, 15, 5, 32, total_length, pc, & fields->f_rd);
850d2201f2fSdrahn         if (length <= 0) break;
851d2201f2fSdrahn         length = extract_normal (cd, ex_info, insn_value, 0, 0, 25, 5, 32, total_length, pc, & fields->f_rs);
852d2201f2fSdrahn         if (length <= 0) break;
853d2201f2fSdrahn {
854d2201f2fSdrahn   FLD (f_rd_rs) = FLD (f_rs);
855d2201f2fSdrahn }
856d2201f2fSdrahn       }
857d2201f2fSdrahn       break;
858d2201f2fSdrahn     case IQ2000_OPERAND_RD_RT :
859d2201f2fSdrahn       {
860d2201f2fSdrahn         length = extract_normal (cd, ex_info, insn_value, 0, 0, 15, 5, 32, total_length, pc, & fields->f_rd);
861d2201f2fSdrahn         if (length <= 0) break;
862d2201f2fSdrahn         length = extract_normal (cd, ex_info, insn_value, 0, 0, 20, 5, 32, total_length, pc, & fields->f_rt);
863d2201f2fSdrahn         if (length <= 0) break;
864d2201f2fSdrahn {
865d2201f2fSdrahn   FLD (f_rd_rt) = FLD (f_rt);
866d2201f2fSdrahn }
867d2201f2fSdrahn       }
868d2201f2fSdrahn       break;
869d2201f2fSdrahn     case IQ2000_OPERAND_RS :
870d2201f2fSdrahn       length = extract_normal (cd, ex_info, insn_value, 0, 0, 25, 5, 32, total_length, pc, & fields->f_rs);
871d2201f2fSdrahn       break;
872d2201f2fSdrahn     case IQ2000_OPERAND_RT :
873d2201f2fSdrahn       length = extract_normal (cd, ex_info, insn_value, 0, 0, 20, 5, 32, total_length, pc, & fields->f_rt);
874d2201f2fSdrahn       break;
875d2201f2fSdrahn     case IQ2000_OPERAND_RT_RS :
876d2201f2fSdrahn       {
877d2201f2fSdrahn         length = extract_normal (cd, ex_info, insn_value, 0, 0, 20, 5, 32, total_length, pc, & fields->f_rt);
878d2201f2fSdrahn         if (length <= 0) break;
879d2201f2fSdrahn         length = extract_normal (cd, ex_info, insn_value, 0, 0, 25, 5, 32, total_length, pc, & fields->f_rs);
880d2201f2fSdrahn         if (length <= 0) break;
881d2201f2fSdrahn {
882d2201f2fSdrahn   FLD (f_rd_rs) = FLD (f_rs);
883d2201f2fSdrahn }
884d2201f2fSdrahn       }
885d2201f2fSdrahn       break;
886d2201f2fSdrahn     case IQ2000_OPERAND_SHAMT :
887d2201f2fSdrahn       length = extract_normal (cd, ex_info, insn_value, 0, 0, 10, 5, 32, total_length, pc, & fields->f_shamt);
888d2201f2fSdrahn       break;
889d2201f2fSdrahn 
890d2201f2fSdrahn     default :
891d2201f2fSdrahn       /* xgettext:c-format */
892d2201f2fSdrahn       fprintf (stderr, _("Unrecognized field %d while decoding insn.\n"),
893d2201f2fSdrahn 	       opindex);
894d2201f2fSdrahn       abort ();
895d2201f2fSdrahn     }
896d2201f2fSdrahn 
897d2201f2fSdrahn   return length;
898d2201f2fSdrahn }
899d2201f2fSdrahn 
900d2201f2fSdrahn cgen_insert_fn * const iq2000_cgen_insert_handlers[] =
901d2201f2fSdrahn {
902d2201f2fSdrahn   insert_insn_normal,
903d2201f2fSdrahn };
904d2201f2fSdrahn 
905d2201f2fSdrahn cgen_extract_fn * const iq2000_cgen_extract_handlers[] =
906d2201f2fSdrahn {
907d2201f2fSdrahn   extract_insn_normal,
908d2201f2fSdrahn };
909d2201f2fSdrahn 
910d2201f2fSdrahn int iq2000_cgen_get_int_operand
911d2201f2fSdrahn   PARAMS ((CGEN_CPU_DESC, int, const CGEN_FIELDS *));
912d2201f2fSdrahn bfd_vma iq2000_cgen_get_vma_operand
913d2201f2fSdrahn   PARAMS ((CGEN_CPU_DESC, int, const CGEN_FIELDS *));
914d2201f2fSdrahn 
915d2201f2fSdrahn /* Getting values from cgen_fields is handled by a collection of functions.
916d2201f2fSdrahn    They are distinguished by the type of the VALUE argument they return.
917d2201f2fSdrahn    TODO: floating point, inlining support, remove cases where result type
918d2201f2fSdrahn    not appropriate.  */
919d2201f2fSdrahn 
920d2201f2fSdrahn int
iq2000_cgen_get_int_operand(cd,opindex,fields)921d2201f2fSdrahn iq2000_cgen_get_int_operand (cd, opindex, fields)
922d2201f2fSdrahn      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
923d2201f2fSdrahn      int opindex;
924d2201f2fSdrahn      const CGEN_FIELDS * fields;
925d2201f2fSdrahn {
926d2201f2fSdrahn   int value;
927d2201f2fSdrahn 
928d2201f2fSdrahn   switch (opindex)
929d2201f2fSdrahn     {
930d2201f2fSdrahn     case IQ2000_OPERAND_BASE :
931d2201f2fSdrahn       value = fields->f_rs;
932d2201f2fSdrahn       break;
933d2201f2fSdrahn     case IQ2000_OPERAND_BASEOFF :
934d2201f2fSdrahn       value = fields->f_imm;
935d2201f2fSdrahn       break;
936d2201f2fSdrahn     case IQ2000_OPERAND_BITNUM :
937d2201f2fSdrahn       value = fields->f_rt;
938d2201f2fSdrahn       break;
939d2201f2fSdrahn     case IQ2000_OPERAND_BYTECOUNT :
940d2201f2fSdrahn       value = fields->f_bytecount;
941d2201f2fSdrahn       break;
942d2201f2fSdrahn     case IQ2000_OPERAND_CAM_Y :
943d2201f2fSdrahn       value = fields->f_cam_y;
944d2201f2fSdrahn       break;
945d2201f2fSdrahn     case IQ2000_OPERAND_CAM_Z :
946d2201f2fSdrahn       value = fields->f_cam_z;
947d2201f2fSdrahn       break;
948d2201f2fSdrahn     case IQ2000_OPERAND_CM_3FUNC :
949d2201f2fSdrahn       value = fields->f_cm_3func;
950d2201f2fSdrahn       break;
951d2201f2fSdrahn     case IQ2000_OPERAND_CM_3Z :
952d2201f2fSdrahn       value = fields->f_cm_3z;
953d2201f2fSdrahn       break;
954d2201f2fSdrahn     case IQ2000_OPERAND_CM_4FUNC :
955d2201f2fSdrahn       value = fields->f_cm_4func;
956d2201f2fSdrahn       break;
957d2201f2fSdrahn     case IQ2000_OPERAND_CM_4Z :
958d2201f2fSdrahn       value = fields->f_cm_4z;
959d2201f2fSdrahn       break;
960d2201f2fSdrahn     case IQ2000_OPERAND_COUNT :
961d2201f2fSdrahn       value = fields->f_count;
962d2201f2fSdrahn       break;
963d2201f2fSdrahn     case IQ2000_OPERAND_EXECODE :
964d2201f2fSdrahn       value = fields->f_excode;
965d2201f2fSdrahn       break;
966*cf2f2c56Smiod     case IQ2000_OPERAND_F_INDEX :
967*cf2f2c56Smiod       value = fields->f_index;
968*cf2f2c56Smiod       break;
969d2201f2fSdrahn     case IQ2000_OPERAND_HI16 :
970d2201f2fSdrahn       value = fields->f_imm;
971d2201f2fSdrahn       break;
972d2201f2fSdrahn     case IQ2000_OPERAND_IMM :
973d2201f2fSdrahn       value = fields->f_imm;
974d2201f2fSdrahn       break;
975d2201f2fSdrahn     case IQ2000_OPERAND_JMPTARG :
976d2201f2fSdrahn       value = fields->f_jtarg;
977d2201f2fSdrahn       break;
978d2201f2fSdrahn     case IQ2000_OPERAND_JMPTARGQ10 :
979d2201f2fSdrahn       value = fields->f_jtargq10;
980d2201f2fSdrahn       break;
981d2201f2fSdrahn     case IQ2000_OPERAND_LO16 :
982d2201f2fSdrahn       value = fields->f_imm;
983d2201f2fSdrahn       break;
984d2201f2fSdrahn     case IQ2000_OPERAND_MASK :
985d2201f2fSdrahn       value = fields->f_mask;
986d2201f2fSdrahn       break;
987d2201f2fSdrahn     case IQ2000_OPERAND_MASKL :
988d2201f2fSdrahn       value = fields->f_maskl;
989d2201f2fSdrahn       break;
990d2201f2fSdrahn     case IQ2000_OPERAND_MASKQ10 :
991d2201f2fSdrahn       value = fields->f_maskq10;
992d2201f2fSdrahn       break;
993d2201f2fSdrahn     case IQ2000_OPERAND_MASKR :
994d2201f2fSdrahn       value = fields->f_rs;
995d2201f2fSdrahn       break;
996d2201f2fSdrahn     case IQ2000_OPERAND_MLO16 :
997d2201f2fSdrahn       value = fields->f_imm;
998d2201f2fSdrahn       break;
999d2201f2fSdrahn     case IQ2000_OPERAND_OFFSET :
1000d2201f2fSdrahn       value = fields->f_offset;
1001d2201f2fSdrahn       break;
1002d2201f2fSdrahn     case IQ2000_OPERAND_RD :
1003d2201f2fSdrahn       value = fields->f_rd;
1004d2201f2fSdrahn       break;
1005d2201f2fSdrahn     case IQ2000_OPERAND_RD_RS :
1006d2201f2fSdrahn       value = fields->f_rd_rs;
1007d2201f2fSdrahn       break;
1008d2201f2fSdrahn     case IQ2000_OPERAND_RD_RT :
1009d2201f2fSdrahn       value = fields->f_rd_rt;
1010d2201f2fSdrahn       break;
1011d2201f2fSdrahn     case IQ2000_OPERAND_RS :
1012d2201f2fSdrahn       value = fields->f_rs;
1013d2201f2fSdrahn       break;
1014d2201f2fSdrahn     case IQ2000_OPERAND_RT :
1015d2201f2fSdrahn       value = fields->f_rt;
1016d2201f2fSdrahn       break;
1017d2201f2fSdrahn     case IQ2000_OPERAND_RT_RS :
1018d2201f2fSdrahn       value = fields->f_rt_rs;
1019d2201f2fSdrahn       break;
1020d2201f2fSdrahn     case IQ2000_OPERAND_SHAMT :
1021d2201f2fSdrahn       value = fields->f_shamt;
1022d2201f2fSdrahn       break;
1023d2201f2fSdrahn 
1024d2201f2fSdrahn     default :
1025d2201f2fSdrahn       /* xgettext:c-format */
1026d2201f2fSdrahn       fprintf (stderr, _("Unrecognized field %d while getting int operand.\n"),
1027d2201f2fSdrahn 		       opindex);
1028d2201f2fSdrahn       abort ();
1029d2201f2fSdrahn   }
1030d2201f2fSdrahn 
1031d2201f2fSdrahn   return value;
1032d2201f2fSdrahn }
1033d2201f2fSdrahn 
1034d2201f2fSdrahn bfd_vma
iq2000_cgen_get_vma_operand(cd,opindex,fields)1035d2201f2fSdrahn iq2000_cgen_get_vma_operand (cd, opindex, fields)
1036d2201f2fSdrahn      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
1037d2201f2fSdrahn      int opindex;
1038d2201f2fSdrahn      const CGEN_FIELDS * fields;
1039d2201f2fSdrahn {
1040d2201f2fSdrahn   bfd_vma value;
1041d2201f2fSdrahn 
1042d2201f2fSdrahn   switch (opindex)
1043d2201f2fSdrahn     {
1044d2201f2fSdrahn     case IQ2000_OPERAND_BASE :
1045d2201f2fSdrahn       value = fields->f_rs;
1046d2201f2fSdrahn       break;
1047d2201f2fSdrahn     case IQ2000_OPERAND_BASEOFF :
1048d2201f2fSdrahn       value = fields->f_imm;
1049d2201f2fSdrahn       break;
1050d2201f2fSdrahn     case IQ2000_OPERAND_BITNUM :
1051d2201f2fSdrahn       value = fields->f_rt;
1052d2201f2fSdrahn       break;
1053d2201f2fSdrahn     case IQ2000_OPERAND_BYTECOUNT :
1054d2201f2fSdrahn       value = fields->f_bytecount;
1055d2201f2fSdrahn       break;
1056d2201f2fSdrahn     case IQ2000_OPERAND_CAM_Y :
1057d2201f2fSdrahn       value = fields->f_cam_y;
1058d2201f2fSdrahn       break;
1059d2201f2fSdrahn     case IQ2000_OPERAND_CAM_Z :
1060d2201f2fSdrahn       value = fields->f_cam_z;
1061d2201f2fSdrahn       break;
1062d2201f2fSdrahn     case IQ2000_OPERAND_CM_3FUNC :
1063d2201f2fSdrahn       value = fields->f_cm_3func;
1064d2201f2fSdrahn       break;
1065d2201f2fSdrahn     case IQ2000_OPERAND_CM_3Z :
1066d2201f2fSdrahn       value = fields->f_cm_3z;
1067d2201f2fSdrahn       break;
1068d2201f2fSdrahn     case IQ2000_OPERAND_CM_4FUNC :
1069d2201f2fSdrahn       value = fields->f_cm_4func;
1070d2201f2fSdrahn       break;
1071d2201f2fSdrahn     case IQ2000_OPERAND_CM_4Z :
1072d2201f2fSdrahn       value = fields->f_cm_4z;
1073d2201f2fSdrahn       break;
1074d2201f2fSdrahn     case IQ2000_OPERAND_COUNT :
1075d2201f2fSdrahn       value = fields->f_count;
1076d2201f2fSdrahn       break;
1077d2201f2fSdrahn     case IQ2000_OPERAND_EXECODE :
1078d2201f2fSdrahn       value = fields->f_excode;
1079d2201f2fSdrahn       break;
1080*cf2f2c56Smiod     case IQ2000_OPERAND_F_INDEX :
1081*cf2f2c56Smiod       value = fields->f_index;
1082*cf2f2c56Smiod       break;
1083d2201f2fSdrahn     case IQ2000_OPERAND_HI16 :
1084d2201f2fSdrahn       value = fields->f_imm;
1085d2201f2fSdrahn       break;
1086d2201f2fSdrahn     case IQ2000_OPERAND_IMM :
1087d2201f2fSdrahn       value = fields->f_imm;
1088d2201f2fSdrahn       break;
1089d2201f2fSdrahn     case IQ2000_OPERAND_JMPTARG :
1090d2201f2fSdrahn       value = fields->f_jtarg;
1091d2201f2fSdrahn       break;
1092d2201f2fSdrahn     case IQ2000_OPERAND_JMPTARGQ10 :
1093d2201f2fSdrahn       value = fields->f_jtargq10;
1094d2201f2fSdrahn       break;
1095d2201f2fSdrahn     case IQ2000_OPERAND_LO16 :
1096d2201f2fSdrahn       value = fields->f_imm;
1097d2201f2fSdrahn       break;
1098d2201f2fSdrahn     case IQ2000_OPERAND_MASK :
1099d2201f2fSdrahn       value = fields->f_mask;
1100d2201f2fSdrahn       break;
1101d2201f2fSdrahn     case IQ2000_OPERAND_MASKL :
1102d2201f2fSdrahn       value = fields->f_maskl;
1103d2201f2fSdrahn       break;
1104d2201f2fSdrahn     case IQ2000_OPERAND_MASKQ10 :
1105d2201f2fSdrahn       value = fields->f_maskq10;
1106d2201f2fSdrahn       break;
1107d2201f2fSdrahn     case IQ2000_OPERAND_MASKR :
1108d2201f2fSdrahn       value = fields->f_rs;
1109d2201f2fSdrahn       break;
1110d2201f2fSdrahn     case IQ2000_OPERAND_MLO16 :
1111d2201f2fSdrahn       value = fields->f_imm;
1112d2201f2fSdrahn       break;
1113d2201f2fSdrahn     case IQ2000_OPERAND_OFFSET :
1114d2201f2fSdrahn       value = fields->f_offset;
1115d2201f2fSdrahn       break;
1116d2201f2fSdrahn     case IQ2000_OPERAND_RD :
1117d2201f2fSdrahn       value = fields->f_rd;
1118d2201f2fSdrahn       break;
1119d2201f2fSdrahn     case IQ2000_OPERAND_RD_RS :
1120d2201f2fSdrahn       value = fields->f_rd_rs;
1121d2201f2fSdrahn       break;
1122d2201f2fSdrahn     case IQ2000_OPERAND_RD_RT :
1123d2201f2fSdrahn       value = fields->f_rd_rt;
1124d2201f2fSdrahn       break;
1125d2201f2fSdrahn     case IQ2000_OPERAND_RS :
1126d2201f2fSdrahn       value = fields->f_rs;
1127d2201f2fSdrahn       break;
1128d2201f2fSdrahn     case IQ2000_OPERAND_RT :
1129d2201f2fSdrahn       value = fields->f_rt;
1130d2201f2fSdrahn       break;
1131d2201f2fSdrahn     case IQ2000_OPERAND_RT_RS :
1132d2201f2fSdrahn       value = fields->f_rt_rs;
1133d2201f2fSdrahn       break;
1134d2201f2fSdrahn     case IQ2000_OPERAND_SHAMT :
1135d2201f2fSdrahn       value = fields->f_shamt;
1136d2201f2fSdrahn       break;
1137d2201f2fSdrahn 
1138d2201f2fSdrahn     default :
1139d2201f2fSdrahn       /* xgettext:c-format */
1140d2201f2fSdrahn       fprintf (stderr, _("Unrecognized field %d while getting vma operand.\n"),
1141d2201f2fSdrahn 		       opindex);
1142d2201f2fSdrahn       abort ();
1143d2201f2fSdrahn   }
1144d2201f2fSdrahn 
1145d2201f2fSdrahn   return value;
1146d2201f2fSdrahn }
1147d2201f2fSdrahn 
1148d2201f2fSdrahn void iq2000_cgen_set_int_operand
1149d2201f2fSdrahn   PARAMS ((CGEN_CPU_DESC, int, CGEN_FIELDS *, int));
1150d2201f2fSdrahn void iq2000_cgen_set_vma_operand
1151d2201f2fSdrahn   PARAMS ((CGEN_CPU_DESC, int, CGEN_FIELDS *, bfd_vma));
1152d2201f2fSdrahn 
1153d2201f2fSdrahn /* Stuffing values in cgen_fields is handled by a collection of functions.
1154d2201f2fSdrahn    They are distinguished by the type of the VALUE argument they accept.
1155d2201f2fSdrahn    TODO: floating point, inlining support, remove cases where argument type
1156d2201f2fSdrahn    not appropriate.  */
1157d2201f2fSdrahn 
1158d2201f2fSdrahn void
iq2000_cgen_set_int_operand(cd,opindex,fields,value)1159d2201f2fSdrahn iq2000_cgen_set_int_operand (cd, opindex, fields, value)
1160d2201f2fSdrahn      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
1161d2201f2fSdrahn      int opindex;
1162d2201f2fSdrahn      CGEN_FIELDS * fields;
1163d2201f2fSdrahn      int value;
1164d2201f2fSdrahn {
1165d2201f2fSdrahn   switch (opindex)
1166d2201f2fSdrahn     {
1167d2201f2fSdrahn     case IQ2000_OPERAND_BASE :
1168d2201f2fSdrahn       fields->f_rs = value;
1169d2201f2fSdrahn       break;
1170d2201f2fSdrahn     case IQ2000_OPERAND_BASEOFF :
1171d2201f2fSdrahn       fields->f_imm = value;
1172d2201f2fSdrahn       break;
1173d2201f2fSdrahn     case IQ2000_OPERAND_BITNUM :
1174d2201f2fSdrahn       fields->f_rt = value;
1175d2201f2fSdrahn       break;
1176d2201f2fSdrahn     case IQ2000_OPERAND_BYTECOUNT :
1177d2201f2fSdrahn       fields->f_bytecount = value;
1178d2201f2fSdrahn       break;
1179d2201f2fSdrahn     case IQ2000_OPERAND_CAM_Y :
1180d2201f2fSdrahn       fields->f_cam_y = value;
1181d2201f2fSdrahn       break;
1182d2201f2fSdrahn     case IQ2000_OPERAND_CAM_Z :
1183d2201f2fSdrahn       fields->f_cam_z = value;
1184d2201f2fSdrahn       break;
1185d2201f2fSdrahn     case IQ2000_OPERAND_CM_3FUNC :
1186d2201f2fSdrahn       fields->f_cm_3func = value;
1187d2201f2fSdrahn       break;
1188d2201f2fSdrahn     case IQ2000_OPERAND_CM_3Z :
1189d2201f2fSdrahn       fields->f_cm_3z = value;
1190d2201f2fSdrahn       break;
1191d2201f2fSdrahn     case IQ2000_OPERAND_CM_4FUNC :
1192d2201f2fSdrahn       fields->f_cm_4func = value;
1193d2201f2fSdrahn       break;
1194d2201f2fSdrahn     case IQ2000_OPERAND_CM_4Z :
1195d2201f2fSdrahn       fields->f_cm_4z = value;
1196d2201f2fSdrahn       break;
1197d2201f2fSdrahn     case IQ2000_OPERAND_COUNT :
1198d2201f2fSdrahn       fields->f_count = value;
1199d2201f2fSdrahn       break;
1200d2201f2fSdrahn     case IQ2000_OPERAND_EXECODE :
1201d2201f2fSdrahn       fields->f_excode = value;
1202d2201f2fSdrahn       break;
1203*cf2f2c56Smiod     case IQ2000_OPERAND_F_INDEX :
1204*cf2f2c56Smiod       fields->f_index = value;
1205*cf2f2c56Smiod       break;
1206d2201f2fSdrahn     case IQ2000_OPERAND_HI16 :
1207d2201f2fSdrahn       fields->f_imm = value;
1208d2201f2fSdrahn       break;
1209d2201f2fSdrahn     case IQ2000_OPERAND_IMM :
1210d2201f2fSdrahn       fields->f_imm = value;
1211d2201f2fSdrahn       break;
1212d2201f2fSdrahn     case IQ2000_OPERAND_JMPTARG :
1213d2201f2fSdrahn       fields->f_jtarg = value;
1214d2201f2fSdrahn       break;
1215d2201f2fSdrahn     case IQ2000_OPERAND_JMPTARGQ10 :
1216d2201f2fSdrahn       fields->f_jtargq10 = value;
1217d2201f2fSdrahn       break;
1218d2201f2fSdrahn     case IQ2000_OPERAND_LO16 :
1219d2201f2fSdrahn       fields->f_imm = value;
1220d2201f2fSdrahn       break;
1221d2201f2fSdrahn     case IQ2000_OPERAND_MASK :
1222d2201f2fSdrahn       fields->f_mask = value;
1223d2201f2fSdrahn       break;
1224d2201f2fSdrahn     case IQ2000_OPERAND_MASKL :
1225d2201f2fSdrahn       fields->f_maskl = value;
1226d2201f2fSdrahn       break;
1227d2201f2fSdrahn     case IQ2000_OPERAND_MASKQ10 :
1228d2201f2fSdrahn       fields->f_maskq10 = value;
1229d2201f2fSdrahn       break;
1230d2201f2fSdrahn     case IQ2000_OPERAND_MASKR :
1231d2201f2fSdrahn       fields->f_rs = value;
1232d2201f2fSdrahn       break;
1233d2201f2fSdrahn     case IQ2000_OPERAND_MLO16 :
1234d2201f2fSdrahn       fields->f_imm = value;
1235d2201f2fSdrahn       break;
1236d2201f2fSdrahn     case IQ2000_OPERAND_OFFSET :
1237d2201f2fSdrahn       fields->f_offset = value;
1238d2201f2fSdrahn       break;
1239d2201f2fSdrahn     case IQ2000_OPERAND_RD :
1240d2201f2fSdrahn       fields->f_rd = value;
1241d2201f2fSdrahn       break;
1242d2201f2fSdrahn     case IQ2000_OPERAND_RD_RS :
1243d2201f2fSdrahn       fields->f_rd_rs = value;
1244d2201f2fSdrahn       break;
1245d2201f2fSdrahn     case IQ2000_OPERAND_RD_RT :
1246d2201f2fSdrahn       fields->f_rd_rt = value;
1247d2201f2fSdrahn       break;
1248d2201f2fSdrahn     case IQ2000_OPERAND_RS :
1249d2201f2fSdrahn       fields->f_rs = value;
1250d2201f2fSdrahn       break;
1251d2201f2fSdrahn     case IQ2000_OPERAND_RT :
1252d2201f2fSdrahn       fields->f_rt = value;
1253d2201f2fSdrahn       break;
1254d2201f2fSdrahn     case IQ2000_OPERAND_RT_RS :
1255d2201f2fSdrahn       fields->f_rt_rs = value;
1256d2201f2fSdrahn       break;
1257d2201f2fSdrahn     case IQ2000_OPERAND_SHAMT :
1258d2201f2fSdrahn       fields->f_shamt = value;
1259d2201f2fSdrahn       break;
1260d2201f2fSdrahn 
1261d2201f2fSdrahn     default :
1262d2201f2fSdrahn       /* xgettext:c-format */
1263d2201f2fSdrahn       fprintf (stderr, _("Unrecognized field %d while setting int operand.\n"),
1264d2201f2fSdrahn 		       opindex);
1265d2201f2fSdrahn       abort ();
1266d2201f2fSdrahn   }
1267d2201f2fSdrahn }
1268d2201f2fSdrahn 
1269d2201f2fSdrahn void
iq2000_cgen_set_vma_operand(cd,opindex,fields,value)1270d2201f2fSdrahn iq2000_cgen_set_vma_operand (cd, opindex, fields, value)
1271d2201f2fSdrahn      CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
1272d2201f2fSdrahn      int opindex;
1273d2201f2fSdrahn      CGEN_FIELDS * fields;
1274d2201f2fSdrahn      bfd_vma value;
1275d2201f2fSdrahn {
1276d2201f2fSdrahn   switch (opindex)
1277d2201f2fSdrahn     {
1278d2201f2fSdrahn     case IQ2000_OPERAND_BASE :
1279d2201f2fSdrahn       fields->f_rs = value;
1280d2201f2fSdrahn       break;
1281d2201f2fSdrahn     case IQ2000_OPERAND_BASEOFF :
1282d2201f2fSdrahn       fields->f_imm = value;
1283d2201f2fSdrahn       break;
1284d2201f2fSdrahn     case IQ2000_OPERAND_BITNUM :
1285d2201f2fSdrahn       fields->f_rt = value;
1286d2201f2fSdrahn       break;
1287d2201f2fSdrahn     case IQ2000_OPERAND_BYTECOUNT :
1288d2201f2fSdrahn       fields->f_bytecount = value;
1289d2201f2fSdrahn       break;
1290d2201f2fSdrahn     case IQ2000_OPERAND_CAM_Y :
1291d2201f2fSdrahn       fields->f_cam_y = value;
1292d2201f2fSdrahn       break;
1293d2201f2fSdrahn     case IQ2000_OPERAND_CAM_Z :
1294d2201f2fSdrahn       fields->f_cam_z = value;
1295d2201f2fSdrahn       break;
1296d2201f2fSdrahn     case IQ2000_OPERAND_CM_3FUNC :
1297d2201f2fSdrahn       fields->f_cm_3func = value;
1298d2201f2fSdrahn       break;
1299d2201f2fSdrahn     case IQ2000_OPERAND_CM_3Z :
1300d2201f2fSdrahn       fields->f_cm_3z = value;
1301d2201f2fSdrahn       break;
1302d2201f2fSdrahn     case IQ2000_OPERAND_CM_4FUNC :
1303d2201f2fSdrahn       fields->f_cm_4func = value;
1304d2201f2fSdrahn       break;
1305d2201f2fSdrahn     case IQ2000_OPERAND_CM_4Z :
1306d2201f2fSdrahn       fields->f_cm_4z = value;
1307d2201f2fSdrahn       break;
1308d2201f2fSdrahn     case IQ2000_OPERAND_COUNT :
1309d2201f2fSdrahn       fields->f_count = value;
1310d2201f2fSdrahn       break;
1311d2201f2fSdrahn     case IQ2000_OPERAND_EXECODE :
1312d2201f2fSdrahn       fields->f_excode = value;
1313d2201f2fSdrahn       break;
1314*cf2f2c56Smiod     case IQ2000_OPERAND_F_INDEX :
1315*cf2f2c56Smiod       fields->f_index = value;
1316*cf2f2c56Smiod       break;
1317d2201f2fSdrahn     case IQ2000_OPERAND_HI16 :
1318d2201f2fSdrahn       fields->f_imm = value;
1319d2201f2fSdrahn       break;
1320d2201f2fSdrahn     case IQ2000_OPERAND_IMM :
1321d2201f2fSdrahn       fields->f_imm = value;
1322d2201f2fSdrahn       break;
1323d2201f2fSdrahn     case IQ2000_OPERAND_JMPTARG :
1324d2201f2fSdrahn       fields->f_jtarg = value;
1325d2201f2fSdrahn       break;
1326d2201f2fSdrahn     case IQ2000_OPERAND_JMPTARGQ10 :
1327d2201f2fSdrahn       fields->f_jtargq10 = value;
1328d2201f2fSdrahn       break;
1329d2201f2fSdrahn     case IQ2000_OPERAND_LO16 :
1330d2201f2fSdrahn       fields->f_imm = value;
1331d2201f2fSdrahn       break;
1332d2201f2fSdrahn     case IQ2000_OPERAND_MASK :
1333d2201f2fSdrahn       fields->f_mask = value;
1334d2201f2fSdrahn       break;
1335d2201f2fSdrahn     case IQ2000_OPERAND_MASKL :
1336d2201f2fSdrahn       fields->f_maskl = value;
1337d2201f2fSdrahn       break;
1338d2201f2fSdrahn     case IQ2000_OPERAND_MASKQ10 :
1339d2201f2fSdrahn       fields->f_maskq10 = value;
1340d2201f2fSdrahn       break;
1341d2201f2fSdrahn     case IQ2000_OPERAND_MASKR :
1342d2201f2fSdrahn       fields->f_rs = value;
1343d2201f2fSdrahn       break;
1344d2201f2fSdrahn     case IQ2000_OPERAND_MLO16 :
1345d2201f2fSdrahn       fields->f_imm = value;
1346d2201f2fSdrahn       break;
1347d2201f2fSdrahn     case IQ2000_OPERAND_OFFSET :
1348d2201f2fSdrahn       fields->f_offset = value;
1349d2201f2fSdrahn       break;
1350d2201f2fSdrahn     case IQ2000_OPERAND_RD :
1351d2201f2fSdrahn       fields->f_rd = value;
1352d2201f2fSdrahn       break;
1353d2201f2fSdrahn     case IQ2000_OPERAND_RD_RS :
1354d2201f2fSdrahn       fields->f_rd_rs = value;
1355d2201f2fSdrahn       break;
1356d2201f2fSdrahn     case IQ2000_OPERAND_RD_RT :
1357d2201f2fSdrahn       fields->f_rd_rt = value;
1358d2201f2fSdrahn       break;
1359d2201f2fSdrahn     case IQ2000_OPERAND_RS :
1360d2201f2fSdrahn       fields->f_rs = value;
1361d2201f2fSdrahn       break;
1362d2201f2fSdrahn     case IQ2000_OPERAND_RT :
1363d2201f2fSdrahn       fields->f_rt = value;
1364d2201f2fSdrahn       break;
1365d2201f2fSdrahn     case IQ2000_OPERAND_RT_RS :
1366d2201f2fSdrahn       fields->f_rt_rs = value;
1367d2201f2fSdrahn       break;
1368d2201f2fSdrahn     case IQ2000_OPERAND_SHAMT :
1369d2201f2fSdrahn       fields->f_shamt = value;
1370d2201f2fSdrahn       break;
1371d2201f2fSdrahn 
1372d2201f2fSdrahn     default :
1373d2201f2fSdrahn       /* xgettext:c-format */
1374d2201f2fSdrahn       fprintf (stderr, _("Unrecognized field %d while setting vma operand.\n"),
1375d2201f2fSdrahn 		       opindex);
1376d2201f2fSdrahn       abort ();
1377d2201f2fSdrahn   }
1378d2201f2fSdrahn }
1379d2201f2fSdrahn 
1380d2201f2fSdrahn /* Function to call before using the instruction builder tables.  */
1381d2201f2fSdrahn 
1382d2201f2fSdrahn void
iq2000_cgen_init_ibld_table(cd)1383d2201f2fSdrahn iq2000_cgen_init_ibld_table (cd)
1384d2201f2fSdrahn      CGEN_CPU_DESC cd;
1385d2201f2fSdrahn {
1386d2201f2fSdrahn   cd->insert_handlers = & iq2000_cgen_insert_handlers[0];
1387d2201f2fSdrahn   cd->extract_handlers = & iq2000_cgen_extract_handlers[0];
1388d2201f2fSdrahn 
1389d2201f2fSdrahn   cd->insert_operand = iq2000_cgen_insert_operand;
1390d2201f2fSdrahn   cd->extract_operand = iq2000_cgen_extract_operand;
1391d2201f2fSdrahn 
1392d2201f2fSdrahn   cd->get_int_operand = iq2000_cgen_get_int_operand;
1393d2201f2fSdrahn   cd->set_int_operand = iq2000_cgen_set_int_operand;
1394d2201f2fSdrahn   cd->get_vma_operand = iq2000_cgen_get_vma_operand;
1395d2201f2fSdrahn   cd->set_vma_operand = iq2000_cgen_set_vma_operand;
1396d2201f2fSdrahn }
1397