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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [insight/] [opcodes/] [fr30-dis.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 578 markom
/* 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 Free Software Foundation, Inc.
8
 
9
This file is part of the GNU Binutils and GDB, the GNU debugger.
10
 
11
This program 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 2, or (at your option)
14
any later version.
15
 
16
This program is distributed in the hope that it will be useful,
17
but WITHOUT ANY WARRANTY; without even the implied warranty of
18
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
GNU General Public 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
59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 "fr30-desc.h"
35
#include "fr30-opc.h"
36
#include "opintl.h"
37
 
38
/* Default text to print if an instruction isn't recognized.  */
39
#define UNKNOWN_INSN_MSG _("*unknown*")
40
 
41
static void print_normal
42
     PARAMS ((CGEN_CPU_DESC, PTR, long, unsigned int, bfd_vma, int));
43
static void print_address
44
     PARAMS ((CGEN_CPU_DESC, PTR, bfd_vma, unsigned int, bfd_vma, int));
45
static void print_keyword
46
     PARAMS ((CGEN_CPU_DESC, PTR, CGEN_KEYWORD *, long, unsigned int));
47
static void print_insn_normal
48
     PARAMS ((CGEN_CPU_DESC, PTR, const CGEN_INSN *, CGEN_FIELDS *,
49
              bfd_vma, int));
50
static int print_insn PARAMS ((CGEN_CPU_DESC, bfd_vma,
51
                               disassemble_info *, char *, int));
52
static int default_print_insn
53
     PARAMS ((CGEN_CPU_DESC, bfd_vma, disassemble_info *));
54
 
55
/* -- disassembler routines inserted here */
56
 
57
/* -- dis.c */
58
 
59
static void
60
print_register_list (dis_info, value, offset, load_store)
61
     PTR dis_info;
62
     long value;
63
     long offset;
64
     int load_store; /* 0 == load, 1 == store */
65
{
66
  disassemble_info *info = dis_info;
67
  int mask;
68
  int index = 0;
69
  char* comma = "";
70
 
71
  if (load_store)
72
    mask = 0x80;
73
  else
74
    mask = 1;
75
 
76
  if (value & mask)
77
    {
78
      (*info->fprintf_func) (info->stream, "r%i", index + offset);
79
      comma = ",";
80
    }
81
 
82
  for (index = 1; index <= 7; ++index)
83
    {
84
      if (load_store)
85
        mask >>= 1;
86
      else
87
        mask <<= 1;
88
 
89
      if (value & mask)
90
        {
91
          (*info->fprintf_func) (info->stream, "%sr%i", comma, index + offset);
92
          comma = ",";
93
        }
94
    }
95
}
96
 
97
static void
98
print_hi_register_list_ld (cd, dis_info, value, attrs, pc, length)
99
     CGEN_CPU_DESC cd;
100
     PTR dis_info;
101
     long value;
102
     unsigned int attrs;
103
     bfd_vma pc;
104
     int length;
105
{
106
  print_register_list (dis_info, value, 8, 0/*load*/);
107
}
108
 
109
static void
110
print_low_register_list_ld (cd, dis_info, value, attrs, pc, length)
111
     CGEN_CPU_DESC cd;
112
     PTR dis_info;
113
     long value;
114
     unsigned int attrs;
115
     bfd_vma pc;
116
     int length;
117
{
118
  print_register_list (dis_info, value, 0, 0/*load*/);
119
}
120
 
121
static void
122
print_hi_register_list_st (cd, dis_info, value, attrs, pc, length)
123
     CGEN_CPU_DESC cd;
124
     PTR dis_info;
125
     long value;
126
     unsigned int attrs;
127
     bfd_vma pc;
128
     int length;
129
{
130
  print_register_list (dis_info, value, 8, 1/*store*/);
131
}
132
 
133
static void
134
print_low_register_list_st (cd, dis_info, value, attrs, pc, length)
135
     CGEN_CPU_DESC cd;
136
     PTR dis_info;
137
     long value;
138
     unsigned int attrs;
139
     bfd_vma pc;
140
     int length;
141
{
142
  print_register_list (dis_info, value, 0, 1/*store*/);
143
}
144
 
145
static void
146
print_m4 (cd, dis_info, value, attrs, pc, length)
147
     CGEN_CPU_DESC cd;
148
     PTR dis_info;
149
     long value;
150
     unsigned int attrs;
151
     bfd_vma pc;
152
     int length;
153
{
154
  disassemble_info *info = (disassemble_info *) dis_info;
155
  (*info->fprintf_func) (info->stream, "%ld", value);
156
}
157
/* -- */
158
 
159
/* Main entry point for printing operands.
160
   XINFO is a `void *' and not a `disassemble_info *' to not put a requirement
161
   of dis-asm.h on cgen.h.
162
 
163
   This function is basically just a big switch statement.  Earlier versions
164
   used tables to look up the function to use, but
165
   - if the table contains both assembler and disassembler functions then
166
     the disassembler contains much of the assembler and vice-versa,
167
   - there's a lot of inlining possibilities as things grow,
168
   - using a switch statement avoids the function call overhead.
169
 
170
   This function could be moved into `print_insn_normal', but keeping it
171
   separate makes clear the interface between `print_insn_normal' and each of
172
   the handlers.
173
*/
174
 
175
void
176
fr30_cgen_print_operand (cd, opindex, xinfo, fields, attrs, pc, length)
177
     CGEN_CPU_DESC cd;
178
     int opindex;
179
     PTR xinfo;
180
     CGEN_FIELDS *fields;
181
     void const *attrs;
182
     bfd_vma pc;
183
     int length;
184
{
185
 disassemble_info *info = (disassemble_info *) xinfo;
186
 
187
  switch (opindex)
188
    {
189
    case FR30_OPERAND_CRI :
190
      print_keyword (cd, info, & fr30_cgen_opval_cr_names, fields->f_CRi, 0);
191
      break;
192
    case FR30_OPERAND_CRJ :
193
      print_keyword (cd, info, & fr30_cgen_opval_cr_names, fields->f_CRj, 0);
194
      break;
195
    case FR30_OPERAND_R13 :
196
      print_keyword (cd, info, & fr30_cgen_opval_h_r13, 0, 0);
197
      break;
198
    case FR30_OPERAND_R14 :
199
      print_keyword (cd, info, & fr30_cgen_opval_h_r14, 0, 0);
200
      break;
201
    case FR30_OPERAND_R15 :
202
      print_keyword (cd, info, & fr30_cgen_opval_h_r15, 0, 0);
203
      break;
204
    case FR30_OPERAND_RI :
205
      print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Ri, 0);
206
      break;
207
    case FR30_OPERAND_RIC :
208
      print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Ric, 0);
209
      break;
210
    case FR30_OPERAND_RJ :
211
      print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Rj, 0);
212
      break;
213
    case FR30_OPERAND_RJC :
214
      print_keyword (cd, info, & fr30_cgen_opval_gr_names, fields->f_Rjc, 0);
215
      break;
216
    case FR30_OPERAND_RS1 :
217
      print_keyword (cd, info, & fr30_cgen_opval_dr_names, fields->f_Rs1, 0);
218
      break;
219
    case FR30_OPERAND_RS2 :
220
      print_keyword (cd, info, & fr30_cgen_opval_dr_names, fields->f_Rs2, 0);
221
      break;
222
    case FR30_OPERAND_CC :
223
      print_normal (cd, info, fields->f_cc, 0, pc, length);
224
      break;
225
    case FR30_OPERAND_CCC :
226
      print_normal (cd, info, fields->f_ccc, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
227
      break;
228
    case FR30_OPERAND_DIR10 :
229
      print_normal (cd, info, fields->f_dir10, 0, pc, length);
230
      break;
231
    case FR30_OPERAND_DIR8 :
232
      print_normal (cd, info, fields->f_dir8, 0, pc, length);
233
      break;
234
    case FR30_OPERAND_DIR9 :
235
      print_normal (cd, info, fields->f_dir9, 0, pc, length);
236
      break;
237
    case FR30_OPERAND_DISP10 :
238
      print_normal (cd, info, fields->f_disp10, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
239
      break;
240
    case FR30_OPERAND_DISP8 :
241
      print_normal (cd, info, fields->f_disp8, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
242
      break;
243
    case FR30_OPERAND_DISP9 :
244
      print_normal (cd, info, fields->f_disp9, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
245
      break;
246
    case FR30_OPERAND_I20 :
247
      print_normal (cd, info, fields->f_i20, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_VIRTUAL), pc, length);
248
      break;
249
    case FR30_OPERAND_I32 :
250
      print_normal (cd, info, fields->f_i32, 0|(1<<CGEN_OPERAND_HASH_PREFIX)|(1<<CGEN_OPERAND_SIGN_OPT), pc, length);
251
      break;
252
    case FR30_OPERAND_I8 :
253
      print_normal (cd, info, fields->f_i8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
254
      break;
255
    case FR30_OPERAND_LABEL12 :
256
      print_address (cd, info, fields->f_rel12, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
257
      break;
258
    case FR30_OPERAND_LABEL9 :
259
      print_address (cd, info, fields->f_rel9, 0|(1<<CGEN_OPERAND_PCREL_ADDR), pc, length);
260
      break;
261
    case FR30_OPERAND_M4 :
262
      print_m4 (cd, info, fields->f_m4, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
263
      break;
264
    case FR30_OPERAND_PS :
265
      print_keyword (cd, info, & fr30_cgen_opval_h_ps, 0, 0);
266
      break;
267
    case FR30_OPERAND_REGLIST_HI_LD :
268
      print_hi_register_list_ld (cd, info, fields->f_reglist_hi_ld, 0, pc, length);
269
      break;
270
    case FR30_OPERAND_REGLIST_HI_ST :
271
      print_hi_register_list_st (cd, info, fields->f_reglist_hi_st, 0, pc, length);
272
      break;
273
    case FR30_OPERAND_REGLIST_LOW_LD :
274
      print_low_register_list_ld (cd, info, fields->f_reglist_low_ld, 0, pc, length);
275
      break;
276
    case FR30_OPERAND_REGLIST_LOW_ST :
277
      print_low_register_list_st (cd, info, fields->f_reglist_low_st, 0, pc, length);
278
      break;
279
    case FR30_OPERAND_S10 :
280
      print_normal (cd, info, fields->f_s10, 0|(1<<CGEN_OPERAND_SIGNED)|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
281
      break;
282
    case FR30_OPERAND_U10 :
283
      print_normal (cd, info, fields->f_u10, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
284
      break;
285
    case FR30_OPERAND_U4 :
286
      print_normal (cd, info, fields->f_u4, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
287
      break;
288
    case FR30_OPERAND_U4C :
289
      print_normal (cd, info, fields->f_u4c, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
290
      break;
291
    case FR30_OPERAND_U8 :
292
      print_normal (cd, info, fields->f_u8, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
293
      break;
294
    case FR30_OPERAND_UDISP6 :
295
      print_normal (cd, info, fields->f_udisp6, 0|(1<<CGEN_OPERAND_HASH_PREFIX), pc, length);
296
      break;
297
 
298
    default :
299
      /* xgettext:c-format */
300
      fprintf (stderr, _("Unrecognized field %d while printing insn.\n"),
301
               opindex);
302
    abort ();
303
  }
304
}
305
 
306
cgen_print_fn * const fr30_cgen_print_handlers[] =
307
{
308
  print_insn_normal,
309
};
310
 
311
 
312
void
313
fr30_cgen_init_dis (cd)
314
     CGEN_CPU_DESC cd;
315
{
316
  fr30_cgen_init_opcode_table (cd);
317
  fr30_cgen_init_ibld_table (cd);
318
  cd->print_handlers = & fr30_cgen_print_handlers[0];
319
  cd->print_operand = fr30_cgen_print_operand;
320
}
321
 
322
 
323
/* Default print handler.  */
324
 
325
static void
326
print_normal (cd, dis_info, value, attrs, pc, length)
327
#ifdef CGEN_PRINT_NORMAL
328
     CGEN_CPU_DESC cd;
329
#else
330
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
331
#endif
332
     PTR dis_info;
333
     long value;
334
     unsigned int attrs;
335
#ifdef CGEN_PRINT_NORMAL
336
     bfd_vma pc;
337
     int length;
338
#else
339
     bfd_vma pc ATTRIBUTE_UNUSED;
340
     int length ATTRIBUTE_UNUSED;
341
#endif
342
{
343
  disassemble_info *info = (disassemble_info *) dis_info;
344
 
345
#ifdef CGEN_PRINT_NORMAL
346
  CGEN_PRINT_NORMAL (cd, info, value, attrs, pc, length);
347
#endif
348
 
349
  /* Print the operand as directed by the attributes.  */
350
  if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
351
    ; /* nothing to do */
352
  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
353
    (*info->fprintf_func) (info->stream, "%ld", value);
354
  else
355
    (*info->fprintf_func) (info->stream, "0x%lx", value);
356
}
357
 
358
/* Default address handler.  */
359
 
360
static void
361
print_address (cd, dis_info, value, attrs, pc, length)
362
#ifdef CGEN_PRINT_NORMAL
363
     CGEN_CPU_DESC cd;
364
#else
365
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
366
#endif
367
     PTR dis_info;
368
     bfd_vma value;
369
     unsigned int attrs;
370
#ifdef CGEN_PRINT_NORMAL
371
     bfd_vma pc;
372
     int length;
373
#else
374
     bfd_vma pc ATTRIBUTE_UNUSED;
375
     int length ATTRIBUTE_UNUSED;
376
#endif
377
{
378
  disassemble_info *info = (disassemble_info *) dis_info;
379
 
380
#ifdef CGEN_PRINT_ADDRESS
381
  CGEN_PRINT_ADDRESS (cd, info, value, attrs, pc, length);
382
#endif
383
 
384
  /* Print the operand as directed by the attributes.  */
385
  if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SEM_ONLY))
386
    ; /* nothing to do */
387
  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_PCREL_ADDR))
388
    (*info->print_address_func) (value, info);
389
  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_ABS_ADDR))
390
    (*info->print_address_func) (value, info);
391
  else if (CGEN_BOOL_ATTR (attrs, CGEN_OPERAND_SIGNED))
392
    (*info->fprintf_func) (info->stream, "%ld", (long) value);
393
  else
394
    (*info->fprintf_func) (info->stream, "0x%lx", (long) value);
395
}
396
 
397
/* Keyword print handler.  */
398
 
399
static void
400
print_keyword (cd, dis_info, keyword_table, value, attrs)
401
     CGEN_CPU_DESC cd ATTRIBUTE_UNUSED;
402
     PTR dis_info;
403
     CGEN_KEYWORD *keyword_table;
404
     long value;
405
     unsigned int attrs ATTRIBUTE_UNUSED;
406
{
407
  disassemble_info *info = (disassemble_info *) dis_info;
408
  const CGEN_KEYWORD_ENTRY *ke;
409
 
410
  ke = cgen_keyword_lookup_value (keyword_table, value);
411
  if (ke != NULL)
412
    (*info->fprintf_func) (info->stream, "%s", ke->name);
413
  else
414
    (*info->fprintf_func) (info->stream, "???");
415
}
416
 
417
/* Default insn printer.
418
 
419
   DIS_INFO is defined as `PTR' so the disassembler needn't know anything
420
   about disassemble_info.  */
421
 
422
static void
423
print_insn_normal (cd, dis_info, insn, fields, pc, length)
424
     CGEN_CPU_DESC cd;
425
     PTR dis_info;
426
     const CGEN_INSN *insn;
427
     CGEN_FIELDS *fields;
428
     bfd_vma pc;
429
     int length;
430
{
431
  const CGEN_SYNTAX *syntax = CGEN_INSN_SYNTAX (insn);
432
  disassemble_info *info = (disassemble_info *) dis_info;
433
  const CGEN_SYNTAX_CHAR_TYPE *syn;
434
 
435
  CGEN_INIT_PRINT (cd);
436
 
437
  for (syn = CGEN_SYNTAX_STRING (syntax); *syn; ++syn)
438
    {
439
      if (CGEN_SYNTAX_MNEMONIC_P (*syn))
440
        {
441
          (*info->fprintf_func) (info->stream, "%s", CGEN_INSN_MNEMONIC (insn));
442
          continue;
443
        }
444
      if (CGEN_SYNTAX_CHAR_P (*syn))
445
        {
446
          (*info->fprintf_func) (info->stream, "%c", CGEN_SYNTAX_CHAR (*syn));
447
          continue;
448
        }
449
 
450
      /* We have an operand.  */
451
      fr30_cgen_print_operand (cd, CGEN_SYNTAX_FIELD (*syn), info,
452
                                 fields, CGEN_INSN_ATTRS (insn), pc, length);
453
    }
454
}
455
 
456
/* Subroutine of print_insn. Reads an insn into the given buffers and updates
457
   the extract info.
458
   Returns 0 if all is well, non-zero otherwise.  */
459
static int
460
read_insn (cd, pc, info, buf, buflen, ex_info, insn_value)
461
     CGEN_CPU_DESC cd;
462
     bfd_vma pc;
463
     disassemble_info *info;
464
     char *buf;
465
     int buflen;
466
     CGEN_EXTRACT_INFO *ex_info;
467
     unsigned long *insn_value;
468
{
469
  int status = (*info->read_memory_func) (pc, buf, buflen, info);
470
  if (status != 0)
471
    {
472
      (*info->memory_error_func) (status, pc, info);
473
      return -1;
474
    }
475
 
476
  ex_info->dis_info = info;
477
  ex_info->valid = (1 << buflen) - 1;
478
  ex_info->insn_bytes = buf;
479
 
480
  *insn_value = bfd_get_bits (buf, buflen * 8, info->endian == BFD_ENDIAN_BIG);
481
  return 0;
482
}
483
 
484
/* Utility to print an insn.
485
   BUF is the base part of the insn, target byte order, BUFLEN bytes long.
486
   The result is the size of the insn in bytes or zero for an unknown insn
487
   or -1 if an error occurs fetching data (memory_error_func will have
488
   been called).  */
489
 
490
static int
491
print_insn (cd, pc, info, buf, buflen)
492
     CGEN_CPU_DESC cd;
493
     bfd_vma pc;
494
     disassemble_info *info;
495
     char *buf;
496
     int buflen;
497
{
498
  unsigned long insn_value;
499
  const CGEN_INSN_LIST *insn_list;
500
  CGEN_EXTRACT_INFO ex_info;
501
 
502
  int rc = read_insn (cd, pc, info, buf, buflen, & ex_info, & insn_value);
503
  if (rc != 0)
504
    return rc;
505
 
506
  /* The instructions are stored in hash lists.
507
     Pick the first one and keep trying until we find the right one.  */
508
 
509
  insn_list = CGEN_DIS_LOOKUP_INSN (cd, buf, insn_value);
510
  while (insn_list != NULL)
511
    {
512
      const CGEN_INSN *insn = insn_list->insn;
513
      CGEN_FIELDS fields;
514
      int length;
515
 
516
#ifdef CGEN_VALIDATE_INSN_SUPPORTED 
517
      /* not needed as insn shouldn't be in hash lists if not supported */
518
      /* Supported by this cpu?  */
519
      if (! fr30_cgen_insn_supported (cd, insn))
520
        {
521
          insn_list = CGEN_DIS_NEXT_INSN (insn_list);
522
          continue;
523
        }
524
#endif
525
 
526
      /* Basic bit mask must be correct.  */
527
      /* ??? May wish to allow target to defer this check until the extract
528
         handler.  */
529
      if ((insn_value & CGEN_INSN_BASE_MASK (insn))
530
          == CGEN_INSN_BASE_VALUE (insn))
531
        {
532
          /* Printing is handled in two passes.  The first pass parses the
533
             machine insn and extracts the fields.  The second pass prints
534
             them.  */
535
 
536
          /* Make sure the entire insn is loaded into insn_value, if it
537
             can fit.  */
538
          if (CGEN_INSN_BITSIZE (insn) > cd->base_insn_bitsize &&
539
              (CGEN_INSN_BITSIZE (insn) / 8) <= sizeof (unsigned long))
540
            {
541
              unsigned long full_insn_value;
542
              int rc = read_insn (cd, pc, info, buf,
543
                                  CGEN_INSN_BITSIZE (insn) / 8,
544
                                  & ex_info, & full_insn_value);
545
              if (rc != 0)
546
                return rc;
547
              length = CGEN_EXTRACT_FN (cd, insn)
548
                (cd, insn, &ex_info, full_insn_value, &fields, pc);
549
            }
550
          else
551
            length = CGEN_EXTRACT_FN (cd, insn)
552
              (cd, insn, &ex_info, insn_value, &fields, pc);
553
 
554
          /* length < 0 -> error */
555
          if (length < 0)
556
            return length;
557
          if (length > 0)
558
            {
559
              CGEN_PRINT_FN (cd, insn) (cd, info, insn, &fields, pc, length);
560
              /* length is in bits, result is in bytes */
561
              return length / 8;
562
            }
563
        }
564
 
565
      insn_list = CGEN_DIS_NEXT_INSN (insn_list);
566
    }
567
 
568
  return 0;
569
}
570
 
571
/* Default value for CGEN_PRINT_INSN.
572
   The result is the size of the insn in bytes or zero for an unknown insn
573
   or -1 if an error occured fetching bytes.  */
574
 
575
#ifndef CGEN_PRINT_INSN
576
#define CGEN_PRINT_INSN default_print_insn
577
#endif
578
 
579
static int
580
default_print_insn (cd, pc, info)
581
     CGEN_CPU_DESC cd;
582
     bfd_vma pc;
583
     disassemble_info *info;
584
{
585
  char buf[CGEN_MAX_INSN_SIZE];
586
  int status;
587
 
588
  /* Read the base part of the insn.  */
589
 
590
  status = (*info->read_memory_func) (pc, buf, cd->base_insn_bitsize / 8, info);
591
  if (status != 0)
592
    {
593
      (*info->memory_error_func) (status, pc, info);
594
      return -1;
595
    }
596
 
597
  return print_insn (cd, pc, info, buf, cd->base_insn_bitsize / 8);
598
}
599
 
600
/* Main entry point.
601
   Print one instruction from PC on INFO->STREAM.
602
   Return the size of the instruction (in bytes).  */
603
 
604
int
605
print_insn_fr30 (pc, info)
606
     bfd_vma pc;
607
     disassemble_info *info;
608
{
609
  static CGEN_CPU_DESC cd = 0;
610
  static int prev_isa;
611
  static int prev_mach;
612
  static int prev_endian;
613
  int length;
614
  int isa,mach;
615
  int endian = (info->endian == BFD_ENDIAN_BIG
616
                ? CGEN_ENDIAN_BIG
617
                : CGEN_ENDIAN_LITTLE);
618
  enum bfd_architecture arch;
619
 
620
  /* ??? gdb will set mach but leave the architecture as "unknown" */
621
#ifndef CGEN_BFD_ARCH
622
#define CGEN_BFD_ARCH bfd_arch_fr30
623
#endif
624
  arch = info->arch;
625
  if (arch == bfd_arch_unknown)
626
    arch = CGEN_BFD_ARCH;
627
 
628
  /* There's no standard way to compute the machine or isa number
629
     so we leave it to the target.  */
630
#ifdef CGEN_COMPUTE_MACH
631
  mach = CGEN_COMPUTE_MACH (info);
632
#else
633
  mach = info->mach;
634
#endif
635
 
636
#ifdef CGEN_COMPUTE_ISA
637
  isa = CGEN_COMPUTE_ISA (info);
638
#else
639
  isa = 0;
640
#endif
641
 
642
  /* If we've switched cpu's, close the current table and open a new one.  */
643
  if (cd
644
      && (isa != prev_isa
645
          || mach != prev_mach
646
          || endian != prev_endian))
647
    {
648
      fr30_cgen_cpu_close (cd);
649
      cd = 0;
650
    }
651
 
652
  /* If we haven't initialized yet, initialize the opcode table.  */
653
  if (! cd)
654
    {
655
      const bfd_arch_info_type *arch_type = bfd_lookup_arch (arch, mach);
656
      const char *mach_name;
657
 
658
      if (!arch_type)
659
        abort ();
660
      mach_name = arch_type->printable_name;
661
 
662
      prev_isa = isa;
663
      prev_mach = mach;
664
      prev_endian = endian;
665
      cd = fr30_cgen_cpu_open (CGEN_CPU_OPEN_ISAS, prev_isa,
666
                                 CGEN_CPU_OPEN_BFDMACH, mach_name,
667
                                 CGEN_CPU_OPEN_ENDIAN, prev_endian,
668
                                 CGEN_CPU_OPEN_END);
669
      if (!cd)
670
        abort ();
671
      fr30_cgen_init_dis (cd);
672
    }
673
 
674
  /* We try to have as much common code as possible.
675
     But at this point some targets need to take over.  */
676
  /* ??? Some targets may need a hook elsewhere.  Try to avoid this,
677
     but if not possible try to move this hook elsewhere rather than
678
     have two hooks.  */
679
  length = CGEN_PRINT_INSN (cd, pc, info);
680
  if (length > 0)
681
    return length;
682
  if (length < 0)
683
    return -1;
684
 
685
  (*info->fprintf_func) (info->stream, UNKNOWN_INSN_MSG);
686
  return cd->default_insn_bitsize / 8;
687
}

powered by: WebSVN 2.1.0

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