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