1dc268d07Schristos /* DO NOT EDIT!  -*- buffer-read-only: t -*- vi:set ro:  */
2a1ba9ba4Schristos /* Instruction building/extraction support for ip2k. -*- C -*-
3a1ba9ba4Schristos 
4a1ba9ba4Schristos    THIS FILE IS MACHINE GENERATED WITH CGEN: Cpu tools GENerator.
5a1ba9ba4Schristos    - the resultant file is machine generated, cgen-ibld.in isn't
6a1ba9ba4Schristos 
7*184b2d41Schristos    Copyright (C) 1996-2020 Free Software Foundation, Inc.
8a1ba9ba4Schristos 
9a1ba9ba4Schristos    This file is part of libopcodes.
10a1ba9ba4Schristos 
11a1ba9ba4Schristos    This library is free software; you can redistribute it and/or modify
12a1ba9ba4Schristos    it under the terms of the GNU General Public License as published by
13a1ba9ba4Schristos    the Free Software Foundation; either version 3, or (at your option)
14a1ba9ba4Schristos    any later version.
15a1ba9ba4Schristos 
16a1ba9ba4Schristos    It is distributed in the hope that it will be useful, but WITHOUT
17a1ba9ba4Schristos    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18a1ba9ba4Schristos    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
19a1ba9ba4Schristos    License for more details.
20a1ba9ba4Schristos 
21a1ba9ba4Schristos    You should have received a copy of the GNU General Public License
22a1ba9ba4Schristos    along with this program; if not, write to the Free Software Foundation, Inc.,
23a1ba9ba4Schristos    51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
24a1ba9ba4Schristos 
25a1ba9ba4Schristos /* ??? Eventually more and more of this stuff can go to cpu-independent files.
26a1ba9ba4Schristos    Keep that in mind.  */
27a1ba9ba4Schristos 
28a1ba9ba4Schristos #include "sysdep.h"
29a1ba9ba4Schristos #include <stdio.h>
30a1ba9ba4Schristos #include "ansidecl.h"
31a1ba9ba4Schristos #include "dis-asm.h"
32a1ba9ba4Schristos #include "bfd.h"
33a1ba9ba4Schristos #include "symcat.h"
34a1ba9ba4Schristos #include "ip2k-desc.h"
35a1ba9ba4Schristos #include "ip2k-opc.h"
36a1ba9ba4Schristos #include "cgen/basic-modes.h"
37a1ba9ba4Schristos #include "opintl.h"
38a1ba9ba4Schristos #include "safe-ctype.h"
39a1ba9ba4Schristos 
40a1ba9ba4Schristos #undef  min
41a1ba9ba4Schristos #define min(a,b) ((a) < (b) ? (a) : (b))
42a1ba9ba4Schristos #undef  max
43a1ba9ba4Schristos #define max(a,b) ((a) > (b) ? (a) : (b))
44a1ba9ba4Schristos 
45a1ba9ba4Schristos /* Used by the ifield rtx function.  */
46a1ba9ba4Schristos #define FLD(f) (fields->f)
47a1ba9ba4Schristos 
48a1ba9ba4Schristos static const char * insert_normal
49a1ba9ba4Schristos   (CGEN_CPU_DESC, long, unsigned int, unsigned int, unsigned int,
50a1ba9ba4Schristos    unsigned int, unsigned int, unsigned int, CGEN_INSN_BYTES_PTR);
51a1ba9ba4Schristos static const char * insert_insn_normal
52a1ba9ba4Schristos   (CGEN_CPU_DESC, const CGEN_INSN *,
53a1ba9ba4Schristos    CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma);
54a1ba9ba4Schristos static int extract_normal
55a1ba9ba4Schristos   (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, CGEN_INSN_INT,
56a1ba9ba4Schristos    unsigned int, unsigned int, unsigned int, unsigned int,
57a1ba9ba4Schristos    unsigned int, unsigned int, bfd_vma, long *);
58a1ba9ba4Schristos static int extract_insn_normal
59a1ba9ba4Schristos   (CGEN_CPU_DESC, const CGEN_INSN *, CGEN_EXTRACT_INFO *,
60a1ba9ba4Schristos    CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma);
61a1ba9ba4Schristos #if CGEN_INT_INSN_P
62a1ba9ba4Schristos static void put_insn_int_value
63a1ba9ba4Schristos   (CGEN_CPU_DESC, CGEN_INSN_BYTES_PTR, int, int, CGEN_INSN_INT);
64a1ba9ba4Schristos #endif
65a1ba9ba4Schristos #if ! CGEN_INT_INSN_P
66a1ba9ba4Schristos static CGEN_INLINE void insert_1
67a1ba9ba4Schristos   (CGEN_CPU_DESC, unsigned long, int, int, int, unsigned char *);
68a1ba9ba4Schristos static CGEN_INLINE int fill_cache
69a1ba9ba4Schristos   (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *,  int, int, bfd_vma);
70a1ba9ba4Schristos static CGEN_INLINE long extract_1
71a1ba9ba4Schristos   (CGEN_CPU_DESC, CGEN_EXTRACT_INFO *, int, int, int, unsigned char *, bfd_vma);
72a1ba9ba4Schristos #endif
73a1ba9ba4Schristos 
74a1ba9ba4Schristos /* Operand insertion.  */
75a1ba9ba4Schristos 
76a1ba9ba4Schristos #if ! CGEN_INT_INSN_P
77a1ba9ba4Schristos 
78a1ba9ba4Schristos /* Subroutine of insert_normal.  */
79a1ba9ba4Schristos 
80a1ba9ba4Schristos static CGEN_INLINE void
insert_1(CGEN_CPU_DESC cd,unsigned long value,int start,int length,int word_length,unsigned char * bufp)81a1ba9ba4Schristos insert_1 (CGEN_CPU_DESC cd,
82a1ba9ba4Schristos 	  unsigned long value,
83a1ba9ba4Schristos 	  int start,
84a1ba9ba4Schristos 	  int length,
85a1ba9ba4Schristos 	  int word_length,
86a1ba9ba4Schristos 	  unsigned char *bufp)
87a1ba9ba4Schristos {
88a1ba9ba4Schristos   unsigned long x, mask;
89a1ba9ba4Schristos   int shift;
90a1ba9ba4Schristos 
91*184b2d41Schristos   x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
92a1ba9ba4Schristos 
93a1ba9ba4Schristos   /* Written this way to avoid undefined behaviour.  */
94*184b2d41Schristos   mask = (1UL << (length - 1) << 1) - 1;
95a1ba9ba4Schristos   if (CGEN_INSN_LSB0_P)
96a1ba9ba4Schristos     shift = (start + 1) - length;
97a1ba9ba4Schristos   else
98a1ba9ba4Schristos     shift = (word_length - (start + length));
99a1ba9ba4Schristos   x = (x & ~(mask << shift)) | ((value & mask) << shift);
100a1ba9ba4Schristos 
101*184b2d41Schristos   cgen_put_insn_value (cd, bufp, word_length, (bfd_vma) x, cd->endian);
102a1ba9ba4Schristos }
103a1ba9ba4Schristos 
104a1ba9ba4Schristos #endif /* ! CGEN_INT_INSN_P */
105a1ba9ba4Schristos 
106a1ba9ba4Schristos /* Default insertion routine.
107a1ba9ba4Schristos 
108a1ba9ba4Schristos    ATTRS is a mask of the boolean attributes.
109a1ba9ba4Schristos    WORD_OFFSET is the offset in bits from the start of the insn of the value.
110a1ba9ba4Schristos    WORD_LENGTH is the length of the word in bits in which the value resides.
111a1ba9ba4Schristos    START is the starting bit number in the word, architecture origin.
112a1ba9ba4Schristos    LENGTH is the length of VALUE in bits.
113a1ba9ba4Schristos    TOTAL_LENGTH is the total length of the insn in bits.
114a1ba9ba4Schristos 
115a1ba9ba4Schristos    The result is an error message or NULL if success.  */
116a1ba9ba4Schristos 
117a1ba9ba4Schristos /* ??? This duplicates functionality with bfd's howto table and
118a1ba9ba4Schristos    bfd_install_relocation.  */
119a1ba9ba4Schristos /* ??? This doesn't handle bfd_vma's.  Create another function when
120a1ba9ba4Schristos    necessary.  */
121a1ba9ba4Schristos 
122a1ba9ba4Schristos 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)123a1ba9ba4Schristos insert_normal (CGEN_CPU_DESC cd,
124a1ba9ba4Schristos 	       long value,
125a1ba9ba4Schristos 	       unsigned int attrs,
126a1ba9ba4Schristos 	       unsigned int word_offset,
127a1ba9ba4Schristos 	       unsigned int start,
128a1ba9ba4Schristos 	       unsigned int length,
129a1ba9ba4Schristos 	       unsigned int word_length,
130a1ba9ba4Schristos 	       unsigned int total_length,
131a1ba9ba4Schristos 	       CGEN_INSN_BYTES_PTR buffer)
132a1ba9ba4Schristos {
133a1ba9ba4Schristos   static char errbuf[100];
134*184b2d41Schristos   unsigned long mask;
135a1ba9ba4Schristos 
136a1ba9ba4Schristos   /* If LENGTH is zero, this operand doesn't contribute to the value.  */
137a1ba9ba4Schristos   if (length == 0)
138a1ba9ba4Schristos     return NULL;
139a1ba9ba4Schristos 
140*184b2d41Schristos   /* Written this way to avoid undefined behaviour.  */
141*184b2d41Schristos   mask = (1UL << (length - 1) << 1) - 1;
142*184b2d41Schristos 
143a1ba9ba4Schristos   if (word_length > 8 * sizeof (CGEN_INSN_INT))
144a1ba9ba4Schristos     abort ();
145a1ba9ba4Schristos 
146a1ba9ba4Schristos   /* For architectures with insns smaller than the base-insn-bitsize,
147a1ba9ba4Schristos      word_length may be too big.  */
148a1ba9ba4Schristos   if (cd->min_insn_bitsize < cd->base_insn_bitsize)
149a1ba9ba4Schristos     {
150a1ba9ba4Schristos       if (word_offset == 0
151a1ba9ba4Schristos 	  && word_length > total_length)
152a1ba9ba4Schristos 	word_length = total_length;
153a1ba9ba4Schristos     }
154a1ba9ba4Schristos 
155a1ba9ba4Schristos   /* Ensure VALUE will fit.  */
156a1ba9ba4Schristos   if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGN_OPT))
157a1ba9ba4Schristos     {
158*184b2d41Schristos       long minval = - (1UL << (length - 1));
159a1ba9ba4Schristos       unsigned long maxval = mask;
160a1ba9ba4Schristos 
161a1ba9ba4Schristos       if ((value > 0 && (unsigned long) value > maxval)
162a1ba9ba4Schristos 	  || value < minval)
163a1ba9ba4Schristos 	{
164a1ba9ba4Schristos 	  /* xgettext:c-format */
165a1ba9ba4Schristos 	  sprintf (errbuf,
166a1ba9ba4Schristos 		   _("operand out of range (%ld not between %ld and %lu)"),
167a1ba9ba4Schristos 		   value, minval, maxval);
168a1ba9ba4Schristos 	  return errbuf;
169a1ba9ba4Schristos 	}
170a1ba9ba4Schristos     }
171a1ba9ba4Schristos   else if (! CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED))
172a1ba9ba4Schristos     {
173a1ba9ba4Schristos       unsigned long maxval = mask;
174a1ba9ba4Schristos       unsigned long val = (unsigned long) value;
175a1ba9ba4Schristos 
176a1ba9ba4Schristos       /* For hosts with a word size > 32 check to see if value has been sign
177a1ba9ba4Schristos 	 extended beyond 32 bits.  If so then ignore these higher sign bits
178a1ba9ba4Schristos 	 as the user is attempting to store a 32-bit signed value into an
179a1ba9ba4Schristos 	 unsigned 32-bit field which is allowed.  */
180a1ba9ba4Schristos       if (sizeof (unsigned long) > 4 && ((value >> 32) == -1))
181a1ba9ba4Schristos 	val &= 0xFFFFFFFF;
182a1ba9ba4Schristos 
183a1ba9ba4Schristos       if (val > maxval)
184a1ba9ba4Schristos 	{
185a1ba9ba4Schristos 	  /* xgettext:c-format */
186a1ba9ba4Schristos 	  sprintf (errbuf,
187a1ba9ba4Schristos 		   _("operand out of range (0x%lx not between 0 and 0x%lx)"),
188a1ba9ba4Schristos 		   val, maxval);
189a1ba9ba4Schristos 	  return errbuf;
190a1ba9ba4Schristos 	}
191a1ba9ba4Schristos     }
192a1ba9ba4Schristos   else
193a1ba9ba4Schristos     {
194a1ba9ba4Schristos       if (! cgen_signed_overflow_ok_p (cd))
195a1ba9ba4Schristos 	{
196*184b2d41Schristos 	  long minval = - (1UL << (length - 1));
197*184b2d41Schristos 	  long maxval =   (1UL << (length - 1)) - 1;
198a1ba9ba4Schristos 
199a1ba9ba4Schristos 	  if (value < minval || value > maxval)
200a1ba9ba4Schristos 	    {
201a1ba9ba4Schristos 	      sprintf
202a1ba9ba4Schristos 		/* xgettext:c-format */
203a1ba9ba4Schristos 		(errbuf, _("operand out of range (%ld not between %ld and %ld)"),
204a1ba9ba4Schristos 		 value, minval, maxval);
205a1ba9ba4Schristos 	      return errbuf;
206a1ba9ba4Schristos 	    }
207a1ba9ba4Schristos 	}
208a1ba9ba4Schristos     }
209a1ba9ba4Schristos 
210a1ba9ba4Schristos #if CGEN_INT_INSN_P
211a1ba9ba4Schristos 
212a1ba9ba4Schristos   {
213b2396a7bSchristos     int shift_within_word, shift_to_word, shift;
214a1ba9ba4Schristos 
215b2396a7bSchristos     /* How to shift the value to BIT0 of the word.  */
216b2396a7bSchristos     shift_to_word = total_length - (word_offset + word_length);
217b2396a7bSchristos 
218b2396a7bSchristos     /* How to shift the value to the field within the word.  */
219a1ba9ba4Schristos     if (CGEN_INSN_LSB0_P)
220b2396a7bSchristos       shift_within_word = start + 1 - length;
221a1ba9ba4Schristos     else
222b2396a7bSchristos       shift_within_word = word_length - start - length;
223b2396a7bSchristos 
224b2396a7bSchristos     /* The total SHIFT, then mask in the value.  */
225b2396a7bSchristos     shift = shift_to_word + shift_within_word;
226a1ba9ba4Schristos     *buffer = (*buffer & ~(mask << shift)) | ((value & mask) << shift);
227a1ba9ba4Schristos   }
228a1ba9ba4Schristos 
229a1ba9ba4Schristos #else /* ! CGEN_INT_INSN_P */
230a1ba9ba4Schristos 
231a1ba9ba4Schristos   {
232a1ba9ba4Schristos     unsigned char *bufp = (unsigned char *) buffer + word_offset / 8;
233a1ba9ba4Schristos 
234a1ba9ba4Schristos     insert_1 (cd, value, start, length, word_length, bufp);
235a1ba9ba4Schristos   }
236a1ba9ba4Schristos 
237a1ba9ba4Schristos #endif /* ! CGEN_INT_INSN_P */
238a1ba9ba4Schristos 
239a1ba9ba4Schristos   return NULL;
240a1ba9ba4Schristos }
241a1ba9ba4Schristos 
242a1ba9ba4Schristos /* Default insn builder (insert handler).
243a1ba9ba4Schristos    The instruction is recorded in CGEN_INT_INSN_P byte order (meaning
244a1ba9ba4Schristos    that if CGEN_INSN_BYTES_PTR is an int * and thus, the value is
245a1ba9ba4Schristos    recorded in host byte order, otherwise BUFFER is an array of bytes
246a1ba9ba4Schristos    and the value is recorded in target byte order).
247a1ba9ba4Schristos    The result is an error message or NULL if success.  */
248a1ba9ba4Schristos 
249a1ba9ba4Schristos 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)250a1ba9ba4Schristos insert_insn_normal (CGEN_CPU_DESC cd,
251a1ba9ba4Schristos 		    const CGEN_INSN * insn,
252a1ba9ba4Schristos 		    CGEN_FIELDS * fields,
253a1ba9ba4Schristos 		    CGEN_INSN_BYTES_PTR buffer,
254a1ba9ba4Schristos 		    bfd_vma pc)
255a1ba9ba4Schristos {
256a1ba9ba4Schristos   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
257a1ba9ba4Schristos   unsigned long value;
258a1ba9ba4Schristos   const CGEN_SYNTAX_CHAR_TYPE * syn;
259a1ba9ba4Schristos 
260a1ba9ba4Schristos   CGEN_INIT_INSERT (cd);
261a1ba9ba4Schristos   value = CGEN_INSN_BASE_VALUE (insn);
262a1ba9ba4Schristos 
263a1ba9ba4Schristos   /* If we're recording insns as numbers (rather than a string of bytes),
264a1ba9ba4Schristos      target byte order handling is deferred until later.  */
265a1ba9ba4Schristos 
266a1ba9ba4Schristos #if CGEN_INT_INSN_P
267a1ba9ba4Schristos 
268a1ba9ba4Schristos   put_insn_int_value (cd, buffer, cd->base_insn_bitsize,
269a1ba9ba4Schristos 		      CGEN_FIELDS_BITSIZE (fields), value);
270a1ba9ba4Schristos 
271a1ba9ba4Schristos #else
272a1ba9ba4Schristos 
273a1ba9ba4Schristos   cgen_put_insn_value (cd, buffer, min ((unsigned) cd->base_insn_bitsize,
274a1ba9ba4Schristos                                         (unsigned) CGEN_FIELDS_BITSIZE (fields)),
275*184b2d41Schristos 		       value, cd->insn_endian);
276a1ba9ba4Schristos 
277a1ba9ba4Schristos #endif /* ! CGEN_INT_INSN_P */
278a1ba9ba4Schristos 
279a1ba9ba4Schristos   /* ??? It would be better to scan the format's fields.
280a1ba9ba4Schristos      Still need to be able to insert a value based on the operand though;
281a1ba9ba4Schristos      e.g. storing a branch displacement that got resolved later.
282a1ba9ba4Schristos      Needs more thought first.  */
283a1ba9ba4Schristos 
284a1ba9ba4Schristos   for (syn = CGEN_SYNTAX_STRING (syntax); * syn; ++ syn)
285a1ba9ba4Schristos     {
286a1ba9ba4Schristos       const char *errmsg;
287a1ba9ba4Schristos 
288a1ba9ba4Schristos       if (CGEN_SYNTAX_CHAR_P (* syn))
289a1ba9ba4Schristos 	continue;
290a1ba9ba4Schristos 
291a1ba9ba4Schristos       errmsg = (* cd->insert_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
292a1ba9ba4Schristos 				       fields, buffer, pc);
293a1ba9ba4Schristos       if (errmsg)
294a1ba9ba4Schristos 	return errmsg;
295a1ba9ba4Schristos     }
296a1ba9ba4Schristos 
297a1ba9ba4Schristos   return NULL;
298a1ba9ba4Schristos }
299a1ba9ba4Schristos 
300a1ba9ba4Schristos #if CGEN_INT_INSN_P
301a1ba9ba4Schristos /* Cover function to store an insn value into an integral insn.  Must go here
302a1ba9ba4Schristos    because it needs <prefix>-desc.h for CGEN_INT_INSN_P.  */
303a1ba9ba4Schristos 
304a1ba9ba4Schristos 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)305a1ba9ba4Schristos put_insn_int_value (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
306a1ba9ba4Schristos 		    CGEN_INSN_BYTES_PTR buf,
307a1ba9ba4Schristos 		    int length,
308a1ba9ba4Schristos 		    int insn_length,
309a1ba9ba4Schristos 		    CGEN_INSN_INT value)
310a1ba9ba4Schristos {
311a1ba9ba4Schristos   /* For architectures with insns smaller than the base-insn-bitsize,
312a1ba9ba4Schristos      length may be too big.  */
313a1ba9ba4Schristos   if (length > insn_length)
314a1ba9ba4Schristos     *buf = value;
315a1ba9ba4Schristos   else
316a1ba9ba4Schristos     {
317a1ba9ba4Schristos       int shift = insn_length - length;
318a1ba9ba4Schristos       /* Written this way to avoid undefined behaviour.  */
319*184b2d41Schristos       CGEN_INSN_INT mask = length == 0 ? 0 : (1UL << (length - 1) << 1) - 1;
320a1ba9ba4Schristos 
321a1ba9ba4Schristos       *buf = (*buf & ~(mask << shift)) | ((value & mask) << shift);
322a1ba9ba4Schristos     }
323a1ba9ba4Schristos }
324a1ba9ba4Schristos #endif
325a1ba9ba4Schristos 
326a1ba9ba4Schristos /* Operand extraction.  */
327a1ba9ba4Schristos 
328a1ba9ba4Schristos #if ! CGEN_INT_INSN_P
329a1ba9ba4Schristos 
330a1ba9ba4Schristos /* Subroutine of extract_normal.
331a1ba9ba4Schristos    Ensure sufficient bytes are cached in EX_INFO.
332a1ba9ba4Schristos    OFFSET is the offset in bytes from the start of the insn of the value.
333a1ba9ba4Schristos    BYTES is the length of the needed value.
334a1ba9ba4Schristos    Returns 1 for success, 0 for failure.  */
335a1ba9ba4Schristos 
336a1ba9ba4Schristos static CGEN_INLINE int
fill_cache(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,CGEN_EXTRACT_INFO * ex_info,int offset,int bytes,bfd_vma pc)337a1ba9ba4Schristos fill_cache (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
338a1ba9ba4Schristos 	    CGEN_EXTRACT_INFO *ex_info,
339a1ba9ba4Schristos 	    int offset,
340a1ba9ba4Schristos 	    int bytes,
341a1ba9ba4Schristos 	    bfd_vma pc)
342a1ba9ba4Schristos {
343a1ba9ba4Schristos   /* It's doubtful that the middle part has already been fetched so
344a1ba9ba4Schristos      we don't optimize that case.  kiss.  */
345a1ba9ba4Schristos   unsigned int mask;
346a1ba9ba4Schristos   disassemble_info *info = (disassemble_info *) ex_info->dis_info;
347a1ba9ba4Schristos 
348a1ba9ba4Schristos   /* First do a quick check.  */
349a1ba9ba4Schristos   mask = (1 << bytes) - 1;
350a1ba9ba4Schristos   if (((ex_info->valid >> offset) & mask) == mask)
351a1ba9ba4Schristos     return 1;
352a1ba9ba4Schristos 
353a1ba9ba4Schristos   /* Search for the first byte we need to read.  */
354a1ba9ba4Schristos   for (mask = 1 << offset; bytes > 0; --bytes, ++offset, mask <<= 1)
355a1ba9ba4Schristos     if (! (mask & ex_info->valid))
356a1ba9ba4Schristos       break;
357a1ba9ba4Schristos 
358a1ba9ba4Schristos   if (bytes)
359a1ba9ba4Schristos     {
360a1ba9ba4Schristos       int status;
361a1ba9ba4Schristos 
362a1ba9ba4Schristos       pc += offset;
363a1ba9ba4Schristos       status = (*info->read_memory_func)
364a1ba9ba4Schristos 	(pc, ex_info->insn_bytes + offset, bytes, info);
365a1ba9ba4Schristos 
366a1ba9ba4Schristos       if (status != 0)
367a1ba9ba4Schristos 	{
368a1ba9ba4Schristos 	  (*info->memory_error_func) (status, pc, info);
369a1ba9ba4Schristos 	  return 0;
370a1ba9ba4Schristos 	}
371a1ba9ba4Schristos 
372a1ba9ba4Schristos       ex_info->valid |= ((1 << bytes) - 1) << offset;
373a1ba9ba4Schristos     }
374a1ba9ba4Schristos 
375a1ba9ba4Schristos   return 1;
376a1ba9ba4Schristos }
377a1ba9ba4Schristos 
378a1ba9ba4Schristos /* Subroutine of extract_normal.  */
379a1ba9ba4Schristos 
380a1ba9ba4Schristos 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)381a1ba9ba4Schristos extract_1 (CGEN_CPU_DESC cd,
382a1ba9ba4Schristos 	   CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
383a1ba9ba4Schristos 	   int start,
384a1ba9ba4Schristos 	   int length,
385a1ba9ba4Schristos 	   int word_length,
386a1ba9ba4Schristos 	   unsigned char *bufp,
387a1ba9ba4Schristos 	   bfd_vma pc ATTRIBUTE_UNUSED)
388a1ba9ba4Schristos {
389a1ba9ba4Schristos   unsigned long x;
390a1ba9ba4Schristos   int shift;
391a1ba9ba4Schristos 
392*184b2d41Schristos   x = cgen_get_insn_value (cd, bufp, word_length, cd->endian);
393a1ba9ba4Schristos 
394a1ba9ba4Schristos   if (CGEN_INSN_LSB0_P)
395a1ba9ba4Schristos     shift = (start + 1) - length;
396a1ba9ba4Schristos   else
397a1ba9ba4Schristos     shift = (word_length - (start + length));
398a1ba9ba4Schristos   return x >> shift;
399a1ba9ba4Schristos }
400a1ba9ba4Schristos 
401a1ba9ba4Schristos #endif /* ! CGEN_INT_INSN_P */
402a1ba9ba4Schristos 
403a1ba9ba4Schristos /* Default extraction routine.
404a1ba9ba4Schristos 
405a1ba9ba4Schristos    INSN_VALUE is the first base_insn_bitsize bits of the insn in host order,
406a1ba9ba4Schristos    or sometimes less for cases like the m32r where the base insn size is 32
407a1ba9ba4Schristos    but some insns are 16 bits.
408a1ba9ba4Schristos    ATTRS is a mask of the boolean attributes.  We only need `SIGNED',
409a1ba9ba4Schristos    but for generality we take a bitmask of all of them.
410a1ba9ba4Schristos    WORD_OFFSET is the offset in bits from the start of the insn of the value.
411a1ba9ba4Schristos    WORD_LENGTH is the length of the word in bits in which the value resides.
412a1ba9ba4Schristos    START is the starting bit number in the word, architecture origin.
413a1ba9ba4Schristos    LENGTH is the length of VALUE in bits.
414a1ba9ba4Schristos    TOTAL_LENGTH is the total length of the insn in bits.
415a1ba9ba4Schristos 
416a1ba9ba4Schristos    Returns 1 for success, 0 for failure.  */
417a1ba9ba4Schristos 
418a1ba9ba4Schristos /* ??? The return code isn't properly used.  wip.  */
419a1ba9ba4Schristos 
420a1ba9ba4Schristos /* ??? This doesn't handle bfd_vma's.  Create another function when
421a1ba9ba4Schristos    necessary.  */
422a1ba9ba4Schristos 
423a1ba9ba4Schristos 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)424a1ba9ba4Schristos extract_normal (CGEN_CPU_DESC cd,
425a1ba9ba4Schristos #if ! CGEN_INT_INSN_P
426a1ba9ba4Schristos 		CGEN_EXTRACT_INFO *ex_info,
427a1ba9ba4Schristos #else
428a1ba9ba4Schristos 		CGEN_EXTRACT_INFO *ex_info ATTRIBUTE_UNUSED,
429a1ba9ba4Schristos #endif
430a1ba9ba4Schristos 		CGEN_INSN_INT insn_value,
431a1ba9ba4Schristos 		unsigned int attrs,
432a1ba9ba4Schristos 		unsigned int word_offset,
433a1ba9ba4Schristos 		unsigned int start,
434a1ba9ba4Schristos 		unsigned int length,
435a1ba9ba4Schristos 		unsigned int word_length,
436a1ba9ba4Schristos 		unsigned int total_length,
437a1ba9ba4Schristos #if ! CGEN_INT_INSN_P
438a1ba9ba4Schristos 		bfd_vma pc,
439a1ba9ba4Schristos #else
440a1ba9ba4Schristos 		bfd_vma pc ATTRIBUTE_UNUSED,
441a1ba9ba4Schristos #endif
442a1ba9ba4Schristos 		long *valuep)
443a1ba9ba4Schristos {
444a1ba9ba4Schristos   long value, mask;
445a1ba9ba4Schristos 
446a1ba9ba4Schristos   /* If LENGTH is zero, this operand doesn't contribute to the value
447a1ba9ba4Schristos      so give it a standard value of zero.  */
448a1ba9ba4Schristos   if (length == 0)
449a1ba9ba4Schristos     {
450a1ba9ba4Schristos       *valuep = 0;
451a1ba9ba4Schristos       return 1;
452a1ba9ba4Schristos     }
453a1ba9ba4Schristos 
454a1ba9ba4Schristos   if (word_length > 8 * sizeof (CGEN_INSN_INT))
455a1ba9ba4Schristos     abort ();
456a1ba9ba4Schristos 
457a1ba9ba4Schristos   /* For architectures with insns smaller than the insn-base-bitsize,
458a1ba9ba4Schristos      word_length may be too big.  */
459a1ba9ba4Schristos   if (cd->min_insn_bitsize < cd->base_insn_bitsize)
460a1ba9ba4Schristos     {
461a1ba9ba4Schristos       if (word_offset + word_length > total_length)
462a1ba9ba4Schristos 	word_length = total_length - word_offset;
463a1ba9ba4Schristos     }
464a1ba9ba4Schristos 
465a1ba9ba4Schristos   /* Does the value reside in INSN_VALUE, and at the right alignment?  */
466a1ba9ba4Schristos 
467a1ba9ba4Schristos   if (CGEN_INT_INSN_P || (word_offset == 0 && word_length == total_length))
468a1ba9ba4Schristos     {
469a1ba9ba4Schristos       if (CGEN_INSN_LSB0_P)
470a1ba9ba4Schristos 	value = insn_value >> ((word_offset + start + 1) - length);
471a1ba9ba4Schristos       else
472a1ba9ba4Schristos 	value = insn_value >> (total_length - ( word_offset + start + length));
473a1ba9ba4Schristos     }
474a1ba9ba4Schristos 
475a1ba9ba4Schristos #if ! CGEN_INT_INSN_P
476a1ba9ba4Schristos 
477a1ba9ba4Schristos   else
478a1ba9ba4Schristos     {
479a1ba9ba4Schristos       unsigned char *bufp = ex_info->insn_bytes + word_offset / 8;
480a1ba9ba4Schristos 
481a1ba9ba4Schristos       if (word_length > 8 * sizeof (CGEN_INSN_INT))
482a1ba9ba4Schristos 	abort ();
483a1ba9ba4Schristos 
484a1ba9ba4Schristos       if (fill_cache (cd, ex_info, word_offset / 8, word_length / 8, pc) == 0)
485*184b2d41Schristos 	{
486*184b2d41Schristos 	  *valuep = 0;
487a1ba9ba4Schristos 	  return 0;
488*184b2d41Schristos 	}
489a1ba9ba4Schristos 
490a1ba9ba4Schristos       value = extract_1 (cd, ex_info, start, length, word_length, bufp, pc);
491a1ba9ba4Schristos     }
492a1ba9ba4Schristos 
493a1ba9ba4Schristos #endif /* ! CGEN_INT_INSN_P */
494a1ba9ba4Schristos 
495a1ba9ba4Schristos   /* Written this way to avoid undefined behaviour.  */
496*184b2d41Schristos   mask = (1UL << (length - 1) << 1) - 1;
497a1ba9ba4Schristos 
498a1ba9ba4Schristos   value &= mask;
499a1ba9ba4Schristos   /* sign extend? */
500a1ba9ba4Schristos   if (CGEN_BOOL_ATTR (attrs, CGEN_IFLD_SIGNED)
501*184b2d41Schristos       && (value & (1UL << (length - 1))))
502a1ba9ba4Schristos     value |= ~mask;
503a1ba9ba4Schristos 
504a1ba9ba4Schristos   *valuep = value;
505a1ba9ba4Schristos 
506a1ba9ba4Schristos   return 1;
507a1ba9ba4Schristos }
508a1ba9ba4Schristos 
509a1ba9ba4Schristos /* Default insn extractor.
510a1ba9ba4Schristos 
511a1ba9ba4Schristos    INSN_VALUE is the first base_insn_bitsize bits, translated to host order.
512a1ba9ba4Schristos    The extracted fields are stored in FIELDS.
513a1ba9ba4Schristos    EX_INFO is used to handle reading variable length insns.
514a1ba9ba4Schristos    Return the length of the insn in bits, or 0 if no match,
515a1ba9ba4Schristos    or -1 if an error occurs fetching data (memory_error_func will have
516a1ba9ba4Schristos    been called).  */
517a1ba9ba4Schristos 
518a1ba9ba4Schristos 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)519a1ba9ba4Schristos extract_insn_normal (CGEN_CPU_DESC cd,
520a1ba9ba4Schristos 		     const CGEN_INSN *insn,
521a1ba9ba4Schristos 		     CGEN_EXTRACT_INFO *ex_info,
522a1ba9ba4Schristos 		     CGEN_INSN_INT insn_value,
523a1ba9ba4Schristos 		     CGEN_FIELDS *fields,
524a1ba9ba4Schristos 		     bfd_vma pc)
525a1ba9ba4Schristos {
526a1ba9ba4Schristos   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
527a1ba9ba4Schristos   const CGEN_SYNTAX_CHAR_TYPE *syn;
528a1ba9ba4Schristos 
529a1ba9ba4Schristos   CGEN_FIELDS_BITSIZE (fields) = CGEN_INSN_BITSIZE (insn);
530a1ba9ba4Schristos 
531a1ba9ba4Schristos   CGEN_INIT_EXTRACT (cd);
532a1ba9ba4Schristos 
533a1ba9ba4Schristos   for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
534a1ba9ba4Schristos     {
535a1ba9ba4Schristos       int length;
536a1ba9ba4Schristos 
537a1ba9ba4Schristos       if (CGEN_SYNTAX_CHAR_P (*syn))
538a1ba9ba4Schristos 	continue;
539a1ba9ba4Schristos 
540a1ba9ba4Schristos       length = (* cd->extract_operand) (cd, CGEN_SYNTAX_FIELD (*syn),
541a1ba9ba4Schristos 					ex_info, insn_value, fields, pc);
542a1ba9ba4Schristos       if (length <= 0)
543a1ba9ba4Schristos 	return length;
544a1ba9ba4Schristos     }
545a1ba9ba4Schristos 
546a1ba9ba4Schristos   /* We recognized and successfully extracted this insn.  */
547a1ba9ba4Schristos   return CGEN_INSN_BITSIZE (insn);
548a1ba9ba4Schristos }
549a1ba9ba4Schristos 
550a1ba9ba4Schristos /* Machine generated code added here.  */
551a1ba9ba4Schristos 
552a1ba9ba4Schristos const char * ip2k_cgen_insert_operand
553a1ba9ba4Schristos   (CGEN_CPU_DESC, int, CGEN_FIELDS *, CGEN_INSN_BYTES_PTR, bfd_vma);
554a1ba9ba4Schristos 
555a1ba9ba4Schristos /* Main entry point for operand insertion.
556a1ba9ba4Schristos 
557a1ba9ba4Schristos    This function is basically just a big switch statement.  Earlier versions
558a1ba9ba4Schristos    used tables to look up the function to use, but
559a1ba9ba4Schristos    - if the table contains both assembler and disassembler functions then
560a1ba9ba4Schristos      the disassembler contains much of the assembler and vice-versa,
561a1ba9ba4Schristos    - there's a lot of inlining possibilities as things grow,
562a1ba9ba4Schristos    - using a switch statement avoids the function call overhead.
563a1ba9ba4Schristos 
564a1ba9ba4Schristos    This function could be moved into `parse_insn_normal', but keeping it
565a1ba9ba4Schristos    separate makes clear the interface between `parse_insn_normal' and each of
566a1ba9ba4Schristos    the handlers.  It's also needed by GAS to insert operands that couldn't be
567a1ba9ba4Schristos    resolved during parsing.  */
568a1ba9ba4Schristos 
569a1ba9ba4Schristos const char *
ip2k_cgen_insert_operand(CGEN_CPU_DESC cd,int opindex,CGEN_FIELDS * fields,CGEN_INSN_BYTES_PTR buffer,bfd_vma pc ATTRIBUTE_UNUSED)570a1ba9ba4Schristos ip2k_cgen_insert_operand (CGEN_CPU_DESC cd,
571a1ba9ba4Schristos 			     int opindex,
572a1ba9ba4Schristos 			     CGEN_FIELDS * fields,
573a1ba9ba4Schristos 			     CGEN_INSN_BYTES_PTR buffer,
574a1ba9ba4Schristos 			     bfd_vma pc ATTRIBUTE_UNUSED)
575a1ba9ba4Schristos {
576a1ba9ba4Schristos   const char * errmsg = NULL;
577a1ba9ba4Schristos   unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
578a1ba9ba4Schristos 
579a1ba9ba4Schristos   switch (opindex)
580a1ba9ba4Schristos     {
581a1ba9ba4Schristos     case IP2K_OPERAND_ADDR16CJP :
582a1ba9ba4Schristos       errmsg = insert_normal (cd, fields->f_addr16cjp, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 12, 13, 16, total_length, buffer);
583a1ba9ba4Schristos       break;
584a1ba9ba4Schristos     case IP2K_OPERAND_ADDR16H :
585a1ba9ba4Schristos       errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 7, 8, 16, total_length, buffer);
586a1ba9ba4Schristos       break;
587a1ba9ba4Schristos     case IP2K_OPERAND_ADDR16L :
588a1ba9ba4Schristos       errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 7, 8, 16, total_length, buffer);
589a1ba9ba4Schristos       break;
590a1ba9ba4Schristos     case IP2K_OPERAND_ADDR16P :
591a1ba9ba4Schristos       errmsg = insert_normal (cd, fields->f_page3, 0, 0, 2, 3, 16, total_length, buffer);
592a1ba9ba4Schristos       break;
593a1ba9ba4Schristos     case IP2K_OPERAND_BITNO :
594a1ba9ba4Schristos       errmsg = insert_normal (cd, fields->f_bitno, 0, 0, 11, 3, 16, total_length, buffer);
595a1ba9ba4Schristos       break;
596a1ba9ba4Schristos     case IP2K_OPERAND_CBIT :
597a1ba9ba4Schristos       break;
598a1ba9ba4Schristos     case IP2K_OPERAND_DCBIT :
599a1ba9ba4Schristos       break;
600a1ba9ba4Schristos     case IP2K_OPERAND_FR :
601a1ba9ba4Schristos       errmsg = insert_normal (cd, fields->f_reg, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 9, 16, total_length, buffer);
602a1ba9ba4Schristos       break;
603a1ba9ba4Schristos     case IP2K_OPERAND_LIT8 :
604a1ba9ba4Schristos       errmsg = insert_normal (cd, fields->f_imm8, 0, 0, 7, 8, 16, total_length, buffer);
605a1ba9ba4Schristos       break;
606a1ba9ba4Schristos     case IP2K_OPERAND_PABITS :
607a1ba9ba4Schristos       break;
608a1ba9ba4Schristos     case IP2K_OPERAND_RETI3 :
609a1ba9ba4Schristos       errmsg = insert_normal (cd, fields->f_reti3, 0, 0, 2, 3, 16, total_length, buffer);
610a1ba9ba4Schristos       break;
611a1ba9ba4Schristos     case IP2K_OPERAND_ZBIT :
612a1ba9ba4Schristos       break;
613a1ba9ba4Schristos 
614a1ba9ba4Schristos     default :
615a1ba9ba4Schristos       /* xgettext:c-format */
616dc268d07Schristos       opcodes_error_handler
617dc268d07Schristos 	(_("internal error: unrecognized field %d while building insn"),
618a1ba9ba4Schristos 	 opindex);
619a1ba9ba4Schristos       abort ();
620a1ba9ba4Schristos   }
621a1ba9ba4Schristos 
622a1ba9ba4Schristos   return errmsg;
623a1ba9ba4Schristos }
624a1ba9ba4Schristos 
625a1ba9ba4Schristos int ip2k_cgen_extract_operand
626a1ba9ba4Schristos   (CGEN_CPU_DESC, int, CGEN_EXTRACT_INFO *, CGEN_INSN_INT, CGEN_FIELDS *, bfd_vma);
627a1ba9ba4Schristos 
628a1ba9ba4Schristos /* Main entry point for operand extraction.
629a1ba9ba4Schristos    The result is <= 0 for error, >0 for success.
630a1ba9ba4Schristos    ??? Actual values aren't well defined right now.
631a1ba9ba4Schristos 
632a1ba9ba4Schristos    This function is basically just a big switch statement.  Earlier versions
633a1ba9ba4Schristos    used tables to look up the function to use, but
634a1ba9ba4Schristos    - if the table contains both assembler and disassembler functions then
635a1ba9ba4Schristos      the disassembler contains much of the assembler and vice-versa,
636a1ba9ba4Schristos    - there's a lot of inlining possibilities as things grow,
637a1ba9ba4Schristos    - using a switch statement avoids the function call overhead.
638a1ba9ba4Schristos 
639a1ba9ba4Schristos    This function could be moved into `print_insn_normal', but keeping it
640a1ba9ba4Schristos    separate makes clear the interface between `print_insn_normal' and each of
641a1ba9ba4Schristos    the handlers.  */
642a1ba9ba4Schristos 
643a1ba9ba4Schristos int
ip2k_cgen_extract_operand(CGEN_CPU_DESC cd,int opindex,CGEN_EXTRACT_INFO * ex_info,CGEN_INSN_INT insn_value,CGEN_FIELDS * fields,bfd_vma pc)644a1ba9ba4Schristos ip2k_cgen_extract_operand (CGEN_CPU_DESC cd,
645a1ba9ba4Schristos 			     int opindex,
646a1ba9ba4Schristos 			     CGEN_EXTRACT_INFO *ex_info,
647a1ba9ba4Schristos 			     CGEN_INSN_INT insn_value,
648a1ba9ba4Schristos 			     CGEN_FIELDS * fields,
649a1ba9ba4Schristos 			     bfd_vma pc)
650a1ba9ba4Schristos {
651a1ba9ba4Schristos   /* Assume success (for those operands that are nops).  */
652a1ba9ba4Schristos   int length = 1;
653a1ba9ba4Schristos   unsigned int total_length = CGEN_FIELDS_BITSIZE (fields);
654a1ba9ba4Schristos 
655a1ba9ba4Schristos   switch (opindex)
656a1ba9ba4Schristos     {
657a1ba9ba4Schristos     case IP2K_OPERAND_ADDR16CJP :
658a1ba9ba4Schristos       length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 12, 13, 16, total_length, pc, & fields->f_addr16cjp);
659a1ba9ba4Schristos       break;
660a1ba9ba4Schristos     case IP2K_OPERAND_ADDR16H :
661a1ba9ba4Schristos       length = extract_normal (cd, ex_info, insn_value, 0, 0, 7, 8, 16, total_length, pc, & fields->f_imm8);
662a1ba9ba4Schristos       break;
663a1ba9ba4Schristos     case IP2K_OPERAND_ADDR16L :
664a1ba9ba4Schristos       length = extract_normal (cd, ex_info, insn_value, 0, 0, 7, 8, 16, total_length, pc, & fields->f_imm8);
665a1ba9ba4Schristos       break;
666a1ba9ba4Schristos     case IP2K_OPERAND_ADDR16P :
667a1ba9ba4Schristos       length = extract_normal (cd, ex_info, insn_value, 0, 0, 2, 3, 16, total_length, pc, & fields->f_page3);
668a1ba9ba4Schristos       break;
669a1ba9ba4Schristos     case IP2K_OPERAND_BITNO :
670a1ba9ba4Schristos       length = extract_normal (cd, ex_info, insn_value, 0, 0, 11, 3, 16, total_length, pc, & fields->f_bitno);
671a1ba9ba4Schristos       break;
672a1ba9ba4Schristos     case IP2K_OPERAND_CBIT :
673a1ba9ba4Schristos       break;
674a1ba9ba4Schristos     case IP2K_OPERAND_DCBIT :
675a1ba9ba4Schristos       break;
676a1ba9ba4Schristos     case IP2K_OPERAND_FR :
677a1ba9ba4Schristos       length = extract_normal (cd, ex_info, insn_value, 0|(1<<CGEN_IFLD_ABS_ADDR), 0, 8, 9, 16, total_length, pc, & fields->f_reg);
678a1ba9ba4Schristos       break;
679a1ba9ba4Schristos     case IP2K_OPERAND_LIT8 :
680a1ba9ba4Schristos       length = extract_normal (cd, ex_info, insn_value, 0, 0, 7, 8, 16, total_length, pc, & fields->f_imm8);
681a1ba9ba4Schristos       break;
682a1ba9ba4Schristos     case IP2K_OPERAND_PABITS :
683a1ba9ba4Schristos       break;
684a1ba9ba4Schristos     case IP2K_OPERAND_RETI3 :
685a1ba9ba4Schristos       length = extract_normal (cd, ex_info, insn_value, 0, 0, 2, 3, 16, total_length, pc, & fields->f_reti3);
686a1ba9ba4Schristos       break;
687a1ba9ba4Schristos     case IP2K_OPERAND_ZBIT :
688a1ba9ba4Schristos       break;
689a1ba9ba4Schristos 
690a1ba9ba4Schristos     default :
691a1ba9ba4Schristos       /* xgettext:c-format */
692dc268d07Schristos       opcodes_error_handler
693dc268d07Schristos 	(_("internal error: unrecognized field %d while decoding insn"),
694a1ba9ba4Schristos 	 opindex);
695a1ba9ba4Schristos       abort ();
696a1ba9ba4Schristos     }
697a1ba9ba4Schristos 
698a1ba9ba4Schristos   return length;
699a1ba9ba4Schristos }
700a1ba9ba4Schristos 
701a1ba9ba4Schristos cgen_insert_fn * const ip2k_cgen_insert_handlers[] =
702a1ba9ba4Schristos {
703a1ba9ba4Schristos   insert_insn_normal,
704a1ba9ba4Schristos };
705a1ba9ba4Schristos 
706a1ba9ba4Schristos cgen_extract_fn * const ip2k_cgen_extract_handlers[] =
707a1ba9ba4Schristos {
708a1ba9ba4Schristos   extract_insn_normal,
709a1ba9ba4Schristos };
710a1ba9ba4Schristos 
711a1ba9ba4Schristos int ip2k_cgen_get_int_operand     (CGEN_CPU_DESC, int, const CGEN_FIELDS *);
712a1ba9ba4Schristos bfd_vma ip2k_cgen_get_vma_operand (CGEN_CPU_DESC, int, const CGEN_FIELDS *);
713a1ba9ba4Schristos 
714a1ba9ba4Schristos /* Getting values from cgen_fields is handled by a collection of functions.
715a1ba9ba4Schristos    They are distinguished by the type of the VALUE argument they return.
716a1ba9ba4Schristos    TODO: floating point, inlining support, remove cases where result type
717a1ba9ba4Schristos    not appropriate.  */
718a1ba9ba4Schristos 
719a1ba9ba4Schristos int
ip2k_cgen_get_int_operand(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,int opindex,const CGEN_FIELDS * fields)720a1ba9ba4Schristos ip2k_cgen_get_int_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
721a1ba9ba4Schristos 			     int opindex,
722a1ba9ba4Schristos 			     const CGEN_FIELDS * fields)
723a1ba9ba4Schristos {
724a1ba9ba4Schristos   int value;
725a1ba9ba4Schristos 
726a1ba9ba4Schristos   switch (opindex)
727a1ba9ba4Schristos     {
728a1ba9ba4Schristos     case IP2K_OPERAND_ADDR16CJP :
729a1ba9ba4Schristos       value = fields->f_addr16cjp;
730a1ba9ba4Schristos       break;
731a1ba9ba4Schristos     case IP2K_OPERAND_ADDR16H :
732a1ba9ba4Schristos       value = fields->f_imm8;
733a1ba9ba4Schristos       break;
734a1ba9ba4Schristos     case IP2K_OPERAND_ADDR16L :
735a1ba9ba4Schristos       value = fields->f_imm8;
736a1ba9ba4Schristos       break;
737a1ba9ba4Schristos     case IP2K_OPERAND_ADDR16P :
738a1ba9ba4Schristos       value = fields->f_page3;
739a1ba9ba4Schristos       break;
740a1ba9ba4Schristos     case IP2K_OPERAND_BITNO :
741a1ba9ba4Schristos       value = fields->f_bitno;
742a1ba9ba4Schristos       break;
743a1ba9ba4Schristos     case IP2K_OPERAND_CBIT :
744a1ba9ba4Schristos       value = 0;
745a1ba9ba4Schristos       break;
746a1ba9ba4Schristos     case IP2K_OPERAND_DCBIT :
747a1ba9ba4Schristos       value = 0;
748a1ba9ba4Schristos       break;
749a1ba9ba4Schristos     case IP2K_OPERAND_FR :
750a1ba9ba4Schristos       value = fields->f_reg;
751a1ba9ba4Schristos       break;
752a1ba9ba4Schristos     case IP2K_OPERAND_LIT8 :
753a1ba9ba4Schristos       value = fields->f_imm8;
754a1ba9ba4Schristos       break;
755a1ba9ba4Schristos     case IP2K_OPERAND_PABITS :
756a1ba9ba4Schristos       value = 0;
757a1ba9ba4Schristos       break;
758a1ba9ba4Schristos     case IP2K_OPERAND_RETI3 :
759a1ba9ba4Schristos       value = fields->f_reti3;
760a1ba9ba4Schristos       break;
761a1ba9ba4Schristos     case IP2K_OPERAND_ZBIT :
762a1ba9ba4Schristos       value = 0;
763a1ba9ba4Schristos       break;
764a1ba9ba4Schristos 
765a1ba9ba4Schristos     default :
766a1ba9ba4Schristos       /* xgettext:c-format */
767dc268d07Schristos       opcodes_error_handler
768dc268d07Schristos 	(_("internal error: unrecognized field %d while getting int operand"),
769a1ba9ba4Schristos 	 opindex);
770a1ba9ba4Schristos       abort ();
771a1ba9ba4Schristos   }
772a1ba9ba4Schristos 
773a1ba9ba4Schristos   return value;
774a1ba9ba4Schristos }
775a1ba9ba4Schristos 
776a1ba9ba4Schristos bfd_vma
ip2k_cgen_get_vma_operand(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,int opindex,const CGEN_FIELDS * fields)777a1ba9ba4Schristos ip2k_cgen_get_vma_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
778a1ba9ba4Schristos 			     int opindex,
779a1ba9ba4Schristos 			     const CGEN_FIELDS * fields)
780a1ba9ba4Schristos {
781a1ba9ba4Schristos   bfd_vma value;
782a1ba9ba4Schristos 
783a1ba9ba4Schristos   switch (opindex)
784a1ba9ba4Schristos     {
785a1ba9ba4Schristos     case IP2K_OPERAND_ADDR16CJP :
786a1ba9ba4Schristos       value = fields->f_addr16cjp;
787a1ba9ba4Schristos       break;
788a1ba9ba4Schristos     case IP2K_OPERAND_ADDR16H :
789a1ba9ba4Schristos       value = fields->f_imm8;
790a1ba9ba4Schristos       break;
791a1ba9ba4Schristos     case IP2K_OPERAND_ADDR16L :
792a1ba9ba4Schristos       value = fields->f_imm8;
793a1ba9ba4Schristos       break;
794a1ba9ba4Schristos     case IP2K_OPERAND_ADDR16P :
795a1ba9ba4Schristos       value = fields->f_page3;
796a1ba9ba4Schristos       break;
797a1ba9ba4Schristos     case IP2K_OPERAND_BITNO :
798a1ba9ba4Schristos       value = fields->f_bitno;
799a1ba9ba4Schristos       break;
800a1ba9ba4Schristos     case IP2K_OPERAND_CBIT :
801a1ba9ba4Schristos       value = 0;
802a1ba9ba4Schristos       break;
803a1ba9ba4Schristos     case IP2K_OPERAND_DCBIT :
804a1ba9ba4Schristos       value = 0;
805a1ba9ba4Schristos       break;
806a1ba9ba4Schristos     case IP2K_OPERAND_FR :
807a1ba9ba4Schristos       value = fields->f_reg;
808a1ba9ba4Schristos       break;
809a1ba9ba4Schristos     case IP2K_OPERAND_LIT8 :
810a1ba9ba4Schristos       value = fields->f_imm8;
811a1ba9ba4Schristos       break;
812a1ba9ba4Schristos     case IP2K_OPERAND_PABITS :
813a1ba9ba4Schristos       value = 0;
814a1ba9ba4Schristos       break;
815a1ba9ba4Schristos     case IP2K_OPERAND_RETI3 :
816a1ba9ba4Schristos       value = fields->f_reti3;
817a1ba9ba4Schristos       break;
818a1ba9ba4Schristos     case IP2K_OPERAND_ZBIT :
819a1ba9ba4Schristos       value = 0;
820a1ba9ba4Schristos       break;
821a1ba9ba4Schristos 
822a1ba9ba4Schristos     default :
823a1ba9ba4Schristos       /* xgettext:c-format */
824dc268d07Schristos       opcodes_error_handler
825dc268d07Schristos 	(_("internal error: unrecognized field %d while getting vma operand"),
826a1ba9ba4Schristos 	 opindex);
827a1ba9ba4Schristos       abort ();
828a1ba9ba4Schristos   }
829a1ba9ba4Schristos 
830a1ba9ba4Schristos   return value;
831a1ba9ba4Schristos }
832a1ba9ba4Schristos 
833a1ba9ba4Schristos void ip2k_cgen_set_int_operand  (CGEN_CPU_DESC, int, CGEN_FIELDS *, int);
834a1ba9ba4Schristos void ip2k_cgen_set_vma_operand  (CGEN_CPU_DESC, int, CGEN_FIELDS *, bfd_vma);
835a1ba9ba4Schristos 
836a1ba9ba4Schristos /* Stuffing values in cgen_fields is handled by a collection of functions.
837a1ba9ba4Schristos    They are distinguished by the type of the VALUE argument they accept.
838a1ba9ba4Schristos    TODO: floating point, inlining support, remove cases where argument type
839a1ba9ba4Schristos    not appropriate.  */
840a1ba9ba4Schristos 
841a1ba9ba4Schristos void
ip2k_cgen_set_int_operand(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,int opindex,CGEN_FIELDS * fields,int value)842a1ba9ba4Schristos ip2k_cgen_set_int_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
843a1ba9ba4Schristos 			     int opindex,
844a1ba9ba4Schristos 			     CGEN_FIELDS * fields,
845a1ba9ba4Schristos 			     int value)
846a1ba9ba4Schristos {
847a1ba9ba4Schristos   switch (opindex)
848a1ba9ba4Schristos     {
849a1ba9ba4Schristos     case IP2K_OPERAND_ADDR16CJP :
850a1ba9ba4Schristos       fields->f_addr16cjp = value;
851a1ba9ba4Schristos       break;
852a1ba9ba4Schristos     case IP2K_OPERAND_ADDR16H :
853a1ba9ba4Schristos       fields->f_imm8 = value;
854a1ba9ba4Schristos       break;
855a1ba9ba4Schristos     case IP2K_OPERAND_ADDR16L :
856a1ba9ba4Schristos       fields->f_imm8 = value;
857a1ba9ba4Schristos       break;
858a1ba9ba4Schristos     case IP2K_OPERAND_ADDR16P :
859a1ba9ba4Schristos       fields->f_page3 = value;
860a1ba9ba4Schristos       break;
861a1ba9ba4Schristos     case IP2K_OPERAND_BITNO :
862a1ba9ba4Schristos       fields->f_bitno = value;
863a1ba9ba4Schristos       break;
864a1ba9ba4Schristos     case IP2K_OPERAND_CBIT :
865a1ba9ba4Schristos       break;
866a1ba9ba4Schristos     case IP2K_OPERAND_DCBIT :
867a1ba9ba4Schristos       break;
868a1ba9ba4Schristos     case IP2K_OPERAND_FR :
869a1ba9ba4Schristos       fields->f_reg = value;
870a1ba9ba4Schristos       break;
871a1ba9ba4Schristos     case IP2K_OPERAND_LIT8 :
872a1ba9ba4Schristos       fields->f_imm8 = value;
873a1ba9ba4Schristos       break;
874a1ba9ba4Schristos     case IP2K_OPERAND_PABITS :
875a1ba9ba4Schristos       break;
876a1ba9ba4Schristos     case IP2K_OPERAND_RETI3 :
877a1ba9ba4Schristos       fields->f_reti3 = value;
878a1ba9ba4Schristos       break;
879a1ba9ba4Schristos     case IP2K_OPERAND_ZBIT :
880a1ba9ba4Schristos       break;
881a1ba9ba4Schristos 
882a1ba9ba4Schristos     default :
883a1ba9ba4Schristos       /* xgettext:c-format */
884dc268d07Schristos       opcodes_error_handler
885dc268d07Schristos 	(_("internal error: unrecognized field %d while setting int operand"),
886a1ba9ba4Schristos 	 opindex);
887a1ba9ba4Schristos       abort ();
888a1ba9ba4Schristos   }
889a1ba9ba4Schristos }
890a1ba9ba4Schristos 
891a1ba9ba4Schristos void
ip2k_cgen_set_vma_operand(CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,int opindex,CGEN_FIELDS * fields,bfd_vma value)892a1ba9ba4Schristos ip2k_cgen_set_vma_operand (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
893a1ba9ba4Schristos 			     int opindex,
894a1ba9ba4Schristos 			     CGEN_FIELDS * fields,
895a1ba9ba4Schristos 			     bfd_vma value)
896a1ba9ba4Schristos {
897a1ba9ba4Schristos   switch (opindex)
898a1ba9ba4Schristos     {
899a1ba9ba4Schristos     case IP2K_OPERAND_ADDR16CJP :
900a1ba9ba4Schristos       fields->f_addr16cjp = value;
901a1ba9ba4Schristos       break;
902a1ba9ba4Schristos     case IP2K_OPERAND_ADDR16H :
903a1ba9ba4Schristos       fields->f_imm8 = value;
904a1ba9ba4Schristos       break;
905a1ba9ba4Schristos     case IP2K_OPERAND_ADDR16L :
906a1ba9ba4Schristos       fields->f_imm8 = value;
907a1ba9ba4Schristos       break;
908a1ba9ba4Schristos     case IP2K_OPERAND_ADDR16P :
909a1ba9ba4Schristos       fields->f_page3 = value;
910a1ba9ba4Schristos       break;
911a1ba9ba4Schristos     case IP2K_OPERAND_BITNO :
912a1ba9ba4Schristos       fields->f_bitno = value;
913a1ba9ba4Schristos       break;
914a1ba9ba4Schristos     case IP2K_OPERAND_CBIT :
915a1ba9ba4Schristos       break;
916a1ba9ba4Schristos     case IP2K_OPERAND_DCBIT :
917a1ba9ba4Schristos       break;
918a1ba9ba4Schristos     case IP2K_OPERAND_FR :
919a1ba9ba4Schristos       fields->f_reg = value;
920a1ba9ba4Schristos       break;
921a1ba9ba4Schristos     case IP2K_OPERAND_LIT8 :
922a1ba9ba4Schristos       fields->f_imm8 = value;
923a1ba9ba4Schristos       break;
924a1ba9ba4Schristos     case IP2K_OPERAND_PABITS :
925a1ba9ba4Schristos       break;
926a1ba9ba4Schristos     case IP2K_OPERAND_RETI3 :
927a1ba9ba4Schristos       fields->f_reti3 = value;
928a1ba9ba4Schristos       break;
929a1ba9ba4Schristos     case IP2K_OPERAND_ZBIT :
930a1ba9ba4Schristos       break;
931a1ba9ba4Schristos 
932a1ba9ba4Schristos     default :
933a1ba9ba4Schristos       /* xgettext:c-format */
934dc268d07Schristos       opcodes_error_handler
935dc268d07Schristos 	(_("internal error: unrecognized field %d while setting vma operand"),
936a1ba9ba4Schristos 	 opindex);
937a1ba9ba4Schristos       abort ();
938a1ba9ba4Schristos   }
939a1ba9ba4Schristos }
940a1ba9ba4Schristos 
941a1ba9ba4Schristos /* Function to call before using the instruction builder tables.  */
942a1ba9ba4Schristos 
943a1ba9ba4Schristos void
ip2k_cgen_init_ibld_table(CGEN_CPU_DESC cd)944a1ba9ba4Schristos ip2k_cgen_init_ibld_table (CGEN_CPU_DESC cd)
945a1ba9ba4Schristos {
946a1ba9ba4Schristos   cd->insert_handlers = & ip2k_cgen_insert_handlers[0];
947a1ba9ba4Schristos   cd->extract_handlers = & ip2k_cgen_extract_handlers[0];
948a1ba9ba4Schristos 
949a1ba9ba4Schristos   cd->insert_operand = ip2k_cgen_insert_operand;
950a1ba9ba4Schristos   cd->extract_operand = ip2k_cgen_extract_operand;
951a1ba9ba4Schristos 
952a1ba9ba4Schristos   cd->get_int_operand = ip2k_cgen_get_int_operand;
953a1ba9ba4Schristos   cd->set_int_operand = ip2k_cgen_set_int_operand;
954a1ba9ba4Schristos   cd->get_vma_operand = ip2k_cgen_get_vma_operand;
955a1ba9ba4Schristos   cd->set_vma_operand = ip2k_cgen_set_vma_operand;
956a1ba9ba4Schristos }
957