[BACK]Return to lm32-ibld.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / external / gpl3 / binutils / dist / opcodes

Annotation of src/external/gpl3/binutils/dist/opcodes/lm32-ibld.c, Revision 1.1.1.1

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

CVSweb <webmaster@jp.NetBSD.org>