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