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