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

Annotation of src/external/gpl3/binutils/dist/opcodes/mt-dis.c, Revision 1.1.1.5.12.2

1.1.1.5.12.1  pgoyette    1: /* DO NOT EDIT!  -*- buffer-read-only: t -*- vi:set ro:  */
1.1       skrll       2: /* Disassembler interface for targets using CGEN. -*- C -*-
                      3:    CGEN: Cpu tools GENerator
                      4:
                      5:    THIS FILE IS MACHINE GENERATED WITH CGEN.
                      6:    - the resultant file is machine generated, cgen-dis.in isn't
                      7:
1.1.1.5.12.1  pgoyette    8:    Copyright (C) 1996-2018 Free Software Foundation, Inc.
1.1       skrll       9:
                     10:    This file is part of libopcodes.
                     11:
                     12:    This library is free software; you can redistribute it and/or modify
                     13:    it under the terms of the GNU General Public License as published by
                     14:    the Free Software Foundation; either version 3, or (at your option)
                     15:    any later version.
                     16:
                     17:    It is distributed in the hope that it will be useful, but WITHOUT
                     18:    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     19:    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
                     20:    License for more details.
                     21:
                     22:    You should have received a copy of the GNU General Public License
                     23:    along with this program; if not, write to the Free Software Foundation, Inc.,
                     24:    51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
                     25:
                     26: /* ??? Eventually more and more of this stuff can go to cpu-independent files.
                     27:    Keep that in mind.  */
                     28:
                     29: #include "sysdep.h"
                     30: #include <stdio.h>
                     31: #include "ansidecl.h"
1.1.1.5.12.1  pgoyette   32: #include "disassemble.h"
1.1       skrll      33: #include "bfd.h"
                     34: #include "symcat.h"
                     35: #include "libiberty.h"
                     36: #include "mt-desc.h"
                     37: #include "mt-opc.h"
                     38: #include "opintl.h"
                     39:
                     40: /* Default text to print if an instruction isn't recognized.  */
                     41: #define UNKNOWN_INSN_MSG _("*unknown*")
                     42:
                     43: static void print_normal
                     44:   (CGEN_CPU_DESC, void *, long, unsigned int, bfd_vma, int);
                     45: static void print_address
                     46:   (CGEN_CPU_DESC, void *, bfd_vma, unsigned int, bfd_vma, int) ATTRIBUTE_UNUSED;
                     47: static void print_keyword
                     48:   (CGEN_CPU_DESC, void *, CGEN_KEYWORD *, long, unsigned int) ATTRIBUTE_UNUSED;
                     49: static void print_insn_normal
                     50:   (CGEN_CPU_DESC, void *, const CGEN_INSN *, CGEN_FIELDS *, bfd_vma, int);
                     51: static int print_insn
                     52:   (CGEN_CPU_DESC, bfd_vma,  disassemble_info *, bfd_byte *, unsigned);
                     53: static int default_print_insn
                     54:   (CGEN_CPU_DESC, bfd_vma, disassemble_info *) ATTRIBUTE_UNUSED;
                     55: static int read_insn
                     56:   (CGEN_CPU_DESC, bfd_vma, disassemble_info *, bfd_byte *, int, CGEN_EXTRACT_INFO *,
                     57:    unsigned long *);
                     58: 
                     59: /* -- disassembler routines inserted here.  */
                     60:
                     61: /* -- dis.c */
                     62: static void print_dollarhex (CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int);
                     63: static void print_pcrel (CGEN_CPU_DESC, PTR, long, unsigned, bfd_vma, int);
                     64:
                     65: static void
                     66: print_dollarhex (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
                     67:                 void * dis_info,
                     68:                 long value,
                     69:                 unsigned int attrs ATTRIBUTE_UNUSED,
                     70:                 bfd_vma pc ATTRIBUTE_UNUSED,
                     71:                 int length ATTRIBUTE_UNUSED)
                     72: {
                     73:   disassemble_info *info = (disassemble_info *) dis_info;
                     74:
1.1.1.3   christos   75:   info->fprintf_func (info->stream, "$%lx", value & 0xffffffff);
1.1       skrll      76:
                     77:   if (0)
                     78:     print_normal (cd, dis_info, value, attrs, pc, length);
                     79: }
                     80:
                     81: static void
                     82: print_pcrel (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
                     83:             void * dis_info,
                     84:             long value,
                     85:             unsigned int attrs ATTRIBUTE_UNUSED,
                     86:             bfd_vma pc ATTRIBUTE_UNUSED,
                     87:             int length ATTRIBUTE_UNUSED)
                     88: {
                     89:   print_address (cd, dis_info, value + pc, attrs, pc, length);
                     90: }
                     91:
                     92: /* -- */
                     93:
                     94: void mt_cgen_print_operand
                     95:   (CGEN_CPU_DESC, int, PTR, CGEN_FIELDS *, void const *, bfd_vma, int);
                     96:
                     97: /* Main entry point for printing operands.
                     98:    XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
                     99:    of dis-asm.h on cgen.h.
                    100:
                    101:    This function is basically just a big switch statement.  Earlier versions
                    102:    used tables to look up the function to use, but
                    103:    - if the table contains both assembler and disassembler functions then
                    104:      the disassembler contains much of the assembler and vice-versa,
                    105:    - there's a lot of inlining possibilities as things grow,
                    106:    - using a switch statement avoids the function call overhead.
                    107:
                    108:    This function could be moved into `print_insn_normal', but keeping it
                    109:    separate makes clear the interface between `print_insn_normal' and each of
                    110:    the handlers.  */
                    111:
                    112: void
                    113: mt_cgen_print_operand (CGEN_CPU_DESC cd,
                    114:                           int opindex,
                    115:                           void * xinfo,
                    116:                           CGEN_FIELDS *fields,
                    117:                           void const *attrs ATTRIBUTE_UNUSED,
                    118:                           bfd_vma pc,
                    119:                           int length)
                    120: {
                    121:   disassemble_info *info = (disassemble_info *) xinfo;
                    122:
                    123:   switch (opindex)
                    124:     {
                    125:     case MT_OPERAND_A23 :
                    126:       print_dollarhex (cd, info, fields->f_a23, 0, pc, length);
                    127:       break;
                    128:     case MT_OPERAND_BALL :
                    129:       print_dollarhex (cd, info, fields->f_ball, 0, pc, length);
                    130:       break;
                    131:     case MT_OPERAND_BALL2 :
                    132:       print_dollarhex (cd, info, fields->f_ball2, 0, pc, length);
                    133:       break;
                    134:     case MT_OPERAND_BANKADDR :
                    135:       print_dollarhex (cd, info, fields->f_bankaddr, 0, pc, length);
                    136:       break;
                    137:     case MT_OPERAND_BRC :
                    138:       print_dollarhex (cd, info, fields->f_brc, 0, pc, length);
                    139:       break;
                    140:     case MT_OPERAND_BRC2 :
                    141:       print_dollarhex (cd, info, fields->f_brc2, 0, pc, length);
                    142:       break;
                    143:     case MT_OPERAND_CB1INCR :
                    144:       print_dollarhex (cd, info, fields->f_cb1incr, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
                    145:       break;
                    146:     case MT_OPERAND_CB1SEL :
                    147:       print_dollarhex (cd, info, fields->f_cb1sel, 0, pc, length);
                    148:       break;
                    149:     case MT_OPERAND_CB2INCR :
                    150:       print_dollarhex (cd, info, fields->f_cb2incr, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
                    151:       break;
                    152:     case MT_OPERAND_CB2SEL :
                    153:       print_dollarhex (cd, info, fields->f_cb2sel, 0, pc, length);
                    154:       break;
                    155:     case MT_OPERAND_CBRB :
                    156:       print_dollarhex (cd, info, fields->f_cbrb, 0, pc, length);
                    157:       break;
                    158:     case MT_OPERAND_CBS :
                    159:       print_dollarhex (cd, info, fields->f_cbs, 0, pc, length);
                    160:       break;
                    161:     case MT_OPERAND_CBX :
                    162:       print_dollarhex (cd, info, fields->f_cbx, 0, pc, length);
                    163:       break;
                    164:     case MT_OPERAND_CCB :
                    165:       print_dollarhex (cd, info, fields->f_ccb, 0, pc, length);
                    166:       break;
                    167:     case MT_OPERAND_CDB :
                    168:       print_dollarhex (cd, info, fields->f_cdb, 0, pc, length);
                    169:       break;
                    170:     case MT_OPERAND_CELL :
                    171:       print_dollarhex (cd, info, fields->f_cell, 0, pc, length);
                    172:       break;
                    173:     case MT_OPERAND_COLNUM :
                    174:       print_dollarhex (cd, info, fields->f_colnum, 0, pc, length);
                    175:       break;
                    176:     case MT_OPERAND_CONTNUM :
                    177:       print_dollarhex (cd, info, fields->f_contnum, 0, pc, length);
                    178:       break;
                    179:     case MT_OPERAND_CR :
                    180:       print_dollarhex (cd, info, fields->f_cr, 0, pc, length);
                    181:       break;
                    182:     case MT_OPERAND_CTXDISP :
                    183:       print_dollarhex (cd, info, fields->f_ctxdisp, 0, pc, length);
                    184:       break;
                    185:     case MT_OPERAND_DUP :
                    186:       print_dollarhex (cd, info, fields->f_dup, 0, pc, length);
                    187:       break;
                    188:     case MT_OPERAND_FBDISP :
                    189:       print_dollarhex (cd, info, fields->f_fbdisp, 0, pc, length);
                    190:       break;
                    191:     case MT_OPERAND_FBINCR :
                    192:       print_dollarhex (cd, info, fields->f_fbincr, 0, pc, length);
                    193:       break;
                    194:     case MT_OPERAND_FRDR :
                    195:       print_keyword (cd, info, & mt_cgen_opval_h_spr, fields->f_dr, 0|(1<<CGEN_OPERAND_ABS_ADDR));
                    196:       break;
                    197:     case MT_OPERAND_FRDRRR :
                    198:       print_keyword (cd, info, & mt_cgen_opval_h_spr, fields->f_drrr, 0|(1<<CGEN_OPERAND_ABS_ADDR));
                    199:       break;
                    200:     case MT_OPERAND_FRSR1 :
                    201:       print_keyword (cd, info, & mt_cgen_opval_h_spr, fields->f_sr1, 0|(1<<CGEN_OPERAND_ABS_ADDR));
                    202:       break;
                    203:     case MT_OPERAND_FRSR2 :
                    204:       print_keyword (cd, info, & mt_cgen_opval_h_spr, fields->f_sr2, 0|(1<<CGEN_OPERAND_ABS_ADDR));
                    205:       break;
                    206:     case MT_OPERAND_ID :
                    207:       print_dollarhex (cd, info, fields->f_id, 0, pc, length);
                    208:       break;
                    209:     case MT_OPERAND_IMM16 :
                    210:       print_dollarhex (cd, info, fields->f_imm16s, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
                    211:       break;
                    212:     case MT_OPERAND_IMM16L :
                    213:       print_dollarhex (cd, info, fields->f_imm16l, 0, pc, length);
                    214:       break;
                    215:     case MT_OPERAND_IMM16O :
                    216:       print_pcrel (cd, info, fields->f_imm16s, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
                    217:       break;
                    218:     case MT_OPERAND_IMM16Z :
                    219:       print_dollarhex (cd, info, fields->f_imm16u, 0, pc, length);
                    220:       break;
                    221:     case MT_OPERAND_INCAMT :
                    222:       print_dollarhex (cd, info, fields->f_incamt, 0, pc, length);
                    223:       break;
                    224:     case MT_OPERAND_INCR :
                    225:       print_dollarhex (cd, info, fields->f_incr, 0, pc, length);
                    226:       break;
                    227:     case MT_OPERAND_LENGTH :
                    228:       print_dollarhex (cd, info, fields->f_length, 0, pc, length);
                    229:       break;
                    230:     case MT_OPERAND_LOOPSIZE :
                    231:       print_pcrel (cd, info, fields->f_loopo, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
                    232:       break;
                    233:     case MT_OPERAND_MASK :
                    234:       print_dollarhex (cd, info, fields->f_mask, 0, pc, length);
                    235:       break;
                    236:     case MT_OPERAND_MASK1 :
                    237:       print_dollarhex (cd, info, fields->f_mask1, 0, pc, length);
                    238:       break;
                    239:     case MT_OPERAND_MODE :
                    240:       print_dollarhex (cd, info, fields->f_mode, 0, pc, length);
                    241:       break;
                    242:     case MT_OPERAND_PERM :
                    243:       print_dollarhex (cd, info, fields->f_perm, 0, pc, length);
                    244:       break;
                    245:     case MT_OPERAND_RBBC :
                    246:       print_dollarhex (cd, info, fields->f_rbbc, 0, pc, length);
                    247:       break;
                    248:     case MT_OPERAND_RC :
                    249:       print_dollarhex (cd, info, fields->f_rc, 0, pc, length);
                    250:       break;
                    251:     case MT_OPERAND_RC1 :
                    252:       print_dollarhex (cd, info, fields->f_rc1, 0, pc, length);
                    253:       break;
                    254:     case MT_OPERAND_RC2 :
                    255:       print_dollarhex (cd, info, fields->f_rc2, 0, pc, length);
                    256:       break;
                    257:     case MT_OPERAND_RC3 :
                    258:       print_dollarhex (cd, info, fields->f_rc3, 0, pc, length);
                    259:       break;
                    260:     case MT_OPERAND_RCNUM :
                    261:       print_dollarhex (cd, info, fields->f_rcnum, 0, pc, length);
                    262:       break;
                    263:     case MT_OPERAND_RDA :
                    264:       print_dollarhex (cd, info, fields->f_rda, 0, pc, length);
                    265:       break;
                    266:     case MT_OPERAND_ROWNUM :
                    267:       print_dollarhex (cd, info, fields->f_rownum, 0, pc, length);
                    268:       break;
                    269:     case MT_OPERAND_ROWNUM1 :
                    270:       print_dollarhex (cd, info, fields->f_rownum1, 0, pc, length);
                    271:       break;
                    272:     case MT_OPERAND_ROWNUM2 :
                    273:       print_dollarhex (cd, info, fields->f_rownum2, 0, pc, length);
                    274:       break;
                    275:     case MT_OPERAND_SIZE :
                    276:       print_dollarhex (cd, info, fields->f_size, 0, pc, length);
                    277:       break;
                    278:     case MT_OPERAND_TYPE :
                    279:       print_dollarhex (cd, info, fields->f_type, 0, pc, length);
                    280:       break;
                    281:     case MT_OPERAND_WR :
                    282:       print_dollarhex (cd, info, fields->f_wr, 0, pc, length);
                    283:       break;
                    284:     case MT_OPERAND_XMODE :
                    285:       print_dollarhex (cd, info, fields->f_xmode, 0, pc, length);
                    286:       break;
                    287:
                    288:     default :
                    289:       /* xgettext:c-format */
1.1.1.5.12.2! pgoyette  290:       opcodes_error_handler
        !           291:        (_("internal error: unrecognized field %d while printing insn"),
        !           292:         opindex);
        !           293:       abort ();
1.1       skrll     294:   }
                    295: }
                    296:
1.1.1.4   christos  297: cgen_print_fn * const mt_cgen_print_handlers[] =
1.1       skrll     298: {
                    299:   print_insn_normal,
                    300: };
                    301:
                    302:
                    303: void
                    304: mt_cgen_init_dis (CGEN_CPU_DESC cd)
                    305: {
                    306:   mt_cgen_init_opcode_table (cd);
                    307:   mt_cgen_init_ibld_table (cd);
                    308:   cd->print_handlers = & mt_cgen_print_handlers[0];
                    309:   cd->print_operand = mt_cgen_print_operand;
                    310: }
                    311:
                    312: 
                    313: /* Default print handler.  */
                    314:
                    315: static void
                    316: print_normal (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
                    317:              void *dis_info,
                    318:              long value,
                    319:              unsigned int attrs,
                    320:              bfd_vma pc ATTRIBUTE_UNUSED,
                    321:              int length ATTRIBUTE_UNUSED)
                    322: {
                    323:   disassemble_info *info = (disassemble_info *) dis_info;
                    324:
                    325:   /* Print the operand as directed by the attributes.  */
                    326:   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
                    327:     ; /* nothing to do */
                    328:   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
                    329:     (*info->fprintf_func) (info->stream, "%ld", value);
                    330:   else
                    331:     (*info->fprintf_func) (info->stream, "0x%lx", value);
                    332: }
                    333:
                    334: /* Default address handler.  */
                    335:
                    336: static void
                    337: print_address (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
                    338:               void *dis_info,
                    339:               bfd_vma value,
                    340:               unsigned int attrs,
                    341:               bfd_vma pc ATTRIBUTE_UNUSED,
                    342:               int length ATTRIBUTE_UNUSED)
                    343: {
                    344:   disassemble_info *info = (disassemble_info *) dis_info;
                    345:
                    346:   /* Print the operand as directed by the attributes.  */
                    347:   if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
                    348:     ; /* Nothing to do.  */
                    349:   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
                    350:     (*info->print_address_func) (value, info);
                    351:   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
                    352:     (*info->print_address_func) (value, info);
                    353:   else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
                    354:     (*info->fprintf_func) (info->stream, "%ld", (long) value);
                    355:   else
                    356:     (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
                    357: }
                    358:
                    359: /* Keyword print handler.  */
                    360:
                    361: static void
                    362: print_keyword (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
                    363:               void *dis_info,
                    364:               CGEN_KEYWORD *keyword_table,
                    365:               long value,
                    366:               unsigned int attrs ATTRIBUTE_UNUSED)
                    367: {
                    368:   disassemble_info *info = (disassemble_info *) dis_info;
                    369:   const CGEN_KEYWORD_ENTRY *ke;
                    370:
                    371:   ke = cgen_keyword_lookup_value (keyword_table, value);
                    372:   if (ke != NULL)
                    373:     (*info->fprintf_func) (info->stream, "%s", ke->name);
                    374:   else
                    375:     (*info->fprintf_func) (info->stream, "???");
                    376: }
                    377: 
                    378: /* Default insn printer.
                    379:
                    380:    DIS_INFO is defined as `void *' so the disassembler needn't know anything
                    381:    about disassemble_info.  */
                    382:
                    383: static void
                    384: print_insn_normal (CGEN_CPU_DESC cd,
                    385:                   void *dis_info,
                    386:                   const CGEN_INSN *insn,
                    387:                   CGEN_FIELDS *fields,
                    388:                   bfd_vma pc,
                    389:                   int length)
                    390: {
                    391:   const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
                    392:   disassemble_info *info = (disassemble_info *) dis_info;
                    393:   const CGEN_SYNTAX_CHAR_TYPE *syn;
                    394:
                    395:   CGEN_INIT_PRINT (cd);
                    396:
                    397:   for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
                    398:     {
                    399:       if (CGEN_SYNTAX_MNEMONIC_P (*syn))
                    400:        {
                    401:          (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
                    402:          continue;
                    403:        }
                    404:       if (CGEN_SYNTAX_CHAR_P (*syn))
                    405:        {
                    406:          (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
                    407:          continue;
                    408:        }
                    409:
                    410:       /* We have an operand.  */
                    411:       mt_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
                    412:                                 fields, CGEN_INSN_ATTRS (insn), pc, length);
                    413:     }
                    414: }
                    415: 
                    416: /* Subroutine of print_insn. Reads an insn into the given buffers and updates
                    417:    the extract info.
                    418:    Returns 0 if all is well, non-zero otherwise.  */
                    419:
                    420: static int
                    421: read_insn (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
                    422:           bfd_vma pc,
                    423:           disassemble_info *info,
                    424:           bfd_byte *buf,
                    425:           int buflen,
                    426:           CGEN_EXTRACT_INFO *ex_info,
                    427:           unsigned long *insn_value)
                    428: {
                    429:   int status = (*info->read_memory_func) (pc, buf, buflen, info);
                    430:
                    431:   if (status != 0)
                    432:     {
                    433:       (*info->memory_error_func) (status, pc, info);
                    434:       return -1;
                    435:     }
                    436:
                    437:   ex_info->dis_info = info;
                    438:   ex_info->valid = (1 << buflen) - 1;
                    439:   ex_info->insn_bytes = buf;
                    440:
                    441:   *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
                    442:   return 0;
                    443: }
                    444:
                    445: /* Utility to print an insn.
                    446:    BUF is the base part of the insn, target byte order, BUFLEN bytes long.
                    447:    The result is the size of the insn in bytes or zero for an unknown insn
                    448:    or -1 if an error occurs fetching data (memory_error_func will have
                    449:    been called).  */
                    450:
                    451: static int
                    452: print_insn (CGEN_CPU_DESC cd,
                    453:            bfd_vma pc,
                    454:            disassemble_info *info,
                    455:            bfd_byte *buf,
                    456:            unsigned int buflen)
                    457: {
                    458:   CGEN_INSN_INT insn_value;
                    459:   const CGEN_INSN_LIST *insn_list;
                    460:   CGEN_EXTRACT_INFO ex_info;
                    461:   int basesize;
                    462:
                    463:   /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
                    464:   basesize = cd->base_insn_bitsize < buflen * 8 ?
                    465:                                      cd->base_insn_bitsize : buflen * 8;
                    466:   insn_value = cgen_get_insn_value (cd, buf, basesize);
                    467:
                    468:
                    469:   /* Fill in ex_info fields like read_insn would.  Don't actually call
                    470:      read_insn, since the incoming buffer is already read (and possibly
                    471:      modified a la m32r).  */
                    472:   ex_info.valid = (1 << buflen) - 1;
                    473:   ex_info.dis_info = info;
                    474:   ex_info.insn_bytes = buf;
                    475:
                    476:   /* The instructions are stored in hash lists.
                    477:      Pick the first one and keep trying until we find the right one.  */
                    478:
                    479:   insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
                    480:   while (insn_list != NULL)
                    481:     {
                    482:       const CGEN_INSN *insn = insn_list->insn;
                    483:       CGEN_FIELDS fields;
                    484:       int length;
                    485:       unsigned long insn_value_cropped;
                    486:
1.1.1.4   christos  487: #ifdef CGEN_VALIDATE_INSN_SUPPORTED
1.1       skrll     488:       /* Not needed as insn shouldn't be in hash lists if not supported.  */
                    489:       /* Supported by this cpu?  */
                    490:       if (! mt_cgen_insn_supported (cd, insn))
                    491:         {
                    492:           insn_list = CGEN_DIS_NEXT_INSN (insn_list);
                    493:          continue;
                    494:         }
                    495: #endif
                    496:
                    497:       /* Basic bit mask must be correct.  */
                    498:       /* ??? May wish to allow target to defer this check until the extract
                    499:         handler.  */
                    500:
                    501:       /* Base size may exceed this instruction's size.  Extract the
                    502:          relevant part from the buffer. */
                    503:       if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
                    504:          (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
1.1.1.4   christos  505:        insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn),
1.1       skrll     506:                                           info->endian == BFD_ENDIAN_BIG);
                    507:       else
                    508:        insn_value_cropped = insn_value;
                    509:
                    510:       if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
                    511:          == CGEN_INSN_BASE_VALUE (insn))
                    512:        {
                    513:          /* Printing is handled in two passes.  The first pass parses the
                    514:             machine insn and extracts the fields.  The second pass prints
                    515:             them.  */
                    516:
                    517:          /* Make sure the entire insn is loaded into insn_value, if it
                    518:             can fit.  */
                    519:          if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
                    520:              (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
                    521:            {
                    522:              unsigned long full_insn_value;
                    523:              int rc = read_insn (cd, pc, info, buf,
                    524:                                  CGEN_INSN_BITSIZE (insn) / 8,
                    525:                                  & ex_info, & full_insn_value);
                    526:              if (rc != 0)
                    527:                return rc;
                    528:              length = CGEN_EXTRACT_FN (cd, insn)
                    529:                (cd, insn, &ex_info, full_insn_value, &fields, pc);
                    530:            }
                    531:          else
                    532:            length = CGEN_EXTRACT_FN (cd, insn)
                    533:              (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
                    534:
                    535:          /* Length < 0 -> error.  */
                    536:          if (length < 0)
                    537:            return length;
                    538:          if (length > 0)
                    539:            {
                    540:              CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
                    541:              /* Length is in bits, result is in bytes.  */
                    542:              return length / 8;
                    543:            }
                    544:        }
                    545:
                    546:       insn_list = CGEN_DIS_NEXT_INSN (insn_list);
                    547:     }
                    548:
                    549:   return 0;
                    550: }
                    551:
                    552: /* Default value for CGEN_PRINT_INSN.
                    553:    The result is the size of the insn in bytes or zero for an unknown insn
                    554:    or -1 if an error occured fetching bytes.  */
                    555:
                    556: #ifndef CGEN_PRINT_INSN
                    557: #define CGEN_PRINT_INSN default_print_insn
                    558: #endif
                    559:
                    560: static int
                    561: default_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
                    562: {
                    563:   bfd_byte buf[CGEN_MAX_INSN_SIZE];
                    564:   int buflen;
                    565:   int status;
                    566:
                    567:   /* Attempt to read the base part of the insn.  */
                    568:   buflen = cd->base_insn_bitsize / 8;
                    569:   status = (*info->read_memory_func) (pc, buf, buflen, info);
                    570:
                    571:   /* Try again with the minimum part, if min < base.  */
                    572:   if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
                    573:     {
                    574:       buflen = cd->min_insn_bitsize / 8;
                    575:       status = (*info->read_memory_func) (pc, buf, buflen, info);
                    576:     }
                    577:
                    578:   if (status != 0)
                    579:     {
                    580:       (*info->memory_error_func) (status, pc, info);
                    581:       return -1;
                    582:     }
                    583:
                    584:   return print_insn (cd, pc, info, buf, buflen);
                    585: }
                    586:
                    587: /* Main entry point.
                    588:    Print one instruction from PC on INFO->STREAM.
                    589:    Return the size of the instruction (in bytes).  */
                    590:
                    591: typedef struct cpu_desc_list
                    592: {
                    593:   struct cpu_desc_list *next;
                    594:   CGEN_BITSET *isa;
                    595:   int mach;
                    596:   int endian;
                    597:   CGEN_CPU_DESC cd;
                    598: } cpu_desc_list;
                    599:
                    600: int
                    601: print_insn_mt (bfd_vma pc, disassemble_info *info)
                    602: {
                    603:   static cpu_desc_list *cd_list = 0;
                    604:   cpu_desc_list *cl = 0;
                    605:   static CGEN_CPU_DESC cd = 0;
                    606:   static CGEN_BITSET *prev_isa;
                    607:   static int prev_mach;
                    608:   static int prev_endian;
                    609:   int length;
                    610:   CGEN_BITSET *isa;
                    611:   int mach;
                    612:   int endian = (info->endian == BFD_ENDIAN_BIG
                    613:                ? CGEN_ENDIAN_BIG
                    614:                : CGEN_ENDIAN_LITTLE);
                    615:   enum bfd_architecture arch;
                    616:
                    617:   /* ??? gdb will set mach but leave the architecture as "unknown" */
                    618: #ifndef CGEN_BFD_ARCH
                    619: #define CGEN_BFD_ARCH bfd_arch_mt
                    620: #endif
                    621:   arch = info->arch;
                    622:   if (arch == bfd_arch_unknown)
                    623:     arch = CGEN_BFD_ARCH;
1.1.1.4   christos  624:
1.1       skrll     625:   /* There's no standard way to compute the machine or isa number
                    626:      so we leave it to the target.  */
                    627: #ifdef CGEN_COMPUTE_MACH
                    628:   mach = CGEN_COMPUTE_MACH (info);
                    629: #else
                    630:   mach = info->mach;
                    631: #endif
                    632:
                    633: #ifdef CGEN_COMPUTE_ISA
                    634:   {
                    635:     static CGEN_BITSET *permanent_isa;
                    636:
                    637:     if (!permanent_isa)
                    638:       permanent_isa = cgen_bitset_create (MAX_ISAS);
                    639:     isa = permanent_isa;
                    640:     cgen_bitset_clear (isa);
                    641:     cgen_bitset_add (isa, CGEN_COMPUTE_ISA (info));
                    642:   }
                    643: #else
                    644:   isa = info->insn_sets;
                    645: #endif
                    646:
                    647:   /* If we've switched cpu's, try to find a handle we've used before */
                    648:   if (cd
                    649:       && (cgen_bitset_compare (isa, prev_isa) != 0
                    650:          || mach != prev_mach
                    651:          || endian != prev_endian))
                    652:     {
                    653:       cd = 0;
                    654:       for (cl = cd_list; cl; cl = cl->next)
                    655:        {
                    656:          if (cgen_bitset_compare (cl->isa, isa) == 0 &&
                    657:              cl->mach == mach &&
                    658:              cl->endian == endian)
                    659:            {
                    660:              cd = cl->cd;
                    661:              prev_isa = cd->isas;
                    662:              break;
                    663:            }
                    664:        }
1.1.1.4   christos  665:     }
1.1       skrll     666:
                    667:   /* If we haven't initialized yet, initialize the opcode table.  */
                    668:   if (! cd)
                    669:     {
                    670:       const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
                    671:       const char *mach_name;
                    672:
                    673:       if (!arch_type)
                    674:        abort ();
                    675:       mach_name = arch_type->printable_name;
                    676:
                    677:       prev_isa = cgen_bitset_copy (isa);
                    678:       prev_mach = mach;
                    679:       prev_endian = endian;
                    680:       cd = mt_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
                    681:                                 CGEN_CPU_OPEN_BFDMACH, mach_name,
                    682:                                 CGEN_CPU_OPEN_ENDIAN, prev_endian,
                    683:                                 CGEN_CPU_OPEN_END);
                    684:       if (!cd)
                    685:        abort ();
                    686:
                    687:       /* Save this away for future reference.  */
                    688:       cl = xmalloc (sizeof (struct cpu_desc_list));
                    689:       cl->cd = cd;
                    690:       cl->isa = prev_isa;
                    691:       cl->mach = mach;
                    692:       cl->endian = endian;
                    693:       cl->next = cd_list;
                    694:       cd_list = cl;
                    695:
                    696:       mt_cgen_init_dis (cd);
                    697:     }
                    698:
                    699:   /* We try to have as much common code as possible.
                    700:      But at this point some targets need to take over.  */
                    701:   /* ??? Some targets may need a hook elsewhere.  Try to avoid this,
                    702:      but if not possible try to move this hook elsewhere rather than
                    703:      have two hooks.  */
                    704:   length = CGEN_PRINT_INSN (cd, pc, info);
                    705:   if (length > 0)
                    706:     return length;
                    707:   if (length < 0)
                    708:     return -1;
                    709:
                    710:   (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
                    711:   return cd->default_insn_bitsize / 8;
                    712: }

CVSweb <webmaster@jp.NetBSD.org>