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