OpenCores
URL https://opencores.org/ocsvn/open8_urisc/open8_urisc/trunk

Subversion Repositories open8_urisc

[/] [open8_urisc/] [trunk/] [gnu/] [binutils/] [opcodes/] [m32r-dis.c] - Blame information for rev 160

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 18 khays
/* Disassembler interface for targets using CGEN. -*- C -*-
2
   CGEN: Cpu tools GENerator
3
 
4
   THIS FILE IS MACHINE GENERATED WITH CGEN.
5
   - the resultant file is machine generated, cgen-dis.in isn't
6
 
7
   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2005, 2007,
8
   2008, 2010  Free Software Foundation, Inc.
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"
32
#include "dis-asm.h"
33
#include "bfd.h"
34
#include "symcat.h"
35
#include "libiberty.h"
36
#include "m32r-desc.h"
37
#include "m32r-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
 
63
/* Print signed operands with '#' prefixes.  */
64
 
65
static void
66
print_signed_with_hash_prefix (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
 
75
  (*info->fprintf_func) (info->stream, "#");
76
  (*info->fprintf_func) (info->stream, "%ld", value);
77
}
78
 
79
/* Print unsigned operands with '#' prefixes.  */
80
 
81
static void
82
print_unsigned_with_hash_prefix (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
  disassemble_info *info = (disassemble_info *) dis_info;
90
 
91
  (*info->fprintf_func) (info->stream, "#");
92
  (*info->fprintf_func) (info->stream, "0x%lx", value);
93
}
94
 
95
/* Handle '#' prefixes as operands.  */
96
 
97
static void
98
print_hash (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
99
            void * dis_info,
100
            long value ATTRIBUTE_UNUSED,
101
            unsigned int attrs ATTRIBUTE_UNUSED,
102
            bfd_vma pc ATTRIBUTE_UNUSED,
103
            int length ATTRIBUTE_UNUSED)
104
{
105
  disassemble_info *info = (disassemble_info *) dis_info;
106
 
107
  (*info->fprintf_func) (info->stream, "#");
108
}
109
 
110
#undef  CGEN_PRINT_INSN
111
#define CGEN_PRINT_INSN my_print_insn
112
 
113
static int
114
my_print_insn (CGEN_CPU_DESC cd,
115
               bfd_vma pc,
116
               disassemble_info *info)
117
{
118
  bfd_byte buffer[CGEN_MAX_INSN_SIZE];
119
  bfd_byte *buf = buffer;
120
  int status;
121
  int buflen = (pc & 3) == 0 ? 4 : 2;
122
  int big_p = CGEN_CPU_INSN_ENDIAN (cd) == CGEN_ENDIAN_BIG;
123
  bfd_byte *x;
124
 
125
  /* Read the base part of the insn.  */
126
 
127
  status = (*info->read_memory_func) (pc - ((!big_p && (pc & 3) != 0) ? 2 : 0),
128
                                      buf, buflen, info);
129
  if (status != 0)
130
    {
131
      (*info->memory_error_func) (status, pc, info);
132
      return -1;
133
    }
134
 
135
  /* 32 bit insn?  */
136
  x = (big_p ? &buf[0] : &buf[3]);
137
  if ((pc & 3) == 0 && (*x & 0x80) != 0)
138
    return print_insn (cd, pc, info, buf, buflen);
139
 
140
  /* Print the first insn.  */
141
  if ((pc & 3) == 0)
142
    {
143
      buf += (big_p ? 0 : 2);
144
      if (print_insn (cd, pc, info, buf, 2) == 0)
145
        (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
146
      buf += (big_p ? 2 : -2);
147
    }
148
 
149
  x = (big_p ? &buf[0] : &buf[1]);
150
  if (*x & 0x80)
151
    {
152
      /* Parallel.  */
153
      (*info->fprintf_func) (info->stream, " || ");
154
      *x &= 0x7f;
155
    }
156
  else
157
    (*info->fprintf_func) (info->stream, " -> ");
158
 
159
  /* The "& 3" is to pass a consistent address.
160
     Parallel insns arguably both begin on the word boundary.
161
     Also, branch insns are calculated relative to the word boundary.  */
162
  if (print_insn (cd, pc & ~ (bfd_vma) 3, info, buf, 2) == 0)
163
    (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
164
 
165
  return (pc & 3) ? 2 : 4;
166
}
167
 
168
/* -- */
169
 
170
void m32r_cgen_print_operand
171
  (CGEN_CPU_DESC, int, PTR, CGEN_FIELDS *, void const *, bfd_vma, int);
172
 
173
/* Main entry point for printing operands.
174
   XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
175
   of dis-asm.h on cgen.h.
176
 
177
   This function is basically just a big switch statement.  Earlier versions
178
   used tables to look up the function to use, but
179
   - if the table contains both assembler and disassembler functions then
180
     the disassembler contains much of the assembler and vice-versa,
181
   - there's a lot of inlining possibilities as things grow,
182
   - using a switch statement avoids the function call overhead.
183
 
184
   This function could be moved into `print_insn_normal', but keeping it
185
   separate makes clear the interface between `print_insn_normal' and each of
186
   the handlers.  */
187
 
188
void
189
m32r_cgen_print_operand (CGEN_CPU_DESC cd,
190
                           int opindex,
191
                           void * xinfo,
192
                           CGEN_FIELDS *fields,
193
                           void const *attrs ATTRIBUTE_UNUSED,
194
                           bfd_vma pc,
195
                           int length)
196
{
197
  disassemble_info *info = (disassemble_info *) xinfo;
198
 
199
  switch (opindex)
200
    {
201
    case M32R_OPERAND_ACC :
202
      print_keyword (cd, info, & m32r_cgen_opval_h_accums, fields->f_acc, 0);
203
      break;
204
    case M32R_OPERAND_ACCD :
205
      print_keyword (cd, info, & m32r_cgen_opval_h_accums, fields->f_accd, 0);
206
      break;
207
    case M32R_OPERAND_ACCS :
208
      print_keyword (cd, info, & m32r_cgen_opval_h_accums, fields->f_accs, 0);
209
      break;
210
    case M32R_OPERAND_DCR :
211
      print_keyword (cd, info, & m32r_cgen_opval_cr_names, fields->f_r1, 0);
212
      break;
213
    case M32R_OPERAND_DISP16 :
214
      print_address (cd, info, fields->f_disp16, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
215
      break;
216
    case M32R_OPERAND_DISP24 :
217
      print_address (cd, info, fields->f_disp24, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
218
      break;
219
    case M32R_OPERAND_DISP8 :
220
      print_address (cd, info, fields->f_disp8, 0|(1<<CGEN_OPERAND_RELAX)|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
221
      break;
222
    case M32R_OPERAND_DR :
223
      print_keyword (cd, info, & m32r_cgen_opval_gr_names, fields->f_r1, 0);
224
      break;
225
    case M32R_OPERAND_HASH :
226
      print_hash (cd, info, 0, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
227
      break;
228
    case M32R_OPERAND_HI16 :
229
      print_normal (cd, info, fields->f_hi16, 0|(1<<CGEN_OPERAND_SIGN_OPT), pc, length);
230
      break;
231
    case M32R_OPERAND_IMM1 :
232
      print_unsigned_with_hash_prefix (cd, info, fields->f_imm1, 0, pc, length);
233
      break;
234
    case M32R_OPERAND_SCR :
235
      print_keyword (cd, info, & m32r_cgen_opval_cr_names, fields->f_r2, 0);
236
      break;
237
    case M32R_OPERAND_SIMM16 :
238
      print_signed_with_hash_prefix (cd, info, fields->f_simm16, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
239
      break;
240
    case M32R_OPERAND_SIMM8 :
241
      print_signed_with_hash_prefix (cd, info, fields->f_simm8, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
242
      break;
243
    case M32R_OPERAND_SLO16 :
244
      print_normal (cd, info, fields->f_simm16, 0|(1<<CGEN_OPERAND_SIGNED), pc, length);
245
      break;
246
    case M32R_OPERAND_SR :
247
      print_keyword (cd, info, & m32r_cgen_opval_gr_names, fields->f_r2, 0);
248
      break;
249
    case M32R_OPERAND_SRC1 :
250
      print_keyword (cd, info, & m32r_cgen_opval_gr_names, fields->f_r1, 0);
251
      break;
252
    case M32R_OPERAND_SRC2 :
253
      print_keyword (cd, info, & m32r_cgen_opval_gr_names, fields->f_r2, 0);
254
      break;
255
    case M32R_OPERAND_UIMM16 :
256
      print_unsigned_with_hash_prefix (cd, info, fields->f_uimm16, 0, pc, length);
257
      break;
258
    case M32R_OPERAND_UIMM24 :
259
      print_address (cd, info, fields->f_uimm24, 0|(1<<CGEN_OPERAND_RELOC)|(1<<CGEN_OPERAND_ABS_ADDR), pc, length);
260
      break;
261
    case M32R_OPERAND_UIMM3 :
262
      print_unsigned_with_hash_prefix (cd, info, fields->f_uimm3, 0, pc, length);
263
      break;
264
    case M32R_OPERAND_UIMM4 :
265
      print_unsigned_with_hash_prefix (cd, info, fields->f_uimm4, 0, pc, length);
266
      break;
267
    case M32R_OPERAND_UIMM5 :
268
      print_unsigned_with_hash_prefix (cd, info, fields->f_uimm5, 0, pc, length);
269
      break;
270
    case M32R_OPERAND_UIMM8 :
271
      print_unsigned_with_hash_prefix (cd, info, fields->f_uimm8, 0, pc, length);
272
      break;
273
    case M32R_OPERAND_ULO16 :
274
      print_normal (cd, info, fields->f_uimm16, 0, pc, length);
275
      break;
276
 
277
    default :
278
      /* xgettext:c-format */
279
      fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
280
               opindex);
281
    abort ();
282
  }
283
}
284
 
285
cgen_print_fn * const m32r_cgen_print_handlers[] =
286
{
287
  print_insn_normal,
288
};
289
 
290
 
291
void
292
m32r_cgen_init_dis (CGEN_CPU_DESC cd)
293
{
294
  m32r_cgen_init_opcode_table (cd);
295
  m32r_cgen_init_ibld_table (cd);
296
  cd->print_handlers = & m32r_cgen_print_handlers[0];
297
  cd->print_operand = m32r_cgen_print_operand;
298
}
299
 
300
 
301
/* Default print handler.  */
302
 
303
static void
304
print_normal (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
305
              void *dis_info,
306
              long value,
307
              unsigned int attrs,
308
              bfd_vma pc ATTRIBUTE_UNUSED,
309
              int length ATTRIBUTE_UNUSED)
310
{
311
  disassemble_info *info = (disassemble_info *) dis_info;
312
 
313
  /* Print the operand as directed by the attributes.  */
314
  if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
315
    ; /* nothing to do */
316
  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
317
    (*info->fprintf_func) (info->stream, "%ld", value);
318
  else
319
    (*info->fprintf_func) (info->stream, "0x%lx", value);
320
}
321
 
322
/* Default address handler.  */
323
 
324
static void
325
print_address (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
326
               void *dis_info,
327
               bfd_vma value,
328
               unsigned int attrs,
329
               bfd_vma pc ATTRIBUTE_UNUSED,
330
               int length ATTRIBUTE_UNUSED)
331
{
332
  disassemble_info *info = (disassemble_info *) dis_info;
333
 
334
  /* Print the operand as directed by the attributes.  */
335
  if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
336
    ; /* Nothing to do.  */
337
  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
338
    (*info->print_address_func) (value, info);
339
  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
340
    (*info->print_address_func) (value, info);
341
  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
342
    (*info->fprintf_func) (info->stream, "%ld", (long) value);
343
  else
344
    (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
345
}
346
 
347
/* Keyword print handler.  */
348
 
349
static void
350
print_keyword (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
351
               void *dis_info,
352
               CGEN_KEYWORD *keyword_table,
353
               long value,
354
               unsigned int attrs ATTRIBUTE_UNUSED)
355
{
356
  disassemble_info *info = (disassemble_info *) dis_info;
357
  const CGEN_KEYWORD_ENTRY *ke;
358
 
359
  ke = cgen_keyword_lookup_value (keyword_table, value);
360
  if (ke != NULL)
361
    (*info->fprintf_func) (info->stream, "%s", ke->name);
362
  else
363
    (*info->fprintf_func) (info->stream, "???");
364
}
365
 
366
/* Default insn printer.
367
 
368
   DIS_INFO is defined as `void *' so the disassembler needn't know anything
369
   about disassemble_info.  */
370
 
371
static void
372
print_insn_normal (CGEN_CPU_DESC cd,
373
                   void *dis_info,
374
                   const CGEN_INSN *insn,
375
                   CGEN_FIELDS *fields,
376
                   bfd_vma pc,
377
                   int length)
378
{
379
  const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
380
  disassemble_info *info = (disassemble_info *) dis_info;
381
  const CGEN_SYNTAX_CHAR_TYPE *syn;
382
 
383
  CGEN_INIT_PRINT (cd);
384
 
385
  for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
386
    {
387
      if (CGEN_SYNTAX_MNEMONIC_P (*syn))
388
        {
389
          (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
390
          continue;
391
        }
392
      if (CGEN_SYNTAX_CHAR_P (*syn))
393
        {
394
          (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
395
          continue;
396
        }
397
 
398
      /* We have an operand.  */
399
      m32r_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
400
                                 fields, CGEN_INSN_ATTRS (insn), pc, length);
401
    }
402
}
403
 
404
/* Subroutine of print_insn. Reads an insn into the given buffers and updates
405
   the extract info.
406
   Returns 0 if all is well, non-zero otherwise.  */
407
 
408
static int
409
read_insn (CGEN_CPU_DESC cd ATTRIBUTE_UNUSED,
410
           bfd_vma pc,
411
           disassemble_info *info,
412
           bfd_byte *buf,
413
           int buflen,
414
           CGEN_EXTRACT_INFO *ex_info,
415
           unsigned long *insn_value)
416
{
417
  int status = (*info->read_memory_func) (pc, buf, buflen, info);
418
 
419
  if (status != 0)
420
    {
421
      (*info->memory_error_func) (status, pc, info);
422
      return -1;
423
    }
424
 
425
  ex_info->dis_info = info;
426
  ex_info->valid = (1 << buflen) - 1;
427
  ex_info->insn_bytes = buf;
428
 
429
  *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
430
  return 0;
431
}
432
 
433
/* Utility to print an insn.
434
   BUF is the base part of the insn, target byte order, BUFLEN bytes long.
435
   The result is the size of the insn in bytes or zero for an unknown insn
436
   or -1 if an error occurs fetching data (memory_error_func will have
437
   been called).  */
438
 
439
static int
440
print_insn (CGEN_CPU_DESC cd,
441
            bfd_vma pc,
442
            disassemble_info *info,
443
            bfd_byte *buf,
444
            unsigned int buflen)
445
{
446
  CGEN_INSN_INT insn_value;
447
  const CGEN_INSN_LIST *insn_list;
448
  CGEN_EXTRACT_INFO ex_info;
449
  int basesize;
450
 
451
  /* Extract base part of instruction, just in case CGEN_DIS_* uses it. */
452
  basesize = cd->base_insn_bitsize < buflen * 8 ?
453
                                     cd->base_insn_bitsize : buflen * 8;
454
  insn_value = cgen_get_insn_value (cd, buf, basesize);
455
 
456
 
457
  /* Fill in ex_info fields like read_insn would.  Don't actually call
458
     read_insn, since the incoming buffer is already read (and possibly
459
     modified a la m32r).  */
460
  ex_info.valid = (1 << buflen) - 1;
461
  ex_info.dis_info = info;
462
  ex_info.insn_bytes = buf;
463
 
464
  /* The instructions are stored in hash lists.
465
     Pick the first one and keep trying until we find the right one.  */
466
 
467
  insn_list = CGEN_DIS_LOOKUP_INSN (cd, (char *) buf, insn_value);
468
  while (insn_list != NULL)
469
    {
470
      const CGEN_INSN *insn = insn_list->insn;
471
      CGEN_FIELDS fields;
472
      int length;
473
      unsigned long insn_value_cropped;
474
 
475
#ifdef CGEN_VALIDATE_INSN_SUPPORTED 
476
      /* Not needed as insn shouldn't be in hash lists if not supported.  */
477
      /* Supported by this cpu?  */
478
      if (! m32r_cgen_insn_supported (cd, insn))
479
        {
480
          insn_list = CGEN_DIS_NEXT_INSN (insn_list);
481
          continue;
482
        }
483
#endif
484
 
485
      /* Basic bit mask must be correct.  */
486
      /* ??? May wish to allow target to defer this check until the extract
487
         handler.  */
488
 
489
      /* Base size may exceed this instruction's size.  Extract the
490
         relevant part from the buffer. */
491
      if ((unsigned) (CGEN_INSN_BITSIZE (insn) / 8) < buflen &&
492
          (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
493
        insn_value_cropped = bfd_get_bits (buf, CGEN_INSN_BITSIZE (insn),
494
                                           info->endian == BFD_ENDIAN_BIG);
495
      else
496
        insn_value_cropped = insn_value;
497
 
498
      if ((insn_value_cropped & CGEN_INSN_BASE_MASK (insn))
499
          == CGEN_INSN_BASE_VALUE (insn))
500
        {
501
          /* Printing is handled in two passes.  The first pass parses the
502
             machine insn and extracts the fields.  The second pass prints
503
             them.  */
504
 
505
          /* Make sure the entire insn is loaded into insn_value, if it
506
             can fit.  */
507
          if (((unsigned) CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize) &&
508
              (unsigned) (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
509
            {
510
              unsigned long full_insn_value;
511
              int rc = read_insn (cd, pc, info, buf,
512
                                  CGEN_INSN_BITSIZE (insn) / 8,
513
                                  & ex_info, & full_insn_value);
514
              if (rc != 0)
515
                return rc;
516
              length = CGEN_EXTRACT_FN (cd, insn)
517
                (cd, insn, &ex_info, full_insn_value, &fields, pc);
518
            }
519
          else
520
            length = CGEN_EXTRACT_FN (cd, insn)
521
              (cd, insn, &ex_info, insn_value_cropped, &fields, pc);
522
 
523
          /* Length < 0 -> error.  */
524
          if (length < 0)
525
            return length;
526
          if (length > 0)
527
            {
528
              CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
529
              /* Length is in bits, result is in bytes.  */
530
              return length / 8;
531
            }
532
        }
533
 
534
      insn_list = CGEN_DIS_NEXT_INSN (insn_list);
535
    }
536
 
537
  return 0;
538
}
539
 
540
/* Default value for CGEN_PRINT_INSN.
541
   The result is the size of the insn in bytes or zero for an unknown insn
542
   or -1 if an error occured fetching bytes.  */
543
 
544
#ifndef CGEN_PRINT_INSN
545
#define CGEN_PRINT_INSN default_print_insn
546
#endif
547
 
548
static int
549
default_print_insn (CGEN_CPU_DESC cd, bfd_vma pc, disassemble_info *info)
550
{
551
  bfd_byte buf[CGEN_MAX_INSN_SIZE];
552
  int buflen;
553
  int status;
554
 
555
  /* Attempt to read the base part of the insn.  */
556
  buflen = cd->base_insn_bitsize / 8;
557
  status = (*info->read_memory_func) (pc, buf, buflen, info);
558
 
559
  /* Try again with the minimum part, if min < base.  */
560
  if (status != 0 && (cd->min_insn_bitsize < cd->base_insn_bitsize))
561
    {
562
      buflen = cd->min_insn_bitsize / 8;
563
      status = (*info->read_memory_func) (pc, buf, buflen, info);
564
    }
565
 
566
  if (status != 0)
567
    {
568
      (*info->memory_error_func) (status, pc, info);
569
      return -1;
570
    }
571
 
572
  return print_insn (cd, pc, info, buf, buflen);
573
}
574
 
575
/* Main entry point.
576
   Print one instruction from PC on INFO->STREAM.
577
   Return the size of the instruction (in bytes).  */
578
 
579
typedef struct cpu_desc_list
580
{
581
  struct cpu_desc_list *next;
582
  CGEN_BITSET *isa;
583
  int mach;
584
  int endian;
585
  CGEN_CPU_DESC cd;
586
} cpu_desc_list;
587
 
588
int
589
print_insn_m32r (bfd_vma pc, disassemble_info *info)
590
{
591
  static cpu_desc_list *cd_list = 0;
592
  cpu_desc_list *cl = 0;
593
  static CGEN_CPU_DESC cd = 0;
594
  static CGEN_BITSET *prev_isa;
595
  static int prev_mach;
596
  static int prev_endian;
597
  int length;
598
  CGEN_BITSET *isa;
599
  int mach;
600
  int endian = (info->endian == BFD_ENDIAN_BIG
601
                ? CGEN_ENDIAN_BIG
602
                : CGEN_ENDIAN_LITTLE);
603
  enum bfd_architecture arch;
604
 
605
  /* ??? gdb will set mach but leave the architecture as "unknown" */
606
#ifndef CGEN_BFD_ARCH
607
#define CGEN_BFD_ARCH bfd_arch_m32r
608
#endif
609
  arch = info->arch;
610
  if (arch == bfd_arch_unknown)
611
    arch = CGEN_BFD_ARCH;
612
 
613
  /* There's no standard way to compute the machine or isa number
614
     so we leave it to the target.  */
615
#ifdef CGEN_COMPUTE_MACH
616
  mach = CGEN_COMPUTE_MACH (info);
617
#else
618
  mach = info->mach;
619
#endif
620
 
621
#ifdef CGEN_COMPUTE_ISA
622
  {
623
    static CGEN_BITSET *permanent_isa;
624
 
625
    if (!permanent_isa)
626
      permanent_isa = cgen_bitset_create (MAX_ISAS);
627
    isa = permanent_isa;
628
    cgen_bitset_clear (isa);
629
    cgen_bitset_add (isa, CGEN_COMPUTE_ISA (info));
630
  }
631
#else
632
  isa = info->insn_sets;
633
#endif
634
 
635
  /* If we've switched cpu's, try to find a handle we've used before */
636
  if (cd
637
      && (cgen_bitset_compare (isa, prev_isa) != 0
638
          || mach != prev_mach
639
          || endian != prev_endian))
640
    {
641
      cd = 0;
642
      for (cl = cd_list; cl; cl = cl->next)
643
        {
644
          if (cgen_bitset_compare (cl->isa, isa) == 0 &&
645
              cl->mach == mach &&
646
              cl->endian == endian)
647
            {
648
              cd = cl->cd;
649
              prev_isa = cd->isas;
650
              break;
651
            }
652
        }
653
    }
654
 
655
  /* If we haven't initialized yet, initialize the opcode table.  */
656
  if (! cd)
657
    {
658
      const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
659
      const char *mach_name;
660
 
661
      if (!arch_type)
662
        abort ();
663
      mach_name = arch_type->printable_name;
664
 
665
      prev_isa = cgen_bitset_copy (isa);
666
      prev_mach = mach;
667
      prev_endian = endian;
668
      cd = m32r_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
669
                                 CGEN_CPU_OPEN_BFDMACH, mach_name,
670
                                 CGEN_CPU_OPEN_ENDIAN, prev_endian,
671
                                 CGEN_CPU_OPEN_END);
672
      if (!cd)
673
        abort ();
674
 
675
      /* Save this away for future reference.  */
676
      cl = xmalloc (sizeof (struct cpu_desc_list));
677
      cl->cd = cd;
678
      cl->isa = prev_isa;
679
      cl->mach = mach;
680
      cl->endian = endian;
681
      cl->next = cd_list;
682
      cd_list = cl;
683
 
684
      m32r_cgen_init_dis (cd);
685
    }
686
 
687
  /* We try to have as much common code as possible.
688
     But at this point some targets need to take over.  */
689
  /* ??? Some targets may need a hook elsewhere.  Try to avoid this,
690
     but if not possible try to move this hook elsewhere rather than
691
     have two hooks.  */
692
  length = CGEN_PRINT_INSN (cd, pc, info);
693
  if (length > 0)
694
    return length;
695
  if (length < 0)
696
    return -1;
697
 
698
  (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
699
  return cd->default_insn_bitsize / 8;
700
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.