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